]> git.sur5r.net Git - openldap/blob - servers/slapd/config.c
Rework backend (lastmod + glue + system schema) flags
[openldap] / servers / slapd / config.c
1 /* config.c - configuration file handling routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/ctype.h>
14 #include <ac/socket.h>
15 #include <ac/errno.h>
16
17 #include "lutil.h"
18 #include "ldap_pvt.h"
19 #include "slap.h"
20
21 #define MAXARGS 500
22
23 /*
24  * defaults for various global variables
25  */
26 struct slap_limits_set deflimit = {
27         SLAPD_DEFAULT_TIMELIMIT,        /* backward compatible limits */
28         0,
29
30         SLAPD_DEFAULT_SIZELIMIT,        /* backward compatible limits */
31         0,
32         -1                              /* no limit on unchecked size */
33 };
34
35 AccessControl   *global_acl = NULL;
36 slap_access_t           global_default_access = ACL_READ;
37 slap_mask_t             global_restrictops = 0;
38 slap_mask_t             global_allows = 0;
39 slap_mask_t             global_disallows = 0;
40 slap_mask_t             global_requires = 0;
41 slap_ssf_set_t  global_ssf_set;
42 char            *replogfile;
43 int             global_idletimeout = 0;
44 char    *global_host = NULL;
45 char    *global_realm = NULL;
46 char            *ldap_srvtab = "";
47 char            *default_passwd_hash;
48 struct berval default_search_base = { 0, NULL };
49 struct berval default_search_nbase = { 0, NULL };
50 unsigned                num_subordinates = 0;
51
52 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
53 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
54
55 char   *slapd_pid_file  = NULL;
56 char   *slapd_args_file = NULL;
57
58 int nSaslRegexp = 0;
59 SaslRegexp_t *SaslRegexp = NULL;
60 int sasl_external_x509dn_convert;
61
62 static char     *fp_getline(FILE *fp, int *lineno);
63 static void     fp_getline_init(int *lineno);
64 static int      fp_parse_line(char *line, int *argcp, char **argv);
65
66 static char     *strtok_quote(char *line, char *sep);
67 static int      load_ucdata(char *path);
68
69 int
70 read_config( const char *fname )
71 {
72         FILE    *fp;
73         char    *line, *savefname, *saveline;
74         int     cargc, savelineno;
75         char    *cargv[MAXARGS+1];
76         int     lineno, i;
77         int rc;
78         struct berval vals[2];
79
80         static int lastmod = ON;
81         static BackendInfo *bi = NULL;
82         static BackendDB        *be = NULL;
83
84         vals[1].bv_val = NULL;
85
86         if ( (fp = fopen( fname, "r" )) == NULL ) {
87                 ldap_syslog = 1;
88 #ifdef NEW_LOGGING
89                 LDAP_LOG(( "config", LDAP_LEVEL_ENTRY, "read_config: "
90                         "could not open config file \"%s\": %s (%d)\n",
91                     fname, strerror(errno), errno ));
92 #else
93                 Debug( LDAP_DEBUG_ANY,
94                     "could not open config file \"%s\": %s (%d)\n",
95                     fname, strerror(errno), errno );
96 #endif
97                 return 1;
98         }
99
100 #ifdef NEW_LOGGING
101         LDAP_LOG(( "config", LDAP_LEVEL_ENTRY,
102                 "read_config: reading config file %s\n", fname ));
103 #else
104         Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0 );
105 #endif
106
107
108         fp_getline_init( &lineno );
109
110         while ( (line = fp_getline( fp, &lineno )) != NULL ) {
111                 /* skip comments and blank lines */
112                 if ( line[0] == '#' || line[0] == '\0' ) {
113                         continue;
114                 }
115
116 #ifdef NEW_LOGGING
117                 LDAP_LOG(( "config", LDAP_LEVEL_DETAIL1,
118                            "line %d (%s)\n", lineno, line ));
119 #else
120                 Debug( LDAP_DEBUG_CONFIG, "line %d (%s)\n", lineno, line, 0 );
121 #endif
122
123
124                 /* fp_parse_line is destructive, we save a copy */
125                 saveline = ch_strdup( line );
126
127                 if ( fp_parse_line( line, &cargc, cargv ) != 0 ) {
128                         return( 1 );
129                 }
130
131                 if ( cargc < 1 ) {
132 #ifdef NEW_LOGGING
133                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
134                                    "%s: line %d: bad config line (ignored)\n",
135                                    fname, lineno ));
136 #else
137                         Debug( LDAP_DEBUG_ANY,
138                             "%s: line %d: bad config line (ignored)\n",
139                             fname, lineno, 0 );
140 #endif
141
142                         continue;
143                 }
144
145                 if ( strcasecmp( cargv[0], "backend" ) == 0 ) {
146                         if ( cargc < 2 ) {
147 #ifdef NEW_LOGGING
148                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
149                                            "%s : line %d: missing type in \"backend\" line.\n",
150                                            fname, lineno ));
151 #else
152                                 Debug( LDAP_DEBUG_ANY,
153                 "%s: line %d: missing type in \"backend <type>\" line\n",
154                                     fname, lineno, 0 );
155 #endif
156
157                                 return( 1 );
158                         }
159
160                         if( be != NULL ) {
161 #ifdef NEW_LOGGING
162                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
163                                            "%s: line %d: backend line must appear before any "
164                                            "database definition.\n", fname, lineno ));
165 #else
166                                 Debug( LDAP_DEBUG_ANY,
167 "%s: line %d: backend line must appear before any database definition\n",
168                                     fname, lineno, 0 );
169 #endif
170
171                                 return( 1 );
172                         }
173
174                         bi = backend_info( cargv[1] );
175
176                         if( bi == NULL ) {
177 #ifdef NEW_LOGGING
178                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
179                                            "read_config: backend %s initialization failed.\n",
180                                            cargv[1] ));
181 #else
182                                 Debug( LDAP_DEBUG_ANY,
183                                         "backend %s initialization failed.\n",
184                                     cargv[1], 0, 0 );
185 #endif
186
187                                 return( 1 );
188                         }
189                 } else if ( strcasecmp( cargv[0], "database" ) == 0 ) {
190                         if ( cargc < 2 ) {
191 #ifdef NEW_LOGGING
192                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
193                                            "%s: line %d: missing type in \"database <type>\" line\n",
194                                            fname, lineno ));
195 #else
196                                 Debug( LDAP_DEBUG_ANY,
197                 "%s: line %d: missing type in \"database <type>\" line\n",
198                                     fname, lineno, 0 );
199 #endif
200
201                                 return( 1 );
202                         }
203
204                         bi = NULL;
205                         be = backend_db_init( cargv[1] );
206
207                         if( lastmod ) be->be_flags |= SLAP_BFLAG_LASTMOD;
208
209                         if( be == NULL ) {
210 #ifdef NEW_LOGGING
211                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
212                                            "database %s initialization failed.\n",
213                                            cargv[1] ));
214 #else
215                                 Debug( LDAP_DEBUG_ANY,
216                                         "database %s initialization failed.\n",
217                                     cargv[1], 0, 0 );
218 #endif
219
220                                 return( 1 );
221                         }
222
223                 /* set thread concurrency */
224                 } else if ( strcasecmp( cargv[0], "concurrency" ) == 0 ) {
225                         int c;
226                         if ( cargc < 2 ) {
227 #ifdef NEW_LOGGING
228                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
229                                            "%s: line %d: missing level in \"concurrency <level\" line\n",
230                                            fname, lineno ));
231 #else
232                                 Debug( LDAP_DEBUG_ANY,
233             "%s: line %d: missing level in \"concurrency <level>\" line\n",
234                                     fname, lineno, 0 );
235 #endif
236
237                                 return( 1 );
238                         }
239
240                         c = atoi( cargv[1] );
241
242                         if( c < 1 ) {
243 #ifdef NEW_LOGGING
244                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
245                                            "%s: line %d: invalid level (%d) in "
246                                            "\"concurrency <level>\" line.\n",
247                                            fname, lineno, c ));
248 #else
249                                 Debug( LDAP_DEBUG_ANY,
250             "%s: line %d: invalid level (%d) in \"concurrency <level>\" line\n",
251                                     fname, lineno, c );
252 #endif
253
254                                 return( 1 );
255                         }
256
257                         ldap_pvt_thread_set_concurrency( c );
258
259                 /* set sockbuf max */
260                 } else if ( strcasecmp( cargv[0], "sockbuf_max_incoming" ) == 0 ) {
261                         long max;
262                         if ( cargc < 2 ) {
263 #ifdef NEW_LOGGING
264                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
265                                            "%s: line %d: missing max in \"sockbuf_max_incoming <bytes>\" line\n",
266                                            fname, lineno ));
267 #else
268                                 Debug( LDAP_DEBUG_ANY,
269                                            "%s: line %d: missing max in \"sockbuf_max_incoming <bytes>\" line\n",
270                                     fname, lineno, 0 );
271 #endif
272
273                                 return( 1 );
274                         }
275
276                         max = atol( cargv[1] );
277
278                         if( max < 0 ) {
279 #ifdef NEW_LOGGING
280                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
281                                            "%s: line %d: invalid max value (%ld) in "
282                                            "\"sockbuf_max_incoming <bytes>\" line.\n",
283                                            fname, lineno, max ));
284 #else
285                                 Debug( LDAP_DEBUG_ANY,
286                                         "%s: line %d: invalid max value (%ld) in "
287                                         "\"sockbuf_max_incoming <bytes>\" line.\n",
288                                     fname, lineno, max );
289 #endif
290
291                                 return( 1 );
292                         }
293
294                         sockbuf_max_incoming = max;
295
296                 /* set sockbuf max authenticated */
297                 } else if ( strcasecmp( cargv[0], "sockbuf_max_incoming_auth" ) == 0 ) {
298                         long max;
299                         if ( cargc < 2 ) {
300 #ifdef NEW_LOGGING
301                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
302                                            "%s: line %d: missing max in \"sockbuf_max_incoming_auth <bytes>\" line\n",
303                                            fname, lineno ));
304 #else
305                                 Debug( LDAP_DEBUG_ANY,
306                                            "%s: line %d: missing max in \"sockbuf_max_incoming_auth <bytes>\" line\n",
307                                     fname, lineno, 0 );
308 #endif
309
310                                 return( 1 );
311                         }
312
313                         max = atol( cargv[1] );
314
315                         if( max < 0 ) {
316 #ifdef NEW_LOGGING
317                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
318                                            "%s: line %d: invalid max value (%ld) in "
319                                            "\"sockbuf_max_incoming_auth <bytes>\" line.\n",
320                                            fname, lineno, max ));
321 #else
322                                 Debug( LDAP_DEBUG_ANY,
323                                         "%s: line %d: invalid max value (%ld) in "
324                                         "\"sockbuf_max_incoming_auth <bytes>\" line.\n",
325                                     fname, lineno, max );
326 #endif
327
328                                 return( 1 );
329                         }
330
331                         sockbuf_max_incoming_auth = max;
332
333                 /* default search base */
334                 } else if ( strcasecmp( cargv[0], "defaultSearchBase" ) == 0 ) {
335                         if ( cargc < 2 ) {
336 #ifdef NEW_LOGGING
337                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
338                                         "%s: line %d: missing dn in \"defaultSearchBase <dn\" "
339                                         "line\n", fname, lineno ));
340 #else
341                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
342                                         "missing dn in \"defaultSearchBase <dn>\" line\n",
343                                         fname, lineno, 0 );
344 #endif
345
346                                 return 1;
347
348                         } else if ( cargc > 2 ) {
349 #ifdef NEW_LOGGING
350                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
351                                         "%s: line %d: extra cruft after <dn> in "
352                                         "\"defaultSearchBase %s\" line (ignored)\n",
353                                         fname, lineno, cargv[1] ));
354 #else
355                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
356                                         "extra cruft after <dn> in \"defaultSearchBase %s\", "
357                                         "line (ignored)\n",
358                                         fname, lineno, cargv[1] );
359 #endif
360                         }
361
362                         if ( bi != NULL || be != NULL ) {
363 #ifdef NEW_LOGGING
364                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
365                                         "%s: line %d: defaultSearchBase line must appear "
366                                         "prior to any backend or database definitions\n",
367                                         fname, lineno ));
368 #else
369                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
370                                         "defaultSearchBaase line must appear prior to "
371                                         "any backend or database definition\n",
372                                     fname, lineno, 0 );
373 #endif
374
375                                 return 1;
376                         }
377
378                         if ( default_search_nbase.bv_len ) {
379 #ifdef NEW_LOGGING
380                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
381                                         "default search base \"%s\" already defined "
382                                         "(discarding old)\n", fname, lineno,
383                                         default_search_base->bv_val ));
384 #else
385                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
386                                         "default search base \"%s\" already defined "
387                                         "(discarding old)\n",
388                                         fname, lineno, default_search_base.bv_val );
389 #endif
390
391                                 free( default_search_base.bv_val );
392                                 free( default_search_nbase.bv_val );
393                         }
394
395                         if ( load_ucdata( NULL ) < 0 ) return 1;
396
397                         {
398                                 struct berval dn;
399
400                                 dn.bv_val = cargv[1];
401                                 dn.bv_len = strlen( dn.bv_val );
402
403                                 rc = dnPrettyNormal( NULL, &dn,
404                                         &default_search_base,
405                                         &default_search_nbase );
406
407                                 if( rc != LDAP_SUCCESS ) {
408 #ifdef NEW_LOGGING
409                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
410                                                 "%s: line %d: defaultSearchBase DN is invalid.\n",
411                                                 fname, lineno ));
412 #else
413                                         Debug( LDAP_DEBUG_ANY,
414                                                 "%s: line %d: defaultSearchBase DN is invalid\n",
415                                            fname, lineno, 0 );
416 #endif
417                                         return( 1 );
418                                 }
419                         }
420
421                 /* set maximum threads in thread pool */
422                 } else if ( strcasecmp( cargv[0], "threads" ) == 0 ) {
423                         int c;
424                         if ( cargc < 2 ) {
425 #ifdef NEW_LOGGING
426                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
427                                            "%s: line %d: missing count in \"threads <count>\" line\n",
428                                            fname, lineno ));
429 #else
430                                 Debug( LDAP_DEBUG_ANY,
431             "%s: line %d: missing count in \"threads <count>\" line\n",
432                                     fname, lineno, 0 );
433 #endif
434
435                                 return( 1 );
436                         }
437
438                         c = atoi( cargv[1] );
439
440                         if( c < 0 ) {
441 #ifdef NEW_LOGGING
442                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
443                                            "%s: line %d: invalid level (%d) in \"threads <count>\""
444                                            "line\n",fname, lineno, c ));
445 #else
446                                 Debug( LDAP_DEBUG_ANY,
447             "%s: line %d: invalid level (%d) in \"threads <count>\" line\n",
448                                     fname, lineno, c );
449 #endif
450
451                                 return( 1 );
452                         }
453
454                         ldap_pvt_thread_pool_maxthreads( &connection_pool, c );
455
456                         /* save for later use */
457                         connection_pool_max = c;
458
459                 /* get pid file name */
460                 } else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
461                         if ( cargc < 2 ) {
462 #ifdef NEW_LOGGING
463                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
464                                            "%s: line %d missing file name in \"pidfile <file>\" line.\n",
465                                            fname, lineno ));
466 #else
467                                 Debug( LDAP_DEBUG_ANY,
468             "%s: line %d: missing file name in \"pidfile <file>\" line\n",
469                                     fname, lineno, 0 );
470 #endif
471
472                                 return( 1 );
473                         }
474
475                         slapd_pid_file = ch_strdup( cargv[1] );
476
477                 /* get args file name */
478                 } else if ( strcasecmp( cargv[0], "argsfile" ) == 0 ) {
479                         if ( cargc < 2 ) {
480 #ifdef NEW_LOGGING
481                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
482                                            "%s: %d: missing file name in "
483                                            "\"argsfile <file>\" line.\n",
484                                            fname, lineno ));
485 #else
486                                 Debug( LDAP_DEBUG_ANY,
487             "%s: line %d: missing file name in \"argsfile <file>\" line\n",
488                                     fname, lineno, 0 );
489 #endif
490
491                                 return( 1 );
492                         }
493
494                         slapd_args_file = ch_strdup( cargv[1] );
495
496                 /* default password hash */
497                 } else if ( strcasecmp( cargv[0], "password-hash" ) == 0 ) {
498                         if ( cargc < 2 ) {
499 #ifdef NEW_LOGGING
500                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
501                                            "%s: line %d: missing hash in "
502                                            "\"password-hash <hash>\" line.\n",
503                                            fname, lineno ));
504 #else
505                                 Debug( LDAP_DEBUG_ANY,
506             "%s: line %d: missing hash in \"password-hash <hash>\" line\n",
507                                     fname, lineno, 0 );
508 #endif
509
510                                 return( 1 );
511                         }
512                         if ( default_passwd_hash != NULL ) {
513 #ifdef NEW_LOGGING
514                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
515                                            "%s: line %d: already set default password_hash!\n",
516                                            fname, lineno ));
517 #else
518                                 Debug( LDAP_DEBUG_ANY,
519                                         "%s: line %d: already set default password_hash!\n",
520                                         fname, lineno, 0 );
521 #endif
522
523                                 return 1;
524
525                         } else {
526                                 default_passwd_hash = ch_strdup( cargv[1] );
527                         }
528
529                 } else if ( strcasecmp( cargv[0], "password-crypt-salt-format" ) == 0 ) 
530                 {
531                         if ( cargc < 2 ) {
532 #ifdef NEW_LOGGING
533                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
534                                         "%s: line %d: missing format in "
535                                         "\"password-crypt-salt-format <format>\" line\n",
536                                         fname, lineno ));
537 #else
538                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: missing format in "
539                                         "\"password-crypt-salt-format <format>\" line\n",
540                                     fname, lineno, 0 );
541 #endif
542
543                                 return 1;
544                         }
545
546                         lutil_salt_format( cargv[1] );
547
548                 /* set SASL host */
549                 } else if ( strcasecmp( cargv[0], "sasl-host" ) == 0 ) {
550                         if ( cargc < 2 ) {
551 #ifdef NEW_LOGGING
552                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
553                                            "%s: line %d: missing host in \"sasl-host <host>\" line\n",
554                                            fname, lineno ));
555 #else
556                                 Debug( LDAP_DEBUG_ANY,
557             "%s: line %d: missing host in \"sasl-host <host>\" line\n",
558                                     fname, lineno, 0 );
559 #endif
560
561                                 return( 1 );
562                         }
563
564                         if ( global_host != NULL ) {
565 #ifdef NEW_LOGGING
566                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
567                                            "%s: line %d: already set sasl-host!\n",
568                                            fname, lineno ));
569 #else
570                                 Debug( LDAP_DEBUG_ANY,
571                                         "%s: line %d: already set sasl-host!\n",
572                                         fname, lineno, 0 );
573 #endif
574
575                                 return 1;
576
577                         } else {
578                                 global_host = ch_strdup( cargv[1] );
579                         }
580
581                 /* set SASL realm */
582                 } else if ( strcasecmp( cargv[0], "sasl-realm" ) == 0 ) {
583                         if ( cargc < 2 ) {
584 #ifdef NEW_LOGGING
585                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
586                                            "%s: line %d: missing realm in \"sasl-realm <realm>\" line.\n",
587                                            fname, lineno ));
588 #else
589                                 Debug( LDAP_DEBUG_ANY,
590             "%s: line %d: missing realm in \"sasl-realm <realm>\" line\n",
591                                     fname, lineno, 0 );
592 #endif
593
594                                 return( 1 );
595                         }
596
597                         if ( global_realm != NULL ) {
598 #ifdef NEW_LOGGING
599                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
600                                            "%s: line %d: already set sasl-realm!\n",
601                                            fname, lineno ));
602 #else
603                                 Debug( LDAP_DEBUG_ANY,
604                                         "%s: line %d: already set sasl-realm!\n",
605                                         fname, lineno, 0 );
606 #endif
607
608                                 return 1;
609
610                         } else {
611                                 global_realm = ch_strdup( cargv[1] );
612                         }
613
614                 } else if ( !strcasecmp( cargv[0], "sasl-regexp" ) 
615                         || !strcasecmp( cargv[0], "saslregexp" ) )
616                 {
617                         int rc;
618                         if ( cargc != 3 ) {
619 #ifdef NEW_LOGGING
620                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
621                                            "%s: line %d: need 2 args in "
622                                            "\"saslregexp <match> <replace>\"\n",
623                                            fname, lineno ));
624 #else
625                                 Debug( LDAP_DEBUG_ANY, 
626                                 "%s: line %d: need 2 args in \"saslregexp <match> <replace>\"\n",
627                                     fname, lineno, 0 );
628 #endif
629
630                                 return( 1 );
631                         }
632                         rc = slap_sasl_regexp_config( cargv[1], cargv[2] );
633                         if ( rc ) {
634                                 return rc;
635                         }
636
637                 /* SASL security properties */
638                 } else if ( strcasecmp( cargv[0], "sasl-secprops" ) == 0 ) {
639                         char *txt;
640
641                         if ( cargc < 2 ) {
642 #ifdef NEW_LOGGING
643                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
644                                            "%s: line %d: missing flags in "
645                                            "\"sasl-secprops <properties>\" line\n",
646                                            fname, lineno ));
647 #else
648                                 Debug( LDAP_DEBUG_ANY,
649             "%s: line %d: missing flags in \"sasl-secprops <properties>\" line\n",
650                                     fname, lineno, 0 );
651 #endif
652
653                                 return 1;
654                         }
655
656                         txt = slap_sasl_secprops( cargv[1] );
657                         if ( txt != NULL ) {
658 #ifdef NEW_LOGGING
659                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
660                                            "%s: line %d sas-secprops: %s\n",
661                                            fname, lineno, txt ));
662 #else
663                                 Debug( LDAP_DEBUG_ANY,
664             "%s: line %d: sasl-secprops: %s\n",
665                                     fname, lineno, txt );
666 #endif
667
668                                 return 1;
669                         }
670
671                 } else if ( strcasecmp( cargv[0], "sasl-external-x509dn-convert" ) == 0 ) {
672                         sasl_external_x509dn_convert++;
673
674                 /* set UCDATA path */
675                 } else if ( strcasecmp( cargv[0], "ucdata-path" ) == 0 ) {
676                         int err;
677                         if ( cargc < 2 ) {
678 #ifdef NEW_LOGGING
679                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
680                                            "%s: line %d: missing path in "
681                                            "\"ucdata-path <path>\" line.\n",
682                                            fname, lineno ));
683 #else
684                                 Debug( LDAP_DEBUG_ANY,
685             "%s: line %d: missing path in \"ucdata-path <path>\" line\n",
686                                     fname, lineno, 0 );
687 #endif
688
689                                 return( 1 );
690                         }
691
692                         err = load_ucdata( cargv[1] );
693                         if ( err <= 0 ) {
694                                 if ( err == 0 ) {
695 #ifdef NEW_LOGGING
696                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
697                                                    "%s: line %d: ucdata already loaded, ucdata-path "
698                                                    "must be set earlier in the file and/or be "
699                                                    "specified only once!\n",
700                                                    fname, lineno ));
701 #else
702                                         Debug( LDAP_DEBUG_ANY,
703                                                "%s: line %d: ucdata already loaded, ucdata-path must be set earlier in the file and/or be specified only once!\n",
704                                                fname, lineno, 0 );
705 #endif
706
707                                 }
708                                 return( 1 );
709                         }
710
711                 /* set size limit */
712                 } else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
713                         int rc = 0, i;
714                         struct slap_limits_set *lim;
715                         
716                         if ( cargc < 2 ) {
717 #ifdef NEW_LOGGING
718                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
719                                            "%s: line %d: missing limit in \"sizelimit <limit>\" line.\n",
720                                            fname, lineno ));
721 #else
722                                 Debug( LDAP_DEBUG_ANY,
723             "%s: line %d: missing limit in \"sizelimit <limit>\" line\n",
724                                     fname, lineno, 0 );
725 #endif
726
727                                 return( 1 );
728                         }
729
730                         if ( be == NULL ) {
731                                 lim = &deflimit;
732                         } else {
733                                 lim = &be->be_def_limit;
734                         }
735
736                         for ( i = 1; i < cargc; i++ ) {
737                                 if ( strncasecmp( cargv[i], "size", 4 ) == 0 ) {
738                                         rc = parse_limit( cargv[i], lim );
739                                 } else {
740                                         lim->lms_s_soft = atoi( cargv[i] );
741                                         lim->lms_s_hard = 0;
742                                 }
743
744                                 if ( rc ) {
745 #ifdef NEW_LOGGING
746                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
747                                                    "%s: line %d: unable "
748                                                    "to parse value \"%s\" "
749                                                    "in \"sizelimit "
750                                                    "<limit>\" line.\n",
751                                                    fname, lineno, cargv[i] ));
752 #else
753                                         Debug( LDAP_DEBUG_ANY,
754                                                 "%s: line %d: unable "
755                                                 "to parse value \"%s\" "
756                                                 "in \"sizelimit "
757                                                 "<limit>\" line\n",
758                                                 fname, lineno, cargv[i] );
759 #endif
760                                 }
761                         }
762
763                 /* set time limit */
764                 } else if ( strcasecmp( cargv[0], "timelimit" ) == 0 ) {
765                         int rc = 0, i;
766                         struct slap_limits_set *lim;
767                         
768                         if ( cargc < 2 ) {
769 #ifdef NEW_LOGGING
770                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
771                                            "%s: line %d missing limit in \"timelimit <limit>\" line.\n",
772                                            fname, lineno ));
773 #else
774                                 Debug( LDAP_DEBUG_ANY,
775             "%s: line %d: missing limit in \"timelimit <limit>\" line\n",
776                                     fname, lineno, 0 );
777 #endif
778
779                                 return( 1 );
780                         }
781                         
782                         if ( be == NULL ) {
783                                 lim = &deflimit;
784                         } else {
785                                 lim = &be->be_def_limit;
786                         }
787
788                         for ( i = 1; i < cargc; i++ ) {
789                                 if ( strncasecmp( cargv[i], "time", 4 ) == 0 ) {
790                                         rc = parse_limit( cargv[i], lim );
791                                 } else {
792                                         lim->lms_t_soft = atoi( cargv[i] );
793                                         lim->lms_t_hard = 0;
794                                 }
795
796                                 if ( rc ) {
797 #ifdef NEW_LOGGING
798                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
799                                                    "%s: line %d: unable "
800                                                    "to parse value \"%s\" "
801                                                    "in \"timelimit "
802                                                    "<limit>\" line.\n",
803                                                    fname, lineno, cargv[i] ));
804 #else
805                                         Debug( LDAP_DEBUG_ANY,
806                                                 "%s: line %d: unable "
807                                                 "to parse value \"%s\" "
808                                                 "in \"timelimit "
809                                                 "<limit>\" line\n",
810                                                 fname, lineno, cargv[i] );
811 #endif
812                                 }
813                         }
814
815                 /* set regex-based limits */
816                 } else if ( strcasecmp( cargv[0], "limits" ) == 0 ) {
817                         if ( be == NULL ) {
818 #ifdef NEW_LOGGING
819                                 LDAP_LOG(( "config", LDAP_LEVEL_WARNING,
820                                            "%s: line %d \"limits\" allowed only in database environment.\n",
821                                            fname, lineno ));
822 #else
823                                 Debug( LDAP_DEBUG_ANY,
824         "%s: line %d \"limits\" allowed only in database environment.\n%s",
825                                         fname, lineno, "" );
826 #endif
827                                 return( 1 );
828                         }
829
830                         if ( parse_limits( be, fname, lineno, cargc, cargv ) ) {
831                                 return( 1 );
832                         }
833
834                 /* mark this as a subordinate database */
835                 } else if ( strcasecmp( cargv[0], "subordinate" ) == 0 ) {
836                         if ( be == NULL ) {
837 #ifdef NEW_LOGGING
838                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
839                                         "subordinate keyword must appear inside a database "
840                                         "definition (ignored).\n", fname, lineno ));
841 #else
842                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix line "
843                                         "must appear inside a database definition (ignored)\n",
844                                     fname, lineno, 0 );
845 #endif
846                         } else {
847                                 be->be_flags |= SLAP_BFLAG_GLUE_SUBORDINATE;
848                                 num_subordinates++;
849                         }
850
851                 /* set database suffix */
852                 } else if ( strcasecmp( cargv[0], "suffix" ) == 0 ) {
853                         Backend *tmp_be;
854                         struct berval dn;
855                         struct berval *pdn = NULL;
856                         struct berval *ndn = NULL;
857
858                         if ( cargc < 2 ) {
859 #ifdef NEW_LOGGING
860                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
861                                         "%s: line %d: missing dn in \"suffix <dn>\" line.\n",
862                                         fname, lineno ));
863 #else
864                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
865                                         "missing dn in \"suffix <dn>\" line\n",
866                                     fname, lineno, 0 );
867 #endif
868
869                                 return( 1 );
870
871                         } else if ( cargc > 2 ) {
872 #ifdef NEW_LOGGING
873                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
874                                         "%s: line %d: extra cruft after <dn> in \"suffix %s\""
875                                         " line (ignored).\n", fname, lineno, cargv[1] ));
876 #else
877                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: extra cruft "
878                                         "after <dn> in \"suffix %s\" line (ignored)\n",
879                                     fname, lineno, cargv[1] );
880 #endif
881                         }
882
883                         if ( be == NULL ) {
884 #ifdef NEW_LOGGING
885                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
886                                         "%s: line %d: suffix line must appear inside a database "
887                                         "definition.\n", fname, lineno ));
888 #else
889                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix line "
890                                         "must appear inside a database definition\n",
891                                     fname, lineno, 0 );
892 #endif
893                                 return( 1 );
894
895 #if defined(SLAPD_MONITOR_DN)
896                         /* "cn=Monitor" is reserved for monitoring slap */
897                         } else if ( strcasecmp( cargv[1], SLAPD_MONITOR_DN ) == 0 ) {
898 #ifdef NEW_LOGGING
899                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: \""
900                                         SLAPD_MONITOR_DN "\" is reserved for monitoring slapd\n", 
901                                         fname, lineno ));
902 #else
903                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: \""
904                                         SLAPD_MONITOR_DN "\" is reserved for monitoring slapd\n", 
905                                         fname, lineno, 0 );
906 #endif
907                                 return( 1 );
908 #endif /* SLAPD_MONITOR_DN */
909                         }
910
911                         if ( load_ucdata( NULL ) < 0 ) return 1;
912
913                         dn.bv_val = cargv[1];
914                         dn.bv_len = strlen( cargv[1] );
915                         pdn = ch_malloc( sizeof( struct berval ));
916                         ndn = ch_malloc( sizeof( struct berval ));
917
918                         rc = dnPrettyNormal( NULL, &dn, pdn, ndn );
919                         if( rc != LDAP_SUCCESS ) {
920 #ifdef NEW_LOGGING
921                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
922                                         "%s: line %d: suffix DN is invalid.\n",
923                                         fname, lineno ));
924 #else
925                                 Debug( LDAP_DEBUG_ANY,
926                                         "%s: line %d: suffix DN is invalid\n",
927                                    fname, lineno, 0 );
928 #endif
929                                 return( 1 );
930                         }
931
932                         tmp_be = select_backend( ndn, 0, 0 );
933                         if ( tmp_be == be ) {
934 #ifdef NEW_LOGGING
935                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
936                                         "%s: line %d: suffix already served by this backend "
937                                         "(ignored)\n", fname, lineno ));
938 #else
939                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix "
940                                         "already served by this backend (ignored)\n",
941                                     fname, lineno, 0 );
942 #endif
943                                 ber_bvfree( pdn );
944                                 ber_bvfree( ndn );
945
946                         } else if ( tmp_be  != NULL ) {
947 #ifdef NEW_LOGGING
948                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
949                                         "%s: line %d: suffix already served by a preceding "
950                                         "backend \"%s\"\n", fname, lineno,
951                                         tmp_be->be_suffix[0]->bv_val ));
952 #else
953                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix "
954                                         "already served by a preceeding backend \"%s\"\n",
955                                     fname, lineno, tmp_be->be_suffix[0]->bv_val );
956 #endif
957                                 ber_bvfree( pdn );
958                                 ber_bvfree( ndn );
959                                 return( 1 );
960
961                         } else if( pdn->bv_len == 0 && default_search_nbase.bv_len ) {
962 #ifdef NEW_LOGGING
963                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
964                                                 "%s: line %d: suffix DN empty and default search "
965                                                 "base provided \"%s\" (assuming okay).\n",
966                                                 fname, lineno, default_search_base.bv_val ));
967 #else
968                                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
969                                                 "suffix DN empty and default "
970                                                 "search base provided \"%s\" (assuming okay)\n",
971                                         fname, lineno, default_search_base.bv_val );
972 #endif
973                         }
974
975                         ber_bvecadd( &be->be_suffix, pdn );
976                         ber_bvecadd( &be->be_nsuffix, ndn );
977
978                 /* set database suffixAlias */
979                 } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) {
980                         Backend *tmp_be;
981                         struct berval alias, *palias, nalias;
982                         struct berval aliased, *paliased, naliased;
983
984                         if ( cargc < 2 ) {
985 #ifdef NEW_LOGGING
986                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
987                                         "%s: line %d: missing alias and aliased_dn in "
988                                         "\"suffixAlias <alias> <aliased_dn>\" line.\n",
989                                         fname, lineno ));
990 #else
991                                 Debug( LDAP_DEBUG_ANY,
992                                         "%s: line %d: missing alias and aliased_dn in "
993                                         "\"suffixAlias <alias> <aliased_dn>\" line.\n",
994                                         fname, lineno, 0 );
995 #endif
996
997                                 return( 1 );
998                         } else if ( cargc < 3 ) {
999 #ifdef NEW_LOGGING
1000                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1001                                         "%s: line %d: missing aliased_dn in "
1002                                         "\"suffixAlias <alias> <aliased_dn>\" line\n",
1003                                         fname, lineno ));
1004 #else
1005                                 Debug( LDAP_DEBUG_ANY,
1006                                         "%s: line %d: missing aliased_dn in "
1007                                         "\"suffixAlias <alias> <aliased_dn>\" line\n",
1008                                         fname, lineno, 0 );
1009 #endif
1010
1011                                 return( 1 );
1012                         } else if ( cargc > 3 ) {
1013 #ifdef NEW_LOGGING
1014                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1015                                         "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
1016                                         fname, lineno ));
1017 #else
1018                                 Debug( LDAP_DEBUG_ANY,
1019                                         "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
1020                                         fname, lineno, 0 );
1021 #endif
1022
1023                         }
1024
1025                         if ( be == NULL ) {
1026 #ifdef NEW_LOGGING
1027                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1028                                         "%s: line %d: suffixAlias line must appear inside a "
1029                                         "database definition (ignored).\n", fname, lineno ));
1030 #else
1031                                 Debug( LDAP_DEBUG_ANY,
1032                                         "%s: line %d: suffixAlias line"
1033                                         " must appear inside a database definition (ignored)\n",
1034                                         fname, lineno, 0 );
1035 #endif
1036                         }
1037
1038                         if ( load_ucdata( NULL ) < 0 ) return 1;
1039                         
1040                         alias.bv_val = cargv[1];
1041                         alias.bv_len = strlen( cargv[1] );
1042                         palias = ch_malloc(sizeof(struct berval));
1043
1044                         rc = dnPrettyNormal( NULL, &alias, palias, &nalias );
1045                         if( rc != LDAP_SUCCESS ) {
1046 #ifdef NEW_LOGGING
1047                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1048                                         "%s: line %d: alias DN is invalid.\n",
1049                                         fname, lineno ));
1050 #else
1051                                 Debug( LDAP_DEBUG_ANY,
1052                                         "%s: line %d: alias DN is invalid\n",
1053                                    fname, lineno, 0 );
1054 #endif
1055                                 return( 1 );
1056                         }
1057
1058                         tmp_be = select_backend( &nalias, 0, 0 );
1059                         free( nalias.bv_val );
1060                         if ( tmp_be && tmp_be != be ) {
1061 #ifdef NEW_LOGGING
1062                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1063                                         "%s: line %d: suffixAlias served by a preceeding "
1064                                         "backend \"%s\"\n",
1065                                         fname, lineno, tmp_be->be_suffix[0]->bv_val ));
1066 #else
1067                                 Debug( LDAP_DEBUG_ANY,
1068                                         "%s: line %d: suffixAlias served by"
1069                                         "  a preceeding backend \"%s\"\n",
1070                                         fname, lineno, tmp_be->be_suffix[0]->bv_val );
1071 #endif
1072                                 ber_bvfree( palias );
1073                                 return -1;
1074                         }
1075
1076                         aliased.bv_val = cargv[2];
1077                         aliased.bv_len = strlen( cargv[2] );
1078                         paliased = ch_malloc(sizeof(struct berval));
1079
1080                         rc = dnPrettyNormal( NULL, &aliased, paliased, &naliased );
1081                         if( rc != LDAP_SUCCESS ) {
1082 #ifdef NEW_LOGGING
1083                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1084                                         "%s: line %d: aliased DN is invalid.\n",
1085                                         fname, lineno ));
1086 #else
1087                                 Debug( LDAP_DEBUG_ANY,
1088                                         "%s: line %d: aliased DN is invalid\n",
1089                                    fname, lineno, 0 );
1090 #endif
1091                                 ber_bvfree( palias );
1092                                 return( 1 );
1093                         }
1094
1095                         tmp_be = select_backend( &naliased, 0, 0 );
1096                         free( naliased.bv_val );
1097                         if ( tmp_be && tmp_be != be ) {
1098 #ifdef NEW_LOGGING
1099                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1100                                         "%s: line %d: suffixAlias derefs to a different backend "
1101                                         "a preceeding backend \"%s\"\n",
1102                                         fname, lineno, tmp_be->be_suffix[0]->bv_val ));
1103 #else
1104                                 Debug( LDAP_DEBUG_ANY,
1105                                         "%s: line %d: suffixAlias derefs to differnet backend"
1106                                         "  a preceeding backend \"%s\"\n",
1107                                         fname, lineno, tmp_be->be_suffix[0]->bv_val );
1108 #endif
1109                                 ber_bvfree( palias );
1110                                 ber_bvfree( paliased );
1111                                 return -1;
1112                         }
1113
1114                         ber_bvecadd( &be->be_suffixAlias, palias ); 
1115                         ber_bvecadd( &be->be_suffixAlias, paliased );
1116
1117                /* set max deref depth */
1118                } else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
1119                                         int i;
1120                        if ( cargc < 2 ) {
1121 #ifdef NEW_LOGGING
1122                                LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1123                                           "%s: line %d: missing depth in \"maxDerefDepth <depth>\""
1124                                           " line\n", fname, lineno ));
1125 #else
1126                                Debug( LDAP_DEBUG_ANY,
1127                    "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
1128                                    fname, lineno, 0 );
1129 #endif
1130
1131                                return( 1 );
1132                        }
1133                        if ( be == NULL ) {
1134 #ifdef NEW_LOGGING
1135                                LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1136                                           "%s: line %d: depth line must appear inside a database "
1137                                           "definition (ignored)\n", fname, lineno ));
1138 #else
1139                                Debug( LDAP_DEBUG_ANY,
1140 "%s: line %d: depth line must appear inside a database definition (ignored)\n",
1141                                    fname, lineno, 0 );
1142 #endif
1143
1144                        } else if ((i = atoi(cargv[1])) < 0) {
1145 #ifdef NEW_LOGGING
1146                                LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1147                                           "%s: line %d: depth must be positive (ignored).\n",
1148                                           fname, lineno ));
1149 #else
1150                                Debug( LDAP_DEBUG_ANY,
1151 "%s: line %d: depth must be positive (ignored)\n",
1152                                    fname, lineno, 0 );
1153 #endif
1154
1155
1156                        } else {
1157                            be->be_max_deref_depth = i;
1158                                            }
1159
1160
1161                 /* set magic "root" dn for this database */
1162                 } else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) {
1163                         if ( cargc < 2 ) {
1164 #ifdef NEW_LOGGING
1165                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1166                                            "%s: line %d: missing dn in \"rootdn <dn>\" line.\n",
1167                                            fname, lineno ));
1168 #else
1169                                 Debug( LDAP_DEBUG_ANY,
1170                     "%s: line %d: missing dn in \"rootdn <dn>\" line\n",
1171                                     fname, lineno, 0 );
1172 #endif
1173
1174                                 return( 1 );
1175                         }
1176                         if ( be == NULL ) {
1177 #ifdef NEW_LOGGING
1178                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1179                                            "%s: line %d: rootdn line must appear inside a database "
1180                                            "definition (ignored).\n", fname, lineno ));
1181 #else
1182                                 Debug( LDAP_DEBUG_ANY,
1183 "%s: line %d: rootdn line must appear inside a database definition (ignored)\n",
1184                                     fname, lineno, 0 );
1185 #endif
1186
1187                         } else {
1188                                 struct berval dn;
1189                                 
1190                                 if ( load_ucdata( NULL ) < 0 ) return 1;
1191
1192                                 dn.bv_val = cargv[1];
1193                                 dn.bv_len = strlen( cargv[1] );
1194
1195                                 rc = dnPrettyNormal( NULL, &dn,
1196                                         &be->be_rootdn,
1197                                         &be->be_rootndn );
1198
1199                                 if( rc != LDAP_SUCCESS ) {
1200 #ifdef NEW_LOGGING
1201                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1202                                                 "%s: line %d: rootdn DN is invalid.\n",
1203                                                 fname, lineno ));
1204 #else
1205                                         Debug( LDAP_DEBUG_ANY,
1206                                                 "%s: line %d: rootdn DN is invalid\n",
1207                                            fname, lineno, 0 );
1208 #endif
1209                                         return( 1 );
1210                                 }
1211                         }
1212
1213                 /* set super-secret magic database password */
1214                 } else if ( strcasecmp( cargv[0], "rootpw" ) == 0 ) {
1215                         if ( cargc < 2 ) {
1216 #ifdef NEW_LOGGING
1217                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1218                                            "%s: line %d: missing passwd in \"rootpw <passwd>\""
1219                                            " line\n", fname, lineno ));
1220 #else
1221                                 Debug( LDAP_DEBUG_ANY,
1222             "%s: line %d: missing passwd in \"rootpw <passwd>\" line\n",
1223                                     fname, lineno, 0 );
1224 #endif
1225
1226                                 return( 1 );
1227                         }
1228                         if ( be == NULL ) {
1229 #ifdef NEW_LOGGING
1230                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1231                                            "%s: line %d: rootpw line must appear inside a database "
1232                                            "definition (ignored)\n", fname, lineno ));
1233 #else
1234                                 Debug( LDAP_DEBUG_ANY,
1235 "%s: line %d: rootpw line must appear inside a database definition (ignored)\n",
1236                                     fname, lineno, 0 );
1237 #endif
1238
1239                         } else {
1240                                 be->be_rootpw.bv_val = ch_strdup( cargv[1] );
1241                                 be->be_rootpw.bv_len = strlen( be->be_rootpw.bv_val );
1242                         }
1243
1244                 /* make this database read-only */
1245                 } else if ( strcasecmp( cargv[0], "readonly" ) == 0 ) {
1246                         if ( cargc < 2 ) {
1247 #ifdef NEW_LOGGING
1248                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1249                                            "%s: line %d: missing on|off in \"readonly <on|off>\" line.\n",
1250                                            fname, lineno ));
1251 #else
1252                                 Debug( LDAP_DEBUG_ANY,
1253             "%s: line %d: missing on|off in \"readonly <on|off>\" line\n",
1254                                     fname, lineno, 0 );
1255 #endif
1256
1257                                 return( 1 );
1258                         }
1259                         if ( be == NULL ) {
1260                                 if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1261                                         global_restrictops |= SLAP_RESTRICT_OP_WRITES;
1262                                 } else {
1263                                         global_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
1264                                 }
1265                         } else {
1266                                 if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1267                                         be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
1268                                 } else {
1269                                         be->be_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
1270                                 }
1271                         }
1272
1273
1274                 /* allow these features */
1275                 } else if ( strcasecmp( cargv[0], "allows" ) == 0 ||
1276                         strcasecmp( cargv[0], "allow" ) == 0 )
1277                 {
1278                         slap_mask_t     allows;
1279
1280                         if ( be != NULL ) {
1281 #ifdef NEW_LOGGING
1282                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1283                                            "%s: line %d: allow line must appear prior to "
1284                                            "database definitions.\n", fname, lineno ));
1285 #else
1286                                 Debug( LDAP_DEBUG_ANY,
1287 "%s: line %d: allow line must appear prior to database definitions\n",
1288                                     fname, lineno, 0 );
1289 #endif
1290
1291                         }
1292
1293                         if ( cargc < 2 ) {
1294 #ifdef NEW_LOGGING
1295                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1296                                            "%s: line %d: missing feature(s) in \"allow <features>\""
1297                                            " line\n", fname, lineno ));
1298 #else
1299                                 Debug( LDAP_DEBUG_ANY,
1300             "%s: line %d: missing feature(s) in \"allow <features>\" line\n",
1301                                     fname, lineno, 0 );
1302 #endif
1303
1304                                 return( 1 );
1305                         }
1306
1307                         allows = 0;
1308
1309                         for( i=1; i < cargc; i++ ) {
1310                                 if( strcasecmp( cargv[i], "bind_v2" ) == 0 ) {
1311                                         allows |= SLAP_ALLOW_BIND_V2;
1312
1313                                 } else if( strcasecmp( cargv[i], "bind_anon_cred" ) == 0 ) {
1314                                         allows |= SLAP_ALLOW_BIND_ANON_CRED;
1315
1316                                 } else if( strcasecmp( cargv[i], "bind_anon_dn" ) == 0 ) {
1317                                         allows |= SLAP_ALLOW_BIND_ANON_DN;
1318
1319                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1320 #ifdef NEW_LOGGING
1321                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1322                                                    "%s: line %d: unknown feature %s in "
1323                                                    "\"allow <features>\" line.\n",
1324                                                    fname, lineno, cargv[1] ));
1325 #else
1326                                         Debug( LDAP_DEBUG_ANY,
1327                     "%s: line %d: unknown feature %s in \"allow <features>\" line\n",
1328                                             fname, lineno, cargv[i] );
1329 #endif
1330
1331                                         return( 1 );
1332                                 }
1333                         }
1334
1335                         global_allows = allows;
1336
1337                 /* disallow these features */
1338                 } else if ( strcasecmp( cargv[0], "disallows" ) == 0 ||
1339                         strcasecmp( cargv[0], "disallow" ) == 0 )
1340                 {
1341                         slap_mask_t     disallows;
1342
1343                         if ( be != NULL ) {
1344 #ifdef NEW_LOGGING
1345                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1346                                            "%s: line %d: disallow line must appear prior to "
1347                                            "database definitions.\n", fname, lineno ));
1348 #else
1349                                 Debug( LDAP_DEBUG_ANY,
1350 "%s: line %d: disallow line must appear prior to database definitions\n",
1351                                     fname, lineno, 0 );
1352 #endif
1353
1354                         }
1355
1356                         if ( cargc < 2 ) {
1357 #ifdef NEW_LOGGING
1358                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1359                                            "%s: line %d: missing feature(s) in \"disallow <features>\""
1360                                            " line.\n", fname, lineno ));
1361 #else
1362                                 Debug( LDAP_DEBUG_ANY,
1363             "%s: line %d: missing feature(s) in \"disallow <features>\" line\n",
1364                                     fname, lineno, 0 );
1365 #endif
1366
1367                                 return( 1 );
1368                         }
1369
1370                         disallows = 0;
1371
1372                         for( i=1; i < cargc; i++ ) {
1373                                 if( strcasecmp( cargv[i], "bind_anon" ) == 0 ) {
1374                                         disallows |= SLAP_DISALLOW_BIND_ANON;
1375
1376                                 } else if( strcasecmp( cargv[i], "bind_simple" ) == 0 ) {
1377                                         disallows |= SLAP_DISALLOW_BIND_SIMPLE;
1378
1379                                 } else if( strcasecmp( cargv[i], "bind_krbv4" ) == 0 ) {
1380                                         disallows |= SLAP_DISALLOW_BIND_KRBV4;
1381
1382                                 } else if( strcasecmp( cargv[i], "tls_2_anon" ) == 0 ) {
1383                                         disallows |= SLAP_DISALLOW_TLS_2_ANON;
1384
1385                                 } else if( strcasecmp( cargv[i], "tls_authc" ) == 0 ) {
1386                                         disallows |= SLAP_DISALLOW_TLS_AUTHC;
1387
1388                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1389 #ifdef NEW_LOGGING
1390                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1391                                                 "%s: line %d: unknown feature %s in "
1392                                                 "\"disallow <features>\" line.\n",
1393                                                 fname, lineno, cargv[i] ));
1394 #else
1395                                         Debug( LDAP_DEBUG_ANY,
1396                     "%s: line %d: unknown feature %s in \"disallow <features>\" line\n",
1397                                             fname, lineno, cargv[i] );
1398 #endif
1399
1400                                         return( 1 );
1401                                 }
1402                         }
1403
1404                         global_disallows = disallows;
1405
1406                 /* require these features */
1407                 } else if ( strcasecmp( cargv[0], "requires" ) == 0 ||
1408                         strcasecmp( cargv[0], "require" ) == 0 )
1409                 {
1410                         slap_mask_t     requires;
1411
1412                         if ( cargc < 2 ) {
1413 #ifdef NEW_LOGGING
1414                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1415                                            "%s: line %d: missing feature(s) in "
1416                                            "\"require <features>\" line.\n", fname, lineno ));
1417 #else
1418                                 Debug( LDAP_DEBUG_ANY,
1419             "%s: line %d: missing feature(s) in \"require <features>\" line\n",
1420                                     fname, lineno, 0 );
1421 #endif
1422
1423                                 return( 1 );
1424                         }
1425
1426                         requires = 0;
1427
1428                         for( i=1; i < cargc; i++ ) {
1429                                 if( strcasecmp( cargv[i], "bind" ) == 0 ) {
1430                                         requires |= SLAP_REQUIRE_BIND;
1431
1432                                 } else if( strcasecmp( cargv[i], "LDAPv3" ) == 0 ) {
1433                                         requires |= SLAP_REQUIRE_LDAP_V3;
1434
1435                                 } else if( strcasecmp( cargv[i], "authc" ) == 0 ) {
1436                                         requires |= SLAP_REQUIRE_AUTHC;
1437
1438                                 } else if( strcasecmp( cargv[i], "SASL" ) == 0 ) {
1439                                         requires |= SLAP_REQUIRE_SASL;
1440
1441                                 } else if( strcasecmp( cargv[i], "strong" ) == 0 ) {
1442                                         requires |= SLAP_REQUIRE_STRONG;
1443
1444                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1445 #ifdef NEW_LOGGING
1446                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1447                                                    "%s: line %d: unknown feature %s in "
1448                                                    "\"require <features>\" line.\n",
1449                                                    fname, lineno ));
1450 #else
1451                                         Debug( LDAP_DEBUG_ANY,
1452                     "%s: line %d: unknown feature %s in \"require <features>\" line\n",
1453                                             fname, lineno, cargv[i] );
1454 #endif
1455
1456                                         return( 1 );
1457                                 }
1458                         }
1459
1460                         if ( be == NULL ) {
1461                                 global_requires = requires;
1462                         } else {
1463                                 be->be_requires = requires;
1464                         }
1465
1466                 /* required security factors */
1467                 } else if ( strcasecmp( cargv[0], "security" ) == 0 ) {
1468                         slap_ssf_set_t *set;
1469
1470                         if ( cargc < 2 ) {
1471 #ifdef NEW_LOGGING
1472                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1473                                            "%s: line %d: missing factor(s) in \"security <factors>\""
1474                                            " line.\n", fname, lineno ));
1475 #else
1476                                 Debug( LDAP_DEBUG_ANY,
1477             "%s: line %d: missing factor(s) in \"security <factors>\" line\n",
1478                                     fname, lineno, 0 );
1479 #endif
1480
1481                                 return( 1 );
1482                         }
1483
1484                         if ( be == NULL ) {
1485                                 set = &global_ssf_set;
1486                         } else {
1487                                 set = &be->be_ssf_set;
1488                         }
1489
1490                         for( i=1; i < cargc; i++ ) {
1491                                 if( strncasecmp( cargv[i], "ssf=",
1492                                         sizeof("ssf") ) == 0 )
1493                                 {
1494                                         set->sss_ssf =
1495                                                 atoi( &cargv[i][sizeof("ssf")] );
1496
1497                                 } else if( strncasecmp( cargv[i], "transport=",
1498                                         sizeof("transport") ) == 0 )
1499                                 {
1500                                         set->sss_transport =
1501                                                 atoi( &cargv[i][sizeof("transport")] );
1502
1503                                 } else if( strncasecmp( cargv[i], "tls=",
1504                                         sizeof("tls") ) == 0 )
1505                                 {
1506                                         set->sss_tls =
1507                                                 atoi( &cargv[i][sizeof("tls")] );
1508
1509                                 } else if( strncasecmp( cargv[i], "sasl=",
1510                                         sizeof("sasl") ) == 0 )
1511                                 {
1512                                         set->sss_sasl =
1513                                                 atoi( &cargv[i][sizeof("sasl")] );
1514
1515                                 } else if( strncasecmp( cargv[i], "update_ssf=",
1516                                         sizeof("update_ssf") ) == 0 )
1517                                 {
1518                                         set->sss_update_ssf =
1519                                                 atoi( &cargv[i][sizeof("update_ssf")] );
1520
1521                                 } else if( strncasecmp( cargv[i], "update_transport=",
1522                                         sizeof("update_transport") ) == 0 )
1523                                 {
1524                                         set->sss_update_transport =
1525                                                 atoi( &cargv[i][sizeof("update_transport")] );
1526
1527                                 } else if( strncasecmp( cargv[i], "update_tls=",
1528                                         sizeof("update_tls") ) == 0 )
1529                                 {
1530                                         set->sss_update_tls =
1531                                                 atoi( &cargv[i][sizeof("update_tls")] );
1532
1533                                 } else if( strncasecmp( cargv[i], "update_sasl=",
1534                                         sizeof("update_sasl") ) == 0 )
1535                                 {
1536                                         set->sss_update_sasl =
1537                                                 atoi( &cargv[i][sizeof("update_sasl")] );
1538
1539                                 } else {
1540 #ifdef NEW_LOGGING
1541                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1542                                                    "%s: line %d: unknown factor %S in "
1543                                                    "\"security <factors>\" line.\n",
1544                                                    fname, lineno, cargv[1] ));
1545 #else
1546                                         Debug( LDAP_DEBUG_ANY,
1547                     "%s: line %d: unknown factor %s in \"security <factors>\" line\n",
1548                                             fname, lineno, cargv[i] );
1549 #endif
1550
1551                                         return( 1 );
1552                                 }
1553                         }
1554                 /* where to send clients when we don't hold it */
1555                 } else if ( strcasecmp( cargv[0], "referral" ) == 0 ) {
1556                         if ( cargc < 2 ) {
1557 #ifdef NEW_LOGGING
1558                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1559                                            "%s: line %d: missing URL in \"referral <URL>\""
1560                                            " line.\n", fname, lineno ));
1561 #else
1562                                 Debug( LDAP_DEBUG_ANY,
1563                     "%s: line %d: missing URL in \"referral <URL>\" line\n",
1564                                     fname, lineno, 0 );
1565 #endif
1566
1567                                 return( 1 );
1568                         }
1569
1570                         if( validate_global_referral( cargv[1] ) ) {
1571 #ifdef NEW_LOGGING
1572                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1573                                         "invalid URL (%s) in \"referral\" line.\n",
1574                                         fname, lineno, cargv[1] ));
1575 #else
1576                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1577                                         "invalid URL (%s) in \"referral\" line.\n",
1578                                     fname, lineno, cargv[1] );
1579 #endif
1580                                 return 1;
1581                         }
1582
1583                         vals[0].bv_val = cargv[1];
1584                         vals[0].bv_len = strlen( vals[0].bv_val );
1585                         value_add( &default_referral, vals );
1586
1587 #ifdef NEW_LOGGING
1588                 } else if ( strcasecmp( cargv[0], "logfile" ) == 0 ) {
1589                         FILE *logfile;
1590                         if ( cargc < 2 ) {
1591 #ifdef NEW_LOGGING
1592                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1593                                            "%s: line %d: Error in logfile directive, "
1594                                            "\"logfile <filename>\"\n", fname, lineno ));
1595 #else
1596                                 Debug( LDAP_DEBUG_ANY,
1597                                        "%s: line %d: Error in logfile directive, \"logfile filename\"\n",
1598                                        fname, lineno, 0 );
1599 #endif
1600
1601                                 return( 1 );
1602                         }
1603                         logfile = fopen( cargv[1], "w" );
1604                         if ( logfile != NULL ) lutil_debug_file( logfile );
1605
1606 #endif
1607                 /* start of a new database definition */
1608                 } else if ( strcasecmp( cargv[0], "debug" ) == 0 ) {
1609                         int level;
1610                         if ( cargc < 3 ) {
1611 #ifdef NEW_LOGGING
1612                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1613                                            "%s: line %d: Error in debug directive, "
1614                                            "\"debug <subsys> <level>\"\n", fname, lineno ));
1615 #else
1616                                 Debug( LDAP_DEBUG_ANY,
1617                                         "%s: line %d: Error in debug directive, \"debug subsys level\"\n",
1618                                         fname, lineno, 0 );
1619 #endif
1620
1621                                 return( 1 );
1622                         }
1623                         level = atoi( cargv[2] );
1624                         if ( level <= 0 ) level = lutil_mnem2level( cargv[2] );
1625                         lutil_set_debug_level( cargv[1], level );
1626                 /* specify an Object Identifier macro */
1627                 } else if ( strcasecmp( cargv[0], "objectidentifier" ) == 0 ) {
1628                         rc = parse_oidm( fname, lineno, cargc, cargv );
1629                         if( rc ) return rc;
1630
1631                 /* specify an objectclass */
1632                 } else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
1633                         if ( *cargv[1] == '(' ) {
1634                                 char * p;
1635                                 p = strchr(saveline,'(');
1636                                 rc = parse_oc( fname, lineno, p, cargv );
1637                                 if( rc ) return rc;
1638
1639                         } else {
1640 #ifdef NEW_LOGGING
1641                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1642                                            "%s: line %d: old objectclass format not supported\n",
1643                                            fname, lineno ));
1644 #else
1645                                 Debug( LDAP_DEBUG_ANY,
1646                                        "%s: line %d: old objectclass format not supported.\n",
1647                                        fname, lineno, 0 );
1648 #endif
1649
1650                         }
1651
1652                 /* specify an attribute type */
1653                 } else if (( strcasecmp( cargv[0], "attributetype" ) == 0 )
1654                         || ( strcasecmp( cargv[0], "attribute" ) == 0 ))
1655                 {
1656                         if ( *cargv[1] == '(' ) {
1657                                 char * p;
1658                                 p = strchr(saveline,'(');
1659                                 rc = parse_at( fname, lineno, p, cargv );
1660                                 if( rc ) return rc;
1661
1662                         } else {
1663 #ifdef NEW_LOGGING
1664                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1665                                            "%s: line %d: old attribute type format not supported.\n",
1666                                            fname, lineno ));
1667 #else
1668                                 Debug( LDAP_DEBUG_ANY,
1669     "%s: line %d: old attribute type format not supported.\n",
1670                                     fname, lineno, 0 );
1671 #endif
1672
1673                         }
1674
1675                 /* turn on/off schema checking */
1676                 } else if ( strcasecmp( cargv[0], "schemacheck" ) == 0 ) {
1677                         if ( cargc < 2 ) {
1678 #ifdef NEW_LOGGING
1679                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1680                                            "%s: line %d: missing on|off in "
1681                                            "\"schemacheck <on|off>\" line.\n",
1682                                            fname, lineno ));
1683 #else
1684                                 Debug( LDAP_DEBUG_ANY,
1685     "%s: line %d: missing on|off in \"schemacheck <on|off>\" line\n",
1686                                     fname, lineno, 0 );
1687 #endif
1688
1689                                 return( 1 );
1690                         }
1691                         if ( strcasecmp( cargv[1], "off" ) == 0 ) {
1692 #ifdef NEW_LOGGING
1693                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1694                                         "%s: line %d: schema checking disabled! your mileage may vary!\n",
1695                                         fname, lineno ));
1696 #else
1697                                 Debug( LDAP_DEBUG_ANY,
1698                                         "%s: line %d: schema checking disabled! your mileage may vary!\n",
1699                                     fname, lineno, 0 );
1700 #endif
1701                                 global_schemacheck = 0;
1702                         } else {
1703                                 global_schemacheck = 1;
1704                         }
1705
1706                 /* specify access control info */
1707                 } else if ( strcasecmp( cargv[0], "access" ) == 0 ) {
1708                         parse_acl( be, fname, lineno, cargc, cargv );
1709
1710                 /* debug level to log things to syslog */
1711                 } else if ( strcasecmp( cargv[0], "loglevel" ) == 0 ) {
1712                         if ( cargc < 2 ) {
1713 #ifdef NEW_LOGGING
1714                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1715                                            "%s: line %d: missing level in \"loglevel <level>\""
1716                                            " line.\n", fname, lineno ));
1717 #else
1718                                 Debug( LDAP_DEBUG_ANY,
1719                     "%s: line %d: missing level in \"loglevel <level>\" line\n",
1720                                     fname, lineno, 0 );
1721 #endif
1722
1723                                 return( 1 );
1724                         }
1725
1726                         ldap_syslog = 0;
1727
1728                         for( i=1; i < cargc; i++ ) {
1729                                 ldap_syslog += atoi( cargv[1] );
1730                         }
1731
1732                 /* list of replicas of the data in this backend (master only) */
1733                 } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
1734                         if ( cargc < 2 ) {
1735 #ifdef NEW_LOGGING
1736                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1737                                            "%s: line %d: missing host in \"replica "
1738                                            " <host[:port]\" line\n", fname, lineno ));
1739 #else
1740                                 Debug( LDAP_DEBUG_ANY,
1741             "%s: line %d: missing host in \"replica <host[:port]>\" line\n",
1742                                     fname, lineno, 0 );
1743 #endif
1744
1745                                 return( 1 );
1746                         }
1747                         if ( be == NULL ) {
1748 #ifdef NEW_LOGGING
1749                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1750                                            "%s: line %d: replica line must appear inside "
1751                                            "a database definition (ignored).\n", fname, lineno ));
1752 #else
1753                                 Debug( LDAP_DEBUG_ANY,
1754 "%s: line %d: replica line must appear inside a database definition (ignored)\n",
1755                                     fname, lineno, 0 );
1756 #endif
1757
1758                         } else {
1759                                 int nr = -1;
1760
1761                                 for ( i = 1; i < cargc; i++ ) {
1762                                         if ( strncasecmp( cargv[i], "host=", 5 )
1763                                             == 0 ) {
1764                                                 nr = add_replica_info( be, 
1765                                                         cargv[i] + 5 );
1766                                                 break;
1767                                         }
1768                                 }
1769                                 if ( i == cargc ) {
1770 #ifdef NEW_LOGGING
1771                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1772                                                    "%s: line %d: missing host in \"replica\" "
1773                                                    "line (ignored)\n", fname, lineno ));
1774 #else
1775                                         Debug( LDAP_DEBUG_ANY,
1776                     "%s: line %d: missing host in \"replica\" line (ignored)\n",
1777                                             fname, lineno, 0 );
1778 #endif
1779
1780                                 } else if ( nr == -1 ) {
1781 #ifdef NEW_LOGGING
1782                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1783                                                    "%s: line %d: unable to add"
1784                                                    " replica \"%s\""
1785                                                    " (ignored)\n",
1786                                                    fname, lineno, 
1787                                                    cargv[i] + 5 ));
1788 #else
1789                                         Debug( LDAP_DEBUG_ANY,
1790                 "%s: line %d: unable to add replica \"%s\" (ignored)\n",
1791                                                 fname, lineno, cargv[i] + 5 );
1792 #endif
1793                                 } else {
1794                                         for ( i = 1; i < cargc; i++ ) {
1795                                                 if ( strncasecmp( cargv[i], "suffix=", 7 ) == 0 ) {
1796
1797                                                         switch ( add_replica_suffix( be, nr, cargv[i] + 7 ) ) {
1798                                                         case 1:
1799 #ifdef NEW_LOGGING
1800                                                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1801                                                                                 "%s: line %d: suffix \"%s\" in \"replica\" line is not valid for backend (ignored)\n",
1802                                                                                 fname, lineno, cargv[i] + 7 ));
1803 #else
1804                                                                 Debug( LDAP_DEBUG_ANY,
1805                                                                                 "%s: line %d: suffix \"%s\" in \"replica\" line is not valid for backend (ignored)\n",
1806                                                                                 fname, lineno, cargv[i] + 7 );
1807 #endif
1808                                                                 break;
1809
1810                                                         case 2:
1811 #ifdef NEW_LOGGING
1812                                                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1813                                                                                         "%s: line %d: unable to normalize suffix in \"replica\" line (ignored)\n",
1814                                                                                         fname, lineno ));
1815 #else
1816                                                                 Debug( LDAP_DEBUG_ANY,
1817                                                                                  "%s: line %d: unable to normalize suffix in \"replica\" line (ignored)\n",
1818                                                                                  fname, lineno, 0 );
1819 #endif
1820                                                                 break;
1821                                                         }
1822                                                 }
1823                                         }
1824                                 }
1825                         }
1826
1827                 /* dn of master entity allowed to write to replica */
1828                 } else if ( strcasecmp( cargv[0], "updatedn" ) == 0 ) {
1829                         if ( cargc < 2 ) {
1830 #ifdef NEW_LOGGING
1831                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1832                                            "%s: line %d: missing dn in \"updatedn <dn>\""
1833                                            " line.\n", fname, lineno ));
1834 #else
1835                                 Debug( LDAP_DEBUG_ANY,
1836                     "%s: line %d: missing dn in \"updatedn <dn>\" line\n",
1837                                     fname, lineno, 0 );
1838 #endif
1839
1840                                 return( 1 );
1841                         }
1842                         if ( be == NULL ) {
1843 #ifdef NEW_LOGGING
1844                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
1845                                            "%s: line %d: updatedn line must appear inside "
1846                                            "a database definition (ignored)\n",
1847                                            fname, lineno ));
1848 #else
1849                                 Debug( LDAP_DEBUG_ANY,
1850 "%s: line %d: updatedn line must appear inside a database definition (ignored)\n",
1851                                     fname, lineno, 0 );
1852 #endif
1853
1854                         } else {
1855                                 struct berval dn;
1856
1857                                 if ( load_ucdata( NULL ) < 0 ) return 1;
1858
1859                                 dn.bv_val = cargv[1];
1860                                 dn.bv_len = strlen( cargv[1] );
1861
1862                                 rc = dnNormalize2( NULL, &dn, &be->be_update_ndn );
1863                                 if( rc != LDAP_SUCCESS ) {
1864 #ifdef NEW_LOGGING
1865                                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1866                                                 "%s: line %d: updatedn DN is invalid.\n",
1867                                                 fname, lineno ));
1868 #else
1869                                         Debug( LDAP_DEBUG_ANY,
1870                                                 "%s: line %d: updatedn DN is invalid\n",
1871                                             fname, lineno, 0 );
1872 #endif
1873                                         return 1;
1874                                 }
1875                         }
1876
1877                 } else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
1878                         if ( cargc < 2 ) {
1879 #ifdef NEW_LOGGING
1880                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1881                                         "missing url in \"updateref <ldapurl>\" line.\n",
1882                                         fname, lineno ));
1883 #else
1884                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1885                                         "missing url in \"updateref <ldapurl>\" line\n",
1886                                     fname, lineno, 0 );
1887 #endif
1888
1889                                 return( 1 );
1890                         }
1891                         if ( be == NULL ) {
1892 #ifdef NEW_LOGGING
1893                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: updateref"
1894                                         " line must appear inside a database definition\n",
1895                                         fname, lineno ));
1896 #else
1897                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: updateref"
1898                                         " line must appear inside a database definition\n",
1899                                         fname, lineno, 0 );
1900 #endif
1901                                 return 1;
1902
1903                         } else if ( !be->be_update_ndn.bv_len ) {
1904 #ifdef NEW_LOGGING
1905                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO, "%s: line %d: "
1906                                         "updateref line must come after updatedn.\n",
1907                                         fname, lineno ));
1908 #else
1909                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1910                                         "updateref line must after updatedn.\n",
1911                                     fname, lineno, 0 );
1912 #endif
1913                                 return 1;
1914                         }
1915
1916                         if( validate_global_referral( cargv[1] ) ) {
1917 #ifdef NEW_LOGGING
1918                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1919                                         "invalid URL (%s) in \"updateref\" line.\n",
1920                                         fname, lineno, cargv[1] ));
1921 #else
1922                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1923                                         "invalid URL (%s) in \"updateref\" line.\n",
1924                                     fname, lineno, cargv[1] );
1925 #endif
1926                                 return 1;
1927                         }
1928
1929                         vals[0].bv_val = cargv[1];
1930                         vals[0].bv_len = strlen( vals[0].bv_val );
1931                         value_add( &be->be_update_refs, vals );
1932
1933                 /* replication log file to which changes are appended */
1934                 } else if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
1935                         if ( cargc < 2 ) {
1936 #ifdef NEW_LOGGING
1937                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1938                                            "%s: line %d: missing filename in \"replogfile <filename>\""
1939                                            " line.\n", fname, lineno ));
1940 #else
1941                                 Debug( LDAP_DEBUG_ANY,
1942             "%s: line %d: missing filename in \"replogfile <filename>\" line\n",
1943                                     fname, lineno, 0 );
1944 #endif
1945
1946                                 return( 1 );
1947                         }
1948                         if ( be ) {
1949                                 be->be_replogfile = ch_strdup( cargv[1] );
1950                         } else {
1951                                 replogfile = ch_strdup( cargv[1] );
1952                         }
1953
1954                 /* file from which to read additional rootdse attrs */
1955                 } else if ( strcasecmp( cargv[0], "rootdse" ) == 0) {
1956                         if ( cargc < 2 ) {
1957 #ifdef NEW_LOGGING
1958                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1959                                         "missing filename in \"rootDSE <filename>\" line.\n",
1960                                         fname, lineno ));
1961 #else
1962                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1963                                         "missing filename in \"rootDSE <filename>\" line.\n",
1964                                     fname, lineno, 0 );
1965 #endif
1966                                 return 1;
1967                         }
1968
1969                         if( read_root_dse_file( cargv[1] ) ) {
1970 #ifdef NEW_LOGGING
1971                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT, "%s: line %d: "
1972                                         "could not read \"rootDSE <filename>\" line.\n",
1973                                         fname, lineno ));
1974 #else
1975                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1976                                         "could not read \"rootDSE <filename>\" line\n",
1977                                     fname, lineno, 0 );
1978 #endif
1979                                 return 1;
1980                         }
1981
1982                 /* maintain lastmodified{by,time} attributes */
1983                 } else if ( strcasecmp( cargv[0], "lastmod" ) == 0 ) {
1984                         if ( cargc < 2 ) {
1985 #ifdef NEW_LOGGING
1986                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
1987                                            "%s: line %d: missing on|off in \"lastmod <on|off>\""
1988                                            " line.\n", fname, lineno ));
1989 #else
1990                                 Debug( LDAP_DEBUG_ANY,
1991             "%s: line %d: missing on|off in \"lastmod <on|off>\" line\n",
1992                                     fname, lineno, 0 );
1993 #endif
1994
1995                                 return( 1 );
1996                         }
1997                         if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1998                                 if ( be )
1999                                         be->be_flags |= SLAP_BFLAG_LASTMOD;
2000                                 else
2001                                         lastmod = ON;
2002                         } else {
2003                                 if ( be )
2004                                         be->be_flags &= ~SLAP_BFLAG_LASTMOD;
2005                                 else
2006                                         lastmod = OFF;
2007                         }
2008
2009                 /* set idle timeout value */
2010                 } else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) {
2011                         int i;
2012                         if ( cargc < 2 ) {
2013 #ifdef NEW_LOGGING
2014                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2015                                            "%s: line %d: missing timeout value in "
2016                                            "\"idletimeout <seconds>\" line.\n", fname, lineno ));
2017 #else
2018                                 Debug( LDAP_DEBUG_ANY,
2019             "%s: line %d: missing timeout value in \"idletimeout <seconds>\" line\n",
2020                                     fname, lineno, 0 );
2021 #endif
2022
2023                                 return( 1 );
2024                         }
2025
2026                         i = atoi( cargv[1] );
2027
2028                         if( i < 0 ) {
2029 #ifdef NEW_LOGGING
2030                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2031                                            "%s: line %d: timeout value (%d) invalid "
2032                                            "\"idletimeout <seconds>\" line.\n",
2033                                            fname, lineno, i ));
2034 #else
2035                                 Debug( LDAP_DEBUG_ANY,
2036             "%s: line %d: timeout value (%d) invalid \"idletimeout <seconds>\" line\n",
2037                                     fname, lineno, i );
2038 #endif
2039
2040                                 return( 1 );
2041                         }
2042
2043                         global_idletimeout = i;
2044
2045                 /* include another config file */
2046                 } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
2047                         if ( cargc < 2 ) {
2048 #ifdef NEW_LOGGING
2049                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2050                                            "%s: line %d: missing filename in \"include "
2051                                            "<filename>\" line.\n", fname, lineno ));
2052 #else
2053                                 Debug( LDAP_DEBUG_ANY,
2054     "%s: line %d: missing filename in \"include <filename>\" line\n",
2055                                     fname, lineno, 0 );
2056 #endif
2057
2058                                 return( 1 );
2059                         }
2060                         savefname = ch_strdup( cargv[1] );
2061                         savelineno = lineno;
2062
2063                         if ( read_config( savefname ) != 0 ) {
2064                                 return( 1 );
2065                         }
2066
2067                         free( savefname );
2068                         lineno = savelineno - 1;
2069
2070                 /* location of kerberos srvtab file */
2071                 } else if ( strcasecmp( cargv[0], "srvtab" ) == 0 ) {
2072                         if ( cargc < 2 ) {
2073 #ifdef NEW_LOGGING
2074                                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2075                                            "%s: line %d: missing filename in \"srvtab "
2076                                            "<filename>\" line.\n", fname, lineno ));
2077 #else
2078                                 Debug( LDAP_DEBUG_ANY,
2079             "%s: line %d: missing filename in \"srvtab <filename>\" line\n",
2080                                     fname, lineno, 0 );
2081 #endif
2082
2083                                 return( 1 );
2084                         }
2085                         ldap_srvtab = ch_strdup( cargv[1] );
2086
2087 #ifdef SLAPD_MODULES
2088                 } else if (strcasecmp( cargv[0], "moduleload") == 0 ) {
2089                    if ( cargc < 2 ) {
2090 #ifdef NEW_LOGGING
2091                            LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2092                                       "%s: line %d: missing filename in \"moduleload "
2093                                       "<filename>\" line.\n", fname, lineno ));
2094 #else
2095                       Debug( LDAP_DEBUG_ANY,
2096                              "%s: line %d: missing filename in \"moduleload <filename>\" line\n",
2097                              fname, lineno, 0 );
2098 #endif
2099
2100                       exit( EXIT_FAILURE );
2101                    }
2102                    if (module_load(cargv[1], cargc - 2, (cargc > 2) ? cargv + 2 : NULL)) {
2103 #ifdef NEW_LOGGING
2104                            LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2105                                       "%s: line %d: failed to load or initialize module %s\n"<
2106                                       fname, lineno, cargv[1] ));
2107 #else
2108                       Debug( LDAP_DEBUG_ANY,
2109                              "%s: line %d: failed to load or initialize module %s\n",
2110                              fname, lineno, cargv[1]);
2111 #endif
2112
2113                       exit( EXIT_FAILURE );
2114                    }
2115                 } else if (strcasecmp( cargv[0], "modulepath") == 0 ) {
2116                    if ( cargc != 2 ) {
2117 #ifdef NEW_LOGGING
2118                            LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2119                                       "%s: line %d: missing path in \"modulepath <path>\""
2120                                       " line\n", fname, lineno ));
2121 #else
2122                       Debug( LDAP_DEBUG_ANY,
2123                              "%s: line %d: missing path in \"modulepath <path>\" line\n",
2124                              fname, lineno, 0 );
2125 #endif
2126
2127                       exit( EXIT_FAILURE );
2128                    }
2129                    if (module_path( cargv[1] )) {
2130 #ifdef NEW_LOGGING
2131                            LDAP_LOG(( "cofig", LDAP_LEVEL_CRIT,
2132                                       "%s: line %d: failed to set module search path to %s.\n",
2133                                       fname, lineno, cargv[1] ));
2134 #else
2135                            Debug( LDAP_DEBUG_ANY,
2136                                   "%s: line %d: failed to set module search path to %s\n",
2137                                   fname, lineno, cargv[1]);
2138 #endif
2139
2140                       exit( EXIT_FAILURE );
2141                    }
2142                    
2143 #endif /*SLAPD_MODULES*/
2144
2145 #ifdef HAVE_TLS
2146                 } else if ( !strcasecmp( cargv[0], "TLSRandFile" ) ) {
2147                         rc = ldap_pvt_tls_set_option( NULL,
2148                                                       LDAP_OPT_X_TLS_RANDOM_FILE,
2149                                                       cargv[1] );
2150                         if ( rc )
2151                                 return rc;
2152
2153                 } else if ( !strcasecmp( cargv[0], "TLSCipherSuite" ) ) {
2154                         rc = ldap_pvt_tls_set_option( NULL,
2155                                                       LDAP_OPT_X_TLS_CIPHER_SUITE,
2156                                                       cargv[1] );
2157                         if ( rc )
2158                                 return rc;
2159
2160                 } else if ( !strcasecmp( cargv[0], "TLSCertificateFile" ) ) {
2161                         rc = ldap_pvt_tls_set_option( NULL,
2162                                                       LDAP_OPT_X_TLS_CERTFILE,
2163                                                       cargv[1] );
2164                         if ( rc )
2165                                 return rc;
2166
2167                 } else if ( !strcasecmp( cargv[0], "TLSCertificateKeyFile" ) ) {
2168                         rc = ldap_pvt_tls_set_option( NULL,
2169                                                       LDAP_OPT_X_TLS_KEYFILE,
2170                                                       cargv[1] );
2171                         if ( rc )
2172                                 return rc;
2173
2174                 } else if ( !strcasecmp( cargv[0], "TLSCACertificatePath" ) ) {
2175                         rc = ldap_pvt_tls_set_option( NULL,
2176                                                       LDAP_OPT_X_TLS_CACERTDIR,
2177                                                       cargv[1] );
2178                         if ( rc )
2179                                 return rc;
2180
2181                 } else if ( !strcasecmp( cargv[0], "TLSCACertificateFile" ) ) {
2182                         rc = ldap_pvt_tls_set_option( NULL,
2183                                                       LDAP_OPT_X_TLS_CACERTFILE,
2184                                                       cargv[1] );
2185                         if ( rc )
2186                                 return rc;
2187                 } else if ( !strcasecmp( cargv[0], "TLSVerifyClient" ) ) {
2188                         i = atoi(cargv[1]);
2189                         rc = ldap_pvt_tls_set_option( NULL,
2190                                                       LDAP_OPT_X_TLS_REQUIRE_CERT,
2191                                                       &i );
2192                         if ( rc )
2193                                 return rc;
2194
2195 #endif
2196
2197                 /* pass anything else to the current backend info/db config routine */
2198                 } else {
2199                         if ( bi != NULL ) {
2200                                 if ( bi->bi_config == 0 ) {
2201 #ifdef NEW_LOGGING
2202                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2203                                                    "%s: line %d: unknown directive \"%s\" inside "
2204                                                    "backend info definition (ignored).\n",
2205                                                    fname, lineno, cargv[0] ));
2206 #else
2207                                         Debug( LDAP_DEBUG_ANY,
2208 "%s: line %d: unknown directive \"%s\" inside backend info definition (ignored)\n",
2209                                                 fname, lineno, cargv[0] );
2210 #endif
2211
2212                                 } else {
2213                                         if ( (*bi->bi_config)( bi, fname, lineno, cargc, cargv )
2214                                                 != 0 )
2215                                         {
2216                                                 return( 1 );
2217                                         }
2218                                 }
2219                         } else if ( be != NULL ) {
2220                                 if ( be->be_config == 0 ) {
2221 #ifdef NEW_LOGGING
2222                                         LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2223                                                    "%s: line %d: uknown directive \"%s\" inside "
2224                                                    "backend database definition (ignored).\n",
2225                                                    fname, lineno, cargv[0] ));
2226 #else
2227                                         Debug( LDAP_DEBUG_ANY,
2228 "%s: line %d: unknown directive \"%s\" inside backend database definition (ignored)\n",
2229                                         fname, lineno, cargv[0] );
2230 #endif
2231
2232                                 } else {
2233                                         if ( (*be->be_config)( be, fname, lineno, cargc, cargv )
2234                                                 != 0 )
2235                                         {
2236                                                 return( 1 );
2237                                         }
2238                                 }
2239                         } else {
2240 #ifdef NEW_LOGGING
2241                                 LDAP_LOG(( "config", LDAP_LEVEL_INFO,
2242                                            "%s: line %d: unknown directive \"%s\" outside backend "
2243                                            "info and database definitions (ignored).\n",
2244                                            fname, lineno, cargv[0] ));
2245 #else
2246                                 Debug( LDAP_DEBUG_ANY,
2247 "%s: line %d: unknown directive \"%s\" outside backend info and database definitions (ignored)\n",
2248                                     fname, lineno, cargv[0] );
2249 #endif
2250
2251                         }
2252                 }
2253                 free( saveline );
2254         }
2255         fclose( fp );
2256
2257         if ( load_ucdata( NULL ) < 0 ) return 1;
2258         return( 0 );
2259 }
2260
2261 static int
2262 fp_parse_line(
2263     char        *line,
2264     int         *argcp,
2265     char        **argv
2266 )
2267 {
2268         char *  token;
2269
2270         *argcp = 0;
2271         for ( token = strtok_quote( line, " \t" ); token != NULL;
2272             token = strtok_quote( NULL, " \t" ) ) {
2273                 if ( *argcp == MAXARGS ) {
2274 #ifdef NEW_LOGGING
2275                         LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2276                                    "fp_parse_line: too many tokens (%d max).\n",
2277                                    MAXARGS ));
2278 #else
2279                         Debug( LDAP_DEBUG_ANY, "Too many tokens (max %d)\n",
2280                             MAXARGS, 0, 0 );
2281 #endif
2282
2283                         return( 1 );
2284                 }
2285                 argv[(*argcp)++] = token;
2286         }
2287         argv[*argcp] = NULL;
2288         return 0;
2289 }
2290
2291 static char *
2292 strtok_quote( char *line, char *sep )
2293 {
2294         int             inquote;
2295         char            *tmp;
2296         static char     *next;
2297
2298         if ( line != NULL ) {
2299                 next = line;
2300         }
2301         while ( *next && strchr( sep, *next ) ) {
2302                 next++;
2303         }
2304
2305         if ( *next == '\0' ) {
2306                 next = NULL;
2307                 return( NULL );
2308         }
2309         tmp = next;
2310
2311         for ( inquote = 0; *next; ) {
2312                 switch ( *next ) {
2313                 case '"':
2314                         if ( inquote ) {
2315                                 inquote = 0;
2316                         } else {
2317                                 inquote = 1;
2318                         }
2319                         AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
2320                         break;
2321
2322                 case '\\':
2323                         if ( next[1] )
2324                                 AC_MEMCPY( next,
2325                                             next + 1, strlen( next + 1 ) + 1 );
2326                         next++;         /* dont parse the escaped character */
2327                         break;
2328
2329                 default:
2330                         if ( ! inquote ) {
2331                                 if ( strchr( sep, *next ) != NULL ) {
2332                                         *next++ = '\0';
2333                                         return( tmp );
2334                                 }
2335                         }
2336                         next++;
2337                         break;
2338                 }
2339         }
2340
2341         return( tmp );
2342 }
2343
2344 static char     buf[BUFSIZ];
2345 static char     *line;
2346 static int      lmax, lcur;
2347
2348 #define CATLINE( buf )  { \
2349         int     len; \
2350         len = strlen( buf ); \
2351         while ( lcur + len + 1 > lmax ) { \
2352                 lmax += BUFSIZ; \
2353                 line = (char *) ch_realloc( line, lmax ); \
2354         } \
2355         strcpy( line + lcur, buf ); \
2356         lcur += len; \
2357 }
2358
2359 static char *
2360 fp_getline( FILE *fp, int *lineno )
2361 {
2362         char            *p;
2363
2364         lcur = 0;
2365         CATLINE( buf );
2366         (*lineno)++;
2367
2368         /* hack attack - keeps us from having to keep a stack of bufs... */
2369         if ( strncasecmp( line, "include", 7 ) == 0 ) {
2370                 buf[0] = '\0';
2371                 return( line );
2372         }
2373
2374         while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
2375                 /* trim off \r\n or \n */
2376                 if ( (p = strchr( buf, '\n' )) != NULL ) {
2377                         if( p > buf && p[-1] == '\r' ) --p;
2378                         *p = '\0';
2379                 }
2380                 if ( ! isspace( (unsigned char) buf[0] ) ) {
2381                         return( line );
2382                 }
2383
2384                 /* change leading whitespace to a space */
2385                 buf[0] = ' ';
2386
2387                 CATLINE( buf );
2388                 (*lineno)++;
2389         }
2390         buf[0] = '\0';
2391
2392         return( line[0] ? line : NULL );
2393 }
2394
2395 static void
2396 fp_getline_init( int *lineno )
2397 {
2398         *lineno = -1;
2399         buf[0] = '\0';
2400 }
2401
2402 /* Loads ucdata, returns 1 if loading, 0 if already loaded, -1 on error */
2403 static int
2404 load_ucdata( char *path )
2405 {
2406         static int loaded = 0;
2407         int err;
2408         
2409         if ( loaded ) {
2410                 return( 0 );
2411         }
2412         err = ucdata_load( path ? path : SLAPD_DEFAULT_UCDATA, UCDATA_ALL );
2413         if ( err ) {
2414 #ifdef NEW_LOGGING
2415                 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
2416                            "load_ucdata: Error %d loading ucdata.\n", err ));
2417 #else
2418                 Debug( LDAP_DEBUG_ANY, "error loading ucdata (error %d)\n",
2419                        err, 0, 0 );
2420 #endif
2421
2422                 return( -1 );
2423         }
2424         loaded = 1;
2425         return( 1 );
2426 }
2427
2428 void
2429 config_destroy( )
2430 {
2431         ucdata_unload( UCDATA_ALL );
2432         free( line );
2433         if ( slapd_args_file )
2434                 free ( slapd_args_file );
2435         if ( slapd_pid_file )
2436                 free ( slapd_pid_file );
2437         acl_destroy( global_acl, NULL );
2438 }