浏览代码

Ticket #529 - dn normalization must handle multiple space characters in attributes

Bug description: If dn has a leaf rdn which contains space(s)
in the value (e.g., dn: cn=ABC DEF,...), it was allowed to add
entries which dn is identical but the number of the spaces
is different.  (e.g., dn: cn=ABC   DEF,...).

Fix description: Applying this patch, dn normalization changes
the behaviour so that multiple consecutive spaces are replaced
with one.  But in case the attribute value pair in the rdn is
not found in the entry and being added, the original spaces are
kept in the attribute value.  For instance, if an entry
  dn: cn=ABC  DEF,dc=example,dc=com
is added and the entry does not have
  cn: ABC  DEF
in it, then in the added entry, the dn would be normalized to
  dn: cn=ABC DEF,dc=example,dc=com
with the original cn value
  cn: ABC  DEF

In addition:
1) In entryrdn_rename_subtree, an error message was suppressed,
which is issued when replacing an rdn with the one which is
identical except the number of spaces (e.g., cn=ABC DEF -->
cn=ABC   DEF).
2) Fixed slapi_sdn_copy which used to trash the original dn
value.  Now it copies the original correctly.
3) Fixed a compiler warning in str2entry_fast.

Reviewed by Ludwig (Thank you!!)
Noriko Hosoi 13 年之前
父节点
当前提交
86ceedbcb6

+ 5 - 4
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c

@@ -573,7 +573,8 @@ entryrdn_rename_subtree(backend *be,
         }
         }
     }
     }
     if (NULL == mynewsrdn && NULL == mynewsupsdn) {
     if (NULL == mynewsrdn && NULL == mynewsupsdn) {
-        slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
+        /* E.g., rename dn: cn=ABC    DEF,... --> cn=ABC DEF,... */
+        slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
                         "entryrdn_rename_subtree: No new superior is given "
                         "entryrdn_rename_subtree: No new superior is given "
                         "and new rdn %s is identical to the original\n",
                         "and new rdn %s is identical to the original\n",
                         slapi_rdn_get_rdn(&oldsrdn));
                         slapi_rdn_get_rdn(&oldsrdn));
@@ -1162,7 +1163,7 @@ entryrdn_lookup_dn(backend *be,
                    const char *rdn,
                    const char *rdn,
                    ID id,
                    ID id,
                    char **dn,
                    char **dn,
-		   Slapi_RDN **psrdn,
+                   Slapi_RDN **psrdn,
                    back_txn *txn)
                    back_txn *txn)
 {
 {
     int rc = -1;
     int rc = -1;
@@ -1351,9 +1352,9 @@ bail:
     /* it is guaranteed that db is not NULL. */
     /* it is guaranteed that db is not NULL. */
     dblayer_release_index_file(be, ai, db);
     dblayer_release_index_file(be, ai, db);
     if (psrdn) {
     if (psrdn) {
-	*psrdn = srdn;
+        *psrdn = srdn;
     } else {
     } else {
-    	slapi_rdn_free(&srdn);
+        slapi_rdn_free(&srdn);
     }
     }
     slapi_ch_free_string(&nrdn);
     slapi_ch_free_string(&nrdn);
     slapi_ch_free_string(&keybuf);
     slapi_ch_free_string(&keybuf);

+ 4 - 4
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c

@@ -166,7 +166,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
          * it's passed to slapi_sdn_init_normdn_byref */
          * it's passed to slapi_sdn_init_normdn_byref */
         slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn );
         slapi_pblock_get( pb, SLAPI_MODRDN_NEWRDN, &newrdn );
         slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn );
         slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn );
-        slapi_sdn_init_normdn_byref(&dn_newrdn, newrdn);
+        slapi_sdn_init_dn_byref(&dn_newrdn, newrdn);
         /* slapi_sdn_init_normdn_byref(&dn_newsuperiordn, newsuperiordn); */
         /* slapi_sdn_init_normdn_byref(&dn_newsuperiordn, newsuperiordn); */
         slapi_sdn_get_parent(sdn, &dn_parentdn);
         slapi_sdn_get_parent(sdn, &dn_parentdn);
     }
     }
@@ -245,7 +245,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
             slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
             slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
             slapi_ch_free_string(&newrdn);
             slapi_ch_free_string(&newrdn);
             slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, original_newrdn);
             slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, original_newrdn);
-            slapi_sdn_set_normdn_byref(&dn_newrdn, original_newrdn);
+            slapi_sdn_set_dn_byref(&dn_newrdn, original_newrdn);
             original_newrdn = slapi_ch_strdup(original_newrdn);
             original_newrdn = slapi_ch_strdup(original_newrdn);
 
 
             slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
             slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn);
