summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGünther Deschner <gd@samba.org>2007-02-22 13:35:01 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:18:08 -0500
commit9684e353a16cd18424f5b35a5d84ae3c2a03ae70 (patch)
treef254fcf8660eb7988d1b1f58168f1fbd7df7f81a
parentca229b0980b5c78f140180db764b3229d5ccb078 (diff)
downloadsamba-9684e353a16cd18424f5b35a5d84ae3c2a03ae70.tar.gz
samba-9684e353a16cd18424f5b35a5d84ae3c2a03ae70.tar.bz2
samba-9684e353a16cd18424f5b35a5d84ae3c2a03ae70.zip
r21500: Fix inappropriate creation of a krb5 ticket refreshing event when a user
changed a password via pam_chauthtok. Only do this if a) a user logs on using an expired password (or a password that needs to be changed immediately) or b) the user itself changes his password. Also make sure to delete the in-memory krb5 credential cache (when a user did not request a FILE based cred cache). Finally honor the krb5 settings in the first pam authentication in the chauthtok block (PAM_PRELIM_CHECK). This circumvents confusion when NTLM samlogon authentication is still possible with the old password after the password has been already changed (on w2k3 sp1 dcs). Guenther (This used to be commit c3005c48cd86bc1dd17fab80da05c2d34071b872)
-rw-r--r--source3/nsswitch/pam_winbind.c62
-rw-r--r--source3/nsswitch/pam_winbind.h1
-rw-r--r--source3/nsswitch/winbindd_pam.c11
3 files changed, 68 insertions, 6 deletions
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
index d2979ed71c..ac87fcf32e 100644
--- a/source3/nsswitch/pam_winbind.c
+++ b/source3/nsswitch/pam_winbind.c
@@ -198,6 +198,7 @@ static void _pam_log_state(const pam_handle_t *pamh, int ctrl)
_PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_LOGONSERVER);
_PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_PROFILEPATH);
_PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD); /* Use atoi to get PAM result code */
+ _PAM_LOG_STATE_DATA_STRING(pamh, ctrl, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH);
_PAM_LOG_STATE_DATA_POINTER(pamh, ctrl, PAM_WINBIND_PWD_LAST_SET);
}
@@ -1564,6 +1565,8 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
if (retval == PAM_NEW_AUTHTOK_REQD ||
retval == PAM_AUTHTOK_EXPIRED) {
+ char *new_authtok_required_during_auth = NULL;
+
if (!asprintf(&new_authtok_required, "%d", retval)) {
retval = PAM_BUF_ERR;
goto out;
@@ -1572,6 +1575,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, new_authtok_required, _pam_winbind_cleanup_func);
retval = PAM_SUCCESS;
+
+ if (!asprintf(&new_authtok_required_during_auth, "%d", True)) {
+ retval = PAM_BUF_ERR;
+ goto out;
+ }
+
+ pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH,
+ new_authtok_required_during_auth, _pam_winbind_cleanup_func);
+
goto out;
}
@@ -1851,6 +1863,49 @@ out:
return retval;
}
+/**
+ * evaluate whether we need to re-authenticate with kerberos after a password change
+ *
+ * @param pamh PAM handle
+ * @param ctrl PAM winbind options.
+ * @param user The username
+ *
+ * @return boolean Returns True if required, False if not.
+ */
+
+static BOOL _pam_require_krb5_auth_after_chauthtok(pam_handle_t *pamh, int ctrl, const char *user)
+{
+
+ /* Make sure that we only do this if
+ * a) the chauthtok got initiated during a logon attempt (authenticate->acct_mgmt->chauthtok)
+ * b) any later password change via the "passwd" command if done by the user itself
+ */
+
+ char *new_authtok_reqd_during_auth = NULL;
+ struct passwd *pwd = NULL;
+
+ if (!(ctrl & WINBIND_KRB5_AUTH)) {
+ return False;
+ }
+
+ _pam_get_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, &new_authtok_reqd_during_auth);
+ pam_set_data(pamh, PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH, NULL, NULL);
+
+ if (new_authtok_reqd_during_auth) {
+ return True;
+ }
+
+ pwd = getpwnam(user);
+ if (!pwd) {
+ return False;
+ }
+
+ if (getuid() == pwd->pw_uid) {
+ return True;
+ }
+
+ return False;
+}
PAM_EXTERN
@@ -1948,9 +2003,6 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
goto out;
}
- /* We don't need krb5 env set for password change test. */
- ctrl &= ~WINBIND_KRB5_AUTH;
-
/* verify that this is the password for this user */
ret = winbind_auth_request(pamh, ctrl, user, pass_old,
@@ -2042,9 +2094,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
goto out;
}
- /* just in case we need krb5 creds after a password change over msrpc */
-
- if (ctrl & WINBIND_KRB5_AUTH) {
+ if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) {
const char *member = get_member_from_config(pamh, argc, argv, ctrl, d);
const char *cctype = get_krb5_cc_type_from_config(pamh, argc, argv, ctrl, d);
diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h
index 05fc2e128e..73da2826ca 100644
--- a/source3/nsswitch/pam_winbind.h
+++ b/source3/nsswitch/pam_winbind.h
@@ -99,6 +99,7 @@ do { \
#define off(x, y) (!(x & y))
#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD"
+#define PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH "PAM_WINBIND_NEW_AUTHTOK_REQD_DURING_AUTH"
#define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR"
#define PAM_WINBIND_LOGONSCRIPT "PAM_WINBIND_LOGONSCRIPT"
#define PAM_WINBIND_LOGONSERVER "PAM_WINBIND_LOGONSERVER"
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 98f76bea92..69e004ec71 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -671,6 +671,17 @@ static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n",
nt_errstr(result)));
}
+ } else {
+
+ /* need to delete the memory cred cache, it is not used anymore */
+
+ krb5_ret = ads_kdestroy(cc);
+ if (krb5_ret) {
+ DEBUG(3,("winbindd_raw_kerberos_login: "
+ "could not destroy krb5 credential cache: "
+ "%s\n", error_message(krb5_ret)));
+ }
+
}
result = NT_STATUS_OK;