xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/slapi/slapi_ops.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: slapi_ops.c,v 1.1.1.6 2018/02/06 01:53:18 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2002-2017 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.1.1.6 2018/02/06 01:53:18 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_mutex_init( &conn->c_write2_mutex );
234 	ldap_pvt_thread_cond_init( &conn->c_write1_cv );
235 	ldap_pvt_thread_cond_init( &conn->c_write2_cv );
236 
237 	ldap_pvt_thread_mutex_lock( &conn->c_mutex );
238 
239 	conn->c_n_ops_received = 0;
240 	conn->c_n_ops_executing = 0;
241 	conn->c_n_ops_pending = 0;
242 	conn->c_n_ops_completed = 0;
243 
244 	conn->c_n_get = 0;
245 	conn->c_n_read = 0;
246 	conn->c_n_write = 0;
247 
248 	conn->c_protocol = LDAP_VERSION3;
249 
250 	conn->c_activitytime = conn->c_starttime = slap_get_time();
251 
252 	/*
253 	 * A real connection ID is required, because syncrepl associates
254 	 * pending CSNs with unique ( connection, operation ) tuples.
255 	 * Setting a fake connection ID will cause slap_get_commit_csn()
256 	 * to return a stale value.
257 	 */
258 	connection_assign_nextid( conn );
259 
260 	conn->c_conn_state  = 0x01;	/* SLAP_C_ACTIVE */
261 	conn->c_struct_state = 0x02;	/* SLAP_C_USED */
262 
263 	conn->c_ssf = conn->c_transport_ssf = local_ssf;
264 	conn->c_tls_ssf = 0;
265 
266 	backend_connection_init( conn );
267 
268 	conn->c_send_ldap_result = slap_send_ldap_result;
269 	conn->c_send_search_entry = slap_send_search_entry;
270 	conn->c_send_ldap_extended = slap_send_ldap_extended;
271 	conn->c_send_search_reference = slap_send_search_reference;
272 
273 	/* operation object */
274 	op->o_tag = tag;
275 	op->o_protocol = LDAP_VERSION3;
276 	BER_BVZERO( &op->o_authmech );
277 	op->o_time = slap_get_time();
278 	op->o_do_not_cache = 1;
279 	op->o_threadctx = ldap_pvt_thread_pool_context();
280 	op->o_tmpmemctx = NULL;
281 	op->o_tmpmfuncs = &ch_mfuncs;
282 	op->o_conn = conn;
283 	op->o_connid = conn->c_connid;
284 	op->o_bd = frontendDB;
285 
286 	/* extensions */
287 	slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op );
288 	slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
289 
290 	pb->pb_rs = (SlapReply *)slapi_ch_calloc( 1, sizeof(SlapReply) );
291 	pb->pb_op = op;
292 	pb->pb_conn = conn;
293 	pb->pb_intop = 1;
294 
295 	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
296 }
297 
298 static void
299 slapi_int_set_operation_dn( Slapi_PBlock *pb )
300 {
301 	Backend			*be;
302 	Operation		*op = pb->pb_op;
303 
304 	if ( BER_BVISNULL( &op->o_ndn ) ) {
305 		/* set to root DN */
306 		be = select_backend( &op->o_req_ndn, 1 );
307 		if ( be != NULL ) {
308 			ber_dupbv( &op->o_dn, &be->be_rootdn );
309 			ber_dupbv( &op->o_ndn, &be->be_rootndn );
310 		}
311 	}
312 }
313 
314 void
315 slapi_int_connection_done_pb( Slapi_PBlock *pb )
316 {
317 	Connection		*conn;
318 	Operation		*op;
319 
320 	PBLOCK_ASSERT_INTOP( pb, 0 );
321 
322 	conn = pb->pb_conn;
323 	op = pb->pb_op;
324 
325 	/* free allocated DNs */
326 	if ( !BER_BVISNULL( &op->o_dn ) )
327 		op->o_tmpfree( op->o_dn.bv_val, op->o_tmpmemctx );
328 	if ( !BER_BVISNULL( &op->o_ndn ) )
329 		op->o_tmpfree( op->o_ndn.bv_val, op->o_tmpmemctx );
330 
331 	if ( !BER_BVISNULL( &op->o_req_dn ) )
332 		op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
333 	if ( !BER_BVISNULL( &op->o_req_ndn ) )
334 		op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
335 
336 	switch ( op->o_tag ) {
337 	case LDAP_REQ_MODRDN:
338 		if ( !BER_BVISNULL( &op->orr_newrdn ))
339 			op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx );
340 		if ( !BER_BVISNULL( &op->orr_nnewrdn ))
341 			op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx );
342 		if ( op->orr_newSup != NULL ) {
343 			assert( !BER_BVISNULL( op->orr_newSup ) );
344 			op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx );
345 			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
346 		}
347 		if ( op->orr_nnewSup != NULL ) {
348 			assert( !BER_BVISNULL( op->orr_nnewSup ) );
349 			op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx );
350 			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
351 		}
352 		slap_mods_free( op->orr_modlist, 1 );
353 		break;
354 	case LDAP_REQ_ADD:
355 		slap_mods_free( op->ora_modlist, 0 );
356 		break;
357 	case LDAP_REQ_MODIFY:
358 		slap_mods_free( op->orm_modlist, 1 );
359 		break;
360 	case LDAP_REQ_SEARCH:
361 		if ( op->ors_attrs != NULL ) {
362 			op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx );
363 			op->ors_attrs = NULL;
364 		}
365 		break;
366 	default:
367 		break;
368 	}
369 
370 	slapi_ch_free_string( &conn->c_authmech.bv_val );
371 	slapi_ch_free_string( &conn->c_dn.bv_val );
372 	slapi_ch_free_string( &conn->c_ndn.bv_val );
373 	slapi_ch_free_string( &conn->c_peer_domain.bv_val );
374 	slapi_ch_free_string( &conn->c_peer_name.bv_val );
375 
376 	if ( conn->c_sb != NULL ) {
377 		ber_sockbuf_free( conn->c_sb );
378 	}
379 
380 	slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op );
381 	slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
382 
383 	slapi_ch_free( (void **)&pb->pb_op->o_callback );
384 	slapi_ch_free( (void **)&pb->pb_op );
385 	slapi_ch_free( (void **)&pb->pb_conn );
386 	slapi_ch_free( (void **)&pb->pb_rs );
387 }
388 
389 static int
390 slapi_int_func_internal_pb( Slapi_PBlock *pb, slap_operation_t which )
391 {
392 	BI_op_bind		**func;
393 	SlapReply		*rs = pb->pb_rs;
394 	int			rc;
395 
396 	PBLOCK_ASSERT_INTOP( pb, 0 );
397 
398 	rc = slapi_int_get_ctrls( pb );
399 	if ( rc != LDAP_SUCCESS ) {
400 		rs->sr_err = rc;
401 		return rc;
402 	}
403 
404 	pb->pb_op->o_bd = frontendDB;
405 	func = &frontendDB->be_bind;
406 
407 	return func[which]( pb->pb_op, pb->pb_rs );
408 }
409 
410 int
411 slapi_delete_internal_pb( Slapi_PBlock *pb )
412 {
413 	if ( pb == NULL ) {
414 		return -1;
415 	}
416 
417 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_DELETE );
418 
419 	slapi_int_func_internal_pb( pb, op_delete );
420 
421 	return 0;
422 }
423 
424 int
425 slapi_add_internal_pb( Slapi_PBlock *pb )
426 {
427 	SlapReply		*rs;
428 	Slapi_Entry		*entry_orig = NULL;
429 	OpExtraDB oex;
430 	int rc;
431 
432 	if ( pb == NULL ) {
433 		return -1;
434 	}
435 
436 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_ADD );
437 
438 	rs = pb->pb_rs;
439 
440 	entry_orig = pb->pb_op->ora_e;
441 	pb->pb_op->ora_e = NULL;
442 
443 	/*
444 	 * The caller can specify a new entry, or a target DN and set
445 	 * of modifications, but not both.
446 	 */
447 	if ( entry_orig != NULL ) {
448 		if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
449 			rs->sr_err = LDAP_PARAM_ERROR;
450 			goto cleanup;
451 		}
452 
453 		assert( BER_BVISNULL( &pb->pb_op->o_req_dn ) ); /* shouldn't get set */
454 		ber_dupbv( &pb->pb_op->o_req_dn, &entry_orig->e_name );
455 		ber_dupbv( &pb->pb_op->o_req_ndn, &entry_orig->e_nname );
456 	} else if ( pb->pb_op->ora_modlist == NULL || BER_BVISNULL( &pb->pb_op->o_req_ndn )) {
457 		rs->sr_err = LDAP_PARAM_ERROR;
458 		goto cleanup;
459 	}
460 
461 	pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) );
462 	ber_dupbv( &pb->pb_op->ora_e->e_name,  &pb->pb_op->o_req_dn );
463 	ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn );
464 
465 	if ( entry_orig != NULL ) {
466 		assert( pb->pb_op->ora_modlist == NULL );
467 
468 		rs->sr_err = slap_entry2mods( entry_orig, &pb->pb_op->ora_modlist,
469 			&rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
470 		if ( rs->sr_err != LDAP_SUCCESS ) {
471 			goto cleanup;
472 		}
473 	} else {
474 		assert( pb->pb_op->ora_modlist != NULL );
475 	}
476 
477 	rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->ora_modlist, &rs->sr_text,
478 		pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
479 	if ( rs->sr_err != LDAP_SUCCESS ) {
480                 goto cleanup;
481         }
482 
483 	/* Duplicate the values, because we may call slapi_entry_free() */
484 	rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e,
485 		1, 0, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) );
486 	if ( rs->sr_err != LDAP_SUCCESS ) {
487 		goto cleanup;
488 	}
489 
490 	oex.oe.oe_key = (void *)do_add;
491 	oex.oe_db = NULL;
492 	LDAP_SLIST_INSERT_HEAD(&pb->pb_op->o_extra, &oex.oe, oe_next);
493 	rc = slapi_int_func_internal_pb( pb, op_add );
494 	LDAP_SLIST_REMOVE(&pb->pb_op->o_extra, &oex.oe, OpExtra, oe_next);
495 
496 	if ( !rc ) {
497 		if ( pb->pb_op->ora_e != NULL && oex.oe_db != NULL ) {
498 			BackendDB	*bd = pb->pb_op->o_bd;
499 
500 			pb->pb_op->o_bd = oex.oe_db;
501 			be_entry_release_w( pb->pb_op, pb->pb_op->ora_e );
502 			pb->pb_op->ora_e = NULL;
503 			pb->pb_op->o_bd = bd;
504 		}
505 	}
506 
507 cleanup:
508 
509 	if ( pb->pb_op->ora_e != NULL ) {
510 		slapi_entry_free( pb->pb_op->ora_e );
511 		pb->pb_op->ora_e = NULL;
512 	}
513 	if ( entry_orig != NULL ) {
514 		pb->pb_op->ora_e = entry_orig;
515 		slap_mods_free( pb->pb_op->ora_modlist, 1 );
516 		pb->pb_op->ora_modlist = NULL;
517 	}
518 
519 	return 0;
520 }
521 
522 int
523 slapi_modrdn_internal_pb( Slapi_PBlock *pb )
524 {
525 	if ( pb == NULL ) {
526 		return -1;
527 	}
528 
529 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODRDN );
530 
531 	if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) {
532 		pb->pb_rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
533 		goto cleanup;
534 	}
535 
536 	slapi_int_func_internal_pb( pb, op_modrdn );
537 
538 cleanup:
539 
540 	return 0;
541 }
542 
543 int
544 slapi_modify_internal_pb( Slapi_PBlock *pb )
545 {
546 	SlapReply		*rs;
547 
548 	if ( pb == NULL ) {
549 		return -1;
550 	}
551 
552 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODIFY );
553 
554 	rs = pb->pb_rs;
555 
556 	if ( pb->pb_op->orm_modlist == NULL ) {
557 		rs->sr_err = LDAP_PARAM_ERROR;
558 		goto cleanup;
559 	}
560 
561 	if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) {
562 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
563 		goto cleanup;
564 	}
565 
566 	rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->orm_modlist,
567 		&rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL );
568 	if ( rs->sr_err != LDAP_SUCCESS ) {
569                 goto cleanup;
570         }
571 
572 	slapi_int_func_internal_pb( pb, op_modify );
573 
574 cleanup:
575 
576 	return 0;
577 }
578 
579 static int
580 slapi_int_search_entry_callback( Slapi_Entry *entry, void *callback_data )
581 {
582 	int		nentries = 0, i = 0;
583 	Slapi_Entry	**head = NULL, **tp;
584 	Slapi_PBlock	*pb = (Slapi_PBlock *)callback_data;
585 
586 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH );
587 
588 	entry = slapi_entry_dup( entry );
589 	if ( entry == NULL ) {
590 		return LDAP_NO_MEMORY;
591 	}
592 
593 	slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
594 	slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );
595 
596 	i = nentries + 1;
597 	if ( nentries == 0 ) {
598 		tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );
599 		if ( tp == NULL ) {
600 			slapi_entry_free( entry );
601 			return LDAP_NO_MEMORY;
602 		}
603 
604 		tp[0] = entry;
605 	} else {
606 		tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,
607 				sizeof(Slapi_Entry *) * ( i + 1 ) );
608 		if ( tp == NULL ) {
609 			slapi_entry_free( entry );
610 			return LDAP_NO_MEMORY;
611 		}
612 		tp[i - 1] = entry;
613 	}
614 	tp[i] = NULL;
615 
616 	slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );
617 	slapi_pblock_set( pb, SLAPI_NENTRIES, (void *)&i );
618 
619 	return LDAP_SUCCESS;
620 }
621 
622 int
623 slapi_search_internal_pb( Slapi_PBlock *pb )
624 {
625 	return slapi_search_internal_callback_pb( pb,
626 		(void *)pb,
627 		NULL,
628 		slapi_int_search_entry_callback,
629 		NULL );
630 }
631 
632 int
633 slapi_search_internal_callback_pb( Slapi_PBlock *pb,
634 	void *callback_data,
635 	plugin_result_callback prc,
636 	plugin_search_entry_callback psec,
637 	plugin_referral_entry_callback prec )
638 {
639 	int			free_filter = 0;
640 	SlapReply		*rs;
641 
642 	if ( pb == NULL ) {
643 		return -1;
644 	}
645 
646 	PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH );
647 
648 	rs = pb->pb_rs;
649 
650 	/* search callback and arguments */
651 	slapi_pblock_set( pb, SLAPI_X_INTOP_RESULT_CALLBACK,         (void *)prc );
652 	slapi_pblock_set( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK,   (void *)psec );
653 	slapi_pblock_set( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, (void *)prec );
654 	slapi_pblock_set( pb, SLAPI_X_INTOP_CALLBACK_DATA,           (void *)callback_data );
655 
656 	if ( BER_BVISEMPTY( &pb->pb_op->ors_filterstr )) {
657 		rs->sr_err = LDAP_PARAM_ERROR;
658 		goto cleanup;
659 	}
660 
661 	if ( pb->pb_op->ors_filter == NULL ) {
662 		pb->pb_op->ors_filter = slapi_str2filter( pb->pb_op->ors_filterstr.bv_val );
663 		if ( pb->pb_op->ors_filter == NULL ) {
664 			rs->sr_err = LDAP_PROTOCOL_ERROR;
665 			goto cleanup;
666 		}
667 
668 		free_filter = 1;
669 	}
670 
671 	slapi_int_func_internal_pb( pb, op_search );
672 
673 cleanup:
674 	if ( free_filter ) {
675 		slapi_filter_free( pb->pb_op->ors_filter, 1 );
676 		pb->pb_op->ors_filter = NULL;
677 	}
678 
679 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_RESULT_CALLBACK );
680 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK );
681 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK );
682 	slapi_pblock_delete_param( pb, SLAPI_X_INTOP_CALLBACK_DATA );
683 
684 	return 0;
685 }
686 
687 /* Wrappers for old API */
688 
689 void
690 slapi_search_internal_set_pb( Slapi_PBlock *pb,
691 	const char *base,
692 	int scope,
693 	const char *filter,
694 	char **attrs,
695 	int attrsonly,
696 	LDAPControl **controls,
697 	const char *uniqueid,
698 	Slapi_ComponentId *plugin_identity,
699 	int operation_flags )
700 {
701 	int no_limit = SLAP_NO_LIMIT;
702 	int deref = LDAP_DEREF_NEVER;
703 
704 	slapi_int_connection_init_pb( pb, LDAP_REQ_SEARCH );
705 	slapi_pblock_set( pb, SLAPI_SEARCH_TARGET,    (void *)base );
706 	slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE,     (void *)&scope );
707 	slapi_pblock_set( pb, SLAPI_SEARCH_FILTER,    (void *)0 );
708 	slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, (void *)filter );
709 	slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS,     (void *)attrs );
710 	slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, (void *)&attrsonly );
711 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,      (void *)controls );
712 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,  (void *)uniqueid );
713 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,  (void *)plugin_identity );
714 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,    (void *)&operation_flags );
715 	slapi_pblock_set( pb, SLAPI_SEARCH_DEREF,     (void *)&deref );
716 	slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, (void *)&no_limit );
717 	slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, (void *)&no_limit );
718 
719 	slapi_int_set_operation_dn( pb );
720 }
721 
722 Slapi_PBlock *
723 slapi_search_internal(
724 	char *ldn,
725 	int scope,
726 	char *filStr,
727 	LDAPControl **controls,
728 	char **attrs,
729 	int attrsonly )
730 {
731 	Slapi_PBlock *pb;
732 
733 	pb = slapi_pblock_new();
734 
735 	slapi_search_internal_set_pb( pb, ldn, scope, filStr,
736 		attrs, attrsonly,
737 		controls, NULL, NULL, 0 );
738 
739 	slapi_search_internal_pb( pb );
740 
741 	return pb;
742 }
743 
744 void
745 slapi_modify_internal_set_pb( Slapi_PBlock *pb,
746 	const char *dn,
747 	LDAPMod **mods,
748 	LDAPControl **controls,
749 	const char *uniqueid,
750 	Slapi_ComponentId *plugin_identity,
751 	int operation_flags )
752 {
753 	slapi_int_connection_init_pb( pb, LDAP_REQ_MODIFY );
754 	slapi_pblock_set( pb, SLAPI_MODIFY_TARGET,   (void *)dn );
755 	slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)mods );
756 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
757 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
758 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
759 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
760 	slapi_int_set_operation_dn( pb );
761 }
762 
763 /* Function : slapi_modify_internal
764  *
765  * Description:	Plugin functions call this routine to modify an entry
766  *				in the backend directly
767  * Return values : LDAP_SUCCESS
768  *                 LDAP_PARAM_ERROR
769  *                 LDAP_NO_MEMORY
770  *                 LDAP_OTHER
771  *                 LDAP_UNWILLING_TO_PERFORM
772 */
773 Slapi_PBlock *
774 slapi_modify_internal(
775 	char *ldn,
776 	LDAPMod **mods,
777 	LDAPControl **controls,
778 	int log_change )
779 {
780 	Slapi_PBlock *pb;
781 
782 	pb = slapi_pblock_new();
783 
784 	slapi_modify_internal_set_pb( pb, ldn, mods, controls, NULL, NULL, 0 );
785 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
786 	slapi_modify_internal_pb( pb );
787 
788 	return pb;
789 }
790 
791 int
792 slapi_add_internal_set_pb( Slapi_PBlock *pb,
793 	const char *dn,
794 	LDAPMod **attrs,
795 	LDAPControl **controls,
796 	Slapi_ComponentId *plugin_identity,
797 	int operation_flags )
798 {
799 	slapi_int_connection_init_pb( pb, LDAP_REQ_ADD );
800 	slapi_pblock_set( pb, SLAPI_ADD_TARGET,      (void *)dn );
801 	slapi_pblock_set( pb, SLAPI_MODIFY_MODS,     (void *)attrs );
802 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
803 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
804 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
805 	slapi_int_set_operation_dn( pb );
806 
807 	return 0;
808 }
809 
810 Slapi_PBlock *
811 slapi_add_internal(
812 	char * dn,
813 	LDAPMod **attrs,
814 	LDAPControl **controls,
815 	int log_change )
816 {
817 	Slapi_PBlock *pb;
818 
819 	pb = slapi_pblock_new();
820 
821 	slapi_add_internal_set_pb( pb, dn, attrs, controls, NULL, 0);
822 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
823 	slapi_add_internal_pb( pb );
824 
825 	return pb;
826 }
827 
828 void
829 slapi_add_entry_internal_set_pb( Slapi_PBlock *pb,
830 	Slapi_Entry *e,
831 	LDAPControl **controls,
832 	Slapi_ComponentId *plugin_identity,
833 	int operation_flags )
834 {
835 	slapi_int_connection_init_pb( pb, LDAP_REQ_ADD );
836 	slapi_pblock_set( pb, SLAPI_ADD_ENTRY,       (void *)e );
837 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
838 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
839 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
840 	slapi_int_set_operation_dn( pb );
841 }
842 
843 Slapi_PBlock *
844 slapi_add_entry_internal(
845 	Slapi_Entry *e,
846 	LDAPControl **controls,
847 	int log_change )
848 {
849 	Slapi_PBlock *pb;
850 
851 	pb = slapi_pblock_new();
852 
853 	slapi_add_entry_internal_set_pb( pb, e, controls, NULL, 0 );
854 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
855 	slapi_add_internal_pb( pb );
856 
857 	return pb;
858 }
859 
860 void
861 slapi_rename_internal_set_pb( Slapi_PBlock *pb,
862 	const char *olddn,
863 	const char *newrdn,
864 	const char *newsuperior,
865 	int deloldrdn,
866 	LDAPControl **controls,
867 	const char *uniqueid,
868 	Slapi_ComponentId *plugin_identity,
869 	int operation_flags )
870 {
871 	slapi_int_connection_init_pb( pb, LDAP_REQ_MODRDN );
872 	slapi_pblock_set( pb, SLAPI_MODRDN_TARGET,      (void *)olddn );
873 	slapi_pblock_set( pb, SLAPI_MODRDN_NEWRDN,      (void *)newrdn );
874 	slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR, (void *)newsuperior );
875 	slapi_pblock_set( pb, SLAPI_MODRDN_DELOLDRDN,   (void *)&deloldrdn );
876 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,        (void *)controls );
877 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID,    (void *)uniqueid );
878 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY,    (void *)plugin_identity );
879 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,      (void *)&operation_flags );
880 	slap_modrdn2mods( pb->pb_op, pb->pb_rs );
881 	slapi_int_set_operation_dn( pb );
882 }
883 
884 /* Function : slapi_modrdn_internal
885  *
886  * Description : Plugin functions call this routine to modify the rdn
887  *				 of an entry in the backend directly
888  * Return values : LDAP_SUCCESS
889  *                 LDAP_PARAM_ERROR
890  *                 LDAP_NO_MEMORY
891  *                 LDAP_OTHER
892  *                 LDAP_UNWILLING_TO_PERFORM
893  *
894  * NOTE: This function does not support the "newSuperior" option from LDAP V3.
895  */
896 Slapi_PBlock *
897 slapi_modrdn_internal(
898 	char *olddn,
899 	char *lnewrdn,
900 	int deloldrdn,
901 	LDAPControl **controls,
902 	int log_change )
903 {
904 	Slapi_PBlock *pb;
905 
906 	pb = slapi_pblock_new ();
907 
908 	slapi_rename_internal_set_pb( pb, olddn, lnewrdn, NULL,
909 		deloldrdn, controls, NULL, NULL, 0 );
910 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
911 	slapi_modrdn_internal_pb( pb );
912 
913 	return pb;
914 }
915 
916 void
917 slapi_delete_internal_set_pb( Slapi_PBlock *pb,
918 	const char *dn,
919 	LDAPControl **controls,
920 	const char *uniqueid,
921 	Slapi_ComponentId *plugin_identity,
922 	int operation_flags )
923 {
924 	slapi_int_connection_init_pb( pb, LDAP_REQ_DELETE );
925 	slapi_pblock_set( pb, SLAPI_TARGET_DN,       (void *)dn );
926 	slapi_pblock_set( pb, SLAPI_REQCONTROLS,     (void *)controls );
927 	slapi_pblock_set( pb, SLAPI_TARGET_UNIQUEID, (void *)uniqueid );
928 	slapi_pblock_set( pb, SLAPI_PLUGIN_IDENTITY, (void *)plugin_identity );
929 	slapi_pblock_set( pb, SLAPI_X_INTOP_FLAGS,   (void *)&operation_flags );
930 	slapi_int_set_operation_dn( pb );
931 }
932 
933 /* Function : slapi_delete_internal
934  *
935  * Description : Plugin functions call this routine to delete an entry
936  *               in the backend directly
937  * Return values : LDAP_SUCCESS
938  *                 LDAP_PARAM_ERROR
939  *                 LDAP_NO_MEMORY
940  *                 LDAP_OTHER
941  *                 LDAP_UNWILLING_TO_PERFORM
942 */
943 Slapi_PBlock *
944 slapi_delete_internal(
945 	char *ldn,
946 	LDAPControl **controls,
947 	int log_change )
948 {
949 	Slapi_PBlock *pb;
950 
951 	pb = slapi_pblock_new();
952 
953 	slapi_delete_internal_set_pb( pb, ldn, controls, NULL, NULL, 0 );
954 	slapi_pblock_set( pb, SLAPI_LOG_OPERATION, (void *)&log_change );
955 	slapi_delete_internal_pb( pb );
956 
957 	return pb;
958 }
959 
960 #endif /* LDAP_SLAPI */
961 
962