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