瀏覽代碼

Update to New DN Format

Fix Description:
. adding slapi_dn_normalize_ext and its siblings to normalize/validate
  invalid DNs; deprecating slapi_dn_normalize and its siblings. (dn.c)
. replacing slapi_dn_normalize with new corresponding functions.
. normalizing hardcoded DNs (e.g., removing spaces around ',')
. setting correct DN syntax to nsslapd-suffix, nsslapd-ldapiautodnsuffix,
  costemplatedn, nsslapd-changelogsuffix, nsBaseDN, nsBindDN
. if nsslapd-dn-validate-strict is enabled, incoming DN is examined and
  rejected if it is invalid.  Once approved, the DN is normalized.
. fixing compiler warnings and typos.

See also:
http://directory.fedoraproject.org/wiki/Upgrade_to_New_DN_Format

Related bugs:
Bug 199923 - subtree search fails to find items under a db containing special
             characters
Bug 567968 - subtree/user level password policy created using 389-ds-console
             doesn't work.
Bug 570107 - The import of LDIFs with base-64 encoded DNs fails, modrdn with
             non-ASCII new rdn incorrect
Bug 570962 - ns-inactivate.pl does not work
Bug 572785 - DN syntax: old style of DN <type>="<DN>",<the_rest> is not
             correctly normalized
Bug 573060 - DN normalizer: ESC HEX HEX is not normalized
Bug 574167 - An escaped space at the end of the RDN value is not handled
             correctly
Noriko Hosoi 15 年之前
父節點
當前提交
78c50664d6
共有 83 個文件被更改,包括 3020 次插入780 次删除
  1. 1 1
      ldap/admin/src/scripts/Migration.pm.in
  2. 1 1
      ldap/admin/src/scripts/Setup.pm.in
  3. 2 0
      ldap/schema/01core389.ldif
  4. 2 1
      ldap/schema/02common.ldif
  5. 2 2
      ldap/schema/30ns-common.ldif
  6. 25 31
      ldap/servers/plugins/acl/acl.c
  7. 6 1
      ldap/servers/plugins/acl/acl.h
  8. 1 1
      ldap/servers/plugins/acl/acl_ext.c
  9. 1 0
      ldap/servers/plugins/acl/aclanom.c
  10. 32 15
      ldap/servers/plugins/acl/acleffectiverights.c
  11. 167 34
      ldap/servers/plugins/acl/acllas.c
  12. 216 170
      ldap/servers/plugins/acl/aclparse.c
  13. 14 3
      ldap/servers/plugins/acl/aclproxy.c
  14. 54 12
      ldap/servers/plugins/acl/aclutil.c
  15. 7 3
      ldap/servers/plugins/chainingdb/cb_config.c
  16. 3 1
      ldap/servers/plugins/chainingdb/cb_init.c
  17. 4 4
      ldap/servers/plugins/chainingdb/cb_instance.c
  18. 117 10
      ldap/servers/plugins/cos/cos_cache.c
  19. 40 13
      ldap/servers/plugins/dna/dna.c
  20. 2 2
      ldap/servers/plugins/linkedattrs/fixup_task.c
  21. 1 3
      ldap/servers/plugins/mep/mep.c
  22. 2 2
      ldap/servers/plugins/pwdstorage/smd5_pwd.c
  23. 33 4
      ldap/servers/plugins/referint/referint.c
  24. 1 0
      ldap/servers/plugins/replication/legacy_consumer.c
  25. 1 1
      ldap/servers/plugins/replication/repl5.h
  26. 14 5
      ldap/servers/plugins/replication/repl5_agmt.c
  27. 2 1
      ldap/servers/plugins/replication/repl5_agmtlist.c
  28. 0 1
      ldap/servers/plugins/replication/repl5_protocol.c
  29. 25 2
      ldap/servers/plugins/replication/repl5_replica.c
  30. 1 0
      ldap/servers/plugins/replication/repl5_replica_config.c
  31. 1 0
      ldap/servers/plugins/replication/repl_init.c
  32. 1 0
      ldap/servers/plugins/retrocl/retrocl.c
  33. 12 1
      ldap/servers/plugins/retrocl/retrocl_create.c
  34. 127 39
      ldap/servers/plugins/syntaxes/string.c
  35. 1 0
      ldap/servers/plugins/syntaxes/syntax.h
  36. 0 12
      ldap/servers/plugins/syntaxes/validate.c
  37. 81 9
      ldap/servers/plugins/syntaxes/value.c
  38. 9 2
      ldap/servers/plugins/usn/usn_cleanup.c
  39. 40 13
      ldap/servers/slapd/add.c
  40. 6 0
      ldap/servers/slapd/attrlist.c
  41. 17 0
      ldap/servers/slapd/attrsyntax.c
  42. 42 8
      ldap/servers/slapd/auth.c
  43. 1 0
      ldap/servers/slapd/back-ldbm/import-threads.c
  44. 16 3
      ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c
  45. 67 23
      ldap/servers/slapd/back-ldbm/ldbm_config.c
  46. 35 15
      ldap/servers/slapd/back-ldbm/ldbm_index_config.c
  47. 132 35
      ldap/servers/slapd/back-ldbm/ldbm_instance_config.c
  48. 0 7
      ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
  49. 1 0
      ldap/servers/slapd/back-ldbm/ldbm_search.c
  50. 1 0
      ldap/servers/slapd/back-ldbm/ldif2ldbm.c
  51. 2 2
      ldap/servers/slapd/back-ldbm/misc.c
  52. 1 1
      ldap/servers/slapd/back-ldbm/nextid.c
  53. 55 23
      ldap/servers/slapd/back-ldbm/vlv.c
  54. 21 7
      ldap/servers/slapd/backend.c
  55. 0 6
      ldap/servers/slapd/backend_manager.c
  56. 31 3
      ldap/servers/slapd/bind.c
  57. 29 2
      ldap/servers/slapd/compare.c
  58. 29 2
      ldap/servers/slapd/delete.c
  59. 705 80
      ldap/servers/slapd/dn.c
  60. 211 43
      ldap/servers/slapd/entry.c
  61. 9 0
      ldap/servers/slapd/entrywsi.c
  62. 32 5
      ldap/servers/slapd/extendop.c
  63. 1 0
      ldap/servers/slapd/fedse.c
  64. 6 5
      ldap/servers/slapd/libglobs.c
  65. 4 0
      ldap/servers/slapd/main.c
  66. 54 35
      ldap/servers/slapd/mapping_tree.c
  67. 31 4
      ldap/servers/slapd/modify.c
  68. 101 7
      ldap/servers/slapd/modrdn.c
  69. 28 2
      ldap/servers/slapd/modutil.c
  70. 32 3
      ldap/servers/slapd/passwd_extop.c
  71. 19 7
      ldap/servers/slapd/plugin.c
  72. 1 1
      ldap/servers/slapd/plugin_syntax.c
  73. 33 2
      ldap/servers/slapd/search.c
  74. 2 2
      ldap/servers/slapd/slap.h
  75. 61 6
      ldap/servers/slapd/slapi-plugin.h
  76. 2 0
      ldap/servers/slapd/slapi-private.h
  77. 2 1
      ldap/servers/slapd/snmp_collator.c
  78. 30 20
      ldap/servers/slapd/task.c
  79. 1 1
      ldap/servers/slapd/tools/dbscan.c
  80. 1 0
      ldap/servers/slapd/tools/ldclt/ldclt.h
  81. 79 19
      ldap/servers/slapd/util.c
  82. 26 0
      ldap/servers/slapd/value.c
  83. 14 0
      ldap/servers/slapd/valueset.c

+ 1 - 1
ldap/admin/src/scripts/Migration.pm.in

@@ -125,7 +125,7 @@ You can supply default .inf data in this format:
 e.g.
     General.FullMachineName=foo.example.com
 or
-    "slapd.Suffix=dc=example, dc=com"
+    "slapd.Suffix=dc=example,dc=com"
 Values passed in this manner will override values in an .inf file
 given with the -f argument.
 

+ 1 - 1
ldap/admin/src/scripts/Setup.pm.in

@@ -110,7 +110,7 @@ You can supply default .inf data in this format:
 e.g.
     General.FullMachineName=foo.example.com
 or
-    "slapd.Suffix=dc=example, dc=com"
+    "slapd.Suffix=dc=example,dc=com"
 Values passed in this manner will override values in an .inf file given with the -f argument.
 EOF
 }

+ 2 - 0
ldap/schema/01core389.ldif

