]> git.sur5r.net Git - openldap/blob - servers/slapd/config.c
500a64c4680980b81d3c2ffd77de79239ea3cd2c
[openldap] / servers / slapd / config.c
1 /* config.c - configuration file handling routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms are permitted
20  * provided that this notice is preserved and that due credit is given
21  * to the University of Michigan at Ann Arbor. The name of the University
22  * may not be used to endorse or promote products derived from this
23  * software without specific prior written permission. This software
24  * is provided ``as is'' without express or implied warranty.
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/string.h>
32 #include <ac/ctype.h>
33 #include <ac/signal.h>
34 #include <ac/socket.h>
35 #include <ac/errno.h>
36
37 #include "slap.h"
38 #ifdef LDAP_SLAPI
39 #include "slapi/slapi.h"
40 #endif
41 #include "lutil.h"
42 #include "config.h"
43
44 #define ARGS_STEP       512
45
46 /*
47  * defaults for various global variables
48  */
49 slap_mask_t             global_allows = 0;
50 slap_mask_t             global_disallows = 0;
51 int             global_gentlehup = 0;
52 int             global_idletimeout = 0;
53 char    *global_host = NULL;
54 char    *global_realm = NULL;
55 char            *ldap_srvtab = "";
56 char            **default_passwd_hash = NULL;
57 struct berval default_search_base = BER_BVNULL;
58 struct berval default_search_nbase = BER_BVNULL;
59
60 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
61 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
62
63 int     slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
64 int     slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
65
66 char   *slapd_pid_file  = NULL;
67 char   *slapd_args_file = NULL;
68
69 int use_reverse_lookup = 0;
70
71 #ifdef LDAP_SLAPI
72 int slapi_plugins_used = 0;
73 #endif
74
75 static int fp_getline(FILE *fp, ConfigArgs *c);
76 static void fp_getline_init(ConfigArgs *c);
77 static int fp_parse_line(ConfigArgs *c);
78
79 static char     *strtok_quote(char *line, char *sep, char **quote_ptr);
80
81 int read_config_file(const char *fname, int depth, ConfigArgs *cf);
82
83 ConfigArgs *
84 new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **argv )
85 {
86         ConfigArgs *c;
87         c = ch_calloc( 1, sizeof( ConfigArgs ) );
88         if ( c == NULL ) return(NULL);
89         c->be     = be; 
90         c->fname  = fname;
91         c->argc   = argc;
92         c->argv   = argv; 
93         c->lineno = lineno;
94         snprintf( c->log, sizeof( c->log ), "%s: line %lu", fname, lineno );
95         return(c);
96 }
97
98 void
99 init_config_argv( ConfigArgs *c )
100 {
101         c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
102         c->argv_size = ARGS_STEP + 1;
103 }
104
105 ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
106         int i;
107
108         for(i = 0; Conf[i].name; i++)
109                 if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
110                         (!strcasecmp(c->argv[0], Conf[i].name)) ) break;
111         if ( !Conf[i].name ) return NULL;
112         return Conf+i;
113 }
114
115 int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
116         int rc, arg_user, arg_type, iarg;
117         long larg;
118         ber_len_t barg;
119         
120         arg_type = Conf->arg_type;
121         if(arg_type == ARG_IGNORED) {
122                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
123                         c->log, Conf->name, 0);
124                 return(0);
125         }
126         if((arg_type & ARG_DN) && c->argc == 1) {
127                 c->argc = 2;
128                 c->argv[1] = "";
129         }
130         if(Conf->min_args && (c->argc < Conf->min_args)) {
131                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> missing <%s> argument\n",
132                         c->log, Conf->name, Conf->what);
133                 return(ARG_BAD_CONF);
134         }
135         if(Conf->max_args && (c->argc > Conf->max_args)) {
136                 Debug(LDAP_DEBUG_CONFIG, "%s: extra cruft after <%s> in <%s> line (ignored)\n",
137                         c->log, Conf->what, Conf->name);
138         }
139         if((arg_type & ARG_DB) && !c->be) {
140                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> allowed only within database declaration\n",
141                         c->log, Conf->name, 0);
142                 return(ARG_BAD_CONF);
143         }
144         if((arg_type & ARG_PRE_BI) && c->bi) {
145                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> must appear before any backend %sdeclaration\n",
146                         c->log, Conf->name, ((arg_type & ARG_PRE_DB)
147                         ? "or database " : "") );
148                 return(ARG_BAD_CONF);
149         }
150         if((arg_type & ARG_PRE_DB) && c->be && c->be != frontendDB) {
151                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> must appear before any database declaration\n",
152                         c->log, Conf->name, 0);
153                 return(ARG_BAD_CONF);
154         }
155         if((arg_type & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
156                 Debug(LDAP_DEBUG_CONFIG, "%s: old <%s> format not supported\n",
157                         c->log, Conf->name, 0);
158                 return(ARG_BAD_CONF);
159         }
160         if((arg_type & ARGS_POINTER) && !Conf->arg_item && !(arg_type & ARG_OFFSET)) {
161                 Debug(LDAP_DEBUG_CONFIG, "%s: null arg_item for <%s>\n",
162                         c->log, Conf->name, 0);
163                 return(ARG_BAD_CONF);
164         }
165         c->type = arg_user = (arg_type & ARGS_USERLAND);
166         memset(&c->values, 0, sizeof(c->values));
167         if(arg_type & ARGS_NUMERIC) {
168                 int j;
169                 iarg = 0; larg = 0; barg = 0;
170                 switch(arg_type & ARGS_NUMERIC) {
171                         case ARG_INT:           iarg = atoi(c->argv[1]);                break;
172                         case ARG_LONG:          larg = strtol(c->argv[1], NULL, 0);     break;
173                         case ARG_BER_LEN_T:     barg = (ber_len_t)atol(c->argv[1]);     break;
174                         case ARG_ON_OFF:
175                                 if(c->argc == 1) {
176                                         iarg = 1;
177                                 } else if(!strcasecmp(c->argv[1], "on") ||
178                                         !strcasecmp(c->argv[1], "true")) {
179                                         iarg = 1;
180                                 } else if(!strcasecmp(c->argv[1], "off") ||
181                                         !strcasecmp(c->argv[1], "false")) {
182                                         iarg = 0;
183                                 } else {
184                                         Debug(LDAP_DEBUG_CONFIG, "%s: ignoring ", c->log, 0, 0);
185                                         Debug(LDAP_DEBUG_CONFIG, "invalid %s value (%s) in <%s> line\n",
186                                                 Conf->what, c->argv[1], Conf->name);
187                                         return(0);
188                                 }
189                                 break;
190                 }
191                 j = (arg_type & ARG_NONZERO) ? 1 : 0;
192                 if(iarg < j && larg < j && barg < j ) {
193                         larg = larg ? larg : (barg ? barg : iarg);
194                         Debug(LDAP_DEBUG_CONFIG, "%s: " , c->log, 0, 0);
195                         Debug(LDAP_DEBUG_CONFIG, "invalid %s value (%ld) in <%s> line\n", Conf->what, larg, Conf->name);
196                         return(ARG_BAD_CONF);
197                 }
198                 switch(arg_type & ARGS_NUMERIC) {
199                         case ARG_ON_OFF:
200                         case ARG_INT:           c->value_int = iarg;            break;
201                         case ARG_LONG:          c->value_long = larg;           break;
202                         case ARG_BER_LEN_T:     c->value_ber_t = barg;          break;
203                 }
204         } else if(arg_type & ARG_STRING) {
205                 if ( !check_only )
206                         c->value_string = ch_strdup(c->argv[1]);
207         } else if(arg_type & ARG_BERVAL) {
208                 if ( !check_only )
209                         ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
210         } else if(arg_type & ARG_DN) {
211                 struct berval bv;
212                 ber_str2bv( c->argv[1], 0, 0, &bv );
213                 rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
214                 if ( rc != LDAP_SUCCESS ) {
215                         Debug(LDAP_DEBUG_CONFIG, "%s: " , c->log, 0, 0);
216                         Debug(LDAP_DEBUG_CONFIG, "%s DN is invalid %d (%s)\n",
217                                 Conf->name, rc, ldap_err2string( rc ));
218                         return(ARG_BAD_CONF);
219                 }
220                 if ( check_only ) {
221                         ch_free( c->value_ndn.bv_val );
222                         ch_free( c->value_dn.bv_val );
223                 }
224         }
225         return 0;
226 }
227
228 int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
229         int rc, arg_type;
230         void *ptr;
231
232         arg_type = Conf->arg_type;
233         if(arg_type & ARG_MAGIC) {
234                 if(!c->be) c->be = frontendDB;
235                 rc = (*((ConfigDriver*)Conf->arg_item))(c);
236 #if 0
237                 if(c->be == frontendDB) c->be = NULL;
238 #endif
239                 if(rc) {
240                         Debug(LDAP_DEBUG_CONFIG, "%s: handler for <%s> exited with %d!\n",
241                                 c->log, Conf->name, rc);
242                         return(ARG_BAD_CONF);
243                 }
244                 return(0);
245         }
246         if(arg_type & ARG_OFFSET) {
247                 if (c->be)
248                         ptr = c->be->be_private;
249                 else if (c->bi)
250                         ptr = c->bi->bi_private;
251                 else {
252                         Debug(LDAP_DEBUG_CONFIG, "%s: offset for <%s> missing base pointer!\n",
253                                 c->log, Conf->name, 0);
254                         return(ARG_BAD_CONF);
255                 }
256                 ptr = (void *)((char *)ptr + (int)Conf->arg_item);
257         } else if (arg_type & ARGS_POINTER) {
258                 ptr = Conf->arg_item;
259         }
260         if(arg_type & ARGS_POINTER)
261                 switch(arg_type & ARGS_POINTER) {
262                         case ARG_ON_OFF:
263                         case ARG_INT:           *(int*)ptr = c->value_int;                      break;
264                         case ARG_LONG:          *(long*)ptr = c->value_long;                    break;
265                         case ARG_BER_LEN_T:     *(ber_len_t*)ptr = c->value_ber_t;                      break;
266                         case ARG_STRING: {
267                                 char *cc = *(char**)ptr;
268                                 if(cc) {
269                                         if (arg_type & ARG_UNIQUE) {
270                                                 Debug(LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
271                                                         c->log, Conf->name, 0 );
272                                                 return(ARG_BAD_CONF);
273                                         }
274                                         ch_free(cc);
275                                 }
276                                 *(char **)ptr = c->value_string;
277                                 break;
278                                 }
279                         case ARG_BERVAL:
280                                 *(struct berval *)ptr = c->value_bv;
281                                 break;
282                 }
283         return(0);
284 }
285
286 int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
287         int rc, arg_type;
288
289         arg_type = Conf->arg_type;
290         if(arg_type == ARG_IGNORED) {
291                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
292                         c->log, Conf->name, 0);
293                 return(0);
294         }
295         rc = config_check_vals( Conf, c, 0 );
296         if ( rc ) return rc;
297         return config_set_vals( Conf, c );
298 }
299
300 int
301 config_del_vals(ConfigTable *cf, ConfigArgs *c)
302 {
303         int rc = 0;
304
305         return rc;
306 }
307
308 int
309 config_get_vals(ConfigTable *cf, ConfigArgs *c)
310 {
311         int rc = 0;
312         struct berval bv;
313         void *ptr;
314
315         if ( cf->arg_type & ARG_IGNORED ) {
316                 return 1;
317         }
318
319         memset(&c->values, 0, sizeof(c->values));
320         c->rvalue_vals = NULL;
321         c->rvalue_nvals = NULL;
322         c->op = SLAP_CONFIG_EMIT;
323         c->type = cf->arg_type & ARGS_USERLAND;
324
325         if ( cf->arg_type & ARG_MAGIC ) {
326                 rc = (*((ConfigDriver*)cf->arg_item))(c);
327                 if ( rc ) return rc;
328         } else {
329                 if ( cf->arg_type & ARG_OFFSET ) {
330                         if ( c->be )
331                                 ptr = c->be->be_private;
332                         else if ( c->bi )
333                                 ptr = c->bi->bi_private;
334                         else
335                                 return 1;
336                         ptr = (void *)((char *)ptr + (int)cf->arg_item);
337                 } else {
338                         ptr = cf->arg_item;
339                 }
340                 
341                 switch(cf->arg_type & ARGS_POINTER) {
342                 case ARG_ON_OFF:
343                 case ARG_INT:   c->value_int = *(int *)ptr; break;
344                 case ARG_LONG:  c->value_long = *(long *)ptr; break;
345                 case ARG_BER_LEN_T:     c->value_ber_t = *(ber_len_t *)ptr; break;
346                 case ARG_STRING:
347                         if ( *(char **)ptr )
348                                 c->value_string = ch_strdup(*(char **)ptr);
349                         break;
350                 case ARG_BERVAL:
351                         ber_dupbv( &c->value_bv, (struct berval *)ptr ); break;
352                 }
353         }
354         if ( cf->arg_type & ARGS_POINTER) {
355                 bv.bv_val = c->log;
356                 switch(cf->arg_type & ARGS_POINTER) {
357                 case ARG_INT: bv.bv_len = sprintf(bv.bv_val, "%d", c->value_int); break;
358                 case ARG_LONG: bv.bv_len = sprintf(bv.bv_val, "%ld", c->value_long); break;
359                 case ARG_BER_LEN_T: bv.bv_len = sprintf(bv.bv_val, "%ld", c->value_ber_t); break;
360                 case ARG_ON_OFF: bv.bv_len = sprintf(bv.bv_val, "%s",
361                         c->value_int ? "TRUE" : "FALSE"); break;
362                 case ARG_STRING:
363                         if ( c->value_string && c->value_string[0]) {
364                                 ber_str2bv( c->value_string, 0, 0, &bv);
365                         } else {
366                                 return 1;
367                         }
368                         break;
369                 case ARG_BERVAL:
370                         if ( !BER_BVISEMPTY( &c->value_bv )) {
371                                 bv = c->value_bv;
372                         } else {
373                                 return 1;
374                         }
375                         break;
376                 }
377                 if (( cf->arg_type & ARGS_POINTER ) == ARG_STRING )
378                         ber_bvarray_add(&c->rvalue_vals, &bv);
379                 else
380                         value_add_one(&c->rvalue_vals, &bv);
381         }
382         return rc;
383 }
384
385 int
386 init_config_attrs(ConfigTable *ct) {
387         LDAPAttributeType *at;
388         int i, code;
389         const char *err;
390
391         for (i=0; ct[i].name; i++ ) {
392                 if ( !ct[i].attribute ) continue;
393                 at = ldap_str2attributetype( ct[i].attribute,
394                         &code, &err, LDAP_SCHEMA_ALLOW_ALL );
395                 if ( !at ) {
396                         fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s, %s\n",
397                                 ct[i].attribute, ldap_scherr2str(code), err );
398                         return code;
399                 }
400                 code = at_add( at, 0, NULL, &err );
401                 if ( code && code != SLAP_SCHERR_ATTR_DUP ) {
402                         fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s, %s\n",
403                                 ct[i].attribute, scherr2str(code), err );
404                         return code;
405                 }
406                 code = slap_str2ad( at->at_names[0], &ct[i].ad, &err );
407                 if ( code ) {
408                         fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s\n",
409                                 ct[i].attribute, err );
410                         return code;
411                 }
412                 ldap_memfree( at );
413         }
414
415         return 0;
416 }
417
418 int
419 init_config_ocs( ConfigOCs *ocs ) {
420         int i;
421
422         for (i=0;ocs[i].def;i++) {
423                 LDAPObjectClass *oc;
424                 int code;
425                 const char *err;
426
427                 oc = ldap_str2objectclass( ocs[i].def, &code, &err,
428                         LDAP_SCHEMA_ALLOW_ALL );
429                 if ( !oc ) {
430                         fprintf( stderr, "init_config_ocs: objectclass \"%s\": %s, %s\n",
431                                 ocs[i].def, ldap_scherr2str(code), err );
432                         return code;
433                 }
434                 code = oc_add(oc,0,NULL,&err);
435                 if ( code && code != SLAP_SCHERR_CLASS_DUP ) {
436                         fprintf( stderr, "init_config_ocs: objectclass \"%s\": %s, %s\n",
437                                 ocs[i].def, scherr2str(code), err );
438                         return code;
439                 }
440                 if ( ocs[i].oc ) {
441                         *ocs[i].oc = oc_find(oc->oc_names[0]);
442                 }
443                 ldap_memfree(oc);
444         }
445         return 0;
446 }
447
448 int
449 config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
450 {
451         int rc = 0;
452
453         snprintf( c->log, sizeof( c->log ), "%s: value #%d",
454                 ct->ad->ad_cname.bv_val, valx );
455         c->argc = 1;
456         c->argv[0] = ct->ad->ad_cname.bv_val;
457         if ( fp_parse_line( c ) ) {
458                 rc = 1;
459         } else {
460                 rc = config_check_vals( ct, c, 1 );
461         }
462
463         ch_free( c->tline );
464         return rc;
465 }
466
467 int
468 config_parse_add(ConfigTable *ct, ConfigArgs *c, int valx)
469 {
470         int rc = 0;
471
472         snprintf( c->log, sizeof( c->log ), "%s: value #%d",
473                 ct->ad->ad_cname.bv_val, valx );
474         c->argc = 1;
475         c->argv[0] = ct->ad->ad_cname.bv_val;
476         if ( fp_parse_line( c ) ) {
477                 rc = 1;
478         } else {
479                 c->op = LDAP_MOD_ADD;
480                 rc = config_add_vals( ct, c );
481         }
482
483         ch_free( c->tline );
484         return rc;
485 }
486
487 int
488 read_config_file(const char *fname, int depth, ConfigArgs *cf)
489 {
490         FILE *fp;
491         ConfigTable *ct;
492         ConfigArgs *c;
493         int rc;
494
495         c = ch_calloc( 1, sizeof( ConfigArgs ) );
496         if ( c == NULL ) {
497                 return 1;
498         }
499
500         if ( depth ) {
501                 memcpy( c, cf, sizeof( ConfigArgs ) );
502         } else {
503                 c->depth = depth; /* XXX */
504                 c->bi = NULL;
505                 c->be = NULL;
506         }
507
508         c->fname = fname;
509         init_config_argv( c );
510
511         fp = fopen( fname, "r" );
512         if ( fp == NULL ) {
513                 ldap_syslog = 1;
514                 Debug(LDAP_DEBUG_ANY,
515                     "could not open config file \"%s\": %s (%d)\n",
516                     fname, strerror(errno), errno);
517                 return(1);
518         }
519
520         Debug(LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0);
521
522         fp_getline_init(c);
523
524         c->tline = NULL;
525
526         while ( fp_getline( fp, c ) ) {
527                 /* skip comments and blank lines */
528                 if ( c->line[0] == '#' || c->line[0] == '\0' ) {
529                         continue;
530                 }
531
532                 snprintf( c->log, sizeof( c->log ), "%s: line %lu",
533                                 c->fname, c->lineno );
534
535                 c->argc = 0;
536                 ch_free( c->tline );
537                 if ( fp_parse_line( c ) ) {
538                         rc = 1;
539                         goto leave;
540                 }
541
542                 if ( c->argc < 1 ) {
543                         Debug(LDAP_DEBUG_CONFIG, "%s: bad config line (ignored)\n", c->log, 0, 0);
544                         continue;
545                 }
546
547                 c->op = SLAP_CONFIG_ADD;
548
549                 ct = config_find_keyword( config_back_cf_table, c );
550                 if ( ct ) {
551                         rc = config_add_vals( ct, c );
552                         if ( !rc ) continue;
553
554                         if ( rc & ARGS_USERLAND ) {
555                                 /* XXX a usertype would be opaque here */
556                                 Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
557                                         c->log, c->argv[0], 0);
558                                 rc = 1;
559                                 goto leave;
560
561                         } else if ( rc == ARG_BAD_CONF ) {
562                                 rc = 1;
563                                 goto leave;
564                         }
565                         
566                 } else if ( c->bi ) {
567                         rc = SLAP_CONF_UNKNOWN;
568                         if ( c->bi->bi_cf_table ) {
569                                 ct = config_find_keyword( c->bi->bi_cf_table, c );
570                                 if ( ct ) {
571                                         rc = config_add_vals( ct, c );
572                                 }
573                         }
574                         if ( c->bi->bi_config && rc == SLAP_CONF_UNKNOWN ) {
575                                 rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno,
576                                         c->argc, c->argv);
577                         }
578                         if ( rc ) {
579                                 switch(rc) {
580                                 case SLAP_CONF_UNKNOWN:
581                                         Debug(LDAP_DEBUG_CONFIG, "%s: "
582                                                 "unknown directive <%s> inside backend info definition (ignored)\n",
583                                                 c->log, *c->argv, 0);
584                                         continue;
585                                 default:
586                                         rc = 1;
587                                         goto leave;
588                                 }
589                         }
590
591                 } else if ( c->be ) {
592                         rc = SLAP_CONF_UNKNOWN;
593                         if ( c->be->be_cf_table ) {
594                                 ct = config_find_keyword( c->be->be_cf_table, c );
595                                 if ( ct ) {
596                                         rc = config_add_vals( ct, c );
597                                 }
598                         }
599                         if ( c->be->be_config && rc == SLAP_CONF_UNKNOWN ) {
600                                 rc = (*c->be->be_config)(c->be, c->fname, c->lineno,
601                                         c->argc, c->argv);
602                         }
603                         if ( rc ) {
604                                 switch(rc) {
605                                 case SLAP_CONF_UNKNOWN:
606                                         Debug( LDAP_DEBUG_CONFIG, "%s: "
607                                                 "unknown directive <%s> inside backend database "
608                                                 "definition (ignored)\n",
609                                                 c->log, *c->argv, 0);
610                                         continue;
611                                 default:
612                                         rc = 1;
613                                         goto leave;
614                                 }
615                         }
616
617                 } else if ( frontendDB->be_config ) {
618                         rc = (*frontendDB->be_config)(frontendDB, c->fname, (int)c->lineno, c->argc, c->argv);
619                         if ( rc ) {
620                                 switch(rc) {
621                                 case SLAP_CONF_UNKNOWN:
622                                         Debug( LDAP_DEBUG_CONFIG, "%s: "
623                                                 "unknown directive <%s> inside global database definition (ignored)\n",
624                                                 c->log, *c->argv, 0);
625                                         continue;
626                                 default:
627                                         rc = 1;
628                                         goto leave;
629                                 }
630                         }
631                         
632                 } else {
633                         Debug(LDAP_DEBUG_CONFIG, "%s: "
634                                 "unknown directive <%s> outside backend info and database definitions (ignored)\n",
635                                 c->log, *c->argv, 0);
636                         continue;
637
638                 }
639         }
640
641         if ( BER_BVISNULL( &frontendDB->be_schemadn ) ) {
642                 ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1,
643                         &frontendDB->be_schemadn );
644                 rc = dnNormalize( 0, NULL, NULL, &frontendDB->be_schemadn, &frontendDB->be_schemandn, NULL );
645                 if ( rc != LDAP_SUCCESS ) {
646                         Debug(LDAP_DEBUG_ANY, "%s: "
647                                 "unable to normalize default schema DN \"%s\"\n",
648                                 c->log, frontendDB->be_schemadn.bv_val, 0 );
649                         /* must not happen */
650                         assert( 0 );
651                 }
652         }
653         rc = 0;
654
655 leave:
656         ch_free(c->tline);
657         fclose(fp);
658         ch_free(c->argv);
659         ch_free(c);
660         return(rc);
661 }
662
663 /* restrictops, allows, disallows, requires, loglevel */
664
665 int
666 verb_to_mask(const char *word, slap_verbmasks *v) {
667         int i;
668         for(i = 0; !BER_BVISNULL(&v[i].word); i++)
669                 if(!strcasecmp(word, v[i].word.bv_val))
670                         break;
671         return(i);
672 }
673
674 int
675 verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) {
676         int i, j;
677         for(i = 1; i < argc; i++) {
678                 j = verb_to_mask(argv[i], v);
679                 if(BER_BVISNULL(&v[j].word)) return(1);
680                 while (!v[j].mask) j--;
681                 *m |= v[j].mask;
682         }
683         return(0);
684 }
685
686 int
687 mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) {
688         int i;
689
690         if (!m) return 1;
691         for (i=0; !BER_BVISNULL(&v[i].word); i++) {
692                 if (!v[i].mask) continue;
693                 if (( m & v[i].mask ) == v[i].mask ) {
694                         value_add_one( bva, &v[i].word );
695                 }
696         }
697         return 0;
698 }
699
700 static slap_verbmasks tlskey[] = {
701         { BER_BVC("no"),                SB_TLS_OFF },
702         { BER_BVC("yes"),               SB_TLS_ON },
703         { BER_BVC("critical"),  SB_TLS_CRITICAL },
704         { BER_BVNULL, 0 }
705 };
706
707 static slap_verbmasks methkey[] = {
708         { BER_BVC("simple"),    LDAP_AUTH_SIMPLE },
709 #ifdef HAVE_CYRUS_SASL
710         { BER_BVC("sasl"),      LDAP_AUTH_SASL },
711 #endif
712         { BER_BVNULL, 0 }
713 };
714
715 typedef struct cf_aux_table {
716         struct berval key;
717         int off;
718         char type;
719         char quote;
720         slap_verbmasks *aux;
721 } cf_aux_table;
722
723 static cf_aux_table bindkey[] = {
724         { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'd', 0, tlskey },
725         { BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'd', 0, methkey },
726         { BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, NULL },
727         { BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
728         { BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 's', 0, NULL },
729         { BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
730         { BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 's', 0, NULL },
731         { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 's', 0, NULL },
732         { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, NULL },
733         { BER_BVNULL, 0, 0, 0, NULL }
734 };
735
736 int bindconf_parse( const char *word, slap_bindconf *bc ) {
737         int rc = 0;
738         cf_aux_table *tab;
739
740         for (tab = bindkey; !BER_BVISNULL(&tab->key); tab++) {
741                 if ( !strncasecmp( word, tab->key.bv_val, tab->key.bv_len )) {
742                         char **cptr;
743                         int *iptr, j;
744                         struct berval *bptr;
745                         const char *val = word + tab->key.bv_len;
746
747                         switch ( tab->type ) {
748                         case 's':
749                                 cptr = (char **)((char *)bc + tab->off);
750                                 *cptr = ch_strdup( val );
751                                 break;
752
753                         case 'b':
754                                 bptr = (struct berval *)((char *)bc + tab->off);
755                                 ber_str2bv( val, 0, 1, bptr );
756                                 break;
757
758                         case 'i':
759                                 assert( tab->aux );
760                                 iptr = (int *)((char *)bc + tab->off);
761
762                                 rc = 1;
763                                 for ( j = 0; !BER_BVISNULL( &tab->aux[j].word ); j++ ) {
764                                         if ( !strcasecmp( val, tab->aux[j].word.bv_val ) ) {
765                                                 *iptr = tab->aux[j].mask;
766                                                 rc = 0;
767                                         }
768                                 }
769                                 break;
770                         }
771
772                         if ( rc ) {
773                                 Debug( LDAP_DEBUG_ANY, "invalid bind config value %s\n",
774                                         word, 0, 0 );
775                         }
776                         
777                         return rc;
778                 }
779         }
780
781         return rc;
782 }
783
784 int bindconf_unparse( slap_bindconf *bc, struct berval *bv ) {
785         char buf[BUFSIZ], *ptr;
786         cf_aux_table *tab;
787         struct berval tmp;
788
789         ptr = buf;
790         for (tab = bindkey; !BER_BVISNULL(&tab->key); tab++) {
791                 char **cptr;
792                 int *iptr, i;
793                 struct berval *bptr;
794
795                 cptr = (char **)((char *)bc + tab->off);
796
797                 switch ( tab->type ) {
798                 case 'b':
799                         bptr = (struct berval *)((char *)bc + tab->off);
800                         cptr = &bptr->bv_val;
801                 case 's':
802                         if ( *cptr ) {
803                                 *ptr++ = ' ';
804                                 ptr = lutil_strcopy( ptr, tab->key.bv_val );
805                                 if ( tab->quote ) *ptr++ = '"';
806                                 ptr = lutil_strcopy( ptr, *cptr );
807                                 if ( tab->quote ) *ptr++ = '"';
808                         }
809                         break;
810
811                 case 'i':
812                         assert( tab->aux );
813                 
814                         for ( i = 0; !BER_BVISNULL( &tab->aux[i].word ); i++ ) {
815                                 if ( *iptr == tab->aux[i].mask ) {
816                                         *ptr++ = ' ';
817                                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
818                                         ptr = lutil_strcopy( ptr, tab->aux[i].word.bv_val );
819                                         break;
820                                 }
821                         }
822                         break;
823                 }
824         }
825         tmp.bv_val = buf;
826         tmp.bv_len = ptr - buf;
827         ber_dupbv( bv, &tmp );
828         return 0;
829 }
830
831 void bindconf_free( slap_bindconf *bc ) {
832         if ( !BER_BVISNULL( &bc->sb_binddn ) ) {
833                 ch_free( bc->sb_binddn.bv_val );
834         }
835         if ( !BER_BVISNULL( &bc->sb_cred ) ) {
836                 ch_free( bc->sb_cred.bv_val );
837         }
838         if ( bc->sb_saslmech ) {
839                 ch_free( bc->sb_saslmech );
840         }
841         if ( bc->sb_secprops ) {
842                 ch_free( bc->sb_secprops );
843         }
844         if ( bc->sb_realm ) {
845                 ch_free( bc->sb_realm );
846         }
847         if ( bc->sb_authcId ) {
848                 ch_free( bc->sb_authcId );
849         }
850         if ( !BER_BVISNULL( &bc->sb_authzId ) ) {
851                 ch_free( bc->sb_authzId.bv_val );
852         }
853 }
854
855
856 /* -------------------------------------- */
857
858
859 static char *
860 strtok_quote( char *line, char *sep, char **quote_ptr )
861 {
862         int             inquote;
863         char            *tmp;
864         static char     *next;
865
866         *quote_ptr = NULL;
867         if ( line != NULL ) {
868                 next = line;
869         }
870         while ( *next && strchr( sep, *next ) ) {
871                 next++;
872         }
873
874         if ( *next == '\0' ) {
875                 next = NULL;
876                 return( NULL );
877         }
878         tmp = next;
879
880         for ( inquote = 0; *next; ) {
881                 switch ( *next ) {
882                 case '"':
883                         if ( inquote ) {
884                                 inquote = 0;
885                         } else {
886                                 inquote = 1;
887                         }
888                         AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
889                         break;
890
891                 case '\\':
892                         if ( next[1] )
893                                 AC_MEMCPY( next,
894                                             next + 1, strlen( next + 1 ) + 1 );
895                         next++;         /* dont parse the escaped character */
896                         break;
897
898                 default:
899                         if ( ! inquote ) {
900                                 if ( strchr( sep, *next ) != NULL ) {
901                                         *quote_ptr = next;
902                                         *next++ = '\0';
903                                         return( tmp );
904                                 }
905                         }
906                         next++;
907                         break;
908                 }
909         }
910
911         return( tmp );
912 }
913
914 static char     buf[BUFSIZ];
915 static char     *line;
916 static size_t lmax, lcur;
917
918 #define CATLINE( buf ) \
919         do { \
920                 size_t len = strlen( buf ); \
921                 while ( lcur + len + 1 > lmax ) { \
922                         lmax += BUFSIZ; \
923                         line = (char *) ch_realloc( line, lmax ); \
924                 } \
925                 strcpy( line + lcur, buf ); \
926                 lcur += len; \
927         } while( 0 )
928
929 static void
930 fp_getline_init(ConfigArgs *c) {
931         c->lineno = -1;
932         buf[0] = '\0';
933 }
934
935 static int
936 fp_getline( FILE *fp, ConfigArgs *c )
937 {
938         char    *p;
939
940         lcur = 0;
941         CATLINE(buf);
942         c->lineno++;
943
944         /* avoid stack of bufs */
945         if ( strncasecmp( line, "include", STRLENOF( "include" ) ) == 0 ) {
946                 buf[0] = '\0';
947                 c->line = line;
948                 return(1);
949         }
950
951         while ( fgets( buf, sizeof( buf ), fp ) ) {
952                 p = strchr( buf, '\n' );
953                 if ( p ) {
954                         if ( p > buf && p[-1] == '\r' ) {
955                                 --p;
956                         }
957                         *p = '\0';
958                 }
959                 /* XXX ugly */
960                 c->line = line;
961                 if ( line[0]
962                                 && ( p = line + strlen( line ) - 1 )[0] == '\\'
963                                 && p[-1] != '\\' )
964                 {
965                         p[0] = '\0';
966                         lcur--;
967                         
968                 } else {
969                         if ( !isspace( (unsigned char)buf[0] ) ) {
970                                 return(1);
971                         }
972                         buf[0] = ' ';
973                 }
974                 CATLINE(buf);
975                 c->lineno++;
976         }
977
978         buf[0] = '\0';
979         c->line = line;
980         return(line[0] ? 1 : 0);
981 }
982
983 static int
984 fp_parse_line(ConfigArgs *c)
985 {
986         char *token;
987         char *hide[] = { "rootpw", "replica", "bindpw", "pseudorootpw", "dbpasswd", '\0' };
988         char *quote_ptr;
989         int i;
990
991         c->tline = ch_strdup(c->line);
992         token = strtok_quote(c->tline, " \t", &quote_ptr);
993
994         if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
995         if(quote_ptr) *quote_ptr = ' ';
996         Debug(LDAP_DEBUG_CONFIG, "line %lu (%s%s)\n", c->lineno,
997                 hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "");
998         if(quote_ptr) *quote_ptr = '\0';
999
1000         for(; token; token = strtok_quote(NULL, " \t", &quote_ptr)) {
1001                 if(c->argc == c->argv_size - 1) {
1002                         char **tmp;
1003                         tmp = ch_realloc(c->argv, (c->argv_size + ARGS_STEP) * sizeof(*c->argv));
1004                         if(!tmp) {
1005                                 Debug(LDAP_DEBUG_ANY, "line %lu: out of memory\n", c->lineno, 0, 0);
1006                                 return -1;
1007                         }
1008                         c->argv = tmp;
1009                         c->argv_size += ARGS_STEP;
1010                 }
1011                 c->argv[c->argc++] = token;
1012         }
1013         c->argv[c->argc] = NULL;
1014         return(0);
1015 }
1016
1017 void
1018 config_destroy( )
1019 {
1020         ucdata_unload( UCDATA_ALL );
1021         if ( frontendDB ) {
1022                 /* NOTE: in case of early exit, frontendDB can be NULL */
1023                 if ( frontendDB->be_schemandn.bv_val )
1024                         free( frontendDB->be_schemandn.bv_val );
1025                 if ( frontendDB->be_schemadn.bv_val )
1026                         free( frontendDB->be_schemadn.bv_val );
1027                 if ( frontendDB->be_acl )
1028                         acl_destroy( frontendDB->be_acl, NULL );
1029         }
1030         free( line );
1031         if ( slapd_args_file )
1032                 free ( slapd_args_file );
1033         if ( slapd_pid_file )
1034                 free ( slapd_pid_file );
1035         if ( default_passwd_hash )
1036                 ldap_charray_free( default_passwd_hash );
1037 }
1038
1039 char **
1040 slap_str2clist( char ***out, char *in, const char *brkstr )
1041 {
1042         char    *str;
1043         char    *s;
1044         char    *lasts;
1045         int     i, j;
1046         char    **new;
1047
1048         /* find last element in list */
1049         for (i = 0; *out && (*out)[i]; i++);
1050
1051         /* protect the input string from strtok */
1052         str = ch_strdup( in );
1053
1054         if ( *str == '\0' ) {
1055                 free( str );
1056                 return( *out );
1057         }
1058
1059         /* Count words in string */
1060         j=1;
1061         for ( s = str; *s; s++ ) {
1062                 if ( strchr( brkstr, *s ) != NULL ) {
1063                         j++;
1064                 }
1065         }
1066
1067         *out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
1068         new = *out + i;
1069         for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
1070                 s != NULL;
1071                 s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
1072         {
1073                 *new = ch_strdup( s );
1074                 new++;
1075         }
1076
1077         *new = NULL;
1078         free( str );
1079         return( *out );
1080 }
1081
1082 int config_generic_wrapper( Backend *be, const char *fname, int lineno,
1083         int argc, char **argv )
1084 {
1085         ConfigArgs c = { 0 };
1086         ConfigTable *ct;
1087         int rc;
1088
1089         c.be = be;
1090         c.fname = fname;
1091         c.lineno = lineno;
1092         c.argc = argc;
1093         c.argv = argv;
1094         sprintf( c.log, "%s: line %lu", fname, lineno );
1095
1096         rc = SLAP_CONF_UNKNOWN;
1097         ct = config_find_keyword( be->be_cf_table, &c );
1098         if ( ct )
1099                 rc = config_add_vals( ct, &c );
1100         return rc;
1101 }