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