1 /* search.c - ldap backend search function */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1999-2011 The OpenLDAP Foundation.
6 * Portions Copyright 1999-2003 Howard Chu.
7 * Portions Copyright 2000-2003 Pierangelo Masarati.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
19 * This work was initially developed by the Howard Chu for inclusion
20 * in OpenLDAP Software and subsequently enhanced by Pierangelo
28 #include <ac/socket.h>
29 #include <ac/string.h>
33 #include "back-ldap.h"
34 #undef ldap_debug /* silence a warning in ldap-int.h */
35 #include "../../../libraries/libldap/ldap-int.h"
40 ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent,
44 * Quick'n'dirty rewrite of filter in case of error, to deal with
45 * <draft-zeilenga-ldap-t-f>.
48 ldap_back_munge_filter(
50 struct berval *filter,
53 ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
58 Debug( LDAP_DEBUG_ARGS, "=> ldap_back_munge_filter \"%s\"\n",
59 filter->bv_val, 0, 0 );
61 for ( ptr = strstr( filter->bv_val, "(?=" );
63 ptr = strstr( ptr, "(?=" ) )
66 bv_true = BER_BVC( "(?=true)" ),
67 bv_false = BER_BVC( "(?=false)" ),
68 bv_undefined = BER_BVC( "(?=undefined)" ),
69 bv_t = BER_BVC( "(&)" ),
70 bv_f = BER_BVC( "(|)" ),
71 bv_T = BER_BVC( "(objectClass=*)" ),
72 bv_F = BER_BVC( "(!(objectClass=*))" );
73 struct berval *oldbv = NULL,
75 oldfilter = BER_BVNULL;
77 if ( strncmp( ptr, bv_true.bv_val, bv_true.bv_len ) == 0 ) {
79 if ( LDAP_BACK_T_F( li ) ) {
86 } else if ( strncmp( ptr, bv_false.bv_val, bv_false.bv_len ) == 0 )
89 if ( LDAP_BACK_T_F( li ) ) {
96 } else if ( strncmp( ptr, bv_undefined.bv_val, bv_undefined.bv_len ) == 0 )
98 /* if undef or invalid filter is not allowed,
99 * don't rewrite filter */
100 if ( LDAP_BACK_NOUNDEFFILTER( li ) ) {
101 if ( filter->bv_val != op->ors_filterstr.bv_val ) {
102 op->o_tmpfree( filter->bv_val, op->o_tmpmemctx );
104 BER_BVZERO( filter );
109 oldbv = &bv_undefined;
118 filter->bv_len += newbv->bv_len - oldbv->bv_len;
119 if ( filter->bv_val == op->ors_filterstr.bv_val ) {
120 filter->bv_val = op->o_tmpalloc( filter->bv_len + 1,
123 AC_MEMCPY( filter->bv_val, op->ors_filterstr.bv_val,
124 op->ors_filterstr.bv_len + 1 );
128 filter->bv_val = op->o_tmprealloc( filter->bv_val,
129 filter->bv_len + 1, op->o_tmpmemctx );
132 ptr = filter->bv_val + ( ptr - oldfilter.bv_val );
134 AC_MEMCPY( &ptr[ newbv->bv_len ],
135 &ptr[ oldbv->bv_len ],
136 oldfilter.bv_len - ( ptr - filter->bv_val ) - oldbv->bv_len + 1 );
137 AC_MEMCPY( ptr, newbv->bv_val, newbv->bv_len );
139 ptr += newbv->bv_len;
144 Debug( LDAP_DEBUG_ARGS, "<= ldap_back_munge_filter \"%s\" (%d)\n",
145 filter->bv_val, gotit, 0 );
155 ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
157 ldapconn_t *lc = NULL;
159 time_t stoptime = (time_t)(-1);
164 struct berval match = BER_BVNULL,
168 int freetext = 0, freefilter = 0;
169 int do_retry = 1, dont_retry = 0;
170 LDAPControl **ctrls = NULL;
171 char **references = NULL;
172 void *matchctx = NULL;
174 if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
179 * FIXME: in case of values return filter, we might want
180 * to map attrs and maybe rewrite value
183 if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
184 tv.tv_sec = op->ors_tlimit;
186 stoptime = op->o_time + op->ors_tlimit;
189 LDAP_BACK_TV_SET( &tv );
192 if ( op->ors_attrs ) {
193 for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ )
194 /* just count attrs */ ;
196 attrs = op->o_tmpalloc( ( i + 1 )*sizeof( char * ),
198 if ( attrs == NULL ) {
199 rs->sr_err = LDAP_NO_MEMORY;
204 for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) {
205 attrs[ i ] = op->ors_attrs[i].an_name.bv_val;
211 rc = ldap_back_controls_add( op, rs, lc, &ctrls );
212 if ( rc != LDAP_SUCCESS ) {
216 /* deal with <draft-zeilenga-ldap-t-f> filters */
217 filter = op->ors_filterstr;
219 rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val,
220 op->ors_scope, filter.bv_val,
221 attrs, op->ors_attrsonly, ctrls, NULL,
222 tv.tv_sec ? &tv : NULL,
223 op->ors_slimit, op->ors_deref, &msgid );
225 if ( rs->sr_err != LDAP_SUCCESS ) {
226 switch ( rs->sr_err ) {
227 case LDAP_SERVER_DOWN:
230 if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
236 /* reset by ldap_back_retry ... */
237 rs->sr_err = slap_map_api2result( rs );
240 rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND );
245 case LDAP_FILTER_ERROR:
246 if (ldap_back_munge_filter( op, &filter, &freefilter ) > 0 ) {
250 /* invalid filters return success with no data */
251 rs->sr_err = LDAP_SUCCESS;
256 rs->sr_err = slap_map_api2result( rs );
262 /* if needed, initialize timeout */
263 if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
264 if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
265 tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
270 /* We pull apart the ber result, stuff it into a slapd entry, and
271 * let send_search_entry stuff it back into ber format. Slow & ugly,
272 * but this is necessary for version matching, and for ACL processing.
275 for ( rc = -2; rc != -1; rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ONE, &tv, &res ) )
277 /* check for abandon */
278 if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( lc ) ) {
282 (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
287 if ( rc == 0 || rc == -2 ) {
288 ldap_pvt_thread_yield();
291 if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
293 (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
294 rs->sr_text = "Operation timed out";
295 rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
296 LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
301 LDAP_BACK_TV_SET( &tv );
304 /* check time limit */
305 if ( op->ors_tlimit != SLAP_NO_LIMIT
306 && slap_get_time() > stoptime )
308 (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
309 rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
315 /* only touch when activity actually took place... */
316 if ( li->li_idle_timeout && lc ) {
317 lc->lc_time = op->o_time;
320 /* don't retry any more */
325 if ( rc == LDAP_RES_SEARCH_ENTRY ) {
327 struct berval bdn = BER_BVNULL;
331 e = ldap_first_entry( lc->lc_ld, res );
332 rc = ldap_build_entry( op, e, &ent, &bdn );
333 if ( rc == LDAP_SUCCESS ) {
334 ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
336 rs->sr_attrs = op->ors_attrs;
337 rs->sr_operational_attrs = NULL;
339 rs->sr_err = LDAP_SUCCESS;
340 rc = rs->sr_err = send_search_entry( op, rs );
341 if ( rs->sr_ctrls ) {
342 ldap_controls_free( rs->sr_ctrls );
346 if ( !BER_BVISNULL( &ent.e_name ) ) {
347 assert( ent.e_name.bv_val != bdn.bv_val );
348 op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );
349 BER_BVZERO( &ent.e_name );
351 if ( !BER_BVISNULL( &ent.e_nname ) ) {
352 op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx );
353 BER_BVZERO( &ent.e_nname );
360 case LDAP_INSUFFICIENT_ACCESS:
364 if ( rc == LDAP_UNAVAILABLE ) {
365 rc = rs->sr_err = LDAP_OTHER;
367 (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
372 } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
373 if ( LDAP_BACK_NOREFS( li ) ) {
379 rc = ldap_parse_reference( lc->lc_ld, res,
380 &references, &rs->sr_ctrls, 1 );
382 if ( rc != LDAP_SUCCESS ) {
386 /* FIXME: there MUST be at least one */
387 if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
390 for ( cnt = 0; references[ cnt ]; cnt++ )
393 /* FIXME: there MUST be at least one */
394 rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
397 for ( cnt = 0; references[ cnt ]; cnt++ ) {
398 ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
400 BER_BVZERO( &rs->sr_ref[ cnt ] );
402 /* ignore return value by now */
404 ( void )send_search_reference( op, rs );
407 Debug( LDAP_DEBUG_ANY,
408 "%s ldap_back_search: "
409 "got SEARCH_REFERENCE "
410 "with no referrals\n",
411 op->o_log_prefix, 0, 0 );
416 ber_memvfree( (void **)references );
417 op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
422 if ( rs->sr_ctrls ) {
423 ldap_controls_free( rs->sr_ctrls );
427 } else if ( rc == LDAP_RES_INTERMEDIATE ) {
428 /* FIXME: response controls
429 * are passed without checks */
430 rc = ldap_parse_intermediate( lc->lc_ld,
432 (char **)&rs->sr_rspoid,
436 if ( rc != LDAP_SUCCESS ) {
440 slap_send_ldap_intermediate( op, rs );
442 if ( rs->sr_rspoid != NULL ) {
443 ber_memfree( (char *)rs->sr_rspoid );
444 rs->sr_rspoid = NULL;
447 if ( rs->sr_rspdata != NULL ) {
448 ber_bvfree( rs->sr_rspdata );
449 rs->sr_rspdata = NULL;
452 if ( rs->sr_ctrls != NULL ) {
453 ldap_controls_free( rs->sr_ctrls );
460 rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
462 &references, &rs->sr_ctrls, 1 );
463 if ( rc == LDAP_SUCCESS ) {
471 rs->sr_err = slap_map_api2result( rs );
473 /* RFC 4511: referrals can only appear
474 * if result code is LDAP_REFERRAL */
477 && references[ 0 ][ 0 ] )
479 if ( rs->sr_err != LDAP_REFERRAL ) {
480 Debug( LDAP_DEBUG_ANY,
481 "%s ldap_back_search: "
482 "got referrals with err=%d\n",
489 for ( cnt = 0; references[ cnt ]; cnt++ )
492 rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
495 for ( cnt = 0; references[ cnt ]; cnt++ ) {
497 ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
499 BER_BVZERO( &rs->sr_ref[ cnt ] );
502 } else if ( rs->sr_err == LDAP_REFERRAL ) {
503 Debug( LDAP_DEBUG_ANY,
504 "%s ldap_back_search: "
505 "got err=%d with null "
506 "or empty referrals\n",
510 rs->sr_err = LDAP_NO_SUCH_OBJECT;
513 if ( match.bv_val != NULL ) {
514 match.bv_len = strlen( match.bv_val );
521 /* if needed, restore timeout */
522 if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
523 if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
524 tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
530 if ( rc == -1 && dont_retry == 0 ) {
533 if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
537 rs->sr_err = LDAP_SERVER_DOWN;
538 rs->sr_err = slap_map_api2result( rs );
543 * Rewrite the matched portion of the search base, if required
545 if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) {
546 struct berval pmatch;
548 if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) == LDAP_SUCCESS ) {
549 ber_memfree( match.bv_val );
550 matchctx = op->o_tmpmemctx;
551 match.bv_val = pmatch.bv_val;
553 rs->sr_matched = match.bv_val;
556 if ( rs->sr_v2ref ) {
557 rs->sr_err = LDAP_REFERRAL;
561 if ( LDAP_BACK_QUARANTINE( li ) ) {
562 ldap_back_quarantine( op, rs );
565 if ( freefilter && filter.bv_val != op->ors_filterstr.bv_val ) {
566 op->o_tmpfree( filter.bv_val, op->o_tmpmemctx );
570 /* let send_ldap_result play cleanup handlers (ITS#4645) */
571 if ( rc != SLAPD_ABANDON )
574 send_ldap_result( op, rs );
577 (void)ldap_back_controls_free( op, rs, &ctrls );
579 if ( rs->sr_ctrls ) {
580 ldap_controls_free( rs->sr_ctrls );
584 if ( match.bv_val ) {
585 ber_memfree_x( match.bv_val, matchctx );
587 rs->sr_matched = NULL;
591 ber_memfree( (char *)rs->sr_text );
597 op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
602 ber_memvfree( (void **)references );
606 op->o_tmpfree( attrs, op->o_tmpmemctx );
610 ldap_back_release_conn( li, lc );
624 BerElement ber = *ldap_get_message_ber( e );
625 Attribute *attr, **attrp;
631 /* safe assumptions ... */
632 assert( ent != NULL );
633 BER_BVZERO( &ent->e_bv );
635 if ( ber_scanf( &ber, "{m", bdn ) == LBER_ERROR ) {
636 return LDAP_DECODING_ERROR;
640 * Note: this may fail if the target host(s) schema differs
641 * from the one known to the meta, and a DN with unknown
642 * attributes is returned.
644 * FIXME: should we log anything, or delegate to dnNormalize?
646 /* Note: if the distinguished values or the naming attributes
647 * change, should we massage them as well?
649 if ( dnPrettyNormal( NULL, bdn, &ent->e_name, &ent->e_nname,
650 op->o_tmpmemctx ) != LDAP_SUCCESS )
652 return LDAP_INVALID_DN_SYNTAX;
656 if ( ber_first_element( &ber, &len, &lastb ) != LBER_SEQUENCE ) {
660 attrp = &ent->e_attrs;
661 while ( ber_next_element( &ber, &len, lastb ) == LBER_SEQUENCE &&
662 ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
664 slap_syntax_validate_func *validate;
665 slap_syntax_transform_func *pretty;
667 attr = attr_alloc( NULL );
668 if ( attr == NULL ) {
671 if ( slap_bv2ad( &a, &attr->a_desc, &text )
674 if ( slap_bv2undef_ad( &a, &attr->a_desc, &text,
675 SLAP_AD_PROXIED ) != LDAP_SUCCESS )
677 Debug( LDAP_DEBUG_ANY,
678 "%s ldap_build_entry: "
679 "slap_bv2undef_ad(%s): %s\n",
680 op->o_log_prefix, a.bv_val, text );
682 ( void )ber_scanf( &ber, "x" /* [W] */ );
688 /* no subschemaSubentry */
689 if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
690 || attr->a_desc == slap_schema.si_ad_entryDN )
694 * We eat target's subschemaSubentry because
695 * a search for this value is likely not
696 * to resolve to the appropriate backend;
697 * later, the local subschemaSubentry is
700 * We also eat entryDN because the frontend
701 * will reattach it without checking if already
704 ( void )ber_scanf( &ber, "x" /* [W] */ );
709 if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
710 || attr->a_vals == NULL )
713 * Note: attr->a_vals can be null when using
714 * values result filter
716 attr->a_vals = (struct berval *)&slap_dummy_bv;
719 validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
720 pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;
722 if ( !validate && !pretty ) {
723 attr->a_nvals = NULL;
728 for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) ;
732 * check that each value is valid per syntax
733 * and pretty if appropriate
735 for ( i = 0; i<last; i++ ) {
740 rc = ordered_value_pretty( attr->a_desc,
741 &attr->a_vals[i], &pval, NULL );
744 rc = ordered_value_validate( attr->a_desc,
745 &attr->a_vals[i], 0 );
748 if ( rc != LDAP_SUCCESS ) {
751 /* check if, by chance, it's an undefined objectClass */
752 if ( attr->a_desc == slap_schema.si_ad_objectClass &&
753 ( oc = oc_bvfind_undef( &attr->a_vals[i] ) ) != NULL )
755 ber_dupbv( &pval, &oc->soc_cname );
759 ber_memfree( attr->a_vals[i].bv_val );
761 BER_BVZERO( &attr->a_vals[i] );
764 attr->a_vals[i] = attr->a_vals[last];
765 BER_BVZERO( &attr->a_vals[last] );
770 if ( rc == LDAP_SUCCESS && pretty ) {
771 ber_memfree( attr->a_vals[i].bv_val );
772 attr->a_vals[i] = pval;
775 attr->a_numvals = last = i;
776 if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
777 attr->a_nvals = NULL;
782 if ( last && attr->a_desc->ad_type->sat_equality &&
783 attr->a_desc->ad_type->sat_equality->smr_normalize )
785 attr->a_nvals = ch_malloc( ( last + 1 )*sizeof( struct berval ) );
786 for ( i = 0; i < last; i++ ) {
789 rc = ordered_value_normalize(
790 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
792 attr->a_desc->ad_type->sat_equality,
793 &attr->a_vals[i], &attr->a_nvals[i],
796 if ( rc != LDAP_SUCCESS ) {
797 ber_memfree( attr->a_vals[i].bv_val );
799 BER_BVZERO( &attr->a_vals[i] );
802 attr->a_vals[i] = attr->a_vals[last];
803 BER_BVZERO( &attr->a_vals[last] );
807 BER_BVZERO( &attr->a_nvals[i] );
814 attr->a_nvals = attr->a_vals;
817 attr->a_numvals = last;
819 /* Handle sorted vals, strip dups but keep the attr */
820 if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
821 while ( attr->a_numvals > 1 ) {
822 int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx );
823 if ( rc != LDAP_TYPE_OR_VALUE_EXISTS )
826 /* Strip duplicate values */
827 if ( attr->a_nvals != attr->a_vals )
828 ber_memfree( attr->a_nvals[i].bv_val );
829 ber_memfree( attr->a_vals[i].bv_val );
833 if ( (unsigned)i < attr->a_numvals ) {
834 attr->a_vals[i] = attr->a_vals[attr->a_numvals];
835 if ( attr->a_nvals != attr->a_vals )
836 attr->a_nvals[i] = attr->a_nvals[attr->a_numvals];
838 BER_BVZERO(&attr->a_vals[attr->a_numvals]);
839 if ( attr->a_nvals != attr->a_vals )
840 BER_BVZERO(&attr->a_nvals[attr->a_numvals]);
842 attr->a_flags |= SLAP_ATTR_SORTED_VALS;
846 attrp = &attr->a_next;
854 /* return 0 IFF we can retrieve the entry with ndn
861 AttributeDescription *at,
865 ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
867 ldapconn_t *lc = NULL;
872 LDAPMessage *result = NULL,
874 char *attr[3], **attrp = NULL;
878 LDAPControl **ctrls = NULL;
882 /* Tell getconn this is a privileged op */
883 do_not_cache = op->o_do_not_cache;
886 op->o_do_not_cache = 1;
887 /* ldap_back_entry_get() is an entry lookup, so it does not need
888 * to know what the entry is being looked up for */
889 op->o_tag = LDAP_REQ_SEARCH;
890 rc = ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND );
891 op->o_do_not_cache = do_not_cache;
899 if ( oc && at != slap_schema.si_ad_objectClass ) {
900 attr[0] = slap_schema.si_ad_objectClass->ad_cname.bv_val;
901 attr[1] = at->ad_cname.bv_val;
905 attr[0] = at->ad_cname.bv_val;
913 filter = op->o_tmpalloc( STRLENOF( "(objectClass=" ")" )
914 + oc->soc_cname.bv_len + 1, op->o_tmpmemctx );
915 ptr = lutil_strcopy( filter, "(objectClass=" );
916 ptr = lutil_strcopy( ptr, oc->soc_cname.bv_val );
923 rc = ldap_back_controls_add( op, &rs, lc, &ctrls );
924 if ( rc != LDAP_SUCCESS ) {
929 rc = ldap_pvt_search_s( lc->lc_ld, ndn->bv_val, LDAP_SCOPE_BASE, filter,
930 attrp, LDAP_DEREF_NEVER, ctrls, NULL,
931 NULL, LDAP_NO_LIMIT, 0, &result );
932 if ( rc != LDAP_SUCCESS ) {
933 if ( rc == LDAP_SERVER_DOWN && do_retry ) {
935 if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
936 /* if the identity changed, there might be need to re-authz */
937 (void)ldap_back_controls_free( op, &rs, &ctrls );
944 e = ldap_first_entry( lc->lc_ld, result );
946 /* the entry exists, but it doesn't match the filter? */
950 *ent = entry_alloc();
951 if ( *ent == NULL ) {
956 rc = ldap_build_entry( op, e, *ent, &bdn );
958 if ( rc != LDAP_SUCCESS ) {
964 (void)ldap_back_controls_free( op, &rs, &ctrls );
967 ldap_msgfree( result );
971 op->o_tmpfree( filter, op->o_tmpmemctx );
975 ldap_back_release_conn( li, lc );