Local Two-Factor Authentication With U2F on Ubuntu 14.04

I received my GitHub-themed U2F Yubikey this week. U2F is an open, standardized protocol for allowing people to authenticate with a device. It hasn’t been around long, but there are already strong efforts to get people to use it.

If you’ve used the Google Authenticator app, you’ll see the utility of a U2F key as it’s much smaller than a smartphone. Getting it to work is as simple as inserting the key and pressing a button. A majority of implementations, and there aren’t many, are web services like Google and GitHub. Yubico has produced a pam-u2f module that allows you to hook in U2F authentication to PAM. PAM is what Linux uses to allow adding and customizing various authentication mechanisms.

Very Important Note - Proceed This Guide At Your Own Risk

If you are worried about potentially locking yourself out of your machine, do not continue.

There is the very real risk of locking yourself out of your machine following this guide.

I have not tested scenarios with a fully-encrypted disk or with an encrypted home directory.

Proceed at your own risk.

Getting Started

Adding U2F to Ubuntu 14.04 is actually straightforward. The documentation for the PAM module is dense, so that’s where this article comes in. These instructions could work with Debian, but I haven’t tried.

First, you need to add Yubico’s package repo:

1
2
sudo add-apt-repository ppa:yubico/stable
sudo apt-get update

Then, you need to install the relevant packages:

1
sudo apt-get install pam-u2f pamu2fcfg

Now we need to install some rules for Linux’s device manager so it can deal with the U2F keys:

1
sudo wget -O /etc/udev/rules.d/70-u2f.rules https://raw.githubusercontent.com/Yubico/libu2f-host/master/70-u2f.rules

After this, you should reboot your machine.

Registering Your Key

When your machine starts up again, we need to setup the locations that will hold our keys:

1
2
3
mkdir ~/.yubico ~/.config/Yubico
touch ~/.config/Yubico/u2f_keys
ln -s ~/.config/Yubico/u2f_keys ~/.yubico/u2f_keys

The latest versions of pam-u2f read from ~/.config/Yubico/u2f_keys while the current version in the Ubuntu repository reads from ~/.yubico/u2f_keys. With this method, the actual key is stored in ~/.config/Yubico. The symbolic link in ~/.yubico/u2f_keys points to ~/.config/Yubico/u2f_keys. I set it up this way because I do not know what will happen when Yubico updates what is in the Ubuntu repository!

Next, we need to tell the system about the key we want to register. We will use the pamu2fcfg tool to do that.

Insert your U2F key and run pamu2fcfg -umyusername where myusername is your account’s username. It should recognize your key. When it does, press the button on your key. It will generate a code that looks like this:

1
myusername:oijoij3o4ijfoi3j4ifj3o4jfiojewlkjflksjefw4g4g34gr34g34-g34g3-4g34g34g34g3,9043809584309850943284023023024230009809809898a09898098b

Now, fire up a text editor and copy the text pamu2fcfg generated and place it in ~/.config/Yubico/u2f_keys. Very important note: If you use zsh, you may see a percent sign at the end. Do not include that!

Configuring PAM

Now it’s time to setup PAM to use your U2F key. What we want to do is require the U2F key for authentication every single time you enter your password.

Located in /etc/pam.d/common-auth are the particular rules for handling this. Mine before I added the U2F rules looked like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#
# /etc/pam.d/common-auth - authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.).  The default is to use the
# traditional Unix authentication mechanisms.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules.  See
# pam-auth-update(8) for details.

# here are the per-package modules (the "Primary" block)
auth  [success=1 default=ignore]  pam_unix.so nullok_secure
# here's the fallback if no module succeeds
auth  requisite     pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth  required      pam_permit.so
# and here are more per-package modules (the "Additional" block)
auth  optional      pam_cap.so
# end of pam-auth-update config

To get U2F working, we need to open /etc/pam.d/common-auth in a text editor. Add this line at the end of the file: auth sufficient pam_u2f.so debug cue

With that addition, it should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#
# /etc/pam.d/common-auth - authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.).  The default is to use the
# traditional Unix authentication mechanisms.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules.  See
# pam-auth-update(8) for details.

# here are the per-package modules (the "Primary" block)
auth  [success=1 default=ignore]  pam_unix.so nullok_secure
# here's the fallback if no module succeeds
auth  requisite     pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth  required      pam_permit.so
# and here are more per-package modules (the "Additional" block)
auth  optional      pam_cap.so
# end of pam-auth-update config

# u2f
auth sufficient pam_u2f.so debug cue

