1 /* result.c - routines to send ldap results, errors, and referrals */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/result.c,v 1.289.2.14 2008/05/28 16:28:18 quanah Exp $ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2008 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the University
22 * may not be used to endorse or promote products derived from this
23 * software without specific prior written permission. This software
24 * is provided ``as is'' without express or implied warranty.
31 #include <ac/socket.h>
33 #include <ac/string.h>
36 #include <ac/unistd.h>
40 const struct berval slap_dummy_bv
= BER_BVNULL
;
42 int slap_null_cb( Operation
*op
, SlapReply
*rs
)
47 int slap_freeself_cb( Operation
*op
, SlapReply
*rs
)
49 assert( op
->o_callback
!= NULL
);
51 op
->o_tmpfree( op
->o_callback
, op
->o_tmpmemctx
);
52 op
->o_callback
= NULL
;
54 return SLAP_CB_CONTINUE
;
57 static char *v2ref( BerVarray ref
, const char *text
)
59 size_t len
= 0, i
= 0;
64 return ch_strdup(text
);
72 if (text
[len
-1] != '\n') {
77 v2
= ch_malloc( len
+i
+sizeof("Referral:") );
85 strcpy( v2
+len
, "Referral:" );
86 len
+= sizeof("Referral:");
88 for( i
=0; ref
[i
].bv_val
!= NULL
; i
++ ) {
89 v2
= ch_realloc( v2
, len
+ ref
[i
].bv_len
+ 1 );
91 AC_MEMCPY(&v2
[len
], ref
[i
].bv_val
, ref
[i
].bv_len
);
93 if (ref
[i
].bv_val
[ref
[i
].bv_len
-1] != '/') {
103 slap_req2res( ber_tag_t tag
)
108 case LDAP_REQ_COMPARE
:
109 case LDAP_REQ_EXTENDED
:
110 case LDAP_REQ_MODIFY
:
111 case LDAP_REQ_MODRDN
:
115 case LDAP_REQ_DELETE
:
116 tag
= LDAP_RES_DELETE
;
119 case LDAP_REQ_ABANDON
:
120 case LDAP_REQ_UNBIND
:
124 case LDAP_REQ_SEARCH
:
125 tag
= LDAP_RES_SEARCH_RESULT
;
135 static long send_ldap_ber(
141 ber_get_option( ber
, LBER_OPT_BER_BYTES_TO_WRITE
, &bytes
);
143 /* write only one pdu at a time - wait til it's our turn */
144 ldap_pvt_thread_mutex_lock( &conn
->c_write_mutex
);
146 /* lock the connection */
147 ldap_pvt_thread_mutex_lock( &conn
->c_mutex
);
153 if ( connection_state_closing( conn
) ) {
154 ldap_pvt_thread_mutex_unlock( &conn
->c_mutex
);
155 ldap_pvt_thread_mutex_unlock( &conn
->c_write_mutex
);
160 if ( ber_flush2( conn
->c_sb
, ber
, LBER_FLUSH_FREE_NEVER
) == 0 ) {
167 * we got an error. if it's ewouldblock, we need to
168 * wait on the socket being writable. otherwise, figure
169 * it's a hard error and return.
172 Debug( LDAP_DEBUG_CONNS
, "ber_flush2 failed errno=%d reason=\"%s\"\n",
173 err
, sock_errstr(err
), 0 );
175 if ( err
!= EWOULDBLOCK
&& err
!= EAGAIN
) {
176 connection_closing( conn
, "connection lost on write" );
178 ldap_pvt_thread_mutex_unlock( &conn
->c_mutex
);
179 ldap_pvt_thread_mutex_unlock( &conn
->c_write_mutex
);
184 /* wait for socket to be write-ready */
185 conn
->c_writewaiter
= 1;
186 slapd_set_write( conn
->c_sd
, 1 );
188 ldap_pvt_thread_cond_wait( &conn
->c_write_cv
, &conn
->c_mutex
);
189 conn
->c_writewaiter
= 0;
192 ldap_pvt_thread_mutex_unlock( &conn
->c_mutex
);
193 ldap_pvt_thread_mutex_unlock( &conn
->c_write_mutex
);
199 send_ldap_control( BerElement
*ber
, LDAPControl
*c
)
205 rc
= ber_printf( ber
, "{s" /*}*/, c
->ldctl_oid
);
207 if( c
->ldctl_iscritical
) {
208 rc
= ber_printf( ber
, "b",
209 (ber_int_t
) c
->ldctl_iscritical
) ;
210 if( rc
== -1 ) return rc
;
213 if( c
->ldctl_value
.bv_val
!= NULL
) {
214 rc
= ber_printf( ber
, "O", &c
->ldctl_value
);
215 if( rc
== -1 ) return rc
;
218 rc
= ber_printf( ber
, /*{*/"N}" );
219 if( rc
== -1 ) return rc
;
225 send_ldap_controls( Operation
*o
, BerElement
*ber
, LDAPControl
**c
)
232 rc
= ber_printf( ber
, "t{"/*}*/, LDAP_TAG_CONTROLS
);
233 if( rc
== -1 ) return rc
;
235 for( ; *c
!= NULL
; c
++) {
236 rc
= send_ldap_control( ber
, *c
);
237 if( rc
== -1 ) return rc
;
240 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
241 /* this is a hack to avoid having to modify op->s_ctrls */
242 if( o
->o_sortedresults
) {
243 BerElementBuffer berbuf
;
244 BerElement
*sber
= (BerElement
*) &berbuf
;
246 BER_BVZERO( &sorted
.ldctl_value
);
247 sorted
.ldctl_oid
= LDAP_CONTROL_SORTRESPONSE
;
248 sorted
.ldctl_iscritical
= 0;
250 ber_init2( sber
, NULL
, LBER_USE_DER
);
252 ber_printf( sber
, "{e}", LDAP_UNWILLING_TO_PERFORM
);
254 if( ber_flatten2( ber
, &sorted
.ldctl_value
, 0 ) == -1 ) {
258 (void) ber_free_buf( ber
);
260 rc
= send_ldap_control( ber
, &sorted
);
261 if( rc
== -1 ) return rc
;
265 rc
= ber_printf( ber
, /*{*/"N}" );
271 * slap_response_play()
273 * plays the callback list; rationale: a callback can
274 * - remove itself from the list, by setting op->o_callback = NULL;
275 * malloc()'ed callbacks should free themselves from inside the
276 * sc_response() function.
277 * - replace itself with another (list of) callback(s), by setting
278 * op->o_callback = a new (list of) callback(s); in this case, it
279 * is the callback's responsibility to to append existing subsequent
280 * callbacks to the end of the list that is passed to the sc_response()
282 * - modify the list of subsequent callbacks by modifying the value
283 * of the sc_next field from inside the sc_response() function; this
284 * case does not require any handling from inside slap_response_play()
286 * To stop execution of the playlist, the sc_response() function must return
287 * a value different from SLAP_SC_CONTINUE.
289 * The same applies to slap_cleanup_play(); only, there is no means to stop
290 * execution of the playlist, since all cleanup functions must be called.
299 slap_callback
*sc
= op
->o_callback
, **scp
;
301 rc
= SLAP_CB_CONTINUE
;
302 for ( scp
= &sc
; *scp
; ) {
303 slap_callback
*sc_next
= (*scp
)->sc_next
, **sc_nextp
= &(*scp
)->sc_next
;
305 op
->o_callback
= *scp
;
306 if ( op
->o_callback
->sc_response
) {
307 rc
= op
->o_callback
->sc_response( op
, rs
);
308 if ( op
->o_callback
== NULL
) {
309 /* the callback has been removed;
314 } else if ( op
->o_callback
!= *scp
) {
315 /* a new callback has been inserted
316 * in place of the existing one; repair the list */
317 *scp
= op
->o_callback
;
320 if ( rc
!= SLAP_CB_CONTINUE
) break;
334 slap_callback
*sc
= op
->o_callback
, **scp
;
336 for ( scp
= &sc
; *scp
; ) {
337 slap_callback
*sc_next
= (*scp
)->sc_next
, **sc_nextp
= &(*scp
)->sc_next
;
339 op
->o_callback
= *scp
;
340 if ( op
->o_callback
->sc_cleanup
) {
341 (void)op
->o_callback
->sc_cleanup( op
, rs
);
342 if ( op
->o_callback
== NULL
) {
343 /* the callback has been removed;
348 } else if ( op
->o_callback
!= *scp
) {
349 /* a new callback has been inserted
350 * after the existing one; repair the list */
351 /* a new callback has been inserted
352 * in place of the existing one; repair the list */
353 *scp
= op
->o_callback
;
356 /* don't care about the result; do all cleanup */
370 BerElementBuffer berbuf
;
371 BerElement
*ber
= (BerElement
*) &berbuf
;
372 int rc
= LDAP_SUCCESS
;
375 if ( rs
->sr_err
== SLAPD_ABANDON
|| op
->o_abandon
) {
380 if ( op
->o_callback
) {
381 rc
= slap_response_play( op
, rs
);
382 if ( rc
!= SLAP_CB_CONTINUE
) {
387 #ifdef LDAP_CONNECTIONLESS
388 if (op
->o_conn
&& op
->o_conn
->c_is_udp
)
393 ber_init_w_nullc( ber
, LBER_USE_DER
);
394 ber_set_option( ber
, LBER_OPT_BER_MEMCTX
, &op
->o_tmpmemctx
);
397 Debug( LDAP_DEBUG_TRACE
,
398 "send_ldap_response: msgid=%d tag=%lu err=%d\n",
399 rs
->sr_msgid
, rs
->sr_tag
, rs
->sr_err
);
402 Debug( LDAP_DEBUG_ARGS
, "send_ldap_response: ref=\"%s\"\n",
403 rs
->sr_ref
[0].bv_val
? rs
->sr_ref
[0].bv_val
: "NULL",
407 #ifdef LDAP_CONNECTIONLESS
408 if (op
->o_conn
&& op
->o_conn
->c_is_udp
&&
409 op
->o_protocol
== LDAP_VERSION2
)
411 rc
= ber_printf( ber
, "t{ess" /*"}"*/,
412 rs
->sr_tag
, rs
->sr_err
,
413 rs
->sr_matched
== NULL
? "" : rs
->sr_matched
,
414 rs
->sr_text
== NULL
? "" : rs
->sr_text
);
417 if ( rs
->sr_type
== REP_INTERMEDIATE
) {
418 rc
= ber_printf( ber
, "{it{" /*"}}"*/,
419 rs
->sr_msgid
, rs
->sr_tag
);
422 rc
= ber_printf( ber
, "{it{ess" /*"}}"*/,
423 rs
->sr_msgid
, rs
->sr_tag
, rs
->sr_err
,
424 rs
->sr_matched
== NULL
? "" : rs
->sr_matched
,
425 rs
->sr_text
== NULL
? "" : rs
->sr_text
);
429 if ( rs
->sr_ref
!= NULL
) {
430 assert( rs
->sr_err
== LDAP_REFERRAL
);
431 rc
= ber_printf( ber
, "t{W}",
432 LDAP_TAG_REFERRAL
, rs
->sr_ref
);
434 assert( rs
->sr_err
!= LDAP_REFERRAL
);
438 if( rc
!= -1 && rs
->sr_type
== REP_SASL
&& rs
->sr_sasldata
!= NULL
) {
439 rc
= ber_printf( ber
, "tO",
440 LDAP_TAG_SASL_RES_CREDS
, rs
->sr_sasldata
);
444 ( rs
->sr_type
== REP_EXTENDED
|| rs
->sr_type
== REP_INTERMEDIATE
))
446 if ( rs
->sr_rspoid
!= NULL
) {
447 rc
= ber_printf( ber
, "ts",
448 rs
->sr_type
== REP_EXTENDED
449 ? LDAP_TAG_EXOP_RES_OID
: LDAP_TAG_IM_RES_OID
,
452 if( rc
!= -1 && rs
->sr_rspdata
!= NULL
) {
453 rc
= ber_printf( ber
, "tO",
454 rs
->sr_type
== REP_EXTENDED
455 ? LDAP_TAG_EXOP_RES_VALUE
: LDAP_TAG_IM_RES_VALUE
,
461 rc
= ber_printf( ber
, /*"{"*/ "N}" );
465 rc
= send_ldap_controls( op
, ber
, rs
->sr_ctrls
);
469 rc
= ber_printf( ber
, /*"{"*/ "N}" );
472 #ifdef LDAP_CONNECTIONLESS
473 if( op
->o_conn
&& op
->o_conn
->c_is_udp
&& op
->o_protocol
== LDAP_VERSION2
476 rc
= ber_printf( ber
, /*"{"*/ "N}" );
481 Debug( LDAP_DEBUG_ANY
, "ber_printf failed\n", 0, 0, 0 );
483 #ifdef LDAP_CONNECTIONLESS
484 if (!op
->o_conn
|| op
->o_conn
->c_is_udp
== 0)
493 bytes
= send_ldap_ber( op
->o_conn
, ber
);
494 #ifdef LDAP_CONNECTIONLESS
495 if (!op
->o_conn
|| op
->o_conn
->c_is_udp
== 0)
502 Debug( LDAP_DEBUG_ANY
,
503 "send_ldap_response: ber write failed\n",
509 ldap_pvt_thread_mutex_lock( &op
->o_counters
->sc_mutex
);
510 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_pdu
, 1 );
511 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_bytes
, (unsigned long)bytes
);
512 ldap_pvt_thread_mutex_unlock( &op
->o_counters
->sc_mutex
);
515 /* Tell caller that we did this for real, as opposed to being
516 * overridden by a callback
518 rc
= SLAP_CB_CONTINUE
;
521 if ( op
->o_callback
) {
522 (void)slap_cleanup_play( op
, rs
);
525 if ( rs
->sr_flags
& REP_MATCHED_MUSTBEFREED
) {
526 rs
->sr_flags
^= REP_MATCHED_MUSTBEFREED
; /* paranoia */
527 if ( rs
->sr_matched
) {
528 free( (char *)rs
->sr_matched
);
529 rs
->sr_matched
= NULL
;
533 if ( rs
->sr_flags
& REP_REF_MUSTBEFREED
) {
534 rs
->sr_flags
^= REP_REF_MUSTBEFREED
; /* paranoia */
536 ber_bvarray_free( rs
->sr_ref
);
546 send_ldap_disconnect( Operation
*op
, SlapReply
*rs
)
548 #define LDAP_UNSOLICITED_ERROR(e) \
549 ( (e) == LDAP_PROTOCOL_ERROR \
550 || (e) == LDAP_STRONG_AUTH_REQUIRED \
551 || (e) == LDAP_UNAVAILABLE )
553 assert( LDAP_UNSOLICITED_ERROR( rs
->sr_err
) );
555 rs
->sr_type
= REP_EXTENDED
;
557 Debug( LDAP_DEBUG_TRACE
,
558 "send_ldap_disconnect %d:%s\n",
559 rs
->sr_err
, rs
->sr_text
? rs
->sr_text
: "", NULL
);
561 if ( op
->o_protocol
< LDAP_VERSION3
) {
562 rs
->sr_rspoid
= NULL
;
563 rs
->sr_tag
= slap_req2res( op
->o_tag
);
564 rs
->sr_msgid
= (rs
->sr_tag
!= LBER_SEQUENCE
) ? op
->o_msgid
: 0;
567 rs
->sr_rspoid
= LDAP_NOTICE_DISCONNECT
;
568 rs
->sr_tag
= LDAP_RES_EXTENDED
;
569 rs
->sr_msgid
= LDAP_RES_UNSOLICITED
;
572 if ( send_ldap_response( op
, rs
) == SLAP_CB_CONTINUE
) {
573 Statslog( LDAP_DEBUG_STATS
,
574 "%s DISCONNECT tag=%lu err=%d text=%s\n",
575 op
->o_log_prefix
, rs
->sr_tag
, rs
->sr_err
,
576 rs
->sr_text
? rs
->sr_text
: "", 0 );
581 slap_send_ldap_result( Operation
*op
, SlapReply
*rs
)
584 const char *otext
= rs
->sr_text
;
585 BerVarray oref
= rs
->sr_ref
;
587 rs
->sr_type
= REP_RESULT
;
589 /* Propagate Abandons so that cleanup callbacks can be processed */
590 if ( rs
->sr_err
== SLAPD_ABANDON
|| op
->o_abandon
)
593 assert( !LDAP_API_ERROR( rs
->sr_err
) );
595 Debug( LDAP_DEBUG_TRACE
,
596 "send_ldap_result: %s p=%d\n",
597 op
->o_log_prefix
, op
->o_protocol
, 0 );
599 Debug( LDAP_DEBUG_ARGS
,
600 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
601 rs
->sr_err
, rs
->sr_matched
? rs
->sr_matched
: "",
602 rs
->sr_text
? rs
->sr_text
: "" );
606 Debug( LDAP_DEBUG_ARGS
,
607 "send_ldap_result: referral=\"%s\"\n",
608 rs
->sr_ref
[0].bv_val
? rs
->sr_ref
[0].bv_val
: "NULL",
612 assert( rs
->sr_err
!= LDAP_PARTIAL_RESULTS
);
614 if ( rs
->sr_err
== LDAP_REFERRAL
) {
615 if( op
->o_domain_scope
) rs
->sr_ref
= NULL
;
617 if( rs
->sr_ref
== NULL
) {
618 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
619 } else if ( op
->o_protocol
< LDAP_VERSION3
) {
620 rs
->sr_err
= LDAP_PARTIAL_RESULTS
;
624 if ( op
->o_protocol
< LDAP_VERSION3
) {
625 tmp
= v2ref( rs
->sr_ref
, rs
->sr_text
);
631 rs
->sr_tag
= slap_req2res( op
->o_tag
);
632 rs
->sr_msgid
= (rs
->sr_tag
!= LBER_SEQUENCE
) ? op
->o_msgid
: 0;
634 if ( rs
->sr_flags
& REP_REF_MUSTBEFREED
) {
635 if ( rs
->sr_ref
== NULL
) {
636 rs
->sr_flags
^= REP_REF_MUSTBEFREED
;
637 ber_bvarray_free( oref
);
639 oref
= NULL
; /* send_ldap_response() will free rs->sr_ref if != NULL */
642 if ( send_ldap_response( op
, rs
) == SLAP_CB_CONTINUE
) {
643 if ( op
->o_tag
== LDAP_REQ_SEARCH
) {
645 snprintf( nbuf
, sizeof nbuf
, "%d nentries=%d",
646 rs
->sr_err
, rs
->sr_nentries
);
648 Statslog( LDAP_DEBUG_STATS
,
649 "%s SEARCH RESULT tag=%lu err=%s text=%s\n",
650 op
->o_log_prefix
, rs
->sr_tag
, nbuf
,
651 rs
->sr_text
? rs
->sr_text
: "", 0 );
653 Statslog( LDAP_DEBUG_STATS
,
654 "%s RESULT tag=%lu err=%d text=%s\n",
655 op
->o_log_prefix
, rs
->sr_tag
, rs
->sr_err
,
656 rs
->sr_text
? rs
->sr_text
: "", 0 );
660 if( tmp
!= NULL
) ch_free(tmp
);
666 send_ldap_sasl( Operation
*op
, SlapReply
*rs
)
668 rs
->sr_type
= REP_SASL
;
669 Debug( LDAP_DEBUG_TRACE
, "send_ldap_sasl: err=%d len=%ld\n",
671 rs
->sr_sasldata
? (long) rs
->sr_sasldata
->bv_len
: -1, NULL
);
673 rs
->sr_tag
= slap_req2res( op
->o_tag
);
674 rs
->sr_msgid
= (rs
->sr_tag
!= LBER_SEQUENCE
) ? op
->o_msgid
: 0;
676 if ( send_ldap_response( op
, rs
) == SLAP_CB_CONTINUE
) {
677 Statslog( LDAP_DEBUG_STATS
,
678 "%s RESULT tag=%lu err=%d text=%s\n",
679 op
->o_log_prefix
, rs
->sr_tag
, rs
->sr_err
,
680 rs
->sr_text
? rs
->sr_text
: "", 0 );
685 slap_send_ldap_extended( Operation
*op
, SlapReply
*rs
)
687 rs
->sr_type
= REP_EXTENDED
;
689 Debug( LDAP_DEBUG_TRACE
,
690 "send_ldap_extended: err=%d oid=%s len=%ld\n",
692 rs
->sr_rspoid
? rs
->sr_rspoid
: "",
693 rs
->sr_rspdata
!= NULL
? rs
->sr_rspdata
->bv_len
: 0 );
695 rs
->sr_tag
= slap_req2res( op
->o_tag
);
696 rs
->sr_msgid
= (rs
->sr_tag
!= LBER_SEQUENCE
) ? op
->o_msgid
: 0;
698 if ( send_ldap_response( op
, rs
) == SLAP_CB_CONTINUE
) {
699 Statslog( LDAP_DEBUG_STATS
,
700 "%s RESULT oid=%s err=%d text=%s\n",
701 op
->o_log_prefix
, rs
->sr_rspoid
? rs
->sr_rspoid
: "",
702 rs
->sr_err
, rs
->sr_text
? rs
->sr_text
: "", 0 );
707 slap_send_ldap_intermediate( Operation
*op
, SlapReply
*rs
)
709 rs
->sr_type
= REP_INTERMEDIATE
;
710 Debug( LDAP_DEBUG_TRACE
,
711 "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
713 rs
->sr_rspoid
? rs
->sr_rspoid
: "",
714 rs
->sr_rspdata
!= NULL
? rs
->sr_rspdata
->bv_len
: 0 );
715 rs
->sr_tag
= LDAP_RES_INTERMEDIATE
;
716 rs
->sr_msgid
= op
->o_msgid
;
717 if ( send_ldap_response( op
, rs
) == SLAP_CB_CONTINUE
) {
718 Statslog( LDAP_DEBUG_STATS2
,
719 "%s INTERM oid=%s\n",
721 rs
->sr_rspoid
? rs
->sr_rspoid
: "", 0, 0, 0 );
728 * LDAP_SUCCESS entry sent
729 * LDAP_OTHER entry not sent (other)
730 * LDAP_INSUFFICIENT_ACCESS entry not sent (ACL)
731 * LDAP_UNAVAILABLE entry not sent (connection closed)
732 * LDAP_SIZELIMIT_EXCEEDED entry not sent (caller must send sizelimitExceeded)
736 slap_send_search_entry( Operation
*op
, SlapReply
*rs
)
738 BerElementBuffer berbuf
;
739 BerElement
*ber
= (BerElement
*) &berbuf
;
741 int i
, j
, rc
= LDAP_UNAVAILABLE
, bytes
;
744 AccessControlState acl_state
= ACL_STATE_INIT
;
746 AttributeDescription
*ad_entry
= slap_schema
.si_ad_entry
;
748 /* a_flags: array of flags telling if the i-th element will be
749 * returned or filtered out
750 * e_flags: array of a_flags
752 char **e_flags
= NULL
;
754 if ( op
->ors_slimit
>= 0 && rs
->sr_nentries
>= op
->ors_slimit
) {
755 return LDAP_SIZELIMIT_EXCEEDED
;
758 /* Every 64 entries, check for thread pool pause */
759 if ( ( ( rs
->sr_nentries
& 0x3f ) == 0x3f ) &&
760 ldap_pvt_thread_pool_pausing( &connection_pool
) > 0 )
765 rs
->sr_type
= REP_SEARCH
;
767 /* eventually will loop through generated operational attribute types
768 * currently implemented types include:
769 * entryDN, subschemaSubentry, and hasSubordinates */
770 /* NOTE: moved before overlays callback circling because
771 * they may modify entry and other stuff in rs */
772 /* check for special all operational attributes ("+") type */
773 /* FIXME: maybe we could set this flag at the operation level;
774 * however, in principle the caller of send_search_entry() may
775 * change the attribute list at each call */
776 rs
->sr_attr_flags
= slap_attr_flags( rs
->sr_attrs
);
778 rc
= backend_operational( op
, rs
);
783 if ( op
->o_callback
) {
784 rc
= slap_response_play( op
, rs
);
785 if ( rc
!= SLAP_CB_CONTINUE
) {
790 Debug( LDAP_DEBUG_TRACE
, "=> send_search_entry: conn %lu dn=\"%s\"%s\n",
791 op
->o_connid
, rs
->sr_entry
->e_name
.bv_val
,
792 op
->ors_attrsonly
? " (attrsOnly)" : "" );
794 attrsonly
= op
->ors_attrsonly
;
796 if ( !access_allowed( op
, rs
->sr_entry
, ad_entry
, NULL
, ACL_READ
, NULL
)) {
797 Debug( LDAP_DEBUG_ACL
,
798 "send_search_entry: conn %lu access to entry (%s) not allowed\n",
799 op
->o_connid
, rs
->sr_entry
->e_name
.bv_val
, 0 );
801 rc
= LDAP_INSUFFICIENT_ACCESS
;
805 edn
= rs
->sr_entry
->e_nname
.bv_val
;
807 if ( op
->o_res_ber
) {
808 /* read back control or LDAP_CONNECTIONLESS */
813 bv
.bv_len
= entry_flatsize( rs
->sr_entry
, 0 );
814 bv
.bv_val
= op
->o_tmpalloc( bv
.bv_len
, op
->o_tmpmemctx
);
816 ber_init2( ber
, &bv
, LBER_USE_DER
);
817 ber_set_option( ber
, LBER_OPT_BER_MEMCTX
, &op
->o_tmpmemctx
);
820 #ifdef LDAP_CONNECTIONLESS
821 if ( op
->o_conn
&& op
->o_conn
->c_is_udp
) {
823 if ( op
->o_protocol
== LDAP_VERSION2
) {
824 rc
= ber_printf(ber
, "t{O{" /*}}*/,
825 LDAP_RES_SEARCH_ENTRY
, &rs
->sr_entry
->e_name
);
827 rc
= ber_printf( ber
, "{it{O{" /*}}}*/, op
->o_msgid
,
828 LDAP_RES_SEARCH_ENTRY
, &rs
->sr_entry
->e_name
);
832 if ( op
->o_res_ber
) {
833 /* read back control */
834 rc
= ber_printf( ber
, "{O{" /*}}*/, &rs
->sr_entry
->e_name
);
836 rc
= ber_printf( ber
, "{it{O{" /*}}}*/, op
->o_msgid
,
837 LDAP_RES_SEARCH_ENTRY
, &rs
->sr_entry
->e_name
);
841 Debug( LDAP_DEBUG_ANY
,
842 "send_search_entry: conn %lu ber_printf failed\n",
843 op
->o_connid
, 0, 0 );
845 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
846 send_ldap_error( op
, rs
, LDAP_OTHER
, "encoding DN error" );
851 /* check for special all user attributes ("*") type */
852 userattrs
= SLAP_USERATTRS( rs
->sr_attr_flags
);
854 /* create an array of arrays of flags. Each flag corresponds
855 * to particular value of attribute and equals 1 if value matches
856 * to ValuesReturnFilter or 0 if not
858 if ( op
->o_vrFilter
!= NULL
) {
862 for ( a
= rs
->sr_entry
->e_attrs
, i
=0; a
!= NULL
; a
= a
->a_next
, i
++ ) {
863 for ( j
= 0; a
->a_vals
[j
].bv_val
!= NULL
; j
++ ) k
++;
866 size
= i
* sizeof(char *) + k
;
869 e_flags
= slap_sl_calloc ( 1, i
* sizeof(char *) + k
, op
->o_tmpmemctx
);
870 if( e_flags
== NULL
) {
871 Debug( LDAP_DEBUG_ANY
,
872 "send_search_entry: conn %lu slap_sl_calloc failed\n",
873 op
->o_connid
? op
->o_connid
: 0, 0, 0 );
876 send_ldap_error( op
, rs
, LDAP_OTHER
, "out of memory" );
879 a_flags
= (char *)(e_flags
+ i
);
880 memset( a_flags
, 0, k
);
881 for ( a
=rs
->sr_entry
->e_attrs
, i
=0; a
!= NULL
; a
=a
->a_next
, i
++ ) {
882 for ( j
= 0; a
->a_vals
[j
].bv_val
!= NULL
; j
++ );
883 e_flags
[i
] = a_flags
;
887 rc
= filter_matched_values(op
, rs
->sr_entry
->e_attrs
, &e_flags
) ;
889 Debug( LDAP_DEBUG_ANY
, "send_search_entry: "
890 "conn %lu matched values filtering failed\n",
891 op
->o_connid
? op
->o_connid
: 0, 0, 0 );
892 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
893 send_ldap_error( op
, rs
, LDAP_OTHER
,
894 "matched values filtering error" );
901 for ( a
= rs
->sr_entry
->e_attrs
, j
= 0; a
!= NULL
; a
= a
->a_next
, j
++ ) {
902 AttributeDescription
*desc
= a
->a_desc
;
905 if ( rs
->sr_attrs
== NULL
) {
906 /* all user attrs request, skip operational attributes */
907 if( is_at_operational( desc
->ad_type
) ) {
912 /* specific attrs requested */
913 if ( is_at_operational( desc
->ad_type
) ) {
914 /* if not explicitly requested */
915 if ( !ad_inlist( desc
, rs
->sr_attrs
)) {
916 /* if not all op attrs requested, skip */
917 if ( !SLAP_OPATTRS( rs
->sr_attr_flags
))
919 /* if DSA-specific and replicating, skip */
920 if ( op
->o_sync
!= SLAP_CONTROL_NONE
&&
921 desc
->ad_type
->sat_usage
== LDAP_SCHEMA_DSA_OPERATION
)
925 if ( !userattrs
&& !ad_inlist( desc
, rs
->sr_attrs
) ) {
932 if ( ! access_allowed( op
, rs
->sr_entry
, desc
, NULL
,
933 ACL_READ
, &acl_state
) )
935 Debug( LDAP_DEBUG_ACL
, "send_search_entry: "
936 "conn %lu access to attribute %s not allowed\n",
937 op
->o_connid
, desc
->ad_cname
.bv_val
, 0 );
941 if (( rc
= ber_printf( ber
, "{O[" /*]}*/ , &desc
->ad_cname
)) == -1 ) {
942 Debug( LDAP_DEBUG_ANY
,
943 "send_search_entry: conn %lu ber_printf failed\n",
944 op
->o_connid
, 0, 0 );
946 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
947 send_ldap_error( op
, rs
, LDAP_OTHER
,
948 "encoding description error");
956 for ( i
= 0; a
->a_nvals
[i
].bv_val
!= NULL
; i
++ ) {
957 if ( ! access_allowed( op
, rs
->sr_entry
,
958 desc
, &a
->a_nvals
[i
], ACL_READ
, &acl_state
) )
960 Debug( LDAP_DEBUG_ACL
,
961 "send_search_entry: conn %lu "
962 "access to attribute %s, value #%d not allowed\n",
963 op
->o_connid
, desc
->ad_cname
.bv_val
, i
);
968 if ( op
->o_vrFilter
&& e_flags
[j
][i
] == 0 ){
975 if (( rc
= ber_printf( ber
, "{O[" /*]}*/ , &desc
->ad_cname
)) == -1 ) {
976 Debug( LDAP_DEBUG_ANY
,
977 "send_search_entry: conn %lu ber_printf failed\n",
978 op
->o_connid
, 0, 0 );
980 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
981 send_ldap_error( op
, rs
, LDAP_OTHER
,
982 "encoding description error");
987 if (( rc
= ber_printf( ber
, "O", &a
->a_vals
[i
] )) == -1 ) {
988 Debug( LDAP_DEBUG_ANY
,
989 "send_search_entry: conn %lu "
990 "ber_printf failed.\n", op
->o_connid
, 0, 0 );
992 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
993 send_ldap_error( op
, rs
, LDAP_OTHER
,
994 "encoding values error" );
1001 if ( finish
&& ( rc
= ber_printf( ber
, /*{[*/ "]N}" )) == -1 ) {
1002 Debug( LDAP_DEBUG_ANY
,
1003 "send_search_entry: conn %lu ber_printf failed\n",
1004 op
->o_connid
, 0, 0 );
1006 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
1007 send_ldap_error( op
, rs
, LDAP_OTHER
, "encode end error" );
1013 /* NOTE: moved before overlays callback circling because
1014 * they may modify entry and other stuff in rs */
1015 if ( rs
->sr_operational_attrs
!= NULL
&& op
->o_vrFilter
!= NULL
) {
1019 for ( a
= rs
->sr_operational_attrs
, i
=0; a
!= NULL
; a
= a
->a_next
, i
++ ) {
1020 for ( j
= 0; a
->a_vals
[j
].bv_val
!= NULL
; j
++ ) k
++;
1023 size
= i
* sizeof(char *) + k
;
1025 char *a_flags
, **tmp
;
1028 * Reuse previous memory - we likely need less space
1029 * for operational attributes
1031 tmp
= slap_sl_realloc( e_flags
, i
* sizeof(char *) + k
,
1033 if ( tmp
== NULL
) {
1034 Debug( LDAP_DEBUG_ANY
,
1035 "send_search_entry: conn %lu "
1036 "not enough memory "
1037 "for matched values filtering\n",
1038 op
->o_connid
, 0, 0 );
1039 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
1040 send_ldap_error( op
, rs
, LDAP_OTHER
,
1041 "not enough memory for matched values filtering" );
1045 a_flags
= (char *)(e_flags
+ i
);
1046 memset( a_flags
, 0, k
);
1047 for ( a
= rs
->sr_operational_attrs
, i
=0; a
!= NULL
; a
= a
->a_next
, i
++ ) {
1048 for ( j
= 0; a
->a_vals
[j
].bv_val
!= NULL
; j
++ );
1049 e_flags
[i
] = a_flags
;
1052 rc
= filter_matched_values(op
, rs
->sr_operational_attrs
, &e_flags
) ;
1055 Debug( LDAP_DEBUG_ANY
,
1056 "send_search_entry: conn %lu "
1057 "matched values filtering failed\n",
1058 op
->o_connid
? op
->o_connid
: 0, 0, 0);
1059 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
1060 send_ldap_error( op
, rs
, LDAP_OTHER
,
1061 "matched values filtering error" );
1068 for (a
= rs
->sr_operational_attrs
, j
=0; a
!= NULL
; a
= a
->a_next
, j
++ ) {
1069 AttributeDescription
*desc
= a
->a_desc
;
1071 if ( rs
->sr_attrs
== NULL
) {
1072 /* all user attrs request, skip operational attributes */
1073 if( is_at_operational( desc
->ad_type
) ) {
1078 /* specific attrs requested */
1079 if( is_at_operational( desc
->ad_type
) ) {
1080 if ( !SLAP_OPATTRS( rs
->sr_attr_flags
) &&
1081 !ad_inlist( desc
, rs
->sr_attrs
) )
1086 if ( !userattrs
&& !ad_inlist( desc
, rs
->sr_attrs
) ) {
1092 if ( ! access_allowed( op
, rs
->sr_entry
, desc
, NULL
,
1093 ACL_READ
, &acl_state
) )
1095 Debug( LDAP_DEBUG_ACL
,
1096 "send_search_entry: conn %lu "
1097 "access to attribute %s not allowed\n",
1098 op
->o_connid
, desc
->ad_cname
.bv_val
, 0 );
1103 rc
= ber_printf( ber
, "{O[" /*]}*/ , &desc
->ad_cname
);
1105 Debug( LDAP_DEBUG_ANY
,
1106 "send_search_entry: conn %lu "
1107 "ber_printf failed\n", op
->o_connid
, 0, 0 );
1109 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
1110 send_ldap_error( op
, rs
, LDAP_OTHER
,
1111 "encoding description error" );
1116 if ( ! attrsonly
) {
1117 for ( i
= 0; a
->a_vals
[i
].bv_val
!= NULL
; i
++ ) {
1118 if ( ! access_allowed( op
, rs
->sr_entry
,
1119 desc
, &a
->a_vals
[i
], ACL_READ
, &acl_state
) )
1121 Debug( LDAP_DEBUG_ACL
,
1122 "send_search_entry: conn %lu "
1123 "access to %s, value %d not allowed\n",
1124 op
->o_connid
, desc
->ad_cname
.bv_val
, i
);
1129 if ( op
->o_vrFilter
&& e_flags
[j
][i
] == 0 ){
1133 if (( rc
= ber_printf( ber
, "O", &a
->a_vals
[i
] )) == -1 ) {
1134 Debug( LDAP_DEBUG_ANY
,
1135 "send_search_entry: conn %lu ber_printf failed\n",
1136 op
->o_connid
, 0, 0 );
1138 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
1139 send_ldap_error( op
, rs
, LDAP_OTHER
,
1140 "encoding values error" );
1147 if (( rc
= ber_printf( ber
, /*{[*/ "]N}" )) == -1 ) {
1148 Debug( LDAP_DEBUG_ANY
,
1149 "send_search_entry: conn %lu ber_printf failed\n",
1150 op
->o_connid
, 0, 0 );
1152 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
1153 send_ldap_error( op
, rs
, LDAP_OTHER
, "encode end error" );
1161 slap_sl_free( e_flags
, op
->o_tmpmemctx
);
1165 rc
= ber_printf( ber
, /*{{*/ "}N}" );
1168 rc
= send_ldap_controls( op
, ber
, rs
->sr_ctrls
);
1172 #ifdef LDAP_CONNECTIONLESS
1173 if( op
->o_conn
&& op
->o_conn
->c_is_udp
) {
1174 if ( op
->o_protocol
!= LDAP_VERSION2
) {
1175 rc
= ber_printf( ber
, /*{*/ "N}" );
1179 if ( op
->o_res_ber
== NULL
) {
1180 rc
= ber_printf( ber
, /*{*/ "N}" );
1185 Debug( LDAP_DEBUG_ANY
, "ber_printf failed\n", 0, 0, 0 );
1187 if ( op
->o_res_ber
== NULL
) ber_free_buf( ber
);
1188 send_ldap_error( op
, rs
, LDAP_OTHER
, "encode entry end error" );
1193 if ( rs
->sr_flags
& REP_ENTRY_MUSTRELEASE
) {
1194 be_entry_release_rw( op
, rs
->sr_entry
, 0 );
1195 rs
->sr_flags
^= REP_ENTRY_MUSTRELEASE
;
1196 rs
->sr_entry
= NULL
;
1199 if ( op
->o_res_ber
== NULL
) {
1200 bytes
= send_ldap_ber( op
->o_conn
, ber
);
1201 ber_free_buf( ber
);
1204 Debug( LDAP_DEBUG_ANY
,
1205 "send_search_entry: conn %lu ber write failed.\n",
1206 op
->o_connid
, 0, 0 );
1208 rc
= LDAP_UNAVAILABLE
;
1213 ldap_pvt_thread_mutex_lock( &op
->o_counters
->sc_mutex
);
1214 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_bytes
, (unsigned long)bytes
);
1215 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_entries
, 1 );
1216 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_pdu
, 1 );
1217 ldap_pvt_thread_mutex_unlock( &op
->o_counters
->sc_mutex
);
1220 Statslog( LDAP_DEBUG_STATS2
, "%s ENTRY dn=\"%s\"\n",
1221 op
->o_log_prefix
, edn
, 0, 0, 0 );
1223 Debug( LDAP_DEBUG_TRACE
,
1224 "<= send_search_entry: conn %lu exit.\n", op
->o_connid
, 0, 0 );
1229 if ( op
->o_callback
) {
1230 (void)slap_cleanup_play( op
, rs
);
1234 slap_sl_free( e_flags
, op
->o_tmpmemctx
);
1237 if ( rs
->sr_operational_attrs
) {
1238 attrs_free( rs
->sr_operational_attrs
);
1239 rs
->sr_operational_attrs
= NULL
;
1241 rs
->sr_attr_flags
= SLAP_ATTRS_UNDEFINED
;
1243 /* FIXME: I think rs->sr_type should be explicitly set to
1244 * REP_SEARCH here. That's what it was when we entered this
1245 * function. send_ldap_error may have changed it, but we
1246 * should set it back so that the cleanup functions know
1247 * what they're doing.
1249 if ( op
->o_tag
== LDAP_REQ_SEARCH
&& rs
->sr_type
== REP_SEARCH
1251 && ( rs
->sr_flags
& REP_ENTRY_MUSTBEFREED
) )
1253 entry_free( rs
->sr_entry
);
1254 rs
->sr_entry
= NULL
;
1255 rs
->sr_flags
&= ~REP_ENTRY_MUSTBEFREED
;
1262 slap_send_search_reference( Operation
*op
, SlapReply
*rs
)
1264 BerElementBuffer berbuf
;
1265 BerElement
*ber
= (BerElement
*) &berbuf
;
1269 AttributeDescription
*ad_ref
= slap_schema
.si_ad_ref
;
1270 AttributeDescription
*ad_entry
= slap_schema
.si_ad_entry
;
1272 rs
->sr_type
= REP_SEARCHREF
;
1273 if ( op
->o_callback
) {
1274 rc
= slap_response_play( op
, rs
);
1275 if ( rc
!= SLAP_CB_CONTINUE
) {
1280 Debug( LDAP_DEBUG_TRACE
,
1281 "=> send_search_reference: dn=\"%s\"\n",
1282 rs
->sr_entry
? rs
->sr_entry
->e_name
.bv_val
: "(null)", 0, 0 );
1284 if ( rs
->sr_entry
&& ! access_allowed( op
, rs
->sr_entry
,
1285 ad_entry
, NULL
, ACL_READ
, NULL
) )
1287 Debug( LDAP_DEBUG_ACL
,
1288 "send_search_reference: access to entry not allowed\n",
1294 if ( rs
->sr_entry
&& ! access_allowed( op
, rs
->sr_entry
,
1295 ad_ref
, NULL
, ACL_READ
, NULL
) )
1297 Debug( LDAP_DEBUG_ACL
,
1298 "send_search_reference: access "
1299 "to reference not allowed\n",
1305 if( op
->o_domain_scope
) {
1306 Debug( LDAP_DEBUG_ANY
,
1307 "send_search_reference: domainScope control in (%s)\n",
1308 rs
->sr_entry
->e_dn
, 0, 0 );
1313 if( rs
->sr_ref
== NULL
) {
1314 Debug( LDAP_DEBUG_ANY
,
1315 "send_search_reference: null ref in (%s)\n",
1316 rs
->sr_entry
? rs
->sr_entry
->e_dn
: "(null)", 0, 0 );
1321 if( op
->o_protocol
< LDAP_VERSION3
) {
1323 /* save the references for the result */
1324 if( rs
->sr_ref
[0].bv_val
!= NULL
) {
1325 if( value_add( &rs
->sr_v2ref
, rs
->sr_ref
) )
1331 #ifdef LDAP_CONNECTIONLESS
1332 if( op
->o_conn
&& op
->o_conn
->c_is_udp
) {
1333 ber
= op
->o_res_ber
;
1337 ber_init_w_nullc( ber
, LBER_USE_DER
);
1338 ber_set_option( ber
, LBER_OPT_BER_MEMCTX
, &op
->o_tmpmemctx
);
1341 rc
= ber_printf( ber
, "{it{W}" /*"}"*/ , op
->o_msgid
,
1342 LDAP_RES_SEARCH_REFERENCE
, rs
->sr_ref
);
1345 rc
= send_ldap_controls( op
, ber
, rs
->sr_ctrls
);
1349 rc
= ber_printf( ber
, /*"{"*/ "N}" );
1353 Debug( LDAP_DEBUG_ANY
,
1354 "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1356 #ifdef LDAP_CONNECTIONLESS
1357 if (!op
->o_conn
|| op
->o_conn
->c_is_udp
== 0)
1359 ber_free_buf( ber
);
1360 send_ldap_error( op
, rs
, LDAP_OTHER
, "encode DN error" );
1365 if ( rs
->sr_flags
& REP_ENTRY_MUSTRELEASE
) {
1366 be_entry_release_rw( op
, rs
->sr_entry
, 0 );
1367 rs
->sr_flags
^= REP_ENTRY_MUSTRELEASE
;
1368 rs
->sr_entry
= NULL
;
1371 #ifdef LDAP_CONNECTIONLESS
1372 if (!op
->o_conn
|| op
->o_conn
->c_is_udp
== 0) {
1374 bytes
= send_ldap_ber( op
->o_conn
, ber
);
1375 ber_free_buf( ber
);
1378 rc
= LDAP_UNAVAILABLE
;
1380 ldap_pvt_thread_mutex_lock( &op
->o_counters
->sc_mutex
);
1381 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_bytes
, (unsigned long)bytes
);
1382 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_refs
, 1 );
1383 ldap_pvt_mp_add_ulong( op
->o_counters
->sc_pdu
, 1 );
1384 ldap_pvt_thread_mutex_unlock( &op
->o_counters
->sc_mutex
);
1386 #ifdef LDAP_CONNECTIONLESS
1389 if ( rs
->sr_ref
!= NULL
) {
1392 for ( r
= 0; !BER_BVISNULL( &rs
->sr_ref
[ r
] ); r
++ ) {
1393 Statslog( LDAP_DEBUG_STATS2
, "%s REF #%d \"%s\"\n",
1394 op
->o_log_prefix
, r
, rs
->sr_ref
[0].bv_val
,
1399 Statslog( LDAP_DEBUG_STATS2
, "%s REF \"(null)\"\n",
1400 op
->o_log_prefix
, 0, 0, 0, 0 );
1403 Debug( LDAP_DEBUG_TRACE
, "<= send_search_reference\n", 0, 0, 0 );
1406 if ( op
->o_callback
) {
1407 (void)slap_cleanup_play( op
, rs
);
1423 *code
= LDAP_SUCCESS
;
1427 if ( strncasecmp( s
, "RESULT", STRLENOF( "RESULT" ) ) != 0 ) {
1428 Debug( LDAP_DEBUG_ANY
, "str2result (%s) expecting \"RESULT\"\n",
1435 while ( (s
= strchr( s
, '\n' )) != NULL
) {
1440 if ( (c
= strchr( s
, ':' )) != NULL
) {
1444 if ( strncasecmp( s
, "code", STRLENOF( "code" ) ) == 0 ) {
1449 Debug( LDAP_DEBUG_ANY
, "str2result (%s) missing value\n",
1455 while ( isspace( (unsigned char) c
[ 0 ] ) ) c
++;
1456 if ( c
[ 0 ] == '\0' ) {
1457 Debug( LDAP_DEBUG_ANY
, "str2result (%s) missing or empty value\n",
1463 retcode
= strtol( c
, &next
, 10 );
1464 if ( next
== NULL
|| next
== c
) {
1465 Debug( LDAP_DEBUG_ANY
, "str2result (%s) unable to parse value\n",
1471 while ( isspace( (unsigned char) next
[ 0 ] ) ) next
++;
1472 if ( next
[ 0 ] != '\0' ) {
1473 Debug( LDAP_DEBUG_ANY
, "str2result (%s) extra cruft after value\n",
1479 /* FIXME: what if it's larger that max int? */
1480 *code
= (int)retcode
;
1482 } else if ( strncasecmp( s
, "matched", STRLENOF( "matched" ) ) == 0 ) {
1486 } else if ( strncasecmp( s
, "info", STRLENOF( "info" ) ) == 0 ) {
1491 Debug( LDAP_DEBUG_ANY
, "str2result (%s) unknown\n",
1501 int slap_read_controls(
1505 const struct berval
*oid
,
1506 LDAPControl
**ctrl
)
1510 BerElementBuffer berbuf
;
1511 BerElement
*ber
= (BerElement
*) &berbuf
;
1515 Debug( LDAP_DEBUG_ANY
, "slap_read_controls: (%s) %s\n",
1516 oid
->bv_val
, e
->e_dn
, 0 );
1519 rs
->sr_attrs
= ( oid
== &slap_pre_read_bv
) ?
1520 op
->o_preread_attrs
: op
->o_postread_attrs
;
1522 bv
.bv_len
= entry_flatsize( rs
->sr_entry
, 0 );
1523 bv
.bv_val
= op
->o_tmpalloc( bv
.bv_len
, op
->o_tmpmemctx
);
1525 ber_init2( ber
, &bv
, LBER_USE_DER
);
1526 ber_set_option( ber
, LBER_OPT_BER_MEMCTX
, &op
->o_tmpmemctx
);
1528 /* create new operation */
1530 /* FIXME: o_bd needed for ACL */
1531 myop
.o_bd
= op
->o_bd
;
1532 myop
.o_res_ber
= ber
;
1533 myop
.o_callback
= NULL
;
1534 myop
.ors_slimit
= 1;
1536 rc
= slap_send_search_entry( &myop
, rs
);
1539 rc
= ber_flatten2( ber
, &c
.ldctl_value
, 0 );
1541 if( rc
== LBER_ERROR
) return LDAP_OTHER
;
1543 c
.ldctl_oid
= oid
->bv_val
;
1544 c
.ldctl_iscritical
= 0;
1546 if ( *ctrl
== NULL
) {
1548 *ctrl
= (LDAPControl
*) slap_sl_calloc( 1, sizeof(LDAPControl
), NULL
);
1550 /* retry: free previous try */
1551 slap_sl_free( (*ctrl
)->ldctl_value
.bv_val
, op
->o_tmpmemctx
);
1555 return LDAP_SUCCESS
;
1558 /* Map API errors to protocol errors... */
1560 slap_map_api2result( SlapReply
*rs
)
1562 switch(rs
->sr_err
) {
1563 case LDAP_SERVER_DOWN
:
1564 return LDAP_UNAVAILABLE
;
1565 case LDAP_LOCAL_ERROR
:
1567 case LDAP_ENCODING_ERROR
:
1568 case LDAP_DECODING_ERROR
:
1569 return LDAP_PROTOCOL_ERROR
;
1571 return LDAP_UNAVAILABLE
;
1572 case LDAP_AUTH_UNKNOWN
:
1573 return LDAP_AUTH_METHOD_NOT_SUPPORTED
;
1574 case LDAP_FILTER_ERROR
:
1575 rs
->sr_text
= "Filter error";
1577 case LDAP_USER_CANCELLED
:
1578 rs
->sr_text
= "User cancelled";
1580 case LDAP_PARAM_ERROR
:
1581 return LDAP_PROTOCOL_ERROR
;
1582 case LDAP_NO_MEMORY
:
1584 case LDAP_CONNECT_ERROR
:
1585 return LDAP_UNAVAILABLE
;
1586 case LDAP_NOT_SUPPORTED
:
1587 return LDAP_UNWILLING_TO_PERFORM
;
1588 case LDAP_CONTROL_NOT_FOUND
:
1589 return LDAP_PROTOCOL_ERROR
;
1590 case LDAP_NO_RESULTS_RETURNED
:
1591 return LDAP_NO_SUCH_OBJECT
;
1592 case LDAP_MORE_RESULTS_TO_RETURN
:
1593 rs
->sr_text
= "More results to return";
1595 case LDAP_CLIENT_LOOP
:
1596 case LDAP_REFERRAL_LIMIT_EXCEEDED
:
1597 return LDAP_LOOP_DETECT
;
1599 if ( LDAP_API_ERROR(rs
->sr_err
) ) return LDAP_OTHER
;
1606 slap_attr_flags( AttributeName
*an
)
1608 slap_mask_t flags
= SLAP_ATTRS_UNDEFINED
;
1611 flags
|= ( SLAP_OPATTRS_NO
| SLAP_USERATTRS_YES
);
1614 flags
|= an_find( an
, &AllOper
)
1615 ? SLAP_OPATTRS_YES
: SLAP_OPATTRS_NO
;
1616 flags
|= an_find( an
, &AllUser
)
1617 ? SLAP_USERATTRS_YES
: SLAP_USERATTRS_NO
;