[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