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