]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
Round one of LDAP_F() macro changes. In this round we rename
[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         struct ldapoptions *lo;
83
84         /* Get pointer to global option structure */
85         lo = LDAP_INT_GLOBAL_OPT();   
86         if (NULL == lo) {
87                 return LDAP_NO_MEMORY;
88         }
89
90         if( lo->ldo_valid != LDAP_INITIALIZED ) {
91                 ldap_int_initialize(lo, NULL);
92         }
93
94         if(ld != NULL) {
95                 assert( LDAP_VALID( ld ) );
96
97                 if( !LDAP_VALID( ld ) ) {
98                         return LDAP_OPT_ERROR;
99                 }
100
101                 lo = &ld->ld_options;
102         }
103
104         if(outvalue == NULL) {
105                 /* no place to get to */
106                 return LDAP_OPT_ERROR;
107         }
108
109         switch(option) {
110         case LDAP_OPT_API_INFO: {
111                         struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
112
113                         if(info == NULL) {
114                                 /* outvalue must point to an apiinfo structure */
115                                 return LDAP_OPT_ERROR;
116                         }
117
118                         if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
119                                 /* api info version mismatch */
120                                 info->ldapai_info_version = LDAP_API_INFO_VERSION;
121                                 return LDAP_OPT_ERROR;
122                         }
123
124                         info->ldapai_api_version = LDAP_API_VERSION;
125                         info->ldapai_api_version = LDAP_API_VERSION;
126                         info->ldapai_protocol_version = LDAP_VERSION_MAX;
127
128                         if(features[0].ldapaif_name == NULL) {
129                                 info->ldapai_extensions = NULL;
130                         } else {
131                                 int i;
132                                 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
133                                         sizeof(features)/sizeof(LDAPAPIFeatureInfo));
134
135                                 for(i=0; features[i].ldapaif_name != NULL; i++) {
136                                         info->ldapai_extensions[i] =
137                                                 LDAP_STRDUP(features[i].ldapaif_name);
138                                 }
139
140                                 info->ldapai_extensions[i] = NULL;
141                         }
142
143                         info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
144                         info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
145
146                         return LDAP_OPT_SUCCESS;
147                 } break;
148
149         case LDAP_OPT_DESC:
150                 if( ld == NULL || ld->ld_sb == NULL ) {
151                         /* bad param */
152                         break;
153                 } 
154
155                 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
156                 return LDAP_OPT_SUCCESS;
157
158         case LDAP_OPT_TIMEOUT:
159                 /* the caller has to free outvalue ! */
160                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 )
161                 {
162                         return LDAP_OPT_ERROR;
163                 }
164                 return LDAP_OPT_SUCCESS;
165                 
166         case LDAP_OPT_NETWORK_TIMEOUT:
167                 /* the caller has to free outvalue ! */
168                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 )
169                 {
170                         return LDAP_OPT_ERROR;
171                 }
172                 return LDAP_OPT_SUCCESS;
173
174         case LDAP_OPT_DEREF:
175                 * (int *) outvalue = lo->ldo_deref;
176                 return LDAP_OPT_SUCCESS;
177
178         case LDAP_OPT_SIZELIMIT:
179                 * (int *) outvalue = lo->ldo_sizelimit;
180                 return LDAP_OPT_SUCCESS;
181
182         case LDAP_OPT_TIMELIMIT:
183                 * (int *) outvalue = lo->ldo_timelimit;
184                 return LDAP_OPT_SUCCESS;
185
186         case LDAP_OPT_REFERRALS:
187                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
188                 return LDAP_OPT_SUCCESS;
189                 
190         case LDAP_OPT_RESTART:
191                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
192                 return LDAP_OPT_SUCCESS;
193
194         case LDAP_OPT_PROTOCOL_VERSION:
195                 * (int *) outvalue = lo->ldo_version;
196                 return LDAP_OPT_SUCCESS;
197
198         case LDAP_OPT_SERVER_CONTROLS:
199                 * (LDAPControl ***) outvalue =
200                         ldap_controls_dup( lo->ldo_sctrls );
201
202                 return LDAP_OPT_SUCCESS;
203
204         case LDAP_OPT_CLIENT_CONTROLS:
205                 * (LDAPControl ***) outvalue =
206                         ldap_controls_dup( lo->ldo_cctrls );
207
208                 return LDAP_OPT_SUCCESS;
209
210         case LDAP_OPT_HOST_NAME:
211                 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
212                 return LDAP_OPT_SUCCESS;
213
214         case LDAP_OPT_URI:
215                 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
216                 return LDAP_OPT_SUCCESS;
217
218         case LDAP_OPT_ERROR_NUMBER:
219                 if(ld == NULL) {
220                         /* bad param */
221                         break;
222                 } 
223                 * (int *) outvalue = ld->ld_errno;
224                 return LDAP_OPT_SUCCESS;
225
226         case LDAP_OPT_ERROR_STRING:
227                 if(ld == NULL) {
228                         /* bad param */
229                         break;
230                 } 
231
232                 if( ld->ld_error == NULL ) {
233                         * (char **) outvalue = NULL;
234                 } else {
235                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
236                 }
237
238                 return LDAP_OPT_SUCCESS;
239
240         case LDAP_OPT_MATCHED_DN:
241                 if(ld == NULL) {
242                         /* bad param */
243                         break;
244                 } 
245
246                 if( ld->ld_matched == NULL ) {
247                         * (char **) outvalue = NULL;
248                 } else {
249                         * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
250                 }
251
252                 return LDAP_OPT_SUCCESS;
253
254         case LDAP_OPT_API_FEATURE_INFO: {
255                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
256                         int i;
257
258                         if(info == NULL) return LDAP_OPT_ERROR;
259
260                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
261                                 /* api info version mismatch */
262                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
263                                 return LDAP_OPT_ERROR;
264                         }
265
266                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
267
268                         for(i=0; features[i].ldapaif_name != NULL; i++) {
269                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
270                                         info->ldapaif_version =
271                                                 features[i].ldapaif_version;
272                                         return LDAP_OPT_SUCCESS;
273                                 }
274                         }
275                 }
276                 break;
277
278         case LDAP_OPT_DEBUG_LEVEL:
279                 * (int *) outvalue = lo->ldo_debug;
280                 return LDAP_OPT_SUCCESS;
281
282         default:
283 #ifdef HAVE_TLS
284                 if ( ldap_pvt_tls_get_option((struct ldapoptions *)lo, option, outvalue ) == 0 )
285                         return LDAP_OPT_SUCCESS;
286 #endif
287 #ifdef HAVE_CYRUS_SASL
288                 if ( ldap_pvt_sasl_get_option(ld, option, outvalue ) == 0 )
289                         return LDAP_OPT_SUCCESS;
290 #endif
291                 /* bad param */
292                 break;
293         }
294
295         return LDAP_OPT_ERROR;
296 }
297
298 int
299 ldap_set_option(
300         LDAP    *ld,
301         int             option,
302         LDAP_CONST void *invalue)
303 {
304         struct ldapoptions *lo;
305         int *dbglvl = NULL;
306
307         /* Get pointer to global option structure */
308         lo = LDAP_INT_GLOBAL_OPT();
309         if (lo == NULL) {
310                 return LDAP_NO_MEMORY;
311         }
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( lo->ldo_valid != LDAP_INITIALIZED ) {
322                 ldap_int_initialize(lo, dbglvl);
323         }
324
325         if(ld != NULL) {
326                 assert( LDAP_VALID( ld ) );
327
328                 if( !LDAP_VALID( ld ) ) {
329                         return LDAP_OPT_ERROR;
330                 }
331
332                 lo = &ld->ld_options;
333         }
334
335         switch(option) {
336         case LDAP_OPT_REFERRALS:
337                 if(invalue == LDAP_OPT_OFF) {
338                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
339                 } else {
340                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
341                 }
342                 return LDAP_OPT_SUCCESS;
343
344         case LDAP_OPT_RESTART:
345                 if(invalue == LDAP_OPT_OFF) {
346                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
347                 } else {
348                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
349                 }
350                 return LDAP_OPT_SUCCESS;
351         }
352
353         /* options which can withstand invalue == NULL */
354         switch ( option ) {
355         case LDAP_OPT_SERVER_CONTROLS: {
356                         LDAPControl *const *controls =
357                                 (LDAPControl *const *) invalue;
358
359                         ldap_controls_free( lo->ldo_sctrls );
360
361                         if( controls == NULL || *controls == NULL ) {
362                                 lo->ldo_sctrls = NULL;
363                                 return LDAP_OPT_SUCCESS;
364                         }
365                                 
366                         lo->ldo_sctrls = ldap_controls_dup( controls );
367
368                         if(lo->ldo_sctrls == NULL) {
369                                 /* memory allocation error ? */
370                                 break;
371                         }
372                 } return LDAP_OPT_SUCCESS;
373
374         case LDAP_OPT_CLIENT_CONTROLS: {
375                         LDAPControl *const *controls =
376                                 (LDAPControl *const *) invalue;
377
378                         ldap_controls_free( lo->ldo_cctrls );
379
380                         if( controls == NULL || *controls == NULL ) {
381                                 lo->ldo_cctrls = NULL;
382                                 return LDAP_OPT_SUCCESS;
383                         }
384                                 
385                         lo->ldo_cctrls = ldap_controls_dup( controls );
386
387                         if(lo->ldo_cctrls == NULL) {
388                                 /* memory allocation error ? */
389                                 break;
390                         }
391                 } return LDAP_OPT_SUCCESS;
392
393         case LDAP_OPT_TIMEOUT: {
394                         const struct timeval *tv = 
395                                 (const struct timeval *) invalue;
396
397                         if ( lo->ldo_tm_api != NULL ) {
398                                 LDAP_FREE( lo->ldo_tm_api );
399                                 lo->ldo_tm_api = NULL;
400                         }
401
402                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
403                                 return LDAP_OPT_ERROR;
404                         }
405                 } return LDAP_OPT_SUCCESS;
406
407         case LDAP_OPT_NETWORK_TIMEOUT: {
408                         const struct timeval *tv = 
409                                 (const struct timeval *) invalue;
410
411                         if ( lo->ldo_tm_net != NULL ) {
412                                 LDAP_FREE( lo->ldo_tm_net );
413                                 lo->ldo_tm_net = NULL;
414                         }
415
416                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
417                                 return LDAP_OPT_ERROR;
418                         }
419                 } return LDAP_OPT_SUCCESS;
420
421         /* Only accessed from inside this function by ldap_set_rebind_proc() */
422         case LDAP_OPT_REBIND_PROC: {
423                         lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;               
424                 } return LDAP_OPT_SUCCESS;
425         }
426
427         if(invalue == NULL) {
428                 /* no place to set from */
429                 return LDAP_OPT_ERROR;
430         }
431
432         /* options which cannot withstand invalue == NULL */
433
434         switch(option) {
435         case LDAP_OPT_API_INFO:
436         case LDAP_OPT_DESC:
437                 /* READ ONLY */
438                 break;
439
440         case LDAP_OPT_DEREF:
441                 lo->ldo_deref = * (const int *) invalue;
442                 return LDAP_OPT_SUCCESS;
443
444         case LDAP_OPT_SIZELIMIT:
445                 lo->ldo_sizelimit = * (const int *) invalue;
446                 return LDAP_OPT_SUCCESS;
447
448         case LDAP_OPT_TIMELIMIT:
449                 lo->ldo_timelimit = * (const int *) invalue;
450                 return LDAP_OPT_SUCCESS;
451
452         case LDAP_OPT_PROTOCOL_VERSION: {
453                         int vers = * (const int *) invalue;
454                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
455                                 /* not supported */
456                                 break;
457                         }
458                         lo->ldo_version = vers;
459                 } return LDAP_OPT_SUCCESS;
460
461
462         case LDAP_OPT_HOST_NAME: {
463                         const char *host = (const char *) invalue;
464                         LDAPURLDesc *ludlist = NULL;
465                         int rc = LDAP_OPT_SUCCESS;
466
467                         if(host != NULL) {
468                                 rc = ldap_url_parsehosts(&ludlist, host);
469
470                         } else if(ld == NULL) {
471                                 /*
472                                  * must want global default returned
473                                  * to initial condition.
474                                  */
475                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
476
477                         } else {
478                                 /*
479                                  * must want the session default
480                                  *   updated to the current global default
481                                  */
482                                 ludlist = ldap_url_duplist(
483                                         ldap_int_global_options.ldo_defludp);
484                                 if (ludlist == NULL)
485                                         rc = LDAP_NO_MEMORY;
486                         }
487
488                         if (rc == LDAP_OPT_SUCCESS) {
489                                 if (lo->ldo_defludp != NULL)
490                                         ldap_free_urllist(lo->ldo_defludp);
491                                 lo->ldo_defludp = ludlist;
492                         }
493                         return rc;
494                 }
495
496         case LDAP_OPT_URI: {
497                         const char *urls = (const char *) invalue;
498                         LDAPURLDesc *ludlist = NULL;
499                         int rc = LDAP_OPT_SUCCESS;
500
501                         if(urls != NULL) {
502                                 rc = ldap_url_parselist(&ludlist, urls);
503
504                         } else if(ld == NULL) {
505                                 /*
506                                  * must want global default returned
507                                  * to initial condition.
508                                  */
509                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
510
511                         } else {
512                                 /*
513                                  * must want the session default
514                                  *   updated to the current global default
515                                  */
516                                 ludlist = ldap_url_duplist(
517                                         ldap_int_global_options.ldo_defludp);
518                                 if (ludlist == NULL)
519                                         rc = LDAP_NO_MEMORY;
520                         }
521
522                         if (rc == LDAP_OPT_SUCCESS) {
523                                 if (lo->ldo_defludp != NULL)
524                                         ldap_free_urllist(lo->ldo_defludp);
525                                 lo->ldo_defludp = ludlist;
526                         }
527                         return rc;
528                 }
529
530         case LDAP_OPT_ERROR_NUMBER: {
531                         int err = * (const int *) invalue;
532
533                         if(ld == NULL) {
534                                 /* need a struct ldap */
535                                 break;
536                         }
537
538                         ld->ld_errno = err;
539                 } return LDAP_OPT_SUCCESS;
540
541         case LDAP_OPT_ERROR_STRING: {
542                         const char *err = (const char *) invalue;
543
544                         if(ld == NULL) {
545                                 /* need a struct ldap */
546                                 break;
547                         }
548
549                         if( ld->ld_error ) {
550                                 LDAP_FREE(ld->ld_error);
551                         }
552
553                         ld->ld_error = LDAP_STRDUP(err);
554                 } return LDAP_OPT_SUCCESS;
555
556         case LDAP_OPT_MATCHED_DN: {
557                         const char *err = (const char *) invalue;
558
559                         if(ld == NULL) {
560                                 /* need a struct ldap */
561                                 break;
562                         }
563
564                         if( ld->ld_matched ) {
565                                 LDAP_FREE(ld->ld_matched);
566                         }
567
568                         ld->ld_matched = LDAP_STRDUP(err);
569                 } return LDAP_OPT_SUCCESS;
570
571         case LDAP_OPT_API_FEATURE_INFO:
572                 /* read-only */
573                 break;
574
575         case LDAP_OPT_DEBUG_LEVEL:
576                 lo->ldo_debug = * (const int *) invalue;
577                 return LDAP_OPT_SUCCESS;
578
579         default:
580 #ifdef HAVE_TLS
581                 if ( ldap_pvt_tls_set_option( lo, option, (void *)invalue ) == 0 )
582                 return LDAP_OPT_SUCCESS;
583 #endif
584 #ifdef HAVE_CYRUS_SASL
585                 if ( ldap_pvt_sasl_set_option( ld, option, (void *)invalue ) == 0 )
586                         return LDAP_OPT_SUCCESS;
587 #endif
588                 /* bad param */
589                 break;
590         }
591         return LDAP_OPT_ERROR;
592 }
593
594 int
595 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
596 {
597         return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));
598 }