1 /* result.c - routines to send ldap results, errors, and referrals */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2006 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>
41 const struct berval slap_dummy_bv = BER_BVNULL;
43 int slap_null_cb( Operation *op, SlapReply *rs )
48 int slap_freeself_cb( Operation *op, SlapReply *rs )
50 assert( op->o_callback != NULL );
52 op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
53 op->o_callback = NULL;
55 return SLAP_CB_CONTINUE;
58 int slap_replog_cb( Operation *op, SlapReply *rs )
60 if ( rs->sr_err == LDAP_SUCCESS ) {
63 return SLAP_CB_CONTINUE;
66 static char *v2ref( BerVarray ref, const char *text )
68 size_t len = 0, i = 0;
73 return ch_strdup(text);
81 if (text[len-1] != '\n') {
86 v2 = SLAP_MALLOC( len+i+sizeof("Referral:") );
88 Debug( LDAP_DEBUG_ANY, "v2ref: SLAP_MALLOC failed", 0, 0, 0 );
98 strcpy( v2+len, "Referral:" );
99 len += sizeof("Referral:");
101 for( i=0; ref[i].bv_val != NULL; i++ ) {
102 v2 = SLAP_REALLOC( v2, len + ref[i].bv_len + 1 );
104 Debug( LDAP_DEBUG_ANY, "v2ref: SLAP_MALLOC failed", 0, 0, 0 );
108 AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len );
109 len += ref[i].bv_len;
110 if (ref[i].bv_val[ref[i].bv_len-1] != '/') {
120 slap_req2res( ber_tag_t tag )
125 case LDAP_REQ_COMPARE:
126 case LDAP_REQ_EXTENDED:
127 case LDAP_REQ_MODIFY:
128 case LDAP_REQ_MODRDN:
132 case LDAP_REQ_DELETE:
133 tag = LDAP_RES_DELETE;
136 case LDAP_REQ_ABANDON:
137 case LDAP_REQ_UNBIND:
141 case LDAP_REQ_SEARCH:
142 tag = LDAP_RES_SEARCH_RESULT;
152 static long send_ldap_ber(
158 ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
160 /* write only one pdu at a time - wait til it's our turn */
161 ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
163 /* lock the connection */
164 ldap_pvt_thread_mutex_lock( &conn->c_mutex );
171 if ( connection_state_closing( conn ) ) {
172 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
173 ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
178 if ( ber_flush( conn->c_sb, ber, 0 ) == 0 ) {
185 * we got an error. if it's ewouldblock, we need to
186 * wait on the socket being writable. otherwise, figure
187 * it's a hard error and return.
190 Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno=%d reason=\"%s\"\n",
191 err, sock_errstr(err), 0 );
193 if ( err != EWOULDBLOCK && err != EAGAIN ) {
194 connection_closing( conn, "connection lost on write" );
196 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
197 ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
202 /* wait for socket to be write-ready */
203 conn->c_writewaiter = 1;
204 ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
205 slapd_set_write( sd, 1 );
207 ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
208 conn->c_writewaiter = 0;
211 ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
212 ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
218 send_ldap_control( BerElement *ber, LDAPControl *c )
224 rc = ber_printf( ber, "{s" /*}*/, c->ldctl_oid );
226 if( c->ldctl_iscritical ) {
227 rc = ber_printf( ber, "b",
228 (ber_int_t) c->ldctl_iscritical ) ;
229 if( rc == -1 ) return rc;
232 if( c->ldctl_value.bv_val != NULL ) {
233 rc = ber_printf( ber, "O", &c->ldctl_value );
234 if( rc == -1 ) return rc;
237 rc = ber_printf( ber, /*{*/"N}" );
238 if( rc == -1 ) return rc;
244 send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
251 rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS );
252 if( rc == -1 ) return rc;
254 for( ; *c != NULL; c++) {
255 rc = send_ldap_control( ber, *c );
256 if( rc == -1 ) return rc;
260 /* this is a hack to avoid having to modify op->s_ctrls */
261 if( o->o_sortedresults ) {
262 BerElementBuffer berbuf;
263 BerElement *sber = (BerElement *) &berbuf;
265 BER_BVZERO( &sorted.ldctl_value );
266 sorted.ldctl_oid = LDAP_CONTROL_SORTRESPONSE;
267 sorted.ldctl_iscritical = 0;
269 ber_init2( sber, NULL, LBER_USE_DER );
271 ber_printf( sber, "{e}", LDAP_UNWILLING_TO_PERFORM );
273 if( ber_flatten2( ber, &sorted.ldctl_value, 0 ) == -1 ) {
277 (void) ber_free_buf( ber );
279 rc = send_ldap_control( ber, &sorted );
280 if( rc == -1 ) return rc;
284 rc = ber_printf( ber, /*{*/"N}" );
297 slap_callback *sc = op->o_callback, **scp;
299 rc = SLAP_CB_CONTINUE;
300 for ( scp = ≻ *scp; ) {
301 slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next;
303 op->o_callback = *scp;
304 if ( op->o_callback->sc_response ) {
305 rc = op->o_callback->sc_response( op, rs );
306 if ( op->o_callback == NULL ) {
307 /* the callback has been removed;
312 } else if ( op->o_callback != *scp ) {
313 /* a new callback has been inserted
314 * after the existing one; repair the list */
315 *sc_nextp = op->o_callback;
316 sc_nextp = &op->o_callback;
318 if ( rc != SLAP_CB_CONTINUE ) break;
325 slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next;
327 rc = SLAP_CB_CONTINUE;
328 for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next) {
329 sc_next = op->o_callback->sc_next;
330 if ( op->o_callback->sc_response ) {
331 slap_callback *sc2 = op->o_callback;
332 rc = op->o_callback->sc_response( op, rs );
333 if ( op->o_callback != sc2 ) {
334 *sc_prev = op->o_callback;
336 if ( rc != SLAP_CB_CONTINUE || !op->o_callback ) break;
337 if ( op->o_callback != sc2 ) continue;
339 sc_prev = &op->o_callback->sc_next;
343 #endif /* ! NEW_CB */
354 slap_callback *sc = op->o_callback, **scp;
356 for ( scp = ≻ *scp; ) {
357 slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next;
359 op->o_callback = *scp;
360 if ( op->o_callback->sc_cleanup ) {
361 (void)op->o_callback->sc_cleanup( op, rs );
362 if ( op->o_callback == NULL ) {
363 /* the callback has been removed;
368 } else if ( op->o_callback != *scp ) {
369 /* a new callback has been inserted
370 * after the existing one; repair the list */
371 *sc_nextp = op->o_callback;
372 sc_nextp = &op->o_callback;
374 /* don't care about the result; do all cleanup */
381 slap_callback *sc = op->o_callback, **sc_prev = &sc, *sc_next;
383 for ( sc_next = op->o_callback; sc_next; op->o_callback = sc_next) {
384 sc_next = op->o_callback->sc_next;
385 if ( op->o_callback->sc_cleanup ) {
386 slap_callback *sc2 = op->o_callback;
387 (void)op->o_callback->sc_cleanup( op, rs );
388 if ( op->o_callback != sc2 ) {
389 *sc_prev = op->o_callback;
391 if ( !op->o_callback ) break;
392 if ( op->o_callback != sc2 ) continue;
394 sc_prev = &op->o_callback->sc_next;
398 #endif /* ! NEW_CB */
408 BerElementBuffer berbuf;
409 BerElement *ber = (BerElement *) &berbuf;
410 int rc = LDAP_SUCCESS;
413 if ( rs->sr_err == SLAPD_ABANDON ) {
418 if ( op->o_callback ) {
419 rc = slap_response_loop( op, rs );
420 if ( rc != SLAP_CB_CONTINUE ) {
425 #ifdef LDAP_CONNECTIONLESS
426 if (op->o_conn && op->o_conn->c_is_udp)
431 ber_init_w_nullc( ber, LBER_USE_DER );
432 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
435 Debug( LDAP_DEBUG_TRACE,
436 "send_ldap_response: msgid=%d tag=%lu err=%d\n",
437 rs->sr_msgid, rs->sr_tag, rs->sr_err );
440 Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
441 rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
445 #ifdef LDAP_CONNECTIONLESS
446 if (op->o_conn && op->o_conn->c_is_udp &&
447 op->o_protocol == LDAP_VERSION2 )
449 rc = ber_printf( ber, "t{ess" /*"}"*/,
450 rs->sr_tag, rs->sr_err,
451 rs->sr_matched == NULL ? "" : rs->sr_matched,
452 rs->sr_text == NULL ? "" : rs->sr_text );
455 if ( rs->sr_type == REP_INTERMEDIATE ) {
456 rc = ber_printf( ber, "{it{" /*"}}"*/,
457 rs->sr_msgid, rs->sr_tag );
460 rc = ber_printf( ber, "{it{ess" /*"}}"*/,
461 rs->sr_msgid, rs->sr_tag, rs->sr_err,
462 rs->sr_matched == NULL ? "" : rs->sr_matched,
463 rs->sr_text == NULL ? "" : rs->sr_text );
467 if ( rs->sr_ref != NULL ) {
468 assert( rs->sr_err == LDAP_REFERRAL );
469 rc = ber_printf( ber, "t{W}",
470 LDAP_TAG_REFERRAL, rs->sr_ref );
472 assert( rs->sr_err != LDAP_REFERRAL );
476 if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) {
477 rc = ber_printf( ber, "tO",
478 LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata );
482 ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE ))
484 if ( rs->sr_rspoid != NULL ) {
485 rc = ber_printf( ber, "ts",
486 rs->sr_type == REP_EXTENDED
487 ? LDAP_TAG_EXOP_RES_OID : LDAP_TAG_IM_RES_OID,
490 if( rc != -1 && rs->sr_rspdata != NULL ) {
491 rc = ber_printf( ber, "tO",
492 rs->sr_type == REP_EXTENDED
493 ? LDAP_TAG_EXOP_RES_VALUE : LDAP_TAG_IM_RES_VALUE,
499 rc = ber_printf( ber, /*"{"*/ "N}" );
503 rc = send_ldap_controls( op, ber, rs->sr_ctrls );
507 rc = ber_printf( ber, /*"{"*/ "N}" );
510 #ifdef LDAP_CONNECTIONLESS
511 if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2
514 rc = ber_printf( ber, /*"{"*/ "N}" );
519 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
521 #ifdef LDAP_CONNECTIONLESS
522 if (!op->o_conn || op->o_conn->c_is_udp == 0)
531 bytes = send_ldap_ber( op->o_conn, ber );
532 #ifdef LDAP_CONNECTIONLESS
533 if (!op->o_conn || op->o_conn->c_is_udp == 0)
540 Debug( LDAP_DEBUG_ANY,
541 "send_ldap_response: ber write failed\n",
547 ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
548 ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
549 ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
550 ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
553 /* Tell caller that we did this for real, as opposed to being
554 * overridden by a callback
556 rc = SLAP_CB_CONTINUE;
559 if ( op->o_callback ) {
560 (void)slap_cleanup_loop( op, rs );
563 if ( rs->sr_matched && rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
564 free( (char *)rs->sr_matched );
565 rs->sr_matched = NULL;
568 if ( rs->sr_ref && rs->sr_flags & REP_REF_MUSTBEFREED ) {
569 ber_bvarray_free( rs->sr_ref );
578 send_ldap_disconnect( Operation *op, SlapReply *rs )
580 #define LDAP_UNSOLICITED_ERROR(e) \
581 ( (e) == LDAP_PROTOCOL_ERROR \
582 || (e) == LDAP_STRONG_AUTH_REQUIRED \
583 || (e) == LDAP_UNAVAILABLE )
585 assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) );
587 rs->sr_type = REP_EXTENDED;
589 Debug( LDAP_DEBUG_TRACE,
590 "send_ldap_disconnect %d:%s\n",
591 rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL );
593 if ( op->o_protocol < LDAP_VERSION3 ) {
594 rs->sr_rspoid = NULL;
595 rs->sr_tag = slap_req2res( op->o_tag );
596 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
599 rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
600 rs->sr_tag = LDAP_RES_EXTENDED;
604 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
605 Statslog( LDAP_DEBUG_STATS,
606 "%s DISCONNECT tag=%lu err=%d text=%s\n",
607 op->o_log_prefix, rs->sr_tag, rs->sr_err,
608 rs->sr_text ? rs->sr_text : "", 0 );
613 slap_send_ldap_result( Operation *op, SlapReply *rs )
616 const char *otext = rs->sr_text;
617 BerVarray oref = rs->sr_ref;
619 rs->sr_type = REP_RESULT;
621 /* Propagate Abandons so that cleanup callbacks can be processed */
622 if ( rs->sr_err == SLAPD_ABANDON )
625 assert( !LDAP_API_ERROR( rs->sr_err ) );
627 Debug( LDAP_DEBUG_TRACE,
628 "send_ldap_result: %s p=%d\n",
629 op->o_log_prefix, op->o_protocol, 0 );
631 Debug( LDAP_DEBUG_ARGS,
632 "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
633 rs->sr_err, rs->sr_matched ? rs->sr_matched : "",
634 rs->sr_text ? rs->sr_text : "" );
638 Debug( LDAP_DEBUG_ARGS,
639 "send_ldap_result: referral=\"%s\"\n",
640 rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
644 assert( rs->sr_err != LDAP_PARTIAL_RESULTS );
646 if ( rs->sr_err == LDAP_REFERRAL ) {
647 if( op->o_domain_scope ) rs->sr_ref = NULL;
649 if( rs->sr_ref == NULL ) {
650 rs->sr_err = LDAP_NO_SUCH_OBJECT;
651 } else if ( op->o_protocol < LDAP_VERSION3 ) {
652 rs->sr_err = LDAP_PARTIAL_RESULTS;
656 if ( op->o_protocol < LDAP_VERSION3 ) {
657 tmp = v2ref( rs->sr_ref, rs->sr_text );
662 rs->sr_tag = slap_req2res( op->o_tag );
663 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
666 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
667 if ( op->o_tag == LDAP_REQ_SEARCH ) {
669 snprintf( nbuf, sizeof nbuf, "%d nentries=%d",
670 rs->sr_err, rs->sr_nentries );
672 Statslog( LDAP_DEBUG_STATS,
673 "%s SEARCH RESULT tag=%lu err=%s text=%s\n",
674 op->o_log_prefix, rs->sr_tag, nbuf,
675 rs->sr_text ? rs->sr_text : "", 0 );
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 );
684 if( tmp != NULL ) ch_free(tmp);
690 send_ldap_sasl( Operation *op, SlapReply *rs )
692 rs->sr_type = REP_SASL;
693 Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n",
695 rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1, NULL );
697 rs->sr_tag = slap_req2res( op->o_tag );
698 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
700 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
701 Statslog( LDAP_DEBUG_STATS,
702 "%s RESULT tag=%lu err=%d text=%s\n",
703 op->o_log_prefix, rs->sr_tag, rs->sr_err,
704 rs->sr_text ? rs->sr_text : "", 0 );
709 slap_send_ldap_extended( Operation *op, SlapReply *rs )
711 rs->sr_type = REP_EXTENDED;
713 Debug( LDAP_DEBUG_TRACE,
714 "send_ldap_extended: err=%d oid=%s len=%ld\n",
716 rs->sr_rspoid ? rs->sr_rspoid : "",
717 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
719 rs->sr_tag = slap_req2res( op->o_tag );
720 rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
722 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
723 Statslog( LDAP_DEBUG_STATS,
724 "%s RESULT oid=%s err=%d text=%s\n",
725 op->o_log_prefix, rs->sr_rspoid ? rs->sr_rspoid : "",
726 rs->sr_err, rs->sr_text ? rs->sr_text : "", 0 );
731 slap_send_ldap_intermediate( Operation *op, SlapReply *rs )
733 rs->sr_type = REP_INTERMEDIATE;
734 Debug( LDAP_DEBUG_TRACE,
735 "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
737 rs->sr_rspoid ? rs->sr_rspoid : "",
738 rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
739 rs->sr_tag = LDAP_RES_INTERMEDIATE;
740 rs->sr_msgid = op->o_msgid;
741 if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
742 Statslog( LDAP_DEBUG_STATS2,
743 "%s INTERM oid=%s\n",
745 rs->sr_rspoid ? rs->sr_rspoid : "", 0, 0, 0 );
752 * LDAP_SUCCESS entry sent
753 * LDAP_OTHER entry not sent (other)
754 * LDAP_INSUFFICIENT_ACCESS entry not sent (ACL)
755 * LDAP_UNAVAILABLE entry not sent (connection closed)
756 * LDAP_SIZELIMIT_EXCEEDED entry not sent (caller must send sizelimitExceeded)
760 slap_send_search_entry( Operation *op, SlapReply *rs )
762 BerElementBuffer berbuf;
763 BerElement *ber = (BerElement *) &berbuf;
765 int i, j, rc = LDAP_UNAVAILABLE, bytes;
768 AccessControlState acl_state = ACL_STATE_INIT;
770 AttributeDescription *ad_entry = slap_schema.si_ad_entry;
772 /* a_flags: array of flags telling if the i-th element will be
773 * returned or filtered out
774 * e_flags: array of a_flags
776 char **e_flags = NULL;
778 if ( op->ors_slimit >= 0 && rs->sr_nentries >= op->ors_slimit ) {
779 return LDAP_SIZELIMIT_EXCEEDED;
782 rs->sr_type = REP_SEARCH;
784 /* eventually will loop through generated operational attribute types
785 * currently implemented types include:
786 * entryDN, subschemaSubentry, and hasSubordinates */
787 /* NOTE: moved before overlays callback circling because
788 * they may modify entry and other stuff in rs */
789 /* check for special all operational attributes ("+") type */
790 /* FIXME: maybe we could set this flag at the operation level;
791 * however, in principle the caller of send_search_entry() may
792 * change the attribute list at each call */
793 rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );
795 rc = backend_operational( op, rs );
800 if ( op->o_callback ) {
801 rc = slap_response_loop( op, rs );
802 if ( rc != SLAP_CB_CONTINUE ) {
807 Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: conn %lu dn=\"%s\"%s\n",
808 op->o_connid, rs->sr_entry->e_name.bv_val,
809 op->ors_attrsonly ? " (attrsOnly)" : "" );
811 attrsonly = op->ors_attrsonly;
813 if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) {
814 Debug( LDAP_DEBUG_ACL,
815 "send_search_entry: conn %lu access to entry (%s) not allowed\n",
816 op->o_connid, rs->sr_entry->e_name.bv_val, 0 );
818 rc = LDAP_INSUFFICIENT_ACCESS;
822 edn = rs->sr_entry->e_nname.bv_val;
824 if ( op->o_res_ber ) {
825 /* read back control or LDAP_CONNECTIONLESS */
830 bv.bv_len = entry_flatsize( rs->sr_entry, 0 );
831 bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );
833 ber_init2( ber, &bv, LBER_USE_DER );
834 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
837 #ifdef LDAP_CONNECTIONLESS
838 if ( op->o_conn && op->o_conn->c_is_udp ) {
840 if ( op->o_protocol == LDAP_VERSION2 ) {
841 rc = ber_printf(ber, "t{O{" /*}}*/,
842 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
844 rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
845 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
849 if ( op->o_res_ber ) {
850 /* read back control */
851 rc = ber_printf( ber, "{O{" /*}}*/, &rs->sr_entry->e_name );
853 rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
854 LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
858 Debug( LDAP_DEBUG_ANY,
859 "send_search_entry: conn %lu ber_printf failed\n",
860 op->o_connid, 0, 0 );
862 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
863 send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" );
868 /* check for special all user attributes ("*") type */
869 userattrs = SLAP_USERATTRS( rs->sr_attr_flags );
871 /* create an array of arrays of flags. Each flag corresponds
872 * to particular value of attribute and equals 1 if value matches
873 * to ValuesReturnFilter or 0 if not
875 if ( op->o_vrFilter != NULL ) {
879 for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
880 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
883 size = i * sizeof(char *) + k;
886 e_flags = slap_sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx );
887 if( e_flags == NULL ) {
888 Debug( LDAP_DEBUG_ANY,
889 "send_search_entry: conn %lu slap_sl_calloc failed\n",
890 op->o_connid ? op->o_connid : 0, 0, 0 );
893 send_ldap_error( op, rs, LDAP_OTHER, "out of memory" );
896 a_flags = (char *)(e_flags + i);
897 memset( a_flags, 0, k );
898 for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) {
899 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
900 e_flags[i] = a_flags;
904 rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ;
906 Debug( LDAP_DEBUG_ANY, "send_search_entry: "
907 "conn %lu matched values filtering failed\n",
908 op->o_connid ? op->o_connid : 0, 0, 0 );
909 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
910 send_ldap_error( op, rs, LDAP_OTHER,
911 "matched values filtering error" );
918 for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
919 AttributeDescription *desc = a->a_desc;
922 if ( rs->sr_attrs == NULL ) {
923 /* all user attrs request, skip operational attributes */
924 if( is_at_operational( desc->ad_type ) ) {
929 /* specific attrs requested */
930 if ( is_at_operational( desc->ad_type ) ) {
931 if ( !SLAP_OPATTRS( rs->sr_attr_flags ) &&
932 !ad_inlist( desc, rs->sr_attrs ) )
938 if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
945 if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
946 ACL_READ, &acl_state ) )
948 Debug( LDAP_DEBUG_ACL, "send_search_entry: "
949 "conn %lu access to attribute %s not allowed\n",
950 op->o_connid, desc->ad_cname.bv_val, 0 );
954 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
955 Debug( LDAP_DEBUG_ANY,
956 "send_search_entry: conn %lu ber_printf failed\n",
957 op->o_connid, 0, 0 );
959 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
960 send_ldap_error( op, rs, LDAP_OTHER,
961 "encoding description error");
969 for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) {
970 if ( ! access_allowed( op, rs->sr_entry,
971 desc, &a->a_nvals[i], ACL_READ, &acl_state ) )
973 Debug( LDAP_DEBUG_ACL,
974 "send_search_entry: conn %lu "
975 "access to attribute %s, value #%d not allowed\n",
976 op->o_connid, desc->ad_cname.bv_val, i );
981 if ( op->o_vrFilter && e_flags[j][i] == 0 ){
988 if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
989 Debug( LDAP_DEBUG_ANY,
990 "send_search_entry: conn %lu ber_printf failed\n",
991 op->o_connid, 0, 0 );
993 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
994 send_ldap_error( op, rs, LDAP_OTHER,
995 "encoding description error");
1000 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1001 Debug( LDAP_DEBUG_ANY,
1002 "send_search_entry: conn %lu "
1003 "ber_printf failed.\n", op->o_connid, 0, 0 );
1005 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1006 send_ldap_error( op, rs, LDAP_OTHER,
1007 "encoding values error" );
1014 if ( finish && ( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1015 Debug( LDAP_DEBUG_ANY,
1016 "send_search_entry: conn %lu ber_printf failed\n",
1017 op->o_connid, 0, 0 );
1019 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1020 send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
1026 /* NOTE: moved before overlays callback circling because
1027 * they may modify entry and other stuff in rs */
1028 if ( rs->sr_operational_attrs != NULL && op->o_vrFilter != NULL ) {
1032 for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
1033 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
1036 size = i * sizeof(char *) + k;
1038 char *a_flags, **tmp;
1041 * Reuse previous memory - we likely need less space
1042 * for operational attributes
1044 tmp = slap_sl_realloc( e_flags, i * sizeof(char *) + k,
1046 if ( tmp == NULL ) {
1047 Debug( LDAP_DEBUG_ANY,
1048 "send_search_entry: conn %lu "
1049 "not enough memory "
1050 "for matched values filtering\n",
1051 op->o_connid, 0, 0 );
1052 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1053 send_ldap_error( op, rs, LDAP_OTHER,
1054 "not enough memory for matched values filtering" );
1058 a_flags = (char *)(e_flags + i);
1059 memset( a_flags, 0, k );
1060 for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
1061 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
1062 e_flags[i] = a_flags;
1065 rc = filter_matched_values(op, rs->sr_operational_attrs, &e_flags) ;
1068 Debug( LDAP_DEBUG_ANY,
1069 "send_search_entry: conn %lu "
1070 "matched values filtering failed\n",
1071 op->o_connid ? op->o_connid : 0, 0, 0);
1072 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1073 send_ldap_error( op, rs, LDAP_OTHER,
1074 "matched values filtering error" );
1081 for (a = rs->sr_operational_attrs, j=0; a != NULL; a = a->a_next, j++ ) {
1082 AttributeDescription *desc = a->a_desc;
1084 if ( rs->sr_attrs == NULL ) {
1085 /* all user attrs request, skip operational attributes */
1086 if( is_at_operational( desc->ad_type ) ) {
1091 /* specific attrs requested */
1092 if( is_at_operational( desc->ad_type ) ) {
1093 if ( !SLAP_OPATTRS( rs->sr_attr_flags ) &&
1094 !ad_inlist( desc, rs->sr_attrs ) )
1099 if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
1105 if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
1106 ACL_READ, &acl_state ) )
1108 Debug( LDAP_DEBUG_ACL,
1109 "send_search_entry: conn %lu "
1110 "access to attribute %s not allowed\n",
1111 op->o_connid, desc->ad_cname.bv_val, 0 );
1116 rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
1118 Debug( LDAP_DEBUG_ANY,
1119 "send_search_entry: conn %lu "
1120 "ber_printf failed\n", op->o_connid, 0, 0 );
1122 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1123 send_ldap_error( op, rs, LDAP_OTHER,
1124 "encoding description error" );
1129 if ( ! attrsonly ) {
1130 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
1131 if ( ! access_allowed( op, rs->sr_entry,
1132 desc, &a->a_vals[i], ACL_READ, &acl_state ) )
1134 Debug( LDAP_DEBUG_ACL,
1135 "send_search_entry: conn %lu "
1136 "access to %s, value %d not allowed\n",
1137 op->o_connid, desc->ad_cname.bv_val, i );
1142 if ( op->o_vrFilter && e_flags[j][i] == 0 ){
1146 if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
1147 Debug( LDAP_DEBUG_ANY,
1148 "send_search_entry: conn %lu ber_printf failed\n",
1149 op->o_connid, 0, 0 );
1151 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1152 send_ldap_error( op, rs, LDAP_OTHER,
1153 "encoding values error" );
1160 if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
1161 Debug( LDAP_DEBUG_ANY,
1162 "send_search_entry: conn %lu ber_printf failed\n",
1163 op->o_connid, 0, 0 );
1165 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1166 send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
1174 slap_sl_free( e_flags, op->o_tmpmemctx );
1178 rc = ber_printf( ber, /*{{*/ "}N}" );
1181 rc = send_ldap_controls( op, ber, rs->sr_ctrls );
1185 #ifdef LDAP_CONNECTIONLESS
1186 if( op->o_conn && op->o_conn->c_is_udp ) {
1187 if ( op->o_protocol != LDAP_VERSION2 ) {
1188 rc = ber_printf( ber, /*{*/ "N}" );
1192 if ( op->o_res_ber == NULL ) {
1193 rc = ber_printf( ber, /*{*/ "N}" );
1198 Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1200 if ( op->o_res_ber == NULL ) ber_free_buf( ber );
1201 send_ldap_error( op, rs, LDAP_OTHER, "encode entry end error" );
1206 if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1207 be_entry_release_rw( op, rs->sr_entry, 0 );
1208 rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
1209 rs->sr_entry = NULL;
1212 if ( op->o_res_ber == NULL ) {
1213 bytes = send_ldap_ber( op->o_conn, ber );
1214 ber_free_buf( ber );
1217 Debug( LDAP_DEBUG_ANY,
1218 "send_search_entry: conn %lu ber write failed.\n",
1219 op->o_connid, 0, 0 );
1221 rc = LDAP_UNAVAILABLE;
1226 ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
1227 ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
1228 ldap_pvt_mp_add_ulong( slap_counters.sc_entries, 1 );
1229 ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
1230 ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
1233 Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n",
1234 op->o_log_prefix, edn, 0, 0, 0 );
1236 Debug( LDAP_DEBUG_TRACE,
1237 "<= send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
1242 if ( op->o_callback ) {
1243 (void)slap_cleanup_loop( op, rs );
1247 slap_sl_free( e_flags, op->o_tmpmemctx );
1250 if ( rs->sr_operational_attrs ) {
1251 attrs_free( rs->sr_operational_attrs );
1252 rs->sr_operational_attrs = NULL;
1254 rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED;
1256 /* FIXME: I think rs->sr_type should be explicitly set to
1257 * REP_SEARCH here. That's what it was when we entered this
1258 * function. send_ldap_error may have changed it, but we
1259 * should set it back so that the cleanup functions know
1260 * what they're doing.
1262 if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH
1264 && ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) )
1266 entry_free( rs->sr_entry );
1267 rs->sr_entry = NULL;
1268 rs->sr_flags &= ~REP_ENTRY_MUSTBEFREED;
1275 slap_send_search_reference( Operation *op, SlapReply *rs )
1277 BerElementBuffer berbuf;
1278 BerElement *ber = (BerElement *) &berbuf;
1282 AttributeDescription *ad_ref = slap_schema.si_ad_ref;
1283 AttributeDescription *ad_entry = slap_schema.si_ad_entry;
1285 rs->sr_type = REP_SEARCHREF;
1286 if ( op->o_callback ) {
1287 rc = slap_response_loop( op, rs );
1288 if ( rc != SLAP_CB_CONTINUE ) {
1293 Debug( LDAP_DEBUG_TRACE,
1294 "=> send_search_reference: dn=\"%s\"\n",
1295 rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0, 0 );
1297 if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
1298 ad_entry, NULL, ACL_READ, NULL ) )
1300 Debug( LDAP_DEBUG_ACL,
1301 "send_search_reference: access to entry not allowed\n",
1307 if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
1308 ad_ref, NULL, ACL_READ, NULL ) )
1310 Debug( LDAP_DEBUG_ACL,
1311 "send_search_reference: access "
1312 "to reference not allowed\n",
1318 if( op->o_domain_scope ) {
1319 Debug( LDAP_DEBUG_ANY,
1320 "send_search_reference: domainScope control in (%s)\n",
1321 rs->sr_entry->e_dn, 0, 0 );
1326 if( rs->sr_ref == NULL ) {
1327 Debug( LDAP_DEBUG_ANY,
1328 "send_search_reference: null ref in (%s)\n",
1329 rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 );
1334 if( op->o_protocol < LDAP_VERSION3 ) {
1336 /* save the references for the result */
1337 if( rs->sr_ref[0].bv_val != NULL ) {
1338 if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
1344 #ifdef LDAP_CONNECTIONLESS
1345 if( op->o_conn && op->o_conn->c_is_udp ) {
1346 ber = op->o_res_ber;
1350 ber_init_w_nullc( ber, LBER_USE_DER );
1351 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
1354 rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
1355 LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );
1358 rc = send_ldap_controls( op, ber, rs->sr_ctrls );
1362 rc = ber_printf( ber, /*"{"*/ "N}" );
1366 Debug( LDAP_DEBUG_ANY,
1367 "send_search_reference: ber_printf failed\n", 0, 0, 0 );
1369 #ifdef LDAP_CONNECTIONLESS
1370 if (!op->o_conn || op->o_conn->c_is_udp == 0)
1372 ber_free_buf( ber );
1373 send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" );
1378 if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1379 be_entry_release_rw( op, rs->sr_entry, 0 );
1380 rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
1381 rs->sr_entry = NULL;
1384 #ifdef LDAP_CONNECTIONLESS
1385 if (!op->o_conn || op->o_conn->c_is_udp == 0) {
1387 bytes = send_ldap_ber( op->o_conn, ber );
1388 ber_free_buf( ber );
1390 ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
1391 ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
1392 ldap_pvt_mp_add_ulong( slap_counters.sc_refs, 1 );
1393 ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
1394 ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
1395 #ifdef LDAP_CONNECTIONLESS
1398 if ( rs->sr_ref != NULL ) {
1401 for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) {
1402 Statslog( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n",
1403 op->o_log_prefix, r, rs->sr_ref[0].bv_val,
1408 Statslog( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n",
1409 op->o_log_prefix, 0, 0, 0, 0 );
1412 Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
1415 if ( op->o_callback ) {
1416 (void)slap_cleanup_loop( op, rs );
1432 *code = LDAP_SUCCESS;
1436 if ( strncasecmp( s, "RESULT", STRLENOF( "RESULT" ) ) != 0 ) {
1437 Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
1444 while ( (s = strchr( s, '\n' )) != NULL ) {
1449 if ( (c = strchr( s, ':' )) != NULL ) {
1453 if ( strncasecmp( s, "code", STRLENOF( "code" ) ) == 0 ) {
1454 if ( c != NULL && lutil_atoi( code, c ) != 0 ) {
1457 } else if ( strncasecmp( s, "matched", STRLENOF( "matched" ) ) == 0 ) {
1461 } else if ( strncasecmp( s, "info", STRLENOF( "info" ) ) == 0 ) {
1467 Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
1477 int slap_read_controls(
1481 const struct berval *oid,
1482 LDAPControl **ctrl )
1486 BerElementBuffer berbuf;
1487 BerElement *ber = (BerElement *) &berbuf;
1491 Debug( LDAP_DEBUG_ANY, "slap_read_controls: (%s) %s\n",
1492 oid->bv_val, e->e_dn, 0 );
1495 rs->sr_attrs = ( oid == &slap_pre_read_bv ) ?
1496 op->o_preread_attrs : op->o_postread_attrs;
1498 bv.bv_len = entry_flatsize( rs->sr_entry, 0 );
1499 bv.bv_val = op->o_tmpalloc(bv.bv_len, op->o_tmpmemctx );
1501 ber_init2( ber, &bv, LBER_USE_DER );
1502 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
1504 /* create new operation */
1507 myop.o_res_ber = ber;
1508 myop.o_callback = NULL;
1509 myop.ors_slimit = 1;
1511 rc = slap_send_search_entry( &myop, rs );
1514 rc = ber_flatten2( ber, &c.ldctl_value, 0 );
1516 if( rc == LBER_ERROR ) return LDAP_OTHER;
1518 c.ldctl_oid = oid->bv_val;
1519 c.ldctl_iscritical = 0;
1521 if ( *ctrl == NULL ) {
1523 *ctrl = (LDAPControl *) slap_sl_calloc( 1, sizeof(LDAPControl), NULL );
1525 /* retry: free previous try */
1526 slap_sl_free( (*ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
1530 return LDAP_SUCCESS;
1533 /* Map API errors to protocol errors... */
1535 slap_map_api2result( SlapReply *rs )
1537 switch(rs->sr_err) {
1538 case LDAP_SERVER_DOWN:
1539 return LDAP_UNAVAILABLE;
1540 case LDAP_LOCAL_ERROR:
1542 case LDAP_ENCODING_ERROR:
1543 case LDAP_DECODING_ERROR:
1544 return LDAP_PROTOCOL_ERROR;
1546 return LDAP_UNAVAILABLE;
1547 case LDAP_AUTH_UNKNOWN:
1548 return LDAP_AUTH_METHOD_NOT_SUPPORTED;
1549 case LDAP_FILTER_ERROR:
1550 rs->sr_text = "Filter error";
1552 case LDAP_USER_CANCELLED:
1553 rs->sr_text = "User cancelled";
1555 case LDAP_PARAM_ERROR:
1556 return LDAP_PROTOCOL_ERROR;
1557 case LDAP_NO_MEMORY:
1559 case LDAP_CONNECT_ERROR:
1560 return LDAP_UNAVAILABLE;
1561 case LDAP_NOT_SUPPORTED:
1562 return LDAP_UNWILLING_TO_PERFORM;
1563 case LDAP_CONTROL_NOT_FOUND:
1564 return LDAP_PROTOCOL_ERROR;
1565 case LDAP_NO_RESULTS_RETURNED:
1566 return LDAP_NO_SUCH_OBJECT;
1567 case LDAP_MORE_RESULTS_TO_RETURN:
1568 rs->sr_text = "More results to return";
1570 case LDAP_CLIENT_LOOP:
1571 case LDAP_REFERRAL_LIMIT_EXCEEDED:
1572 return LDAP_LOOP_DETECT;
1574 if ( LDAP_API_ERROR(rs->sr_err) ) return LDAP_OTHER;
1581 slap_attr_flags( AttributeName *an )
1583 slap_mask_t flags = SLAP_ATTRS_UNDEFINED;
1586 flags |= ( SLAP_OPATTRS_NO | SLAP_USERATTRS_YES );
1589 flags |= an_find( an, &AllOper )
1590 ? SLAP_OPATTRS_YES : SLAP_OPATTRS_NO;
1591 flags |= an_find( an, &AllUser )
1592 ? SLAP_USERATTRS_YES : SLAP_USERATTRS_NO;