X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-ldap%2Fsearch.c;h=094d76ec424a6910565514df592667e29972d1a3;hb=f9e417a2634a6681941772ed488ffaff47f33a4c;hp=0b569fe2f13064612277c8837dd45fd65057f260;hpb=569344fb86fd1e7b4b304598839c157aa92e5447;p=openldap
diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c
index 0b569fe2f1..094d76ec42 100644
--- a/servers/slapd/back-ldap/search.c
+++ b/servers/slapd/back-ldap/search.c
@@ -2,7 +2,7 @@
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software .
*
- * Copyright 1999-2011 The OpenLDAP Foundation.
+ * Copyright 1999-2013 The OpenLDAP Foundation.
* Portions Copyright 1999-2003 Howard Chu.
* Portions Copyright 2000-2003 Pierangelo Masarati.
* All rights reserved.
@@ -40,77 +40,57 @@ ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent,
struct berval *bdn );
/*
- * Quick'n'dirty rewrite of filter in case of error, to deal with
- * .
+ * replaces (&) with (objectClass=*) and (|) with (!(objectClass=*))
+ * as the best replacement for RFC 4526 absolute true/absolute false
+ * filters; the only difference (AFAIK) is that they require search
+ * access to objectClass.
+ *
+ * filter->bv_val may be alloc'd on the thread's slab, if equal to
+ * op->ors_filterstr.bv_val, or realloc'd on the thread's slab otherwise.
*/
static int
ldap_back_munge_filter(
Operation *op,
- struct berval *filter,
- int *freeit )
+ struct berval *filter )
{
- ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
-
- char *ptr;
- int gotit = 0;
+ char *ptr;
+ int gotit = 0;
Debug( LDAP_DEBUG_ARGS, "=> ldap_back_munge_filter \"%s\"\n",
filter->bv_val, 0, 0 );
- for ( ptr = strstr( filter->bv_val, "(?=" );
+ for ( ptr = strchr( filter->bv_val, '(' );
ptr;
- ptr = strstr( ptr, "(?=" ) )
+ ptr = strchr( ptr, '(' ) )
{
static struct berval
- bv_true = BER_BVC( "(?=true)" ),
- bv_false = BER_BVC( "(?=false)" ),
- bv_undefined = BER_BVC( "(?=undefined)" ),
bv_t = BER_BVC( "(&)" ),
bv_f = BER_BVC( "(|)" ),
bv_T = BER_BVC( "(objectClass=*)" ),
bv_F = BER_BVC( "(!(objectClass=*))" );
- struct berval *oldbv = NULL,
- *newbv = NULL,
- oldfilter = BER_BVNULL;
-
- if ( strncmp( ptr, bv_true.bv_val, bv_true.bv_len ) == 0 ) {
- oldbv = &bv_true;
- if ( LDAP_BACK_T_F( li ) ) {
- newbv = &bv_t;
+ struct berval *oldbv = NULL,
+ *newbv = NULL,
+ oldfilter = BER_BVNULL;
- } else {
- newbv = &bv_T;
- }
-
- } else if ( strncmp( ptr, bv_false.bv_val, bv_false.bv_len ) == 0 )
- {
- oldbv = &bv_false;
- if ( LDAP_BACK_T_F( li ) ) {
- newbv = &bv_f;
-
- } else {
- newbv = &bv_F;
- }
+ if ( ptr[2] != ')' ) {
+ ptr++;
+ continue;
+ }
- } else if ( strncmp( ptr, bv_undefined.bv_val, bv_undefined.bv_len ) == 0 )
- {
- /* if undef or invalid filter is not allowed,
- * don't rewrite filter */
- if ( LDAP_BACK_NOUNDEFFILTER( li ) ) {
- if ( filter->bv_val != op->ors_filterstr.bv_val ) {
- op->o_tmpfree( filter->bv_val, op->o_tmpmemctx );
- }
- BER_BVZERO( filter );
- gotit = -1;
- goto done;
- }
+ switch ( ptr[1] ) {
+ case '&':
+ oldbv = &bv_t;
+ newbv = &bv_T;
+ break;
- oldbv = &bv_undefined;
+ case '|':
+ oldbv = &bv_f;
newbv = &bv_F;
+ break;
- } else {
- gotit = 0;
- goto done;
+ default:
+ /* should be an error */
+ continue;
}
oldfilter = *filter;
@@ -120,9 +100,8 @@ ldap_back_munge_filter(
op->o_tmpmemctx );
AC_MEMCPY( filter->bv_val, op->ors_filterstr.bv_val,
- op->ors_filterstr.bv_len + 1 );
+ ptr - oldfilter.bv_val );
- *freeit = 1;
} else {
filter->bv_val = op->o_tmprealloc( filter->bv_val,
filter->bv_len + 1, op->o_tmpmemctx );
@@ -136,10 +115,10 @@ ldap_back_munge_filter(
AC_MEMCPY( ptr, newbv->bv_val, newbv->bv_len );
ptr += newbv->bv_len;
- gotit = 1;
+
+ gotit++;
}
-done:;
Debug( LDAP_DEBUG_ARGS, "<= ldap_back_munge_filter \"%s\" (%d)\n",
filter->bv_val, gotit, 0 );
@@ -162,13 +141,12 @@ ldap_back_search(
msgid;
struct berval match = BER_BVNULL,
filter = BER_BVNULL;
- int i;
+ int i, x;
char **attrs = NULL;
- int freetext = 0, freefilter = 0;
+ int freetext = 0, filter_undef = 0;
int do_retry = 1, dont_retry = 0;
LDAPControl **ctrls = NULL;
char **references = NULL;
- void *matchctx = NULL;
rs_assert_ready( rs );
rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */
@@ -191,22 +169,48 @@ ldap_back_search(
LDAP_BACK_TV_SET( &tv );
}
+ i = 0;
if ( op->ors_attrs ) {
- for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ )
+ for ( ; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ )
/* just count attrs */ ;
+ }
- attrs = op->o_tmpalloc( ( i + 1 )*sizeof( char * ),
+ x = 0;
+ if ( op->o_bd->be_extra_anlist ) {
+ for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ )
+ /* just count attrs */ ;
+ }
+
+ if ( i > 0 || x > 0 ) {
+ int j = 0;
+
+ attrs = op->o_tmpalloc( ( i + x + 1 )*sizeof( char * ),
op->o_tmpmemctx );
if ( attrs == NULL ) {
rs->sr_err = LDAP_NO_MEMORY;
rc = -1;
goto finish;
}
-
- for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) {
- attrs[ i ] = op->ors_attrs[i].an_name.bv_val;
+
+ if ( i > 0 ) {
+ for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++, j++ ) {
+ attrs[ j ] = op->ors_attrs[i].an_name.bv_val;
+ }
+ }
+
+ if ( x > 0 ) {
+ for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++, j++ ) {
+ if ( op->o_bd->be_extra_anlist[x].an_desc &&
+ ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, op->ors_attrs ) )
+ {
+ continue;
+ }
+
+ attrs[ j ] = op->o_bd->be_extra_anlist[x].an_name.bv_val;
+ }
}
- attrs[ i ] = NULL;
+
+ attrs[ j ] = NULL;
}
ctrls = op->o_ctrls;
@@ -218,12 +222,24 @@ ldap_back_search(
/* deal with filters */
filter = op->ors_filterstr;
retry:
+ /* this goes after retry because ldap_back_munge_filter()
+ * optionally replaces RFC 4526 T-F filters (&) (|)
+ * if already computed, they will be re-installed
+ * by filter2bv_undef_x() later */
+ if ( !LDAP_BACK_T_F( li ) ) {
+ ldap_back_munge_filter( op, &filter );
+ }
+
rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val,
op->ors_scope, filter.bv_val,
attrs, op->ors_attrsonly, ctrls, NULL,
tv.tv_sec ? &tv : NULL,
op->ors_slimit, op->ors_deref, &msgid );
+ ldap_pvt_thread_mutex_lock( &li->li_counter_mutex );
+ ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_SEARCH ], 1 );
+ ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex );
+
if ( rs->sr_err != LDAP_SUCCESS ) {
switch ( rs->sr_err ) {
case LDAP_SERVER_DOWN:
@@ -245,7 +261,14 @@ retry:
goto finish;
case LDAP_FILTER_ERROR:
- if (ldap_back_munge_filter( op, &filter, &freefilter ) > 0 ) {
+ /* first try? */
+ if ( !filter_undef &&
+ strstr( filter.bv_val, "(?" ) &&
+ !LDAP_BACK_NOUNDEFFILTER( li ) )
+ {
+ BER_BVZERO( &filter );
+ filter2bv_undef_x( op, op->ors_filter, 1, &filter );
+ filter_undef = 1;
goto retry;
}
@@ -531,16 +554,25 @@ retry:
}
}
- if ( rc == -1 && dont_retry == 0 ) {
- if ( do_retry ) {
- do_retry = 0;
- if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
- goto retry;
+ if ( rc == -1 ) {
+ if ( dont_retry == 0 ) {
+ if ( do_retry ) {
+ do_retry = 0;
+ if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
+ goto retry;
+ }
}
+
+ rs->sr_err = LDAP_SERVER_DOWN;
+ rs->sr_err = slap_map_api2result( rs );
+ goto finish;
+
+ } else if ( LDAP_BACK_ONERR_STOP( li ) ) {
+ /* if onerr == STOP */
+ rs->sr_err = LDAP_SERVER_DOWN;
+ rs->sr_err = slap_map_api2result( rs );
+ goto finish;
}
- rs->sr_err = LDAP_SERVER_DOWN;
- rs->sr_err = slap_map_api2result( rs );
- goto finish;
}
/*
@@ -549,24 +581,28 @@ retry:
if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) {
struct berval pmatch;
- if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) == LDAP_SUCCESS ) {
- ber_memfree( match.bv_val );
- matchctx = op->o_tmpmemctx;
- match.bv_val = pmatch.bv_val;
+ if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) != LDAP_SUCCESS ) {
+ pmatch.bv_val = match.bv_val;
+ match.bv_val = NULL;
}
- rs->sr_matched = match.bv_val;
+ rs->sr_matched = pmatch.bv_val;
+ rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
+ }
+
+finish:;
+ if ( !BER_BVISNULL( &match ) ) {
+ ber_memfree( match.bv_val );
}
if ( rs->sr_v2ref ) {
rs->sr_err = LDAP_REFERRAL;
}
-finish:;
if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs );
}
- if ( freefilter && filter.bv_val != op->ors_filterstr.bv_val ) {
+ if ( filter.bv_val != op->ors_filterstr.bv_val ) {
op->o_tmpfree( filter.bv_val, op->o_tmpmemctx );
}
@@ -585,11 +621,6 @@ finish:;
rs->sr_ctrls = NULL;
}
- if ( match.bv_val ) {
- ber_memfree_x( match.bv_val, matchctx );
- }
- rs->sr_matched = NULL;
-
if ( rs->sr_text ) {
if ( freetext ) {
ber_memfree( (char *)rs->sr_text );