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_api_version = LDAP_API_VERSION;
136 info->ldapai_protocol_version = LDAP_VERSION_MAX;
138 if(features[0].ldapaif_name == NULL) {
139 info->ldapai_extensions = NULL;
142 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
143 sizeof(features)/sizeof(LDAPAPIFeatureInfo));
145 for(i=0; features[i].ldapaif_name != NULL; i++) {
146 info->ldapai_extensions[i] =
147 LDAP_STRDUP(features[i].ldapaif_name);
150 info->ldapai_extensions[i] = NULL;
153 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
154 info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
156 return LDAP_OPT_SUCCESS;
160 if( ld == NULL || ld->ld_sb == NULL ) {
165 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
166 return LDAP_OPT_SUCCESS;
168 case LDAP_OPT_SOCKBUF:
169 if( ld == NULL ) break;
170 outvalue = ld->ld_sb;
171 return LDAP_OPT_SUCCESS;
173 case LDAP_OPT_TIMEOUT:
174 /* the caller has to free outvalue ! */
175 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 ) {
176 return LDAP_OPT_ERROR;
178 return LDAP_OPT_SUCCESS;
180 case LDAP_OPT_NETWORK_TIMEOUT:
181 /* the caller has to free outvalue ! */
182 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 ) {
183 return LDAP_OPT_ERROR;
185 return LDAP_OPT_SUCCESS;
188 * (int *) outvalue = lo->ldo_deref;
189 return LDAP_OPT_SUCCESS;
191 case LDAP_OPT_SIZELIMIT:
192 * (int *) outvalue = lo->ldo_sizelimit;
193 return LDAP_OPT_SUCCESS;
195 case LDAP_OPT_TIMELIMIT:
196 * (int *) outvalue = lo->ldo_timelimit;
197 return LDAP_OPT_SUCCESS;
199 case LDAP_OPT_REFERRALS:
200 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
201 return LDAP_OPT_SUCCESS;
203 case LDAP_OPT_RESTART:
204 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
205 return LDAP_OPT_SUCCESS;
207 case LDAP_OPT_PROTOCOL_VERSION:
208 * (int *) outvalue = lo->ldo_version;
209 return LDAP_OPT_SUCCESS;
211 case LDAP_OPT_SERVER_CONTROLS:
212 * (LDAPControl ***) outvalue =
213 ldap_controls_dup( lo->ldo_sctrls );
215 return LDAP_OPT_SUCCESS;
217 case LDAP_OPT_CLIENT_CONTROLS:
218 * (LDAPControl ***) outvalue =
219 ldap_controls_dup( lo->ldo_cctrls );
221 return LDAP_OPT_SUCCESS;
223 case LDAP_OPT_HOST_NAME:
224 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
225 return LDAP_OPT_SUCCESS;
228 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
229 return LDAP_OPT_SUCCESS;
231 case LDAP_OPT_ERROR_NUMBER:
236 * (int *) outvalue = ld->ld_errno;
237 return LDAP_OPT_SUCCESS;
239 case LDAP_OPT_ERROR_STRING:
245 if( ld->ld_error == NULL ) {
246 * (char **) outvalue = NULL;
248 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
251 return LDAP_OPT_SUCCESS;
253 case LDAP_OPT_MATCHED_DN:
259 if( ld->ld_matched == NULL ) {
260 * (char **) outvalue = NULL;
262 * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
265 return LDAP_OPT_SUCCESS;
267 case LDAP_OPT_REFERRAL_URLS:
273 if( ld->ld_referrals == NULL ) {
274 * (char ***) outvalue = NULL;
276 * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
279 return LDAP_OPT_SUCCESS;
281 case LDAP_OPT_API_FEATURE_INFO: {
282 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
285 if(info == NULL) return LDAP_OPT_ERROR;
287 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
288 /* api info version mismatch */
289 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
290 return LDAP_OPT_ERROR;
293 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
295 for(i=0; features[i].ldapaif_name != NULL; i++) {
296 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
297 info->ldapaif_version =
298 features[i].ldapaif_version;
299 return LDAP_OPT_SUCCESS;
305 case LDAP_OPT_DEBUG_LEVEL:
306 * (int *) outvalue = lo->ldo_debug;
307 return LDAP_OPT_SUCCESS;
311 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
312 return LDAP_OPT_SUCCESS;
315 #ifdef HAVE_CYRUS_SASL
316 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
317 return LDAP_OPT_SUCCESS;
324 return LDAP_OPT_ERROR;
331 LDAP_CONST void *invalue)
333 struct ldapoptions *lo;
336 /* Get pointer to global option structure */
337 lo = LDAP_INT_GLOBAL_OPT();
339 return LDAP_NO_MEMORY;
343 * The architecture to turn on debugging has a chicken and egg
344 * problem. Thus, we introduce a fix here.
347 if (option == LDAP_OPT_DEBUG_LEVEL) {
348 dbglvl = (int *) invalue;
351 if( lo->ldo_valid != LDAP_INITIALIZED ) {
352 ldap_int_initialize(lo, dbglvl);
356 assert( LDAP_VALID( ld ) );
358 if( !LDAP_VALID( ld ) ) {
359 return LDAP_OPT_ERROR;
362 lo = &ld->ld_options;
366 case LDAP_OPT_REFERRALS:
367 if(invalue == LDAP_OPT_OFF) {
368 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
370 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
372 return LDAP_OPT_SUCCESS;
374 case LDAP_OPT_RESTART:
375 if(invalue == LDAP_OPT_OFF) {
376 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
378 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
380 return LDAP_OPT_SUCCESS;
383 /* options which can withstand invalue == NULL */
385 case LDAP_OPT_SERVER_CONTROLS: {
386 LDAPControl *const *controls =
387 (LDAPControl *const *) invalue;
389 ldap_controls_free( lo->ldo_sctrls );
391 if( controls == NULL || *controls == NULL ) {
392 lo->ldo_sctrls = NULL;
393 return LDAP_OPT_SUCCESS;
396 lo->ldo_sctrls = ldap_controls_dup( controls );
398 if(lo->ldo_sctrls == NULL) {
399 /* memory allocation error ? */
402 } return LDAP_OPT_SUCCESS;
404 case LDAP_OPT_CLIENT_CONTROLS: {
405 LDAPControl *const *controls =
406 (LDAPControl *const *) invalue;
408 ldap_controls_free( lo->ldo_cctrls );
410 if( controls == NULL || *controls == NULL ) {
411 lo->ldo_cctrls = NULL;
412 return LDAP_OPT_SUCCESS;
415 lo->ldo_cctrls = ldap_controls_dup( controls );
417 if(lo->ldo_cctrls == NULL) {
418 /* memory allocation error ? */
421 } return LDAP_OPT_SUCCESS;
423 case LDAP_OPT_TIMEOUT: {
424 const struct timeval *tv =
425 (const struct timeval *) invalue;
427 if ( lo->ldo_tm_api != NULL ) {
428 LDAP_FREE( lo->ldo_tm_api );
429 lo->ldo_tm_api = NULL;
432 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
433 return LDAP_OPT_ERROR;
435 } return LDAP_OPT_SUCCESS;
437 case LDAP_OPT_NETWORK_TIMEOUT: {
438 const struct timeval *tv =
439 (const struct timeval *) invalue;
441 if ( lo->ldo_tm_net != NULL ) {
442 LDAP_FREE( lo->ldo_tm_net );
443 lo->ldo_tm_net = NULL;
446 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
447 return LDAP_OPT_ERROR;
449 } return LDAP_OPT_SUCCESS;
451 /* Only accessed from inside this function by ldap_set_rebind_proc() */
452 case LDAP_OPT_REBIND_PROC: {
453 lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
454 } return LDAP_OPT_SUCCESS;
455 case LDAP_OPT_REBIND_PARAMS: {
456 lo->ldo_rebind_params = (void *)invalue;
457 } return LDAP_OPT_SUCCESS;
460 if(invalue == NULL) {
461 /* no place to set from */
462 return LDAP_OPT_ERROR;
465 /* options which cannot withstand invalue == NULL */
468 case LDAP_OPT_API_INFO:
474 lo->ldo_deref = * (const int *) invalue;
475 return LDAP_OPT_SUCCESS;
477 case LDAP_OPT_SIZELIMIT:
478 lo->ldo_sizelimit = * (const int *) invalue;
479 return LDAP_OPT_SUCCESS;
481 case LDAP_OPT_TIMELIMIT:
482 lo->ldo_timelimit = * (const int *) invalue;
483 return LDAP_OPT_SUCCESS;
485 case LDAP_OPT_PROTOCOL_VERSION: {
486 int vers = * (const int *) invalue;
487 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
491 lo->ldo_version = vers;
492 } return LDAP_OPT_SUCCESS;
495 case LDAP_OPT_HOST_NAME: {
496 const char *host = (const char *) invalue;
497 LDAPURLDesc *ludlist = NULL;
498 int rc = LDAP_OPT_SUCCESS;
501 rc = ldap_url_parsehosts( &ludlist, host,
502 lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
504 } else if(ld == NULL) {
506 * must want global default returned
507 * to initial condition.
509 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
513 * must want the session default
514 * updated to the current global default
516 ludlist = ldap_url_duplist(
517 ldap_int_global_options.ldo_defludp);
522 if (rc == LDAP_OPT_SUCCESS) {
523 if (lo->ldo_defludp != NULL)
524 ldap_free_urllist(lo->ldo_defludp);
525 lo->ldo_defludp = ludlist;
531 const char *urls = (const char *) invalue;
532 LDAPURLDesc *ludlist = NULL;
533 int rc = LDAP_OPT_SUCCESS;
536 rc = ldap_url_parselist(&ludlist, urls);
537 } else if(ld == NULL) {
539 * must want global default returned
540 * to initial condition.
542 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
546 * must want the session default
547 * updated to the current global default
549 ludlist = ldap_url_duplist(
550 ldap_int_global_options.ldo_defludp);
556 case LDAP_URL_SUCCESS: /* Success */
560 case LDAP_URL_ERR_MEM: /* can't allocate memory space */
564 case LDAP_URL_ERR_PARAM: /* parameter is bad */
565 case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */
566 case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
567 case LDAP_URL_ERR_BADURL: /* URL is bad */
568 case LDAP_URL_ERR_BADHOST: /* host port is bad */
569 case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */
570 case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */
571 case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */
572 case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */
573 rc = LDAP_PARAM_ERROR;
577 if (rc == LDAP_OPT_SUCCESS) {
578 if (lo->ldo_defludp != NULL)
579 ldap_free_urllist(lo->ldo_defludp);
580 lo->ldo_defludp = ludlist;
585 case LDAP_OPT_ERROR_NUMBER: {
586 int err = * (const int *) invalue;
589 /* need a struct ldap */
594 } return LDAP_OPT_SUCCESS;
596 case LDAP_OPT_ERROR_STRING: {
597 const char *err = (const char *) invalue;
600 /* need a struct ldap */
605 LDAP_FREE(ld->ld_error);
608 ld->ld_error = LDAP_STRDUP(err);
609 } return LDAP_OPT_SUCCESS;
611 case LDAP_OPT_MATCHED_DN: {
612 const char *err = (const char *) invalue;
615 /* need a struct ldap */
619 if( ld->ld_matched ) {
620 LDAP_FREE(ld->ld_matched);
623 ld->ld_matched = LDAP_STRDUP(err);
624 } return LDAP_OPT_SUCCESS;
626 case LDAP_OPT_REFERRAL_URLS: {
627 char *const *referrals = (char *const *) invalue;
630 /* need a struct ldap */
634 if( ld->ld_referrals ) {
635 LDAP_VFREE(ld->ld_referrals);
638 ld->ld_referrals = ldap_value_dup(referrals);
639 } return LDAP_OPT_SUCCESS;
641 case LDAP_OPT_API_FEATURE_INFO:
645 case LDAP_OPT_DEBUG_LEVEL:
646 lo->ldo_debug = * (const int *) invalue;
647 return LDAP_OPT_SUCCESS;
651 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
652 return LDAP_OPT_SUCCESS;
654 #ifdef HAVE_CYRUS_SASL
655 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
656 return LDAP_OPT_SUCCESS;
661 return LDAP_OPT_ERROR;
665 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
668 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
669 if( rc != LDAP_OPT_SUCCESS ) return rc;
671 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );