]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
move --enable-dns (LDAP_API_FEATURE_X_OPENLDAP_V2_DNS) to Attic
[openldap] / libraries / libldap / options.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/stdlib.h>
12
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16
17 #include "ldap-int.h"
18
19 #define LDAP_OPT_REBIND_PROC 0x4e814d
20
21 static const LDAPAPIFeatureInfo features[] = {
22 #ifdef LDAP_API_FEATURE_X_OPENLDAP
23         {       /* OpenLDAP Extensions API Feature */
24                 LDAP_FEATURE_INFO_VERSION,
25                 "X_OPENLDAP",
26                 LDAP_API_FEATURE_X_OPENLDAP
27         },
28 #endif
29
30 #ifdef LDAP_API_FEATURE_THREAD_SAFE
31         {       /* Basic Thread Safe */
32                 LDAP_FEATURE_INFO_VERSION,
33                 "THREAD_SAFE",
34                 LDAP_API_FEATURE_THREAD_SAFE
35         },
36 #endif
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
42         },
43 #endif
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
49         },
50 #endif
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
56         },
57 #endif
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
64         },
65 #endif
66 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
67         {       /* V2 Referrals */
68                 LDAP_FEATURE_INFO_VERSION,
69                 "X_OPENLDAP_V2_REFERRALS",
70                 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
71         },
72 #endif
73         {0, NULL, 0}
74 };
75
76 int
77 ldap_get_option(
78         LDAP    *ld,
79         int             option,
80         void    *outvalue)
81 {
82         const struct ldapoptions *lo;
83
84         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
85                 ldap_int_initialize(NULL);
86         }
87
88         if(ld == NULL) {
89                 lo = &ldap_int_global_options;
90
91         } else {
92                 assert( LDAP_VALID( ld ) );
93
94                 if( !LDAP_VALID( ld ) ) {
95                         return LDAP_OPT_ERROR;
96                 }
97
98                 lo = &ld->ld_options;
99         }
100
101         if(outvalue == NULL) {
102                 /* no place to get to */
103                 return LDAP_OPT_ERROR;
104         }
105
106         switch(option) {
107         case LDAP_OPT_API_INFO: {
108                         struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
109
110                         if(info == NULL) {
111                                 /* outvalue must point to an apiinfo structure */
112                                 return LDAP_OPT_ERROR;
113                         }
114
115                         if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
116                                 /* api info version mismatch */
117                                 info->ldapai_info_version = LDAP_API_INFO_VERSION;
118                                 return LDAP_OPT_ERROR;
119                         }
120
121                         info->ldapai_api_version = LDAP_API_VERSION;
122                         info->ldapai_api_version = LDAP_API_VERSION;
123                         info->ldapai_protocol_version = LDAP_VERSION_MAX;
124
125                         if(features[0].ldapaif_name == NULL) {
126                                 info->ldapai_extensions = NULL;
127                         } else {
128                                 int i;
129                                 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
130                                         sizeof(features)/sizeof(LDAPAPIFeatureInfo));
131
132                                 for(i=0; features[i].ldapaif_name != NULL; i++) {
133                                         info->ldapai_extensions[i] =
134                                                 LDAP_STRDUP(features[i].ldapaif_name);
135                                 }
136
137                                 info->ldapai_extensions[i] = NULL;
138                         }
139
140                         info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
141                         info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
142
143                         return LDAP_OPT_SUCCESS;
144                 } break;
145
146         case LDAP_OPT_DESC:
147                 if( ld == NULL || ld->ld_sb == NULL ) {
148                         /* bad param */
149                         break;
150                 } 
151
152                 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
153                 return LDAP_OPT_SUCCESS;
154
155         case LDAP_OPT_TIMEOUT:
156                 /* the caller has to free outvalue ! */
157                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
158                 {
159                         return LDAP_OPT_ERROR;
160                 }
161                 return LDAP_OPT_SUCCESS;
162                 
163         case LDAP_OPT_NETWORK_TIMEOUT:
164                 /* the caller has to free outvalue ! */
165                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
166                 {
167                         return LDAP_OPT_ERROR;
168                 }
169                 return LDAP_OPT_SUCCESS;
170
171         case LDAP_OPT_DEREF:
172                 * (int *) outvalue = lo->ldo_deref;
173                 return LDAP_OPT_SUCCESS;
174
175         case LDAP_OPT_SIZELIMIT:
176                 * (int *) outvalue = lo->ldo_sizelimit;
177                 return LDAP_OPT_SUCCESS;
178
179         case LDAP_OPT_TIMELIMIT:
180                 * (int *) outvalue = lo->ldo_timelimit;
181                 return LDAP_OPT_SUCCESS;
182
183         case LDAP_OPT_REFERRALS:
184                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
185                 return LDAP_OPT_SUCCESS;
186                 
187         case LDAP_OPT_RESTART:
188                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
189                 return LDAP_OPT_SUCCESS;
190
191         case LDAP_OPT_DNS:      /* LDAPv2 */
192                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
193                 return LDAP_OPT_SUCCESS;
194
195         case LDAP_OPT_PROTOCOL_VERSION:
196                 * (int *) outvalue = lo->ldo_version;
197                 return LDAP_OPT_SUCCESS;
198
199         case LDAP_OPT_SERVER_CONTROLS:
200                 * (LDAPControl ***) outvalue =
201                         ldap_controls_dup( lo->ldo_sctrls );
202
203                 return LDAP_OPT_SUCCESS;
204
205         case LDAP_OPT_CLIENT_CONTROLS:
206                 * (LDAPControl ***) outvalue =
207                         ldap_controls_dup( lo->ldo_cctrls );
208
209                 return LDAP_OPT_SUCCESS;
210
211         case LDAP_OPT_HOST_NAME:
212                 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
213                 return LDAP_OPT_SUCCESS;
214
215         case LDAP_OPT_URI:
216                 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
217                 return LDAP_OPT_SUCCESS;
218
219         case LDAP_OPT_ERROR_NUMBER:
220                 if(ld == NULL) {
221                         /* bad param */
222                         break;
223                 } 
224                 * (int *) outvalue = ld->ld_errno;
225                 return LDAP_OPT_SUCCESS;
226
227         case LDAP_OPT_ERROR_STRING:
228                 if(ld == NULL) {
229                         /* bad param */
230                         break;
231                 } 
232
233                 if( ld->ld_error == NULL ) {
234                         * (char **) outvalue = NULL;
235                 } else {
236                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
237                 }
238
239                 return LDAP_OPT_SUCCESS;
240
241         case LDAP_OPT_MATCHED_DN:
242                 if(ld == NULL) {
243                         /* bad param */
244                         break;
245                 } 
246
247                 if( ld->ld_matched == NULL ) {
248                         * (char **) outvalue = NULL;
249                 } else {
250                         * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
251                 }
252
253                 return LDAP_OPT_SUCCESS;
254
255         case LDAP_OPT_API_FEATURE_INFO: {
256                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
257                         int i;
258
259                         if(info == NULL) return LDAP_OPT_ERROR;
260
261                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
262                                 /* api info version mismatch */
263                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
264                                 return LDAP_OPT_ERROR;
265                         }
266
267                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
268
269                         for(i=0; features[i].ldapaif_name != NULL; i++) {
270                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
271                                         info->ldapaif_version =
272                                                 features[i].ldapaif_version;
273                                         return LDAP_OPT_SUCCESS;
274                                 }
275                         }
276                 }
277                 break;
278
279         case LDAP_OPT_DEBUG_LEVEL:
280                 * (int *) outvalue = lo->ldo_debug;
281                 return LDAP_OPT_SUCCESS;
282
283         default:
284 #ifdef HAVE_TLS
285                 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
286                         return LDAP_OPT_SUCCESS;
287 #endif
288 #ifdef HAVE_CYRUS_SASL
289                 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
290                         return LDAP_OPT_SUCCESS;
291 #endif
292                 /* bad param */
293                 break;
294         }
295
296         return LDAP_OPT_ERROR;
297 }
298
299 int
300 ldap_set_option(
301         LDAP    *ld,
302         int             option,
303         LDAP_CONST void *invalue)
304 {
305         struct ldapoptions *lo;
306         int *dbglvl = NULL;
307
308         /*
309          * The architecture to turn on debugging has a chicken and egg
310          * problem. Thus, we introduce a fix here.
311          */
312
313         if (option == LDAP_OPT_DEBUG_LEVEL)
314             dbglvl = (int *) invalue;
315
316         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
317                 ldap_int_initialize(dbglvl);
318         }
319
320         if(ld == NULL) {
321                 lo = &ldap_int_global_options;
322
323         } else {
324                 assert( LDAP_VALID( ld ) );
325
326                 if( !LDAP_VALID( ld ) ) {
327                         return LDAP_OPT_ERROR;
328                 }
329
330                 lo = &ld->ld_options;
331         }
332
333         switch(option) {
334         case LDAP_OPT_REFERRALS:
335                 if(invalue == LDAP_OPT_OFF) {
336                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
337                 } else {
338                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
339                 }
340                 return LDAP_OPT_SUCCESS;
341
342         case LDAP_OPT_RESTART:
343                 if(invalue == LDAP_OPT_OFF) {
344                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
345                 } else {
346                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
347                 }
348                 return LDAP_OPT_SUCCESS;
349         }
350
351         /* options which can withstand invalue == NULL */
352         switch ( option ) {
353         case LDAP_OPT_SERVER_CONTROLS: {
354                         LDAPControl *const *controls =
355                                 (LDAPControl *const *) invalue;
356
357                         ldap_controls_free( lo->ldo_sctrls );
358
359                         if( controls == NULL || *controls == NULL ) {
360                                 lo->ldo_sctrls = NULL;
361                                 return LDAP_OPT_SUCCESS;
362                         }
363                                 
364                         lo->ldo_sctrls = ldap_controls_dup( controls );
365
366                         if(lo->ldo_sctrls == NULL) {
367                                 /* memory allocation error ? */
368                                 break;
369                         }
370                 } return LDAP_OPT_SUCCESS;
371
372         case LDAP_OPT_CLIENT_CONTROLS: {
373                         LDAPControl *const *controls =
374                                 (LDAPControl *const *) invalue;
375
376                         ldap_controls_free( lo->ldo_cctrls );
377
378                         if( controls == NULL || *controls == NULL ) {
379                                 lo->ldo_cctrls = NULL;
380                                 return LDAP_OPT_SUCCESS;
381                         }
382                                 
383                         lo->ldo_cctrls = ldap_controls_dup( controls );
384
385                         if(lo->ldo_cctrls == NULL) {
386                                 /* memory allocation error ? */
387                                 break;
388                         }
389                 } return LDAP_OPT_SUCCESS;
390
391         case LDAP_OPT_TIMEOUT: {
392                         const struct timeval *tv = 
393                                 (const struct timeval *) invalue;
394
395                         if ( lo->ldo_tm_api != NULL ) {
396                                 LDAP_FREE( lo->ldo_tm_api );
397                                 lo->ldo_tm_api = NULL;
398                         }
399
400                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
401                                 return LDAP_OPT_ERROR;
402                         }
403                 } return LDAP_OPT_SUCCESS;
404
405         case LDAP_OPT_NETWORK_TIMEOUT: {
406                         const struct timeval *tv = 
407                                 (const struct timeval *) invalue;
408
409                         if ( lo->ldo_tm_net != NULL ) {
410                                 LDAP_FREE( lo->ldo_tm_net );
411                                 lo->ldo_tm_net = NULL;
412                         }
413
414                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
415                                 return LDAP_OPT_ERROR;
416                         }
417                 } return LDAP_OPT_SUCCESS;
418
419         /* Only accessed from inside this function by ldap_set_rebind_proc() */
420         case LDAP_OPT_REBIND_PROC: {
421                         lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;               
422                 } return LDAP_OPT_SUCCESS;
423         }
424
425         if(invalue == NULL) {
426                 /* no place to set from */
427                 return LDAP_OPT_ERROR;
428         }
429
430         /* options which cannot withstand invalue == NULL */
431
432         switch(option) {
433         case LDAP_OPT_API_INFO:
434         case LDAP_OPT_DESC:
435                 /* READ ONLY */
436                 break;
437
438         case LDAP_OPT_DEREF:
439                 lo->ldo_deref = * (const int *) invalue;
440                 return LDAP_OPT_SUCCESS;
441
442         case LDAP_OPT_SIZELIMIT:
443                 lo->ldo_sizelimit = * (const int *) invalue;
444                 return LDAP_OPT_SUCCESS;
445
446         case LDAP_OPT_TIMELIMIT:
447                 lo->ldo_timelimit = * (const int *) invalue;
448                 return LDAP_OPT_SUCCESS;
449
450         case LDAP_OPT_PROTOCOL_VERSION: {
451                         int vers = * (const int *) invalue;
452                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
453                                 /* not supported */
454                                 break;
455                         }
456                         lo->ldo_version = vers;
457                 } return LDAP_OPT_SUCCESS;
458
459
460         case LDAP_OPT_HOST_NAME: {
461                         const char *host = (const char *) invalue;
462                         LDAPURLDesc *ludlist = NULL;
463                         int rc = LDAP_OPT_SUCCESS;
464
465                         if(host != NULL) {
466                                 rc = ldap_url_parsehosts(&ludlist, host);
467
468                         } else if(ld == NULL) {
469                                 /*
470                                  * must want global default returned
471                                  * to initial condition.
472                                  */
473                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
474
475                         } else {
476                                 /*
477                                  * must want the session default
478                                  *   updated to the current global default
479                                  */
480                                 ludlist = ldap_url_duplist(
481                                         ldap_int_global_options.ldo_defludp);
482                                 if (ludlist == NULL)
483                                         rc = LDAP_NO_MEMORY;
484                         }
485
486                         if (rc == LDAP_OPT_SUCCESS) {
487                                 if (lo->ldo_defludp != NULL)
488                                         ldap_free_urllist(lo->ldo_defludp);
489                                 lo->ldo_defludp = ludlist;
490                         }
491                         return rc;
492                 }
493
494         case LDAP_OPT_URI: {
495                         const char *urls = (const char *) invalue;
496                         LDAPURLDesc *ludlist = NULL;
497                         int rc = LDAP_OPT_SUCCESS;
498
499                         if(urls != NULL) {
500                                 rc = ldap_url_parselist(&ludlist, urls);
501
502                         } else if(ld == NULL) {
503                                 /*
504                                  * must want global default returned
505                                  * to initial condition.
506                                  */
507                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
508
509                         } else {
510                                 /*
511                                  * must want the session default
512                                  *   updated to the current global default
513                                  */
514                                 ludlist = ldap_url_duplist(
515                                         ldap_int_global_options.ldo_defludp);
516                                 if (ludlist == NULL)
517                                         rc = LDAP_NO_MEMORY;
518                         }
519
520                         if (rc == LDAP_OPT_SUCCESS) {
521                                 if (lo->ldo_defludp != NULL)
522                                         ldap_free_urllist(lo->ldo_defludp);
523                                 lo->ldo_defludp = ludlist;
524                         }
525                         return rc;
526                 }
527
528         case LDAP_OPT_ERROR_NUMBER: {
529                         int err = * (const int *) invalue;
530
531                         if(ld == NULL) {
532                                 /* need a struct ldap */
533                                 break;
534                         }
535
536                         ld->ld_errno = err;
537                 } return LDAP_OPT_SUCCESS;
538
539         case LDAP_OPT_ERROR_STRING: {
540                         const char *err = (const char *) invalue;
541
542                         if(ld == NULL) {
543                                 /* need a struct ldap */
544                                 break;
545                         }
546
547                         if( ld->ld_error ) {
548                                 LDAP_FREE(ld->ld_error);
549                         }
550
551                         ld->ld_error = LDAP_STRDUP(err);
552                 } return LDAP_OPT_SUCCESS;
553
554         case LDAP_OPT_MATCHED_DN: {
555                         const char *err = (const char *) invalue;
556
557                         if(ld == NULL) {
558                                 /* need a struct ldap */
559                                 break;
560                         }
561
562                         if( ld->ld_matched ) {
563                                 LDAP_FREE(ld->ld_matched);
564                         }
565
566                         ld->ld_matched = LDAP_STRDUP(err);
567                 } return LDAP_OPT_SUCCESS;
568
569         case LDAP_OPT_API_FEATURE_INFO:
570                 /* read-only */
571                 break;
572
573         case LDAP_OPT_DEBUG_LEVEL:
574                 lo->ldo_debug = * (const int *) invalue;
575                 return LDAP_OPT_SUCCESS;
576
577         default:
578 #ifdef HAVE_TLS
579                 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
580                 return LDAP_OPT_SUCCESS;
581 #endif
582 #ifdef HAVE_CYRUS_SASL
583                 if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
584                         return LDAP_OPT_SUCCESS;
585 #endif
586                 /* bad param */
587                 break;
588         }
589         return LDAP_OPT_ERROR;
590 }
591
592 LIBLDAP_F(int)
593 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
594 {
595         return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));
596 }