SSSD / sssd

A daemon to manage identity, authentication and authorization for centrally-managed systems.
https://sssd.io
GNU General Public License v3.0
607 stars 246 forks source link

Problem with transition user's credentials through pam-stack #5418

Closed enot586 closed 11 months ago

enot586 commented 3 years ago

Hello,

i'm not sure my situation is issue or not but i can't see any mistake on my side. It seems there is an issue in case of using use_first_pass parameter when we need to get old password from another module. i would be grateful if somebody could give any advice or clarification.

my stuff and environment:

i have several test hosts(based on Debian and Red Hat) and two test domains FreeIpa and AD each of them includes test user with password q1w2e3r4t5y6. In the both domains the password marked as expired so the first user's login lead to changing current password.

In client host i put this configs on the top of all main pam-configs(just for test to avoid any interaction with other pam-modules):

password [default=die success=ok]   my_custom_pam.so
password [default=die success=done] pam_sss.so use_authtok use_first_pass

So i expect that after authentication pam_sss will get the current and new user's password from my_custom_pam.so without any prompt and the process of changing password will be performed automatically without user's participation.

my_custom_pam.so includes two simple functions which provide test user credentials:

PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char
**argv) {
    pam_set_item(pamh, PAM_AUTHTOK, "q1w2e3r4t5y6");
    return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char
**argv) {
    pam_set_item(pamh, PAM_OLDAUTHTOK, "q1w2e3r4t5y6");
    pam_set_item(pamh, PAM_AUTHTOK, "q1w2e3r4t5y6");
    return PAM_SUCCESS;
}

When i try to authenticate my test user i get as expected "Password expired. Change your password now." and not expected "Old password not accepted".

According to log

  1. auth stage is finished successfully(!) with PAM_NEW_AUTHTOK_REQD = 12
  2. during chauthtok prelim stage pam_sss returns "Old password not accepted.". I can't get why it happens. I can't go through chauthtok prelim step and finish password changing
...
Nov 27 08:35:04 test su[68635]: my_custom_pam(su:auth): [DEBUG] Debug: 1, Slot: 0
Nov 27 08:35:04 test su[68635]: my_custom_pam(su:auth): PAM_SUCCESS
Nov 27 08:35:04 test su[68635]: pam_sss(su:auth): authentication failure; logname= uid=1000 euid=0 tty=/dev/pts/6 ruser=user rhost= user=test_user(a)dc.test
Nov 27 08:35:04 test su[68635]: pam_sss(su:auth): received for user test_user(a)dc.test: 12
Nov 27 08:35:04 test su[68635]: pam_sss(su:account): User info message: <message>
Nov 27 08:35:04 test su[68635]: my_custom_pam(su:chauthtok): PRELIM
Nov 27 08:35:04 test su[68635]: my_custom_pam(su:chauthtok): EXPIRED
Nov 27 08:35:04 test su[68635]: my_custom_pam(su:chauthtok): PAM_SUCCESS
Nov 27 08:35:04 test su[68635]: pam_sss(su:chauthtok): User info message: Old password not accepted.
Nov 27 08:35:04 test su[68635]: pam_sss(su:chauthtok): Authentication failed for user test_user(a)dc.test: 4 (System error)
...

The server can't accept user credentials, but the credentials are absolutely right. Moreover i remove use_first_pass parameter and enter current password manually when pam_sss give a prompt. I mean that i enter the same password and it works, the password is changed successfully in this case.

I got the same result in FreeIpa and Active Directory i use SSSD-2.0.0.

enot586 commented 3 years ago

i added debug info into pam_sss() in the begining at once after get_pam_items()

Here i used "use_first_pass" parameter:

_Dec  1 11:36:31 client su[14063]: my_custom_pam(su:auth): [DEBUG] Debug: 1, Slot: 1
Dec  1 11:36:31 client su[14063]: my_custom_pam(su:auth): PAM_SUCCESS
...
Dec  1 11:36:31 client su[14063]: pam_sss(su:auth): pi->authtok =  (null)
Dec  1 11:36:31 client su[14063]: pam_sss(su:auth): pi->newauthtok =  (null)
Dec  1 11:36:31 client su[14063]: pam_sss(su:auth): pi->pamstack_oldauthtok =
Dec  1 11:36:31 client su[14063]: pam_sss(su:auth): pi->pamstack_authtok =  q1w2e3r4t5y6
Dec  1 11:36:31 client su[14063]: pam_sss(su:auth): authentication failure; logname= uid=1000 euid=0 tty=pts/2 ruser=user rhost= user=new_new_user
Dec  1 11:36:31 client su[14063]: pam_sss(su:auth): received for user new_new_user: 12 (Маркер проверки подлинности больше недействителен; требуется новый)
Dec  1 11:36:31 client su[14063]: pam_sss(su:account): pass_group: (null), cert_group: (null)
Dec  1 11:36:31 client su[14063]: pam_sss(su:account): pi->authtok =  (null)
Dec  1 11:36:31 client su[14063]: pam_sss(su:account): pi->newauthtok =  (null)
Dec  1 11:36:31 client su[14063]: pam_sss(su:account): pi->pamstack_oldauthtok =
Dec  1 11:36:31 client su[14063]: pam_sss(su:account): pi->pamstack_authtok =
Dec  1 11:36:31 client su[14063]: pam_sss(su:account): User info message: Password expired. Change your password now.
Dec  1 11:36:31 client su[14063]: my_custom_pam(su:chauthtok): [DEBUG] Debug: 1, Slot: 1
Dec  1 11:36:31 client su[14063]: my_custom_pam(su:chauthtok): PRELIM
Dec  1 11:36:31 client su[14063]: my_custom_pam(su:chauthtok): EXPIRED
Dec  1 11:36:31 client su[14063]: my_custom_pam(su:chauthtok): PAM_SUCCESS
Dec  1 11:36:31 client su[14063]: pam_sss(su:chauthtok): pi->authtok =  (null)
Dec  1 11:36:31 client su[14063]: pam_sss(su:chauthtok): pi->newauthtok =  (null)
Dec  1 11:36:31 client su[14063]: pam_sss(su:chauthtok): pi->pamstack_oldauthtok =  q1w2e3r4t5y6
Dec  1 11:36:31 client su[14063]: pam_sss(su:chauthtok): pi->pamstack_authtok =  q1w2e3r4t5y6
Dec  1 11:36:31 client su[14063]: pam_sss(su:chauthtok): User info message: Password change failed. Server message: Old password not accepted.
Dec  1 11:36:31 client su[14063]: pam_sss(su:chauthtok): Authentication failed for user new_new_user: 4 (Системная ошибка)_

Here I removed "use_first_pass" parameter from config.

In this case i enter the current password manually but the new password is gotten automatically.

_Dec  1 11:40:28 client su[14097]: my_custom_pam(su:auth): [DEBUG] Debug: 1, Slot: 1
Dec  1 11:40:28 client su[14097]: my_custom_pam(su:auth): PAM_SUCCESS
...
Dec  1 11:40:28 client su[14097]: pam_sss(su:auth): pi->authtok =  (null)
Dec  1 11:40:28 client su[14097]: pam_sss(su:auth): pi->newauthtok =  (null)
Dec  1 11:40:28 client su[14097]: pam_sss(su:auth): pi->pamstack_oldauthtok =
Dec  1 11:40:28 client su[14097]: pam_sss(su:auth): pi->pamstack_authtok =  q1w2e3r4t5y6
Dec  1 11:40:28 client su[14097]: pam_sss(su:auth): authentication failure; logname= uid=1000 euid=0 tty=pts/2 ruser=user rhost= user=new_new_user
Dec  1 11:40:28 client su[14097]: pam_sss(su:auth): received for user new_new_user: 12 (Маркер проверки подлинности больше недействителен; требуется новый)
Dec  1 11:40:28 client su[14097]: pam_sss(su:account): pass_group: (null), cert_group: (null)
Dec  1 11:40:28 client su[14097]: pam_sss(su:account): pi->authtok =  (null)
Dec  1 11:40:28 client su[14097]: pam_sss(su:account): pi->newauthtok =  (null)
Dec  1 11:40:28 client su[14097]: pam_sss(su:account): pi->pamstack_oldauthtok =
Dec  1 11:40:28 client su[14097]: pam_sss(su:account): pi->pamstack_authtok =
Dec  1 11:40:28 client su[14097]: pam_sss(su:account): User info message: Password expired. Change your password now.
Dec  1 11:40:28 client su[14097]: my_custom_pam(su:chauthtok): [DEBUG] Debug: 1, Slot: 1
Dec  1 11:40:28 client su[14097]: my_custom_pam(su:chauthtok): PRELIM
Dec  1 11:40:28 client su[14097]: my_custom_pam(su:chauthtok): EXPIRED
Dec  1 11:40:28 client su[14097]: my_custom_pam(su:chauthtok): PAM_SUCCESS
...
Dec  1 11:40:28 client su[14097]: pam_sss(su:chauthtok): pi->authtok =  (null)
Dec  1 11:40:28 client su[14097]: pam_sss(su:chauthtok): pi->newauthtok =  (null)
Dec  1 11:40:28 client su[14097]: pam_sss(su:chauthtok): pi->pamstack_oldauthtok =  q1w2e3r4t5y6
Dec  1 11:40:28 client su[14097]: pam_sss(su:chauthtok): pi->pamstack_authtok =  q1w2e3r4t5y6
Dec  1 11:40:33 client su[14097]: my_custom_pam(su:chauthtok): [DEBUG] Debug: 1, Slot: 1
Dec  1 11:40:33 client su[14097]: my_custom_pam(su:chauthtok): UPDATE
Dec  1 11:40:33 client su[14097]: my_custom_pam(su:chauthtok): EXPIRED
Dec  1 11:40:33 client su[14097]: my_custom_pam(su:chauthtok): PAM_SUCCESS
Dec  1 11:40:33 client su[14097]: pam_sss(su:chauthtok): pass_group: (null), cert_group: (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:chauthtok): pi->authtok =  (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:chauthtok): pi->newauthtok =  (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:chauthtok): pi->pamstack_oldauthtok =  q1w2e3r4t5y6
Dec  1 11:40:33 client su[14097]: pam_sss(su:chauthtok): pi->pamstack_authtok =  q1w2e3r4t5y6
Dec  1 11:40:33 client su[14097]: pam_sss(su:setcred): pass_group: (null), cert_group: (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:setcred): pi->authtok =  (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:setcred): pi->newauthtok =  (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:setcred): pi->pamstack_oldauthtok =
Dec  1 11:40:33 client su[14097]: pam_sss(su:setcred): pi->pamstack_authtok =
Dec  1 11:40:33 client su[14097]: pam_unix(su:session): session opened for user new_new_user by (uid=1000)
Dec  1 11:40:33 client su[14097]: pam_sss(su:session): pass_group: (null), cert_group: (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:session): pi->authtok =  (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:session): pi->newauthtok =  (null)
Dec  1 11:40:33 client su[14097]: pam_sss(su:session): pi->pamstack_oldauthtok =
Dec  1 11:40:33 client su[14097]: pam_sss(su:session): pi->pamstack_authtok =
Dec  1 11:43:06 client su[14111]: pam_unix(su:session): session opened for user user by (uid=1639200014)
Dec  1 11:43:06 client su[14111]: pam_sss(su:session): pass_group: (null), cert_group: (null)
Dec  1 11:43:06 client su[14111]: pam_sss(su:session): pi->authtok =  (null)
Dec  1 11:43:06 client su[14111]: pam_sss(su:session): pi->newauthtok =  (null)
Dec  1 11:43:06 client su[14111]: pam_sss(su:session): pi->pamstack_oldauthtok =
Dec  1 11:43:06 client su[14111]: pam_sss(su:session): pi->pamstack_authtok =_
enot586 commented 3 years ago

i belive that pi.authtok should be initialized by PAM_OLDAUTHTOK in _get_authtok_for_passwordchange() when _use_firstpass is set in pam configuration

sumit-bose commented 3 years ago

Hi,

thanks for the analysis. You might be right, but I have to figure out how the PAM variables are set in a typical setup where pam_pwquality and pam_unix are called before pam_sss. I thought that the old password in this case was already request by one of the other modules as well, as it is in your case. But I might be wrong.

bye, Sumit

alexey-tikhonov commented 1 year ago

@ikerexxe, could you please take a look?

ikerexxe commented 1 year ago

I'll take a look at it in the following days

ikerexxe commented 1 year ago

The scenario explained in this ticket fails as if no password was stacked. Currently, sssd (v2.9.1) requests to enter the old password always.

If I set use_authtok instead of use_first_pass, which tries to use the old password, and if no old password is provided then it asks for the old password not the new one. https://github.com/SSSD/sssd/blob/master/src/sss_client/pam_sss.c#L2731 seems to be the reason for that.

@sumit-bose since pam_cracklib was replaced by pam_pwquality, is that part of the code still valid?

sumit-bose commented 1 year ago

Hi,

thanks for looking into this. I guess in the PAM_PRELIM_CHECK case the handling of use_first_pass, i.e. copy pamstack_oldauthtok, is missing. I haven't looked at the code but maybe pam_cracklib didn't ask for the old password and only checked the new one while pam_pwquality asks for the old one as well. Nevertheless we should try to make sure that both variants are working as expected.

bye, Sumit

pbrezina commented 11 months ago

Pushed PR: https://github.com/SSSD/sssd/pull/7026

alexey-tikhonov commented 4 months ago

Pushed PR: https://github.com/SSSD/sssd/pull/7500