X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fresult.c;h=b765a7637f09e053f51e90b7357d259ce2fa034d;hb=4e15a84452f0493b1b5bc7b779c7bd1cd4fa4b73;hp=ccc1de308336c816201a3ada61da4c65b11bc830;hpb=a038ef68e618e9f8f43220af52c2729c7c7b36c9;p=openldap diff --git a/servers/slapd/result.c b/servers/slapd/result.c index ccc1de3083..b765a7637f 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -1,8 +1,27 @@ /* result.c - routines to send ldap results, errors, and referrals */ /* $OpenLDAP$ */ -/* - * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2003 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. */ #include "portable.h" @@ -18,6 +37,10 @@ #include "slap.h" +#ifdef LDAP_SLAPI +#include "slapi.h" +#endif + static char *v2ref( BerVarray ref, const char *text ) { size_t len = 0, i = 0; @@ -38,7 +61,16 @@ static char *v2ref( BerVarray ref, const char *text ) } } - v2 = ch_malloc( len+i+sizeof("Referral:") ); + v2 = SLAP_MALLOC( len+i+sizeof("Referral:") ); + if( v2 == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ERR, "v2ref: SLAP_MALLOC failed", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "v2ref: SLAP_MALLOC failed", 0, 0, 0 ); +#endif + return NULL; + } + if( text != NULL ) { strcpy(v2, text); if( i ) { @@ -49,7 +81,15 @@ static char *v2ref( BerVarray ref, const char *text ) len += sizeof("Referral:"); for( i=0; ref[i].bv_val != NULL; i++ ) { - v2 = ch_realloc( v2, len + ref[i].bv_len + 1 ); + v2 = SLAP_REALLOC( v2, len + ref[i].bv_len + 1 ); + if( v2 == NULL ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ERR, "v2ref: SLAP_MALLOC failed", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "v2ref: SLAP_MALLOC failed", 0, 0, 0 ); +#endif + return NULL; + } v2[len-1] = '\n'; AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len ); len += ref[i].bv_len; @@ -197,120 +237,109 @@ send_ldap_controls( BerElement *ber, LDAPControl **c ) return rc; } -static void +void send_ldap_response( - Connection *conn, - Operation *op, - ber_tag_t tag, - ber_int_t msgid, - ber_int_t err, - const char *matched, - const char *text, - BerVarray ref, - const char *resoid, - struct berval *resdata, - struct berval *sasldata, - LDAPControl **ctrls -) + Operation *op, + SlapReply *rs ) { - char berbuf[256]; - BerElement *ber = (BerElement *)berbuf; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; int rc; long bytes; if (op->o_callback && op->o_callback->sc_response) { - op->o_callback->sc_response( conn, op, tag, msgid, err, matched, - text, ref, resoid, resdata, sasldata, ctrls ); - return; + rc = op->o_callback->sc_response( op, rs ); + if ( rc != SLAP_CB_CONTINUE ) return; } - assert( ctrls == NULL ); /* ctrls not implemented */ - - ber_init_w_nullc( ber, LBER_USE_DER ); +#ifdef LDAP_CONNECTIONLESS + if (op->o_conn && op->o_conn->c_is_udp) + ber = op->o_res_ber; + else +#endif + { + ber_init_w_nullc( ber, LBER_USE_DER ); + ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); + } #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "send_ldap_response: msgid=%d tag=%lu err=%d\n", - msgid, tag, err ); + rs->sr_msgid, rs->sr_tag, rs->sr_err ); #else Debug( LDAP_DEBUG_TRACE, "send_ldap_response: msgid=%d tag=%lu err=%d\n", - msgid, tag, err ); + rs->sr_msgid, rs->sr_tag, rs->sr_err ); #endif - if( ref ) { + if( rs->sr_ref ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, "send_ldap_response: conn %lu ref=\"%s\"\n", - conn ? conn->c_connid : 0, - ref[0].bv_val ? ref[0].bv_val : "NULL" , 0 ); + op->o_connid, + rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL" , 0 ); #else Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n", - ref[0].bv_val ? ref[0].bv_val : "NULL", + rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL", NULL, NULL ); #endif } #ifdef LDAP_CONNECTIONLESS - if (conn->c_is_udp) { - rc = ber_write(ber, (char *)&op->o_peeraddr, sizeof(struct sockaddr), 0); - if (rc != sizeof(struct sockaddr)) { -#ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "send_ldap_response: conn %lu ber_write failed\n", - conn ? conn->c_connid : 0 , 0, 0); -#else - Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 ); -#endif - ber_free_buf( ber ); - return; - } - } - if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2) { - rc = ber_printf( ber, "{is{t{ess" /*"}}}"*/, - msgid, "", tag, err, - matched == NULL ? "" : matched, - text == NULL ? "" : text ); - } else -#endif + if (op->o_conn && op->o_conn->c_is_udp && + op->o_protocol == LDAP_VERSION2 ) { + rc = ber_printf( ber, "t{ess" /*"}}"*/, + rs->sr_tag, rs->sr_err, + rs->sr_matched == NULL ? "" : rs->sr_matched, + rs->sr_text == NULL ? "" : rs->sr_text ); + } else +#endif + if ( rs->sr_type == REP_INTERMEDIATE ) { + rc = ber_printf( ber, "{it{" /*"}}"*/, + rs->sr_msgid, rs->sr_tag ); + + } else { rc = ber_printf( ber, "{it{ess" /*"}}"*/, - msgid, tag, err, - matched == NULL ? "" : matched, - text == NULL ? "" : text ); + rs->sr_msgid, rs->sr_tag, rs->sr_err, + rs->sr_matched == NULL ? "" : rs->sr_matched, + rs->sr_text == NULL ? "" : rs->sr_text ); } if( rc != -1 ) { - if ( ref != NULL ) { - assert( err == LDAP_REFERRAL ); + if ( rs->sr_ref != NULL ) { + assert( rs->sr_err == LDAP_REFERRAL ); rc = ber_printf( ber, "t{W}", - LDAP_TAG_REFERRAL, ref ); + LDAP_TAG_REFERRAL, rs->sr_ref ); } else { - assert( err != LDAP_REFERRAL ); + assert( rs->sr_err != LDAP_REFERRAL ); } } - if( rc != -1 && sasldata != NULL ) { + if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) { rc = ber_printf( ber, "tO", - LDAP_TAG_SASL_RES_CREDS, sasldata ); - } - - if( rc != -1 && resoid != NULL ) { - rc = ber_printf( ber, "ts", - LDAP_TAG_EXOP_RES_OID, resoid ); + LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata ); } - if( rc != -1 && resdata != NULL ) { - rc = ber_printf( ber, "tO", - LDAP_TAG_EXOP_RES_VALUE, resdata ); + if( rc != -1 && + ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE )) + { + if ( rs->sr_rspoid != NULL ) { + rc = ber_printf( ber, "ts", + LDAP_TAG_EXOP_RES_OID, rs->sr_rspoid ); + } + if( rc != -1 && rs->sr_rspdata != NULL ) { + rc = ber_printf( ber, "tO", + LDAP_TAG_EXOP_RES_VALUE, rs->sr_rspdata ); + } } if( rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } - if( rc != -1 && ctrls != NULL ) { - rc = send_ldap_controls( ber, ctrls ); + if( rc != -1 && rs->sr_ctrls != NULL ) { + rc = send_ldap_controls( ber, rs->sr_ctrls ); } if( rc != -1 ) { @@ -318,33 +347,39 @@ send_ldap_response( } #ifdef LDAP_CONNECTIONLESS - if( conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1 ) { + if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } #endif - + if ( rc == -1 ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "send_ldap_response: conn %lu ber_printf failed\n", - conn ? conn->c_connid : 0, 0, 0 ); + op->o_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); #endif +#ifdef LDAP_CONNECTIONLESS + if (!op->o_conn || op->o_conn->c_is_udp == 0) +#endif ber_free_buf( ber ); return; } /* send BER */ - bytes = send_ldap_ber( conn, ber ); + bytes = send_ldap_ber( op->o_conn, ber ); +#ifdef LDAP_CONNECTIONLESS + if (!op->o_conn || op->o_conn->c_is_udp == 0) +#endif ber_free_buf( ber ); if ( bytes < 0 ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "send_ldap_response: conn %lu ber write failed\n", - conn ? conn->c_connid : 0, 0, 0 ); + op->o_connid ? op->o_connid : 0, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "send_ldap_response: ber write failed\n", @@ -354,6 +389,14 @@ send_ldap_response( return; } +#ifdef LDAP_SLAPI + if ( op->o_pb ) { + slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text ); + } +#endif /* LDAP_SLAPI */ + ldap_pvt_thread_mutex_lock( &num_sent_mutex ); num_bytes_sent += bytes; num_pdu_sent++; @@ -363,75 +406,60 @@ send_ldap_response( void -send_ldap_disconnect( - Connection *conn, - Operation *op, - ber_int_t err, - const char *text -) +send_ldap_disconnect( Operation *op, SlapReply *rs ) { - ber_tag_t tag; - ber_int_t msgid; - char *reqoid; - #define LDAP_UNSOLICITED_ERROR(e) \ ( (e) == LDAP_PROTOCOL_ERROR \ || (e) == LDAP_STRONG_AUTH_REQUIRED \ || (e) == LDAP_UNAVAILABLE ) - assert( LDAP_UNSOLICITED_ERROR( err ) ); + assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) ); + + rs->sr_type = REP_EXTENDED; #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "send_ldap_disconnect: conn %lu %d:%s\n", - conn ? conn->c_connid : 0, err, text ? text : "" ); + op->o_connid, rs->sr_err, rs->sr_text ? rs->sr_text : "" ); #else Debug( LDAP_DEBUG_TRACE, "send_ldap_disconnect %d:%s\n", - err, text ? text : "", NULL ); + rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL ); #endif if ( op->o_protocol < LDAP_VERSION3 ) { - reqoid = NULL; - tag = req2res( op->o_tag ); - msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0; + rs->sr_rspoid = NULL; + rs->sr_tag = req2res( op->o_tag ); + rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; } else { - reqoid = LDAP_NOTICE_DISCONNECT; - tag = LDAP_RES_EXTENDED; - msgid = 0; + rs->sr_rspoid = LDAP_NOTICE_DISCONNECT; + rs->sr_tag = LDAP_RES_EXTENDED; + rs->sr_msgid = 0; } - send_ldap_response( conn, op, tag, msgid, - err, NULL, text, NULL, - reqoid, NULL, NULL, NULL ); + send_ldap_response( op, rs ); Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu DISCONNECT tag=%lu err=%d text=%s\n", - op->o_connid, op->o_opid, tag, err, text ? text : "" ); + op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err, rs->sr_text ? rs->sr_text : "" ); } void -send_ldap_result( - Connection *conn, - Operation *op, - ber_int_t err, - const char *matched, - const char *text, - BerVarray ref, - LDAPControl **ctrls -) +slap_send_ldap_result( Operation *op, SlapReply *rs ) { - ber_tag_t tag; - ber_int_t msgid; char *tmp = NULL; + const char *otext = rs->sr_text; + BerVarray oref = rs->sr_ref; + + rs->sr_type = REP_RESULT; - assert( !LDAP_API_ERROR( err ) ); + assert( !LDAP_API_ERROR( rs->sr_err ) && ( rs->sr_err >= 0 )); #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, - "send_ldap_result : conn %lu op=%lu p=%d\n", + "send_ldap_result: conn %lu op=%lu p=%d\n", op->o_connid, op->o_opid, op->o_protocol ); #else Debug( LDAP_DEBUG_TRACE, @@ -442,229 +470,175 @@ send_ldap_result( #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n", - err, matched ? matched : "", text ? text : "" ); + rs->sr_err, rs->sr_matched ? rs->sr_matched : "", + rs->sr_text ? rs->sr_text : "" ); #else Debug( LDAP_DEBUG_ARGS, "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n", - err, matched ? matched : "", text ? text : "" ); + rs->sr_err, rs->sr_matched ? rs->sr_matched : "", + rs->sr_text ? rs->sr_text : "" ); #endif - if( ref ) { + if( rs->sr_ref ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, "send_ldap_result: referral=\"%s\"\n", - ref[0].bv_val ? ref[0].bv_val : "NULL", 0, 0 ); + rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL", 0, 0 ); #else Debug( LDAP_DEBUG_ARGS, "send_ldap_result: referral=\"%s\"\n", - ref[0].bv_val ? ref[0].bv_val : "NULL", + rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL", NULL, NULL ); #endif } - assert( err != LDAP_PARTIAL_RESULTS ); + assert( rs->sr_err != LDAP_PARTIAL_RESULTS ); - if ( err == LDAP_REFERRAL ) { - if( ref == NULL ) { - err = LDAP_NO_SUCH_OBJECT; + if ( rs->sr_err == LDAP_REFERRAL ) { +#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE + if( op->o_domain_scope ) { + rs->sr_ref = NULL; + } +#endif + if( rs->sr_ref == NULL ) { + rs->sr_err = LDAP_NO_SUCH_OBJECT; } else if ( op->o_protocol < LDAP_VERSION3 ) { - err = LDAP_PARTIAL_RESULTS; + rs->sr_err = LDAP_PARTIAL_RESULTS; } } +#ifdef LDAP_SLAPI + /* + * Call pre-result plugins. To avoid infinite recursion plugins + * should just set SLAPI_RESULT_CODE rather than sending a + * result if they wish to change the result. + */ + if ( op->o_pb ) { + slapi_x_pblock_set_operation( op->o_pb, op ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text ); + slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched ); + + (void) doPluginFNs( op->o_bd, SLAPI_PLUGIN_PRE_RESULT_FN, op->o_pb ); + } +#endif /* LDAP_SLAPI */ + if ( op->o_protocol < LDAP_VERSION3 ) { - tmp = v2ref( ref, text ); - text = tmp; - ref = NULL; + tmp = v2ref( rs->sr_ref, rs->sr_text ); + rs->sr_text = tmp; + rs->sr_ref = NULL; } - tag = req2res( op->o_tag ); - msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0; + rs->sr_tag = req2res( op->o_tag ); + rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; - send_ldap_response( conn, op, tag, msgid, - err, matched, text, ref, - NULL, NULL, NULL, ctrls ); + send_ldap_response( op, rs ); - Statslog( LDAP_DEBUG_STATS, - "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n", - op->o_connid, op->o_opid, tag, err, text ? text : "" ); + if ( op->o_tag == LDAP_REQ_SEARCH ) { + char nbuf[64]; + snprintf( nbuf, sizeof nbuf, "%d nentries=%d", + rs->sr_err, rs->sr_nentries ); - if( tmp != NULL ) { - ch_free(tmp); + Statslog( LDAP_DEBUG_STATS, + "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n", + op->o_connid, op->o_opid, rs->sr_tag, nbuf, + rs->sr_text ? rs->sr_text : "" ); + } else { + Statslog( LDAP_DEBUG_STATS, + "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n", + op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err, + rs->sr_text ? rs->sr_text : "" ); } + + if( tmp != NULL ) ch_free(tmp); + rs->sr_text = otext; + rs->sr_ref = oref; } void -send_ldap_sasl( - Connection *conn, - Operation *op, - ber_int_t err, - const char *matched, - const char *text, - BerVarray ref, - LDAPControl **ctrls, - struct berval *cred -) +send_ldap_sasl( Operation *op, SlapReply *rs ) { - ber_tag_t tag; - ber_int_t msgid; - + rs->sr_type = REP_SASL; #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "send_ldap_sasl: conn %lu err=%d len=%lu\n", - op->o_connid, err, cred ? cred->bv_len : -1 ); + op->o_connid, rs->sr_err, + rs->sr_sasldata ? rs->sr_sasldata->bv_len : -1 ); #else Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n", - err, cred ? (long) cred->bv_len : -1, NULL ); + rs->sr_err, + rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1, NULL ); #endif + rs->sr_tag = req2res( op->o_tag ); + rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; - tag = req2res( op->o_tag ); - msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0; - - send_ldap_response( conn, op, tag, msgid, - err, matched, text, ref, - NULL, NULL, cred, ctrls ); + send_ldap_response( op, rs ); } void -send_ldap_extended( - Connection *conn, - Operation *op, - ber_int_t err, - const char *matched, - const char *text, - BerVarray refs, - const char *rspoid, - struct berval *rspdata, - LDAPControl **ctrls -) +slap_send_ldap_extended( Operation *op, SlapReply *rs ) { - ber_tag_t tag; - ber_int_t msgid; + rs->sr_type = REP_EXTENDED; #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "send_ldap_extended: err=%d oid=%s len=%ld\n", - err, rspoid ? rspoid : "", - rspdata != NULL ? rspdata->bv_len : 0 ); + rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "", + rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); #else Debug( LDAP_DEBUG_TRACE, - "send_ldap_extended err=%d oid=%s len=%ld\n", - err, - rspoid ? rspoid : "", - rspdata != NULL ? rspdata->bv_len : 0 ); + "send_ldap_extended: err=%d oid=%s len=%ld\n", + rs->sr_err, + rs->sr_rspoid ? rs->sr_rspoid : "", + rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); #endif + rs->sr_tag = req2res( op->o_tag ); + rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; - tag = req2res( op->o_tag ); - msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0; - - send_ldap_response( conn, op, tag, msgid, - err, matched, text, refs, - rspoid, rspdata, NULL, ctrls ); + send_ldap_response( op, rs ); } - void -send_search_result( - Connection *conn, - Operation *op, - ber_int_t err, - const char *matched, - const char *text, - BerVarray refs, - LDAPControl **ctrls, - int nentries -) +slap_send_ldap_intermediate( Operation *op, SlapReply *rs ) { - ber_tag_t tag; - ber_int_t msgid; - char *tmp = NULL; - - assert( !LDAP_API_ERROR( err ) ); - - if (op->o_callback && op->o_callback->sc_sresult) { - op->o_callback->sc_sresult(conn, op, err, matched, text, refs, - ctrls, nentries); - return; - } - + rs->sr_type = REP_INTERMEDIATE; #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ENTRY, - "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n", - err, matched ? matched : "", text ? text : "" ); + LDAP_LOG( OPERATION, ENTRY, + "send_ldap_intermediate: err=%d oid=%s len=%ld\n", + rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "", + rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); #else Debug( LDAP_DEBUG_TRACE, - "send_search_result: err=%d matched=\"%s\" text=\"%s\"\n", - err, matched ? matched : "", text ? text : "" ); + "send_ldap_intermediate: err=%d oid=%s len=%ld\n", + rs->sr_err, + rs->sr_rspoid ? rs->sr_rspoid : "", + rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); #endif - - - assert( err != LDAP_PARTIAL_RESULTS ); - - if( op->o_protocol < LDAP_VERSION3 ) { - /* send references in search results */ - if( err == LDAP_REFERRAL ) { - err = LDAP_PARTIAL_RESULTS; - } - - tmp = v2ref( refs, text ); - text = tmp; - refs = NULL; - - } else { - /* don't send references in search results */ - assert( refs == NULL ); - refs = NULL; - - if( err == LDAP_REFERRAL ) { - err = LDAP_SUCCESS; - } - } - - tag = req2res( op->o_tag ); - msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0; - - send_ldap_response( conn, op, tag, msgid, - err, matched, text, refs, - NULL, NULL, NULL, ctrls ); - - { - char nbuf[64]; - snprintf( nbuf, sizeof nbuf, "%d nentries=%d", err, nentries ); - - Statslog( LDAP_DEBUG_STATS, - "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n", - op->o_connid, op->o_opid, tag, nbuf, text ? text : "" ); - } - - if (tmp != NULL) { - ch_free(tmp); - } + rs->sr_tag = LDAP_RES_INTERMEDIATE; + rs->sr_msgid = op->o_msgid; + send_ldap_response( op, rs ); } int -send_search_entry( - Backend *be, - Connection *conn, - Operation *op, - Entry *e, - AttributeName *attrs, - int attrsonly, - LDAPControl **ctrls -) +slap_send_search_entry( Operation *op, SlapReply *rs ) { - char berbuf[256]; - BerElement *ber = (BerElement *)berbuf; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; Attribute *a, *aa; int i, j, rc=-1, bytes; char *edn; int userattrs; int opattrs; - static AccessControlState acl_state_init = ACL_STATE_INIT; - AccessControlState acl_state; + AccessControlState acl_state = ACL_STATE_INIT; +#ifdef LDAP_SLAPI + /* Support for computed attribute plugins */ + computed_attr_context ctx; + AttributeName *anp; +#endif + void *mark = NULL; AttributeDescription *ad_entry = slap_schema.si_ad_entry; @@ -674,64 +648,74 @@ send_search_entry( */ char **e_flags = NULL; - if (op->o_callback && op->o_callback->sc_sendentry) { - return op->o_callback->sc_sendentry( be, conn, op, e, attrs, - attrsonly, ctrls ); + rs->sr_type = REP_SEARCH; + if (op->o_callback && op->o_callback->sc_response) { + rc = op->o_callback->sc_response( op, rs ); + if ( rc != SLAP_CB_CONTINUE ) return rc; } #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ENTRY, - "send_search_entry: conn %lu dn=\"%s\"%s\n", - op->o_connid, e->e_dn, attrsonly ? " (attrsOnly)" : "" ); + LDAP_LOG( OPERATION, ENTRY, "send_search_entry: conn %lu dn=\"%s\"%s\n", + op->o_connid, rs->sr_entry->e_name.bv_val, + op->ors_attrsonly ? " (attrsOnly)" : "" ); #else - Debug( LDAP_DEBUG_TRACE, - "=> send_search_entry: dn=\"%s\"%s\n", - e->e_dn, attrsonly ? " (attrsOnly)" : "", 0 ); + Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: dn=\"%s\"%s\n", + rs->sr_entry->e_name.bv_val, + op->ors_attrsonly ? " (attrsOnly)" : "", 0 ); #endif - if ( ! access_allowed( be, conn, op, e, - ad_entry, NULL, ACL_READ, NULL ) ) - { + mark = sl_mark( op->o_tmpmemctx ); + + if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) { #ifdef NEW_LOGGING LDAP_LOG( ACL, INFO, "send_search_entry: conn %lu access to entry (%s) not allowed\n", - op->o_connid, e->e_dn, 0 ); + op->o_connid, rs->sr_entry->e_name.bv_val, 0 ); #else Debug( LDAP_DEBUG_ACL, "send_search_entry: access to entry not allowed\n", 0, 0, 0 ); #endif + sl_release( mark, op->o_tmpmemctx ); return( 1 ); } - edn = e->e_ndn; + edn = rs->sr_entry->e_nname.bv_val; - ber_init_w_nullc( ber, LBER_USE_DER ); + if ( op->o_res_ber ) { + /* read back control or LDAP_CONNECTIONLESS */ + ber = op->o_res_ber; + } else { + ber_len_t siz, len; + struct berval bv; -#ifdef LDAP_CONNECTIONLESS - if (conn->c_is_udp) { - rc = ber_write(ber, (char *)&op->o_peeraddr, sizeof(struct sockaddr), 0); - if (rc != sizeof(struct sockaddr)) { -#ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "send_search_entry: conn %lu ber_printf failed\n", - conn ? conn->c_connid : 0, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); -#endif - ber_free_buf( ber ); - return( 1 ); - } + entry_flatsize( rs->sr_entry, &siz, &len, 0 ); + bv.bv_len = siz + len; + bv.bv_val = op->o_tmpalloc(bv.bv_len, op->o_tmpmemctx ); + + ber_init2( ber, &bv, LBER_USE_DER ); + ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); } - if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2) { - rc = ber_printf( ber, "{is{t{O{" /*}}}*/, - op->o_msgid, "", LDAP_RES_SEARCH_ENTRY, &e->e_name ); + +#ifdef LDAP_CONNECTIONLESS + if ( op->o_conn && op->o_conn->c_is_udp ) { + /* CONNECTIONLESS */ + if ( op->o_protocol == LDAP_VERSION2 ) { + rc = ber_printf(ber, "t{O{" /*}}*/, + LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); + } else { + rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid, + LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); + } } else -#endif /* LDAP_CONNECTIONLESS */ - { +#endif + if ( op->o_res_ber ) { + /* read back control */ + rc = ber_printf( ber, "{O{" /*}}*/, &rs->sr_entry->e_name ); + } else { rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid, - LDAP_RES_SEARCH_ENTRY, &e->e_name ); + LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); } if ( rc == -1 ) { @@ -743,62 +727,79 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encoding DN error", NULL, NULL ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" ); goto error_return; } /* check for special all user attributes ("*") type */ - userattrs = ( attrs == NULL ) ? 1 - : an_find( attrs, &AllUser ); + userattrs = ( rs->sr_attrs == NULL ) ? 1 + : an_find( rs->sr_attrs, &AllUser ); /* check for special all operational attributes ("+") type */ - opattrs = ( attrs == NULL ) ? 0 - : an_find( attrs, &AllOper ); + opattrs = ( rs->sr_attrs == NULL ) ? 0 + : an_find( rs->sr_attrs, &AllOper ); /* create an array of arrays of flags. Each flag corresponds * to particular value of attribute and equals 1 if value matches * to ValuesReturnFilter or 0 if not */ - if ( op->vrFilter != NULL ) { - int k = 0; - char *a_flags; + if ( op->o_vrFilter != NULL ) { + int k = 0; + size_t size; - for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) { + for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) { for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++; } - e_flags = ch_calloc ( 1, i * sizeof(char *) + k ); - a_flags = (char *)(e_flags + i); - for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) { - for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); - e_flags[i] = a_flags; - a_flags += j; - } - rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ; - if ( rc == -1 ) { + size = i * sizeof(char *) + k; + if ( size > 0 ) { + char *a_flags; + e_flags = sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx ); + if( e_flags == NULL ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "send_search_entry: conn %lu matched values filtering failed\n", - conn ? conn->c_connid : 0, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "send_search_entry: conn %lu sl_calloc failed\n", + op->o_connid ? op->o_connid : 0, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, - "matched values filtering failed\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, + "send_search_entry: sl_calloc failed\n", 0, 0, 0 ); #endif - ber_free( ber, 1 ); - - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "matched values filtering error", - NULL, NULL ); - goto error_return; + ber_free( ber, 1 ); + + send_ldap_error( op, rs, LDAP_OTHER, "out of memory" ); + goto error_return; + } + a_flags = (char *)(e_flags + i); + memset( a_flags, 0, k ); + for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) { + for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); + e_flags[i] = a_flags; + a_flags += j; + } + + rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ; + if ( rc == -1 ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ERR, "send_search_entry: " + "conn %lu matched values filtering failed\n", + op->o_connid ? op->o_connid : 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ANY, + "matched values filtering failed\n", 0, 0, 0 ); +#endif + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, + "matched values filtering error" ); + goto error_return; + } } } - for ( a = e->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) { + for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) { AttributeDescription *desc = a->a_desc; - if ( attrs == NULL ) { + if ( rs->sr_attrs == NULL ) { /* all attrs request, skip operational attributes */ if( is_at_operational( desc->ad_type ) ) { continue; @@ -807,20 +808,18 @@ send_search_entry( } else { /* specific attrs requested */ if ( is_at_operational( desc->ad_type ) ) { - if( !opattrs && !ad_inlist( desc, attrs ) ) { + if( !opattrs && !ad_inlist( desc, rs->sr_attrs ) ) { continue; } } else { - if (!userattrs && !ad_inlist( desc, attrs ) ) { + if (!userattrs && !ad_inlist( desc, rs->sr_attrs ) ) { continue; } } } - acl_state = acl_state_init; - - if ( ! access_allowed( be, conn, op, e, desc, NULL, + if ( ! access_allowed( op, rs->sr_entry, desc, NULL, ACL_READ, &acl_state ) ) { #ifdef NEW_LOGGING @@ -844,15 +843,14 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encoding description error", NULL, NULL ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, "encoding description error"); goto error_return; } - if ( ! attrsonly ) { + if ( ! op->ors_attrsonly ) { for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { - if ( ! access_allowed( be, conn, op, e, + if ( ! access_allowed( op, rs->sr_entry, desc, &a->a_vals[i], ACL_READ, &acl_state ) ) { #ifdef NEW_LOGGING @@ -870,7 +868,7 @@ send_search_entry( continue; } - if ( op->vrFilter && e_flags[j][i] == 0 ){ + if ( op->o_vrFilter && e_flags[j][i] == 0 ){ continue; } @@ -884,10 +882,9 @@ send_search_entry( "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encoding values error", - NULL, NULL ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, + "encoding values error" ); goto error_return; } } @@ -902,62 +899,85 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encode end error", NULL, NULL ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, "encode end error" ); goto error_return; } } - /* free e_flags */ - if ( e_flags ) { - free( e_flags ); - e_flags = NULL; - } - /* eventually will loop through generated operational attributes */ - /* only have subschemaSubentry implemented */ - aa = backend_operational( be, conn, op, e, attrs, opattrs ); + /* only have subschemaSubentry and numSubordinates are implemented */ + aa = backend_operational( op, rs, opattrs ); - if ( aa != NULL && op->vrFilter != NULL ) { - int k = 0; - char *a_flags; + if ( aa != NULL && op->o_vrFilter != NULL ) { + int k = 0; + size_t size; for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) { for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++; } - e_flags = ch_calloc ( 1, i * sizeof(char *) + k ); - a_flags = (char *)(e_flags + i); - for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) { - for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); - e_flags[i] = a_flags; - a_flags += j; - } - rc = filter_matched_values(be, conn, op, aa, &e_flags) ; - - if ( rc == -1 ) { + + size = i * sizeof(char *) + k; + if ( size > 0 ) { + char *a_flags, **tmp; + + /* + * Reuse previous memory - we likely need less space + * for operational attributes + */ + tmp = sl_realloc( e_flags, i * sizeof(char *) + k, + op->o_tmpmemctx ); + if ( tmp == NULL ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "send_search_entry: conn %lu " - "matched values filtering failed\n", - conn ? conn->c_connid : 0, 0, 0); + LDAP_LOG( OPERATION, ERR, + "send_search_entry: conn %lu " + "not enough memory " + "for matched values filtering\n", + op->o_connid, 0, 0); #else - Debug( LDAP_DEBUG_ANY, - "matched values filtering failed\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, + "send_search_entry: conn %lu " + "not enough memory " + "for matched values filtering\n", + op->o_connid, 0, 0 ); #endif - ber_free( ber, 1 ); - - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "matched values filtering error", - NULL, NULL ); - goto error_return; + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, + "not enough memory for matched values filtering" ); + goto error_return; + } + e_flags = tmp; + a_flags = (char *)(e_flags + i); + memset( a_flags, 0, k ); + for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) { + for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ); + e_flags[i] = a_flags; + a_flags += j; + } + rc = filter_matched_values(op, aa, &e_flags) ; + + if ( rc == -1 ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ERR, + "send_search_entry: conn %lu " + "matched values filtering failed\n", + op->o_connid ? op->o_connid : 0, 0, 0); +#else + Debug( LDAP_DEBUG_ANY, + "matched values filtering failed\n", 0, 0, 0 ); +#endif + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, + "matched values filtering error" ); + goto error_return; + } } } for (a = aa, j=0; a != NULL; a = a->a_next, j++ ) { AttributeDescription *desc = a->a_desc; - if ( attrs == NULL ) { + if ( rs->sr_attrs == NULL ) { /* all attrs request, skip operational attributes */ if( is_at_operational( desc->ad_type ) ) { continue; @@ -966,20 +986,17 @@ send_search_entry( } else { /* specific attrs requested */ if( is_at_operational( desc->ad_type ) ) { - if( !opattrs && !ad_inlist( desc, attrs ) ) { + if( !opattrs && !ad_inlist( desc, rs->sr_attrs ) ) { continue; } } else { - if (!userattrs && !ad_inlist( desc, attrs ) ) - { + if (!userattrs && !ad_inlist( desc, rs->sr_attrs ) ) { continue; } } } - acl_state = acl_state_init; - - if ( ! access_allowed( be, conn, op, e, desc, NULL, + if ( ! access_allowed( op, rs->sr_entry, desc, NULL, ACL_READ, &acl_state ) ) { #ifdef NEW_LOGGING @@ -988,9 +1005,8 @@ send_search_entry( "access to attribute %s not allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 ); #else - Debug( LDAP_DEBUG_ACL, "acl: access to attribute %s " - "not allowed\n", - desc->ad_cname.bv_val, 0, 0 ); + Debug( LDAP_DEBUG_ACL, "send_search_entry: access to attribute %s " + "not allowed\n", desc->ad_cname.bv_val, 0, 0 ); #endif continue; @@ -1006,17 +1022,15 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encoding description error", NULL, NULL ); - + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, "encoding description error" ); attrs_free( aa ); goto error_return; } - if ( ! attrsonly ) { + if ( ! op->ors_attrsonly ) { for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) { - if ( ! access_allowed( be, conn, op, e, + if ( ! access_allowed( op, rs->sr_entry, desc, &a->a_vals[i], ACL_READ, &acl_state ) ) { #ifdef NEW_LOGGING @@ -1026,7 +1040,7 @@ send_search_entry( op->o_connid, desc->ad_cname.bv_val, i ); #else Debug( LDAP_DEBUG_ACL, - "acl: access to attribute %s, " + "send_search_entry: access to attribute %s, " "value %d not allowed\n", desc->ad_cname.bv_val, i, 0 ); #endif @@ -1034,7 +1048,7 @@ send_search_entry( continue; } - if ( op->vrFilter && e_flags[j][i] == 0 ){ + if ( op->o_vrFilter && e_flags[j][i] == 0 ){ continue; } @@ -1048,11 +1062,9 @@ send_search_entry( "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encoding values error", - NULL, NULL ); - + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, + "encoding values error" ); attrs_free( aa ); goto error_return; } @@ -1068,36 +1080,81 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encode end error", NULL, NULL ); - + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, "encode end error" ); attrs_free( aa ); goto error_return; } } +#ifdef LDAP_SLAPI + /* + * First, setup the computed attribute context that is + * passed to all plugins. + */ + if ( op->o_pb ) { + ctx.cac_pb = op->o_pb; + ctx.cac_attrs = rs->sr_attrs; + ctx.cac_attrsonly = op->ors_attrsonly; + ctx.cac_userattrs = userattrs; + ctx.cac_opattrs = opattrs; + ctx.cac_acl_state = acl_state; + ctx.cac_private = (void *)ber; + + /* + * For each client requested attribute, call the plugins. + */ + if ( rs->sr_attrs != NULL ) { + for ( anp = rs->sr_attrs; anp->an_name.bv_val != NULL; anp++ ) { + rc = compute_evaluator( &ctx, anp->an_name.bv_val, + rs->sr_entry, slapi_x_compute_output_ber ); + if ( rc == 1 ) { + break; + } + } + } else { + /* + * Technically we shouldn't be returning operational attributes + * when the user requested only user attributes. We'll let the + * plugin decide whether to be naughty or not. + */ + rc = compute_evaluator( &ctx, "*", + rs->sr_entry, slapi_x_compute_output_ber ); + } + if ( rc == 1 ) { + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, "computed attribute error" ); + goto error_return; + } + } +#endif /* LDAP_SLAPI */ + /* free e_flags */ if ( e_flags ) { - free( e_flags ); + sl_free( e_flags, op->o_tmpmemctx ); e_flags = NULL; } attrs_free( aa ); rc = ber_printf( ber, /*{{*/ "}N}" ); - if( rc != -1 && ctrls != NULL ) { - rc = send_ldap_controls( ber, ctrls ); + if( rc != -1 && rs->sr_ctrls != NULL ) { + rc = send_ldap_controls( ber, rs->sr_ctrls ); } if( rc != -1 ) { - rc = ber_printf( ber, /*{*/ "N}" ); - } - #ifdef LDAP_CONNECTIONLESS - if (conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1) - rc = ber_printf( ber, "}" ); + if( op->o_conn && op->o_conn->c_is_udp ) { + if ( op->o_protocol != LDAP_VERSION2 ) { + rc = ber_printf( ber, /*{*/ "N}" ); + } + } else #endif + if ( op->o_res_ber == NULL ) { + rc = ber_printf( ber, /*{*/ "N}" ); + } + } + if ( rc == -1 ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, @@ -1107,37 +1164,41 @@ send_search_entry( Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); #endif - ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encode entry end error", NULL, NULL ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); + send_ldap_error( op, rs, LDAP_OTHER, "encode entry end error" ); + sl_release( mark, op->o_tmpmemctx ); return( 1 ); } - bytes = send_ldap_ber( conn, ber ); - ber_free_buf( ber ); + if ( op->o_res_ber == NULL ) { + bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber ); + ber_free_buf( ber ); - if ( bytes < 0 ) { + if ( bytes < 0 ) { #ifdef NEW_LOGGING - LDAP_LOG( OPERATION, ERR, - "send_search_entry: conn %lu ber write failed.\n", - op->o_connid, 0, 0 ); + LDAP_LOG( OPERATION, ERR, + "send_search_entry: conn %lu ber write failed.\n", + op->o_connid, 0, 0 ); #else - Debug( LDAP_DEBUG_ANY, - "send_search_entry: ber write failed\n", - 0, 0, 0 ); + Debug( LDAP_DEBUG_ANY, + "send_search_entry: ber write failed\n", + 0, 0, 0 ); #endif - return -1; - } + sl_release( mark, op->o_tmpmemctx ); + return -1; + } + rs->sr_nentries++; - ldap_pvt_thread_mutex_lock( &num_sent_mutex ); - num_bytes_sent += bytes; - num_entries_sent++; - num_pdu_sent++; - ldap_pvt_thread_mutex_unlock( &num_sent_mutex ); + ldap_pvt_thread_mutex_lock( &num_sent_mutex ); + num_bytes_sent += bytes; + num_entries_sent++; + num_pdu_sent++; + ldap_pvt_thread_mutex_unlock( &num_sent_mutex ); + } Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu ENTRY dn=\"%s\"\n", - conn->c_connid, op->o_opid, e->e_dn, 0, 0 ); + op->o_connid, op->o_opid, rs->sr_entry->e_dn, 0, 0 ); #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, @@ -1149,57 +1210,60 @@ send_search_entry( rc = 0; error_return:; - if ( e_flags ) free( e_flags ); + sl_release( mark, op->o_tmpmemctx ); + if ( e_flags ) sl_free( e_flags, op->o_tmpmemctx ); return( rc ); } int -send_search_reference( - Backend *be, - Connection *conn, - Operation *op, - Entry *e, - BerVarray refs, - LDAPControl **ctrls, - BerVarray *v2refs -) +slap_send_search_reference( Operation *op, SlapReply *rs ) { - char berbuf[256]; - BerElement *ber = (BerElement *)berbuf; - int rc; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; + int rc = 0; int bytes; + void *mark; AttributeDescription *ad_ref = slap_schema.si_ad_ref; AttributeDescription *ad_entry = slap_schema.si_ad_entry; + rs->sr_type = REP_SEARCHREF; + if (op->o_callback && op->o_callback->sc_response) { + rc = op->o_callback->sc_response( op, rs ); + if ( rc != SLAP_CB_CONTINUE ) return rc; + } + + mark = sl_mark( op->o_tmpmemctx ); + #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "send_search_reference: conn %lu dn=\"%s\"\n", - op->o_connid, e->e_dn, 0 ); + op->o_connid, + rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0 ); #else Debug( LDAP_DEBUG_TRACE, "=> send_search_reference: dn=\"%s\"\n", - e->e_dn, 0, 0 ); + rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0, 0 ); #endif - - if ( ! access_allowed( be, conn, op, e, + if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL ) ) { #ifdef NEW_LOGGING LDAP_LOG( ACL, INFO, "send_search_reference: conn %lu " - "access to entry %s not allowed\n", op->o_connid, e->e_dn, 0 ); + "access to entry %s not allowed\n", + op->o_connid, rs->sr_entry->e_dn, 0 ); #else Debug( LDAP_DEBUG_ACL, "send_search_reference: access to entry not allowed\n", 0, 0, 0 ); #endif - - return( 1 ); + rc = 1; + goto rel; } - if ( ! access_allowed( be, conn, op, e, + if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, ad_ref, NULL, ACL_READ, NULL ) ) { #ifdef NEW_LOGGING @@ -1212,44 +1276,69 @@ send_search_reference( "to reference not allowed\n", 0, 0, 0 ); #endif + rc = 1; + goto rel; + } - return( 1 ); +#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE + if( op->o_domain_scope ) { +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ERR, + "send_search_reference: conn %lu domainScope control in (%s).\n", + op->o_connid, rs->sr_entry->e_dn, 0 ); +#else + Debug( LDAP_DEBUG_ANY, + "send_search_reference: domainScope control in (%s)\n", + rs->sr_entry->e_dn, 0, 0 ); +#endif + rc = 0; + goto rel; } +#endif - if( refs == NULL ) { + if( rs->sr_ref == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "send_search_reference: conn %lu null ref in (%s).\n", - op->o_connid, e->e_dn, 0 ); + op->o_connid, rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0 ); #else Debug( LDAP_DEBUG_ANY, "send_search_reference: null ref in (%s)\n", - e->e_dn, 0, 0 ); + rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 ); #endif - - return( 1 ); + rc = 1; + goto rel; } if( op->o_protocol < LDAP_VERSION3 ) { /* save the references for the result */ - if( refs[0].bv_val != NULL ) { - value_add( v2refs, refs ); + if( rs->sr_ref[0].bv_val != NULL ) { + if( value_add( &rs->sr_v2ref, rs->sr_ref ) ) + return LDAP_OTHER; } - return 0; + rc = 0; + goto rel; } - ber_init_w_nullc( ber, LBER_USE_DER ); +#ifdef LDAP_CONNECTIONLESS + if( op->o_conn && op->o_conn->c_is_udp ) { + ber = op->o_res_ber; + } else +#endif + { + ber_init_w_nullc( ber, LBER_USE_DER ); + ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); + } rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid, - LDAP_RES_SEARCH_REFERENCE, refs ); + LDAP_RES_SEARCH_REFERENCE, rs->sr_ref ); - if( rc != -1 && ctrls != NULL ) { - rc = send_ldap_controls( ber, ctrls ); + if( rc != -1 && rs->sr_ctrls != NULL ) { + rc = send_ldap_controls( ber, rs->sr_ctrls ); } if( rc != -1 ) { - rc = ber_printf( ber, /*"{"*/ "N}", op->o_msgid, - LDAP_RES_SEARCH_REFERENCE, refs ); + rc = ber_printf( ber, /*"{"*/ "N}" ); } if ( rc == -1 ) { @@ -1262,13 +1351,18 @@ send_search_reference( "send_search_reference: ber_printf failed\n", 0, 0, 0 ); #endif +#ifdef LDAP_CONNECTIONLESS + if (!op->o_conn || op->o_conn->c_is_udp == 0) +#endif ber_free_buf( ber ); - send_ldap_result( conn, op, LDAP_OTHER, - NULL, "encode DN error", NULL, NULL ); - return -1; + send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" ); + goto rel; } - bytes = send_ldap_ber( conn, ber ); +#ifdef LDAP_CONNECTIONLESS + if (!op->o_conn || op->o_conn->c_is_udp == 0) { +#endif + bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber ); ber_free_buf( ber ); ldap_pvt_thread_mutex_lock( &num_sent_mutex ); @@ -1276,9 +1370,12 @@ send_search_reference( num_refs_sent++; num_pdu_sent++; ldap_pvt_thread_mutex_unlock( &num_sent_mutex ); +#ifdef LDAP_CONNECTIONLESS + } +#endif Statslog( LDAP_DEBUG_STATS2, "conn=%lu op=%lu REF dn=\"%s\"\n", - conn->c_connid, op->o_opid, e->e_dn, 0, 0 ); + op->o_connid, op->o_opid, rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 ); #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, @@ -1287,10 +1384,11 @@ send_search_reference( Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 ); #endif - return 0; +rel: + sl_release( mark, op->o_tmpmemctx ); + return rc; } - int str2result( char *s, @@ -1354,3 +1452,57 @@ str2result( return( rc ); } + +int slap_read_controls( + Operation *op, + SlapReply *rs, + Entry *e, + const struct berval *oid, + LDAPControl **ctrl ) +{ + int rc; + struct berval bv; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; + LDAPControl c; + ber_len_t siz, len; + Operation myop; + +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, INFO, "slap_read_controls: (%s) %s\n", + oid->bv_val, e->e_dn, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "slap_read_controls: (%s) %s\n", + oid->bv_val, e->e_dn, 0 ); +#endif + + rs->sr_entry = e; + rs->sr_attrs = ( oid == &slap_pre_read_bv ) ? + op->o_preread_attrs : op->o_postread_attrs; + + entry_flatsize( rs->sr_entry, &siz, &len, 0 ); + bv.bv_len = siz + len; + bv.bv_val = op->o_tmpalloc(bv.bv_len, op->o_tmpmemctx ); + + ber_init2( ber, &bv, LBER_USE_DER ); + ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); + + /* create new operation */ + myop = *op; + myop.o_bd = NULL; + myop.o_res_ber = ber; + + rc = slap_send_search_entry( &myop, rs ); + if( rc ) return rc; + + rc = ber_flatten2( ber, &c.ldctl_value, 0 ); + + if( rc == LBER_ERROR ) return LDAP_OTHER; + + c.ldctl_oid = oid->bv_val; + c.ldctl_iscritical = 0; + + *ctrl = sl_calloc( 1, sizeof(LDAPControl), NULL ); + **ctrl = c; + return LDAP_SUCCESS; +}