X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Ffilter.c;h=259c9a459089dba1a482147aa463f1c82ea06ab7;hb=3b9f4a82ee478c943a66696adf9133dc9f503e16;hp=96abc9c1213646369141b980081a6243e335eaa8;hpb=6c80cfb2e8a291cb8f88c0e9aa7e047afb9a939f;p=openldap diff --git a/libraries/libldap/filter.c b/libraries/libldap/filter.c index 96abc9c121..259c9a4590 100644 --- a/libraries/libldap/filter.c +++ b/libraries/libldap/filter.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -22,6 +22,14 @@ #include "ldap-int.h" +static int put_simple_vrFilter LDAP_P(( + BerElement *ber, + char *str )); + +static int put_vrFilter_list LDAP_P(( + BerElement *ber, + char *str )); + static char *put_complex_filter LDAP_P(( BerElement *ber, char *str, @@ -181,6 +189,10 @@ ldap_pvt_find_wildcard( const char *s ) case '*': /* found wildcard */ return (char *) s; + case '(': + case ')': + return NULL; + case '\\': if( s[1] == '\0' ) return NULL; @@ -215,6 +227,11 @@ ldap_pvt_filter_value_unescape( char *fval ) for( r=v=0; fval[v] != '\0'; v++ ) { switch( fval[v] ) { + case '(': + case ')': + case '*': + return -1; + case '\\': /* escape */ v++; @@ -298,7 +315,7 @@ put_complex_filter( BerElement *ber, char *str, ber_tag_t tag, int not ) } int -ldap_int_put_filter( BerElement *ber, const char *str_in ) +ldap_pvt_put_filter( BerElement *ber, const char *str_in ) { int rc; char *freeme; @@ -339,7 +356,11 @@ ldap_int_put_filter( BerElement *ber, const char *str_in ) * Note: tags in a choice are always explicit */ +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, ARGS, "ldap_pvt_put_filter: \"%s\"\n", str_in,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_filter: \"%s\"\n", str_in, 0, 0 ); +#endif freeme = LDAP_STRDUP( str_in ); if( freeme == NULL ) return LDAP_NO_MEMORY; @@ -357,8 +378,12 @@ ldap_int_put_filter( BerElement *ber, const char *str_in ) switch ( *str ) { case '&': +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: AND\n", 0,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n", 0, 0, 0 ); +#endif str = put_complex_filter( ber, str, LDAP_FILTER_AND, 0 ); @@ -371,8 +396,12 @@ ldap_int_put_filter( BerElement *ber, const char *str_in ) break; case '|': +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: OR\n", 0,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n", 0, 0, 0 ); +#endif str = put_complex_filter( ber, str, LDAP_FILTER_OR, 0 ); @@ -385,8 +414,12 @@ ldap_int_put_filter( BerElement *ber, const char *str_in ) break; case '!': +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: NOT\n", 0,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n", 0, 0, 0 ); +#endif str = put_complex_filter( ber, str, LDAP_FILTER_NOT, 0 ); @@ -399,8 +432,12 @@ ldap_int_put_filter( BerElement *ber, const char *str_in ) break; default: +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: simple\n", 0,0,0); +#else Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n", 0, 0, 0 ); +#endif balance = 1; escape = 0; @@ -445,8 +482,12 @@ ldap_int_put_filter( BerElement *ber, const char *str_in ) break; case /*'('*/ ')': +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: end\n", 0,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", 0, 0, 0 ); +#endif if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) { rc = -1; goto done; @@ -460,8 +501,12 @@ ldap_int_put_filter( BerElement *ber, const char *str_in ) break; default: /* assume it's a simple type=value filter */ +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: default\n", 0,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", 0, 0, 0 ); +#endif next = strchr( str, '\0' ); if ( put_simple_filter( ber, str ) == -1 ) { rc = -1; @@ -489,8 +534,12 @@ put_filter_list( BerElement *ber, char *str, ber_tag_t tag ) char *next = NULL; char save; +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, ARGS, "put_filter_list \"%s\"\n", str,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_filter_list \"%s\"\n", str, 0, 0 ); +#endif while ( *str ) { while ( *str && LDAP_SPACE( (unsigned char) *str ) ) { @@ -505,7 +554,7 @@ put_filter_list( BerElement *ber, char *str, ber_tag_t tag ) /* now we have "(filter)" with str pointing to it */ *next = '\0'; - if ( ldap_int_put_filter( ber, str ) == -1 ) return -1; + if ( ldap_pvt_put_filter( ber, str ) == -1 ) return -1; *next = save; str = next; @@ -529,8 +578,12 @@ put_simple_filter( ber_tag_t ftype; int rc = -1; +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, ARGS, "put_simple_filter: \"%s\"\n", str,0,0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_simple_filter: \"%s\"\n", str, 0, 0 ); +#endif str = LDAP_STRDUP( str ); if( str == NULL ) return -1; @@ -696,8 +749,12 @@ put_substring_filter( BerElement *ber, char *type, char *val ) int gotstar = 0; ber_tag_t ftype = LDAP_FILTER_SUBSTRINGS; +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, ARGS, "put_substring_filter \"%s=%s\"\n", type, val, 0 ); +#else Debug( LDAP_DEBUG_TRACE, "put_substring_filter \"%s=%s\"\n", type, val, 0 ); +#endif if ( ber_printf( ber, "t{s{" /*"}}"*/, ftype, type ) == -1 ) { return -1; @@ -712,14 +769,15 @@ put_substring_filter( BerElement *ber, char *type, char *val ) if ( *nextstar == '\0' ) { ftype = LDAP_SUBSTRING_FINAL; - } else if ( gotstar++ == 0 ) { - ftype = LDAP_SUBSTRING_INITIAL; } else { - ftype = LDAP_SUBSTRING_ANY; + *nextstar++ = '\0'; + if ( gotstar++ == 0 ) { + ftype = LDAP_SUBSTRING_INITIAL; + } else { + ftype = LDAP_SUBSTRING_ANY; + } } - *nextstar++ = '\0'; - if ( *val != '\0' || ftype == LDAP_SUBSTRING_ANY ) { ber_slen_t len = ldap_pvt_filter_value_unescape( val ); @@ -739,3 +797,384 @@ put_substring_filter( BerElement *ber, char *type, char *val ) return 0; } + +static int +put_vrFilter( BerElement *ber, const char *str_in ) +{ + int rc; + char *freeme; + char *str; + char *next; + int parens, balance, escape; + + /* + * A ValuesReturnFilter looks like this: + * + * ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem + * SimpleFilterItem ::= CHOICE { + * equalityMatch [3] AttributeValueAssertion, + * substrings [4] SubstringFilter, + * greaterOrEqual [5] AttributeValueAssertion, + * lessOrEqual [6] AttributeValueAssertion, + * present [7] AttributeType, + * approxMatch [8] AttributeValueAssertion, + * extensibleMatch [9] SimpleMatchingAssertion -- LDAPv3 + * } + * + * SubstringFilter ::= SEQUENCE { + * type AttributeType, + * SEQUENCE OF CHOICE { + * initial [0] IA5String, + * any [1] IA5String, + * final [2] IA5String + * } + * } + * + * SimpleMatchingAssertion ::= SEQUENCE { -- LDAPv3 + * matchingRule [1] MatchingRuleId OPTIONAL, + * type [2] AttributeDescription OPTIONAL, + * matchValue [3] AssertionValue } + */ + +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, ARGS, "ldap_pvt_put_vrFilter: \"%s\"\n", + str_in, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "put_vrFilter: \"%s\"\n", str_in, 0, 0 ); +#endif + + freeme = LDAP_STRDUP( str_in ); + if( freeme == NULL ) return LDAP_NO_MEMORY; + str = freeme; + + parens = 0; + while ( *str ) { + switch ( *str ) { + case '(': /*')'*/ + str++; + parens++; + + /* skip spaces */ + while( LDAP_SPACE( *str ) ) str++; + + switch ( *str ) { + case '(': + if ( (next = find_right_paren( str )) == NULL ) { + rc = -1; + goto done; + } + + *next = '\0'; + + if ( put_vrFilter_list( ber, str ) == -1 ) { + rc = -1; + goto done; + } + + /* close the '(' */ + *next++ = ')'; + + str = next; + + parens--; + break; + + + default: +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, + "put_vrFilter: simple\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "put_vrFilter: simple\n", + 0, 0, 0 ); +#endif + + balance = 1; + escape = 0; + next = str; + + while ( *next && balance ) { + if ( escape == 0 ) { + if ( *next == '(' ) { + balance++; + } else if ( *next == ')' ) { + balance--; + } + } + + if ( *next == '\\' && ! escape ) { + escape = 1; + } else { + escape = 0; + } + + if ( balance ) next++; + } + + if ( balance != 0 ) { + rc = -1; + goto done; + } + + *next = '\0'; + + if ( put_simple_vrFilter( ber, str ) == -1 ) { + rc = -1; + goto done; + } + + *next++ = /*'('*/ ')'; + + str = next; + parens--; + break; + } + break; + + case /*'('*/ ')': +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: end\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "put_filter: end\n", + 0, 0, 0 ); +#endif + if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) { + rc = -1; + goto done; + } + str++; + parens--; + break; + + case ' ': + str++; + break; + + default: /* assume it's a simple type=value filter */ +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: default\n", + 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "put_filter: default\n", + 0, 0, 0 ); +#endif + next = strchr( str, '\0' ); + if ( put_simple_filter( ber, str ) == -1 ) { + rc = -1; + goto done; + } + str = next; + break; + } + } + + rc = parens ? -1 : 0; + +done: + LDAP_FREE( freeme ); + return rc; +} + +int +ldap_put_vrFilter( BerElement *ber, const char *str_in ) +{ + int rc =0; + + if ( ber_printf( ber, "{" /*"}"*/ ) == -1 ) { + rc = -1; + } + + rc = put_vrFilter( ber, str_in ); + + if ( ber_printf( ber, /*"{"*/ "N}" ) == -1 ) { + rc = -1; + } + + return rc; +} + +static int +put_vrFilter_list( BerElement *ber, char *str ) +{ + char *next = NULL; + char save; + +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, ARGS, "put_vrFilter_list \"%s\"\n", str, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "put_vrFilter_list \"%s\"\n", + str, 0, 0 ); +#endif + + while ( *str ) { + while ( *str && LDAP_SPACE( (unsigned char) *str ) ) { + str++; + } + if ( *str == '\0' ) break; + + if ( (next = find_right_paren( str + 1 )) == NULL ) { + return -1; + } + save = *++next; + + /* now we have "(filter)" with str pointing to it */ + *next = '\0'; + if ( put_vrFilter( ber, str ) == -1 ) return -1; + *next = save; + str = next; + } + + return 0; +} + +static int +put_simple_vrFilter( + BerElement *ber, + char *str ) +{ + char *s; + char *value; + ber_tag_t ftype; + int rc = -1; + +#ifdef NEW_LOGGING + LDAP_LOG ( FILTER, ARGS, "put_simple_vrFilter: \"%s\"\n", str, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "put_simple_vrFilter: \"%s\"\n", + str, 0, 0 ); +#endif + + str = LDAP_STRDUP( str ); + if( str == NULL ) return -1; + + if ( (s = strchr( str, '=' )) == NULL ) { + goto done; + } + + value = s + 1; + *s-- = '\0'; + + switch ( *s ) { + case '<': + ftype = LDAP_FILTER_LE; + *s = '\0'; + break; + + case '>': + ftype = LDAP_FILTER_GE; + *s = '\0'; + break; + + case '~': + ftype = LDAP_FILTER_APPROX; + *s = '\0'; + break; + + case ':': + /* According to ValuesReturnFilter control definition + * extensible filters are off the form: + * type [:rule] := value + * or :rule := value + */ + ftype = LDAP_FILTER_EXT; + *s = '\0'; + + { + char *rule = strchr( str, ':' ); + *rule++ = '\0'; + + if( rule == NULL ) { + /* must have attribute */ + if( !ldap_is_desc( str ) ) { + goto done; + } + rule = ""; + + } else { + *rule++ = '\0'; + } + + + if ( *str == '\0' && ( !rule || *rule == '\0' ) ) { + /* must have either type or rule */ + goto done; + } + + if ( *str != '\0' && !ldap_is_desc( str ) ) { + goto done; + } + + if ( rule && *rule != '\0' && !ldap_is_oid( rule ) ) { + goto done; + } + + rc = ber_printf( ber, "t{" /*"}"*/, ftype ); + + if( rc != -1 && rule && *rule != '\0' ) { + rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_OID, rule ); + } + + if( rc != -1 && *str != '\0' ) { + rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_TYPE, str ); + } + + if( rc != -1 ) { + ber_slen_t len = ldap_pvt_filter_value_unescape( value ); + + if( len >= 0 ) { + rc = ber_printf( ber, "to", + LDAP_FILTER_EXT_VALUE, value, len ); + } else { + rc = -1; + } + } + + if( rc != -1 ) { + rc = ber_printf( ber, /*"{"*/ "N}" ); + } + } + goto done; + + default: + if( !ldap_is_desc( str ) ) { + goto done; + + } else { + char *nextstar = ldap_pvt_find_wildcard( value ); + + if ( nextstar == NULL ) { + goto done; + + } else if ( *nextstar == '\0' ) { + ftype = LDAP_FILTER_EQUALITY; + + } else if ( strcmp( value, "*" ) == 0 ) { + ftype = LDAP_FILTER_PRESENT; + + } else { + rc = put_substring_filter( ber, str, value ); + goto done; + } + } break; + } + + if( !ldap_is_desc( str ) ) goto done; + + if ( ftype == LDAP_FILTER_PRESENT ) { + rc = ber_printf( ber, "ts", ftype, str ); + + } else { + ber_slen_t len = ldap_pvt_filter_value_unescape( value ); + + if( len >= 0 ) { + rc = ber_printf( ber, "t{soN}", + ftype, str, value, len ); + } + } + +done: + if( rc != -1 ) rc = 0; + LDAP_FREE( str ); + return rc; +} +