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