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