]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
acea330be965bf77c170e25d2ecedb06331b07cd
[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_PROTOCOL_VERSION:
192                 * (int *) outvalue = lo->ldo_version;
193                 return LDAP_OPT_SUCCESS;
194
195         case LDAP_OPT_SERVER_CONTROLS:
196                 * (LDAPControl ***) outvalue =
197                         ldap_controls_dup( lo->ldo_sctrls );
198
199                 return LDAP_OPT_SUCCESS;
200
201         case LDAP_OPT_CLIENT_CONTROLS:
202                 * (LDAPControl ***) outvalue =
203                         ldap_controls_dup( lo->ldo_cctrls );
204
205                 return LDAP_OPT_SUCCESS;
206
207         case LDAP_OPT_HOST_NAME:
208                 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
209                 return LDAP_OPT_SUCCESS;
210
211         case LDAP_OPT_URI:
212                 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
213                 return LDAP_OPT_SUCCESS;
214
215         case LDAP_OPT_ERROR_NUMBER:
216                 if(ld == NULL) {
217                         /* bad param */
218                         break;
219                 } 
220                 * (int *) outvalue = ld->ld_errno;
221                 return LDAP_OPT_SUCCESS;
222
223         case LDAP_OPT_ERROR_STRING:
224                 if(ld == NULL) {
225                         /* bad param */
226                         break;
227                 } 
228
229                 if( ld->ld_error == NULL ) {
230                         * (char **) outvalue = NULL;
231                 } else {
232                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
233                 }
234
235                 return LDAP_OPT_SUCCESS;
236
237         case LDAP_OPT_MATCHED_DN:
238                 if(ld == NULL) {
239                         /* bad param */
240                         break;
241                 } 
242
243                 if( ld->ld_matched == NULL ) {
244                         * (char **) outvalue = NULL;
245                 } else {
246                         * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
247                 }
248
249                 return LDAP_OPT_SUCCESS;
250
251         case LDAP_OPT_API_FEATURE_INFO: {
252                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
253                         int i;
254
255                         if(info == NULL) return LDAP_OPT_ERROR;
256
257                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
258                                 /* api info version mismatch */
259                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
260                                 return LDAP_OPT_ERROR;
261                         }
262
263                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
264
265                         for(i=0; features[i].ldapaif_name != NULL; i++) {
266                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
267                                         info->ldapaif_version =
268                                                 features[i].ldapaif_version;
269                                         return LDAP_OPT_SUCCESS;
270                                 }
271                         }
272                 }
273                 break;
274
275         case LDAP_OPT_DEBUG_LEVEL:
276                 * (int *) outvalue = lo->ldo_debug;
277                 return LDAP_OPT_SUCCESS;
278
279         default:
280 #ifdef HAVE_TLS
281                 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
282                         return LDAP_OPT_SUCCESS;
283 #endif
284 #ifdef HAVE_CYRUS_SASL
285                 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
286                         return LDAP_OPT_SUCCESS;
287 #endif
288                 /* bad param */
289                 break;
290         }
291
292         return LDAP_OPT_ERROR;
293 }
294
295 int
296 ldap_set_option(
297         LDAP    *ld,
298         int             option,
299         LDAP_CONST void *invalue)
300 {
301         struct ldapoptions *lo;
302         int *dbglvl = NULL;
303
304         /*
305          * The architecture to turn on debugging has a chicken and egg
306          * problem. Thus, we introduce a fix here.
307          */
308
309         if (option == LDAP_OPT_DEBUG_LEVEL)
310             dbglvl = (int *) invalue;
311
312         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
313                 ldap_int_initialize(dbglvl);
314         }
315
316         if(ld == NULL) {
317                 lo = &ldap_int_global_options;
318
319         } else {
320                 assert( LDAP_VALID( ld ) );
321
322                 if( !LDAP_VALID( ld ) ) {
323                         return LDAP_OPT_ERROR;
324                 }
325
326                 lo = &ld->ld_options;
327         }
328
329         switch(option) {
330         case LDAP_OPT_REFERRALS:
331                 if(invalue == LDAP_OPT_OFF) {
332                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
333                 } else {
334                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
335                 }
336                 return LDAP_OPT_SUCCESS;
337
338         case LDAP_OPT_RESTART:
339                 if(invalue == LDAP_OPT_OFF) {
340                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
341                 } else {
342                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
343                 }
344                 return LDAP_OPT_SUCCESS;
345         }
346
347         /* options which can withstand invalue == NULL */
348         switch ( option ) {
349         case LDAP_OPT_SERVER_CONTROLS: {
350                         LDAPControl *const *controls =
351                                 (LDAPControl *const *) invalue;
352
353                         ldap_controls_free( lo->ldo_sctrls );
354
355                         if( controls == NULL || *controls == NULL ) {
356                                 lo->ldo_sctrls = NULL;
357                                 return LDAP_OPT_SUCCESS;
358                         }
359                                 
360                         lo->ldo_sctrls = ldap_controls_dup( controls );
361
362                         if(lo->ldo_sctrls == NULL) {
363                                 /* memory allocation error ? */
364                                 break;
365                         }
366                 } return LDAP_OPT_SUCCESS;
367
368         case LDAP_OPT_CLIENT_CONTROLS: {
369                         LDAPControl *const *controls =
370                                 (LDAPControl *const *) invalue;
371
372                         ldap_controls_free( lo->ldo_cctrls );
373
374                         if( controls == NULL || *controls == NULL ) {
375                                 lo->ldo_cctrls = NULL;
376                                 return LDAP_OPT_SUCCESS;
377                         }
378                                 
379                         lo->ldo_cctrls = ldap_controls_dup( controls );
380
381                         if(lo->ldo_cctrls == NULL) {
382                                 /* memory allocation error ? */
383                                 break;
384                         }
385                 } return LDAP_OPT_SUCCESS;
386
387         case LDAP_OPT_TIMEOUT: {
388                         const struct timeval *tv = 
389                                 (const struct timeval *) invalue;
390
391                         if ( lo->ldo_tm_api != NULL ) {
392                                 LDAP_FREE( lo->ldo_tm_api );
393                                 lo->ldo_tm_api = NULL;
394                         }
395
396                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
397                                 return LDAP_OPT_ERROR;
398                         }
399                 } return LDAP_OPT_SUCCESS;
400
401         case LDAP_OPT_NETWORK_TIMEOUT: {
402                         const struct timeval *tv = 
403                                 (const struct timeval *) invalue;
404
405                         if ( lo->ldo_tm_net != NULL ) {
406                                 LDAP_FREE( lo->ldo_tm_net );
407                                 lo->ldo_tm_net = NULL;
408                         }
409
410                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
411                                 return LDAP_OPT_ERROR;
412                         }
413                 } return LDAP_OPT_SUCCESS;
414
415         /* Only accessed from inside this function by ldap_set_rebind_proc() */
416         case LDAP_OPT_REBIND_PROC: {
417                         lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;               
418                 } return LDAP_OPT_SUCCESS;
419         }
420
421         if(invalue == NULL) {
422                 /* no place to set from */
423                 return LDAP_OPT_ERROR;
424         }
425
426         /* options which cannot withstand invalue == NULL */
427
428         switch(option) {
429         case LDAP_OPT_API_INFO:
430         case LDAP_OPT_DESC:
431                 /* READ ONLY */
432                 break;
433
434         case LDAP_OPT_DEREF:
435                 lo->ldo_deref = * (const int *) invalue;
436                 return LDAP_OPT_SUCCESS;
437
438         case LDAP_OPT_SIZELIMIT:
439                 lo->ldo_sizelimit = * (const int *) invalue;
440                 return LDAP_OPT_SUCCESS;
441
442         case LDAP_OPT_TIMELIMIT:
443                 lo->ldo_timelimit = * (const int *) invalue;
444                 return LDAP_OPT_SUCCESS;
445
446         case LDAP_OPT_PROTOCOL_VERSION: {
447                         int vers = * (const int *) invalue;
448                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
449                                 /* not supported */
450                                 break;
451                         }
452                         lo->ldo_version = vers;
453                 } return LDAP_OPT_SUCCESS;
454
455
456         case LDAP_OPT_HOST_NAME: {
457                         const char *host = (const char *) invalue;
458                         LDAPURLDesc *ludlist = NULL;
459                         int rc = LDAP_OPT_SUCCESS;
460
461                         if(host != NULL) {
462                                 rc = ldap_url_parsehosts(&ludlist, host);
463
464                         } else if(ld == NULL) {
465                                 /*
466                                  * must want global default returned
467                                  * to initial condition.
468                                  */
469                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
470
471                         } else {
472                                 /*
473                                  * must want the session default
474                                  *   updated to the current global default
475                                  */
476                                 ludlist = ldap_url_duplist(
477                                         ldap_int_global_options.ldo_defludp);
478                                 if (ludlist == NULL)
479                                         rc = LDAP_NO_MEMORY;
480                         }
481
482                         if (rc == LDAP_OPT_SUCCESS) {
483                                 if (lo->ldo_defludp != NULL)
484                                         ldap_free_urllist(lo->ldo_defludp);
485                                 lo->ldo_defludp = ludlist;
486                         }
487                         return rc;
488                 }
489
490         case LDAP_OPT_URI: {
491                         const char *urls = (const char *) invalue;
492                         LDAPURLDesc *ludlist = NULL;
493                         int rc = LDAP_OPT_SUCCESS;
494
495                         if(urls != NULL) {
496                                 rc = ldap_url_parselist(&ludlist, urls);
497
498                         } else if(ld == NULL) {
499                                 /*
500                                  * must want global default returned
501                                  * to initial condition.
502                                  */
503                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
504
505                         } else {
506                                 /*
507                                  * must want the session default
508                                  *   updated to the current global default
509                                  */
510                                 ludlist = ldap_url_duplist(
511                                         ldap_int_global_options.ldo_defludp);
512                                 if (ludlist == NULL)
513                                         rc = LDAP_NO_MEMORY;
514                         }
515
516                         if (rc == LDAP_OPT_SUCCESS) {
517                                 if (lo->ldo_defludp != NULL)
518                                         ldap_free_urllist(lo->ldo_defludp);
519                                 lo->ldo_defludp = ludlist;
520                         }
521                         return rc;
522                 }
523
524         case LDAP_OPT_ERROR_NUMBER: {
525                         int err = * (const int *) invalue;
526
527                         if(ld == NULL) {
528                                 /* need a struct ldap */
529                                 break;
530                         }
531
532                         ld->ld_errno = err;
533                 } return LDAP_OPT_SUCCESS;
534
535         case LDAP_OPT_ERROR_STRING: {
536                         const char *err = (const char *) invalue;
537
538                         if(ld == NULL) {
539                                 /* need a struct ldap */
540                                 break;
541                         }
542
543                         if( ld->ld_error ) {
544                                 LDAP_FREE(ld->ld_error);
545                         }
546
547                         ld->ld_error = LDAP_STRDUP(err);
548                 } return LDAP_OPT_SUCCESS;
549
550         case LDAP_OPT_MATCHED_DN: {
551                         const char *err = (const char *) invalue;
552
553                         if(ld == NULL) {
554                                 /* need a struct ldap */
555                                 break;
556                         }
557
558                         if( ld->ld_matched ) {
559                                 LDAP_FREE(ld->ld_matched);
560                         }
561
562                         ld->ld_matched = LDAP_STRDUP(err);
563                 } return LDAP_OPT_SUCCESS;
564
565         case LDAP_OPT_API_FEATURE_INFO:
566                 /* read-only */
567                 break;
568
569         case LDAP_OPT_DEBUG_LEVEL:
570                 lo->ldo_debug = * (const int *) invalue;
571                 return LDAP_OPT_SUCCESS;
572
573         default:
574 #ifdef HAVE_TLS
575                 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
576                 return LDAP_OPT_SUCCESS;
577 #endif
578 #ifdef HAVE_CYRUS_SASL
579                 if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
580                         return LDAP_OPT_SUCCESS;
581 #endif
582                 /* bad param */
583                 break;
584         }
585         return LDAP_OPT_ERROR;
586 }
587
588 LIBLDAP_F(int)
589 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
590 {
591         return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));
592 }