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