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#include <slap.h>
25#include <slapi.h>
26
27#ifdef LDAP_SLAPI
28
29/* some parameters require a valid connection and operation */
30#define PBLOCK_LOCK_CONN( _pb )		do { \
31		ldap_pvt_thread_mutex_lock( &(_pb)->pb_conn->c_mutex ); \
32	} while (0)
33
34#define PBLOCK_UNLOCK_CONN( _pb )	do { \
35		ldap_pvt_thread_mutex_unlock( &(_pb)->pb_conn->c_mutex ); \
36	} while (0)
37
38/* some parameters are only settable for internal operations */
39#define PBLOCK_VALIDATE_IS_INTOP( _pb )	do { if ( (_pb)->pb_intop == 0 ) break; } while ( 0 )
40
41static slapi_pblock_class_t
42pblock_get_param_class( int param )
43{
44	switch ( param ) {
45	case SLAPI_PLUGIN_TYPE:
46	case SLAPI_PLUGIN_ARGC:
47	case SLAPI_PLUGIN_OPRETURN:
48	case SLAPI_PLUGIN_INTOP_RESULT:
49	case SLAPI_CONFIG_LINENO:
50	case SLAPI_CONFIG_ARGC:
51	case SLAPI_BIND_METHOD:
52	case SLAPI_MODRDN_DELOLDRDN:
53	case SLAPI_SEARCH_SCOPE:
54	case SLAPI_SEARCH_DEREF:
55	case SLAPI_SEARCH_SIZELIMIT:
56	case SLAPI_SEARCH_TIMELIMIT:
57	case SLAPI_SEARCH_ATTRSONLY:
58	case SLAPI_NENTRIES:
59	case SLAPI_CHANGENUMBER:
60	case SLAPI_DBSIZE:
61	case SLAPI_REQUESTOR_ISROOT:
62	case SLAPI_BE_READONLY:
63	case SLAPI_BE_LASTMOD:
64	case SLAPI_DB2LDIF_PRINTKEY:
65	case SLAPI_LDIF2DB_REMOVEDUPVALS:
66	case SLAPI_MANAGEDSAIT:
67	case SLAPI_X_RELAX:
68	case SLAPI_X_OPERATION_NO_SCHEMA_CHECK:
69	case SLAPI_IS_REPLICATED_OPERATION:
70	case SLAPI_X_CONN_IS_UDP:
71	case SLAPI_X_CONN_SSF:
72	case SLAPI_RESULT_CODE:
73	case SLAPI_LOG_OPERATION:
74	case SLAPI_IS_INTERNAL_OPERATION:
75		return PBLOCK_CLASS_INTEGER;
76		break;
77
78	case SLAPI_CONN_ID:
79	case SLAPI_OPERATION_ID:
80	case SLAPI_OPINITIATED_TIME:
81	case SLAPI_ABANDON_MSGID:
82	case SLAPI_X_OPERATION_DELETE_GLUE_PARENT:
83	case SLAPI_OPERATION_MSGID:
84		return PBLOCK_CLASS_LONG_INTEGER;
85		break;
86
87	case SLAPI_PLUGIN_DESTROY_FN:
88	case SLAPI_PLUGIN_DB_BIND_FN:
89	case SLAPI_PLUGIN_DB_UNBIND_FN:
90	case SLAPI_PLUGIN_DB_SEARCH_FN:
91	case SLAPI_PLUGIN_DB_COMPARE_FN:
92	case SLAPI_PLUGIN_DB_MODIFY_FN:
93	case SLAPI_PLUGIN_DB_MODRDN_FN:
94	case SLAPI_PLUGIN_DB_ADD_FN:
95	case SLAPI_PLUGIN_DB_DELETE_FN:
96	case SLAPI_PLUGIN_DB_ABANDON_FN:
97	case SLAPI_PLUGIN_DB_CONFIG_FN:
98	case SLAPI_PLUGIN_CLOSE_FN:
99	case SLAPI_PLUGIN_DB_FLUSH_FN:
100	case SLAPI_PLUGIN_START_FN:
101	case SLAPI_PLUGIN_DB_SEQ_FN:
102	case SLAPI_PLUGIN_DB_ENTRY_FN:
103	case SLAPI_PLUGIN_DB_REFERRAL_FN:
104	case SLAPI_PLUGIN_DB_RESULT_FN:
105	case SLAPI_PLUGIN_DB_LDIF2DB_FN:
106	case SLAPI_PLUGIN_DB_DB2LDIF_FN:
107	case SLAPI_PLUGIN_DB_BEGIN_FN:
108	case SLAPI_PLUGIN_DB_COMMIT_FN:
109	case SLAPI_PLUGIN_DB_ABORT_FN:
110	case SLAPI_PLUGIN_DB_ARCHIVE2DB_FN:
111	case SLAPI_PLUGIN_DB_DB2ARCHIVE_FN:
112	case SLAPI_PLUGIN_DB_NEXT_SEARCH_ENTRY_FN:
113	case SLAPI_PLUGIN_DB_FREE_RESULT_SET_FN:
114	case SLAPI_PLUGIN_DB_SIZE_FN:
115	case SLAPI_PLUGIN_DB_TEST_FN:
116	case SLAPI_PLUGIN_DB_NO_ACL:
117	case SLAPI_PLUGIN_EXT_OP_FN:
118	case SLAPI_PLUGIN_EXT_OP_OIDLIST:
119	case SLAPI_PLUGIN_PRE_BIND_FN:
120	case SLAPI_PLUGIN_PRE_UNBIND_FN:
121	case SLAPI_PLUGIN_PRE_SEARCH_FN:
122	case SLAPI_PLUGIN_PRE_COMPARE_FN:
123	case SLAPI_PLUGIN_PRE_MODIFY_FN:
124	case SLAPI_PLUGIN_PRE_MODRDN_FN:
125	case SLAPI_PLUGIN_PRE_ADD_FN:
126	case SLAPI_PLUGIN_PRE_DELETE_FN:
127	case SLAPI_PLUGIN_PRE_ABANDON_FN:
128	case SLAPI_PLUGIN_PRE_ENTRY_FN:
129	case SLAPI_PLUGIN_PRE_REFERRAL_FN:
130	case SLAPI_PLUGIN_PRE_RESULT_FN:
131	case SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN:
132	case SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN:
133	case SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN:
134	case SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN:
135	case SLAPI_PLUGIN_BE_PRE_ADD_FN:
136	case SLAPI_PLUGIN_BE_PRE_MODIFY_FN:
137	case SLAPI_PLUGIN_BE_PRE_MODRDN_FN:
138	case SLAPI_PLUGIN_BE_PRE_DELETE_FN:
139	case SLAPI_PLUGIN_POST_BIND_FN:
140	case SLAPI_PLUGIN_POST_UNBIND_FN:
141	case SLAPI_PLUGIN_POST_SEARCH_FN:
142	case SLAPI_PLUGIN_POST_COMPARE_FN:
143	case SLAPI_PLUGIN_POST_MODIFY_FN:
144	case SLAPI_PLUGIN_POST_MODRDN_FN:
145	case SLAPI_PLUGIN_POST_ADD_FN:
146	case SLAPI_PLUGIN_POST_DELETE_FN:
147	case SLAPI_PLUGIN_POST_ABANDON_FN:
148	case SLAPI_PLUGIN_POST_ENTRY_FN:
149	case SLAPI_PLUGIN_POST_REFERRAL_FN:
150	case SLAPI_PLUGIN_POST_RESULT_FN:
151	case SLAPI_PLUGIN_INTERNAL_POST_ADD_FN:
152	case SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN:
153	case SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN:
154	case SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN:
155	case SLAPI_PLUGIN_BE_POST_ADD_FN:
156	case SLAPI_PLUGIN_BE_POST_MODIFY_FN:
157	case SLAPI_PLUGIN_BE_POST_MODRDN_FN:
158	case SLAPI_PLUGIN_BE_POST_DELETE_FN:
159	case SLAPI_PLUGIN_MR_FILTER_CREATE_FN:
160	case SLAPI_PLUGIN_MR_INDEXER_CREATE_FN:
161	case SLAPI_PLUGIN_MR_FILTER_MATCH_FN:
162	case SLAPI_PLUGIN_MR_FILTER_INDEX_FN:
163	case SLAPI_PLUGIN_MR_FILTER_RESET_FN:
164	case SLAPI_PLUGIN_MR_INDEX_FN:
165	case SLAPI_PLUGIN_COMPUTE_EVALUATOR_FN:
166	case SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN:
167	case SLAPI_PLUGIN_ACL_ALLOW_ACCESS:
168	case SLAPI_X_PLUGIN_PRE_GROUP_FN:
169	case SLAPI_X_PLUGIN_POST_GROUP_FN:
170	case SLAPI_PLUGIN_AUDIT_FN:
171	case SLAPI_PLUGIN_INTERNAL_PRE_BIND_FN:
172	case SLAPI_PLUGIN_INTERNAL_PRE_UNBIND_FN:
173	case SLAPI_PLUGIN_INTERNAL_PRE_SEARCH_FN:
174	case SLAPI_PLUGIN_INTERNAL_PRE_COMPARE_FN:
175	case SLAPI_PLUGIN_INTERNAL_PRE_ABANDON_FN:
176	case SLAPI_PLUGIN_INTERNAL_POST_BIND_FN:
177	case SLAPI_PLUGIN_INTERNAL_POST_UNBIND_FN:
178	case SLAPI_PLUGIN_INTERNAL_POST_SEARCH_FN:
179	case SLAPI_PLUGIN_INTERNAL_POST_COMPARE_FN:
180	case SLAPI_PLUGIN_INTERNAL_POST_ABANDON_FN:
181		return PBLOCK_CLASS_FUNCTION_POINTER;
182		break;
183
184	case SLAPI_BACKEND:
185	case SLAPI_CONNECTION:
186	case SLAPI_OPERATION:
187	case SLAPI_OPERATION_PARAMETERS:
188	case SLAPI_OPERATION_TYPE:
189	case SLAPI_OPERATION_AUTHTYPE:
190	case SLAPI_BE_MONITORDN:
191	case SLAPI_BE_TYPE:
192	case SLAPI_REQUESTOR_DN:
193	case SLAPI_CONN_DN:
194	case SLAPI_CONN_CLIENTIP:
195	case SLAPI_CONN_SERVERIP:
196	case SLAPI_CONN_AUTHTYPE:
197	case SLAPI_CONN_AUTHMETHOD:
198	case SLAPI_CONN_CERT:
199	case SLAPI_X_CONN_CLIENTPATH:
200	case SLAPI_X_CONN_SERVERPATH:
201	case SLAPI_X_CONN_SASL_CONTEXT:
202	case SLAPI_X_CONFIG_ARGV:
203	case SLAPI_X_INTOP_FLAGS:
204	case SLAPI_X_INTOP_RESULT_CALLBACK:
205	case SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK:
206	case SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK:
207	case SLAPI_X_INTOP_CALLBACK_DATA:
208	case SLAPI_PLUGIN_MR_OID:
209	case SLAPI_PLUGIN_MR_TYPE:
210	case SLAPI_PLUGIN_MR_VALUE:
211	case SLAPI_PLUGIN_MR_VALUES:
212	case SLAPI_PLUGIN_MR_KEYS:
213	case SLAPI_PLUGIN:
214	case SLAPI_PLUGIN_PRIVATE:
215	case SLAPI_PLUGIN_ARGV:
216	case SLAPI_PLUGIN_OBJECT:
217	case SLAPI_PLUGIN_DESCRIPTION:
218	case SLAPI_PLUGIN_IDENTITY:
219	case SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES:
220	case SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS:
221	case SLAPI_PLUGIN_MR_FILTER_REUSABLE:
222	case SLAPI_PLUGIN_MR_QUERY_OPERATOR:
223	case SLAPI_PLUGIN_MR_USAGE:
224	case SLAPI_OP_LESS:
225	case SLAPI_OP_LESS_OR_EQUAL:
226	case SLAPI_PLUGIN_MR_USAGE_INDEX:
227	case SLAPI_PLUGIN_SYNTAX_FILTER_AVA:
228	case SLAPI_PLUGIN_SYNTAX_FILTER_SUB:
229	case SLAPI_PLUGIN_SYNTAX_VALUES2KEYS:
230	case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA:
231	case SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB:
232	case SLAPI_PLUGIN_SYNTAX_NAMES:
233	case SLAPI_PLUGIN_SYNTAX_OID:
234	case SLAPI_PLUGIN_SYNTAX_FLAGS:
235	case SLAPI_PLUGIN_SYNTAX_COMPARE:
236	case SLAPI_CONFIG_FILENAME:
237	case SLAPI_CONFIG_ARGV:
238	case SLAPI_TARGET_ADDRESS:
239	case SLAPI_TARGET_UNIQUEID:
240	case SLAPI_TARGET_DN:
241	case SLAPI_REQCONTROLS:
242	case SLAPI_ENTRY_PRE_OP:
243	case SLAPI_ENTRY_POST_OP:
244	case SLAPI_RESCONTROLS:
245	case SLAPI_X_OLD_RESCONTROLS:
246	case SLAPI_ADD_RESCONTROL:
247	case SLAPI_CONTROLS_ARG:
248	case SLAPI_ADD_ENTRY:
249	case SLAPI_ADD_EXISTING_DN_ENTRY:
250	case SLAPI_ADD_PARENT_ENTRY:
251	case SLAPI_ADD_PARENT_UNIQUEID:
252	case SLAPI_ADD_EXISTING_UNIQUEID_ENTRY:
253	case SLAPI_BIND_CREDENTIALS:
254	case SLAPI_BIND_SASLMECHANISM:
255	case SLAPI_BIND_RET_SASLCREDS:
256	case SLAPI_COMPARE_TYPE:
257	case SLAPI_COMPARE_VALUE:
258	case SLAPI_MODIFY_MODS:
259	case SLAPI_MODRDN_NEWRDN:
260	case SLAPI_MODRDN_NEWSUPERIOR:
261	case SLAPI_MODRDN_PARENT_ENTRY:
262	case SLAPI_MODRDN_NEWPARENT_ENTRY:
263	case SLAPI_MODRDN_TARGET_ENTRY:
264	case SLAPI_MODRDN_NEWSUPERIOR_ADDRESS:
265	case SLAPI_SEARCH_FILTER:
266	case SLAPI_SEARCH_STRFILTER:
267	case SLAPI_SEARCH_ATTRS:
268	case SLAPI_SEQ_TYPE:
269	case SLAPI_SEQ_ATTRNAME:
270	case SLAPI_SEQ_VAL:
271	case SLAPI_EXT_OP_REQ_OID:
272	case SLAPI_EXT_OP_REQ_VALUE:
273	case SLAPI_EXT_OP_RET_OID:
274	case SLAPI_EXT_OP_RET_VALUE:
275	case SLAPI_MR_FILTER_ENTRY:
276	case SLAPI_MR_FILTER_TYPE:
277	case SLAPI_MR_FILTER_VALUE:
278	case SLAPI_MR_FILTER_OID:
279	case SLAPI_MR_FILTER_DNATTRS:
280	case SLAPI_LDIF2DB_FILE:
281	case SLAPI_PARENT_TXN:
282	case SLAPI_TXN:
283	case SLAPI_SEARCH_RESULT_SET:
284	case SLAPI_SEARCH_RESULT_ENTRY:
285	case SLAPI_SEARCH_REFERRALS:
286	case SLAPI_RESULT_TEXT:
287	case SLAPI_RESULT_MATCHED:
288	case SLAPI_X_GROUP_ENTRY:
289	case SLAPI_X_GROUP_ATTRIBUTE:
290	case SLAPI_X_GROUP_OPERATION_DN:
291	case SLAPI_X_GROUP_TARGET_ENTRY:
292	case SLAPI_X_ADD_STRUCTURAL_CLASS:
293	case SLAPI_PLUGIN_AUDIT_DATA:
294	case SLAPI_IBM_PBLOCK:
295	case SLAPI_PLUGIN_VERSION:
296		return PBLOCK_CLASS_POINTER;
297		break;
298	default:
299		break;
300	}
301
302	return PBLOCK_CLASS_INVALID;
303}
304
305static void
306pblock_lock( Slapi_PBlock *pb )
307{
308	ldap_pvt_thread_mutex_lock( &pb->pb_mutex );
309}
310
311static void
312pblock_unlock( Slapi_PBlock *pb )
313{
314	ldap_pvt_thread_mutex_unlock( &pb->pb_mutex );
315}
316
317static int
318pblock_get_default( Slapi_PBlock *pb, int param, void **value )
319{
320	int i;
321	slapi_pblock_class_t pbClass;
322
323	pbClass = pblock_get_param_class( param );
324	if ( pbClass == PBLOCK_CLASS_INVALID ) {
325		return PBLOCK_ERROR;
326	}
327
328	switch ( pbClass ) {
329	case PBLOCK_CLASS_INTEGER:
330		*((int *)value) = 0;
331		break;
332	case PBLOCK_CLASS_LONG_INTEGER:
333		*((long *)value) = 0L;
334		break;
335	case PBLOCK_CLASS_POINTER:
336	case PBLOCK_CLASS_FUNCTION_POINTER:
337		*value = NULL;
338		break;
339	case PBLOCK_CLASS_INVALID:
340		return PBLOCK_ERROR;
341	}
342
343	for ( i = 0; i < pb->pb_nParams; i++ ) {
344		if ( pb->pb_params[i] == param ) {
345			switch ( pbClass ) {
346			case PBLOCK_CLASS_INTEGER:
347				*((int *)value) = pb->pb_values[i].pv_integer;
348				break;
349			case PBLOCK_CLASS_LONG_INTEGER:
350				*((long *)value) = pb->pb_values[i].pv_long_integer;
351				break;
352			case PBLOCK_CLASS_POINTER:
353				*value = pb->pb_values[i].pv_pointer;
354				break;
355			case PBLOCK_CLASS_FUNCTION_POINTER:
356				*value = pb->pb_values[i].pv_function_pointer;
357				break;
358			default:
359				break;
360			}
361			break;
362	  	}
363	}
364
365	return PBLOCK_SUCCESS;
366}
367
368static char *
369pblock_get_authtype( AuthorizationInformation *authz, int is_tls )
370{
371	char *authType;
372
373	switch ( authz->sai_method ) {
374	case LDAP_AUTH_SASL:
375		authType = SLAPD_AUTH_SASL;
376		break;
377	case LDAP_AUTH_SIMPLE:
378		authType = SLAPD_AUTH_SIMPLE;
379		break;
380	case LDAP_AUTH_NONE:
381		authType = SLAPD_AUTH_NONE;
382		break;
383	default:
384		authType = NULL;
385		break;
386	}
387
388	if ( is_tls && authType == NULL ) {
389		authType = SLAPD_AUTH_SSL;
390	}
391
392	return authType;
393}
394
395static int
396pblock_set_default( Slapi_PBlock *pb, int param, void *value )
397{
398	slapi_pblock_class_t pbClass;
399	int i;
400
401	pbClass = pblock_get_param_class( param );
402	if ( pbClass == PBLOCK_CLASS_INVALID ) {
403		return PBLOCK_ERROR;
404	}
405
406	if ( pb->pb_nParams == PBLOCK_MAX_PARAMS ) {
407		return PBLOCK_ERROR;
408	}
409
410	for ( i = 0; i < pb->pb_nParams; i++ ) {
411		if ( pb->pb_params[i] == param )
412			break;
413	}
414	if ( i >= pb->pb_nParams ) {
415		pb->pb_params[i] = param;
416	  	pb->pb_nParams++;
417	}
418
419	switch ( pbClass ) {
420	case PBLOCK_CLASS_INTEGER:
421		pb->pb_values[i].pv_integer = (*((int *)value));
422		break;
423	case PBLOCK_CLASS_LONG_INTEGER:
424		pb->pb_values[i].pv_long_integer = (*((long *)value));
425		break;
426	case PBLOCK_CLASS_POINTER:
427		pb->pb_values[i].pv_pointer = value;
428		break;
429	case PBLOCK_CLASS_FUNCTION_POINTER:
430		pb->pb_values[i].pv_function_pointer = value;
431		break;
432	default:
433		break;
434	}
435
436	return PBLOCK_SUCCESS;
437}
438
439static int
440pblock_be_call( Slapi_PBlock *pb, int (*bep)(Operation *) )
441{
442	BackendDB *be_orig;
443	Operation *op;
444	int rc;
445
446	PBLOCK_ASSERT_OP( pb, 0 );
447	op = pb->pb_op;
448
449	be_orig = op->o_bd;
450	op->o_bd = select_backend( &op->o_req_ndn, 0 );
451	rc = (*bep)( op );
452	op->o_bd = be_orig;
453
454	return rc;
455}
456
457static int
458pblock_get( Slapi_PBlock *pb, int param, void **value )
459{
460	int rc = PBLOCK_SUCCESS;
461
462	pblock_lock( pb );
463
464	switch ( param ) {
465	case SLAPI_OPERATION:
466		*value = pb->pb_op;
467		break;
468	case SLAPI_OPINITIATED_TIME:
469		PBLOCK_ASSERT_OP( pb, 0 );
470		*((long *)value) = pb->pb_op->o_time;
471		break;
472	case SLAPI_OPERATION_ID:
473		PBLOCK_ASSERT_OP( pb, 0 );
474		*((long *)value) = pb->pb_op->o_opid;
475		break;
476	case SLAPI_OPERATION_TYPE:
477		PBLOCK_ASSERT_OP( pb, 0 );
478		*((ber_tag_t *)value) = pb->pb_op->o_tag;
479		break;
480	case SLAPI_OPERATION_MSGID:
481		PBLOCK_ASSERT_OP( pb, 0 );
482		*((long *)value) = pb->pb_op->o_msgid;
483		break;
484	case SLAPI_X_OPERATION_DELETE_GLUE_PARENT:
485		PBLOCK_ASSERT_OP( pb, 0 );
486		*((int *)value) = pb->pb_op->o_delete_glue_parent;
487		break;
488	case SLAPI_X_OPERATION_NO_SCHEMA_CHECK:
489		PBLOCK_ASSERT_OP( pb, 0 );
490		*((int *)value) = get_no_schema_check( pb->pb_op );
491		break;
492	case SLAPI_X_ADD_STRUCTURAL_CLASS:
493		PBLOCK_ASSERT_OP( pb, 0 );
494
495		if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) {
496			struct berval tmpval = BER_BVNULL;
497
498			rc = mods_structural_class( pb->pb_op->ora_modlist,
499				&tmpval, &pb->pb_rs->sr_text,
500				pb->pb_textbuf, sizeof( pb->pb_textbuf ),
501				pb->pb_op->o_tmpmemctx );
502			*((char **)value) = tmpval.bv_val;
503		} else {
504			rc = PBLOCK_ERROR;
505		}
506		break;
507	case SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE:
508		PBLOCK_ASSERT_OP( pb, 0 );
509		*((int *)value) = pb->pb_op->o_no_subordinate_glue;
510		break;
511	case SLAPI_REQCONTROLS:
512		PBLOCK_ASSERT_OP( pb, 0 );
513		*((LDAPControl ***)value) = pb->pb_op->o_ctrls;
514		break;
515	case SLAPI_REQUESTOR_DN:
516		PBLOCK_ASSERT_OP( pb, 0 );
517		*((char **)value) = pb->pb_op->o_dn.bv_val;
518		break;
519	case SLAPI_MANAGEDSAIT:
520		PBLOCK_ASSERT_OP( pb, 0 );
521		*((int *)value) = get_manageDSAit( pb->pb_op );
522		break;
523	case SLAPI_X_RELAX:
524		PBLOCK_ASSERT_OP( pb, 0 );
525		*((int *)value) = get_relax( pb->pb_op );
526		break;
527	case SLAPI_BACKEND:
528		PBLOCK_ASSERT_OP( pb, 0 );
529		*((BackendDB **)value) = select_backend( &pb->pb_op->o_req_ndn, 0 );
530		break;
531	case SLAPI_BE_TYPE:
532		PBLOCK_ASSERT_OP( pb, 0 );
533		if ( pb->pb_op->o_bd != NULL )
534			*((char **)value) = pb->pb_op->o_bd->bd_info->bi_type;
535		else
536			*value = NULL;
537		break;
538	case SLAPI_CONNECTION:
539		*value = pb->pb_conn;
540		break;
541	case SLAPI_X_CONN_SSF:
542		PBLOCK_ASSERT_OP( pb, 0 );
543		*((slap_ssf_t *)value) = pb->pb_conn->c_ssf;
544		break;
545	case SLAPI_X_CONN_SASL_CONTEXT:
546		PBLOCK_ASSERT_CONN( pb );
547		if ( pb->pb_conn->c_sasl_authctx != NULL )
548			*value = pb->pb_conn->c_sasl_authctx;
549		else
550			*value = pb->pb_conn->c_sasl_sockctx;
551		break;
552	case SLAPI_TARGET_DN:
553		PBLOCK_ASSERT_OP( pb, 0 );
554		*((char **)value) = pb->pb_op->o_req_dn.bv_val;
555		break;
556	case SLAPI_REQUESTOR_ISROOT:
557		*((int *)value) = pblock_be_call( pb, be_isroot );
558		break;
559	case SLAPI_IS_REPLICATED_OPERATION:
560		*((int *)value) = pblock_be_call( pb, be_slurp_update );
561		break;
562	case SLAPI_CONN_AUTHTYPE:
563	case SLAPI_CONN_AUTHMETHOD: /* XXX should return SASL mech */
564		PBLOCK_ASSERT_CONN( pb );
565		*((char **)value) = pblock_get_authtype( &pb->pb_conn->c_authz,
566#ifdef HAVE_TLS
567							 pb->pb_conn->c_is_tls
568#else
569							 0
570#endif
571							 );
572		break;
573	case SLAPI_IS_INTERNAL_OPERATION:
574		*((int *)value) = pb->pb_intop;
575		break;
576	case SLAPI_X_CONN_IS_UDP:
577		PBLOCK_ASSERT_CONN( pb );
578#ifdef LDAP_CONNECTIONLESS
579		*((int *)value) = pb->pb_conn->c_is_udp;
580#else
581		*((int *)value) = 0;
582#endif
583		break;
584	case SLAPI_CONN_ID:
585		PBLOCK_ASSERT_CONN( pb );
586		*((long *)value) = pb->pb_conn->c_connid;
587		break;
588	case SLAPI_CONN_DN:
589		PBLOCK_ASSERT_CONN( pb );
590#if 0
591		/* This would be necessary to keep plugin compat after the fix in ITS#4158 */
592		if ( pb->pb_op->o_tag == LDAP_REQ_BIND && pb->pb_rs->sr_err == LDAP_SUCCESS )
593			*((char **)value) = pb->pb_op->orb_edn.bv_val;
594		else
595#endif
596		*((char **)value) = pb->pb_conn->c_dn.bv_val;
597		break;
598	case SLAPI_CONN_CLIENTIP:
599		PBLOCK_ASSERT_CONN( pb );
600		if ( strncmp( pb->pb_conn->c_peer_name.bv_val, "IP=", 3 ) == 0 )
601			*((char **)value) = &pb->pb_conn->c_peer_name.bv_val[3];
602		else
603			*value = NULL;
604		break;
605	case SLAPI_X_CONN_CLIENTPATH:
606		PBLOCK_ASSERT_CONN( pb );
607		if ( strncmp( pb->pb_conn->c_peer_name.bv_val, "PATH=", 3 ) == 0 )
608			*((char **)value) = &pb->pb_conn->c_peer_name.bv_val[5];
609		else
610			*value = NULL;
611		break;
612	case SLAPI_CONN_SERVERIP:
613		PBLOCK_ASSERT_CONN( pb );
614		if ( strncmp( pb->pb_conn->c_sock_name.bv_val, "IP=", 3 ) == 0 )
615			*((char **)value) = &pb->pb_conn->c_sock_name.bv_val[3];
616		else
617			*value = NULL;
618		break;
619	case SLAPI_X_CONN_SERVERPATH:
620		PBLOCK_ASSERT_CONN( pb );
621		if ( strncmp( pb->pb_conn->c_sock_name.bv_val, "PATH=", 3 ) == 0 )
622			*((char **)value) = &pb->pb_conn->c_sock_name.bv_val[5];
623		else
624			*value = NULL;
625		break;
626	case SLAPI_RESULT_CODE:
627	case SLAPI_PLUGIN_INTOP_RESULT:
628		PBLOCK_ASSERT_OP( pb, 0 );
629		*((int *)value) = pb->pb_rs->sr_err;
630		break;
631        case SLAPI_RESULT_TEXT:
632		PBLOCK_ASSERT_OP( pb, 0 );
633		*((const char **)value) = pb->pb_rs->sr_text;
634		break;
635        case SLAPI_RESULT_MATCHED:
636		PBLOCK_ASSERT_OP( pb, 0 );
637		*((const char **)value) = pb->pb_rs->sr_matched;
638		break;
639	case SLAPI_ADD_ENTRY:
640		PBLOCK_ASSERT_OP( pb, 0 );
641		if ( pb->pb_op->o_tag == LDAP_REQ_ADD )
642			*((Slapi_Entry **)value) = pb->pb_op->ora_e;
643		else
644			*value = NULL;
645		break;
646	case SLAPI_MODIFY_MODS: {
647		LDAPMod **mods = NULL;
648		Modifications *ml = NULL;
649
650		pblock_get_default( pb, param, (void **)&mods );
651		if ( mods == NULL && pb->pb_intop == 0 ) {
652			switch ( pb->pb_op->o_tag ) {
653			case LDAP_REQ_MODIFY:
654				ml = pb->pb_op->orm_modlist;
655				break;
656			case LDAP_REQ_MODRDN:
657				ml = pb->pb_op->orr_modlist;
658				break;
659			default:
660				rc = PBLOCK_ERROR;
661				break;
662			}
663			if ( rc != PBLOCK_ERROR ) {
664				mods = slapi_int_modifications2ldapmods( ml );
665				pblock_set_default( pb, param, (void *)mods );
666			}
667		}
668		*((LDAPMod ***)value) = mods;
669		break;
670	}
671	case SLAPI_MODRDN_NEWRDN:
672		PBLOCK_ASSERT_OP( pb, 0 );
673		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
674			*((char **)value) = pb->pb_op->orr_newrdn.bv_val;
675		else
676			*value = NULL;
677		break;
678	case SLAPI_MODRDN_NEWSUPERIOR:
679		PBLOCK_ASSERT_OP( pb, 0 );
680		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN && pb->pb_op->orr_newSup != NULL )
681			*((char **)value) = pb->pb_op->orr_newSup->bv_val;
682		else
683			*value = NULL;
684		break;
685	case SLAPI_MODRDN_DELOLDRDN:
686		PBLOCK_ASSERT_OP( pb, 0 );
687		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
688			*((int *)value) = pb->pb_op->orr_deleteoldrdn;
689		else
690			*((int *)value) = 0;
691		break;
692	case SLAPI_SEARCH_SCOPE:
693		PBLOCK_ASSERT_OP( pb, 0 );
694		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
695			*((int *)value) = pb->pb_op->ors_scope;
696		else
697			*((int *)value) = 0;
698		break;
699	case SLAPI_SEARCH_DEREF:
700		PBLOCK_ASSERT_OP( pb, 0 );
701		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
702			*((int *)value) = pb->pb_op->ors_deref;
703		else
704			*((int *)value) = 0;
705		break;
706	case SLAPI_SEARCH_SIZELIMIT:
707		PBLOCK_ASSERT_OP( pb, 0 );
708		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
709			*((int *)value) = pb->pb_op->ors_slimit;
710		else
711			*((int *)value) = 0;
712		break;
713	case SLAPI_SEARCH_TIMELIMIT:
714		PBLOCK_ASSERT_OP( pb, 0 );
715		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
716			*((int *)value) = pb->pb_op->ors_tlimit;
717		else
718			*((int *)value) = 0;
719		break;
720	case SLAPI_SEARCH_FILTER:
721		PBLOCK_ASSERT_OP( pb, 0 );
722		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
723			*((Slapi_Filter **)value) = pb->pb_op->ors_filter;
724		else
725			*((Slapi_Filter **)value) = NULL;
726		break;
727	case SLAPI_SEARCH_STRFILTER:
728		PBLOCK_ASSERT_OP( pb, 0 );
729		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
730			*((char **)value) = pb->pb_op->ors_filterstr.bv_val;
731		else
732			*((char **)value) = NULL;
733		break;
734	case SLAPI_SEARCH_ATTRS: {
735		char **attrs = NULL;
736
737		PBLOCK_ASSERT_OP( pb, 0 );
738		if ( pb->pb_op->o_tag != LDAP_REQ_SEARCH ) {
739			rc = PBLOCK_ERROR;
740			break;
741		}
742		pblock_get_default( pb, param, (void **)&attrs );
743		if ( attrs == NULL && pb->pb_intop == 0 ) {
744			attrs = anlist2charray_x( pb->pb_op->ors_attrs, 0, pb->pb_op->o_tmpmemctx );
745			pblock_set_default( pb, param, (void *)attrs );
746		}
747		*((char ***)value) = attrs;
748		break;
749	}
750	case SLAPI_SEARCH_ATTRSONLY:
751		PBLOCK_ASSERT_OP( pb, 0 );
752		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
753			*((int *)value) = pb->pb_op->ors_attrsonly;
754		else
755			*((int *)value) = 0;
756		break;
757	case SLAPI_SEARCH_RESULT_ENTRY:
758		PBLOCK_ASSERT_OP( pb, 0 );
759		*((Slapi_Entry **)value) = pb->pb_rs->sr_entry;
760		break;
761	case SLAPI_BIND_RET_SASLCREDS:
762		PBLOCK_ASSERT_OP( pb, 0 );
763		*((struct berval **)value) = pb->pb_rs->sr_sasldata;
764		break;
765	case SLAPI_EXT_OP_REQ_OID:
766		*((const char **)value) = pb->pb_op->ore_reqoid.bv_val;
767		break;
768	case SLAPI_EXT_OP_REQ_VALUE:
769		*((struct berval **)value) = pb->pb_op->ore_reqdata;
770		break;
771	case SLAPI_EXT_OP_RET_OID:
772		PBLOCK_ASSERT_OP( pb, 0 );
773		*((const char **)value) = pb->pb_rs->sr_rspoid;
774		break;
775	case SLAPI_EXT_OP_RET_VALUE:
776		PBLOCK_ASSERT_OP( pb, 0 );
777		*((struct berval **)value) = pb->pb_rs->sr_rspdata;
778		break;
779	case SLAPI_BIND_METHOD:
780		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
781			*((int *)value) = pb->pb_op->orb_method;
782		else
783			*((int *)value) = 0;
784		break;
785	case SLAPI_BIND_CREDENTIALS:
786		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
787			*((struct berval **)value) = &pb->pb_op->orb_cred;
788		else
789			*value = NULL;
790		break;
791	case SLAPI_COMPARE_TYPE:
792		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
793			*((char **)value) = pb->pb_op->orc_ava->aa_desc->ad_cname.bv_val;
794		else
795			*value = NULL;
796		break;
797	case SLAPI_COMPARE_VALUE:
798		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
799			*((struct berval **)value) = &pb->pb_op->orc_ava->aa_value;
800		else
801			*value = NULL;
802		break;
803	case SLAPI_ABANDON_MSGID:
804		if ( pb->pb_op->o_tag == LDAP_REQ_ABANDON )
805			*((int *)value) = pb->pb_op->orn_msgid;
806		else
807			*((int *)value) = 0;
808		break;
809	default:
810		rc = pblock_get_default( pb, param, value );
811		break;
812	}
813
814	pblock_unlock( pb );
815
816	return rc;
817}
818
819static int
820pblock_add_control( Slapi_PBlock *pb, LDAPControl *control )
821{
822	LDAPControl **controls = NULL;
823	size_t i;
824
825	pblock_get_default( pb, SLAPI_RESCONTROLS, (void **)&controls );
826
827	if ( controls != NULL ) {
828		for ( i = 0; controls[i] != NULL; i++ )
829			;
830	} else {
831		i = 0;
832	}
833
834	controls = (LDAPControl **)slapi_ch_realloc( (char *)controls,
835		( i + 2 ) * sizeof(LDAPControl *));
836	controls[i++] = slapi_dup_control( control );
837	controls[i] = NULL;
838
839	return pblock_set_default( pb, SLAPI_RESCONTROLS, (void *)controls );
840}
841
842static int
843pblock_set_dn( void *value, struct berval *dn, struct berval *ndn, void *memctx )
844{
845	struct berval bv;
846
847	if ( !BER_BVISNULL( dn )) {
848		slap_sl_free( dn->bv_val, memctx );
849		BER_BVZERO( dn );
850	}
851	if ( !BER_BVISNULL( ndn )) {
852		slap_sl_free( ndn->bv_val, memctx );
853		BER_BVZERO( ndn );
854	}
855
856	bv.bv_val = (char *)value;
857	bv.bv_len = ( value != NULL ) ? strlen( bv.bv_val ) : 0;
858
859	return dnPrettyNormal( NULL, &bv, dn, ndn, memctx );
860}
861
862static int
863pblock_set( Slapi_PBlock *pb, int param, void *value )
864{
865	int rc = PBLOCK_SUCCESS;
866
867	pblock_lock( pb );
868
869	switch ( param ) {
870	case SLAPI_OPERATION:
871		pb->pb_op = (Operation *)value;
872		break;
873	case SLAPI_OPINITIATED_TIME:
874		PBLOCK_ASSERT_OP( pb, 0 );
875		pb->pb_op->o_time = *((long *)value);
876		break;
877	case SLAPI_OPERATION_ID:
878		PBLOCK_ASSERT_OP( pb, 0 );
879		pb->pb_op->o_opid = *((long *)value);
880		break;
881	case SLAPI_OPERATION_TYPE:
882		PBLOCK_ASSERT_OP( pb, 0 );
883		pb->pb_op->o_tag = *((ber_tag_t *)value);
884		break;
885	case SLAPI_OPERATION_MSGID:
886		PBLOCK_ASSERT_OP( pb, 0 );
887		pb->pb_op->o_msgid = *((long *)value);
888		break;
889	case SLAPI_X_OPERATION_DELETE_GLUE_PARENT:
890		PBLOCK_ASSERT_OP( pb, 0 );
891		pb->pb_op->o_delete_glue_parent = *((int *)value);
892		break;
893	case SLAPI_X_OPERATION_NO_SCHEMA_CHECK:
894		PBLOCK_ASSERT_OP( pb, 0 );
895		pb->pb_op->o_no_schema_check = *((int *)value);
896		break;
897	case SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE:
898		PBLOCK_ASSERT_OP( pb, 0 );
899		pb->pb_op->o_no_subordinate_glue = *((int *)value);
900		break;
901	case SLAPI_REQCONTROLS:
902		PBLOCK_ASSERT_OP( pb, 0 );
903		pb->pb_op->o_ctrls = (LDAPControl **)value;
904		break;
905	case SLAPI_RESCONTROLS: {
906		LDAPControl **ctrls = NULL;
907
908		pblock_get_default( pb, param, (void **)&ctrls );
909		if ( ctrls != NULL ) {
910			/* free old ones first */
911			ldap_controls_free( ctrls );
912		}
913		rc = pblock_set_default( pb, param, value );
914		break;
915	}
916	case SLAPI_ADD_RESCONTROL:
917		PBLOCK_ASSERT_OP( pb, 0 );
918		rc = pblock_add_control( pb, (LDAPControl *)value );
919		break;
920	case SLAPI_REQUESTOR_DN:
921		PBLOCK_ASSERT_OP( pb, 0 );
922		rc = pblock_set_dn( value, &pb->pb_op->o_dn, &pb->pb_op->o_ndn, pb->pb_op->o_tmpmemctx );
923		break;
924	case SLAPI_MANAGEDSAIT:
925		PBLOCK_ASSERT_OP( pb, 0 );
926		pb->pb_op->o_managedsait = *((int *)value);
927		break;
928	case SLAPI_X_RELAX:
929		PBLOCK_ASSERT_OP( pb, 0 );
930		pb->pb_op->o_relax = *((int *)value);
931		break;
932	case SLAPI_BACKEND:
933		PBLOCK_ASSERT_OP( pb, 0 );
934		pb->pb_op->o_bd = (BackendDB *)value;
935		break;
936	case SLAPI_CONNECTION:
937		pb->pb_conn = (Connection *)value;
938		break;
939	case SLAPI_X_CONN_SSF:
940		PBLOCK_ASSERT_CONN( pb );
941		PBLOCK_LOCK_CONN( pb );
942		pb->pb_conn->c_ssf = (slap_ssf_t)(long)value;
943		PBLOCK_UNLOCK_CONN( pb );
944		break;
945	case SLAPI_X_CONN_SASL_CONTEXT:
946		PBLOCK_ASSERT_CONN( pb );
947		PBLOCK_LOCK_CONN( pb );
948		pb->pb_conn->c_sasl_authctx = value;
949		PBLOCK_UNLOCK_CONN( pb );
950		break;
951	case SLAPI_TARGET_DN:
952		PBLOCK_ASSERT_OP( pb, 0 );
953		rc = pblock_set_dn( value, &pb->pb_op->o_req_dn, &pb->pb_op->o_req_ndn, pb->pb_op->o_tmpmemctx );
954		break;
955	case SLAPI_CONN_ID:
956		PBLOCK_ASSERT_CONN( pb );
957		PBLOCK_LOCK_CONN( pb );
958		pb->pb_conn->c_connid = *((long *)value);
959		PBLOCK_UNLOCK_CONN( pb );
960		break;
961	case SLAPI_CONN_DN:
962		PBLOCK_ASSERT_CONN( pb );
963		PBLOCK_LOCK_CONN( pb );
964		rc = pblock_set_dn( value, &pb->pb_conn->c_dn, &pb->pb_conn->c_ndn, NULL );
965		PBLOCK_UNLOCK_CONN( pb );
966		break;
967	case SLAPI_RESULT_CODE:
968	case SLAPI_PLUGIN_INTOP_RESULT:
969		PBLOCK_ASSERT_OP( pb, 0 );
970		pb->pb_rs->sr_err = *((int *)value);
971		break;
972	case SLAPI_RESULT_TEXT:
973		PBLOCK_ASSERT_OP( pb, 0 );
974		snprintf( pb->pb_textbuf, sizeof( pb->pb_textbuf ), "%s", (char *)value );
975		pb->pb_rs->sr_text = pb->pb_textbuf;
976		break;
977	case SLAPI_RESULT_MATCHED:
978		PBLOCK_ASSERT_OP( pb, 0 );
979		pb->pb_rs->sr_matched = (char *)value; /* XXX should dup? */
980		break;
981	case SLAPI_ADD_ENTRY:
982		PBLOCK_ASSERT_OP( pb, 0 );
983		if ( pb->pb_op->o_tag == LDAP_REQ_ADD )
984			pb->pb_op->ora_e = (Slapi_Entry *)value;
985		else
986			rc = PBLOCK_ERROR;
987		break;
988	case SLAPI_MODIFY_MODS: {
989		Modifications **mlp;
990		Modifications *newmods;
991
992		PBLOCK_ASSERT_OP( pb, 0 );
993		rc = pblock_set_default( pb, param, value );
994		if ( rc != PBLOCK_SUCCESS ) {
995			break;
996		}
997
998		if ( pb->pb_op->o_tag == LDAP_REQ_MODIFY ) {
999			mlp = &pb->pb_op->orm_modlist;
1000		} else if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) {
1001			mlp = &pb->pb_op->ora_modlist;
1002		} else if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) {
1003			mlp = &pb->pb_op->orr_modlist;
1004		} else {
1005			break;
1006		}
1007
1008		newmods = slapi_int_ldapmods2modifications( pb->pb_op, (LDAPMod **)value );
1009		if ( newmods != NULL ) {
1010			slap_mods_free( *mlp, 1 );
1011			*mlp = newmods;
1012		}
1013		break;
1014	}
1015	case SLAPI_MODRDN_NEWRDN:
1016		PBLOCK_ASSERT_OP( pb, 0 );
1017		PBLOCK_VALIDATE_IS_INTOP( pb );
1018		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) {
1019			rc = pblock_set_dn( value, &pb->pb_op->orr_newrdn, &pb->pb_op->orr_nnewrdn, pb->pb_op->o_tmpmemctx );
1020			if ( rc == LDAP_SUCCESS )
1021				rc = rdn_validate( &pb->pb_op->orr_nnewrdn );
1022		} else {
1023			rc = PBLOCK_ERROR;
1024		}
1025		break;
1026	case SLAPI_MODRDN_NEWSUPERIOR:
1027		PBLOCK_ASSERT_OP( pb, 0 );
1028		PBLOCK_VALIDATE_IS_INTOP( pb );
1029		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) {
1030			if ( value == NULL ) {
1031				if ( pb->pb_op->orr_newSup != NULL ) {
1032					pb->pb_op->o_tmpfree( pb->pb_op->orr_newSup, pb->pb_op->o_tmpmemctx );
1033					BER_BVZERO( pb->pb_op->orr_newSup );
1034					pb->pb_op->orr_newSup = NULL;
1035				}
1036				if ( pb->pb_op->orr_newSup != NULL ) {
1037					pb->pb_op->o_tmpfree( pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx );
1038					BER_BVZERO( pb->pb_op->orr_nnewSup );
1039					pb->pb_op->orr_nnewSup = NULL;
1040				}
1041			} else {
1042				if ( pb->pb_op->orr_newSup == NULL ) {
1043					pb->pb_op->orr_newSup = (struct berval *)pb->pb_op->o_tmpalloc(
1044						sizeof(struct berval), pb->pb_op->o_tmpmemctx );
1045					BER_BVZERO( pb->pb_op->orr_newSup );
1046				}
1047				if ( pb->pb_op->orr_nnewSup == NULL ) {
1048					pb->pb_op->orr_nnewSup = (struct berval *)pb->pb_op->o_tmpalloc(
1049						sizeof(struct berval), pb->pb_op->o_tmpmemctx );
1050					BER_BVZERO( pb->pb_op->orr_nnewSup );
1051				}
1052				rc = pblock_set_dn( value, pb->pb_op->orr_newSup, pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx );
1053			}
1054		} else {
1055			rc = PBLOCK_ERROR;
1056		}
1057		break;
1058	case SLAPI_MODRDN_DELOLDRDN:
1059		PBLOCK_ASSERT_OP( pb, 0 );
1060		PBLOCK_VALIDATE_IS_INTOP( pb );
1061		if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN )
1062			pb->pb_op->orr_deleteoldrdn = *((int *)value);
1063		else
1064			rc = PBLOCK_ERROR;
1065		break;
1066	case SLAPI_SEARCH_SCOPE: {
1067		int scope = *((int *)value);
1068
1069		PBLOCK_ASSERT_OP( pb, 0 );
1070		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) {
1071			switch ( *((int *)value) ) {
1072			case LDAP_SCOPE_BASE:
1073			case LDAP_SCOPE_ONELEVEL:
1074			case LDAP_SCOPE_SUBTREE:
1075			case LDAP_SCOPE_SUBORDINATE:
1076				pb->pb_op->ors_scope = scope;
1077				break;
1078			default:
1079				rc = PBLOCK_ERROR;
1080				break;
1081			}
1082		} else {
1083			rc = PBLOCK_ERROR;
1084		}
1085		break;
1086	}
1087	case SLAPI_SEARCH_DEREF:
1088		PBLOCK_ASSERT_OP( pb, 0 );
1089		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
1090			pb->pb_op->ors_deref = *((int *)value);
1091		else
1092			rc = PBLOCK_ERROR;
1093		break;
1094	case SLAPI_SEARCH_SIZELIMIT:
1095		PBLOCK_ASSERT_OP( pb, 0 );
1096		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
1097			pb->pb_op->ors_slimit = *((int *)value);
1098		else
1099			rc = PBLOCK_ERROR;
1100		break;
1101	case SLAPI_SEARCH_TIMELIMIT:
1102		PBLOCK_ASSERT_OP( pb, 0 );
1103		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
1104			pb->pb_op->ors_tlimit = *((int *)value);
1105		else
1106			rc = PBLOCK_ERROR;
1107		break;
1108	case SLAPI_SEARCH_FILTER:
1109		PBLOCK_ASSERT_OP( pb, 0 );
1110		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
1111			pb->pb_op->ors_filter = (Slapi_Filter *)value;
1112		else
1113			rc = PBLOCK_ERROR;
1114		break;
1115	case SLAPI_SEARCH_STRFILTER:
1116		PBLOCK_ASSERT_OP( pb, 0 );
1117		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) {
1118			pb->pb_op->ors_filterstr.bv_val = (char *)value;
1119			pb->pb_op->ors_filterstr.bv_len = strlen((char *)value);
1120		} else {
1121			rc = PBLOCK_ERROR;
1122		}
1123		break;
1124	case SLAPI_SEARCH_ATTRS: {
1125		AttributeName *an = NULL;
1126		size_t i = 0, j = 0;
1127		char **attrs = (char **)value;
1128
1129		PBLOCK_ASSERT_OP( pb, 0 );
1130		PBLOCK_VALIDATE_IS_INTOP( pb );
1131
1132		if ( pb->pb_op->o_tag != LDAP_REQ_SEARCH ) {
1133			rc = PBLOCK_ERROR;
1134			break;
1135		}
1136		/* also set mapped attrs */
1137		rc = pblock_set_default( pb, param, value );
1138		if ( rc != PBLOCK_SUCCESS ) {
1139			break;
1140		}
1141		if ( pb->pb_op->ors_attrs != NULL ) {
1142			pb->pb_op->o_tmpfree( pb->pb_op->ors_attrs, pb->pb_op->o_tmpmemctx );
1143			pb->pb_op->ors_attrs = NULL;
1144		}
1145		if ( attrs != NULL ) {
1146			for ( i = 0; attrs[i] != NULL; i++ )
1147				;
1148		}
1149		if ( i ) {
1150			an = (AttributeName *)pb->pb_op->o_tmpcalloc( i + 1,
1151				sizeof(AttributeName), pb->pb_op->o_tmpmemctx );
1152			for ( i = 0; attrs[i] != NULL; i++ ) {
1153				an[j].an_desc = NULL;
1154				an[j].an_oc = NULL;
1155				an[j].an_flags = 0;
1156				an[j].an_name.bv_val = attrs[i];
1157				an[j].an_name.bv_len = strlen( attrs[i] );
1158				if ( slap_bv2ad( &an[j].an_name, &an[j].an_desc, &pb->pb_rs->sr_text ) == LDAP_SUCCESS ) {
1159					j++;
1160				}
1161			}
1162			an[j].an_name.bv_val = NULL;
1163			an[j].an_name.bv_len = 0;
1164		}
1165		pb->pb_op->ors_attrs = an;
1166		break;
1167	}
1168	case SLAPI_SEARCH_ATTRSONLY:
1169		PBLOCK_ASSERT_OP( pb, 0 );
1170		PBLOCK_VALIDATE_IS_INTOP( pb );
1171
1172		if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH )
1173			pb->pb_op->ors_attrsonly = *((int *)value);
1174		else
1175			rc = PBLOCK_ERROR;
1176		break;
1177	case SLAPI_SEARCH_RESULT_ENTRY:
1178		PBLOCK_ASSERT_OP( pb, 0 );
1179		rs_replace_entry( pb->pb_op, pb->pb_rs, NULL, (Slapi_Entry *)value );
1180		/* TODO: Should REP_ENTRY_MODIFIABLE be set? */
1181		pb->pb_rs->sr_flags |= REP_ENTRY_MUSTBEFREED;
1182		break;
1183	case SLAPI_BIND_RET_SASLCREDS:
1184		PBLOCK_ASSERT_OP( pb, 0 );
1185		pb->pb_rs->sr_sasldata = (struct berval *)value;
1186		break;
1187	case SLAPI_EXT_OP_REQ_OID:
1188		PBLOCK_ASSERT_OP( pb, 0 );
1189		PBLOCK_VALIDATE_IS_INTOP( pb );
1190
1191		if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED ) {
1192			pb->pb_op->ore_reqoid.bv_val = (char *)value;
1193			pb->pb_op->ore_reqoid.bv_len = strlen((char *)value);
1194		} else {
1195			rc = PBLOCK_ERROR;
1196		}
1197		break;
1198	case SLAPI_EXT_OP_REQ_VALUE:
1199		PBLOCK_ASSERT_OP( pb, 0 );
1200		PBLOCK_VALIDATE_IS_INTOP( pb );
1201
1202		if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED )
1203			pb->pb_op->ore_reqdata = (struct berval *)value;
1204		else
1205			rc = PBLOCK_ERROR;
1206		break;
1207	case SLAPI_EXT_OP_RET_OID:
1208		PBLOCK_ASSERT_OP( pb, 0 );
1209		pb->pb_rs->sr_rspoid = (char *)value;
1210		break;
1211	case SLAPI_EXT_OP_RET_VALUE:
1212		PBLOCK_ASSERT_OP( pb, 0 );
1213		pb->pb_rs->sr_rspdata = (struct berval *)value;
1214		break;
1215	case SLAPI_BIND_METHOD:
1216		PBLOCK_ASSERT_OP( pb, 0 );
1217		PBLOCK_VALIDATE_IS_INTOP( pb );
1218
1219		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
1220			pb->pb_op->orb_method = *((int *)value);
1221		else
1222			rc = PBLOCK_ERROR;
1223		break;
1224	case SLAPI_BIND_CREDENTIALS:
1225		PBLOCK_ASSERT_OP( pb, 0 );
1226		PBLOCK_VALIDATE_IS_INTOP( pb );
1227
1228		if ( pb->pb_op->o_tag == LDAP_REQ_BIND )
1229			pb->pb_op->orb_cred = *((struct berval *)value);
1230		else
1231			rc = PBLOCK_ERROR;
1232		break;
1233	case SLAPI_COMPARE_TYPE:
1234		PBLOCK_ASSERT_OP( pb, 0 );
1235		PBLOCK_VALIDATE_IS_INTOP( pb );
1236
1237		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE ) {
1238			const char *text;
1239
1240			pb->pb_op->orc_ava->aa_desc = NULL;
1241			rc = slap_str2ad( (char *)value, &pb->pb_op->orc_ava->aa_desc, &text );
1242		} else {
1243			rc = PBLOCK_ERROR;
1244		}
1245		break;
1246	case SLAPI_COMPARE_VALUE:
1247		PBLOCK_ASSERT_OP( pb, 0 );
1248		PBLOCK_VALIDATE_IS_INTOP( pb );
1249
1250		if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE )
1251			pb->pb_op->orc_ava->aa_value = *((struct berval *)value);
1252		else
1253			rc = PBLOCK_ERROR;
1254		break;
1255	case SLAPI_ABANDON_MSGID:
1256		PBLOCK_ASSERT_OP( pb, 0 );
1257		PBLOCK_VALIDATE_IS_INTOP( pb );
1258
1259		if ( pb->pb_op->o_tag == LDAP_REQ_ABANDON)
1260			pb->pb_op->orn_msgid = *((int *)value);
1261		else
1262			rc = PBLOCK_ERROR;
1263		break;
1264	case SLAPI_REQUESTOR_ISROOT:
1265	case SLAPI_IS_REPLICATED_OPERATION:
1266	case SLAPI_CONN_AUTHTYPE:
1267	case SLAPI_CONN_AUTHMETHOD:
1268	case SLAPI_IS_INTERNAL_OPERATION:
1269	case SLAPI_X_CONN_IS_UDP:
1270	case SLAPI_CONN_CLIENTIP:
1271	case SLAPI_X_CONN_CLIENTPATH:
1272	case SLAPI_CONN_SERVERIP:
1273	case SLAPI_X_CONN_SERVERPATH:
1274	case SLAPI_X_ADD_STRUCTURAL_CLASS:
1275		/* These parameters cannot be set */
1276		rc = PBLOCK_ERROR;
1277		break;
1278	default:
1279		rc = pblock_set_default( pb, param, value );
1280		break;
1281	}
1282
1283	pblock_unlock( pb );
1284
1285	return rc;
1286}
1287
1288static void
1289pblock_clear( Slapi_PBlock *pb )
1290{
1291	pb->pb_nParams = 1;
1292}
1293
1294static int
1295pblock_delete_param( Slapi_PBlock *p, int param )
1296{
1297	int i;
1298
1299	pblock_lock(p);
1300
1301	for ( i = 0; i < p->pb_nParams; i++ ) {
1302		if ( p->pb_params[i] == param ) {
1303			break;
1304		}
1305	}
1306
1307	if (i >= p->pb_nParams ) {
1308		pblock_unlock( p );
1309		return PBLOCK_ERROR;
1310	}
1311
1312	/* move last parameter to index of deleted parameter */
1313	if ( p->pb_nParams > 1 ) {
1314		p->pb_params[i] = p->pb_params[p->pb_nParams - 1];
1315		p->pb_values[i] = p->pb_values[p->pb_nParams - 1];
1316	}
1317	p->pb_nParams--;
1318
1319	pblock_unlock( p );
1320
1321	return PBLOCK_SUCCESS;
1322}
1323
1324Slapi_PBlock *
1325slapi_pblock_new(void)
1326{
1327	Slapi_PBlock *pb;
1328
1329	pb = (Slapi_PBlock *) ch_calloc( 1, sizeof(Slapi_PBlock) );
1330	if ( pb != NULL ) {
1331		ldap_pvt_thread_mutex_init( &pb->pb_mutex );
1332
1333		pb->pb_params[0] = SLAPI_IBM_PBLOCK;
1334		pb->pb_values[0].pv_pointer = NULL;
1335		pb->pb_nParams = 1;
1336		pb->pb_conn = NULL;
1337		pb->pb_op = NULL;
1338		pb->pb_rs = NULL;
1339		pb->pb_intop = 0;
1340	}
1341	return pb;
1342}
1343
1344static void
1345pblock_destroy( Slapi_PBlock *pb )
1346{
1347	LDAPControl **controls = NULL;
1348	LDAPMod **mods = NULL;
1349	char **attrs = NULL;
1350
1351	assert( pb != NULL );
1352
1353	pblock_get_default( pb, SLAPI_RESCONTROLS, (void **)&controls );
1354	if ( controls != NULL ) {
1355		ldap_controls_free( controls );
1356	}
1357
1358	if ( pb->pb_intop ) {
1359		slapi_int_connection_done_pb( pb );
1360	} else {
1361		pblock_get_default( pb, SLAPI_MODIFY_MODS, (void **)&mods );
1362		ldap_mods_free( mods, 1 );
1363
1364		pblock_get_default( pb, SLAPI_SEARCH_ATTRS, (void **)&attrs );
1365		if ( attrs != NULL )
1366			pb->pb_op->o_tmpfree( attrs, pb->pb_op->o_tmpmemctx );
1367	}
1368
1369	ldap_pvt_thread_mutex_destroy( &pb->pb_mutex );
1370	slapi_ch_free( (void **)&pb );
1371}
1372
1373void
1374slapi_pblock_destroy( Slapi_PBlock *pb )
1375{
1376	if ( pb != NULL ) {
1377		pblock_destroy( pb );
1378	}
1379}
1380
1381int
1382slapi_pblock_get( Slapi_PBlock *pb, int arg, void *value )
1383{
1384	return pblock_get( pb, arg, (void **)value );
1385}
1386
1387int
1388slapi_pblock_set( Slapi_PBlock *pb, int arg, void *value )
1389{
1390	return pblock_set( pb, arg, value );
1391}
1392
1393void
1394slapi_pblock_clear( Slapi_PBlock *pb )
1395{
1396	pblock_clear( pb );
1397}
1398
1399int
1400slapi_pblock_delete_param( Slapi_PBlock *p, int param )
1401{
1402	return pblock_delete_param( p, param );
1403}
1404
1405/*
1406 * OpenLDAP extension
1407 */
1408int
1409slapi_int_pblock_get_first( Backend *be, Slapi_PBlock **pb )
1410{
1411	assert( pb != NULL );
1412	*pb = SLAPI_BACKEND_PBLOCK( be );
1413	return (*pb == NULL ? LDAP_OTHER : LDAP_SUCCESS);
1414}
1415
1416/*
1417 * OpenLDAP extension
1418 */
1419int
1420slapi_int_pblock_get_next( Slapi_PBlock **pb )
1421{
1422	assert( pb != NULL );
1423	return slapi_pblock_get( *pb, SLAPI_IBM_PBLOCK, pb );
1424}
1425
1426#endif /* LDAP_SLAPI */
1427