r20687: Implement grace logons for offline authentications in pam_winbind.
authorGünther Deschner <gd@samba.org>
Thu, 11 Jan 2007 15:41:02 +0000 (15:41 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:17:02 +0000 (12:17 -0500)
In case a user authenticated sucessfully and his password just expired
while beeing disconnected, we should allow a user to logon (given a
clear warning). We currently forced the user into a password change
dialogue in that scenario; this did not make much sense while offline.

Guenther
(This used to be commit 668b278653acfc4de7807834988f7af557e608a5)

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

index 6b683d682d8dfa568ae2d0147e80cdcda15f6ab1..f0a60233c55792139083e5c88ffb735615645560 100644 (file)
@@ -420,6 +420,11 @@ static void _pam_warn_password_expires_in_future(pam_handle_t *pamh, struct winb
                return;
        }
 
+       /* no point in sending a warning if this is a grace logon */
+       if (PAM_WB_GRACE_LOGON(response->data.auth.info3.user_flgs)) {
+               return;
+       }
+
        /* check if the info3 must change timestamp has been set */
        next_change = response->data.auth.info3.pass_must_change_time;
 
@@ -586,6 +591,7 @@ static int winbind_auth_request(pam_handle_t * pamh,
        /* handle the case where the auth was ok, but the password must expire right now */
        /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */
        if ( ! (response.data.auth.info3.acct_flags & ACB_PWNOEXP) &&
+            ! (PAM_WB_GRACE_LOGON(response.data.auth.info3.user_flgs)) &&
            (response.data.auth.policy.expire > 0) && 
            (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) {
 
@@ -604,9 +610,20 @@ static int winbind_auth_request(pam_handle_t * pamh,
        /* warn a user if the password is about to expire soon */
        _pam_warn_password_expires_in_future(pamh, &response);
 
-       if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) {
-               _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable");
-               _pam_log_debug(pamh, ctrl, LOG_DEBUG,"User %s logged on using cached account\n", user);
+       /* inform about logon type */
+       if (PAM_WB_GRACE_LOGON(response.data.auth.info3.user_flgs)) {
+
+               _make_remark(pamh, PAM_ERROR_MSG, 
+                       "Grace login. Please change your password as soon you're online again");
+               _pam_log_debug(pamh, ctrl, LOG_DEBUG,
+                       "User %s logged on using grace logon\n", user);
+
+       } else if (PAM_WB_CACHED_LOGON(response.data.auth.info3.user_flgs)) {
+
+               _make_remark(pamh, PAM_ERROR_MSG, 
+                       "Logging on using cached account. Network ressources can be unavailable");
+               _pam_log_debug(pamh, ctrl, LOG_DEBUG,
+                       "User %s logged on using cached account\n", user);
        }
 
        /* save the CIFS homedir for pam_cifs / pam_mount */
index e817c5a840fbdf0fb06ea605e9ca577a943e7ba3..87307d740d82bd88fc53f82db3c0920ca0abe476 100644 (file)
@@ -164,4 +164,7 @@ do {                             \
 
 /* from include/rpc_netlogon.h */
 #define LOGON_CACHED_ACCOUNT           0x00000004
+#define LOGON_GRACE_LOGON              0x01000000
 
+#define PAM_WB_CACHED_LOGON(x) (x & LOGON_CACHED_ACCOUNT)
+#define PAM_WB_GRACE_LOGON(x)  ((LOGON_CACHED_ACCOUNT|LOGON_GRACE_LOGON) == ( x & (LOGON_CACHED_ACCOUNT|LOGON_GRACE_LOGON)))
index 47721b1bb059a1e7e6cbf85ab2c3c842d4909dcf..70007d481c620dfd89873f2494d8663ecd6942c8 100644 (file)
@@ -826,26 +826,12 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
 
                must_change_time = nt_time_to_unix(my_info3->pass_must_change_time);
                if (must_change_time != 0 && must_change_time < time(NULL)) {
-                       return NT_STATUS_PASSWORD_EXPIRED;
+                       /* we allow grace logons when the password has expired */
+                       my_info3->user_flgs |= LOGON_GRACE_LOGON;
+                       /* return NT_STATUS_PASSWORD_EXPIRED; */
+                       goto success;
                }
        
-               /* FIXME: we possibly should handle logon hours as well (does xp when
-                * offline?) see auth/auth_sam.c:sam_account_ok for details */
-
-               unix_to_nt_time(&my_info3->logon_time, time(NULL));
-               my_info3->bad_pw_count = 0;
-
-               result = winbindd_update_creds_by_info3(domain,
-                                                       state->mem_ctx,
-                                                       state->request.data.auth.user,
-                                                       state->request.data.auth.pass,
-                                                       my_info3);
-               if (!NT_STATUS_IS_OK(result)) {
-                       DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n",
-                               nt_errstr(result)));
-                       return result;
-               }
-
 #ifdef HAVE_KRB5
                /* FIXME: what else points out that the remote domain is AD ? */
                if (!strequal(domain->name, domain->alt_name) &&
@@ -909,6 +895,24 @@ NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
                        }
                }
 #endif /* HAVE_KRB5 */
+ success:
+               /* FIXME: we possibly should handle logon hours as well (does xp when
+                * offline?) see auth/auth_sam.c:sam_account_ok for details */
+
+               unix_to_nt_time(&my_info3->logon_time, time(NULL));
+               my_info3->bad_pw_count = 0;
+
+               result = winbindd_update_creds_by_info3(domain,
+                                                       state->mem_ctx,
+                                                       state->request.data.auth.user,
+                                                       state->request.data.auth.pass,
+                                                       my_info3);
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(1,("winbindd_dual_pam_auth_cached: failed to update creds: %s\n",
+                               nt_errstr(result)));
+                       return result;
+               }
+
                return NT_STATUS_OK;
 
        }