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