X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fresult.c;h=07b8d2d904e85903dcf497ac7bcc51e908ee5efb;hb=49b0985c88ea6836a24c314aea2cb2dd0d129544;hp=e59f4a434c53323bbd46eef314f5557e93e75da5;hpb=2ff82a82c59795be091291d53fecb294c3af0d8c;p=openldap diff --git a/servers/slapd/result.c b/servers/slapd/result.c index e59f4a434c..07b8d2d904 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-2003 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" @@ -22,6 +41,11 @@ #include "slapi.h" #endif +int slap_null_cb( Operation *op, SlapReply *rs ) +{ + return 0; +} + static char *v2ref( BerVarray ref, const char *text ) { size_t len = 0, i = 0; @@ -223,8 +247,8 @@ send_ldap_response( Operation *op, SlapReply *rs ) { - char berbuf[LBER_ELEMENT_SIZEOF]; - BerElement *ber = (BerElement *)berbuf; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; int rc; long bytes; @@ -371,9 +395,11 @@ send_ldap_response( } #ifdef LDAP_SLAPI - slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err ); - slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, ( rs->sr_matched != NULL ) ? (void *)ch_strdup( rs->sr_matched ) : NULL ); - slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, ( rs->sr_text != NULL ) ? (void *)ch_strdup( rs->sr_text ) : NULL ); + 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 ); @@ -449,11 +475,13 @@ slap_send_ldap_result( Operation *op, SlapReply *rs ) #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n", - rs->sr_err, rs->sr_matched ? rs->sr_matched : "", rs->sr_text ? rs->sr_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", - rs->sr_err, rs->sr_matched ? rs->sr_matched : "", rs->sr_text ? rs->sr_text : "" ); + rs->sr_err, rs->sr_matched ? rs->sr_matched : "", + rs->sr_text ? rs->sr_text : "" ); #endif @@ -485,6 +513,22 @@ slap_send_ldap_result( Operation *op, SlapReply *rs ) } } +#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( rs->sr_ref, rs->sr_text ); rs->sr_text = tmp; @@ -498,20 +542,21 @@ slap_send_ldap_result( Operation *op, SlapReply *rs ) if ( op->o_tag == LDAP_REQ_SEARCH ) { char nbuf[64]; - snprintf( nbuf, sizeof nbuf, "%d nentries=%d", rs->sr_err, rs->sr_nentries ); + snprintf( nbuf, sizeof nbuf, "%d nentries=%d", + rs->sr_err, rs->sr_nentries ); 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 : "" ); + "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 : "" ); + op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err, + rs->sr_text ? rs->sr_text : "" ); } - if( tmp != NULL ) { - ch_free(tmp); - } + if( tmp != NULL ) ch_free(tmp); rs->sr_text = otext; rs->sr_ref = oref; } @@ -523,10 +568,12 @@ send_ldap_sasl( Operation *op, SlapReply *rs ) #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "send_ldap_sasl: conn %lu err=%d len=%lu\n", - op->o_connid, rs->sr_err, rs->sr_sasldata ? rs->sr_sasldata->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", - rs->sr_err, rs->sr_sasldata ? (long) rs->sr_sasldata->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 ); @@ -583,8 +630,8 @@ slap_send_ldap_intermediate( Operation *op, SlapReply *rs ) int slap_send_search_entry( Operation *op, SlapReply *rs ) { - char berbuf[LBER_ELEMENT_SIZEOF]; - BerElement *ber = (BerElement *)berbuf; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; Attribute *a, *aa; int i, j, rc=-1, bytes; char *edn; @@ -641,12 +688,10 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) edn = rs->sr_entry->e_nname.bv_val; -#ifdef LDAP_CONNECTIONLESS - if (op->o_conn && op->o_conn->c_is_udp) { + if ( op->o_res_ber ) { + /* read back control or LDAP_CONNECTIONLESS */ ber = op->o_res_ber; - } else -#endif - { + } else { ber_len_t siz, len; struct berval bv; @@ -659,14 +704,23 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) } #ifdef LDAP_CONNECTIONLESS - if (op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2) { - rc = ber_printf(ber, "t{O{" /*}}*/, - LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name); + 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 - { + 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, &rs->sr_entry->e_name ); + LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); } if ( rc == -1 ) { @@ -678,10 +732,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) 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 ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" ); goto error_return; } @@ -742,13 +793,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_ANY, "matched values filtering failed\n", 0, 0, 0 ); #endif -#ifdef LDAP_CONNECTIONLESS - if (!op->o_conn || op->o_conn->c_is_udp == 0) -#endif - { - ber_free( ber, 1 ); - } - + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "matched values filtering error" ); goto error_return; @@ -803,10 +848,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) 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 ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "encoding description error"); goto error_return; } @@ -845,10 +887,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) "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 ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "encoding values error" ); goto error_return; @@ -865,17 +904,14 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) 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 ); + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "encode end error" ); goto error_return; } } /* eventually will loop through generated operational attributes */ - /* only have subschemaSubentry implemented */ + /* only have subschemaSubentry and numSubordinates are implemented */ aa = backend_operational( op, rs, opattrs ); if ( aa != NULL && op->o_vrFilter != NULL ) { @@ -910,8 +946,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) "for matched values filtering\n", op->o_connid, 0, 0 ); #endif - ber_free( ber, 1 ); - + 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; @@ -936,13 +971,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_ANY, "matched values filtering failed\n", 0, 0, 0 ); #endif -#ifdef LDAP_CONNECTIONLESS - if (!op->o_conn || op->o_conn->c_is_udp == 0) -#endif - { - ber_free( ber, 1 ); - } - + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "matched values filtering error" ); goto error_return; @@ -998,14 +1027,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) 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 ); - } + 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; } @@ -1044,12 +1067,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) "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 ); - } + if ( op->o_res_ber == NULL ) ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "encoding values error" ); attrs_free( aa ); @@ -1067,14 +1085,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) 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 ); - } + 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; } @@ -1085,38 +1097,40 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) * First, setup the computed attribute context that is * passed to all plugins. */ - 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; + 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. + * For each client requested attribute, call the plugins. */ - rc = compute_evaluator( &ctx, "*", - rs->sr_entry, slapi_x_compute_output_ber ); - } - if ( rc == 1 ) { - ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "computed attribute error" ); - goto error_return; + 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 */ @@ -1133,15 +1147,17 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) rc = send_ldap_controls( ber, rs->sr_ctrls ); } + if( rc != -1 ) { #ifdef LDAP_CONNECTIONLESS - if( op->o_conn && op->o_conn->c_is_udp && - op->o_protocol == LDAP_VERSION2 ) - { - ; /* empty, skip following if */ - } else + if( op->o_conn && op->o_conn->c_is_udp ) { + if ( op->o_protocol != LDAP_VERSION2 ) { + rc = ber_printf( ber, /*{*/ "N}" ); + } + } else #endif - if( rc != -1 ) { - rc = ber_printf( ber, /*{*/ "N}" ); + if ( op->o_res_ber == NULL ) { + rc = ber_printf( ber, /*{*/ "N}" ); + } } if ( rc == -1 ) { @@ -1153,21 +1169,13 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) 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 ); - } + 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 ); } -#ifdef LDAP_CONNECTIONLESS - if (!op->o_conn || op->o_conn->c_is_udp == 0) -#endif - { + if ( op->o_res_ber == NULL ) { bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber ); ber_free_buf( ber ); @@ -1215,8 +1223,8 @@ error_return:; int slap_send_search_reference( Operation *op, SlapReply *rs ) { - char berbuf[LBER_ELEMENT_SIZEOF]; - BerElement *ber = (BerElement *)berbuf; + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; int rc = 0; int bytes; void *mark; @@ -1235,7 +1243,8 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "send_search_reference: conn %lu dn=\"%s\"\n", - op->o_connid, rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 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", @@ -1317,9 +1326,9 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) } #ifdef LDAP_CONNECTIONLESS - if (op->o_conn && op->o_conn->c_is_udp) + if( op->o_conn && op->o_conn->c_is_udp ) { ber = op->o_res_ber; - else + } else #endif { ber_init_w_nullc( ber, LBER_USE_DER ); @@ -1448,3 +1457,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; +}