[Fedora-directory-commits] ldapserver/ldap/servers/slapd slapi-private.h, 1.31, 1.32 ava.c, 1.8, 1.9 dn.c, 1.10, 1.11 util.c, 1.23, 1.24

Noriko Hosoi nhosoi at fedoraproject.org
Tue Jan 6 22:50:33 UTC 2009


Author: nhosoi

Update of /cvs/dirsec/ldapserver/ldap/servers/slapd
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv2079

Modified Files:
	slapi-private.h ava.c dn.c util.c 
Log Message:
Resolves: #438139
Summary: DN with antislash('\') rename (modrdn) problem
Problem description:
Unescape codes in the DS (strcpy_special_undo in ava.c and
strcpy_unescape_dnvalue in dn.c) were "unescaping" more than the escape code
(e.g., escape_dn_value in NET LDAP) does escaping.  The test string 
'BeforeSlash\AfterSlash' fortunately/unfortunately contains '\Af', which is 
considered '\##' (where # is hex number) by the DS unescape functions even 
though it was not meant to be escaped.  As long as using UTF-8, there is no 
chance for the server to receive "\af".

Change description:
1) There were identical static functions: strcpy_special_undo (ava.c) and
strcpy_special_undo (dn.c).  Merged them to strcpy_unescape_value and put it in
util.c.
2) In the unescape/normalize functions for dn (strcpy_unescape_value in util.c
and substr_dn_normalize in dn.c), added a check for the first hex number in
'\##'.  If the 8th bit is on, we don't do unescaping but store it as is since
the unescaped character is not UTF-8.
3) If 2 consecutive '\'s are passed to the unescape/normalize functions, keep
one of them.



Index: slapi-private.h
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-private.h,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- slapi-private.h	2 Dec 2008 15:29:30 -0000	1.31
+++ slapi-private.h	6 Jan 2009 22:50:29 -0000	1.32
@@ -1111,11 +1111,12 @@
 int slapd_security_library_is_initialized( void );
 char* slapd_get_tmp_dir( void );
 
-/* Misc crrrrrrap */
+/* util.c */
 #include <stdio.h> /* GGOODREPL - For BUFSIZ, below, gak */
 const char* escape_string (const char* str, char buf[BUFSIZ]);
 const char* escape_string_with_punctuation(const char* str, char buf[BUFSIZ]);
 const char* escape_filter_value(const char* str, int len, char buf[BUFSIZ]);
+void strcpy_unescape_value( char *d, const char *s );
 
 char *slapi_berval_get_string_copy(const struct berval *bval);
 


Index: ava.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/ava.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ava.c	15 Oct 2008 06:30:03 -0000	1.8
+++ ava.c	6 Jan 2009 22:50:30 -0000	1.9
@@ -96,73 +96,9 @@
 	*s++ = '\0';
 
 	ava->ava_type = rdn;
-	strcpy_special_undo( s, s );
+	strcpy_unescape_value( s, s );
 	ava->ava_value.bv_val = s;
 	ava->ava_value.bv_len = strlen( s );
 
 	return( 0 );
 }
-
-/*
-** This function takes a quoted attribute value of the form "abc",
-** and strips off the enclosing quotes.  It also deals with quoted
-** characters by removing the preceeding '\' character.
-**
-*/
-static void
-strcpy_special_undo( char *d, const char *s )
-{
-    const char *end = s + strlen(s);
-	for ( ; s < end && *s; s++ )
-	{
-		switch ( *s )
-		{
-		case '"':
-			break;
-		case '\\':
-            {
-            /*
-             * The '\' could be escaping a single character, ie \"
-             * or could be escaping a hex byte, ie \01
-             */
-            int singlecharacter= 1;
-            if ( s+2 < end )
-            {
-                int n = hexchar2int( s[1] );
-                if ( n >= 0 )
-                {
-                    int n2 = hexchar2int( s[2] );
-                    if ( n2 >= 0 )
-                    {
-                        singlecharacter= 0;
-                        n = (n << 4) + n2;
-                        if (n == 0)
-                        {
-                            /* don't change \00 */
-                            *d++ = *++s;
-                            *d++ = *++s;
-                        }
-                        else
-                        {
-                            /* change \xx to a single char */
-                            ++s;
-                            *(unsigned char*)(s+1) = n;
-                        }
-                    }
-                }
-            }
-            if(singlecharacter)
-            {
-                s++;
-                *d++ = *s;
-            }
-            break;
-            }
-		default:
-			*d++ = *s;
-			break;
-		}
-	}
-	*d = '\0';
-}
-


