Friday, August 27, 2010

Yubikeys and KDEs

The yubikey is a small usb flash drive like device which can generate a one time password on demand. When it does this it inputs it as though it were a usb keyboard. You can set your own keys on the device and authenticate yourself locally using OTPs which is useful as well as cool.

A little series of hurdles later and I have the key unlocking KDE4. Some of the issues you are likely to see are that /etc/yubikey needs to be +rw by whatever is trying to use it. So making a yubifoo group and setting /sbin/yk_chkpwd to be setuid that group can be a plus. The biggest problem I had was trying to get the YubiPAM module to unlock KDE. It turns out that it was getting the user name and sending that to a child yk_chkpwd to verify instead of sending the current auth token.

To fix it, you might like to mangle pam_sm_authenticate() to use the following to get the authtok and send it through as the one time password for verification...

const char *prompt = 0;
const char *authtok;
int rc = pam_get_authtok( pamh, PAM_AUTHTOK, &authtok, prompt );
if( rc == PAM_SUCCESS )
otp = authtok;

REMOVE these two lines which don't seem to work

otp = get_response(pamh, "Yubikey OTP: ", verbose_otp);
retval = pam_set_item(pamh, PAM_AUTHTOK, otp);

With this in place and the normal line in /etc/pam.d/kscreensaver:

auth sufficient

the key should unlock you, or a regular password too. If you want two phase then it is easy to hack that into pam_sm_authenticate() looking for a pin prefix inside the authtok. Breaks the rules of module stacking in PAM, but works as they say.

To setup an offline aes key, make one somehow and use

ykpersonalize -o fixed=$modhexwhatever -a $aes_key_here \
-o -static-ticket -o -strong-pw1 -o -strong-pw2 \
-o -man-update

ykpasswd -d $my_user_name
ykpasswd -a $my_user_name -k $aes_key_here \
-f $modhexwhatever \
-o OTP

ykvalidate -u $my_user_name OTP

where OTP indicates a tap of the yubikey.

You can also get a layer down from ykvalidate using

echo -n OTP | /sbin/yk_chkpwd $my_user_name

There are other groovy scripts around to lock the screen when the yubikey is removed from the machine which might be a nice next step... now that it actually works to *un*lock.

1 comment:

rstuart said...

I had a bug report about my own pam-pathon module not working with KDM. Tracing it down, it looks to me like KDM's PAM handling code did adhere to the API as described in the Linux-PAM Application Developers' Guide.

For example, take this piece of code:

pam_error = pam_get_item (pamh, PAM_USER, &pam_item);
if (strcmp((const char *)pam_item, user)) {
pam_end(pamh, PAM_SUCCESS); /* maybe use PAM_AUTH_ERR? */
return AuthBad;

Which roughly translates to: if PAM does something mildly tricky like translating the entered user name to a UNIX one then barf.

Unfortunately if you want to do 2-factor auth with a YubiKey (something he knows [a password] plus something he has [the YubiKey]) translating the YubiKey token to a user name in /etc/password is exactly what you want to do - and that possibility was foreseen by PAM's authors. But not KDM's author, it seems.