浏览代码

implement slapi_ldap_explode_dn and slapi_ldap_explode_rdn

The DS has some problems with the openldap versions of these functions:
1) They are deprecated - should use the str2[r]dn and [r]dn2str and the
bv versions of those functions instead
2) They escape utf-8 and other values in the strings - the mozldap functions
do not do this
3) They handle double quoted strings, but they remove the quotes - our
code expects the quotes to be left in place
Until we fix our DN handling, and get rid of the double quoted DNs, we just
use the mozldap versions of these functions.
Rich Megginson 15 年之前
父节点
当前提交
8a94317513

+ 2 - 2
ldap/servers/plugins/acl/acl.c

@@ -172,9 +172,9 @@ static int check_rdn_access( Slapi_PBlock *pb, Slapi_Entry *e, char *dn,
 	int retCode = LDAP_INSUFFICIENT_ACCESS;
 	int retCode = LDAP_INSUFFICIENT_ACCESS;
 	int i;
 	int i;
 
 
-	if ( (dns = ldap_explode_dn( dn, 0 )) != NULL ) {
+	if ( (dns = slapi_ldap_explode_dn( dn, 0 )) != NULL ) {
 
 
-		if ( (rdns = ldap_explode_rdn( dns[0], 0 )) != NULL ) {
+		if ( (rdns = slapi_ldap_explode_rdn( dns[0], 0 )) != NULL ) {
 	
 	
 			for ( i = 0; rdns[i] != NULL; i++ ) {
 			for ( i = 0; rdns[i] != NULL; i++ ) {
 				char *type;			
 				char *type;			

+ 2 - 2
ldap/servers/plugins/acl/aclutil.c

@@ -556,8 +556,8 @@ aclutil_expand_paramString ( char *str, Slapi_Entry *e )
 	char		*buf = NULL;
 	char		*buf = NULL;
 
 
 
 
-	e_dns = ldap_explode_dn ( slapi_entry_get_ndn ( e ), 0 );
-	a_dns = ldap_explode_dn ( str, 0 );
+	e_dns = slapi_ldap_explode_dn ( slapi_entry_get_ndn ( e ), 0 );
+	a_dns = slapi_ldap_explode_dn ( str, 0 );
 
 
 	i = 0;
 	i = 0;
 	ncomponents = 0;
 	ncomponents = 0;

+ 2 - 2
ldap/servers/plugins/referint/referint.c

@@ -375,7 +375,7 @@ _update_one_per_mod(const char *entryDN, /* DN of the searched entry */
         Slapi_Value *v = NULL;
         Slapi_Value *v = NULL;
 
 
         /* need to put together rdn into a dn */
         /* need to put together rdn into a dn */
-        dnParts = ldap_explode_dn( origDN, 0 );
+        dnParts = slapi_ldap_explode_dn( origDN, 0 );
         if (NULL == newRDN) {
         if (NULL == newRDN) {
             newRDN = dnParts[0];
             newRDN = dnParts[0];
         }
         }
@@ -553,7 +553,7 @@ _update_all_per_mod(const char *entryDN, /* DN of the searched entry */
         Slapi_Value *v = NULL;
         Slapi_Value *v = NULL;
 
 
         /* need to put together rdn into a dn */
         /* need to put together rdn into a dn */
-        dnParts = ldap_explode_dn( origDN, 0 );
+        dnParts = slapi_ldap_explode_dn( origDN, 0 );
         if (NULL == newRDN) {
         if (NULL == newRDN) {
             newRDN = dnParts[0];
             newRDN = dnParts[0];
         }
         }

+ 1 - 1
ldap/servers/plugins/replication/winsync-plugin.h

@@ -371,7 +371,7 @@ test_winsync_get_new_ds_user_dn_cb(void *cbdata, const Slapi_Entry *rawentry,
                     "--> test_winsync_get_new_ds_user_dn_cb -- old dn [%s] -- begin\n",
                     "--> test_winsync_get_new_ds_user_dn_cb -- old dn [%s] -- begin\n",
                     *new_dn_string);
                     *new_dn_string);
 
 
-    rdns = ldap_explode_dn(*new_dn_string, 0);
+    rdns = slapi_ldap_explode_dn(*new_dn_string, 0);
     if (!rdns || !rdns[0]) {
     if (!rdns || !rdns[0]) {
         ldap_value_free(rdns);
         ldap_value_free(rdns);
         return;
         return;

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

@@ -867,8 +867,8 @@ int slapi_sdn_suffix_cmp(
     size_t len = 0;
     size_t len = 0;
     char *p, *ndnstr;
     char *p, *ndnstr;
 
 
-    rdns1 = ldap_explode_dn(slapi_sdn_get_ndn(left), 0);
-    rdns2 = ldap_explode_dn(slapi_sdn_get_ndn(right), 0);
+    rdns1 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(left), 0);
+    rdns2 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(right), 0);
 
 
     for(count1 = 0; rdns1[count1]!=NULL; count1++){
     for(count1 = 0; rdns1[count1]!=NULL; count1++){
     }
     }

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

@@ -1497,7 +1497,7 @@ upgradedn_producer(void *param)
                         workdn = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
                         workdn = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
                         isentrydn = 1;
                         isentrydn = 1;
                     }
                     }
-                    rdns = ldap_explode_dn(workdn, 0);
+                    rdns = slapi_ldap_explode_dn(workdn, 0);
                     skipit = 0;
                     skipit = 0;
                     for (rdnsp = rdns; rdnsp && *rdnsp; rdnsp++) {
                     for (rdnsp = rdns; rdnsp && *rdnsp; rdnsp++) {
                         valueptr = PL_strchr(*rdnsp, '=');
                         valueptr = PL_strchr(*rdnsp, '=');

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

@@ -701,7 +701,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
         {
         {
             char **rdns;
             char **rdns;
             int i;
             int i;
-            if ( (rdns = ldap_explode_rdn( slapi_sdn_get_dn(&dn_newrdn), 0 )) != NULL ) 
+            if ( (rdns = slapi_ldap_explode_rdn( slapi_sdn_get_dn(&dn_newrdn), 0 )) != NULL ) 
             {
             {
                 for ( i = 0; rdns[i] != NULL; i++ ) 
                 for ( i = 0; rdns[i] != NULL; i++ ) 
                 {
                 {
@@ -1202,10 +1202,10 @@ moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Sla
     int baddn = 0; /* set to true if could not parse dn */
     int baddn = 0; /* set to true if could not parse dn */
     int badrdn = 0; /* set to true if could not parse rdn */
     int badrdn = 0; /* set to true if could not parse rdn */
     dn = slapi_ch_strdup(olddn);
     dn = slapi_ch_strdup(olddn);
-    dns = ldap_explode_dn( dn, 0 );
+    dns = slapi_ldap_explode_dn( dn, 0 );
     if ( dns != NULL )
     if ( dns != NULL )
     {
     {
-        rdns = ldap_explode_rdn( dns[0], 0 );
+        rdns = slapi_ldap_explode_rdn( dns[0], 0 );
         if ( rdns != NULL )
         if ( rdns != NULL )
         {
         {
             for ( i = 0; rdns[i] != NULL; i++ )
             for ( i = 0; rdns[i] != NULL; i++ )
@@ -1254,7 +1254,7 @@ moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Sla
     /*
     /*
      * add new RDN values to the entry (non-normalized)
      * add new RDN values to the entry (non-normalized)
      */
      */
-    rdns = ldap_explode_rdn( newrdn, 0 );
+    rdns = slapi_ldap_explode_rdn( newrdn, 0 );
     if ( rdns != NULL )
     if ( rdns != NULL )
     {
     {
         for ( i = 0; rdns[i] != NULL; i++ )
         for ( i = 0; rdns[i] != NULL; i++ )
@@ -1434,7 +1434,7 @@ moddn_rename_child_entry(
      * excluding the old parent entry DN, and adding the new
      * excluding the old parent entry DN, and adding the new
      * superior entry DN.
      * superior entry DN.
      *
      *
-     * ldap_explode_dn is probably a bit slow, but it knows about
+     * slapi_ldap_explode_dn is probably a bit slow, but it knows about
      * DN escaping which is pretty complicated, and we wouldn't
      * DN escaping which is pretty complicated, and we wouldn't
      * want to reimplement that here.
      * want to reimplement that here.
      *
      *
@@ -1449,7 +1449,7 @@ moddn_rename_child_entry(
     int i;
     int i;
 
 
     olddn = slapi_entry_get_dn(ec->ep_entry);
     olddn = slapi_entry_get_dn(ec->ep_entry);
-    olddns = ldap_explode_dn( olddn, 0 );
+    olddns = slapi_ldap_explode_dn( olddn, 0 );
     for(;olddns[olddncomps]!=NULL;olddncomps++);
     for(;olddns[olddncomps]!=NULL;olddncomps++);
     for(i=0;i<olddncomps-parentdncomps;i++)
     for(i=0;i<olddncomps-parentdncomps;i++)
     {
     {
@@ -1540,7 +1540,7 @@ moddn_rename_children(
      * Break down the parent entry dn into its components.
      * Break down the parent entry dn into its components.
      */
      */
     {
     {
-        char **parentdns = ldap_explode_dn( slapi_sdn_get_dn(dn_parentdn), 0 );
+        char **parentdns = slapi_ldap_explode_dn( slapi_sdn_get_dn(dn_parentdn), 0 );
         if (parentdns)
         if (parentdns)
         {
         {
             for(;parentdns[parentdncomps]!=NULL;parentdncomps++);
             for(;parentdns[parentdncomps]!=NULL;parentdncomps++);
@@ -1555,7 +1555,7 @@ moddn_rename_children(
     /*
     /*
      * Break down the new superior entry dn into its components.
      * Break down the new superior entry dn into its components.
      */    
      */    
-    newsuperiordns = ldap_explode_dn( slapi_sdn_get_dn(dn_newsuperiordn), 0 );
+    newsuperiordns = slapi_ldap_explode_dn( slapi_sdn_get_dn(dn_newsuperiordn), 0 );
     if (newsuperiordns)
     if (newsuperiordns)
     {
     {
         for(;newsuperiordns[newsuperiordncomps]!=NULL;newsuperiordncomps++);
         for(;newsuperiordns[newsuperiordncomps]!=NULL;newsuperiordncomps++);

+ 6 - 6
ldap/servers/slapd/back-ldif/modrdn.c

@@ -170,8 +170,8 @@ ldif_back_modrdn( Slapi_PBlock *pb )
   mods = NULL;
   mods = NULL;
   bvps[0] = &bv;
   bvps[0] = &bv;
   bvps[1] = NULL;
   bvps[1] = NULL;
-  if ( (dns = ldap_explode_dn( dn, 0 )) != NULL ) {
-    if ( (rdns = ldap_explode_rdn( dns[0], 0 )) != NULL ) {
+  if ( (dns = slapi_ldap_explode_dn( dn, 0 )) != NULL ) {
+    if ( (rdns = slapi_ldap_explode_rdn( dns[0], 0 )) != NULL ) {
       for ( i = 0; rdns[i] != NULL; i++ ) {
       for ( i = 0; rdns[i] != NULL; i++ ) {
 
 
 	/* Delete from entry attributes */
 	/* Delete from entry attributes */
@@ -179,23 +179,23 @@ ldif_back_modrdn( Slapi_PBlock *pb )
 	  ldif_add_mod( &mods, LDAP_MOD_DELETE, type, bvps );
 	  ldif_add_mod( &mods, LDAP_MOD_DELETE, type, bvps );
 	}
 	}
       }
       }
-      ldap_value_free( rdns );
+      slapi_ldap_value_free( rdns );
     }
     }
-    ldap_value_free( dns );
+    slapi_ldap_value_free( dns );
   }
   }
   if ( dns == NULL || rdns == NULL ) {
   if ( dns == NULL || rdns == NULL ) {
     slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
     slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
     goto error_return;
     goto error_return;
   }
   }
   /* Add new rdn values to the entry */
   /* Add new rdn values to the entry */
-  if ( (rdns = ldap_explode_rdn( newrdn, 0 )) != NULL ) {
+  if ( (rdns = slapi_ldap_explode_rdn( newrdn, 0 )) != NULL ) {
     for ( i = 0; rdns[i] != NULL; i++ ) {
     for ( i = 0; rdns[i] != NULL; i++ ) {
       /* Add to entry */
       /* Add to entry */
       if ( rdn2typval( rdns[i], &type, &bv ) == 0 ) {
       if ( rdn2typval( rdns[i], &type, &bv ) == 0 ) {
 	ldif_add_mod( &mods, LDAP_MOD_ADD, type, bvps );
 	ldif_add_mod( &mods, LDAP_MOD_ADD, type, bvps );
       }
       }
     }
     }
-    ldap_value_free( rdns );
+    slapi_ldap_value_free( rdns );
   } else {
   } else {
     slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
     slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
     goto error_return;
     goto error_return;

+ 2 - 2
ldap/servers/slapd/dse.c

@@ -1184,8 +1184,8 @@ entry_dn_cmp( caddr_t d1, caddr_t d2 )
 		{
 		{
 			/* put fewer rdns before more rdns */
 			/* put fewer rdns before more rdns */
 			int rc = 0;
 			int rc = 0;
-			char **dnlist1 = ldap_explode_dn(slapi_sdn_get_ndn(dn1), 0);
-			char **dnlist2 = ldap_explode_dn(slapi_sdn_get_ndn(dn2), 0);
+			char **dnlist1 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(dn1), 0);
+			char **dnlist2 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(dn2), 0);
 			int len1 = 0;
 			int len1 = 0;
 			int len2 = 0;
 			int len2 = 0;
 			if (dnlist1)
 			if (dnlist1)

+ 4 - 4
ldap/servers/slapd/entry.c

@@ -2873,9 +2873,9 @@ slapi_entry_rdn_values_present( const Slapi_Entry *e )
 
 
 	/* JCM Use the Slapi_RDN code */
 	/* JCM Use the Slapi_RDN code */
 	rc = 1;
 	rc = 1;
-	if ( (dns = ldap_explode_dn( slapi_entry_get_dn_const(e), 0 )) != NULL )
+	if ( (dns = slapi_ldap_explode_dn( slapi_entry_get_dn_const(e), 0 )) != NULL )
 	{
 	{
-		if ( (rdns = ldap_explode_rdn( dns[0], 0 )) != NULL )
+		if ( (rdns = slapi_ldap_explode_rdn( dns[0], 0 )) != NULL )
 		{
 		{
 			for ( i = 0; rdns[i] != NULL; i++ )
 			for ( i = 0; rdns[i] != NULL; i++ )
 			{
 			{
@@ -2934,10 +2934,10 @@ slapi_entry_add_rdn_values( Slapi_Entry *e )
 
 
     /* JCM Use the Slapi_RDN code */
     /* JCM Use the Slapi_RDN code */
     /* make sure RDN values are also in the entry */
     /* make sure RDN values are also in the entry */
-    if ( (dns = ldap_explode_dn( dn, 0 )) == NULL ) {
+    if ( (dns = slapi_ldap_explode_dn( dn, 0 )) == NULL ) {
         return( LDAP_INVALID_DN_SYNTAX );
         return( LDAP_INVALID_DN_SYNTAX );
     }
     }
-    if ( (rdns = ldap_explode_rdn( dns[0], 0 )) == NULL ) {
+    if ( (rdns = slapi_ldap_explode_rdn( dns[0], 0 )) == NULL ) {
         slapi_ldap_value_free( dns );
         slapi_ldap_value_free( dns );
         return( LDAP_INVALID_DN_SYNTAX );
         return( LDAP_INVALID_DN_SYNTAX );
     }
     }

+ 2 - 2
ldap/servers/slapd/filterentry.c

@@ -415,13 +415,13 @@ dn2attrs(const char *dn)
 {
 {
     int rc= 0;
     int rc= 0;
     Slapi_Attr* dnAttrs = NULL;
     Slapi_Attr* dnAttrs = NULL;
-    char** rdns = ldap_explode_dn (dn, 0);
+    char** rdns = slapi_ldap_explode_dn (dn, 0);
     if (rdns)
     if (rdns)
     {
     {
         char** rdn = rdns;
         char** rdn = rdns;
         for (; !rc && *rdn; ++rdn)
         for (; !rc && *rdn; ++rdn)
         {
         {
-            char** avas = ldap_explode_rdn (*rdn, 0);
+            char** avas = slapi_ldap_explode_rdn (*rdn, 0);
             if (avas)
             if (avas)
             {
             {
                 char** ava = avas;
                 char** ava = avas;

+ 230 - 0
ldap/servers/slapd/ldaputil.c

@@ -34,6 +34,47 @@
  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  * Copyright (C) 2005 Red Hat, Inc.
  * Copyright (C) 2005 Red Hat, Inc.
  * All rights reserved.
  * All rights reserved.
+ *
+ * mozldap_ldap_explode, mozldap_ldap_explode_dn, mozldap_ldap_explode_rdn
+ * are from the file ldap/libraries/libldap/getdn.c in the Mozilla LDAP C SDK
+ *
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * 
+ * The contents of this file are subject to the Mozilla Public License Version 
+ * 1.1 (the "License"); you may not use this file except in compliance with 
+ * the License. You may obtain a copy of the License at 
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ * 
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ * 
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ * 
+ * Contributor(s):
+ * 
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ * 
+ *  Copyright (c) 1994 Regents of the University of Michigan.
+ *  All rights reserved.
+ *
  * END COPYRIGHT BLOCK **/
  * END COPYRIGHT BLOCK **/
 
 
 #ifdef HAVE_CONFIG_H
 #ifdef HAVE_CONFIG_H
@@ -60,6 +101,15 @@
 #include <ldappr.h>
 #include <ldappr.h>
 #endif
 #endif
 
 
+#if defined(USE_OPENLDAP)
+/* the server depends on the old, deprecated ldap_explode behavior which openldap
+   does not support - the use of the mozldap code should be seen as a temporary
+   measure which we should remove as we improve our internal DN handling */
+static char **mozldap_ldap_explode( const char *dn, const int notypes, const int nametype );
+static char **mozldap_ldap_explode_dn( const char *dn, const int notypes );
+static char **mozldap_ldap_explode_rdn( const char *rdn, const int notypes );
+#endif
+
 #ifdef MEMPOOL_EXPERIMENTAL
 #ifdef MEMPOOL_EXPERIMENTAL
 void _free_wrapper(void *ptr)
 void _free_wrapper(void *ptr)
 {
 {
@@ -79,6 +129,7 @@ slapi_ldap_unbind( LDAP *ld )
     }
     }
 }
 }
 
 
+#if defined(USE_OPENLDAP)
 /* mozldap ldap_init and ldap_url_parse accept a hostname in the form
 /* mozldap ldap_init and ldap_url_parse accept a hostname in the form
    host1[:port1]SPACEhost2[:port2]SPACEhostN[:portN]
    host1[:port1]SPACEhost2[:port2]SPACEhostN[:portN]
    where SPACE is a single space (0x20) character
    where SPACE is a single space (0x20) character
@@ -151,6 +202,7 @@ end:
     slapi_ch_free_string(&my_copy);
     slapi_ch_free_string(&my_copy);
     return retstr;    
     return retstr;    
 }
 }
+#endif /* USE_OPENLDAP */
 
 
 const char *
 const char *
 slapi_urlparse_err2string( int err )
 slapi_urlparse_err2string( int err )
@@ -1034,6 +1086,26 @@ done:
     return rc;
     return rc;
 }
 }
 
 
+char **
+slapi_ldap_explode_rdn(const char *rdn, int notypes)
+{
+#if defined(USE_OPENLDAP)
+    return mozldap_ldap_explode_rdn(rdn, notypes);
+#else
+    return ldap_explode_dn(rdn, notypes);
+#endif
+}
+
+char **
+slapi_ldap_explode_dn(const char *dn, int notypes)
+{
+#if defined(USE_OPENLDAP)
+    return mozldap_ldap_explode_dn(dn, notypes);
+#else
+    return ldap_explode_dn(dn, notypes);
+#endif
+}
+
 void
 void
 slapi_add_auth_response_control( Slapi_PBlock *pb, const char *binddn )
 slapi_add_auth_response_control( Slapi_PBlock *pb, const char *binddn )
 {
 {
@@ -1871,3 +1943,161 @@ cleanup:
 }
 }
 
 
 #endif /* HAVE_KRB5 */
 #endif /* HAVE_KRB5 */
+
+#if defined(USE_OPENLDAP)
+
+#define LDAP_DN		1
+#define LDAP_RDN	2
+
+#define INQUOTE		1
+#define OUTQUOTE	2
+
+static char **
+mozldap_ldap_explode( const char *dn, const int notypes, const int nametype )
+{
+	char	*p, *q, *rdnstart, **rdns = NULL;
+	size_t	plen = 0;
+	int		state = 0;
+	int		count = 0;
+	int		startquote = 0;
+	int		endquote = 0;
+	int		len = 0;
+	int		goteq = 0;
+
+	if ( dn == NULL ) {
+		dn = "";
+	}
+
+	while ( ldap_utf8isspace( (char *)dn )) { /* ignore leading spaces */
+		++dn;
+	}
+
+	p = rdnstart = (char *) dn;
+	state = OUTQUOTE;
+
+	do {
+		p += plen;
+		plen = 1;
+		switch ( *p ) {
+		case '\\':
+			if ( *++p == '\0' )
+				p--;
+			else
+				plen = LDAP_UTF8LEN(p);
+			break;
+		case '"':
+			if ( state == INQUOTE )
+				state = OUTQUOTE;
+			else
+				state = INQUOTE;
+			break;
+		case '+': if ( nametype != LDAP_RDN ) break;
+		case ';':
+		case ',':
+		case '\0':
+			if ( state == OUTQUOTE ) {
+				/*
+				 * semicolon and comma are not valid RDN
+				 * separators.
+				 */
+				if ( nametype == LDAP_RDN && 
+					( *p == ';' || *p == ',' || !goteq)) {
+					charray_free( rdns );
+					return NULL;
+				}
+				if ( (*p == ',' || *p == ';') && !goteq ) {
+                                   /* If we get here, we have a case similar
+				    * to <attr>=<value>,<string>,<attr>=<value>
+				    * This is not a valid dn */
+				    charray_free( rdns );
+				    return NULL;
+				}
+				goteq = 0;
+				++count;
+				if ( rdns == NULL ) {
+					if (( rdns = (char **)slapi_ch_malloc( 8
+						 * sizeof( char *))) == NULL )
+						return( NULL );
+				} else if ( count >= 8 ) {
+					if (( rdns = (char **)slapi_ch_realloc(
+					    rdns, (count+1) *
+					    sizeof( char *))) == NULL )
+						return( NULL );
+				}
+				rdns[ count ] = NULL;
+				endquote = 0;
+				if ( notypes ) {
+					for ( q = rdnstart;
+					    q < p && *q != '='; ++q ) {
+						;
+					}
+					if ( q < p ) { /* *q == '=' */
+						rdnstart = ++q;
+					}
+					if ( *rdnstart == '"' ) {
+						startquote = 1;
+						++rdnstart;
+					}
+					
+					if ( (*(p-1) == '"') && startquote ) {
+						endquote = 1;
+						--p;
+					}
+				}
+
+				len = p - rdnstart;
+				if (( rdns[ count-1 ] = (char *)slapi_ch_calloc(
+				    1, len + 1 )) != NULL ) {
+				    	memcpy( rdns[ count-1 ], rdnstart,
+					    len );
+					if ( !endquote ) {
+						/* trim trailing spaces */
+						while ( len > 0 &&
+						    ldap_utf8isspace(
+						    &rdns[count-1][len-1] )) {
+							--len;
+						}
+					}
+					rdns[ count-1 ][ len ] = '\0';
+				}
+
+				/*
+				 *  Don't forget to increment 'p' back to where
+				 *  it should be.  If we don't, then we will
+				 *  never get past an "end quote."
+				 */
+				if ( endquote == 1 )
+					p++;
+
+				rdnstart = *p ? p + 1 : p;
+				while ( ldap_utf8isspace( rdnstart ))
+					++rdnstart;
+			}
+			break;
+		case '=':
+			if ( state == OUTQUOTE ) {
+				goteq = 1;
+			}
+			/* FALL */
+		default:
+			plen = LDAP_UTF8LEN(p);
+			break;
+		}
+	} while ( *p );
+
+	return( rdns );
+}
+
+static char **
+mozldap_ldap_explode_dn( const char *dn, const int notypes )
+{
+	return( mozldap_ldap_explode( dn, notypes, LDAP_DN ) );
+}
+
+static char **
+mozldap_ldap_explode_rdn( const char *rdn, const int notypes )
+{
+	return( mozldap_ldap_explode( rdn, notypes, LDAP_RDN ) );
+}
+
+#endif /* USE_OPENLDAP */

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

@@ -465,7 +465,7 @@ op_shared_rename(Slapi_PBlock *pb, int passin_args)
 	}
 	}
 
 
 	/* check that the rdn is formatted correctly */
 	/* check that the rdn is formatted correctly */
-	if ((rdns = ldap_explode_rdn(newrdn, 0)) == NULL) 
+	if ((rdns = slapi_ldap_explode_rdn(newrdn, 0)) == NULL) 
 	{
 	{
 		if ( !internal_op ) {
 		if ( !internal_op ) {
 			slapi_log_error(SLAPI_LOG_ARGS, NULL, 
 			slapi_log_error(SLAPI_LOG_ARGS, NULL, 

+ 7 - 7
ldap/servers/slapd/rdn.c

@@ -101,7 +101,7 @@ slapi_rdn_init_dn(Slapi_RDN *rdn,const char *dn)
 	slapi_rdn_init(rdn);
 	slapi_rdn_init(rdn);
 	if(dn!=NULL)
 	if(dn!=NULL)
 	{
 	{
-		char **dns= ldap_explode_dn(dn, 0);
+		char **dns= slapi_ldap_explode_dn(dn, 0);
 		if(dns!=NULL)
 		if(dns!=NULL)
 		{
 		{
 			rdn->rdn= slapi_ch_strdup(dns[0]);
 			rdn->rdn= slapi_ch_strdup(dns[0]);
@@ -174,9 +174,9 @@ _slapi_rdn_init_all_dn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn)
 				if (q) {
 				if (q) {
 					char bakup = *q;
 					char bakup = *q;
 					*q = '\0';
 					*q = '\0';
-					dns = ldap_explode_dn(dn, 0);
+					dns = slapi_ldap_explode_dn(dn, 0);
 					if (NULL == dns) { /* if dn contains NULL RDN (e.g., ",,"),
 					if (NULL == dns) { /* if dn contains NULL RDN (e.g., ",,"),
-										  ldap_explode_dn returns NULL */
+										  slapi_ldap_explode_dn returns NULL */
 						*q = bakup;
 						*q = bakup;
 						return -1;
 						return -1;
 					}
 					}
@@ -187,16 +187,16 @@ _slapi_rdn_init_all_dn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn)
 					rc = 0; /* success */
 					rc = 0; /* success */
 				} else {
 				} else {
 					/* Given dn does not belong to this server. Just set it. */
 					/* Given dn does not belong to this server. Just set it. */
-					dns = ldap_explode_dn(dn, 0);
+					dns = slapi_ldap_explode_dn(dn, 0);
 				}
 				}
 			}
 			}
 		} else {
 		} else {
 			/* Given dn does not belong to this server. Just set it. */
 			/* Given dn does not belong to this server. Just set it. */
-			dns = ldap_explode_dn(dn, 0);
+			dns = slapi_ldap_explode_dn(dn, 0);
 		}
 		}
 	} else {
 	} else {
 		/* Given dn does not belong to this server. Just set it. */
 		/* Given dn does not belong to this server. Just set it. */
-		dns = ldap_explode_dn(dn, 0);
+		dns = slapi_ldap_explode_dn(dn, 0);
 	}
 	}
 
 
 	/* Get the last matched position */
 	/* Get the last matched position */
@@ -329,7 +329,7 @@ slapi_rdn_get_rdns(Slapi_RDN *rdn)
 		}
 		}
 		if(rdn->rdn!=NULL)
 		if(rdn->rdn!=NULL)
 		{
 		{
-		   	rdn->rdns = ldap_explode_rdn( rdn->rdn, 0 );
+		   	rdn->rdns = slapi_ldap_explode_rdn( rdn->rdn, 0 );
 			rdns= rdn->rdns;
 			rdns= rdn->rdns;
 		}
 		}
 	    slapi_setbit_uchar(rdn->flag,FLAG_RDNS);
 	    slapi_setbit_uchar(rdn->flag,FLAG_RDNS);

+ 34 - 0
ldap/servers/slapd/slapi-plugin.h

@@ -5170,6 +5170,40 @@ int slapi_ldif_parse_line(
     int *freeval /* values will usually be returned in place as pointers into line - if the value is a url, the value will be malloced and must be freed by the caller */
     int *freeval /* values will usually be returned in place as pointers into line - if the value is a url, the value will be malloced and must be freed by the caller */
 );
 );
 
 
+/**
+ * Parse an LDAP DN string.  Return an array of RDN strings, terminated by a NULL.  This
+ * function differs from the standard openldap ldap_explode_dn, which will escape utf-8
+ * characters.  In the directory server, we do not want to escape them.  The caller
+ * should use slapi_ldap_value_free to free the returned memory when finished.
+ *
+ * \param dn      The LDAP DN
+ * \param notypes set to true (1) to return only the attribute values with no attribute types  
+ * \return \c     An array of RDN strings - use slapi_ch_array_free to free
+ *
+ * \see slapi_ldap_value_free()
+ */
+char **slapi_ldap_explode_dn(
+    const char *dn, /* dn to explode */
+    int notypes /* set to true to return only the values with no types */
+);
+
+/**
+ * Parse an LDAP RDN string.  Return an array of AVA strings, terminated by a NULL.  This
+ * function differs from the standard openldap ldap_explode_rdn, which will escape utf-8
+ * characters.  In the directory server, we do not want to escape them.  The caller
+ * should use slapi_ldap_value_free to free the returned memory when finished.
+ *
+ * \param dn      The LDAP RDN
+ * \param notypes set to true (1) to return only the attribute values with no attribute types  
+ * \return \c     An array of AVA strings - use slapi_ch_array_free to free
+ *
+ * \see slapi_ldap_value_free()
+ */
+char **slapi_ldap_explode_rdn(
+    const char *rdn, /* rdn to explode */
+    int notypes /* set to true to return only the values with no types */
+);
+
 /*
 /*
  * computed attributes
  * computed attributes
  */
  */

+ 2 - 2
lib/ldaputil/cert.c

@@ -221,12 +221,12 @@ _explode_dn (const char* dn)
 {
 {
     auto char*** exp = NULL;
     auto char*** exp = NULL;
     if (dn && *dn) {
     if (dn && *dn) {
-	auto char** rdns = ldap_explode_dn (dn, 0);
+	auto char** rdns = slapi_ldap_explode_dn (dn, 0);
 	if (rdns) {
 	if (rdns) {
 	    auto size_t expLen = 0;
 	    auto size_t expLen = 0;
 	    auto char** rdn;
 	    auto char** rdn;
 	    for (rdn = rdns; *rdn; ++rdn) {
 	    for (rdn = rdns; *rdn; ++rdn) {
-		auto char** avas = ldap_explode_rdn (*rdn, 0);
+		auto char** avas = slapi_ldap_explode_rdn (*rdn, 0);
 		if (avas && *avas) {
 		if (avas && *avas) {
 		    exp = (char***) ldapu_realloc (exp, sizeof(char**) * (expLen + 2));
 		    exp = (char***) ldapu_realloc (exp, sizeof(char**) * (expLen + 2));
 		    if (exp) {
 		    if (exp) {