xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/slapi/slapi_ops.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: slapi_ops.c,v 1.3 2021/08/14 16:15:02 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2002-2021 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.3 2021/08/14 16:15:02 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 **
slapi_int_dup_controls(LDAPControl ** controls)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
slapi_int_result(Operation * op,SlapReply * rs)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
slapi_int_search_entry(Operation * op,SlapReply * rs)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
slapi_int_search_reference(Operation * op,SlapReply * rs)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
slapi_int_response(Slapi_Operation * op,SlapReply * rs)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
slapi_int_get_ctrls(Slapi_PBlock * pb)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
slapi_int_connection_init_pb(Slapi_PBlock * pb,ber_tag_t tag)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 
242 	conn->c_n_get = 0;
243 	conn->c_n_read = 0;
244 	conn->c_n_write = 0;
245 
246 	conn->c_protocol = LDAP_VERSION3;
247 
248 	conn->c_activitytime = conn->c_starttime = slap_get_time();
249 
250 	/*
251 	 * A real connection ID is required, because syncrepl associates
252 	 * pending CSNs with unique ( connection, operation ) tuples.
253 	 * Setting a fake connection ID will cause slap_get_commit_csn()
254 	 * to return a stale value.
255 	 */
256 	connection_assign_nextid( conn );
257 
258 	conn->c_conn_state  = SLAP_C_ACTIVE;
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
slapi_int_set_operation_dn(Slapi_PBlock * pb)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
slapi_int_connection_done_pb(Slapi_PBlock * pb)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
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