Project:Infrastructure/dev.gentoo.org 2-step authentication

The SSH server on our developer machine (dev.gentoo.org) now has an experimental support for 2-step authentication, in which the usual public key authentication is followed by HOTP/TOTP input (see also: article on Two-factor authentication). The two-step authentication is implemented using PAM module.

TOTP with default settings
In order to enable two-step authentication with the default settings, you can use our simple wrapper script:

The above summary includes a QRCode for easy setup (you may need to zoom the terminal out to use it) and the Base32-encoded secret for manual setup. It also includes a verification code which will probably expire before you manage to set it up, and 5 emergency scratch codes that you should write down and keep in a safe place.

After enabling it, please make sure to test it using a parallel session. If you lock yourself out, you can use the emergency codes to login.

The default settings are:
 * TOTP (as specified in RFC6238) with SHA-1 algorithm and X=30 second period
 * window of 3 codes allowed (i.e. the previous one, the current one and the next one), accounting for a clock drift of ±30 seconds
 * code reuse disallowed (i.e. you can't use the same TOTP code to establish two sessions, you need to wait for the next one)
 * rate limiting to 3 attempts over 30 seconds
 * 5 emergency scratch codes

HOTP or TOTP with custom settings
If you'd like to use different settings, you can run the configuration app directly and follow the on-screen instructions:

There are also some additional options available only via command-line arguments.

Disabling HOTP/TOTP
In order to disable the two-step authentication, just remove the configuration file:

The authentication process
If you do not have HOTP/TOTP enabled, you should be able to log in as usual. Please note that due to protocol limitations some SSH clients may ask you for a password — if that is the case, please type any non-empty string and the authentication should succeed.

If you do have HOTP/TOTP enabled, your SSH client will first authenticate using the public key, then ask you for a verification code (or 'password', depending on the implementation). Type in your current verification code to proceed.

In either case, you will never be asked for your account/LDAP password.

authorized_keys automated command keys
Enabling HOTP/TOTP will explicitly enforce it for all logins to your account. If you are using command= lines in authorized_keys to allow automated logins from some services, the additional authentication token will be requested from them as well. If you need those commands to work, please don't use enable it yet. We are planning to provide additional support for this use case later on.

SHA2 hashes
does not support non-SHA1 hashes even though they are permitted by the TOTP standard and supported by some clients. Upstream seems to be willing to accept a patch for that. For more information, see https://github.com/google/google-authenticator-libpam/issues/11.

U2F
U2F would require direct support both on server and client-side of OpenSSH. However, it seems that nobody is currently working on this, and the available patches have serious flaws. For more details, see https://bugzilla.mindrot.org/show_bug.cgi?id=2319; in particular the following comment: https://bugzilla.mindrot.org/show_bug.cgi?id=2319#c21

Installed packages
The following packages are installed to implement the service:
 * — providing the PAM module and setup tool
 * — needed to display QRCode

OpenSSH setup
The following configuration is used to enable 2-step authentication:

The first two are needed to enable the password and keyboard-interactive methods respectively. The third sets it appropriately for 2-step verification.

AuthenticationMethods is a list of space-separated alternatives where each alternative specifies comma-separated list of required steps. This setting means that the user needs to do either:
 * publickey followed by password
 * or publickey followed by keyboard-interactive.

Note that this setting alone would require the user to both use his SSH key and his account password.

PAM setup
Once SSH is explicitly set to require publickey authentication, PAM settings can be altered. For Gentoo purposes, we created a separate pam.d file for this setup.

The explicit pam_permit module is necessary to allow users without OTP set up. If that is the case, pam_google_authenticator considers itself ignored and PAM needs another module to succeed to consider the authentication successful.

To trace the specific logic:
 * if user has OTP set up, pam_google_authenticator asks him for the code:
 * if the code is correct, pam_google_authenticator succeeds and pam_permit succeeds → login succeeds
 * if the code is incorrect, pam_google_authenticator fails → login fails
 * if user does not have OTP set up, nullok makes pam_google_authenticator return ignore status
 * however, pam_permit succeeds → login succeeds