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_TIMEOUT:
169 /* the caller has to free outvalue ! */
170 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 ) {
171 return LDAP_OPT_ERROR;
173 return LDAP_OPT_SUCCESS;
175 case LDAP_OPT_NETWORK_TIMEOUT:
176 /* the caller has to free outvalue ! */
177 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 ) {
178 return LDAP_OPT_ERROR;
180 return LDAP_OPT_SUCCESS;
183 * (int *) outvalue = lo->ldo_deref;
184 return LDAP_OPT_SUCCESS;
186 case LDAP_OPT_SIZELIMIT:
187 * (int *) outvalue = lo->ldo_sizelimit;
188 return LDAP_OPT_SUCCESS;
190 case LDAP_OPT_TIMELIMIT:
191 * (int *) outvalue = lo->ldo_timelimit;
192 return LDAP_OPT_SUCCESS;
194 case LDAP_OPT_REFERRALS:
195 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
196 return LDAP_OPT_SUCCESS;
198 case LDAP_OPT_RESTART:
199 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
200 return LDAP_OPT_SUCCESS;
202 case LDAP_OPT_PROTOCOL_VERSION:
203 * (int *) outvalue = lo->ldo_version;
204 return LDAP_OPT_SUCCESS;
206 case LDAP_OPT_SERVER_CONTROLS:
207 * (LDAPControl ***) outvalue =
208 ldap_controls_dup( lo->ldo_sctrls );
210 return LDAP_OPT_SUCCESS;
212 case LDAP_OPT_CLIENT_CONTROLS:
213 * (LDAPControl ***) outvalue =
214 ldap_controls_dup( lo->ldo_cctrls );
216 return LDAP_OPT_SUCCESS;
218 case LDAP_OPT_HOST_NAME:
219 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
220 return LDAP_OPT_SUCCESS;
223 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
224 return LDAP_OPT_SUCCESS;
226 case LDAP_OPT_ERROR_NUMBER:
231 * (int *) outvalue = ld->ld_errno;
232 return LDAP_OPT_SUCCESS;
234 case LDAP_OPT_ERROR_STRING:
240 if( ld->ld_error == NULL ) {
241 * (char **) outvalue = NULL;
243 * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
246 return LDAP_OPT_SUCCESS;
248 case LDAP_OPT_MATCHED_DN:
254 if( ld->ld_matched == NULL ) {
255 * (char **) outvalue = NULL;
257 * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
260 return LDAP_OPT_SUCCESS;
262 case LDAP_OPT_REFERRAL_URLS:
268 if( ld->ld_referrals == NULL ) {
269 * (char ***) outvalue = NULL;
271 * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
274 return LDAP_OPT_SUCCESS;
276 case LDAP_OPT_API_FEATURE_INFO: {
277 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
280 if(info == NULL) return LDAP_OPT_ERROR;
282 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
283 /* api info version mismatch */
284 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
285 return LDAP_OPT_ERROR;
288 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
290 for(i=0; features[i].ldapaif_name != NULL; i++) {
291 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
292 info->ldapaif_version =
293 features[i].ldapaif_version;
294 return LDAP_OPT_SUCCESS;
300 case LDAP_OPT_DEBUG_LEVEL:
301 * (int *) outvalue = lo->ldo_debug;
302 return LDAP_OPT_SUCCESS;
306 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
307 return LDAP_OPT_SUCCESS;
310 #ifdef HAVE_CYRUS_SASL
311 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
312 return LDAP_OPT_SUCCESS;
319 return LDAP_OPT_ERROR;
326 LDAP_CONST void *invalue)
328 struct ldapoptions *lo;
331 /* Get pointer to global option structure */
332 lo = LDAP_INT_GLOBAL_OPT();
334 return LDAP_NO_MEMORY;
338 * The architecture to turn on debugging has a chicken and egg
339 * problem. Thus, we introduce a fix here.
342 if (option == LDAP_OPT_DEBUG_LEVEL) {
343 dbglvl = (int *) invalue;
346 if( lo->ldo_valid != LDAP_INITIALIZED ) {
347 ldap_int_initialize(lo, dbglvl);
351 assert( LDAP_VALID( ld ) );
353 if( !LDAP_VALID( ld ) ) {
354 return LDAP_OPT_ERROR;
357 lo = &ld->ld_options;
361 case LDAP_OPT_REFERRALS:
362 if(invalue == LDAP_OPT_OFF) {
363 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
365 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
367 return LDAP_OPT_SUCCESS;
369 case LDAP_OPT_RESTART:
370 if(invalue == LDAP_OPT_OFF) {
371 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
373 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
375 return LDAP_OPT_SUCCESS;
378 /* options which can withstand invalue == NULL */
380 case LDAP_OPT_SERVER_CONTROLS: {
381 LDAPControl *const *controls =
382 (LDAPControl *const *) invalue;
384 ldap_controls_free( lo->ldo_sctrls );
386 if( controls == NULL || *controls == NULL ) {
387 lo->ldo_sctrls = NULL;
388 return LDAP_OPT_SUCCESS;
391 lo->ldo_sctrls = ldap_controls_dup( controls );
393 if(lo->ldo_sctrls == NULL) {
394 /* memory allocation error ? */
397 } return LDAP_OPT_SUCCESS;
399 case LDAP_OPT_CLIENT_CONTROLS: {
400 LDAPControl *const *controls =
401 (LDAPControl *const *) invalue;
403 ldap_controls_free( lo->ldo_cctrls );
405 if( controls == NULL || *controls == NULL ) {
406 lo->ldo_cctrls = NULL;
407 return LDAP_OPT_SUCCESS;
410 lo->ldo_cctrls = ldap_controls_dup( controls );
412 if(lo->ldo_cctrls == NULL) {
413 /* memory allocation error ? */
416 } return LDAP_OPT_SUCCESS;
418 case LDAP_OPT_TIMEOUT: {
419 const struct timeval *tv =
420 (const struct timeval *) invalue;
422 if ( lo->ldo_tm_api != NULL ) {
423 LDAP_FREE( lo->ldo_tm_api );
424 lo->ldo_tm_api = NULL;
427 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
428 return LDAP_OPT_ERROR;
430 } return LDAP_OPT_SUCCESS;
432 case LDAP_OPT_NETWORK_TIMEOUT: {
433 const struct timeval *tv =
434 (const struct timeval *) invalue;
436 if ( lo->ldo_tm_net != NULL ) {
437 LDAP_FREE( lo->ldo_tm_net );
438 lo->ldo_tm_net = NULL;
441 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
442 return LDAP_OPT_ERROR;
444 } return LDAP_OPT_SUCCESS;
446 /* Only accessed from inside this function by ldap_set_rebind_proc() */
447 case LDAP_OPT_REBIND_PROC: {
448 lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
449 } return LDAP_OPT_SUCCESS;
450 case LDAP_OPT_REBIND_PARAMS: {
451 lo->ldo_rebind_params = (void *)invalue;
452 } return LDAP_OPT_SUCCESS;
455 if(invalue == NULL) {
456 /* no place to set from */
457 return LDAP_OPT_ERROR;
460 /* options which cannot withstand invalue == NULL */
463 case LDAP_OPT_API_INFO:
469 lo->ldo_deref = * (const int *) invalue;
470 return LDAP_OPT_SUCCESS;
472 case LDAP_OPT_SIZELIMIT:
473 lo->ldo_sizelimit = * (const int *) invalue;
474 return LDAP_OPT_SUCCESS;
476 case LDAP_OPT_TIMELIMIT:
477 lo->ldo_timelimit = * (const int *) invalue;
478 return LDAP_OPT_SUCCESS;
480 case LDAP_OPT_PROTOCOL_VERSION: {
481 int vers = * (const int *) invalue;
482 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
486 lo->ldo_version = vers;
487 } return LDAP_OPT_SUCCESS;
490 case LDAP_OPT_HOST_NAME: {
491 const char *host = (const char *) invalue;
492 LDAPURLDesc *ludlist = NULL;
493 int rc = LDAP_OPT_SUCCESS;
496 rc = ldap_url_parsehosts( &ludlist, host,
497 lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
499 } else if(ld == NULL) {
501 * must want global default returned
502 * to initial condition.
504 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
508 * must want the session default
509 * updated to the current global default
511 ludlist = ldap_url_duplist(
512 ldap_int_global_options.ldo_defludp);
517 if (rc == LDAP_OPT_SUCCESS) {
518 if (lo->ldo_defludp != NULL)
519 ldap_free_urllist(lo->ldo_defludp);
520 lo->ldo_defludp = ludlist;
526 const char *urls = (const char *) invalue;
527 LDAPURLDesc *ludlist = NULL;
528 int rc = LDAP_OPT_SUCCESS;
531 rc = ldap_url_parselist(&ludlist, urls);
533 } else if(ld == NULL) {
535 * must want global default returned
536 * to initial condition.
538 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
542 * must want the session default
543 * updated to the current global default
545 ludlist = ldap_url_duplist(
546 ldap_int_global_options.ldo_defludp);
551 if (rc == LDAP_OPT_SUCCESS) {
552 if (lo->ldo_defludp != NULL)
553 ldap_free_urllist(lo->ldo_defludp);
554 lo->ldo_defludp = ludlist;
559 case LDAP_OPT_ERROR_NUMBER: {
560 int err = * (const int *) invalue;
563 /* need a struct ldap */
568 } return LDAP_OPT_SUCCESS;
570 case LDAP_OPT_ERROR_STRING: {
571 const char *err = (const char *) invalue;
574 /* need a struct ldap */
579 LDAP_FREE(ld->ld_error);
582 ld->ld_error = LDAP_STRDUP(err);
583 } return LDAP_OPT_SUCCESS;
585 case LDAP_OPT_MATCHED_DN: {
586 const char *err = (const char *) invalue;
589 /* need a struct ldap */
593 if( ld->ld_matched ) {
594 LDAP_FREE(ld->ld_matched);
597 ld->ld_matched = LDAP_STRDUP(err);
598 } return LDAP_OPT_SUCCESS;
600 case LDAP_OPT_REFERRAL_URLS: {
601 char *const *referrals = (char *const *) invalue;
604 /* need a struct ldap */
608 if( ld->ld_referrals ) {
609 LDAP_VFREE(ld->ld_referrals);
612 ld->ld_referrals = ldap_value_dup(referrals);
613 } return LDAP_OPT_SUCCESS;
615 case LDAP_OPT_API_FEATURE_INFO:
619 case LDAP_OPT_DEBUG_LEVEL:
620 lo->ldo_debug = * (const int *) invalue;
621 return LDAP_OPT_SUCCESS;
625 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
626 return LDAP_OPT_SUCCESS;
628 #ifdef HAVE_CYRUS_SASL
629 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
630 return LDAP_OPT_SUCCESS;
635 return LDAP_OPT_ERROR;
639 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
642 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
643 if( rc != LDAP_OPT_SUCCESS ) return rc;
645 rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );