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