]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
Added debuglevel parameter to ldap_int_initialize().
[openldap] / libraries / libldap / options.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 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 static const LDAPAPIFeatureInfo features[] = {
20 #ifdef LDAP_API_FEATURE_X_OPENLDAP
21         {       /* OpenLDAP Extensions API Feature */
22                 LDAP_FEATURE_INFO_VERSION,
23                 "X_OPENLDAP",
24                 LDAP_API_FEATURE_X_OPENLDAP
25         },
26 #endif
27
28 #ifdef LDAP_API_FEATURE_THREAD_SAFE
29         {       /* Basic Thread Safe */
30                 LDAP_FEATURE_INFO_VERSION,
31                 "THREAD_SAFE",
32                 LDAP_API_FEATURE_THREAD_SAFE
33         },
34 #endif
35 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
36         {       /* Session Thread Safe */
37                 LDAP_FEATURE_INFO_VERSION,
38                 "SESSION_THREAD_SAFE",
39                 LDAP_API_FEATURE_SESSION_THREAD_SAFE
40         },
41 #endif
42 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
43         {       /* Operation Thread Safe */
44                 LDAP_FEATURE_INFO_VERSION,
45                 "OPERATION_THREAD_SAFE",
46                 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
47         },
48 #endif
49 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
50         {       /* OpenLDAP Reentrant */
51                 LDAP_FEATURE_INFO_VERSION,
52                 "X_OPENLDAP_REENTRANT",
53                 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
54         },
55 #endif
56 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
57         defined( LDAP_THREAD_SAFE )
58         {       /* OpenLDAP Thread Safe */
59                 LDAP_FEATURE_INFO_VERSION,
60                 "X_OPENLDAP_THREAD_SAFE",
61                 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
62         },
63 #endif
64 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
65         {       /* DNS */
66                 LDAP_FEATURE_INFO_VERSION,
67                 "X_OPENLDAP_V2_DNS",
68                 LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
69         },
70 #endif
71 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
72         {       /* V2 Referrals */
73                 LDAP_FEATURE_INFO_VERSION,
74                 "X_OPENLDAP_V2_REFERRALS",
75                 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
76         },
77 #endif
78         {0, NULL, 0}
79 };
80
81 int
82 ldap_get_option(
83         LDAP    *ld,
84         int             option,
85         void    *outvalue)
86 {
87         const struct ldapoptions *lo;
88
89         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
90                 ldap_int_initialize(NULL);
91         }
92
93         if(ld == NULL) {
94                 lo = &ldap_int_global_options;
95
96         } else {
97                 assert( LDAP_VALID( ld ) );
98
99                 if( !LDAP_VALID( ld ) ) {
100                         return LDAP_OPT_ERROR;
101                 }
102
103                 lo = &ld->ld_options;
104         }
105
106         if(outvalue == NULL) {
107                 /* no place to get to */
108                 return LDAP_OPT_ERROR;
109         }
110
111         switch(option) {
112         case LDAP_OPT_API_INFO: {
113                         struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
114
115                         if(info == NULL) {
116                                 /* outvalue must point to an apiinfo structure */
117                                 return LDAP_OPT_ERROR;
118                         }
119
120                         if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
121                                 /* api info version mismatch */
122                                 info->ldapai_info_version = LDAP_API_INFO_VERSION;
123                                 return LDAP_OPT_ERROR;
124                         }
125
126                         info->ldapai_api_version = LDAP_API_VERSION;
127                         info->ldapai_api_version = LDAP_API_VERSION;
128                         info->ldapai_protocol_version = LDAP_VERSION_MAX;
129
130                         if(features[0].ldapaif_name == NULL) {
131                                 info->ldapai_extensions = NULL;
132                         } else {
133                                 int i;
134                                 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
135                                         sizeof(features)/sizeof(LDAPAPIFeatureInfo));
136
137                                 for(i=0; features[i].ldapaif_name != NULL; i++) {
138                                         info->ldapai_extensions[i] =
139                                                 LDAP_STRDUP(features[i].ldapaif_name);
140                                 }
141
142                                 info->ldapai_extensions[i] = NULL;
143                         }
144
145                         info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
146                         info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
147
148                         return LDAP_OPT_SUCCESS;
149                 } break;
150
151         case LDAP_OPT_DESC:
152                 if(ld == NULL) {
153                         /* bad param */
154                         break;
155                 } 
156
157                 * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
158                 return LDAP_OPT_SUCCESS;
159
160         case LDAP_OPT_TIMEOUT:
161                 /* the caller has to free outvalue ! */
162                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
163                 {
164                         return LDAP_OPT_ERROR;
165                 }
166                 return LDAP_OPT_SUCCESS;
167                 
168         case LDAP_OPT_NETWORK_TIMEOUT:
169                 /* the caller has to free outvalue ! */
170                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
171                 {
172                         return LDAP_OPT_ERROR;
173                 }
174                 return LDAP_OPT_SUCCESS;
175
176         case LDAP_OPT_DEREF:
177                 * (int *) outvalue = lo->ldo_deref;
178                 return LDAP_OPT_SUCCESS;
179
180         case LDAP_OPT_SIZELIMIT:
181                 * (int *) outvalue = lo->ldo_sizelimit;
182                 return LDAP_OPT_SUCCESS;
183
184         case LDAP_OPT_TIMELIMIT:
185                 * (int *) outvalue = lo->ldo_timelimit;
186                 return LDAP_OPT_SUCCESS;
187
188         case LDAP_OPT_REFERRALS:
189                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
190                 return LDAP_OPT_SUCCESS;
191                 
192         case LDAP_OPT_RESTART:
193                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
194                 return LDAP_OPT_SUCCESS;
195
196         case LDAP_OPT_DNS:      /* LDAPv2 */
197                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
198                 return LDAP_OPT_SUCCESS;
199
200         case LDAP_OPT_PROTOCOL_VERSION:
201                 * (int *) outvalue = lo->ldo_version;
202                 return LDAP_OPT_SUCCESS;
203
204         case LDAP_OPT_SERVER_CONTROLS:
205                 * (LDAPControl ***) outvalue =
206                         ldap_controls_dup( lo->ldo_sctrls );
207
208                 return LDAP_OPT_SUCCESS;
209
210         case LDAP_OPT_CLIENT_CONTROLS:
211                 * (LDAPControl ***) outvalue =
212                         ldap_controls_dup( lo->ldo_cctrls );
213
214                 return LDAP_OPT_SUCCESS;
215
216         case LDAP_OPT_HOST_NAME:
217                 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
218                 return LDAP_OPT_SUCCESS;
219
220         case LDAP_OPT_URI:
221                 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
222                 return LDAP_OPT_SUCCESS;
223
224         case LDAP_OPT_ERROR_NUMBER:
225                 if(ld == NULL) {
226                         /* bad param */
227                         break;
228                 } 
229                 * (int *) outvalue = ld->ld_errno;
230                 return LDAP_OPT_SUCCESS;
231
232         case LDAP_OPT_ERROR_STRING:
233                 if(ld == NULL) {
234                         /* bad param */
235                         break;
236                 } 
237
238                 if( ld->ld_error == NULL ) {
239                         * (char **) outvalue = NULL;
240                 } else {
241                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
242                 }
243
244                 return LDAP_OPT_SUCCESS;
245
246         case LDAP_OPT_MATCHED_DN:
247                 if(ld == NULL) {
248                         /* bad param */
249                         break;
250                 } 
251
252                 if( ld->ld_matched == NULL ) {
253                         * (char **) outvalue = NULL;
254                 } else {
255                         * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
256                 }
257
258                 return LDAP_OPT_SUCCESS;
259
260         case LDAP_OPT_API_FEATURE_INFO: {
261                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
262                         int i;
263
264                         if(info == NULL) return LDAP_OPT_ERROR;
265
266                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
267                                 /* api info version mismatch */
268                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
269                                 return LDAP_OPT_ERROR;
270                         }
271
272                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
273
274                         for(i=0; features[i].ldapaif_name != NULL; i++) {
275                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
276                                         info->ldapaif_version =
277                                                 features[i].ldapaif_version;
278                                         return LDAP_OPT_SUCCESS;
279                                 }
280                         }
281                 }
282                 break;
283
284         case LDAP_OPT_DEBUG_LEVEL:
285                 * (int *) outvalue = lo->ldo_debug;
286                 return LDAP_OPT_SUCCESS;
287
288         default:
289 #ifdef HAVE_TLS
290                 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
291                         return LDAP_OPT_SUCCESS;
292 #endif
293 #ifdef HAVE_CYRUS_SASL
294                 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
295                         return LDAP_OPT_SUCCESS;
296 #endif
297                 /* bad param */
298                 break;
299         }
300
301         return LDAP_OPT_ERROR;
302 }
303
304 int
305 ldap_set_option(
306         LDAP    *ld,
307         int             option,
308         LDAP_CONST void *invalue)
309 {
310         struct ldapoptions *lo;
311         int *dbglvl = NULL;
312
313         /*
314          * The architecture to turn on debugging has a chicken and egg
315          * problem. Thus, we introduce a fix here.
316          */
317
318         if (option == LDAP_OPT_DEBUG_LEVEL)
319             dbglvl = (int *) invalue;
320
321         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
322                 ldap_int_initialize(dbglvl);
323         }
324
325         if(ld == NULL) {
326                 lo = &ldap_int_global_options;
327
328         } else {
329                 assert( LDAP_VALID( ld ) );
330
331                 if( !LDAP_VALID( ld ) ) {
332                         return LDAP_OPT_ERROR;
333                 }
334
335                 lo = &ld->ld_options;
336         }
337
338         switch(option) {
339         case LDAP_OPT_REFERRALS:
340                 if(invalue == LDAP_OPT_OFF) {
341                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
342                 } else {
343                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
344                 }
345                 return LDAP_OPT_SUCCESS;
346
347         case LDAP_OPT_RESTART:
348                 if(invalue == LDAP_OPT_OFF) {
349                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
350                 } else {
351                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
352                 }
353                 return LDAP_OPT_SUCCESS;
354         }
355
356         /* options which can withstand invalue == NULL */
357         switch ( option ) {
358         case LDAP_OPT_SERVER_CONTROLS: {
359                         LDAPControl *const *controls =
360                                 (LDAPControl *const *) invalue;
361
362                         ldap_controls_free( lo->ldo_sctrls );
363
364                         if( controls == NULL || *controls == NULL ) {
365                                 lo->ldo_sctrls = NULL;
366                                 return LDAP_OPT_SUCCESS;
367                         }
368                                 
369                         lo->ldo_sctrls = ldap_controls_dup( controls );
370
371                         if(lo->ldo_sctrls == NULL) {
372                                 /* memory allocation error ? */
373                                 break;
374                         }
375                 } return LDAP_OPT_SUCCESS;
376
377         case LDAP_OPT_CLIENT_CONTROLS: {
378                         LDAPControl *const *controls =
379                                 (LDAPControl *const *) invalue;
380
381                         ldap_controls_free( lo->ldo_cctrls );
382
383                         if( controls == NULL || *controls == NULL ) {
384                                 lo->ldo_cctrls = NULL;
385                                 return LDAP_OPT_SUCCESS;
386                         }
387                                 
388                         lo->ldo_cctrls = ldap_controls_dup( controls );
389
390                         if(lo->ldo_cctrls == NULL) {
391                                 /* memory allocation error ? */
392                                 break;
393                         }
394                 } return LDAP_OPT_SUCCESS;
395
396         case LDAP_OPT_TIMEOUT: {
397                         const struct timeval *tv = 
398                                 (const struct timeval *) invalue;
399
400                         if ( lo->ldo_tm_api != NULL ) {
401                                 LDAP_FREE( lo->ldo_tm_api );
402                                 lo->ldo_tm_api = NULL;
403                         }
404
405                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
406                                 return LDAP_OPT_ERROR;
407                         }
408                 } return LDAP_OPT_SUCCESS;
409
410         case LDAP_OPT_NETWORK_TIMEOUT: {
411                         const struct timeval *tv = 
412                                 (const struct timeval *) invalue;
413
414                         if ( lo->ldo_tm_net != NULL ) {
415                                 LDAP_FREE( lo->ldo_tm_net );
416                                 lo->ldo_tm_net = NULL;
417                         }
418
419                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
420                                 return LDAP_OPT_ERROR;
421                         }
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 }