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 | |
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.
-rw-r--r-- | ldap/servers/plugins/syntaxes/validate.c | 1 | ||||
-rw-r--r-- | ldap/servers/slapd/back-ldbm/ldbm_add.c | 9 | ||||
-rw-r--r-- | ldap/servers/slapd/dn.c | 153 |
3 files changed, 102 insertions, 61 deletions
diff --git a/ldap/servers/plugins/syntaxes/validate.c b/ldap/servers/plugins/syntaxes/validate.c index d0da4be0..aab6d9c2 100644 --- a/ldap/servers/plugins/syntaxes/validate.c +++ b/ldap/servers/plugins/syntaxes/validate.c @@ -535,7 +535,6 @@ int rdn_validate( const char *begin, const char *end, const char **last ) } p++; } - p++; /* Only allow 'SUTF1' chars now. */ } else if (!IS_SUTF1(*p)) { rc = 1; diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c index 0db57f67..11b2fa64 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_add.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c @@ -112,7 +112,7 @@ ldbm_back_add( Slapi_PBlock *pb ) int is_fixup_operation= 0; int is_ruv = 0; /* True if the current entry is RUV */ CSN *opcsn = NULL; - entry_address addr; + entry_address addr = {0}; slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li ); slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e ); @@ -188,7 +188,7 @@ ldbm_back_add( Slapi_PBlock *pb ) { /* Check if an entry with the intended uniqueid already exists. */ done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_UNIQUEID_ENTRY); /* Could be through this multiple times */ - addr.dn = NULL; + addr.dn = addr.udn = NULL; addr.uniqueid = (char*)slapi_entry_get_uniqueid(e); /* jcm - cast away const */ ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, !is_replicated_operation); } @@ -211,6 +211,7 @@ ldbm_back_add( Slapi_PBlock *pb ) /* Check if an entry with the intended DN already exists. */ done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY); /* Could be through this multiple times */ addr.dn = dn; + addr.udn = NULL; addr.uniqueid = NULL; ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_EXISTING_DN_ENTRY, !is_replicated_operation); if(ldap_result_code==LDAP_OPERATIONS_ERROR || @@ -226,6 +227,7 @@ ldbm_back_add( Slapi_PBlock *pb ) { done_with_pblock_entry(pb,SLAPI_ADD_PARENT_ENTRY); /* Could be through this multiple times */ addr.dn = (char*)slapi_sdn_get_dn (&parentsdn); /* get_copy_of_entry assumes the DN is not normalized */ + addr.udn = NULL; addr.uniqueid = operation->o_params.p.p_add.parentuniqueid; ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_PARENT_ENTRY, !is_replicated_operation); /* need to set parentsdn or parentuniqueid if either is not set? */ @@ -265,6 +267,7 @@ ldbm_back_add( Slapi_PBlock *pb ) if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid)) { addr.dn = (char*)slapi_sdn_get_dn (&parentsdn); + addr.udn = NULL; addr.uniqueid = operation->o_params.p.p_add.parentuniqueid; parententry = find_entry2modify_only(pb,be,&addr,&txn); if (parententry && parententry->ep_entry) { @@ -345,7 +348,7 @@ ldbm_back_add( Slapi_PBlock *pb ) * When we resurect a tombstone we must use its UniqueID * to find the tombstone entry and lock it down in the cache. */ - addr.dn = NULL; + addr.dn = addr.udn = NULL; addr.uniqueid = (char *)slapi_entry_get_uniqueid(e); /* jcm - cast away const */ tombstoneentry = find_entry2modify( pb, be, &addr, NULL ); if ( tombstoneentry==NULL ) 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 ); } |