2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2006 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
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>.
20 #include <ac/stdlib.h>
22 #include <ac/socket.h>
23 #include <ac/string.h>
28 #define LDAP_OPT_REBIND_PROC 0x4e814d
29 #define LDAP_OPT_REBIND_PARAMS 0x4e814e
31 #define LDAP_OPT_NEXTREF_PROC 0x4e815d
32 #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
34 static const LDAPAPIFeatureInfo features[] = {
35 #ifdef LDAP_API_FEATURE_X_OPENLDAP
36 { /* OpenLDAP Extensions API Feature */
37 LDAP_FEATURE_INFO_VERSION,
39 LDAP_API_FEATURE_X_OPENLDAP
43 #ifdef LDAP_API_FEATURE_THREAD_SAFE
44 { /* Basic Thread Safe */
45 LDAP_FEATURE_INFO_VERSION,
47 LDAP_API_FEATURE_THREAD_SAFE
50 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
51 { /* Session Thread Safe */
52 LDAP_FEATURE_INFO_VERSION,
53 "SESSION_THREAD_SAFE",
54 LDAP_API_FEATURE_SESSION_THREAD_SAFE
57 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
58 { /* Operation Thread Safe */
59 LDAP_FEATURE_INFO_VERSION,
60 "OPERATION_THREAD_SAFE",
61 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
64 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
65 { /* OpenLDAP Reentrant */
66 LDAP_FEATURE_INFO_VERSION,
67 "X_OPENLDAP_REENTRANT",
68 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
71 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
72 defined( LDAP_THREAD_SAFE )
73 { /* OpenLDAP Thread Safe */
74 LDAP_FEATURE_INFO_VERSION,
75 "X_OPENLDAP_THREAD_SAFE",
76 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
79 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
81 LDAP_FEATURE_INFO_VERSION,
82 "X_OPENLDAP_V2_REFERRALS",
83 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
95 struct ldapoptions *lo;
97 /* Get pointer to global option structure */
98 lo = LDAP_INT_GLOBAL_OPT();
100 return LDAP_NO_MEMORY;
103 if( lo->ldo_valid != LDAP_INITIALIZED ) {
104 ldap_int_initialize(lo, NULL);
108 assert( LDAP_VALID( ld ) );
110 if( !LDAP_VALID( ld ) ) {
111 return LDAP_OPT_ERROR;
114 lo = &ld->ld_options;
117 if(outvalue == NULL) {
118 /* no place to get to */
119 return LDAP_OPT_ERROR;
123 case LDAP_OPT_API_INFO: {
124 struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
127 /* outvalue must point to an apiinfo structure */
128 return LDAP_OPT_ERROR;
131 if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
132 /* api info version mismatch */
133 info->ldapai_info_version = LDAP_API_INFO_VERSION;
134 return LDAP_OPT_ERROR;
137 info->ldapai_api_version = LDAP_API_VERSION;
138 info->ldapai_protocol_version = LDAP_VERSION_MAX;
140 if(features[0].ldapaif_name == NULL) {
141 info->ldapai_extensions = NULL;
144 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
145 sizeof(features)/sizeof(LDAPAPIFeatureInfo));
147 for(i=0; features[i].ldapaif_name != NULL; i++) {
148 info->ldapai_extensions[i] =
149 LDAP_STRDUP(features[i].ldapaif_name);
152 info->ldapai_extensions[i] = NULL;
155 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
156 info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
158 return LDAP_OPT_SUCCESS;
162 if( ld == NULL || ld->ld_sb == NULL ) {
167 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
168 return LDAP_OPT_SUCCESS;
170 case LDAP_OPT_SOCKBUF:
171 if( ld == NULL ) break;
172 *(Sockbuf **)outvalue = ld->ld_sb;
173 return LDAP_OPT_SUCCESS;
175 case LDAP_OPT_TIMEOUT:
176 /* the caller has to free outvalue ! */
177 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 ) {
178 return LDAP_OPT_ERROR;
180 return LDAP_OPT_SUCCESS;
182 case LDAP_OPT_NETWORK_TIMEOUT:
183 /* the caller has to free outvalue ! */
184 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 ) {
185 return LDAP_OPT_ERROR;
187 return LDAP_OPT_SUCCESS;
190 * (int *) outvalue = lo->ldo_deref;
191 return LDAP_OPT_SUCCESS;
193 case LDAP_OPT_SIZELIMIT:
194 * (int *) outvalue = lo->ldo_sizelimit;
195 return LDAP_OPT_SUCCESS;
197 case LDAP_OPT_TIMELIMIT:
198 * (int *) outvalue = lo->ldo_timelimit;
199 return LDAP_OPT_SUCCESS;
201 case LDAP_OPT_REFERRALS:
202 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
203 return LDAP_OPT_SUCCESS;
205 case LDAP_OPT_RESTART:
206 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
207 return LDAP_OPT_SUCCESS;
209 case LDAP_OPT_PROTOCOL_VERSION:
210 * (int *) outvalue = lo->ldo_version;
211 return LDAP_OPT_SUCCESS;
213 case LDAP_OPT_SERVER_CONTROLS:
214 * (LDAPControl ***) outvalue =
215 ldap_controls_dup( lo->ldo_sctrls );
217 return LDAP_OPT_SUCCESS;
219 case LDAP_OPT_CLIENT_CONTROLS:
220 * (LDAPControl ***) outvalue =
221 ldap_controls_dup( lo->ldo_cctrls );
223 return LDAP_OPT_SUCCESS;
225 case LDAP_OPT_HOST_NAME:
226 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
227 return LDAP_OPT_SUCCESS;
230 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
231 return LDAP_OPT_SUCCESS;
233 case LDAP_OPT_DEFBASE:
234 if( lo->ldo_defbase == NULL ) {
235 * (char **) outvalue = NULL;
237 * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
240 return LDAP_OPT_SUCCESS;
242 case LDAP_OPT_ERROR_NUMBER:
247 * (int *) outvalue = ld->ld_errno;
248 return LDAP_OPT_SUCCESS;
250 case LDAP_OPT_ERROR_STRING:
256 if( ld->ld_error == NULL ) {
257 * (char **) outvalue = NULL;
259 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
262 return LDAP_OPT_SUCCESS;
264 case LDAP_OPT_MATCHED_DN:
270 if( ld->ld_matched == NULL ) {
271 * (char **) outvalue = NULL;
273 * (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
276 return LDAP_OPT_SUCCESS;
278 case LDAP_OPT_REFERRAL_URLS:
284 if( ld->ld_referrals == NULL ) {
285 * (char ***) outvalue = NULL;
287 * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
290 return LDAP_OPT_SUCCESS;
292 case LDAP_OPT_API_FEATURE_INFO: {
293 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
296 if(info == NULL) return LDAP_OPT_ERROR;
298 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
299 /* api info version mismatch */
300 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
301 return LDAP_OPT_ERROR;
304 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
306 for(i=0; features[i].ldapaif_name != NULL; i++) {
307 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
308 info->ldapaif_version =
309 features[i].ldapaif_version;
310 return LDAP_OPT_SUCCESS;
316 case LDAP_OPT_DEBUG_LEVEL:
317 * (int *) outvalue = lo->ldo_debug;
318 return LDAP_OPT_SUCCESS;
322 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
323 return LDAP_OPT_SUCCESS;
326 #ifdef HAVE_CYRUS_SASL
327 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
328 return LDAP_OPT_SUCCESS;
335 return LDAP_OPT_ERROR;
342 LDAP_CONST void *invalue)
344 struct ldapoptions *lo;
347 /* Get pointer to global option structure */
348 lo = LDAP_INT_GLOBAL_OPT();
350 return LDAP_NO_MEMORY;
354 * The architecture to turn on debugging has a chicken and egg
355 * problem. Thus, we introduce a fix here.
358 if (option == LDAP_OPT_DEBUG_LEVEL) {
359 dbglvl = (int *) invalue;
362 if( lo->ldo_valid != LDAP_INITIALIZED ) {
363 ldap_int_initialize(lo, dbglvl);
367 assert( LDAP_VALID( ld ) );
369 if( !LDAP_VALID( ld ) ) {
370 return LDAP_OPT_ERROR;
373 lo = &ld->ld_options;
377 case LDAP_OPT_REFERRALS:
378 if(invalue == LDAP_OPT_OFF) {
379 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
381 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
383 return LDAP_OPT_SUCCESS;
385 case LDAP_OPT_RESTART:
386 if(invalue == LDAP_OPT_OFF) {
387 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
389 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
391 return LDAP_OPT_SUCCESS;
394 /* options which can withstand invalue == NULL */
396 case LDAP_OPT_SERVER_CONTROLS: {
397 LDAPControl *const *controls =
398 (LDAPControl *const *) invalue;
401 ldap_controls_free( lo->ldo_sctrls );
403 if( controls == NULL || *controls == NULL ) {
404 lo->ldo_sctrls = NULL;
405 return LDAP_OPT_SUCCESS;
408 lo->ldo_sctrls = ldap_controls_dup( controls );
410 if(lo->ldo_sctrls == NULL) {
411 /* memory allocation error ? */
414 } return LDAP_OPT_SUCCESS;
416 case LDAP_OPT_CLIENT_CONTROLS: {
417 LDAPControl *const *controls =
418 (LDAPControl *const *) invalue;
421 ldap_controls_free( lo->ldo_cctrls );
423 if( controls == NULL || *controls == NULL ) {
424 lo->ldo_cctrls = NULL;
425 return LDAP_OPT_SUCCESS;
428 lo->ldo_cctrls = ldap_controls_dup( controls );
430 if(lo->ldo_cctrls == NULL) {
431 /* memory allocation error ? */
434 } return LDAP_OPT_SUCCESS;
436 case LDAP_OPT_TIMEOUT: {
437 const struct timeval *tv =
438 (const struct timeval *) invalue;
440 if ( lo->ldo_tm_api != NULL ) {
441 LDAP_FREE( lo->ldo_tm_api );
442 lo->ldo_tm_api = NULL;
445 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
446 return LDAP_OPT_ERROR;
448 } return LDAP_OPT_SUCCESS;
450 case LDAP_OPT_NETWORK_TIMEOUT: {
451 const struct timeval *tv =
452 (const struct timeval *) invalue;
454 if ( lo->ldo_tm_net != NULL ) {
455 LDAP_FREE( lo->ldo_tm_net );
456 lo->ldo_tm_net = NULL;
459 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
460 return LDAP_OPT_ERROR;
462 } return LDAP_OPT_SUCCESS;
464 case LDAP_OPT_HOST_NAME: {
465 const char *host = (const char *) invalue;
466 LDAPURLDesc *ludlist = NULL;
467 int rc = LDAP_OPT_SUCCESS;
470 rc = ldap_url_parsehosts( &ludlist, host,
471 lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
473 } else if(ld == NULL) {
475 * must want global default returned
476 * to initial condition.
478 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
482 * must want the session default
483 * updated to the current global default
485 ludlist = ldap_url_duplist(
486 ldap_int_global_options.ldo_defludp);
491 if (rc == LDAP_OPT_SUCCESS) {
492 if (lo->ldo_defludp != NULL)
493 ldap_free_urllist(lo->ldo_defludp);
494 lo->ldo_defludp = ludlist;
500 const char *urls = (const char *) invalue;
501 LDAPURLDesc *ludlist = NULL;
502 int rc = LDAP_OPT_SUCCESS;
505 rc = ldap_url_parselist(&ludlist, urls);
506 } else if(ld == NULL) {
508 * must want global default returned
509 * to initial condition.
511 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
515 * must want the session default
516 * updated to the current global default
518 ludlist = ldap_url_duplist(
519 ldap_int_global_options.ldo_defludp);
521 rc = LDAP_URL_ERR_MEM;
525 case LDAP_URL_SUCCESS: /* Success */
529 case LDAP_URL_ERR_MEM: /* can't allocate memory space */
533 case LDAP_URL_ERR_PARAM: /* parameter is bad */
534 case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */
535 case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
536 case LDAP_URL_ERR_BADURL: /* URL is bad */
537 case LDAP_URL_ERR_BADHOST: /* host port is bad */
538 case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */
539 case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */
540 case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */
541 case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */
542 rc = LDAP_PARAM_ERROR;
546 if (rc == LDAP_SUCCESS) {
547 if (lo->ldo_defludp != NULL)
548 ldap_free_urllist(lo->ldo_defludp);
549 lo->ldo_defludp = ludlist;
554 case LDAP_OPT_DEFBASE: {
555 const char *newbase = (const char *) invalue;
556 char *defbase = NULL;
558 if ( newbase != NULL ) {
559 defbase = LDAP_STRDUP( newbase );
560 if ( defbase == NULL ) return LDAP_NO_MEMORY;
562 } else if ( ld != NULL ) {
563 defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
564 if ( defbase == NULL ) return LDAP_NO_MEMORY;
567 if ( lo->ldo_defbase != NULL )
568 LDAP_FREE( lo->ldo_defbase );
569 lo->ldo_defbase = defbase;
570 } return LDAP_OPT_SUCCESS;
572 case LDAP_OPT_ERROR_STRING: {
573 const char *err = (const char *) invalue;
576 /* need a struct ldap */
577 return LDAP_OPT_ERROR;
581 LDAP_FREE(ld->ld_error);
586 ld->ld_error = LDAP_STRDUP(err);
588 } return LDAP_OPT_SUCCESS;
590 case LDAP_OPT_MATCHED_DN: {
591 const char *matched = (const char *) invalue;
594 /* need a struct ldap */
595 return LDAP_OPT_ERROR;
598 if( ld->ld_matched ) {
599 LDAP_FREE(ld->ld_matched);
600 ld->ld_matched = NULL;
604 ld->ld_matched = LDAP_STRDUP( matched );
606 } return LDAP_OPT_SUCCESS;
608 case LDAP_OPT_REFERRAL_URLS: {
609 char *const *referrals = (char *const *) invalue;
612 /* need a struct ldap */
613 return LDAP_OPT_ERROR;
616 if( ld->ld_referrals ) {
617 LDAP_VFREE(ld->ld_referrals);
621 ld->ld_referrals = ldap_value_dup(referrals);
623 } return LDAP_OPT_SUCCESS;
625 /* Only accessed from inside this function by ldap_set_rebind_proc() */
626 case LDAP_OPT_REBIND_PROC: {
627 lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
628 } return LDAP_OPT_SUCCESS;
629 case LDAP_OPT_REBIND_PARAMS: {
630 lo->ldo_rebind_params = (void *)invalue;
631 } return LDAP_OPT_SUCCESS;
633 /* Only accessed from inside this function by ldap_set_nextref_proc() */
634 case LDAP_OPT_NEXTREF_PROC: {
635 lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;
636 } return LDAP_OPT_SUCCESS;
637 case LDAP_OPT_NEXTREF_PARAMS: {
638 lo->ldo_nextref_params = (void *)invalue;
639 } return LDAP_OPT_SUCCESS;
641 /* read-only options */
642 case LDAP_OPT_API_INFO:
644 case LDAP_OPT_API_FEATURE_INFO:
645 return LDAP_OPT_ERROR;
647 /* options which cannot withstand invalue == NULL */
649 case LDAP_OPT_SIZELIMIT:
650 case LDAP_OPT_TIMELIMIT:
651 case LDAP_OPT_PROTOCOL_VERSION:
652 case LDAP_OPT_ERROR_NUMBER:
653 case LDAP_OPT_DEBUG_LEVEL:
654 if(invalue == NULL) {
655 /* no place to set from */
656 return LDAP_OPT_ERROR;
662 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
663 return LDAP_OPT_SUCCESS;
665 #ifdef HAVE_CYRUS_SASL
666 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
667 return LDAP_OPT_SUCCESS;
670 return LDAP_OPT_ERROR;
673 /* options which cannot withstand invalue == NULL */
677 lo->ldo_deref = * (const int *) invalue;
678 return LDAP_OPT_SUCCESS;
680 case LDAP_OPT_SIZELIMIT:
681 lo->ldo_sizelimit = * (const int *) invalue;
682 return LDAP_OPT_SUCCESS;
684 case LDAP_OPT_TIMELIMIT:
685 lo->ldo_timelimit = * (const int *) invalue;
686 return LDAP_OPT_SUCCESS;
688 case LDAP_OPT_PROTOCOL_VERSION: {
689 int vers = * (const int *) invalue;
690 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
694 lo->ldo_version = vers;
695 } return LDAP_OPT_SUCCESS;
697 case LDAP_OPT_ERROR_NUMBER: {
698 int err = * (const int *) invalue;
701 /* need a struct ldap */
706 } return LDAP_OPT_SUCCESS;
708 case LDAP_OPT_DEBUG_LEVEL:
709 lo->ldo_debug = * (const int *) invalue;
710 return LDAP_OPT_SUCCESS;
712 return LDAP_OPT_ERROR;
716 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
719 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
720 if( rc != LDAP_OPT_SUCCESS ) return rc;
722 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
727 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
730 rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
731 if( rc != LDAP_OPT_SUCCESS ) return rc;
733 rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );