]> git.sur5r.net Git - openldap/blob - libraries/libldap/init.c
Extern URI code to support literal IPv6 addresses
[openldap] / libraries / libldap / init.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 #include "portable.h"
7
8 #include <stdio.h>
9 #include <ac/stdlib.h>
10
11 #include <ac/socket.h>
12 #include <ac/string.h>
13 #include <ac/ctype.h>
14 #include <ac/time.h>
15
16 #include <limits.h>
17
18 #include "ldap-int.h"
19 #include "ldap_defaults.h"
20
21 struct ldapoptions ldap_int_global_options =
22         { LDAP_UNINITIALIZED, LDAP_DEBUG_NONE };  
23
24 #define ATTR_NONE       0
25 #define ATTR_BOOL       1
26 #define ATTR_INT        2
27 #define ATTR_KV         3
28 #define ATTR_STRING     4
29 #define ATTR_TLS        5
30 #define ATTR_URIS       6
31
32 struct ol_keyvalue {
33         const char *            key;
34         int                     value;
35 };
36
37 static const struct ol_keyvalue deref_kv[] = {
38         {"never", LDAP_DEREF_NEVER},
39         {"searching", LDAP_DEREF_SEARCHING},
40         {"finding", LDAP_DEREF_FINDING},
41         {"always", LDAP_DEREF_ALWAYS},
42         {NULL, 0}
43 };
44
45 static const struct ol_attribute {
46         int                     useronly;
47         int                     type;
48         const char *    name;
49         const void *    data;
50         size_t          offset;
51 } attrs[] = {
52         {0, ATTR_KV,            "DEREF",        deref_kv, /* or &deref_kv[0] */
53                 offsetof(struct ldapoptions, ldo_deref)},
54         {0, ATTR_INT,           "SIZELIMIT",    NULL,
55                 offsetof(struct ldapoptions, ldo_sizelimit)},
56         {0, ATTR_INT,           "TIMELIMIT",    NULL,
57                 offsetof(struct ldapoptions, ldo_timelimit)},
58         {1, ATTR_STRING,        "BINDDN",               NULL,
59                 offsetof(struct ldapoptions, ldo_defbinddn)},
60         {0, ATTR_STRING,        "BASE",                 NULL,
61                 offsetof(struct ldapoptions, ldo_defbase)},
62         {0, ATTR_INT,           "PORT",                 NULL,
63                 offsetof(struct ldapoptions, ldo_defport)},
64         /* **** keep this around for backward compatibility */
65         {0, ATTR_URIS,          "HOST",                 NULL,   1},
66         /* **** */
67         {0, ATTR_URIS,          "URI",                  NULL,   0},
68         {0, ATTR_BOOL,          "REFERRALS",    NULL,   LDAP_BOOL_REFERRALS},
69         {0, ATTR_BOOL,          "RESTART",              NULL,   LDAP_BOOL_RESTART},
70         {0, ATTR_TLS,           "TLS",                  NULL,   LDAP_OPT_X_TLS},
71         {0, ATTR_TLS,           "TLS_CERT",             NULL,   LDAP_OPT_X_TLS_CERTFILE},
72         {0, ATTR_TLS,           "TLS_KEY",              NULL,   LDAP_OPT_X_TLS_KEYFILE},
73         {0, ATTR_TLS,           "TLS_CACERT",   NULL,   LDAP_OPT_X_TLS_CACERTFILE},
74         {0, ATTR_TLS,           "TLS_CACERTDIR",NULL,   LDAP_OPT_X_TLS_CACERTDIR},
75         {0, ATTR_TLS,           "TLS_REQCERT",  NULL,   LDAP_OPT_X_TLS_REQUIRE_CERT},
76 #ifdef HAVE_CYRUS_SASL
77         {0, ATTR_INT,           "SASL_MINSSF",  NULL,
78                 offsetof(struct ldapoptions, ldo_sasl_minssf)},
79         {0, ATTR_INT,           "SASL_MAXSSF",  NULL,
80                 offsetof(struct ldapoptions, ldo_sasl_maxssf)},
81 #endif
82         {0, ATTR_NONE,          NULL,           NULL,   0}
83 };
84
85 #define MAX_LDAP_ATTR_LEN  sizeof("TLS_CACERTDIR")
86 #define MAX_LDAP_ENV_PREFIX_LEN 8
87
88 static void openldap_ldap_init_w_conf(
89         const char *file, int userconf )
90 {
91         char linebuf[128];
92         FILE *fp;
93         int i;
94         char *cmd, *opt;
95         char *start, *end;
96         struct ldapoptions *gopts;
97
98         if ((gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
99                 return;                 /* Could not allocate mem for global options */
100         }
101
102         if (file == NULL) {
103                 /* no file name */
104                 return;
105         }
106
107         Debug(LDAP_DEBUG_TRACE, "ldap_init: trying %s\n", file, 0, 0);
108
109         fp = fopen(file, "r");
110         if(fp == NULL) {
111                 /* could not open file */
112                 return;
113         }
114
115         Debug(LDAP_DEBUG_TRACE, "ldap_init: using %s\n", file, 0, 0);
116
117         while((start = fgets(linebuf, sizeof(linebuf), fp)) != NULL) {
118                 /* skip lines starting with '#' */
119                 if(*start == '#') continue;
120
121                 /* trim leading white space */
122                 while((*start != '\0') && isspace((unsigned char) *start))
123                         start++;
124
125                 /* anything left? */
126                 if(*start == '\0') continue;
127
128                 /* trim trailing white space */
129                 end = &start[strlen(start)-1];
130                 while(isspace((unsigned char)*end)) end--;
131                 end[1] = '\0';
132
133                 /* anything left? */
134                 if(*start == '\0') continue;
135                 
136
137                 /* parse the command */
138                 cmd=start;
139                 while((*start != '\0') && !isspace((unsigned char)*start)) {
140                         start++;
141                 }
142                 if(*start == '\0') {
143                         /* command has no argument */
144                         continue;
145                 } 
146
147                 *start++ = '\0';
148
149                 /* we must have some whitespace to skip */
150                 while(isspace((unsigned char)*start)) start++;
151                 opt = start;
152
153                 for(i=0; attrs[i].type != ATTR_NONE; i++) {
154                         void *p;
155
156                         if( !userconf && attrs[i].useronly ) {
157                                 continue;
158                         }
159
160                         if(strcasecmp(cmd, attrs[i].name) != 0) {
161                                 continue;
162                         }
163
164                         switch(attrs[i].type) {
165                         case ATTR_BOOL:
166                                 if((strcasecmp(opt, "on") == 0) 
167                                         || (strcasecmp(opt, "yes") == 0)
168                                         || (strcasecmp(opt, "true") == 0))
169                                 {
170                                         LDAP_BOOL_SET(gopts, attrs[i].offset);
171
172                                 } else {
173                                         LDAP_BOOL_CLR(gopts, attrs[i].offset);
174                                 }
175
176                                 break;
177
178                         case ATTR_INT:
179                                 p = &((char *) gopts)[attrs[i].offset];
180                                 * (int*) p = atoi(opt);
181                                 break;
182
183                         case ATTR_KV: {
184                                         const struct ol_keyvalue *kv;
185
186                                         for(kv = attrs[i].data;
187                                                 kv->key != NULL;
188                                                 kv++) {
189
190                                                 if(strcasecmp(opt, kv->key) == 0) {
191                                                         p = &((char *) gopts)[attrs[i].offset];
192                                                         * (int*) p = kv->value;
193                                                         break;
194                                                 }
195                                         }
196                                 } break;
197
198                         case ATTR_STRING:
199                                 p = &((char *) gopts)[attrs[i].offset];
200                                 if (* (char**) p != NULL) LDAP_FREE(* (char**) p);
201                                 * (char**) p = LDAP_STRDUP(opt);
202                                 break;
203                         case ATTR_TLS:
204 #ifdef HAVE_TLS
205                                 ldap_pvt_tls_config( gopts, attrs[i].offset, opt );
206 #endif
207                                 break;
208                         case ATTR_URIS:
209                                 if (attrs[i].offset == 0) {
210                                         ldap_set_option( NULL, LDAP_OPT_URI, opt );
211                                 } else {
212                                         ldap_set_option( NULL, LDAP_OPT_HOST_NAME, opt );
213                                 }
214                                 break;
215                         }
216                         break;
217                 }
218         }
219
220         fclose(fp);
221 }
222
223 static void openldap_ldap_init_w_sysconf(const char *file)
224 {
225         openldap_ldap_init_w_conf( file, 0 );
226 }
227
228 static void openldap_ldap_init_w_userconf(const char *file)
229 {
230         char *home;
231         char *path = NULL;
232
233         if (file == NULL) {
234                 /* no file name */
235                 return;
236         }
237
238         home = getenv("HOME");
239
240         if (home != NULL) {
241                 Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is %s\n",
242                       home, 0, 0);
243                 path = LDAP_MALLOC(strlen(home) + strlen(file) + 3);
244         } else {
245                 Debug(LDAP_DEBUG_TRACE, "ldap_init: HOME env is NULL\n",
246                       0, 0, 0);
247         }
248
249         if(home != NULL && path != NULL) {
250                 /* we assume UNIX path syntax is used... */
251
252                 /* try ~/file */
253                 sprintf(path, "%s/%s", home, file);
254                 openldap_ldap_init_w_conf(path, 1);
255
256                 /* try ~/.file */
257                 sprintf(path, "%s/.%s", home, file);
258                 openldap_ldap_init_w_conf(path, 1);
259         }
260
261         if(path != NULL) {
262                 LDAP_FREE(path);
263         }
264
265         /* try file */
266         openldap_ldap_init_w_conf(file, 1);
267 }
268
269 static void openldap_ldap_init_w_env(
270                 struct ldapoptions *gopts,
271                 const char *prefix)
272 {
273         char buf[MAX_LDAP_ATTR_LEN+MAX_LDAP_ENV_PREFIX_LEN];
274         int len;
275         int i;
276         void *p;
277         char *value;
278
279         if (prefix == NULL) {
280                 prefix = LDAP_ENV_PREFIX;
281         }
282
283         strncpy(buf, prefix, MAX_LDAP_ENV_PREFIX_LEN);
284         buf[MAX_LDAP_ENV_PREFIX_LEN] = '\0';
285         len = strlen(buf);
286
287         for(i=0; attrs[i].type != ATTR_NONE; i++) {
288                 strcpy(&buf[len], attrs[i].name);
289                 value = getenv(buf);
290
291                 if(value == NULL) {
292                         continue;
293                 }
294
295                 switch(attrs[i].type) {
296                 case ATTR_BOOL:
297                         if((strcasecmp(value, "on") == 0) 
298                                 || (strcasecmp(value, "yes") == 0)
299                                 || (strcasecmp(value, "true") == 0))
300                         {
301                                 LDAP_BOOL_SET(gopts, attrs[i].offset);
302
303                         } else {
304                                 LDAP_BOOL_CLR(gopts, attrs[i].offset);
305                         }
306                         break;
307
308                 case ATTR_INT:
309                         p = &((char *) gopts)[attrs[i].offset];
310                         * (int*) p = atoi(value);
311                         break;
312
313                 case ATTR_KV: {
314                                 const struct ol_keyvalue *kv;
315
316                                 for(kv = attrs[i].data;
317                                         kv->key != NULL;
318                                         kv++) {
319
320                                         if(strcasecmp(value, kv->key) == 0) {
321                                                 p = &((char *) gopts)[attrs[i].offset];
322                                                 * (int*) p = kv->value;
323                                                 break;
324                                         }
325                                 }
326                         } break;
327
328                 case ATTR_STRING:
329                         p = &((char *) gopts)[attrs[i].offset];
330                         if (* (char**) p != NULL) LDAP_FREE(* (char**) p);
331                         if (*value == '\0') {
332                                 * (char**) p = NULL;
333                         } else {
334                                 * (char**) p = LDAP_STRDUP(value);
335                         }
336                         break;
337                 case ATTR_TLS:
338 #ifdef HAVE_TLS
339                         ldap_pvt_tls_config( gopts, attrs[i].offset, value );
340 #endif                          
341                         break;
342                 case ATTR_URIS:
343                         if (attrs[i].offset == 0) {
344                                 ldap_set_option( NULL, LDAP_OPT_URI, value );
345                         } else {
346                                 ldap_set_option( NULL, LDAP_OPT_HOST_NAME, value );
347                         }
348                         break;
349                 }
350         }
351 }
352
353 /* 
354  * Initialize the global options structure with default values.
355  */
356 void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl )
357 {
358         if (dbglvl)
359             gopts->ldo_debug = *dbglvl;
360         else
361                 gopts->ldo_debug = 0;
362
363         gopts->ldo_version   = LDAP_VERSION2;
364         gopts->ldo_deref     = LDAP_DEREF_NEVER;
365         gopts->ldo_timelimit = LDAP_NO_LIMIT;
366         gopts->ldo_sizelimit = LDAP_NO_LIMIT;
367
368         gopts->ldo_tm_api = (struct timeval *)NULL;
369         gopts->ldo_tm_net = (struct timeval *)NULL;
370
371         /* ldo_defludp is leaked, we should have an at_exit() handler
372          * to free this and whatever else needs to cleaned up. 
373          */
374         ldap_url_parselist(&gopts->ldo_defludp, "ldap://localhost/");
375         gopts->ldo_defport = LDAP_PORT;
376
377         gopts->ldo_refhoplimit = LDAP_DEFAULT_REFHOPLIMIT;
378         gopts->ldo_rebindproc = NULL;
379
380         LDAP_BOOL_ZERO(gopts);
381
382         LDAP_BOOL_SET(gopts, LDAP_BOOL_REFERRALS);
383
384 #ifdef HAVE_TLS
385         gopts->ldo_tls_ctx = NULL;
386 #endif
387 #ifdef HAVE_CYRUS_SASL
388         gopts->ldo_sasl_minssf = 0;
389         gopts->ldo_sasl_maxssf = INT_MAX;
390 #endif
391
392         gopts->ldo_valid = LDAP_INITIALIZED;
393
394         return;
395 }
396
397 void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl )
398 {
399         if ( gopts->ldo_valid == LDAP_INITIALIZED ) {
400                 return;
401         }
402
403         ldap_int_utils_init();
404
405 #ifdef HAVE_TLS
406         ldap_pvt_tls_init();
407 #endif
408
409 #ifdef HAVE_CYRUS_SASL
410         ldap_pvt_sasl_init();
411 #endif
412
413         if ( ldap_int_tblsize == 0 )
414                 ldap_int_ip_init();
415
416         ldap_int_initialize_global_options(gopts, NULL);
417
418         if( getenv("LDAPNOINIT") != NULL ) {
419                 return;
420         }
421
422         openldap_ldap_init_w_sysconf(LDAP_CONF_FILE);
423         openldap_ldap_init_w_userconf(LDAP_USERRC_FILE);
424
425         {
426                 char *altfile = getenv(LDAP_ENV_PREFIX "CONF");
427
428                 if( altfile != NULL ) {
429                         Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n",
430                               LDAP_ENV_PREFIX "CONF", altfile, 0);
431                         openldap_ldap_init_w_sysconf( altfile );
432                 }
433                 else
434                         Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n",
435                               LDAP_ENV_PREFIX "CONF", 0, 0);
436         }
437
438         {
439                 char *altfile = getenv(LDAP_ENV_PREFIX "RC");
440
441                 if( altfile != NULL ) {
442                         Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is %s\n",
443                               LDAP_ENV_PREFIX "RC", altfile, 0);
444                         openldap_ldap_init_w_userconf( altfile );
445                 }
446                 else
447                         Debug(LDAP_DEBUG_TRACE, "ldap_init: %s env is NULL\n",
448                               LDAP_ENV_PREFIX "RC", 0, 0);
449         }
450
451         openldap_ldap_init_w_env(gopts, NULL);
452 }