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