X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fback-ldap%2Fsearch.c;h=85c334f9c98315df16e4eeae8aa1e08eca89b702;hb=99e2e5d8866aa0726f55726ee472b2d1a225005b;hp=3a16c4d8185125c55d23f5a84d140a7bb80a0091;hpb=be53e8265065e7de61a0996e37732f44e22fdec7;p=openldap diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 3a16c4d818..85c334f9c9 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -64,6 +64,7 @@ ldap_back_munge_filter( 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=*)" ), @@ -91,13 +92,18 @@ ldap_back_munge_filter( newbv = &bv_F; } + } else if ( strncmp( ptr, bv_undefined.bv_val, bv_undefined.bv_len ) == 0 ) + { + oldbv = &bv_undefined; + newbv = &bv_F; + } else { gotit = 0; goto done; } oldfilter = *filter; - if ( !( li->flags & LDAP_BACK_F_SUPPORT_T_F ) ) { + if ( newbv->bv_len > oldbv->bv_len ) { filter->bv_len += newbv->bv_len - oldbv->bv_len; if ( filter->bv_val == op->ors_filterstr.bv_val ) { filter->bv_val = op->o_tmpalloc( filter->bv_len + 1, @@ -137,6 +143,7 @@ ldap_back_search( { struct ldapconn *lc; struct timeval tv; + time_t stoptime; LDAPMessage *res, *e; int rc = 0, @@ -145,12 +152,12 @@ ldap_back_search( filter = BER_BVNULL; int i; char **attrs = NULL; - int dontfreetext = 0; + int freetext = 0; int do_retry = 1; LDAPControl **ctrls = NULL; lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR ); - if ( !lc ) { + if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } @@ -158,9 +165,6 @@ ldap_back_search( * FIXME: in case of values return filter, we might want * to map attrs and maybe rewrite value */ - if ( !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) { - return rs->sr_err; - } /* should we check return values? */ if ( op->ors_deref != -1 ) { @@ -171,6 +175,7 @@ ldap_back_search( if ( op->ors_tlimit != SLAP_NO_LIMIT ) { tv.tv_sec = op->ors_tlimit; tv.tv_usec = 0; + stoptime = op->o_time + op->ors_tlimit; } else { tv.tv_sec = 0; @@ -196,7 +201,6 @@ ldap_back_search( ctrls = op->o_ctrls; rc = ldap_back_proxy_authz_ctrl( lc, op, rs, &ctrls ); if ( rc != LDAP_SUCCESS ) { - dontfreetext = 1; goto finish; } @@ -250,6 +254,9 @@ fail:; { /* check for abandon */ if ( op->o_abandon ) { + if ( rc > 0 ) { + ldap_msgfree( res ); + } ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL ); rc = SLAPD_ABANDON; goto finish; @@ -260,16 +267,25 @@ fail:; tv.tv_usec = 100000; ldap_pvt_thread_yield(); + /* check time limit */ + if ( op->ors_tlimit != SLAP_NO_LIMIT + && slap_get_time() > stoptime ) + { + ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL ); + rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; + goto finish; + } + } else if ( rc == LDAP_RES_SEARCH_ENTRY ) { - Entry ent = {0}; - struct berval bdn; + Entry ent = { 0 }; + struct berval bdn = BER_BVNULL; int abort = 0; do_retry = 0; e = ldap_first_entry( lc->lc_ld, res ); rc = ldap_build_entry( op, e, &ent, &bdn ); - if ( rc == LDAP_SUCCESS ) { + if ( rc == LDAP_SUCCESS ) { rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; @@ -294,7 +310,6 @@ fail:; } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) { char **references = NULL; - int cnt; do_retry = 0; rc = ldap_parse_reference( lc->lc_ld, res, @@ -304,21 +319,31 @@ fail:; continue; } - if ( references == NULL ) { - continue; - } + /* FIXME: there MUST be at least one */ + if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) { + int cnt; - for ( cnt = 0; references[ cnt ]; cnt++ ) - /* NO OP */ ; - - rs->sr_ref = ch_calloc( cnt + 1, sizeof( struct berval ) ); + for ( cnt = 0; references[ cnt ]; cnt++ ) + /* NO OP */ ; - for ( cnt = 0; references[ cnt ]; cnt++ ) { - ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] ); - } + /* FIXME: there MUST be at least one */ + rs->sr_ref = ch_malloc( ( cnt + 1 ) * sizeof( struct berval ) ); - /* ignore return value by now */ - ( void )send_search_reference( op, rs ); + for ( cnt = 0; references[ cnt ]; cnt++ ) { + ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] ); + } + BER_BVZERO( &rs->sr_ref[ cnt ] ); + + /* ignore return value by now */ + ( void )send_search_reference( op, rs ); + + } else { + Debug( LDAP_DEBUG_ANY, + "%s ldap_back_search: " + "got SEARCH_REFERENCE " + "with no referrals\n", + op->o_log_prefix, 0, 0 ); + } /* cleanup */ if ( references ) { @@ -338,27 +363,40 @@ fail:; rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, &match.bv_val, (char **)&rs->sr_text, &references, &rs->sr_ctrls, 1 ); + freetext = 1; if ( rc != LDAP_SUCCESS ) { rs->sr_err = rc; } rs->sr_err = slap_map_api2result( rs ); - if ( references ) { + if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) { int cnt; + if ( rs->sr_err != LDAP_REFERRAL ) { + /* FIXME: error */ + Debug( LDAP_DEBUG_ANY, + "%s ldap_back_search: " + "got referrals with %d\n", + op->o_log_prefix, + rs->sr_err, 0 ); + rs->sr_err = LDAP_REFERRAL; + } + for ( cnt = 0; references[ cnt ]; cnt++ ) /* NO OP */ ; - rs->sr_ref = ch_calloc( cnt + 1, sizeof( struct berval ) ); + rs->sr_ref = ch_malloc( ( cnt + 1 ) * sizeof( struct berval ) ); for ( cnt = 0; references[ cnt ]; cnt++ ) { + /* duplicating ...*/ ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] ); } + BER_BVZERO( &rs->sr_ref[ cnt ] ); + } - /* cleanup */ - if ( references ) { - ldap_value_free( references ); - } + /* cleanup */ + if ( references ) { + ldap_value_free( references ); } rc = 0; @@ -383,6 +421,7 @@ fail:; if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) { rs->sr_matched = match.bv_val; } + if ( rs->sr_v2ref ) { rs->sr_err = LDAP_REFERRAL; } @@ -409,7 +448,7 @@ finish:; } if ( rs->sr_text ) { - if ( !dontfreetext ) { + if ( freetext ) { LDAP_FREE( (char *)rs->sr_text ); } rs->sr_text = NULL; @@ -424,6 +463,10 @@ finish:; ch_free( attrs ); } + if ( lc != NULL ) { + ldap_back_release_conn( op, rs, lc ); + } + return rc; } @@ -441,7 +484,7 @@ ldap_build_entry( int last; /* safe assumptions ... */ - assert( ent ); + assert( ent != NULL ); BER_BVZERO( &ent->e_bv ); if ( ber_scanf( &ber, "{m{", bdn ) == LBER_ERROR ) { @@ -705,6 +748,10 @@ cleanup: ch_free( filter ); } + if ( lc != NULL ) { + ldap_back_release_conn( op, &rs, lc ); + } + return rc; }