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