5

I want to allow these two authentication types: public key + google authenticator OR password + google authenticator.

I have the following in my sshd_config:

AuthenticationMethods publickey,keyboard-interactive:pam password,keyboard-interactive:pam
UsePAM yes
ChallengeResponseAuthentication yes
PubkeyAuthentication yes
PasswordAuthentication yes

And in the /etc/pam.d/ssh I uncommented

#@include common-auth and added auth required pam_google_authenticator.so

at the end of the file.

The key + token route still works, but for some reason my password always gets rejected with the message "Access denied".

I found out that whenever I set UsePAM to "yes", the password authentication fails. Not sure why?

Contents of /etc/pam.d/sshd: (this file seems very long for me but it was just the default for ubuntu, maybe I could shorten this down?)

# PAM configuration for the Secure Shell service

# Standard Un*x authentication.
#@include common-auth

# Disallow non-root logins when /etc/nologin exists.
account    required     pam_nologin.so

# Uncomment and edit /etc/security/access.conf if you need to set     complex
# access limits that are hard to express in sshd_config.
# account  required     pam_access.so

# Standard Un*x authorization.
@include common-account

# SELinux needs to be the first session rule.  This ensures that any
# lingering context has been cleared.  Without this it is possible     that a
# module could execute code in the wrong domain.
session [success=ok ignore=ignore module_unknown=ignore default=bad]            pam_selinux.so close

# Set the loginuid process attribute.
session    required     pam_loginuid.so

# Create a new session keyring.
session    optional     pam_keyinit.so force revoke

# Standard Un*x session setup and teardown.
@include common-session

# Print the message of the day upon successful login.
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session    optional     pam_motd.so  motd=/run/motd.dynamic noupdate
session    optional     pam_motd.so # [1]

# Print the status of the user's mailbox upon successful login.
session    optional     pam_mail.so standard noenv # [1]

# Set up user limits from /etc/security/limits.conf.
session    required     pam_limits.so

# Read environment variables from /etc/environment and
# /etc/security/pam_env.conf.
session    required     pam_env.so # [1]
# In Debian 4.0 (etch), locale-related environment variables were moved to
# /etc/default/locale, so read that as well.
session    required     pam_env.so user_readenv=1     envfile=/etc/default/locale

# SELinux needs to intervene at login time to ensure that the process     starts
# in the proper default security context.  Only sessions which are intended
# to run in the user's context should be run after this.
session [success=ok ignore=ignore module_unknown=ignore default=bad]            pam_selinux.so open

# Standard Un*x password updating.
@include common-password

auth required pam_google_authenticator.so

Contents of /etc/pam.d/common-auth:

#
# /etc/pam.d/common-auth - authentication settings common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.).  The default is to use the
# traditional Unix authentication mechanisms.
#
# As of pam 1.0.1-6, this file is managed by pam-auth-update by default.
# To take advantage of this, it is recommended that you configure any
# local modules either before or after the default block, and use
# pam-auth-update to manage selection of other modules.  See
# pam-auth-update(8) for details.

# here are the per-package modules (the "Primary" block)
auth    [success=1 default=ignore]  pam_unix.so nullok_secure
# here's the fallback if no module succeeds
auth    requisite           pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around 
auth    required            pam_permit.so
# and here are more per-package modules (the "Additional" block)
auth    optional            pam_cap.so 
# end of pam-auth-update config

My question actually breaks down to: How do I use "UsePAM yes" together with "AuthenticationMethods password". Maybe I should delete this question and open a new one?

7
  • what can you see in the server log as a reason for rejecting? Are you connecting as a root? – Jakuje Feb 2 '16 at 18:54
  • I think this is the relevant part: sshd[28572]: debug1: userauth-request for user user1 service ssh-connection method password [preauth] sshd[28572]: debug1: attempt 1 failures 0 [preauth] sshd(pam_google_authenticator)[28572]: Invalid verification code sshd[28572]: debug1: PAM: password authentication failed for user1: Cannot make/remove an entry for the specified session sshd[28572]: Failed password for user1 from 192.168.1.5 port 2616 ssh2 – Timothy Feb 2 '16 at 21:49
  • The password method is using pam and therefore google authenticator, which is the issue. – Jakuje Feb 2 '16 at 21:53
  • So how do I achieve what I want? Is there no way to mix non pam and pam in the AuthenticationMethods? – Timothy Feb 2 '16 at 22:01
  • I don't know about any way how to do that. Choosing only one (password+2FA or key+2FA) works fine though. – Jakuje Feb 2 '16 at 22:05
3

I found out that whenever I set UsePAM to yes, the password authentication fails. Not sure why?

UsePAM option makes the authentication method password use the same PAM module as you want to use for second factor. This is why it rejects your password.


This is answer to your question, explaining "why", but not complete solution "how to make it better". Setting up this combination is tricky. I wanted to learn how to do that simply and correctly, but did have the time so far. But I am open to your ideas :)

1

I spent all morning trying to get this one to work. AFAIK now, the publickey authentication method occurs OUTSIDE the PAM stack.

From what I can observe, having ChallengeResponseAuthentication yes and UsePAM yes means that the value of PasswordAuthentication is effectively ignored and can be considered no. This means the password value of AuthenticationMethods will always fail.

Which would not be an issue if we could observe the success or failure state of a publickey login inside the PAM stack. But we can't - it seems to be handled entirely inside SSH.

This means that we can do (as valid AuthenticationMethods sets):

  • publickey and nothing else
  • The entire PAM stack
  • publickey and the entire PAM stack

But not as we are wanting, publickey and part of the PAM stack based on whether publickey was a success.

Would love to be proven wrong on this!

1

The answer is simply that it is not possible to request two factors with password authentication, but with an explanation for you that will help get things working. You're looking at password authentication as the way to use a password. This is incorrect.

'password authentication' is a simple request for a single password. There's no specific prompt sent by the server to the client. It's the client that chooses how to label the prompt- such as when it asks "Enter password for user@host:".

'keyboard-interactive' is a more complex request for arbitrary number of pieces of information. For each piece of information the server sends the label for the prompt. Moreover it allows the server to provide a description of the form of the response it expects. The server can also specify which inputs are secret (passwords need to be obfuscated on screen) and which are not (OTPs)

In majority of cases the keyboard-interactive authentication is used to request the single "secret" password prompt, so there's hardly any difference compared to the password authentication for the end user.

Since keyboard-interactive is an authentication mechanism that allows the server to send multiple challenge/response pairs, the Google Authenticator PAM plug-in needs it to send two questions- the password and the OTP.

So password authentication will NEVER work with Google Authenticator, since it doesn't have the ability to prompt for more than one thing. Google Authenticator will work with private-keys and the OTP into the password prompt (though not ideally). Google Authenticator will work with keyboard-interactive with the password and the OTP. Google Authenticator will NOT work with a password prompt as it cannot ask for the right information.

In your client software, prioritize keyboard-interactive over password and you'll be set with getting the two prompts with your current configuration. To avoid having it at all, we can disable password authentication entirely.

My question actually breaks down to: How do I use "UsePAM yes" together with "AuthenticationMethods password"

To directly answer this, you can't. Remove password as a supported authentication method and rely on keyboard-interactive for your password authentications. Set "PasswordAuthentication no" in /etc/ssh/sshd_config

So: /etc/ssh/sshd_config

UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
PubkeyAuthentication yes
# I don't use AuthenticationMethods at all and rely on my yes/no's

/etc/pam.d/sshd (at the bottom)

auth required pam_google_authenticator.so nullok

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.