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_ERROR_NUMBER:
238 * (int *) outvalue = ld->ld_errno;
239 return LDAP_OPT_SUCCESS;
241 case LDAP_OPT_ERROR_STRING:
247 if( ld->ld_error == NULL ) {
248 * (char **) outvalue = NULL;
250 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
253 return LDAP_OPT_SUCCESS;
255 case LDAP_OPT_MATCHED_DN:
261 if( ld->ld_matched == NULL ) {
262 * (char **) outvalue = NULL;
264 * (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
267 return LDAP_OPT_SUCCESS;
269 case LDAP_OPT_REFERRAL_URLS:
275 if( ld->ld_referrals == NULL ) {
276 * (char ***) outvalue = NULL;
278 * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
281 return LDAP_OPT_SUCCESS;
283 case LDAP_OPT_API_FEATURE_INFO: {
284 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
287 if(info == NULL) return LDAP_OPT_ERROR;
289 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
290 /* api info version mismatch */
291 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
292 return LDAP_OPT_ERROR;
295 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
297 for(i=0; features[i].ldapaif_name != NULL; i++) {
298 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
299 info->ldapaif_version =
300 features[i].ldapaif_version;
301 return LDAP_OPT_SUCCESS;
307 case LDAP_OPT_DEBUG_LEVEL:
308 * (int *) outvalue = lo->ldo_debug;
309 return LDAP_OPT_SUCCESS;
313 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
314 return LDAP_OPT_SUCCESS;
317 #ifdef HAVE_CYRUS_SASL
318 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
319 return LDAP_OPT_SUCCESS;
326 return LDAP_OPT_ERROR;
333 LDAP_CONST void *invalue)
335 struct ldapoptions *lo;
338 /* Get pointer to global option structure */
339 lo = LDAP_INT_GLOBAL_OPT();
341 return LDAP_NO_MEMORY;
345 * The architecture to turn on debugging has a chicken and egg
346 * problem. Thus, we introduce a fix here.
349 if (option == LDAP_OPT_DEBUG_LEVEL) {
350 dbglvl = (int *) invalue;
353 if( lo->ldo_valid != LDAP_INITIALIZED ) {
354 ldap_int_initialize(lo, dbglvl);
358 assert( LDAP_VALID( ld ) );
360 if( !LDAP_VALID( ld ) ) {
361 return LDAP_OPT_ERROR;
364 lo = &ld->ld_options;
368 case LDAP_OPT_REFERRALS:
369 if(invalue == LDAP_OPT_OFF) {
370 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
372 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
374 return LDAP_OPT_SUCCESS;
376 case LDAP_OPT_RESTART:
377 if(invalue == LDAP_OPT_OFF) {
378 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
380 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
382 return LDAP_OPT_SUCCESS;
385 /* options which can withstand invalue == NULL */
387 case LDAP_OPT_SERVER_CONTROLS: {
388 LDAPControl *const *controls =
389 (LDAPControl *const *) invalue;
392 ldap_controls_free( lo->ldo_sctrls );
394 if( controls == NULL || *controls == NULL ) {
395 lo->ldo_sctrls = NULL;
396 return LDAP_OPT_SUCCESS;
399 lo->ldo_sctrls = ldap_controls_dup( controls );
401 if(lo->ldo_sctrls == NULL) {
402 /* memory allocation error ? */
405 } return LDAP_OPT_SUCCESS;
407 case LDAP_OPT_CLIENT_CONTROLS: {
408 LDAPControl *const *controls =
409 (LDAPControl *const *) invalue;
412 ldap_controls_free( lo->ldo_cctrls );
414 if( controls == NULL || *controls == NULL ) {
415 lo->ldo_cctrls = NULL;
416 return LDAP_OPT_SUCCESS;
419 lo->ldo_cctrls = ldap_controls_dup( controls );
421 if(lo->ldo_cctrls == NULL) {
422 /* memory allocation error ? */
425 } return LDAP_OPT_SUCCESS;
427 case LDAP_OPT_TIMEOUT: {
428 const struct timeval *tv =
429 (const struct timeval *) invalue;
431 if ( lo->ldo_tm_api != NULL ) {
432 LDAP_FREE( lo->ldo_tm_api );
433 lo->ldo_tm_api = NULL;
436 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
437 return LDAP_OPT_ERROR;
439 } return LDAP_OPT_SUCCESS;
441 case LDAP_OPT_NETWORK_TIMEOUT: {
442 const struct timeval *tv =
443 (const struct timeval *) invalue;
445 if ( lo->ldo_tm_net != NULL ) {
446 LDAP_FREE( lo->ldo_tm_net );
447 lo->ldo_tm_net = NULL;
450 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
451 return LDAP_OPT_ERROR;
453 } return LDAP_OPT_SUCCESS;
455 case LDAP_OPT_HOST_NAME: {
456 const char *host = (const char *) invalue;
457 LDAPURLDesc *ludlist = NULL;
458 int rc = LDAP_OPT_SUCCESS;
461 rc = ldap_url_parsehosts( &ludlist, host,
462 lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
464 } else if(ld == NULL) {
466 * must want global default returned
467 * to initial condition.
469 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
473 * must want the session default
474 * updated to the current global default
476 ludlist = ldap_url_duplist(
477 ldap_int_global_options.ldo_defludp);
482 if (rc == LDAP_OPT_SUCCESS) {
483 if (lo->ldo_defludp != NULL)
484 ldap_free_urllist(lo->ldo_defludp);
485 lo->ldo_defludp = ludlist;
491 const char *urls = (const char *) invalue;
492 LDAPURLDesc *ludlist = NULL;
493 int rc = LDAP_OPT_SUCCESS;
496 rc = ldap_url_parselist(&ludlist, urls);
497 } else if(ld == NULL) {
499 * must want global default returned
500 * to initial condition.
502 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
506 * must want the session default
507 * updated to the current global default
509 ludlist = ldap_url_duplist(
510 ldap_int_global_options.ldo_defludp);
516 case LDAP_URL_SUCCESS: /* Success */
520 case LDAP_URL_ERR_MEM: /* can't allocate memory space */
524 case LDAP_URL_ERR_PARAM: /* parameter is bad */
525 case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */
526 case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
527 case LDAP_URL_ERR_BADURL: /* URL is bad */
528 case LDAP_URL_ERR_BADHOST: /* host port is bad */
529 case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */
530 case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */
531 case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */
532 case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */
533 rc = LDAP_PARAM_ERROR;
537 if (rc == LDAP_OPT_SUCCESS) {
538 if (lo->ldo_defludp != NULL)
539 ldap_free_urllist(lo->ldo_defludp);
540 lo->ldo_defludp = ludlist;
545 case LDAP_OPT_ERROR_STRING: {
546 const char *err = (const char *) invalue;
549 /* need a struct ldap */
550 return LDAP_OPT_ERROR;
554 LDAP_FREE(ld->ld_error);
559 ld->ld_error = LDAP_STRDUP(err);
561 } return LDAP_OPT_SUCCESS;
563 case LDAP_OPT_MATCHED_DN: {
564 const char *matched = (const char *) invalue;
567 /* need a struct ldap */
568 return LDAP_OPT_ERROR;
571 if( ld->ld_matched ) {
572 LDAP_FREE(ld->ld_matched);
573 ld->ld_matched = NULL;
577 ld->ld_matched = LDAP_STRDUP( matched );
579 } return LDAP_OPT_SUCCESS;
581 case LDAP_OPT_REFERRAL_URLS: {
582 char *const *referrals = (char *const *) invalue;
585 /* need a struct ldap */
586 return LDAP_OPT_ERROR;
589 if( ld->ld_referrals ) {
590 LDAP_VFREE(ld->ld_referrals);
594 ld->ld_referrals = ldap_value_dup(referrals);
596 } return LDAP_OPT_SUCCESS;
598 /* Only accessed from inside this function by ldap_set_rebind_proc() */
599 case LDAP_OPT_REBIND_PROC: {
600 lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
601 } return LDAP_OPT_SUCCESS;
602 case LDAP_OPT_REBIND_PARAMS: {
603 lo->ldo_rebind_params = (void *)invalue;
604 } return LDAP_OPT_SUCCESS;
606 /* Only accessed from inside this function by ldap_set_nextref_proc() */
607 case LDAP_OPT_NEXTREF_PROC: {
608 lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;
609 } return LDAP_OPT_SUCCESS;
610 case LDAP_OPT_NEXTREF_PARAMS: {
611 lo->ldo_nextref_params = (void *)invalue;
612 } return LDAP_OPT_SUCCESS;
614 /* read-only options */
615 case LDAP_OPT_API_INFO:
617 case LDAP_OPT_API_FEATURE_INFO:
618 return LDAP_OPT_ERROR;
620 /* options which cannot withstand invalue == NULL */
622 case LDAP_OPT_SIZELIMIT:
623 case LDAP_OPT_TIMELIMIT:
624 case LDAP_OPT_PROTOCOL_VERSION:
625 case LDAP_OPT_ERROR_NUMBER:
626 case LDAP_OPT_DEBUG_LEVEL:
627 if(invalue == NULL) {
628 /* no place to set from */
629 return LDAP_OPT_ERROR;
635 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
636 return LDAP_OPT_SUCCESS;
638 #ifdef HAVE_CYRUS_SASL
639 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
640 return LDAP_OPT_SUCCESS;
643 return LDAP_OPT_ERROR;
646 /* options which cannot withstand invalue == NULL */
650 lo->ldo_deref = * (const int *) invalue;
651 return LDAP_OPT_SUCCESS;
653 case LDAP_OPT_SIZELIMIT:
654 lo->ldo_sizelimit = * (const int *) invalue;
655 return LDAP_OPT_SUCCESS;
657 case LDAP_OPT_TIMELIMIT:
658 lo->ldo_timelimit = * (const int *) invalue;
659 return LDAP_OPT_SUCCESS;
661 case LDAP_OPT_PROTOCOL_VERSION: {
662 int vers = * (const int *) invalue;
663 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
667 lo->ldo_version = vers;
668 } return LDAP_OPT_SUCCESS;
670 case LDAP_OPT_ERROR_NUMBER: {
671 int err = * (const int *) invalue;
674 /* need a struct ldap */
679 } return LDAP_OPT_SUCCESS;
681 case LDAP_OPT_DEBUG_LEVEL:
682 lo->ldo_debug = * (const int *) invalue;
683 return LDAP_OPT_SUCCESS;
685 return LDAP_OPT_ERROR;
689 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
692 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
693 if( rc != LDAP_OPT_SUCCESS ) return rc;
695 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
700 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
703 rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
704 if( rc != LDAP_OPT_SUCCESS ) return rc;
706 rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );