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