]> git.sur5r.net Git - openldap/blob - servers/slapd/config.c
Hide starttls keyword if no TLS
[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-2006 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 <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40
41 #include "slap.h"
42 #ifdef LDAP_SLAPI
43 #include "slapi/slapi.h"
44 #endif
45 #include "lutil.h"
46 #include "config.h"
47
48 #ifdef HAVE_TLS
49 #include <openssl/ssl.h>
50 #endif
51
52 #define ARGS_STEP       512
53
54 /*
55  * defaults for various global variables
56  */
57 slap_mask_t             global_allows = 0;
58 slap_mask_t             global_disallows = 0;
59 int             global_gentlehup = 0;
60 int             global_idletimeout = 0;
61 char    *global_host = NULL;
62 char    *global_realm = NULL;
63 char            *ldap_srvtab = "";
64 char            **default_passwd_hash = NULL;
65 struct berval default_search_base = BER_BVNULL;
66 struct berval default_search_nbase = BER_BVNULL;
67
68 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
69 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
70
71 int     slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
72 int     slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
73
74 char   *slapd_pid_file  = NULL;
75 char   *slapd_args_file = NULL;
76
77 int use_reverse_lookup = 0;
78
79 #ifdef LDAP_SLAPI
80 int slapi_plugins_used = 0;
81 #endif
82
83 static int fp_getline(FILE *fp, ConfigArgs *c);
84 static void fp_getline_init(ConfigArgs *c);
85 static int fp_parse_line(ConfigArgs *c);
86
87 static char     *strtok_quote(char *line, char *sep, char **quote_ptr);
88 static char *strtok_quote_ldif(char **line);
89
90 ConfigArgs *
91 new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **argv )
92 {
93         ConfigArgs *c;
94         c = ch_calloc( 1, sizeof( ConfigArgs ) );
95         if ( c == NULL ) return(NULL);
96         c->be     = be; 
97         c->fname  = fname;
98         c->argc   = argc;
99         c->argv   = argv; 
100         c->lineno = lineno;
101         snprintf( c->log, sizeof( c->log ), "%s: line %d", fname, lineno );
102         return(c);
103 }
104
105 void
106 init_config_argv( ConfigArgs *c )
107 {
108         c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
109         c->argv_size = ARGS_STEP + 1;
110 }
111
112 ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
113         int i;
114
115         for(i = 0; Conf[i].name; i++)
116                 if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
117                         (!strcasecmp(c->argv[0], Conf[i].name)) ) break;
118         if ( !Conf[i].name ) return NULL;
119         return Conf+i;
120 }
121
122 int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
123         int rc, arg_user, arg_type, iarg;
124         long larg;
125         ber_len_t barg;
126         
127         arg_type = Conf->arg_type;
128         if(arg_type == ARG_IGNORED) {
129                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
130                         c->log, Conf->name, 0);
131                 return(0);
132         }
133         if((arg_type & ARG_DN) && c->argc == 1) {
134                 c->argc = 2;
135                 c->argv[1] = "";
136         }
137         if(Conf->min_args && (c->argc < Conf->min_args)) {
138                 snprintf( c->msg, sizeof( c->msg ), "<%s> missing <%s> argument",
139                         c->argv[0], Conf->what );
140                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n", c->log, c->msg, 0 );
141                 return(ARG_BAD_CONF);
142         }
143         if(Conf->max_args && (c->argc > Conf->max_args)) {
144                 char    *ignored = " ignored";
145
146                 snprintf( c->msg, sizeof( c->msg ), "<%s> extra cruft after <%s>",
147                         c->argv[0], Conf->what );
148
149 #ifdef LDAP_DEVEL
150                 ignored = "";
151 #endif /* LDAP_DEVEL */
152                 Debug(LDAP_DEBUG_CONFIG, "%s: %s%s.\n",
153                                 c->log, c->msg, ignored );
154 #ifdef LDAP_DEVEL
155                 return(ARG_BAD_CONF);
156 #endif /* LDAP_DEVEL */
157         }
158         if((arg_type & ARG_DB) && !c->be) {
159                 snprintf( c->msg, sizeof( c->msg ), "<%s> only allowed within database declaration",
160                         c->argv[0] );
161                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
162                         c->log, c->msg, 0);
163                 return(ARG_BAD_CONF);
164         }
165         if((arg_type & ARG_PRE_BI) && c->bi) {
166                 snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any backend %sdeclaration",
167                         c->argv[0], (arg_type & ARG_PRE_DB) ? "or database " : "" );
168                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
169                         c->log, c->msg, 0 );
170                 return(ARG_BAD_CONF);
171         }
172         if((arg_type & ARG_PRE_DB) && c->be && c->be != frontendDB) {
173                 snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any database declaration",
174                         c->argv[0] );
175                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
176                         c->log, c->msg, 0);
177                 return(ARG_BAD_CONF);
178         }
179         if((arg_type & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
180                 snprintf( c->msg, sizeof( c->msg ), "<%s> old format not supported", c->argv[0] );
181                 Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
182                         c->log, c->msg, 0);
183                 return(ARG_BAD_CONF);
184         }
185         if((arg_type & ARGS_POINTER) && !Conf->arg_item && !(arg_type & ARG_OFFSET)) {
186                 snprintf( c->msg, sizeof( c->msg ), "<%s> invalid config_table, arg_item is NULL",
187                         c->argv[0] );
188                 Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
189                         c->log, c->msg, 0);
190                 return(ARG_BAD_CONF);
191         }
192         c->type = arg_user = (arg_type & ARGS_USERLAND);
193         memset(&c->values, 0, sizeof(c->values));
194         if(arg_type & ARGS_NUMERIC) {
195                 int j;
196                 iarg = 0; larg = 0; barg = 0;
197                 switch(arg_type & ARGS_NUMERIC) {
198                         case ARG_INT:
199                                 if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
200                                         snprintf( c->msg, sizeof( c->msg ),
201                                                 "<%s> unable to parse \"%s\" as int",
202                                                 c->argv[0], c->argv[1] );
203                                         Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
204                                                 c->log, c->msg, 0);
205                                         return(ARG_BAD_CONF);
206                                 }
207                                 break;
208                         case ARG_LONG:
209                                 if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
210                                         snprintf( c->msg, sizeof( c->msg ),
211                                                 "<%s> unable to parse \"%s\" as long",
212                                                 c->argv[0], c->argv[1] );
213                                         Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
214                                                 c->log, c->msg, 0);
215                                         return(ARG_BAD_CONF);
216                                 }
217                                 break;
218                         case ARG_BER_LEN_T: {
219                                 unsigned long   l;
220                                 if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
221                                         snprintf( c->msg, sizeof( c->msg ),
222                                                 "<%s> unable to parse \"%s\" as ber_len_t",
223                                                 c->argv[0], c->argv[1] );
224                                         Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
225                                                 c->log, c->msg, 0);
226                                         return(ARG_BAD_CONF);
227                                 }
228                                 barg = (ber_len_t)l;
229                                 } break;
230                         case ARG_ON_OFF:
231                                 if (c->argc == 1) {
232                                         iarg = 1;
233                                 } else if ( !strcasecmp(c->argv[1], "on") ||
234                                         !strcasecmp(c->argv[1], "true") ||
235                                         !strcasecmp(c->argv[1], "yes") )
236                                 {
237                                         iarg = 1;
238                                 } else if ( !strcasecmp(c->argv[1], "off") ||
239                                         !strcasecmp(c->argv[1], "false") ||
240                                         !strcasecmp(c->argv[1], "no") )
241                                 {
242                                         iarg = 0;
243                                 } else {
244                                         snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value",
245                                                 c->argv[0] );
246                                         Debug(LDAP_DEBUG_ANY, "%s: %s\n",
247                                                 c->log, c->msg, 0 );
248                                         return(ARG_BAD_CONF);
249                                 }
250                                 break;
251                 }
252                 j = (arg_type & ARG_NONZERO) ? 1 : 0;
253                 if(iarg < j && larg < j && barg < j ) {
254                         larg = larg ? larg : (barg ? barg : iarg);
255                         snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value",
256                                 c->argv[0] );
257                         Debug(LDAP_DEBUG_ANY, "%s: %s\n",
258                                 c->log, c->msg, 0 );
259                         return(ARG_BAD_CONF);
260                 }
261                 switch(arg_type & ARGS_NUMERIC) {
262                         case ARG_ON_OFF:
263                         case ARG_INT:           c->value_int = iarg;            break;
264                         case ARG_LONG:          c->value_long = larg;           break;
265                         case ARG_BER_LEN_T:     c->value_ber_t = barg;          break;
266                 }
267         } else if(arg_type & ARG_STRING) {
268                 if ( !check_only )
269                         c->value_string = ch_strdup(c->argv[1]);
270         } else if(arg_type & ARG_BERVAL) {
271                 if ( !check_only )
272                         ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
273         } else if(arg_type & ARG_DN) {
274                 struct berval bv;
275                 ber_str2bv( c->argv[1], 0, 0, &bv );
276                 rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
277                 if ( rc != LDAP_SUCCESS ) {
278                         snprintf( c->msg, sizeof( c->msg ), "<%s> invalid DN %d (%s)",
279                                 c->argv[0], rc, ldap_err2string( rc ));
280                         Debug(LDAP_DEBUG_CONFIG, "%s: %s\n" , c->log, c->msg, 0);
281                         return(ARG_BAD_CONF);
282                 }
283                 if ( check_only ) {
284                         ch_free( c->value_ndn.bv_val );
285                         ch_free( c->value_dn.bv_val );
286                 }
287         }
288         return 0;
289 }
290
291 int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
292         int rc, arg_type;
293         void *ptr = NULL;
294
295         arg_type = Conf->arg_type;
296         if(arg_type & ARG_MAGIC) {
297                 if(!c->be) c->be = frontendDB;
298                 c->msg[0] = '\0';
299                 rc = (*((ConfigDriver*)Conf->arg_item))(c);
300 #if 0
301                 if(c->be == frontendDB) c->be = NULL;
302 #endif
303                 if(rc) {
304                         if ( !c->msg[0] ) {
305                                 snprintf( c->msg, sizeof( c->msg ), "<%s> handler exited with %d",
306                                         c->argv[0], rc );
307                                 Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
308                                         c->log, c->msg, 0 );
309                         }
310                         return(ARG_BAD_CONF);
311                 }
312                 return(0);
313         }
314         if(arg_type & ARG_OFFSET) {
315                 if (c->be)
316                         ptr = c->be->be_private;
317                 else if (c->bi)
318                         ptr = c->bi->bi_private;
319                 else {
320                         snprintf( c->msg, sizeof( c->msg ), "<%s> offset is missing base pointer",
321                                 c->argv[0] );
322                         Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
323                                 c->log, c->msg, 0);
324                         return(ARG_BAD_CONF);
325                 }
326                 ptr = (void *)((char *)ptr + (long)Conf->arg_item);
327         } else if (arg_type & ARGS_POINTER) {
328                 ptr = Conf->arg_item;
329         }
330         if(arg_type & ARGS_POINTER)
331                 switch(arg_type & ARGS_POINTER) {
332                         case ARG_ON_OFF:
333                         case ARG_INT:           *(int*)ptr = c->value_int;                      break;
334                         case ARG_LONG:          *(long*)ptr = c->value_long;                    break;
335                         case ARG_BER_LEN_T:     *(ber_len_t*)ptr = c->value_ber_t;                      break;
336                         case ARG_STRING: {
337                                 char *cc = *(char**)ptr;
338                                 if(cc) {
339                                         if ((arg_type & ARG_UNIQUE) && c->op == SLAP_CONFIG_ADD ) {
340                                                 Debug(LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
341                                                         c->log, Conf->name, 0 );
342                                                 return(ARG_BAD_CONF);
343                                         }
344                                         ch_free(cc);
345                                 }
346                                 *(char **)ptr = c->value_string;
347                                 break;
348                                 }
349                         case ARG_BERVAL:
350                                 *(struct berval *)ptr = c->value_bv;
351                                 break;
352                 }
353         return(0);
354 }
355
356 int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
357         int rc, arg_type;
358
359         arg_type = Conf->arg_type;
360         if(arg_type == ARG_IGNORED) {
361                 Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
362                         c->log, Conf->name, 0);
363                 return(0);
364         }
365         rc = config_check_vals( Conf, c, 0 );
366         if ( rc ) return rc;
367         return config_set_vals( Conf, c );
368 }
369
370 int
371 config_del_vals(ConfigTable *cf, ConfigArgs *c)
372 {
373         int rc = 0;
374
375         /* If there is no handler, just ignore it */
376         if ( cf->arg_type & ARG_MAGIC ) {
377                 c->op = LDAP_MOD_DELETE;
378                 c->type = cf->arg_type & ARGS_USERLAND;
379                 rc = (*((ConfigDriver*)cf->arg_item))(c);
380         }
381         return rc;
382 }
383
384 int
385 config_get_vals(ConfigTable *cf, ConfigArgs *c)
386 {
387         int rc = 0;
388         struct berval bv;
389         void *ptr;
390
391         if ( cf->arg_type & ARG_IGNORED ) {
392                 return 1;
393         }
394
395         memset(&c->values, 0, sizeof(c->values));
396         c->rvalue_vals = NULL;
397         c->rvalue_nvals = NULL;
398         c->op = SLAP_CONFIG_EMIT;
399         c->type = cf->arg_type & ARGS_USERLAND;
400
401         if ( cf->arg_type & ARG_MAGIC ) {
402                 rc = (*((ConfigDriver*)cf->arg_item))(c);
403                 if ( rc ) return rc;
404         } else {
405                 if ( cf->arg_type & ARG_OFFSET ) {
406                         if ( c->be )
407                                 ptr = c->be->be_private;
408                         else if ( c->bi )
409                                 ptr = c->bi->bi_private;
410                         else
411                                 return 1;
412                         ptr = (void *)((char *)ptr + (long)cf->arg_item);
413                 } else {
414                         ptr = cf->arg_item;
415                 }
416                 
417                 switch(cf->arg_type & ARGS_POINTER) {
418                 case ARG_ON_OFF:
419                 case ARG_INT:   c->value_int = *(int *)ptr; break;
420                 case ARG_LONG:  c->value_long = *(long *)ptr; break;
421                 case ARG_BER_LEN_T:     c->value_ber_t = *(ber_len_t *)ptr; break;
422                 case ARG_STRING:
423                         if ( *(char **)ptr )
424                                 c->value_string = ch_strdup(*(char **)ptr);
425                         break;
426                 case ARG_BERVAL:
427                         ber_dupbv( &c->value_bv, (struct berval *)ptr ); break;
428                 }
429         }
430         if ( cf->arg_type & ARGS_POINTER) {
431                 bv.bv_val = c->log;
432                 switch(cf->arg_type & ARGS_POINTER) {
433                 case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
434                 case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
435                 case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
436                 case ARG_ON_OFF: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%s",
437                         c->value_int ? "TRUE" : "FALSE"); break;
438                 case ARG_STRING:
439                         if ( c->value_string && c->value_string[0]) {
440                                 ber_str2bv( c->value_string, 0, 0, &bv);
441                         } else {
442                                 return 1;
443                         }
444                         break;
445                 case ARG_BERVAL:
446                         if ( !BER_BVISEMPTY( &c->value_bv )) {
447                                 bv = c->value_bv;
448                         } else {
449                                 return 1;
450                         }
451                         break;
452                 }
453                 if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) {
454                         return 1;
455                 }
456                 if (( cf->arg_type & ARGS_POINTER ) == ARG_STRING )
457                         ber_bvarray_add(&c->rvalue_vals, &bv);
458                 else
459                         value_add_one(&c->rvalue_vals, &bv);
460         }
461         return rc;
462 }
463
464 int
465 init_config_attrs(ConfigTable *ct) {
466         LDAPAttributeType *at;
467         int i, code;
468         const char *err;
469
470         for (i=0; ct[i].name; i++ ) {
471                 int             freeit = 0;
472
473                 if ( !ct[i].attribute ) continue;
474                 at = ldap_str2attributetype( ct[i].attribute,
475                         &code, &err, LDAP_SCHEMA_ALLOW_ALL );
476                 if ( !at ) {
477                         fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s, %s\n",
478                                 ct[i].attribute, ldap_scherr2str(code), err );
479                         return code;
480                 }
481
482                 code = at_add( at, 0, NULL, &err );
483                 if ( code ) {
484                         if ( code == SLAP_SCHERR_ATTR_DUP ) {
485                                 freeit = 1;
486
487                         } else {
488                                 ldap_attributetype_free( at );
489                                 fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s, %s\n",
490                                         ct[i].attribute, scherr2str(code), err );
491                                 return code;
492                         }
493                 }
494                 code = slap_str2ad( at->at_names[0], &ct[i].ad, &err );
495                 if ( freeit || code ) {
496                         ldap_attributetype_free( at );
497                 } else {
498                         ldap_memfree( at );
499                 }
500                 if ( code ) {
501                         fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s\n",
502                                 ct[i].attribute, err );
503                         return code;
504                 }
505         }
506
507         return 0;
508 }
509
510 int
511 init_config_ocs( ConfigOCs *ocs ) {
512         int i;
513
514         for (i=0;ocs[i].co_def;i++) {
515                 LDAPObjectClass *oc;
516                 int code;
517                 const char *err;
518
519                 oc = ldap_str2objectclass( ocs[i].co_def, &code, &err,
520                         LDAP_SCHEMA_ALLOW_ALL );
521                 if ( !oc ) {
522                         fprintf( stderr, "init_config_ocs: objectclass \"%s\": %s, %s\n",
523                                 ocs[i].co_def, ldap_scherr2str(code), err );
524                         return code;
525                 }
526                 code = oc_add(oc,0,NULL,&err);
527                 if ( code && code != SLAP_SCHERR_CLASS_DUP ) {
528                         fprintf( stderr, "init_config_ocs: objectclass \"%s\": %s, %s\n",
529                                 ocs[i].co_def, scherr2str(code), err );
530                         ldap_objectclass_free(oc);
531                         return code;
532                 }
533                 ocs[i].co_oc = oc_find(oc->oc_names[0]);
534                 if ( code )
535                         ldap_objectclass_free(oc);
536                 else
537                         ldap_memfree(oc);
538         }
539         return 0;
540 }
541
542 /* Split an LDIF line into space-separated tokens. Words may be grouped
543  * by quotes. A quoted string may begin in the middle of a word, but must
544  * end at the end of the word (be followed by whitespace or EOS). Any other
545  * quotes are passed through unchanged. All other characters are passed
546  * through unchanged.
547  */
548 static char *
549 strtok_quote_ldif( char **line )
550 {
551         char *beg, *ptr, *quote=NULL;
552         int inquote=0;
553
554         ptr = *line;
555
556         if ( !ptr || !*ptr )
557                 return NULL;
558
559         while( isspace( (unsigned char) *ptr )) ptr++;
560
561         if ( *ptr == '"' ) {
562                 inquote = 1;
563                 ptr++;
564         }
565
566         beg = ptr;
567
568         for (;*ptr;ptr++) {
569                 if ( *ptr == '"' ) {
570                         if ( inquote && ( !ptr[1] || isspace((unsigned char) ptr[1]))) {
571                                 *ptr++ = '\0';
572                                 break;
573                         }
574                         inquote = 1;
575                         quote = ptr;
576                         continue;
577                 }
578                 if ( inquote )
579                         continue;
580                 if ( isspace( (unsigned char) *ptr )) {
581                         *ptr++ = '\0';
582                         break;
583                 }
584         }
585         if ( quote ) {
586                 while ( quote < ptr ) {
587                         *quote = quote[1];
588                         quote++;
589                 }
590         }
591         if ( !*ptr ) {
592                 *line = NULL;
593         } else {
594                 while ( isspace( (unsigned char) *ptr )) ptr++;
595                 *line = ptr;
596         }
597         return beg;
598 }
599
600 static void
601 config_parse_ldif( ConfigArgs *c )
602 {
603         char *next;
604         c->tline = ch_strdup(c->line);
605         next = c->tline;
606
607         while ((c->argv[c->argc] = strtok_quote_ldif( &next )) != NULL) {
608                 c->argc++;
609                 if ( c->argc >= c->argv_size ) {
610                         char **tmp = ch_realloc( c->argv, (c->argv_size + ARGS_STEP) *
611                                 sizeof( *c->argv ));
612                         c->argv = tmp;
613                         c->argv_size += ARGS_STEP;
614                 }
615         }
616         c->argv[c->argc] = NULL;
617 }
618
619 int
620 config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
621 {
622         int     rc = 0;
623
624         snprintf( c->log, sizeof( c->log ), "%s: value #%d",
625                 ct->ad->ad_cname.bv_val, valx );
626         c->argc = 1;
627         c->argv[0] = ct->ad->ad_cname.bv_val;
628
629         if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
630                 c->argv[c->argc] = c->line;
631                 c->argc++;
632                 c->argv[c->argc] = NULL;
633                 c->tline = NULL;
634         } else {
635                 config_parse_ldif( c );
636         }
637         rc = config_check_vals( ct, c, 1 );
638         ch_free( c->tline );
639         c->tline = NULL;
640
641         if ( rc )
642                 rc = LDAP_CONSTRAINT_VIOLATION;
643
644         return rc;
645 }
646
647 int
648 config_parse_add(ConfigTable *ct, ConfigArgs *c)
649 {
650         int     rc = 0;
651
652         snprintf( c->log, sizeof( c->log ), "%s: value #%d",
653                 ct->ad->ad_cname.bv_val, c->valx );
654         c->argc = 1;
655         c->argv[0] = ct->ad->ad_cname.bv_val;
656
657         if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
658                 c->argv[c->argc] = c->line;
659                 c->argc++;
660                 c->argv[c->argc] = NULL;
661                 c->tline = NULL;
662         } else {
663                 config_parse_ldif( c );
664         }
665         c->op = LDAP_MOD_ADD;
666         rc = config_add_vals( ct, c );
667         ch_free( c->tline );
668
669         return rc;
670 }
671
672 int
673 read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
674 {
675         FILE *fp;
676         ConfigTable *ct;
677         ConfigArgs *c;
678         int rc;
679         struct stat s;
680
681         c = ch_calloc( 1, sizeof( ConfigArgs ) );
682         if ( c == NULL ) {
683                 return 1;
684         }
685
686         if ( depth ) {
687                 memcpy( c, cf, sizeof( ConfigArgs ) );
688         } else {
689                 c->depth = depth; /* XXX */
690                 c->bi = NULL;
691                 c->be = NULL;
692         }
693
694         c->valx = -1;
695         c->fname = fname;
696         init_config_argv( c );
697
698         if ( stat( fname, &s ) != 0 ) {
699                 ldap_syslog = 1;
700                 Debug(LDAP_DEBUG_ANY,
701                     "could not stat config file \"%s\": %s (%d)\n",
702                     fname, strerror(errno), errno);
703                 ch_free( c );
704                 return(1);
705         }
706
707         if ( !S_ISREG( s.st_mode ) ) {
708                 ldap_syslog = 1;
709                 Debug(LDAP_DEBUG_ANY,
710                     "regular file expected, got \"%s\"\n",
711                     fname, 0, 0 );
712                 ch_free( c );
713                 return(1);
714         }
715
716         fp = fopen( fname, "r" );
717         if ( fp == NULL ) {
718                 ldap_syslog = 1;
719                 Debug(LDAP_DEBUG_ANY,
720                     "could not open config file \"%s\": %s (%d)\n",
721                     fname, strerror(errno), errno);
722                 ch_free( c );
723                 return(1);
724         }
725
726         Debug(LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0);
727
728         fp_getline_init(c);
729
730         c->tline = NULL;
731
732         while ( fp_getline( fp, c ) ) {
733                 /* skip comments and blank lines */
734                 if ( c->line[0] == '#' || c->line[0] == '\0' ) {
735                         continue;
736                 }
737
738                 snprintf( c->log, sizeof( c->log ), "%s: line %d",
739                                 c->fname, c->lineno );
740
741                 c->argc = 0;
742                 ch_free( c->tline );
743                 if ( fp_parse_line( c ) ) {
744                         rc = 1;
745                         goto done;
746                 }
747
748                 if ( c->argc < 1 ) {
749                         Debug( LDAP_DEBUG_ANY, "%s: bad config line.\n",
750                                 c->log, 0, 0);
751                         rc = 1;
752                         goto done;
753                 }
754
755                 c->op = SLAP_CONFIG_ADD;
756
757                 ct = config_find_keyword( cft, c );
758                 if ( ct ) {
759                         rc = config_add_vals( ct, c );
760                         if ( !rc ) continue;
761
762                         if ( rc & ARGS_USERLAND ) {
763                                 /* XXX a usertype would be opaque here */
764                                 Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
765                                         c->log, c->argv[0], 0);
766                                 rc = 1;
767                                 goto done;
768
769                         } else if ( rc == ARG_BAD_CONF ) {
770                                 rc = 1;
771                                 goto done;
772                         }
773                         
774                 } else if ( c->bi && !c->be ) {
775                         rc = SLAP_CONF_UNKNOWN;
776                         if ( c->bi->bi_cf_ocs ) {
777                                 ct = config_find_keyword( c->bi->bi_cf_ocs->co_table, c );
778                                 if ( ct ) {
779                                         rc = config_add_vals( ct, c );
780                                 }
781                         }
782                         if ( c->bi->bi_config && rc == SLAP_CONF_UNKNOWN ) {
783                                 rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno,
784                                         c->argc, c->argv);
785                         }
786                         if ( rc ) {
787                                 switch(rc) {
788                                 case SLAP_CONF_UNKNOWN:
789                                         Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
790                                                 "<%s> inside backend info definition.\n",
791                                                 c->log, *c->argv, 0);
792                                 default:
793                                         rc = 1;
794                                         goto done;
795                                 }
796                         }
797
798                 } else if ( c->be && c->be != frontendDB ) {
799                         rc = SLAP_CONF_UNKNOWN;
800                         if ( c->be->be_cf_ocs ) {
801                                 ct = config_find_keyword( c->be->be_cf_ocs->co_table, c );
802                                 if ( ct ) {
803                                         rc = config_add_vals( ct, c );
804                                 }
805                         }
806                         if ( c->be->be_config && rc == SLAP_CONF_UNKNOWN ) {
807                                 rc = (*c->be->be_config)(c->be, c->fname, c->lineno,
808                                         c->argc, c->argv);
809                         }
810                         if ( rc == SLAP_CONF_UNKNOWN && SLAP_ISGLOBALOVERLAY( frontendDB ) )
811                         {
812                                 /* global overlays may need 
813                                  * definitions inside other databases...
814                                  */
815                                 rc = (*frontendDB->be_config)( frontendDB,
816                                         c->fname, (int)c->lineno, c->argc, c->argv );
817                         }
818
819                         switch ( rc ) {
820                         case 0:
821                                 break;
822
823                         case SLAP_CONF_UNKNOWN:
824                                 Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
825                                         "<%s> inside backend database definition.\n",
826                                         c->log, *c->argv, 0);
827                                 
828                         default:
829                                 rc = 1;
830                                 goto done;
831                         }
832
833                 } else if ( frontendDB->be_config ) {
834                         rc = (*frontendDB->be_config)( frontendDB,
835                                 c->fname, (int)c->lineno, c->argc, c->argv);
836                         if ( rc ) {
837                                 switch(rc) {
838                                 case SLAP_CONF_UNKNOWN:
839                                         Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
840                                                 "<%s> inside global database definition.\n",
841                                                 c->log, *c->argv, 0);
842
843                                 default:
844                                         rc = 1;
845                                         goto done;
846                                 }
847                         }
848                         
849                 } else {
850                         Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
851                                 "<%s> outside backend info and database definitions.\n",
852                                 c->log, *c->argv, 0);
853                         rc = 1;
854                         goto done;
855                 }
856         }
857
858         rc = 0;
859
860 done:
861         ch_free(c->tline);
862         fclose(fp);
863         ch_free(c->argv);
864         ch_free(c);
865         return(rc);
866 }
867
868 /* restrictops, allows, disallows, requires, loglevel */
869
870 int
871 verb_to_mask(const char *word, slap_verbmasks *v) {
872         int i;
873         for(i = 0; !BER_BVISNULL(&v[i].word); i++) {
874                 if(!strcasecmp(word, v[i].word.bv_val)) break;
875         }
876         return(i);
877 }
878
879 int
880 verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) {
881         int i, j;
882         for(i = 1; i < argc; i++) {
883                 j = verb_to_mask(argv[i], v);
884                 if(BER_BVISNULL(&v[j].word)) return i;
885                 while (!v[j].mask) j--;
886                 *m |= v[j].mask;
887         }
888         return(0);
889 }
890
891 /* Mask keywords that represent multiple bits should occur before single
892  * bit keywords in the verbmasks array.
893  */
894 int
895 mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) {
896         int i, rc = 1;
897
898         if (m) {
899                 for (i=0; !BER_BVISNULL(&v[i].word); i++) {
900                         if (!v[i].mask) continue;
901                         if (( m & v[i].mask ) == v[i].mask ) {
902                                 value_add_one( bva, &v[i].word );
903                                 rc = 0;
904                                 m ^= v[i].mask;
905                                 if ( !m ) break;
906                         }
907                 }
908         }
909         return rc;
910 }
911
912 int
913 slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
914 {
915         int             i;
916
917         assert( *vp == NULL );
918
919         for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */;
920
921         *vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );
922
923         for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
924                 ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
925                 *((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
926         }
927
928         BER_BVZERO( &(*vp)[ i ].word );
929
930         return 0;               
931 }
932
933 int
934 slap_verbmasks_destroy( slap_verbmasks *v )
935 {
936         int             i;
937
938         assert( v != NULL );
939
940         for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
941                 ch_free( v[ i ].word.bv_val );
942         }
943
944         ch_free( v );
945
946         return 0;
947 }
948
949 int
950 slap_verbmasks_append(
951         slap_verbmasks  **vp,
952         slap_mask_t     m,
953         struct berval   *v,
954         slap_mask_t     *ignore )
955 {
956         int     i;
957
958         if ( !m ) {
959                 return LDAP_OPERATIONS_ERROR;
960         }
961
962         for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
963                 if ( !(*vp)[ i ].mask ) continue;
964
965                 if ( ignore != NULL ) {
966                         int     j;
967
968                         for ( j = 0; ignore[ j ] != 0; j++ ) {
969                                 if ( (*vp)[ i ].mask == ignore[ j ] ) {
970                                         goto check_next;
971                                 }
972                         }
973                 }
974
975                 if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
976                         if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
977                                 /* already set; ignore */
978                                 return LDAP_SUCCESS;
979                         }
980                         /* conflicts */
981                         return LDAP_TYPE_OR_VALUE_EXISTS;
982                 }
983
984                 if ( m & (*vp)[ i ].mask ) {
985                         /* conflicts */
986                         return LDAP_CONSTRAINT_VIOLATION;
987                 }
988 check_next:;
989         }
990
991         *vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
992         ber_dupbv( &(*vp)[ i ].word, v );
993         *((slap_mask_t *)&(*vp)[ i ].mask) = m;
994         BER_BVZERO( &(*vp)[ i + 1 ].word );
995
996         return LDAP_SUCCESS;
997 }
998
999 int
1000 enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
1001         int i;
1002
1003         for (i=0; !BER_BVISNULL(&v[i].word); i++) {
1004                 if ( m == v[i].mask ) {
1005                         if ( bv != NULL ) {
1006                                 *bv = v[i].word;
1007                         }
1008                         return i;
1009                 }
1010         }
1011         return -1;
1012 }
1013
1014 #ifdef HAVE_TLS
1015 static slap_verbmasks tlskey[] = {
1016         { BER_BVC("no"),        SB_TLS_OFF },
1017         { BER_BVC("yes"),       SB_TLS_ON },
1018         { BER_BVC("critical"),  SB_TLS_CRITICAL },
1019         { BER_BVNULL, 0 }
1020 };
1021 #endif
1022
1023 static slap_verbmasks methkey[] = {
1024         { BER_BVC("none"),      LDAP_AUTH_NONE },
1025         { BER_BVC("simple"),    LDAP_AUTH_SIMPLE },
1026 #ifdef HAVE_CYRUS_SASL
1027         { BER_BVC("sasl"),      LDAP_AUTH_SASL },
1028 #endif
1029         { BER_BVNULL, 0 }
1030 };
1031
1032 static slap_cf_aux_table bindkey[] = {
1033         { BER_BVC("uri="), offsetof(slap_bindconf, sb_uri), 'b', 1, NULL },
1034         { BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'd', 0, methkey },
1035         { BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, NULL },
1036         { BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
1037         { BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
1038         { BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
1039         { BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
1040         { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 0, NULL },
1041         { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, NULL },
1042 #ifdef HAVE_TLS
1043         { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'd', 0, tlskey },
1044
1045 #define aux_TLS (bindkey+10)    /* beginning of TLS keywords */
1046
1047         { BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL },
1048         { BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL },
1049         { BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL },
1050         { BER_BVC("tls_cacertdir="), offsetof(slap_bindconf, sb_tls_cacertdir), 's', 1, NULL },
1051         { BER_BVC("tls_reqcert="), offsetof(slap_bindconf, sb_tls_reqcert), 's', 1, NULL },
1052         { BER_BVC("tls_cipher_suite="), offsetof(slap_bindconf, sb_tls_cipher_suite), 's', 1, NULL },
1053 #ifdef HAVE_OPENSSL_CRL
1054         { BER_BVC("tls_crlcheck="), offsetof(slap_bindconf, sb_tls_crlcheck), 's', 1, NULL },
1055 #endif
1056 #endif
1057         { BER_BVNULL, 0, 0, 0, NULL }
1058 };
1059
1060 int
1061 slap_cf_aux_table_parse( const char *word, void *dst, slap_cf_aux_table *tab0, LDAP_CONST char *tabmsg )
1062 {
1063         int rc = SLAP_CONF_UNKNOWN;
1064         slap_cf_aux_table *tab;
1065
1066         for (tab = tab0; !BER_BVISNULL(&tab->key); tab++ ) {
1067                 if ( !strncasecmp( word, tab->key.bv_val, tab->key.bv_len )) {
1068                         char **cptr;
1069                         int *iptr, j;
1070                         unsigned *uptr;
1071                         long *lptr;
1072                         unsigned long *ulptr;
1073                         struct berval *bptr;
1074                         const char *val = word + tab->key.bv_len;
1075
1076                         switch ( tab->type ) {
1077                         case 's':
1078                                 cptr = (char **)((char *)dst + tab->off);
1079                                 *cptr = ch_strdup( val );
1080                                 rc = 0;
1081                                 break;
1082
1083                         case 'b':
1084                                 bptr = (struct berval *)((char *)dst + tab->off);
1085                                 ber_str2bv( val, 0, 1, bptr );
1086                                 rc = 0;
1087                                 break;
1088
1089                         case 'd':
1090                                 assert( tab->aux != NULL );
1091                                 iptr = (int *)((char *)dst + tab->off);
1092
1093                                 rc = 1;
1094                                 for ( j = 0; !BER_BVISNULL( &tab->aux[j].word ); j++ ) {
1095                                         if ( !strcasecmp( val, tab->aux[j].word.bv_val ) ) {
1096                                                 *iptr = tab->aux[j].mask;
1097                                                 rc = 0;
1098                                         }
1099                                 }
1100                                 break;
1101
1102                         case 'i':
1103                                 iptr = (int *)((char *)dst + tab->off);
1104
1105                                 rc = lutil_atoix( iptr, val, 0 );
1106                                 break;
1107
1108                         case 'u':
1109                                 uptr = (unsigned *)((char *)dst + tab->off);
1110
1111                                 rc = lutil_atoux( uptr, val, 0 );
1112                                 break;
1113
1114                         case 'I':
1115                                 lptr = (long *)((char *)dst + tab->off);
1116
1117                                 rc = lutil_atolx( lptr, val, 0 );
1118                                 break;
1119
1120                         case 'U':
1121                                 ulptr = (unsigned long *)((char *)dst + tab->off);
1122
1123                                 rc = lutil_atoulx( ulptr, val, 0 );
1124                                 break;
1125                         }
1126
1127                         if ( rc ) {
1128                                 Debug( LDAP_DEBUG_ANY, "invalid %s value %s\n",
1129                                         tabmsg, word, 0 );
1130                         }
1131                         
1132                         return rc;
1133                 }
1134         }
1135
1136         return rc;
1137 }
1138
1139 int
1140 slap_cf_aux_table_unparse( void *src, struct berval *bv, slap_cf_aux_table *tab0 )
1141 {
1142         char buf[BUFSIZ], *ptr;
1143         slap_cf_aux_table *tab;
1144         struct berval tmp;
1145
1146         ptr = buf;
1147         for (tab = tab0; !BER_BVISNULL(&tab->key); tab++ ) {
1148                 char **cptr;
1149                 int *iptr, i;
1150                 unsigned *uptr;
1151                 long *lptr;
1152                 unsigned long *ulptr;
1153                 struct berval *bptr;
1154
1155                 cptr = (char **)((char *)src + tab->off);
1156
1157                 switch ( tab->type ) {
1158                 case 'b':
1159                         bptr = (struct berval *)((char *)src + tab->off);
1160                         cptr = &bptr->bv_val;
1161                 case 's':
1162                         if ( *cptr ) {
1163                                 *ptr++ = ' ';
1164                                 ptr = lutil_strcopy( ptr, tab->key.bv_val );
1165                                 if ( tab->quote ) *ptr++ = '"';
1166                                 ptr = lutil_strcopy( ptr, *cptr );
1167                                 if ( tab->quote ) *ptr++ = '"';
1168                         }
1169                         break;
1170
1171                 case 'd':
1172                         assert( tab->aux != NULL );
1173                         iptr = (int *)((char *)src + tab->off);
1174                 
1175                         for ( i = 0; !BER_BVISNULL( &tab->aux[i].word ); i++ ) {
1176                                 if ( *iptr == tab->aux[i].mask ) {
1177                                         *ptr++ = ' ';
1178                                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1179                                         ptr = lutil_strcopy( ptr, tab->aux[i].word.bv_val );
1180                                         break;
1181                                 }
1182                         }
1183                         break;
1184
1185                 case 'i':
1186                         iptr = (int *)((char *)src + tab->off);
1187                         *ptr++ = ' ';
1188                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1189                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%d", *iptr );
1190                         break;
1191
1192                 case 'u':
1193                         uptr = (unsigned *)((char *)src + tab->off);
1194                         *ptr++ = ' ';
1195                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1196                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%u", *uptr );
1197                         break;
1198
1199                 case 'I':
1200                         lptr = (long *)((char *)src + tab->off);
1201                         *ptr++ = ' ';
1202                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1203                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%ld", *lptr );
1204                         break;
1205
1206                 case 'U':
1207                         ulptr = (unsigned long *)((char *)src + tab->off);
1208                         *ptr++ = ' ';
1209                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1210                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%lu", *ulptr );
1211                         break;
1212
1213                 default:
1214                         assert( 0 );
1215                 }
1216         }
1217         tmp.bv_val = buf;
1218         tmp.bv_len = ptr - buf;
1219         ber_dupbv( bv, &tmp );
1220         return 0;
1221 }
1222
1223 int
1224 bindconf_parse( const char *word, slap_bindconf *bc )
1225 {
1226 #ifdef HAVE_TLS
1227         /* Detect TLS config changes explicitly */
1228         if ( slap_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) {
1229                 bc->sb_tls_do_init = 1;
1230                 return 0;
1231         }
1232 #endif
1233         return slap_cf_aux_table_parse( word, bc, bindkey, "bind config" );
1234 }
1235
1236 int
1237 bindconf_unparse( slap_bindconf *bc, struct berval *bv )
1238 {
1239         return slap_cf_aux_table_unparse( bc, bv, bindkey );
1240 }
1241
1242 void bindconf_free( slap_bindconf *bc ) {
1243         if ( !BER_BVISNULL( &bc->sb_uri ) ) {
1244                 ch_free( bc->sb_uri.bv_val );
1245                 BER_BVZERO( &bc->sb_uri );
1246         }
1247         if ( !BER_BVISNULL( &bc->sb_binddn ) ) {
1248                 ch_free( bc->sb_binddn.bv_val );
1249                 BER_BVZERO( &bc->sb_binddn );
1250         }
1251         if ( !BER_BVISNULL( &bc->sb_cred ) ) {
1252                 ch_free( bc->sb_cred.bv_val );
1253                 BER_BVZERO( &bc->sb_cred );
1254         }
1255         if ( !BER_BVISNULL( &bc->sb_saslmech ) ) {
1256                 ch_free( bc->sb_saslmech.bv_val );
1257                 BER_BVZERO( &bc->sb_saslmech );
1258         }
1259         if ( bc->sb_secprops ) {
1260                 ch_free( bc->sb_secprops );
1261                 bc->sb_secprops = NULL;
1262         }
1263         if ( !BER_BVISNULL( &bc->sb_realm ) ) {
1264                 ch_free( bc->sb_realm.bv_val );
1265                 BER_BVZERO( &bc->sb_realm );
1266         }
1267         if ( !BER_BVISNULL( &bc->sb_authcId ) ) {
1268                 ch_free( bc->sb_authcId.bv_val );
1269                 BER_BVZERO( &bc->sb_authcId );
1270         }
1271         if ( !BER_BVISNULL( &bc->sb_authzId ) ) {
1272                 ch_free( bc->sb_authzId.bv_val );
1273                 BER_BVZERO( &bc->sb_authzId );
1274         }
1275 #ifdef HAVE_TLS
1276         if ( bc->sb_tls_ctx ) {
1277                 SSL_CTX_free( bc->sb_tls_ctx );
1278                 bc->sb_tls_ctx = NULL;
1279         }
1280         if ( bc->sb_tls_cert ) {
1281                 ch_free( bc->sb_tls_cert );
1282                 bc->sb_tls_cert = NULL;
1283         }
1284         if ( bc->sb_tls_key ) {
1285                 ch_free( bc->sb_tls_key );
1286                 bc->sb_tls_key = NULL;
1287         }
1288         if ( bc->sb_tls_cacert ) {
1289                 ch_free( bc->sb_tls_cacert );
1290                 bc->sb_tls_cacert = NULL;
1291         }
1292         if ( bc->sb_tls_cacertdir ) {
1293                 ch_free( bc->sb_tls_cacertdir );
1294                 bc->sb_tls_cacertdir = NULL;
1295         }
1296         if ( bc->sb_tls_reqcert ) {
1297                 ch_free( bc->sb_tls_reqcert );
1298                 bc->sb_tls_reqcert = NULL;
1299         }
1300         if ( bc->sb_tls_cipher_suite ) {
1301                 ch_free( bc->sb_tls_cipher_suite );
1302                 bc->sb_tls_cipher_suite = NULL;
1303         }
1304 #ifdef HAVE_OPENSSL_CRL
1305         if ( bc->sb_tls_crlcheck ) {
1306                 ch_free( bc->sb_tls_crlcheck );
1307                 bc->sb_tls_crlcheck = NULL;
1308         }
1309 #endif
1310 #endif
1311 }
1312
1313 #ifdef HAVE_TLS
1314 static struct {
1315         const char *key;
1316         size_t offset;
1317         int opt;
1318 } bindtlsopts[] = {
1319         { "tls_cert", offsetof(slap_bindconf, sb_tls_cert), LDAP_OPT_X_TLS_CERTFILE },
1320         { "tls_key", offsetof(slap_bindconf, sb_tls_key), LDAP_OPT_X_TLS_KEYFILE },
1321         { "tls_cacert", offsetof(slap_bindconf, sb_tls_cacert), LDAP_OPT_X_TLS_CACERTFILE },
1322         { "tls_cacertdir", offsetof(slap_bindconf, sb_tls_cacertdir), LDAP_OPT_X_TLS_CACERTDIR },
1323         { "tls_cipher_suite", offsetof(slap_bindconf, sb_tls_cipher_suite), LDAP_OPT_X_TLS_CIPHER_SUITE },
1324         {0, 0}
1325 };
1326
1327 int bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
1328 {
1329         int i, rc, newctx = 0, res = 0;
1330         char *ptr = (char *)bc, **word;
1331
1332         bc->sb_tls_do_init = 0;
1333
1334         for (i=0; bindtlsopts[i].opt; i++) {
1335                 word = (char **)(ptr + bindtlsopts[i].offset);
1336                 if ( *word ) {
1337                         rc = ldap_set_option( ld, bindtlsopts[i].opt, *word );
1338                         if ( rc ) {
1339                                 Debug( LDAP_DEBUG_ANY,
1340                                         "bindconf_tls_set: failed to set %s to %s\n",
1341                                                 bindtlsopts[i].key, *word, 0 );
1342                                 res = -1;
1343                         } else
1344                                 newctx = 1;
1345                 }
1346         }
1347         if ( bc->sb_tls_reqcert ) {
1348                 rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_REQUIRE_CERT,
1349                         bc->sb_tls_reqcert );
1350                 if ( rc ) {
1351                         Debug( LDAP_DEBUG_ANY,
1352                                 "bindconf_tls_set: failed to set tls_reqcert to %s\n",
1353                                         bc->sb_tls_reqcert, 0, 0 );
1354                         res = -1;
1355                 } else
1356                         newctx = 1;
1357         }
1358 #ifdef HAVE_OPENSSL_CRL
1359         if ( bc->sb_tls_crlcheck ) {
1360                 rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_CRLCHECK,
1361                         bc->sb_tls_crlcheck );
1362                 if ( rc ) {
1363                         Debug( LDAP_DEBUG_ANY,
1364                                 "bindconf_tls_set: failed to set tls_crlcheck to %s\n",
1365                                         bc->sb_tls_crlcheck, 0, 0 );
1366                         res = -1;
1367                 } else
1368                         newctx = 1;
1369         }
1370 #endif
1371         if ( newctx ) {
1372                 int opt = 0;
1373
1374                 if ( bc->sb_tls_ctx ) {
1375                         SSL_CTX_free( bc->sb_tls_ctx );
1376                         bc->sb_tls_ctx = NULL;
1377                 }
1378                 rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
1379                 if ( rc )
1380                         res = rc;
1381                 else
1382                         ldap_get_option( ld, LDAP_OPT_X_TLS_CTX, &bc->sb_tls_ctx );
1383         }
1384         
1385         return res;
1386 }
1387 #endif
1388
1389 /* -------------------------------------- */
1390
1391
1392 static char *
1393 strtok_quote( char *line, char *sep, char **quote_ptr )
1394 {
1395         int             inquote;
1396         char            *tmp;
1397         static char     *next;
1398
1399         *quote_ptr = NULL;
1400         if ( line != NULL ) {
1401                 next = line;
1402         }
1403         while ( *next && strchr( sep, *next ) ) {
1404                 next++;
1405         }
1406
1407         if ( *next == '\0' ) {
1408                 next = NULL;
1409                 return( NULL );
1410         }
1411         tmp = next;
1412
1413         for ( inquote = 0; *next; ) {
1414                 switch ( *next ) {
1415                 case '"':
1416                         if ( inquote ) {
1417                                 inquote = 0;
1418                         } else {
1419                                 inquote = 1;
1420                         }
1421                         AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
1422                         break;
1423
1424                 case '\\':
1425                         if ( next[1] )
1426                                 AC_MEMCPY( next,
1427                                             next + 1, strlen( next + 1 ) + 1 );
1428                         next++;         /* dont parse the escaped character */
1429                         break;
1430
1431                 default:
1432                         if ( ! inquote ) {
1433                                 if ( strchr( sep, *next ) != NULL ) {
1434                                         *quote_ptr = next;
1435                                         *next++ = '\0';
1436                                         return( tmp );
1437                                 }
1438                         }
1439                         next++;
1440                         break;
1441                 }
1442         }
1443
1444         return( tmp );
1445 }
1446
1447 static char     buf[BUFSIZ];
1448 static char     *line;
1449 static size_t lmax, lcur;
1450
1451 #define CATLINE( buf ) \
1452         do { \
1453                 size_t len = strlen( buf ); \
1454                 while ( lcur + len + 1 > lmax ) { \
1455                         lmax += BUFSIZ; \
1456                         line = (char *) ch_realloc( line, lmax ); \
1457                 } \
1458                 strcpy( line + lcur, buf ); \
1459                 lcur += len; \
1460         } while( 0 )
1461
1462 static void
1463 fp_getline_init(ConfigArgs *c) {
1464         c->lineno = -1;
1465         buf[0] = '\0';
1466 }
1467
1468 static int
1469 fp_getline( FILE *fp, ConfigArgs *c )
1470 {
1471         char    *p;
1472
1473         lcur = 0;
1474         CATLINE(buf);
1475         c->lineno++;
1476
1477         /* avoid stack of bufs */
1478         if ( strncasecmp( line, "include", STRLENOF( "include" ) ) == 0 ) {
1479                 buf[0] = '\0';
1480                 c->line = line;
1481                 return(1);
1482         }
1483
1484         while ( fgets( buf, sizeof( buf ), fp ) ) {
1485                 p = strchr( buf, '\n' );
1486                 if ( p ) {
1487                         if ( p > buf && p[-1] == '\r' ) {
1488                                 --p;
1489                         }
1490                         *p = '\0';
1491                 }
1492                 /* XXX ugly */
1493                 c->line = line;
1494                 if ( line[0]
1495                                 && ( p = line + strlen( line ) - 1 )[0] == '\\'
1496                                 && p[-1] != '\\' )
1497                 {
1498                         p[0] = '\0';
1499                         lcur--;
1500                         
1501                 } else {
1502                         if ( !isspace( (unsigned char)buf[0] ) ) {
1503                                 return(1);
1504                         }
1505                         buf[0] = ' ';
1506                 }
1507                 CATLINE(buf);
1508                 c->lineno++;
1509         }
1510
1511         buf[0] = '\0';
1512         c->line = line;
1513         return(line[0] ? 1 : 0);
1514 }
1515
1516 static int
1517 fp_parse_line(ConfigArgs *c)
1518 {
1519         char *token;
1520         static char *const hide[] = {
1521                 "rootpw", "replica", "syncrepl",  /* in slapd */
1522                 "acl-bind", "acl-method", "idassert-bind",  /* in back-ldap */
1523                 "acl-passwd", "bindpw",  /* in back-<ldap/meta> */
1524                 "pseudorootpw",  /* in back-meta */
1525                 "dbpasswd",  /* in back-sql */
1526                 NULL
1527         };
1528         char *quote_ptr;
1529         int i = (int)(sizeof(hide)/sizeof(hide[0])) - 1;
1530
1531         c->tline = ch_strdup(c->line);
1532         token = strtok_quote(c->tline, " \t", &quote_ptr);
1533
1534         if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
1535         if(quote_ptr) *quote_ptr = ' ';
1536         Debug(LDAP_DEBUG_CONFIG, "line %d (%s%s)\n", c->lineno,
1537                 hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "");
1538         if(quote_ptr) *quote_ptr = '\0';
1539
1540         for(;; token = strtok_quote(NULL, " \t", &quote_ptr)) {
1541                 if(c->argc >= c->argv_size) {
1542                         char **tmp;
1543                         tmp = ch_realloc(c->argv, (c->argv_size + ARGS_STEP) * sizeof(*c->argv));
1544                         if(!tmp) {
1545                                 Debug(LDAP_DEBUG_ANY, "line %d: out of memory\n", c->lineno, 0, 0);
1546                                 return -1;
1547                         }
1548                         c->argv = tmp;
1549                         c->argv_size += ARGS_STEP;
1550                 }
1551                 if(token == NULL)
1552                         break;
1553                 c->argv[c->argc++] = token;
1554         }
1555         c->argv[c->argc] = NULL;
1556         return(0);
1557 }
1558
1559 void
1560 config_destroy( )
1561 {
1562         ucdata_unload( UCDATA_ALL );
1563         if ( frontendDB ) {
1564                 /* NOTE: in case of early exit, frontendDB can be NULL */
1565                 if ( frontendDB->be_schemandn.bv_val )
1566                         free( frontendDB->be_schemandn.bv_val );
1567                 if ( frontendDB->be_schemadn.bv_val )
1568                         free( frontendDB->be_schemadn.bv_val );
1569                 if ( frontendDB->be_acl )
1570                         acl_destroy( frontendDB->be_acl, NULL );
1571         }
1572         free( line );
1573         if ( slapd_args_file )
1574                 free ( slapd_args_file );
1575         if ( slapd_pid_file )
1576                 free ( slapd_pid_file );
1577         if ( default_passwd_hash )
1578                 ldap_charray_free( default_passwd_hash );
1579 }
1580
1581 char **
1582 slap_str2clist( char ***out, char *in, const char *brkstr )
1583 {
1584         char    *str;
1585         char    *s;
1586         char    *lasts;
1587         int     i, j;
1588         char    **new;
1589
1590         /* find last element in list */
1591         for (i = 0; *out && (*out)[i]; i++);
1592
1593         /* protect the input string from strtok */
1594         str = ch_strdup( in );
1595
1596         if ( *str == '\0' ) {
1597                 free( str );
1598                 return( *out );
1599         }
1600
1601         /* Count words in string */
1602         j=1;
1603         for ( s = str; *s; s++ ) {
1604                 if ( strchr( brkstr, *s ) != NULL ) {
1605                         j++;
1606                 }
1607         }
1608
1609         *out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
1610         new = *out + i;
1611         for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
1612                 s != NULL;
1613                 s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
1614         {
1615                 *new = ch_strdup( s );
1616                 new++;
1617         }
1618
1619         *new = NULL;
1620         free( str );
1621         return( *out );
1622 }
1623
1624 int config_generic_wrapper( Backend *be, const char *fname, int lineno,
1625         int argc, char **argv )
1626 {
1627         ConfigArgs c = { 0 };
1628         ConfigTable *ct;
1629         int rc;
1630
1631         c.be = be;
1632         c.fname = fname;
1633         c.lineno = lineno;
1634         c.argc = argc;
1635         c.argv = argv;
1636         c.valx = -1;
1637         c.line = line;
1638         c.op = SLAP_CONFIG_ADD;
1639         snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
1640
1641         rc = SLAP_CONF_UNKNOWN;
1642         ct = config_find_keyword( be->be_cf_ocs->co_table, &c );
1643         if ( ct )
1644                 rc = config_add_vals( ct, &c );
1645         return rc;
1646 }