After you do this reboot. When your computer boots back up again. Place your U2F key in a USB slot. Type in your password and login. Your U2F key should blink. Touch the button on your U2F key and it should log you in.

WARNING: If your U2F key did not blink or pressing the blinking button on your U2F did not log you in, do not continue this guide.

The sufficient option in our U2F PAM config above allows us to not require the key, but we can still use the key optionally.

Let’s test the U2F key on sudo after we login. Open up a terminal, insert your U2F key and type sudo ls. It will ask you for your password. After you enter your password you should see a bunch of text. At the end you should see something like:

1
2
3
4
[../util.c:get_devices_from_authfile(140)] Length of key number 1 is 65
[../util.c:get_devices_from_authfile(166)] Found 1 device(s) for user seabre
[../util.c:do_authentication(219)] Device max index is 0
[../util.c:do_authentication(242)] Attempting authentication with device number 1

If you do, you’ll see your key blinking. Press the button on your U2F key. It should authenticate you and run the ls command.

WARNING: Do not continue if your key did not blink after you entered your password. You probably won’t be able to log in to your machine if you follow the instructions after this point.

If you did see your key blink after you entered your password and were able to touch your key to access your machine, feel free to continue beyond this point. However, proceed with caution. You can now change the U2F options in your PAM config to auth required pam_u2f.so cue

So now your /etc/pam.d/common-auth should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#
# /etc/pam.d/common-auth - authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.).  The default is to use the
# traditional Unix authentication mechanisms.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules.  See
# pam-auth-update(8) for details.

# here are the per-package modules (the "Primary" block)
auth  [success=1 default=ignore]  pam_unix.so nullok_secure
# here's the fallback if no module succeeds
auth  requisite     pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth  required      pam_permit.so
# and here are more per-package modules (the "Additional" block)
auth  optional      pam_cap.so
# end of pam-auth-update config

# u2f
auth required pam_u2f.so cue

After this change, you will need to reboot. After you reboot, try logging in without your key. You will notice that it will tell you your password is wrong. Try again, but first insert your U2F key. Enter your password as usual and press enter. You should see your U2F key blinking. Press the button on your U2F key. You should now be logged in.

Recommendations

Get A Second U2F Key

If you intend to require U2F for login, what happens if you lose your key? You won’t be able to get in. Get a second key, register it, then put it in a safe place. Yubico describes the format of u2f_keys:

1
<username>:<KeyHandle1>,<UserKey1>:<KeyHandle2>,<UserKey2>:...

So you can run pamu2fcfg with your second key and follow the format to add it to u2f_keys described above.

Consider Full Disk Encryption

As far as I know, you won’t be able to do this if you’ve installed Ubuntu without it already. But, doing this makes it less possible to bypass two-factor authentication.

Setting Up Travis CI for OpenCV and Midje

I’ve been fiddling with OpenCV for a few weeks. Using OpenCV and Clojure is straightforward. The hardest part was setting up OpenCV.

When I’m experimenting and I get to a place where I feel like I know what I’m doing, I’ll start writing tests. Eventually you’ll setup continuous integration, but then you remember how difficult installing OpenCV was! If you’d like to use Travis CI with your Clojure project using OpenCV, I’ve already done the work for you! Swapping out midje isn’t a problem, if you’d rather use core.test or speclj, but I’m going to focus on midje here.

I’m assuming your project looks something like Magomimmo’s opencv-start. He’s also the guy that wrote the Clojure tutorial on OpenCV’s documentation site. If you setup your project using those instructions, that is fine since they are almost identical. The only difference is that I’m using a more more up to date version of OpenCV. You will have to make a few changes to the Travis CI yaml configuration below if you want to use a different version.

First, we need to add the midje and lein localrepo plugins to our project.clj if they aren’t there already. Travis CI needs to know about them. Adding the following line inside defproject within your project.clj should suffice:

1
:plugins [[lein-localrepo "0.5.3"] [lein-midje "3.1.3"]]

Next, we need to add the .travis.yml config to the root of the repo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
language: clojure
lein: lein2
script: lein2 midje
jdk:
  - oraclejdk7

compiler:
  - gcc

before_install:
  - sudo apt-get update

install:
  - sudo apt-get install python-dev python-numpy

