r15398: Attempt to send the correct warning when a password change was attempted
authorGünther Deschner <gd@samba.org>
Tue, 2 May 2006 19:22:39 +0000 (19:22 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:16:40 +0000 (11:16 -0500)
too early.

Guenther
(This used to be commit 7f64a66d25f2a4aa48c2639da8e783c1759c5dd4)

source3/nsswitch/pam_winbind.c
source3/nsswitch/pam_winbind.h
source3/nsswitch/winbindd_pam.c

index b2c3a01164302eab017731a51afa0254f51d1947..b340b8c6a766550fed436b61682c4eea6cffb807 100644 (file)
@@ -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;
index 89553ebfc385406cb23345e23401eaefa92812e1..38fe365f4c5ad7ca38b89641bd963db88585832e 100644 (file)
@@ -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
 
index 9e4fd3970730f2c3b37b8df447a174adef01b18f..ad2127452ca30f1439c537d38c9da281436afda5 100644 (file)
@@ -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);
        }