3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/stdlib.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
19 #define LDAP_OPT_REBIND_PROC 0x4e814d
21 static const LDAPAPIFeatureInfo features[] = {
22 #ifdef LDAP_API_FEATURE_X_OPENLDAP
23 { /* OpenLDAP Extensions API Feature */
24 LDAP_FEATURE_INFO_VERSION,
26 LDAP_API_FEATURE_X_OPENLDAP
30 #ifdef LDAP_API_FEATURE_THREAD_SAFE
31 { /* Basic Thread Safe */
32 LDAP_FEATURE_INFO_VERSION,
34 LDAP_API_FEATURE_THREAD_SAFE
37 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
38 { /* Session Thread Safe */
39 LDAP_FEATURE_INFO_VERSION,
40 "SESSION_THREAD_SAFE",
41 LDAP_API_FEATURE_SESSION_THREAD_SAFE
44 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
45 { /* Operation Thread Safe */
46 LDAP_FEATURE_INFO_VERSION,
47 "OPERATION_THREAD_SAFE",
48 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
51 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
52 { /* OpenLDAP Reentrant */
53 LDAP_FEATURE_INFO_VERSION,
54 "X_OPENLDAP_REENTRANT",
55 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
58 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
59 defined( LDAP_THREAD_SAFE )
60 { /* OpenLDAP Thread Safe */
61 LDAP_FEATURE_INFO_VERSION,
62 "X_OPENLDAP_THREAD_SAFE",
63 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
66 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
68 LDAP_FEATURE_INFO_VERSION,
70 LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
73 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
75 LDAP_FEATURE_INFO_VERSION,
76 "X_OPENLDAP_V2_REFERRALS",
77 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
89 const struct ldapoptions *lo;
91 if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
92 ldap_int_initialize(NULL);
96 lo = &ldap_int_global_options;
99 assert( LDAP_VALID( ld ) );
101 if( !LDAP_VALID( ld ) ) {
102 return LDAP_OPT_ERROR;
105 lo = &ld->ld_options;
108 if(outvalue == NULL) {
109 /* no place to get to */
110 return LDAP_OPT_ERROR;
114 case LDAP_OPT_API_INFO: {
115 struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
118 /* outvalue must point to an apiinfo structure */
119 return LDAP_OPT_ERROR;
122 if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
123 /* api info version mismatch */
124 info->ldapai_info_version = LDAP_API_INFO_VERSION;
125 return LDAP_OPT_ERROR;
128 info->ldapai_api_version = LDAP_API_VERSION;
129 info->ldapai_api_version = LDAP_API_VERSION;
130 info->ldapai_protocol_version = LDAP_VERSION_MAX;
132 if(features[0].ldapaif_name == NULL) {
133 info->ldapai_extensions = NULL;
136 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
137 sizeof(features)/sizeof(LDAPAPIFeatureInfo));
139 for(i=0; features[i].ldapaif_name != NULL; i++) {
140 info->ldapai_extensions[i] =
141 LDAP_STRDUP(features[i].ldapaif_name);
144 info->ldapai_extensions[i] = NULL;
147 info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
148 info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
150 return LDAP_OPT_SUCCESS;
154 if( ld == NULL || ld->ld_sb == NULL ) {
159 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
160 return LDAP_OPT_SUCCESS;
162 case LDAP_OPT_TIMEOUT:
163 /* the caller has to free outvalue ! */
164 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
166 return LDAP_OPT_ERROR;
168 return LDAP_OPT_SUCCESS;
170 case LDAP_OPT_NETWORK_TIMEOUT:
171 /* the caller has to free outvalue ! */
172 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
174 return LDAP_OPT_ERROR;
176 return LDAP_OPT_SUCCESS;
179 * (int *) outvalue = lo->ldo_deref;
180 return LDAP_OPT_SUCCESS;
182 case LDAP_OPT_SIZELIMIT:
183 * (int *) outvalue = lo->ldo_sizelimit;
184 return LDAP_OPT_SUCCESS;
186 case LDAP_OPT_TIMELIMIT:
187 * (int *) outvalue = lo->ldo_timelimit;
188 return LDAP_OPT_SUCCESS;
190 case LDAP_OPT_REFERRALS:
191 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
192 return LDAP_OPT_SUCCESS;
194 case LDAP_OPT_RESTART:
195 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
196 return LDAP_OPT_SUCCESS;
198 case LDAP_OPT_DNS: /* LDAPv2 */
199 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
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_API_FEATURE_INFO: {
263 LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
266 if(info == NULL) return LDAP_OPT_ERROR;
268 if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
269 /* api info version mismatch */
270 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
271 return LDAP_OPT_ERROR;
274 if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
276 for(i=0; features[i].ldapaif_name != NULL; i++) {
277 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
278 info->ldapaif_version =
279 features[i].ldapaif_version;
280 return LDAP_OPT_SUCCESS;
286 case LDAP_OPT_DEBUG_LEVEL:
287 * (int *) outvalue = lo->ldo_debug;
288 return LDAP_OPT_SUCCESS;
292 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
293 return LDAP_OPT_SUCCESS;
295 #ifdef HAVE_CYRUS_SASL
296 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
297 return LDAP_OPT_SUCCESS;
303 return LDAP_OPT_ERROR;
310 LDAP_CONST void *invalue)
312 struct ldapoptions *lo;
316 * The architecture to turn on debugging has a chicken and egg
317 * problem. Thus, we introduce a fix here.
320 if (option == LDAP_OPT_DEBUG_LEVEL)
321 dbglvl = (int *) invalue;
323 if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
324 ldap_int_initialize(dbglvl);
328 lo = &ldap_int_global_options;
331 assert( LDAP_VALID( ld ) );
333 if( !LDAP_VALID( ld ) ) {
334 return LDAP_OPT_ERROR;
337 lo = &ld->ld_options;
341 case LDAP_OPT_REFERRALS:
342 if(invalue == LDAP_OPT_OFF) {
343 LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
345 LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
347 return LDAP_OPT_SUCCESS;
349 case LDAP_OPT_RESTART:
350 if(invalue == LDAP_OPT_OFF) {
351 LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
353 LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
355 return LDAP_OPT_SUCCESS;
358 /* options which can withstand invalue == NULL */
360 case LDAP_OPT_SERVER_CONTROLS: {
361 LDAPControl *const *controls =
362 (LDAPControl *const *) invalue;
364 ldap_controls_free( lo->ldo_sctrls );
366 if( controls == NULL || *controls == NULL ) {
367 lo->ldo_sctrls = NULL;
368 return LDAP_OPT_SUCCESS;
371 lo->ldo_sctrls = ldap_controls_dup( controls );
373 if(lo->ldo_sctrls == NULL) {
374 /* memory allocation error ? */
377 } return LDAP_OPT_SUCCESS;
379 case LDAP_OPT_CLIENT_CONTROLS: {
380 LDAPControl *const *controls =
381 (LDAPControl *const *) invalue;
383 ldap_controls_free( lo->ldo_cctrls );
385 if( controls == NULL || *controls == NULL ) {
386 lo->ldo_cctrls = NULL;
387 return LDAP_OPT_SUCCESS;
390 lo->ldo_cctrls = ldap_controls_dup( controls );
392 if(lo->ldo_cctrls == NULL) {
393 /* memory allocation error ? */
396 } return LDAP_OPT_SUCCESS;
398 case LDAP_OPT_TIMEOUT: {
399 const struct timeval *tv =
400 (const struct timeval *) invalue;
402 if ( lo->ldo_tm_api != NULL ) {
403 LDAP_FREE( lo->ldo_tm_api );
404 lo->ldo_tm_api = NULL;
407 if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
408 return LDAP_OPT_ERROR;
410 } return LDAP_OPT_SUCCESS;
412 case LDAP_OPT_NETWORK_TIMEOUT: {
413 const struct timeval *tv =
414 (const struct timeval *) invalue;
416 if ( lo->ldo_tm_net != NULL ) {
417 LDAP_FREE( lo->ldo_tm_net );
418 lo->ldo_tm_net = NULL;
421 if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
422 return LDAP_OPT_ERROR;
424 } return LDAP_OPT_SUCCESS;
426 /* Only accessed from inside this function by ldap_set_rebind_proc() */
427 case LDAP_OPT_REBIND_PROC: {
428 lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;
429 } return LDAP_OPT_SUCCESS;
432 if(invalue == NULL) {
433 /* no place to set from */
434 return LDAP_OPT_ERROR;
437 /* options which cannot withstand invalue == NULL */
440 case LDAP_OPT_API_INFO:
446 lo->ldo_deref = * (const int *) invalue;
447 return LDAP_OPT_SUCCESS;
449 case LDAP_OPT_SIZELIMIT:
450 lo->ldo_sizelimit = * (const int *) invalue;
451 return LDAP_OPT_SUCCESS;
453 case LDAP_OPT_TIMELIMIT:
454 lo->ldo_timelimit = * (const int *) invalue;
455 return LDAP_OPT_SUCCESS;
457 case LDAP_OPT_PROTOCOL_VERSION: {
458 int vers = * (const int *) invalue;
459 if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
463 lo->ldo_version = vers;
464 } return LDAP_OPT_SUCCESS;
467 case LDAP_OPT_HOST_NAME: {
468 const char *host = (const char *) invalue;
469 LDAPURLDesc *ludlist = NULL;
470 int rc = LDAP_OPT_SUCCESS;
473 rc = ldap_url_parsehosts(&ludlist, host);
475 } else if(ld == NULL) {
477 * must want global default returned
478 * to initial condition.
480 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
484 * must want the session default
485 * updated to the current global default
487 ludlist = ldap_url_duplist(
488 ldap_int_global_options.ldo_defludp);
493 if (rc == LDAP_OPT_SUCCESS) {
494 if (lo->ldo_defludp != NULL)
495 ldap_free_urllist(lo->ldo_defludp);
496 lo->ldo_defludp = ludlist;
502 const char *urls = (const char *) invalue;
503 LDAPURLDesc *ludlist = NULL;
504 int rc = LDAP_OPT_SUCCESS;
507 rc = ldap_url_parselist(&ludlist, urls);
509 } else if(ld == NULL) {
511 * must want global default returned
512 * to initial condition.
514 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
518 * must want the session default
519 * updated to the current global default
521 ludlist = ldap_url_duplist(
522 ldap_int_global_options.ldo_defludp);
527 if (rc == LDAP_OPT_SUCCESS) {
528 if (lo->ldo_defludp != NULL)
529 ldap_free_urllist(lo->ldo_defludp);
530 lo->ldo_defludp = ludlist;
535 case LDAP_OPT_ERROR_NUMBER: {
536 int err = * (const int *) invalue;
539 /* need a struct ldap */
544 } return LDAP_OPT_SUCCESS;
546 case LDAP_OPT_ERROR_STRING: {
547 const char *err = (const char *) invalue;
550 /* need a struct ldap */
555 LDAP_FREE(ld->ld_error);
558 ld->ld_error = LDAP_STRDUP(err);
559 } return LDAP_OPT_SUCCESS;
561 case LDAP_OPT_MATCHED_DN: {
562 const char *err = (const char *) invalue;
565 /* need a struct ldap */
569 if( ld->ld_matched ) {
570 LDAP_FREE(ld->ld_matched);
573 ld->ld_matched = LDAP_STRDUP(err);
574 } return LDAP_OPT_SUCCESS;
576 case LDAP_OPT_API_FEATURE_INFO:
580 case LDAP_OPT_DEBUG_LEVEL:
581 lo->ldo_debug = * (const int *) invalue;
582 return LDAP_OPT_SUCCESS;
586 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
587 return LDAP_OPT_SUCCESS;
589 #ifdef HAVE_CYRUS_SASL
590 if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
591 return LDAP_OPT_SUCCESS;
596 return LDAP_OPT_ERROR;
600 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
602 return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));