1 /* search.c - ldap backend search function */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-ldap/search.c,v 1.201.2.11 2008/07/10 00:28:39 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1999-2008 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
)
52 ldapinfo_t
*li
= (ldapinfo_t
*) op
->o_bd
->be_private
;
57 Debug( LDAP_DEBUG_ARGS
, "=> ldap_back_munge_filter \"%s\"\n",
58 filter
->bv_val
, 0, 0 );
60 for ( ptr
= strstr( filter
->bv_val
, "(?=" );
62 ptr
= strstr( ptr
, "(?=" ) )
65 bv_true
= BER_BVC( "(?=true)" ),
66 bv_false
= BER_BVC( "(?=false)" ),
67 bv_undefined
= BER_BVC( "(?=undefined)" ),
68 bv_t
= BER_BVC( "(&)" ),
69 bv_f
= BER_BVC( "(|)" ),
70 bv_T
= BER_BVC( "(objectClass=*)" ),
71 bv_F
= BER_BVC( "(!(objectClass=*))" );
72 struct berval
*oldbv
= NULL
,
74 oldfilter
= BER_BVNULL
;
76 if ( strncmp( ptr
, bv_true
.bv_val
, bv_true
.bv_len
) == 0 ) {
78 if ( LDAP_BACK_T_F( li
) ) {
85 } else if ( strncmp( ptr
, bv_false
.bv_val
, bv_false
.bv_len
) == 0 )
88 if ( LDAP_BACK_T_F( li
) ) {
95 } else if ( strncmp( ptr
, bv_undefined
.bv_val
, bv_undefined
.bv_len
) == 0 )
97 oldbv
= &bv_undefined
;
106 if ( newbv
->bv_len
> oldbv
->bv_len
) {
107 filter
->bv_len
+= newbv
->bv_len
- oldbv
->bv_len
;
108 if ( filter
->bv_val
== op
->ors_filterstr
.bv_val
) {
109 filter
->bv_val
= op
->o_tmpalloc( filter
->bv_len
+ 1,
112 AC_MEMCPY( filter
->bv_val
, op
->ors_filterstr
.bv_val
,
113 op
->ors_filterstr
.bv_len
+ 1 );
116 filter
->bv_val
= op
->o_tmprealloc( filter
->bv_val
,
117 filter
->bv_len
+ 1, op
->o_tmpmemctx
);
120 ptr
= filter
->bv_val
+ ( ptr
- oldfilter
.bv_val
);
123 AC_MEMCPY( &ptr
[ newbv
->bv_len
],
124 &ptr
[ oldbv
->bv_len
],
125 oldfilter
.bv_len
- ( ptr
- filter
->bv_val
) - oldbv
->bv_len
+ 1 );
126 AC_MEMCPY( ptr
, newbv
->bv_val
, newbv
->bv_len
);
128 ptr
+= newbv
->bv_len
;
133 Debug( LDAP_DEBUG_ARGS
, "<= ldap_back_munge_filter \"%s\" (%d)\n",
134 filter
->bv_val
, gotit
, 0 );
144 ldapinfo_t
*li
= (ldapinfo_t
*) op
->o_bd
->be_private
;
146 ldapconn_t
*lc
= NULL
;
148 time_t stoptime
= (time_t)(-1);
153 struct berval match
= BER_BVNULL
,
159 int do_retry
= 1, dont_retry
= 0;
160 LDAPControl
**ctrls
= NULL
;
161 char **references
= NULL
;
163 /* FIXME: shouldn't this be null? */
164 const char *save_matched
= rs
->sr_matched
;
166 if ( !ldap_back_dobind( &lc
, op
, rs
, LDAP_BACK_SENDERR
) ) {
171 * FIXME: in case of values return filter, we might want
172 * to map attrs and maybe rewrite value
175 /* should we check return values? */
176 if ( op
->ors_deref
!= -1 ) {
177 ldap_set_option( lc
->lc_ld
, LDAP_OPT_DEREF
,
178 (void *)&op
->ors_deref
);
181 if ( op
->ors_tlimit
!= SLAP_NO_LIMIT
) {
182 tv
.tv_sec
= op
->ors_tlimit
;
184 stoptime
= op
->o_time
+ op
->ors_tlimit
;
187 LDAP_BACK_TV_SET( &tv
);
190 if ( op
->ors_attrs
) {
191 for ( i
= 0; !BER_BVISNULL( &op
->ors_attrs
[i
].an_name
); i
++ )
192 /* just count attrs */ ;
194 attrs
= ch_malloc( ( i
+ 1 )*sizeof( char * ) );
195 if ( attrs
== NULL
) {
196 rs
->sr_err
= LDAP_NO_MEMORY
;
201 for ( i
= 0; !BER_BVISNULL( &op
->ors_attrs
[i
].an_name
); i
++ ) {
202 attrs
[ i
] = op
->ors_attrs
[i
].an_name
.bv_val
;
208 rc
= ldap_back_controls_add( op
, rs
, lc
, &ctrls
);
209 if ( rc
!= LDAP_SUCCESS
) {
213 /* deal with <draft-zeilenga-ldap-t-f> filters */
214 filter
= op
->ors_filterstr
;
216 rs
->sr_err
= ldap_search_ext( lc
->lc_ld
, op
->o_req_dn
.bv_val
,
217 op
->ors_scope
, filter
.bv_val
,
218 attrs
, op
->ors_attrsonly
, ctrls
, NULL
,
219 tv
.tv_sec
? &tv
: NULL
,
220 op
->ors_slimit
, &msgid
);
222 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
223 switch ( rs
->sr_err
) {
224 case LDAP_SERVER_DOWN
:
227 if ( ldap_back_retry( &lc
, op
, rs
, LDAP_BACK_DONTSEND
) ) {
233 /* reset by ldap_back_retry ... */
234 rs
->sr_err
= slap_map_api2result( rs
);
237 rc
= ldap_back_op_result( lc
, op
, rs
, msgid
, 0, LDAP_BACK_DONTSEND
);
242 case LDAP_FILTER_ERROR
:
243 if ( ldap_back_munge_filter( op
, &filter
) ) {
248 /* invalid filters return success with no data */
249 rs
->sr_err
= LDAP_SUCCESS
;
254 rs
->sr_err
= slap_map_api2result( rs
);
260 /* if needed, initialize timeout */
261 if ( li
->li_timeout
[ SLAP_OP_SEARCH
] ) {
262 if ( tv
.tv_sec
== 0 || tv
.tv_sec
> li
->li_timeout
[ SLAP_OP_SEARCH
] ) {
263 tv
.tv_sec
= li
->li_timeout
[ SLAP_OP_SEARCH
];
268 /* We pull apart the ber result, stuff it into a slapd entry, and
269 * let send_search_entry stuff it back into ber format. Slow & ugly,
270 * but this is necessary for version matching, and for ACL processing.
273 for ( rc
= -2; rc
!= -1; rc
= ldap_result( lc
->lc_ld
, msgid
, LDAP_MSG_ONE
, &tv
, &res
) )
275 /* check for abandon */
276 if ( op
->o_abandon
|| LDAP_BACK_CONN_ABANDON( lc
) ) {
280 (void)ldap_back_cancel( lc
, op
, rs
, msgid
, LDAP_BACK_DONTSEND
);
285 if ( rc
== 0 || rc
== -2 ) {
286 ldap_pvt_thread_yield();
289 if ( li
->li_timeout
[ SLAP_OP_SEARCH
] ) {
291 (void)ldap_back_cancel( lc
, op
, rs
, msgid
, LDAP_BACK_DONTSEND
);
292 rs
->sr_text
= "Operation timed out";
293 rc
= rs
->sr_err
= op
->o_protocol
>= LDAP_VERSION3
?
294 LDAP_ADMINLIMIT_EXCEEDED
: LDAP_OTHER
;
299 LDAP_BACK_TV_SET( &tv
);
302 /* check time limit */
303 if ( op
->ors_tlimit
!= SLAP_NO_LIMIT
304 && slap_get_time() > stoptime
)
306 (void)ldap_back_cancel( lc
, op
, rs
, msgid
, LDAP_BACK_DONTSEND
);
307 rc
= rs
->sr_err
= LDAP_TIMELIMIT_EXCEEDED
;
313 /* only touch when activity actually took place... */
314 if ( li
->li_idle_timeout
&& lc
) {
315 lc
->lc_time
= op
->o_time
;
318 /* don't retry any more */
323 if ( rc
== LDAP_RES_SEARCH_ENTRY
) {
325 struct berval bdn
= BER_BVNULL
;
329 e
= ldap_first_entry( lc
->lc_ld
, res
);
330 rc
= ldap_build_entry( op
, e
, &ent
, &bdn
);
331 if ( rc
== LDAP_SUCCESS
) {
332 ldap_get_entry_controls( lc
->lc_ld
, res
, &rs
->sr_ctrls
);
334 rs
->sr_attrs
= op
->ors_attrs
;
335 rs
->sr_operational_attrs
= NULL
;
337 rs
->sr_err
= LDAP_SUCCESS
;
338 rc
= rs
->sr_err
= send_search_entry( op
, rs
);
339 if ( rs
->sr_ctrls
) {
340 ldap_controls_free( rs
->sr_ctrls
);
344 if ( !BER_BVISNULL( &ent
.e_name
) ) {
345 assert( ent
.e_name
.bv_val
!= bdn
.bv_val
);
346 op
->o_tmpfree( ent
.e_name
.bv_val
, op
->o_tmpmemctx
);
347 BER_BVZERO( &ent
.e_name
);
349 if ( !BER_BVISNULL( &ent
.e_nname
) ) {
350 op
->o_tmpfree( ent
.e_nname
.bv_val
, op
->o_tmpmemctx
);
351 BER_BVZERO( &ent
.e_nname
);
356 if ( rc
!= LDAP_SUCCESS
) {
357 if ( rc
== LDAP_UNAVAILABLE
) {
358 rc
= rs
->sr_err
= LDAP_OTHER
;
360 (void)ldap_back_cancel( lc
, op
, rs
, msgid
, LDAP_BACK_DONTSEND
);
365 } else if ( rc
== LDAP_RES_SEARCH_REFERENCE
) {
366 if ( LDAP_BACK_NOREFS( li
) ) {
372 rc
= ldap_parse_reference( lc
->lc_ld
, res
,
373 &references
, &rs
->sr_ctrls
, 1 );
375 if ( rc
!= LDAP_SUCCESS
) {
379 /* FIXME: there MUST be at least one */
380 if ( references
&& references
[ 0 ] && references
[ 0 ][ 0 ] ) {
383 for ( cnt
= 0; references
[ cnt
]; cnt
++ )
386 /* FIXME: there MUST be at least one */
387 rs
->sr_ref
= op
->o_tmpalloc( ( cnt
+ 1 ) * sizeof( struct berval
),
390 for ( cnt
= 0; references
[ cnt
]; cnt
++ ) {
391 ber_str2bv( references
[ cnt
], 0, 0, &rs
->sr_ref
[ cnt
] );
393 BER_BVZERO( &rs
->sr_ref
[ cnt
] );
395 /* ignore return value by now */
397 ( void )send_search_reference( op
, rs
);
400 Debug( LDAP_DEBUG_ANY
,
401 "%s ldap_back_search: "
402 "got SEARCH_REFERENCE "
403 "with no referrals\n",
404 op
->o_log_prefix
, 0, 0 );
409 ber_memvfree( (void **)references
);
410 op
->o_tmpfree( rs
->sr_ref
, op
->o_tmpmemctx
);
415 if ( rs
->sr_ctrls
) {
416 ldap_controls_free( rs
->sr_ctrls
);
423 rc
= ldap_parse_result( lc
->lc_ld
, res
, &rs
->sr_err
,
425 &references
, &rs
->sr_ctrls
, 1 );
426 if ( rc
!= LDAP_SUCCESS
) {
429 rs
->sr_err
= slap_map_api2result( rs
);
435 /* RFC 4511: referrals can only appear
436 * if result code is LDAP_REFERRAL */
439 && references
[ 0 ][ 0 ] )
441 if ( rs
->sr_err
!= LDAP_REFERRAL
) {
442 Debug( LDAP_DEBUG_ANY
,
443 "%s ldap_back_search: "
444 "got referrals with err=%d\n",
451 for ( cnt
= 0; references
[ cnt
]; cnt
++ )
454 rs
->sr_ref
= op
->o_tmpalloc( ( cnt
+ 1 ) * sizeof( struct berval
),
457 for ( cnt
= 0; references
[ cnt
]; cnt
++ ) {
459 ber_str2bv( references
[ cnt
], 0, 0, &rs
->sr_ref
[ cnt
] );
461 BER_BVZERO( &rs
->sr_ref
[ cnt
] );
464 } else if ( rs
->sr_err
== LDAP_REFERRAL
) {
465 Debug( LDAP_DEBUG_ANY
,
466 "%s ldap_back_search: "
467 "got err=%d with null "
468 "or empty referrals\n",
472 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
475 if ( match
.bv_val
!= NULL
) {
476 match
.bv_len
= strlen( match
.bv_val
);
483 /* if needed, restore timeout */
484 if ( li
->li_timeout
[ SLAP_OP_SEARCH
] ) {
485 if ( tv
.tv_sec
== 0 || tv
.tv_sec
> li
->li_timeout
[ SLAP_OP_SEARCH
] ) {
486 tv
.tv_sec
= li
->li_timeout
[ SLAP_OP_SEARCH
];
492 if ( rc
== -1 && dont_retry
== 0 ) {
495 if ( ldap_back_retry( &lc
, op
, rs
, LDAP_BACK_DONTSEND
) ) {
499 rs
->sr_err
= LDAP_SERVER_DOWN
;
500 rs
->sr_err
= slap_map_api2result( rs
);
505 * Rewrite the matched portion of the search base, if required
507 if ( !BER_BVISNULL( &match
) && !BER_BVISEMPTY( &match
) ) {
508 struct berval pmatch
;
510 if ( dnPretty( NULL
, &match
, &pmatch
, op
->o_tmpmemctx
) == LDAP_SUCCESS
) {
511 rs
->sr_matched
= pmatch
.bv_val
;
512 LDAP_FREE( match
.bv_val
);
515 rs
->sr_matched
= match
.bv_val
;
519 if ( rs
->sr_v2ref
) {
520 rs
->sr_err
= LDAP_REFERRAL
;
524 if ( LDAP_BACK_QUARANTINE( li
) ) {
525 ldap_back_quarantine( op
, rs
);
529 /* let send_ldap_result play cleanup handlers (ITS#4645) */
530 if ( rc
!= SLAPD_ABANDON
)
533 send_ldap_result( op
, rs
);
536 (void)ldap_back_controls_free( op
, rs
, &ctrls
);
538 if ( rs
->sr_ctrls
) {
539 ldap_controls_free( rs
->sr_ctrls
);
543 if ( rs
->sr_matched
!= NULL
&& rs
->sr_matched
!= save_matched
) {
544 if ( rs
->sr_matched
!= match
.bv_val
) {
545 ber_memfree_x( (char *)rs
->sr_matched
, op
->o_tmpmemctx
);
548 LDAP_FREE( match
.bv_val
);
550 rs
->sr_matched
= save_matched
;
554 op
->o_tmpfree( filter
.bv_val
, op
->o_tmpmemctx
);
559 LDAP_FREE( (char *)rs
->sr_text
);
565 op
->o_tmpfree( rs
->sr_ref
, op
->o_tmpmemctx
);
570 ber_memvfree( (void **)references
);
578 ldap_back_release_conn( li
, lc
);
592 BerElement ber
= *e
->lm_ber
;
593 Attribute
*attr
, **attrp
;
599 /* safe assumptions ... */
600 assert( ent
!= NULL
);
601 BER_BVZERO( &ent
->e_bv
);
603 if ( ber_scanf( &ber
, "{m", bdn
) == LBER_ERROR
) {
604 return LDAP_DECODING_ERROR
;
608 * Note: this may fail if the target host(s) schema differs
609 * from the one known to the meta, and a DN with unknown
610 * attributes is returned.
612 * FIXME: should we log anything, or delegate to dnNormalize?
614 /* Note: if the distinguished values or the naming attributes
615 * change, should we massage them as well?
617 if ( dnPrettyNormal( NULL
, bdn
, &ent
->e_name
, &ent
->e_nname
,
618 op
->o_tmpmemctx
) != LDAP_SUCCESS
)
620 return LDAP_INVALID_DN_SYNTAX
;
624 if ( ber_first_element( &ber
, &len
, &lastb
) != LBER_SEQUENCE
) {
628 attrp
= &ent
->e_attrs
;
629 while ( ber_next_element( &ber
, &len
, lastb
) == LBER_SEQUENCE
&&
630 ber_scanf( &ber
, "{m", &a
) != LBER_ERROR
) {
632 slap_syntax_validate_func
*validate
;
633 slap_syntax_transform_func
*pretty
;
635 attr
= attr_alloc( NULL
);
636 if ( attr
== NULL
) {
639 if ( slap_bv2ad( &a
, &attr
->a_desc
, &text
)
642 if ( slap_bv2undef_ad( &a
, &attr
->a_desc
, &text
,
643 SLAP_AD_PROXIED
) != LDAP_SUCCESS
)
645 Debug( LDAP_DEBUG_ANY
,
646 "%s ldap_build_entry: "
647 "slap_bv2undef_ad(%s): %s\n",
648 op
->o_log_prefix
, a
.bv_val
, text
);
654 /* no subschemaSubentry */
655 if ( attr
->a_desc
== slap_schema
.si_ad_subschemaSubentry
656 || attr
->a_desc
== slap_schema
.si_ad_entryDN
)
660 * We eat target's subschemaSubentry because
661 * a search for this value is likely not
662 * to resolve to the appropriate backend;
663 * later, the local subschemaSubentry is
666 * We also eat entryDN because the frontend
667 * will reattach it without checking if already
670 ( void )ber_scanf( &ber
, "x" /* [W] */ );
676 if ( ber_scanf( &ber
, "[W]", &attr
->a_vals
) == LBER_ERROR
677 || attr
->a_vals
== NULL
)
680 * Note: attr->a_vals can be null when using
681 * values result filter
683 attr
->a_vals
= (struct berval
*)&slap_dummy_bv
;
686 validate
= attr
->a_desc
->ad_type
->sat_syntax
->ssyn_validate
;
687 pretty
= attr
->a_desc
->ad_type
->sat_syntax
->ssyn_pretty
;
689 if ( !validate
&& !pretty
) {
690 attr
->a_nvals
= NULL
;
695 for ( i
= 0; !BER_BVISNULL( &attr
->a_vals
[i
] ); i
++ ) {
700 rc
= pretty( attr
->a_desc
->ad_type
->sat_syntax
,
701 &attr
->a_vals
[i
], &pval
, NULL
);
704 rc
= validate( attr
->a_desc
->ad_type
->sat_syntax
,
708 if ( rc
!= LDAP_SUCCESS
) {
709 /* check if, by chance, it's an undefined objectClass */
710 if ( attr
->a_desc
== slap_schema
.si_ad_objectClass
&&
711 oc_bvfind_undef( &attr
->a_vals
[i
] ) != NULL
)
713 ber_dupbv( &pval
, &attr
->a_vals
[i
] );
716 attr
->a_nvals
= NULL
;
723 LBER_FREE( attr
->a_vals
[i
].bv_val
);
724 attr
->a_vals
[i
] = pval
;
727 attr
->a_numvals
= last
= i
;
729 if ( last
&& attr
->a_desc
->ad_type
->sat_equality
&&
730 attr
->a_desc
->ad_type
->sat_equality
->smr_normalize
)
732 attr
->a_nvals
= ch_malloc( ( last
+ 1 )*sizeof( struct berval
) );
733 for ( i
= 0; i
< last
; i
++ ) {
737 * check that each value is valid per syntax
738 * and pretty if appropriate
740 rc
= attr
->a_desc
->ad_type
->sat_equality
->smr_normalize(
741 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
,
742 attr
->a_desc
->ad_type
->sat_syntax
,
743 attr
->a_desc
->ad_type
->sat_equality
,
744 &attr
->a_vals
[i
], &attr
->a_nvals
[i
],
747 if ( rc
!= LDAP_SUCCESS
) {
748 BER_BVZERO( &attr
->a_nvals
[i
] );
753 BER_BVZERO( &attr
->a_nvals
[i
] );
756 attr
->a_nvals
= attr
->a_vals
;
759 attrp
= &attr
->a_next
;
767 /* return 0 IFF we can retrieve the entry with ndn
774 AttributeDescription
*at
,
778 ldapinfo_t
*li
= (ldapinfo_t
*) op
->o_bd
->be_private
;
780 ldapconn_t
*lc
= NULL
;
785 LDAPMessage
*result
= NULL
,
787 char *attr
[3], **attrp
= NULL
;
791 LDAPControl
**ctrls
= NULL
;
795 /* Tell getconn this is a privileged op */
796 do_not_cache
= op
->o_do_not_cache
;
799 op
->o_do_not_cache
= 1;
800 /* ldap_back_entry_get() is an entry lookup, so it does not need
801 * to know what the entry is being looked up for */
802 op
->o_tag
= LDAP_REQ_SEARCH
;
803 rc
= ldap_back_dobind( &lc
, op
, &rs
, LDAP_BACK_DONTSEND
);
804 op
->o_do_not_cache
= do_not_cache
;
812 if ( oc
&& at
!= slap_schema
.si_ad_objectClass
) {
813 attr
[0] = slap_schema
.si_ad_objectClass
->ad_cname
.bv_val
;
814 attr
[1] = at
->ad_cname
.bv_val
;
818 attr
[0] = at
->ad_cname
.bv_val
;
826 filter
= op
->o_tmpalloc( STRLENOF( "(objectClass=" ")" )
827 + oc
->soc_cname
.bv_len
+ 1, op
->o_tmpmemctx
);
828 ptr
= lutil_strcopy( filter
, "(objectClass=" );
829 ptr
= lutil_strcopy( ptr
, oc
->soc_cname
.bv_val
);
836 rc
= ldap_back_controls_add( op
, &rs
, lc
, &ctrls
);
837 if ( rc
!= LDAP_SUCCESS
) {
842 rc
= ldap_search_ext_s( lc
->lc_ld
, ndn
->bv_val
, LDAP_SCOPE_BASE
, filter
,
843 attrp
, 0, ctrls
, NULL
,
844 NULL
, LDAP_NO_LIMIT
, &result
);
845 if ( rc
!= LDAP_SUCCESS
) {
846 if ( rc
== LDAP_SERVER_DOWN
&& do_retry
) {
848 if ( ldap_back_retry( &lc
, op
, &rs
, LDAP_BACK_DONTSEND
) ) {
849 /* if the identity changed, there might be need to re-authz */
850 (void)ldap_back_controls_free( op
, &rs
, &ctrls
);
857 e
= ldap_first_entry( lc
->lc_ld
, result
);
859 /* the entry exists, but it doesn't match the filter? */
863 *ent
= entry_alloc();
864 if ( *ent
== NULL
) {
869 rc
= ldap_build_entry( op
, e
, *ent
, &bdn
);
871 if ( rc
!= LDAP_SUCCESS
) {
877 (void)ldap_back_controls_free( op
, &rs
, &ctrls
);
880 ldap_msgfree( result
);
884 op
->o_tmpfree( filter
, op
->o_tmpmemctx
);
888 ldap_back_release_conn( li
, lc
);