privacyidea / pam_python

Add two factor authentication to PAM via privacyIDEA
18 stars 18 forks source link

privacyidea_pam.py always set authtok in pam #11

Open gojufhv opened 4 years ago

gojufhv commented 4 years ago

If privacyidea_pam.py is called, it always sets the authtok variable in pam. If pam_unix is executed after privacyidea_pam.py it won't prompt for a user password and instead tries to use the authtok taken from the previous module.

I've made a pull request which adds an option to prevent this.

10

gregharvey commented 2 years ago

Hi,

Bumping this, as the PR has fixed a problem for us. We were trying to migrate from the old LinOTP2 module written in C (https://github.com/LinOTP/linotp-auth-pam) I've been testing with sudo.

Here's the previous working config for reference:

/etc/pam.d/common-linotp

auth required  pam_linotp.so url=https://MY_LINOTP2_SERVER/validate/simplecheck

/etc/pam.d/common-auth

auth    [success=2 default=ignore]      pam_unix.so nullok_secure
auth    [success=1 default=ignore]      pam_ldap.so minimum_uid=1000
auth     requisite                                        pam_deny.so
auth     required                                         pam_permit.so
auth required    pam_access.so

/etc/pam.d/sudo

@include common-linotp
@include common-auth
@include common-account
@include common-session-noninteractive

This was fine, so we created a new config like this:

/etc/pam.d/common-privacyidea

auth requisite pam_python.so /opt/pam_python/privacyidea_pam.py url=https://MY_PI_SERVER

/etc/pam.d/common-auth

auth    [success=2 default=ignore]      pam_unix.so nullok_secure
auth    [success=1 default=ignore]      pam_ldap.so minimum_uid=1000
auth     requisite                                        pam_deny.so
auth     required                                         pam_permit.so
auth required    pam_access.so

/etc/pam.d/sudo

@include common-privacyidea
@include common-auth
@include common-account
@include common-session-noninteractive

But this fails, here's what the logs look like:

Feb 18 10:33:02 ip-10-111-2-41 sudo: offline check returned: False, None
Feb 18 10:33:02 ip-10-111-2-41 sudo: Authenticating greg against https://MY_PI_SERVER
Feb 18 10:33:02 ip-10-111-2-41 sudo: requests > 1.0
Feb 18 10:33:02 ip-10-111-2-41 sudo: privacyidea_pam: result: {u'status': True, u'value': True}
Feb 18 10:33:02 ip-10-111-2-41 sudo: privacyidea_pam: detail: {u'message': u'matching 1 tokens', u'type': u'yubico', u'serial': u'UBCM0000F9AC', u'otplen': 44, u'threadid': 139810408089344}
Feb 18 10:33:02 ip-10-111-2-41 sudo: privacyidea_pam: offline save authitem: None
Feb 18 10:33:02 ip-10-111-2-41 sudo: pam_unix(sudo:auth): authentication failure; logname=greg uid=1001 euid=0 tty=/dev/pts/1 ruser=greg rhost=  user=greg
Feb 18 10:33:02 ip-10-111-2-41 sudo: pam_ldap(sudo:auth): Authentication failure; user=greg

Turns out that no matter what you set the pam_ldap settings to, it will not prompt you for your LDAP password. I tried no options, with try_first_pass, etc. but nothing worked, it was all ignored/overridden somehow. In the end pam_ldap was always using the token already passed in the previous step - which isn't an LDAP password, it's a Yubikey token in this case. So for sure, it'll fail every time.

If you change the order like this it works again: /etc/pam.d/sudo

@include common-auth
@include common-privacyidea
@include common-account
@include common-session-noninteractive

But that's just annoying, I should not be forced to do that! Something is not behaving as documented.

ANYWAY, my colleague found the PR referenced in this post and I applied the changes and it now works. Config looks like this:

/etc/pam.d/common-privacyidea

auth requisite pam_python.so /opt/pam_python/privacyidea_pam.py url=https://MY_PI_SERVER no_authtok

/etc/pam.d/common-auth

auth    [success=2 default=ignore]      pam_unix.so nullok_secure
auth    [success=1 default=ignore]      pam_ldap.so minimum_uid=1000
auth     requisite                                        pam_deny.so
auth     required                                         pam_permit.so
auth required    pam_access.so

/etc/pam.d/sudo

@include common-privacyidea
@include common-auth
@include common-account
@include common-session-noninteractive

For now I will fork this script into our company GitHub so I can use it without having to patch it with Ansible each time it gets pulled, but it would be great if you could accept this PR. It prevents the behaviour of the token being passed to subsequent PAM modules, thus preventing them from demanding a new password. I don't fully understand why PAM behaves like this, and way try_first_pass doesn't make pam_ldap prompt post-failure, but it doesn't - it is what it is, and the PR works!

Thanks,

Greg