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