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