@@ -358,8 +358,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
                     /* newrdn is normalized, bu tno need to be case-ignored as 
                     /* newrdn is normalized, bu tno need to be case-ignored as 
                      * it's passed to slapi_sdn_init_normdn_byref */
                      * it's passed to slapi_sdn_init_normdn_byref */
                     slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
                     slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
-                    slapi_sdn_init_normdn_byref(&dn_newrdn, newrdn);
-                    newdn= moddn_get_newdn(pb,sdn, &dn_newrdn, dn_newsuperiordn);
+                    slapi_sdn_init_dn_byref(&dn_newrdn, newrdn);
+                    newdn = moddn_get_newdn(pb,sdn, &dn_newrdn, dn_newsuperiordn);
                     slapi_sdn_set_dn_passin(&dn_newdn,newdn);
                     slapi_sdn_set_dn_passin(&dn_newdn,newdn);
                     new_addr.sdn = &dn_newdn;
                     new_addr.sdn = &dn_newdn;
                     new_addr.udn = NULL;
                     new_addr.udn = NULL;

+ 30 - 2
ldap/servers/slapd/dn.c

@@ -912,7 +912,12 @@ slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len)
                 }
                 }
                 state = B4SEPARATOR;
                 state = B4SEPARATOR;
                 break;
                 break;
-            } else { /* else if (SEPARATOR(*s)) */
+            } else if (ISSPACE(*s)) {
+                /* remove extra spaces, e.g., "cn=ABC   DEF" --> "cn=ABC DEF" */
+                *d++ = *s++;
+                while (ISSPACE(*s))
+                    s++;
+            } else {
                 *d++ = *s++;
                 *d++ = *s++;
             }
             }
             if (state == INVALUE1ST) {
             if (state == INVALUE1ST) {
@@ -2419,7 +2424,30 @@ slapi_sdn_copy(const Slapi_DN *from, Slapi_DN *to)
 	SDN_DUMP( from, "slapi_sdn_copy from");
 	SDN_DUMP( from, "slapi_sdn_copy from");
 	SDN_DUMP( to, "slapi_sdn_copy to");
 	SDN_DUMP( to, "slapi_sdn_copy to");
 	slapi_sdn_done(to);
 	slapi_sdn_done(to);
-	slapi_sdn_set_normdn_byval(to, slapi_sdn_get_dn(from));
+	if (from->udn)
+	{
+		to->flag = slapi_setbit_uchar(to->flag, FLAG_UDN);
+		to->udn= slapi_ch_strdup(from->udn);
+		PR_INCREMENT_COUNTER(slapi_sdn_counter_udn_created);
+		PR_INCREMENT_COUNTER(slapi_sdn_counter_udn_exist);
+	}
+	if (from->dn)
+	{
+		to->flag = slapi_setbit_uchar(to->flag, FLAG_DN);
+		to->dn = slapi_ch_strdup(from->dn);
+		/* dn is normalized; strlen(dn) == strlen(ndn) */
+		to->ndn_len = strlen(to->dn);
+		PR_INCREMENT_COUNTER(slapi_sdn_counter_dn_created);
+		PR_INCREMENT_COUNTER(slapi_sdn_counter_dn_exist);
+	}
+	if (from->ndn)
+	{
+		to->flag = slapi_setbit_uchar(to->flag, FLAG_NDN);
+		to->ndn = slapi_ch_strdup(from->ndn);
+		to->ndn_len = strlen(to->ndn);
+		PR_INCREMENT_COUNTER(slapi_sdn_counter_ndn_created);
+		PR_INCREMENT_COUNTER(slapi_sdn_counter_ndn_exist);
+	}
 }
 }
 
 
 int
 int

+ 11 - 5
ldap/servers/slapd/entry.c

