Ubuntu FreeRadius YubiKey ------------------------- Create and login to a fresh Ubuntu 10.04 LTS machine: ------ vmbuilder kvm ubuntu \ --dest /var/lib/libvirt/images/freeradius \ --proxy http://192.168.1.2/ubuntu \ --rootsize 10000 \ --mem 600 \ --suite lucid \ --flavour virtual \ --addpkg unattended-upgrades \ --addpkg openssh-server \ --addpkg avahi-daemon \ --addpkg acpid \ --ssh-key /root/.ssh/authorized_keys \ --libvirt qemu:///system \ --hostname freeradius \ --bridge br0 \ --debug ssh -l root freeradius.local ------ Install and configure software : -------------------------------- ------ apt-get install build-essential wget apt-get install libpam0g-dev libykclient3 libykclient-dev ------ Install PAM module: ------ wget http://yubico-pam.googlecode.com/files/pam_yubico-2.4.tar.gz tar xfz pam_yubico-2.4.tar.gz cd pam_yubico-2.4 ./configure make check install ln -s /usr/local/lib/security/pam_yubico.so /lib/security/ ------ Setup PAM debug log file: ------ touch /var/run/pam-debug.log chmod go+w /var/run/pam-debug.log tail -F /var/run/pam-debug.log & ------ Install FreeRadius: ------ apt-get install freeradius /etc/init.d/freeradius stop ------ Next we configure FreeRadius. First add this to /etc/freeradius/users: ------ DEFAULT Auth-Type = pam ------ Then comment out 'pap' and uncomment 'pam' from /etc/freeradius/sites-available/default. Add to the top of /etc/pam.d/radiusd: ------ auth sufficient pam_yubico.so id=1 debug authfile=/etc/yubikey_mapping ------ If you want to use HMAC signing, specify the 'key=' field too, like this: ------ auth sufficient pam_yubico.so id=1 key=b64foo debug authfile=/etc/yubikey_mapping ------ Create a file /etc/yubikey_mapping (ccccccccltnc is Alice's YubiKey's public ID) : ------ alice:ccccccccltnc ------ Create a Unix account 'alice': XXX should not be necessary? ------ adduser --disabled-password alice ------ Just press RET and finally 'y RET' on the prompts. Start radiusd: ------ LD_PRELOAD=/lib/libpam.so.0 freeradius -X ------ Testing authentication : ------------------------ Confirm that it works with radtest (use a real OTP from Alice's YubiKey) : ------ radtest alice ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef 127.0.0.1 0 testing123 ------ Output should be like this: ------ Sending Access-Request of id 69 to 127.0.0.1 port 1812 User-Name = "alice" User-Password = "ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef" NAS-IP-Address = 127.0.1.1 NAS-Port = 0 rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=69, length=20 ------ PAM debug output should be like this: ------ [pam_yubico.c:parse_cfg(404)] called. [pam_yubico.c:parse_cfg(405)] flags 0 argc 3 [pam_yubico.c:parse_cfg(407)] argv[0]=id=1 [pam_yubico.c:parse_cfg(407)] argv[1]=debug [pam_yubico.c:parse_cfg(407)] argv[2]=authfile=/etc/yubikey_mapping [pam_yubico.c:parse_cfg(408)] id=1 [pam_yubico.c:parse_cfg(409)] key=(null) [pam_yubico.c:parse_cfg(410)] debug=1 [pam_yubico.c:parse_cfg(411)] alwaysok=0 [pam_yubico.c:parse_cfg(412)] verbose_otp=0 [pam_yubico.c:parse_cfg(413)] try_first_pass=0 [pam_yubico.c:parse_cfg(414)] use_first_pass=0 [pam_yubico.c:parse_cfg(415)] authfile=/etc/yubikey_mapping [pam_yubico.c:parse_cfg(416)] ldapserver=(null) [pam_yubico.c:parse_cfg(417)] ldap_uri=(null) [pam_yubico.c:parse_cfg(418)] ldapdn=(null) [pam_yubico.c:parse_cfg(419)] user_attr=(null) [pam_yubico.c:parse_cfg(420)] yubi_attr=(null) [pam_yubico.c:pam_sm_authenticate(452)] get user returned: alice [pam_yubico.c:pam_sm_authenticate(542)] conv returned: ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef [pam_yubico.c:pam_sm_authenticate(558)] OTP: ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef ID: ccccccccltnc [pam_yubico.c:pam_sm_authenticate(583)] ykclient return value (0): Success [pam_yubico.c:check_user_token(117)] Authorization line: alice:ccccccccltnc [pam_yubico.c:check_user_token(121)] Matched user: alice [pam_yubico.c:check_user_token(125)] Authorization token: ccccccccltnc [pam_yubico.c:check_user_token(128)] Match user/token as alice/ccccccccltnc [pam_yubico.c:pam_sm_authenticate(625)] done. [Success] ------ FreeRadius debug output should be like this: ------ rad_recv: Access-Request packet from host 127.0.0.1 port 38575, id=69, length=89 User-Name = "alice" User-Password = "ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef" NAS-IP-Address = 127.0.1.1 NAS-Port = 0 +- entering group authorize {...} ++[preprocess] returns ok ++[chap] returns noop ++[mschap] returns noop [suffix] No '@' in User-Name = "alice", looking up realm NULL [suffix] No such realm "NULL" ++[suffix] returns noop [eap] No EAP-Message, not doing EAP ++[eap] returns noop [files] users: Matched entry DEFAULT at line 204 ++[files] returns ok ++[expiration] returns noop ++[logintime] returns noop Found Auth-Type = PAM +- entering group authenticate {...} pam_pass: using pamauth string for pam.conf lookup pam_pass: authentication succeeded for ++[pam] returns ok +- entering group post-auth {...} ++[exec] returns noop Sending Access-Accept of id 69 to 127.0.0.1 port 38575 Finished request 0. Going to the next request Waking up in 4.9 seconds. Cleaning up request 0 ID 69 with timestamp +17 Ready to process requests. ------ Testing a OTP replay : ---------------------- Run the command again, with the _same_ OTP : ------ radtest alice ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef 127.0.0.1 0 testing123 ------ Then output should be like this, since the OTP was replayed: ------ Sending Access-Request of id 32 to 127.0.0.1 port 1812 User-Name = "alice" User-Password = "ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef" NAS-IP-Address = 127.0.1.1 NAS-Port = 0 rad_recv: Access-Reject packet from host 127.0.0.1 port 1812, id=32, length=20 ------ PAM debug log: ------ [pam_yubico.c:parse_cfg(404)] called. [pam_yubico.c:parse_cfg(405)] flags 0 argc 3 [pam_yubico.c:parse_cfg(407)] argv[0]=id=1 [pam_yubico.c:parse_cfg(407)] argv[1]=debug [pam_yubico.c:parse_cfg(407)] argv[2]=authfile=/etc/yubikey_mapping [pam_yubico.c:parse_cfg(408)] id=1 [pam_yubico.c:parse_cfg(409)] key=(null) [pam_yubico.c:parse_cfg(410)] debug=1 [pam_yubico.c:parse_cfg(411)] alwaysok=0 [pam_yubico.c:parse_cfg(412)] verbose_otp=0 [pam_yubico.c:parse_cfg(413)] try_first_pass=0 [pam_yubico.c:parse_cfg(414)] use_first_pass=0 [pam_yubico.c:parse_cfg(415)] authfile=/etc/yubikey_mapping [pam_yubico.c:parse_cfg(416)] ldapserver=(null) [pam_yubico.c:parse_cfg(417)] ldap_uri=(null) [pam_yubico.c:parse_cfg(418)] ldapdn=(null) [pam_yubico.c:parse_cfg(419)] user_attr=(null) [pam_yubico.c:parse_cfg(420)] yubi_attr=(null) [pam_yubico.c:pam_sm_authenticate(452)] get user returned: alice [pam_yubico.c:pam_sm_authenticate(542)] conv returned: ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef [pam_yubico.c:pam_sm_authenticate(558)] OTP: ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef ID: ccccccccltnc [pam_yubico.c:pam_sm_authenticate(583)] ykclient return value (2): Yubikey OTP was replayed (REPLAYED_OTP) [pam_yubico.c:pam_sm_authenticate(625)] done. [Authentication failure] ------ FreeRadius debug log: ------ rad_recv: Access-Request packet from host 127.0.0.1 port 55170, id=32, length=89 User-Name = "alice" User-Password = "ccccccccltncdjjifceergtnukivgiujhgehgnkrfcef" NAS-IP-Address = 127.0.1.1 NAS-Port = 0 +- entering group authorize {...} ++[preprocess] returns ok ++[chap] returns noop ++[mschap] returns noop [suffix] No '@' in User-Name = "alice", looking up realm NULL [suffix] No such realm "NULL" ++[suffix] returns noop [eap] No EAP-Message, not doing EAP ++[eap] returns noop [files] users: Matched entry DEFAULT at line 204 ++[files] returns ok ++[expiration] returns noop ++[logintime] returns noop Found Auth-Type = PAM +- entering group authenticate {...} pam_pass: using pamauth string for pam.conf lookup pam_pass: function pam_authenticate FAILED for . Reason: Permission denied ++[pam] returns reject Failed to authenticate the user. Using Post-Auth-Type Reject +- entering group REJECT {...} [attr_filter.access_reject] expand: %{User-Name} -> alice attr_filter: Matched entry DEFAULT at line 11 ++[attr_filter.access_reject] returns updated Delaying reject of request 1 for 1 seconds Going to the next request Waking up in 0.5 seconds. Sending delayed reject for request 1 Sending Access-Reject of id 32 to 127.0.0.1 port 55170 Waking up in 4.9 seconds. Cleaning up request 1 ID 32 with timestamp +66 Ready to process requests. ------