]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
Re: Patch: ctype functions require 'unsigned char' args (ITS#1678)
[openldap] / libraries / libldap / options.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 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 #define LDAP_OPT_REBIND_PARAMS 0x4e814e
21
22 static const LDAPAPIFeatureInfo features[] = {
23 #ifdef LDAP_API_FEATURE_X_OPENLDAP
24         {       /* OpenLDAP Extensions API Feature */
25                 LDAP_FEATURE_INFO_VERSION,
26                 "X_OPENLDAP",
27                 LDAP_API_FEATURE_X_OPENLDAP
28         },
29 #endif
30
31 #ifdef LDAP_API_FEATURE_THREAD_SAFE
32         {       /* Basic Thread Safe */
33                 LDAP_FEATURE_INFO_VERSION,
34                 "THREAD_SAFE",
35                 LDAP_API_FEATURE_THREAD_SAFE
36         },
37 #endif
38 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
39         {       /* Session Thread Safe */
40                 LDAP_FEATURE_INFO_VERSION,
41                 "SESSION_THREAD_SAFE",
42                 LDAP_API_FEATURE_SESSION_THREAD_SAFE
43         },
44 #endif
45 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
46         {       /* Operation Thread Safe */
47                 LDAP_FEATURE_INFO_VERSION,
48                 "OPERATION_THREAD_SAFE",
49                 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
50         },
51 #endif
52 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
53         {       /* OpenLDAP Reentrant */
54                 LDAP_FEATURE_INFO_VERSION,
55                 "X_OPENLDAP_REENTRANT",
56                 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
57         },
58 #endif
59 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
60         defined( LDAP_THREAD_SAFE )
61         {       /* OpenLDAP Thread Safe */
62                 LDAP_FEATURE_INFO_VERSION,
63                 "X_OPENLDAP_THREAD_SAFE",
64                 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
65         },
66 #endif
67 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
68         {       /* V2 Referrals */
69                 LDAP_FEATURE_INFO_VERSION,
70                 "X_OPENLDAP_V2_REFERRALS",
71                 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
72         },
73 #endif
74         {0, NULL, 0}
75 };
76
77 int
78 ldap_get_option(
79         LDAP    *ld,
80         int             option,
81         void    *outvalue)
82 {
83         struct ldapoptions *lo;
84
85         /* Get pointer to global option structure */
86         lo = LDAP_INT_GLOBAL_OPT();   
87         if (NULL == lo) {
88                 return LDAP_NO_MEMORY;
89         }
90
91         if( lo->ldo_valid != LDAP_INITIALIZED ) {
92                 ldap_int_initialize(lo, NULL);
93         }
94
95         if(ld != NULL) {
96                 assert( LDAP_VALID( ld ) );
97
98                 if( !LDAP_VALID( ld ) ) {
99                         return LDAP_OPT_ERROR;
100                 }
101
102                 lo = &ld->ld_options;
103         }
104
105         if(outvalue == NULL) {
106                 /* no place to get to */
107                 return LDAP_OPT_ERROR;
108         }
109
110         switch(option) {
111         case LDAP_OPT_API_INFO: {
112                         struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
113
114                         if(info == NULL) {
115                                 /* outvalue must point to an apiinfo structure */
116                                 return LDAP_OPT_ERROR;
117                         }
118
119                         if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
120                                 /* api info version mismatch */
121                                 info->ldapai_info_version = LDAP_API_INFO_VERSION;
122                                 return LDAP_OPT_ERROR;
123                         }
124
125                         info->ldapai_api_version = LDAP_API_VERSION;
126                         info->ldapai_api_version = LDAP_API_VERSION;
127                         info->ldapai_protocol_version = LDAP_VERSION_MAX;
128
129                         if(features[0].ldapaif_name == NULL) {
130                                 info->ldapai_extensions = NULL;
131                         } else {
132                                 int i;
133                                 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
134                                         sizeof(features)/sizeof(LDAPAPIFeatureInfo));
135
136                                 for(i=0; features[i].ldapaif_name != NULL; i++) {
137                                         info->ldapai_extensions[i] =
138                                                 LDAP_STRDUP(features[i].ldapaif_name);
139                                 }
140
141                                 info->ldapai_extensions[i] = NULL;
142                         }
143
144                         info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
145                         info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
146
147                         return LDAP_OPT_SUCCESS;
148                 } break;
149
150         case LDAP_OPT_DESC:
151                 if( ld == NULL || ld->ld_sb == NULL ) {
152                         /* bad param */
153                         break;
154                 } 
155
156                 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
157                 return LDAP_OPT_SUCCESS;
158
159         case LDAP_OPT_TIMEOUT:
160                 /* the caller has to free outvalue ! */
161                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
162                 {
163                         return LDAP_OPT_ERROR;
164                 }
165                 return LDAP_OPT_SUCCESS;
166                 
167         case LDAP_OPT_NETWORK_TIMEOUT:
168                 /* the caller has to free outvalue ! */
169                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
170                 {
171                         return LDAP_OPT_ERROR;
172                 }
173                 return LDAP_OPT_SUCCESS;
174
175         case LDAP_OPT_DEREF:
176                 * (int *) outvalue = lo->ldo_deref;
177                 return LDAP_OPT_SUCCESS;
178
179         case LDAP_OPT_SIZELIMIT:
180                 * (int *) outvalue = lo->ldo_sizelimit;
181                 return LDAP_OPT_SUCCESS;
182
183         case LDAP_OPT_TIMELIMIT:
184                 * (int *) outvalue = lo->ldo_timelimit;
185                 return LDAP_OPT_SUCCESS;
186
187         case LDAP_OPT_REFERRALS:
188                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
189                 return LDAP_OPT_SUCCESS;
190                 
191         case LDAP_OPT_RESTART:
192                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
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( ld, option, outvalue ) == 0 ) {
286                         return LDAP_OPT_SUCCESS;
287                 }
288 #endif
289 #ifdef HAVE_CYRUS_SASL
290                 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
291                         return LDAP_OPT_SUCCESS;
292                 }
293 #endif
294                 /* bad param */
295                 break;
296         }
297
298         return LDAP_OPT_ERROR;
299 }
300
301 int
302 ldap_set_option(
303         LDAP    *ld,
304         int             option,
305         LDAP_CONST void *invalue)
306 {
307         struct ldapoptions *lo;
308         int *dbglvl = NULL;
309
310         /* Get pointer to global option structure */
311         lo = LDAP_INT_GLOBAL_OPT();
312         if (lo == NULL) {
313                 return LDAP_NO_MEMORY;
314         }
315
316         /*
317          * The architecture to turn on debugging has a chicken and egg
318          * problem. Thus, we introduce a fix here.
319          */
320
321         if (option == LDAP_OPT_DEBUG_LEVEL)
322             dbglvl = (int *) invalue;
323
324         if( lo->ldo_valid != LDAP_INITIALIZED ) {
325                 ldap_int_initialize(lo, dbglvl);
326         }
327
328         if(ld != NULL) {
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         /* Only accessed from inside this function by ldap_set_rebind_proc() */
425         case LDAP_OPT_REBIND_PROC: {
426                         lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;              
427                 } return LDAP_OPT_SUCCESS;
428         case LDAP_OPT_REBIND_PARAMS: {
429                         lo->ldo_rebind_params = (void *)invalue;                
430                 } return LDAP_OPT_SUCCESS;
431         }
432
433         if(invalue == NULL) {
434                 /* no place to set from */
435                 return LDAP_OPT_ERROR;
436         }
437
438         /* options which cannot withstand invalue == NULL */
439
440         switch(option) {
441         case LDAP_OPT_API_INFO:
442         case LDAP_OPT_DESC:
443                 /* READ ONLY */
444                 break;
445
446         case LDAP_OPT_DEREF:
447                 lo->ldo_deref = * (const int *) invalue;
448                 return LDAP_OPT_SUCCESS;
449
450         case LDAP_OPT_SIZELIMIT:
451                 lo->ldo_sizelimit = * (const int *) invalue;
452                 return LDAP_OPT_SUCCESS;
453
454         case LDAP_OPT_TIMELIMIT:
455                 lo->ldo_timelimit = * (const int *) invalue;
456                 return LDAP_OPT_SUCCESS;
457
458         case LDAP_OPT_PROTOCOL_VERSION: {
459                         int vers = * (const int *) invalue;
460                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
461                                 /* not supported */
462                                 break;
463                         }
464                         lo->ldo_version = vers;
465                 } return LDAP_OPT_SUCCESS;
466
467
468         case LDAP_OPT_HOST_NAME: {
469                         const char *host = (const char *) invalue;
470                         LDAPURLDesc *ludlist = NULL;
471                         int rc = LDAP_OPT_SUCCESS;
472
473                         if(host != NULL) {
474                                 rc = ldap_url_parsehosts( &ludlist, host,
475                                         lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
476
477                         } else if(ld == NULL) {
478                                 /*
479                                  * must want global default returned
480                                  * to initial condition.
481                                  */
482                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
483
484                         } else {
485                                 /*
486                                  * must want the session default
487                                  *   updated to the current global default
488                                  */
489                                 ludlist = ldap_url_duplist(
490                                         ldap_int_global_options.ldo_defludp);
491                                 if (ludlist == NULL)
492                                         rc = LDAP_NO_MEMORY;
493                         }
494
495                         if (rc == LDAP_OPT_SUCCESS) {
496                                 if (lo->ldo_defludp != NULL)
497                                         ldap_free_urllist(lo->ldo_defludp);
498                                 lo->ldo_defludp = ludlist;
499                         }
500                         return rc;
501                 }
502
503         case LDAP_OPT_URI: {
504                         const char *urls = (const char *) invalue;
505                         LDAPURLDesc *ludlist = NULL;
506                         int rc = LDAP_OPT_SUCCESS;
507
508                         if(urls != NULL) {
509                                 rc = ldap_url_parselist(&ludlist, urls);
510
511                         } else if(ld == NULL) {
512                                 /*
513                                  * must want global default returned
514                                  * to initial condition.
515                                  */
516                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
517
518                         } else {
519                                 /*
520                                  * must want the session default
521                                  *   updated to the current global default
522                                  */
523                                 ludlist = ldap_url_duplist(
524                                         ldap_int_global_options.ldo_defludp);
525                                 if (ludlist == NULL)
526                                         rc = LDAP_NO_MEMORY;
527                         }
528
529                         if (rc == LDAP_OPT_SUCCESS) {
530                                 if (lo->ldo_defludp != NULL)
531                                         ldap_free_urllist(lo->ldo_defludp);
532                                 lo->ldo_defludp = ludlist;
533                         }
534                         return rc;
535                 }
536
537         case LDAP_OPT_ERROR_NUMBER: {
538                         int err = * (const int *) invalue;
539
540                         if(ld == NULL) {
541                                 /* need a struct ldap */
542                                 break;
543                         }
544
545                         ld->ld_errno = err;
546                 } return LDAP_OPT_SUCCESS;
547
548         case LDAP_OPT_ERROR_STRING: {
549                         const char *err = (const char *) invalue;
550
551                         if(ld == NULL) {
552                                 /* need a struct ldap */
553                                 break;
554                         }
555
556                         if( ld->ld_error ) {
557                                 LDAP_FREE(ld->ld_error);
558                         }
559
560                         ld->ld_error = LDAP_STRDUP(err);
561                 } return LDAP_OPT_SUCCESS;
562
563         case LDAP_OPT_MATCHED_DN: {
564                         const char *err = (const char *) invalue;
565
566                         if(ld == NULL) {
567                                 /* need a struct ldap */
568                                 break;
569                         }
570
571                         if( ld->ld_matched ) {
572                                 LDAP_FREE(ld->ld_matched);
573                         }
574
575                         ld->ld_matched = LDAP_STRDUP(err);
576                 } return LDAP_OPT_SUCCESS;
577
578         case LDAP_OPT_API_FEATURE_INFO:
579                 /* read-only */
580                 break;
581
582         case LDAP_OPT_DEBUG_LEVEL:
583                 lo->ldo_debug = * (const int *) invalue;
584                 return LDAP_OPT_SUCCESS;
585
586         default:
587 #ifdef HAVE_TLS
588                 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
589                 return LDAP_OPT_SUCCESS;
590 #endif
591 #ifdef HAVE_CYRUS_SASL
592                 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
593                         return LDAP_OPT_SUCCESS;
594 #endif
595                 /* bad param */
596                 break;
597         }
598         return LDAP_OPT_ERROR;
599 }
600
601 int
602 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
603 {
604         int rc;
605         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
606         if( rc != LDAP_OPT_SUCCESS ) return rc;
607
608         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
609         return rc;
610 }