Dec 222014
 

This is a series of working notes on the Yubikey which is an interesting device used to supplement passwords to make two-factor authentication easier. It is essentially a hardware security token device that pretends to your computer to be a keyboard and enters a one-time only password that can be used to verify your identity – much like a password, but much more secure.

Well perhaps "easier" only if someone does all the configuration for you, although I am inclined to look a bit deeper into such things for my own amusement. My own key is a Yubikey NEO, but much of what follows also applies to the other Yubikey models.

Observations

This is the spot for observations on using the Yubikey over time.

  1. For some reason the Yubikey doesn't always "light up" on my workstation at work. It works fine at home – the green light always turns on ready for a key press – but at work it often seems to flicker and stay out. Not sure what causes this, but it always seems to be persistent when you really need to use it! 

Configuration

… is to some extent unnecessary, but under Linux there are three bits of software that can be installed to configure additional features of the Yubikey :-

  1. The library: https://developers.yubico.com/libykneomgr/
  2. The command-line tool: https://developers.yubico.com/yubikey-personalization/
  3. The GUI: https://developers.yubico.com/yubikey-personalization-gui/

All three build easily from the instructions given. Just make sure to remember to copy the udev rules from yubikey-personalization to /etc/udev/rules.d/ and run udevadm trigger to enable them. This will make sure you can access your yubikey as a console user, so you don't have to become root.

Enabling Linux Authentication

This was all done with a Linux container (LXC), so it could be relatively easily thrown away and restarted. The first step was to install the relevant PAM module :-

# apt-get install libpam-yubico

This pulls in a ton of other required packages.

The next is to grab the unchanging part of your Yubikey token. This is the first 12 characters of what you get when you activate it. Whilst you have it to hand, now would be a good time to create the mapping file – /etc/yubikey-mappings :-

# Yubikey ID mappings
# Format:
#       user-id:yubikey-id:yubikey-id:...
# (But usually only one)
user-id:ccccccsomeid

Next step is to add a little something to one of the pam files. For testing (assuming you have console) access, the relevant file might be /etc/pam.d/sshd but once you have things working, /etc/pam.d/common-auth might be a better choice. Right at the top of the file add :-

auth       sufficient   pam_yubico.so debug id=16 authfile=/etc/yubikey-mappings
#       Added for Yubikey authentication.

Because these things always have problems when you first try them, it makes sense to set up the debugging log :-

touch /var/run/pam-debug.log
chmod a+w /var/run/pam-debug.log

At this point, assuming everything works as expected :-

  1. You will be able to authenticate using ssh using either your Yubikey, or your password.
  2. This assumes your server is able to communicate with the Yubi Cloud.

There are further improvements to be made … and we'll get to those shortly.

But That's Not Two-Factor Authentication!

Indeed not, so we'll fix that right now.

Firstly remove the line we previously added to /etc/pam.d/sshd; because of the way that Debian configures pam, it is less disruptive (i.e. fewer changes) to make the change to /etc/pam.d/common-auth :-

auth       requisite     pam_yubico.so id=16 debug authfile=/etc/yubikey-mappings
#       Yubikey configuration added.
auth    [success=1 default=ignore]      pam_unix.so nullok_secure use_first_pass

