svn commit: samba r21500 - in branches: SAMBA_3_0/source/nsswitch SAMBA_3_0_25/source/nsswitch

gd at samba.org gd at samba.org
Thu Feb 22 13:35:02 GMT 2007


Author: gd
Date: 2007-02-22 13:35:01 +0000 (Thu, 22 Feb 2007)
New Revision: 21500

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=21500

Log:
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

Modified:
   branches/SAMBA_3_0/source/nsswitch/pam_winbind.c
   branches/SAMBA_3_0/source/nsswitch/pam_winbind.h
   branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c
   branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.c
   branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.h
   branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c


Changeset:
Modified: branches/SAMBA_3_0/source/nsswitch/pam_winbind.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/pam_winbind.c	2007-02-22 13:15:49 UTC (rev 21499)
+++ branches/SAMBA_3_0/source/nsswitch/pam_winbind.c	2007-02-22 13:35:01 UTC (rev 21500)
@@ -198,6 +198,7 @@
 	_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 @@
 	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 @@
 		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,8 +1863,51 @@
 	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 
 int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
 		     int argc, const char **argv)
@@ -1948,9 +2003,6 @@
 			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,10 +2094,8 @@
 			goto out;
 		}
 
-		/* just in case we need krb5 creds after a password change over msrpc */
+		if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) {
 
-		if (ctrl & WINBIND_KRB5_AUTH) {
-
 			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);
 

Modified: branches/SAMBA_3_0/source/nsswitch/pam_winbind.h
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/pam_winbind.h	2007-02-22 13:15:49 UTC (rev 21499)
+++ branches/SAMBA_3_0/source/nsswitch/pam_winbind.h	2007-02-22 13:35:01 UTC (rev 21500)
@@ -99,6 +99,7 @@
 #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"

Modified: branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c
===================================================================
--- branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c	2007-02-22 13:15:49 UTC (rev 21499)
+++ branches/SAMBA_3_0/source/nsswitch/winbindd_pam.c	2007-02-22 13:35:01 UTC (rev 21500)
@@ -671,6 +671,17 @@
 			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;

Modified: branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.c
===================================================================
--- branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.c	2007-02-22 13:15:49 UTC (rev 21499)
+++ branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.c	2007-02-22 13:35:01 UTC (rev 21500)
@@ -198,6 +198,7 @@
 	_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 @@
 	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 @@
 		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,8 +1863,51 @@
 	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 
 int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
 		     int argc, const char **argv)
@@ -1948,9 +2003,6 @@
 			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,10 +2094,8 @@
 			goto out;
 		}
 
-		/* just in case we need krb5 creds after a password change over msrpc */
+		if (_pam_require_krb5_auth_after_chauthtok(pamh, ctrl, user)) {
 
-		if (ctrl & WINBIND_KRB5_AUTH) {
-
 			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);
 

Modified: branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.h
===================================================================
--- branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.h	2007-02-22 13:15:49 UTC (rev 21499)
+++ branches/SAMBA_3_0_25/source/nsswitch/pam_winbind.h	2007-02-22 13:35:01 UTC (rev 21500)
@@ -99,6 +99,7 @@
 #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"

Modified: branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c
===================================================================
--- branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c	2007-02-22 13:15:49 UTC (rev 21499)
+++ branches/SAMBA_3_0_25/source/nsswitch/winbindd_pam.c	2007-02-22 13:35:01 UTC (rev 21500)
@@ -671,6 +671,17 @@
 			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;



More information about the samba-cvs mailing list