1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2021 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 
16 #include "portable.h"
17 
18 #include <stdio.h>
19 
20 #include <ac/string.h>
21 #include <ac/socket.h>
22 
23 #include "slap.h"
24 #include "ldif.h"
25 #include "lutil.h"
26 
27 #include "../../libraries/liblber/lber-int.h"
28 
29 static SLAP_CTRL_PARSE_FN parseAssert;
30 static SLAP_CTRL_PARSE_FN parseDomainScope;
31 static SLAP_CTRL_PARSE_FN parseDontUseCopy;
32 static SLAP_CTRL_PARSE_FN parseManageDSAit;
33 static SLAP_CTRL_PARSE_FN parseNoOp;
34 static SLAP_CTRL_PARSE_FN parsePagedResults;
35 static SLAP_CTRL_PARSE_FN parsePermissiveModify;
36 static SLAP_CTRL_PARSE_FN parsePreRead, parsePostRead;
37 static SLAP_CTRL_PARSE_FN parseProxyAuthz;
38 static SLAP_CTRL_PARSE_FN parseRelax;
39 static SLAP_CTRL_PARSE_FN parseSearchOptions;
40 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
41 static SLAP_CTRL_PARSE_FN parseSortedResults;
42 #endif
43 static SLAP_CTRL_PARSE_FN parseSubentries;
44 #ifdef SLAP_CONTROL_X_TREE_DELETE
45 static SLAP_CTRL_PARSE_FN parseTreeDelete;
46 #endif
47 static SLAP_CTRL_PARSE_FN parseValuesReturnFilter;
48 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
49 static SLAP_CTRL_PARSE_FN parseSessionTracking;
50 #endif
51 #ifdef SLAP_CONTROL_X_WHATFAILED
52 static SLAP_CTRL_PARSE_FN parseWhatFailed;
53 #endif
54 #ifdef SLAP_CONTROL_X_LAZY_COMMIT
55 static SLAP_CTRL_PARSE_FN parseLazyCommit;
56 #endif
57 
58 #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */
59 
60 const struct berval slap_pre_read_bv = BER_BVC(LDAP_CONTROL_PRE_READ);
61 const struct berval slap_post_read_bv = BER_BVC(LDAP_CONTROL_POST_READ);
62 
63 struct slap_control_ids slap_cids;
64 
65 struct slap_control {
66 	/* Control OID */
67 	char *sc_oid;
68 
69 	/* The controlID for this control */
70 	int sc_cid;
71 
72 	/* Operations supported by control */
73 	slap_mask_t sc_mask;
74 
75 	/* Extended operations supported by control */
76 	char **sc_extendedops;		/* input */
77 	BerVarray sc_extendedopsbv;	/* run-time use */
78 
79 	/* Control parsing callback */
80 	SLAP_CTRL_PARSE_FN *sc_parse;
81 
82 	LDAP_SLIST_ENTRY(slap_control) sc_next;
83 };
84 
85 static LDAP_SLIST_HEAD(ControlsList, slap_control) controls_list
86 	= LDAP_SLIST_HEAD_INITIALIZER(&controls_list);
87 
88 /*
89  * all known request control OIDs should be added to this list
90  */
91 /*
92  * NOTE: initialize num_known_controls to 1 so that cid = 0 always
93  * addresses an undefined control; this allows to safely test for
94  * well known controls even if they are not registered, e.g. if
95  * they get moved to modules.  An example is sc_LDAPsync, which
96  * is implemented in the syncprov overlay and thus, if configured
97  * as dynamic module, may not be registered.  One side effect is that
98  * slap_known_controls[0] == NULL, so it should always be used
99  * starting from 1.
100  * FIXME: should we define the "undefined control" oid?
101  */
102 char *slap_known_controls[SLAP_MAX_CIDS+1];
103 static int num_known_controls = 1;
104 
105 static char *proxy_authz_extops[] = {
106 	LDAP_EXOP_MODIFY_PASSWD,
107 	LDAP_EXOP_WHO_AM_I,
108 	LDAP_EXOP_REFRESH,
109 	NULL
110 };
111 
112 static char *manageDSAit_extops[] = {
113 	LDAP_EXOP_REFRESH,
114 	NULL
115 };
116 
117 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
118 static char *session_tracking_extops[] = {
119 	LDAP_EXOP_MODIFY_PASSWD,
120 	LDAP_EXOP_WHO_AM_I,
121 	LDAP_EXOP_REFRESH,
122 	NULL
123 };
124 #endif
125 
126 static struct slap_control control_defs[] = {
127 	{  LDAP_CONTROL_ASSERT,
128  		(int)offsetof(struct slap_control_ids, sc_assert),
129 		SLAP_CTRL_UPDATE|SLAP_CTRL_COMPARE|SLAP_CTRL_SEARCH,
130 		NULL, NULL,
131 		parseAssert, LDAP_SLIST_ENTRY_INITIALIZER(next) },
132 	{ LDAP_CONTROL_PRE_READ,
133  		(int)offsetof(struct slap_control_ids, sc_preRead),
134 		SLAP_CTRL_DELETE|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME,
135 		NULL, NULL,
136 		parsePreRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
137 	{ LDAP_CONTROL_POST_READ,
138  		(int)offsetof(struct slap_control_ids, sc_postRead),
139 		SLAP_CTRL_ADD|SLAP_CTRL_MODIFY|SLAP_CTRL_RENAME,
140 		NULL, NULL,
141 		parsePostRead, LDAP_SLIST_ENTRY_INITIALIZER(next) },
142  	{ LDAP_CONTROL_VALUESRETURNFILTER,
143  		(int)offsetof(struct slap_control_ids, sc_valuesReturnFilter),
144  		SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH,
145 		NULL, NULL,
146 		parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) },
147 	{ LDAP_CONTROL_PAGEDRESULTS,
148  		(int)offsetof(struct slap_control_ids, sc_pagedResults),
149 		SLAP_CTRL_SEARCH,
150 		NULL, NULL,
151 		parsePagedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
152 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
153 	{ LDAP_CONTROL_SORTREQUEST,
154  		(int)offsetof(struct slap_control_ids, sc_sortedResults),
155 		SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
156 		NULL, NULL,
157 		parseSortedResults, LDAP_SLIST_ENTRY_INITIALIZER(next) },
158 #endif
159 	{ LDAP_CONTROL_X_DOMAIN_SCOPE,
160  		(int)offsetof(struct slap_control_ids, sc_domainScope),
161 		SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
162 		NULL, NULL,
163 		parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
164 	{ LDAP_CONTROL_DONTUSECOPY,
165  		(int)offsetof(struct slap_control_ids, sc_dontUseCopy),
166 		SLAP_CTRL_GLOBAL|SLAP_CTRL_INTROGATE,
167 		NULL, NULL,
168 		parseDontUseCopy, LDAP_SLIST_ENTRY_INITIALIZER(next) },
169 	{ LDAP_CONTROL_X_PERMISSIVE_MODIFY,
170  		(int)offsetof(struct slap_control_ids, sc_permissiveModify),
171 		SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE,
172 		NULL, NULL,
173 		parsePermissiveModify, LDAP_SLIST_ENTRY_INITIALIZER(next) },
174 #ifdef SLAP_CONTROL_X_TREE_DELETE
175 	{ LDAP_CONTROL_X_TREE_DELETE,
176  		(int)offsetof(struct slap_control_ids, sc_treeDelete),
177 		SLAP_CTRL_DELETE|SLAP_CTRL_HIDE,
178 		NULL, NULL,
179 		parseTreeDelete, LDAP_SLIST_ENTRY_INITIALIZER(next) },
180 #endif
181 	{ LDAP_CONTROL_X_SEARCH_OPTIONS,
182  		(int)offsetof(struct slap_control_ids, sc_searchOptions),
183 		SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH|SLAP_CTRL_HIDE,
184 		NULL, NULL,
185 		parseSearchOptions, LDAP_SLIST_ENTRY_INITIALIZER(next) },
186 	{ LDAP_CONTROL_SUBENTRIES,
187  		(int)offsetof(struct slap_control_ids, sc_subentries),
188 		SLAP_CTRL_SEARCH,
189 		NULL, NULL,
190 		parseSubentries, LDAP_SLIST_ENTRY_INITIALIZER(next) },
191 	{ LDAP_CONTROL_NOOP,
192  		(int)offsetof(struct slap_control_ids, sc_noOp),
193 		SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
194 		NULL, NULL,
195 		parseNoOp, LDAP_SLIST_ENTRY_INITIALIZER(next) },
196 	{ LDAP_CONTROL_RELAX,
197  		(int)offsetof(struct slap_control_ids, sc_relax),
198 		SLAP_CTRL_GLOBAL|SLAP_CTRL_UPDATE|SLAP_CTRL_HIDE,
199 		NULL, NULL,
200 		parseRelax, LDAP_SLIST_ENTRY_INITIALIZER(next) },
201 	{ LDAP_CONTROL_TXN_SPEC,
202  		(int)offsetof(struct slap_control_ids, sc_txnSpec),
203 		SLAP_CTRL_UPDATE|SLAP_CTRL_HIDE,
204 		NULL, NULL,
205 		txn_spec_ctrl, LDAP_SLIST_ENTRY_INITIALIZER(next) },
206 	{ LDAP_CONTROL_MANAGEDSAIT,
207  		(int)offsetof(struct slap_control_ids, sc_manageDSAit),
208 		SLAP_CTRL_ACCESS,
209 		manageDSAit_extops, NULL,
210 		parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
211 	{ LDAP_CONTROL_PROXY_AUTHZ,
212  		(int)offsetof(struct slap_control_ids, sc_proxyAuthz),
213 		SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS,
214 		proxy_authz_extops, NULL,
215 		parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
216 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
217 	{ LDAP_CONTROL_X_SESSION_TRACKING,
218  		(int)offsetof(struct slap_control_ids, sc_sessionTracking),
219 		SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_BIND|SLAP_CTRL_HIDE,
220 		session_tracking_extops, NULL,
221 		parseSessionTracking, LDAP_SLIST_ENTRY_INITIALIZER(next) },
222 #endif
223 #ifdef SLAP_CONTROL_X_WHATFAILED
224 	{ LDAP_CONTROL_X_WHATFAILED,
225  		(int)offsetof(struct slap_control_ids, sc_whatFailed),
226 		SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
227 		NULL, NULL,
228 		parseWhatFailed, LDAP_SLIST_ENTRY_INITIALIZER(next) },
229 #endif
230 #ifdef SLAP_CONTROL_X_LAZY_COMMIT
231 	{ LDAP_CONTROL_X_LAZY_COMMIT,
232 		(int)offsetof(struct slap_control_ids, sc_lazyCommit),
233 		SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE,
234 		NULL, NULL,
235 		parseLazyCommit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
236 #endif
237 
238 	{ NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) }
239 };
240 
241 static struct slap_control *
242 find_ctrl( const char *oid );
243 
244 /*
245  * Register a supported control.
246  *
247  * This can be called by an OpenLDAP plugin or, indirectly, by a
248  * SLAPI plugin calling slapi_register_supported_control().
249  *
250  * NOTE: if flags == 1 the control is replaced if already registered;
251  * otherwise registering an already registered control is not allowed.
252  */
253 int
register_supported_control2(const char * controloid,slap_mask_t controlmask,char ** controlexops,SLAP_CTRL_PARSE_FN * controlparsefn,unsigned flags,int * controlcid)254 register_supported_control2(const char *controloid,
255 	slap_mask_t controlmask,
256 	char **controlexops,
257 	SLAP_CTRL_PARSE_FN *controlparsefn,
258 	unsigned flags,
259 	int *controlcid)
260 {
261 	struct slap_control *sc = NULL;
262 	int i;
263 	BerVarray extendedopsbv = NULL;
264 
265 	if ( num_known_controls >= SLAP_MAX_CIDS ) {
266 		Debug( LDAP_DEBUG_ANY, "Too many controls registered."
267 			" Recompile slapd with SLAP_MAX_CIDS defined > %d\n",
268 		num_known_controls );
269 		return LDAP_OTHER;
270 	}
271 
272 	if ( controloid == NULL ) {
273 		return LDAP_PARAM_ERROR;
274 	}
275 
276 	/* check if already registered */
277 	for ( i = 0; slap_known_controls[ i ]; i++ ) {
278 		if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
279 			if ( flags == 1 ) {
280 				Debug( LDAP_DEBUG_TRACE,
281 					"Control %s already registered; replacing.\n",
282 					controloid );
283 				/* (find and) replace existing handler */
284 				sc = find_ctrl( controloid );
285 				assert( sc != NULL );
286 				break;
287 			}
288 
289 			Debug( LDAP_DEBUG_ANY,
290 				"Control %s already registered.\n",
291 				controloid );
292 			return LDAP_PARAM_ERROR;
293 		}
294 	}
295 
296 	/* turn compatible extended operations into bervals */
297 	if ( controlexops != NULL ) {
298 		int i;
299 
300 		for ( i = 0; controlexops[ i ]; i++ );
301 
302 		extendedopsbv = ber_memcalloc( i + 1, sizeof( struct berval ) );
303 		if ( extendedopsbv == NULL ) {
304 			return LDAP_NO_MEMORY;
305 		}
306 
307 		for ( i = 0; controlexops[ i ]; i++ ) {
308 			ber_str2bv( controlexops[ i ], 0, 1, &extendedopsbv[ i ] );
309 		}
310 	}
311 
312 	if ( sc == NULL ) {
313 		sc = (struct slap_control *)SLAP_MALLOC( sizeof( *sc ) );
314 		if ( sc == NULL ) {
315 			ber_bvarray_free( extendedopsbv );
316 			return LDAP_NO_MEMORY;
317 		}
318 
319 		sc->sc_oid = ch_strdup( controloid );
320 		sc->sc_cid = num_known_controls;
321 
322 		/* Update slap_known_controls, too. */
323 		slap_known_controls[num_known_controls - 1] = sc->sc_oid;
324 		slap_known_controls[num_known_controls++] = NULL;
325 
326 		LDAP_SLIST_NEXT( sc, sc_next ) = NULL;
327 		LDAP_SLIST_INSERT_HEAD( &controls_list, sc, sc_next );
328 
329 	} else {
330 		if ( sc->sc_extendedopsbv ) {
331 			ber_bvarray_free( sc->sc_extendedopsbv );
332 			sc->sc_extendedopsbv = NULL;
333 			sc->sc_extendedops = NULL;
334 		}
335 	}
336 
337 	sc->sc_extendedopsbv = extendedopsbv;
338 	sc->sc_mask = controlmask;
339 	sc->sc_parse = controlparsefn;
340 	if ( controlcid ) {
341 		*controlcid = sc->sc_cid;
342 	}
343 
344 	return LDAP_SUCCESS;
345 }
346 
347 #ifdef SLAP_CONFIG_DELETE
348 int
unregister_supported_control(const char * controloid)349 unregister_supported_control( const char *controloid )
350 {
351 	struct slap_control *sc;
352 	int i;
353 
354 	if ( controloid == NULL || (sc = find_ctrl( controloid )) == NULL ){
355 		return -1;
356 	}
357 
358 	for ( i = 0; slap_known_controls[ i ]; i++ ) {
359 		if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
360 			do {
361 				slap_known_controls[ i ] = slap_known_controls[ i+1 ];
362 			} while ( slap_known_controls[ i++ ] );
363 			num_known_controls--;
364 			break;
365 		}
366 	}
367 
368 	LDAP_SLIST_REMOVE(&controls_list, sc, slap_control, sc_next);
369 	ch_free( sc->sc_oid );
370 	if ( sc->sc_extendedopsbv != NULL ) {
371 		ber_bvarray_free( sc->sc_extendedopsbv );
372 	}
373 	ch_free( sc );
374 
375 	return 0;
376 }
377 #endif /* SLAP_CONFIG_DELETE */
378 
379 int
register_control_exop(const char * controloid,char * exopoid)380 register_control_exop( const char *controloid, char *exopoid )
381 {
382 	struct slap_control *sc = NULL;
383 	BerVarray extendedopsbv;
384 	char **extendedops;
385 	int i;
386 
387 	if ( controloid == NULL || exopoid == NULL ) {
388 		return LDAP_PARAM_ERROR;
389 	}
390 
391 	for ( i = 0; slap_known_controls[ i ]; i++ ) {
392 		if ( strcmp( controloid, slap_known_controls[ i ] ) == 0 ) {
393 			sc = find_ctrl( controloid );
394 			assert( sc != NULL );
395 			break;
396 		}
397 	}
398 
399 	if ( !sc ) {
400 		Debug( LDAP_DEBUG_ANY, "register_control_exop: "
401 			"Control %s not registered.\n",
402 			controloid );
403 		return LDAP_PARAM_ERROR;
404 	}
405 
406 	for ( i = 0; sc->sc_extendedopsbv && !BER_BVISNULL( &sc->sc_extendedopsbv[ i ] ); i++ ) {
407 		if ( strcmp( exopoid, sc->sc_extendedopsbv[ i ].bv_val ) == 0 ) {
408 			return LDAP_SUCCESS;
409 		}
410 	}
411 
412 	extendedopsbv = ber_memrealloc( sc->sc_extendedopsbv, (i + 2) * sizeof( struct berval ) );
413 	if ( extendedopsbv == NULL ) {
414 		return LDAP_NO_MEMORY;
415 	}
416 	sc->sc_extendedopsbv = extendedopsbv;
417 
418 	ber_str2bv( exopoid, 0, 1, &extendedopsbv[ i ] );
419 	BER_BVZERO( &extendedopsbv[ i+1 ] );
420 
421 	return LDAP_SUCCESS;
422 }
423 
424 /*
425  * One-time initialization of internal controls.
426  */
427 int
slap_controls_init(void)428 slap_controls_init( void )
429 {
430 	int i, rc;
431 
432 	rc = LDAP_SUCCESS;
433 
434 	for ( i = 0; control_defs[i].sc_oid != NULL; i++ ) {
435 		int *cid = (int *)(((char *)&slap_cids) + control_defs[i].sc_cid );
436 		rc = register_supported_control( control_defs[i].sc_oid,
437 			control_defs[i].sc_mask, control_defs[i].sc_extendedops,
438 			control_defs[i].sc_parse, cid );
439 		if ( rc != LDAP_SUCCESS ) break;
440 	}
441 
442 	return rc;
443 }
444 
445 /*
446  * Free memory associated with list of supported controls.
447  */
448 void
controls_destroy(void)449 controls_destroy( void )
450 {
451 	struct slap_control *sc;
452 
453 	while ( !LDAP_SLIST_EMPTY(&controls_list) ) {
454 		sc = LDAP_SLIST_FIRST(&controls_list);
455 		LDAP_SLIST_REMOVE_HEAD(&controls_list, sc_next);
456 
457 		ch_free( sc->sc_oid );
458 		if ( sc->sc_extendedopsbv != NULL ) {
459 			ber_bvarray_free( sc->sc_extendedopsbv );
460 		}
461 		ch_free( sc );
462 	}
463 }
464 
465 /*
466  * Format the supportedControl attribute of the root DSE,
467  * detailing which controls are supported by the directory
468  * server.
469  */
470 int
controls_root_dse_info(Entry * e)471 controls_root_dse_info( Entry *e )
472 {
473 	AttributeDescription *ad_supportedControl
474 		= slap_schema.si_ad_supportedControl;
475 	struct berval vals[2];
476 	struct slap_control *sc;
477 
478 	vals[1].bv_val = NULL;
479 	vals[1].bv_len = 0;
480 
481 	LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
482 		if( sc->sc_mask & SLAP_CTRL_HIDE ) continue;
483 
484 		vals[0].bv_val = sc->sc_oid;
485 		vals[0].bv_len = strlen( sc->sc_oid );
486 
487 		if ( attr_merge( e, ad_supportedControl, vals, NULL ) ) {
488 			return -1;
489 		}
490 	}
491 
492 	return 0;
493 }
494 
495 /*
496  * Return a list of OIDs and operation masks for supported
497  * controls. Used by SLAPI.
498  */
499 int
get_supported_controls(char *** ctrloidsp,slap_mask_t ** ctrlmasks)500 get_supported_controls(char ***ctrloidsp,
501 	slap_mask_t **ctrlmasks)
502 {
503 	int n;
504 	char **oids;
505 	slap_mask_t *masks;
506 	struct slap_control *sc;
507 
508 	n = 0;
509 
510 	LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
511 		n++;
512 	}
513 
514 	if ( n == 0 ) {
515 		*ctrloidsp = NULL;
516 		*ctrlmasks = NULL;
517 		return LDAP_SUCCESS;
518 	}
519 
520 	oids = (char **)SLAP_MALLOC( (n + 1) * sizeof(char *) );
521 	if ( oids == NULL ) {
522 		return LDAP_NO_MEMORY;
523 	}
524 	masks = (slap_mask_t *)SLAP_MALLOC( (n + 1) * sizeof(slap_mask_t) );
525 	if  ( masks == NULL ) {
526 		SLAP_FREE( oids );
527 		return LDAP_NO_MEMORY;
528 	}
529 
530 	n = 0;
531 
532 	LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
533 		oids[n] = ch_strdup( sc->sc_oid );
534 		masks[n] = sc->sc_mask;
535 		n++;
536 	}
537 	oids[n] = NULL;
538 	masks[n] = 0;
539 
540 	*ctrloidsp = oids;
541 	*ctrlmasks = masks;
542 
543 	return LDAP_SUCCESS;
544 }
545 
546 /*
547  * Find a control given its OID.
548  */
549 static struct slap_control *
find_ctrl(const char * oid)550 find_ctrl( const char *oid )
551 {
552 	struct slap_control *sc;
553 
554 	LDAP_SLIST_FOREACH( sc, &controls_list, sc_next ) {
555 		if ( strcmp( oid, sc->sc_oid ) == 0 ) {
556 			return sc;
557 		}
558 	}
559 
560 	return NULL;
561 }
562 
563 int
slap_find_control_id(const char * oid,int * cid)564 slap_find_control_id(
565 	const char *oid,
566 	int *cid )
567 {
568 	struct slap_control *ctrl = find_ctrl( oid );
569 	if ( ctrl ) {
570 		if ( cid ) *cid = ctrl->sc_cid;
571 		return LDAP_SUCCESS;
572 	}
573 	return LDAP_CONTROL_NOT_FOUND;
574 }
575 
576 int
slap_global_control(Operation * op,const char * oid,int * cid)577 slap_global_control( Operation *op, const char *oid, int *cid )
578 {
579 	struct slap_control *ctrl = find_ctrl( oid );
580 
581 	if ( ctrl == NULL ) {
582 		/* should not be reachable */
583 		Debug( LDAP_DEBUG_ANY,
584 			"slap_global_control: unrecognized control: %s\n",
585 			oid );
586 		return LDAP_CONTROL_NOT_FOUND;
587 	}
588 
589 	if ( cid ) *cid = ctrl->sc_cid;
590 
591 	if ( ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) ||
592 		( ( op->o_tag & LDAP_REQ_SEARCH ) &&
593 		( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH ) ) )
594 	{
595 		return LDAP_COMPARE_TRUE;
596 	}
597 
598 #if 0
599 	Debug( LDAP_DEBUG_TRACE,
600 		"slap_global_control: unavailable control: %s\n",
601 		oid );
602 #endif
603 
604 	return LDAP_COMPARE_FALSE;
605 }
606 
slap_free_ctrls(Operation * op,LDAPControl ** ctrls)607 void slap_free_ctrls(
608 	Operation *op,
609 	LDAPControl **ctrls )
610 {
611 	int i;
612 
613 	if( ctrls == op->o_ctrls ) {
614 		if( op->o_assertion != NULL ) {
615 			filter_free_x( op, op->o_assertion, 1 );
616 			op->o_assertion = NULL;
617 		}
618 		if( op->o_vrFilter != NULL) {
619 			vrFilter_free( op, op->o_vrFilter );
620 			op->o_vrFilter = NULL;
621 		}
622 		if( op->o_preread_attrs != NULL ) {
623 			op->o_tmpfree( op->o_preread_attrs, op->o_tmpmemctx );
624 			op->o_preread_attrs = NULL;
625 		}
626 		if( op->o_postread_attrs != NULL ) {
627 			op->o_tmpfree( op->o_postread_attrs, op->o_tmpmemctx );
628 			op->o_postread_attrs = NULL;
629 		}
630 		if( op->o_pagedresults_state != NULL ) {
631 			op->o_tmpfree( op->o_pagedresults_state, op->o_tmpmemctx );
632 			op->o_pagedresults_state = NULL;
633 		}
634 	}
635 
636 	for (i=0; ctrls[i]; i++) {
637 		op->o_tmpfree(ctrls[i], op->o_tmpmemctx );
638 	}
639 	op->o_tmpfree( ctrls, op->o_tmpmemctx );
640 }
641 
slap_add_ctrls(Operation * op,SlapReply * rs,LDAPControl ** ctrls)642 int slap_add_ctrls(
643 	Operation *op,
644 	SlapReply *rs,
645 	LDAPControl **ctrls )
646 {
647 	int i = 0, j;
648 	LDAPControl **ctrlsp;
649 
650 	if ( rs->sr_ctrls ) {
651 		for ( ; rs->sr_ctrls[ i ]; i++ ) ;
652 	}
653 
654 	for ( j=0; ctrls[j]; j++ ) ;
655 
656 	ctrlsp = op->o_tmpalloc(( i+j+1 )*sizeof(LDAPControl *), op->o_tmpmemctx );
657 	i = 0;
658 	if ( rs->sr_ctrls ) {
659 		for ( ; rs->sr_ctrls[i]; i++ )
660 			ctrlsp[i] = rs->sr_ctrls[i];
661 	}
662 	for ( j=0; ctrls[j]; j++)
663 		ctrlsp[i++] = ctrls[j];
664 	ctrlsp[i] = NULL;
665 
666 	if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED )
667 		op->o_tmpfree( rs->sr_ctrls, op->o_tmpmemctx );
668 	rs->sr_ctrls = ctrlsp;
669 	rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
670 	return i;
671 }
672 
slap_parse_ctrl(Operation * op,SlapReply * rs,LDAPControl * control,const char ** text)673 int slap_parse_ctrl(
674 	Operation *op,
675 	SlapReply *rs,
676 	LDAPControl *control,
677 	const char **text )
678 {
679 	struct slap_control *sc;
680 	int rc = LDAP_SUCCESS;
681 
682 	sc = find_ctrl( control->ldctl_oid );
683 	if( sc != NULL ) {
684 		/* recognized control */
685 		slap_mask_t tagmask;
686 		switch( op->o_tag ) {
687 		case LDAP_REQ_ADD:
688 			tagmask = SLAP_CTRL_ADD;
689 			break;
690 		case LDAP_REQ_BIND:
691 			tagmask = SLAP_CTRL_BIND;
692 			break;
693 		case LDAP_REQ_COMPARE:
694 			tagmask = SLAP_CTRL_COMPARE;
695 			break;
696 		case LDAP_REQ_DELETE:
697 			tagmask = SLAP_CTRL_DELETE;
698 			break;
699 		case LDAP_REQ_MODIFY:
700 			tagmask = SLAP_CTRL_MODIFY;
701 			break;
702 		case LDAP_REQ_RENAME:
703 			tagmask = SLAP_CTRL_RENAME;
704 			break;
705 		case LDAP_REQ_SEARCH:
706 			tagmask = SLAP_CTRL_SEARCH;
707 			break;
708 		case LDAP_REQ_UNBIND:
709 			tagmask = SLAP_CTRL_UNBIND;
710 			break;
711 		case LDAP_REQ_ABANDON:
712 			tagmask = SLAP_CTRL_ABANDON;
713 			break;
714 		case LDAP_REQ_EXTENDED:
715 			tagmask=~0L;
716 			assert( op->ore_reqoid.bv_val != NULL );
717 			if( sc->sc_extendedopsbv != NULL ) {
718 				int i;
719 				for( i=0; !BER_BVISNULL( &sc->sc_extendedopsbv[i] ); i++ ) {
720 					if( bvmatch( &op->ore_reqoid,
721 						&sc->sc_extendedopsbv[i] ) )
722 					{
723 						tagmask=0L;
724 						break;
725 					}
726 				}
727 			}
728 			break;
729 		default:
730 			*text = "controls internal error";
731 			return LDAP_OTHER;
732 		}
733 
734 		if (( sc->sc_mask & tagmask ) == tagmask ) {
735 			/* available extension */
736 			if ( sc->sc_parse ) {
737 				rc = sc->sc_parse( op, rs, control );
738 				assert( rc != LDAP_UNAVAILABLE_CRITICAL_EXTENSION );
739 
740 			} else if ( control->ldctl_iscritical ) {
741 				*text = "not yet implemented";
742 				rc = LDAP_OTHER;
743 			}
744 
745 
746 		} else if ( control->ldctl_iscritical ) {
747 			/* unavailable CRITICAL control */
748 			*text = "critical extension is unavailable";
749 			rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
750 		}
751 
752 	} else if ( control->ldctl_iscritical ) {
753 		/* unrecognized CRITICAL control */
754 		*text = "critical extension is not recognized";
755 		rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
756 	}
757 
758 	return rc;
759 }
760 
761 int
get_ctrls(Operation * op,SlapReply * rs,int sendres)762 get_ctrls(
763 	Operation *op,
764 	SlapReply *rs,
765 	int sendres )
766 {
767 	return get_ctrls2( op, rs, sendres, LDAP_TAG_CONTROLS );
768 }
769 
770 int
get_ctrls2(Operation * op,SlapReply * rs,int sendres,ber_tag_t ctag)771 get_ctrls2(
772 	Operation *op,
773 	SlapReply *rs,
774 	int sendres,
775 	ber_tag_t ctag )
776 {
777 	int nctrls = 0;
778 	ber_tag_t tag;
779 	ber_len_t len;
780 	char *opaque;
781 	BerElement *ber = op->o_ber;
782 	struct berval bv;
783 #ifdef SLAP_CONTROL_X_WHATFAILED
784 	/* NOTE: right now, slapd checks the validity of each control
785 	 * while parsing.  As a consequence, it can only detect one
786 	 * cause of failure at a time.  This results in returning
787 	 * exactly one OID with the whatFailed control, or no control
788 	 * at all.
789 	 */
790 	char *failed_oid = NULL;
791 #endif
792 
793 	len = ber_pvt_ber_remaining(ber);
794 
795 	if( len == 0) {
796 		/* no controls */
797 		rs->sr_err = LDAP_SUCCESS;
798 		return rs->sr_err;
799 	}
800 
801 	if(( tag = ber_peek_tag( ber, &len )) != ctag ) {
802 		if( tag == LBER_ERROR ) {
803 			rs->sr_err = SLAPD_DISCONNECT;
804 			rs->sr_text = "unexpected data in PDU";
805 		}
806 
807 		goto return_results;
808 	}
809 
810 	Debug( LDAP_DEBUG_TRACE,
811 		"=> get_ctrls\n" );
812 
813 	if( op->o_protocol < LDAP_VERSION3 ) {
814 		rs->sr_err = SLAPD_DISCONNECT;
815 		rs->sr_text = "controls require LDAPv3";
816 		goto return_results;
817 	}
818 
819 	/* one for first control, one for termination */
820 	op->o_ctrls = op->o_tmpalloc( 2 * sizeof(LDAPControl *), op->o_tmpmemctx );
821 
822 #if 0
823 	if( op->ctrls == NULL ) {
824 		rs->sr_err = LDAP_NO_MEMORY;
825 		rs->sr_text = "no memory";
826 		goto return_results;
827 	}
828 #endif
829 
830 	op->o_ctrls[nctrls] = NULL;
831 
832 	/* step through each element */
833 	for( tag = ber_first_element( ber, &len, &opaque );
834 		tag != LBER_ERROR;
835 		tag = ber_next_element( ber, &len, opaque ) )
836 	{
837 		LDAPControl *c;
838 		LDAPControl **tctrls;
839 
840 		c = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
841 		memset(c, 0, sizeof(LDAPControl));
842 
843 		/* allocate pointer space for current controls (nctrls)
844 		 * + this control + extra NULL
845 		 */
846 		tctrls = op->o_tmprealloc( op->o_ctrls,
847 			(nctrls+2) * sizeof(LDAPControl *), op->o_tmpmemctx );
848 
849 #if 0
850 		if( tctrls == NULL ) {
851 			ch_free( c );
852 			ldap_controls_free(op->o_ctrls);
853 			op->o_ctrls = NULL;
854 
855 			rs->sr_err = LDAP_NO_MEMORY;
856 			rs->sr_text = "no memory";
857 			goto return_results;
858 		}
859 #endif
860 		op->o_ctrls = tctrls;
861 
862 		op->o_ctrls[nctrls++] = c;
863 		op->o_ctrls[nctrls] = NULL;
864 
865 		tag = ber_scanf( ber, "{m" /*}*/, &bv );
866 		c->ldctl_oid = bv.bv_val;
867 
868 		if( tag == LBER_ERROR ) {
869 			Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n" );
870 
871 			slap_free_ctrls( op, op->o_ctrls );
872 			op->o_ctrls = NULL;
873 			rs->sr_err = SLAPD_DISCONNECT;
874 			rs->sr_text = "decoding controls error";
875 			goto return_results;
876 
877 		} else if( c->ldctl_oid == NULL ) {
878 			Debug( LDAP_DEBUG_TRACE,
879 				"get_ctrls: conn %lu got empty OID.\n",
880 				op->o_connid );
881 
882 			slap_free_ctrls( op, op->o_ctrls );
883 			op->o_ctrls = NULL;
884 			rs->sr_err = LDAP_PROTOCOL_ERROR;
885 			rs->sr_text = "OID field is empty";
886 			goto return_results;
887 		}
888 
889 		tag = ber_peek_tag( ber, &len );
890 
891 		if( tag == LBER_BOOLEAN ) {
892 			ber_int_t crit;
893 			tag = ber_scanf( ber, "b", &crit );
894 
895 			if( tag == LBER_ERROR ) {
896 				Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n" );
897 				slap_free_ctrls( op, op->o_ctrls );
898 				op->o_ctrls = NULL;
899 				rs->sr_err = SLAPD_DISCONNECT;
900 				rs->sr_text = "decoding controls error";
901 				goto return_results;
902 			}
903 
904 			c->ldctl_iscritical = (crit != 0);
905 			tag = ber_peek_tag( ber, &len );
906 		}
907 
908 		if( tag == LBER_OCTETSTRING ) {
909 			tag = ber_scanf( ber, "m", &c->ldctl_value );
910 
911 			if( tag == LBER_ERROR ) {
912 				Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: conn %lu: "
913 					"%s (%scritical): get value failed.\n",
914 					op->o_connid, c->ldctl_oid,
915 					c->ldctl_iscritical ? "" : "non" );
916 				slap_free_ctrls( op, op->o_ctrls );
917 				op->o_ctrls = NULL;
918 				rs->sr_err = SLAPD_DISCONNECT;
919 				rs->sr_text = "decoding controls error";
920 				goto return_results;
921 			}
922 		}
923 
924 		Debug( LDAP_DEBUG_TRACE,
925 			"=> get_ctrls: oid=\"%s\" (%scritical)\n",
926 			c->ldctl_oid, c->ldctl_iscritical ? "" : "non" );
927 
928 		rs->sr_err = slap_parse_ctrl( op, rs, c, &rs->sr_text );
929 		if ( rs->sr_err != LDAP_SUCCESS ) {
930 #ifdef SLAP_CONTROL_X_WHATFAILED
931 			failed_oid = c->ldctl_oid;
932 #endif
933 			goto return_results;
934 		}
935 	}
936 
937 return_results:
938 	Debug( LDAP_DEBUG_TRACE,
939 		"<= get_ctrls: n=%d rc=%d err=\"%s\"\n",
940 		nctrls, rs->sr_err, rs->sr_text ? rs->sr_text : "");
941 
942 	if( sendres && rs->sr_err != LDAP_SUCCESS ) {
943 		if( rs->sr_err == SLAPD_DISCONNECT ) {
944 			rs->sr_err = LDAP_PROTOCOL_ERROR;
945 			send_ldap_disconnect( op, rs );
946 			rs->sr_err = SLAPD_DISCONNECT;
947 		} else {
948 #ifdef SLAP_CONTROL_X_WHATFAILED
949 			/* might have not been parsed yet? */
950 			if ( failed_oid != NULL ) {
951 				if ( !get_whatFailed( op ) ) {
952 					/* look it up */
953 
954 					/* step through each remaining element */
955 					for ( ; tag != LBER_ERROR; tag = ber_next_element( ber, &len, opaque ) )
956 					{
957 						LDAPControl c = { 0 };
958 
959 						tag = ber_scanf( ber, "{m" /*}*/, &bv );
960 						c.ldctl_oid = bv.bv_val;
961 
962 						if ( tag == LBER_ERROR ) {
963 							slap_free_ctrls( op, op->o_ctrls );
964 							op->o_ctrls = NULL;
965 							break;
966 
967 						} else if ( c.ldctl_oid == NULL ) {
968 							slap_free_ctrls( op, op->o_ctrls );
969 							op->o_ctrls = NULL;
970 							break;
971 						}
972 
973 						tag = ber_peek_tag( ber, &len );
974 						if ( tag == LBER_BOOLEAN ) {
975 							ber_int_t crit;
976 							tag = ber_scanf( ber, "b", &crit );
977 							if( tag == LBER_ERROR ) {
978 								slap_free_ctrls( op, op->o_ctrls );
979 								op->o_ctrls = NULL;
980 								break;
981 							}
982 
983 							tag = ber_peek_tag( ber, &len );
984 						}
985 
986 						if ( tag == LBER_OCTETSTRING ) {
987 							tag = ber_scanf( ber, "m", &c.ldctl_value );
988 
989 							if( tag == LBER_ERROR ) {
990 								slap_free_ctrls( op, op->o_ctrls );
991 								op->o_ctrls = NULL;
992 								break;
993 							}
994 						}
995 
996 						if ( strcmp( c.ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) == 0 ) {
997 							const char *text;
998 							slap_parse_ctrl( op, rs, &c, &text );
999 							break;
1000 						}
1001 					}
1002 				}
1003 
1004 				if ( get_whatFailed( op ) ) {
1005 					char *oids[ 2 ];
1006 					oids[ 0 ] = failed_oid;
1007 					oids[ 1 ] = NULL;
1008 					slap_ctrl_whatFailed_add( op, rs, oids );
1009 				}
1010 			}
1011 #endif
1012 
1013 			send_ldap_result( op, rs );
1014 		}
1015 	}
1016 
1017 	return rs->sr_err;
1018 }
1019 
1020 int
slap_remove_control(Operation * op,SlapReply * rs,int ctrl,BI_chk_controls fnc)1021 slap_remove_control(
1022 	Operation	*op,
1023 	SlapReply	*rs,
1024 	int		ctrl,
1025 	BI_chk_controls	fnc )
1026 {
1027 	int		i, j;
1028 
1029 	switch ( op->o_ctrlflag[ ctrl ] ) {
1030 	case SLAP_CONTROL_NONCRITICAL:
1031 		for ( i = 0, j = -1; op->o_ctrls[ i ] != NULL; i++ ) {
1032 			if ( strcmp( op->o_ctrls[ i ]->ldctl_oid,
1033 				slap_known_controls[ ctrl - 1 ] ) == 0 )
1034 			{
1035 				j = i;
1036 			}
1037 		}
1038 
1039 		if ( j == -1 ) {
1040 			rs->sr_err = LDAP_OTHER;
1041 			break;
1042 		}
1043 
1044 		if ( fnc ) {
1045 			(void)fnc( op, rs );
1046 		}
1047 
1048 		op->o_tmpfree( op->o_ctrls[ j ], op->o_tmpmemctx );
1049 
1050 		if ( i > 1 ) {
1051 			AC_MEMCPY( &op->o_ctrls[ j ], &op->o_ctrls[ j + 1 ],
1052 				( i - j ) * sizeof( LDAPControl * ) );
1053 
1054 		} else {
1055 			op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
1056 			op->o_ctrls = NULL;
1057 		}
1058 
1059 		op->o_ctrlflag[ ctrl ] = SLAP_CONTROL_IGNORED;
1060 
1061 		Debug( LDAP_DEBUG_ANY, "%s: "
1062 			"non-critical control \"%s\" not supported; stripped.\n",
1063 			op->o_log_prefix, slap_known_controls[ ctrl ] );
1064 		/* fall thru */
1065 
1066 	case SLAP_CONTROL_IGNORED:
1067 	case SLAP_CONTROL_NONE:
1068 		rs->sr_err = SLAP_CB_CONTINUE;
1069 		break;
1070 
1071 	case SLAP_CONTROL_CRITICAL:
1072 		rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
1073 		if ( fnc ) {
1074 			(void)fnc( op, rs );
1075 		}
1076 		Debug( LDAP_DEBUG_ANY, "%s: "
1077 			"critical control \"%s\" not supported.\n",
1078 			op->o_log_prefix, slap_known_controls[ ctrl ] );
1079 		break;
1080 
1081 	default:
1082 		/* handle all cases! */
1083 		assert( 0 );
1084 	}
1085 
1086 	return rs->sr_err;
1087 }
1088 
parseDontUseCopy(Operation * op,SlapReply * rs,LDAPControl * ctrl)1089 static int parseDontUseCopy (
1090 	Operation *op,
1091 	SlapReply *rs,
1092 	LDAPControl *ctrl )
1093 {
1094 	if ( op->o_dontUseCopy != SLAP_CONTROL_NONE ) {
1095 		rs->sr_text = "dontUseCopy control specified multiple times";
1096 		return LDAP_PROTOCOL_ERROR;
1097 	}
1098 
1099 	if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1100 		rs->sr_text = "dontUseCopy control value not absent";
1101 		return LDAP_PROTOCOL_ERROR;
1102 	}
1103 
1104 	if ( ( global_disallows & SLAP_DISALLOW_DONTUSECOPY_N_CRIT )
1105 		&& !ctrl->ldctl_iscritical )
1106 	{
1107 		rs->sr_text = "dontUseCopy criticality of FALSE not allowed";
1108 		return LDAP_PROTOCOL_ERROR;
1109 	}
1110 
1111 	op->o_dontUseCopy = ctrl->ldctl_iscritical
1112 		? SLAP_CONTROL_CRITICAL
1113 		: SLAP_CONTROL_NONCRITICAL;
1114 
1115 	return LDAP_SUCCESS;
1116 }
1117 
parseRelax(Operation * op,SlapReply * rs,LDAPControl * ctrl)1118 static int parseRelax (
1119 	Operation *op,
1120 	SlapReply *rs,
1121 	LDAPControl *ctrl )
1122 {
1123 	if ( op->o_relax != SLAP_CONTROL_NONE ) {
1124 		rs->sr_text = "relax control specified multiple times";
1125 		return LDAP_PROTOCOL_ERROR;
1126 	}
1127 
1128 	if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1129 		rs->sr_text = "relax control value not absent";
1130 		return LDAP_PROTOCOL_ERROR;
1131 	}
1132 
1133 	op->o_relax = ctrl->ldctl_iscritical
1134 		? SLAP_CONTROL_CRITICAL
1135 		: SLAP_CONTROL_NONCRITICAL;
1136 
1137 	return LDAP_SUCCESS;
1138 }
1139 
parseManageDSAit(Operation * op,SlapReply * rs,LDAPControl * ctrl)1140 static int parseManageDSAit (
1141 	Operation *op,
1142 	SlapReply *rs,
1143 	LDAPControl *ctrl )
1144 {
1145 	if ( op->o_managedsait != SLAP_CONTROL_NONE ) {
1146 		rs->sr_text = "manageDSAit control specified multiple times";
1147 		return LDAP_PROTOCOL_ERROR;
1148 	}
1149 
1150 	if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1151 		rs->sr_text = "manageDSAit control value not absent";
1152 		return LDAP_PROTOCOL_ERROR;
1153 	}
1154 
1155 	op->o_managedsait = ctrl->ldctl_iscritical
1156 		? SLAP_CONTROL_CRITICAL
1157 		: SLAP_CONTROL_NONCRITICAL;
1158 
1159 	return LDAP_SUCCESS;
1160 }
1161 
parseProxyAuthz(Operation * op,SlapReply * rs,LDAPControl * ctrl)1162 static int parseProxyAuthz (
1163 	Operation *op,
1164 	SlapReply *rs,
1165 	LDAPControl *ctrl )
1166 {
1167 	int		rc;
1168 	struct berval	dn = BER_BVNULL;
1169 
1170 	if ( op->o_proxy_authz != SLAP_CONTROL_NONE ) {
1171 		rs->sr_text = "proxy authorization control specified multiple times";
1172 		return LDAP_PROTOCOL_ERROR;
1173 	}
1174 
1175 	if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1176 		rs->sr_text = "proxy authorization control value absent";
1177 		return LDAP_PROTOCOL_ERROR;
1178 	}
1179 
1180 	if ( ( global_disallows & SLAP_DISALLOW_PROXY_AUTHZ_N_CRIT )
1181 		&& !ctrl->ldctl_iscritical )
1182 	{
1183 		rs->sr_text = "proxied authorization criticality of FALSE not allowed";
1184 		return LDAP_PROTOCOL_ERROR;
1185 	}
1186 
1187 	if ( !( global_allows & SLAP_ALLOW_PROXY_AUTHZ_ANON )
1188 		&& BER_BVISEMPTY( &op->o_ndn ) )
1189 	{
1190 		rs->sr_text = "anonymous proxied authorization not allowed";
1191 		return LDAP_PROXIED_AUTHORIZATION_DENIED;
1192 	}
1193 
1194 	op->o_proxy_authz = ctrl->ldctl_iscritical
1195 		? SLAP_CONTROL_CRITICAL
1196 		: SLAP_CONTROL_NONCRITICAL;
1197 
1198 	Debug( LDAP_DEBUG_ARGS,
1199 		"parseProxyAuthz: conn %lu authzid=\"%s\"\n",
1200 		op->o_connid,
1201 		ctrl->ldctl_value.bv_len ?  ctrl->ldctl_value.bv_val : "anonymous" );
1202 
1203 	if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1204 		Debug( LDAP_DEBUG_TRACE,
1205 			"parseProxyAuthz: conn=%lu anonymous\n",
1206 			op->o_connid );
1207 
1208 		/* anonymous */
1209 		if ( !BER_BVISNULL( &op->o_ndn ) ) {
1210 			op->o_ndn.bv_val[ 0 ] = '\0';
1211 		}
1212 		op->o_ndn.bv_len = 0;
1213 
1214 		if ( !BER_BVISNULL( &op->o_dn ) ) {
1215 			op->o_dn.bv_val[ 0 ] = '\0';
1216 		}
1217 		op->o_dn.bv_len = 0;
1218 
1219 		return LDAP_SUCCESS;
1220 	}
1221 
1222 	rc = slap_sasl_getdn( op->o_conn, op, &ctrl->ldctl_value,
1223 			NULL, &dn, SLAP_GETDN_AUTHZID );
1224 
1225 	/* FIXME: empty DN in proxyAuthz control should be legal... */
1226 	if( rc != LDAP_SUCCESS /* || !dn.bv_len */ ) {
1227 		if ( dn.bv_val ) {
1228 			ch_free( dn.bv_val );
1229 		}
1230 		rs->sr_text = "authzId mapping failed";
1231 		return LDAP_PROXIED_AUTHORIZATION_DENIED;
1232 	}
1233 
1234 	Debug( LDAP_DEBUG_TRACE,
1235 		"parseProxyAuthz: conn=%lu \"%s\"\n",
1236 		op->o_connid,
1237 		dn.bv_len ? dn.bv_val : "(NULL)" );
1238 
1239 	rc = slap_sasl_authorized( op, &op->o_ndn, &dn );
1240 
1241 	if ( rc ) {
1242 		ch_free( dn.bv_val );
1243 		rs->sr_text = "not authorized to assume identity";
1244 		return LDAP_PROXIED_AUTHORIZATION_DENIED;
1245 	}
1246 
1247 	ch_free( op->o_ndn.bv_val );
1248 
1249 	/*
1250 	 * NOTE: since slap_sasl_getdn() returns a normalized dn,
1251 	 * from now on op->o_dn is normalized
1252 	 */
1253 	op->o_ndn = dn;
1254 	ber_bvreplace( &op->o_dn, &dn );
1255 
1256 	Debug( LDAP_DEBUG_STATS, "%s PROXYAUTHZ dn=\"%s\"\n",
1257 	    op->o_log_prefix, dn.bv_val );
1258 
1259 	return LDAP_SUCCESS;
1260 }
1261 
parseNoOp(Operation * op,SlapReply * rs,LDAPControl * ctrl)1262 static int parseNoOp (
1263 	Operation *op,
1264 	SlapReply *rs,
1265 	LDAPControl *ctrl )
1266 {
1267 	if ( op->o_noop != SLAP_CONTROL_NONE ) {
1268 		rs->sr_text = "noop control specified multiple times";
1269 		return LDAP_PROTOCOL_ERROR;
1270 	}
1271 
1272 	if ( !BER_BVISNULL( &ctrl->ldctl_value ) ) {
1273 		rs->sr_text = "noop control value not empty";
1274 		return LDAP_PROTOCOL_ERROR;
1275 	}
1276 
1277 	op->o_noop = ctrl->ldctl_iscritical
1278 		? SLAP_CONTROL_CRITICAL
1279 		: SLAP_CONTROL_NONCRITICAL;
1280 
1281 	return LDAP_SUCCESS;
1282 }
1283 
parsePagedResults(Operation * op,SlapReply * rs,LDAPControl * ctrl)1284 static int parsePagedResults (
1285 	Operation *op,
1286 	SlapReply *rs,
1287 	LDAPControl *ctrl )
1288 {
1289 	BerElementBuffer berbuf;
1290 	BerElement	*ber = (BerElement *)&berbuf;
1291 	struct berval	cookie;
1292 	PagedResultsState	*ps;
1293 	int		rc = LDAP_SUCCESS;
1294 	ber_tag_t	tag;
1295 	ber_int_t	size;
1296 
1297 	if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
1298 		rs->sr_text = "paged results control specified multiple times";
1299 		return LDAP_PROTOCOL_ERROR;
1300 	}
1301 
1302 	if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1303 		rs->sr_text = "paged results control value is absent";
1304 		return LDAP_PROTOCOL_ERROR;
1305 	}
1306 
1307 	if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1308 		rs->sr_text = "paged results control value is empty";
1309 		return LDAP_PROTOCOL_ERROR;
1310 	}
1311 
1312 	/* Parse the control value
1313 	 *	realSearchControlValue ::= SEQUENCE {
1314 	 *		size	INTEGER (0..maxInt),
1315 	 *				-- requested page size from client
1316 	 *				-- result set size estimate from server
1317 	 *		cookie	OCTET STRING
1318 	 * }
1319 	 */
1320 	ber_init2( ber, &ctrl->ldctl_value, LBER_USE_DER );
1321 
1322 	tag = ber_scanf( ber, "{im}", &size, &cookie );
1323 
1324 	if ( tag == LBER_ERROR ) {
1325 		rs->sr_text = "paged results control could not be decoded";
1326 		rc = LDAP_PROTOCOL_ERROR;
1327 		goto done;
1328 	}
1329 
1330 	if ( size < 0 ) {
1331 		rs->sr_text = "paged results control size invalid";
1332 		rc = LDAP_PROTOCOL_ERROR;
1333 		goto done;
1334 	}
1335 
1336 	ps = op->o_tmpalloc( sizeof(PagedResultsState), op->o_tmpmemctx );
1337 	*ps = op->o_conn->c_pagedresults_state;
1338 	ps->ps_size = size;
1339 	ps->ps_cookieval = cookie;
1340 	op->o_pagedresults_state = ps;
1341 	if ( !cookie.bv_len ) {
1342 		ps->ps_count = 0;
1343 		ps->ps_cookie = 0;
1344 		/* taint ps_cookie, to detect whether it's set */
1345 		op->o_conn->c_pagedresults_state.ps_cookie = NOID;
1346 	}
1347 
1348 	/* NOTE: according to RFC 2696 3.:
1349 
1350     If the page size is greater than or equal to the sizeLimit value, the
1351     server should ignore the control as the request can be satisfied in a
1352     single page.
1353 
1354 	 * NOTE: this assumes that the op->ors_slimit be set
1355 	 * before the controls are parsed.
1356 	 */
1357 
1358 	if ( op->ors_slimit > 0 && size >= op->ors_slimit ) {
1359 		op->o_pagedresults = SLAP_CONTROL_IGNORED;
1360 
1361 	} else if ( ctrl->ldctl_iscritical ) {
1362 		op->o_pagedresults = SLAP_CONTROL_CRITICAL;
1363 
1364 	} else {
1365 		op->o_pagedresults = SLAP_CONTROL_NONCRITICAL;
1366 	}
1367 
1368 done:;
1369 	return rc;
1370 }
1371 
1372 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
parseSortedResults(Operation * op,SlapReply * rs,LDAPControl * ctrl)1373 static int parseSortedResults (
1374 	Operation *op,
1375 	SlapReply *rs,
1376 	LDAPControl *ctrl )
1377 {
1378 	int		rc = LDAP_SUCCESS;
1379 
1380 	if ( op->o_sortedresults != SLAP_CONTROL_NONE ) {
1381 		rs->sr_text = "sorted results control specified multiple times";
1382 		return LDAP_PROTOCOL_ERROR;
1383 	}
1384 
1385 	if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1386 		rs->sr_text = "sorted results control value is absent";
1387 		return LDAP_PROTOCOL_ERROR;
1388 	}
1389 
1390 	if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1391 		rs->sr_text = "sorted results control value is empty";
1392 		return LDAP_PROTOCOL_ERROR;
1393 	}
1394 
1395 	/* blow off parsing the value */
1396 
1397 	op->o_sortedresults = ctrl->ldctl_iscritical
1398 		? SLAP_CONTROL_CRITICAL
1399 		: SLAP_CONTROL_NONCRITICAL;
1400 
1401 	return rc;
1402 }
1403 #endif
1404 
parseAssert(Operation * op,SlapReply * rs,LDAPControl * ctrl)1405 static int parseAssert (
1406 	Operation *op,
1407 	SlapReply *rs,
1408 	LDAPControl *ctrl )
1409 {
1410 	BerElement	*ber;
1411 	struct berval	fstr = BER_BVNULL;
1412 
1413 	if ( op->o_assert != SLAP_CONTROL_NONE ) {
1414 		rs->sr_text = "assert control specified multiple times";
1415 		return LDAP_PROTOCOL_ERROR;
1416 	}
1417 
1418 	if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1419 		rs->sr_text = "assert control value is absent";
1420 		return LDAP_PROTOCOL_ERROR;
1421 	}
1422 
1423 	if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1424 		rs->sr_text = "assert control value is empty";
1425 		return LDAP_PROTOCOL_ERROR;
1426 	}
1427 
1428 	ber = ber_init( &(ctrl->ldctl_value) );
1429 	if (ber == NULL) {
1430 		rs->sr_text = "assert control: internal error";
1431 		return LDAP_OTHER;
1432 	}
1433 
1434 	rs->sr_err = get_filter( op, ber, (Filter **)&(op->o_assertion),
1435 		&rs->sr_text);
1436 	(void) ber_free( ber, 1 );
1437 	if( rs->sr_err != LDAP_SUCCESS ) {
1438 		if( rs->sr_err == SLAPD_DISCONNECT ) {
1439 			rs->sr_err = LDAP_PROTOCOL_ERROR;
1440 			send_ldap_disconnect( op, rs );
1441 			rs->sr_err = SLAPD_DISCONNECT;
1442 		} else {
1443 			send_ldap_result( op, rs );
1444 		}
1445 		if( op->o_assertion != NULL ) {
1446 			filter_free_x( op, op->o_assertion, 1 );
1447 			op->o_assertion = NULL;
1448 		}
1449 		return rs->sr_err;
1450 	}
1451 
1452 #ifdef LDAP_DEBUG
1453 	filter2bv_x( op, op->o_assertion, &fstr );
1454 
1455 	Debug( LDAP_DEBUG_ARGS, "parseAssert: conn %ld assert: %s\n",
1456 		op->o_connid, fstr.bv_len ? fstr.bv_val : "empty" );
1457 	op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1458 #endif
1459 
1460 	op->o_assert = ctrl->ldctl_iscritical
1461 		? SLAP_CONTROL_CRITICAL
1462 		: SLAP_CONTROL_NONCRITICAL;
1463 
1464 	rs->sr_err = LDAP_SUCCESS;
1465 	return LDAP_SUCCESS;
1466 }
1467 
1468 #define READMSG(post, msg) \
1469 	( post ? "postread control: " msg : "preread control: " msg )
1470 
1471 static int
parseReadAttrs(Operation * op,SlapReply * rs,LDAPControl * ctrl,int post)1472 parseReadAttrs(
1473 	Operation *op,
1474 	SlapReply *rs,
1475 	LDAPControl *ctrl,
1476 	int post )
1477 {
1478 	ber_len_t	siz, off, i;
1479 	BerElement	*ber;
1480 	AttributeName	*an = NULL;
1481 
1482 	if ( ( post && op->o_postread != SLAP_CONTROL_NONE ) ||
1483 		( !post && op->o_preread != SLAP_CONTROL_NONE ) )
1484 	{
1485 		rs->sr_text = READMSG( post, "specified multiple times" );
1486 		return LDAP_PROTOCOL_ERROR;
1487 	}
1488 
1489 	if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1490 		rs->sr_text = READMSG( post, "value is absent" );
1491 		return LDAP_PROTOCOL_ERROR;
1492 	}
1493 
1494 	if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1495 		rs->sr_text = READMSG( post, "value is empty" );
1496 		return LDAP_PROTOCOL_ERROR;
1497 	}
1498 
1499 	if ( op->o_txnSpec ) { /* temporary limitation */
1500 		rs->sr_text = READMSG( post, "cannot perform in transaction" );
1501 		return LDAP_UNWILLING_TO_PERFORM;
1502 	}
1503 
1504 	ber = ber_init( &ctrl->ldctl_value );
1505 	if ( ber == NULL ) {
1506 		rs->sr_text = READMSG( post, "internal error" );
1507 		return LDAP_OTHER;
1508 	}
1509 
1510 	rs->sr_err = LDAP_SUCCESS;
1511 	siz = sizeof( AttributeName );
1512 	off = offsetof( AttributeName, an_name );
1513 	if ( ber_scanf( ber, "{M}", &an, &siz, off ) == LBER_ERROR ) {
1514 		rs->sr_text = READMSG( post, "decoding error" );
1515 		rs->sr_err = LDAP_PROTOCOL_ERROR;
1516 		goto done;
1517 	}
1518 
1519 	for ( i = 0; i < siz; i++ ) {
1520 		const char	*dummy = NULL;
1521 		int		rc;
1522 
1523 		an[i].an_desc = NULL;
1524 		an[i].an_oc = NULL;
1525 		an[i].an_flags = 0;
1526 		rc = slap_bv2ad( &an[i].an_name, &an[i].an_desc, &dummy );
1527 		if ( rc == LDAP_SUCCESS ) {
1528 			an[i].an_name = an[i].an_desc->ad_cname;
1529 
1530 		} else {
1531 			int			j;
1532 			static struct berval	special_attrs[] = {
1533 				BER_BVC( LDAP_NO_ATTRS ),
1534 				BER_BVC( LDAP_ALL_USER_ATTRIBUTES ),
1535 				BER_BVC( LDAP_ALL_OPERATIONAL_ATTRIBUTES ),
1536 				BER_BVNULL
1537 			};
1538 
1539 			/* deal with special attribute types */
1540 			for ( j = 0; !BER_BVISNULL( &special_attrs[ j ] ); j++ ) {
1541 				if ( bvmatch( &an[i].an_name, &special_attrs[ j ] ) ) {
1542 					an[i].an_name = special_attrs[ j ];
1543 					break;
1544 				}
1545 			}
1546 
1547 			if ( BER_BVISNULL( &special_attrs[ j ] ) && ctrl->ldctl_iscritical ) {
1548 				rs->sr_err = rc;
1549 				rs->sr_text = dummy ? dummy
1550 					: READMSG( post, "unknown attributeType" );
1551 				goto done;
1552 			}
1553 		}
1554 	}
1555 
1556 	if ( post ) {
1557 		op->o_postread_attrs = an;
1558 		op->o_postread = ctrl->ldctl_iscritical
1559 			? SLAP_CONTROL_CRITICAL
1560 			: SLAP_CONTROL_NONCRITICAL;
1561 	} else {
1562 		op->o_preread_attrs = an;
1563 		op->o_preread = ctrl->ldctl_iscritical
1564 			? SLAP_CONTROL_CRITICAL
1565 			: SLAP_CONTROL_NONCRITICAL;
1566 	}
1567 
1568 done:
1569 	(void) ber_free( ber, 1 );
1570 	return rs->sr_err;
1571 }
1572 
parsePreRead(Operation * op,SlapReply * rs,LDAPControl * ctrl)1573 static int parsePreRead (
1574 	Operation *op,
1575 	SlapReply *rs,
1576 	LDAPControl *ctrl )
1577 {
1578 	return parseReadAttrs( op, rs, ctrl, 0 );
1579 }
1580 
parsePostRead(Operation * op,SlapReply * rs,LDAPControl * ctrl)1581 static int parsePostRead (
1582 	Operation *op,
1583 	SlapReply *rs,
1584 	LDAPControl *ctrl )
1585 {
1586 	return parseReadAttrs( op, rs, ctrl, 1 );
1587 }
1588 
parseValuesReturnFilter(Operation * op,SlapReply * rs,LDAPControl * ctrl)1589 static int parseValuesReturnFilter (
1590 	Operation *op,
1591 	SlapReply *rs,
1592 	LDAPControl *ctrl )
1593 {
1594 	BerElement	*ber;
1595 	struct berval	fstr = BER_BVNULL;
1596 
1597 	if ( op->o_valuesreturnfilter != SLAP_CONTROL_NONE ) {
1598 		rs->sr_text = "valuesReturnFilter control specified multiple times";
1599 		return LDAP_PROTOCOL_ERROR;
1600 	}
1601 
1602 	if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1603 		rs->sr_text = "valuesReturnFilter control value is absent";
1604 		return LDAP_PROTOCOL_ERROR;
1605 	}
1606 
1607 	if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1608 		rs->sr_text = "valuesReturnFilter control value is empty";
1609 		return LDAP_PROTOCOL_ERROR;
1610 	}
1611 
1612 	ber = ber_init( &(ctrl->ldctl_value) );
1613 	if (ber == NULL) {
1614 		rs->sr_text = "internal error";
1615 		return LDAP_OTHER;
1616 	}
1617 
1618 	rs->sr_err = get_vrFilter( op, ber,
1619 		(ValuesReturnFilter **)&(op->o_vrFilter), &rs->sr_text);
1620 
1621 	(void) ber_free( ber, 1 );
1622 
1623 	if( rs->sr_err != LDAP_SUCCESS ) {
1624 		if( rs->sr_err == SLAPD_DISCONNECT ) {
1625 			rs->sr_err = LDAP_PROTOCOL_ERROR;
1626 			send_ldap_disconnect( op, rs );
1627 			rs->sr_err = SLAPD_DISCONNECT;
1628 		} else {
1629 			send_ldap_result( op, rs );
1630 		}
1631 		if( op->o_vrFilter != NULL) {
1632 			vrFilter_free( op, op->o_vrFilter );
1633 			op->o_vrFilter = NULL;
1634 		}
1635 	}
1636 #ifdef LDAP_DEBUG
1637 	else {
1638 		vrFilter2bv( op, op->o_vrFilter, &fstr );
1639 	}
1640 
1641 	Debug( LDAP_DEBUG_ARGS, "	vrFilter: %s\n",
1642 		fstr.bv_len ? fstr.bv_val : "empty" );
1643 	op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1644 #endif
1645 
1646 	op->o_valuesreturnfilter = ctrl->ldctl_iscritical
1647 		? SLAP_CONTROL_CRITICAL
1648 		: SLAP_CONTROL_NONCRITICAL;
1649 
1650 	rs->sr_err = LDAP_SUCCESS;
1651 	return LDAP_SUCCESS;
1652 }
1653 
parseSubentries(Operation * op,SlapReply * rs,LDAPControl * ctrl)1654 static int parseSubentries (
1655 	Operation *op,
1656 	SlapReply *rs,
1657 	LDAPControl *ctrl )
1658 {
1659 	if ( op->o_subentries != SLAP_CONTROL_NONE ) {
1660 		rs->sr_text = "subentries control specified multiple times";
1661 		return LDAP_PROTOCOL_ERROR;
1662 	}
1663 
1664 	/* FIXME: should use BER library */
1665 	if( ( ctrl->ldctl_value.bv_len != 3 )
1666 		|| ( ctrl->ldctl_value.bv_val[0] != 0x01 )
1667 		|| ( ctrl->ldctl_value.bv_val[1] != 0x01 ))
1668 	{
1669 		rs->sr_text = "subentries control value encoding is bogus";
1670 		return LDAP_PROTOCOL_ERROR;
1671 	}
1672 
1673 	op->o_subentries = ctrl->ldctl_iscritical
1674 		? SLAP_CONTROL_CRITICAL
1675 		: SLAP_CONTROL_NONCRITICAL;
1676 
1677 	if (ctrl->ldctl_value.bv_val[2]) {
1678 		set_subentries_visibility( op );
1679 	}
1680 
1681 	return LDAP_SUCCESS;
1682 }
1683 
parsePermissiveModify(Operation * op,SlapReply * rs,LDAPControl * ctrl)1684 static int parsePermissiveModify (
1685 	Operation *op,
1686 	SlapReply *rs,
1687 	LDAPControl *ctrl )
1688 {
1689 	if ( op->o_permissive_modify != SLAP_CONTROL_NONE ) {
1690 		rs->sr_text = "permissiveModify control specified multiple times";
1691 		return LDAP_PROTOCOL_ERROR;
1692 	}
1693 
1694 	if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1695 		rs->sr_text = "permissiveModify control value not absent";
1696 		return LDAP_PROTOCOL_ERROR;
1697 	}
1698 
1699 	op->o_permissive_modify = ctrl->ldctl_iscritical
1700 		? SLAP_CONTROL_CRITICAL
1701 		: SLAP_CONTROL_NONCRITICAL;
1702 
1703 	return LDAP_SUCCESS;
1704 }
1705 
parseDomainScope(Operation * op,SlapReply * rs,LDAPControl * ctrl)1706 static int parseDomainScope (
1707 	Operation *op,
1708 	SlapReply *rs,
1709 	LDAPControl *ctrl )
1710 {
1711 	if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1712 		rs->sr_text = "domainScope control specified multiple times";
1713 		return LDAP_PROTOCOL_ERROR;
1714 	}
1715 
1716 	/* this should be checking BVISNULL, but M$ clients are broken
1717 	 * and include the value even though the M$ spec says it must be
1718 	 * omitted. ITS#9100.
1719 	 */
1720 	if ( !BER_BVISEMPTY( &ctrl->ldctl_value )) {
1721 		rs->sr_text = "domainScope control value not absent";
1722 		return LDAP_PROTOCOL_ERROR;
1723 	}
1724 
1725 	op->o_domain_scope = ctrl->ldctl_iscritical
1726 		? SLAP_CONTROL_CRITICAL
1727 		: SLAP_CONTROL_NONCRITICAL;
1728 
1729 	return LDAP_SUCCESS;
1730 }
1731 
1732 #ifdef SLAP_CONTROL_X_TREE_DELETE
parseTreeDelete(Operation * op,SlapReply * rs,LDAPControl * ctrl)1733 static int parseTreeDelete (
1734 	Operation *op,
1735 	SlapReply *rs,
1736 	LDAPControl *ctrl )
1737 {
1738 	if ( op->o_tree_delete != SLAP_CONTROL_NONE ) {
1739 		rs->sr_text = "treeDelete control specified multiple times";
1740 		return LDAP_PROTOCOL_ERROR;
1741 	}
1742 
1743 	if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
1744 		rs->sr_text = "treeDelete control value not absent";
1745 		return LDAP_PROTOCOL_ERROR;
1746 	}
1747 
1748 	op->o_tree_delete = ctrl->ldctl_iscritical
1749 		? SLAP_CONTROL_CRITICAL
1750 		: SLAP_CONTROL_NONCRITICAL;
1751 
1752 	return LDAP_SUCCESS;
1753 }
1754 #endif
1755 
parseSearchOptions(Operation * op,SlapReply * rs,LDAPControl * ctrl)1756 static int parseSearchOptions (
1757 	Operation *op,
1758 	SlapReply *rs,
1759 	LDAPControl *ctrl )
1760 {
1761 	BerElement *ber;
1762 	ber_int_t search_flags;
1763 	ber_tag_t tag;
1764 
1765 	if ( BER_BVISNULL( &ctrl->ldctl_value )) {
1766 		rs->sr_text = "searchOptions control value is absent";
1767 		return LDAP_PROTOCOL_ERROR;
1768 	}
1769 
1770 	if ( BER_BVISEMPTY( &ctrl->ldctl_value )) {
1771 		rs->sr_text = "searchOptions control value is empty";
1772 		return LDAP_PROTOCOL_ERROR;
1773 	}
1774 
1775 	ber = ber_init( &ctrl->ldctl_value );
1776 	if( ber == NULL ) {
1777 		rs->sr_text = "internal error";
1778 		return LDAP_OTHER;
1779 	}
1780 
1781 	tag = ber_scanf( ber, "{i}", &search_flags );
1782 	(void) ber_free( ber, 1 );
1783 
1784 	if ( tag == LBER_ERROR ) {
1785 		rs->sr_text = "searchOptions control decoding error";
1786 		return LDAP_PROTOCOL_ERROR;
1787 	}
1788 
1789 	if ( search_flags & ~(LDAP_SEARCH_FLAG_DOMAIN_SCOPE) ) {
1790 		/* Search flags not recognised so far,
1791 		 * including:
1792 		 *		LDAP_SEARCH_FLAG_PHANTOM_ROOT
1793 		 */
1794 		if ( ctrl->ldctl_iscritical ) {
1795 			rs->sr_text = "searchOptions contained unrecognized flag";
1796 			return LDAP_UNWILLING_TO_PERFORM;
1797 		}
1798 
1799 		/* Ignore */
1800 		Debug( LDAP_DEBUG_TRACE,
1801 			"searchOptions: conn=%lu unrecognized flag(s) 0x%x (non-critical)\n",
1802 			op->o_connid, (unsigned)search_flags );
1803 
1804 		return LDAP_SUCCESS;
1805 	}
1806 
1807 	if ( search_flags & LDAP_SEARCH_FLAG_DOMAIN_SCOPE ) {
1808 		if ( op->o_domain_scope != SLAP_CONTROL_NONE ) {
1809 			rs->sr_text = "searchOptions control specified multiple times "
1810 				"or with domainScope control";
1811 			return LDAP_PROTOCOL_ERROR;
1812 		}
1813 
1814 		op->o_domain_scope = ctrl->ldctl_iscritical
1815 			? SLAP_CONTROL_CRITICAL
1816 			: SLAP_CONTROL_NONCRITICAL;
1817 	}
1818 
1819 	return LDAP_SUCCESS;
1820 }
1821 
1822 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1823 struct berval session_tracking_formats[] = {
1824 	BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_SESSION_ID ),
1825 		BER_BVC( "RADIUS-Acct-Session-Id" ),
1826 	BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_RADIUS_ACCT_MULTI_SESSION_ID ),
1827 		BER_BVC( "RADIUS-Acct-Multi-Session-Id" ),
1828 	BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME ),
1829 		BER_BVC( "USERNAME" ),
1830 
1831 	BER_BVNULL
1832 };
1833 
parseSessionTracking(Operation * op,SlapReply * rs,LDAPControl * ctrl)1834 static int parseSessionTracking(
1835 	Operation *op,
1836 	SlapReply *rs,
1837 	LDAPControl *ctrl )
1838 {
1839 	BerElement		*ber;
1840 	ber_tag_t		tag;
1841 	ber_len_t		len;
1842 	int			i, rc;
1843 
1844 	struct berval		sessionSourceIp = BER_BVNULL,
1845 				sessionSourceName = BER_BVNULL,
1846 				formatOID = BER_BVNULL,
1847 				sessionTrackingIdentifier = BER_BVNULL;
1848 
1849 	size_t			st_len, st_pos;
1850 
1851 	if ( ctrl->ldctl_iscritical ) {
1852 		rs->sr_text = "sessionTracking criticality is TRUE";
1853 		return LDAP_PROTOCOL_ERROR;
1854 	}
1855 
1856 	if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
1857 		rs->sr_text = "sessionTracking control value is absent";
1858 		return LDAP_PROTOCOL_ERROR;
1859 	}
1860 
1861 	if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
1862 		rs->sr_text = "sessionTracking control value is empty";
1863 		return LDAP_PROTOCOL_ERROR;
1864 	}
1865 
1866 	/* TODO: add the capability to determine if a client is allowed
1867 	 * to use this control, based on identity, ip and so */
1868 
1869 	ber = ber_init( &ctrl->ldctl_value );
1870 	if ( ber == NULL ) {
1871 		rs->sr_text = "internal error";
1872 		return LDAP_OTHER;
1873 	}
1874 
1875 	tag = ber_skip_tag( ber, &len );
1876 	if ( tag != LBER_SEQUENCE ) {
1877 		tag = LBER_ERROR;
1878 		goto error;
1879 	}
1880 
1881 	/* sessionSourceIp */
1882 	tag = ber_peek_tag( ber, &len );
1883 	if ( tag == LBER_DEFAULT ) {
1884 		tag = LBER_ERROR;
1885 		goto error;
1886 	}
1887 
1888 	if ( len == 0 ) {
1889 		tag = ber_skip_tag( ber, &len );
1890 
1891 	} else if ( len > 128 ) {
1892 		rs->sr_text = "sessionTracking.sessionSourceIp too long";
1893 		rs->sr_err = LDAP_PROTOCOL_ERROR;
1894 		goto error;
1895 
1896 	} else {
1897 		tag = ber_scanf( ber, "m", &sessionSourceIp );
1898 	}
1899 
1900 	if ( ldif_is_not_printable( sessionSourceIp.bv_val, sessionSourceIp.bv_len ) ) {
1901 		BER_BVZERO( &sessionSourceIp );
1902 	}
1903 
1904 	/* sessionSourceName */
1905 	tag = ber_peek_tag( ber, &len );
1906 	if ( tag == LBER_DEFAULT ) {
1907 		tag = LBER_ERROR;
1908 		goto error;
1909 	}
1910 
1911 	if ( len == 0 ) {
1912 		tag = ber_skip_tag( ber, &len );
1913 
1914 	} else if ( len > 65536 ) {
1915 		rs->sr_text = "sessionTracking.sessionSourceName too long";
1916 		rs->sr_err = LDAP_PROTOCOL_ERROR;
1917 		goto error;
1918 
1919 	} else {
1920 		tag = ber_scanf( ber, "m", &sessionSourceName );
1921 	}
1922 
1923 	if ( ldif_is_not_printable( sessionSourceName.bv_val, sessionSourceName.bv_len ) ) {
1924 		BER_BVZERO( &sessionSourceName );
1925 	}
1926 
1927 	/* formatOID */
1928 	tag = ber_peek_tag( ber, &len );
1929 	if ( tag == LBER_DEFAULT ) {
1930 		tag = LBER_ERROR;
1931 		goto error;
1932 	}
1933 
1934 	if ( len == 0 ) {
1935 		rs->sr_text = "sessionTracking.formatOID empty";
1936 		rs->sr_err = LDAP_PROTOCOL_ERROR;
1937 		goto error;
1938 
1939 	} else if ( len > 1024 ) {
1940 		rs->sr_text = "sessionTracking.formatOID too long";
1941 		rs->sr_err = LDAP_PROTOCOL_ERROR;
1942 		goto error;
1943 
1944 	} else {
1945 		tag = ber_scanf( ber, "m", &formatOID );
1946 	}
1947 
1948 	rc = numericoidValidate( NULL, &formatOID );
1949 	if ( rc != LDAP_SUCCESS ) {
1950 		rs->sr_text = "sessionTracking.formatOID invalid";
1951 		goto error;
1952 	}
1953 
1954 	for ( i = 0; !BER_BVISNULL( &session_tracking_formats[ i ] ); i += 2 )
1955 	{
1956 		if ( bvmatch( &formatOID, &session_tracking_formats[ i ] ) ) {
1957 			formatOID = session_tracking_formats[ i + 1 ];
1958 			break;
1959 		}
1960 	}
1961 
1962 	/* sessionTrackingIdentifier */
1963 	tag = ber_peek_tag( ber, &len );
1964 	if ( tag == LBER_DEFAULT ) {
1965 		tag = LBER_ERROR;
1966 		goto error;
1967 	}
1968 
1969 	if ( len == 0 ) {
1970 		tag = ber_skip_tag( ber, &len );
1971 
1972 	} else {
1973 		/* note: should not be more than 65536... */
1974 		tag = ber_scanf( ber, "m", &sessionTrackingIdentifier );
1975 		if ( ldif_is_not_printable( sessionTrackingIdentifier.bv_val, sessionTrackingIdentifier.bv_len ) ) {
1976 			/* we want the OID printed, at least */
1977 			BER_BVSTR( &sessionTrackingIdentifier, "" );
1978 		}
1979 	}
1980 
1981 	/* closure */
1982 	tag = ber_skip_tag( ber, &len );
1983 	if ( tag != LBER_DEFAULT || len != 0 ) {
1984 		tag = LBER_ERROR;
1985 		goto error;
1986 	}
1987 	tag = 0;
1988 
1989 	st_len = 0;
1990 	if ( !BER_BVISNULL( &sessionSourceIp ) ) {
1991 		st_len += STRLENOF( "IP=" ) + sessionSourceIp.bv_len;
1992 	}
1993 	if ( !BER_BVISNULL( &sessionSourceName ) ) {
1994 		if ( st_len ) st_len++;
1995 		st_len += STRLENOF( "NAME=" ) + sessionSourceName.bv_len;
1996 	}
1997 	if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
1998 		if ( st_len ) st_len++;
1999 		st_len += formatOID.bv_len + STRLENOF( "=" )
2000 			+ sessionTrackingIdentifier.bv_len;
2001 	}
2002 
2003 	if ( st_len == 0 ) {
2004 		goto error;
2005 	}
2006 
2007 	st_len += STRLENOF( " []" );
2008 	st_pos = strlen( op->o_log_prefix );
2009 
2010 	if ( sizeof( op->o_log_prefix ) - st_pos > st_len ) {
2011 		char	*ptr = &op->o_log_prefix[ st_pos ];
2012 
2013 		ptr = lutil_strcopy( ptr, " [" /*]*/ );
2014 
2015 		st_len = 0;
2016 		if ( !BER_BVISNULL( &sessionSourceIp ) ) {
2017 			ptr = lutil_strcopy( ptr, "IP=" );
2018 			ptr = lutil_strcopy( ptr, sessionSourceIp.bv_val );
2019 			st_len++;
2020 		}
2021 
2022 		if ( !BER_BVISNULL( &sessionSourceName ) ) {
2023 			if ( st_len ) *ptr++ = ' ';
2024 			ptr = lutil_strcopy( ptr, "NAME=" );
2025 			ptr = lutil_strcopy( ptr, sessionSourceName.bv_val );
2026 			st_len++;
2027 		}
2028 
2029 		if ( !BER_BVISNULL( &sessionTrackingIdentifier ) ) {
2030 			if ( st_len ) *ptr++ = ' ';
2031 			ptr = lutil_strcopy( ptr, formatOID.bv_val );
2032 			*ptr++ = '=';
2033 			ptr = lutil_strcopy( ptr, sessionTrackingIdentifier.bv_val );
2034 		}
2035 
2036 		*ptr++ = /*[*/ ']';
2037 		*ptr = '\0';
2038 	}
2039 
2040 error:;
2041 	(void)ber_free( ber, 1 );
2042 
2043 	if ( tag == LBER_ERROR ) {
2044 		rs->sr_text = "sessionTracking control decoding error";
2045 		return LDAP_PROTOCOL_ERROR;
2046 	}
2047 
2048 
2049 	return rs->sr_err;
2050 }
2051 
2052 int
slap_ctrl_session_tracking_add(Operation * op,SlapReply * rs,struct berval * ip,struct berval * name,struct berval * id,LDAPControl * ctrl)2053 slap_ctrl_session_tracking_add(
2054 	Operation *op,
2055 	SlapReply *rs,
2056 	struct berval *ip,
2057 	struct berval *name,
2058 	struct berval *id,
2059 	LDAPControl *ctrl )
2060 {
2061 	BerElementBuffer berbuf;
2062 	BerElement	*ber = (BerElement *)&berbuf;
2063 
2064 	static struct berval	oid = BER_BVC( LDAP_CONTROL_X_SESSION_TRACKING_USERNAME );
2065 
2066 	assert( ctrl != NULL );
2067 
2068 	ber_init2( ber, NULL, LBER_USE_DER );
2069 
2070 	ber_printf( ber, "{OOOO}", ip, name, &oid, id );
2071 
2072 	if ( ber_flatten2( ber, &ctrl->ldctl_value, 0 ) == -1 ) {
2073 		rs->sr_err = LDAP_OTHER;
2074 		goto done;
2075 	}
2076 
2077 	ctrl->ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING;
2078 	ctrl->ldctl_iscritical = 0;
2079 
2080 	rs->sr_err = LDAP_SUCCESS;
2081 
2082 done:;
2083 	return rs->sr_err;
2084 }
2085 
2086 int
slap_ctrl_session_tracking_request_add(Operation * op,SlapReply * rs,LDAPControl * ctrl)2087 slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPControl *ctrl )
2088 {
2089 	static struct berval	bv_unknown = BER_BVC( SLAP_STRING_UNKNOWN );
2090 	struct berval		ip = BER_BVNULL,
2091 				name = BER_BVNULL,
2092 				id = BER_BVNULL;
2093 
2094 	if ( !BER_BVISNULL( &op->o_conn->c_peer_name ) &&
2095 		memcmp( op->o_conn->c_peer_name.bv_val, "IP=", STRLENOF( "IP=" ) ) == 0 )
2096 	{
2097 		char	*ptr;
2098 
2099 		ip.bv_val = op->o_conn->c_peer_name.bv_val + STRLENOF( "IP=" );
2100 		ip.bv_len = op->o_conn->c_peer_name.bv_len - STRLENOF( "IP=" );
2101 
2102 		ptr = ber_bvchr( &ip, ':' );
2103 		if ( ptr ) {
2104 			ip.bv_len = ptr - ip.bv_val;
2105 		}
2106 	}
2107 
2108 	if ( !BER_BVISNULL( &op->o_conn->c_peer_domain ) &&
2109 		!bvmatch( &op->o_conn->c_peer_domain, &bv_unknown ) )
2110 	{
2111 		name = op->o_conn->c_peer_domain;
2112 	}
2113 
2114 	if ( !BER_BVISNULL( &op->o_dn ) && !BER_BVISEMPTY( &op->o_dn ) ) {
2115 		id = op->o_dn;
2116 	}
2117 
2118 	return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl );
2119 }
2120 #endif
2121 
2122 #ifdef SLAP_CONTROL_X_WHATFAILED
parseWhatFailed(Operation * op,SlapReply * rs,LDAPControl * ctrl)2123 static int parseWhatFailed(
2124 	Operation *op,
2125 	SlapReply *rs,
2126 	LDAPControl *ctrl )
2127 {
2128 	if ( op->o_whatFailed != SLAP_CONTROL_NONE ) {
2129 		rs->sr_text = "\"WHat Failed?\" control specified multiple times";
2130 		return LDAP_PROTOCOL_ERROR;
2131 	}
2132 
2133 	if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
2134 		rs->sr_text = "\"What Failed?\" control value not absent";
2135 		return LDAP_PROTOCOL_ERROR;
2136 	}
2137 
2138 	op->o_whatFailed = ctrl->ldctl_iscritical
2139 		? SLAP_CONTROL_CRITICAL
2140 		: SLAP_CONTROL_NONCRITICAL;
2141 
2142 	return LDAP_SUCCESS;
2143 }
2144 
2145 int
slap_ctrl_whatFailed_add(Operation * op,SlapReply * rs,char ** oids)2146 slap_ctrl_whatFailed_add(
2147 	Operation *op,
2148 	SlapReply *rs,
2149 	char **oids )
2150 {
2151 	BerElementBuffer berbuf;
2152 	BerElement *ber = (BerElement *) &berbuf;
2153 	LDAPControl **ctrls = NULL;
2154 	struct berval ctrlval;
2155 	int i, rc = LDAP_SUCCESS;
2156 
2157 	ber_init2( ber, NULL, LBER_USE_DER );
2158 	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
2159 	ber_printf( ber, "[" /*]*/ );
2160 	for ( i = 0; oids[ i ] != NULL; i++ ) {
2161 		ber_printf( ber, "s", oids[ i ] );
2162 	}
2163 	ber_printf( ber, /*[*/ "]" );
2164 
2165 	if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
2166 		rc = LDAP_OTHER;
2167 		goto done;
2168 	}
2169 
2170 	i = 0;
2171 	if ( rs->sr_ctrls != NULL ) {
2172 		for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) {
2173 			if ( strcmp( rs->sr_ctrls[ i ]->ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) != 0 ) {
2174 				/* TODO: add */
2175 				assert( 0 );
2176 			}
2177 		}
2178 	}
2179 
2180 	ctrls = op->o_tmprealloc( rs->sr_ctrls,
2181 			sizeof(LDAPControl *)*( i + 2 )
2182 			+ sizeof(LDAPControl)
2183 			+ ctrlval.bv_len + 1,
2184 			op->o_tmpmemctx );
2185 	if ( ctrls == NULL ) {
2186 		rc = LDAP_OTHER;
2187 		goto done;
2188 	}
2189 	ctrls[ i + 1 ] = NULL;
2190 	ctrls[ i ] = (LDAPControl *)&ctrls[ i + 2 ];
2191 	ctrls[ i ]->ldctl_oid = LDAP_CONTROL_X_WHATFAILED;
2192 	ctrls[ i ]->ldctl_iscritical = 0;
2193 	ctrls[ i ]->ldctl_value.bv_val = (char *)&ctrls[ i ][ 1 ];
2194 	AC_MEMCPY( ctrls[ i ]->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len + 1 );
2195 	ctrls[ i ]->ldctl_value.bv_len = ctrlval.bv_len;
2196 
2197 	ber_free_buf( ber );
2198 
2199 	rs->sr_ctrls = ctrls;
2200 
2201 done:;
2202 	return rc;
2203 }
2204 #endif
2205 
2206 #ifdef SLAP_CONTROL_X_LAZY_COMMIT
parseLazyCommit(Operation * op,SlapReply * rs,LDAPControl * ctrl)2207 static int parseLazyCommit(
2208 	Operation *op,
2209 	SlapReply *rs,
2210 	LDAPControl *ctrl )
2211 {
2212 	if ( op->o_lazyCommit != SLAP_CONTROL_NONE ) {
2213 		rs->sr_text = "\"Lazy Commit?\" control specified multiple times";
2214 		return LDAP_PROTOCOL_ERROR;
2215 	}
2216 
2217 	if ( !BER_BVISNULL( &ctrl->ldctl_value )) {
2218 		rs->sr_text = "\"Lazy Commit?\" control value not absent";
2219 		return LDAP_PROTOCOL_ERROR;
2220 	}
2221 
2222 	op->o_lazyCommit = ctrl->ldctl_iscritical
2223 		? SLAP_CONTROL_CRITICAL
2224 		: SLAP_CONTROL_NONCRITICAL;
2225 
2226 	return LDAP_SUCCESS;
2227 }
2228 #endif
2229