From af3490061b83ce83efb363bddcbcccf9f8a14d89 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 2 May 2006 19:22:39 +0000 Subject: r15398: Attempt to send the correct warning when a password change was attempted too early. Guenther (This used to be commit 7f64a66d25f2a4aa48c2639da8e783c1759c5dd4) --- source3/nsswitch/pam_winbind.c | 45 +++++++++++++++++++++++++++++++---------- source3/nsswitch/pam_winbind.h | 1 + source3/nsswitch/winbindd_pam.c | 5 +++-- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index b2c3a01164..b340b8c6a7 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -320,7 +320,8 @@ static int winbind_auth_request(pam_handle_t * pamh, const char *pass, const char *member, const char *cctype, - int process_result) + int process_result, + time_t *pwd_last_set) { struct winbindd_request request; struct winbindd_response response; @@ -329,6 +330,10 @@ static int winbind_auth_request(pam_handle_t * pamh, ZERO_STRUCT(request); ZERO_STRUCT(response); + if (pwd_last_set) { + *pwd_last_set = 0; + } + strncpy(request.data.auth.user, user, sizeof(request.data.auth.user)-1); @@ -401,6 +406,10 @@ static int winbind_auth_request(pam_handle_t * pamh, ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user); + if (pwd_last_set) { + *pwd_last_set = response.data.auth.info3.pass_last_set_time; + } + if ((ctrl & WINBIND_KRB5_AUTH) && response.data.auth.krb5ccname[0] != '\0') { @@ -487,7 +496,8 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, int ctrl, const char *user, const char *oldpass, - const char *newpass) + const char *newpass, + time_t pwd_last_set) { struct winbindd_request request; struct winbindd_response response; @@ -541,7 +551,13 @@ static int winbind_chauthtok_request(pam_handle_t * pamh, /* FIXME: avoid to send multiple PAM messages after another */ switch (response.data.auth.reject_reason) { - case 0: + case -1: + break; + case REJECT_REASON_OTHER: + if ((response.data.auth.policy.min_passwordage > 0)) && + (pwd_last_set + response.data.auth.policy.min_passwordage > time(NULL)) { + PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_RECENT"); + } break; case REJECT_REASON_TOO_SHORT: PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT"); @@ -892,7 +908,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); /* Now use the username to look up password */ - retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True); + retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True, NULL); if (retval == PAM_NEW_AUTHTOK_REQD || retval == PAM_AUTHTOK_EXPIRED) { @@ -1174,6 +1190,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if (flags & PAM_PRELIM_CHECK) { + time_t pwdlastset_prelim = 0; + /* instruct user what is happening */ #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting) + strlen(user)); @@ -1198,16 +1216,18 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } /* verify that this is the password for this user */ - retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False); + retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False, &pwdlastset_prelim); - if (retval != PAM_ACCT_EXPIRED - && retval != PAM_AUTHTOK_EXPIRED - && retval != PAM_NEW_AUTHTOK_REQD - && retval != PAM_SUCCESS) { + if (retval != PAM_ACCT_EXPIRED && + retval != PAM_AUTHTOK_EXPIRED && + retval != PAM_NEW_AUTHTOK_REQD && + retval != PAM_SUCCESS) { pass_old = NULL; goto out; } + pam_set_data(pamh, PAM_WINBIND_PWD_LAST_SET, (void *)pwdlastset_prelim, _pam_winbind_cleanup_func); + retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); pass_old = NULL; if (retval != PAM_SUCCESS) { @@ -1215,6 +1235,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, } } else if (flags & PAM_UPDATE_AUTHTOK) { + time_t pwdlastset_update = 0; + /* * obtain the proposed password */ @@ -1272,8 +1294,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, * By reaching here we have approved the passwords and must now * rebuild the password database file. */ + pam_get_data( pamh, PAM_WINBIND_PWD_LAST_SET, (const void **)&pwdlastset_update); - retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new); + retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new, pwdlastset_update); if (retval) { _pam_overwrite(pass_new); _pam_overwrite(pass_old); @@ -1288,7 +1311,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, const char *member = get_member_from_config(argc, argv, ctrl, d); const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl, d); - retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False); + retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False, NULL); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_old = pass_new = NULL; diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h index 89553ebfc3..38fe365f4c 100644 --- a/source3/nsswitch/pam_winbind.h +++ b/source3/nsswitch/pam_winbind.h @@ -107,6 +107,7 @@ do { \ #define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD" #define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR" +#define PAM_WINBIND_PWD_LAST_SET "PAM_WINBIND_PWD_LAST_SET" #define SECONDS_PER_DAY 86400 diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 9e4fd39707..ad2127452c 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -1652,6 +1652,9 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state) oldpass = state->request.data.chauthtok.oldpass; newpass = state->request.data.chauthtok.newpass; + /* Initialize reject reason */ + state->response.data.auth.reject_reason = Undefined; + /* Get sam handle */ result = cm_connect_sam(contact_domain, state->mem_ctx, &cli, @@ -1690,8 +1693,6 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state) DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n", nt_errstr(result))); - state->response.data.auth.reject_reason = 0; - result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass); } -- cgit