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