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 );