2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2004 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 static const LDAPAPIFeatureInfo features[] = {
32 #ifdef LDAP_API_FEATURE_X_OPENLDAP
33 { /* OpenLDAP Extensions API Feature */
34 LDAP_FEATURE_INFO_VERSION,
36 LDAP_API_FEATURE_X_OPENLDAP
40 #ifdef LDAP_API_FEATURE_THREAD_SAFE
41 { /* Basic Thread Safe */
42 LDAP_FEATURE_INFO_VERSION,
44 LDAP_API_FEATURE_THREAD_SAFE
47 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
48 { /* Session Thread Safe */
49 LDAP_FEATURE_INFO_VERSION,
50 "SESSION_THREAD_SAFE",
51 LDAP_API_FEATURE_SESSION_THREAD_SAFE
54 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
55 { /* Operation Thread Safe */
56 LDAP_FEATURE_INFO_VERSION,
57 "OPERATION_THREAD_SAFE",
58 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
61 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
62 { /* OpenLDAP Reentrant */
63 LDAP_FEATURE_INFO_VERSION,
64 "X_OPENLDAP_REENTRANT",
65 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
68 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
69 defined( LDAP_THREAD_SAFE )
70 { /* OpenLDAP Thread Safe */
71 LDAP_FEATURE_INFO_VERSION,
72 "X_OPENLDAP_THREAD_SAFE",
73 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
76 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
78 LDAP_FEATURE_INFO_VERSION,
79 "X_OPENLDAP_V2_REFERRALS",
80 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
92 struct ldapoptions *lo;
94 /* Get pointer to global option structure */
95 lo = LDAP_INT_GLOBAL_OPT();
97 return LDAP_NO_MEMORY;
100 if( lo->ldo_valid != LDAP_INITIALIZED ) {
101 ldap_int_initialize(lo, NULL);
105 assert( LDAP_VALID( ld ) );
107 if( !LDAP_VALID( ld ) ) {
108 return LDAP_OPT_ERROR;
111 lo = &ld->ld_options;
114 if(outvalue == NULL) {
115 /* no place to get to */
116 return LDAP_OPT_ERROR;
120 case LDAP_OPT_API_INFO: {
121 struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
124 /* outvalue must point to an apiinfo structure */
125 return LDAP_OPT_ERROR;
128 if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
129 /* api info version mismatch */
130 info->ldapai_info_version = LDAP_API_INFO_VERSION;
131 return LDAP_OPT_ERROR;
134 info->ldapai_api_version = LDAP_API_VERSION;
135 info->ldapai_protocol_version = LDAP_VERSION_MAX;
137 if(features[0].ldapaif_name == NULL) {
138 info->ldapai_extensions = NULL;
141 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
142 sizeof(features)/sizeof(LDAPAPIFeatureInfo));
144 for(i=0; features[i].ldapaif_name != NULL; i++) {
145 info->ldapai_extensions[i] =
146 LDAP_STRDUP(features[i].ldapaif_name);
149 info->ldapai_extensions[i] = NULL;
152 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
153 info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
155 return LDAP_OPT_SUCCESS;
159 if( ld == NULL || ld->ld_sb == NULL ) {
164 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
165 return LDAP_OPT_SUCCESS;
167 case LDAP_OPT_SOCKBUF:
168 if( ld == NULL ) break;
169 outvalue = ld->ld_sb;
170 return LDAP_OPT_SUCCESS;
172 case LDAP_OPT_TIMEOUT:
173 /* the caller has to free outvalue ! */
174 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 ) {
175 return LDAP_OPT_ERROR;
177 return LDAP_OPT_SUCCESS;
179 case LDAP_OPT_NETWORK_TIMEOUT:
180 /* the caller has to free outvalue ! */
181 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 ) {
182 return LDAP_OPT_ERROR;
184 return LDAP_OPT_SUCCESS;
187 * (int *) outvalue = lo->ldo_deref;
188 return LDAP_OPT_SUCCESS;
190 case LDAP_OPT_SIZELIMIT:
191 * (int *) outvalue = lo->ldo_sizelimit;
192 return LDAP_OPT_SUCCESS;
194 case LDAP_OPT_TIMELIMIT:
195 * (int *) outvalue = lo->ldo_timelimit;
196 return LDAP_OPT_SUCCESS;
198 case LDAP_OPT_REFERRALS:
199 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
200 return LDAP_OPT_SUCCESS;
202 case LDAP_OPT_RESTART:
203 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
204 return LDAP_OPT_SUCCESS;
206 case LDAP_OPT_PROTOCOL_VERSION:
207 * (int *) outvalue = lo->ldo_version;
208 return LDAP_OPT_SUCCESS;
210 case LDAP_OPT_SERVER_CONTROLS:
211 * (LDAPControl ***) outvalue =
212 ldap_controls_dup( lo->ldo_sctrls );
214 return LDAP_OPT_SUCCESS;
216 case LDAP_OPT_CLIENT_CONTROLS:
217 * (LDAPControl ***) outvalue =
218 ldap_controls_dup( lo->ldo_cctrls );
220 return LDAP_OPT_SUCCESS;
222 case LDAP_OPT_HOST_NAME:
223 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
224 return LDAP_OPT_SUCCESS;
227 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
228 return LDAP_OPT_SUCCESS;
230 case LDAP_OPT_ERROR_NUMBER:
235 * (int *) outvalue = ld->ld_errno;
236 return LDAP_OPT_SUCCESS;
238 case LDAP_OPT_ERROR_STRING:
244 if( ld->ld_error == NULL ) {
245 * (char **) outvalue = NULL;
247 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
250 return LDAP_OPT_SUCCESS;
252 case LDAP_OPT_MATCHED_DN:
258 if( ld->ld_matched == NULL ) {
259 * (char **) outvalue = NULL;
261 * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
264 return LDAP_OPT_SUCCESS;
266 case LDAP_OPT_REFERRAL_URLS:
272 if( ld->ld_referrals == NULL ) {
273 * (char ***) outvalue = NULL;
275 * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
278 return LDAP_OPT_SUCCESS;
280 case LDAP_OPT_API_FEATURE_INFO: {
281 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
284 if(info == NULL) return LDAP_OPT_ERROR;
286 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
287 /* api info version mismatch */
288 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
289 return LDAP_OPT_ERROR;
292 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
294 for(i=0; features[i].ldapaif_name != NULL; i++) {
295 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
296 info->ldapaif_version =
297 features[i].ldapaif_version;
298 return LDAP_OPT_SUCCESS;
304 case LDAP_OPT_DEBUG_LEVEL:
305 * (int *) outvalue = lo->ldo_debug;
306 return LDAP_OPT_SUCCESS;
310 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
311 return LDAP_OPT_SUCCESS;
314 #ifdef HAVE_CYRUS_SASL
315 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
316 return LDAP_OPT_SUCCESS;
323 return LDAP_OPT_ERROR;
330 LDAP_CONST void *invalue)
332 struct ldapoptions *lo;
335 /* Get pointer to global option structure */
336 lo = LDAP_INT_GLOBAL_OPT();
338 return LDAP_NO_MEMORY;
342 * The architecture to turn on debugging has a chicken and egg
343 * problem. Thus, we introduce a fix here.
346 if (option == LDAP_OPT_DEBUG_LEVEL) {
347 dbglvl = (int *) invalue;
350 if( lo->ldo_valid != LDAP_INITIALIZED ) {
351 ldap_int_initialize(lo, dbglvl);
355 assert( LDAP_VALID( ld ) );
357 if( !LDAP_VALID( ld ) ) {
358 return LDAP_OPT_ERROR;
361 lo = &ld->ld_options;
365 case LDAP_OPT_REFERRALS:
366 if(invalue == LDAP_OPT_OFF) {
367 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
369 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
371 return LDAP_OPT_SUCCESS;
373 case LDAP_OPT_RESTART:
374 if(invalue == LDAP_OPT_OFF) {
375 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
377 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
379 return LDAP_OPT_SUCCESS;
382 /* options which can withstand invalue == NULL */
384 case LDAP_OPT_SERVER_CONTROLS: {
385 LDAPControl *const *controls =
386 (LDAPControl *const *) invalue;
388 ldap_controls_free( lo->ldo_sctrls );
390 if( controls == NULL || *controls == NULL ) {
391 lo->ldo_sctrls = NULL;
392 return LDAP_OPT_SUCCESS;
395 lo->ldo_sctrls = ldap_controls_dup( controls );
397 if(lo->ldo_sctrls == NULL) {
398 /* memory allocation error ? */
401 } return LDAP_OPT_SUCCESS;
403 case LDAP_OPT_CLIENT_CONTROLS: {
404 LDAPControl *const *controls =
405 (LDAPControl *const *) invalue;
407 ldap_controls_free( lo->ldo_cctrls );
409 if( controls == NULL || *controls == NULL ) {
410 lo->ldo_cctrls = NULL;
411 return LDAP_OPT_SUCCESS;
414 lo->ldo_cctrls = ldap_controls_dup( controls );
416 if(lo->ldo_cctrls == NULL) {
417 /* memory allocation error ? */
420 } return LDAP_OPT_SUCCESS;
422 case LDAP_OPT_TIMEOUT: {
423 const struct timeval *tv =
424 (const struct timeval *) invalue;
426 if ( lo->ldo_tm_api != NULL ) {
427 LDAP_FREE( lo->ldo_tm_api );
428 lo->ldo_tm_api = NULL;
431 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
432 return LDAP_OPT_ERROR;
434 } return LDAP_OPT_SUCCESS;
436 case LDAP_OPT_NETWORK_TIMEOUT: {
437 const struct timeval *tv =
438 (const struct timeval *) invalue;
440 if ( lo->ldo_tm_net != NULL ) {
441 LDAP_FREE( lo->ldo_tm_net );
442 lo->ldo_tm_net = NULL;
445 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
446 return LDAP_OPT_ERROR;
448 } return LDAP_OPT_SUCCESS;
450 /* Only accessed from inside this function by ldap_set_rebind_proc() */
451 case LDAP_OPT_REBIND_PROC: {
452 lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
453 } return LDAP_OPT_SUCCESS;
454 case LDAP_OPT_REBIND_PARAMS: {
455 lo->ldo_rebind_params = (void *)invalue;
456 } return LDAP_OPT_SUCCESS;
459 if(invalue == NULL) {
460 /* no place to set from */
461 return LDAP_OPT_ERROR;
464 /* options which cannot withstand invalue == NULL */
467 case LDAP_OPT_API_INFO:
473 lo->ldo_deref = * (const int *) invalue;
474 return LDAP_OPT_SUCCESS;
476 case LDAP_OPT_SIZELIMIT:
477 lo->ldo_sizelimit = * (const int *) invalue;
478 return LDAP_OPT_SUCCESS;
480 case LDAP_OPT_TIMELIMIT:
481 lo->ldo_timelimit = * (const int *) invalue;
482 return LDAP_OPT_SUCCESS;
484 case LDAP_OPT_PROTOCOL_VERSION: {
485 int vers = * (const int *) invalue;
486 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
490 lo->ldo_version = vers;
491 } return LDAP_OPT_SUCCESS;
494 case LDAP_OPT_HOST_NAME: {
495 const char *host = (const char *) invalue;
496 LDAPURLDesc *ludlist = NULL;
497 int rc = LDAP_OPT_SUCCESS;
500 rc = ldap_url_parsehosts( &ludlist, host,
501 lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
503 } else if(ld == NULL) {
505 * must want global default returned
506 * to initial condition.
508 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
512 * must want the session default
513 * updated to the current global default
515 ludlist = ldap_url_duplist(
516 ldap_int_global_options.ldo_defludp);
521 if (rc == LDAP_OPT_SUCCESS) {
522 if (lo->ldo_defludp != NULL)
523 ldap_free_urllist(lo->ldo_defludp);
524 lo->ldo_defludp = ludlist;
530 const char *urls = (const char *) invalue;
531 LDAPURLDesc *ludlist = NULL;
532 int rc = LDAP_OPT_SUCCESS;
535 rc = ldap_url_parselist(&ludlist, urls);
536 } else if(ld == NULL) {
538 * must want global default returned
539 * to initial condition.
541 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
545 * must want the session default
546 * updated to the current global default
548 ludlist = ldap_url_duplist(
549 ldap_int_global_options.ldo_defludp);
555 case LDAP_URL_SUCCESS: /* Success */
559 case LDAP_URL_ERR_MEM: /* can't allocate memory space */
563 case LDAP_URL_ERR_PARAM: /* parameter is bad */
564 case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */
565 case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
566 case LDAP_URL_ERR_BADURL: /* URL is bad */
567 case LDAP_URL_ERR_BADHOST: /* host port is bad */
568 case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */
569 case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */
570 case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */
571 case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */
572 rc = LDAP_PARAM_ERROR;
576 if (rc == LDAP_OPT_SUCCESS) {
577 if (lo->ldo_defludp != NULL)
578 ldap_free_urllist(lo->ldo_defludp);
579 lo->ldo_defludp = ludlist;
584 case LDAP_OPT_ERROR_NUMBER: {
585 int err = * (const int *) invalue;
588 /* need a struct ldap */
593 } return LDAP_OPT_SUCCESS;
595 case LDAP_OPT_ERROR_STRING: {
596 const char *err = (const char *) invalue;
599 /* need a struct ldap */
604 LDAP_FREE(ld->ld_error);
607 ld->ld_error = LDAP_STRDUP(err);
608 } return LDAP_OPT_SUCCESS;
610 case LDAP_OPT_MATCHED_DN: {
611 const char *err = (const char *) invalue;
614 /* need a struct ldap */
618 if( ld->ld_matched ) {
619 LDAP_FREE(ld->ld_matched);
622 ld->ld_matched = LDAP_STRDUP(err);
623 } return LDAP_OPT_SUCCESS;
625 case LDAP_OPT_REFERRAL_URLS: {
626 char *const *referrals = (char *const *) invalue;
629 /* need a struct ldap */
633 if( ld->ld_referrals ) {
634 LDAP_VFREE(ld->ld_referrals);
637 ld->ld_referrals = ldap_value_dup(referrals);
638 } return LDAP_OPT_SUCCESS;
640 case LDAP_OPT_API_FEATURE_INFO:
644 case LDAP_OPT_DEBUG_LEVEL:
645 lo->ldo_debug = * (const int *) invalue;
646 return LDAP_OPT_SUCCESS;
650 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
651 return LDAP_OPT_SUCCESS;
653 #ifdef HAVE_CYRUS_SASL
654 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
655 return LDAP_OPT_SUCCESS;
660 return LDAP_OPT_ERROR;
664 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
667 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
668 if( rc != LDAP_OPT_SUCCESS ) return rc;
670 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );