Browse Source

Resolves: 248924
Summary: Make password modify extended operation reset expired passwords.

Nathan Kinder 17 năm trước cách đây
mục cha
commit
2e7ad54fbe
2 tập tin đã thay đổi với 44 bổ sung11 xóa
  1. 18 6
      ldap/servers/slapd/passwd_extop.c
  2. 26 5
      ldap/servers/slapd/pw.c

+ 18 - 6
ldap/servers/slapd/passwd_extop.c

@@ -143,8 +143,8 @@ passwd_modify_getEntry( const char *dn, Slapi_Entry **e2 ) {
 /* Construct Mods pblock and perform the modify operation 
  * Sets result of operation in SLAPI_PLUGIN_INTOP_RESULT 
  */
-static int passwd_apply_mods(const char *dn, Slapi_Mods *mods, LDAPControl **req_controls,
-	LDAPControl ***resp_controls) 
+static int passwd_apply_mods(Slapi_PBlock *pb_orig, const char *dn, Slapi_Mods *mods,
+	LDAPControl **req_controls, LDAPControl ***resp_controls) 
 {
 	Slapi_PBlock pb;
 	LDAPControl **req_controls_copy = NULL;
@@ -168,7 +168,19 @@ static int passwd_apply_mods(const char *dn, Slapi_Mods *mods, LDAPControl **req
 			pw_get_componentID(), /* PluginID */
 			0); /* Flags */ 
 
+		/* We copy the connection from the original pblock into the
+		 * pblock we use for the internal modify operation.  We do
+		 * this to allow the password policy code to be able to tell
+		 * that the password change was initiated by the user who
+		 * sent the extended operation instead of always assuming
+		 * that it was done by the root DN. */
+		pb.pb_conn = pb_orig->pb_conn;
+
 		ret =slapi_modify_internal_pb (&pb);
+
+		/* We now clean up the connection that we copied into the
+		 * new pblock.  We want to leave it untouched. */
+		pb.pb_conn = NULL;
   
 		slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
 
@@ -195,8 +207,8 @@ static int passwd_apply_mods(const char *dn, Slapi_Mods *mods, LDAPControl **req
 
 
 /* Modify the userPassword attribute field of the entry */
-static int passwd_modify_userpassword(Slapi_Entry *targetEntry, const char *newPasswd,
-	LDAPControl **req_controls, LDAPControl ***resp_controls)
+static int passwd_modify_userpassword(Slapi_PBlock *pb_orig, Slapi_Entry *targetEntry,
+	const char *newPasswd, LDAPControl **req_controls, LDAPControl ***resp_controls)
 {
 	char *dn = NULL;
 	int ret = 0;
@@ -209,7 +221,7 @@ static int passwd_modify_userpassword(Slapi_Entry *targetEntry, const char *newP
 	slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, SLAPI_USERPWD_ATTR, newPasswd);
 
 
-	ret = passwd_apply_mods(dn, &smods, req_controls, resp_controls);
+	ret = passwd_apply_mods(pb_orig, dn, &smods, req_controls, resp_controls);
  
 	slapi_mods_done(&smods);
 	
@@ -770,7 +782,7 @@ parse_req_done:
 	slapi_pblock_get(pb, SLAPI_REQCONTROLS, &req_controls);
 	
 	/* Now we're ready to make actual password change */
-	ret = passwd_modify_userpassword(targetEntry, newPasswd, req_controls, &resp_controls);
+	ret = passwd_modify_userpassword(pb, targetEntry, newPasswd, req_controls, &resp_controls);
 
 	/* Set the response controls if necessary.  We want to do this now
 	 * so it is set for both the success and failure cases.  The pblock

+ 26 - 5
ldap/servers/slapd/pw.c

@@ -160,6 +160,7 @@ slapi_pw_find_sv(
 /* Checks if the specified value is encoded.
    Returns 1 if it is and 0 otherwise 
  */
+/* NGK - Use this for checking if the password is hashed */
 int slapi_is_encoded (char *value)
 {
 	struct pw_scheme *is_hashed = NULL;
@@ -554,6 +555,11 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
 	time_t          cur_time;
 	char 		*dn;
 	passwdPolicy *pwpolicy = NULL;
+	int internal_op = 0;
+	Slapi_Operation *operation = NULL;
+
+	slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
+	internal_op = slapi_operation_is_flag_set(operation, SLAPI_OP_FLAG_INTERNAL);
 
 	cur_time = current_time();
 	slapi_pblock_get( pb, SLAPI_TARGET_DN, &dn );
@@ -588,12 +594,13 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
 	/* Clear the passwordgraceusertime from the user entry */
 	slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordgraceusertime", "0");
 
-	/* if the password is reset by root, mark it the first time logon */
-	
-	if ( pb->pb_requestor_isroot == 1 && 
-	     pwpolicy->pw_must_change){
+	/* If the password is reset by root, mark it the first time logon.  If this is an internal
+	 * operation, we have a special case for the password modify extended operation where
+	 * we stuff the actual user who initiated the password change in pb_conn.  We check
+	 * for this special case to ensure we reset the expiration date properly. */
+	if ((internal_op && pwpolicy->pw_must_change && (!pb->pb_conn || slapi_dn_isroot(pb->pb_conn->c_dn))) ||
+		(!internal_op && pwpolicy->pw_must_change && (pb->pb_requestor_isroot == 1))) {
 		pw_exp_date = NO_TIME;
-
 	} else if ( pwpolicy->pw_exp == 1 ) {
 		Slapi_Entry *pse = NULL;
 
@@ -757,6 +764,20 @@ check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
 			int max_repeated = 0;
 			int num_categories = 0;
 
+			/* NGK - Check if password is already hashed and reject if so. */
+			/* NGK - Allow if root or if replication user */
+			if (slapi_is_encoded(slapi_value_get_string(vals[i]))) {
+				PR_snprintf( errormsg, BUFSIZ,
+					"invalid password syntax - pre-hashed passwords are not allowed");
+				if ( pwresponse_req == 1 ) {
+					slapi_pwpolicy_make_response_control ( pb, -1, -1,
+							LDAP_PWPOLICY_INVALIDPWDSYNTAX );
+				}
+				pw_send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, errormsg, 0, NULL );
+                                delete_passwdPolicy(&pwpolicy);
+				return( 1 );
+			}
+
 			/* check for the minimum password length */
 			if ( pwpolicy->pw_minlength >
 				ldap_utf8characters((char *)slapi_value_get_string( vals[i] )) )