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