@@ -189,11 +189,13 @@ str2entry_fast( const char *rawdn, const Slapi_RDN *srdn, char *s, int flags, in
 	CSNSet *valuecsnset= NULL; /* Moved to this level so that the JCM csn_free call below gets useful */
 	CSNSet *valuecsnset= NULL; /* Moved to this level so that the JCM csn_free call below gets useful */
 	CSN *maxcsn = NULL;
 	CSN *maxcsn = NULL;
 	char *normdn = NULL;
 	char *normdn = NULL;
-	int strict = 0;
 	Slapi_Attr **a = NULL;
 	Slapi_Attr **a = NULL;
 
 
-    /* Check if we should be performing strict validation. */
-    strict = config_get_dn_validate_strict();
+#ifdef OBSOLETE_DN_SYNTAX_CHECK
+	int strict = 0;
+	/* Check if we should be performing strict validation. */
+	strict = config_get_dn_validate_strict();
+#endif
 
 
 	/*
 	/*
 	 * In string format, an entry looks like either of these:
 	 * In string format, an entry looks like either of these:
@@ -456,7 +458,7 @@ str2entry_fast( const char *rawdn, const Slapi_RDN *srdn, char *s, int flags, in
 			/* moved the value setting code here to check Slapi_Attr 'a'
 			/* moved the value setting code here to check Slapi_Attr 'a'
 			 * to retrieve the attribute syntax info */
 			 * to retrieve the attribute syntax info */
 			svalue = value_new(NULL, CSN_TYPE_NONE, NULL);
 			svalue = value_new(NULL, CSN_TYPE_NONE, NULL);
-#if 0
+#ifdef OBSOLETE_DN_SYNTAX_CHECK
 			if (slapi_attr_is_dn_syntax_attr(*a)) {
 			if (slapi_attr_is_dn_syntax_attr(*a)) {
 				int rc = 0;
 				int rc = 0;
 				char *dn_aval = NULL;
 				char *dn_aval = NULL;
@@ -3085,14 +3087,18 @@ slapi_entry_add_rdn_values( Slapi_Entry *e )
 {
 {
     const char *dn;
     const char *dn;
     char	**dns, **rdns;
     char	**dns, **rdns;
+    const Slapi_DN *sdn;
     int	i, rc = LDAP_SUCCESS;
     int	i, rc = LDAP_SUCCESS;
     Slapi_Value *foundVal;
     Slapi_Value *foundVal;
     Slapi_Attr *attr;
     Slapi_Attr *attr;
 
 
-    if ( NULL == e || (dn = slapi_entry_get_dn_const(e))==NULL ) {
+    if (NULL == e || NULL == (sdn = slapi_entry_get_sdn_const(e))) {
         return( LDAP_SUCCESS );
         return( LDAP_SUCCESS );
     }
     }
 
 
+    /* Preserve the original in case the RDN is missing as an attr-val pair
+     * in the entry. */
+    dn = slapi_sdn_get_udn(sdn);
     if (slapi_is_rootdse(dn)) {
     if (slapi_is_rootdse(dn)) {
         return( LDAP_SUCCESS );
         return( LDAP_SUCCESS );
     }
     }

+ 9 - 21
ldap/servers/slapd/modrdn.c

@@ -74,7 +74,6 @@ do_modrdn( Slapi_PBlock *pb )
 	BerElement	*ber;
 	BerElement	*ber;
 	char		*rawdn = NULL, *rawnewsuperior = NULL;
 	char		*rawdn = NULL, *rawnewsuperior = NULL;
 	const char	*dn = NULL, *newsuperior = NULL;
 	const char	*dn = NULL, *newsuperior = NULL;
-	char		*rawnewrdn = NULL;
 	char		*newrdn = NULL;
 	char		*newrdn = NULL;
 	int		err = 0, deloldrdn = 0;
 	int		err = 0, deloldrdn = 0;
 	ber_len_t	len = 0;
 	ber_len_t	len = 0;
@@ -106,8 +105,7 @@ do_modrdn( Slapi_PBlock *pb )
 	 *	}
 	 *	}
 	 */
 	 */
 
 
-	if ( ber_scanf( ber, "{aab", &rawdn, &rawnewrdn, &deloldrdn )
-	    == LBER_ERROR ) {
+	if (ber_scanf(ber, "{aab", &rawdn, &newrdn, &deloldrdn) == LBER_ERROR) {
 		LDAPDebug( LDAP_DEBUG_ANY,
 		LDAPDebug( LDAP_DEBUG_ANY,
 		    "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n",
 		    "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n",
 		    0, 0, 0 );
 		    0, 0, 0 );
@@ -128,7 +126,7 @@ do_modrdn( Slapi_PBlock *pb )
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			    "received newSuperior in LDAPv2 modrdn", 0, NULL );
 			    "received newSuperior in LDAPv2 modrdn", 0, NULL );
 			slapi_ch_free_string( &rawdn );
 			slapi_ch_free_string( &rawdn );
-			slapi_ch_free_string( &rawnewrdn );
+			slapi_ch_free_string( &newrdn );
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
 		if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) {
 		if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) {
@@ -139,7 +137,7 @@ do_modrdn( Slapi_PBlock *pb )
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			    "unable to decode newSuperior parameter", 0, NULL );
 			    "unable to decode newSuperior parameter", 0, NULL );
 			slapi_ch_free_string( &rawdn );
 			slapi_ch_free_string( &rawdn );
-			slapi_ch_free_string( &rawnewrdn );
+			slapi_ch_free_string( &newrdn );
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
 	}
 	}