Index: dn.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/dn.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- dn.c	4 Oct 2007 16:27:47 -0000	1.10
+++ dn.c	6 Jan 2009 22:50:30 -0000	1.11
@@ -138,11 +138,11 @@
 char *
 substr_dn_normalize( char *dn, char *end )
 {
-    /* \xx is changed to \c.
-     * \c is changed to c, unless this would change its meaning.
-     * All values that contain 2 or more separators are "enquoted";
-     * all other values are not enquoted.
-     */
+	/* \xx is changed to \c.
+	 * \c is changed to c, unless this would change its meaning.
+	 * All values that contain 2 or more separators are "enquoted";
+	 * all other values are not enquoted.
+	 */
 	char		*value = NULL;
 	char 		*value_separator = NULL;
 	char		*d = NULL;
@@ -192,22 +192,22 @@
 			break;
 		case INVALUE:
 			if ( gotesc ) {
-			    if ( SEPARATOR( *s ) ) {
-				value_separator = d;
-			    } else if ( ! NEEDSESCAPE( *s ) ) {
-				--d; /* eliminate the \ */
-			    }
+				if ( SEPARATOR( *s ) ) {
+					value_separator = d;
+				} else if ( ! NEEDSESCAPE( *s ) ) {
+					--d; /* eliminate the \ */
+				}
 			} else if ( SEPARATOR( *s ) ) {
-			    while ( SPACE( *(d - 1) ) )
-				d--;
-			    if ( value_separator == dn ) { /* 2 or more separators */
+				while ( SPACE( *(d - 1) ) )
+					d--;
+				if ( value_separator == dn ) { /* 2 or more separators */
 				/* convert to quoted value: */
 				char *L = NULL; /* char after last seperator */
 				char *R; /* value character iterator */
 				int escape_skips = 0; /* number of escapes we have seen after the first */
 
 				for ( R = value; (R = strchr( R, '\\' )) && (R < d); L = ++R ) {
-				    if ( SEPARATOR( R[1] )) {
+					if ( SEPARATOR( R[1] )) {
 						if ( L == NULL ) {
 							/* executes once, at first escape, adds opening quote */
 							const size_t len = R - value;
@@ -229,113 +229,120 @@
 							--d;
 							++escape_skips;
 						}
-				    }
+					}
 				}
 				memmove( value, L, d - L + escape_skips );
 				*d++ = '"'; /* closing quote */
-			    }
-			    state = B4TYPE;
+			}
+			state = B4TYPE;
 
-			    /*
-			     * Track and sort attribute values within
-			     * multivalued RDNs.
-			     */
-			    if ( *s == '+' || rdn_av_count > 0 ) {
+			/*
+			 * Track and sort attribute values within
+			 * multivalued RDNs.
+			 */
+			if ( *s == '+' || rdn_av_count > 0 ) {
 				add_rdn_av( typestart, d, &rdn_av_count,
 					&rdn_avs, initial_rdn_av_stack );
-			    }
-			    if ( *s != '+' ) {	/* at end of this RDN */
+			}
+			if ( *s != '+' ) {	/* at end of this RDN */
 				if ( rdn_av_count > 1 ) {
-				    sort_rdn_avs( rdn_avs, rdn_av_count );
+					sort_rdn_avs( rdn_avs, rdn_av_count );
 				}
 				if ( rdn_av_count > 0 ) {
-				    reset_rdn_avs( &rdn_avs, &rdn_av_count );
+					reset_rdn_avs( &rdn_avs, &rdn_av_count );
 				}
-			    }
+			}
 
-			    *d++ = (*s == '+') ? '+' : ',';
-			    break;
+			*d++ = (*s == '+') ? '+' : ',';
+			break;
 			}
 			*d++ = *s;
 			break;
 		case INQUOTEDVALUE:
 			if ( gotesc ) {
-			    if ( ! NEEDSESCAPE( *s ) ) {
-				--d; /* eliminate the \ */
-			    }
+				if ( ! NEEDSESCAPE( *s ) ) {
+					--d; /* eliminate the \ */
+				}
 			} else if ( *s == '"' ) {
-			    state = B4SEPARATOR;
-			    if ( value_separator == dn /* 2 or more separators */
-				|| SPACE( value[1] ) || SPACE( d[-1] ) ) {
-				*d++ = *s;
-			    } else {
-				/* convert to non-quoted value: */
-				if ( value_separator == NULL ) { /* no separators */
-				    memmove ( value, value+1, (d-value)-1 );
-				    --d;
-				} else { /* 1 separator */
-				    memmove ( value, value+1, (value_separator-value)-1 );
-				    *(value_separator - 1) = '\\';
+				state = B4SEPARATOR;
+				if ( value_separator == dn /* 2 or more separators */
+					 || SPACE( value[1] ) || SPACE( d[-1] ) ) {
+					*d++ = *s;
+				} else {
+					/* convert to non-quoted value: */
+					if ( value_separator == NULL ) { /* no separators */
+						memmove ( value, value+1, (d-value)-1 );
+						--d;
+					} else { /* 1 separator */
+						memmove ( value, value+1, (value_separator-value)-1 );
+						*(value_separator - 1) = '\\';
+					}
 				}
-			    }
-			    break;
+				break;
 			}
 			if ( SEPARATOR( *s )) {
-			    if ( value_separator ) value_separator = dn;
-			    else value_separator = d;
+				if ( value_separator ) value_separator = dn;
+				else value_separator = d;
 			}
 			*d++ = *s;
 			break;
 		case B4SEPARATOR:
 			if ( SEPARATOR( *s ) ) {
-			    state = B4TYPE;
+				state = B4TYPE;
 
-			    /*
-			     * Track and sort attribute values within
-			     * multivalued RDNs.
-			     */
-			    if ( *s == '+' || rdn_av_count > 0 ) {
-				add_rdn_av( typestart, d, &rdn_av_count,
-					&rdn_avs, initial_rdn_av_stack );
-			    }
-			    if ( *s != '+' ) {	/* at end of this RDN */
-				if ( rdn_av_count > 1 ) {
-				    sort_rdn_avs( rdn_avs, rdn_av_count );
+				/*
+				 * Track and sort attribute values within
+				 * multivalued RDNs.
+				 */
+				if ( *s == '+' || rdn_av_count > 0 ) {
+					add_rdn_av( typestart, d, &rdn_av_count,
+						&rdn_avs, initial_rdn_av_stack );
 				}
-				if ( rdn_av_count > 0 ) {
-				    reset_rdn_avs( &rdn_avs, &rdn_av_count );
+				if ( *s != '+' ) {	/* at end of this RDN */
+					if ( rdn_av_count > 1 ) {
+						sort_rdn_avs( rdn_avs, rdn_av_count );
+					}
+					if ( rdn_av_count > 0 ) {
+						reset_rdn_avs( &rdn_avs, &rdn_av_count );
+					}
 				}
-			    }
 
-			    *d++ = (*s == '+') ? '+' : ',';
+				*d++ = (*s == '+') ? '+' : ',';
 			}
 			break;
 		default:
 			LDAPDebug( LDAP_DEBUG_ANY,
-			    "slapi_dn_normalize - unknown state %d\n", state, 0, 0 );
+				"slapi_dn_normalize - unknown state %d\n", state, 0, 0 );
 			break;
 		}
-		if ( *s != '\\' ) {
-			gotesc = 0;
-		} else {
-			gotesc = 1;
-			if ( s+2 < end ) {
-			    int n = hexchar2int( s[1] );
-			    if ( n >= 0 ) {
-				int n2 = hexchar2int( s[2] );
-				if ( n2 >= 0 ) {
-				    n = (n << 4) + n2;
-				    if (n == 0) { /* don't change \00 */
-					*d++ = *++s;
-					*d++ = *++s;
-					gotesc = 0;
-				    } else { /* change \xx to a single char */
-					++s;
-					*(unsigned char*)(s+1) = n;
-				    }
+		if ( *s == '\\' ) {
+			if ( gotesc ) { /* '\\', again */
+				/* <type>=XXX\\\\7AYYY; we should keep \\\\. */
+				gotesc = 0;
+			} else {
+				gotesc = 1;
+				if ( s+2 < end ) {
+					int n = hexchar2int( s[1] );
+					/* If 8th bit is on, the char is not ASCII (not UTF-8).  
+					 * Thus, not UTF-8 */
+					if ( n >= 0 && n < 8 ) {
+						int n2 = hexchar2int( s[2] );
+						if ( n2 >= 0 ) {
+							n = (n << 4) + n2;
+							if (n == 0) { /* don't change \00 */
+								*d++ = *++s;
+								*d++ = *++s;
+								gotesc = 0;
+							} else { /* change \xx to a single char */
+								++s;
+								*(unsigned char*)(s+1) = n;
+							}
+						}
+					}
 				}
-			    }
 			}
+		} else {
+			gotesc = 0;
 		}
 	}
 
@@ -349,14 +356,14 @@
 	 * or B4SEPARATOR state if we have a valid rdn component to 
 	 * be added. */
 	if ((rdn_av_count > 0) && ((state == INVALUE) || (state == B4SEPARATOR))) {
-	    add_rdn_av( typestart, d, &rdn_av_count,
-		    &rdn_avs, initial_rdn_av_stack );
+		add_rdn_av( typestart, d, &rdn_av_count,
+			&rdn_avs, initial_rdn_av_stack );
 	}
 	if ( rdn_av_count > 1 ) {
-	    sort_rdn_avs( rdn_avs, rdn_av_count );
+		sort_rdn_avs( rdn_avs, rdn_av_count );
 	}
 	if ( rdn_av_count > 0 ) {
-	    reset_rdn_avs( &rdn_avs, &rdn_av_count );
+		reset_rdn_avs( &rdn_avs, &rdn_av_count );
 	}
 	/* Trim trailing spaces */
 	while ( d != dn && *(d - 1) == ' ' ) d--;  /* XXX 518524 */
@@ -793,73 +800,6 @@
     return 0;
 }
 
-
-
-/*
-** This function takes a quoted attribute value of the form "abc",
-** and strips off the enclosing quotes.  It also deals with quoted
-** characters by removing the preceeding '\' character.
-**
-*/
-static void
-strcpy_unescape_dnvalue( char *d, const char *s )
-{
-    const char *end = s + strlen(s);
-	for ( ; *s; s++ )
-	{
-		switch ( *s )
-		{
-		case '"':
-			break;
-		case '\\':
-            {
-            /*
-             * The '\' could be escaping a single character, ie \"
-             * or could be escaping a hex byte, ie \01
-             */
-            int singlecharacter= 1;
-            if ( s+2 < end )
-            {
-                int n = hexchar2int( s[1] );
-                if ( n >= 0 )
-                {
-                    int n2 = hexchar2int( s[2] );
-                    if ( n2 >= 0 )
-                    {
-                        singlecharacter= 0;
-                        n = (n << 4) + n2;
-                        if (n == 0)
-                        {
-                            /* don't change \00 */
-                            *d++ = *++s;
-                            *d++ = *++s;
-                        }
-                        else
-                        {
-                            /* change \xx to a single char */
-                            ++s;
-                            *(unsigned char*)(s+1) = n;
-                        }
-                    }
-                }
-            }
-            if(singlecharacter)
-            {
-                s++;
-                *d++ = *s;
-            }
-            break;
-            }
-		default:
-			*d++ = *s;
-			break;
-		}
-	}
-	*d = '\0';
-}
-
-
-
 int
 slapi_rdn2typeval(
     char        	*rdn,
@@ -881,7 +821,7 @@
        When adding the rdn attribute in the entry, we need to remove
        all special escaped characters included in the value itself,
        i.e., strings like "\;" must be converted to ";" and so on... */
-    strcpy_unescape_dnvalue(s,s);
+    strcpy_unescape_value(s,s);
 
     bv->bv_val = s;
     bv->bv_len = strlen( s );


Index: util.c
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/servers/slapd/util.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- util.c	19 Dec 2008 19:26:01 -0000	1.23
+++ util.c	6 Jan 2009 22:50:30 -0000	1.24
@@ -198,6 +198,64 @@
     return do_escape_string(str,len,buf,special_filter);
 }
 
+/*
+** This function takes a quoted attribute value of the form "abc",
+** and strips off the enclosing quotes.  It also deals with quoted
+** characters by removing the preceeding '\' character.
+**
+*/
+void
+strcpy_unescape_value( char *d, const char *s )
+{
+    char *head = d;
+    int gotesc = 0;
+    const char *end = s + strlen(s);
+    for ( ; *s; s++ )
+    {
+        switch ( *s )
+        {
+        case '\\':
+            if ( gotesc ) {
+                gotesc = 0;
+            } else {
+                gotesc = 1;
+                if ( s+2 < end ) {
+                    int n = hexchar2int( s[1] );
+                    /* If 8th bit is on, the char is not ASCII (not UTF-8).  
+                     * Thus, not UTF-8 */
+                    if ( n >= 0 && n < 8 ) {
+                        int n2 = hexchar2int( s[2] );
+                        if ( n2 >= 0 ) {
+                            n = (n << 4) + n2;
+                            if (n == 0) { /* don't change \00 */
+                                *d++ = *s++;
+                                *d++ = *s++;
+                                *d++ = *s;
+                            } else { /* change \xx to a single char */
+                                *d++ = (char)n;
+                                s += 2;
+                            }
+                            gotesc = 0;
+                        }
+                    }
+                }
+                if (gotesc) {
+                    *d++ = *s;
+                }
+            }
+            break;
+        default:
+            if (gotesc) {
+                d--;
+            }
+            *d++ = *s;
+            gotesc = 0;
+            break;
+        }
+    }
+    *d = '\0';
+}
+
 /* functions to convert between an entry and a set of mods */
 int slapi_mods2entry (Slapi_Entry **e, const char *idn, LDAPMod **iattrs)
 {




More information about the Fedora-directory-commits mailing list