diff options
author | Noriko Hosoi <nhosoi@redhat.com> | 2010-03-11 11:10:48 -0800 |
---|---|---|
committer | Noriko Hosoi <nhosoi@redhat.com> | 2010-03-11 11:10:48 -0800 |
commit | f11afee0ca0c4039cebc0efe4388b95776b6da4b (patch) | |
tree | 3fa553f53f52b01df054d02d972b7d72914874c5 /ldap/servers/slapd/dn.c | |
parent | be17b937b06eeb0822189951a6f63cfb87749e32 (diff) | |
download | ds-f11afee0ca0c4039cebc0efe4388b95776b6da4b.tar.gz ds-f11afee0ca0c4039cebc0efe4388b95776b6da4b.tar.xz ds-f11afee0ca0c4039cebc0efe4388b95776b6da4b.zip |
199923 - subtree search fails to find items under a db
containing special characters
https://bugzilla.redhat.com/show_bug.cgi?id=199923
Description: regression observed in the tests.
> as of March 04, 2010, this is happening again.
Fix Description:
dn.c: Based upon RFC 4514, the following characters in the RDN
values need to be escaped:
'+', ';', '<', '>', and '=' for the intermediate characters
'+', ';', '<', '>', '=', '#' and ' ' for leading characters
'+', ';', '<', '>', '=', and ' ' for trailing characters
validate.c: If an escaped character followed by another escaped
character, e.g., \#\<, the pointer was moved twice skipping '\'
before '<' and it makes the validation fail.
ldbm_add.c: a local variable addr was not initialized.
Diffstat (limited to 'ldap/servers/slapd/dn.c')
-rw-r--r-- | ldap/servers/slapd/dn.c | 153 |
1 files changed, 96 insertions, 57 deletions
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c index 2fb36e99..2e5ac001 100644 --- a/ldap/servers/slapd/dn.c +++ b/ldap/servers/slapd/dn.c @@ -77,10 +77,16 @@ hexchar2int( char c ) return( -1 ); } -#define DNSEPARATOR(c) (c == ',' || c == ';') -#define SEPARATOR(c) (c == ',' || c == ';' || c == '+') -#define SPACE(c) (c == ' ' || c == '\n') /* XXX 518524 */ -#define NEEDSESCAPE(c) (c == '\\' || c == '"') +#define DNSEPARATOR(c) (((c) == ',') || ((c) == ';')) +#define SEPARATOR(c) (((c) == ',') || ((c) == ';') || ((c) == '+')) +#define SPACE(c) (((c) == ' ') || ((c) == '\n')) /* XXX 518524 */ +#define NEEDSESCAPE(c) (((c) == '\\') || ((c) == '"') || ((c) == '+') || \ + ((c) == ',') || ((c) == ';') || ((c) == '<') || ((c) == '>') || ((c) == '=')) +#define LEADNEEDSESCAPE(c) (((c) == ' ') || ((c) == '#') || NEEDSESCAPE(c)) +#if 0 /* not used */ +#define ONLYTRAILNEEDSESCAPE(c) ((c) == ' ') +#define TRAILNEEDSESCAPE(c) (ONLYTRAILNEEDSESCAPE(c) || NEEDSESCAPE(c)) +#endif #define B4TYPE 0 #define INTYPE 1 #define B4EQUAL 2 @@ -88,6 +94,7 @@ hexchar2int( char c ) #define INVALUE 4 #define INQUOTEDVALUE 5 #define B4SEPARATOR 6 +#define INVALUE1ST 7 #define SLAPI_DNNORM_INITIAL_RDN_AVS 10 #define SLAPI_DNNORM_SMALL_RDN_AV 512 @@ -148,6 +155,8 @@ substr_dn_normalize( char *dn, char *end ) char *d = NULL; char *s = NULL; char *typestart = NULL; + char *rdnbegin = NULL; + char *lastesc = NULL; int gotesc = 0; int state = B4TYPE; int rdn_av_count = 0; @@ -186,75 +195,104 @@ substr_dn_normalize( char *dn, char *end ) if ( *s == '"' || ! SPACE( *s ) ) { value_separator = NULL; value = d; - state = ( *s == '"' ) ? INQUOTEDVALUE : INVALUE; + state = ( *s == '"' ) ? INQUOTEDVALUE : INVALUE1ST; + rdnbegin = d; + lastesc = NULL; *d++ = *s; } break; + case INVALUE1ST: case INVALUE: if ( gotesc ) { if ( SEPARATOR( *s ) ) { value_separator = d; - } else if ( ! NEEDSESCAPE( *s ) ) { + } + if ( INVALUE1ST == state ) { + if ( !LEADNEEDSESCAPE( *s )) { + /* checking the leading char + special chars */ + --d; /* eliminate the \ */ + } + } else if ( !NEEDSESCAPE( *s ) ) { --d; /* eliminate the \ */ + lastesc = d; } } else if ( SEPARATOR( *s ) ) { - while ( SPACE( *(d - 1) ) ) - d--; + /* handling a trailing escaped space */ + /* assuming a space is the only an extra character which + * is not escaped if it appears in the middle, but should + * be if it does at the end of the RDN value */ + /* e.g., ou=ABC \ ,o=XYZ --> ou=ABC \ ,o=XYZ */ + if ( lastesc ) { + while ( SPACE( *(d - 1) ) && d > lastesc ) { + d--; + } + if ( d == lastesc ) { + *d++ = '\\'; + *d++ = ' '; /* escaped trailing space */ + } + } else { + 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 ( L == NULL ) { - /* executes once, at first escape, adds opening quote */ - const size_t len = R - value; + /* 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 ( L == NULL ) { + /* executes once, at first escape, adds opening quote */ + const size_t len = R - value; - /* make room for quote by covering escape */ - if ( len > 0 ) { - memmove( value+1, value, len ); + /* make room for quote by covering escape */ + if ( len > 0 ) { + memmove( value+1, value, len ); + } + + *value = '"'; /* opening quote */ + value = R + 1; /* move passed what has been parsed */ + } else { + const size_t len = R - L; + if ( len > 0 ) { + /* remove the seperator */ + memmove( value, L, len ); + value += len; /* move passed what has been parsed */ + } + --d; + ++escape_skips; } + } /* if ( SEPARATOR( R[1] )) */ + } /* for */ + memmove( value, L, d - L + escape_skips ); + *d++ = '"'; /* closing quote */ + } /* if (value_separator == dn) */ + state = B4TYPE; - *value = '"'; /* opening quote */ - value = R + 1; /* move passed what has been parsed */ - } else { - const size_t len = R - L; - if ( len > 0 ) { - /* remove the seperator */ - memmove( value, L, len ); - value += len; /* move passed what has been parsed */ - } - --d; - ++escape_skips; - } - } - } - memmove( value, L, d - L + escape_skips ); - *d++ = '"'; /* closing quote */ - } - 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 == '+') ? '+' : ','; - break; + *d++ = (*s == '+') ? '+' : ','; + break; + } /* else if ( SEPARATOR( *s ) ) */ + if ( INVALUE1ST == state ) { + state = INVALUE; } *d++ = *s; break; @@ -355,7 +393,8 @@ substr_dn_normalize( char *dn, char *end ) * rdn to our list to sort. We should only be in the INVALUE * or B4SEPARATOR state if we have a valid rdn component to * be added. */ - if ((rdn_av_count > 0) && ((state == INVALUE) || (state == B4SEPARATOR))) { + if ((rdn_av_count > 0) && ((state == INVALUE1ST) || + (state == INVALUE) || (state == B4SEPARATOR))) { add_rdn_av( typestart, d, &rdn_av_count, &rdn_avs, initial_rdn_av_stack ); } |