@@ -154,19 +152,19 @@ do_modrdn( Slapi_PBlock *pb )
 			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
 			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
 							 NULL, "invalid dn", 0, NULL);
 							 NULL, "invalid dn", 0, NULL);
 			slapi_ch_free_string( &rawdn );
 			slapi_ch_free_string( &rawdn );
-			slapi_ch_free_string( &rawnewrdn );
+			slapi_ch_free_string( &newrdn );
 			slapi_ch_free_string( &rawnewsuperior );
 			slapi_ch_free_string( &rawnewsuperior );
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
 		/* check that the new rdn is formatted correctly */
 		/* check that the new rdn is formatted correctly */
-		err = slapi_dn_syntax_check(pb, rawnewrdn, 1);
+		err = slapi_dn_syntax_check(pb, newrdn, 1);
 		if (err) { /* syntax check failed */
 		if (err) { /* syntax check failed */
-			op_shared_log_error_access(pb, "MODRDN", rawnewrdn?rawnewrdn:"", 
+			op_shared_log_error_access(pb, "MODRDN", newrdn?newrdn:"", 
 							"strict: invalid new rdn");
 							"strict: invalid new rdn");
 			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
 			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
 							 NULL, "invalid new rdn", 0, NULL);
 							 NULL, "invalid new rdn", 0, NULL);
 			slapi_ch_free_string( &rawdn );
 			slapi_ch_free_string( &rawdn );
-			slapi_ch_free_string( &rawnewrdn );
+			slapi_ch_free_string( &newrdn );
 			slapi_ch_free_string( &rawnewsuperior );
 			slapi_ch_free_string( &rawnewsuperior );
 			goto free_and_return;
 			goto free_and_return;
 		}
 		}
@@ -178,20 +176,10 @@ do_modrdn( Slapi_PBlock *pb )
 		op_shared_log_error_access(pb, "MODRDN", rawdn, "invalid dn");
 		op_shared_log_error_access(pb, "MODRDN", rawdn, "invalid dn");
 		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, 
 		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, 
 		                 "invalid dn", 0, NULL);
 		                 "invalid dn", 0, NULL);
-		slapi_ch_free_string( &rawnewrdn );
+		slapi_ch_free_string( &newrdn );
 		slapi_ch_free_string( &rawnewsuperior );
 		slapi_ch_free_string( &rawnewsuperior );
 		goto free_and_return;
 		goto free_and_return;
 	}
 	}
-	newrdn = slapi_create_dn_string("%s", rawnewrdn);
-	if (rawnewrdn && (NULL == newrdn)) {
-		op_shared_log_error_access(pb, "MODRDN", rawnewrdn, "invalid newrdn");
-		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX,
-		                 NULL, "invalid newrdn", 0, NULL);
-		slapi_ch_free_string( &rawnewrdn );
-		slapi_ch_free_string( &rawnewsuperior );
-		goto free_and_return;
-	}
-	slapi_ch_free_string( &rawnewrdn );
 
 
 	if (rawnewsuperior) {
 	if (rawnewsuperior) {
 		if (config_get_dn_validate_strict()) {
 		if (config_get_dn_validate_strict()) {
@@ -219,7 +207,7 @@ do_modrdn( Slapi_PBlock *pb )
 	newdn = slapi_ch_smprintf("%s,%s", newrdn, parent);
 	newdn = slapi_ch_smprintf("%s,%s", newrdn, parent);
 	/* slapi_sdn_init_normdn_passin expects normalized but NOT
 	/* slapi_sdn_init_normdn_passin expects normalized but NOT
 	 * decapitalized dn */
 	 * decapitalized dn */
-	slapi_sdn_init_normdn_passin(&snewdn, newdn); /* newdn is normalized */
+	slapi_sdn_init_dn_passin(&snewdn, newdn);
 	if (0 == slapi_sdn_compare(&sdn, snewsuperior) ||
 	if (0 == slapi_sdn_compare(&sdn, snewsuperior) ||
 	    0 == slapi_sdn_compare(&snewdn, snewsuperior)) {
 	    0 == slapi_sdn_compare(&snewdn, snewsuperior)) {
 		op_shared_log_error_access(pb, "MODRDN", newsuperior,
 		op_shared_log_error_access(pb, "MODRDN", newsuperior,