before_script:
  - git clone https://github.com/Itseez/opencv.git
  - cd opencv
  - git checkout 2.4
  - mkdir build
  - cd build
  - cmake ..
  - make -j8
  - sudo make -j8 install
  - cd ../..
  - mkdir -p native/linux/x86_64
  - cp opencv/build/lib/libopencv_java248.so native/linux/x86_64/libopencv_java248.so
  - cp opencv/build/bin/opencv-248.jar .
  - jar -cMf opencv-native-248.jar native
  - lein2 localrepo install opencv-248.jar opencv/opencv 2.4.8
  - lein2 localrepo install opencv-native-248.jar opencv/opencv-native 2.4.8

With this configuration, we tell Travis CI that: our project is a Clojure project, that we are using Leiningen 2.0, midje for testing, and Oracle JDK 7. The lines after that are for building OpenCV.

The lines before before_script tell Travis CI that: we need to use the GCC compiler, install python dev dependencies, and numpy for OpenCV. The lines in before_script are the actual build process automation for OpenCV.

If you noticed that the before_script is similar to the build steps in Magomimmo’s tutorial, you would be right. The only change I made was to use OpenCV 2.4.8. If you’d like to use a different release, you should change the before_script to match your needs. On Travis CI, the build process takes about 8 minutes.

A Simple Livecoding Environment for Overtone With Light Table

I’ve been using Overtone off and on for a while, and I’ve been wanting to try out Light Table, so I decided to see if I could get Overtone working with it.

Emacs is pretty much the standard for livecoding in Overtone, but it’s not the most accessible environment for beginners. I actually use vim, but it’s not that great, either. Light Table seems to be a good alternative, but I ran into some project dependency problems getting it setup. The fixes are easy to duplicate. After the problem is solved, it’s nice.

I’m going to assume the following: you’re in a Linux environment, you already have a copy of Light Table installed and working, you have Leiningen installed and working, and that you already have SuperCollider installed and working, which we need for Overtone.

First, let’s generate a new project somewhere:

$ lein new livecoding

Now, add the livecoding project to your workspace in Light Table. If you need help doing this, check the docs.

Inside your livecoding project, you should have project.clj, which looks like this:

1
2
3
4
5
6
(defproject livecoding "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]])

OK, great. But now we need to add Overtone. Usually, we’d just change project.clj to look like this:

1
2
3
4
5
6
7
(defproject livecoding "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [overtone "0.8.1"]])

The problem with this is that Overtone has a dependency on Clojure 1.3.0, which Light Table’s REPL refuses to use. We need to force Overtone to use Clojure 1.5.1. Let’s fix that:

1
2
3
4
5
6
7
8
(defproject livecoding "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [overtone "0.8.1" :exclusions [org.clojure/clojure]]
                 [org.clojure/data.json "0.2.2"]])

OK. So what does that do? We’re forcing overtone to ignore its dependency on Clojure 1.3. We’re also adding data.json, because Light Table’s REPL appears to have a dependency on that. Now, we’re good to go.

Make sure you saved the changes to project.clj and let’s now open up core.clj, which should be in src/livecoding in our workspace.

Let’s change it to this:

1
2
(ns livecoding.core
  (:use overtone.live))

Now let’s get the REPL going. Just press Ctrl+Enter to boot up Overtone. It takes a little bit to get started, but once it boots up, let’s just confirm it works. Change core.clj to:

1
2
3
4
(ns livecoding.core
  (:use overtone.live))

  (demo (sin-osc))

Highlight (demo (sin-osc)) and press Ctrl+Enter and you should hear a simple Sine wave.

Blum Blum Shub Pseudo Random Number Generator Coffeescript Implementation

This weekend hasn’t been as busy as they have been lately, so I’ve had a lot more time to just sit around. I was reading some articles on PRNGs, and a PRNG I’ve never heard of caught my eye. Mainly, I think, because of its name. Blum Blum Shub is a PRNG devised by some mathematicians and computer scientists in the mid 1980’s. I decided to do a Coffeescript implementation of it.

Common MySQL Tasks

I’m pretty terrible at remembering some of the simpler MySQL tasks, so here are a few of the more common tasks I do on a regular basis that I keep written down so I don’t forget them.

Dump The MySQL Database

mysqldump -u username -p -r my_output.sql my_database

Compress Output with 7zip using the PPMd Algorithm (Optional)

7z a -t7z my_output.7z my_output.sql -m0=PPMd

Decompress Output with 7zip (Optional)

7z e my_output.7z

Restore The MySQL Database

mysql -u username -p my_database < my_output.sql

Export Table as CSV From MySQL

SELECT * INTO OUTFILE '/tmp/my_table_name.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' ESCAPED BY '\\' LINES TERMINATED BY '\n' FROM my_table_name;