]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
Import latest leak fix from HEAD.
[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( ld, option, outvalue ) == 0 ) {
285                         return LDAP_OPT_SUCCESS;
286                 }
287 #endif
288 #ifdef HAVE_CYRUS_SASL
289                 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
290                         return LDAP_OPT_SUCCESS;
291                 }
292 #endif
293                 /* bad param */
294                 break;
295         }
296
297         return LDAP_OPT_ERROR;
298 }
299
300 int
301 ldap_set_option(
302         LDAP    *ld,
303         int             option,
304         LDAP_CONST void *invalue)
305 {
306         struct ldapoptions *lo;
307         int *dbglvl = NULL;
308
309         /* Get pointer to global option structure */
310         lo = LDAP_INT_GLOBAL_OPT();
311         if (lo == NULL) {
312                 return LDAP_NO_MEMORY;
313         }
314
315         /*
316          * The architecture to turn on debugging has a chicken and egg
317          * problem. Thus, we introduce a fix here.
318          */
319
320         if (option == LDAP_OPT_DEBUG_LEVEL)
321             dbglvl = (int *) invalue;
322
323         if( lo->ldo_valid != LDAP_INITIALIZED ) {
324                 ldap_int_initialize(lo, dbglvl);
325         }
326
327         if(ld != NULL) {
328                 assert( LDAP_VALID( ld ) );
329
330                 if( !LDAP_VALID( ld ) ) {
331                         return LDAP_OPT_ERROR;
332                 }
333
334                 lo = &ld->ld_options;
335         }
336
337         switch(option) {
338         case LDAP_OPT_REFERRALS:
339                 if(invalue == LDAP_OPT_OFF) {
340                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
341                 } else {
342                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
343                 }
344                 return LDAP_OPT_SUCCESS;
345
346         case LDAP_OPT_RESTART:
347                 if(invalue == LDAP_OPT_OFF) {
348                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
349                 } else {
350                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
351                 }
352                 return LDAP_OPT_SUCCESS;
353         }
354
355         /* options which can withstand invalue == NULL */
356         switch ( option ) {
357         case LDAP_OPT_SERVER_CONTROLS: {
358                         LDAPControl *const *controls =
359                                 (LDAPControl *const *) invalue;
360
361                         ldap_controls_free( lo->ldo_sctrls );
362
363                         if( controls == NULL || *controls == NULL ) {
364                                 lo->ldo_sctrls = NULL;
365                                 return LDAP_OPT_SUCCESS;
366                         }
367                                 
368                         lo->ldo_sctrls = ldap_controls_dup( controls );
369
370                         if(lo->ldo_sctrls == NULL) {
371                                 /* memory allocation error ? */
372                                 break;
373                         }
374                 } return LDAP_OPT_SUCCESS;
375
376         case LDAP_OPT_CLIENT_CONTROLS: {
377                         LDAPControl *const *controls =
378                                 (LDAPControl *const *) invalue;
379
380                         ldap_controls_free( lo->ldo_cctrls );
381
382                         if( controls == NULL || *controls == NULL ) {
383                                 lo->ldo_cctrls = NULL;
384                                 return LDAP_OPT_SUCCESS;
385                         }
386                                 
387                         lo->ldo_cctrls = ldap_controls_dup( controls );
388
389                         if(lo->ldo_cctrls == NULL) {
390                                 /* memory allocation error ? */
391                                 break;
392                         }
393                 } return LDAP_OPT_SUCCESS;
394
395         case LDAP_OPT_TIMEOUT: {
396                         const struct timeval *tv = 
397                                 (const struct timeval *) invalue;
398
399                         if ( lo->ldo_tm_api != NULL ) {
400                                 LDAP_FREE( lo->ldo_tm_api );
401                                 lo->ldo_tm_api = NULL;
402                         }
403
404                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
405                                 return LDAP_OPT_ERROR;
406                         }
407                 } return LDAP_OPT_SUCCESS;
408
409         case LDAP_OPT_NETWORK_TIMEOUT: {
410                         const struct timeval *tv = 
411                                 (const struct timeval *) invalue;
412
413                         if ( lo->ldo_tm_net != NULL ) {
414                                 LDAP_FREE( lo->ldo_tm_net );
415                                 lo->ldo_tm_net = NULL;
416                         }
417
418                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
419                                 return LDAP_OPT_ERROR;
420                         }
421                 } return LDAP_OPT_SUCCESS;
422
423         /* Only accessed from inside this function by ldap_set_rebind_proc() */
424         case LDAP_OPT_REBIND_PROC: {
425                         lo->ldo_rebindproc = (LDAP_REBIND_PROC *)invalue;               
426                 } return LDAP_OPT_SUCCESS;
427         }
428
429         if(invalue == NULL) {
430                 /* no place to set from */
431                 return LDAP_OPT_ERROR;
432         }
433
434         /* options which cannot withstand invalue == NULL */
435
436         switch(option) {
437         case LDAP_OPT_API_INFO:
438         case LDAP_OPT_DESC:
439                 /* READ ONLY */
440                 break;
441
442         case LDAP_OPT_DEREF:
443                 lo->ldo_deref = * (const int *) invalue;
444                 return LDAP_OPT_SUCCESS;
445
446         case LDAP_OPT_SIZELIMIT:
447                 lo->ldo_sizelimit = * (const int *) invalue;
448                 return LDAP_OPT_SUCCESS;
449
450         case LDAP_OPT_TIMELIMIT:
451                 lo->ldo_timelimit = * (const int *) invalue;
452                 return LDAP_OPT_SUCCESS;
453
454         case LDAP_OPT_PROTOCOL_VERSION: {
455                         int vers = * (const int *) invalue;
456                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
457                                 /* not supported */
458                                 break;
459                         }
460                         lo->ldo_version = vers;
461                 } return LDAP_OPT_SUCCESS;
462
463
464         case LDAP_OPT_HOST_NAME: {
465                         const char *host = (const char *) invalue;
466                         LDAPURLDesc *ludlist = NULL;
467                         int rc = LDAP_OPT_SUCCESS;
468
469                         if(host != NULL) {
470                                 rc = ldap_url_parsehosts( &ludlist, host,
471                                         lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
472
473                         } else if(ld == NULL) {
474                                 /*
475                                  * must want global default returned
476                                  * to initial condition.
477                                  */
478                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
479
480                         } else {
481                                 /*
482                                  * must want the session default
483                                  *   updated to the current global default
484                                  */
485                                 ludlist = ldap_url_duplist(
486                                         ldap_int_global_options.ldo_defludp);
487                                 if (ludlist == NULL)
488                                         rc = LDAP_NO_MEMORY;
489                         }
490
491                         if (rc == LDAP_OPT_SUCCESS) {
492                                 if (lo->ldo_defludp != NULL)
493                                         ldap_free_urllist(lo->ldo_defludp);
494                                 lo->ldo_defludp = ludlist;
495                         }
496                         return rc;
497                 }
498
499         case LDAP_OPT_URI: {
500                         const char *urls = (const char *) invalue;
501                         LDAPURLDesc *ludlist = NULL;
502                         int rc = LDAP_OPT_SUCCESS;
503
504                         if(urls != NULL) {
505                                 rc = ldap_url_parselist(&ludlist, urls);
506
507                         } else if(ld == NULL) {
508                                 /*
509                                  * must want global default returned
510                                  * to initial condition.
511                                  */
512                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
513
514                         } else {
515                                 /*
516                                  * must want the session default
517                                  *   updated to the current global default
518                                  */
519                                 ludlist = ldap_url_duplist(
520                                         ldap_int_global_options.ldo_defludp);
521                                 if (ludlist == NULL)
522                                         rc = LDAP_NO_MEMORY;
523                         }
524
525                         if (rc == LDAP_OPT_SUCCESS) {
526                                 if (lo->ldo_defludp != NULL)
527                                         ldap_free_urllist(lo->ldo_defludp);
528                                 lo->ldo_defludp = ludlist;
529                         }
530                         return rc;
531                 }
532
533         case LDAP_OPT_ERROR_NUMBER: {
534                         int err = * (const int *) invalue;
535
536                         if(ld == NULL) {
537                                 /* need a struct ldap */
538                                 break;
539                         }
540
541                         ld->ld_errno = err;
542                 } return LDAP_OPT_SUCCESS;
543
544         case LDAP_OPT_ERROR_STRING: {
545                         const char *err = (const char *) invalue;
546
547                         if(ld == NULL) {
548                                 /* need a struct ldap */
549                                 break;
550                         }
551
552                         if( ld->ld_error ) {
553                                 LDAP_FREE(ld->ld_error);
554                         }
555
556                         ld->ld_error = LDAP_STRDUP(err);
557                 } return LDAP_OPT_SUCCESS;
558
559         case LDAP_OPT_MATCHED_DN: {
560                         const char *err = (const char *) invalue;
561
562                         if(ld == NULL) {
563                                 /* need a struct ldap */
564                                 break;
565                         }
566
567                         if( ld->ld_matched ) {
568                                 LDAP_FREE(ld->ld_matched);
569                         }
570
571                         ld->ld_matched = LDAP_STRDUP(err);
572                 } return LDAP_OPT_SUCCESS;
573
574         case LDAP_OPT_API_FEATURE_INFO:
575                 /* read-only */
576                 break;
577
578         case LDAP_OPT_DEBUG_LEVEL:
579                 lo->ldo_debug = * (const int *) invalue;
580                 return LDAP_OPT_SUCCESS;
581
582         default:
583 #ifdef HAVE_TLS
584                 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
585                 return LDAP_OPT_SUCCESS;
586 #endif
587 #ifdef HAVE_CYRUS_SASL
588                 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
589                         return LDAP_OPT_SUCCESS;
590 #endif
591                 /* bad param */
592                 break;
593         }
594         return LDAP_OPT_ERROR;
595 }
596
597 int
598 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *rebind_proc)
599 {
600         return( ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)rebind_proc));
601 }