From 0d538f7370f13b175f127f061d5bff18e631cd5e Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Thu, 11 Jan 2007 15:41:02 +0000 Subject: r20687: Implement grace logons for offline authentications in pam_winbind. 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 | 23 ++++++++++++++++++++--- source3/nsswitch/pam_winbind.h | 3 +++ source3/nsswitch/winbindd_pam.c | 40 ++++++++++++++++++++++------------------ 3 files changed, 45 insertions(+), 21 deletions(-) (limited to 'source3') diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c index 6b683d682d..f0a60233c5 100644 --- a/source3/nsswitch/pam_winbind.c +++ b/source3/nsswitch/pam_winbind.c @@ -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 */ diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h index e817c5a840..87307d740d 100644 --- a/source3/nsswitch/pam_winbind.h +++ b/source3/nsswitch/pam_winbind.h @@ -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))) diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 47721b1bb0..70007d481c 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -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; } -- cgit