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