But before restarting sshd (you have been doing that haven't you?), you will need to add a Yubikey ID to /etc/yubikey-mappings for the root user.

At this point, you will only be able to authenticate if you enter your username, followed by both your Unix password and activate your Yubikey at the password prompt. Entering both at the same prompt is a little weird especially when you consider that there is no indications anywhere that Yubikey authentication is required.

But we can fix that. First of all, one small change to common-auth – remove the use_first_pass phrase.

Next edit the file /etc/ssh/sshd_config and find the ChallengeResponseAuthentication phrase and set to "Yes" :-

ChallengeResponseAuthentication yes

And after a quick reboot, the log in process works in a sensible way :-

» ssh chagers
Yubikey for `mike': (Press YubiKey)
Password: (Enter Unix password)
Linux chagers 3.14-0.bpo.1-amd64 #1 SMP Debian 3.14.12-1~bpo70+1 (2014-07-13) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Dec 31 15:37:05 2014
...
</pre>
Aug 272014
 

This post came about because HP (in their infinite wisdom) decided to make the web-based printer control all neat and tidy by aligning all of the IP columns and filling up the space with leading zeros. Spotted the problem yet?

Well you’re quicker than I was; although I had the advantage of knowing that something was wrong and that somebody had pasted that IP address with leading zeros, it took me a few seconds to wonder if it was just possible that leading zeros might be doing something “odd”.

The thing about IPv4 addresses (and IPv6 as well, but I’ll not be pasting in examples for those as they’re too long) is that they are not simply what we see on screen as 10.0.0.1 (or whatever). That representation is converted into a 32-bit binary number which is used as the address. As an example :-

✓ mike@pica» ping -c 1 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=255 time=0.688 ms

--- 10.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.688/0.688/0.688/0.000 ms
✓ mike@pica» ping -c 1 167772161  
PING 167772161 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=255 time=6.04 ms

--- 167772161 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 6.040/6.040/6.040/0.000 ms

As you can see, you do not have to use the conventional “dotted quad” representation; you can use the integer equivalent instead. You can also see why the “dotted quad” representation was invented!

To convert the “dotted quad” notation to an integer that can be used at the lowest level, certain calculations are performed. Either because of a peculiar clause in the original specifications of IPv4 addresses, or (and potentially more likely) as a side effect of one of the earliest implementations of IPv4, certain other representations are possible :-

✓ mike@pica» ping -c 1 0xa.0.0.1
PING 0xa.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=255 time=1.34 ms

--- 0xa.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.341/1.341/1.341/0.000 ms
✓ mike@pica» ping -c 1 012.0.0.1
PING 012.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_req=1 ttl=255 time=1.03 ms

--- 012.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.034/1.034/1.034/0.000 ms

As you can see, each individual octet (the numbers between the dots) can be represented in decimal (as we expect), in hexadecimal (by prepending “0x”), or most dangerously, octal (by prepending at least one “0”).

So an apparently innocuous IP address like 10.0.0.030 will actually by converted into an integer that can be converted back into a more usual 10.0.0.24 :-

✓ mike@pica» ping 10.0.0.030
PING 10.0.0.030 (10.0.0.24) 56(84) bytes of data.

There are several lessons to learn from this :-

  1. HP needs slapping with a really rotten haddock to make them realise that their printers have web interfaces that are unhelpful in the extreme.
  2. Leading zeros may be harmful, or at least may result in being slapped with a rotten haddock.
  3. Leading zeros in IP addresses indicate the use of octal and so the result may not be what you expect.
  4. Reading the screen can be helpful when diagnosing problems. It may be easy to miss, but there are clues enough to solve this little challenge even without knowing about octal.

 

Aug 152014
 

This post is likely to change frequently after it first appears as experiments/research/etc. occurs to me.

To get to grips with it, let’s first define the software that is in control of your PC when it first starts as the system firmware rather than the BIOS, as system firmware is a generic term which can refer to BIOS, EFI, UEFI, OpenFirmware, or anything else that someone comes up with.

UEFI (and the older EFI) is a replacement for the legacy BIOS that we’ve been stuck with for decades. Despite advances in almost every aspect of the “PC standard”, the BIOS has hardly advanced at all. To be fair, the user interface has gotten a bit less 1980s, and it of course deals with hardware devices that weren’t even imagined decades ago. But there are still some rather nasty limitations, which UEFI is supposed to resolve.

Of course there are those who claim that UEFI is a complete mess with no redeeming qualities, but the truth is probably somewhere between it being that and the neatest bit of system firmware ever invented.

This posting are my working notes (with the addition of a bit of pointless waffling) on UEFI, given that I’m likely to be found staring at a UEFI shell on a broken server at some point in the future. All experiments (so far) have been carried out with a VirtualBox-powered virtual machine (with UEFI turned on) running Ubuntu server.

Installation

The boot process looks a little different … unsurprisingly. And there’s an error in relation to missing UEFI stuff from the hard disk. But once the CD is booted the process looks the same …

Partitioning: Initially “Guided – use entire disk and set up LVM”

Doesn’t give an opportunity to review the partitioning, but :-

  1. EFISystem (/boot/efi) is roughly 512Mbytes
  2. /boot is roughly 256Mbytes
  3. LVM Volume Group

The Ubuntu installation uses grub as the boot loader, although it’s hardly the only option and there are hints that grub has been known to have issues with EFI. Although this could be “early adopters pain”, and not applicable currently.

GPT Partitions

See the Wikipedia article, but basically GPT replaced the old Master Boot Record partitions. The main advantage is that there are fewer dumb limits with GPT – there is no limit of 4 primary partitions (and no hacks to support extended partitions), but instead a minimum maximum of 128 partitions, which basically translates as the required minimum size of a partition table allows for up to 128 partitions but the partition table can be bigger.  More than you’re likely to need anyway.

Cleverly (if you want to put it that way), GPT can live alongside the old MBR partitions as the GPT starts at block 1 rather than block 0. This has been used by Apple to keep two partition tables so that OSX can use GPT whilst Windows still uses MBR.

Keeping two partition tables in sync is perhaps not the best idea for stability and given the need for backwards compatibility has only a limited useful lifetime, I’d rather live without it. In fact it would be nice if I could fill up the old MBR with stuff that told all MBR tools not to mess around with the partition tables.

In theory, (U)EFI and GPT are independent of each other, but in practice, GPT implies booting from UEFI and MBR implies booting from BIOS (some UEFI implementation switch to a BIOS-compatibility mode when they see an MBR).

The EFI System Partition

(U)EFI requires that to boot, a disk must have an EFI System Partition formatted as FAT. This is used as effectively a replacement for the BIOS boot method of loading code from block 0. This file system is usually mounted under Linux as /boot/efi and contains various files that allow Linux to be booted (more details to be added).

It is perhaps a shame that the EFI standards people didn’t suggest making the EFI system partition part of the on-board firmware. It wouldn’t be impossible (or very expensive) to incorporate a small writeable FAT file system into the motherboard to avoid the need for the EFI partition on one of the storage disks. It is not as if the EFI system partition needs to be very big – Ubuntu configured one as 512Mbytes in size which is vastly larger than required for what is actually installed which adds up to less than 4Mbytes.

EFIBOOTMGR

The tool efibootmgr is for interacting with the EFI boot manager and the EFI variables that control what gets booted in which order :-

# efibootmgr
BootCurrent: 0003
BootOrder: 0003,0000,0001,0002
Boot0000* EFI DVD/CDROM
Boot0001* EFI Hard Drive
Boot0002* EFI Internal Shell
Boot0003* ubuntu

The command has plenty of other options …

You can set the boot order with: efibootmgr -o 0002,0003,0001,0000. So I’ve set the preferred boot order to include the internal shell first … the purpose here is to look into EFI after all.

I also somehow managed to erase the “ubuntu” so re-created that with: efibootmgr -c -L UbuntuServer -l “\EFI\ubuntu\shimx64.efi” (yes unfortunately they use the wrong path separator).

EFI Shell

Is surprisingly limited. And rather too DOS-like for me.

Command Description
help Displays a list of the commands available … which very unhelpfully doesn’t pause at the end of the screen. Can also display additional details of a command if you try help command.
mode Displays a list of the available screen mode commands.
mode x y Sets the screen mode to the size specified (as listed with mode).
cls Clears the screen.
cls ${n} Clears the screen and sets the colours to a set specified by the number (0-7). Don’t bother; most of the choices are nasty.
map Displays teh mapping table showing the block devices (BLK${n}) and the recognised file systems (FS${n}). If you don’t have fs0 you’ve got problems!
fs0: Sets the specified file system as the current file system. This will change the prompt appropriately.
cd ${directory} Changes to the specified directory. Remember that the path separator is the DOS preferred character (\).
ls Lists files in the current directory.
edit ${filename} Edits the specified file (^S saves, ^Q quits), but don’t try editing files ending in .efi!
${filename}.efi Runs the EFI binary from the current directory, and yes that does mean you can boot Ubuntu Server by browsing to the \EFI\ubuntu directory and entering shimx64.efi (as I discovered after breaking the ubuntu boot option).
Aug 022014
 

One of the questions I always ask myself when setting up a resilient server, is just how well will it cope with a disk failure? Ultimately you cannot answer that without trying it out.

But as practice (and to determine whether it mostly works), it’s perfectly sensible to try it out on a virtual machine.

Debian Installation

If you are looking for full instructions on installing Debian, this is not the place to look. I configured the virtual machine with 2GBytes of memory, an LsiLogic SAS controller with two attached disks each of 64GBytes.

The installation process was much as per normal (I unselected “Desktop” to save time), but the storage was somewhat different :-

  • Manual partitioning method
  • Create an empty partition on both disks
  • Select Software RAID
  • Create an MD device
  • RAID1
  • And put both disks into the RAID
  • Configure LVM
  • Create a Volume Group (“sys”)
  • Select md0 for the volume group device
  • Create logical volumes (boot: 512MB, root: 16GB, var: 8GB, home: 512M (it’s a server))
  • In the partitioning manager select each Logical Volume in turn and specify the file system parameters.

You will notice that no swap was created – this was a mistake that I’m in the unfortunate habit of making! However for a test, it wasn’t a problem and with LVM it is possible to create swap after the installation.

Post Installation

After the server has booted, it is possible to check the second hard disk for the presence of grub in the MBR (dd if=/dev/sdb of=/var/tmp/sdb.boot bs=1M count=1, and then run strings on the result). It turns out that nothing is installed in the MBR of the second disk by default. Which would make booting in a degraded environment an interesting challenge (i.e. you’ll have to find a rescue CD and boot off the relevant hard disk).

However this can be fixed by installing grub onto the second hard disk: grub-install /dev/sdb

Testing Resilience

But what happens when you lose a disk? Now is the time to test. Shut down the virtual machine and remove the second hard disk – leaving the first hard disk in place does not provide a full test.

If your first attempt at booting afterwards results in a failure to acquire a grub menu, then either you have failed to run grub-install as detailed above (guess what mistake I made?), or your BIOS settings don’t permit the computer to boot off anything other than the first hard disk.

However, in my second attempt, the server booted normally with the addition of a few messages that indicate that there is just one disk making up the mirrored pair.

Summary

  1. Yes, you can put /boot onto an LVM file system that sits on mirrored disks. That hasn’t always been the case.
  2. It is still necessary to run grub-install to put Grub onto the MBR of the second hard disk.
  3. It works.
Jul 042014
 

Well, relatively safely anyway.

The other day I felt the urge to knock up some SQL to clean up a MySQL table I’m responsible for. So I got the SQL prepared, but then needed to find out how to run this as a cron job (or batch file if you prefer). This was because I wanted to run the job on a regular and frequent basis; and I’m too lazy to sit around with a stopwatch running the same command every 15 minute.

I came up with a method that I knew wasn’t recommended – as it said so in the manual. The method involved passing the contents of a file to the command line (i.e. mysql -u root -p$(cat somefile). And today I decided to have a look around to see if there was a better way.

It turns out that much of the most visible advice on the Internet is wrong. It all suggests using the -p option where the account password is visible in the process table (i.e. you can read it with ps aux). If you can guarantee that no rogue person will be able to login to your server and read the process table, then you are safe; and I would like to ask how you can achieve the impossible.

Putting a password in a file (as suggested below) is at least somewhat better, but it would be nice if MySQL were to offer something a bit more sophisticated.

However, on to the method.

The first step is to create an options file, and make sure that it is readable only by the current user :-

$ touch mysql-options-root.cnf
$ chmod go= mysql-options-root.cnf

Once securely created, you can edit the file and add the relevant options :-

[client]
password=do-you-really-think-i-would-tell-the-internet-what-my-mysql-root-password-is?

That list of options is fairly minimal; it only specifies the password to use. You can add additional options – just use the normal command-line options without the hyphens.

To use this options file, add the command-line option –defaults-extra-file=${filename}. A full example follows :-

$ mysql --defaults-extra-file=mysql-options-root.cnf --user=root --host=polio < use misc;
heredoc> select count(*) from films;
heredoc> END

The output is not included (it’s none of your business how many films I’ve watched). And yes this does work for what I intended it to.

As has been pointed out, it is also possible to schedule batch jobs within MySQL itself which may be a better answer in most cases.