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