4

I'm trying to implement two-factor authentication for OpenSSH. The environment is Centos 7 (kernel: 3.10.0-229.1.2.el7.x86_64) with OpenSSH_6.6.1p1, OpenSSL 1.0.1e-fips 11 Feb 2013. We have Active Directory (LDAP) + Kerberos deployed. The specification is as follows:

  • A user with an existing, valid Kerberos ticket must be asked only for the second factor
  • A user without an existing, valid Kerberos ticket must be asked for both his password and a second factor
  • Local users (no LDAP acc.) should be able to authenticate with their local passwords
  • The second factor must not be offered before the first one
  • Besides Kerberos, public key authentication should be also accepted as first factor if available
  • The feature should be able to be limited to a set of users - others just get let in with their passwords

For performing the second factor's authentication process, there is 3rd party a PAM module available that knows nothing about Kerberos. So here is what I did:

Put these lines into /etc/ssh/sshd_config:

# To enable PAM - this will make sshd use PAM with configuration /etc/pam.d/sshd
UsePam yes
ChallengeResponseAuthentication yes

# To enable Kerberos and public key authentication - it will let sshd use existing Kerberos tickets
GSSAPIAuthentication yes

# Enable public key authentication
PubkeyAuthentication yes

# Password validation should be done via the KDC
PasswordAuthentication yes
KerberosAuthentication yes
KerberosOrLocalPasswd yes

# Kerberos / Public Key + PAM
AuthenticationMethods gssapi-with-mic,keyboard-interactive:pam publickey,keyboard-interactive:pam password,keyboard-interactive:pam
# (only supported for OpenSSH 6.2 or higher)

The auth section of the PAM configuration for sshd (/etc/pam.d/sshd)

auth       [success=ignore default=1] pam_localuser.so
auth       substack     password-auth
auth       [success=1 default=ignore] pam_localuser.so
auth       required     pam_2fa.so [...some arguments...]
auth       include      postlogin

The module pam_2fa.so is responsible for prompting for and validating the second factor.

Now for Kerberos, this does almost everything I wanted to achieve. However, for local accounts, it results in two subsequent password prompts. This is my main problem here. This is because in this case the path "password,keyboard-interactive:pam" is used,as expected. (I need this auth. path so someone with a Kerberos account but without a valid ticket can get a ticket by entering the password then the OTP.) If I remove the password-auth substack completely from the PAM config, then Kerberos accounts remain working and local accounts remain not working. To me, it seems like the KerberosOrLocalPasswd yes statement gets ignored, because UsePAM yes is also present. However, sshd really keeps using KDC for password validation, because otherwise it would not work for LDAP accounts either.

So again, to further clarify what I wish to implement here is the pseudocode that described the desired authentication logic:

if gssapi_auth_ok(principal) or pubkey_auth_ok(pubkey):
  return second_factor_auth(user, read_otp())
else:
  if is_local_account(user):
    if local_passwd_auth(user, read_password()):
      return second_factor_auth(user, read_otp())
    else:
      return AUTH_ERR
  else:
    if krb5_auth(principal, read_password()):
      return second_factor_auth(user, read_otp())
    return AUTH_ERR

So my scenario I think is not too complex or ambitious in any way, but I still could not find a clear way to implement it despite I spent days researching and experimenting. Could you please help me find a solution?

Thank you very much in advance!

migrated from stackoverflow.com May 6 '15 at 15:02

This question came from our site for professional and enthusiast programmers.

  • So in fact you want to do two factor authentication (password and OTP), but the password should be entered only once (making use of Kerberos)? All your requirements (local users, 2nd factor, users with one factor...) are met by 2FA systems like privacyIDEA (see privacyidea.org). But presenting the first factor (password) only once is an interesting new requirement. Do I get it right? – cornelinux May 28 '15 at 9:47
1

I don't know of any way to do what you want with PAM without writing a new pam module. PAM is relatively complex and the way that sshd interacts with PAM and kerberos has been in my experience such that there is always an edge case that just doesn't work.

What you want may be possible, I just don't know how to do it. If you only need to secure ssh what I would suggest is using

ForceCommand  /path/to/2fa_executable 

in your sshd_config. This would allow you to implement the logic you want, the drawback is that the 2fa_executable needs to be setuid to read any 2fa secrets.

There's an example and code on the Duo Security website. You could use the duo setuid wrapper and whatever 2fa code you are using.

Duo Unix Configuration

  • 1
    I'll upvote for the ForceCommand trick, but as indicated by the link you need to proceed very carefully with this. By the time this command has fired, from the perspective of sshd the user is authenticated and authorized. Regardless of the acknowledgements provided by that link, I'm incredibly uncomfortable with this designspace in general. – Andrew B May 7 '15 at 0:27
  • Unfortunately, FoceCommand is easy to circumvent. One might just add "exec /bin/sh" or similar to his shell control file (e.g. .bashrc) and that's it. ForceCommand gets triggered after spawning the shell with its environment. So it's not an option for me, but thank you very much for the idea. – dgyuri92 May 19 '15 at 13:22
1
  • A user with an existing, valid Kerberos ticket must be asked only for the second factor.

This can't be achieved through PAM.

Successful key-based authentication performed against sshd bypasses the auth stack of PAM. This includes GSSAPI, which is a requirement for ticket based Kerberos authentication. It has no choice but to do this as PAM was simply not designed with this type of authentication in mind.

Setting UsePAM yes does the following:

  • ChallengeResponseAuthentication and PasswordAuthentication will hook the auth stack of PAM to validate the password. Any form of authentication other than these two methods will not touch the auth stack.
  • On successful authentication, the account stack of PAM will be called to determine if the authenticated user is permitted access. (always)
  • The session stack of PAM will be called to handle session setup tasks.

Summary: There is absolutely no way to get a two-factor auth prompt located within the auth stack to fire for someone who has authenticated with a GSSAPI or ssh key. You can use account and session stacks in conjunction with those authentication methods, but that's as far as PAM will go.

  • This is only partially true with OpenSSH versions that have AuthenticationMethods, which as seen in the question can require both Kerberos and PAM-based auth. – grawity May 28 '15 at 20:56
  • @grawity Thanks for pointing out the new option, due to being unfamiliar with it my brain parsed it as PreferredAuthentications due to the parameters they share (even though that makes no sense in a sshd_config context). I'll leave the answer so that others learn from my mistake. – Andrew B May 29 '15 at 16:29
0

Here is an explanation how to do it https://cern-cert.github.io/pam_2fa/

  • The basis: 2 factor authentication with pam
  • A pam module that understands more about ssh authentication methods:

    auth [success=2 ignore=ignore default=die] pam_ssh_user_auth.so

  • Recent or patched OpenSSH to expose this to pam

    AuthenticationMethods gssapi-with-mic,keyboard-interactive:pam publickey,keyboard-interactive:pam keyboard-interactive:pam

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.