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