Hey, Judging from the (private) responses I?ve got, there is quite a bit of interest in the U2F feature I proposed a while ago. Therefore, I?ve taken some time to resolve the remaining issues, and I think the resulting patch (attached to this email) is in quite a good state now. I also posted the new version of the patch to https://bugzilla.mindrot.org/show_bug.cgi?id=2319 (which I?ve opened based on Damien Miller?s request). In case you?re interested, please feel free to try the patch. I?m happy for any feedback. All you need is libu2f-host installed and a clean copy of OpenSSH 6.7p1. Apply the attached patch, delete configure, use autoreconf -i to regenerate it, then run ./configure --with-u2f and compile OpenSSH. Afterwards, follow the patch description/manpages to see how it works. Quote from the description follows: ------------------------------------------------------------------------------- Recently, the FIDO alliance announced U2F [1], and Google announced that it supports U2F tokens (?security keys?) for Google accounts [2]. As the spec is not a very short read, I gave a presentation last week about U2F which may be a good quick introduction to the details [3]. For the rest of this description, I?ll assume that you read either my presentation or the U2F spec. (side note: I?m not working on U2F, playing around with it and implementing it in OpenSSH is my private fun project :)) This commit adds U2F support to OpenSSH. More specifically, it adds an authentication mechanism called ?u2f?, together with the ssh-u2f key format. The new u2f authentication mechanism can operate in two modes, specified by the client with the U2FMode option: registration (necessary once per U2F security key) or authentication (the default). Since U2F is a two-factor authentication mechanism, you should never use it as the sole AuthenticationMethod. Therefore, whenever you enable U2FAuthentication, please also set AuthenticationMethods on the server. As an example, add the following to your sshd_config: U2FAuthentication yes AuthenticationMethods publickey,u2f (This assumes that you always enter your passphrase for the pubkey, otherwise perhaps AuthenticationMethods password,u2f would be a better choice ? YMMV.) For users without an ssh-u2f key in their authorized_keys file, this is a noop and will not change behavior ? the u2f authentication method will just always report success in this case. For users with at least one ssh-u2f key in their authorized_keys, the user must have the U2F security key in order to login. The server will send a challenge, and ssh(1) on the user?s machine will ask the user to touch the U2F security key. Upon being touched, the U2F security key cryptographically signs the challenge, and the server can verify that the registered security key is indeed present. To register a U2F security key, use: ssh -o U2FMode=registration my.server.example > /tmp/u2f-key.pub Now append the contents of /tmp/u2f-key.pub to your authorized_keys file on the server.>From now on, you should be prompted to touch the registered U2F securitykey after successful publickey authentication. In case you want to register another U2F security key, just repeat the process. Thanks to Thomas Habets, Christian Svensson and Axel Wagner for their support in implementing/discussing/testing this feature. [1] https://fidoalliance.org/ [2] http://googleonlinesecurity.blogspot.ch/2014/10/strengthening-2-step-verification-with.html [3] https://www.noname-ev.de/w/File:C14h-u2f-how-security-keys-work.pdf ------------------------------------------------------------------------------- Best regards, Michael -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-Implement-U2F-support-with-u2f-requires-libu2f-host.patch Type: text/x-patch Size: 58460 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20141224/7a591785/attachment-0001.bin>
On 24 December 2014 at 18:57, Michael Stapelberg <stapelberg+openssh at google.com> wrote:> In case you?re interested, please feel free to try the patch. I?m happy for > any feedback. All you need is libu2f-host installed and a clean copy of > OpenSSH 6.7p1. Apply the attached patch, delete configure, use autoreconf > -i to regenerate it, then run ./configure --with-u2f and compile OpenSSH.Transferring my notes from the other thread: 1) PAM doesn't work (--with-pam, then UsePAM yes and ChallengeResponseAuthentication yes) Fix: detect loops in ssh2connect:userauth_u2f in some other way, such as a dedicated variable in authctxt. (but also see point 5) 2) origin doesn't seem to be respected by YubiKeys (if I understand the spec correctly) Is AppID a better choice for this reason? 3) Include paths (probably bug in libu2f-host) This is https://github.com/Yubico/libu2f-host/issues/13 that you filed. 4) What happened to 51? MONITOR_REQ_TERM = 50, + MONITOR_REQ_READUSERU2FKEY = 52, MONITOR_ANS_READUSERU2FKEY = 53, 5) Why does registration connect to the server anyway, if the server doesn't keep state and origin is not tied to the server pubkey? Indeed, without AuthenticationMethods registration returns the blob before password prompt is shown. Registration only makes sense if server writes the key handle to ~/.ssh/authorized_keys, right? Hmm, unless authorized_keys is signed by the server, the registration process will never be "online" asyway, as U2F intends, so it may as well be generated on the client and copy-pasted into the server's authorized_keys. Enforced origin (but point 2) should prevent accidentally pasting the same blob to multiple servers). Tested on: Ubunty Trusty OpenSSH 6.7p1 Yubikey Security key -- typedef struct me_s { char name[] = { "Thomas Habets" }; char email[] = { "thomas at habets.pp.se" }; char kernel[] = { "Linux" }; char *pgpKey[] = { "http://www.habets.pp.se/pubkey.txt" }; char pgp[] = { "A8A3 D1DD 4AE0 8467 7FDE 0945 286A E90A AD48 E854" }; char coolcmd[] = { "echo '. ./_&. ./_'>_;. ./_" }; } me_t;
At this point it should be obvious, but let me state that I don?t have motivation/time to spend on this right now, given that upstream shows 0 interest in this at all :(. Hence, any help on this is welcome. On Sat, Dec 27, 2014 at 1:53 AM, Thomas Habets <thomas at habets.se> wrote:> On 24 December 2014 at 18:57, Michael Stapelberg > <stapelberg+openssh at google.com> wrote: > > In case you?re interested, please feel free to try the patch. I?m happy > for > > any feedback. All you need is libu2f-host installed and a clean copy of > > OpenSSH 6.7p1. Apply the attached patch, delete configure, use autoreconf > > -i to regenerate it, then run ./configure --with-u2f and compile OpenSSH. > > Transferring my notes from the other thread: > > 1) PAM doesn't work (--with-pam, then UsePAM yes and > ChallengeResponseAuthentication yes) > Fix: detect loops in ssh2connect:userauth_u2f in some other way, such > as a dedicated variable in authctxt. (but also see point 5) > > 2) origin doesn't seem to be respected by YubiKeys (if I understand > the spec correctly) > Is AppID a better choice for this reason? > > 3) Include paths (probably bug in libu2f-host) > This is https://github.com/Yubico/libu2f-host/issues/13 that you filed. > > 4) What happened to 51? > MONITOR_REQ_TERM = 50, > + MONITOR_REQ_READUSERU2FKEY = 52, MONITOR_ANS_READUSERU2FKEY = 53, > > 5) Why does registration connect to the server anyway, if the server > doesn't keep state and origin is not tied to the server pubkey? > Indeed, without AuthenticationMethods registration returns the blob before > password prompt is shown. > Registration only makes sense if server writes the key handle to > ~/.ssh/authorized_keys, right? > Hmm, unless authorized_keys is signed by the server, the registration > process will never be "online" asyway, as U2F intends, so it may as > well be generated on the client and copy-pasted into the server's > authorized_keys. Enforced origin (but point 2) should prevent > accidentally pasting the same blob to multiple servers). > > Tested on: > Ubunty Trusty > OpenSSH 6.7p1 > Yubikey Security key > > > -- > typedef struct me_s { > char name[] = { "Thomas Habets" }; > char email[] = { "thomas at habets.pp.se" }; > char kernel[] = { "Linux" }; > char *pgpKey[] = { "http://www.habets.pp.se/pubkey.txt" }; > char pgp[] = { "A8A3 D1DD 4AE0 8467 7FDE 0945 286A E90A AD48 E854" }; > char coolcmd[] = { "echo '. ./_&. ./_'>_;. ./_" }; > } me_t; >