]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
Error handling changes including separation of client v. server
[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();
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
312         if( ldap_int_global_options.ldo_valid != LDAP_INITIALIZED ) {
313                 ldap_int_initialize();
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
416         if(invalue == NULL) {
417                 /* no place to set from */
418                 return LDAP_OPT_ERROR;
419         }
420
421         /* options which cannot withstand invalue == NULL */
422
423         switch(option) {
424         case LDAP_OPT_API_INFO:
425         case LDAP_OPT_DESC:
426                 /* READ ONLY */
427                 break;
428
429         case LDAP_OPT_DEREF:
430                 lo->ldo_deref = * (const int *) invalue;
431                 return LDAP_OPT_SUCCESS;
432
433         case LDAP_OPT_SIZELIMIT:
434                 lo->ldo_sizelimit = * (const int *) invalue;
435                 return LDAP_OPT_SUCCESS;
436
437         case LDAP_OPT_TIMELIMIT:
438                 lo->ldo_timelimit = * (const int *) invalue;
439                 return LDAP_OPT_SUCCESS;
440
441         case LDAP_OPT_PROTOCOL_VERSION: {
442                         int vers = * (const int *) invalue;
443                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
444                                 /* not supported */
445                                 break;
446                         }
447                         lo->ldo_version = vers;
448                 } return LDAP_OPT_SUCCESS;
449
450
451         case LDAP_OPT_HOST_NAME: {
452                         const char *host = (const char *) invalue;
453                         LDAPURLDesc *ludlist = NULL;
454                         int rc = LDAP_OPT_SUCCESS;
455
456                         if(host != NULL) {
457                                 rc = ldap_url_parsehosts(&ludlist, host);
458
459                         } else if(ld == NULL) {
460                                 /*
461                                  * must want global default returned
462                                  * to initial condition.
463                                  */
464                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
465
466                         } else {
467                                 /*
468                                  * must want the session default
469                                  *   updated to the current global default
470                                  */
471                                 ludlist = ldap_url_duplist(
472                                         ldap_int_global_options.ldo_defludp);
473                                 if (ludlist == NULL)
474                                         rc = LDAP_NO_MEMORY;
475                         }
476
477                         if (rc == LDAP_OPT_SUCCESS) {
478                                 if (lo->ldo_defludp != NULL)
479                                         ldap_free_urllist(lo->ldo_defludp);
480                                 lo->ldo_defludp = ludlist;
481                         }
482                         return rc;
483                 }
484
485         case LDAP_OPT_URI: {
486                         const char *urls = (const char *) invalue;
487                         LDAPURLDesc *ludlist = NULL;
488                         int rc = LDAP_OPT_SUCCESS;
489
490                         if(urls != NULL) {
491                                 rc = ldap_url_parselist(&ludlist, urls);
492
493                         } else if(ld == NULL) {
494                                 /*
495                                  * must want global default returned
496                                  * to initial condition.
497                                  */
498                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
499
500                         } else {
501                                 /*
502                                  * must want the session default
503                                  *   updated to the current global default
504                                  */
505                                 ludlist = ldap_url_duplist(
506                                         ldap_int_global_options.ldo_defludp);
507                                 if (ludlist == NULL)
508                                         rc = LDAP_NO_MEMORY;
509                         }
510
511                         if (rc == LDAP_OPT_SUCCESS) {
512                                 if (lo->ldo_defludp != NULL)
513                                         ldap_free_urllist(lo->ldo_defludp);
514                                 lo->ldo_defludp = ludlist;
515                         }
516                         return rc;
517                 }
518
519         case LDAP_OPT_ERROR_NUMBER: {
520                         int err = * (const int *) invalue;
521
522                         if(ld == NULL) {
523                                 /* need a struct ldap */
524                                 break;
525                         }
526
527                         ld->ld_errno = err;
528                 } return LDAP_OPT_SUCCESS;
529
530         case LDAP_OPT_ERROR_STRING: {
531                         const char *err = (const char *) invalue;
532
533                         if(ld == NULL) {
534                                 /* need a struct ldap */
535                                 break;
536                         }
537
538                         if( ld->ld_error ) {
539                                 LDAP_FREE(ld->ld_error);
540                         }
541
542                         ld->ld_error = LDAP_STRDUP(err);
543                 } return LDAP_OPT_SUCCESS;
544
545         case LDAP_OPT_MATCHED_DN: {
546                         const char *err = (const char *) invalue;
547
548                         if(ld == NULL) {
549                                 /* need a struct ldap */
550                                 break;
551                         }
552
553                         if( ld->ld_matched ) {
554                                 LDAP_FREE(ld->ld_matched);
555                         }
556
557                         ld->ld_matched = LDAP_STRDUP(err);
558                 } return LDAP_OPT_SUCCESS;
559
560         case LDAP_OPT_API_FEATURE_INFO:
561                 /* read-only */
562                 break;
563
564         case LDAP_OPT_DEBUG_LEVEL:
565                 lo->ldo_debug = * (const int *) invalue;
566                 return LDAP_OPT_SUCCESS;
567
568         default:
569 #ifdef HAVE_TLS
570                 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
571                 return LDAP_OPT_SUCCESS;
572 #endif
573 #ifdef HAVE_CYRUS_SASL
574                 if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
575                         return LDAP_OPT_SUCCESS;
576 #endif
577                 /* bad param */
578                 break;
579         }
580         return LDAP_OPT_ERROR;
581 }