1998-08-08 20:43:13 -04:00
|
|
|
/* str2filter.c - parse an rfc 1588 string filter */
|
1999-09-08 15:06:24 -04:00
|
|
|
/* $OpenLDAP$ */
|
1999-08-06 19:07:46 -04:00
|
|
|
/*
|
2000-05-12 22:47:56 -04:00
|
|
|
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
|
1999-08-06 19:07:46 -04:00
|
|
|
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
|
|
|
|
*/
|
1998-08-08 20:43:13 -04:00
|
|
|
|
1998-10-24 21:41:42 -04:00
|
|
|
#include "portable.h"
|
|
|
|
|
|
1998-08-08 20:43:13 -04:00
|
|
|
#include <stdio.h>
|
1998-10-24 21:41:42 -04:00
|
|
|
|
|
|
|
|
#include <ac/string.h>
|
Protoized, moved extern definitions to .h files, fixed related bugs.
Most function and variable definitions are now preceded by its extern
definition, for error checking. Retyped a number of functions, usually
to return void. Fixed a number of printf format errors.
API changes (in ldap/include):
Added avl_dup_ok, avl_prefixapply, removed ber_fatten (probably typo
for ber_flatten), retyped ldap_sort_strcasecmp, grew lutil.h.
A number of `extern' declarations are left (some added by protoize), to
be cleaned away later. Mostly strdup(), strcasecmp(), mktemp(), optind,
optarg, errno.
1998-11-15 17:40:11 -05:00
|
|
|
#include <ac/ctype.h>
|
1998-10-24 21:41:42 -04:00
|
|
|
#include <ac/socket.h>
|
|
|
|
|
|
1998-08-08 20:43:13 -04:00
|
|
|
#include "slap.h"
|
1999-08-30 20:44:49 -04:00
|
|
|
#include <ldap_pvt.h>
|
1998-08-08 20:43:13 -04:00
|
|
|
|
2000-02-14 15:57:34 -05:00
|
|
|
static char *find_matching_paren( const char *s );
|
|
|
|
|
static Filter *str2list( const char *str, long unsigned int ftype);
|
|
|
|
|
static Filter *str2simple( const char *str);
|
|
|
|
|
static int str2subvals( const char *val, Filter *f);
|
1998-08-08 20:43:13 -04:00
|
|
|
|
|
|
|
|
Filter *
|
2000-02-14 15:57:34 -05:00
|
|
|
str2filter( const char *str )
|
1998-08-08 20:43:13 -04:00
|
|
|
{
|
1998-10-23 17:51:32 -04:00
|
|
|
Filter *f = NULL;
|
1999-08-30 20:44:49 -04:00
|
|
|
char *end, *freeme;
|
1998-08-08 20:43:13 -04:00
|
|
|
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "str2filter \"%s\"\n", str, 0, 0 );
|
|
|
|
|
|
|
|
|
|
if ( str == NULL || *str == '\0' ) {
|
|
|
|
|
return( NULL );
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-30 20:44:49 -04:00
|
|
|
str = freeme = ch_strdup( str );
|
|
|
|
|
|
1998-08-08 20:43:13 -04:00
|
|
|
switch ( *str ) {
|
|
|
|
|
case '(':
|
|
|
|
|
if ( (end = find_matching_paren( str )) == NULL ) {
|
|
|
|
|
filter_free( f );
|
1999-08-30 20:44:49 -04:00
|
|
|
free( freeme );
|
1998-08-08 20:43:13 -04:00
|
|
|
return( NULL );
|
|
|
|
|
}
|
|
|
|
|
*end = '\0';
|
|
|
|
|
|
|
|
|
|
str++;
|
|
|
|
|
switch ( *str ) {
|
|
|
|
|
case '&':
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "str2filter: AND\n",
|
|
|
|
|
0, 0, 0 );
|
|
|
|
|
|
|
|
|
|
str++;
|
|
|
|
|
f = str2list( str, LDAP_FILTER_AND );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '|':
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "put_filter: OR\n",
|
|
|
|
|
0, 0, 0 );
|
|
|
|
|
|
|
|
|
|
str++;
|
|
|
|
|
f = str2list( str, LDAP_FILTER_OR );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '!':
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "put_filter: NOT\n",
|
|
|
|
|
0, 0, 0 );
|
|
|
|
|
|
|
|
|
|
str++;
|
|
|
|
|
f = str2list( str, LDAP_FILTER_NOT );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "str2filter: simple\n",
|
|
|
|
|
0, 0, 0 );
|
|
|
|
|
|
|
|
|
|
f = str2simple( str );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*end = ')';
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default: /* assume it's a simple type=value filter */
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "str2filter: default\n", 0, 0,
|
|
|
|
|
0 );
|
|
|
|
|
|
|
|
|
|
f = str2simple( str );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-30 20:44:49 -04:00
|
|
|
free( freeme );
|
1998-08-08 20:43:13 -04:00
|
|
|
return( f );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Put a list of filters like this "(filter1)(filter2)..."
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static Filter *
|
2000-02-14 15:57:34 -05:00
|
|
|
str2list( const char *str, unsigned long ftype )
|
1998-08-08 20:43:13 -04:00
|
|
|
{
|
|
|
|
|
Filter *f;
|
|
|
|
|
Filter **fp;
|
|
|
|
|
char *next;
|
|
|
|
|
char save;
|
|
|
|
|
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "str2list \"%s\"\n", str, 0, 0 );
|
|
|
|
|
|
|
|
|
|
f = (Filter *) ch_calloc( 1, sizeof(Filter) );
|
|
|
|
|
f->f_choice = ftype;
|
|
|
|
|
fp = &f->f_list;
|
|
|
|
|
|
|
|
|
|
while ( *str ) {
|
1999-02-22 12:57:22 -05:00
|
|
|
while ( *str && isspace( (unsigned char) *str ) )
|
1998-08-08 20:43:13 -04:00
|
|
|
str++;
|
|
|
|
|
if ( *str == '\0' )
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if ( (next = find_matching_paren( str )) == NULL ) {
|
|
|
|
|
filter_free( f );
|
|
|
|
|
return( NULL );
|
|
|
|
|
}
|
|
|
|
|
save = *++next;
|
|
|
|
|
*next = '\0';
|
|
|
|
|
|
|
|
|
|
/* now we have "(filter)" with str pointing to it */
|
|
|
|
|
if ( (*fp = str2filter( str )) == NULL ) {
|
|
|
|
|
filter_free( f );
|
|
|
|
|
*next = save;
|
|
|
|
|
return( NULL );
|
|
|
|
|
}
|
|
|
|
|
*next = save;
|
|
|
|
|
|
|
|
|
|
str = next;
|
|
|
|
|
fp = &(*fp)->f_next;
|
|
|
|
|
}
|
|
|
|
|
*fp = NULL;
|
|
|
|
|
|
|
|
|
|
return( f );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Filter *
|
2000-02-14 15:57:34 -05:00
|
|
|
str2simple( const char *str )
|
1998-08-08 20:43:13 -04:00
|
|
|
{
|
|
|
|
|
Filter *f;
|
|
|
|
|
char *s;
|
|
|
|
|
char *value, savechar;
|
|
|
|
|
|
|
|
|
|
Debug( LDAP_DEBUG_FILTER, "str2simple \"%s\"\n", str, 0, 0 );
|
|
|
|
|
|
|
|
|
|
if ( (s = strchr( str, '=' )) == NULL ) {
|
|
|
|
|
return( NULL );
|
|
|
|
|
}
|
2000-02-14 15:57:34 -05:00
|
|
|
value = &s[1];
|
1998-08-08 20:43:13 -04:00
|
|
|
*s-- = '\0';
|
|
|
|
|
savechar = *s;
|
|
|
|
|
|
|
|
|
|
f = (Filter *) ch_calloc( 1, sizeof(Filter) );
|
|
|
|
|
|
|
|
|
|
switch ( *s ) {
|
|
|
|
|
case '<':
|
|
|
|
|
f->f_choice = LDAP_FILTER_LE;
|
|
|
|
|
*s = '\0';
|
|
|
|
|
break;
|
|
|
|
|
case '>':
|
|
|
|
|
f->f_choice = LDAP_FILTER_GE;
|
|
|
|
|
*s = '\0';
|
|
|
|
|
break;
|
|
|
|
|
case '~':
|
|
|
|
|
f->f_choice = LDAP_FILTER_APPROX;
|
|
|
|
|
*s = '\0';
|
|
|
|
|
break;
|
2000-02-14 15:57:34 -05:00
|
|
|
case ':':
|
|
|
|
|
f->f_choice = LDAP_FILTER_EXT;
|
|
|
|
|
*s = '\0';
|
|
|
|
|
break;
|
|
|
|
|
|
1998-08-08 20:43:13 -04:00
|
|
|
default:
|
1999-08-30 20:44:49 -04:00
|
|
|
if ( ldap_pvt_find_wildcard( value ) == NULL ) {
|
1998-08-08 20:43:13 -04:00
|
|
|
f->f_choice = LDAP_FILTER_EQUALITY;
|
|
|
|
|
} else if ( strcmp( value, "*" ) == 0 ) {
|
|
|
|
|
f->f_choice = LDAP_FILTER_PRESENT;
|
|
|
|
|
} else {
|
|
|
|
|
f->f_choice = LDAP_FILTER_SUBSTRINGS;
|
2000-02-14 15:57:34 -05:00
|
|
|
#ifndef SLAPD_SCHEMA_NOT_COMPAT
|
1998-11-27 15:21:54 -05:00
|
|
|
f->f_sub_type = ch_strdup( str );
|
1998-08-08 20:43:13 -04:00
|
|
|
if ( str2subvals( value, f ) != 0 ) {
|
|
|
|
|
filter_free( f );
|
|
|
|
|
*(value-1) = '=';
|
|
|
|
|
return( NULL );
|
|
|
|
|
}
|
|
|
|
|
*(value-1) = '=';
|
|
|
|
|
return( f );
|
2000-02-14 15:57:34 -05:00
|
|
|
#endif
|
1998-08-08 20:43:13 -04:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-14 15:57:34 -05:00
|
|
|
#ifndef SLAPD_SCHEMA_NOT_COMPAT
|
1998-08-08 20:43:13 -04:00
|
|
|
if ( f->f_choice == LDAP_FILTER_PRESENT ) {
|
1998-11-27 15:21:54 -05:00
|
|
|
f->f_type = ch_strdup( str );
|
1998-08-08 20:43:13 -04:00
|
|
|
} else {
|
1998-11-27 15:21:54 -05:00
|
|
|
f->f_avtype = ch_strdup( str );
|
|
|
|
|
f->f_avvalue.bv_val = ch_strdup( value );
|
1999-08-30 20:44:49 -04:00
|
|
|
ldap_pvt_filter_value_unescape( f->f_avvalue.bv_val );
|
1998-08-08 20:43:13 -04:00
|
|
|
f->f_avvalue.bv_len = strlen( value );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*s = savechar;
|
|
|
|
|
*(value-1) = '=';
|
2000-02-14 15:57:34 -05:00
|
|
|
#endif
|
1998-08-08 20:43:13 -04:00
|
|
|
return( f );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2000-02-14 15:57:34 -05:00
|
|
|
str2subvals( const char *in, Filter *f )
|
1998-08-08 20:43:13 -04:00
|
|
|
{
|
2000-02-14 15:57:34 -05:00
|
|
|
char *nextstar, *val, *freeme;
|
1998-08-08 20:43:13 -04:00
|
|
|
int gotstar;
|
|
|
|
|
|
2000-02-14 15:57:34 -05:00
|
|
|
Debug( LDAP_DEBUG_FILTER, "str2subvals \"%s\"\n", in, 0, 0 );
|
1998-08-08 20:43:13 -04:00
|
|
|
|
2000-02-14 15:57:34 -05:00
|
|
|
if( in == NULL ) return 0;
|
2000-01-25 16:13:31 -05:00
|
|
|
|
2000-02-14 15:57:34 -05:00
|
|
|
val = freeme = ch_strdup( in );
|
1998-08-08 20:43:13 -04:00
|
|
|
gotstar = 0;
|
2000-01-25 16:13:31 -05:00
|
|
|
|
|
|
|
|
while ( *val ) {
|
1999-08-30 20:44:49 -04:00
|
|
|
if ( (nextstar = ldap_pvt_find_wildcard( val )) != NULL )
|
1998-08-08 20:43:13 -04:00
|
|
|
*nextstar++ = '\0';
|
|
|
|
|
|
1999-08-30 20:44:49 -04:00
|
|
|
ldap_pvt_filter_value_unescape( val );
|
2000-01-25 16:13:31 -05:00
|
|
|
|
1998-08-08 20:43:13 -04:00
|
|
|
if ( gotstar == 0 ) {
|
2000-01-25 16:13:31 -05:00
|
|
|
f->f_sub_initial = ber_bvstrdup( val );
|
|
|
|
|
|
1998-08-08 20:43:13 -04:00
|
|
|
} else if ( nextstar == NULL ) {
|
2000-01-25 16:13:31 -05:00
|
|
|
f->f_sub_final = ber_bvstrdup( val );
|
|
|
|
|
|
1998-08-08 20:43:13 -04:00
|
|
|
} else {
|
2000-01-25 16:13:31 -05:00
|
|
|
charray_add( (char ***) &f->f_sub_any, (char *) ber_bvstrdup( val ) );
|
1998-08-08 20:43:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gotstar = 1;
|
|
|
|
|
val = nextstar;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-30 20:44:49 -04:00
|
|
|
free( freeme );
|
1998-08-08 20:43:13 -04:00
|
|
|
return( 0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* find_matching_paren - return a pointer to the right paren in s matching
|
|
|
|
|
* the left paren to which *s currently points
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static char *
|
2000-02-14 15:57:34 -05:00
|
|
|
find_matching_paren( const char *s )
|
1998-08-08 20:43:13 -04:00
|
|
|
{
|
|
|
|
|
int balance, escape;
|
|
|
|
|
|
|
|
|
|
balance = 0;
|
|
|
|
|
escape = 0;
|
|
|
|
|
for ( ; *s; s++ ) {
|
|
|
|
|
if ( escape == 0 ) {
|
|
|
|
|
if ( *s == '(' )
|
|
|
|
|
balance++;
|
|
|
|
|
else if ( *s == ')' )
|
|
|
|
|
balance--;
|
|
|
|
|
}
|
|
|
|
|
if ( balance == 0 ) {
|
2000-02-14 15:57:34 -05:00
|
|
|
return (char *) s;
|
1998-08-08 20:43:13 -04:00
|
|
|
}
|
|
|
|
|
if ( *s == '\\' && ! escape )
|
|
|
|
|
escape = 1;
|
|
|
|
|
else
|
|
|
|
|
escape = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-14 15:57:34 -05:00
|
|
|
return NULL;
|
1998-08-08 20:43:13 -04:00
|
|
|
}
|