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