Home | History | Annotate | Line # | Download | only in slapi
      1 /*	$NetBSD: slapi_ops.c,v 1.4 2025/09/05 21:16:33 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 2002-2024 The OpenLDAP Foundation.
      7  * Portions Copyright 1997,2002-2003 IBM Corporation.
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted only as authorized by the OpenLDAP
     12  * Public License.
     13  *
     14  * A copy of this license is available in the file LICENSE in the
     15  * top-level directory of the distribution or, alternatively, at
     16  * <http://www.OpenLDAP.org/license.html>.
     17  */
     18 /* ACKNOWLEDGEMENTS:
     19  * This work was initially developed by IBM Corporation for use in
     20  * IBM products and subsequently ported to OpenLDAP Software by
     21  * Steve Omrani.  Additional significant contributors include:
     22  *   Luke Howard
     23  */
     24 
     25 #include <sys/cdefs.h>
     26 __RCSID("$NetBSD: slapi_ops.c,v 1.4 2025/09/05 21:16:33 christos Exp $");
     27 
     28 #include "portable.h"
     29 
     30 #include <ac/string.h>
     31 #include <ac/stdarg.h>
     32 #include <ac/ctype.h>
     33 #include <ac/unistd.h>
     34 
     35 #include <slap.h>
     36 #include <lber_pvt.h>
     37 #include <slapi.h>
     38 
     39 #ifdef LDAP_SLAPI
     40 
     41 static struct Listener slapi_listener = {
     42 	BER_BVC("slapi://"),
     43 	BER_BVC("slapi://")
     44 };
     45 
     46 static LDAPControl **
     47 slapi_int_dup_controls( LDAPControl **controls )
     48 {
     49 	LDAPControl **c;
     50 	size_t i;
     51 
     52 	if ( controls == NULL )
     53 		return NULL;
     54 
     55 	for ( i = 0; controls[i] != NULL; i++ )
     56 		;
     57 
     58 	c = (LDAPControl **) slapi_ch_calloc( i + 1, sizeof(LDAPControl *) );
     59 
     60 	for ( i = 0; controls[i] != NULL; i++ ) {
     61 		c[i] = slapi_dup_control( controls[i] );
     62 	}
     63 
     64 	return c;
     65 }
     66 
     67 static int
     68 slapi_int_result(
     69 	Operation	*op,
     70 	SlapReply	*rs )
     71 {
     72 	Slapi_PBlock		*pb = SLAPI_OPERATION_PBLOCK( op );
     73 	plugin_result_callback	prc = NULL;
     74 	void			*callback_data = NULL;
     75 	LDAPControl		**ctrls = NULL;
     76 
     77 	assert( pb != NULL );
     78 
     79 	slapi_pblock_get( pb, SLAPI_X_INTOP_RESULT_CALLBACK, (void **)&prc );
     80 	slapi_pblock_get( pb, SLAPI_X_INTOP_CALLBACK_DATA,   &callback_data );
     81 
     82 	/* we need to duplicate controls because they might go out of scope */
     83 	ctrls = slapi_int_dup_controls( rs->sr_ctrls );
     84 	slapi_pblock_set( pb, SLAPI_RESCONTROLS, ctrls );
     85 
     86 	if ( prc != NULL ) {
     87 		(*prc)( rs->sr_err, callback_data );
     88 	}
     89 
     90 	return rs->sr_err;
     91 }
     92 
     93 static int
     94 slapi_int_search_entry(
     95 	Operation	*op,
     96 	SlapReply	*rs )
     97 {
     98 	Slapi_PBlock			*pb = SLAPI_OPERATION_PBLOCK( op );
     99 	plugin_search_entry_callback	psec = NULL;
    100 	void				*callback_data = NULL;
    101 	int				rc = LDAP_SUCCESS;
    102 
    103 	assert( pb != NULL );
    104 
    105 	slapi_pblock_get( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK, (void **)&psec );
    106 	slapi_pblock_get( pb, SLAPI_X_INTOP_CALLBACK_DATA,         &callback_data );
    107 
    108 	if ( psec != NULL ) {
    109 		rc = (*psec)( rs->sr_entry, callback_data );
    110 	}
    111 
    112 	return rc;
    113 }
    114 
    115 static int
    116 slapi_int_search_reference(
    117 	Operation	*op,
    118 	SlapReply	*rs )
    119 {
    120 	int				i, rc = LDAP_SUCCESS;
    121 	plugin_referral_entry_callback	prec = NULL;
    122 	void				*callback_data = NULL;
    123 	Slapi_PBlock			*pb = SLAPI_OPERATION_PBLOCK( op );
    124 
    125 	assert( pb != NULL );
    126 
    127 	slapi_pblock_get( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, (void **)&prec );
    128 	slapi_pblock_get( pb, SLAPI_X_INTOP_CALLBACK_DATA,           &callback_data );
    129 
    130 	if ( prec != NULL ) {
    131 		for ( i = 0; rs->sr_ref[i].bv_val != NULL; i++ ) {
    132 			rc = (*prec)( rs->sr_ref[i].bv_val, callback_data );
    133 			if ( rc != LDAP_SUCCESS ) {
    134 				break;
    135 			}
    136 		}
    137 	}
    138 
    139 	return rc;
    140 }
    141 
    142 int
    143 slapi_int_response( Slapi_Operation *op, SlapReply *rs )
    144 {
    145 	int				rc;
    146 
    147 	switch ( rs->sr_type ) {
    148 	case REP_RESULT:
    149 		rc = slapi_int_result( op, rs );
    150 		break;
    151 	case REP_SEARCH:
    152 		rc = slapi_int_search_entry( op, rs );
    153 		break;
    154 	case REP_SEARCHREF:
    155 		rc = slapi_int_search_reference( op, rs );
    156 		break;
    157 	default:
    158 		rc = LDAP_OTHER;
    159 		break;
    160 	}
    161 
    162 	assert( rc != SLAP_CB_CONTINUE ); /* never try to send a wire response */
    163 
    164 	return rc;
    165 }
    166 
    167 static int
    168 slapi_int_get_ctrls( Slapi_PBlock *pb )
    169 {
    170 	LDAPControl		**c;
    171 	int			rc = LDAP_SUCCESS;
    172 
    173 	if ( pb->pb_op->o_ctrls != NULL ) {
    174 		for ( c = pb->pb_op->o_ctrls; *c != NULL; c++ ) {
    175 			rc = slap_parse_ctrl( pb->pb_op, pb->pb_rs, *c, &pb->pb_rs->sr_text );
    176 			if ( rc != LDAP_SUCCESS )
    177 				break;
    178 		}
    179 	}
    180 
    181 	return rc;
    182 }
    183 
    184 void
    185 slapi_int_connection_init_pb( Slapi_PBlock *pb, ber_tag_t tag )
    186 {
    187 	Connection		*conn;
    188 	Operation		*op;
    189 	ber_len_t		max = sockbuf_max_incoming;
    190 
    191 	conn = (Connection *) slapi_ch_calloc( 1, sizeof(Connection) );
    192 
    193 	LDAP_STAILQ_INIT( &conn->c_pending_ops );
    194 
    195 	op = (Operation *) slapi_ch_calloc( 1, sizeof(OperationBuffer) );
    196 	op->o_hdr = &((OperationBuffer *) op)->ob_hdr;
    197 	op->o_controls = ((OperationBuffer *) op)->ob_controls;
    198 
    199 	op->o_callback = (slap_callback *) slapi_ch_calloc( 1, sizeof(slap_callback) );
    200 	op->o_callback->sc_response = slapi_int_response;
    201 	op->o_callback->sc_cleanup = NULL;
    202 	op->o_callback->sc_private = pb;
    203 	op->o_callback->sc_next = NULL;
    204 
    205 	conn->c_pending_ops.stqh_first = op;
    206 
    207 	/* connection object authorization information */
    208 	conn->c_authtype = LDAP_AUTH_NONE;
    209 	BER_BVZERO( &conn->c_authmech );
    210 	BER_BVZERO( &conn->c_dn );
    211 	BER_BVZERO( &conn->c_ndn );
    212 
    213 	conn->c_listener = &slapi_listener;
    214 	ber_dupbv( &conn->c_peer_domain, (struct berval *)&slap_unknown_bv );
    215 	ber_dupbv( &conn->c_peer_name, (struct berval *)&slap_unknown_bv );
    216 
    217 	LDAP_STAILQ_INIT( &conn->c_ops );
    218 
    219 	BER_BVZERO( &conn->c_sasl_bind_mech );
    220 	conn->c_sasl_authctx = NULL;
    221 	conn->c_sasl_sockctx = NULL;
    222 	conn->c_sasl_extra = NULL;
    223 
    224 	conn->c_sb = ber_sockbuf_alloc();
    225 
    226 	ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
    227 
    228 	conn->c_currentber = NULL;
    229 
    230 	/* should check status of thread calls */
    231 	ldap_pvt_thread_mutex_init( &conn->c_mutex );
    232 	ldap_pvt_thread_mutex_init( &conn->c_write1_mutex );
    233 	ldap_pvt_thread_cond_init( &conn->c_write1_cv );
    234 
    235 	ldap_pvt_thread_mutex_lock( &conn->c_mutex );
    236 
    237 	conn->c_n_ops_received = 0;
    238 	conn->c_n_ops_executing = 0;
    239 	conn->c_n_ops_pending = 0;
    240 	conn->c_n_ops_completed = 0;
    241 	conn->c_n_ops_async = 0;
    242 
    243 	conn->c_n_get = 0;
    244 	conn->c_n_read = 0;
    245 	conn->c_n_write = 0;
    246 
    247 	conn->c_protocol = LDAP_VERSION3;
    248 
    249 	conn->c_activitytime = conn->c_starttime = slap_get_time();
    250 
    251 	/*
    252 	 * A real connection ID is required, because syncrepl associates
    253 	 * pending CSNs with unique ( connection, operation ) tuples.
    254 	 * Setting a fake connection ID will cause slap_get_commit_csn()
    255 	 * to return a stale value.
    256 	 */
    257 	connection_assign_nextid( conn );
    258 
    259 	conn->c_conn_state  = SLAP_C_ACTIVE;
    260 
    261 	conn->c_ssf = conn->c_transport_ssf = local_ssf;
    262 	conn->c_tls_ssf = 0;
    263 
    264 	backend_connection_init( conn );
    265 
    266 	conn->c_send_ldap_result = slap_send_ldap_result;
    267 	conn->c_send_search_entry = slap_send_search_entry;
    268 	conn->c_send_ldap_extended = slap_send_ldap_extended;
    269 	conn->c_send_search_reference = slap_send_search_reference;
    270 
    271 	/* operation object */
    272 	op->o_tag = tag;
    273 	op->o_protocol = LDAP_VERSION3;
    274 	BER_BVZERO( &op->o_authmech );
    275 	op->o_time = slap_get_time();
    276 	op->o_do_not_cache = 1;
    277 	op->o_threadctx = ldap_pvt_thread_pool_context();
    278 	op->o_tmpmemctx = NULL;
    279 	op->o_tmpmfuncs = &ch_mfuncs;
    280 	op->o_conn = conn;
    281 	op->o_connid = conn->c_connid;
    282 	op->o_bd = frontendDB;
    283 
    284 	/* extensions */
    285 	slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op );
    286 	slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
    287 
    288 	pb->pb_rs = (SlapReply *)slapi_ch_calloc( 1, sizeof(SlapReply) );
    289 	pb->pb_op = op;
    290 	pb->pb_conn = conn;
    291 	pb->pb_intop = 1;
    292 
    293 	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
    294 }
    295 
    296 static void
    297 slapi_int_set_operation_dn( Slapi_PBlock *pb )
    298 {
    299 	Backend			*be;
    300 	Operation		*op = pb->pb_op;
    301 
    302 	if ( BER_BVISNULL( &op->o_ndn ) ) {
    303 		/* set to root DN */
    304 		be = select_backend( &op->o_req_ndn, 1 );
    305 		if ( be != NULL ) {
    306 			ber_dupbv( &op->o_dn, &be->be_rootdn );
    307 			ber_dupbv( &op->o_ndn, &be->be_rootndn );
    308 		}
    309 	}
    310 }
    311 
    312 void
    313 slapi_int_connection_done_pb( Slapi_PBlock *pb )
    314 {
    315 	Connection		*conn;
    316 	Operation		*op;
    317 
    318 	PBLOCK_ASSERT_INTOP( pb, 0 );
    319 
    320 	conn = pb->pb_conn;
    321 	op = pb->pb_op;
    322 
    323 	/* free allocated DNs */
    324 	if ( !BER_BVISNULL( &op->o_dn ) )
    325 		op->o_tmpfree( op->o_dn.bv_val, op->o_tmpmemctx );
    326 	if ( !BER_BVISNULL( &op->o_ndn ) )
    327 		op->o_tmpfree( op->o_ndn.bv_val, op->o_tmpmemctx );
    328 
    329 	if ( !BER_BVISNULL( &op->o_req_dn ) )
    330 		op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
    331 	if ( !BER_BVISNULL( &op->o_req_ndn ) )
    332 		op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
    333 
    334 	switch ( op->o_tag ) {
    335 	case LDAP_REQ_MODRDN:
    336 		if ( !BER_BVISNULL( &op->orr_newrdn ))
    337 			op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx );
    338 		if ( !BER_BVISNULL( &op->orr_nnewrdn ))
    339 			op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx );
    340 		if ( op->orr_newSup != NULL ) {
    341 			assert( !BER_BVISNULL( op->orr_newSup ) );
    342 			op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx );
    343 			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
    344 		}
    345 		if ( op->orr_nnewSup != NULL ) {
    346 			assert( !BER_BVISNULL( op->orr_nnewSup ) );
    347 			op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx );
    348 			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
    349 		}
    350 		if ( !BER_BVISNULL( &op->orr_newDN ))
    351 			op->o_tmpfree( op->orr_newDN.bv_val, op->o_tmpmemctx );
    352 		if ( !BER_BVISNULL( &op->orr_nnewDN ))
    353 			op->o_tmpfree( op->orr_nnewDN.bv_val, op->o_tmpmemctx );
    354 		slap_mods_free( op->orr_modlist, 1 );
    355 		break;
    356 	case LDAP_REQ_ADD:
    357 		slap_mods_free( op->ora_modlist, 0 );
    358 		break;
    359 	case LDAP_REQ_MODIFY:
    360 		slap_mods_free( op->orm_modlist, 1 );
    361 		break;
    362 	case LDAP_REQ_SEARCH:
    363 		if ( op->ors_attrs != NULL ) {
    364 			op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx );
    365 			op->ors_attrs = NULL;
    366 		}
    367 		break;
    368 	default:
    369 		break;
    370 	}
    371 
    372 	slapi_ch_free_string( &conn->c_authmech.bv_val );
    373 	slapi_ch_free_string( &conn->c_dn.bv_val );
    374 	slapi_ch_free_string( &conn->c_ndn.bv_val );
    375 	slapi_ch_free_string( &conn->c_peer_domain.bv_val );
    376 	slapi_ch_free_string( &conn->c_peer_name.bv_val );
    377 
    378 	if ( conn->c_sb != NULL ) {
    379 		ber_sockbuf_free( conn->c_sb );
    380 	}
    381 
    382 	slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op );
    383 	slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
    384 
    385 	slapi_ch_free( (void **)&pb->pb_op->o_callback );
    386 	slapi_ch_free( (void **)&pb->pb_op );
    387 	slapi_ch_free( (void **)&pb->pb_conn );
    388 	slapi_ch_free( (void **)&pb->pb_rs );
    389 }
    390 
    391 static int
    392 slapi_int_func_internal_pb( Slapi_PBlock *pb, slap_operation_t which )
    393 {
    394 	SlapReply		*rs = pb->pb_rs;
    395 	int			rc;
    396 
    397 	PBLOCK_ASSERT_INTOP( pb, 0 );
    398 
    399 	rc = slapi_int_get_ctrls( pb );
    400 	if ( rc != LDAP_SUCCESS ) {
    401 		rs->sr_err = rc;
    402 		return rc;
    403 	}
    404 
    405 	pb->pb_op->o_bd = frontendDB;
    406 	return (&frontendDB->be_bind)[which]( pb->pb_op, pb->pb_rs );
    407 }
    408 
    409 int
    410 slapi_delete_internal_pb( Slapi_PBlock *pb )
    411 {
    412 	if ( pb == NULL ) {
    413 		return -1;
    414 	}
    415 
    416 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_DELETE );
    417 
    418 	slapi_int_func_internal_pb( pb, op_delete );
    419 
    420 	return 0;
    421 }
    422 
    423 int
    424 slapi_add_internal_pb( Slapi_PBlock *pb )
    425 {
    426 	SlapReply		*rs;
    427 	Slapi_Entry		*entry_orig = NULL;
    428 	OpExtraDB oex;
    429 	int rc;
    430 
    431 	if ( pb == NULL ) {
    432 		return -1;
    433 	}
    434 
    435 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_ADD );
    436 
    437 	rs = pb->pb_rs;
    438 
    439 	entry_orig = pb->pb_op->ora_e;
    440 	pb->pb_op->ora_e = NULL;
    441 
    442 	/*
    443 	 * The caller can specify a new entry, or a target DN and set
    444 	 * of modifications, but not both.
    445 	 */
    446 	if ( entry_orig != NULL ) {
    447 		if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
    448 			rs->sr_err = LDAP_PARAM_ERROR;
    449 			goto cleanup;
    450 		}
    451 
    452 		assert( BER_BVISNULL( &pb->pb_op->o_req_dn ) ); /* shouldn't get set */
    453 		ber_dupbv( &pb->pb_op->o_req_dn, &entry_orig->e_name );
    454 		ber_dupbv( &pb->pb_op->o_req_ndn, &entry_orig->e_nname );
    455 	} else if ( pb->pb_op->ora_modlist == NULL || BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
    456 		rs->sr_err = LDAP_PARAM_ERROR;
    457 		goto cleanup;
    458 	}
    459 
    460 	pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) );
    461 	ber_dupbv( &pb->pb_op->ora_e->e_name,  &pb->pb_op->o_req_dn );
    462 	ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn );
    463 
    464 	if ( entry_orig != NULL ) {
    465 		assert( pb->pb_op->ora_modlist == NULL );
    466 
    467 		rs->sr_err = slap_entry2mods( entry_orig, &pb->pb_op->ora_modlist,
    468 			&rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
    469 		if ( rs->sr_err != LDAP_SUCCESS ) {
    470 			goto cleanup;
    471 		}
    472 	} else {
    473 		assert( pb->pb_op->ora_modlist != NULL );
    474 	}
    475 
    476 	rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->ora_modlist, &rs->sr_text,
    477 		pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
    478 	if ( rs->sr_err != LDAP_SUCCESS ) {
    479                 goto cleanup;
    480         }
    481 
    482 	/* Duplicate the values, because we may call slapi_entry_free() */
    483 	rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e,
    484 		1, 0, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
    485 	if ( rs->sr_err != LDAP_SUCCESS ) {
    486 		goto cleanup;
    487 	}
    488 
    489 	oex.oe.oe_key = (void *)do_add;
    490 	oex.oe_db = NULL;
    491 	LDAP_SLIST_INSERT_HEAD(&pb->pb_op->o_extra, &oex.oe, oe_next);
    492 	rc = slapi_int_func_internal_pb( pb, op_add );
    493 	LDAP_SLIST_REMOVE(&pb->pb_op->o_extra, &oex.oe, OpExtra, oe_next);
    494 
    495 	if ( !rc ) {
    496 		if ( pb->pb_op->ora_e != NULL && oex.oe_db != NULL ) {
    497 			BackendDB	*bd = pb->pb_op->o_bd;
    498 
    499 			pb->pb_op->o_bd = oex.oe_db;
    500 			be_entry_release_w( pb->pb_op, pb->pb_op->ora_e );
    501 			pb->pb_op->ora_e = NULL;
    502 			pb->pb_op->o_bd = bd;
    503 		}
    504 	}
    505 
    506 cleanup:
    507 
    508 	if ( pb->pb_op->ora_e != NULL ) {
    509 		slapi_entry_free( pb->pb_op->ora_e );
    510 		pb->pb_op->ora_e = NULL;
    511 	}
    512 	if ( entry_orig != NULL ) {
    513 		pb->pb_op->ora_e = entry_orig;
    514 		slap_mods_free( pb->pb_op->ora_modlist, 1 );
    515 		pb->pb_op->ora_modlist = NULL;
    516 	}
    517 
    518 	return 0;
    519 }
    520 
    521 int
    522 slapi_modrdn_internal_pb( Slapi_PBlock *pb )
    523 {
    524 	if ( pb == NULL ) {
    525 		return -1;
    526 	}
    527 
    528 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODRDN );
    529 
    530 	if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) {
    531 		pb->pb_rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
    532 		goto cleanup;
    533 	}
    534 
    535 	slapi_int_func_internal_pb( pb, op_modrdn );
    536 
    537 cleanup:
    538 
    539 	return 0;
    540 }
    541 
    542 int
    543 slapi_modify_internal_pb( Slapi_PBlock *pb )
    544 {
    545 	SlapReply		*rs;
    546 
    547 	if ( pb == NULL ) {
    548 		return -1;
    549 	}
    550 
    551 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODIFY );
    552 
    553 	rs = pb->pb_rs;
    554 
    555 	if ( pb->pb_op->orm_modlist == NULL ) {
    556 		rs->sr_err = LDAP_PARAM_ERROR;
    557 		goto cleanup;
    558 	}
    559 
    560 	if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) {
    561 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
    562 		goto cleanup;
    563 	}
    564 
    565 	rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->orm_modlist,
    566 		&rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
    567 	if ( rs->sr_err != LDAP_SUCCESS ) {
    568                 goto cleanup;
    569         }
    570 
    571 	slapi_int_func_internal_pb( pb, op_modify );
    572 
    573 cleanup:
    574 
    575 	return 0;
    576 }
    577 
    578 static int
    579 slapi_int_search_entry_callback( Slapi_Entry *entry, void *callback_data )
    580 {
    581 	int		nentries = 0, i = 0;
    582 	Slapi_Entry	**head = NULL, **tp;
    583 	Slapi_PBlock	*pb = (Slapi_PBlock *)callback_data;
    584 
    585 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH );
    586 
    587 	entry = slapi_entry_dup( entry );
    588 	if ( entry == NULL ) {
    589 		return LDAP_NO_MEMORY;
    590 	}
    591 
    592 	slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
    593 	slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );
    594 
    595 	i = nentries + 1;
    596 	if ( nentries == 0 ) {
    597 		tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );
    598 		if ( tp == NULL ) {
    599 			slapi_entry_free( entry );
    600 			return LDAP_NO_MEMORY;
    601 		}
    602 
    603 		tp[0] = entry;
    604 	} else {
    605 		tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,
    606 				sizeof(Slapi_Entry *) * ( i + 1 ) );
    607 		if ( tp == NULL ) {
    608 			slapi_entry_free( entry );
    609 			return LDAP_NO_MEMORY;
    610 		}
    611 		tp[i - 1] = entry;
    612 	}
    613 	tp[i] = NULL;
    614 
    615 	slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );
    616 	slapi_pblock_set( pb, SLAPI_NENTRIES, (void *)&i );
    617 
    618 	return LDAP_SUCCESS;
    619 }
    620 
    621 int
    622 slapi_search_internal_pb( Slapi_PBlock *pb )
    623 {
    624 	return slapi_search_internal_callback_pb( pb,
    625 		(void *)pb,
    626 		NULL,
    627 		slapi_int_search_entry_callback,
    628 		NULL );
    629 }
    630 
    631 int
    632 slapi_search_internal_callback_pb( Slapi_PBlock *pb,
    633 	void *callback_data,
    634 	plugin_result_callback prc,
    635 	plugin_search_entry_callback psec,
    636 	plugin_referral_entry_callback prec )
    637 {
    638 	int			free_filter = 0;
    639 	SlapReply		*rs;
    640 
    641 	if ( pb == NULL ) {
    642 		return -1;
    643 	}
    644 
    645 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH );
    646 
    647 	rs = pb->pb_rs;
    648 
    649 	/* search callback and arguments */
    650 	slapi_pblock_set( pb, SLAPI_X_INTOP_RESULT_CALLBACK,         (void *)prc );
    651 	slapi_pblock_set( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK,   (void *)psec );
    652 	slapi_pblock_set( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, (void *)prec );
    653 	slapi_pblock_set( pb, SLAPI_X_INTOP_CALLBACK_DATA,           (void *)callback_data );
    654 
    655 	if ( BER_BVISEMPTY( &pb->pb_op->ors_filterstr )) {
    656 		rs->sr_err = LDAP_PARAM_ERROR;
    657 		goto cleanup;
    658 	}
    659 
    660 	if ( pb->pb_op->ors_filter == NULL ) {
    661 		pb->pb_op->ors_filter = slapi_str2filter( pb->pb_op->ors_filterstr.bv_val );
    662 		if ( pb->pb_op->ors_filter == NULL ) {
    663 			rs->sr_err = LDAP_PROTOCOL_ERROR;
    664 			goto cleanup;
    665 		}
    666 
    667 		free_filter = 1;
    668 	}
    669 
    670 	slapi_int_func_internal_pb( pb, op_search );
    671 
    672 cleanup:
    673 	if ( free_filter ) {
    674 		slapi_filter_free( pb->pb_op->ors_filter, 1 );
    675 		pb->pb_op->ors_filter = NULL;
    676 	}
    677 
    678 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_RESULT_CALLBACK );
    679 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK );
    680 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK );
    681 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_CALLBACK_DATA );
    682 
    683 	return 0;
    684 }
    685 
    686 /* Wrappers for old API */
    687 
    688 void
    689 slapi_search_internal_set_pb( Slapi_PBlock *pb,
    690 	const char *base,
    691 	int scope,
    692 	const char *filter,
    693 	char **attrs,
    694 	int attrsonly,
    695 	LDAPControl **controls,
    696 	const char *uniqueid,
    697 	Slapi_ComponentId *plugin_identity,
    698 	int operation_flags )
    699 {
    700 	int no_limit = SLAP_NO_LIMIT;
    701 	int deref = LDAP_DEREF_NEVER;
    702 
    703 	slapi_int_connection_init_pb( pb, LDAP_REQ_SEARCH );
    704 	slapi_pblock_set( pb, SLAPI_SEARCH_TARGET,    (void *)base );
    705 	slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE,     (void *)&scope );
    706 	slapi_pblock_set( pb, SLAPI_SEARCH_FILTER,    (void *)0 );
    707 	slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)filter );
    708 	slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS,     (void *)attrs );
    709 	slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)&attrsonly );
    710 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,      (void *)controls );
    711 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,  (void *)uniqueid );
    712 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,  (void *)plugin_identity );
    713 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,    (void *)&operation_flags );
    714 	slapi_pblock_set( pb, SLAPI_SEARCH_DEREF,     (void *)&deref );
    715 	slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, (void *)&no_limit );
    716 	slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, (void *)&no_limit );
    717 
    718 	slapi_int_set_operation_dn( pb );
    719 }
    720 
    721 Slapi_PBlock *
    722 slapi_search_internal(
    723 	char *ldn,
    724 	int scope,
    725 	char *filStr,
    726 	LDAPControl **controls,
    727 	char **attrs,
    728 	int attrsonly )
    729 {
    730 	Slapi_PBlock *pb;
    731 
    732 	pb = slapi_pblock_new();
    733 
    734 	slapi_search_internal_set_pb( pb, ldn, scope, filStr,
    735 		attrs, attrsonly,
    736 		controls, NULL, NULL, 0 );
    737 
    738 	slapi_search_internal_pb( pb );
    739 
    740 	return pb;
    741 }
    742 
    743 void
    744 slapi_modify_internal_set_pb( Slapi_PBlock *pb,
    745 	const char *dn,
    746 	LDAPMod **mods,
    747 	LDAPControl **controls,
    748 	const char *uniqueid,
    749 	Slapi_ComponentId *plugin_identity,
    750 	int operation_flags )
    751 {
    752 	slapi_int_connection_init_pb( pb, LDAP_REQ_MODIFY );
    753 	slapi_pblock_set( pb, SLAPI_MODIFY_TARGET,   (void *)dn );
    754 	slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)mods );
    755 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
    756 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
    757 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
    758 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
    759 	slapi_int_set_operation_dn( pb );
    760 }
    761 
    762 /* Function : slapi_modify_internal
    763  *
    764  * Description:	Plugin functions call this routine to modify an entry
    765  *				in the backend directly
    766  * Return values : LDAP_SUCCESS
    767  *                 LDAP_PARAM_ERROR
    768  *                 LDAP_NO_MEMORY
    769  *                 LDAP_OTHER
    770  *                 LDAP_UNWILLING_TO_PERFORM
    771 */
    772 Slapi_PBlock *
    773 slapi_modify_internal(
    774 	char *ldn,
    775 	LDAPMod **mods,
    776 	LDAPControl **controls,
    777 	int log_change )
    778 {
    779 	Slapi_PBlock *pb;
    780 
    781 	pb = slapi_pblock_new();
    782 
    783 	slapi_modify_internal_set_pb( pb, ldn, mods, controls, NULL, NULL, 0 );
    784 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
    785 	slapi_modify_internal_pb( pb );
    786 
    787 	return pb;
    788 }
    789 
    790 int
    791 slapi_add_internal_set_pb( Slapi_PBlock *pb,
    792 	const char *dn,
    793 	LDAPMod **attrs,
    794 	LDAPControl **controls,
    795 	Slapi_ComponentId *plugin_identity,
    796 	int operation_flags )
    797 {
    798 	slapi_int_connection_init_pb( pb, LDAP_REQ_ADD );
    799 	slapi_pblock_set( pb, SLAPI_ADD_TARGET,      (void *)dn );
    800 	slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)attrs );
    801 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
    802 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
    803 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
    804 	slapi_int_set_operation_dn( pb );
    805 
    806 	return 0;
    807 }
    808 
    809 Slapi_PBlock *
    810 slapi_add_internal(
    811 	char * dn,
    812 	LDAPMod **attrs,
    813 	LDAPControl **controls,
    814 	int log_change )
    815 {
    816 	Slapi_PBlock *pb;
    817 
    818 	pb = slapi_pblock_new();
    819 
    820 	slapi_add_internal_set_pb( pb, dn, attrs, controls, NULL, 0);
    821 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
    822 	slapi_add_internal_pb( pb );
    823 
    824 	return pb;
    825 }
    826 
    827 void
    828 slapi_add_entry_internal_set_pb( Slapi_PBlock *pb,
    829 	Slapi_Entry *e,
    830 	LDAPControl **controls,
    831 	Slapi_ComponentId *plugin_identity,
    832 	int operation_flags )
    833 {
    834 	slapi_int_connection_init_pb( pb, LDAP_REQ_ADD );
    835 	slapi_pblock_set( pb, SLAPI_ADD_ENTRY,       (void *)e );
    836 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
    837 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
    838 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
    839 	slapi_int_set_operation_dn( pb );
    840 }
    841 
    842 Slapi_PBlock *
    843 slapi_add_entry_internal(
    844 	Slapi_Entry *e,
    845 	LDAPControl **controls,
    846 	int log_change )
    847 {
    848 	Slapi_PBlock *pb;
    849 
    850 	pb = slapi_pblock_new();
    851 
    852 	slapi_add_entry_internal_set_pb( pb, e, controls, NULL, 0 );
    853 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
    854 	slapi_add_internal_pb( pb );
    855 
    856 	return pb;
    857 }
    858 
    859 void
    860 slapi_rename_internal_set_pb( Slapi_PBlock *pb,
    861 	const char *olddn,
    862 	const char *newrdn,
    863 	const char *newsuperior,
    864 	int deloldrdn,
    865 	LDAPControl **controls,
    866 	const char *uniqueid,
    867 	Slapi_ComponentId *plugin_identity,
    868 	int operation_flags )
    869 {
    870 	slapi_int_connection_init_pb( pb, LDAP_REQ_MODRDN );
    871 	slapi_pblock_set( pb, SLAPI_MODRDN_TARGET,      (void *)olddn );
    872 	slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN,      (void *)newrdn );
    873 	slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, (void *)newsuperior );
    874 	slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN,   (void *)&deloldrdn );
    875 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,        (void *)controls );
    876 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,    (void *)uniqueid );
    877 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,    (void *)plugin_identity );
    878 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,      (void *)&operation_flags );
    879 	slap_modrdn2mods( pb->pb_op, pb->pb_rs );
    880 	slapi_int_set_operation_dn( pb );
    881 }
    882 
    883 /* Function : slapi_modrdn_internal
    884  *
    885  * Description : Plugin functions call this routine to modify the rdn
    886  *				 of an entry in the backend directly
    887  * Return values : LDAP_SUCCESS
    888  *                 LDAP_PARAM_ERROR
    889  *                 LDAP_NO_MEMORY
    890  *                 LDAP_OTHER
    891  *                 LDAP_UNWILLING_TO_PERFORM
    892  *
    893  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
    894  */
    895 Slapi_PBlock *
    896 slapi_modrdn_internal(
    897 	char *olddn,
    898 	char *lnewrdn,
    899 	int deloldrdn,
    900 	LDAPControl **controls,
    901 	int log_change )
    902 {
    903 	Slapi_PBlock *pb;
    904 
    905 	pb = slapi_pblock_new ();
    906 
    907 	slapi_rename_internal_set_pb( pb, olddn, lnewrdn, NULL,
    908 		deloldrdn, controls, NULL, NULL, 0 );
    909 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
    910 	slapi_modrdn_internal_pb( pb );
    911 
    912 	return pb;
    913 }
    914 
    915 void
    916 slapi_delete_internal_set_pb( Slapi_PBlock *pb,
    917 	const char *dn,
    918 	LDAPControl **controls,
    919 	const char *uniqueid,
    920 	Slapi_ComponentId *plugin_identity,
    921 	int operation_flags )
    922 {
    923 	slapi_int_connection_init_pb( pb, LDAP_REQ_DELETE );
    924 	slapi_pblock_set( pb, SLAPI_TARGET_DN,       (void *)dn );
    925 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
    926 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
    927 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
    928 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
    929 	slapi_int_set_operation_dn( pb );
    930 }
    931 
    932 /* Function : slapi_delete_internal
    933  *
    934  * Description : Plugin functions call this routine to delete an entry
    935  *               in the backend directly
    936  * Return values : LDAP_SUCCESS
    937  *                 LDAP_PARAM_ERROR
    938  *                 LDAP_NO_MEMORY
    939  *                 LDAP_OTHER
    940  *                 LDAP_UNWILLING_TO_PERFORM
    941 */
    942 Slapi_PBlock *
    943 slapi_delete_internal(
    944 	char *ldn,
    945 	LDAPControl **controls,
    946 	int log_change )
    947 {
    948 	Slapi_PBlock *pb;
    949 
    950 	pb = slapi_pblock_new();
    951 
    952 	slapi_delete_internal_set_pb( pb, ldn, controls, NULL, NULL, 0 );
    953 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
    954 	slapi_delete_internal_pb( pb );
    955 
    956 	return pb;
    957 }
    958 
    959 #endif /* LDAP_SLAPI */
    960