1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2011 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/stdlib.h> 21 22#include <ac/socket.h> 23#include <ac/string.h> 24#include <ac/time.h> 25 26#include "ldap-int.h" 27 28#define LDAP_OPT_REBIND_PROC 0x4e814d 29#define LDAP_OPT_REBIND_PARAMS 0x4e814e 30 31#define LDAP_OPT_NEXTREF_PROC 0x4e815d 32#define LDAP_OPT_NEXTREF_PARAMS 0x4e815e 33 34#define LDAP_OPT_URLLIST_PROC 0x4e816d 35#define LDAP_OPT_URLLIST_PARAMS 0x4e816e 36 37static const LDAPAPIFeatureInfo features[] = { 38#ifdef LDAP_API_FEATURE_X_OPENLDAP 39 { /* OpenLDAP Extensions API Feature */ 40 LDAP_FEATURE_INFO_VERSION, 41 "X_OPENLDAP", 42 LDAP_API_FEATURE_X_OPENLDAP 43 }, 44#endif 45 46#ifdef LDAP_API_FEATURE_THREAD_SAFE 47 { /* Basic Thread Safe */ 48 LDAP_FEATURE_INFO_VERSION, 49 "THREAD_SAFE", 50 LDAP_API_FEATURE_THREAD_SAFE 51 }, 52#endif 53#ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE 54 { /* Session Thread Safe */ 55 LDAP_FEATURE_INFO_VERSION, 56 "SESSION_THREAD_SAFE", 57 LDAP_API_FEATURE_SESSION_THREAD_SAFE 58 }, 59#endif 60#ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE 61 { /* Operation Thread Safe */ 62 LDAP_FEATURE_INFO_VERSION, 63 "OPERATION_THREAD_SAFE", 64 LDAP_API_FEATURE_OPERATION_THREAD_SAFE 65 }, 66#endif 67#ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT 68 { /* OpenLDAP Reentrant */ 69 LDAP_FEATURE_INFO_VERSION, 70 "X_OPENLDAP_REENTRANT", 71 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT 72 }, 73#endif 74#if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \ 75 defined( LDAP_THREAD_SAFE ) 76 { /* OpenLDAP Thread Safe */ 77 LDAP_FEATURE_INFO_VERSION, 78 "X_OPENLDAP_THREAD_SAFE", 79 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE 80 }, 81#endif 82#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS 83 { /* V2 Referrals */ 84 LDAP_FEATURE_INFO_VERSION, 85 "X_OPENLDAP_V2_REFERRALS", 86 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS 87 }, 88#endif 89 {0, NULL, 0} 90}; 91 92int 93ldap_get_option( 94 LDAP *ld, 95 int option, 96 void *outvalue) 97{ 98 struct ldapoptions *lo; 99 int rc = LDAP_OPT_ERROR; 100 101#if defined(__APPLE__) && defined(LDAP_R_COMPILE) 102 /* Init the global options in a nice thread-safe manner. */ 103 dispatch_once_f(&ldap_global_opts_initialized, NULL, ldap_int_init_global_opts); 104#endif 105 106 /* Get pointer to global option structure */ 107 lo = LDAP_INT_GLOBAL_OPT(); 108 if (NULL == lo) { 109 return LDAP_NO_MEMORY; 110 } 111 112 if( lo->ldo_valid != LDAP_INITIALIZED ) { 113 ldap_int_initialize(lo, NULL); 114 } 115 116 /* Apple-specific option */ 117 if (option == LDAP_OPT_TEST_SESSION) { 118 if ( ld == NULL || !LDAP_VALID(ld) ) 119 return LDAP_OPT_ERROR; 120 121 return LDAP_OPT_SUCCESS; 122 } 123 /* END Apple-specific option */ 124 125 if(ld != NULL) { 126 assert( LDAP_VALID( ld ) ); 127 128 if( !LDAP_VALID( ld ) ) { 129 return LDAP_OPT_ERROR; 130 } 131 132 lo = &ld->ld_options; 133 } 134 135 if(outvalue == NULL) { 136 /* no place to get to */ 137 return LDAP_OPT_ERROR; 138 } 139 140 LDAP_MUTEX_LOCK( &lo->ldo_mutex ); 141 142 switch(option) { 143 case LDAP_OPT_API_INFO: { 144 struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue; 145 146 if(info == NULL) { 147 /* outvalue must point to an apiinfo structure */ 148 break; /* LDAP_OPT_ERROR */ 149 } 150 151 if(info->ldapai_info_version != LDAP_API_INFO_VERSION) { 152 /* api info version mismatch */ 153 info->ldapai_info_version = LDAP_API_INFO_VERSION; 154 break; /* LDAP_OPT_ERROR */ 155 } 156 157 info->ldapai_api_version = LDAP_API_VERSION; 158 info->ldapai_protocol_version = LDAP_VERSION_MAX; 159 160 if(features[0].ldapaif_name == NULL) { 161 info->ldapai_extensions = NULL; 162 } else { 163 int i; 164 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) * 165 sizeof(features)/sizeof(LDAPAPIFeatureInfo)); 166 167 for(i=0; features[i].ldapaif_name != NULL; i++) { 168 info->ldapai_extensions[i] = 169 LDAP_STRDUP(features[i].ldapaif_name); 170 } 171 172 info->ldapai_extensions[i] = NULL; 173 } 174 175 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME); 176 info->ldapai_vendor_version = LDAP_VENDOR_VERSION; 177 178 rc = LDAP_OPT_SUCCESS; 179 break; 180 } break; 181 182 case LDAP_OPT_DESC: 183 if( ld == NULL || ld->ld_sb == NULL ) { 184 /* bad param */ 185 break; 186 } 187 188 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue ); 189 rc = LDAP_OPT_SUCCESS; 190 break; 191 192 case LDAP_OPT_SOCKBUF: 193 if( ld == NULL ) break; 194 *(Sockbuf **)outvalue = ld->ld_sb; 195 rc = LDAP_OPT_SUCCESS; 196 break; 197 198 case LDAP_OPT_TIMEOUT: 199 /* the caller has to free outvalue ! */ 200 if ( lo->ldo_tm_api.tv_sec < 0 ) { 201 *(void **)outvalue = NULL; 202 } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) { 203 break; /* LDAP_OPT_ERROR */ 204 } 205 rc = LDAP_OPT_SUCCESS; 206 break; 207 208 case LDAP_OPT_NETWORK_TIMEOUT: 209 /* the caller has to free outvalue ! */ 210 if ( lo->ldo_tm_net.tv_sec < 0 ) { 211 *(void **)outvalue = NULL; 212 } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) { 213 break; /* LDAP_OPT_ERROR */ 214 } 215 rc = LDAP_OPT_SUCCESS; 216 break; 217 218 case LDAP_OPT_DEREF: 219 * (int *) outvalue = lo->ldo_deref; 220 rc = LDAP_OPT_SUCCESS; 221 break; 222 223 case LDAP_OPT_SIZELIMIT: 224 * (int *) outvalue = lo->ldo_sizelimit; 225 rc = LDAP_OPT_SUCCESS; 226 break; 227 228 case LDAP_OPT_TIMELIMIT: 229 * (int *) outvalue = lo->ldo_timelimit; 230 rc = LDAP_OPT_SUCCESS; 231 break; 232 233 case LDAP_OPT_REFERRALS: 234 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS); 235 rc = LDAP_OPT_SUCCESS; 236 break; 237 238 case LDAP_OPT_RESTART: 239 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART); 240 rc = LDAP_OPT_SUCCESS; 241 break; 242 243 case LDAP_OPT_PROTOCOL_VERSION: 244 * (int *) outvalue = lo->ldo_version; 245 rc = LDAP_OPT_SUCCESS; 246 break; 247 248 case LDAP_OPT_SERVER_CONTROLS: 249 * (LDAPControl ***) outvalue = 250 ldap_controls_dup( lo->ldo_sctrls ); 251 rc = LDAP_OPT_SUCCESS; 252 break; 253 254 case LDAP_OPT_CLIENT_CONTROLS: 255 * (LDAPControl ***) outvalue = 256 ldap_controls_dup( lo->ldo_cctrls ); 257 rc = LDAP_OPT_SUCCESS; 258 break; 259 260 case LDAP_OPT_HOST_NAME: 261 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp); 262 rc = LDAP_OPT_SUCCESS; 263 break; 264 265 case LDAP_OPT_URI: 266 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp); 267 rc = LDAP_OPT_SUCCESS; 268 break; 269 270 case LDAP_OPT_DEFBASE: 271 if( lo->ldo_defbase == NULL ) { 272 * (char **) outvalue = NULL; 273 } else { 274 * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase); 275 } 276 rc = LDAP_OPT_SUCCESS; 277 break; 278 279 case LDAP_OPT_CONNECT_ASYNC: 280 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC); 281 rc = LDAP_OPT_SUCCESS; 282 break; 283 284 case LDAP_OPT_CONNECT_CB: 285 { 286 /* Getting deletes the specified callback */ 287 ldaplist **ll = &lo->ldo_conn_cbs; 288 for (;*ll;ll = &(*ll)->ll_next) { 289 if ((*ll)->ll_data == outvalue) { 290 ldaplist *lc = *ll; 291 *ll = lc->ll_next; 292 LDAP_FREE(lc); 293 break; 294 } 295 } 296 } 297 rc = LDAP_OPT_SUCCESS; 298 break; 299 300 case LDAP_OPT_RESULT_CODE: 301 if(ld == NULL) { 302 /* bad param */ 303 break; 304 } 305 * (int *) outvalue = ld->ld_errno; 306 rc = LDAP_OPT_SUCCESS; 307 break; 308 309 case LDAP_OPT_DIAGNOSTIC_MESSAGE: 310 if(ld == NULL) { 311 /* bad param */ 312 break; 313 } 314 315 if( ld->ld_error == NULL ) { 316 * (char **) outvalue = NULL; 317 } else { 318 * (char **) outvalue = LDAP_STRDUP(ld->ld_error); 319 } 320 rc = LDAP_OPT_SUCCESS; 321 break; 322 323 case LDAP_OPT_MATCHED_DN: 324 if(ld == NULL) { 325 /* bad param */ 326 break; 327 } 328 329 if( ld->ld_matched == NULL ) { 330 * (char **) outvalue = NULL; 331 } else { 332 * (char **) outvalue = LDAP_STRDUP( ld->ld_matched ); 333 } 334 rc = LDAP_OPT_SUCCESS; 335 break; 336 337 case LDAP_OPT_REFERRAL_URLS: 338 if(ld == NULL) { 339 /* bad param */ 340 break; 341 } 342 343 if( ld->ld_referrals == NULL ) { 344 * (char ***) outvalue = NULL; 345 } else { 346 * (char ***) outvalue = ldap_value_dup(ld->ld_referrals); 347 } 348 rc = LDAP_OPT_SUCCESS; 349 break; 350 351 case LDAP_OPT_API_FEATURE_INFO: { 352 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue; 353 int i; 354 355 if(info == NULL) 356 break; /* LDAP_OPT_ERROR */ 357 358 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) { 359 /* api info version mismatch */ 360 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; 361 break; /* LDAP_OPT_ERROR */ 362 } 363 364 if(info->ldapaif_name == NULL) 365 break; /* LDAP_OPT_ERROR */ 366 367 for(i=0; features[i].ldapaif_name != NULL; i++) { 368 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) { 369 info->ldapaif_version = 370 features[i].ldapaif_version; 371 rc = LDAP_OPT_SUCCESS; 372 break; 373 } 374 } 375 } 376 break; 377 378 case LDAP_OPT_DEBUG_LEVEL: 379 * (int *) outvalue = lo->ldo_debug; 380 rc = LDAP_OPT_SUCCESS; 381 break; 382 383 case LDAP_OPT_SESSION_REFCNT: 384 if(ld == NULL) { 385 /* bad param */ 386 break; 387 } 388 * (int *) outvalue = ld->ld_ldcrefcnt; 389 rc = LDAP_OPT_SUCCESS; 390 break; 391 392 case LDAP_OPT_X_KEEPALIVE_IDLE: 393 * (int *) outvalue = lo->ldo_keepalive_idle; 394 rc = LDAP_OPT_SUCCESS; 395 break; 396 397 case LDAP_OPT_X_KEEPALIVE_PROBES: 398 * (int *) outvalue = lo->ldo_keepalive_probes; 399 rc = LDAP_OPT_SUCCESS; 400 break; 401 402 case LDAP_OPT_X_KEEPALIVE_INTERVAL: 403 * (int *) outvalue = lo->ldo_keepalive_interval; 404 rc = LDAP_OPT_SUCCESS; 405 break; 406 407 default: 408#ifdef HAVE_TLS 409 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) { 410 rc = LDAP_OPT_SUCCESS; 411 break; 412 } 413#endif 414#ifdef HAVE_CYRUS_SASL 415 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) { 416 rc = LDAP_OPT_SUCCESS; 417 break; 418 } 419#endif 420#ifdef HAVE_GSSAPI 421 if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) { 422 rc = LDAP_OPT_SUCCESS; 423 break; 424 } 425#endif 426 /* bad param */ 427 break; 428 } 429 430 LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); 431 return ( rc ); 432} 433 434int 435ldap_set_option( 436 LDAP *ld, 437 int option, 438 LDAP_CONST void *invalue) 439{ 440 struct ldapoptions *lo; 441 int *dbglvl = NULL; 442 int rc = LDAP_OPT_ERROR; 443 444 /* Get pointer to global option structure */ 445 lo = LDAP_INT_GLOBAL_OPT(); 446 if (lo == NULL) { 447 return LDAP_NO_MEMORY; 448 } 449 450 /* 451 * The architecture to turn on debugging has a chicken and egg 452 * problem. Thus, we introduce a fix here. 453 */ 454 455 if (option == LDAP_OPT_DEBUG_LEVEL) { 456 dbglvl = (int *) invalue; 457 } 458 459 if( lo->ldo_valid != LDAP_INITIALIZED ) { 460 ldap_int_initialize(lo, dbglvl); 461 } 462 463 if(ld != NULL) { 464 assert( LDAP_VALID( ld ) ); 465 466 if( !LDAP_VALID( ld ) ) { 467 return LDAP_OPT_ERROR; 468 } 469 470 lo = &ld->ld_options; 471 } 472 473 LDAP_MUTEX_LOCK( &lo->ldo_mutex ); 474 475 switch ( option ) { 476 477 /* options with boolean values */ 478 case LDAP_OPT_REFERRALS: 479 if(invalue == LDAP_OPT_OFF) { 480 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS); 481 } else { 482 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS); 483 } 484 rc = LDAP_OPT_SUCCESS; 485 break; 486 487 case LDAP_OPT_RESTART: 488 if(invalue == LDAP_OPT_OFF) { 489 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART); 490 } else { 491 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART); 492 } 493 rc = LDAP_OPT_SUCCESS; 494 break; 495 496 case LDAP_OPT_CONNECT_ASYNC: 497 if(invalue == LDAP_OPT_OFF) { 498 LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC); 499 } else { 500 LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC); 501 } 502 rc = LDAP_OPT_SUCCESS; 503 break; 504 505 /* options which can withstand invalue == NULL */ 506 case LDAP_OPT_SERVER_CONTROLS: { 507 LDAPControl *const *controls = 508 (LDAPControl *const *) invalue; 509 510 if( lo->ldo_sctrls ) 511 ldap_controls_free( lo->ldo_sctrls ); 512 513 if( controls == NULL || *controls == NULL ) { 514 lo->ldo_sctrls = NULL; 515 rc = LDAP_OPT_SUCCESS; 516 break; 517 } 518 519 lo->ldo_sctrls = ldap_controls_dup( controls ); 520 521 if(lo->ldo_sctrls == NULL) { 522 /* memory allocation error ? */ 523 break; /* LDAP_OPT_ERROR */ 524 } 525 } 526 rc = LDAP_OPT_SUCCESS; 527 break; 528 529 case LDAP_OPT_CLIENT_CONTROLS: { 530 LDAPControl *const *controls = 531 (LDAPControl *const *) invalue; 532 533 if( lo->ldo_cctrls ) 534 ldap_controls_free( lo->ldo_cctrls ); 535 536 if( controls == NULL || *controls == NULL ) { 537 lo->ldo_cctrls = NULL; 538 rc = LDAP_OPT_SUCCESS; 539 break; 540 } 541 542 lo->ldo_cctrls = ldap_controls_dup( controls ); 543 544 if(lo->ldo_cctrls == NULL) { 545 /* memory allocation error ? */ 546 break; /* LDAP_OPT_ERROR */ 547 } 548 } 549 rc = LDAP_OPT_SUCCESS; 550 break; 551 552 553 case LDAP_OPT_HOST_NAME: { 554 const char *host = (const char *) invalue; 555 LDAPURLDesc *ludlist = NULL; 556 rc = LDAP_OPT_SUCCESS; 557 558 if(host != NULL) { 559 rc = ldap_url_parsehosts( &ludlist, host, 560 lo->ldo_defport ? lo->ldo_defport : LDAP_PORT ); 561 562 } else if(ld == NULL) { 563 /* 564 * must want global default returned 565 * to initial condition. 566 */ 567 rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, 568 LDAP_PVT_URL_PARSE_NOEMPTY_HOST 569 | LDAP_PVT_URL_PARSE_DEF_PORT ); 570 571 } else { 572 /* 573 * must want the session default 574 * updated to the current global default 575 */ 576 ludlist = ldap_url_duplist( 577 ldap_int_global_options.ldo_defludp); 578 if (ludlist == NULL) 579 rc = LDAP_NO_MEMORY; 580 } 581 582 if (rc == LDAP_OPT_SUCCESS) { 583 if (lo->ldo_defludp != NULL) 584 ldap_free_urllist(lo->ldo_defludp); 585 lo->ldo_defludp = ludlist; 586 } 587 break; 588 } 589 590 case LDAP_OPT_URI: { 591 const char *urls = (const char *) invalue; 592 LDAPURLDesc *ludlist = NULL; 593 rc = LDAP_OPT_SUCCESS; 594 595 if(urls != NULL) { 596 rc = ldap_url_parselist_ext(&ludlist, urls, NULL, 597 LDAP_PVT_URL_PARSE_NOEMPTY_HOST 598 | LDAP_PVT_URL_PARSE_DEF_PORT ); 599 } else if(ld == NULL) { 600 /* 601 * must want global default returned 602 * to initial condition. 603 */ 604 rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, 605 LDAP_PVT_URL_PARSE_NOEMPTY_HOST 606 | LDAP_PVT_URL_PARSE_DEF_PORT ); 607 608 } else { 609 /* 610 * must want the session default 611 * updated to the current global default 612 */ 613 ludlist = ldap_url_duplist( 614 ldap_int_global_options.ldo_defludp); 615 if (ludlist == NULL) 616 rc = LDAP_URL_ERR_MEM; 617 } 618 619 switch (rc) { 620 case LDAP_URL_SUCCESS: /* Success */ 621 rc = LDAP_SUCCESS; 622 break; 623 624 case LDAP_URL_ERR_MEM: /* can't allocate memory space */ 625 rc = LDAP_NO_MEMORY; 626 break; 627 628 case LDAP_URL_ERR_PARAM: /* parameter is bad */ 629 case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */ 630 case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */ 631 case LDAP_URL_ERR_BADURL: /* URL is bad */ 632 case LDAP_URL_ERR_BADHOST: /* host port is bad */ 633 case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */ 634 case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */ 635 case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */ 636 case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */ 637 rc = LDAP_PARAM_ERROR; 638 break; 639 } 640 641 if (rc == LDAP_SUCCESS) { 642 if (lo->ldo_defludp != NULL) 643 ldap_free_urllist(lo->ldo_defludp); 644 lo->ldo_defludp = ludlist; 645 } 646 break; 647 } 648 649 case LDAP_OPT_DEFBASE: { 650 const char *newbase = (const char *) invalue; 651 char *defbase = NULL; 652 653 if ( newbase != NULL ) { 654 defbase = LDAP_STRDUP( newbase ); 655 if ( defbase == NULL ) { 656 rc = LDAP_NO_MEMORY; 657 break; 658 } 659 660 } else if ( ld != NULL ) { 661 defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase ); 662 if ( defbase == NULL ) { 663 rc = LDAP_NO_MEMORY; 664 break; 665 } 666 } 667 668 if ( lo->ldo_defbase != NULL ) 669 LDAP_FREE( lo->ldo_defbase ); 670 lo->ldo_defbase = defbase; 671 } 672 rc = LDAP_OPT_SUCCESS; 673 break; 674 675 case LDAP_OPT_DIAGNOSTIC_MESSAGE: { 676 const char *err = (const char *) invalue; 677 678 if(ld == NULL) { 679 /* need a struct ldap */ 680 break; /* LDAP_OPT_ERROR */ 681 } 682 683 if( ld->ld_error ) { 684 LDAP_FREE(ld->ld_error); 685 ld->ld_error = NULL; 686 } 687 688 if ( err ) { 689 ld->ld_error = LDAP_STRDUP(err); 690 } 691 } 692 rc = LDAP_OPT_SUCCESS; 693 break; 694 695 case LDAP_OPT_MATCHED_DN: { 696 const char *matched = (const char *) invalue; 697 698 if (ld == NULL) { 699 /* need a struct ldap */ 700 break; /* LDAP_OPT_ERROR */ 701 } 702 703 if( ld->ld_matched ) { 704 LDAP_FREE(ld->ld_matched); 705 ld->ld_matched = NULL; 706 } 707 708 if ( matched ) { 709 ld->ld_matched = LDAP_STRDUP( matched ); 710 } 711 } 712 rc = LDAP_OPT_SUCCESS; 713 break; 714 715 case LDAP_OPT_REFERRAL_URLS: { 716 char *const *referrals = (char *const *) invalue; 717 718 if(ld == NULL) { 719 /* need a struct ldap */ 720 break; /* LDAP_OPT_ERROR */ 721 } 722 723 if( ld->ld_referrals ) { 724 LDAP_VFREE(ld->ld_referrals); 725 } 726 727 if ( referrals ) { 728 ld->ld_referrals = ldap_value_dup(referrals); 729 } 730 } 731 rc = LDAP_OPT_SUCCESS; 732 break; 733 734 /* Only accessed from inside this function by ldap_set_rebind_proc() */ 735 case LDAP_OPT_REBIND_PROC: { 736 lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue; 737 } 738 rc = LDAP_OPT_SUCCESS; 739 break; 740 case LDAP_OPT_REBIND_PARAMS: { 741 lo->ldo_rebind_params = (void *)invalue; 742 } 743 rc = LDAP_OPT_SUCCESS; 744 break; 745 746 /* Only accessed from inside this function by ldap_set_nextref_proc() */ 747 case LDAP_OPT_NEXTREF_PROC: { 748 lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue; 749 } 750 rc = LDAP_OPT_SUCCESS; 751 break; 752 case LDAP_OPT_NEXTREF_PARAMS: { 753 lo->ldo_nextref_params = (void *)invalue; 754 } 755 rc = LDAP_OPT_SUCCESS; 756 break; 757 758 /* Only accessed from inside this function by ldap_set_urllist_proc() */ 759 case LDAP_OPT_URLLIST_PROC: { 760 lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue; 761 } 762 rc = LDAP_OPT_SUCCESS; 763 break; 764 case LDAP_OPT_URLLIST_PARAMS: { 765 lo->ldo_urllist_params = (void *)invalue; 766 } 767 rc = LDAP_OPT_SUCCESS; 768 break; 769 770 /* read-only options */ 771 case LDAP_OPT_API_INFO: 772 case LDAP_OPT_DESC: 773 case LDAP_OPT_SOCKBUF: 774 case LDAP_OPT_API_FEATURE_INFO: 775 break; /* LDAP_OPT_ERROR */ 776 777 /* options which cannot withstand invalue == NULL */ 778 case LDAP_OPT_DEREF: 779 case LDAP_OPT_SIZELIMIT: 780 case LDAP_OPT_TIMELIMIT: 781 case LDAP_OPT_PROTOCOL_VERSION: 782 case LDAP_OPT_RESULT_CODE: 783 case LDAP_OPT_DEBUG_LEVEL: 784 case LDAP_OPT_TIMEOUT: 785 case LDAP_OPT_NETWORK_TIMEOUT: 786 case LDAP_OPT_CONNECT_CB: 787 case LDAP_OPT_X_KEEPALIVE_IDLE: 788 case LDAP_OPT_X_KEEPALIVE_PROBES : 789 case LDAP_OPT_X_KEEPALIVE_INTERVAL : 790 if(invalue == NULL) { 791 /* no place to set from */ 792 LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); 793 return ( LDAP_OPT_ERROR ); 794 } 795 break; 796 797 default: 798#ifdef HAVE_TLS 799 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) { 800 LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); 801 return ( LDAP_OPT_SUCCESS ); 802 } 803#endif 804#ifdef HAVE_CYRUS_SASL 805 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) { 806 LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); 807 return ( LDAP_OPT_SUCCESS ); 808 } 809#endif 810#ifdef HAVE_GSSAPI 811 if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 ) { 812 LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); 813 return ( LDAP_OPT_SUCCESS ); 814 } 815#endif 816 /* bad param */ 817 break; /* LDAP_OPT_ERROR */ 818 } 819 820 /* options which cannot withstand invalue == NULL */ 821 822 switch(option) { 823 case LDAP_OPT_DEREF: 824 /* FIXME: check value for protocol compliance? */ 825 lo->ldo_deref = * (const int *) invalue; 826 rc = LDAP_OPT_SUCCESS; 827 break; 828 829 case LDAP_OPT_SIZELIMIT: 830 /* FIXME: check value for protocol compliance? */ 831 lo->ldo_sizelimit = * (const int *) invalue; 832 rc = LDAP_OPT_SUCCESS; 833 break; 834 835 case LDAP_OPT_TIMELIMIT: 836 /* FIXME: check value for protocol compliance? */ 837 lo->ldo_timelimit = * (const int *) invalue; 838 rc = LDAP_OPT_SUCCESS; 839 break; 840 841 case LDAP_OPT_TIMEOUT: { 842 const struct timeval *tv = 843 (const struct timeval *) invalue; 844 845 lo->ldo_tm_api = *tv; 846 } 847 rc = LDAP_OPT_SUCCESS; 848 break; 849 850 case LDAP_OPT_NETWORK_TIMEOUT: { 851 const struct timeval *tv = 852 (const struct timeval *) invalue; 853 854 lo->ldo_tm_net = *tv; 855 } 856 rc = LDAP_OPT_SUCCESS; 857 break; 858 859 case LDAP_OPT_PROTOCOL_VERSION: { 860 int vers = * (const int *) invalue; 861 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) { 862 /* not supported */ 863 break; 864 } 865 lo->ldo_version = vers; 866 } 867 rc = LDAP_OPT_SUCCESS; 868 break; 869 870 case LDAP_OPT_RESULT_CODE: { 871 int err = * (const int *) invalue; 872 873 if(ld == NULL) { 874 /* need a struct ldap */ 875 break; 876 } 877 878 ld->ld_errno = err; 879 } 880 rc = LDAP_OPT_SUCCESS; 881 break; 882 883 case LDAP_OPT_DEBUG_LEVEL: 884 lo->ldo_debug = * (const int *) invalue; 885 rc = LDAP_OPT_SUCCESS; 886 break; 887 888 case LDAP_OPT_CONNECT_CB: 889 { 890 /* setting pushes the callback */ 891 ldaplist *ll; 892 ll = LDAP_MALLOC( sizeof( *ll )); 893 ll->ll_data = (void *)invalue; 894 ll->ll_next = lo->ldo_conn_cbs; 895 lo->ldo_conn_cbs = ll; 896 } 897 rc = LDAP_OPT_SUCCESS; 898 break; 899 case LDAP_OPT_X_KEEPALIVE_IDLE: 900 lo->ldo_keepalive_idle = * (const int *) invalue; 901 rc = LDAP_OPT_SUCCESS; 902 break; 903 case LDAP_OPT_X_KEEPALIVE_PROBES : 904 lo->ldo_keepalive_probes = * (const int *) invalue; 905 rc = LDAP_OPT_SUCCESS; 906 break; 907 case LDAP_OPT_X_KEEPALIVE_INTERVAL : 908 lo->ldo_keepalive_interval = * (const int *) invalue; 909 rc = LDAP_OPT_SUCCESS; 910 break; 911 /* Apple specific options */ 912 case LDAP_OPT_NOADDRERR: 913 if(invalue == LDAP_OPT_OFF) 914 lo->ldo_noaddr_option = 0; 915 else 916 lo->ldo_noaddr_option = 1; 917 rc = LDAP_OPT_SUCCESS; 918 break; 919 } 920 LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); 921 return ( rc ); 922} 923 924int 925ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params ) 926{ 927 int rc; 928 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc ); 929 if( rc != LDAP_OPT_SUCCESS ) return rc; 930 931 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params ); 932 return rc; 933} 934 935int 936ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params ) 937{ 938 int rc; 939 rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc ); 940 if( rc != LDAP_OPT_SUCCESS ) return rc; 941 942 rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params ); 943 return rc; 944} 945 946int 947ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params ) 948{ 949 int rc; 950 rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc ); 951 if( rc != LDAP_OPT_SUCCESS ) return rc; 952 953 rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params ); 954 return rc; 955} 956