summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoriko Hosoi <nhosoi@redhat.com>2010-03-11 11:10:48 -0800
committerNoriko Hosoi <nhosoi@redhat.com>2010-03-11 11:10:48 -0800
commitf11afee0ca0c4039cebc0efe4388b95776b6da4b (patch)
tree3fa553f53f52b01df054d02d972b7d72914874c5
parentbe17b937b06eeb0822189951a6f63cfb87749e32 (diff)
downloadds-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.c1
-rw-r--r--ldap/servers/slapd/back-ldbm/ldbm_add.c9
-rw-r--r--ldap/servers/slapd/dn.c153
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 );
}