]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
create SASL_LIBS to hold -lsasl
[openldap] / libraries / libldap / options.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5
6 #include "portable.h"
7
8 #include <stdio.h>
9
10 #include <ac/stdlib.h>
11
12 #include <ac/socket.h>
13 #include <ac/string.h>
14 #include <ac/time.h>
15
16 #include "ldap-int.h"
17
18 static const LDAPAPIFeatureInfo features[] = {
19 #ifdef LDAP_API_FEATURE_X_OPENLDAP
20         {       /* OpenLDAP Extensions API Feature */
21                 LDAP_FEATURE_INFO_VERSION,
22                 "X_OPENLDAP",
23                 LDAP_API_FEATURE_X_OPENLDAP
24         },
25 #endif
26
27 #ifdef LDAP_API_FEATURE_THREAD_SAFE
28         {       /* Basic Thread Safe */
29                 LDAP_FEATURE_INFO_VERSION,
30                 "THREAD_SAFE",
31                 LDAP_API_FEATURE_THREAD_SAFE
32         },
33 #endif
34 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
35         {       /* Session Thread Safe */
36                 LDAP_FEATURE_INFO_VERSION,
37                 "SESSION_THREAD_SAFE",
38                 LDAP_API_FEATURE_SESSION_THREAD_SAFE
39         },
40 #endif
41 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
42         {       /* Operation Thread Safe */
43                 LDAP_FEATURE_INFO_VERSION,
44                 "OPERATION_THREAD_SAFE",
45                 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
46         },
47 #endif
48 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
49         {       /* OpenLDAP Reentrant */
50                 LDAP_FEATURE_INFO_VERSION,
51                 "X_OPENLDAP_REENTRANT",
52                 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
53         },
54 #endif
55 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
56         defined( LDAP_THREAD_SAFE )
57         {       /* OpenLDAP Thread Safe */
58                 LDAP_FEATURE_INFO_VERSION,
59                 "X_OPENLDAP_THREAD_SAFE",
60                 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
61         },
62 #endif
63 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
64         {       /* DNS */
65                 LDAP_FEATURE_INFO_VERSION,
66                 "X_OPENLDAP_V2_DNS",
67                 LDAP_API_FEATURE_X_OPENLDAP_V2_DNS
68         },
69 #endif
70 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
71         {       /* V2 Referrals */
72                 LDAP_FEATURE_INFO_VERSION,
73                 "X_OPENLDAP_V2_REFERRALS",
74                 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
75         },
76 #endif
77         {0, NULL, 0}
78 };
79
80 int
81 ldap_get_option(
82         LDAP_CONST LDAP *ld,
83         int             option,
84         void    *outvalue)
85 {
86         LDAP_CONST struct ldapoptions *lo;
87
88         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
89                 ldap_int_initialize();
90         }
91
92         if(ld == NULL) {
93                 lo = &ldap_int_global_options;
94
95         } else {
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) {
152                         /* bad param */
153                         break;
154                 } 
155
156                 * (ber_socket_t *) outvalue = ber_pvt_sb_get_desc( &(ld->ld_sb) );
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_DNS:      /* LDAPv2 */
196                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_DNS);
197                 return LDAP_OPT_SUCCESS;
198
199         case LDAP_OPT_PROTOCOL_VERSION:
200                 if ((ld != NULL) && ld->ld_version) {
201                         * (int *) outvalue = ld->ld_version;
202                 } else { 
203                         * (int *) outvalue = lo->ldo_version;
204                 }
205                 return LDAP_OPT_SUCCESS;
206
207         case LDAP_OPT_SERVER_CONTROLS:
208                 * (LDAPControl ***) outvalue =
209                         ldap_controls_dup( lo->ldo_sctrls );
210
211                 return LDAP_OPT_SUCCESS;
212
213         case LDAP_OPT_CLIENT_CONTROLS:
214                 * (LDAPControl ***) outvalue =
215                         ldap_controls_dup( lo->ldo_cctrls );
216
217                 return LDAP_OPT_SUCCESS;
218
219         case LDAP_OPT_HOST_NAME:
220                 * (char **) outvalue = LDAP_STRDUP(lo->ldo_defhost);
221                 return LDAP_OPT_SUCCESS;
222
223         case LDAP_OPT_ERROR_NUMBER:
224                 if(ld == NULL) {
225                         /* bad param */
226                         break;
227                 } 
228                 * (int *) outvalue = ld->ld_errno;
229                 return LDAP_OPT_SUCCESS;
230
231         case LDAP_OPT_ERROR_STRING:
232                 if(ld == NULL) {
233                         /* bad param */
234                         break;
235                 } 
236
237                 if( ld->ld_error == NULL ) {
238                         * (char **) outvalue = NULL;
239                 } else {
240                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
241                 }
242
243                 return LDAP_OPT_SUCCESS;
244
245         case LDAP_OPT_MATCHED_DN:
246                 if(ld == NULL) {
247                         /* bad param */
248                         break;
249                 } 
250
251                 if( ld->ld_matched == NULL ) {
252                         * (char **) outvalue = NULL;
253                 } else {
254                         * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
255                 }
256
257                 return LDAP_OPT_SUCCESS;
258
259         case LDAP_OPT_API_FEATURE_INFO: {
260                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
261                         int i;
262
263                         if(info == NULL) return LDAP_OPT_ERROR;
264
265                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
266                                 /* api info version mismatch */
267                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
268                                 return LDAP_OPT_ERROR;
269                         }
270
271                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
272
273                         for(i=0; features[i].ldapaif_name != NULL; i++) {
274                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
275                                         info->ldapaif_version =
276                                                 features[i].ldapaif_version;
277                                         return LDAP_OPT_SUCCESS;
278                                 }
279                         }
280                 }
281                 break;
282
283         case LDAP_OPT_DEBUG_LEVEL:
284                 * (int *) outvalue = lo->ldo_debug;
285                 return LDAP_OPT_SUCCESS;
286
287         default:
288 #ifdef HAVE_TLS
289                 if ( ldap_pvt_tls_get_option(lo, 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
307         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
308                 ldap_int_initialize();
309         }
310
311         if(ld == NULL) {
312                 lo = &ldap_int_global_options;
313
314         } else {
315                 assert( LDAP_VALID( ld ) );
316
317                 if( !LDAP_VALID( ld ) ) {
318                         return LDAP_OPT_ERROR;
319                 }
320
321                 lo = &ld->ld_options;
322         }
323
324         switch(option) {
325         case LDAP_OPT_REFERRALS:
326                 if(invalue == LDAP_OPT_OFF) {
327                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
328                 } else {
329                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
330                 }
331                 return LDAP_OPT_SUCCESS;
332
333         case LDAP_OPT_RESTART:
334                 if(invalue == LDAP_OPT_OFF) {
335                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
336                 } else {
337                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
338                 }
339                 return LDAP_OPT_SUCCESS;
340         }
341
342         /* options which can withstand invalue == NULL */
343         switch ( option ) {
344         case LDAP_OPT_SERVER_CONTROLS: {
345                         LDAPControl *const *controls =
346                                 (LDAPControl *const *) invalue;
347
348                         ldap_controls_free( lo->ldo_sctrls );
349
350                         if( controls == NULL || *controls == NULL ) {
351                                 lo->ldo_sctrls = NULL;
352                                 return LDAP_OPT_SUCCESS;
353                         }
354                                 
355                         lo->ldo_sctrls = ldap_controls_dup( controls );
356
357                         if(lo->ldo_sctrls == NULL) {
358                                 /* memory allocation error ? */
359                                 break;
360                         }
361                 } return LDAP_OPT_SUCCESS;
362
363         case LDAP_OPT_CLIENT_CONTROLS: {
364                         LDAPControl *const *controls =
365                                 (LDAPControl *const *) invalue;
366
367                         ldap_controls_free( lo->ldo_cctrls );
368
369                         if( controls == NULL || *controls == NULL ) {
370                                 lo->ldo_cctrls = NULL;
371                                 return LDAP_OPT_SUCCESS;
372                         }
373                                 
374                         lo->ldo_cctrls = ldap_controls_dup( controls );
375
376                         if(lo->ldo_cctrls == NULL) {
377                                 /* memory allocation error ? */
378                                 break;
379                         }
380                 } return LDAP_OPT_SUCCESS;
381
382         case LDAP_OPT_TIMEOUT: {
383                         const struct timeval *tv = 
384                                 (struct timeval *) invalue;
385
386                         if ( lo->ldo_tm_api != NULL ) {
387                                 LDAP_FREE( lo->ldo_tm_api );
388                                 lo->ldo_tm_api = NULL;
389                         }
390
391                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
392                                 return LDAP_OPT_ERROR;
393                         }
394                 } return LDAP_OPT_SUCCESS;
395
396         case LDAP_OPT_NETWORK_TIMEOUT: {
397                         const struct timeval *tv = 
398                                 (struct timeval *) invalue;
399
400                         if ( lo->ldo_tm_net != NULL ) {
401                                 LDAP_FREE( lo->ldo_tm_net );
402                                 lo->ldo_tm_net = NULL;
403                         }
404
405                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
406                                 return LDAP_OPT_ERROR;
407                         }
408                 } return LDAP_OPT_SUCCESS;
409         }
410
411         if(invalue == NULL) {
412                 /* no place to set from */
413                 return LDAP_OPT_ERROR;
414         }
415
416         /* options which cannot withstand invalue == NULL */
417
418         switch(option) {
419         case LDAP_OPT_API_INFO:
420         case LDAP_OPT_DESC:
421                 /* READ ONLY */
422                 break;
423
424         case LDAP_OPT_DEREF:
425                 lo->ldo_deref = * (const int *) invalue;
426                 return LDAP_OPT_SUCCESS;
427
428         case LDAP_OPT_SIZELIMIT:
429                 lo->ldo_sizelimit = * (const int *) invalue;
430                 return LDAP_OPT_SUCCESS;
431
432         case LDAP_OPT_TIMELIMIT:
433                 lo->ldo_timelimit = * (const int *) invalue;
434                 return LDAP_OPT_SUCCESS;
435
436         case LDAP_OPT_PROTOCOL_VERSION: {
437                         int vers = * (const int *) invalue;
438                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
439                                 /* not supported */
440                                 break;
441                         }
442                         ld->ld_version = vers;
443                 } return LDAP_OPT_SUCCESS;
444
445
446         case LDAP_OPT_HOST_NAME: {
447                         const char *host = (const char *) invalue;
448
449                         if(lo->ldo_defhost != NULL) {
450                                 LDAP_FREE(lo->ldo_defhost);
451                                 lo->ldo_defhost = NULL;
452                         }
453
454                         if(host != NULL) {
455                                 lo->ldo_defhost = LDAP_STRDUP(host);
456                                 return LDAP_OPT_SUCCESS;
457                         }
458
459                         if(ld == NULL) {
460                                 /*
461                                  * must want global default returned
462                                  * to initial condition.
463                                  */
464                                 lo->ldo_defhost = LDAP_STRDUP("localhost");
465
466                         } else {
467                                 /*
468                                  * must want the session default
469                                  *   updated to the current global default
470                                  */
471                                 lo->ldo_defhost = LDAP_STRDUP(
472                                         ldap_int_global_options.ldo_defhost);
473                         }
474                 } return LDAP_OPT_SUCCESS;
475
476         case LDAP_OPT_ERROR_NUMBER: {
477                         int err = * (const int *) invalue;
478
479                         if(ld == NULL) {
480                                 /* need a struct ldap */
481                                 break;
482                         }
483
484                         ld->ld_errno = err;
485                 } return LDAP_OPT_SUCCESS;
486
487         case LDAP_OPT_ERROR_STRING: {
488                         const char *err = (const char *) invalue;
489
490                         if(ld == NULL) {
491                                 /* need a struct ldap */
492                                 break;
493                         }
494
495                         if( ld->ld_error ) {
496                                 LDAP_FREE(ld->ld_error);
497                         }
498
499                         ld->ld_error = LDAP_STRDUP(err);
500                 } return LDAP_OPT_SUCCESS;
501
502         case LDAP_OPT_MATCHED_DN: {
503                         const char *err = (const char *) invalue;
504
505                         if(ld == NULL) {
506                                 /* need a struct ldap */
507                                 break;
508                         }
509
510                         if( ld->ld_matched ) {
511                                 LDAP_FREE(ld->ld_matched);
512                         }
513
514                         ld->ld_matched = LDAP_STRDUP(err);
515                 } return LDAP_OPT_SUCCESS;
516
517         case LDAP_OPT_API_FEATURE_INFO:
518                 /* read-only */
519                 break;
520
521         case LDAP_OPT_DEBUG_LEVEL:
522                 lo->ldo_debug = * (const int *) invalue;
523                 return LDAP_OPT_SUCCESS;
524
525         default:
526 #ifdef HAVE_TLS
527                 if ( ldap_pvt_tls_set_option( lo, option, invalue ) == 0 )
528                         return LDAP_OPT_SUCCESS;
529 #endif
530                 /* bad param */
531                 break;
532         }
533         return LDAP_OPT_ERROR;
534 }