@@ -122,6 +122,8 @@ attributeTypes: ( nsSSLSupportedCiphers-oid NAME 'nsSSLSupportedCiphers' DESC 'N
 attributeTypes: ( nsSSLToken-oid NAME 'nsSSLToken' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
 attributeTypes: ( nsSSLPersonalitySSL-oid NAME 'nsSSLPersonalitySSL' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
 attributeTypes: ( nsSSLActivation-oid NAME 'nsSSLActivation' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2091 NAME 'nsslapd-suffix' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2092 NAME 'nsslapd-ldapiautodnsuffix' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
 #
 # objectclasses
 #

+ 2 - 1
ldap/schema/02common.ldif

@@ -110,7 +110,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.223 NAME ( 'passwordResetFailureCount' '
 attributeTypes: ( 2.16.840.1.113730.3.1.550 NAME 'cosAttribute' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.551 NAME 'cosspecifier' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.552 NAME 'costargettree' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
-attributeTypes: ( 2.16.840.1.113730.3.1.553 NAME 'costemplatedn' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.553 NAME 'costemplatedn' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.35 NAME 'changeLog' DESC 'the distinguished name of the entry which contains the set of entries comprising this servers changelog' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Changelog Internet Draft' )
 attributeTypes: ( 2.16.840.1.113730.3.1.200 NAME 'changeLogMaximumAge' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.201 NAME 'changeLogMaximumSize' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
@@ -144,6 +144,7 @@ attributeTypes: ( 1.3.6.1.1.4 NAME 'vendorName' EQUALITY 1.3.6.1.4.1.1466.109.11
 attributeTypes: ( 1.3.6.1.1.5 NAME 'vendorVersion' EQUALITY 1.3.6.1.4.1.1466.109.114.1 SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation X-ORIGIN 'RFC 3045' )
 attributeTypes: ( 2.16.840.1.113730.3.1.3023 NAME 'nsViewFilter' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Netscape Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2063 NAME 'nsEncryptionAlgorithm' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2093 NAME 'nsslapd-changelogsuffix' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
 #
 # objectclasses:
 #

+ 2 - 2
ldap/schema/30ns-common.ldif

@@ -42,8 +42,8 @@
 #
 dn: cn=schema
 attributeTypes: ( nsServerID-oid NAME 'nsServerID' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
-attributeTypes: ( nsBaseDN-oid NAME 'nsBaseDN' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
-attributeTypes: ( nsBindDN-oid NAME 'nsBindDN' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
+attributeTypes: ( nsBaseDN-oid NAME 'nsBaseDN' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
+attributeTypes: ( nsBindDN-oid NAME 'nsBindDN' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'Netscape' )
 attributeTypes: ( nsBindPassword-oid NAME 'nsBindPassword' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
 attributeTypes: ( nsServerPort-oid NAME 'nsServerPort' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )
 attributeTypes: ( nsServerAddress-oid NAME 'nsServerAddress' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )

+ 25 - 31
ldap/servers/plugins/acl/acl.c

@@ -358,8 +358,8 @@ acl_access_allowed(
 		if (oid && ((strcasecmp(oid, DN_SYNTAX_OID) == 0) ||
 		            (strcasecmp(oid, NAMEANDOPTIONALUID_SYNTAX_OID) == 0))) { 
 			/* should use slapi_sdn_compare() but that'a an extra malloc/free */
-			char *dn_val_to_write = slapi_dn_normalize(slapi_ch_strdup(val->bv_val));
-			if ( aclpb->aclpb_authorization_sdn && 
+			char *dn_val_to_write = slapi_create_dn_string("%s", val->bv_val);
+			if ( dn_val_to_write && aclpb->aclpb_authorization_sdn && 
 					slapi_utf8casecmp((ACLUCHP)dn_val_to_write, (ACLUCHP)
 					slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn)) == 0) { 
 				access |= SLAPI_ACL_SELF;
@@ -754,9 +754,10 @@ static void print_access_control_summary( char *source, int ret_val, char *clien
 
 		if ( aclpb->aclpb_authorization_sdn != NULL ) {
 
-				proxy_user = (char *)(aclpb->aclpb_authorization_sdn->ndn ?
-										aclpb->aclpb_authorization_sdn->ndn:
-										null_user);
+				proxy_user = 
+					(char *)(slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn)?
+					slapi_sdn_get_ndn(aclpb->aclpb_authorization_sdn):
+					null_user);
 
 				slapi_log_error(loglevel, plugin_name, 
 		"conn=%" NSPRIu64 " op=%d (%s): %s %s on entry(%s).attr(%s) to proxy (%s)"
@@ -1764,8 +1765,7 @@ acl_modified (Slapi_PBlock *pb, int optype, char *n_dn, void *change)
 		if (parent_DN == NULL) {
 			new_DN = new_RDN;
 		} else {
-			new_DN = slapi_ch_smprintf("%s,%s", new_RDN, parent_DN);
-			slapi_dn_normalize (new_DN);
+			new_DN = slapi_create_dn_string("%s,%s", new_RDN, parent_DN);
 		}
 
 		/* Change the acls */
@@ -2028,8 +2028,7 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *
 	** We have a single ACI which we need to find if it applies to
 	** the resource or not.
 	*/
-	if ((aci->aci_type & ACI_TARGET_DN) && 
-			(aclpb->aclpb_curr_entry_sdn)) {
+	if ((aci->aci_type & ACI_TARGET_DN) && (aclpb->aclpb_curr_entry_sdn)) {
 		char		*avaType;
 		struct berval	*avaValue;		
 
@@ -2246,10 +2245,10 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *
 	 *
 	*/
 
-	if ((aclpb->aclpb_access & SLAPI_ACL_ADD &&
-		aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS )||
-		(aclpb->aclpb_access & SLAPI_ACL_DELETE && 
-		aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS ) ) {
+	if (((aclpb->aclpb_access & SLAPI_ACL_ADD) &&
+		 (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) )||
+		((aclpb->aclpb_access & SLAPI_ACL_DELETE) && 
+		 (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS) ) ) {
 		
 			Targetattrfilter **attrFilterArray;
 
@@ -2367,10 +2366,10 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *
 			goto acl__resource_match_aci_EXIT;	
 		}
 
-	} else  if ( (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD &&
-                   aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) ||
-                 (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL &&
-                   aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS ) ) {
+	} else  if ( ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) &&
+                  (aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) ||
+                 ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) &&
+                  (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)) ) {
 
             
 		/*     
@@ -2381,28 +2380,28 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *
 		 * match that filter.
 		 *
 		 *
-		*/
+		 */
 
 		Targetattrfilter **attrFilterArray = NULL;
 		Targetattrfilter	*attrFilter;
 		int found = 0;
 
-		if (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD &&
-				aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS) {
+		if ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_ADD) &&
+			(aci->aci_type & ACI_TARGET_ATTR_ADD_FILTERS)) {
 
-				attrFilterArray = aci->targetAttrAddFilters;
+			attrFilterArray = aci->targetAttrAddFilters;
 
-		} else if (aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL && 
-						aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS) {
+		} else if ((aclpb->aclpb_access & ACLPB_SLAPI_ACL_WRITE_DEL) && 
+				   (aci->aci_type & ACI_TARGET_ATTR_DEL_FILTERS)) {
 				
-				attrFilterArray = aci->targetAttrDelFilters;
+			attrFilterArray = aci->targetAttrDelFilters;
 
 		}
 		
 
 		/*
 		 * Scan this filter list for an applicable filter.
-		*/
+		 */
 
 		found = 0;
 		num_attrs = 0;
@@ -2435,7 +2434,7 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *
 				attr_matched= acl__test_filter(aclpb->aclpb_filter_test_entry,
 										attrFilter->filter,
 										1 /* Do filter sense evaluation below */
-							 			);                            
+										);                            
 				slapi_entry_free( aclpb->aclpb_filter_test_entry );			
 			}           
 
@@ -2452,8 +2451,6 @@ acl__resource_match_aci( Acl_PBlock *aclpb, aci_t *aci, int skip_attrEval, int *
 			*/
 		
 			attr_matched_in_targetattrfilters = 1;
-
-
 		}                                
 	} /* targetvaluefilters */ 
 	
@@ -3233,9 +3230,6 @@ acl_match_substring ( Slapi_Filter *f, char *str, int exact_match)
 		realval = tmp;
 	}
 
-	slapi_dn_normalize (realval);
-
-
 	/* What we have built is a regular pattaren expression.
 	** Now we will compile the pattern and compare wth the string to
 	** see if the input string matches with the patteren or not.

+ 6 - 1
ldap/servers/plugins/acl/acl.h

@@ -119,7 +119,11 @@ static char* const aci_targetattr 			= "targetattr";
 static char* const aci_targetattrfilters 	= "targattrfilters";
 static char* const aci_targetfilter 		= "targetfilter";
 
+static char* const LDAP_URL_prefix_core 	= "ldap://";
+static char* const LDAPS_URL_prefix_core 	= "ldaps://";
+
 static char* const LDAP_URL_prefix 	= "ldap:///";
+static char* const LDAPS_URL_prefix 	= "ldaps:///";
 
 static char* const access_str_compare 	= "compare";
 static char* const access_str_search  	= "search";
@@ -827,7 +831,7 @@ int			acl_skip_access_check ( Slapi_PBlock *pb,  Slapi_Entry *e );
 
 int			aclext_alloc_lockarray ();
 
-int			aclutil_str_appened(char **str1, const char *str2);
+int			aclutil_str_append(char **str1, const char *str2);
 void		aclutil_print_err (int rv , const Slapi_DN *sdn,
 			const struct berval* val, char **errbuf);
 void		aclutil_print_aci (aci_t *aci_item, char *type);
@@ -911,6 +915,7 @@ acl_replace_str(char * s, char *substr, char* replace_with);
 int		acl_strstr(char * s, char *substr);
 int		aclutil_evaluate_macro( char * rule, lasInfo *lasinfo,
 								acl_eval_types evalType );
+int aclutil_str_append_ext(char **dest, size_t *dlen, const char *src, size_t slen);
 
 /* acl hash table functions */
 void acl_ht_add_and_freeOld(acl_ht_t * acl_ht, PLHashNumber key,char *value);

+ 1 - 1
ldap/servers/plugins/acl/acl_ext.c

@@ -791,7 +791,7 @@ acl__done_aclpb ( struct acl_pblock *aclpb )
 	*/		
 
 	/* Nothing needs to be cleaned up in this case */
-	if ( !aclpb->aclpb_state & ACLPB_INITIALIZED)
+	if (!(aclpb->aclpb_state & ACLPB_INITIALIZED))
 		return;
 
 	/* Check the state */

+ 1 - 0
ldap/servers/plugins/acl/aclanom.c

@@ -205,6 +205,7 @@ aclanom_gen_anomProfile (acl_lock_flag_t lock_flag)
 
 			/* see if this is a monitor acl */
 			if (( strcasecmp ( dn, "cn=monitor") == 0 )  ||
+			    /* cn=monitor,cn=ldbm: No such object */
 			    ( strcasecmp ( dn, "cn=monitor,cn=ldbm") == 0 )) {
 				aci =  acllist_get_next_aci ( NULL, aci, &cookie);
 				continue;

+ 32 - 15
ldap/servers/plugins/acl/acleffectiverights.c

@@ -170,7 +170,7 @@ _ger_g_permission_granted (
 		goto bailout;
 	}
 
-	aclutil_str_appened ( errbuf, "get-effective-rights: requestor has no g permission on the entry" );
+	aclutil_str_append ( errbuf, "get-effective-rights: requestor has no g permission on the entry" );
 	slapi_log_error (SLAPI_LOG_ACL, plugin_name,
 				"_ger_g_permission_granted: %s\n", *errbuf);
 	rc = LDAP_INSUFFICIENT_ACCESS;
@@ -195,7 +195,10 @@ _ger_parse_control (
 	LDAPControl **requestcontrols;
 	struct berval *subjectber;
 	BerElement *ber;
-	int subjectndnlen = 0;
+	size_t subjectndnlen = 0;
+	char *orig = NULL;
+	char *normed = NULL;
+	int rc = 0;
 
 	if (NULL == subjectndn)
 	{
@@ -215,7 +218,7 @@ _ger_parse_control (
 	if ( subjectber == NULL || subjectber->bv_val == NULL ||
 		 subjectber->bv_len == 0 )
 	{
-		aclutil_str_appened ( errbuf, "get-effective-rights: missing subject" );
+		aclutil_str_append ( errbuf, "get-effective-rights: missing subject" );
 		slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
 		return LDAP_INVALID_SYNTAX;
 	}
@@ -227,23 +230,23 @@ _ger_parse_control (
 		 * or base64 encoding string. Hence users using -J option in
 		 * ldapsearch don't have to do BER encoding for the subject.
 		 */
-		*subjectndn = slapi_ch_malloc ( subjectber->bv_len + 1 );
-		strncpy ( *subjectndn, subjectber->bv_val, subjectber->bv_len );
-		*(*subjectndn + subjectber->bv_len) = '\0';
+		orig = slapi_ch_malloc ( subjectber->bv_len + 1 );
+		strncpy ( orig, subjectber->bv_val, subjectber->bv_len );
+		*(orig + subjectber->bv_len) = '\0';
 	}
 	else
 	{
 		ber = ber_init (subjectber);
 		if ( ber == NULL )
 		{
-			aclutil_str_appened ( errbuf, "get-effective-rights: ber_init failed for the subject" );
+			aclutil_str_append ( errbuf, "get-effective-rights: ber_init failed for the subject" );
 			slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
 			return LDAP_OPERATIONS_ERROR;
 		}
 		/* "a" means to allocate storage as needed for octet string */
-		if ( ber_scanf (ber, "a", subjectndn) == LBER_ERROR )
+		if ( ber_scanf (ber, "a", orig) == LBER_ERROR )
 		{
-			aclutil_str_appened ( errbuf, "get-effective-rights: invalid ber tag in the subject" );
+			aclutil_str_append ( errbuf, "get-effective-rights: invalid ber tag in the subject" );
 			slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
 			ber_free ( ber, 1 );
 			return LDAP_INVALID_SYNTAX;
@@ -256,18 +259,32 @@ _ger_parse_control (
 	 * (see section 9 of RFC 2829) only. It also only supports the "dnAuthzId"
 	 * flavor, which looks like "dn:<DN>" where null <DN> is for anonymous.
 	 */
-	subjectndnlen = strlen(*subjectndn);
-	if ( NULL == *subjectndn || subjectndnlen < 3 ||
-		 strncasecmp ( "dn:", *subjectndn, 3 ) != 0 )
+	subjectndnlen = strlen(orig);
+	if ( NULL == orig || subjectndnlen < 3 || strncasecmp ( "dn:", orig, 3 ) != 0 )
 	{
-		aclutil_str_appened ( errbuf, "get-effective-rights: subject is not dnAuthzId" );
+		aclutil_str_append ( errbuf, "get-effective-rights: subject is not dnAuthzId" );
 		slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
+		slapi_ch_free_string(&orig);
 		return LDAP_INVALID_SYNTAX;
 	}
 
 	/* memmove is safe for overlapping copy */
-	memmove ( *subjectndn, *subjectndn + 3, subjectndnlen - 2);/* 1 for '\0' */
-	slapi_dn_normalize ( *subjectndn );
+	rc = slapi_dn_normalize_ext(orig + 3, 0, &normed, &subjectndnlen);
+	if (rc < 0) {
+		aclutil_str_append ( errbuf, "get-effective-rights: failed to normalize dn: ");
+		aclutil_str_append ( errbuf, orig);
+		slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
+		slapi_ch_free_string(&orig);
+		return LDAP_INVALID_SYNTAX;
+	}
+	if (rc == 0) { /* orig+3 is passed in; not terminated */
+		*(normed + subjectndnlen) = '\0';
+		*subjectndn = slapi_ch_strdup(normed);
+		slapi_ch_free_string(&orig);
+	} else {
+		slapi_ch_free_string(&orig);
+		*subjectndn = normed;
+	}
 	return LDAP_SUCCESS;
 }
 

+ 167 - 34
ldap/servers/plugins/acl/acllas.c

@@ -480,6 +480,7 @@ DS_LASUserDnEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
 	int			rc;
 	short		len;
 	const size_t 	LDAP_URL_prefix_len = strlen(LDAP_URL_prefix);
+	const size_t 	LDAPS_URL_prefix_len = strlen(LDAPS_URL_prefix);
 	lasInfo			lasinfo;
 	int			got_undefined = 0;
 
@@ -530,15 +531,15 @@ DS_LASUserDnEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
 		** userdn = "ldap:///DN1 || ldap:///DN2" 
 		*/
 	
-
 		/* The DN is now "ldap:///DN" 
 		** remove the "ldap:///" part
 		*/
-		if (strncasecmp (user, LDAP_URL_prefix, 
-				LDAP_URL_prefix_len) == 0) {
+		if (strncasecmp (user, LDAP_URL_prefix, LDAP_URL_prefix_len) == 0) {
 			s_user = user;
 			user += LDAP_URL_prefix_len;
-
+		} else if (strncasecmp (user, LDAPS_URL_prefix, LDAPS_URL_prefix_len) == 0) {
+			s_user = user;
+			user += LDAPS_URL_prefix_len;
 		} else {
 			char ebuf[ BUFSIZ ];
 			slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
@@ -677,8 +678,19 @@ DS_LASUserDnEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
 				slapi_filter_free(f,1);
 			} else {
 				/* Must be a simple dn then */
-				if (slapi_utf8casecmp((ACLUCHP)lasinfo.clientDn, 
-						(ACLUCHP)slapi_dn_normalize(user)) == 0) {
+				char *normed = NULL;
+				size_t dnlen = 0;
+				rc = slapi_dn_normalize_ext(user, 0, &normed, &dnlen);
+				if (rc == 0) { /* user passed in; not terminated */
+					*(normed + dnlen) = '\0';
+				} else if (rc < 0) { /* normalization failed, user the original */
+					normed = user;
+				}
+				rc = slapi_utf8casecmp((ACLUCHP)lasinfo.clientDn, (ACLUCHP)normed);
+				if (normed != user) {
+					slapi_ch_free_string(&normed);
+				}
+				if (0 == rc) {
 					matched = ACL_TRUE;
 					break;
 				}
@@ -1274,8 +1286,14 @@ DS_LASUserDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
 			while ( j != -1 ) {
 				attrVal = slapi_value_get_berval ( sval );
 				/* Here if atleast 1 value matches then we are done.*/
-				val = slapi_dn_normalize (
-					slapi_ch_strdup( attrVal->bv_val));
+				val = slapi_create_dn_string("%s", attrVal->bv_val);
+				if (NULL == val) {
+					slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+							"DS_LASUserDnAttrEval: Invalid syntax: %s\n",
+							attrVal->bv_val );
+					slapi_ch_free ( (void**) &s_attrName);
+					return LAS_EVAL_FAIL;
+				}
 
 				if (slapi_utf8casecmp((ACLUCHP)val, (ACLUCHP)lasinfo.clientDn ) == 0) {
 					char	ebuf [ BUFSIZ ];
@@ -2380,7 +2398,13 @@ acllas__handle_group_entry (Slapi_Entry* e, void *callback_data)
 			while ( i != -1 ) {
 				struct member_info	*groupMember = NULL;
 				attrVal = slapi_value_get_berval ( sval );
-				n_dn = slapi_dn_normalize ( slapi_ch_strdup( attrVal->bv_val ));
+				n_dn = slapi_create_dn_string( attrVal->bv_val );
+				if (NULL == n_dn) {
+					slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+						"acllas__handle_group_entry: Invalid syntax: %s\n",
+						attrVal->bv_val );
+					return 0;
+				}
 				n = ++info->lu_idx;
 				if (n < 0) {
 					slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
@@ -2433,7 +2457,14 @@ acllas__handle_group_entry (Slapi_Entry* e, void *callback_data)
 				 */
 				if (strncasecmp( attrVal->bv_val, "ldap://",7) == 0 ||
 					strncasecmp( attrVal->bv_val, "ldaps://",8) == 0) {
-					savURL = memberURL = slapi_ch_strdup ( attrVal->bv_val);
+					savURL = memberURL = 
+							slapi_create_dn_string("%s", attrVal->bv_val);
+					if (NULL == savURL) {
+						slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+							"acllas__handle_group_entry: Invalid syntax: %s\n",
+							attrVal->bv_val );
+						return 0;
+					}
 					slapi_log_error( SLAPI_LOG_ACL, plugin_name,
 						  "ACL Group Eval:MemberURL:%s\n", memberURL);
 					info->result = acllas__client_match_URL (
@@ -2656,8 +2687,13 @@ DS_LASGroupDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
 				attr_i= slapi_attr_first_value ( attr,&sval );
 				while ( attr_i != -1 ) {
 			        attrVal = slapi_value_get_berval ( sval );
-					n_groupdn = slapi_dn_normalize(
-								slapi_ch_strdup( attrVal->bv_val));
+					n_groupdn = slapi_create_dn_string("%s", attrVal->bv_val);
+					if (NULL == n_groupdn) {
+						slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+							"DS_LASGroupDnAttrEval: Invalid syntax: %s\n",
+							attrVal->bv_val );
+						return 0;
+					}
 					matched =  acllas__user_ismember_of_group (
 										lasinfo.aclpb, n_groupdn, lasinfo.clientDn,
 										ACLLAS_CACHE_MEMBER_GROUPS, 
@@ -2855,6 +2891,7 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e,
 		char			*curMemberDn;
 		int			Done = 0;
 		int			ngr, tt;
+		char		*normed = NULL;
 
 		/* Add the scope to the list of scopes */
 		if (aclpb->aclpb_numof_bases >= (aclpb->aclpb_grpsearchbase_size-1)) {
@@ -2866,9 +2903,15 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e,
 					    sizeof (char *));
 			aclpb->aclpb_grpsearchbase_size += ACLPB_INCR_BASES;
 		}
-		aclpb->aclpb_grpsearchbase[aclpb->aclpb_numof_bases++] = 
-				slapi_dn_normalize(slapi_ch_strdup(base));
-
+		normed = slapi_create_dn_string("%s", base);
+		if (NULL == normed) {
+			slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+						"acllas__eval_memberGroupDnAttr: Invalid syntax: %s\n",
+						base );
+			slapi_ch_free ( (void **)&s_str );
+			return ACL_FALSE;
+		}
+		aclpb->aclpb_grpsearchbase[aclpb->aclpb_numof_bases++] = normed;
 		/* Set up info to do a search */
 		attrs[0] = type_member;
 		attrs[1] = type_uniquemember;
@@ -2991,8 +3034,14 @@ acllas__eval_memberGroupDnAttr (char *attrName, Slapi_Entry *e,
 	while ( k != -1 ) {
         char *n_attrval;
 		attrVal = slapi_value_get_berval ( sval );
-		n_attrval = slapi_ch_strdup( attrVal->bv_val);
-		n_attrval = slapi_dn_normalize (n_attrval);
+		n_attrval = slapi_create_dn_string("%s", attrVal->bv_val);
+		if (NULL == n_attrval) {
+			slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+						"acllas__eval_memberGroupDnAttr: Invalid syntax: %s\n",
+						attrVal->bv_val );
+			slapi_ch_free ( (void **)&s_str );
+			return ACL_FALSE;
+		}
 
 		/*  We support: The attribute value can be a USER or a GROUP.
 		** Let's compare with the client, thi might be just an user. If it is not
@@ -3147,7 +3196,13 @@ acllas__verify_client (Slapi_Entry* e, void *callback_data)
 	i = slapi_attr_first_value ( attr,&sval );
 	while ( i != -1 ) {
 		attrVal = slapi_value_get_berval ( sval );
-		val = slapi_dn_normalize(slapi_ch_strdup(attrVal->bv_val));
+		val = slapi_create_dn_string("%s", attrVal->bv_val);
+		if (NULL == val) {
+			slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+							"acllas__verify_client: Invalid syntax: %s\n",
+							attrVal->bv_val );
+			return 0;
+		}
 
 		if (slapi_utf8casecmp((ACLUCHP)val, (ACLUCHP)info->clientdn ) == 0) {
 			info->result = 1;
@@ -3235,7 +3290,12 @@ acllas__get_members (Slapi_Entry* e, void *callback_data)
 	i = slapi_attr_first_value ( attr,&sval );
 	while ( i != -1 ) {
 	    attrVal =slapi_value_get_berval ( sval );
-	    info->member[i] = slapi_dn_normalize ( slapi_ch_strdup(attrVal->bv_val));
+	    info->member[i] = slapi_create_dn_string ("%s", attrVal->bv_val);
+		if (NULL == info->member[i]) {
+			slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+							"acllas__get_members: Invalid syntax: %s\n",
+							attrVal->bv_val );
+		}
 	    i = slapi_attr_next_value ( attr, i, &sval );
 	}
 	return 0;	
@@ -3426,7 +3486,17 @@ acllas__client_match_URL (struct acl_pblock *aclpb, char *n_clientdn, char *url
 	LDAPURLDesc	*ludp;
 	int		rc;
 	Slapi_Filter	*f = NULL;
-
+	char *rawdn = NULL;
+	char *dn = NULL;
+	size_t dnlen = 0;
+	char *p = NULL;
+	char *normed = NULL;
+	/* ldap(s)://host:port/suffix?attrs?scope?filter */
+	const size_t 	LDAP_URL_prefix_len = strlen(LDAP_URL_prefix_core);
+	const size_t 	LDAPS_URL_prefix_len = strlen(LDAPS_URL_prefix_core);
+	size_t 	prefix_len = 0;
+	char Q = '?';
+	char *hostport = NULL;
 
 	/* Get the client's entry if we don't have already */
 	if ( aclpb && ( NULL == aclpb->aclpb_client_entry )) {
@@ -3459,23 +3529,83 @@ acllas__client_match_URL (struct acl_pblock *aclpb, char *n_clientdn, char *url
 	}
 
 	if ( NULL == aclpb->aclpb_client_entry ) {
-		slapi_log_error (  SLAPI_LOG_ACL, plugin_name, 
-			"DS_LASUserAttrEval: Unable to get client's entry\n");
+		slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
+			"acllas__client_match_URL: Unable to get client's entry\n");
 		return ACL_FALSE;
 	}
 
-	if (( rc = ldap_url_parse( url, &ludp)) != 0 ) {
+	/* DN potion of URL must be normalized before calling ldap_url_parse.
+	 * lud_dn is pointing at the middle of lud_string.
+	 * lud_dn won't be freed in ldap_free_urldesc.
+	 */
+	/* remove the "ldap{s}:///" part */
+	if (strncasecmp (url, LDAP_URL_prefix, LDAP_URL_prefix_len) == 0) {
+		prefix_len = LDAP_URL_prefix_len;
+	} else if (strncasecmp (url, LDAPS_URL_prefix, LDAPS_URL_prefix_len) == 0) {
+		prefix_len = LDAPS_URL_prefix_len;
+	} else {
+		slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
+			"acllas__client_match_URL: url %s does not include ldap prefix: %s\n", url);
+		return ACL_FALSE;
+	}
+	rawdn = url + prefix_len; /* ldap(s)://host:port/... or ldap(s):///... */
+	                          /* rawdn at  ^             or           ^    */
+	/* let rawdn point the suffix */
+	if ('/' == *(rawdn+1)) { /* ldap(s):/// */
+		rawdn += 2;
+		hostport = "/";
+	} else {
+		char *tmpp = rawdn;
+		rawdn = strchr(tmpp, '/');
+		size_t hostport_len = 0;
+		if (NULL == rawdn) {
+			slapi_log_error (SLAPI_LOG_ACL, plugin_name, 
+				"acllas__client_match_URL: url %s does not include correct ldap prefix: %s\n", url);
+			return ACL_FALSE;
+		}
+		hostport_len = ++rawdn - tmpp; /* ldap(s)://host:port/... */
+		                               /*           <-------->    */
+		hostport = (char *)slapi_ch_malloc(hostport_len + 1);
+		memcpy(hostport, tmpp, hostport_len);
+		*(hostport+hostport_len) = '\0';
+	}
+	p = strchr(rawdn, Q);
+	if (p) { 
+		/* url has scope and/or filter: ldap(s):///suffix?attr?scope?filter */
+		*p = '\0';
+	}
+	rc = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen);
+	if (rc < 0) {
+		slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+						"acllas__client_match_URL: Invalid syntax: %s\n", url);
+		return ACL_FALSE;
+	} else if (rc == 0) { /* url is passed in and not terminated with NULL*/
+		*(dn + dnlen) = '\0';
+	}
+	if (p) {
+		*p = Q;
+	}
+	normed = slapi_ch_smprintf("%s%s%s%s", 
+			 (prefix_len==LDAP_URL_prefix_len)?
+			  LDAP_URL_prefix_core:LDAPS_URL_prefix_core,
+			 hostport, dn, p?p:"");
+	if (rc > 0) {
+		/* dn was allocated in slapi_dn_normalize_ext */
+		slapi_ch_free_string(&dn);
+	}
+	if ('/' != *hostport) {
+		slapi_ch_free_string(&hostport);
+	}
+	rc = ldap_url_parse(normed, &ludp);
+	slapi_ch_free_string(&normed);
+	if (rc) {
 		return ACL_FALSE;
-
 	}
 	if ( ( NULL == ludp->lud_dn) || ( NULL == ludp->lud_filter) ) {
 		ldap_free_urldesc( ludp );
 		return ACL_FALSE;
 	}
 
-	/* Normalize in place the dn */
-	slapi_dn_normalize ( ludp->lud_dn ); 
-
 	/* Check the scope */
 	if ( ludp->lud_scope == LDAP_SCOPE_SUBTREE ) {
 		if (!slapi_dn_issuffix(n_clientdn, ludp->lud_dn)) {
@@ -3777,8 +3907,13 @@ DS_LASRoleDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
 			Slapi_DN *roleDN;
 
 			attrVal = slapi_value_get_berval ( sval );
-			n_attrval = slapi_ch_strdup( attrVal->bv_val);
-			n_attrval = slapi_dn_normalize (n_attrval);
+			n_attrval = slapi_create_dn_string("%s", attrVal->bv_val);
+			if (NULL == n_attrval) {
+				slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
+							"DS_LASRoleDnAttrEval: Invalid syntax: %s\n",
+							attrVal->bv_val );
+				return LAS_EVAL_FAIL;
+			}
 			roleDN = slapi_sdn_new_dn_byval(n_attrval);
 
 			/*  We support: The attribute value can be a USER or a GROUP.
@@ -3831,14 +3966,12 @@ DS_LASRoleDnAttrEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
  * returns: ACL_TRUE for matched,
  * 			ACL_FALSE for matched.
  *			ACL_DONT_KNOW otherwise.
- *
- *
-*/
+ */
 
 int
 aclutil_evaluate_macro( char * rule, lasInfo *lasinfo,
-						acl_eval_types evalType ) {
-						
+						acl_eval_types evalType )
+{
 	int matched = 0;
 	aci_t *aci;
 	char *matched_val = NULL;

+ 216 - 170
ldap/servers/plugins/acl/aclparse.c

@@ -50,7 +50,6 @@ static int		__aclp__sanity_check_acltxt(aci_t *aci_item, char *str);
 static char *	__aclp__normalize_acltxt (aci_t *aci_item, char *str);
 static char *	__aclp__getNextLASRule(aci_t *aci_item, char *str,
         								 char **endOfCurrRule);
-static char *	__aclp__dn_normalize( char *dn , char *end);
 static int	__aclp__get_aci_right ( char *str);
 static int 	__aclp__init_targetattr (aci_t *aci, char *attr_val);
 static int			__acl__init_targetattrfilters( aci_t *aci_item, char *str);
@@ -239,10 +238,10 @@ __aclp__parse_aci (char 	*str, aci_t  *aci_item)
 
 		
 			/* 
-          * The targetattrfilters bit looks like this:
-          *  (targetattrfilters="add= attr1:F1 && attr2:F2 ... && attrn:Fn,
-          *                      del= attr1:F1 && attr2:F2... && attrn:Fn")
-			*/
+			 * The targetattrfilters bit looks like this:
+			 *  (targetattrfilters="add= attr1:F1 && attr2:F2 ... && attrn:Fn,
+			 *                      del= attr1:F1 && attr2:F2... && attrn:Fn")
+			 */
 			if ( 0 != (rv= __acl__init_targetattrfilters(
 					aci_item, str))) {
 				return  rv;
@@ -256,15 +255,14 @@ __aclp__parse_aci (char 	*str, aci_t  *aci_item)
 			}
 			/* Get individual components of the targetattr.
 			 * (targetattr = "cn || u* || phone ||tel:add:(tel=1234) 
-             *  || sn:del:(gn=5678)")
-             * If it contains a value filter, the type will also be
-             *	ACI_TARGET_VALUE_ATTR.
-			*/
-			if ( 0 != (rv= __aclp__init_targetattr(
-					aci_item, str))) {
+			 *  || sn:del:(gn=5678)")
+			 * If it contains a value filter, the type will also be
+			 *	ACI_TARGET_VALUE_ATTR.
+			 */
+			if (0 != (rv =  __aclp__init_targetattr(aci_item, str))) {
 				return  rv;
 			}
-		} else if (strncmp(str, aci_targetfilter,tfilterlen ) == 0) {	
+		} else if (strncmp(str, aci_targetfilter,tfilterlen ) == 0) {
 			if ( aci_item->targetFilter)
 				return ACL_SYNTAX_ERR;
 
@@ -311,8 +309,8 @@ __aclp__parse_aci (char 	*str, aci_t  *aci_item)
 
 		} else if (strncmp(str, aci_targetdn, targetdnlen) == 0) {
 			char		*tstr = NULL;
-			const size_t    LDAP_URL_prefix_len = strlen (LDAP_URL_prefix);
-			char	*tt;
+			size_t    LDAP_URL_prefix_len = 0;
+			size_t	tmplen = 0;
 			type = ACI_TARGET_DN;
 			/* Keep a copy of the target attr */
 			if (aci_item->target) {
@@ -322,30 +320,40 @@ __aclp__parse_aci (char 	*str, aci_t  *aci_item)
 				type |= ACI_TARGET_NOT;
 				strncpy(s, " ", 1);
 			}			
-				
-			/* Convert it to lower as slapi_dn_normalize() does not */
-			for (tt = str; *tt; tt++) *tt = TOLOWER ( *tt );
-			
 			if ( (s = strchr( str, '=' )) != NULL ) {
 				value = s + 1;
-				slapi_dn_normalize(value);
+				__acl_strip_leading_space(&value);
 				len =  strlen ( value );
-				if (*value == '"' &&  value[len-1] == '"'){
+				/* strip double quotes */
+				if (*value == '"' &&  value[len-1] == '"') {
 					value[len-1] = '\0';
 					value++;
 				}	
 				__acl_strip_leading_space(&value);
-			} else { 
+			} else {
 				return ( ACL_SYNTAX_ERR );
 			}
-
-			if ( strncasecmp ( value, LDAP_URL_prefix , LDAP_URL_prefix_len) )
+			if (0 ==
+				strncasecmp(value, LDAP_URL_prefix, strlen(LDAP_URL_prefix))) {
+				LDAP_URL_prefix_len = strlen(LDAP_URL_prefix);
+			} else if (0 == strncasecmp(value, LDAPS_URL_prefix,
+										strlen(LDAPS_URL_prefix))) {
+				LDAP_URL_prefix_len = strlen(LDAPS_URL_prefix);
+			} else {
 				return ( ACL_SYNTAX_ERR );
+			}
 
 			value += LDAP_URL_prefix_len;
-			len = strlen ( value );
-			tstr =  (char *) slapi_ch_malloc ( targetdnlen + len + 4 );
-			sprintf ( tstr, "(target=%s)", value);
+			rv = slapi_dn_normalize_case_ext(value, 0, &tmpstr, &tmplen);
+			if (rv < 0) {
+				return ACL_SYNTAX_ERR;
+			} else if (rv == 0) { /* value passed in; not null terminated */
+				*(tmpstr + tmplen) = '\0';
+			}
+			tstr = slapi_ch_smprintf("(target=%s)", tmpstr);
+			if (rv > 0) {
+				slapi_ch_free_string(&tmpstr);
+			}
 			if ( (rv = acl_check_for_target_macro( aci_item, value)) == -1) {
 				slapi_ch_free ( (void **) &tstr );				
 				return(ACL_SYNTAX_ERR);
@@ -356,7 +364,7 @@ __aclp__parse_aci (char 	*str, aci_t  *aci_item)
 				/* it's a normal target with no macros inside */	
 				f = slapi_str2filter ( tstr );				
 			}
-			slapi_ch_free ( (void **) &tstr );
+			slapi_ch_free_string ( &tstr );
 		} else {
 			/* did start with a 't' but was not a recognsied keyword */
 			return(ACL_SYNTAX_ERR);
@@ -492,20 +500,86 @@ __aclp__sanity_check_acltxt (aci_t *aci_item, char *str)
 	slapi_log_error(SLAPI_LOG_ACL, plugin_name, "Normalized String:%s\n", newstr);
 
 	/* check for acl syntax error */ 
-	if ((handle = (ACLListHandle_t *) ACL_ParseString(&errp, 
-							   newstr)) == NULL) {
+	if ((handle = (ACLListHandle_t *) ACL_ParseString(&errp, newstr)) == NULL) {
 		acl_print_acllib_err(&errp, str);
-		slapi_ch_free ( (void **) &newstr );
+		slapi_ch_free_string(&newstr);
 		return ACL_SYNTAX_ERR;
 	} else {
 		/* get the rights and the aci type */
 		aci_item->aci_handle = handle;
 		nserrDispose(&errp);
-		slapi_ch_free ( (void **) &newstr );
+		slapi_ch_free_string(&newstr);
 
 		return  0;
 	}
 }
+
+/*
+ * If the src includes "ldap(s):///<dn>", normalize <dn> and copy
+ * the string starting from start to *dest.
+ * If isstrict is non-zero, if ldap(s):/// is not included in the src
+ * string, it returns an error (-1).  
+ * If isstrict is zero, the string is copied as is.
+ *
+ * return value: 0 or positive: success
+ *                    negative: failure
+ */
+int
+__aclp__copy_normalized_str (char *src, char *endsrc, char *start,
+							 char **dest, size_t *destlen, int isstrict)
+{
+	char *p = NULL;
+	int rc = -1; 
+	char *dn = NULL;
+	size_t dnlen = 0;
+
+	p = PL_strnstr(src, LDAP_URL_prefix, endsrc - src);
+	if (p) {
+		p += strlen(LDAP_URL_prefix);
+	} else {
+		p = PL_strnstr(src, LDAPS_URL_prefix, endsrc - src);
+		if (p) {
+			p += strlen(LDAPS_URL_prefix);
+		}
+	}
+
+	if (isstrict && ((NULL == p) || 0 == strlen(p))) {
+		return rc; /* error */
+	}
+	
+	rc = 0;
+	if (p && strlen(p) > 0) {
+		size_t len = 0;
+		/* strip the string starting from ? */
+		char *q = PL_strnchr(p, '?', endsrc - p);
+		if (q) {
+			len = q - p;
+		} else {
+			len = endsrc - p;
+		}
+		/* Normalize the value of userdn and append it to ret_str */
+		rc = slapi_dn_normalize_ext(p, len, &dn, &dnlen);
+		if (rc < 0) {
+			return rc;
+		}
+		/* append up to ldap(s):/// */
+		aclutil_str_append_ext(dest, destlen, start, p - start);
+		/* append the DN part */
+		aclutil_str_append_ext(dest, destlen, dn, dnlen);
+		if (rc > 0) { /* if rc == 0, p is passed in */
+			slapi_ch_free_string(&dn);
+		}
+		if (q) {
+			/* append the rest from '?' */
+			aclutil_str_append_ext(dest, destlen, q, endsrc - q);
+		}
+	} else {
+		aclutil_str_append_ext(dest, destlen, start, endsrc - start);
+	}
+
+	return rc;
+}
+
 /******************************************************************************
 *
 * acl__normalize_acltxt
@@ -534,23 +608,25 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str )
 	char		*s, *p;
 	char		*end;
 	char		*aclstr, *s_aclstr;
+	char		*prevend = NULL;
 	char		*ret_str = NULL;
+	size_t		retstr_len = 0;
 	int			len;
-	char		*ptr, *aclName;
+	char		*aclName;
 	char		*nextACE;
 	char		*tmp_str = NULL;
 	char		*acestr = NULL;
 	char		*s_acestr = NULL;
 	int 		aci_rights_val 	= 0; /* bug 389975 */ 
+	int			rc = 0;
 
 	/* make a copy first */
 	s_aclstr = aclstr = slapi_ch_strdup ( str );
 
 	/* The rules are like this version 3.0; acl "xyz"; rule1; rule2; */
 	s = strchr (aclstr, ';');
-	if ( NULL == s) {
-		slapi_ch_free ( (void **) &s_aclstr );
-		return NULL;
+	if (NULL == s) {
+		goto error;
 	}
 	aclstr = ++s;
 
@@ -564,9 +640,8 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str )
 	aclName = s+3;
 
 	s = strchr (aclstr, ';');
-	if ( NULL == s) {
-		slapi_ch_free ( (void **) &s_aclstr );
-		return NULL;
+	if (NULL == s) {
+		goto error;
 	}
 
 	aclstr = s;
@@ -576,8 +651,10 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str )
 	/* Here aclName is the acl description string */
 	aci_item->aclName = slapi_ch_strdup ( aclName );
 
-	aclutil_str_appened (&ret_str, s_aclstr);
-	aclutil_str_appened (&ret_str, ";");
+	retstr_len = strlen(str) * 3;
+	ret_str = (char *)slapi_ch_calloc(sizeof(char), retstr_len);
+	aclutil_str_append_ext (&ret_str, &retstr_len, s_aclstr, strlen(s_aclstr));
+	aclutil_str_append_ext (&ret_str, &retstr_len, ";", 1);
 
 	/* start with the string */
 	acestr = aclstr;
@@ -586,37 +663,34 @@ __aclp__normalize_acltxt ( aci_t * aci_item, char * str )
 	 * Here acestr is something like:
 	 *
 	 * " allow (all) groupdn = "ldap:///cn=Domain Administrators, o=$dn.o, o=ISP";)"
-	 *
-	 *
-	*/
+	 */
 
 normalize_nextACERule:
 
 	/* now we are in the rule part */
 	tmp_str = acestr;
 	s = strchr (tmp_str, ';');
-	if ( s == NULL) {
-		if (ret_str) slapi_ch_free ( (void **) &ret_str );
-		slapi_ch_free ( (void **) &s_aclstr );
-		return NULL;
+	if (s == NULL) {
+		goto error;
 	}
+
 	nextACE = s;
 	LDAP_UTF8INC(nextACE);
 	*s = '\0';
 
-	/* acestr now will hold  copy of the ACE. Also add
+	/* acestr now will hold copy of the ACE. Also add
 	** some more space in case we need to add "absolute"
-	** for deny rule. We will never need more 2 times 
-	** the len.
+	** for deny rule. We will never need more 3 times 
+	** the len (even if all the chars are escaped).
 	*/
 	__acl_strip_leading_space(&tmp_str);
 	len = strlen (tmp_str);
-	s_acestr = acestr = slapi_ch_calloc ( 1, 2 * len);
+	s_acestr = acestr = slapi_ch_calloc (1, 3 * len);
 
 	/*
 	 * Now it's something like:
 	 * allow (all) groupdn = "ldap:///cn=Domain Administrators, o=$dn.o, o=ISP";
-	*/
+	 */
 	if (strncasecmp(tmp_str, "allow", 5) == 0) {
 		memcpy(acestr, tmp_str, len);
 		tmp_str += 5;
@@ -624,6 +698,14 @@ normalize_nextACERule:
 		aci_rights_val =  __aclp__get_aci_right (tmp_str);/* bug 389975 */
 		aci_item->aci_type |= ACI_HAS_ALLOW_RULE;
 
+		s = strchr(acestr, ')');
+		if (NULL == s) {
+			/* wrong syntax */
+			goto error;
+		}
+		/* add "allow(rights...)" */
+		aclutil_str_append_ext(&ret_str, &retstr_len, acestr, s - acestr + 1);
+		prevend = s + 1;
 	} else if (strncasecmp(tmp_str, "deny", 4) == 0) {
 		char 		*d_rule ="deny absolute";
 		/* Then we have to  add "absolute" to the deny rule
@@ -652,6 +734,15 @@ normalize_nextACERule:
 		len = strlen ( d_rule );
 		memcpy (acestr, d_rule, len );
 		memcpy (acestr+len, tmp_str, strlen (tmp_str) );
+
+		s = strchr(acestr, ')');
+		if (NULL == s) {
+			/* wrong syntax */
+			goto error;
+		}
+		/* add "deny(rights...)" */
+		aclutil_str_append_ext(&ret_str, &retstr_len, acestr, s - acestr + 1);
+		prevend = s + 1;
 	} else {
 		/* wrong syntax */
 		aci_rights_val = -1 ;
@@ -659,32 +750,32 @@ normalize_nextACERule:
 	if (aci_rights_val == -1 )
 	{
 		/* wrong syntax */
-		slapi_ch_free ( (void **) &ret_str );
-		slapi_ch_free ( (void **) &s_acestr );
-		slapi_ch_free ( (void **) &s_aclstr );
-		return NULL;
+		goto error;
 	} else
-        	aci_item->aci_access |= aci_rights_val;
+		aci_item->aci_access |= aci_rights_val;
  
-
-	/* Normalize all the DNs in the userdn rule */
-
+	/* Normalize all the DNs in the userdn, groupdn, roledn rules */
 	/*
 	 *
 	 * Here acestr starts like this:
-	 * " allow (all) groupdn = "ldap:///cn=Domain Administrators, o=$dn.o, o=ISP"
-	*/
-
+	 * " allow (all) groupdn = "ldap:///cn=Domain Administrators,o=$dn.o,o=ISP"
+	 */
 	s =  __aclp__getNextLASRule(aci_item, acestr, &end);
 	while ( s ) {
-		if ( 0 == strncmp ( s, DS_LAS_USERDNATTR, 10) ||
-			( 0 == strncmp ( s, DS_LAS_USERATTR, 8))) {
+		if ( (0 == strncmp(s, DS_LAS_USERDNATTR, 10)) ||
+			 (0 == strncmp(s, DS_LAS_USERATTR, 8)) ) {
 			/* 
 			** For userdnattr/userattr rule, the resources changes and hence
 			** we cannot cache the result. See above for more comments.
 			*/
 			aci_item->aci_elevel = ACI_ELEVEL_USERDNATTR;
-		} else if ( 0== strncmp ( s, DS_LAS_USERDN, 6)) {
+
+			rc = __aclp__copy_normalized_str(s, end, prevend,
+											 &ret_str, &retstr_len, 0);
+			if (rc < 0) {
+				goto error;
+			}
+		} else if ( 0 == strncmp ( s, DS_LAS_USERDN, 6)) {
 			p = strstr ( s, "=");
 			p--;
 			if ( strncmp (p, "!=", 2) == 0)
@@ -699,22 +790,12 @@ normalize_nextACERule:
 			 * which would ensure that acl info is not cached from
 			 * one resource entry to the next. (bug 558519)
 			*/
-			p = strstr ( p, "ldap");
-			if (p == NULL) {   
-				/* must start with ldap */
-				if (s_acestr) slapi_ch_free ( (void **) &s_acestr );
-				if (ret_str) slapi_ch_free ( (void **) &ret_str );
-				slapi_ch_free ( (void **) &s_aclstr );
-				return (NULL);
-			}
-			p += 8; /* for ldap:/// */
-			if( __aclp__dn_normalize (p, end) == NULL) {
-				if (s_acestr) slapi_ch_free ( (void **) &s_acestr );
-				if (ret_str) slapi_ch_free ( (void **) &ret_str );
-				slapi_ch_free ( (void **) &s_aclstr );
-				return (NULL);
+			rc = __aclp__copy_normalized_str(s, end, prevend,
+											 &ret_str, &retstr_len, 1);
+			if (rc < 0) {
+				goto error;
 			}
-		
+
 			/* we have a rule like userdn = "ldap:///blah". s points to blah now.
 			** let's find if we have a SELF rule like userdn = "ldap:///self".
 			** Since the resource changes on entry basis, we can't cache the 
@@ -750,6 +831,12 @@ normalize_nextACERule:
 				aci_item->aci_elevel = ACI_ELEVEL_GROUPDNATTR;
 			}
 			aci_item->aci_ruleType |= ACI_GROUPDNATTR_RULE;
+
+			rc = __aclp__copy_normalized_str(s, end, prevend,
+											 &ret_str, &retstr_len, 0);
+			if (rc < 0) {
+				goto error;
+			}
 		} else if ( 0 == strncmp ( s, DS_LAS_GROUPDN, 7)) {
 
 			p = strstr ( s, "=");
@@ -757,21 +844,12 @@ normalize_nextACERule:
 			if ( strncmp (p, "!=", 2) == 0)
 				aci_item->aci_type |= ACI_CONTAIN_NOT_GROUPDN;
 
-			p = strstr ( s, "ldap");
-			if (p == NULL) {   
-				/* must start with ldap */
-				if (s_acestr) slapi_ch_free ( (void **) &s_acestr );
-				if (ret_str) slapi_ch_free ( (void **) &ret_str );
-				slapi_ch_free ( (void **) &s_aclstr );
-				return (NULL);
-			}
-			p += 8;
-			if (__aclp__dn_normalize (p, end) == NULL) {
-				if (s_acestr) slapi_ch_free ( (void **) &s_acestr );
-				if (ret_str) slapi_ch_free ( (void **) &ret_str );
-				slapi_ch_free ( (void **) &s_aclstr );
-				return (NULL);
+			rc = __aclp__copy_normalized_str(s, end, prevend,
+											 &ret_str, &retstr_len, 1);
+			if (rc < 0) {
+				goto error;
 			}
+
 			/* check for param rules */
 			__aclp_chk_paramRules ( aci_item, p, end );
 
@@ -786,21 +864,12 @@ normalize_nextACERule:
 			if ( strncmp (p, "!=", 2) == 0)
 				aci_item->aci_type |= ACI_CONTAIN_NOT_ROLEDN;
 
-			p = strstr ( s, "ldap");
-			if (p == NULL) {   
-				/* must start with ldap */
-				if (s_acestr) slapi_ch_free ( (void **) &s_acestr );
-				if (ret_str) slapi_ch_free ( (void **) &ret_str );
-				slapi_ch_free ( (void **) &s_aclstr );
-				return (NULL);
-			}
-			p += 8;
-			if (__aclp__dn_normalize (p, end) == NULL) {
-				if (s_acestr) slapi_ch_free ( (void **) &s_acestr );
-				if (ret_str) slapi_ch_free ( (void **) &ret_str );
-				slapi_ch_free ( (void **) &s_aclstr );
-				return (NULL);
+			rc = __aclp__copy_normalized_str(s, end, prevend,
+											 &ret_str, &retstr_len, 1);
+			if (rc < 0) {
+				goto error;
 			}
+
 			/* check for param rules */
 			__aclp_chk_paramRules ( aci_item, p, end );
 
@@ -808,40 +877,47 @@ normalize_nextACERule:
 			if ( aci_item->aci_elevel > ACI_ELEVEL_GROUPDN )
 				aci_item->aci_elevel = ACI_ELEVEL_GROUPDN;*/
 			aci_item->aci_ruleType |= ACI_ROLEDN_RULE;
+		} else {
+			/* adding the string no need to be processed
+			 * (e.g., dns="lab.example.com)" */
+			aclutil_str_append_ext(&ret_str, &retstr_len, 
+									prevend, end - prevend);
 		}
+		prevend = end;
 		s = ++end;
 		s =  __aclp__getNextLASRule(aci_item, s, &end);
-	}/* while */
+		if (NULL == s) {
+			/* adding the rest of the string, e.g. '\"' */
+			aclutil_str_append_ext(&ret_str, &retstr_len, 
+									prevend, strlen(prevend));
+		}
+	} /* while */
 
-	/* get the head of the string */
-	acestr = s_acestr;
-	len = strlen( acestr);
-	ptr =  acestr +len-1;
-	while (*ptr && *ptr != '\"'  && *ptr != ')' ) *ptr-- = ' ';
-	ptr++;
-	*ptr = ';';
-
-	aclutil_str_appened (&ret_str, acestr);
-	if (s_acestr)  {
-		slapi_ch_free ( (void **) &s_acestr );
-	}
-	s_acestr = NULL;
+	slapi_ch_free_string (&s_acestr);
+    __acl_strip_trailing_space(ret_str);
+	aclutil_str_append_ext(&ret_str, &retstr_len, ";", 1);
 
 	if (nextACE) {
 		s = strstr (nextACE, "allow");
 		if (s == NULL) s = strstr (nextACE, "deny");
 		if (s == NULL)  {
 			if (nextACE && *nextACE != '\0')
-				aclutil_str_appened (&ret_str, nextACE);
-			slapi_ch_free ( (void **) &s_aclstr );
+				aclutil_str_append (&ret_str, nextACE);
+			slapi_ch_free_string (&s_aclstr);
 			return (ret_str);
 		}
 		acestr = nextACE;
 		goto normalize_nextACERule;
 	}
 
-	slapi_ch_free ( (void **) &s_aclstr );
+	slapi_ch_free_string (&s_aclstr);
 	return (ret_str);
+
+error:
+	slapi_ch_free_string (&ret_str);
+	slapi_ch_free_string (&s_aclstr);
+	slapi_ch_free_string (&s_acestr);
+	return NULL;
 }
 /*
  * 
@@ -857,7 +933,7 @@ __aclp__getNextLASRule (aci_t *aci_item, char *original_str , char **endOfCurrRu
 {
 	char	*newstr, *word, *next, *start, *end;
 	char	*ruleStart = NULL;
-	int		len, ruleLen;
+	int		len, ruleLen = 0;
 	int in_dn_expr = 0;
 
 	*endOfCurrRule = NULL;	
@@ -1029,43 +1105,7 @@ __aclp__getNextLASRule (aci_t *aci_item, char *original_str , char **endOfCurrRu
 
 	return ( ruleStart );
 }
-/******************************************************************************
-*
-* __aclp__dn_normalize
-*
-*	Normalize the DN INPLACE. This routine is similar to slapi_dn_normalize()
-*	except various small stuff at the end.
-*	Normalize until the "end" and not to the end of string.
-*
-******************************************************************************/
-static char *
-__aclp__dn_normalize( char *dn , char *end)
-{
-	char *d;
-
-	if ((end - dn) < 0) {
-		return(NULL);
-	}
 
-	d = slapi_dn_normalize_to_end ( dn, end );
-
-	/* Do I have the quotes already */
-	if (*d != '\"' ) {
-		/* 
-		** We are taking care of this situation
-		**  "   ") ". We need to remove the space
-		** infront and tack it after the quote like this.
-		**  ""   ) ". 
-		*/
-
-		*d = '\"';
-		d++;	
-		while (*d && *d != '\"') *d++ = ' ';
-		*d = ' ';
-	}
-
-	return( dn );
-}
 /***************************************************************************
 * acl__get_aci_right
 *
@@ -1263,6 +1303,7 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 	}
 
 	while (str != 0 && *str != 0) {
+		int lenstr = 0;
 
 		__acl_strip_leading_space(&str);
 
@@ -1292,23 +1333,28 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 		attr = (Targetattr *) slapi_ch_malloc (sizeof (Targetattr));
 		memset (attr, 0, sizeof(Targetattr));
                                 
-            if (strchr(str, '*')) { 
-
+		/* strip double quotes */
+		lenstr = strlen(str);
+		if (*str == '"' && *(str + lenstr - 1) == '"') {
+			*(str + lenstr - 1) = '\0';
+			str++;
+		}
+		if (strchr(str, '*')) {
+             		
 			/* It contains a * so it's something like * or cn* */
 			if (strcmp(str, "*" ) != 0) {
 				char			line[100];
 				char *lineptr = &line[0];
 				char *newline = NULL;
-				int lenstr = 0;
 				struct  slapi_filter	*f = NULL;
 
-				if ((lenstr = strlen(str)) > 91) { /* 100 - 8 for "(attr =%s)" */
-					newline = slapi_ch_malloc(lenstr + 9);
+				if (lenstr > 92) { /* 100 - 8 for "(attr=%s)\0" */
+					newline = slapi_ch_malloc(lenstr + 8);
 					lineptr = newline;
 				}
 
 				attr->attr_type = ACL_ATTR_FILTER;
-				sprintf (lineptr, "(attr =%s)", str);
+				sprintf (lineptr, "(attr=%s)", str);
 				f = slapi_str2filter (lineptr);
 	
 				if (f == NULL)  {
@@ -1320,7 +1366,7 @@ __aclp__init_targetattr (aci_t *aci, char *attr_val)
 
 				if (newline) slapi_ch_free((void **) &newline);
 			} else {
-             		attr->attr_type = ACL_ATTR_STAR;
+				attr->attr_type = ACL_ATTR_STAR;
 				attr->u.attr_str = slapi_ch_strdup (str);
 			}
 

+ 14 - 3
ldap/servers/plugins/acl/aclproxy.c

@@ -87,7 +87,9 @@ parse_LDAPProxyAuth(struct berval *spec_ber, int version, char **errtextp,
   LDAPProxyAuth *spec = NULL;
   BerElement *ber = NULL;
   char *errstring = "unable to parse proxied authorization control";
-
+  int rc = 0;
+  char *normed = NULL;
+  size_t dnlen = 0;
 
   BEGIN
     ber_tag_t tag;
@@ -132,11 +134,20 @@ parse_LDAPProxyAuth(struct berval *spec_ber, int version, char **errtextp,
 			errstring = "proxied authorization id must be a DN (dn:...)";
 			break;
 		}
-		strcpy( spec->auth_dn, spec->auth_dn + 3 );
+		/* memmove is safe for overlapping copy */
+		memmove ( spec->auth_dn, spec->auth_dn + 3, strlen(spec->auth_dn) - 2);/* 1 for '\0' */
 	}
 
-	slapi_dn_normalize(spec->auth_dn);
 	lderr = LDAP_SUCCESS;	/* got it! */
+	rc = slapi_dn_normalize_ext(spec->auth_dn, 0, &normed, &dnlen);
+	if (rc < 0) {
+		lderr = LDAP_INVALID_SYNTAX;
+	} else if (rc == 0) { /* spec->auth_dn is passed in; not terminated */
+		*(normed + dnlen) = '\0';
+	} else {
+		slapi_ch_free_string(&spec->auth_dn);
+		spec->auth_dn = normed;
+	}
   END
 
   /* Cleanup */

+ 54 - 12
ldap/servers/plugins/acl/aclutil.c

@@ -65,7 +65,7 @@ static PRIntn	acl_ht_display_entry(PLHashEntry *he, PRIntn i, void *arg);
 /*	UTILITY FUNCTIONS						   */
 /***************************************************************************/
 int
-aclutil_str_appened(char **str1, const char *str2)
+aclutil_str_append(char **str1, const char *str2)
 {
 	int new_len;
  
@@ -87,6 +87,43 @@ aclutil_str_appened(char **str1, const char *str2)
     return(0);
 }
 
+/* 
+ * dlen: the length of the buffer *dest (not the string length in *dest)
+ */ 
+int
+aclutil_str_append_ext(char **dest, size_t *dlen, const char *src, size_t slen)
+{
+    char *ptr = NULL;
+    int rc = 0;
+
+    if ( dest == NULL || src == NULL ) {
+        return rc;    
+    }
+
+    if (0 == slen) {
+        slen = strlen(src);
+    }
+    if (*dest && dlen > 0) {
+        size_t dest_strlen = strlen(*dest);
+        size_t new_len = dest_strlen + slen + 1;
+        if (new_len > *dlen) {
+            *dest = (char *)slapi_ch_realloc(*dest, new_len);
+            *dlen = new_len;
+            ptr = *dest + dest_strlen;
+        } else {
+            ptr = *dest + dest_strlen;
+        }
+    } else {
+        *dlen = slen + 1;
+        *dest = (char *)slapi_ch_malloc(*dlen);
+        ptr = *dest;
+    }
+    memcpy(ptr, src, slen);
+    *(ptr + slen) = '\0';
+
+    return rc;
+}
+
 /***************************************************************************/
 /*	Print routines     						   */
 /***************************************************************************/
@@ -104,9 +141,14 @@ acl_print_acllib_err (NSErr_t *errp , char * str)
 	aclErrorFmt(errp, msgbuf, ACLUTIL_ACLLIB_MSGBUF_LEN, 1);      
 	msgbuf[ACLUTIL_ACLLIB_MSGBUF_LEN-1] = '\0';
 
-	if (msgbuf)
-		slapi_log_error(SLAPI_LOG_ACL, plugin_name,"ACL LIB ERR:(%s)(%s)\n", 
-				msgbuf, str ? str: "NULL"); 
+	if (strlen(msgbuf) > 0) {
+		slapi_log_error(SLAPI_LOG_ACL, plugin_name,"ACL LIB ERR:(%s)(%s)\n",
+				msgbuf, str ? str: "NULL");
+	} else {
+		slapi_log_error(SLAPI_LOG_ACL, plugin_name,"ACL LIB ERR:(%s)\n", 
+				str ? str: "NULL"); 
+	}
+
 }
 void
 aclutil_print_aci (aci_t *aci_item, char *type)
@@ -240,7 +282,7 @@ aclutil_print_err (int rv , const Slapi_DN *sdn, const struct berval* val,
 
 	if (errbuf) {
 		/* If a buffer is provided, then copy the error */
-		aclutil_str_appened(errbuf, lineptr );	
+		aclutil_str_append(errbuf, lineptr );	
 	}
 
 	slapi_log_error( SLAPI_LOG_FATAL, plugin_name, "%s", lineptr);
@@ -436,7 +478,7 @@ acl_gen_err_msg(int access, char *edn, char *attr, char **errbuf)
 		line = PR_smprintf(
 			"Insufficient 'delete' privilege to delete the entry '%s'.\n",edn);
 	}
-	aclutil_str_appened(errbuf, line );
+	aclutil_str_append(errbuf, line );
 
 	if (line) {
 		PR_smprintf_free(line);
@@ -540,7 +582,7 @@ aclutil_expand_paramString ( char *str, Slapi_Entry *e )
 				goto cleanup;
 			}
 			*p = '\0';
-			aclutil_str_appened ( &buf,a_dns[i]);
+			aclutil_str_append ( &buf,a_dns[i]);
 
 			if ( type == 1 ) {
 				/* xyz = $dn.o */
@@ -573,15 +615,15 @@ aclutil_expand_paramString ( char *str, Slapi_Entry *e )
 					kk= slapi_attr_next_value( attr, kk, &sval );
 					if ( kk != -1 )  /* can't handle multiple --error */
 						goto cleanup;
+					attrValue = slapi_value_get_berval ( t_sval );
+					attrVal = attrValue->bv_val;
 				}
-				attrValue = slapi_value_get_berval ( t_sval );
-				attrVal = attrValue->bv_val;
 			}
 		} else {
 			attrVal = a_dns[i];
 		}
-		aclutil_str_appened ( &buf, attrVal);
-		aclutil_str_appened ( &buf, ",");
+		aclutil_str_append ( &buf, attrVal);
+		aclutil_str_append ( &buf, ",");
 	}
 	rc = 0;		/* everything is okay*/
 	/* remove the last comma */
@@ -607,7 +649,7 @@ __aclutil_extract_dn_component ( char **e_dns,  int position, char *attrName )
 
 	int			i, matched, len;
 	char		*s;
-	int			matchedPosition;
+	int			matchedPosition = 0;
 
 	len = strlen ( attrName );
 

+ 7 - 3
ldap/servers/plugins/chainingdb/cb_config.c

@@ -63,24 +63,28 @@ int cb_config_add_dse_entries(cb_backend *cb, char **entries, char *string1, cha
         Slapi_PBlock *util_pb = NULL;
         int res, rc = 0;
         char entry_string[CB_BUFSIZE];
+        char *dn = NULL;
 
         for(x = 0; strlen(entries[x]) > 0; x++) {
                 util_pb = slapi_pblock_new();
                 PR_snprintf(entry_string, sizeof(entry_string), entries[x], string1, string2, string3);
                 e = slapi_str2entry(entry_string, 0);
+                dn = slapi_ch_strdup(slapi_entry_get_dn(e)); /* for err msg */
                 slapi_add_entry_internal_set_pb(util_pb, e, NULL, cb->identity, 0);
 		slapi_add_internal_pb(util_pb);
 		slapi_pblock_get(util_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
 		if ( LDAP_SUCCESS != res && LDAP_ALREADY_EXISTS != res ) {
 		  char ebuf[ BUFSIZ ];
-		  slapi_log_error(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, 
+		  slapi_log_error(SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM, 
 				  "Unable to add config entry (%s) to the DSE: %s\n",
-				  escape_string(slapi_entry_get_dn(e), ebuf),
+				  escape_string(dn, ebuf),
 				  ldap_err2string(res));
 		  rc = res;
 		  slapi_pblock_destroy(util_pb);
+		  slapi_ch_free_string(&dn);
 		  break;
 		}
+		slapi_ch_free_string(&dn);
 		slapi_pblock_destroy(util_pb);
         }
         return rc;
@@ -161,7 +165,7 @@ int cb_config_load_dse_info(Slapi_PBlock * pb) {
 
 	/* Get the default instance value entry if it exists */
 	/* else create it 				     */
-
+	/* This dn is already normalized */
 	PR_snprintf(defaultDn,sizeof(defaultDn),"cn=default instance config,%s",cb->pluginDN);
 
         default_pb = slapi_pblock_new();

+ 3 - 1
ldap/servers/plugins/chainingdb/cb_init.c

@@ -82,7 +82,9 @@ chaining_back_init( Slapi_PBlock *pb )
 
 	/* Initialize misc. fields */
 	cb->config.rwl_config_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "chaining_db");
-        rc = slapi_pblock_set( pb, SLAPI_PLUGIN_PRIVATE, (void *) cb );
+	rc = slapi_pblock_set( pb, SLAPI_PLUGIN_PRIVATE, (void *) cb );
+
+	/* These DNs are already normalized */
 	cb->pluginDN=slapi_ch_smprintf("cn=%s,%s",CB_PLUGIN_NAME,PLUGIN_BASE_DN);
 
 	cb->configDN=slapi_ch_smprintf("cn=config,%s",cb->pluginDN);

+ 4 - 4
ldap/servers/plugins/chainingdb/cb_instance.c

@@ -153,10 +153,10 @@ cb_dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
 static char *cb_skeleton_entries[] =
 {
 
-    "dn:cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config\n"
-    "objectclass:top\n"
-    "objectclass:extensibleObject\n"
-    "cn:monitor\n",
+    "dn: cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config\n"
+    "objectclass: top\n"
+    "objectclass: extensibleObject\n"
+    "cn: monitor\n",
 
         ""
 };

+ 117 - 10
ldap/servers/plugins/cos/cos_cache.c

@@ -69,6 +69,8 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
+
 #include "portable.h"
 #include "slapi-plugin.h"
 
@@ -324,6 +326,8 @@ static int cos_cache_vattr_compare(vattr_sp_handle *handle, vattr_context *c, Sl
 static int cos_cache_vattr_types(vattr_sp_handle *handle,Slapi_Entry *e,vattr_type_list_context *type_context,int flags);
 static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Slapi_Entry *e, char *type, Slapi_ValueSet **out_attr, Slapi_Value *test_this, int *result, int *ops);
 
+static int hexchar2int( char c );
+
 /* 
 	compares s2 to s1 starting from end of string until the beginning of either
 	matches result in the s2 value being clipped from s1 with a NULL char
@@ -904,14 +908,29 @@ static int 	cos_dn_defs_cb (Slapi_Entry* e, void *callback_data) {
 										{
 											/* get the parent of the definition */
 											
-											char *parent = slapi_dn_parent(pDn->val);
-											slapi_dn_normalize( parent );
+											char *parent = NULL;
+											size_t plen = 0;
+											int rc = 0;
+											char *orig = slapi_dn_parent(pDn->val);
+											rc = slapi_dn_normalize_ext(orig,
+															0, &parent, &plen);
+											if (rc < 0) {
+												LDAPDebug(LDAP_DEBUG_ANY, 
+													"cos_cache_build_definition_list: failed to normalize parent dn %s. Adding the pre normalized dn.\n", orig, 0, 0);
+												parent = orig;
+											} else if (rc == 0) {
+												/* passed in. not terminated */
+												*(parent + plen) = '\0';
+											}
 											
 											cos_cache_add_attrval(&pCosTargetTree, parent);
 											if(!pCosTemplateDn)
 												cos_cache_add_attrval(&pCosTemplateDn, parent);
 											
-											slapi_ch_free((void**)&parent);
+											if (orig != parent) {
+												slapi_ch_free_string(&orig);
+											}
+											slapi_ch_free_string(&parent);
 										}
 										
 										slapi_vattrspi_regattr((vattr_sp_handle *)vattr_handle, dnVals[valIndex]->bv_val, NULL, NULL);			
@@ -1916,16 +1935,33 @@ static int cos_cache_add_tmpl(cosTemplates **pTemplates, cosAttrValue *dn, cosAt
 	theTemp = (cosTemplates*) slapi_ch_malloc(sizeof(cosTemplates));
 	if(theTemp)
 	{
-		char *grade = (char*)slapi_ch_malloc(strlen(dn->val)+1);
+		char *grade = NULL;
 		int grade_index = 0;
 		int index = 0;
+		int lastindex = 0;
 		int template_default = 0;
-
-		slapi_dn_normalize(dn->val);
+		char *dnval = NULL;
+		size_t dnlen = 0;
+		int rc = 0;
+
+		rc = slapi_dn_normalize_ext(dn->val, 0, &dnval, &dnlen);
+		if (rc < 0) {
+			LDAPDebug(LDAP_DEBUG_ANY, 
+				"cos_cache_add_tmpl: failed to normalize dn %s. "
+				"Processing the pre normalized dn.\n", dn->val, 0, 0);
+		} else if (rc == 0) {
+			/* passed in. not terminated */
+			*(dnval + dnlen) = '\0';
+		} else {
+			slapi_ch_free_string(&dn->val);
+			dn->val = dnval;
+		}
+		grade = (char*)slapi_ch_malloc(strlen(dn->val)+1);
 
 		/* extract the cos grade */
 		while(dn->val[index] != '=' && dn->val[index] != '\0')
 			index++;
+		lastindex = strlen(dn->val) - 1;
 		
 		if(dn->val[index] == '=')
 		{
@@ -1945,7 +1981,29 @@ static int cos_cache_add_tmpl(cosTemplates **pTemplates, cosAttrValue *dn, cosAt
 				}
 				else
 				{
-					if(dn->val[index] != '\\') /* skip escape chars */
+					if(dn->val[index] == '\\')
+					{ 
+						if ((index+2 <= lastindex) && isxdigit(dn->val[index+1]) && 
+							isxdigit(dn->val[index+2])) {
+							/* Convert ESC HEX HEX to a real char */
+							int n = hexchar2int(dn->val[index+1]);
+							int n2 = hexchar2int(dn->val[index+2]);
+							n = (n << 4) + n2;
+							if (n == 0) { /* don't change \00 */
+								grade[grade_index] = dn->val[index++]; /* '\\' */
+								grade_index++;
+								grade[grade_index] = dn->val[index++]; /* 0 */
+								grade_index++;
+								grade[grade_index] = dn->val[index]; /* 0 */
+								grade_index++;
+							} else {
+								grade[grade_index] = n;
+								index += 2;
+								grade_index++;
+							}
+						} /* else: skip escape chars */
+					}
+					else
 					{
 						grade[grade_index] = dn->val[index];
 						grade_index++;
@@ -2329,8 +2387,24 @@ static int cos_cache_query_attr(cos_cache *ptheCache, vattr_context *context, Sl
 		/* is this entry a child of the target tree(s)? */
 		do
 		{
-			if(pTargetTree)
-				slapi_dn_normalize( pTargetTree->val );
+			if(pTargetTree) {
+				int rc = 0;
+				char *tval = NULL;
+				size_t tlen = 0;
+				rc = slapi_dn_normalize_ext(pTargetTree->val, 0, &tval, &tlen);
+				if (rc < 0) {
+					LDAPDebug(LDAP_DEBUG_ANY, 
+						"cos_cache_query_attr: failed to normalize dn %s. "
+						"Processing the pre normalized dn.\n",
+						pTargetTree->val, 0, 0);
+				} else if (rc == 0) {
+					/* passed in. not terminated */
+					*(tval + tlen) = '\0';
+				} else {
+					slapi_ch_free_string(&pTargetTree->val);
+					pTargetTree->val = tval;
+				}
+			}
 
     		if(	pTargetTree->val == 0 || 
 				slapi_dn_issuffix(pDn, pTargetTree->val) != 0 || 
@@ -2800,7 +2874,23 @@ static int cos_cache_index_all(cosCache *pCache)
 
 				while(pAttrVal)
 				{
-					slapi_dn_normalize(pAttrVal->val);
+					int rc = 0;
+					char *dnval = NULL;
+					size_t dnlen = 0;
+					rc = slapi_dn_normalize_ext(pAttrVal->val, 0,
+												&dnval, &dnlen);
+					if (rc < 0) {
+						LDAPDebug(LDAP_DEBUG_ANY, 
+							"cos_cache_index_all: failed to normalize dn %s. "
+							"Processing the pre normalized dn.\n", 
+							pAttrVal->val, 0, 0);
+					} else if (rc == 0) {
+						/* passed in. not terminated */
+						*(dnval + dnlen) = '\0';
+					} else {
+						slapi_ch_free_string(&pAttrVal->val);
+						pAttrVal->val = dnval;
+					}
 					pCache->ppTemplateList[tmpindex] = pAttrVal->val;
 
 					tmpindex++;
@@ -3519,3 +3609,20 @@ static int cos_cache_entry_is_cos_related( Slapi_Entry *e) {
 	}
 	return(rc);
 }
+
+/* copied from dn.c */
+static int
+hexchar2int( char c )
+{
+    if ( '0' <= c && c <= '9' ) {
+        return( c - '0' );
+    }
+    if ( 'a' <= c && c <= 'f' ) {
+        return( c - 'a' + 10 );
+    }
+    if ( 'A' <= c && c <= 'F' ) {
+        return( c - 'A' + 10 );
+    }
+    return( -1 );
+}
+

+ 40 - 13
ldap/servers/plugins/dna/dna.c

@@ -680,7 +680,7 @@ dna_parse_config_entry(Slapi_Entry * e, int apply)
     }
 
     entry = (struct configEntry *)
-	slapi_ch_calloc(1, sizeof(struct configEntry));
+    slapi_ch_calloc(1, sizeof(struct configEntry));
     if (NULL == entry) {
         ret = DNA_FAILURE;
         goto bail;
@@ -787,7 +787,7 @@ dna_parse_config_entry(Slapi_Entry * e, int apply)
     if (value) {
         /* TODO - Allow multiple scope settings for a single range.  This may
          * make ordering the scopes tough when we put them in the clist. */
-        entry->scope = slapi_dn_normalize(value);
+        entry->scope = value;
     } else {
         slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
                         "dna_parse_config_entry: The %s config "
@@ -817,6 +817,7 @@ dna_parse_config_entry(Slapi_Entry * e, int apply)
     if (value) {
         Slapi_Entry *shared_e = NULL;
         Slapi_DN *sdn = NULL;
+        char *normdn = NULL;
 
         sdn = slapi_sdn_new_dn_byref(value);
 
@@ -840,15 +841,29 @@ dna_parse_config_entry(Slapi_Entry * e, int apply)
             shared_e = NULL;
         }
 
-        entry->shared_cfg_base = slapi_ch_strdup(value);
-        slapi_dn_normalize(entry->shared_cfg_base);
+        normdn = slapi_create_dn_string("%s", value);
+        if (NULL == normdn) {
+            slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
+                            "dna_parse_config_entry: failed to normalize dn: "
+                            "%s\n", value);
+            ret = DNA_FAILURE;
+            goto bail;
+        }
+        entry->shared_cfg_base = normdn;
 
         /* We prepend the host & port of this instance as a
          * multi-part RDN for the shared config entry. */
-        entry->shared_cfg_dn = slapi_ch_smprintf("%s=%s+%s=%s,%s", DNA_HOSTNAME,
-                                          hostname, DNA_PORTNUM, portnum, value);
-        slapi_ch_free_string(&value);
-        slapi_dn_normalize(entry->shared_cfg_dn);
+        normdn = slapi_create_dn_string("%s=%s+%s=%s,%s", DNA_HOSTNAME,
+                                        hostname, DNA_PORTNUM, portnum, normdn);
+        if (NULL == normdn) {
+            slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
+                            "dna_parse_config_entry: failed to create dn: "
+                            "%s=%s+%s=%s,%s", DNA_HOSTNAME,
+                            hostname, DNA_PORTNUM, portnum, value);
+            ret = DNA_FAILURE;
+            goto bail;
+        }
+        entry->shared_cfg_dn = normdn;
 
         slapi_log_error(SLAPI_LOG_CONFIG, DNA_PLUGIN_SUBSYSTEM,
                         "----------> %s [%s]\n", DNA_SHARED_CFG_DN,
@@ -1680,8 +1695,6 @@ static char *dna_get_dn(Slapi_PBlock * pb)
         goto bail;
     }
 
-/*        slapi_dn_normalize( dn );
-*/
   bail:
     slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
                     "<-- dna_get_dn\n");
@@ -2310,7 +2323,14 @@ static int dna_is_replica_bind_dn(char *range_dn, char *bind_dn)
      * the shared config.  We need to see what the configured
      * replica bind DN is. */
     if (be_suffix) {
-        replica_dn = slapi_ch_smprintf("cn=replica,cn=\"%s\",cn=mapping tree,cn=config", be_suffix);
+        /* This function converts the old DN style to the new one. */
+        replica_dn = slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config", be_suffix);
+        if (NULL == replica_dn) {
+            slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
+                            "dna_is_replica_bind_dn: failed to create "
+                            "replica dn for %s\n", be_suffix);
+            return 1;
+        }
         replica_sdn = slapi_sdn_new_dn_passin(replica_dn);
 
         attrs[0] = DNA_REPL_BIND_DN;
@@ -2370,8 +2390,15 @@ static int dna_get_replica_bind_creds(char *range_dn, struct dnaServer *server,
 
     /* Fetch the replication agreement entry */
     if (be_suffix) {
-        replica_dn = slapi_ch_smprintf("cn=replica,cn=\"%s\",cn=mapping tree,cn=config",
-                                       be_suffix);
+        /* This function converts the old DN style to the new one. */
+        replica_dn = slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config", be_suffix);
+        if (NULL == replica_dn) {
+            slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
+                            "dna_get_replica_bind_creds: failed to create "
+                            "replica dn for %s\n", be_suffix);
+            ret = LDAP_PARAM_ERROR;
+            goto bail;
+        }
 
         filter = slapi_ch_smprintf("(&(nsds5ReplicaHost=%s)(|(" DNA_REPL_PORT "=%u)"
                                    "(" DNA_REPL_PORT "=%u)))",

+ 2 - 2
ldap/servers/plugins/linkedattrs/fixup_task.c

@@ -80,9 +80,9 @@ linked_attrs_fixup_task_add(Slapi_PBlock *pb, Slapi_Entry *e,
 		goto out;
 	}
 
-        if (linkdn) {
+	if (linkdn) {
 	    mytaskdata->linkdn = slapi_dn_normalize(slapi_ch_strdup(linkdn));
-        }
+	}
 
 	/* allocate new task now */
 	task = slapi_new_task(slapi_entry_get_ndn(e));

+ 1 - 3
ldap/servers/plugins/mep/mep.c

@@ -88,7 +88,6 @@ static int mep_modrdn_pre_op(Slapi_PBlock *pb);
 static int mep_load_config();
 static void mep_delete_config();
 static int mep_parse_config_entry(Slapi_Entry * e, int apply);
-static void mep_insert_config_index(struct configEntry *entry);
 static void mep_free_config_entry(struct configEntry ** entry);
 
 /*
@@ -949,7 +948,6 @@ mep_create_managed_entry(struct configEntry *config, Slapi_Entry *origin)
     Slapi_Entry *template = NULL;
     char *rdn_type = NULL;
     char **vals = NULL;
-    char *p = NULL;
     char *type = NULL;
     char *value = NULL;
     int vlen = 0;
@@ -1055,7 +1053,7 @@ mep_create_managed_entry(struct configEntry *config, Slapi_Entry *origin)
 
         /* Create the DN using the mapped RDN value
          * and the base specified in the config. */
-        dn = slapi_ch_smprintf("%s=%s,%s", rdn_type, rdn_val, config->managed_base);
+        dn = slapi_create_dn_string("%s=%s,%s", rdn_type, rdn_val, config->managed_base);
 
         slapi_ch_free_string(&rdn_val);
 

+ 2 - 2
ldap/servers/plugins/pwdstorage/smd5_pwd.c

@@ -89,7 +89,7 @@ smd5_pw_cmp( const char *userpwd, const char *dbpwd )
       memset( quick_dbhash, 0, sizeof(quick_dbhash) );
    }
 
-   hashresult = PL_Base64Decode( dbpwd, 0, (char *)dbhash );
+   hashresult = PL_Base64Decode( dbpwd, 0, dbhash );
    if (NULL == hashresult) {
       slapi_log_error( SLAPI_LOG_PLUGIN, SALTED_MD5_SUBSYSTEM_NAME,
             "smd5_pw_cmp: userPassword \"%s\" is the wrong length "
@@ -139,7 +139,7 @@ smd5_pw_enc( const char *pwd )
    memset( hash_out, 0, sizeof(hash_out) );
 
    /* generate a new random salt */
-   slapi_rand_array( salt, MD5_DEFAULT_SALT_LENGTH );
+   slapi_rand_array( (void *)salt, MD5_DEFAULT_SALT_LENGTH );
    saltval.bv_val = (void*)salt;
    saltval.bv_len = MD5_DEFAULT_SALT_LENGTH;
 

+ 33 - 4
ldap/servers/plugins/referint/referint.c

@@ -385,6 +385,7 @@ _update_one_per_mod(const char *entryDN, /* DN of the searched entry */
             /* no need to free superior */
             superior = slapi_dn_find_parent(origDN);
         }
+        /* newRDN and superior are already normalized. */
         newDN = slapi_ch_smprintf("%s,%s", newRDN, superior);
         /* 
          * Compare the modified dn with the value of 
@@ -409,9 +410,19 @@ _update_one_per_mod(const char *entryDN, /* DN of the searched entry */
              nval != -1;
              nval = slapi_attr_next_value(attr, nval, &v)) {
             char *p = NULL;
+            size_t dnlen = 0;
             /* DN syntax, which should be a string */
             sval = slapi_ch_strdup(slapi_value_get_string(v));
-            slapi_dn_normalize_case(sval);
+            rc = slapi_dn_normalize_case_ext(sval, 0,  &p, &dnlen);
+            if (rc == 0) { /* sval is passed in; not terminated */
+                *(p + dnlen) = '\0';
+                sval = p;
+            } else if (rc > 0) {
+                slapi_ch_free_string(&sval);
+                sval = p;
+            }
+            /* else: (rc < 0) Ignore the DN normalization error for now. */
+
             p = PL_strstr(sval, norm_origDN);
             if (p == sval) {
                 /* (case 1) */
@@ -448,6 +459,7 @@ _update_one_per_mod(const char *entryDN, /* DN of the searched entry */
 
                 bak = *p;
                 *p = '\0';
+                /* newRDN and superior are already normalized. */
                 newvalue = slapi_ch_smprintf("%s%s", sval, newDN);
                 *p = bak;
                 values_add[0]=newvalue;
@@ -579,9 +591,19 @@ _update_all_per_mod(const char *entryDN, /* DN of the searched entry */
              nval != -1;
              nval = slapi_attr_next_value(attr, nval, &v)) {
             char *p = NULL;
+            size_t dnlen = 0;
             /* DN syntax, which should be a string */
             sval = slapi_ch_strdup(slapi_value_get_string(v));
-            slapi_dn_normalize_case(sval);
+            rc = slapi_dn_normalize_case_ext(sval, 0,  &p, &dnlen);
+            if (rc == 0) { /* sval is passed in; not terminated */
+                *(p + dnlen) = '\0';
+                sval = p;
+            } else if (rc > 0) {
+                slapi_ch_free_string(&sval);
+                sval = p;
+            }
+            /* else: (rc < 0) Ignore the DN normalization error for now. */
+
             p = PL_strstr(sval, norm_origDN);
             if (p == sval) {
                 /* (case 1) */
@@ -632,6 +654,7 @@ update_integrity(char **argv, char *origDN,
     int i, j;
     const char *search_base = NULL;
     char *norm_origDN = NULL;
+    size_t dnlen = 0;
     int rc;
    
     if ( argv == NULL ) {
@@ -644,8 +667,14 @@ update_integrity(char **argv, char *origDN,
     /* for now, just putting attributes to keep integrity on in conf file,
        until resolve the other timing mode issue */
   
-    norm_origDN = slapi_ch_strdup(origDN);
-    slapi_dn_normalize_case(norm_origDN);
+    rc = slapi_dn_normalize_case_ext(origDN, 0,  &norm_origDN, &dnlen);
+    if (rc == 0) { /* origDN is passed in; not terminated */
+        *(norm_origDN + dnlen) = '\0';
+        norm_origDN = slapi_ch_strdup(norm_origDN);
+    } else if (rc < 0) {
+        /* Ignore the DN normalization error for now. */
+        norm_origDN = slapi_ch_strdup(origDN);
+    }
 
     search_result_pb = slapi_pblock_new();
 

+ 1 - 0
ldap/servers/plugins/replication/legacy_consumer.c

@@ -83,6 +83,7 @@ static void legacy_consumer_encode_pw (Slapi_Entry *e);
 static void set_legacy_purl (Slapi_PBlock *pb, const char *purl);
 static int get_legacy_referral (Slapi_Entry *e, char **referral, char **state);
 
+/* LEGACY_CONSUMER_CONFIG_DN is no need to be normalized. */
 #define LEGACY_CONSUMER_CONFIG_DN "cn=legacy consumer," REPL_CONFIG_TOP
 #define LEGACY_CONSUMER_FILTER "(objectclass=*)"
 

+ 1 - 1
ldap/servers/plugins/replication/repl5.h

@@ -319,8 +319,8 @@ char **agmt_validate_replicated_attributes(Repl_Agmt *ra);
 void* agmt_get_priv (const Repl_Agmt *agmt);
 void agmt_set_priv (Repl_Agmt *agmt, void* priv);
 
-
 int get_agmt_agreement_type ( Repl_Agmt *agmt);
+int agmt_has_protocol(Repl_Agmt *agmt);
 
 typedef struct replica Replica;
 

+ 14 - 5
ldap/servers/plugins/replication/repl5_agmt.c

@@ -2216,13 +2216,21 @@ agmt_get_consumer_rid ( Repl_Agmt *agmt, void *conn )
 {
 	if ( agmt->consumerRID <= 0 ) {
 
-		char mapping_tree_node[512];
+		char *mapping_tree_node = NULL;
 		struct berval **bvals = NULL;
 
-		PR_snprintf ( mapping_tree_node,
-					  sizeof (mapping_tree_node), 
-					 "cn=replica,cn=\"%s\",cn=mapping tree,cn=config",
-					  slapi_sdn_get_dn (agmt->replarea) );
+
+		/* This function converts the old style DN to the new one. */
+		mapping_tree_node = 
+		slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config",
+							   slapi_sdn_get_dn (agmt->replarea) );
+		if (NULL == mapping_tree_node) {
+			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, 
+							"agmt_get_consumer_rid: failed to normalize "
+							"replica dn for %s\n", 
+							slapi_sdn_get_dn (agmt->replarea));
+			agmt->consumerRID = 0;
+		}
 		conn_read_entry_attribute ( conn, mapping_tree_node, "nsDS5ReplicaID", &bvals );
 		if ( NULL != bvals && NULL != bvals[0] ) {
 			char *ridstr = slapi_ch_malloc( bvals[0]->bv_len + 1 );
@@ -2232,6 +2240,7 @@ agmt_get_consumer_rid ( Repl_Agmt *agmt, void *conn )
 			slapi_ch_free ( (void**) &ridstr );
 			ber_bvecfree ( bvals );
 		}
+		slapi_ch_free_string(&mapping_tree_node);
 	}
 
 	return agmt->consumerRID;

+ 2 - 1
ldap/servers/plugins/replication/repl5_agmtlist.c

@@ -50,7 +50,8 @@
 #include "repl5.h"
 #include <plstr.h>
 
-#define AGMT_CONFIG_BASE "cn=mapping tree, cn=config"
+/* normalized DN */
+#define AGMT_CONFIG_BASE "cn=mapping tree,cn=config"
 #define CONFIG_FILTER "(objectclass=nsds5replicationagreement)"
 #define WINDOWS_CONFIG_FILTER "(objectclass=nsdsWindowsreplicationagreement)"
 #define GLOBAL_CONFIG_FILTER "(|" CONFIG_FILTER WINDOWS_CONFIG_FILTER " )"

+ 0 - 1
ldap/servers/plugins/replication/repl5_protocol.c

@@ -173,7 +173,6 @@ void
 prot_free(Repl_Protocol **rpp)
 {
     Repl_Protocol *rp = NULL;
-    PRIntervalTime interval;
 
     if (rpp == NULL || *rpp == NULL) return;
 

+ 25 - 2
ldap/servers/plugins/replication/repl5_replica.c

@@ -1528,6 +1528,12 @@ _replica_get_config_entry (const Slapi_DN *root)
 	Slapi_PBlock *pb = NULL;
 
 	dn = _replica_get_config_dn (root);
+	if (NULL == dn) {
+		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+			"_replica_get_config_entry: failed to get the config dn for %s\n",
+			slapi_sdn_get_dn (root));
+		return NULL;
+	}
 	pb = slapi_pblock_new ();
 
 	slapi_search_internal_set_pb (pb, dn, LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, NULL,
@@ -1839,8 +1845,9 @@ _replica_get_config_dn (const Slapi_DN *root)
 
     PR_ASSERT (root);
 
-    dn = slapi_ch_smprintf("%s,cn=\"%s\",%s", REPLICA_RDN, slapi_sdn_get_dn (root), mp_base);
-
+    /* This function converts the old style DN to the new style. */
+    dn = slapi_create_dn_string("%s,cn=\"%s\",%s", 
+                                REPLICA_RDN, slapi_sdn_get_dn (root), mp_base);
     return dn;
 }
 
@@ -2162,6 +2169,13 @@ _replica_update_state (time_t when, void *arg)
 	r->repl_csn_assigned = PR_FALSE;
 
 	dn = _replica_get_config_dn (r->repl_root);
+	if (NULL == dn) {
+		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+			"_replica_update_state: failed to get the config dn for %s\n",
+			slapi_sdn_get_dn (r->repl_root));
+		PR_Unlock(r->repl_lock);
+		goto done;
+	}
 	pb = slapi_pblock_new();
 	mods[0] = (LDAPMod*)slapi_mod_get_ldapmod_byref(&smod);
 
@@ -3057,6 +3071,14 @@ replica_replace_ruv_tombstone(Replica *r)
     ruv_last_modified_to_smod ((RUV*)object_get_data(r->repl_ruv), &smod_last_modified);
 
     dn = _replica_get_config_dn (r->repl_root);
+	if (NULL == dn) {
+		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+			"replica_replace_ruv_tombstone: "
+			"failed to get the config dn for %s\n",
+			slapi_sdn_get_dn (r->repl_root));
+		PR_Unlock(r->repl_lock);
+		goto bail;
+	}
     mods[0] = (LDAPMod*)slapi_mod_get_ldapmod_byref(&smod);
     mods[1] = (LDAPMod*)slapi_mod_get_ldapmod_byref(&smod_last_modified);
 
@@ -3090,6 +3112,7 @@ replica_replace_ruv_tombstone(Replica *r)
 
     slapi_ch_free ((void**)&dn);
     slapi_pblock_destroy (pb);
+bail:
     slapi_mod_done (&smod);
     slapi_mod_done (&smod_last_modified);
 }

+ 1 - 0
ldap/servers/plugins/replication/repl5_replica_config.c

@@ -47,6 +47,7 @@
 #include "repl5.h"
 #include "cl5_api.h"
 
+/* CONFIG_BASE: no need to optimize */
 #define CONFIG_BASE		    "cn=mapping tree,cn=config"
 #define CONFIG_FILTER	    "(objectclass=nsDS5Replica)"
 #define TASK_ATTR           "nsds5Task"

+ 1 - 0
ldap/servers/plugins/replication/repl_init.c

@@ -207,6 +207,7 @@ legacy_entry_init( Slapi_PBlock *pb )
 static int
 create_config_top()
 {
+	/* DN part of this entry_string: no need to be optimized. */
 	char *entry_string = slapi_ch_strdup("dn: cn=replication,cn=config\nobjectclass: top\nobjectclass: extensibleobject\ncn: replication\n");
 	Slapi_PBlock *pb = slapi_pblock_new();
 	Slapi_Entry *e = slapi_str2entry(entry_string, 0);

+ 1 - 0
ldap/servers/plugins/retrocl/retrocl.c

@@ -266,6 +266,7 @@ char *retrocl_get_config_str(const char *attrt)
     int rc = 0;
     char *dn;
     
+    /* RETROCL_PLUGIN_DN is no need to be normalized. */
     dn = RETROCL_PLUGIN_DN;
     
     pb = slapi_pblock_new();

+ 12 - 1
ldap/servers/plugins/retrocl/retrocl_create.c

@@ -77,6 +77,7 @@ static int retrocl_create_be(const char *bedir)
     vals[1] = NULL; 
 
     e = slapi_entry_alloc();
+    /* RETROCL_LDBM_DN is no need to be normalized. */
     slapi_entry_set_dn(e,slapi_ch_strdup(RETROCL_LDBM_DN));
 
     /* Set the objectclass attribute */
@@ -142,6 +143,7 @@ static int retrocl_create_be(const char *bedir)
 
     /* we need the changenumber indexed */
     e = slapi_entry_alloc();
+    /* RETROCL_INDEX_DN is no need to be normalized. */
     slapi_entry_set_dn(e,slapi_ch_strdup(RETROCL_INDEX_DN));
 
     /* Set the objectclass attribute */
@@ -210,6 +212,7 @@ int retrocl_create_config(void)
     struct berval *vals[2];
     struct berval val;
     int rc;
+    char *mappingtree_dn = NULL;
 
     vals[0] = &val;
     vals[1] = NULL; 
@@ -219,7 +222,15 @@ int retrocl_create_config(void)
      * in the errors file when the referenced backend does not exist.
      */
     e = slapi_entry_alloc();
-    slapi_entry_set_dn(e,slapi_ch_strdup(RETROCL_MAPPINGTREE_DN));
+    /* This function converts the old DN style to the new one. */
+    mappingtree_dn = slapi_create_dn_string("%s", RETROCL_MAPPINGTREE_DN);
+    if (NULL == mappingtree_dn) {
+        slapi_log_error (SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
+                         "retrocl_create_config: failed to normalize "
+                         "mappingtree dn %s\n", RETROCL_MAPPINGTREE_DN);
+        return LDAP_PARAM_ERROR;
+    }
+    slapi_entry_set_dn(e, mappingtree_dn); /* mappingtree_dn is consumed */
     
     /* Set the objectclass attribute */
     val.bv_val = "top";

+ 127 - 39
ldap/servers/plugins/syntaxes/string.c

@@ -63,6 +63,7 @@ string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax,
 {
 	int	i, rc;
 	struct berval bvfilter_norm;
+	char *alt = NULL;
 
 	if(retVal) {
 		*retVal = NULL;
@@ -74,7 +75,12 @@ string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax,
 	bvfilter_norm.bv_val = slapi_ch_malloc( bvfilter->bv_len + 1 );
 	SAFEMEMCPY( bvfilter_norm.bv_val, bvfilter->bv_val, bvfilter->bv_len );
 	bvfilter_norm.bv_val[bvfilter->bv_len] = '\0';
-	value_normalize( bvfilter_norm.bv_val, syntax, 1 /* trim leading blanks */ );
+	/* 3rd arg: 1 - trim leading blanks */
+	value_normalize_ext( bvfilter_norm.bv_val, syntax, 1, &alt );
+	if (alt) {
+		slapi_ch_free_string(&bvfilter_norm.bv_val);
+		bvfilter_norm.bv_val = alt;
+	}
 	bvfilter_norm.bv_len = strlen(bvfilter_norm.bv_val);
 
 	for ( i = 0; (bvals != NULL) && (bvals[i] != NULL); i++ ) {
@@ -211,6 +217,7 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final,
 	Operation	*op = NULL;
 	Slapi_Regex	*re = NULL;
 	const char  *re_result = NULL;
+	char *alt = NULL;
 
 	LDAPDebug( LDAP_DEBUG_FILTER, "=> string_filter_sub\n",
 	    0, 0, 0 );
@@ -260,27 +267,45 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final,
 	}
 
 	if ( initial != NULL ) {
-		value_normalize( initial, syntax, 1 /* trim leading blanks */ );
+		/* 3rd arg: 1 - trim leading blanks */
+		value_normalize_ext( initial, syntax, 1, &alt );
 		*p++ = '^';
-		filter_strcpy_special_ext( p, initial, FILTER_STRCPY_ESCAPE_RECHARS );
+		if (alt) {
+			filter_strcpy_special_ext( p, alt, FILTER_STRCPY_ESCAPE_RECHARS );
+			slapi_ch_free_string(&alt);
+		} else {
+			filter_strcpy_special_ext( p, initial, FILTER_STRCPY_ESCAPE_RECHARS );
+		}
 		p = strchr( p, '\0' );
 	}
 	if ( any != NULL ) {
 		for ( i = 0; any[i] != NULL; i++ ) {
-			value_normalize( any[i], syntax, 0 /* DO NOT trim leading blanks */ );
+			/* 3rd arg: 0 - DO NOT trim leading blanks */
+			value_normalize_ext( any[i], syntax, 0, &alt );
 			/* ".*" + value */
 			*p++ = '.';
 			*p++ = '*';
-			filter_strcpy_special_ext( p, any[i], FILTER_STRCPY_ESCAPE_RECHARS );
+			if (alt) {
+				filter_strcpy_special_ext( p, alt, FILTER_STRCPY_ESCAPE_RECHARS );
+				slapi_ch_free_string(&alt);
+			} else {
+				filter_strcpy_special_ext( p, any[i], FILTER_STRCPY_ESCAPE_RECHARS );
+			}
 			p = strchr( p, '\0' );
 		}
 	}
 	if ( final != NULL ) {
-		value_normalize( final, syntax, 0 /* DO NOT trim leading blanks */ );
+		/* 3rd arg: 0 - DO NOT trim leading blanks */
+		value_normalize_ext( final, syntax, 0, &alt );
 		/* ".*" + value */
 		*p++ = '.';
 		*p++ = '*';
-		filter_strcpy_special_ext( p, final, FILTER_STRCPY_ESCAPE_RECHARS );
+		if (alt) {
+			filter_strcpy_special_ext( p, alt, FILTER_STRCPY_ESCAPE_RECHARS );
+			slapi_ch_free_string(&alt);
+		} else {
+			filter_strcpy_special_ext( p, final, FILTER_STRCPY_ESCAPE_RECHARS );
+		}
 		strcat( p, "$" );
 	}
 
@@ -327,9 +352,15 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final,
 			strcpy( tmpbuf, bvp->bv_val );
 			realval = tmpbuf;
 		}
-		value_normalize( realval, syntax, 1 /* trim leading blanks */ );
+		/* 3rd arg: 1 - trim leading blanks */
+		value_normalize_ext( realval, syntax, 1, &alt );
 
-		tmprc = slapi_re_exec( re, realval, time_up );
+		if (alt) {
+			tmprc = slapi_re_exec( re, alt, time_up );
+			slapi_ch_free_string(&alt);
+		} else {
+			tmprc = slapi_re_exec( re, realval, time_up );
+		}
 
 		LDAPDebug( LDAP_DEBUG_TRACE, "re_exec (%s) %i\n",
 				   escape_string( realval, ebuf ), tmprc, 0 );
@@ -359,6 +390,7 @@ string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,
 	Slapi_Value	**nbvals, **nbvlp;
 	Slapi_Value **bvlp;
 	char		*w, *c, *p;
+	char *alt = NULL;
 
 	if (NULL == ivals) {
 		return 1;
@@ -380,9 +412,16 @@ string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,
 		{
 			c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
 			/* if the NORMALIZED flag is set, skip normalizing */
-			if (!(slapi_value_get_flags(*bvlp) & SLAPI_ATTR_FLAG_NORMALIZED))
-				value_normalize( c, syntax, 1 /* trim leading blanks */ );
-		    *nbvlp = slapi_value_new_string_passin(c);
+			if (!(slapi_value_get_flags(*bvlp) & SLAPI_ATTR_FLAG_NORMALIZED)) {
+				/* 3rd arg: 1 - trim leading blanks */
+				value_normalize_ext( c, syntax, 1, &alt );
+			}
+			if (alt) {
+				slapi_ch_free_string(&c);
+		    	*nbvlp = slapi_value_new_string_passin(alt);
+			} else {
+		    	*nbvlp = slapi_value_new_string_passin(c);
+			}
 		}
 		*ivals = nbvals;
 		break;
@@ -470,14 +509,16 @@ string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,
 		for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) {
 			/*
 			 * Note: this calculation may err on the high side,
-			 * because value_normalize(), which is called below
+			 * because value_normalize_ext(), which is called below
 			 * before we actually create the substring keys, may
-			 * reduce the length of the value in some cases. For
-			 * example, spaces are removed when space insensitive
-			 * strings are normalized. But it's okay for nsubs to
-			 * be too big. Since the ivals array is NULL terminated,
-			 * the only downside is that we allocate more space than
-			 * we really need.
+			 * reduce the length of the value in some cases or 
+			 * increase the length in other cases. For example,
+			 * spaces are removed when space insensitive strings 
+			 * are normalized. Or if the value includes '\"' (2 bytes),
+			 * it's normalized to '\22' (3 bytes). But it's okay 
+			 * for nsubs to be too big. Since the ivals array is 
+			 * NULL terminated, the only downside is that we 
+			 * allocate more space than we really need.
 			 */
 			nsubs += slapi_value_get_length(*bvlp) - substrlens[INDEX_SUBSTRMIDDLE] + 3;
 		}
@@ -489,8 +530,14 @@ string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,
 		bvdup= slapi_value_new(); 
 		for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) {
 			c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
-			value_normalize( c, syntax, 1 /* trim leading blanks */ );
-			slapi_value_set_string_passin(bvdup, c);
+			/* 3rd arg: 1 - trim leading blanks */
+			value_normalize_ext( c, syntax, 1, &alt );
+			if (alt) {
+				slapi_ch_free_string(&c);
+				slapi_value_set_string_passin(bvdup, alt);
+			} else {
+				slapi_value_set_string_passin(bvdup, c);
+			}
 
 			bvp = slapi_value_get_berval(bvdup);
 
@@ -554,6 +601,7 @@ string_assertion2keys_ava(
     size_t len;
 	char		*w, *c;
     Slapi_Value *tmpval=NULL;
+	char *alt = NULL;
 
     switch ( ftype ) {
     case LDAP_FILTER_EQUALITY_FAST: 
@@ -565,13 +613,23 @@ string_assertion2keys_ava(
         }
         memcpy(tmpval->bv.bv_val,slapi_value_get_string(val),len);
         tmpval->bv.bv_val[len]='\0';
-        value_normalize(tmpval->bv.bv_val, syntax, 1 /* trim leading blanks */ );
+		/* 3rd arg: 1 - trim leading blanks */
+        value_normalize_ext(tmpval->bv.bv_val, syntax, 1, &alt );
+		if (alt) {
+            slapi_ch_free_string(&tmpval->bv.bv_val);
+        	tmpval->bv.bv_val = alt;
+		}
         tmpval->bv.bv_len=strlen(tmpval->bv.bv_val);
         break;
 	case LDAP_FILTER_EQUALITY:
 		(*ivals) = (Slapi_Value **) slapi_ch_malloc( 2 * sizeof(Slapi_Value *) );
 		(*ivals)[0] = slapi_value_dup( val );
-		value_normalize( (*ivals)[0]->bv.bv_val, syntax, 1 /* trim leading blanks */ );
+		/* 3rd arg: 1 - trim leading blanks */
+		value_normalize_ext( (*ivals)[0]->bv.bv_val, syntax, 1, &alt );
+		if (alt) {
+            slapi_ch_free_string(&(*ivals)[0]->bv.bv_val);
+			(*ivals)[0]->bv.bv_val = alt;
+		}
 		(*ivals)[0]->bv.bv_len = strlen( (*ivals)[0]->bv.bv_val );
 		(*ivals)[1] = NULL;
 		break;
@@ -628,6 +686,10 @@ string_assertion2keys_sub(
 	int localsublens[3] = {SUBBEGIN, SUBMIDDLE, SUBEND};/* default values */
 	int maxsublen;
 	char	*comp_buf = NULL;
+	char *altinit = NULL;
+	char **altany = NULL;
+	char *altfinal = NULL;
+	int anysize = 0;
 
 	slapi_pblock_get(pb, SLAPI_SYNTAX_SUBSTRLENS, &substrlens);
 
@@ -650,13 +712,17 @@ string_assertion2keys_sub(
 	 * First figure out how many keys we will return. The answer is based
 	 * on the length of each assertion value. Since normalization may
 	 * reduce the length (such as when spaces are removed from space
-	 * insensitive strings), we call value_normalize() before checking
+	 * insensitive strings), we call value_normalize_ext() before checking
 	 * the length.
 	 */
 	nsubs = 0;
 	if ( initial != NULL ) {
-		value_normalize( initial, syntax, 0 /* do not trim leading blanks */ );
-		initiallen = strlen( initial );
+		/* 3rd arg: 0 - DO NOT trim leading blanks */
+		value_normalize_ext( initial, syntax, 0, &altinit );
+		if (NULL == altinit) {
+			altinit = initial;
+		}
+		initiallen = strlen( altinit );
 		if ( initiallen > substrlens[INDEX_SUBSTRBEGIN] - 2 ) {
 			nsubs += 1; /* for the initial begin string key */
 			/* the rest of the sub keys are "any" keys for this case */
@@ -664,19 +730,31 @@ string_assertion2keys_sub(
 				nsubs += initiallen - substrlens[INDEX_SUBSTRMIDDLE] + 1;
 			}
 		} else {
-			initial = NULL;	/* save some work later */
+			altinit = NULL;	/* save some work later */
 		}
 	}
 	for ( i = 0; any != NULL && any[i] != NULL; i++ ) {
-		value_normalize( any[i], syntax, 0 /* do not trim leading blanks */ );
-		len = strlen( any[i] );
+		anysize++;
+	}
+	altany = (char **)slapi_ch_calloc(anysize + 1, sizeof(char *));
+	for ( i = 0; any != NULL && any[i] != NULL; i++ ) {
+		/* 3rd arg: 0 - DO NOT trim leading blanks */
+		value_normalize_ext( any[i], syntax, 0, &altany[i] );
+		if (NULL == altany[i]) {
+			altany[i] = any[i];
+		}
+		len = strlen( altany[i] );
 		if ( len >= substrlens[INDEX_SUBSTRMIDDLE] ) {
 			nsubs += len - substrlens[INDEX_SUBSTRMIDDLE] + 1;
 		}
 	}
 	if ( final != NULL ) {
-		value_normalize( final, syntax, 0 /* do not trim leading blanks */ );
-		finallen = strlen( final );
+		/* 3rd arg: 0 - DO NOT trim leading blanks */
+		value_normalize_ext( final, syntax, 0, &altfinal );
+		if (NULL == altfinal) {
+			altfinal = final;
+		}
+		finallen = strlen( altfinal );
 		if ( finallen > substrlens[INDEX_SUBSTREND] - 2 ) {
 			nsubs += 1; /* for the final end string key */
 			/* the rest of the sub keys are "any" keys for this case */
@@ -684,7 +762,7 @@ string_assertion2keys_sub(
 				nsubs += finallen - substrlens[INDEX_SUBSTRMIDDLE] + 1;
 			}
 		} else {
-			final = NULL; /* save some work later */
+			altfinal = NULL; /* save some work later */
 		}
 	}
 	if ( nsubs == 0 ) {	/* no keys to return */
@@ -703,21 +781,31 @@ string_assertion2keys_sub(
 
 	nsubs = 0;
 	comp_buf = (char *)slapi_ch_malloc(maxsublen + 1);
-	if ( initial != NULL ) {
-		substring_comp_keys( ivals, &nsubs, initial, initiallen, '^', syntax,
+	if ( altinit != NULL ) {
+		substring_comp_keys( ivals, &nsubs, altinit, initiallen, '^', syntax,
 							 comp_buf, substrlens );
+		if (altinit != initial) {
+			slapi_ch_free_string(&altinit);
+		}
 	}
-	for ( i = 0; any != NULL && any[i] != NULL; i++ ) {
-		len = strlen( any[i] );
+	for ( i = 0; altany != NULL && altany[i] != NULL; i++ ) {
+		len = strlen( altany[i] );
 		if ( len < substrlens[INDEX_SUBSTRMIDDLE] ) {
 			continue;
 		}
-		substring_comp_keys( ivals, &nsubs, any[i], len, 0, syntax,
+		substring_comp_keys( ivals, &nsubs, altany[i], len, 0, syntax,
 							 comp_buf, substrlens );
+		if (altany[i] != any[i]) {
+			slapi_ch_free_string(&altany[i]);
+		}
 	}
-	if ( final != NULL ) {
-		substring_comp_keys( ivals, &nsubs, final, finallen, '$', syntax,
+	slapi_ch_free((void **)&altany);
+	if ( altfinal != NULL ) {
+		substring_comp_keys( ivals, &nsubs, altfinal, finallen, '$', syntax,
 							 comp_buf, substrlens );
+		if (altfinal != final) {
+			slapi_ch_free_string(&final);
+		}
 	}
 	(*ivals)[nsubs] = NULL;
 	slapi_ch_free_string(&comp_buf);

+ 1 - 0
ldap/servers/plugins/syntaxes/syntax.h

@@ -113,6 +113,7 @@ int string_assertion2keys_ava(Slapi_PBlock *pb,Slapi_Value *val,Slapi_Value ***i
 int string_assertion2keys_sub(Slapi_PBlock *pb,char *initial,char **any,char *final,Slapi_Value ***ivals,int syntax);
 int value_cmp(struct berval	*v1,struct berval *v2,int syntax,int normalize);
 void value_normalize(char *s,int syntax,int trim_leading_blanks);
+void value_normalize_ext(char *s,int syntax,int trim_leading_blanks, char **alt);
 
 char *first_word( char *s );
 char *next_word( char *s );

+ 0 - 12
ldap/servers/plugins/syntaxes/validate.c

@@ -362,7 +362,6 @@ int distinguishedname_validate(
 {
 	int rc = 0; /* Assume value is valid */
 	char *val_copy = NULL;
-	int strict = 0;
 	const char *p = begin;
 	const char *last = NULL;
 
@@ -377,17 +376,6 @@ int distinguishedname_validate(
 	 * attributeValue = string / hexstring
 	 */
 
-	/* Check if we should be performing strict validation. */
-	strict = config_get_dn_validate_strict();
-	if (!strict) {
-		/* Create a normalized copy of the value to use
-		 * for validation.  The original value will be
-		 * stored in the backend unmodified. */
-		val_copy = PL_strndup(begin, end - begin + 1);
-		p = val_copy;
-		end = slapi_dn_normalize_to_end(val_copy, NULL) - 1;
-	}
-
 	/* Validate one RDN at a time in a loop. */
 	while (p <= end) {
 		if ((rc = rdn_validate(p, end, &last)) != 0) {

+ 81 - 9
ldap/servers/plugins/syntaxes/value.c

@@ -86,23 +86,40 @@ utf8isspace_fast( char* s )
 ** Also note that this deviates from rfc 4517 INTEGER syntax, but we must
 ** support legacy clients for the time being
 */
+/*
+ * alt stores the normalized value in case the normalized value is longer
+ * than the original value.  It may happen the value is DN.
+ */
 void
-value_normalize(
+value_normalize_ext(
     char    *s,
     int     syntax,
-    int     trim_spaces
+    int     trim_spaces,
+    char    **alt
 )
 {
 	char *head = s;
 	char *d;
 	int  prevspace, curspace;
 
+	if (NULL == alt) {
+		return;
+	}
+	*alt = NULL;
+
 	if ( ! (syntax & SYNTAX_CIS) && ! (syntax & SYNTAX_CES) ) {
 		return;
 	}
 
 	if ( syntax & SYNTAX_DN ) {
-		(void) slapi_dn_normalize_case( s );
+		char *dest = NULL;
+		size_t dlen = 0;
+		int rc = slapi_dn_normalize_case_ext(s, 0, &dest, &dlen);
+		if (rc > 0) {
+			*alt = dest;
+		} else if (rc == 0) { /* normalized in line; not terminated */
+			*(dest + dlen) = '\0';
+		}
 		return;
 	}
 
@@ -203,6 +220,16 @@ value_normalize(
 	}
 }
 
+void
+value_normalize(
+    char    *s,
+    int     syntax,
+    int     trim_spaces
+)
+{
+	/* deprecated */
+}
+
 int
 value_cmp(
     struct berval	*v1,
@@ -220,6 +247,7 @@ value_cmp(
 	int free_v1 = 0;
 	int free_v2 = 0;
 	int v1sign = 1, v2sign = 1; /* default to positive */
+	char *alt = NULL;
 
 	/* This code used to call malloc up to four times in the copying
 	 * of attributes to be normalized. Now we attempt to keep everything
@@ -233,13 +261,35 @@ value_cmp(
 			bvcopy1.bv_val = &little_buffer[buffer_offset];
 			bvcopy1.bv_val[v1->bv_len] = '\0';
 			v1 = &bvcopy1;
-			buffer_space-= v1->bv_len+1;
-			buffer_offset+= v1->bv_len+1;
 		} else {
 			v1 = ber_bvdup( v1 );
 			free_v1 = 1;
 		}
-		value_normalize( v1->bv_val, syntax, 1 /* trim leading blanks */ );
+		value_normalize_ext( v1->bv_val, syntax, 
+							 1 /* trim leading blanks */, &alt );
+		if (alt) {
+			if (free_v1) {
+				slapi_ch_free_string(&v1->bv_val);
+				v1->bv_val = alt;
+				v1->bv_len = strlen(alt);
+			} else {
+				if (strlen(alt) < buffer_space) {
+					v1->bv_len = strlen(alt);
+					/* Copying to little_buffer */
+					SAFEMEMCPY(v1->bv_val, alt, v1->bv_len);
+					*(v1->bv_val + v1->bv_len) = '\0';
+				} else {
+					free_v1 = 1;
+					v1 = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+					v1->bv_val = alt;
+					v1->bv_len = strlen(alt);
+				}
+			}
+		}
+		if (!free_v1) {
+			buffer_space -= v1->bv_len + 1;
+			buffer_offset += v1->bv_len + 1;
+		}
 	}
 	if ( normalize & 2 ) {
 		/* Do we have space in the little buffer ? */
@@ -249,13 +299,35 @@ value_cmp(
 			bvcopy2.bv_val = &little_buffer[buffer_offset];
 			bvcopy2.bv_val[v2->bv_len] = '\0';
 			v2 = &bvcopy2;
-			buffer_space-= v2->bv_len+1;
-			buffer_offset+= v2->bv_len+1;
 		} else {
 			v2 = ber_bvdup( v2 );
 			free_v2 = 1;
 		}
-		value_normalize( v2->bv_val, syntax, 1 /* trim leading blanks */ );
+		value_normalize_ext( v2->bv_val, syntax, 
+							 1 /* trim leading blanks */, &alt );
+		if (alt) {
+			if (free_v2) {
+				slapi_ch_free_string(&v2->bv_val);
+				v2->bv_val = alt;
+				v2->bv_len = strlen(alt);
+			} else {
+				if (strlen(alt) < buffer_space) {
+					v2->bv_len = strlen(alt);
+					/* Copying to little_buffer */
+					SAFEMEMCPY(v2->bv_val, alt, v2->bv_len);
+					*(v2->bv_val + v2->bv_len) = '\0';
+				} else {
+					free_v2 = 1;
+					v2 = (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+					v2->bv_val = alt;
+					v2->bv_len = strlen(alt);
+				}
+			}
+		}
+		if (!free_v2) {
+			buffer_space -= v2->bv_len + 1;
+			buffer_offset += v2->bv_len + 1;
+		}
 	}
 
 	if (syntax & SYNTAX_INT) {

+ 9 - 2
ldap/servers/plugins/usn/usn_cleanup.c

@@ -194,8 +194,15 @@ _usn_cleanup_is_mmr_enabled(const char *suffix)
     char *base_dn = NULL;
     int rc = 0; /* disabled, by default */
 
-    base_dn = slapi_ch_smprintf("cn=replica,cn=\"%s\",%s",
-                                suffix, MAPPING_TREE_BASE_DN);
+    /* This function converts the old style DN to the new one */
+    base_dn = slapi_create_dn_string("cn=replica,cn=\"%s\",%s",
+                                     suffix, MAPPING_TREE_BASE_DN);
+    if (NULL == base_dn) {
+        slapi_log_error(SLAPI_LOG_FATAL, USN_PLUGIN_SUBSYSTEM,
+                        "_usn_cleanup_is_mmr_enabled: failed to normalize "
+                        "mappingtree dn for %s\n", suffix);
+        return 1;
+    }
     search_pb = slapi_pblock_new();
     slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_ONELEVEL,
                                  "objectclass=nsDS5ReplicationAgreement",

+ 40 - 13
ldap/servers/slapd/add.c

@@ -115,20 +115,47 @@ do_add( Slapi_PBlock *pb )
 	 */
 	/* get the name */
 	{
-    	char *dn = NULL;
-    	if ( ber_scanf( ber, "{a", &dn ) == LBER_ERROR ) {
-            slapi_ch_free_string(&dn);
-    		LDAPDebug( LDAP_DEBUG_ANY,
-    		    "ber_scanf failed (op=Add; params=DN)\n", 0, 0, 0 );
+		char *rawdn = NULL;
+		char *dn = NULL;
+		size_t dnlen = 0;
+		if ( ber_scanf( ber, "{a", &rawdn ) == LBER_ERROR ) {
+			slapi_ch_free_string(&rawdn);
+			LDAPDebug( LDAP_DEBUG_ANY,
+				"ber_scanf failed (op=Add; params=DN)\n", 0, 0, 0 );
 			op_shared_log_error_access (pb, "ADD", "???", "decoding error");
-    		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
-    		    "decoding error", 0, NULL );
-    		return;
-    	}
-    	e = slapi_entry_alloc();
-        slapi_entry_init(e,dn,NULL); /* Responsibility for DN is passed to the Entry. */
-    }
-	LDAPDebug( LDAP_DEBUG_ARGS, "    do_add: dn (%s)\n", slapi_entry_get_dn_const(e), 0, 0 );
+			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
+				"decoding error", 0, NULL );
+			return;
+		}
+		/* Check if we should be performing strict validation. */
+		if (config_get_dn_validate_strict()) {
+			/* check that the dn is formatted correctly */
+			rc = slapi_dn_syntax_check(pb, rawdn, 1);
+			if (rc) { /* syntax check failed */
+				op_shared_log_error_access(pb, "ADD", rawdn?rawdn:"",
+										   "strict: invalid dn");
+				send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+								 NULL, "invalid dn", 0, NULL);
+				slapi_ch_free_string(&rawdn);
+				return;
+			}
+		}
+		rc = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen);
+		if (rc < 0) {
+			op_shared_log_error_access(pb, "ADD", rawdn?rawdn:"", "invalid dn");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid dn", 0, NULL);
+			slapi_ch_free_string(&rawdn);
+			return;
+		} else if (rc > 0) {
+			slapi_ch_free_string(&rawdn);
+		} else { /* rc == 0; rawdn is passed in; not null terminated */
+			*(dn + dnlen) = '\0';
+		}
+		e = slapi_entry_alloc();
+		slapi_entry_init(e,dn,NULL); /* Responsibility for DN is passed to the Entry. */
+	}
+	LDAPDebug( LDAP_DEBUG_ARGS, "	do_add: dn (%s)\n", slapi_entry_get_dn_const(e), 0, 0 );
 
 	/* get the attrs */
 	for ( tag = ber_first_element( ber, &len, &last );

+ 6 - 0
ldap/servers/slapd/attrlist.c

@@ -289,6 +289,9 @@ int attrlist_replace(Slapi_Attr **alist, const char *type, struct berval **vals)
     } else {
         attrlist_find_or_create(alist, type, &a);
         valuearray_init_bervalarray(vals, &values);
+        if (slapi_attr_is_dn_syntax_attr(*a)) {
+            valuearray_normalize_value(values);
+        }
         rc = attr_replace(*a, values);
     }
     return rc;
@@ -312,6 +315,9 @@ int attrlist_replace_with_flags(Slapi_Attr **alist, const char *type, struct ber
     } else {
         attrlist_find_or_create(alist, type, &a);
         valuearray_init_bervalarray_with_flags(vals, &values, flags);
+        if (slapi_attr_is_dn_syntax_attr(*a)) {
+            valuearray_normalize_value(values);
+        }
         rc = attr_replace(*a, values);
     }
     return rc;

+ 17 - 0
ldap/servers/slapd/attrsyntax.c

@@ -819,6 +819,23 @@ slapi_attr_get_syntax_oid_copy( const Slapi_Attr *a, char **oidp )
 	}
 }
 
+int
+slapi_attr_is_dn_syntax_attr(Slapi_Attr *attr)
+{
+	char *syntaxoid = NULL;
+	int dn_syntax = 0; /* not DN, by default */
+
+	if (attr->a_plugin) { /* If not set, there is no way to get the info */
+		slapi_attr_get_syntax_oid_copy(attr, &syntaxoid);
+		if (syntaxoid) {
+			dn_syntax = ((0 == strcmp(syntaxoid, NAMEANDOPTIONALUID_SYNTAX_OID))
+						 || (0 == strcmp(syntaxoid, DN_SYNTAX_OID)));
+			slapi_ch_free_string(&syntaxoid);
+		}
+	}
+	return dn_syntax;
+}
+
 #ifdef ATTR_LDAP_DEBUG
 
 PRIntn

+ 42 - 8
ldap/servers/slapd/auth.c

@@ -75,15 +75,33 @@ slapu_msgfree( LDAP* ld, LDAPMessage* msg )
 }
 
 static int LDAP_CALL LDAP_CALLBACK
-slapu_search_s( LDAP* ld, const char* baseDN, int scope, const char* filter, 
+slapu_search_s( LDAP* ld, const char* rawbaseDN, int scope, const char* filter, 
 	char** attrs, int attrsonly, LDAPMessage** result )
 {
     int err = LDAP_NO_SUCH_OBJECT;
-    Slapi_PBlock* pb;
+    Slapi_PBlock* pb = NULL;
     LDAPControl **ctrls;
+    char *baseDN = slapi_ch_strdup(rawbaseDN);
+    char *normDN = NULL;
+    size_t dnlen = 0;
+
+    err = slapi_dn_normalize_ext(baseDN, 0, &normDN, &dnlen);
+    if (err < 0) {
+        err = LDAP_INVALID_DN_SYNTAX;
+        LDAPDebug (LDAP_DEBUG_TRACE, "<= slapu_search_s %i\n", err, 0, 0);
+        return err;
+    } else if (err == 0) { /* baseDN is passed in; not terminated */
+        *(normDN + dnlen) = '\0';
+    } else {
+        slapi_ch_free_string(&baseDN);
+        baseDN = normDN;
+    }
 
     if (ld != internal_ld) {
-	return ldap_search_ext_s (ld, baseDN, scope, filter, attrs, attrsonly, NULL, NULL, NULL, -1, result);
+        err = ldap_search_ext_s(ld, baseDN, scope, filter, attrs, attrsonly,
+                                NULL, NULL, NULL, -1, result);
+        slapi_ch_free_string(&baseDN);
+        return err;
     }
     LDAPDebug (LDAP_DEBUG_TRACE, "=> slapu_search_s (\"%s\", %i, %s)\n",
 	       baseDN, scope, filter);
@@ -120,6 +138,7 @@ slapu_search_s( LDAP* ld, const char* baseDN, int scope, const char* filter,
 	LDAPDebug (LDAP_DEBUG_ANY, "slapi_search_internal (\"%s\", %i, %s) NULL\n",
 		   escape_string( (char*)baseDN, ebuf ), scope, escape_string( (char*)filter, fbuf ));
     }
+    slapi_ch_free_string(&baseDN);
     *result = (LDAPMessage*)pb;
     LDAPDebug (LDAP_DEBUG_TRACE, "<= slapu_search_s %i\n", err, 0, 0);
     return err;
@@ -486,8 +505,8 @@ handle_handshake_done (PRFileDesc *prfd, void* clientData)
 	    if (err == LDAPU_SUCCESS && chain) {
 		LDAPMessage* entry = slapu_first_entry (internal_ld, chain);
 		if (entry) {
+		    /* clientDN is duplicated in slapu_get_dn */
 		    clientDN = slapu_get_dn (internal_ld, entry);
-		    if (clientDN) slapi_dn_normalize (clientDN);
 		} else {
 		  
 		    extraErrorMsg = "no entry";
@@ -507,12 +526,27 @@ handle_handshake_done (PRFileDesc *prfd, void* clientData)
 
     if (clientDN != NULL) {
         char ebuf[ BUFSIZ ];
-        slapi_log_access (LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " SSL client bound as %s\n",
-    	       conn->c_connid, escape_string( clientDN, ebuf ));
+        int rc = 0;
+        char *normedDN = NULL;
+        size_t dnlen = 0;
+
+        rc = slapi_dn_normalize_ext(clientDN, 0, &normedDN, &dnlen);
+        if (rc < 0) {
+            /* ignoring the normalization error, use the pre normalized DN */
+        } else if (rc == 0) { /* clientDN is passed in; not terminated */
+            *(normedDN + dnlen) = '\0';
+        } else {
+            slapi_ch_free_string(&clientDN);
+            clientDN = normedDN;
+        }
+        slapi_log_access (LDAP_DEBUG_STATS, 
+                          "conn=%" NSPRIu64 " SSL client bound as %s\n",
+                          conn->c_connid, escape_string( clientDN, ebuf ));
     } else if (clientCert != NULL) {
         slapi_log_access (LDAP_DEBUG_STATS,
-		"conn=%" NSPRIu64 " SSL failed to map client certificate to LDAP DN (%s)\n",
-    	       conn->c_connid, extraErrorMsg );
+                          "conn=%" NSPRIu64 " SSL failed to map client "
+                          "certificate to LDAP DN (%s)\n",
+                          conn->c_connid, extraErrorMsg );
     }
 
 	/*

+ 1 - 0
ldap/servers/slapd/back-ldbm/import-threads.c

@@ -533,6 +533,7 @@ import_producer(void *param)
                 FREE(estr);
                 continue;
             }
+            /* get_value_from_string decodes base64 if it is encoded. */
             rc = get_value_from_string((const char *)estr, "dn", &dn);
             if (rc) {
                 import_log_notice(job, "WARNING: skipping bad LDIF entry (dn "

+ 16 - 3
ldap/servers/slapd/back-ldbm/ldbm_attrcrypt.c

@@ -142,13 +142,25 @@ attrcrypt_keymgmt_get_key(ldbm_instance *li, attrcrypt_cipher_state *acs, SECKEY
 {
 	int ret = 0;
 	Slapi_Entry *entry = NULL;
-	char *dn_template = "cn=%s,cn=encrypted attribute keys,cn=%s,cn=ldbm database,cn=plugins,cn=config";
+	char *dn_template = "cn=%s,cn=encrypted attribute keys,cn=%s,cn=%s,cn=plugins,cn=config";
 	char *instance_name =  li->inst_name;
-	char *dn_string = NULL;
 	Slapi_Attr *keyattr = NULL;
+	char *dn_string = NULL;
 	
 	LDAPDebug(LDAP_DEBUG_TRACE,"-> attrcrypt_keymgmt_get_key\n", 0, 0, 0);
-	dn_string = slapi_ch_smprintf(dn_template, acs->ace->cipher_display_name, instance_name);
+	dn_string = slapi_create_dn_string(dn_template,
+								acs->ace->cipher_display_name, instance_name,
+								li->inst_li->li_plugin->plg_name);
+	if (NULL == dn_string) {
+		LDAPDebug(LDAP_DEBUG_ANY,
+				  "attrcrypt_keymgmt_get_key: "
+				  "failed create attrcrypt key dn for plugin %s, "
+				  "instance %s, cypher %s\n", 
+				  li->inst_li->li_plugin->plg_name,
+				  li->inst_name, acs->ace->cipher_display_name);
+		ret = -1;
+		goto bail;
+	}
 	/* Fetch the entry */
 	getConfigEntry(dn_string, &entry);
 	/* Did we find the entry ? */
@@ -170,6 +182,7 @@ attrcrypt_keymgmt_get_key(ldbm_instance *li, attrcrypt_cipher_state *acs, SECKEY
 	} else {
 		ret = -2; /* Means: we didn't find the entry (which happens if the key has never been generated) */	
 	}
+bail:
 	slapi_ch_free_string(&dn_string);
 	LDAPDebug(LDAP_DEBUG_TRACE,"<- attrcrypt_keymgmt_get_key\n", 0, 0, 0);
 	return ret;

+ 67 - 23
ldap/servers/slapd/back-ldbm/ldbm_config.c

@@ -1047,7 +1047,7 @@ static int ldbm_config_entryrdn_switch_set(void *arg, void *value,
     if (apply) {
         entryrdn_set_switch((int)((uintptr_t)value));
     }
-	return LDAP_SUCCESS;
+    return LDAP_SUCCESS;
 }
 
 static void *ldbm_config_entryrdn_noancestorid_get(void *arg)
@@ -1061,7 +1061,7 @@ static int ldbm_config_entryrdn_noancestorid_set(void *arg, void *value,
     if (apply) {
         entryrdn_set_noancestorid((int)((uintptr_t)value));
     }
-	return LDAP_SUCCESS;
+    return LDAP_SUCCESS;
 }
 
 static void *ldbm_config_legacy_errcode_get(void *arg)
@@ -1296,11 +1296,17 @@ void
 ldbm_config_read_instance_entries(struct ldbminfo *li, const char *backend_type)
 {
     Slapi_PBlock *tmp_pb;
-    char basedn[BUFSIZ];
     Slapi_Entry **entries = NULL;
+    char *basedn = NULL;
 
     /* Construct the base dn of the subtree that holds the instance entries. */
-    PR_snprintf(basedn, BUFSIZ, "cn=%s, cn=plugins, cn=config", backend_type);
+    basedn = slapi_create_dn_string("cn=%s,cn=plugins,cn=config", backend_type);
+    if (NULL == basedn) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "ldbm_config_read_instance_entries: "
+                      "failed create backend dn for %s\n", backend_type);
+        return;
+    }
 
     /* Do a search of the subtree containing the instance entries */
     tmp_pb = slapi_pblock_new();
@@ -1327,29 +1333,38 @@ int ldbm_config_load_dse_info(struct ldbminfo *li)
 {
     Slapi_PBlock *search_pb;
     Slapi_Entry **entries = NULL;
-    int res;
-    char dn[BUFSIZ];
+    char *dn = NULL;
+    int rval = 0;
 
     /* We try to read the entry 
      * cn=config, cn=ldbm database, cn=plugins, cn=config.  If the entry is
      * there, then we process the config information it stores.
      */
-    PR_snprintf(dn, BUFSIZ, "cn=config, cn=%s, cn=plugins, cn=config", 
-                li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=config,cn=%s,cn=plugins,cn=config", 
+                                li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "ldbm_config_load_dse_info: "
+                      "failed create config dn for %s\n",
+                      li->li_plugin->plg_name); 
+        rval = 1;
+        goto bail;
+    }
     search_pb = slapi_pblock_new();
     slapi_search_internal_set_pb(search_pb, dn, LDAP_SCOPE_BASE, 
         "objectclass=*", NULL, 0, NULL, NULL, li->li_identity, 0);
     slapi_search_internal_pb (search_pb);
-    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
+    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rval);
 
-    if (LDAP_NO_SUCH_OBJECT == res) {
+    if (LDAP_NO_SUCH_OBJECT == rval) {
         /* Add skeleten dse entries for the ldbm plugin */
         ldbm_config_add_dse_entries(li, ldbm_skeleton_entries,
                                     li->li_plugin->plg_name, NULL, NULL, 0);
-    } else if (res != LDAP_SUCCESS) {
+    } else if (rval != LDAP_SUCCESS) {
         LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the ldbm config DSE\n",
                   0, 0, 0);
-        return 1;
+        rval = 1;
+        goto bail;
     } else {
         /* Need to parse the configuration information for the ldbm
          * plugin that is held in the DSE. */
@@ -1358,12 +1373,14 @@ int ldbm_config_load_dse_info(struct ldbminfo *li)
         if (NULL == entries || entries[0] == NULL) {
             LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the ldbm config DSE\n",
                       0, 0, 0);
-            return 1;
+            rval = 1;
+            goto bail;
         }
         if (0 != parse_ldbm_config_entry(li, entries[0], ldbm_config)) {
             LDAPDebug(LDAP_DEBUG_ANY, "Error parsing the ldbm config DSE\n",
                       0, 0, 0);
-            return 1;
+            rval = 1;
+            goto bail;
         }
     }
 
@@ -1377,8 +1394,6 @@ int ldbm_config_load_dse_info(struct ldbminfo *li)
     ldbm_config_read_instance_entries(li, li->li_plugin->plg_name);
 
     /* setup the dse callback functions for the ldbm backend config entry */
-    PR_snprintf(dn, BUFSIZ, "cn=config, cn=%s, cn=plugins, cn=config",
-            li->li_plugin->plg_name);
     slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_config_search_entry_callback,
         (void *) li);
@@ -1388,24 +1403,52 @@ int ldbm_config_load_dse_info(struct ldbminfo *li)
     slapi_config_register_callback(DSE_OPERATION_WRITE, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_config_search_entry_callback,
         (void *) li);
+    slapi_ch_free_string(&dn);
 
     /* setup the dse callback functions for the ldbm backend monitor entry */
-    PR_snprintf(dn, BUFSIZ, "cn=monitor, cn=%s, cn=plugins, cn=config",
-            li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=monitor,cn=%s,cn=plugins,cn=config",
+                                li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "ldbm_config_load_dse_info: "
+                      "failed create monitor dn for %s\n",
+                      li->li_plugin->plg_name); 
+        rval = 1;
+        goto bail;
+    }
     slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_search,
         (void *)li);
+    slapi_ch_free_string(&dn);
 
     /* And the ldbm backend database monitor entry */
-    PR_snprintf(dn, BUFSIZ, "cn=database, cn=monitor, cn=%s, cn=plugins, cn=config",
-        li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=database,cn=monitor,cn=%s,cn=plugins,cn=config",
+                                li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "ldbm_config_load_dse_info: "
+                      "failed create monitor database dn for %s\n",
+                      li->li_plugin->plg_name); 
+        rval = 1;
+        goto bail;
+    }
     slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_dbmonitor_search,
         (void *)li);
+    slapi_ch_free_string(&dn);
 
     /* setup the dse callback functions for the ldbm backend instance
      * entries */
-    PR_snprintf(dn, BUFSIZ, "cn=%s, cn=plugins, cn=config", li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=%s,cn=plugins,cn=config", 
+                                li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "ldbm_config_load_dse_info: "
+                      "failed create plugin dn for %s\n",
+                      li->li_plugin->plg_name); 
+        rval = 1;
+        goto bail;
+    }
     slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, "(objectclass=nsBackendInstance)",
         ldbm_instance_add_instance_entry_callback, (void *) li);
@@ -1418,8 +1461,9 @@ int ldbm_config_load_dse_info(struct ldbminfo *li)
     slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, dn,
         LDAP_SCOPE_SUBTREE, "(objectclass=nsBackendInstance)",
         ldbm_instance_post_delete_instance_entry_callback, (void *) li);
-
-    return 0;
+bail:
+    slapi_ch_free_string(&dn);
+    return rval;
 }
 
 

+ 35 - 15
ldap/servers/slapd/back-ldbm/ldbm_index_config.c

@@ -622,6 +622,7 @@ int ldbm_instance_config_add_index_entry(
     char tmpIndexesStr[256];
     char tmpMatchingRulesStr[1024];
     struct ldbminfo *li = inst->inst_li;
+    char *dn = NULL;
 
     if ((argc < 2) || (NULL == argv) || (NULL == argv[0]) || 
         (NULL == argv[1])) {
@@ -642,31 +643,42 @@ int ldbm_instance_config_add_index_entry(
     {
         if('\0' == attrs[i][0]) continue;
         basetype = slapi_attr_basetype(attrs[i], NULL, 0);
+        dn = slapi_create_dn_string("cn=%s,cn=index,cn=%s,cn=%s,cn=plugins,cn=config", 
+                            basetype, inst->inst_name, li->li_plugin->plg_name);
+        if (NULL == dn) {
+            LDAPDebug(LDAP_DEBUG_ANY,
+                      "ldbm_instance_config_add_index_entry: "
+                      "failed create index dn with type %s for plugin %s, "
+                      "instance %s\n",
+                      basetype, inst->inst_li->li_plugin->plg_name,
+                      inst->inst_name);
+            return -1;
+        }
         eBuf = PR_smprintf(
-                "dn: cn=%s, cn=index, cn=%s, cn=%s, cn=plugins, cn=config\n"
-                "objectclass:top\n"
-                "objectclass:nsIndex\n"
-                "cn:%s\n"
-                "nsSystemIndex:%s\n",
-                basetype, inst->inst_name, li->li_plugin->plg_name,
-                basetype,
+                "dn: %s\n"
+                "objectclass: top\n"
+                "objectclass: nsIndex\n"
+                "cn: %s\n"
+                "nsSystemIndex: %s\n",
+                dn, basetype,
                 (ldbm_attribute_always_indexed(basetype)?"true":"false"));
+        slapi_ch_free_string(&dn);
         for(j=0; indexes[j] != NULL; j++)
         {
-			eBuf = PR_sprintf_append(eBuf, "nsIndexType:%s\n", indexes[j]);
+            eBuf = PR_sprintf_append(eBuf, "nsIndexType:%s\n", indexes[j]);
         }
         if((argc>2)&&(argv[2]))
         {
             for(j=0; matchingRules[j] != NULL; j++)
             { 
-				eBuf = PR_sprintf_append(eBuf, "nsMatchingRule:%s\n", matchingRules[j]);
+                eBuf = PR_sprintf_append(eBuf, "nsMatchingRule:%s\n", matchingRules[j]);
             }
         }
 
         ldbm_config_add_dse_entry(li, eBuf, flags);
-		if (eBuf) {
-			PR_smprintf_free(eBuf);
-		}
+        if (eBuf) {
+            PR_smprintf_free(eBuf);
+        }
 
         slapi_ch_free((void**)&basetype);
     }
@@ -722,10 +734,10 @@ int ldbm_instance_create_default_user_indexes(ldbm_instance *inst)
     Slapi_Value *sval = NULL;
     const struct berval *attrValue;
     char *argv[ 8 ];
-    char basedn[BUFSIZ];
     char tmpBuf[MAX_TMPBUF];
     char tmpBuf2[MAX_TMPBUF];
     int argc;
+    char *basedn = NULL;
 
     struct ldbminfo *li;
 
@@ -742,8 +754,15 @@ int ldbm_instance_create_default_user_indexes(ldbm_instance *inst)
     strcpy(tmpBuf,"");
 
     /* Construct the base dn of the subtree that holds the default user indexes. */
-    PR_snprintf(basedn, BUFSIZ, "cn=default indexes, cn=config, cn=%s, cn=plugins, cn=config", 
-	li->li_plugin->plg_name);
+	basedn = slapi_create_dn_string("cn=default indexes,cn=config,cn=%s,cn=plugins,cn=config", 
+										li->li_plugin->plg_name);
+	if (NULL == basedn) {
+		LDAPDebug1Arg(LDAP_DEBUG_ANY,
+				      "ldbm_instance_create_default_user_indexes: "
+				      "failed create default index dn for plugin %s\n",
+				      inst->inst_li->li_plugin->plg_name);
+        return -1;
+	}
 
     /* Do a search of the subtree containing the index entries */
     aPb = slapi_pblock_new();
@@ -821,5 +840,6 @@ int ldbm_instance_create_default_user_indexes(ldbm_instance *inst)
 
     slapi_free_search_results_internal(aPb);
     slapi_pblock_destroy(aPb);
+    slapi_ch_free_string(&basedn);
     return 0;
 }

+ 132 - 35
ldap/servers/slapd/back-ldbm/ldbm_instance_config.c

@@ -336,13 +336,20 @@ read_instance_index_entries(ldbm_instance *inst)
 {
     Slapi_PBlock *tmp_pb;
     int scope = LDAP_SCOPE_SUBTREE;
-    char basedn[BUFSIZ];
     const char *searchfilter = "(objectclass=nsIndex)";
+    char *basedn = NULL;
 
     /* Construct the base dn of the subtree that holds the index entries 
      * for this instance. */
-    PR_snprintf(basedn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, inst->inst_li->li_plugin->plg_name); 
+    basedn = slapi_create_dn_string("cn=index,cn=%s,cn=%s,cn=plugins,cn=config",
+                          inst->inst_name, inst->inst_li->li_plugin->plg_name); 
+    if (NULL == basedn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "read_instance_index_entries: "
+                       "failed create index dn for plugin %s, instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name); 
+        return 1;
+    }
 
     /* Set up a tmp callback that will handle the init for each index entry */
     slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
@@ -361,6 +368,7 @@ read_instance_index_entries(ldbm_instance *inst)
     slapi_free_search_results_internal(tmp_pb);
     slapi_pblock_destroy(tmp_pb);
 
+    slapi_ch_free_string(&basedn);
     return 0;
 }
 
@@ -372,13 +380,21 @@ read_instance_attrcrypt_entries(ldbm_instance *inst)
 {
     Slapi_PBlock *tmp_pb;
     int scope = LDAP_SCOPE_SUBTREE;
-    char basedn[BUFSIZ];
     const char *searchfilter = ldbm_instance_attrcrypt_filter;
+    char *basedn = NULL;
 
     /* Construct the base dn of the subtree that holds the index entries 
      * for this instance. */
-    PR_snprintf(basedn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, inst->inst_li->li_plugin->plg_name); 
+    basedn = slapi_create_dn_string("cn=encrypted attributes,cn=%s,cn=%s,cn=plugins,cn=config",
+                          inst->inst_name, inst->inst_li->li_plugin->plg_name); 
+    if (NULL == basedn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "read_instance_attrcrypt_entries: "
+                       "failed create encrypted attributes dn for plugin %s, "
+                       "instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        return 1;
+    }
 
     /* Set up a tmp callback that will handle the init for each index entry */
     slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
@@ -397,6 +413,7 @@ read_instance_attrcrypt_entries(ldbm_instance *inst)
     slapi_free_search_results_internal(tmp_pb);
     slapi_pblock_destroy(tmp_pb);
 
+    slapi_ch_free_string(&basedn);
     return 0;
 }
 
@@ -427,10 +444,11 @@ parse_ldbm_instance_config_entry(ldbm_instance *inst, Slapi_Entry *e, config_inf
             Slapi_DN suffix;
 
             slapi_attr_first_value(attr, &sval);
+            
             bval = (struct berval *) slapi_value_get_berval(sval);
             slapi_sdn_init_dn_byref(&suffix, bval->bv_val);
             if (!slapi_be_issuffix(inst->inst_be, &suffix)) {
-            be_addsuffix(inst->inst_be, &suffix);
+                be_addsuffix(inst->inst_be, &suffix);
             }
             slapi_sdn_done(&suffix);
             continue;
@@ -477,25 +495,34 @@ ldbm_instance_config_load_dse_info(ldbm_instance *inst)
     struct ldbminfo *li = inst->inst_li;
     Slapi_PBlock *search_pb;
     Slapi_Entry **entries = NULL;
-    int res;
-    char dn[BUFSIZ];
+    char *dn = NULL;
+    int rval = 0;
 
     /* We try to read the entry 
      * cn=instance_name, cn=ldbm database, cn=plugins, cn=config.  If the
      * entry is there, then we process the config information it stores.
      */
-    PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_config_load_dse_info: "
+                       "failed create instance dn %s for plugin %s\n",
+                       inst->inst_name, inst->inst_li->li_plugin->plg_name);
+        rval = 1;
+        goto bail;
+    }
     search_pb = slapi_pblock_new();
     slapi_search_internal_set_pb(search_pb, dn, LDAP_SCOPE_BASE, 
                                  "objectclass=*", NULL, 0, NULL, NULL,
                                  li->li_identity, 0);
     slapi_search_internal_pb (search_pb);
-    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
+    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rval);
 
-    if (res != LDAP_SUCCESS) {
+    if (rval != LDAP_SUCCESS) {
         LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n", 0, 0, 0);
-        return 1;
+        rval = 1;
+        goto bail;
     } else {
         /* Need to parse the configuration information for the ldbm
          * plugin that is held in the DSE. */
@@ -504,13 +531,15 @@ ldbm_instance_config_load_dse_info(ldbm_instance *inst)
         if ((!entries) || (!entries[0])) {
             LDAPDebug(LDAP_DEBUG_ANY, "Error accessing the config DSE\n",
                       0, 0, 0);
-            return 1;
+            rval = 1;
+            goto bail;
         }
         if (0 != parse_ldbm_instance_config_entry(inst, entries[0],
                                          ldbm_instance_config)) {
             LDAPDebug(LDAP_DEBUG_ANY, "Error parsing the config DSE\n",
                       0, 0, 0);
-            return 1;
+            rval = 1;
+            goto bail;
         }
     }
 
@@ -527,8 +556,6 @@ ldbm_instance_config_load_dse_info(ldbm_instance *inst)
                                 inst->inst_name, 0);
 
     /* setup the dse callback functions for the ldbm instance config entry */
-    PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
     slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)",
         ldbm_instance_search_config_entry_callback, (void *) inst);
@@ -543,9 +570,20 @@ ldbm_instance_config_load_dse_info(ldbm_instance *inst)
         ldbm_instance_deny_config, (void *)inst);
     /* delete is handled by a callback set in ldbm_config.c */
 
+    slapi_ch_free_string(&dn);
+
     /* don't forget the monitor! */
-    PR_snprintf(dn, BUFSIZ, "cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_config_load_dse_info: "
+                       "failed create monitor instance dn for plugin %s, "
+                       "instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        rval = 1;
+        goto bail;
+    }
     /* make callback on search; deny add/modify/delete */
     slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_instance_search,
@@ -557,10 +595,20 @@ ldbm_instance_config_load_dse_info(ldbm_instance *inst)
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_instance_deny_config,
         (void *)inst);
     /* delete is okay */
+    slapi_ch_free_string(&dn);
 
     /* Callbacks to handle indexes */
-    PR_snprintf(dn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=index,cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_config_load_dse_info: "
+                       "failed create index instance dn for plugin %s, "
+                       "instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        rval = 1;
+        goto bail;
+    }
     slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
         ldbm_instance_index_config_add_callback, (void *) inst);
@@ -570,10 +618,20 @@ ldbm_instance_config_load_dse_info(ldbm_instance *inst)
     slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
         ldbm_instance_index_config_modify_callback, (void *) inst);
+    slapi_ch_free_string(&dn);
 
     /* Callbacks to handle attribute encryption */
-    PR_snprintf(dn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=encrypted attributes,cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_config_load_dse_info: "
+                       "failed create encrypted attribute instance dn "
+                       "for plugin %s, instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        rval = 1;
+        goto bail;
+    }
     slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
         ldbm_instance_attrcrypt_config_add_callback, (void *) inst);
@@ -583,8 +641,10 @@ ldbm_instance_config_load_dse_info(ldbm_instance *inst)
     slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
         ldbm_instance_attrcrypt_config_modify_callback, (void *) inst);
-
-    return 0;
+    rval = 0;
+bail:
+    slapi_ch_free_string(&dn);
+    return rval;
 }
 
 /*
@@ -880,11 +940,19 @@ ldbm_instance_add_instance_entry_callback(Slapi_PBlock *pb, Slapi_Entry* entryBe
 static void ldbm_instance_unregister_callbacks(ldbm_instance *inst)
 {
     struct ldbminfo *li = inst->inst_li;
-    char dn[BUFSIZ];
+    char *dn = NULL;
 
     /* tear down callbacks for the instance config entry */
-    PR_snprintf(dn, BUFSIZ, "cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_unregister_callbacks: "
+                       "failed create instance dn for plugin %s, "
+                       "instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        goto bail;
+    }
     slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)",
         ldbm_instance_search_config_entry_callback);
@@ -897,20 +965,38 @@ static void ldbm_instance_unregister_callbacks(ldbm_instance *inst)
     slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)",
         ldbm_instance_deny_config);
+    slapi_ch_free_string(&dn);
 
     /* now the cn=monitor entry */
-    PR_snprintf(dn, BUFSIZ, "cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_unregister_callbacks: "
+                       "failed create monitor instance dn for plugin %s, "
+                       "instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        goto bail;
+    }
     slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_back_monitor_instance_search);
     slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, "(objectclass=*)", ldbm_instance_deny_config);
     slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_BASE, "(objectclass=*)", ldbm_instance_deny_config);
+    slapi_ch_free_string(&dn);
 
     /* now the cn=index entries */
-    PR_snprintf(dn, BUFSIZ, "cn=index, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=index,cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_unregister_callbacks: "
+                       "failed create index dn for plugin %s, "
+                       "instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        goto bail;
+    }
     slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
         ldbm_instance_index_config_add_callback);
@@ -920,10 +1006,19 @@ static void ldbm_instance_unregister_callbacks(ldbm_instance *inst)
     slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, "(objectclass=nsIndex)",
         ldbm_instance_index_config_modify_callback);
+    slapi_ch_free_string(&dn);
 
     /* now the cn=encrypted attributes entries */
-    PR_snprintf(dn, BUFSIZ, "cn=encrypted attributes, cn=%s, cn=%s, cn=plugins, cn=config",
-            inst->inst_name, li->li_plugin->plg_name);
+    dn = slapi_create_dn_string("cn=encrypted attributes,cn=%s,cn=%s,cn=plugins,cn=config",
+                                inst->inst_name, li->li_plugin->plg_name);
+    if (NULL == dn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "ldbm_instance_unregister_callbacks: "
+                       "failed create encrypted attributes dn for plugin %s, "
+                       "instance %s\n",
+                       inst->inst_li->li_plugin->plg_name, inst->inst_name);
+        goto bail;
+    }
     slapi_config_remove_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
         LDAP_SCOPE_SUBTREE, ldbm_instance_attrcrypt_filter,
         ldbm_instance_attrcrypt_config_add_callback);
@@ -935,6 +1030,8 @@ static void ldbm_instance_unregister_callbacks(ldbm_instance *inst)
         ldbm_instance_attrcrypt_config_modify_callback);
 
     vlv_remove_callbacks(inst);
+bail:
+    slapi_ch_free_string(&dn);
 }
 
 

+ 0 - 7
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c

@@ -277,13 +277,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
             /* find and lock the entry we are about to modify */
             done_with_pblock_entry(pb,SLAPI_MODRDN_TARGET_ENTRY); /* Could be through this multiple times */
             slapi_pblock_get (pb, SLAPI_TARGET_ADDRESS, &old_addr);
-            ldap_result_code = slapi_dn_syntax_check(pb, old_addr->dn, 1);
-            if (ldap_result_code)
-            {
-                ldap_result_code = LDAP_INVALID_DN_SYNTAX;
-                slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
-                goto error_return;
-            }
             ldap_result_code= get_copy_of_entry(pb, old_addr, &txn, SLAPI_MODRDN_TARGET_ENTRY, !is_replicated_operation);
             if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
                ldap_result_code==LDAP_INVALID_DN_SYNTAX)

+ 1 - 0
ldap/servers/slapd/back-ldbm/ldbm_search.c

@@ -242,6 +242,7 @@ ldbm_back_search( Slapi_PBlock *pb )
 
                     dummyAttrs[0] = dummyAttr;
 
+                    /* This dn is normalized. */
                     PR_snprintf(dn,sizeof(dn),"dn: oid=%s,cn=features,cn=config",LDAP_CONTROL_VLVREQUEST);
                     feature= slapi_str2entry(dn,0);
                     r= plugin_call_acl_plugin (pb, feature, dummyAttrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL);

+ 1 - 0
ldap/servers/slapd/back-ldbm/ldif2ldbm.c

@@ -619,6 +619,7 @@ int ldbm_back_ldif2ldbm( Slapi_PBlock *pb )
     if (task_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) {
         /* initialize UniqueID generator - must be done once backends are started
            and event queue is initialized but before plugins are started */
+        /* This dn is normalize. */
         Slapi_DN *sdn = slapi_sdn_new_dn_byval ("cn=uniqueid generator,cn=config");
         int rc = uniqueIDGenInit (NULL, sdn, 0 /* use single thread mode */);
         slapi_sdn_free (&sdn);

+ 2 - 2
ldap/servers/slapd/back-ldbm/misc.c

@@ -143,7 +143,7 @@ compute_entry_tombstone_dn(const char *entrydn, const char *uniqueid)
     PR_ASSERT(NULL != entrydn);
     PR_ASSERT(NULL != uniqueid);
 
-    tombstone_dn = slapi_ch_smprintf("%s=%s, %s",
+    tombstone_dn = slapi_ch_smprintf("%s=%s,%s",
         SLAPI_ATTR_UNIQUEID,
         uniqueid,
         entrydn);
@@ -158,7 +158,7 @@ compute_entry_tombstone_rdn(const char *entryrdn, const char *uniqueid)
     PR_ASSERT(NULL != entryrdn);
     PR_ASSERT(NULL != uniqueid);
 
-    tombstone_rdn = slapi_ch_smprintf("%s=%s, %s",
+    tombstone_rdn = slapi_ch_smprintf("%s=%s,%s",
         SLAPI_ATTR_UNIQUEID,
         uniqueid,
         entryrdn);

+ 1 - 1
ldap/servers/slapd/back-ldbm/nextid.c

@@ -214,7 +214,7 @@ get_ids_from_disk(backend *be)
 void id_internal_to_stored(ID i,char *b)
 {
 	if ( sizeof(ID) > 4 ) {
-		memset (b+4, 0, sizeof(ID)-4);
+		(void)memset (b+4, 0, sizeof(ID)-4);
 	}
 
 	b[0] = (char)(i >> 24);

+ 55 - 23
ldap/servers/slapd/back-ldbm/vlv.c

@@ -339,7 +339,7 @@ vlv_init(ldbm_instance *inst)
     /* The FE DSE *must* be initialised before we get here */
     int return_value= LDAP_SUCCESS;
     int scope= LDAP_SCOPE_SUBTREE;
-    char *basedn, buf[512];
+    char *basedn = NULL;
     const char *searchfilter = "(objectclass=vlvsearch)";
     const char *indexfilter = "(objectclass=vlvindex)";
     backend *be= inst->inst_be;
@@ -368,9 +368,15 @@ vlv_init(ldbm_instance *inst)
     if (inst == NULL) {
         basedn = NULL;
     } else {
-        PR_snprintf(buf, sizeof(buf), "cn=%s,cn=%s,cn=plugins,cn=config",
-                inst->inst_name, inst->inst_li->li_plugin->plg_name);
-        basedn = buf;
+        basedn = slapi_create_dn_string("cn=%s,cn=%s,cn=plugins,cn=config",
+                           inst->inst_name, inst->inst_li->li_plugin->plg_name);
+        if (NULL == basedn) {
+            LDAPDebug2Args(LDAP_DEBUG_ANY,
+               "vlv_init: failed to create vlv dn for plugin %s, instance %s\n",
+               inst->inst_name, inst->inst_li->li_plugin->plg_name);
+            return_value = LDAP_PARAM_ERROR;
+            return return_value;
+        }
     }
 
     /* Find the VLV Search Entries */
@@ -405,6 +411,7 @@ vlv_init(ldbm_instance *inst)
         slapi_config_register_callback(SLAPI_OPERATION_DELETE,DSE_FLAG_PREOP,basedn,scope,indexfilter,vlv_DeleteIndexEntry,(void*)inst);
         slapi_config_register_callback(SLAPI_OPERATION_MODRDN,DSE_FLAG_PREOP,basedn,scope,searchfilter,vlv_ModifyRDNSearchEntry,(void*)inst);
         slapi_config_register_callback(SLAPI_OPERATION_MODRDN,DSE_FLAG_PREOP,basedn,scope,indexfilter,vlv_ModifyRDNIndexEntry,(void*)inst);
+		slapi_ch_free_string(&basedn);
     }
 
     return return_value;
@@ -417,16 +424,22 @@ vlv_remove_callbacks(ldbm_instance *inst) {
 
     int return_value= LDAP_SUCCESS;
     int scope= LDAP_SCOPE_SUBTREE;
-    char *basedn, buf[512];
+    char *basedn = NULL;
     const char *searchfilter = "(objectclass=vlvsearch)";
     const char *indexfilter = "(objectclass=vlvindex)";
 
     if (inst == NULL) {
         basedn = NULL;
     } else {
-        PR_snprintf(buf, sizeof(buf), "cn=%s,cn=%s,cn=plugins,cn=config",
-                inst->inst_name, inst->inst_li->li_plugin->plg_name);
-        basedn = buf;
+        basedn = slapi_create_dn_string("cn=%s,cn=%s,cn=plugins,cn=config",
+                           inst->inst_name, inst->inst_li->li_plugin->plg_name);
+        if (NULL == basedn) {
+            LDAPDebug2Args(LDAP_DEBUG_ANY,
+                 "vlv_remove_callbacks: failed to create vlv dn for plugin %s, "
+                 "instance %s\n",
+                 inst->inst_name, inst->inst_li->li_plugin->plg_name);
+            return_value = LDAP_PARAM_ERROR;
+        }
     }
     if(basedn!=NULL)
     {
@@ -439,8 +452,9 @@ vlv_remove_callbacks(ldbm_instance *inst) {
         slapi_config_remove_callback(SLAPI_OPERATION_DELETE,DSE_FLAG_PREOP,basedn,scope,indexfilter,vlv_DeleteIndexEntry);
         slapi_config_remove_callback(SLAPI_OPERATION_MODRDN,DSE_FLAG_PREOP,basedn,scope,searchfilter,vlv_ModifyRDNSearchEntry);
         slapi_config_remove_callback(SLAPI_OPERATION_MODRDN,DSE_FLAG_PREOP,basedn,scope,indexfilter,vlv_ModifyRDNIndexEntry);
+        slapi_ch_free_string(&basedn);
     }
-	return return_value;
+    return return_value;
 }
 
 /* Find an enabled index which matches this description. */
@@ -1980,17 +1994,13 @@ char *create_vlv_search_tag(const char* dn) {
 /* Builds strings from Slapi_DN similar console GUI. Uses those dns to
    delete vlvsearch's if they match. New write lock.
  */
-
-#define LDBM_PLUGIN_ROOT ", cn=ldbm database, cn=plugins, cn=config"
-#define TAG "cn=by MCC "
-
 int vlv_delete_search_entry(Slapi_PBlock *pb, Slapi_Entry* e, ldbm_instance *inst)
 {
 	int rc=0;
 	Slapi_PBlock *tmppb;
 	Slapi_DN *newdn;
 	struct vlvSearch* p=NULL;
-	char *buf, *buf2, *tag1, *tag2; 
+	char *base1 = NULL, *base2 = NULL, *tag1 = NULL, *tag2 = NULL; 
 	const char *dn= slapi_sdn_get_dn(&e->e_sdn);
 	backend *be= NULL;
 	if (NULL == inst) {
@@ -2007,8 +2017,18 @@ int vlv_delete_search_entry(Slapi_PBlock *pb, Slapi_Entry* e, ldbm_instance *ins
 		return LDAP_OPERATIONS_ERROR;
 	}
 	tag1=create_vlv_search_tag(dn);
-	buf=slapi_ch_smprintf("%s%s%s%s%s","cn=MCC ",tag1,", cn=",inst->inst_name,LDBM_PLUGIN_ROOT);
-	newdn=slapi_sdn_new_dn_byval(buf);
+	base1 = slapi_create_dn_string("cn=MCC %s,cn=%s,cn=%s,cn=plugins,cn=config",
+					tag1, inst->inst_name, inst->inst_li->li_plugin->plg_name);
+	if (NULL == base1) {
+		LDAPDebug(LDAP_DEBUG_ANY,
+				  "vlv_delete_search_entry: "
+				  "failed to craete vlv search entry dn (rdn: cn=MCC %s) for "
+				  "plugin %s, instance %s\n",
+				  tag1, inst->inst_li->li_plugin->plg_name, inst->inst_name); 
+		rc = LDAP_PARAM_ERROR;
+		goto bail;
+	}
+	newdn = slapi_sdn_new_dn_byval(base1);
 	/* vlvSearchList is modified; need Wlock */
 	PR_RWLock_Wlock(be->vlvSearchList_lock);
 	p = vlvSearch_finddn((struct vlvSearch *)be->vlvSearchList, newdn);
@@ -2016,37 +2036,49 @@ int vlv_delete_search_entry(Slapi_PBlock *pb, Slapi_Entry* e, ldbm_instance *ins
 	{
 		LDAPDebug( LDAP_DEBUG_ANY, "Deleted Virtual List View Search (%s).\n", p->vlv_name, 0, 0);
 		tag2=create_vlv_search_tag(dn);
-		buf2=slapi_ch_smprintf("%s%s,%s",TAG,tag2,buf);
+		base2 = slapi_create_dn_string("cn=by MCC %s,%s", tag2, base1);
+		if (NULL == base2) {
+			LDAPDebug(LDAP_DEBUG_ANY,
+					  "vlv_delete_search_entry: failed to create "
+					  "vlv search entry dn (rdn: cn=by MCC %s) for "
+					  "plugin %s, instance %s\n",
+					  tag2, inst->inst_li->li_plugin->plg_name, inst->inst_name); 
+			rc = LDAP_PARAM_ERROR;
+			slapi_ch_free((void **)&tag2);
+			PR_RWLock_Unlock(be->vlvSearchList_lock);
+			goto bail;
+		}
 		vlvSearch_removefromlist((struct vlvSearch **)&be->vlvSearchList,p->vlv_dn);
 		/* This line release lock to prevent recursive deadlock caused by slapi_internal_delete calling vlvDeleteSearchEntry */
 		PR_RWLock_Unlock(be->vlvSearchList_lock); 
 		vlvSearch_delete(&p);	
 		tmppb = slapi_pblock_new();
-		slapi_delete_internal_set_pb(tmppb, buf2, NULL, NULL,
+		slapi_delete_internal_set_pb(tmppb, base2, NULL, NULL,
 								 (void *)plugin_get_default_component_id(), 0);
 		slapi_delete_internal_pb(tmppb);
 		slapi_pblock_get (tmppb, SLAPI_PLUGIN_INTOP_RESULT, &rc); 
 		if(rc != LDAP_SUCCESS) {
-			LDAPDebug(LDAP_DEBUG_ANY, "vlv_delete_search_entry:can't delete dse entry '%s'\n", buf2, 0, 0);			
+			LDAPDebug(LDAP_DEBUG_ANY, "vlv_delete_search_entry:can't delete dse entry '%s'\n", base2, 0, 0);			
 		}
 		pblock_done(tmppb);
 		pblock_init(tmppb);
-		slapi_delete_internal_set_pb(tmppb, buf, NULL, NULL,
+		slapi_delete_internal_set_pb(tmppb, base1, NULL, NULL,
 								 (void *)plugin_get_default_component_id(), 0);
 		slapi_delete_internal_pb(tmppb);
 		slapi_pblock_get (tmppb, SLAPI_PLUGIN_INTOP_RESULT, &rc); 
 		if(rc != LDAP_SUCCESS) {
-			  LDAPDebug(LDAP_DEBUG_ANY, "vlv_delete_search_entry:can't delete dse entry '%s'\n", buf, 0, 0);
+			  LDAPDebug(LDAP_DEBUG_ANY, "vlv_delete_search_entry:can't delete dse entry '%s'\n", base1, 0, 0);
 		}
 		slapi_pblock_destroy(tmppb);
 		slapi_ch_free((void **)&tag2);
-		slapi_ch_free((void **)&buf2);
+		slapi_ch_free((void **)&base2);
     } else {
 		PR_RWLock_Unlock(be->vlvSearchList_lock);
 	}
+bail:
 	instance_set_not_busy(inst);
 	slapi_ch_free((void **)&tag1);
-	slapi_ch_free((void **)&buf);
+	slapi_ch_free((void **)&base1);
 	slapi_sdn_free(&newdn);
 	return rc;
 }

+ 21 - 7
ldap/servers/slapd/backend.c

@@ -47,18 +47,32 @@
 void
 be_init( Slapi_Backend *be, const char *type, const char *name, int isprivate, int logchanges, int sizelimit, int timelimit )
 {
-    char text[128];
     slapdFrontendConfig_t *fecfg;
     be->be_suffix = NULL;
     be->be_suffixlock= PR_NewLock();
     be->be_suffixcount= 0;
     /* e.g. dn: cn=config,cn=NetscapeRoot,cn=ldbm database,cn=plugins,cn=config */
-    PR_snprintf(text, sizeof(text),"cn=%s,cn=%s,cn=plugins,cn=config", name, type);
-    be->be_basedn= slapi_ch_strdup(slapi_dn_normalize(text));
-    PR_snprintf(text, sizeof(text), "cn=config,cn=%s,cn=%s,cn=plugins,cn=config", name, type);
-    be->be_configdn= slapi_ch_strdup(slapi_dn_normalize(text));
-    PR_snprintf(text, sizeof(text), "cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config", name, type);
-    be->be_monitordn= slapi_ch_strdup(slapi_dn_normalize(text));
+    be->be_basedn = slapi_create_dn_string("cn=%s,cn=%s,cn=plugins,cn=config",
+                                           name, type);
+    if (NULL == be->be_basedn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "be_init: failed create instance dn for plugin %s, "
+                       "instance %s\n", type, name);
+    }
+    be->be_configdn = slapi_create_dn_string("cn=config,cn=%s,cn=%s,cn=plugins,cn=config",
+                                             name, type);
+    if (NULL == be->be_configdn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "be_init: failed create instance config dn for "
+                       "plugin %s, instance %s\n", type, name);
+    }
+    be->be_monitordn = slapi_create_dn_string("cn=monitor,cn=%s,cn=%s,cn=plugins,cn=config",
+                                             name, type);
+    if (NULL == be->be_configdn) {
+        LDAPDebug2Args(LDAP_DEBUG_ANY,
+                       "be_init: failed create instance monitor dn for "
+                       "plugin %s, instance %s\n", type, name);
+    }
     be->be_sizelimit = sizelimit;
     be->be_timelimit = timelimit;
     /* maximum group nesting level before giving up */

+ 0 - 6
ldap/servers/slapd/backend_manager.c

@@ -423,12 +423,6 @@ be_nbackends_public()
 }
 
 /* backend instance management */
-/* JCM - These are hardcoded for the LDBM database */
-#define LDBM_CLASS_PREFIX	"cn=ldbm database,cn=plugins,cn=config"
-#define LDBM_CONFIG_ENTRY	"cn=config,cn=ldbm database,cn=plugins,cn=config"	
-#define INSTANCE_ATTR		"nsslapd-instance"
-#define	SUFFIX_ATTR			"nsslapd-suffix"
-#define CACHE_ATTR			"nsslapd-cachememsize"
 
 void 
 slapi_be_Rlock(Slapi_Backend * be)

+ 31 - 3
ldap/servers/slapd/bind.c

@@ -123,6 +123,7 @@ do_bind( Slapi_PBlock *pb )
     ber_int_t	version = -1;
     int		auth_response_requested = 0;
     int		pw_response_requested = 0;
+    char		*rawdn = NULL;
     char		*dn = NULL, *saslmech = NULL;
     struct berval	cred = {0};
     Slapi_Backend		*be = NULL;
@@ -136,6 +137,7 @@ do_bind( Slapi_PBlock *pb )
     int auto_bind = 0;
     int minssf = 0;
     char *test_bind_dn = NULL;
+    size_t dnlen = 0;
 
     LDAPDebug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
 
@@ -159,7 +161,7 @@ do_bind( Slapi_PBlock *pb )
      *	}
      */
 
-    rc = ber_scanf( ber, "{iat", &version, &dn, &method );
+    rc = ber_scanf( ber, "{iat", &version, &rawdn, &method );
     if ( rc == LBER_ERROR ) {
         LDAPDebug( LDAP_DEBUG_ANY,
                    "ber_scanf failed (op=Bind; params=Version,DN,Method)\n",
@@ -167,11 +169,37 @@ do_bind( Slapi_PBlock *pb )
         log_bind_access (pb, "???", method, version, saslmech, "decoding error");
         send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
                           "decoding error", 0, NULL );
-        slapi_ch_free_string(&dn);
+        slapi_ch_free_string(&rawdn);
         return;
     }
+    /* Check if we should be performing strict validation. */
+    if (config_get_dn_validate_strict()) { 
+        /* check that the dn is formatted correctly */
+        rc = slapi_dn_syntax_check(pb, rawdn, 1);
+        if (rc) { /* syntax check failed */
+            op_shared_log_error_access(pb, "BIND", rawdn?rawdn:"",
+                                       "strict: invalid bind dn");
+            send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+                             NULL, "invalid bind dn", 0, NULL);
+            slapi_ch_free_string(&rawdn);
+            return;
+        }
+    }
+    rc = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen);
+    if (rc < 0) {
+        op_shared_log_error_access(pb, "BIND", rawdn?rawdn:"",
+                                   "invalid bind dn");
+        send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+                         NULL, "invalid bind dn", 0, NULL);
+        slapi_ch_free_string(&rawdn);
+        return;
+    } else if (rc > 0) { /* if rc == 0, rawdn is passed in */
+        slapi_ch_free_string(&rawdn);
+    } else { /* rc == 0; rawdn is passed in; not null terminated */
+        *(dn + dnlen) = '\0';
+    }
 
-    slapi_sdn_init_dn_passin(&sdn,dn);
+    slapi_sdn_init_dn_passin(&sdn, dn);
 
     LDAPDebug( LDAP_DEBUG_TRACE, "BIND dn=\"%s\" method=%d version=%d\n",
                dn, method, version );

+ 29 - 2
ldap/servers/slapd/compare.c

@@ -65,7 +65,9 @@ void
 do_compare( Slapi_PBlock *pb )
 {
 	BerElement	*ber = pb->pb_op->o_ber;
+	char		*rawdn = NULL;
 	char		*dn = NULL;
+	size_t		 len = 0;
 	struct ava	ava = {0};
 	Slapi_Backend		*be = NULL;
 	int		err;
@@ -94,15 +96,40 @@ do_compare( Slapi_PBlock *pb )
 	 *	}
 	 */
 
-	if ( ber_scanf( ber, "{a{ao}}", &dn, &ava.ava_type,
+	if ( ber_scanf( ber, "{a{ao}}", &rawdn, &ava.ava_type,
 	    &ava.ava_value ) == LBER_ERROR ) {
 		LDAPDebug( LDAP_DEBUG_ANY,
 		    "ber_scanf failed (op=Compare; params=DN,Type,Value)\n",
 		    0, 0, 0 );
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
-		    NULL );
+			NULL );
 		goto free_and_return;
 	}
+	/* Check if we should be performing strict validation. */
+	if (config_get_dn_validate_strict()) {
+		/* check that the dn is formatted correctly */
+		err = slapi_dn_syntax_check(pb, rawdn, 1);
+		if (err) { /* syntax check failed */
+			op_shared_log_error_access(pb, "CMP",
+							rawdn?rawdn:"", "strict: invalid dn");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid dn", 0, NULL);
+			slapi_ch_free((void **) &rawdn);
+			return;
+		}
+	}
+	err = slapi_dn_normalize_ext(rawdn, 0, &dn, &len);
+	if (err < 0) {
+		op_shared_log_error_access(pb, "CMP", rawdn?rawdn:"", "invalid dn");
+		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+						 NULL, "invalid dn", 0, NULL);
+		slapi_ch_free((void **) &rawdn);
+		return;
+	} else if (err > 0) { /* if rc == 0, rawdn is passed in */
+		slapi_ch_free((void **) &rawdn);
+	} else { /* rc == 0; rawdn is passed in; not null terminated */
+		*(dn + len) = '\0';
+	}
 	/*
 	 * in LDAPv3 there can be optional control extensions on
 	 * the end of an LDAPMessage. we need to read them in and

+ 29 - 2
ldap/servers/slapd/delete.c

@@ -71,8 +71,10 @@ do_delete( Slapi_PBlock *pb )
 {
 	Slapi_Operation *operation;
 	BerElement	*ber;
+	char	    *rawdn = NULL;
 	char	    *dn = NULL;
-	int			err;
+	size_t		dnlen = 0;
+	int			err = 0;
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
 	
@@ -88,7 +90,7 @@ do_delete( Slapi_PBlock *pb )
 	 *	DelRequest := DistinguishedName
 	 */
 
-	if ( ber_scanf( pb->pb_op->o_ber, "a", &dn ) == LBER_ERROR ) {
+	if ( ber_scanf( pb->pb_op->o_ber, "a", &rawdn ) == LBER_ERROR ) {
 		LDAPDebug( LDAP_DEBUG_ANY,
 		    "ber_scanf failed (op=Delete; params=DN)\n", 0, 0, 0 );
 		op_shared_log_error_access (pb, "DEL", "???", "decoding error");
@@ -96,6 +98,31 @@ do_delete( Slapi_PBlock *pb )
 		    NULL );
 		goto free_and_return;
 	}
+	/* Check if we should be performing strict validation. */
+	if (config_get_dn_validate_strict()) {
+		/* check that the dn is formatted correctly */
+		err = slapi_dn_syntax_check(pb, rawdn, 1);
+		if (err) { /* syntax check failed */
+			op_shared_log_error_access(pb, "DEL", rawdn?rawdn:"",
+							"strict: invalid dn");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid dn", 0, NULL);
+			slapi_ch_free_string(&rawdn);
+			goto free_and_return;
+		}
+	}
+	err = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen);
+	if (err < 0) {
+		op_shared_log_error_access(pb, "DEL", "???", "invalid dn");
+		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+						 NULL, "invalid dn", 0, NULL);
+		slapi_ch_free_string(&rawdn);
+		goto free_and_return;
+	} else if (err > 0) { /* if err == 0, rawdn is passed in */
+		slapi_ch_free_string(&rawdn);
+	} else { /* err == 0; rawdn is passed in; not null terminated */
+		*(dn + dnlen) = '\0';
+	}
 
 	/*
 	 * in LDAPv3 there can be optional control extensions on

File diff suppressed because it is too large
+ 705 - 80
ldap/servers/slapd/dn.c


+ 211 - 43
ldap/servers/slapd/entry.c

@@ -150,9 +150,9 @@ str2entry_state_information_from_type(char *s,CSNSet **csnset,CSN **attributedel
 	}
 }
 
-/* dn is not consumed.  Caller needs to free it. */
+/* rawdn is not consumed.  Caller needs to free it. */
 static Slapi_Entry *
-str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
+str2entry_fast( const char *rawdn, char *s, int flags, int read_stateinfo )
 {
 	Slapi_Entry	*e;
 	char		*next, *ptype=NULL;
@@ -163,6 +163,11 @@ str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
 	CSN *attributedeletioncsn= 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;
+	char *normdn = NULL;
+	int strict = 0;
+
+    /* Check if we should be performing strict validation. */
+    strict = config_get_dn_validate_strict();
 
 	/*
 	 * In string format, an entry looks like either of these:
@@ -267,13 +272,41 @@ str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
 			a = NULL;
 		}
 
-		if ( dn ) {
-		    if ( NULL == slapi_entry_get_dn_const( e )) {
-				slapi_entry_set_dn( e, slapi_ch_strdup( dn ));
+		if ( rawdn ) {
+			if ( NULL == slapi_entry_get_dn_const( e )) {
+				normdn = slapi_create_dn_string("%s", rawdn);
+				if (NULL == normdn) {
+					LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+							  	"str2entry_fast: Invalid DN: %s\n", rawdn);
+					slapi_entry_free( e );
+					if (retmalloc) slapi_ch_free_string(&valuecharptr);
+					if (freetype) slapi_ch_free_string(&type);
+					return NULL;
+				}
+				/* normdn is consumed in e */
+				slapi_entry_set_dn(e, normdn);
 			}
-		    if ( NULL == slapi_entry_get_rdn_const( e )) {
-				slapi_entry_set_rdn( e,  (char *)dn );
+			if ( NULL == slapi_entry_get_rdn_const( e )) {
+				if (normdn) {
+					/* normdn is just referred in slapi_entry_set_rdn. */
+					slapi_entry_set_rdn(e, normdn);
+				} else {
+					normdn = slapi_create_dn_string("%s", rawdn);
+					if (NULL == normdn) {
+						LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+							  	"str2entry_fast: Invalid DN: %s\n", rawdn);
+						slapi_entry_free( e );
+						if (retmalloc) slapi_ch_free_string(&valuecharptr);
+						if (freetype) slapi_ch_free_string(&type);
+						return NULL;
+					}
+					/* normdn is just referred in slapi_entry_set_rdn. */
+					slapi_entry_set_rdn(e, normdn);
+					slapi_ch_free_string(&normdn);
+				}
 			}
+			rawdn = NULL; /* Set once in the loop. 
+							 This won't affect the caller's passed address. */
 		}
 		if ( strcasecmp( type, "dn" ) == 0 ) {
 			if ( slapi_entry_get_dn_const(e)!=NULL ) {
@@ -288,11 +321,22 @@ str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
 				if (freetype) slapi_ch_free_string(&type);
 				continue;
 			}
-			slapi_entry_set_dn(e,slapi_ch_strdup( valuecharptr ));
+			normdn = slapi_create_dn_string("%s", valuecharptr);
+			if (NULL == normdn) {
+				LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+							  "str2entry_fast: Invalid DN: %s\n", valuecharptr);
+				slapi_entry_free( e );
+				if (retmalloc) slapi_ch_free_string(&valuecharptr);
+				if (freetype) slapi_ch_free_string(&type);
+				return NULL;
+			}
+			/* normdn is consumed in e */
+			slapi_entry_set_dn(e, normdn);
+
 			/* the memory below was not allocated by the slapi_ch_ functions */
 			if (retmalloc) slapi_ch_free_string(&valuecharptr);
 			if (freetype) slapi_ch_free_string(&type);
-		    continue;
+			continue;
 		}
 
 		if ( strcasecmp( type, "rdn" ) == 0 ) {
@@ -302,7 +346,7 @@ str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
 			/* the memory below was not allocated by the slapi_ch_ functions */
 			if (retmalloc) slapi_ch_free_string(&valuecharptr);
 			if (freetype) slapi_ch_free_string(&type);
-		    continue;
+			continue;
 		}
 
 
@@ -310,8 +354,9 @@ str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
 		if ( strcasecmp (type, SLAPI_ATTR_UNIQUEID) == 0 ){
 
 			if (e->e_uniqueid != NULL){
-				LDAPDebug (LDAP_DEBUG_ANY, "str2entry_fast: entry has multiple "
-						   "uniqueids %s and %s (second ignored)\n",
+				LDAPDebug (LDAP_DEBUG_TRACE, 
+						   "str2entry_fast: entry has multiple uniqueids %s "
+						   "and %s (second ignored)\n",
 						   e->e_uniqueid, valuecharptr, 0);
 			}else{
 				/* name2asi will be locked in slapi_entry_set_uniqueid */
@@ -333,12 +378,7 @@ str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
 		}
 		
 		{
-			Slapi_Value	*value= value_new(NULL,CSN_TYPE_NONE,NULL);
-			slapi_value_set( value, valuecharptr, valuelen );
-			/* the memory below was not allocated by the slapi_ch_ functions */	
-			if (retmalloc) slapi_ch_free_string(&valuecharptr);
-			value->v_csnset= valuecsnset;
-			valuecsnset= NULL;
+			Slapi_Value	*value = NULL;
 			if(a==NULL)
 			{
 				switch(attr_state)
@@ -368,9 +408,51 @@ str2entry_fast( const char *dn, char *s, int flags, int read_stateinfo )
 					continue;
 					/* break; ??? */
 				}
-
+			}
+			/* moved the value setting code here to check Slapi_Attr 'a'
+			 * to retrieve the attribute syntax info */
+			value = value_new(NULL, CSN_TYPE_NONE, NULL);
+			if (slapi_attr_is_dn_syntax_attr(*a)) {
+				int rc = 0;
+				char *dn_aval = NULL;
+				size_t dnlen = 0;
+				if (strict) {
+					/* check that the dn is formatted correctly */
+					rc = slapi_dn_syntax_check(NULL, valuecharptr, 1);
+					if (rc) { /* syntax check failed */
+						LDAPDebug2Args(LDAP_DEBUG_TRACE, 
+							"str2entry_fast: strict: Invalid DN value: %s: %s\n",
+							type, valuecharptr);
+						slapi_entry_free( e );
+						if (retmalloc) slapi_ch_free_string(&valuecharptr);
+						if (freetype) slapi_ch_free_string(&type);
+						return NULL;
+					}
+				}
+				rc = slapi_dn_normalize_ext(valuecharptr, 0, &dn_aval, &dnlen);
+				if (rc < 0) {
+					/* Give up normalizing the attribute value */
+					LDAPDebug2Args(LDAP_DEBUG_TRACE,
+							       "str2entry_fast: Invalid DN value: %s: %s\n",
+							       type, valuecharptr);
+					dn_aval = valuecharptr;
+					dnlen = valuelen;
+				}
+				slapi_value_set(value, dn_aval, dnlen);
+				if (rc > 0) { /* if rc == 0, valuecharptr is passed in */
+					slapi_ch_free_string(&dn_aval);
+				} else if (rc == 0) { /* rc == 0; valuecharptr is passed in; 
+										 not null terminated */
+					*(dn_aval + dnlen) = '\0';
+				}
+			} else {
+				slapi_value_set(value, valuecharptr, valuelen);
 			}
 			if (freetype) slapi_ch_free_string(&type); /* don't need type anymore */
+			/* the memory below was not allocated by the slapi_ch_ functions */	
+			if (retmalloc) slapi_ch_free_string(&valuecharptr);
+			value->v_csnset = valuecsnset;
+			valuecsnset = NULL;
 			{
 				const CSN *distinguishedcsn= csnset_get_csn_of_type(value->v_csnset,CSN_TYPE_VALUE_DISTINGUISHED);
 				if(distinguishedcsn!=NULL)
@@ -601,7 +683,7 @@ entry_attrs_find(entry_attrs *ea,char *type)
 
 /* dn is not consumed.  Caller needs to free it. */
 static Slapi_Entry *
-str2entry_dupcheck( const char *dn, char *s, int flags, int read_stateinfo )
+str2entry_dupcheck( const char *rawdn, char *s, int flags, int read_stateinfo )
 {
     Slapi_Entry	*e;
     str2entry_attr stack_attrs[STR2ENTRY_SMALL_BUFFER_SIZE];
@@ -625,6 +707,11 @@ str2entry_dupcheck( const char *dn, char *s, int flags, int read_stateinfo )
 			( 0 != ( flags & SLAPI_STR2ENTRY_REMOVEDUPVALS ));
 	Slapi_Value *value = 0;
 	CSN *maxcsn= NULL;
+	char *normdn = NULL;
+	int strict = 0;
+
+    /* Check if we should be performing strict validation. */
+    strict = config_get_dn_validate_strict();
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "=> str2entry_dupcheck\n", 0, 0, 0 );
 
@@ -688,16 +775,44 @@ str2entry_dupcheck( const char *dn, char *s, int flags, int read_stateinfo )
 			csnset_free(&valuecsnset);
 		}
 
-		if ( dn ) {
-		    if ( NULL == slapi_entry_get_dn_const(e) ) {
-				slapi_entry_set_dn( e, slapi_ch_strdup( dn ));
+		if ( rawdn ) {
+			if ( NULL == slapi_entry_get_dn_const(e) ) {
+				normdn = slapi_create_dn_string("%s", rawdn);
+				if (NULL == normdn) {
+					LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+							  "str2entry_dupcheck: Invalid DN: %s\n", rawdn);
+					slapi_entry_free( e );
+					if (retmalloc) slapi_ch_free_string(&valuecharptr);
+					if (freetype) slapi_ch_free_string(&type);
+					return NULL;
+				}
+				/* normdn is consumed in e */
+				slapi_entry_set_dn(e, normdn);
 			}
-		    if ( NULL == slapi_entry_get_rdn_const(e) ) {
-				slapi_entry_set_rdn( e, (char *)dn );
+			if ( NULL == slapi_entry_get_rdn_const(e) ) {
+				if (normdn) {
+					/* normdn is just referred in slapi_entry_set_rdn. */
+					slapi_entry_set_rdn(e, normdn);
+				} else {
+					normdn = slapi_create_dn_string("%s", rawdn);
+					if (NULL == normdn) {
+						LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+							  	"str2entry_fast: Invalid DN: %s\n", rawdn);
+						slapi_entry_free( e );
+						if (retmalloc) slapi_ch_free_string(&valuecharptr);
+						if (freetype) slapi_ch_free_string(&type);
+						return NULL;
+					}
+					/* normdn is just referred in slapi_entry_set_rdn. */
+					slapi_entry_set_rdn(e, normdn);
+					slapi_ch_free_string(&normdn);
+				}
 			}
+			rawdn = NULL; /* Set once in the loop. 
+							 This won't affect the caller's passed address. */
 		}
 		if ( strcasecmp( type, "dn" ) == 0 ) {
-		    if ( slapi_entry_get_dn_const(e)!=NULL ) {
+			if ( slapi_entry_get_dn_const(e)!=NULL ) {
 				char ebuf[ BUFSIZ ];
 				LDAPDebug( LDAP_DEBUG_TRACE,
 					"str2entry_dupcheck: entry has multiple dns \"%s\" "
@@ -708,8 +823,18 @@ str2entry_dupcheck( const char *dn, char *s, int flags, int read_stateinfo )
 				if (retmalloc) slapi_ch_free_string(&valuecharptr);
 				if (freetype) slapi_ch_free_string(&type);
 				continue;
-		    }
-			slapi_entry_set_dn(e,slapi_ch_strdup( valuecharptr ));
+			}
+			normdn = slapi_create_dn_string("%s", valuecharptr);
+			if (NULL == normdn) {
+				LDAPDebug1Arg(LDAP_DEBUG_TRACE,
+						"str2entry_dupcheck: Invalid DN: %s\n", valuecharptr);
+				slapi_entry_free( e ); e = NULL;
+				if (retmalloc) slapi_ch_free_string(&valuecharptr);
+				if (freetype) slapi_ch_free_string(&type);
+				goto free_and_return;
+			}
+			/* normdn is consumed in e */
+			slapi_entry_set_dn(e, normdn);
 			/* the memory below was not allocated by the slapi_ch_ functions */
 			if (retmalloc) slapi_ch_free_string(&valuecharptr);
 			if (freetype) slapi_ch_free_string(&type);
@@ -730,8 +855,9 @@ str2entry_dupcheck( const char *dn, char *s, int flags, int read_stateinfo )
 		if ( strcasecmp (type, SLAPI_ATTR_UNIQUEID) == 0 ){
 
 			if (e->e_uniqueid != NULL){
-				LDAPDebug (LDAP_DEBUG_ANY, "str2entry_dupcheck: entry has multiple "
-						   "uniqueids %s and %s (second ignored)\n", 
+				LDAPDebug (LDAP_DEBUG_TRACE, 
+						   "str2entry_dupcheck: entry has multiple uniqueids %s "
+						   "and %s (second ignored)\n", 
 						   e->e_uniqueid, valuecharptr, 0);
 			}else{
 				slapi_entry_set_uniqueid (e, slapi_ch_strdup(valuecharptr));
@@ -853,10 +979,44 @@ str2entry_dupcheck( const char *dn, char *s, int flags, int read_stateinfo )
 			nattrs++;
 		}
 
-		if (freetype) slapi_ch_free_string(&type);
 		sa = prev_attr;	/* For readability */
-		value= value_new(NULL,CSN_TYPE_NONE,NULL);
-		slapi_value_set( value, valuecharptr, valuelen );
+		value= value_new(NULL, CSN_TYPE_NONE, NULL);
+		if (slapi_attr_is_dn_syntax_attr(&(sa->sa_attr))) {
+			char *dn_aval = NULL;
+			size_t dnlen = 0;
+			if (strict) {
+				/* check that the dn is formatted correctly */
+				rc = slapi_dn_syntax_check(NULL, valuecharptr, 1);
+				if (rc) { /* syntax check failed */
+					LDAPDebug2Args(LDAP_DEBUG_ANY, 
+						"str2entry_dupcheck: strict: Invalid DN value: %s: %s\n",
+						type, valuecharptr);
+					slapi_entry_free( e ); e = NULL;
+					if (retmalloc) slapi_ch_free_string(&valuecharptr);
+					if (freetype) slapi_ch_free_string(&type);
+					goto free_and_return;
+				}
+			}
+			rc = slapi_dn_normalize_ext(valuecharptr, 0, &dn_aval, &dnlen);
+			if (rc < 0) {
+				/* Give up normalizing the attribute value */
+				LDAPDebug2Args(LDAP_DEBUG_TRACE,
+							   "str2entry_dupcheck: Invalid DN value: %s: %s\n",
+							   type, valuecharptr);
+				dn_aval = valuecharptr;
+				dnlen = valuelen;
+			}
+			slapi_value_set(value, dn_aval, dnlen);
+			if (rc > 0) { /* if rc == 0, valuecharptr is passed in */
+				slapi_ch_free_string(&dn_aval);
+			} else if (rc == 0) { /* rc == 0; valuecharptr is passed in; 
+									 not null terminated */
+				*(dn_aval + dnlen) = '\0';
+			}
+		} else {
+			slapi_value_set(value, valuecharptr, valuelen);
+		}
+		if (freetype) slapi_ch_free_string(&type);
 		/* the memory below was not allocated by the slapi_ch_ functions */
 		if (retmalloc) slapi_ch_free_string(&valuecharptr);
 		value->v_csnset= valuecsnset;
@@ -1166,6 +1326,7 @@ slapi_str2entry( char *s, int flags )
 
 /*
  * string s does not include dn.
+ * NOTE: the first arg "dn" should have been normalized before passing.
  */
 Slapi_Entry *
 slapi_str2entry_ext( const char *dn, char *s, int flags )
@@ -1190,15 +1351,15 @@ slapi_str2entry_ext( const char *dn, char *s, int flags )
 	 */
 	if ( 0 != ( flags & SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ) ||
 			0 != ( flags & ~SLAPI_STRENTRY_FLAGS_HANDLED_BY_STR2ENTRY_FAST ))
-    {
+	{
 	    e= str2entry_dupcheck( dn, s, flags, read_stateinfo );
-    }
-    else
-    {
+	}
+	else
+	{
 	    e= str2entry_fast( dn, s, flags, read_stateinfo );
-    }
-    if (!e)
-       return e;	/* e == NULL */
+	}
+	if (!e)
+		return e;	/* e == NULL */
 
 	if ( flags & SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES )
 	{
@@ -1770,8 +1931,12 @@ static size_t slapi_dn_size(Slapi_DN *sdn)
 
     if (sdn == NULL) return 0;
 
-    if (sdn->dn) size += strlen(sdn->dn) + 1;
-    if (sdn->ndn) size *= 2;
+    if (slapi_sdn_get_dn(sdn)) {
+        size += strlen(slapi_sdn_get_dn(sdn)) + 1;
+    }
+    if (slapi_sdn_get_ndn(sdn)) {
+        size += strlen(slapi_sdn_get_ndn(sdn)) + 1;
+    }
 
     return size;
 }
@@ -2922,7 +3087,7 @@ entry_apply_mod( Slapi_Entry *e, const LDAPMod *mod )
 	case LDAP_MOD_ADD:
 		LDAPDebug( LDAP_DEBUG_ARGS, "   add: %s\n", mod->mod_type, 0, 0 );
 		if(sawsubentry) e->e_flags |= SLAPI_ENTRY_LDAPSUBENTRY;
-		err =  slapi_entry_add_values( e, mod->mod_type, mod->mod_bvalues );
+		err = slapi_entry_add_values( e, mod->mod_type, mod->mod_bvalues );
 		break;
 
 	case LDAP_MOD_DELETE:
@@ -2980,6 +3145,9 @@ slapi_entry_add_values_sv(Slapi_Entry *e,
 		Slapi_Attr **a= NULL;
 		Slapi_Attr **alist= &e->e_attrs;
 		attrlist_find_or_create(alist, type, &a);
+		if (slapi_attr_is_dn_syntax_attr(*a)) {
+			valuearray_normalize_value(vals);
+		}
 		rc= attr_add_valuearray(*a,vals,slapi_entry_get_dn_const(e));
     }
     return( rc );

+ 9 - 0
ldap/servers/slapd/entrywsi.c

@@ -450,6 +450,10 @@ entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **b
 		}
         a_flags_orig = a->a_flags;
 		a->a_flags |= flags;
+		/* Check if the type of the to-be-added values has DN syntax or not. */
+		if (slapi_attr_is_dn_syntax_attr(a)) {
+			valuearray_normalize_value(valuestoadd);
+		}
 		if(urp)
 		{
 			/*
@@ -566,6 +570,11 @@ entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval
 			/* delete some specific values */
 		    Slapi_Value **valuestodelete= NULL;
 		    valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
+			/* Check if the type of the to-be-deleted values has DN syntax 
+			 * or not. */
+			if (slapi_attr_is_dn_syntax_attr(a)) {
+				valuearray_normalize_value(valuestodelete);
+			}
 			if(urp)
 			{
 				Slapi_Value **valuesupdated= NULL;

+ 32 - 5
ldap/servers/slapd/extendop.c

@@ -53,7 +53,9 @@ static const char *extended_op_oid2string( const char *oid );
 static void extop_handle_import_start(Slapi_PBlock *pb, char *extoid,
                                       struct berval *extval)
 {
-    char *suffix;
+    char *orig = NULL;
+    char *suffix = NULL;
+    size_t dnlen = 0;
     Slapi_DN *sdn = NULL;
     Slapi_Backend *be = NULL;
     struct berval bv;
@@ -66,10 +68,34 @@ static void extop_handle_import_start(Slapi_PBlock *pb, char *extoid,
                          "no data supplied", 0, NULL);
         return;
     }
-    suffix = slapi_ch_malloc(extval->bv_len+1);
-    strncpy(suffix, extval->bv_val, extval->bv_len);
-    suffix[extval->bv_len] = 0;
-
+    orig = slapi_ch_malloc(extval->bv_len+1);
+    strncpy(orig, extval->bv_val, extval->bv_len);
+    orig[extval->bv_len] = 0;
+    /* Check if we should be performing strict validation. */
+    if (config_get_dn_validate_strict()) {
+        /* check that the dn is formatted correctly */
+        ret = slapi_dn_syntax_check(pb, orig, 1);
+        if (ret) { /* syntax check failed */
+            LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                          "extop_handle_import_start: strict: invalid suffix\n",
+                          orig);
+            send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL,
+                             "invalid suffix", 0, NULL);
+            return;
+        }
+    }
+    ret = slapi_dn_normalize_ext(orig, 0, &suffix, &dnlen);
+    if (ret < 0) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "extop_handle_import_start: invalid suffix\n", orig);
+        send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL,
+                         "invalid suffix", 0, NULL);
+        return;
+    } else if (ret > 0) {
+        slapi_ch_free_string(&orig);
+    } else { /* ret == 0; orig is passed in; not null terminated */
+        *(suffix + dnlen) = '\0';
+    }
     sdn = slapi_sdn_new_dn_byval(suffix);
     if (!sdn) {
         LDAPDebug(LDAP_DEBUG_ANY,
@@ -109,6 +135,7 @@ static void extop_handle_import_start(Slapi_PBlock *pb, char *extoid,
 		/* slapi_str2entry modify its dn parameter so we must copy
 		 * this string each time we call it !
 		 */
+		/* This dn is no need to be normalized. */
 		PR_snprintf(dn, sizeof(dn), "dn: oid=%s,cn=features,cn=config",
 			EXTOP_BULK_IMPORT_START_OID);
 

+ 1 - 0
ldap/servers/slapd/fedse.c

@@ -76,6 +76,7 @@
 
 extern char ** getSupportedCiphers();
 
+/* Note: These DNs are no need to be normalized */
 static const char *internal_entries[] =
 {
     "dn:\n"

+ 6 - 5
ldap/servers/slapd/libglobs.c

@@ -870,7 +870,8 @@ FrontendConfig_init () {
   cfg->ldapi_map_entries = LDAP_OFF;
   cfg->ldapi_uidnumber_type = slapi_ch_strdup("uidNumber");
   cfg->ldapi_gidnumber_type = slapi_ch_strdup("gidNumber");
-  cfg->ldapi_search_base_dn = slapi_ch_strdup("dc=example, dc=com");
+  /* These DNs are no need to be normalized. */
+  cfg->ldapi_search_base_dn = slapi_ch_strdup("dc=example,dc=com");
 #if defined(ENABLE_AUTO_DN_SUFFIX)
   cfg->ldapi_auto_dn_suffix = slapi_ch_strdup("cn=peercred,cn=external,cn=auth");
 #endif
@@ -4884,18 +4885,18 @@ config_set_instancedir(const char *attrname, char *value, char *errorbuf, int ap
 {
 	int retVal = LDAP_SUCCESS;
 	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
-  
+   
 	if ( config_value_is_null( attrname, value, errorbuf, 0 )) {
 		return LDAP_OPERATIONS_ERROR;
 	}
-  
+   
 	if (!apply) {
 		return retVal;
 	}
-
+ 
 	CFG_LOCK_WRITE(slapdFrontendConfig);
 	/* We don't want to allow users to modify instance dir.
- 	 * Set it once when the server starts. */
+	 * Set it once when the server starts. */
 	if (NULL == slapdFrontendConfig->instancedir) {
 		slapdFrontendConfig->instancedir = slapi_ch_strdup(value);
 	}

+ 4 - 0
ldap/servers/slapd/main.c

@@ -1107,6 +1107,7 @@ main( int argc, char **argv)
 
 		/* initialize UniqueID generator - must be done once backends are started
 		   and event queue is initialized but before plugins are started */
+		/* Note: This DN is no need to be normalized. */
 		sdn = slapi_sdn_new_dn_byval ("cn=uniqueid generator,cn=config");
 		rc = uniqueIDGenInit (NULL, sdn, slapd_exemode == SLAPD_EXEMODE_SLAPD);
 		slapi_sdn_free (&sdn);
@@ -1908,6 +1909,7 @@ lookup_instance_name_by_suffix(char *suffix,
         if (query == NULL)
             goto done;
     
+        /* Note: This DN is no need to be normalized. */
         slapi_search_internal_set_pb(pb, "cn=mapping tree,cn=config",
             LDAP_SCOPE_SUBTREE, query, NULL, 0, NULL, NULL,
             (void *)plugin_get_default_component_id(), 0);
@@ -1928,6 +1930,7 @@ lookup_instance_name_by_suffix(char *suffix,
             query = slapi_ch_smprintf("(&(objectclass=nsmappingtree)(|(cn=*%s\")(cn=*%s)))", suffixp, suffixp);
             if (query == NULL)
                 goto done;
+            /* Note: This DN is no need to be normalized. */
             slapi_search_internal_set_pb(pb, "cn=mapping tree,cn=config",
                 LDAP_SCOPE_SUBTREE, query, NULL, 0, NULL, NULL,
                 (void *)plugin_get_default_component_id(), 0);
@@ -2015,6 +2018,7 @@ static struct slapdplugin *lookup_plugin_by_instance_name(const char *name)
         return NULL;
     }
 
+    /* Note: This DN is no need to be normalized. */
     slapi_search_internal_set_pb(pb, "cn=plugins,cn=config",
         LDAP_SCOPE_SUBTREE, query, NULL, 0, NULL, NULL,
         (void *)plugin_get_default_component_id(), 0);

+ 54 - 35
ldap/servers/slapd/mapping_tree.c

@@ -133,6 +133,7 @@ static int extension_type = -1;    /* type returned from the factory */
 
 /* Need to add a modifier flag to the state - such as round robin */
 
+/* Note: This DN is no need to be normalized. */
 #define MAPPING_TREE_BASE_DN "cn=mapping tree,cn=config"
 #define MAPPING_TREE_PARENT_ATTRIBUTE "nsslapd-parent-suffix"
 
@@ -365,24 +366,30 @@ static Slapi_DN *
 get_parent_from_entry(Slapi_Entry * entry)
 {
     Slapi_Attr *attr = NULL;
-    char * parent;
+    char *origparent = NULL;
+    char *parent = NULL;
     Slapi_Value *val = NULL;
-    Slapi_DN *parent_sdn;
+    Slapi_DN *parent_sdn = NULL;
 
     if (slapi_entry_attr_find(entry, MAPPING_TREE_PARENT_ATTRIBUTE, &attr))
         return NULL;
 
     slapi_attr_first_value(attr, &val);
 
-    parent = slapi_ch_strdup(slapi_value_get_string(val));
-    if(parent[0]=='\"')
-    {
-        parent[strlen(parent) - 1] = '\0';
-        parent_sdn = slapi_sdn_new_dn_byval(parent+1);
+    origparent = parent = slapi_ch_strdup(slapi_value_get_string(val));
+    if (parent) {
+        if(*parent == '"') {
+            char *ptr = NULL;
+            parent++; /* skipping the starting '"' */
+            ptr = PL_strnrchr(parent, '"', strlen(parent));
+            if (ptr) {
+                *ptr = '\0';
+            }
+        }
+        parent_sdn = 
+                slapi_sdn_new_dn_passin(slapi_create_dn_string("%s", parent));
+        slapi_ch_free_string(&origparent);
     }
-    else
-        parent_sdn = slapi_sdn_new_dn_byval(parent);
-    slapi_ch_free((void **) &parent);
     
     return parent_sdn;
 }
@@ -393,9 +400,10 @@ static Slapi_DN *
 get_subtree_from_entry(Slapi_Entry * entry)
 {
     Slapi_Attr *attr = NULL;
-    char * cn;
+    char *origcn = NULL;
+    char *cn = NULL;
     Slapi_Value *val = NULL;
-    Slapi_DN *subtree;
+    Slapi_DN *subtree = NULL;
 
     if (slapi_entry_attr_find(entry, "cn", &attr))
         return NULL;
@@ -415,15 +423,19 @@ get_subtree_from_entry(Slapi_Entry * entry)
     /* GB : I think removing the first and last " in the cn value
      * is the right stuff to do
      */
-    cn = slapi_ch_strdup(slapi_value_get_string(val));
-    if(cn[0]=='\"')
-    {
-        cn[strlen(cn) - 1] = '\0';
-        subtree = slapi_sdn_new_dn_byval(cn+1);
+    origcn = cn = slapi_ch_strdup(slapi_value_get_string(val));
+    if (cn) {
+        if(*cn == '"') {
+            char *ptr = NULL;
+            cn++; /* skipping the starting '"' */
+            ptr = PL_strnrchr(cn, '"', strlen(cn));
+            if (ptr) {
+                *ptr = '\0';
+            }
+        }
+        subtree = slapi_sdn_new_dn_passin(slapi_create_dn_string("%s", cn));
+        slapi_ch_free_string(&origcn);
     }
-    else
-        subtree = slapi_sdn_new_dn_byval(cn);
-    slapi_ch_free((void **) &cn);
     
     return subtree;
 }
@@ -2790,7 +2802,7 @@ get_mapping_tree_node_by_name(mapping_tree_node * node, char * be_name)
 char* 
 slapi_get_mapping_tree_node_configdn (const Slapi_DN *root)
 {
-    char *dn;
+    char *dn = NULL;
 
     if(mapping_tree_freed){
         /* shutdown detected */
@@ -2799,7 +2811,16 @@ slapi_get_mapping_tree_node_configdn (const Slapi_DN *root)
     if (root == NULL)
         return NULL;
 
-    dn = slapi_ch_smprintf("cn=\"%s\",%s", slapi_sdn_get_dn(root), MAPPING_TREE_BASE_DN);
+    /* This function converts the old DN style to the new one. */
+    dn = slapi_create_dn_string("cn=\"%s\",%s", 
+                                slapi_sdn_get_dn(root), MAPPING_TREE_BASE_DN);
+    if (NULL == dn) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "slapi_get_mapping_tree_node_configdn: "
+                      "failed to crate mapping tree dn for %s\n", 
+                      slapi_sdn_get_dn(root));
+        return NULL;
+    }
 
     return dn;
 }
@@ -3114,7 +3135,7 @@ slapi_mtn_set_referral(const Slapi_DN *sdn, char ** referral)
     }
 
     slapi_mods_done(&smods);
-    slapi_ch_free((void **) &node_dn);
+    slapi_ch_free_string(&node_dn);
 
     return rc;
 } 
@@ -3135,13 +3156,13 @@ slapi_mtn_set_state(const Slapi_DN *sdn, char *state)
     char * node_dn;
     char * value;
 
-    node_dn = slapi_get_mapping_tree_node_configdn(sdn);
-    if(!node_dn){
-     /* shutdown has been detected */
+    if (NULL == state) {
         return LDAP_OPERATIONS_ERROR;
     }
 
-    if (NULL == state) {
+    node_dn = slapi_get_mapping_tree_node_configdn(sdn);
+    if(!node_dn){
+     /* shutdown has been detected */
         return LDAP_OPERATIONS_ERROR;
     }
 
@@ -3150,9 +3171,7 @@ slapi_mtn_set_state(const Slapi_DN *sdn, char *state)
         if ( strcasecmp(value, state) == 0 )
         {
             /* Same state, don't change anything */
-            slapi_ch_free((void **) &value);
-            slapi_ch_free((void **) &node_dn);
-            return rc;
+            goto bail;
         }
     }
     
@@ -3168,10 +3187,10 @@ slapi_mtn_set_state(const Slapi_DN *sdn, char *state)
     slapi_pblock_get (&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
 
     slapi_mods_done(&smods);
-    slapi_ch_free((void **) &node_dn);
     pblock_done(&pb);
-    slapi_ch_free((void **) &value);
-
+bail:
+    slapi_ch_free_string(&value);
+    slapi_ch_free_string(&node_dn);
     return rc;
 }
 
@@ -3265,7 +3284,7 @@ slapi_mtn_get_referral(const Slapi_DN *sdn)
         slapi_attr_free(&attr);
     }
 
-    slapi_ch_free((void **) &node_dn);
+    slapi_ch_free_string(&node_dn);
     return referral;
 }
 
@@ -3301,7 +3320,7 @@ slapi_mtn_get_state(const Slapi_DN *sdn)
         slapi_attr_free(&attr);
     }
 
-    slapi_ch_free((void **) &node_dn);
+    slapi_ch_free_string(&node_dn);
     return state;
 }
 

+ 31 - 4
ldap/servers/slapd/modify.c

@@ -166,16 +166,43 @@ do_modify( Slapi_PBlock *pb )
 	 */
 
     {
-    	if ( ber_scanf( ber, "{a", &dn ) == LBER_ERROR )
+		char *rawdn = NULL;
+		size_t dnlen = 0;
+		int rc = 0;
+    	if ( ber_scanf( ber, "{a", &rawdn ) == LBER_ERROR )
     	{
     		LDAPDebug( LDAP_DEBUG_ANY,
     		    "ber_scanf failed (op=Modify; params=DN)\n", 0, 0, 0 );
 			op_shared_log_error_access (pb, "MOD", "???", "decoding error");
-    		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0,
-    		    NULL );
-    		slapi_ch_free_string(&dn);
+    		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL );
+    		slapi_ch_free_string(&rawdn);
     		return;
     	}
+		/* Check if we should be performing strict validation. */
+		if (config_get_dn_validate_strict()) {
+			/* check that the dn is formatted correctly */
+			rc = slapi_dn_syntax_check(pb, rawdn, 1);
+			if (rc) { /* syntax check failed */
+				op_shared_log_error_access(pb, "MOD", rawdn?rawdn:"",
+								"strict: invalid dn");
+				send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+								 NULL, "invalid dn", 0, NULL);
+				slapi_ch_free((void **) &rawdn);
+				return;
+			}
+		}
+		rc = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen);
+		if (rc < 0) {
+			op_shared_log_error_access(pb, "MOD", "???", "invalid dn");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+								 NULL, "invalid dn", 0, NULL);
+			slapi_ch_free((void **) &rawdn);
+			return;
+		} else if (rc > 0) { /* if rc == 0, rawdn is passed in */
+			slapi_ch_free_string(&rawdn);
+		} else { /* rc == 0; rawdn is passed in; not null terminated */
+			*(dn + dnlen) = '\0';
+		}
 	}
 
 	LDAPDebug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", dn, 0, 0 );

+ 101 - 7
ldap/servers/slapd/modrdn.c

@@ -72,10 +72,13 @@ do_modrdn( Slapi_PBlock *pb )
 {
 	Slapi_Operation *operation;
 	BerElement	*ber;
+	char		*rawdn = NULL, *rawnewsuperior = NULL;
 	char		*dn = NULL, *newsuperior = NULL;
+	char		*rawnewrdn = NULL;
 	char		*newrdn = NULL;
 	int		err = 0, deloldrdn = 0;
 	ber_len_t	len = 0;
+	size_t		dnlen = 0;
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
 
@@ -96,7 +99,7 @@ do_modrdn( Slapi_PBlock *pb )
 	 *	}
 	 */
 
-	if ( ber_scanf( ber, "{aab", &dn, &newrdn, &deloldrdn )
+	if ( ber_scanf( ber, "{aab", &rawdn, &rawnewrdn, &deloldrdn )
 	    == LBER_ERROR ) {
 		LDAPDebug( LDAP_DEBUG_ANY,
 		    "ber_scanf failed (op=ModRDN; params=DN,newRDN,deleteOldRDN)\n",
@@ -109,25 +112,116 @@ do_modrdn( Slapi_PBlock *pb )
 	}
 
 	if ( ber_peek_tag( ber, &len ) == LDAP_TAG_NEWSUPERIOR ) {
+		/* This "len" is not used... */
 		if ( pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) {
 			LDAPDebug( LDAP_DEBUG_ANY,
 			    "got newSuperior in LDAPv2 modrdn op\n", 0, 0, 0 );
-			op_shared_log_error_access (pb, "MODRDN", dn, "decoding error");
+			op_shared_log_error_access (pb, "MODRDN",
+										rawdn?rawdn:"", "decoding error");
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			    "received newSuperior in LDAPv2 modrdn", 0, NULL );
+			slapi_ch_free_string( &rawdn );
+			slapi_ch_free_string( &rawnewrdn );
 			goto free_and_return;
 		}
-		if ( ber_scanf( ber, "a", &newsuperior ) == LBER_ERROR ) {
+		if ( ber_scanf( ber, "a", &rawnewsuperior ) == LBER_ERROR ) {
 			LDAPDebug( LDAP_DEBUG_ANY,
 			    "ber_scanf failed (op=ModRDN; params=newSuperior)\n",
 			    0, 0, 0 );
-			op_shared_log_error_access (pb, "MODRDN", dn, "decoding error");
+			op_shared_log_error_access (pb, "MODRDN", rawdn, "decoding error");
 			send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL,
 			    "unable to decode newSuperior parameter", 0, NULL );
+			slapi_ch_free_string( &rawdn );
+			slapi_ch_free_string( &rawnewrdn );
 			goto free_and_return;
 		}
 	}
 
+	/* Check if we should be performing strict validation. */
+	if (config_get_dn_validate_strict()) {
+		/* check that the dn is formatted correctly */
+		err = slapi_dn_syntax_check(pb, rawdn, 1);
+		if (err) { /* syntax check failed */
+			op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"",
+							"strict: invalid dn");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid dn", 0, NULL);
+			slapi_ch_free_string( &rawdn );
+			slapi_ch_free_string( &rawnewrdn );
+			slapi_ch_free_string( &rawnewsuperior );
+			goto free_and_return;
+		}
+		/* check that the new rdn is formatted correctly */
+		err = slapi_dn_syntax_check(pb, rawnewrdn, 1);
+		if (err) { /* syntax check failed */
+			op_shared_log_error_access(pb, "MODRDN", rawnewrdn?rawnewrdn:"", 
+							"strict: invalid new rdn");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid new rdn", 0, NULL);
+			slapi_ch_free_string( &rawdn );
+			slapi_ch_free_string( &rawnewrdn );
+			slapi_ch_free_string( &rawnewsuperior );
+			goto free_and_return;
+		}
+	}
+	err = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen);
+	if (err < 0) {
+		op_shared_log_error_access(pb, "MODRDN", rawdn?rawdn:"", "invalid dn");
+		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid dn", 0, NULL);
+		slapi_ch_free_string( &rawdn );
+		slapi_ch_free_string( &rawnewrdn );
+		slapi_ch_free_string( &rawnewsuperior );
+		goto free_and_return;
+	} else if (err > 0) {
+		slapi_ch_free((void **) &rawdn);
+	} else { /* err == 0; rawdn is passed in; not null terminated */
+		*(dn + dnlen) = '\0';
+	}
+	err = slapi_dn_normalize_ext(rawnewrdn, 0, &newrdn, &dnlen);
+	if (err < 0) {
+		op_shared_log_error_access(pb, "MODRDN", rawnewrdn?rawnewrdn:"", 
+									"invalid new rdn");
+		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+						 NULL, "invalid new rdn", 0, NULL);
+		slapi_ch_free_string( &rawnewrdn );
+		slapi_ch_free_string( &rawnewsuperior );
+		goto free_and_return;
+	} else if (err > 0) {
+		slapi_ch_free((void **) &rawnewrdn);
+	} else { /* err == 0; rawnewdn is passed in; not null terminated */
+		*(newrdn + dnlen) = '\0';
+	}
+	if (rawnewsuperior) {
+		if (config_get_dn_validate_strict()) {
+			/* check that the dn is formatted correctly */
+			err = slapi_dn_syntax_check(pb, rawnewsuperior, 1);
+			if (err) { /* syntax check failed */
+				op_shared_log_error_access(pb, "MODRDN",
+							rawnewsuperior?rawnewsuperior:"",
+							"strict: invalid new superior");
+				send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+								 NULL, "invalid new superior", 0, NULL);
+				slapi_ch_free_string( &rawnewsuperior );
+				goto free_and_return;
+			}
+		}
+		err = slapi_dn_normalize_ext(rawnewsuperior, 0, &newsuperior, &dnlen);
+		if (err < 0) {
+			op_shared_log_error_access(pb, "MODRDN",
+							rawnewsuperior?rawnewsuperior:"",
+							"invalid new superior");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid new superior", 0, NULL);
+			slapi_ch_free_string( &rawnewsuperior);
+			goto free_and_return;
+		} else if (err > 0) {
+			slapi_ch_free((void **) &rawnewsuperior);
+		} else { /* err == 0; rawnewsuperior is passed in; not terminated */
+			*(newsuperior + dnlen) = '\0';
+		}
+	}
+
 	/*
 	 * in LDAPv3 there can be optional control extensions on
 	 * the end of an LDAPMessage. we need to read them in and
@@ -153,9 +247,9 @@ do_modrdn( Slapi_PBlock *pb )
 	return;
 
 free_and_return:
-	slapi_ch_free((void **) &dn );
-	slapi_ch_free((void **) &newrdn );
-	slapi_ch_free((void **) &newsuperior );
+	slapi_ch_free_string( &dn );
+	slapi_ch_free_string( &newrdn );
+	slapi_ch_free_string( &newsuperior );
 	return;
 }
 

+ 28 - 2
ldap/servers/slapd/modutil.c

@@ -188,11 +188,37 @@ void
 slapi_mods_insert_at(Slapi_Mods *smods, LDAPMod *mod, int pos)
 {
 	int	i;
-    slapi_mods_add_one_element(smods);
-    for( i=smods->num_mods-1; i>=pos; i--)
+	Slapi_Attr a = {0};
+
+	if (NULL == mod) {
+		return;
+	}
+	slapi_mods_add_one_element(smods);
+	for( i=smods->num_mods-1; i>=pos; i--)
 	{
 	    smods->mods[i+1]= smods->mods[i];
 	}
+	slapi_attr_init(&a, mod->mod_type);
+	/* Check if the type of the to-be-added values has DN syntax or not. */
+	if (slapi_attr_is_dn_syntax_attr(&a)) {
+		int rc = 0;
+		struct berval **mbvp = NULL;
+		char *normed = NULL;
+		size_t len = 0;
+		for (mbvp = mod->mod_bvalues; mbvp && *mbvp; mbvp++) {
+			rc = slapi_dn_normalize_ext((*mbvp)->bv_val, (*mbvp)->bv_len,
+										&normed, &len);
+			if (rc > 0) {
+				slapi_ch_free((void **)&((*mbvp)->bv_val));
+			} else if (rc == 0) { 
+				/* original is passed in; not null terminated */
+				*(normed + len) = '\0';
+			}
+			(*mbvp)->bv_val = normed;
+			(*mbvp)->bv_len = len;
+		}
+	}
+	attr_done(&a);
 	smods->mods[pos]= mod;
 	smods->num_mods++;
 	smods->mods[smods->num_mods]= NULL;

+ 32 - 3
ldap/servers/slapd/passwd_extop.c

@@ -455,7 +455,9 @@ passwd_modify_extop( Slapi_PBlock *pb )
 	char		*oid = NULL;
 	char 		*bindDN = NULL;
 	char		*authmethod = NULL;
+	char		*rawdn = NULL;
 	char		*dn = NULL;
+	size_t		dnlen = 0;
 	char		*otdn = NULL;
 	char		*oldPasswd = NULL;
 	char		*newPasswd = NULL;
@@ -561,16 +563,43 @@ passwd_modify_extop( Slapi_PBlock *pb )
 	/* identify userID field by tags */
 	if (tag == LDAP_EXTOP_PASSMOD_TAG_USERID )
 	{
-		if ( ber_scanf( ber, "a", &dn) == LBER_ERROR )
+		int rc = 0;
+		if ( ber_scanf( ber, "a", &rawdn) == LBER_ERROR )
     		{
-    		slapi_ch_free_string(&dn);
+    		slapi_ch_free_string(&rawdn);
     		LDAPDebug( LDAP_DEBUG_ANY,
     		    "ber_scanf failed :{\n", 0, 0, 0 );
     		errMesg = "ber_scanf failed at userID parse.\n";
 		rc = LDAP_PROTOCOL_ERROR;
 		goto free_and_return;
     		}
-		
+
+		/* Check if we should be performing strict validation. */
+		if (config_get_dn_validate_strict()) {
+			/* check that the dn is formatted correctly */
+			rc = slapi_dn_syntax_check(pb, rawdn, 1);
+			if (rc) { /* syntax check failed */
+				op_shared_log_error_access(pb, "EXT", rawdn?rawdn:"",
+								"strict: invalid target dn");
+				errMesg = "invalid target dn.\n";
+				slapi_ch_free_string(&rawdn);
+				rc = LDAP_INVALID_SYNTAX;
+				goto free_and_return;
+			}
+		}
+		rc = slapi_dn_normalize_ext(rawdn, 0, &dn, &dnlen);
+		if (rc < 0) {
+			op_shared_log_error_access(pb, "EXT", rawdn?rawdn:"",
+								"invalid target dn");
+			slapi_ch_free_string(&rawdn);
+			errMesg = "invalid target dn.\n";
+			rc = LDAP_INVALID_SYNTAX;
+			goto free_and_return;
+		} else if (rc == 0) { /* rawdn is passed in, not terminated */
+			*(dn + dnlen) = '\0';
+		} else {
+			slapi_ch_free_string(&rawdn);
+		}
 		tag = ber_peek_tag( ber, &len);
 	} 
 	

+ 19 - 7
ldap/servers/slapd/plugin.c

@@ -268,8 +268,15 @@ slapi_register_plugin_ext(
 {
 	int ii = 0;
     int rc = 0;
-	Slapi_Entry *e = slapi_entry_alloc();
-	char *dn = slapi_ch_smprintf("cn=%s, %s", name, PLUGIN_BASE_DN);
+	Slapi_Entry *e = NULL;
+	char *dn = slapi_create_dn_string("cn=%s,%s", name, PLUGIN_BASE_DN);
+	if (NULL == dn) {
+		slapi_log_error(SLAPI_LOG_FATAL, NULL,
+					"slapi_register_plugin_ext: "
+					"failed to create plugin dn (plugin name: %s)\n", name);
+		return 1;
+	}
+	e = slapi_entry_alloc();
 	/* this function consumes dn */
 	slapi_entry_init(e, dn, NULL);
 
@@ -2461,7 +2468,7 @@ plugin_invoke_plugin_sdn (struct slapdplugin *plugin, int operation, Slapi_PBloc
  */
 char* plugin_get_dn (const struct slapdplugin *plugin)
 {
-	char *plugindn;
+	char *plugindn = NULL;
 	char *pattern = "cn=%s," PLUGIN_BASE_DN;
 
 	if (plugin == NULL)	/* old plugin that does not pass identity - use default */
@@ -2470,8 +2477,13 @@ char* plugin_get_dn (const struct slapdplugin *plugin)
 	if (plugin->plg_name == NULL)
 		return NULL;
 
-	plugindn = slapi_ch_smprintf(pattern, plugin->plg_name);
-
+	plugindn = slapi_create_dn_string(pattern, plugin->plg_name);
+	if (NULL == plugindn) {
+		slapi_log_error(SLAPI_LOG_FATAL, NULL,
+					"plugin_get_dn: failed to create plugin dn "
+					"(plugin name: %s)\n", plugin->plg_name);
+		return NULL;
+	}
 	return plugindn;
 }
 
@@ -2965,7 +2977,7 @@ slapi_set_plugin_default_config(const char *type, Slapi_Value *value)
     /* cn=plugin default config,cn=config */
     pblock_init(&pb);
     slapi_search_internal_set_pb(&pb,
-                    SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN */
+                    SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN (normalized) */
                     LDAP_SCOPE_BASE,
                     "(objectclass=*)",
                     search_attrs, /* Attrs */
@@ -3069,7 +3081,7 @@ slapi_get_plugin_default_config(char *type, Slapi_ValueSet **valueset)
     /* cn=plugin default config,cn=config */
     pblock_init(&pb);
     slapi_search_internal_set_pb(&pb,
-                    SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN */
+                    SLAPI_PLUGIN_DEFAULT_CONFIG, /* Base DN (normalized) */
                     LDAP_SCOPE_BASE,
                     "(objectclass=*)",
                     search_attrs, /* Attrs */

+ 1 - 1
ldap/servers/slapd/plugin_syntax.c

@@ -334,7 +334,7 @@ slapi_dn_syntax_check(
 	}
 
 	/* See if we need to set the error text in the pblock. */
-	if (errp != &errtext[0]) {
+	if (pb && errp != &errtext[0]) {
 		/* SLAPI_PB_RESULT_TEXT duplicates the text in slapi_pblock_set */
 		slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext );
 	}

+ 33 - 2
ldap/servers/slapd/search.c

@@ -68,6 +68,7 @@ do_search( Slapi_PBlock *pb )
 	BerElement	*ber;
 	int			i, err, attrsonly;
 	ber_int_t		scope, deref, sizelimit, timelimit;
+	char		*rawbase = NULL;
 	char		*base = NULL, *fstr = NULL;
 	struct slapi_filter	*filter = NULL;
 	char		**attrs = NULL;
@@ -80,6 +81,8 @@ do_search( Slapi_PBlock *pb )
 	int			rc = -1;
 	char		*original_base = 0;
 	char		*new_base = 0;
+	size_t		baselen = 0;
+	int strict = 0;
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
 
@@ -114,13 +117,41 @@ do_search( Slapi_PBlock *pb )
 	 */
 
 	/* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
-	if ( ber_scanf( ber, "{aiiiib", &base, &scope, &deref, &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ){
-		slapi_ch_free((void**)&base );
+	if ( ber_scanf( ber, "{aiiiib", &rawbase, &scope, &deref, &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ){
+		slapi_ch_free((void**)&rawbase );
 		log_search_access (pb, "???", -1, "???", "decoding error");
 		send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL );
 		return;
 	}
 
+	/* Check if we should be performing strict validation. */
+	strict = config_get_dn_validate_strict();
+	if (strict) {
+		/* check that the dn is formatted correctly */
+		rc = slapi_dn_syntax_check(pb, rawbase, 1);
+		if (rc) { /* syntax check failed */
+			op_shared_log_error_access(pb, "SRCH", 
+							rawbase?rawbase:"", "strict: invalid dn");
+			send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid dn", 0, NULL);
+			slapi_ch_free((void **) &rawbase);
+			return;
+		}
+	}
+	rc = slapi_dn_normalize_ext(rawbase, 0, &base, &baselen);
+	if (rc < 0) {
+		op_shared_log_error_access(pb, "SRCH", 
+							rawbase?rawbase:"", "invalid dn");
+		send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, 
+							 NULL, "invalid dn", 0, NULL);
+		slapi_ch_free((void **) &rawbase);
+		return;
+	} else if (rc > 0) { /* if rc == 0, rawbase is passed in */
+		slapi_ch_free((void **) &rawbase);
+	} else { /* rc == 0; rawbase is passed in; not null terminated */
+		*(base + baselen) = '\0';
+	}
+
 	/*
 	 * ignore negative time and size limits since they make no sense
 	 */

+ 2 - 2
ldap/servers/slapd/slap.h

@@ -575,9 +575,9 @@ typedef int (*SyntaxEnumFunc)(char **names, Slapi_PluginDesc *plugindesc,
 struct slapi_dn
 {
     unsigned char flag;
-    const char *dn; /* DN */
+    const char *dn; /* DN [normalized] */
     const char *ndn; /* Case Normalised DN */
-    int ndn_len; /* normalize dn len */
+    int ndn_len; /* normalized dn length */
 };
 
 /* 

+ 61 - 6
ldap/servers/slapd/slapi-plugin.h

@@ -3025,27 +3025,73 @@ int slapi_rdn_partial_dup(Slapi_RDN *from, Slapi_RDN **to, int idx);
  * utility routines for dealing with DNs
  */
 /**
- * Normalizes a DN.
+ * Does nothing. (DEPRECATED)
  *
  * \param dn The DN to normalize.
  * \return The normalized DN.
- * \deprecated Use slapi_sdn_get_ndn() instead.
+ * \deprecated Use slapi_dn_normalized_ext.
  */
 char *slapi_dn_normalize( char *dn );
 
 /**
- * Normalizes a portion of a DN value.
+ * Does nothing. (DEPRECATED)
  *
  * \param dn The DN value to normalize.
  * \param end Pointer to the end of what will be normalized from the DN
  *        value in \c dn.  If this parameter is \c NULL, the DN value
  *        will be wholly normalized.
- * \return A pointer to the end of the DN that has been normalized.
- * \warning This function does not null-terminate the string.  Use this
- *          function only if you know what you are doing.
+ * \return The normalized DN.
+ * \deprecated Use slapi_dn_normalized_ext.
  */
 char *slapi_dn_normalize_to_end( char *dn, char *end );
 
+/**
+ * Normalizes a DN.
+ *
+ * \param src The DN to normalize.
+ * \param src_len The length of src DN to normalize. If 0 is given, strlen(src) is used.
+ * \param dest The normalized DN.
+ * \param dest The length of the normalized DN dest.
+ * \return \c 0 if successful. The dest DN is normalized in line. Caller must not free dest.
+ * \return \c 1 if successful. The dest DN is allocated.  Caller must free dest.
+ * \return \c -1 if an error occurs (for example, if the src DN cannot be normalized)
+ */
+int slapi_dn_normalize_ext(char *src, size_t src_len, char **dest, size_t *dest_len);
+
+/**
+ * Normalizes a DN (in lower-case characters).
+ *
+ * \param src The DN to normalize.
+ * \param src_len The length of src DN to normalize. If 0 is given, strlen(src) is used internally.
+ * \param dest The normalized DN with the cases lowered.
+ * \param dest_len The length of the normalized DN dest.
+ * \return \c 0 if successful. The dest DN is normalized in line. Caller must not free dest.  The string is NOT NULL terminated.
+ * \return \c 1 if successful. The dest DN is allocated.  Caller must free dest.
+ * \return \c -1 if an error occurs (for example, if src DN cannot be normalized)
+ */
+int slapi_dn_normalize_case_ext(char *src, size_t src_len, char **dest, size_t *dest_len);
+
+/**
+ * Generate a valid DN string.
+ *
+ * \param fmt The format used to generate a DN string.
+ * \param ... The arguments to generate a DN string.
+ * \return A pointer to the generated DN.  The 
+ * \return NULL if failed.
+ * \note When a DN needs to be internally created, this function is supposed to be called.  This function allocates the enough memory for the normalized DN and returns it filled with the normalized DN.
+ */
+char *slapi_create_dn_string(const char *fmt, ...);
+
+/**
+ * Generates a valid DN string (in lower-case characters).
+ *
+ * \param fmt The format used to generate a DN string.
+ * \param ... The arguments to generate a DN string.
+ * \return A pointer to the generated DN.
+ * \return NULL if failed.
+ */
+char *slapi_create_dn_string_case(const char *fmt, ...);
+
 /**
  * Converts a DN to lowercase.
  *
@@ -3331,6 +3377,15 @@ int slapi_attr_get_oid_copy( const Slapi_Attr *attr, char **oidp );
  */
 int slapi_attr_get_syntax_oid_copy( const Slapi_Attr *a, char **oidp );
 
+/**
+ * Checks if the attribute uses a DN syntax or not.
+ *
+ * \param attr The attribute to be checked.
+ * \return \c non 0 if the attribute uses a DN syntax.
+ * \return \c 0 if the attribute does not use a DN syntax.
+ */
+int slapi_attr_is_dn_syntax_attr(Slapi_Attr *attr);
+
 /**
  * Get the flags associated with a particular attribute.
  *

+ 2 - 0
ldap/servers/slapd/slapi-private.h

@@ -364,6 +364,7 @@ const CSN *value_get_csn( const Slapi_Value *value, CSNType t );
 const CSNSet *value_get_csnset ( const Slapi_Value *value);
 Slapi_Value *value_remove_csn( Slapi_Value *value, CSNType t);
 int value_contains_csn( const Slapi_Value *value, CSN *csn);
+int value_normalize_value(Slapi_Value *value);
 
 /* dn.c */
 /* this functions should only be used for dns allocated on the stack */
@@ -820,6 +821,7 @@ void valuearray_add_value_fast(Slapi_Value ***vals, Slapi_Value *addval, int nva
 void valuearray_add_valuearray( Slapi_Value ***vals, Slapi_Value **addvals, PRUint32 flags );
 void valuearray_add_valuearray_fast( Slapi_Value ***vals, Slapi_Value **addvals, int nvals, int naddvals, int *maxvals, int exact, int passin );
 int valuearray_find(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v);
+int valuearray_normalize_value(Slapi_Value **vals);
 
 
 /******************************************************************************

+ 2 - 1
ldap/servers/slapd/snmp_collator.c

@@ -873,7 +873,8 @@ loadConfigStats() {
 static Slapi_Entry *
 getConfigEntry( Slapi_Entry **e ) {
         Slapi_DN        sdn;
-                                                                                                                          
+
+        /* SNMP_CONFIG_DN: no need to be normalized */
         slapi_sdn_init_dn_byref( &sdn, SNMP_CONFIG_DN );
         slapi_search_internal_get_entry( &sdn, NULL, e,
                         plugin_get_default_component_id());

+ 30 - 20
ldap/servers/slapd/task.c

@@ -60,13 +60,13 @@ static int shutting_down = 0;
 /***********************************
  * Private Defines
  ***********************************/
-#define TASK_BASE_DN      "cn=tasks, cn=config"
-#define TASK_IMPORT_DN    "cn=import, cn=tasks, cn=config"
-#define TASK_EXPORT_DN    "cn=export, cn=tasks, cn=config"
-#define TASK_BACKUP_DN    "cn=backup, cn=tasks, cn=config"
-#define TASK_RESTORE_DN   "cn=restore, cn=tasks, cn=config"
-#define TASK_INDEX_DN     "cn=index, cn=tasks, cn=config"
-#define TASK_UPGRADEDB_DN "cn=upgradedb, cn=tasks, cn=config"
+#define TASK_BASE_DN      "cn=tasks,cn=config"
+#define TASK_IMPORT_DN    "cn=import,cn=tasks,cn=config"
+#define TASK_EXPORT_DN    "cn=export,cn=tasks,cn=config"
+#define TASK_BACKUP_DN    "cn=backup,cn=tasks,cn=config"
+#define TASK_RESTORE_DN   "cn=restore,cn=tasks,cn=config"
+#define TASK_INDEX_DN     "cn=index,cn=tasks,cn=config"
+#define TASK_UPGRADEDB_DN "cn=upgradedb,cn=tasks,cn=config"
 
 #define TASK_LOG_NAME           "nsTaskLog"
 #define TASK_STATUS_NAME        "nsTaskStatus"
@@ -403,9 +403,12 @@ int slapi_task_register_handler(const char *name, dseCallbackFn func)
     int ret = -1;
     int x;
 
-    dn = slapi_ch_smprintf("cn=%s, %s", name, TASK_BASE_DN);
-    if (dn == NULL) {
-        goto out;
+    dn = slapi_create_dn_string("cn=%s,%s", name, TASK_BASE_DN);
+    if (NULL == dn) {
+        LDAPDebug1Arg( LDAP_DEBUG_ANY,
+                       "slapi_task_register_handler: "
+                       "failed to create task dn for %s\n", name);
+        return ret;
     }
 
     pb = slapi_pblock_new();
@@ -458,9 +461,7 @@ int slapi_task_register_handler(const char *name, dseCallbackFn func)
     ret = 0;
 
 out:
-    if (dn) {
-        slapi_ch_free((void **)&dn);
-    }
+    slapi_ch_free_string(&dn);
     if (pb) {
         slapi_pblock_destroy(pb);
     }
@@ -487,18 +488,27 @@ void slapi_task_set_cancel_fn(Slapi_Task *task, TaskCallbackFn func)
  ***********************************/
 /* create a new task, fill in DN, and setup modify callback */
 static Slapi_Task *
-new_task(const char *dn)
+new_task(const char *rawdn)
 {
-    Slapi_Task *task = (Slapi_Task *)slapi_ch_calloc(1, sizeof(Slapi_Task));
+    Slapi_Task *task = NULL;
+    char *dn = NULL;
+
+    if (rawdn == NULL) {
+        return NULL;
+    }
 
-    if (task == NULL)
+    dn = slapi_create_dn_string("%s", rawdn);
+    if (NULL == dn) {
+        LDAPDebug1Arg(LDAP_DEBUG_ANY,
+                      "new_task failed: invalid task dn: %s\n", rawdn);
         return NULL;
+    }
+    task = (Slapi_Task *)slapi_ch_calloc(1, sizeof(Slapi_Task));
     PR_Lock(global_task_lock);
     task->next = global_task_list;
     global_task_list = task;
     PR_Unlock(global_task_lock);
-
-    task->task_dn = slapi_ch_strdup(dn);
+    task->task_dn = dn;
     task->task_state = SLAPI_TASK_SETUP;
     task->task_flags = SLAPI_TASK_RUNNING_AS_TASK;
     task->destructor = NULL;
@@ -511,8 +521,8 @@ new_task(const char *dn)
     /* don't add entries under this one */
 #if 0
     /* don't know why, but this doesn't work.  it makes the current add
- *      * operation fail. :(
- *           */
+     * operation fail. :(
+     */
     slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, dn,
                                    LDAP_SCOPE_SUBTREE, "(objectclass=*)", task_deny, NULL);
 #endif

+ 1 - 1
ldap/servers/slapd/tools/dbscan.c

@@ -434,7 +434,7 @@ static ID id_stored_to_internal(char* b)
 static void id_internal_to_stored(ID i,char *b)
 {
     if ( sizeof(ID) > 4 ) {
-        memset (b+4, 0, sizeof(ID)-4);
+        (void)memset (b+4, 0, sizeof(ID)-4);
     }
 
     b[0] = (char)(i >> 24);

+ 1 - 0
ldap/servers/slapd/tools/ldclt/ldclt.h

@@ -741,6 +741,7 @@ extern char	*dnFromMessage (thread_context *tttctx, LDAPMessage *res);
 extern int	 doAddEntry    (thread_context *tttctx);
 extern int	 doAttrReplace (thread_context *tttctx);	/*JLS 21-11-00*/
 extern int	 doAttrFileReplace (thread_context	*tttctx);
+
 extern int	 doBindOnly    (thread_context *tttctx);	/*JLS 04-05-01*/
 extern int	 doDeleteEntry (thread_context *tttctx);
 extern int	 doExactSearch (thread_context *tttctx);

+ 79 - 19
ldap/servers/slapd/util.c

@@ -335,8 +335,9 @@ int slapi_entry2mods (const Slapi_Entry *e, char **dn, LDAPMod ***attrs)
 *
 *  normalize_mods2bvals
 *
-*     
-*  
+*  Return value: normalized mods
+*  The values/bvals are all duplicated in this function since
+*  the normalized mods are freed with ldap_mods_free by the caller.
 *
 *******************************************************************************/
 
@@ -360,6 +361,18 @@ normalize_mods2bvals(const LDAPMod **mods)
 
     for (w = 0; mods[w] != NULL; w++) 
     {
+        Slapi_Attr a = {0};
+        slapi_attr_init(&a, mods[w]->mod_type);
+        int is_dn_syntax = 0;
+        struct berval **normmbvp = NULL;
+
+        /* Check if the type of the to-be-added values has DN syntax 
+         * or not. */
+        if (slapi_attr_is_dn_syntax_attr(&a)) {
+            is_dn_syntax = 1;
+        }
+        attr_done(&a);
+
         /* copy each mod into a normalized modbvalue */
         normalized_mods[w] = (LDAPMod *) slapi_ch_calloc(1, sizeof(LDAPMod));
         normalized_mods[w]->mod_op = mods[w]->mod_op | LDAP_MOD_BVALUES;
@@ -397,32 +410,79 @@ normalize_mods2bvals(const LDAPMod **mods)
        
         if (mods[w]->mod_op & LDAP_MOD_BVALUES) 
         {
-            for (x = 0; mods[w]->mod_bvalues != NULL &&
-                    mods[w]->mod_bvalues[x] != NULL; x++) 
+            struct berval **mbvp = NULL;
+
+            for (mbvp = mods[w]->mod_bvalues,
+                 normmbvp = normalized_mods[w]->mod_bvalues; 
+                 mbvp && *mbvp; mbvp++, normmbvp++)
             {
-                normalized_mods[w]->mod_bvalues[x] = ber_bvdup(mods[w]->mod_bvalues[x]);
+                if (is_dn_syntax) {
+                    int rc = 0;
+                    char *normed = NULL;
+                    size_t dnlen = 0;
+
+                    rc = slapi_dn_normalize_ext((*mbvp)->bv_val, 
+                                                (*mbvp)->bv_len,
+                                                &normed, &dnlen);
+                    if (rc < 0) { /* normalization failed; use the original */
+                        *normmbvp = ber_bvdup(*mbvp);
+                    } else if (rc == 0) { /* if rc == 0, value is passed in */
+                        *(normed + dnlen) = '\0';
+                        *normmbvp = ber_bvdup(*mbvp);
+                    } else {
+                        (*normmbvp)->bv_val = normed;
+                        (*normmbvp)->bv_len = dnlen;
+                    }
+                } else {
+                    *normmbvp = ber_bvdup(*mbvp);
+                }
             }
         } else {
-            for (x = 0; mods[w]->mod_values != NULL &&
-                    mods[w]->mod_values[x] != NULL; x++) 
+            char **mvp = NULL;
+
+            for (mvp = mods[w]->mod_values, 
+                 normmbvp = normalized_mods[w]->mod_bvalues; 
+                 mvp && *mvp; mvp++, normmbvp++)
             {
-                normalized_mods[w]->mod_bvalues[ x ] = (struct berval *)
-                    slapi_ch_calloc(1, sizeof(struct berval));
-		
-                vlen = strlen(mods[w]->mod_values[x]);
-                normalized_mods[w]->mod_bvalues[ x ]->bv_val =
-                    slapi_ch_calloc(vlen + 1, sizeof(char));
-                memcpy(normalized_mods[w]->mod_bvalues[ x ]->bv_val,
-                         mods[w]->mod_values[x], vlen);
-                normalized_mods[w]->mod_bvalues[ x ]->bv_val[vlen] = '\0';
-                normalized_mods[w]->mod_bvalues[ x ]->bv_len = vlen;
+                *normmbvp = 
+                    (struct berval *)slapi_ch_malloc(sizeof(struct berval));
+        
+                vlen = strlen(*mvp);
+
+                if (is_dn_syntax) {
+                    int rc = 0;
+                    char *normed = NULL;
+                    size_t dnlen = 0;
+                    rc = slapi_dn_normalize_ext(*mvp, vlen,
+                                                &normed, &dnlen);
+                    if (rc < 0) { /* normalization failed; use the original */
+                        (*normmbvp)->bv_val = slapi_ch_malloc(vlen + 1);
+                        memcpy((*normmbvp)->bv_val, *mvp, vlen);
+                        (*normmbvp)->bv_val[vlen] = '\0';
+                        (*normmbvp)->bv_len = vlen;
+                    } else if (rc == 0) { /* if rc == 0, value is passed in */
+                        *(normed + dnlen) = '\0';
+                        (*normmbvp)->bv_val = slapi_ch_strdup(normed);
+                        (*normmbvp)->bv_len = dnlen;
+                    } else {
+                        (*normmbvp)->bv_val = normed;
+                        (*normmbvp)->bv_len = dnlen;
+                    }
+                } else {
+                    (*normmbvp)->bv_val = slapi_ch_malloc(vlen + 1);
+                    memcpy((*normmbvp)->bv_val, *mvp, vlen);
+                    (*normmbvp)->bv_val[vlen] = '\0';
+                    (*normmbvp)->bv_len = vlen;
+                }
             }
         }
 
+        PR_ASSERT(normmbvp - normalized_mods[w]->mod_bvalues <= num_values);
+
         /* don't forget to null terminate it */
-        if (num_values > 0) 
+        if (num_values > 0)
         {
-            normalized_mods[w]->mod_bvalues[ x ] = NULL;
+            *normmbvp = NULL;
         }
     }
     

+ 26 - 0
ldap/servers/slapd/value.c

@@ -551,3 +551,29 @@ value_dump( const Slapi_Value *value, const char *text)
 }
 #endif
 
+int
+value_normalize_value(Slapi_Value *value)
+{
+	char *normval = NULL;
+	size_t len = 0;
+	int rc = 0;
+
+	if (NULL == value) {
+		return 0;
+	}
+
+	rc = slapi_dn_normalize_ext(value->bv.bv_val, value->bv.bv_len,
+								&normval, &len);
+	if (rc < 0) {
+		return 1;
+	} else if (rc > 0) {	/* if rc == 0, the original value is passed in */
+		slapi_ch_free_string(&value->bv.bv_val);
+	} else { /* rc == 0; original is passed in; not null terminated */
+		/* since bvalue, no need to terminate with null, tho */
+		*(normval + len) = '\0';
+	}
+	value->bv.bv_val = normval;
+	value->bv.bv_len = len;
+
+	return 0;
+}

+ 14 - 0
ldap/servers/slapd/valueset.c

@@ -1437,3 +1437,17 @@ valueset_update_csn_for_valuearray(Slapi_ValueSet *vs, const Slapi_Attr *a, Slap
 		*valuesupdated= vaf_valuesupdated.va;
 	}
 }
+
+int
+valuearray_normalize_value(Slapi_Value **vals)
+{
+	int rc = 0;
+	Slapi_Value **vp = NULL;
+
+	for (vp = vals; vp && *vp; vp++) {
+		rc |= value_normalize_value(*vp);
+	}
+
+	return rc;
+}
+

Some files were not shown because too many files changed in this diff