From: Kurt Zeilenga Date: Sat, 7 Aug 1999 04:48:16 +0000 (+0000) Subject: Fix filter escapes. ITS#247 X-Git-Tag: TWEB_OL_BASE~264 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=0fe5da0f9a4b512fb4e01fedcbc6a1daae39b682;p=openldap Fix filter escapes. ITS#247 --- diff --git a/libraries/libldap/search.c b/libraries/libldap/search.c index 9d27820f93..a94f17a38c 100644 --- a/libraries/libldap/search.c +++ b/libraries/libldap/search.c @@ -22,9 +22,24 @@ #include "ldap-int.h" +static int ldap_is_attribute LDAP_P(( + const char *attr )); + +static int ldap_is_attribute_ext LDAP_P(( + const char *attr )); + +static int hex2value LDAP_P(( + int c )); + +static ber_slen_t filter_value_unescape LDAP_P(( + char *filter )); + static char *find_right_paren LDAP_P(( char *s )); +static char *find_wildcard LDAP_P(( + char *s )); + static char *put_complex_filter LDAP_P(( BerElement *ber, char *str, @@ -64,7 +79,7 @@ static int put_filter_list LDAP_P(( * * Example: * char *attrs[] = { "mail", "title", 0 }; - * ldap_search_ext( ld, "c=us@o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob", + * ldap_search_ext( ld, "c=us,o=UM", LDAP_SCOPE_SUBTREE, "cn~=bob", * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit, * &msgid ); */ @@ -318,6 +333,35 @@ ldap_build_search_req( return( ber ); } +#ifndef LDAP_UNDERSCORE +#define LDAP_UNDERSCORE "" +#endif + +static char *spanset = + ":-.;" LDAP_UNDERSCORE + "ABCDEFGHIGKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789"; + +#define ATTR_SPANSET (spanset) +#define EXT_SPANSET (&spanset[1]) + +static int ldap_is_attribute LDAP_P(( const char *attr )) +{ + size_t len = strlen( attr ); + size_t span = strspn( attr, ATTR_SPANSET ); + + return span == len; +} + +static int ldap_is_attribute_ext LDAP_P(( const char *attr )) +{ + size_t len = strlen( attr ); + size_t span = strspn( attr, EXT_SPANSET ); + + return span == len; +} + static char * find_right_paren( char *s ) { @@ -343,6 +387,89 @@ find_right_paren( char *s ) return( *s ? s : NULL ); } +static int hex2value( int c ) +{ + if( c >= '0' && c <= '9' ) { + return c - '0'; + } + + if( c >= 'A' && c <= 'F' ) { + return c + (10 - (int) 'A'); + } + + if( c >= 'a' && c <= 'f' ) { + return c + (10 - (int) 'a'); + } + + return -1; +} + +static char * +find_wildcard( char *s ) +{ + for( ; *s != '\0' ; s++ ) { + switch( *s ) { + case '*': /* found wildcard */ + return s; + + case '\\': + s++; /* skip over escape */ + if( hex2value( s[0] ) >= 0 && hex2value( s[1] ) >= 0 ) { + /* skip over lead digit of two hex digit code */ + s++; + } + } + } + + return NULL; +} + +/* unescape filter value */ +/* support both LDAP v2 and v3 escapes */ +/* output can include nul characters */ +static ber_slen_t +filter_value_unescape( char *fval ) +{ + ber_slen_t r, v; + int v1, v2; + + for( r=v=0; fval[v] != '\0'; v++ ) { + switch( fval[v] ) { + case '\\': + /* escape */ + v++; + + if ( fval[v] == '\0' ) { + /* escape at end of string */ + return -1; + + } else if (( v1 = hex2value( fval[v] )) < 0 ) { + /* LDAPv3 escape */ + + if (( v2 = hex2value( fval[v+1] )) < 0 ) { + /* must be two digit code */ + return -1; + } + + fval[r++] = v1 * 16 + v2; + v++; + + } else { + /* LDAPv2 escape */ + fval[r++] = fval[v]; + } + + break; + + default: + fval[r++] = fval[v]; + } + } + + fval[r] = '\0'; + return r; +} + static char * put_complex_filter( BerElement *ber, char *str, ber_tag_t tag, int not ) { @@ -378,8 +505,8 @@ put_complex_filter( BerElement *ber, char *str, ber_tag_t tag, int not ) static int put_filter( BerElement *ber, char *str ) { - char *next, *tmp, *s, *d; - int parens, balance, escape, gotescape; + char *next; + int parens, balance, escape; /* * A Filter looks like this: @@ -416,7 +543,7 @@ put_filter( BerElement *ber, char *str ) Debug( LDAP_DEBUG_TRACE, "put_filter \"%s\"\n", str, 0, 0 ); - gotescape = parens = 0; + parens = 0; while ( *str ) { switch ( *str ) { case '(': @@ -471,7 +598,7 @@ put_filter( BerElement *ber, char *str ) balance--; } if ( *next == '\\' && ! escape ) - gotescape = escape = 1; + escape = 1; else escape = 0; if ( balance ) @@ -481,24 +608,9 @@ put_filter( BerElement *ber, char *str ) return( -1 ); *next = '\0'; - tmp = LDAP_STRDUP( str ); - if ( gotescape ) { - escape = 0; - for ( s = d = tmp; *s; s++ ) { - if ( *s != '\\' || escape ) { - *d++ = *s; - escape = 0; - } else { - escape = 1; - } - } - *d = '\0'; - } - if ( put_simple_filter( ber, tmp ) == -1 ) { - LDAP_FREE( tmp ); + if ( put_simple_filter( ber, str ) == -1 ) { return( -1 ); } - LDAP_FREE( tmp ); *next++ = ')'; str = next; parens--; @@ -523,24 +635,9 @@ put_filter( BerElement *ber, char *str ) Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0, 0 ); next = strchr( str, '\0' ); - tmp = LDAP_STRDUP( str ); - if ( strchr( tmp, '\\' ) != NULL ) { - escape = 0; - for ( s = d = tmp; *s; s++ ) { - if ( *s != '\\' || escape ) { - *d++ = *s; - escape = 0; - } else { - escape = 1; - } - } - *d = '\0'; - } - if ( put_simple_filter( ber, tmp ) == -1 ) { - LDAP_FREE( tmp ); + if ( put_simple_filter( ber, str ) == -1 ) { return( -1 ); } - LDAP_FREE( tmp ); str = next; break; } @@ -589,57 +686,76 @@ put_simple_filter( char *str ) { char *s; - char *value, savechar; + char *value; ber_tag_t ftype; - int rc; + int rc = -1; Debug( LDAP_DEBUG_TRACE, "put_simple_filter \"%s\"\n", str, 0, 0 ); - if ( (s = strchr( str, '=' )) == NULL ) - return( -1 ); + str = LDAP_STRDUP( str ); + if( str == NULL ) return -1; + + if ( (s = strchr( str, '=' )) == NULL ) { + goto done; + } + value = s + 1; *s-- = '\0'; - savechar = *s; switch ( *s ) { case '<': ftype = LDAP_FILTER_LE; *s = '\0'; + if(! ldap_is_attribute( str ) ) goto done; break; + case '>': ftype = LDAP_FILTER_GE; *s = '\0'; + if(! ldap_is_attribute( str ) ) goto done; break; + case '~': ftype = LDAP_FILTER_APPROX; *s = '\0'; + if(! ldap_is_attribute( str ) ) goto done; break; + case ':': /* LDAPv3 extended filter */ ftype = LDAP_FILTER_EXTENDED; - return -1; + if(! ldap_is_attribute_ext( str ) ) goto done; + goto done; /* XXX not yet implemented */ break; + default: - if ( strchr( value, '*' ) == NULL ) { + if ( find_wildcard( value ) == NULL ) { ftype = LDAP_FILTER_EQUALITY; } else if ( strcmp( value, "*" ) == 0 ) { ftype = LDAP_FILTER_PRESENT; } else { rc = put_substring_filter( ber, str, value ); - *(value-1) = '='; - return( rc ); + goto done; } break; } if ( ftype == LDAP_FILTER_PRESENT ) { rc = ber_printf( ber, "ts", ftype, str ); + } else { - rc = ber_printf( ber, "t{ss}", ftype, str, value ); + ber_slen_t len = filter_value_unescape( value ); + + if( len >= 0 ) { + rc = ber_printf( ber, "t{so}", + ftype, str, value, len ); + } } - *s = savechar; - *(value-1) = '='; - return( rc == -1 ? rc : 0 ); + if( rc != -1 ) rc = 0; + +done: + LDAP_FREE( str ); + return rc; } static int @@ -654,8 +770,8 @@ put_substring_filter( BerElement *ber, char *type, char *val ) if ( ber_printf( ber, "t{s{", ftype, type ) == -1 ) return( -1 ); - while ( val != NULL ) { - if ( (nextstar = strchr( val, '*' )) != NULL ) + for( ; val != NULL; val=nextstar ) { + if ( (nextstar = find_wildcard( val )) != NULL ) *nextstar++ = '\0'; if ( gotstar == 0 ) { @@ -665,15 +781,20 @@ put_substring_filter( BerElement *ber, char *type, char *val ) } else { ftype = LDAP_SUBSTRING_ANY; } + if ( *val != '\0' ) { - if ( ber_printf( ber, "ts", ftype, val ) == -1 ) + ber_slen_t len = filter_value_unescape( val ); + + if ( len < 0 ) { + return -1; + } + + if ( ber_printf( ber, "to", ftype, val, len ) == -1 ) { return( -1 ); + } } gotstar = 1; - if ( nextstar != NULL ) - *(nextstar-1) = '*'; - val = nextstar; } if ( ber_printf( ber, /* {{ */ "}}" ) == -1 )