]> git.sur5r.net Git - openldap/blob - servers/slapd/config.c
completion of limits w/ paged results control
[openldap] / servers / slapd / config.c
1 /* config.c - configuration file handling routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2004 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms are permitted
20  * provided that this notice is preserved and that due credit is given
21  * to the University of Michigan at Ann Arbor. The name of the University
22  * may not be used to endorse or promote products derived from this
23  * software without specific prior written permission. This software
24  * is provided ``as is'' without express or implied warranty.
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/string.h>
32 #include <ac/ctype.h>
33 #include <ac/signal.h>
34 #include <ac/socket.h>
35 #include <ac/errno.h>
36
37 #include "ldap_pvt.h"
38 #include "slap.h"
39 #ifdef LDAP_SLAPI
40 #include "slapi/slapi.h"
41 #endif
42 #include "lutil.h"
43
44 #define ARGS_STEP       512
45
46 /*
47  * defaults for various global variables
48  */
49 struct slap_limits_set deflimit = {
50         SLAPD_DEFAULT_TIMELIMIT,        /* backward compatible limits */
51         0,
52
53         SLAPD_DEFAULT_SIZELIMIT,        /* backward compatible limits */
54         0,
55         -1,                             /* no limit on unchecked size */
56         0,                              /* page limit */
57         0,                              /* hide number of entries left */
58         -1                              /* unlimited number of total entries returned by paged results */
59 };
60
61 AccessControl   *global_acl = NULL;
62 slap_access_t           global_default_access = ACL_READ;
63 slap_mask_t             global_restrictops = 0;
64 slap_mask_t             global_allows = 0;
65 slap_mask_t             global_disallows = 0;
66 slap_mask_t             global_requires = 0;
67 slap_ssf_set_t  global_ssf_set;
68 char            *replogfile;
69 int             global_gentlehup = 0;
70 int             global_idletimeout = 0;
71 char    *global_host = NULL;
72 char    *global_realm = NULL;
73 char            *ldap_srvtab = "";
74 char            **default_passwd_hash = NULL;
75 int             cargc = 0, cargv_size = 0;
76 char    **cargv;
77 struct berval default_search_base = BER_BVNULL;
78 struct berval default_search_nbase = BER_BVNULL;
79 unsigned                num_subordinates = 0;
80 struct berval global_schemadn = BER_BVNULL;
81 struct berval global_schemandn = BER_BVNULL;
82
83 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
84 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
85
86 int     slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
87 int     slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
88
89 char   *slapd_pid_file  = NULL;
90 char   *slapd_args_file = NULL;
91
92 char   *strtok_quote_ptr;
93
94 int use_reverse_lookup = 0;
95
96 #ifdef LDAP_SLAPI
97 int slapi_plugins_used = 0;
98 #endif
99
100 static char *fp_getline(FILE *fp, int *lineno);
101 static void fp_getline_init(int *lineno);
102 static int fp_parse_line(int lineno, char *line);
103
104 static char     *strtok_quote(char *line, char *sep);
105 static int load_ucdata(char *path);
106
107 static int add_syncrepl LDAP_P(( Backend *, char **, int ));
108 static int parse_syncrepl_line LDAP_P(( char **, int, syncinfo_t *));
109
110 int
111 read_config( const char *fname, int depth )
112 {
113         FILE    *fp;
114         char    *line, *savefname, *saveline;
115         int savelineno;
116         int     lineno, i;
117         int rc;
118         struct berval vals[2];
119         char *replicahost;
120         LDAPURLDesc *ludp;
121         static int lastmod = 1;
122         static BackendInfo *bi = NULL;
123         static BackendDB        *be = NULL;
124
125         vals[1].bv_val = NULL;
126
127         if ( depth == 0 ) {
128                 cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) );
129                 cargv_size = ARGS_STEP + 1;
130         }
131
132         if ( (fp = fopen( fname, "r" )) == NULL ) {
133                 ldap_syslog = 1;
134 #ifdef NEW_LOGGING
135                 LDAP_LOG( CONFIG, ENTRY, 
136                         "read_config: " "could not open config file \"%s\": %s (%d)\n",
137                     fname, strerror(errno), errno );
138 #else
139                 Debug( LDAP_DEBUG_ANY,
140                     "could not open config file \"%s\": %s (%d)\n",
141                     fname, strerror(errno), errno );
142 #endif
143                 return 1;
144         }
145
146 #ifdef NEW_LOGGING
147         LDAP_LOG( CONFIG, ENTRY, 
148                 "read_config: reading config file %s\n", fname, 0, 0 );
149 #else
150         Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0 );
151 #endif
152
153
154         fp_getline_init( &lineno );
155
156         while ( (line = fp_getline( fp, &lineno )) != NULL ) {
157                 /* skip comments and blank lines */
158                 if ( line[0] == '#' || line[0] == '\0' ) {
159                         continue;
160                 }
161
162                 /* fp_parse_line is destructive, we save a copy */
163                 saveline = ch_strdup( line );
164
165                 if ( fp_parse_line( lineno, line ) != 0 ) {
166                         return( 1 );
167                 }
168
169                 if ( cargc < 1 ) {
170 #ifdef NEW_LOGGING
171                         LDAP_LOG( CONFIG, INFO, 
172                                 "%s: line %d: bad config line (ignored)\n", fname, lineno, 0 );
173 #else
174                         Debug( LDAP_DEBUG_ANY,
175                             "%s: line %d: bad config line (ignored)\n",
176                             fname, lineno, 0 );
177 #endif
178
179                         continue;
180                 }
181
182                 if ( strcasecmp( cargv[0], "backend" ) == 0 ) {
183                         if ( cargc < 2 ) {
184 #ifdef NEW_LOGGING
185                                 LDAP_LOG( CONFIG, CRIT, 
186                                            "%s : line %d: missing type in \"backend\" line.\n",
187                                            fname, lineno, 0 );
188 #else
189                                 Debug( LDAP_DEBUG_ANY,
190                 "%s: line %d: missing type in \"backend <type>\" line\n",
191                                     fname, lineno, 0 );
192 #endif
193
194                                 return( 1 );
195                         }
196
197                         if( be != NULL ) {
198 #ifdef NEW_LOGGING
199                                 LDAP_LOG( CONFIG, CRIT, 
200                                            "%s: line %d: backend line must appear before any "
201                                            "database definition.\n", fname, lineno , 0 );
202 #else
203                                 Debug( LDAP_DEBUG_ANY,
204 "%s: line %d: backend line must appear before any database definition\n",
205                                     fname, lineno, 0 );
206 #endif
207
208                                 return( 1 );
209                         }
210
211                         bi = backend_info( cargv[1] );
212
213                         if( bi == NULL ) {
214 #ifdef NEW_LOGGING
215                                 LDAP_LOG( CONFIG, CRIT, 
216                                            "read_config: backend %s initialization failed.\n",
217                                            cargv[1], 0, 0 );
218 #else
219                                 Debug( LDAP_DEBUG_ANY,
220                                         "backend %s initialization failed.\n",
221                                     cargv[1], 0, 0 );
222 #endif
223
224                                 return( 1 );
225                         }
226                 } else if ( strcasecmp( cargv[0], "database" ) == 0 ) {
227                         if ( cargc < 2 ) {
228 #ifdef NEW_LOGGING
229                                 LDAP_LOG( CONFIG, CRIT, 
230                                         "%s: line %d: missing type in \"database <type>\" line\n",
231                                         fname, lineno, 0 );
232 #else
233                                 Debug( LDAP_DEBUG_ANY,
234                 "%s: line %d: missing type in \"database <type>\" line\n",
235                                     fname, lineno, 0 );
236 #endif
237
238                                 return( 1 );
239                         }
240
241                         bi = NULL;
242                         be = backend_db_init( cargv[1] );
243
244                         if( be == NULL ) {
245 #ifdef NEW_LOGGING
246                                 LDAP_LOG( CONFIG, CRIT, 
247                                         "database %s initialization failed.\n", cargv[1], 0, 0 );
248 #else
249                                 Debug( LDAP_DEBUG_ANY,
250                                         "database %s initialization failed.\n",
251                                     cargv[1], 0, 0 );
252 #endif
253
254                                 return( 1 );
255                         }
256
257                 /* set thread concurrency */
258                 } else if ( strcasecmp( cargv[0], "concurrency" ) == 0 ) {
259                         int c;
260                         if ( cargc < 2 ) {
261 #ifdef NEW_LOGGING
262                                 LDAP_LOG( CONFIG, CRIT, 
263                                         "%s: line %d: missing level in \"concurrency <level\" "
264                                         " line\n", fname, lineno, 0 );
265 #else
266                                 Debug( LDAP_DEBUG_ANY,
267             "%s: line %d: missing level in \"concurrency <level>\" line\n",
268                                     fname, lineno, 0 );
269 #endif
270
271                                 return( 1 );
272                         }
273
274                         c = atoi( cargv[1] );
275
276                         if( c < 1 ) {
277 #ifdef NEW_LOGGING
278                                 LDAP_LOG( CONFIG, CRIT, 
279                                         "%s: line %d: invalid level (%d) in "
280                                         "\"concurrency <level>\" line.\n", fname, lineno, c );
281 #else
282                                 Debug( LDAP_DEBUG_ANY,
283             "%s: line %d: invalid level (%d) in \"concurrency <level>\" line\n",
284                                     fname, lineno, c );
285 #endif
286
287                                 return( 1 );
288                         }
289
290                         ldap_pvt_thread_set_concurrency( c );
291
292                 /* set sockbuf max */
293                 } else if ( strcasecmp( cargv[0], "sockbuf_max_incoming" ) == 0 ) {
294                         long max;
295                         if ( cargc < 2 ) {
296 #ifdef NEW_LOGGING
297                                 LDAP_LOG( CONFIG, CRIT, 
298                                    "%s: line %d: missing max in \"sockbuf_max_incoming "
299                                    "<bytes>\" line\n", fname, lineno, 0 );
300 #else
301                                 Debug( LDAP_DEBUG_ANY,
302                                            "%s: line %d: missing max in \"sockbuf_max_incoming <bytes>\" line\n",
303                                     fname, lineno, 0 );
304 #endif
305
306                                 return( 1 );
307                         }
308
309                         max = atol( cargv[1] );
310
311                         if( max < 0 ) {
312 #ifdef NEW_LOGGING
313                                 LDAP_LOG( CONFIG, CRIT, 
314                                            "%s: line %d: invalid max value (%ld) in "
315                                            "\"sockbuf_max_incoming <bytes>\" line.\n",
316                                            fname, lineno, max );
317 #else
318                                 Debug( LDAP_DEBUG_ANY,
319                                         "%s: line %d: invalid max value (%ld) in "
320                                         "\"sockbuf_max_incoming <bytes>\" line.\n",
321                                     fname, lineno, max );
322 #endif
323
324                                 return( 1 );
325                         }
326
327                         sockbuf_max_incoming = max;
328
329                 /* set sockbuf max authenticated */
330                 } else if ( strcasecmp( cargv[0], "sockbuf_max_incoming_auth" ) == 0 ) {
331                         long max;
332                         if ( cargc < 2 ) {
333 #ifdef NEW_LOGGING
334                                 LDAP_LOG( CONFIG, CRIT, 
335                                    "%s: line %d: missing max in \"sockbuf_max_incoming_auth "
336                                    "<bytes>\" line\n", fname, lineno, 0 );
337 #else
338                                 Debug( LDAP_DEBUG_ANY,
339                                            "%s: line %d: missing max in \"sockbuf_max_incoming_auth <bytes>\" line\n",
340                                     fname, lineno, 0 );
341 #endif
342
343                                 return( 1 );
344                         }
345
346                         max = atol( cargv[1] );
347
348                         if( max < 0 ) {
349 #ifdef NEW_LOGGING
350                                 LDAP_LOG( CONFIG, CRIT, 
351                                            "%s: line %d: invalid max value (%ld) in "
352                                            "\"sockbuf_max_incoming_auth <bytes>\" line.\n",
353                                            fname, lineno, max );
354 #else
355                                 Debug( LDAP_DEBUG_ANY,
356                                         "%s: line %d: invalid max value (%ld) in "
357                                         "\"sockbuf_max_incoming_auth <bytes>\" line.\n",
358                                     fname, lineno, max );
359 #endif
360
361                                 return( 1 );
362                         }
363
364                         sockbuf_max_incoming_auth = max;
365
366                 /* set conn pending max */
367                 } else if ( strcasecmp( cargv[0], "conn_max_pending" ) == 0 ) {
368                         long max;
369                         if ( cargc < 2 ) {
370 #ifdef NEW_LOGGING
371                                 LDAP_LOG( CONFIG, CRIT, 
372                                    "%s: line %d: missing max in \"conn_max_pending "
373                                    "<requests>\" line\n", fname, lineno, 0 );
374 #else
375                                 Debug( LDAP_DEBUG_ANY,
376                                            "%s: line %d: missing max in \"conn_max_pending <requests>\" line\n",
377                                     fname, lineno, 0 );
378 #endif
379
380                                 return( 1 );
381                         }
382
383                         max = atol( cargv[1] );
384
385                         if( max < 0 ) {
386 #ifdef NEW_LOGGING
387                                 LDAP_LOG( CONFIG, CRIT, 
388                                            "%s: line %d: invalid max value (%ld) in "
389                                            "\"conn_max_pending <requests>\" line.\n",
390                                            fname, lineno, max );
391 #else
392                                 Debug( LDAP_DEBUG_ANY,
393                                         "%s: line %d: invalid max value (%ld) in "
394                                         "\"conn_max_pending <requests>\" line.\n",
395                                     fname, lineno, max );
396 #endif
397
398                                 return( 1 );
399                         }
400
401                         slap_conn_max_pending = max;
402
403                 /* set conn pending max authenticated */
404                 } else if ( strcasecmp( cargv[0], "conn_max_pending_auth" ) == 0 ) {
405                         long max;
406                         if ( cargc < 2 ) {
407 #ifdef NEW_LOGGING
408                                 LDAP_LOG( CONFIG, CRIT, 
409                                    "%s: line %d: missing max in \"conn_max_pending_auth "
410                                    "<requests>\" line\n", fname, lineno, 0 );
411 #else
412                                 Debug( LDAP_DEBUG_ANY,
413                                            "%s: line %d: missing max in \"conn_max_pending_auth <requests>\" line\n",
414                                     fname, lineno, 0 );
415 #endif
416
417                                 return( 1 );
418                         }
419
420                         max = atol( cargv[1] );
421
422                         if( max < 0 ) {
423 #ifdef NEW_LOGGING
424                                 LDAP_LOG( CONFIG, CRIT, 
425                                            "%s: line %d: invalid max value (%ld) in "
426                                            "\"conn_max_pending_auth <requests>\" line.\n",
427                                            fname, lineno, max );
428 #else
429                                 Debug( LDAP_DEBUG_ANY,
430                                         "%s: line %d: invalid max value (%ld) in "
431                                         "\"conn_max_pending_auth <requests>\" line.\n",
432                                     fname, lineno, max );
433 #endif
434
435                                 return( 1 );
436                         }
437
438                         slap_conn_max_pending_auth = max;
439
440                 /* default search base */
441                 } else if ( strcasecmp( cargv[0], "defaultSearchBase" ) == 0 ) {
442                         if ( cargc < 2 ) {
443 #ifdef NEW_LOGGING
444                                 LDAP_LOG( CONFIG, CRIT, 
445                                         "%s: line %d: missing dn in \"defaultSearchBase <dn\" "
446                                         "line\n", fname, lineno, 0 );
447 #else
448                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
449                                         "missing dn in \"defaultSearchBase <dn>\" line\n",
450                                         fname, lineno, 0 );
451 #endif
452
453                                 return 1;
454
455                         } else if ( cargc > 2 ) {
456 #ifdef NEW_LOGGING
457                                 LDAP_LOG( CONFIG, INFO, 
458                                         "%s: line %d: extra cruft after <dn> in "
459                                         "\"defaultSearchBase %s\" line (ignored)\n",
460                                         fname, lineno, cargv[1] );
461 #else
462                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
463                                         "extra cruft after <dn> in \"defaultSearchBase %s\", "
464                                         "line (ignored)\n",
465                                         fname, lineno, cargv[1] );
466 #endif
467                         }
468
469                         if ( bi != NULL || be != NULL ) {
470 #ifdef NEW_LOGGING
471                                 LDAP_LOG( CONFIG, CRIT, 
472                                         "%s: line %d: defaultSearchBase line must appear "
473                                         "prior to any backend or database definitions\n",
474                                         fname, lineno, 0 );
475 #else
476                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
477                                         "defaultSearchBaase line must appear prior to "
478                                         "any backend or database definition\n",
479                                     fname, lineno, 0 );
480 #endif
481
482                                 return 1;
483                         }
484
485                         if ( default_search_nbase.bv_len ) {
486 #ifdef NEW_LOGGING
487                                 LDAP_LOG( CONFIG, INFO, "%s: line %d: "
488                                         "default search base \"%s\" already defined "
489                                         "(discarding old)\n", fname, lineno,
490                                         default_search_base.bv_val );
491 #else
492                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
493                                         "default search base \"%s\" already defined "
494                                         "(discarding old)\n",
495                                         fname, lineno, default_search_base.bv_val );
496 #endif
497
498                                 free( default_search_base.bv_val );
499                                 free( default_search_nbase.bv_val );
500                         }
501
502                         if ( load_ucdata( NULL ) < 0 ) return 1;
503
504                         {
505                                 struct berval dn;
506
507                                 dn.bv_val = cargv[1];
508                                 dn.bv_len = strlen( dn.bv_val );
509
510                                 rc = dnPrettyNormal( NULL, &dn,
511                                         &default_search_base,
512                                         &default_search_nbase, NULL );
513
514                                 if( rc != LDAP_SUCCESS ) {
515 #ifdef NEW_LOGGING
516                                         LDAP_LOG( CONFIG, CRIT, 
517                                                 "%s: line %d: defaultSearchBase DN is invalid.\n",
518                                                 fname, lineno, 0 );
519 #else
520                                         Debug( LDAP_DEBUG_ANY,
521                                                 "%s: line %d: defaultSearchBase DN is invalid\n",
522                                            fname, lineno, 0 );
523 #endif
524                                         return( 1 );
525                                 }
526                         }
527
528                 /* set maximum threads in thread pool */
529                 } else if ( strcasecmp( cargv[0], "threads" ) == 0 ) {
530                         int c;
531                         if ( cargc < 2 ) {
532 #ifdef NEW_LOGGING
533                                 LDAP_LOG( CONFIG, CRIT, 
534                                         "%s: line %d: missing count in \"threads <count>\" line\n",
535                                         fname, lineno, 0 );
536 #else
537                                 Debug( LDAP_DEBUG_ANY,
538             "%s: line %d: missing count in \"threads <count>\" line\n",
539                                     fname, lineno, 0 );
540 #endif
541
542                                 return( 1 );
543                         }
544
545                         c = atoi( cargv[1] );
546
547                         if( c < 0 ) {
548 #ifdef NEW_LOGGING
549                                 LDAP_LOG( CONFIG, CRIT, 
550                                            "%s: line %d: invalid level (%d) in \"threads <count>\""
551                                            "line\n", fname, lineno, c );
552 #else
553                                 Debug( LDAP_DEBUG_ANY,
554             "%s: line %d: invalid level (%d) in \"threads <count>\" line\n",
555                                     fname, lineno, c );
556 #endif
557
558                                 return( 1 );
559                         }
560
561                         ldap_pvt_thread_pool_maxthreads( &connection_pool, c );
562
563                         /* save for later use */
564                         connection_pool_max = c;
565
566                 /* get pid file name */
567                 } else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
568                         if ( cargc < 2 ) {
569 #ifdef NEW_LOGGING
570                                 LDAP_LOG( CONFIG, CRIT, 
571                                         "%s: line %d missing file name in \"pidfile <file>\" "
572                                         "line.\n", fname, lineno, 0 );
573 #else
574                                 Debug( LDAP_DEBUG_ANY,
575             "%s: line %d: missing file name in \"pidfile <file>\" line\n",
576                                     fname, lineno, 0 );
577 #endif
578
579                                 return( 1 );
580                         }
581
582                         slapd_pid_file = ch_strdup( cargv[1] );
583
584                 /* get args file name */
585                 } else if ( strcasecmp( cargv[0], "argsfile" ) == 0 ) {
586                         if ( cargc < 2 ) {
587 #ifdef NEW_LOGGING
588                                 LDAP_LOG( CONFIG, CRIT, 
589                                            "%s: %d: missing file name in "
590                                            "\"argsfile <file>\" line.\n",
591                                            fname, lineno, 0 );
592 #else
593                                 Debug( LDAP_DEBUG_ANY,
594             "%s: line %d: missing file name in \"argsfile <file>\" line\n",
595                                     fname, lineno, 0 );
596 #endif
597
598                                 return( 1 );
599                         }
600
601                         slapd_args_file = ch_strdup( cargv[1] );
602
603                 } else if ( strcasecmp( cargv[0], "replica-pidfile" ) == 0 ) {
604                         /* ignore */ ;
605
606                 } else if ( strcasecmp( cargv[0], "replica-argsfile" ) == 0 ) {
607                         /* ignore */ ;
608
609                 /* default password hash */
610                 } else if ( strcasecmp( cargv[0], "password-hash" ) == 0 ) {
611                         if ( cargc < 2 ) {
612 #ifdef NEW_LOGGING
613                                 LDAP_LOG( CONFIG, CRIT, 
614                                            "%s: line %d: missing hash in "
615                                            "\"password-hash <hash>\" line.\n",
616                                            fname, lineno, 0 );
617 #else
618                                 Debug( LDAP_DEBUG_ANY,
619             "%s: line %d: missing hash in \"password-hash <hash>\" line\n",
620                                     fname, lineno, 0 );
621 #endif
622
623                                 return( 1 );
624                         }
625                         if ( default_passwd_hash != NULL ) {
626 #ifdef NEW_LOGGING
627                                 LDAP_LOG( CONFIG, CRIT, 
628                                            "%s: line %d: already set default password_hash!\n",
629                                            fname, lineno, 0 );
630 #else
631                                 Debug( LDAP_DEBUG_ANY,
632                                         "%s: line %d: already set default password_hash!\n",
633                                         fname, lineno, 0 );
634 #endif
635
636                                 return 1;
637
638                         }
639                         for(i = 1; i < cargc; i++) {
640                                 if ( lutil_passwd_scheme( cargv[i] ) == 0 ) {
641 #ifdef NEW_LOGGING
642                                         LDAP_LOG( CONFIG, CRIT, 
643                                                 "%s: line %d: password scheme \"%s\" not available\n",
644                                                 fname, lineno, cargv[i] );
645 #else
646                                         Debug( LDAP_DEBUG_ANY,
647                                                 "%s: line %d: password scheme \"%s\" not available\n",
648                                                 fname, lineno, cargv[i] );
649 #endif
650                                 } else {
651                                         ldap_charray_add( &default_passwd_hash, cargv[i] );
652                                 }
653                         }
654                         if( !default_passwd_hash ) {
655 #ifdef NEW_LOGGING
656                                 LDAP_LOG( CONFIG, CRIT, 
657                                         "%s: line %d: no valid hashes found\n",
658                                         fname, lineno, 0 );
659 #else
660                                 Debug( LDAP_DEBUG_ANY,
661                                         "%s: line %d: no valid hashes found\n",
662                                         fname, lineno, 0 );
663                                 return 1;
664 #endif
665                         }
666
667                 } else if ( strcasecmp( cargv[0], "password-crypt-salt-format" ) == 0 ) 
668                 {
669                         if ( cargc < 2 ) {
670 #ifdef NEW_LOGGING
671                                 LDAP_LOG( CONFIG, CRIT, 
672                                         "%s: line %d: missing format in "
673                                         "\"password-crypt-salt-format <format>\" line\n",
674                                         fname, lineno, 0 );
675 #else
676                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: missing format in "
677                                         "\"password-crypt-salt-format <format>\" line\n",
678                                     fname, lineno, 0 );
679 #endif
680
681                                 return 1;
682                         }
683
684                         lutil_salt_format( cargv[1] );
685
686                 /* SASL config options */
687                 } else if ( strncasecmp( cargv[0], "sasl", 4 ) == 0 ) {
688                         if ( slap_sasl_config( cargc, cargv, line, fname, lineno ) )
689                                 return 1;
690 #ifdef SLAP_X_SASL_REWRITE
691                 /* use authid rewrite instead of sasl regexp */
692                 } else if ( strncasecmp( cargv[0], "authid-rewrite", sizeof("authid-rewrite") - 1 ) == 0 ) {
693                         int rc = slap_sasl_rewrite_config( fname, lineno,
694                                         cargc, cargv );
695                         if ( rc ) {
696                                 return rc;
697                         }
698 #endif /* SLAP_X_SASL_REWRITE */
699
700                 } else if ( strcasecmp( cargv[0], "schemadn" ) == 0 ) {
701                         struct berval dn;
702                         if ( cargc < 2 ) {
703 #ifdef NEW_LOGGING
704                                 LDAP_LOG( CONFIG, CRIT, 
705                                            "%s: line %d: missing dn in "
706                                            "\"schemadn <dn>\" line.\n", fname, lineno, 0  );
707 #else
708                                 Debug( LDAP_DEBUG_ANY,
709             "%s: line %d: missing dn in \"schemadn <dn>\" line\n",
710                                     fname, lineno, 0 );
711 #endif
712                                 return 1 ;
713                         }
714                         ber_str2bv( cargv[1], 0, 0, &dn );
715                         if ( be ) {
716                                 rc = dnPrettyNormal( NULL, &dn, &be->be_schemadn,
717                                         &be->be_schemandn, NULL );
718                         } else {
719                                 rc = dnPrettyNormal( NULL, &dn, &global_schemadn,
720                                         &global_schemandn, NULL );
721                         }
722                         if ( rc != LDAP_SUCCESS ) {
723 #ifdef NEW_LOGGING
724                                 LDAP_LOG( CONFIG, CRIT, 
725                                         "%s: line %d: schemadn DN is invalid.\n",
726                                         fname, lineno , 0 );
727 #else
728                                 Debug( LDAP_DEBUG_ANY,
729                                         "%s: line %d: schemadn DN is invalid\n",
730                                         fname, lineno, 0 );
731 #endif
732                                 return 1;
733                         }
734
735                 /* set UCDATA path */
736                 } else if ( strcasecmp( cargv[0], "ucdata-path" ) == 0 ) {
737                         int err;
738                         if ( cargc < 2 ) {
739 #ifdef NEW_LOGGING
740                                 LDAP_LOG( CONFIG, CRIT, 
741                                            "%s: line %d: missing path in "
742                                            "\"ucdata-path <path>\" line.\n", fname, lineno, 0  );
743 #else
744                                 Debug( LDAP_DEBUG_ANY,
745             "%s: line %d: missing path in \"ucdata-path <path>\" line\n",
746                                     fname, lineno, 0 );
747 #endif
748
749                                 return( 1 );
750                         }
751
752                         err = load_ucdata( cargv[1] );
753                         if ( err <= 0 ) {
754                                 if ( err == 0 ) {
755 #ifdef NEW_LOGGING
756                                         LDAP_LOG( CONFIG, CRIT, 
757                                                    "%s: line %d: ucdata already loaded, ucdata-path "
758                                                    "must be set earlier in the file and/or be "
759                                                    "specified only once!\n", fname, lineno, 0 );
760 #else
761                                         Debug( LDAP_DEBUG_ANY,
762                                                "%s: line %d: ucdata already loaded, ucdata-path must be set earlier in the file and/or be specified only once!\n",
763                                                fname, lineno, 0 );
764 #endif
765
766                                 }
767                                 return( 1 );
768                         }
769
770                 /* set size limit */
771                 } else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
772                         int rc = 0, i;
773                         struct slap_limits_set *lim;
774                         
775                         if ( cargc < 2 ) {
776 #ifdef NEW_LOGGING
777                                 LDAP_LOG( CONFIG, CRIT, 
778                                    "%s: line %d: missing limit in \"sizelimit <limit>\" "
779                                    "line.\n", fname, lineno, 0 );
780 #else
781                                 Debug( LDAP_DEBUG_ANY,
782             "%s: line %d: missing limit in \"sizelimit <limit>\" line\n",
783                                     fname, lineno, 0 );
784 #endif
785
786                                 return( 1 );
787                         }
788
789                         if ( be == NULL ) {
790                                 lim = &deflimit;
791                         } else {
792                                 lim = &be->be_def_limit;
793                         }
794
795                         for ( i = 1; i < cargc; i++ ) {
796                                 if ( strncasecmp( cargv[i], "size", 4 ) == 0 ) {
797                                         rc = limits_parse_one( cargv[i], lim );
798                                         if ( rc ) {
799 #ifdef NEW_LOGGING
800                                                 LDAP_LOG( CONFIG, CRIT, 
801                                                         "%s: line %d: unable "
802                                                            "to parse value \"%s\" in \"sizelimit "
803                                                            "<limit>\" line.\n", fname, lineno, cargv[i] );
804 #else
805                                                 Debug( LDAP_DEBUG_ANY,
806                                                         "%s: line %d: unable "
807                                                         "to parse value \"%s\" "
808                                                         "in \"sizelimit "
809                                                         "<limit>\" line\n",
810                                                         fname, lineno, cargv[i] );
811 #endif
812                                                 return( 1 );
813                                         }
814
815                                 } else {
816                                         if ( strcasecmp( cargv[i], "unlimited" ) == 0 ) {
817                                                 lim->lms_s_soft = -1;
818                                         } else {
819                                                 char *next;
820
821                                                 lim->lms_s_soft = strtol( cargv[i] , &next, 0 );
822                                                 if ( next == cargv[i] ) {
823 #ifdef NEW_LOGGING
824                                                         LDAP_LOG( CONFIG, CRIT, 
825                                                            "%s: line %d: unable to parse limit \"%s\" in \"sizelimit <limit>\" "
826                                                            "line.\n", fname, lineno, cargv[i] );
827 #else
828                                                         Debug( LDAP_DEBUG_ANY,
829                                                             "%s: line %d: unable to parse limit \"%s\" in \"sizelimit <limit>\" line\n",
830                                                             fname, lineno, cargv[i] );
831 #endif
832                                                         return( 1 );
833
834                                                 } else if ( next[0] != '\0' ) {
835 #ifdef NEW_LOGGING
836                                                         LDAP_LOG( CONFIG, CRIT, 
837                                                            "%s: line %d: trailing chars \"%s\" in \"sizelimit <limit>\" "
838                                                            "line ignored.\n", fname, lineno, next );
839 #else
840                                                         Debug( LDAP_DEBUG_ANY,
841                                                             "%s: line %d: trailing chars \"%s\" in \"sizelimit <limit>\" line ignored\n",
842                                                             fname, lineno, next );
843 #endif
844                                                 }
845                                         }
846                                         lim->lms_s_hard = 0;
847                                 }
848                         }
849
850                 /* set time limit */
851                 } else if ( strcasecmp( cargv[0], "timelimit" ) == 0 ) {
852                         int rc = 0, i;
853                         struct slap_limits_set *lim;
854                         
855                         if ( cargc < 2 ) {
856 #ifdef NEW_LOGGING
857                                 LDAP_LOG( CONFIG, CRIT, 
858                                         "%s: line %d missing limit in \"timelimit <limit>\" "
859                                         "line.\n", fname, lineno, 0 );
860 #else
861                                 Debug( LDAP_DEBUG_ANY,
862             "%s: line %d: missing limit in \"timelimit <limit>\" line\n",
863                                     fname, lineno, 0 );
864 #endif
865
866                                 return( 1 );
867                         }
868                         
869                         if ( be == NULL ) {
870                                 lim = &deflimit;
871                         } else {
872                                 lim = &be->be_def_limit;
873                         }
874
875                         for ( i = 1; i < cargc; i++ ) {
876                                 if ( strncasecmp( cargv[i], "time", 4 ) == 0 ) {
877                                         rc = limits_parse_one( cargv[i], lim );
878                                         if ( rc ) {
879 #ifdef NEW_LOGGING
880                                                 LDAP_LOG( CONFIG, CRIT, 
881                                                             "%s: line %d: unable to parse value \"%s\" "
882                                                            "in \"timelimit <limit>\" line.\n",
883                                                            fname, lineno, cargv[i] );
884 #else
885                                                 Debug( LDAP_DEBUG_ANY,
886                                                         "%s: line %d: unable "
887                                                         "to parse value \"%s\" "
888                                                         "in \"timelimit "
889                                                         "<limit>\" line\n",
890                                                         fname, lineno, cargv[i] );
891 #endif
892                                                 return( 1 );
893                                         }
894
895                                 } else {
896                                         if ( strcasecmp( cargv[i], "unlimited" ) == 0 ) {
897                                                 lim->lms_t_soft = -1;
898                                         } else {
899                                                 char *next;
900
901                                                 lim->lms_t_soft = strtol( cargv[i] , &next, 0 );
902                                                 if ( next == cargv[i] ) {
903 #ifdef NEW_LOGGING
904                                                         LDAP_LOG( CONFIG, CRIT, 
905                                                            "%s: line %d: unable to parse limit \"%s\" in \"timelimit <limit>\" "
906                                                            "line.\n", fname, lineno, cargv[i] );
907 #else
908                                                         Debug( LDAP_DEBUG_ANY,
909                                                             "%s: line %d: unable to parse limit \"%s\" in \"timelimit <limit>\" line\n",
910                                                             fname, lineno, cargv[i] );
911 #endif
912                                                         return( 1 );
913
914                                                 } else if ( next[0] != '\0' ) {
915 #ifdef NEW_LOGGING
916                                                         LDAP_LOG( CONFIG, CRIT, 
917                                                            "%s: line %d: trailing chars \"%s\" in \"timelimit <limit>\" "
918                                                            "line ignored.\n", fname, lineno, next );
919 #else
920                                                         Debug( LDAP_DEBUG_ANY,
921                                                             "%s: line %d: trailing chars \"%s\" in \"timelimit <limit>\" line ignored\n",
922                                                             fname, lineno, next );
923 #endif
924                                                 }
925                                         }
926                                         lim->lms_t_hard = 0;
927                                 }
928                         }
929
930                 /* set regex-based limits */
931                 } else if ( strcasecmp( cargv[0], "limits" ) == 0 ) {
932                         if ( be == NULL ) {
933 #ifdef NEW_LOGGING
934                                 LDAP_LOG( CONFIG, WARNING, 
935                                            "%s: line %d \"limits\" allowed only in database "
936                                            "environment.\n", fname, lineno, 0 );
937 #else
938                                 Debug( LDAP_DEBUG_ANY,
939         "%s: line %d \"limits\" allowed only in database environment.\n%s",
940                                         fname, lineno, "" );
941 #endif
942                                 return( 1 );
943                         }
944
945                         if ( limits_parse( be, fname, lineno, cargc, cargv ) ) {
946                                 return( 1 );
947                         }
948
949                 /* mark this as a subordinate database */
950                 } else if ( strcasecmp( cargv[0], "subordinate" ) == 0 ) {
951                         if ( be == NULL ) {
952 #ifdef NEW_LOGGING
953                                 LDAP_LOG( CONFIG, INFO, "%s: line %d: "
954                                         "subordinate keyword must appear inside a database "
955                                         "definition.\n", fname, lineno, 0 );
956 #else
957                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: subordinate keyword "
958                                         "must appear inside a database definition.\n",
959                                     fname, lineno, 0 );
960 #endif
961                                 return 1;
962
963                         } else {
964                                 SLAP_DBFLAGS(be) |= SLAP_DBFLAG_GLUE_SUBORDINATE;
965                                 num_subordinates++;
966                         }
967
968                 /* add an overlay to this backend */
969                 } else if ( strcasecmp( cargv[0], "overlay" ) == 0 ) {
970                         if ( be == NULL ) {
971 #ifdef NEW_LOGGING
972                                 LDAP_LOG( CONFIG, INFO, "%s: line %d: "
973                                         "overlay keyword must appear inside a database "
974                                         "definition.\n", fname, lineno, 0 );
975 #else
976                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: overlay keyword "
977                                         "must appear inside a database definition.\n",
978                                     fname, lineno, 0 );
979 #endif
980                                 return 1;
981
982                         } else if ( overlay_config( be, cargv[1] )) {
983                                 return 1;
984                         }
985
986                 /* set database suffix */
987                 } else if ( strcasecmp( cargv[0], "suffix" ) == 0 ) {
988                         Backend *tmp_be;
989                         struct berval dn, pdn, ndn;
990
991                         if ( cargc < 2 ) {
992 #ifdef NEW_LOGGING
993                                 LDAP_LOG( CONFIG, CRIT, 
994                                         "%s: line %d: missing dn in \"suffix <dn>\" line.\n",
995                                         fname, lineno, 0 );
996 #else
997                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
998                                         "missing dn in \"suffix <dn>\" line\n",
999                                     fname, lineno, 0 );
1000 #endif
1001
1002                                 return( 1 );
1003
1004                         } else if ( cargc > 2 ) {
1005 #ifdef NEW_LOGGING
1006                                 LDAP_LOG( CONFIG, INFO, 
1007                                         "%s: line %d: extra cruft after <dn> in \"suffix %s\""
1008                                         " line (ignored).\n", fname, lineno, cargv[1] );
1009 #else
1010                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: extra cruft "
1011                                         "after <dn> in \"suffix %s\" line (ignored)\n",
1012                                     fname, lineno, cargv[1] );
1013 #endif
1014                         }
1015
1016                         if ( be == NULL ) {
1017 #ifdef NEW_LOGGING
1018                                 LDAP_LOG( CONFIG, INFO, 
1019                                         "%s: line %d: suffix line must appear inside a database "
1020                                         "definition.\n", fname, lineno, 0 );
1021 #else
1022                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix line "
1023                                         "must appear inside a database definition\n",
1024                                     fname, lineno, 0 );
1025 #endif
1026                                 return( 1 );
1027
1028 #if defined(SLAPD_MONITOR_DN)
1029                         /* "cn=Monitor" is reserved for monitoring slap */
1030                         } else if ( strcasecmp( cargv[1], SLAPD_MONITOR_DN ) == 0 ) {
1031 #ifdef NEW_LOGGING
1032                                 LDAP_LOG( CONFIG, CRIT, "%s: line %d: \""
1033                                         "%s\" is reserved for monitoring slapd\n", 
1034                                         fname, lineno, SLAPD_MONITOR_DN );
1035 #else
1036                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: \""
1037                                         "%s\" is reserved for monitoring slapd\n", 
1038                                         fname, lineno, SLAPD_MONITOR_DN );
1039 #endif
1040                                 return( 1 );
1041 #endif /* SLAPD_MONITOR_DN */
1042                         }
1043
1044                         if ( load_ucdata( NULL ) < 0 ) return 1;
1045
1046                         dn.bv_val = cargv[1];
1047                         dn.bv_len = strlen( cargv[1] );
1048
1049                         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL );
1050                         if( rc != LDAP_SUCCESS ) {
1051 #ifdef NEW_LOGGING
1052                                 LDAP_LOG( CONFIG, CRIT, 
1053                                         "%s: line %d: suffix DN is invalid.\n",
1054                                         fname, lineno, 0 );
1055 #else
1056                                 Debug( LDAP_DEBUG_ANY,
1057                                         "%s: line %d: suffix DN is invalid\n",
1058                                    fname, lineno, 0 );
1059 #endif
1060                                 return( 1 );
1061                         }
1062
1063                         tmp_be = select_backend( &ndn, 0, 0 );
1064                         if ( tmp_be == be ) {
1065 #ifdef NEW_LOGGING
1066                                 LDAP_LOG( CONFIG, INFO, 
1067                                         "%s: line %d: suffix already served by this backend "
1068                                         "(ignored)\n", fname, lineno, 0 );
1069 #else
1070                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix "
1071                                         "already served by this backend (ignored)\n",
1072                                     fname, lineno, 0 );
1073 #endif
1074                                 free( pdn.bv_val );
1075                                 free( ndn.bv_val );
1076
1077                         } else if ( tmp_be  != NULL ) {
1078 #ifdef NEW_LOGGING
1079                                 LDAP_LOG( CONFIG, INFO, 
1080                                         "%s: line %d: suffix already served by a preceding "
1081                                         "backend \"%s\"\n", fname, lineno,
1082                                         tmp_be->be_suffix[0].bv_val );
1083 #else
1084                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix "
1085                                         "already served by a preceeding backend \"%s\"\n",
1086                                     fname, lineno, tmp_be->be_suffix[0].bv_val );
1087 #endif
1088                                 free( pdn.bv_val );
1089                                 free( ndn.bv_val );
1090                                 return( 1 );
1091
1092                         } else if( pdn.bv_len == 0 && default_search_nbase.bv_len ) {
1093 #ifdef NEW_LOGGING
1094                                         LDAP_LOG( CONFIG, INFO, 
1095                                                 "%s: line %d: suffix DN empty and default search "
1096                                                 "base provided \"%s\" (assuming okay).\n",
1097                                                 fname, lineno, default_search_base.bv_val );
1098 #else
1099                                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1100                                                 "suffix DN empty and default "
1101                                                 "search base provided \"%s\" (assuming okay)\n",
1102                                         fname, lineno, default_search_base.bv_val );
1103 #endif
1104                         }
1105
1106                         ber_bvarray_add( &be->be_suffix, &pdn );
1107                         ber_bvarray_add( &be->be_nsuffix, &ndn );
1108
1109                /* set max deref depth */
1110                } else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
1111                                         int i;
1112                        if ( cargc < 2 ) {
1113 #ifdef NEW_LOGGING
1114                                LDAP_LOG( CONFIG, CRIT, 
1115                                           "%s: line %d: missing depth in \"maxDerefDepth <depth>\""
1116                                           " line\n", fname, lineno, 0 );
1117 #else
1118                                Debug( LDAP_DEBUG_ANY,
1119                    "%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
1120                                    fname, lineno, 0 );
1121 #endif
1122
1123                                return( 1 );
1124                        }
1125                        if ( be == NULL ) {
1126 #ifdef NEW_LOGGING
1127                                LDAP_LOG( CONFIG, INFO, 
1128                                           "%s: line %d: depth line must appear inside a database "
1129                                           "definition.\n", fname, lineno ,0 );
1130 #else
1131                                Debug( LDAP_DEBUG_ANY,
1132 "%s: line %d: depth line must appear inside a database definition.\n",
1133                                    fname, lineno, 0 );
1134 #endif
1135                                                         return 1;
1136
1137                        } else if ((i = atoi(cargv[1])) < 0) {
1138 #ifdef NEW_LOGGING
1139                                LDAP_LOG( CONFIG, INFO, 
1140                                           "%s: line %d: depth must be positive.\n",
1141                                           fname, lineno ,0 );
1142 #else
1143                                Debug( LDAP_DEBUG_ANY,
1144 "%s: line %d: depth must be positive.\n",
1145                                    fname, lineno, 0 );
1146 #endif
1147                                                         return 1;
1148
1149
1150                        } else {
1151                            be->be_max_deref_depth = i;
1152                                            }
1153
1154
1155                 /* set magic "root" dn for this database */
1156                 } else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) {
1157                         if ( cargc < 2 ) {
1158 #ifdef NEW_LOGGING
1159                                 LDAP_LOG( CONFIG, INFO, 
1160                                            "%s: line %d: missing dn in \"rootdn <dn>\" line.\n",
1161                                            fname, lineno ,0 );
1162 #else
1163                                 Debug( LDAP_DEBUG_ANY,
1164                     "%s: line %d: missing dn in \"rootdn <dn>\" line\n",
1165                                     fname, lineno, 0 );
1166 #endif
1167
1168                                 return( 1 );
1169                         }
1170
1171                         if ( be == NULL ) {
1172 #ifdef NEW_LOGGING
1173                                 LDAP_LOG( CONFIG, INFO, 
1174                                            "%s: line %d: rootdn line must appear inside a database "
1175                                            "definition.\n", fname, lineno ,0 );
1176 #else
1177                                 Debug( LDAP_DEBUG_ANY,
1178 "%s: line %d: rootdn line must appear inside a database definition.\n",
1179                                     fname, lineno, 0 );
1180 #endif
1181                                 return 1;
1182
1183                         } else {
1184                                 struct berval dn;
1185                                 
1186                                 if ( load_ucdata( NULL ) < 0 ) return 1;
1187
1188                                 dn.bv_val = cargv[1];
1189                                 dn.bv_len = strlen( cargv[1] );
1190
1191                                 rc = dnPrettyNormal( NULL, &dn,
1192                                         &be->be_rootdn,
1193                                         &be->be_rootndn, NULL );
1194
1195                                 if( rc != LDAP_SUCCESS ) {
1196 #ifdef NEW_LOGGING
1197                                         LDAP_LOG( CONFIG, CRIT, 
1198                                                 "%s: line %d: rootdn DN is invalid.\n", 
1199                                                 fname, lineno ,0 );
1200 #else
1201                                         Debug( LDAP_DEBUG_ANY,
1202                                                 "%s: line %d: rootdn DN is invalid\n",
1203                                            fname, lineno, 0 );
1204 #endif
1205                                         return( 1 );
1206                                 }
1207                         }
1208
1209                 /* set super-secret magic database password */
1210                 } else if ( strcasecmp( cargv[0], "rootpw" ) == 0 ) {
1211                         if ( cargc < 2 ) {
1212 #ifdef NEW_LOGGING
1213                                 LDAP_LOG( CONFIG, CRIT, 
1214                                         "%s: line %d: missing passwd in \"rootpw <passwd>\""
1215                                         " line\n", fname, lineno ,0 );
1216 #else
1217                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1218                                         "missing passwd in \"rootpw <passwd>\" line\n",
1219                                     fname, lineno, 0 );
1220 #endif
1221
1222                                 return( 1 );
1223                         }
1224
1225                         if ( be == NULL ) {
1226 #ifdef NEW_LOGGING
1227                                 LDAP_LOG( CONFIG, INFO, "%s: line %d: "
1228                                         "rootpw line must appear inside a database "
1229                                         "definition.\n", fname, lineno ,0 );
1230 #else
1231                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1232                                         "rootpw line must appear inside a database "
1233                                         "definition.\n",
1234                                     fname, lineno, 0 );
1235 #endif
1236                                 return 1;
1237
1238                         } else {
1239                                 Backend *tmp_be = select_backend( &be->be_rootndn, 0, 0 );
1240
1241                                 if( tmp_be != be ) {
1242 #ifdef NEW_LOGGING
1243                                         LDAP_LOG( CONFIG, INFO,
1244                                                 "%s: line %d: "
1245                                                 "rootpw can only be set when rootdn is under suffix\n",
1246                                                 fname, lineno, "" );
1247 #else
1248                                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1249                                                 "rootpw can only be set when rootdn is under suffix\n",
1250                                         fname, lineno, 0 );
1251 #endif
1252                                         return 1;
1253                                 }
1254
1255                                 be->be_rootpw.bv_val = ch_strdup( cargv[1] );
1256                                 be->be_rootpw.bv_len = strlen( be->be_rootpw.bv_val );
1257                         }
1258
1259                 /* make this database read-only */
1260                 } else if ( strcasecmp( cargv[0], "readonly" ) == 0 ) {
1261                         if ( cargc < 2 ) {
1262 #ifdef NEW_LOGGING
1263                                 LDAP_LOG( CONFIG, CRIT, 
1264                                         "%s: line %d: missing on|off in \"readonly <on|off>\" "
1265                                         "line.\n", fname, lineno ,0 );
1266 #else
1267                                 Debug( LDAP_DEBUG_ANY,
1268             "%s: line %d: missing on|off in \"readonly <on|off>\" line\n",
1269                                     fname, lineno, 0 );
1270 #endif
1271
1272                                 return( 1 );
1273                         }
1274                         if ( be == NULL ) {
1275                                 if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1276                                         global_restrictops |= SLAP_RESTRICT_OP_WRITES;
1277                                 } else {
1278                                         global_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
1279                                 }
1280                         } else {
1281                                 if ( strcasecmp( cargv[1], "on" ) == 0 ) {
1282                                         be->be_restrictops |= SLAP_RESTRICT_OP_WRITES;
1283                                 } else {
1284                                         be->be_restrictops &= ~SLAP_RESTRICT_OP_WRITES;
1285                                 }
1286                         }
1287
1288
1289                 /* allow these features */
1290                 } else if ( strcasecmp( cargv[0], "allows" ) == 0 ||
1291                         strcasecmp( cargv[0], "allow" ) == 0 )
1292                 {
1293                         slap_mask_t     allows;
1294
1295                         if ( be != NULL ) {
1296 #ifdef NEW_LOGGING
1297                                 LDAP_LOG( CONFIG, INFO, 
1298                                            "%s: line %d: allow line must appear prior to "
1299                                            "database definitions.\n", fname, lineno ,0 );
1300 #else
1301                                 Debug( LDAP_DEBUG_ANY,
1302 "%s: line %d: allow line must appear prior to database definitions\n",
1303                                     fname, lineno, 0 );
1304 #endif
1305
1306                         }
1307
1308                         if ( cargc < 2 ) {
1309 #ifdef NEW_LOGGING
1310                                 LDAP_LOG( CONFIG, CRIT, 
1311                                            "%s: line %d: missing feature(s) in \"allow <features>\""
1312                                            " line\n", fname, lineno ,0 );
1313 #else
1314                                 Debug( LDAP_DEBUG_ANY,
1315             "%s: line %d: missing feature(s) in \"allow <features>\" line\n",
1316                                     fname, lineno, 0 );
1317 #endif
1318
1319                                 return( 1 );
1320                         }
1321
1322                         allows = 0;
1323
1324                         for( i=1; i < cargc; i++ ) {
1325                                 if( strcasecmp( cargv[i], "bind_v2" ) == 0 ) {
1326                                         allows |= SLAP_ALLOW_BIND_V2;
1327
1328                                 } else if( strcasecmp( cargv[i], "bind_anon_cred" ) == 0 ) {
1329                                         allows |= SLAP_ALLOW_BIND_ANON_CRED;
1330
1331                                 } else if( strcasecmp( cargv[i], "bind_anon_dn" ) == 0 ) {
1332                                         allows |= SLAP_ALLOW_BIND_ANON_DN;
1333
1334                                 } else if( strcasecmp( cargv[i], "update_anon" ) == 0 ) {
1335                                         allows |= SLAP_ALLOW_UPDATE_ANON;
1336
1337                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1338 #ifdef NEW_LOGGING
1339                                         LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
1340                                                 "unknown feature %s in \"allow <features>\" line.\n",
1341                                                 fname, lineno, cargv[1] );
1342 #else
1343                                         Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1344                                                 "unknown feature %s in \"allow <features>\" line\n",
1345                                                 fname, lineno, cargv[i] );
1346 #endif
1347
1348                                         return( 1 );
1349                                 }
1350                         }
1351
1352                         global_allows = allows;
1353
1354                 /* disallow these features */
1355                 } else if ( strcasecmp( cargv[0], "disallows" ) == 0 ||
1356                         strcasecmp( cargv[0], "disallow" ) == 0 )
1357                 {
1358                         slap_mask_t     disallows;
1359
1360                         if ( be != NULL ) {
1361 #ifdef NEW_LOGGING
1362                                 LDAP_LOG( CONFIG, INFO, 
1363                                            "%s: line %d: disallow line must appear prior to "
1364                                            "database definitions.\n", fname, lineno ,0 );
1365 #else
1366                                 Debug( LDAP_DEBUG_ANY,
1367 "%s: line %d: disallow line must appear prior to database definitions\n",
1368                                     fname, lineno, 0 );
1369 #endif
1370
1371                         }
1372
1373                         if ( cargc < 2 ) {
1374 #ifdef NEW_LOGGING
1375                                 LDAP_LOG( CONFIG, CRIT, 
1376                                         "%s: line %d: missing feature(s) in \"disallow <features>\""
1377                                         " line.\n", fname, lineno ,0 );
1378 #else
1379                                 Debug( LDAP_DEBUG_ANY,
1380             "%s: line %d: missing feature(s) in \"disallow <features>\" line\n",
1381                                     fname, lineno, 0 );
1382 #endif
1383
1384                                 return( 1 );
1385                         }
1386
1387                         disallows = 0;
1388
1389                         for( i=1; i < cargc; i++ ) {
1390                                 if( strcasecmp( cargv[i], "bind_anon" ) == 0 ) {
1391                                         disallows |= SLAP_DISALLOW_BIND_ANON;
1392
1393                                 } else if( strcasecmp( cargv[i], "bind_simple" ) == 0 ) {
1394                                         disallows |= SLAP_DISALLOW_BIND_SIMPLE;
1395
1396                                 } else if( strcasecmp( cargv[i], "bind_krbv4" ) == 0 ) {
1397                                         disallows |= SLAP_DISALLOW_BIND_KRBV4;
1398
1399                                 } else if( strcasecmp( cargv[i], "tls_2_anon" ) == 0 ) {
1400                                         disallows |= SLAP_DISALLOW_TLS_2_ANON;
1401
1402                                 } else if( strcasecmp( cargv[i], "tls_authc" ) == 0 ) {
1403                                         disallows |= SLAP_DISALLOW_TLS_AUTHC;
1404
1405                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1406 #ifdef NEW_LOGGING
1407                                         LDAP_LOG( CONFIG, CRIT, 
1408                                                 "%s: line %d: unknown feature %s in "
1409                                                 "\"disallow <features>\" line.\n",
1410                                                 fname, lineno, cargv[i] );
1411 #else
1412                                         Debug( LDAP_DEBUG_ANY,
1413                     "%s: line %d: unknown feature %s in \"disallow <features>\" line\n",
1414                                             fname, lineno, cargv[i] );
1415 #endif
1416
1417                                         return( 1 );
1418                                 }
1419                         }
1420
1421                         global_disallows = disallows;
1422
1423                 /* require these features */
1424                 } else if ( strcasecmp( cargv[0], "requires" ) == 0 ||
1425                         strcasecmp( cargv[0], "require" ) == 0 )
1426                 {
1427                         slap_mask_t     requires;
1428
1429                         if ( cargc < 2 ) {
1430 #ifdef NEW_LOGGING
1431                                 LDAP_LOG( CONFIG, CRIT, 
1432                                            "%s: line %d: missing feature(s) in "
1433                                            "\"require <features>\" line.\n", fname, lineno ,0 );
1434 #else
1435                                 Debug( LDAP_DEBUG_ANY,
1436             "%s: line %d: missing feature(s) in \"require <features>\" line\n",
1437                                     fname, lineno, 0 );
1438 #endif
1439
1440                                 return( 1 );
1441                         }
1442
1443                         requires = 0;
1444
1445                         for( i=1; i < cargc; i++ ) {
1446                                 if( strcasecmp( cargv[i], "bind" ) == 0 ) {
1447                                         requires |= SLAP_REQUIRE_BIND;
1448
1449                                 } else if( strcasecmp( cargv[i], "LDAPv3" ) == 0 ) {
1450                                         requires |= SLAP_REQUIRE_LDAP_V3;
1451
1452                                 } else if( strcasecmp( cargv[i], "authc" ) == 0 ) {
1453                                         requires |= SLAP_REQUIRE_AUTHC;
1454
1455                                 } else if( strcasecmp( cargv[i], "SASL" ) == 0 ) {
1456                                         requires |= SLAP_REQUIRE_SASL;
1457
1458                                 } else if( strcasecmp( cargv[i], "strong" ) == 0 ) {
1459                                         requires |= SLAP_REQUIRE_STRONG;
1460
1461                                 } else if( strcasecmp( cargv[i], "none" ) != 0 ) {
1462 #ifdef NEW_LOGGING
1463                                         LDAP_LOG( CONFIG, CRIT, 
1464                                                    "%s: line %d: unknown feature %s in "
1465                                                    "\"require <features>\" line.\n", 
1466                                                    fname, lineno , cargv[i] );
1467 #else
1468                                         Debug( LDAP_DEBUG_ANY,
1469                     "%s: line %d: unknown feature %s in \"require <features>\" line\n",
1470                                             fname, lineno, cargv[i] );
1471 #endif
1472
1473                                         return( 1 );
1474                                 }
1475                         }
1476
1477                         if ( be == NULL ) {
1478                                 global_requires = requires;
1479                         } else {
1480                                 be->be_requires = requires;
1481                         }
1482
1483                 /* required security factors */
1484                 } else if ( strcasecmp( cargv[0], "security" ) == 0 ) {
1485                         slap_ssf_set_t *set;
1486
1487                         if ( cargc < 2 ) {
1488 #ifdef NEW_LOGGING
1489                                 LDAP_LOG( CONFIG, CRIT, 
1490                                         "%s: line %d: missing factor(s) in \"security <factors>\""
1491                                         " line.\n", fname, lineno ,0 );
1492 #else
1493                                 Debug( LDAP_DEBUG_ANY,
1494             "%s: line %d: missing factor(s) in \"security <factors>\" line\n",
1495                                     fname, lineno, 0 );
1496 #endif
1497
1498                                 return( 1 );
1499                         }
1500
1501                         if ( be == NULL ) {
1502                                 set = &global_ssf_set;
1503                         } else {
1504                                 set = &be->be_ssf_set;
1505                         }
1506
1507                         for( i=1; i < cargc; i++ ) {
1508                                 if( strncasecmp( cargv[i], "ssf=",
1509                                         sizeof("ssf") ) == 0 )
1510                                 {
1511                                         set->sss_ssf =
1512                                                 atoi( &cargv[i][sizeof("ssf")] );
1513
1514                                 } else if( strncasecmp( cargv[i], "transport=",
1515                                         sizeof("transport") ) == 0 )
1516                                 {
1517                                         set->sss_transport =
1518                                                 atoi( &cargv[i][sizeof("transport")] );
1519
1520                                 } else if( strncasecmp( cargv[i], "tls=",
1521                                         sizeof("tls") ) == 0 )
1522                                 {
1523                                         set->sss_tls =
1524                                                 atoi( &cargv[i][sizeof("tls")] );
1525
1526                                 } else if( strncasecmp( cargv[i], "sasl=",
1527                                         sizeof("sasl") ) == 0 )
1528                                 {
1529                                         set->sss_sasl =
1530                                                 atoi( &cargv[i][sizeof("sasl")] );
1531
1532                                 } else if( strncasecmp( cargv[i], "update_ssf=",
1533                                         sizeof("update_ssf") ) == 0 )
1534                                 {
1535                                         set->sss_update_ssf =
1536                                                 atoi( &cargv[i][sizeof("update_ssf")] );
1537
1538                                 } else if( strncasecmp( cargv[i], "update_transport=",
1539                                         sizeof("update_transport") ) == 0 )
1540                                 {
1541                                         set->sss_update_transport =
1542                                                 atoi( &cargv[i][sizeof("update_transport")] );
1543
1544                                 } else if( strncasecmp( cargv[i], "update_tls=",
1545                                         sizeof("update_tls") ) == 0 )
1546                                 {
1547                                         set->sss_update_tls =
1548                                                 atoi( &cargv[i][sizeof("update_tls")] );
1549
1550                                 } else if( strncasecmp( cargv[i], "update_sasl=",
1551                                         sizeof("update_sasl") ) == 0 )
1552                                 {
1553                                         set->sss_update_sasl =
1554                                                 atoi( &cargv[i][sizeof("update_sasl")] );
1555
1556                                 } else if( strncasecmp( cargv[i], "simple_bind=",
1557                                         sizeof("simple_bind") ) == 0 )
1558                                 {
1559                                         set->sss_simple_bind =
1560                                                 atoi( &cargv[i][sizeof("simple_bind")] );
1561
1562                                 } else {
1563 #ifdef NEW_LOGGING
1564                                         LDAP_LOG( CONFIG, CRIT, 
1565                                                    "%s: line %d: unknown factor %S in "
1566                                                    "\"security <factors>\" line.\n",
1567                                                    fname, lineno, cargv[1] );
1568 #else
1569                                         Debug( LDAP_DEBUG_ANY,
1570                     "%s: line %d: unknown factor %s in \"security <factors>\" line\n",
1571                                             fname, lineno, cargv[i] );
1572 #endif
1573
1574                                         return( 1 );
1575                                 }
1576                         }
1577                 /* where to send clients when we don't hold it */
1578                 } else if ( strcasecmp( cargv[0], "referral" ) == 0 ) {
1579                         if ( cargc < 2 ) {
1580 #ifdef NEW_LOGGING
1581                                 LDAP_LOG( CONFIG, CRIT, 
1582                                         "%s: line %d: missing URL in \"referral <URL>\""
1583                                         " line.\n", fname, lineno , 0 );
1584 #else
1585                                 Debug( LDAP_DEBUG_ANY,
1586                     "%s: line %d: missing URL in \"referral <URL>\" line\n",
1587                                     fname, lineno, 0 );
1588 #endif
1589
1590                                 return( 1 );
1591                         }
1592
1593                         if( validate_global_referral( cargv[1] ) ) {
1594 #ifdef NEW_LOGGING
1595                                 LDAP_LOG( CONFIG, CRIT, 
1596                                         "%s: line %d: invalid URL (%s) in \"referral\" line.\n",
1597                                         fname, lineno, cargv[1]  );
1598 #else
1599                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1600                                         "invalid URL (%s) in \"referral\" line.\n",
1601                                     fname, lineno, cargv[1] );
1602 #endif
1603                                 return 1;
1604                         }
1605
1606                         vals[0].bv_val = cargv[1];
1607                         vals[0].bv_len = strlen( vals[0].bv_val );
1608                         if( value_add( &default_referral, vals ) )
1609                                 return LDAP_OTHER;
1610
1611 #ifdef NEW_LOGGING
1612                 } else if ( strcasecmp( cargv[0], "logfile" ) == 0 ) {
1613                         FILE *logfile;
1614                         if ( cargc < 2 ) {
1615 #ifdef NEW_LOGGING
1616                                 LDAP_LOG( CONFIG, CRIT, 
1617                                         "%s: line %d: Error in logfile directive, "
1618                                         "\"logfile <filename>\"\n", fname, lineno , 0 );
1619 #else
1620                                 Debug( LDAP_DEBUG_ANY,
1621                                        "%s: line %d: Error in logfile directive, \"logfile filename\"\n",
1622                                        fname, lineno, 0 );
1623 #endif
1624
1625                                 return( 1 );
1626                         }
1627                         logfile = fopen( cargv[1], "w" );
1628                         if ( logfile != NULL ) lutil_debug_file( logfile  );
1629
1630 #endif
1631                 /* start of a new database definition */
1632                 } else if ( strcasecmp( cargv[0], "debug" ) == 0 ) {
1633                         int level;
1634                         if ( cargc < 3 ) {
1635 #ifdef NEW_LOGGING
1636                                 LDAP_LOG( CONFIG, CRIT, 
1637                                            "%s: line %d: Error in debug directive, "
1638                                            "\"debug <subsys> <level>\"\n", fname, lineno , 0 );
1639 #else
1640                                 Debug( LDAP_DEBUG_ANY,
1641                                         "%s: line %d: Error in debug directive, \"debug subsys level\"\n",
1642                                         fname, lineno, 0 );
1643 #endif
1644
1645                                 return( 1 );
1646                         }
1647                         level = atoi( cargv[2] );
1648                         if ( level <= 0 ) level = lutil_mnem2level( cargv[2] );
1649                         lutil_set_debug_level( cargv[1], level );
1650                 /* specify an Object Identifier macro */
1651                 } else if ( strcasecmp( cargv[0], "objectidentifier" ) == 0 ) {
1652                         rc = parse_oidm( fname, lineno, cargc, cargv );
1653                         if( rc ) return rc;
1654
1655                 /* specify an objectclass */
1656                 } else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
1657                         if ( cargc < 2 ) {
1658 #ifdef NEW_LOGGING
1659                                 LDAP_LOG( CONFIG, INFO, 
1660                                         "%s: line %d: illegal objectclass format.\n",
1661                                         fname, lineno , 0 );
1662 #else
1663                                 Debug( LDAP_DEBUG_ANY,
1664                                        "%s: line %d: illegal objectclass format.\n",
1665                                        fname, lineno, 0 );
1666 #endif
1667                                 return( 1 );
1668
1669                         } else if ( *cargv[1] == '('  /*')'*/) {
1670                                 char * p;
1671                                 p = strchr(saveline,'(' /*')'*/);
1672                                 rc = parse_oc( fname, lineno, p, cargv );
1673                                 if( rc ) return rc;
1674
1675                         } else {
1676 #ifdef NEW_LOGGING
1677                                 LDAP_LOG( CONFIG, INFO, 
1678                                         "%s: line %d: old objectclass format not supported\n",
1679                                         fname, lineno , 0 );
1680 #else
1681                                 Debug( LDAP_DEBUG_ANY,
1682                                        "%s: line %d: old objectclass format not supported.\n",
1683                                        fname, lineno, 0 );
1684 #endif
1685                         }
1686
1687                 } else if ( strcasecmp( cargv[0], "ditcontentrule" ) == 0 ) {
1688                         char * p;
1689                         p = strchr(saveline,'(' /*')'*/);
1690                         rc = parse_cr( fname, lineno, p, cargv );
1691                         if( rc ) return rc;
1692
1693                 /* specify an attribute type */
1694                 } else if (( strcasecmp( cargv[0], "attributetype" ) == 0 )
1695                         || ( strcasecmp( cargv[0], "attribute" ) == 0 ))
1696                 {
1697                         if ( cargc < 2 ) {
1698 #ifdef NEW_LOGGING
1699                                 LDAP_LOG( CONFIG, INFO, "%s: line %d: "
1700                                         "illegal attribute type format.\n",
1701                                         fname, lineno , 0 );
1702 #else
1703                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1704                                         "illegal attribute type format.\n",
1705                                         fname, lineno, 0 );
1706 #endif
1707                                 return( 1 );
1708
1709                         } else if ( *cargv[1] == '(' /*')'*/) {
1710                                 char * p;
1711                                 p = strchr(saveline,'(' /*')'*/);
1712                                 rc = parse_at( fname, lineno, p, cargv );
1713                                 if( rc ) return rc;
1714
1715                         } else {
1716 #ifdef NEW_LOGGING
1717                                 LDAP_LOG( CONFIG, INFO, 
1718                                         "%s: line %d: old attribute type format not supported.\n",
1719                                         fname, lineno , 0 );
1720 #else
1721                                 Debug( LDAP_DEBUG_ANY,
1722     "%s: line %d: old attribute type format not supported.\n",
1723                                     fname, lineno, 0 );
1724 #endif
1725
1726                         }
1727
1728                 /* define attribute option(s) */
1729                 } else if ( strcasecmp( cargv[0], "attributeoptions" ) == 0 ) {
1730                         ad_define_option( NULL, NULL, 0 );
1731                         for ( i = 1; i < cargc; i++ )
1732                                 if ( ad_define_option( cargv[i], fname, lineno ) != 0 )
1733                                         return 1;
1734
1735                 /* turn on/off schema checking */
1736                 } else if ( strcasecmp( cargv[0], "schemacheck" ) == 0 ) {
1737                         if ( cargc < 2 ) {
1738 #ifdef NEW_LOGGING
1739                                 LDAP_LOG( CONFIG, CRIT, 
1740                                         "%s: line %d: missing on|off in \"schemacheck <on|off>\""
1741                                         " line.\n", fname, lineno , 0 );
1742 #else
1743                                 Debug( LDAP_DEBUG_ANY,
1744     "%s: line %d: missing on|off in \"schemacheck <on|off>\" line\n",
1745                                     fname, lineno, 0 );
1746 #endif
1747
1748                                 return( 1 );
1749                         }
1750                         if ( strcasecmp( cargv[1], "off" ) == 0 ) {
1751 #ifdef NEW_LOGGING
1752                                 LDAP_LOG( CONFIG, CRIT, 
1753                                         "%s: line %d: schema checking disabled! your mileage may "
1754                                         "vary!\n", fname, lineno , 0 );
1755 #else
1756                                 Debug( LDAP_DEBUG_ANY,
1757                                         "%s: line %d: schema checking disabled! your mileage may vary!\n",
1758                                     fname, lineno, 0 );
1759 #endif
1760                                 global_schemacheck = 0;
1761                         } else {
1762                                 global_schemacheck = 1;
1763                         }
1764
1765                 /* specify access control info */
1766                 } else if ( strcasecmp( cargv[0], "access" ) == 0 ) {
1767                         parse_acl( be, fname, lineno, cargc, cargv );
1768
1769                 /* debug level to log things to syslog */
1770                 } else if ( strcasecmp( cargv[0], "loglevel" ) == 0 ) {
1771                         if ( cargc < 2 ) {
1772 #ifdef NEW_LOGGING
1773                                 LDAP_LOG( CONFIG, CRIT, 
1774                                         "%s: line %d: missing level in \"loglevel <level>\""
1775                                         " line.\n", fname, lineno , 0 );
1776 #else
1777                                 Debug( LDAP_DEBUG_ANY,
1778                     "%s: line %d: missing level in \"loglevel <level>\" line\n",
1779                                     fname, lineno, 0 );
1780 #endif
1781
1782                                 return( 1 );
1783                         }
1784
1785                         ldap_syslog = 0;
1786
1787                         for( i=1; i < cargc; i++ ) {
1788                                 ldap_syslog += atoi( cargv[1] );
1789                         }
1790
1791                 /* list of sync replication information in this backend (slave only) */
1792                 } else if ( strcasecmp( cargv[0], "syncrepl" ) == 0 ) {
1793
1794                         if ( be == NULL ) {
1795 #ifdef NEW_LOGGING
1796                                 LDAP_LOG( CONFIG, INFO, 
1797                                             "%s: line %d: syncrepl line must appear inside "
1798                                             "a database definition.\n", fname, lineno, 0);
1799 #else
1800                                 Debug( LDAP_DEBUG_ANY,
1801                                             "%s: line %d: syncrepl line must appear inside "
1802                                             "a database definition.\n", fname, lineno, 0);
1803 #endif
1804                                 return 1;
1805
1806                         } else if ( SLAP_SHADOW( be )) {
1807 #ifdef NEW_LOGGING
1808                                 LDAP_LOG( CONFIG, INFO, 
1809                                         "%s: line %d: syncrepl: database already shadowed.\n",
1810                                         fname, lineno, 0);
1811 #else
1812                                 Debug( LDAP_DEBUG_ANY,
1813                                         "%s: line %d: syncrepl: database already shadowed.\n",
1814                                         fname, lineno, 0);
1815 #endif
1816                                 return 1;
1817
1818                         } else if ( add_syncrepl( be, cargv, cargc )) {
1819                                 return 1;
1820                         }
1821
1822                         SLAP_DBFLAGS(be) |= SLAP_DBFLAG_SHADOW;
1823
1824                 /* list of replicas of the data in this backend (master only) */
1825                 } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
1826                         if ( cargc < 2 ) {
1827 #ifdef NEW_LOGGING
1828                                 LDAP_LOG( CONFIG, CRIT, 
1829                                         "%s: line %d: missing host or uri in \"replica "
1830                                         " <host[:port]\" line\n", fname, lineno , 0 );
1831 #else
1832                                 Debug( LDAP_DEBUG_ANY,
1833             "%s: line %d: missing host or uri in \"replica <host[:port]>\" line\n",
1834                                     fname, lineno, 0 );
1835 #endif
1836
1837                                 return( 1 );
1838                         }
1839                         if ( be == NULL ) {
1840 #ifdef NEW_LOGGING
1841                                 LDAP_LOG( CONFIG, INFO, 
1842                                             "%s: line %d: replica line must appear inside "
1843                                             "a database definition.\n", fname, lineno, 0);
1844 #else
1845                                 Debug( LDAP_DEBUG_ANY,
1846 "%s: line %d: replica line must appear inside a database definition\n",
1847                                     fname, lineno, 0 );
1848 #endif
1849                                 return 1;
1850
1851                         } else {
1852                                 int nr = -1;
1853
1854                                 for ( i = 1; i < cargc; i++ ) {
1855                                         if ( strncasecmp( cargv[i], "host=", 5 )
1856                                             == 0 ) {
1857                                                 nr = add_replica_info( be, 
1858                                                         cargv[i] + 5 );
1859                                                 break;
1860                                         } else if (strncasecmp( cargv[i], "uri=", 4 )
1861                                             == 0 ) {
1862                                             if ( ldap_url_parse( cargv[ i ] + 4, &ludp )
1863                                                 != LDAP_SUCCESS ) {
1864 #ifdef NEW_LOGGING
1865                                                         LDAP_LOG( CONFIG, INFO, 
1866                                                         "%s: line %d: replica line contains invalid "
1867                                                         "uri definition.\n", fname, lineno, 0);
1868 #else
1869                                                         Debug( LDAP_DEBUG_ANY,
1870                                                         "%s: line %d: replica line contains invalid "
1871                                                         "uri definition.\n", fname, lineno, 0);
1872 #endif
1873                                                         return 1;
1874                                                 }
1875                                                 if (ludp->lud_host == NULL ) {
1876 #ifdef NEW_LOGGING
1877                                                         LDAP_LOG( CONFIG, INFO, 
1878                                                         "%s: line %d: replica line contains invalid "
1879                                                         "uri definition - missing hostname.\n", 
1880                                                         fname, lineno, 0);
1881 #else
1882                                                         Debug( LDAP_DEBUG_ANY,
1883                                                         "%s: line %d: replica line contains invalid "
1884                                                         "uri definition - missing hostname.\n", fname, lineno, 0);
1885 #endif
1886                                                         return 1;
1887                                                 }
1888                                         replicahost = ch_malloc( strlen( cargv[ i ] ) );
1889                                                 if ( replicahost == NULL ) {
1890 #ifdef NEW_LOGGING
1891                                                         LDAP_LOG( CONFIG, ERR, 
1892                                                         "out of memory in read_config\n", 0, 0,0 );
1893 #else
1894                                                         Debug( LDAP_DEBUG_ANY, 
1895                                                         "out of memory in read_config\n", 0, 0, 0 );
1896 #endif
1897                                                         ldap_free_urldesc( ludp );                              
1898                                                         exit( EXIT_FAILURE );
1899                                                 }
1900                                                 sprintf(replicahost, "%s:%d", 
1901                                                         ludp->lud_host, ludp->lud_port);
1902                                                 nr = add_replica_info( be, replicahost );
1903                                                 ldap_free_urldesc( ludp );                              
1904                                                 ch_free(replicahost);
1905                                                 break;
1906                                         }
1907                                 }
1908                                 if ( i == cargc ) {
1909 #ifdef NEW_LOGGING
1910                                         LDAP_LOG( CONFIG, INFO, 
1911                                                 "%s: line %d: missing host or uri in \"replica\" line\n", 
1912                                                 fname, lineno , 0 );
1913 #else
1914                                         Debug( LDAP_DEBUG_ANY,
1915                     "%s: line %d: missing host or uri in \"replica\" line\n",
1916                                             fname, lineno, 0 );
1917 #endif
1918                                         return 1;
1919
1920                                 } else if ( nr == -1 ) {
1921 #ifdef NEW_LOGGING
1922                                         LDAP_LOG( CONFIG, INFO, 
1923                                                    "%s: line %d: unable to add"
1924                                                    " replica \"%s\"\n",
1925                                                    fname, lineno, 
1926                                                    cargv[i] + 5 );
1927 #else
1928                                         Debug( LDAP_DEBUG_ANY,
1929                 "%s: line %d: unable to add replica \"%s\"\n",
1930                                                 fname, lineno, cargv[i] + 5 );
1931 #endif
1932                                         return 1;
1933                                 } else {
1934                                         for ( i = 1; i < cargc; i++ ) {
1935                                                 if ( strncasecmp( cargv[i], "suffix=", 7 ) == 0 ) {
1936
1937                                                         switch ( add_replica_suffix( be, nr, cargv[i] + 7 ) ) {
1938                                                         case 1:
1939 #ifdef NEW_LOGGING
1940                                                                 LDAP_LOG( CONFIG, INFO, 
1941                                                                         "%s: line %d: suffix \"%s\" in \"replica\""
1942                                                                         " line is not valid for backend(ignored)\n",
1943                                                                         fname, lineno, cargv[i] + 7 );
1944 #else
1945                                                                 Debug( LDAP_DEBUG_ANY,
1946                                                                                 "%s: line %d: suffix \"%s\" in \"replica\" line is not valid for backend (ignored)\n",
1947                                                                                 fname, lineno, cargv[i] + 7 );
1948 #endif
1949                                                                 break;
1950
1951                                                         case 2:
1952 #ifdef NEW_LOGGING
1953                                                                 LDAP_LOG( CONFIG, INFO, 
1954                                                                         "%s: line %d: unable to normalize suffix"
1955                                                                         " in \"replica\" line (ignored)\n",
1956                                                                         fname, lineno , 0 );
1957 #else
1958                                                                 Debug( LDAP_DEBUG_ANY,
1959                                                                                  "%s: line %d: unable to normalize suffix in \"replica\" line (ignored)\n",
1960                                                                                  fname, lineno, 0 );
1961 #endif
1962                                                                 break;
1963                                                         }
1964
1965                                                 } else if ( strncasecmp( cargv[i], "attr", 4 ) == 0 ) {
1966                                                         int exclude = 0;
1967                                                         char *arg = cargv[i] + 4;
1968
1969                                                         if ( arg[0] == '!' ) {
1970                                                                 arg++;
1971                                                                 exclude = 1;
1972                                                         }
1973
1974                                                         if ( arg[0] != '=' ) {
1975                                                                 continue;
1976                                                         }
1977
1978                                                         if ( add_replica_attrs( be, nr, arg + 1, exclude ) ) {
1979 #ifdef NEW_LOGGING
1980                                                                 LDAP_LOG( CONFIG, INFO, 
1981                                                                         "%s: line %d: attribute \"%s\" in "
1982                                                                         "\"replica\" line is unknown\n",
1983                                                                         fname, lineno, arg + 1 ); 
1984 #else
1985                                                                 Debug( LDAP_DEBUG_ANY,
1986                                                                                 "%s: line %d: attribute \"%s\" in \"replica\" line is unknown\n",
1987                                                                                 fname, lineno, arg + 1 );
1988 #endif
1989                                                                 return( 1 );
1990                                                         }
1991                                                 }
1992                                         }
1993                                 }
1994                         }
1995
1996                 } else if ( strcasecmp( cargv[0], "replicationInterval" ) == 0 ) {
1997                         /* ignore */
1998
1999                 /* dn of slave entity allowed to write to replica */
2000                 } else if ( strcasecmp( cargv[0], "updatedn" ) == 0 ) {
2001                         if ( cargc < 2 ) {
2002 #ifdef NEW_LOGGING
2003                                 LDAP_LOG( CONFIG, CRIT, 
2004                                         "%s: line %d: missing dn in \"updatedn <dn>\""
2005                                         " line.\n", fname, lineno , 0 );
2006 #else
2007                                 Debug( LDAP_DEBUG_ANY,
2008                     "%s: line %d: missing dn in \"updatedn <dn>\" line\n",
2009                                     fname, lineno, 0 );
2010 #endif
2011
2012                                 return( 1 );
2013                         }
2014                         if ( be == NULL ) {
2015 #ifdef NEW_LOGGING
2016                                 LDAP_LOG( CONFIG, INFO, 
2017                                         "%s: line %d: updatedn line must appear inside "
2018                                         "a database definition\n", 
2019                                         fname, lineno , 0 );
2020 #else
2021                                 Debug( LDAP_DEBUG_ANY,
2022 "%s: line %d: updatedn line must appear inside a database definition\n",
2023                                     fname, lineno, 0 );
2024 #endif
2025                                 return 1;
2026
2027                         } else if ( SLAP_SHADOW(be) ) {
2028 #ifdef NEW_LOGGING
2029                                 LDAP_LOG( CONFIG, INFO, 
2030                                         "%s: line %d: updatedn: database already shadowed.\n",
2031                                         fname, lineno, 0);
2032 #else
2033                                 Debug( LDAP_DEBUG_ANY,
2034                                         "%s: line %d: updatedn: database already shadowed.\n",
2035                                         fname, lineno, 0);
2036 #endif
2037                                 return 1;
2038
2039                         } else {
2040                                 struct berval dn;
2041
2042                                 if ( load_ucdata( NULL ) < 0 ) return 1;
2043
2044                                 dn.bv_val = cargv[1];
2045                                 dn.bv_len = strlen( cargv[1] );
2046
2047                                 rc = dnNormalize( 0, NULL, NULL, &dn, &be->be_update_ndn, NULL );
2048                                 if( rc != LDAP_SUCCESS ) {
2049 #ifdef NEW_LOGGING
2050                                         LDAP_LOG( CONFIG, CRIT, 
2051                                                 "%s: line %d: updatedn DN is invalid.\n",
2052                                                 fname, lineno , 0 );
2053 #else
2054                                         Debug( LDAP_DEBUG_ANY,
2055                                                 "%s: line %d: updatedn DN is invalid\n",
2056                                             fname, lineno, 0 );
2057 #endif
2058                                         return 1;
2059                                 }
2060
2061                         }
2062                         SLAP_DBFLAGS(be) |= SLAP_DBFLAG_SHADOW;
2063
2064                 } else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
2065                         if ( cargc < 2 ) {
2066 #ifdef NEW_LOGGING
2067                                 LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
2068                                         "missing url in \"updateref <ldapurl>\" line.\n",
2069                                         fname, lineno , 0 );
2070 #else
2071                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2072                                         "missing url in \"updateref <ldapurl>\" line\n",
2073                                     fname, lineno, 0 );
2074 #endif
2075
2076                                 return( 1 );
2077                         }
2078                         if ( be == NULL ) {
2079 #ifdef NEW_LOGGING
2080                                 LDAP_LOG( CONFIG, INFO, "%s: line %d: updateref"
2081                                         " line must appear inside a database definition\n",
2082                                         fname, lineno , 0 );
2083 #else
2084                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: updateref"
2085                                         " line must appear inside a database definition\n",
2086                                         fname, lineno, 0 );
2087 #endif
2088                                 return 1;
2089
2090                         } else if ( !SLAP_SHADOW(be) ) {
2091 #ifdef NEW_LOGGING
2092                                 LDAP_LOG( CONFIG, INFO, "%s: line %d: "
2093                                         "updateref line must come after syncrepl or updatedn.\n",
2094                                         fname, lineno , 0 );
2095 #else
2096                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2097                                         "updateref line must after syncrepl or updatedn.\n",
2098                                     fname, lineno, 0 );
2099 #endif
2100                                 return 1;
2101                         }
2102
2103                         if( validate_global_referral( cargv[1] ) ) {
2104 #ifdef NEW_LOGGING
2105                                 LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
2106                                         "invalid URL (%s) in \"updateref\" line.\n",
2107                                         fname, lineno, cargv[1] );
2108 #else
2109                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2110                                         "invalid URL (%s) in \"updateref\" line.\n",
2111                                     fname, lineno, cargv[1] );
2112 #endif
2113                                 return 1;
2114                         }
2115
2116                         vals[0].bv_val = cargv[1];
2117                         vals[0].bv_len = strlen( vals[0].bv_val );
2118                         if( value_add( &be->be_update_refs, vals ) ) {
2119                                 return LDAP_OTHER;
2120                         }
2121
2122                 /* replication log file to which changes are appended */
2123                 } else if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
2124                         if ( cargc < 2 ) {
2125 #ifdef NEW_LOGGING
2126                                 LDAP_LOG( CONFIG, CRIT, 
2127                                         "%s: line %d: missing filename in \"replogfile <filename>\""
2128                                         " line.\n", fname, lineno , 0 );
2129 #else
2130                                 Debug( LDAP_DEBUG_ANY,
2131             "%s: line %d: missing filename in \"replogfile <filename>\" line\n",
2132                                     fname, lineno, 0 );
2133 #endif
2134
2135                                 return( 1 );
2136                         }
2137                         if ( be ) {
2138                                 be->be_replogfile = ch_strdup( cargv[1] );
2139                         } else {
2140                                 replogfile = ch_strdup( cargv[1] );
2141                         }
2142
2143                 /* file from which to read additional rootdse attrs */
2144                 } else if ( strcasecmp( cargv[0], "rootDSE" ) == 0) {
2145                         if ( cargc < 2 ) {
2146 #ifdef NEW_LOGGING
2147                                 LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
2148                                         "missing filename in \"rootDSE <filename>\" line.\n",
2149                                         fname, lineno , 0 );
2150 #else
2151                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2152                                         "missing filename in \"rootDSE <filename>\" line.\n",
2153                                     fname, lineno, 0 );
2154 #endif
2155                                 return 1;
2156                         }
2157
2158                         if( read_root_dse_file( cargv[1] ) ) {
2159 #ifdef NEW_LOGGING
2160                                 LDAP_LOG( CONFIG, CRIT, "%s: line %d: "
2161                                         "could not read \"rootDSE <filename>\" line.\n",
2162                                         fname, lineno , 0 );
2163 #else
2164                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
2165                                         "could not read \"rootDSE <filename>\" line\n",
2166                                     fname, lineno, 0 );
2167 #endif
2168                                 return 1;
2169                         }
2170
2171                 /* maintain lastmodified{by,time} attributes */
2172                 } else if ( strcasecmp( cargv[0], "lastmod" ) == 0 ) {
2173                         if ( cargc < 2 ) {
2174 #ifdef NEW_LOGGING
2175                                 LDAP_LOG( CONFIG, CRIT, 
2176                                            "%s: line %d: missing on|off in \"lastmod <on|off>\""
2177                                            " line.\n", fname, lineno , 0 );
2178 #else
2179                                 Debug( LDAP_DEBUG_ANY,
2180             "%s: line %d: missing on|off in \"lastmod <on|off>\" line\n",
2181                                     fname, lineno, 0 );
2182 #endif
2183
2184                                 return( 1 );
2185                         }
2186                         if ( strcasecmp( cargv[1], "on" ) == 0 ) {
2187                                 if ( be ) {
2188                                         SLAP_DBFLAGS(be) &= ~SLAP_DBFLAG_NOLASTMOD;
2189                                 } else {
2190                                         lastmod = 1;
2191                                 }
2192                         } else {
2193                                 if ( be ) {
2194                                         SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NOLASTMOD;
2195                                 } else {
2196                                         lastmod = 0;
2197                                 }
2198                         }
2199
2200 #ifdef SIGHUP
2201                 /* turn on/off gentle SIGHUP handling */
2202                 } else if ( strcasecmp( cargv[0], "gentlehup" ) == 0 ) {
2203                         if ( cargc < 2 ) {
2204                                 Debug( LDAP_DEBUG_ANY,
2205     "%s: line %d: missing on|off in \"gentlehup <on|off>\" line\n",
2206                                     fname, lineno, 0 );
2207                                 return( 1 );
2208                         }
2209                         if ( strcasecmp( cargv[1], "off" ) == 0 ) {
2210                                 global_gentlehup = 0;
2211                         } else {
2212                                 global_gentlehup = 1;
2213                         }
2214 #endif
2215
2216                 /* set idle timeout value */
2217                 } else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) {
2218                         int i;
2219                         if ( cargc < 2 ) {
2220 #ifdef NEW_LOGGING
2221                                 LDAP_LOG( CONFIG, CRIT, 
2222                                         "%s: line %d: missing timeout value in "
2223                                         "\"idletimeout <seconds>\" line.\n", fname, lineno , 0 );
2224 #else
2225                                 Debug( LDAP_DEBUG_ANY,
2226             "%s: line %d: missing timeout value in \"idletimeout <seconds>\" line\n",
2227                                     fname, lineno, 0 );
2228 #endif
2229
2230                                 return( 1 );
2231                         }
2232
2233                         i = atoi( cargv[1] );
2234
2235                         if( i < 0 ) {
2236 #ifdef NEW_LOGGING
2237                                 LDAP_LOG( CONFIG, CRIT, 
2238                                         "%s: line %d: timeout value (%d) invalid "
2239                                         "\"idletimeout <seconds>\" line.\n", fname, lineno, i );
2240 #else
2241                                 Debug( LDAP_DEBUG_ANY,
2242             "%s: line %d: timeout value (%d) invalid \"idletimeout <seconds>\" line\n",
2243                                     fname, lineno, i );
2244 #endif
2245
2246                                 return( 1 );
2247                         }
2248
2249                         global_idletimeout = i;
2250
2251                 /* include another config file */
2252                 } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
2253                         if ( cargc < 2 ) {
2254 #ifdef NEW_LOGGING
2255                                 LDAP_LOG( CONFIG, CRIT, 
2256                                         "%s: line %d: missing filename in \"include "
2257                                         "<filename>\" line.\n", fname, lineno , 0 );
2258 #else
2259                                 Debug( LDAP_DEBUG_ANY,
2260     "%s: line %d: missing filename in \"include <filename>\" line\n",
2261                                     fname, lineno, 0 );
2262 #endif
2263
2264                                 return( 1 );
2265                         }
2266                         savefname = ch_strdup( cargv[1] );
2267                         savelineno = lineno;
2268
2269                         if ( read_config( savefname, depth+1 ) != 0 ) {
2270                                 return( 1 );
2271                         }
2272
2273                         free( savefname );
2274                         lineno = savelineno - 1;
2275
2276                 /* location of kerberos srvtab file */
2277                 } else if ( strcasecmp( cargv[0], "srvtab" ) == 0 ) {
2278                         if ( cargc < 2 ) {
2279 #ifdef NEW_LOGGING
2280                                 LDAP_LOG( CONFIG, CRIT, 
2281                                         "%s: line %d: missing filename in \"srvtab "
2282                                         "<filename>\" line.\n", fname, lineno , 0 );
2283 #else
2284                                 Debug( LDAP_DEBUG_ANY,
2285             "%s: line %d: missing filename in \"srvtab <filename>\" line\n",
2286                                     fname, lineno, 0 );
2287 #endif
2288
2289                                 return( 1 );
2290                         }
2291                         ldap_srvtab = ch_strdup( cargv[1] );
2292
2293 #ifdef SLAPD_MODULES
2294                 } else if (strcasecmp( cargv[0], "moduleload") == 0 ) {
2295                    if ( cargc < 2 ) {
2296 #ifdef NEW_LOGGING
2297                            LDAP_LOG( CONFIG, INFO, 
2298                                    "%s: line %d: missing filename in \"moduleload "
2299                                    "<filename>\" line.\n", fname, lineno , 0 );
2300 #else
2301                       Debug( LDAP_DEBUG_ANY,
2302                              "%s: line %d: missing filename in \"moduleload <filename>\" line\n",
2303                              fname, lineno, 0 );
2304 #endif
2305
2306                       exit( EXIT_FAILURE );
2307                    }
2308                    if (module_load(cargv[1], cargc - 2, (cargc > 2) ? cargv + 2 : NULL)) {
2309 #ifdef NEW_LOGGING
2310                            LDAP_LOG( CONFIG, CRIT, 
2311                                    "%s: line %d: failed to load or initialize module %s\n",
2312                                    fname, lineno, cargv[1] );
2313 #else
2314                       Debug( LDAP_DEBUG_ANY,
2315                              "%s: line %d: failed to load or initialize module %s\n",
2316                              fname, lineno, cargv[1]);
2317 #endif
2318
2319                       exit( EXIT_FAILURE );
2320                    }
2321                 } else if (strcasecmp( cargv[0], "modulepath") == 0 ) {
2322                    if ( cargc != 2 ) {
2323 #ifdef NEW_LOGGING
2324                            LDAP_LOG( CONFIG, INFO, 
2325                                   "%s: line %d: missing path in \"modulepath <path>\""
2326                                   " line\n", fname, lineno , 0 );
2327 #else
2328                       Debug( LDAP_DEBUG_ANY,
2329                              "%s: line %d: missing path in \"modulepath <path>\" line\n",
2330                              fname, lineno, 0 );
2331 #endif
2332
2333                       exit( EXIT_FAILURE );
2334                    }
2335                    if (module_path( cargv[1] )) {
2336 #ifdef NEW_LOGGING
2337                            LDAP_LOG( CONFIG, CRIT, 
2338                                   "%s: line %d: failed to set module search path to %s.\n",
2339                                   fname, lineno, cargv[1] );
2340 #else
2341                            Debug( LDAP_DEBUG_ANY,
2342                                   "%s: line %d: failed to set module search path to %s\n",
2343                                   fname, lineno, cargv[1]);
2344 #endif
2345
2346                       exit( EXIT_FAILURE );
2347                    }
2348                    
2349 #endif /*SLAPD_MODULES*/
2350
2351 #ifdef HAVE_TLS
2352                 } else if ( !strcasecmp( cargv[0], "TLSRandFile" ) ) {
2353                         rc = ldap_pvt_tls_set_option( NULL,
2354                                                       LDAP_OPT_X_TLS_RANDOM_FILE,
2355                                                       cargv[1] );
2356                         if ( rc )
2357                                 return rc;
2358
2359                 } else if ( !strcasecmp( cargv[0], "TLSCipherSuite" ) ) {
2360                         rc = ldap_pvt_tls_set_option( NULL,
2361                                                       LDAP_OPT_X_TLS_CIPHER_SUITE,
2362                                                       cargv[1] );
2363                         if ( rc )
2364                                 return rc;
2365
2366                 } else if ( !strcasecmp( cargv[0], "TLSCertificateFile" ) ) {
2367                         rc = ldap_pvt_tls_set_option( NULL,
2368                                                       LDAP_OPT_X_TLS_CERTFILE,
2369                                                       cargv[1] );
2370                         if ( rc )
2371                                 return rc;
2372
2373                 } else if ( !strcasecmp( cargv[0], "TLSCertificateKeyFile" ) ) {
2374                         rc = ldap_pvt_tls_set_option( NULL,
2375                                                       LDAP_OPT_X_TLS_KEYFILE,
2376                                                       cargv[1] );
2377                         if ( rc )
2378                                 return rc;
2379
2380                 } else if ( !strcasecmp( cargv[0], "TLSCACertificatePath" ) ) {
2381                         rc = ldap_pvt_tls_set_option( NULL,
2382                                                       LDAP_OPT_X_TLS_CACERTDIR,
2383                                                       cargv[1] );
2384                         if ( rc )
2385                                 return rc;
2386
2387                 } else if ( !strcasecmp( cargv[0], "TLSCACertificateFile" ) ) {
2388                         rc = ldap_pvt_tls_set_option( NULL,
2389                                                       LDAP_OPT_X_TLS_CACERTFILE,
2390                                                       cargv[1] );
2391                         if ( rc )
2392                                 return rc;
2393                 } else if ( !strcasecmp( cargv[0], "TLSVerifyClient" ) ) {
2394                         if ( isdigit( (unsigned char) cargv[1][0] ) ) {
2395                                 i = atoi(cargv[1]);
2396                                 rc = ldap_pvt_tls_set_option( NULL,
2397                                                       LDAP_OPT_X_TLS_REQUIRE_CERT,
2398                                                       &i );
2399                         } else {
2400                                 rc = ldap_int_tls_config( NULL,
2401                                                       LDAP_OPT_X_TLS_REQUIRE_CERT,
2402                                                       cargv[1] );
2403                         }
2404
2405                         if ( rc )
2406                                 return rc;
2407
2408 #endif
2409
2410                 } else if ( !strcasecmp( cargv[0], "reverse-lookup" ) ) {
2411 #ifdef SLAPD_RLOOKUPS
2412                         if ( cargc < 2 ) {
2413 #ifdef NEW_LOGGING
2414                                 LDAP_LOG( CONFIG, INFO, 
2415                                         "%s: line %d: reverse-lookup: missing \"on\" or \"off\"\n",
2416                                         fname, lineno , 0 );
2417 #else
2418                                 Debug( LDAP_DEBUG_ANY,
2419 "%s: line %d: reverse-lookup: missing \"on\" or \"off\"\n",
2420                                         fname, lineno, 0 );
2421 #endif
2422                                 return( 1 );
2423                         }
2424
2425                         if ( !strcasecmp( cargv[1], "on" ) ) {
2426                                 use_reverse_lookup = 1;
2427                         } else if ( !strcasecmp( cargv[1], "off" ) ) {
2428                                 use_reverse_lookup = 0;
2429                         } else {
2430 #ifdef NEW_LOGGING
2431                                 LDAP_LOG( CONFIG, INFO, 
2432                                         "%s: line %d: reverse-lookup: "
2433                                         "must be \"on\" (default) or \"off\"\n", fname, lineno, 0 );
2434 #else
2435                                 Debug( LDAP_DEBUG_ANY,
2436 "%s: line %d: reverse-lookup: must be \"on\" (default) or \"off\"\n",
2437                                         fname, lineno, 0 );
2438 #endif
2439                                 return( 1 );
2440                         }
2441
2442 #else /* !SLAPD_RLOOKUPS */
2443 #ifdef NEW_LOGGING
2444                         LDAP_LOG( CONFIG, INFO, 
2445                                 "%s: line %d: reverse lookups "
2446                                 "are not configured (ignored).\n", fname, lineno , 0 );
2447 #else
2448                         Debug( LDAP_DEBUG_ANY,
2449 "%s: line %d: reverse lookups are not configured (ignored).\n",
2450                                 fname, lineno, 0 );
2451 #endif
2452 #endif /* !SLAPD_RLOOKUPS */
2453
2454                 /* Netscape plugins */
2455                 } else if ( strcasecmp( cargv[0], "plugin" ) == 0 ) {
2456 #if defined( LDAP_SLAPI )
2457
2458 #ifdef notdef /* allow global plugins, too */
2459                         /*
2460                          * a "plugin" line must be inside a database
2461                          * definition, since we implement pre-,post- 
2462                          * and extended operation plugins
2463                          */
2464                         if ( be == NULL ) {
2465 #ifdef NEW_LOGGING
2466                                 LDAP_LOG( CONFIG, INFO, 
2467                                         "%s: line %d: plugin line must appear "
2468                                         "insid a database definition.\n",
2469                                         fname, lineno, 0 );
2470 #else
2471                                 Debug( LDAP_DEBUG_ANY, "%s: line %d: plugin "
2472                                     "line must appear inside a database "
2473                                     "definition\n", fname, lineno, 0 );
2474 #endif
2475                                 return( 1 );
2476                         }
2477 #endif /* notdef */
2478
2479                         if ( slapi_int_read_config( be, fname, lineno, cargc, cargv ) 
2480                                         != LDAP_SUCCESS ) {
2481                                 return( 1 );
2482                         }
2483                         slapi_plugins_used++;
2484
2485 #else /* !defined( LDAP_SLAPI ) */
2486 #ifdef NEW_LOGGING
2487                         LDAP_LOG( CONFIG, INFO, 
2488                                 "%s: line %d: SLAPI not supported.\n",
2489                                 fname, lineno, 0 );
2490 #else
2491                         Debug( LDAP_DEBUG_ANY, "%s: line %d: SLAPI "
2492                             "not supported.\n", fname, lineno, 0 );
2493 #endif
2494                         return( 1 );
2495                         
2496 #endif /* !defined( LDAP_SLAPI ) */
2497
2498                 /* Netscape plugins */
2499                 } else if ( strcasecmp( cargv[0], "pluginlog" ) == 0 ) {
2500 #if defined( LDAP_SLAPI )
2501                         if ( cargc < 2 ) {
2502 #ifdef NEW_LOGGING
2503                                 LDAP_LOG( CONFIG, INFO, 
2504                                         "%s: line %d: missing file name "
2505                                         "in pluginlog <filename> line.\n",
2506                                         fname, lineno, 0 );
2507 #else
2508                                 Debug( LDAP_DEBUG_ANY, 
2509                                         "%s: line %d: missing file name "
2510                                         "in pluginlog <filename> line.\n",
2511                                         fname, lineno, 0 );
2512 #endif
2513                                 return( 1 );
2514                         }
2515
2516                         if ( slapi_log_file != NULL ) {
2517                                 ch_free( slapi_log_file );
2518                         }
2519
2520                         slapi_log_file = ch_strdup( cargv[1] );
2521 #endif /* !defined( LDAP_SLAPI ) */
2522
2523                 /* pass anything else to the current backend info/db config routine */
2524                 } else {
2525                         if ( bi != NULL ) {
2526                                 if ( bi->bi_config ) {
2527                                         rc = (*bi->bi_config)( bi, fname, lineno, cargc, cargv );
2528
2529                                         switch ( rc ) {
2530                                         case 0:
2531                                                 break;
2532
2533                                         case SLAP_CONF_UNKNOWN:
2534 #ifdef NEW_LOGGING
2535                                                 LDAP_LOG( CONFIG, INFO, 
2536                                                         "%s: line %d: unknown directive \"%s\" inside "
2537                                                         "backend info definition (ignored).\n",
2538                                                         fname, lineno, cargv[0] );
2539 #else
2540                                                 Debug( LDAP_DEBUG_ANY,
2541 "%s: line %d: unknown directive \"%s\" inside backend info definition (ignored)\n",
2542                                                         fname, lineno, cargv[0] );
2543 #endif
2544                                                 break;
2545
2546                                         default:
2547                                                 return 1;
2548                                         }
2549                                 }
2550
2551                         } else if ( be != NULL ) {
2552                                 if ( be->be_config ) {
2553                                         rc = (*be->be_config)( be, fname, lineno, cargc, cargv );
2554
2555                                         switch ( rc ) {
2556                                         case 0:
2557                                                 break;
2558
2559                                         case SLAP_CONF_UNKNOWN:
2560 #ifdef NEW_LOGGING
2561                                                 LDAP_LOG( CONFIG, INFO, 
2562                                                         "%s: line %d: unknown directive \"%s\" inside "
2563                                                         "backend database definition (ignored).\n",
2564                                                         fname, lineno, cargv[0] );
2565 #else
2566                                                 Debug( LDAP_DEBUG_ANY,
2567 "%s: line %d: unknown directive \"%s\" inside backend database definition (ignored)\n",
2568                                                         fname, lineno, cargv[0] );
2569 #endif
2570                                                 break;
2571
2572                                         default:
2573                                                 return 1;
2574                                         }
2575                                 }
2576
2577                         } else {
2578 #ifdef NEW_LOGGING
2579                                 LDAP_LOG( CONFIG, INFO, 
2580                                         "%s: line %d: unknown directive \"%s\" outside backend "
2581                                         "info and database definitions (ignored).\n",
2582                                         fname, lineno, cargv[0] );
2583 #else
2584                                 Debug( LDAP_DEBUG_ANY,
2585 "%s: line %d: unknown directive \"%s\" outside backend info and database definitions (ignored)\n",
2586                                     fname, lineno, cargv[0] );
2587 #endif
2588
2589                         }
2590                 }
2591                 free( saveline );
2592         }
2593         fclose( fp );
2594
2595         if ( depth == 0 ) ch_free( cargv );
2596
2597         if ( !global_schemadn.bv_val ) {
2598                 ber_str2bv( SLAPD_SCHEMA_DN, sizeof(SLAPD_SCHEMA_DN)-1, 1,
2599                         &global_schemadn );
2600                 dnNormalize( 0, NULL, NULL, &global_schemadn, &global_schemandn, NULL );
2601         }
2602
2603         if ( load_ucdata( NULL ) < 0 ) return 1;
2604         return( 0 );
2605 }
2606
2607 static int
2608 fp_parse_line(
2609     int         lineno,
2610     char        *line
2611 )
2612 {
2613         char *  token;
2614         char *  logline;
2615         char    logbuf[sizeof("pseudorootpw ***")];
2616
2617         cargc = 0;
2618         token = strtok_quote( line, " \t" );
2619
2620         logline = line;
2621
2622         if ( token && ( strcasecmp( token, "rootpw" ) == 0 ||
2623                 strcasecmp( token, "replica" ) == 0 ||          /* contains "credentials" */
2624                 strcasecmp( token, "bindpw" ) == 0 ||           /* used in back-ldap */
2625                 strcasecmp( token, "pseudorootpw" ) == 0 ||     /* used in back-meta */
2626                 strcasecmp( token, "dbpasswd" ) == 0 ) )        /* used in back-sql */
2627         {
2628                 snprintf( logline = logbuf, sizeof logbuf, "%s ***", token );
2629         }
2630
2631         if ( strtok_quote_ptr ) {
2632                 *strtok_quote_ptr = ' ';
2633         }
2634
2635 #ifdef NEW_LOGGING
2636         LDAP_LOG( CONFIG, DETAIL1, "line %d (%s)\n", lineno, logline , 0 );
2637 #else
2638         Debug( LDAP_DEBUG_CONFIG, "line %d (%s)\n", lineno, logline, 0 );
2639 #endif
2640
2641         if ( strtok_quote_ptr ) {
2642                 *strtok_quote_ptr = '\0';
2643         }
2644
2645         for ( ; token != NULL; token = strtok_quote( NULL, " \t" ) ) {
2646                 if ( cargc == cargv_size - 1 ) {
2647                         char **tmp;
2648                         tmp = ch_realloc( cargv, (cargv_size + ARGS_STEP) *
2649                                             sizeof(*cargv) );
2650                         if ( tmp == NULL ) {
2651 #ifdef NEW_LOGGING
2652                                 LDAP_LOG( CONFIG, ERR, "line %d: out of memory\n", lineno, 0,0 );
2653 #else
2654                                 Debug( LDAP_DEBUG_ANY, 
2655                                                 "line %d: out of memory\n", 
2656                                                 lineno, 0, 0 );
2657 #endif
2658                                 return -1;
2659                         }
2660                         cargv = tmp;
2661                         cargv_size += ARGS_STEP;
2662                 }
2663                 cargv[cargc++] = token;
2664         }
2665         cargv[cargc] = NULL;
2666         return 0;
2667 }
2668
2669 static char *
2670 strtok_quote( char *line, char *sep )
2671 {
2672         int             inquote;
2673         char            *tmp;
2674         static char     *next;
2675
2676         strtok_quote_ptr = NULL;
2677         if ( line != NULL ) {
2678                 next = line;
2679         }
2680         while ( *next && strchr( sep, *next ) ) {
2681                 next++;
2682         }
2683
2684         if ( *next == '\0' ) {
2685                 next = NULL;
2686                 return( NULL );
2687         }
2688         tmp = next;
2689
2690         for ( inquote = 0; *next; ) {
2691                 switch ( *next ) {
2692                 case '"':
2693                         if ( inquote ) {
2694                                 inquote = 0;
2695                         } else {
2696                                 inquote = 1;
2697                         }
2698                         AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
2699                         break;
2700
2701                 case '\\':
2702                         if ( next[1] )
2703                                 AC_MEMCPY( next,
2704                                             next + 1, strlen( next + 1 ) + 1 );
2705                         next++;         /* dont parse the escaped character */
2706                         break;
2707
2708                 default:
2709                         if ( ! inquote ) {
2710                                 if ( strchr( sep, *next ) != NULL ) {
2711                                         strtok_quote_ptr = next;
2712                                         *next++ = '\0';
2713                                         return( tmp );
2714                                 }
2715                         }
2716                         next++;
2717                         break;
2718                 }
2719         }
2720
2721         return( tmp );
2722 }
2723
2724 static char     buf[BUFSIZ];
2725 static char     *line;
2726 static size_t lmax, lcur;
2727
2728 #define CATLINE( buf ) \
2729         do { \
2730                 size_t len = strlen( buf ); \
2731                 while ( lcur + len + 1 > lmax ) { \
2732                         lmax += BUFSIZ; \
2733                         line = (char *) ch_realloc( line, lmax ); \
2734                 } \
2735                 strcpy( line + lcur, buf ); \
2736                 lcur += len; \
2737         } while( 0 )
2738
2739 static char *
2740 fp_getline( FILE *fp, int *lineno )
2741 {
2742         char            *p;
2743
2744         lcur = 0;
2745         CATLINE( buf );
2746         (*lineno)++;
2747
2748         /* hack attack - keeps us from having to keep a stack of bufs... */
2749         if ( strncasecmp( line, "include", 7 ) == 0 ) {
2750                 buf[0] = '\0';
2751                 return( line );
2752         }
2753
2754         while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
2755                 /* trim off \r\n or \n */
2756                 if ( (p = strchr( buf, '\n' )) != NULL ) {
2757                         if( p > buf && p[-1] == '\r' ) --p;
2758                         *p = '\0';
2759                 }
2760                 
2761                 /* trim off trailing \ and append the next line */
2762                 if ( line[ 0 ] != '\0' 
2763                                 && (p = line + strlen( line ) - 1)[ 0 ] == '\\'
2764                                 && p[ -1 ] != '\\' ) {
2765                         p[ 0 ] = '\0';
2766                         lcur--;
2767
2768                 } else {
2769                         if ( ! isspace( (unsigned char) buf[0] ) ) {
2770                                 return( line );
2771                         }
2772
2773                         /* change leading whitespace to a space */
2774                         buf[0] = ' ';
2775                 }
2776
2777                 CATLINE( buf );
2778                 (*lineno)++;
2779         }
2780         buf[0] = '\0';
2781
2782         return( line[0] ? line : NULL );
2783 }
2784
2785 static void
2786 fp_getline_init( int *lineno )
2787 {
2788         *lineno = -1;
2789         buf[0] = '\0';
2790 }
2791
2792 /* Loads ucdata, returns 1 if loading, 0 if already loaded, -1 on error */
2793 static int
2794 load_ucdata( char *path )
2795 {
2796         static int loaded = 0;
2797         int err;
2798         
2799         if ( loaded ) {
2800                 return( 0 );
2801         }
2802         err = ucdata_load( path ? path : SLAPD_DEFAULT_UCDATA, UCDATA_ALL );
2803         if ( err ) {
2804 #ifdef NEW_LOGGING
2805                 LDAP_LOG( CONFIG, CRIT, 
2806                         "load_ucdata: Error %d loading ucdata.\n", err, 0,0 );
2807 #else
2808                 Debug( LDAP_DEBUG_ANY, "error loading ucdata (error %d)\n",
2809                        err, 0, 0 );
2810 #endif
2811
2812                 return( -1 );
2813         }
2814         loaded = 1;
2815         return( 1 );
2816 }
2817
2818 void
2819 config_destroy( )
2820 {
2821         ucdata_unload( UCDATA_ALL );
2822         free( global_schemandn.bv_val );
2823         free( global_schemadn.bv_val );
2824         free( line );
2825         if ( slapd_args_file )
2826                 free ( slapd_args_file );
2827         if ( slapd_pid_file )
2828                 free ( slapd_pid_file );
2829         if ( default_passwd_hash )
2830                 ldap_charray_free( default_passwd_hash );
2831         acl_destroy( global_acl, NULL );
2832 }
2833
2834 static int
2835 add_syncrepl(
2836         Backend *be,
2837         char    **cargv,
2838         int     cargc
2839 )
2840 {
2841         syncinfo_t *si;
2842         syncinfo_t *si_entry;
2843         int     rc = 0;
2844         int duplicated_replica_id = 0;
2845
2846         si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
2847
2848         if ( si == NULL ) {
2849 #ifdef NEW_LOGGING
2850                 LDAP_LOG( CONFIG, ERR, "out of memory in add_syncrepl\n", 0, 0,0 );
2851 #else
2852                 Debug( LDAP_DEBUG_ANY, "out of memory in add_syncrepl\n", 0, 0, 0 );
2853 #endif
2854                 return 1;
2855         }
2856
2857         si->si_tls = SYNCINFO_TLS_OFF;
2858         if ( be->be_rootndn.bv_val ) {
2859                 ber_dupbv( &si->si_updatedn, &be->be_rootndn );
2860         }
2861         si->si_bindmethod = LDAP_AUTH_SIMPLE;
2862         si->si_schemachecking = 0;
2863         ber_str2bv( "(objectclass=*)", sizeof("(objectclass=*)")-1, 0,
2864                 &si->si_filterstr );
2865         si->si_base.bv_val = NULL;
2866         si->si_scope = LDAP_SCOPE_SUBTREE;
2867         si->si_attrsonly = 0;
2868         si->si_attrs = (char **) ch_calloc( 1, sizeof( char * ));
2869         si->si_attrs[0] = NULL;
2870         si->si_type = LDAP_SYNC_REFRESH_ONLY;
2871         si->si_interval = 86400;
2872         si->si_syncCookie.ctxcsn = NULL;
2873         si->si_syncCookie.octet_str = NULL;
2874         si->si_syncCookie.sid = -1;
2875         si->si_manageDSAit = 0;
2876         si->si_tlimit = -1;
2877         si->si_slimit = -1;
2878         si->si_syncUUID_ndn.bv_val = NULL;
2879         si->si_syncUUID_ndn.bv_len = 0;
2880
2881         si->si_presentlist = NULL;
2882         LDAP_LIST_INIT( &si->si_nonpresentlist );
2883
2884         rc = parse_syncrepl_line( cargv, cargc, si );
2885
2886         LDAP_STAILQ_FOREACH( si_entry, &be->be_syncinfo, si_next ) {
2887                 if ( si->si_rid == si_entry->si_rid ) {
2888 #ifdef NEW_LOGGING
2889                         LDAP_LOG( CONFIG, ERR,
2890                                 "add_syncrepl: duplicated replica id\n", 0, 0,0 );
2891 #else
2892                         Debug( LDAP_DEBUG_ANY,
2893                                 "add_syncrepl: duplicated replica id\n",0, 0, 0 );
2894 #endif
2895                         duplicated_replica_id = 1;
2896                         break;
2897                 }
2898         }
2899
2900         if ( rc < 0 || duplicated_replica_id ) {
2901                 syncinfo_t *si_entry;
2902                 /* Something bad happened - back out */
2903 #ifdef NEW_LOGGING
2904                 LDAP_LOG( CONFIG, ERR, "failed to add syncinfo\n", 0, 0,0 );
2905 #else
2906                 Debug( LDAP_DEBUG_ANY, "failed to add syncinfo\n", 0, 0, 0 );
2907 #endif
2908
2909                 /* If error, remove all syncinfo */
2910                 LDAP_STAILQ_FOREACH( si_entry, &be->be_syncinfo, si_next ) {
2911                         if ( si_entry->si_updatedn.bv_val ) {
2912                                 ch_free( si->si_updatedn.bv_val );
2913                         }
2914                         if ( si_entry->si_filterstr.bv_val ) {
2915                                 ch_free( si->si_filterstr.bv_val );
2916                         }
2917                         if ( si_entry->si_attrs ) {
2918                                 int i = 0;
2919                                 while ( si_entry->si_attrs[i] != NULL ) {
2920                                         ch_free( si_entry->si_attrs[i] );
2921                                         i++;
2922                                 }
2923                                 ch_free( si_entry->si_attrs );
2924                         }
2925                 }
2926
2927                 while ( !LDAP_STAILQ_EMPTY( &be->be_syncinfo )) {
2928                         si_entry = LDAP_STAILQ_FIRST( &be->be_syncinfo );
2929                         LDAP_STAILQ_REMOVE_HEAD( &be->be_syncinfo, si_next );
2930                         ch_free( si_entry );
2931                 }
2932                 LDAP_STAILQ_INIT( &be->be_syncinfo );
2933                 return 1;
2934         } else {
2935 #ifdef NEW_LOGGING
2936                 LDAP_LOG ( CONFIG, RESULTS,
2937                         "add_syncrepl: Config: ** successfully added syncrepl \"%s\"\n",
2938                         si->si_provideruri == NULL ? "(null)" : si->si_provideruri, 0, 0 );
2939 #else
2940                 Debug( LDAP_DEBUG_CONFIG,
2941                         "Config: ** successfully added syncrepl \"%s\"\n",
2942                         si->si_provideruri == NULL ? "(null)" : si->si_provideruri, 0, 0 );
2943 #endif
2944                 if ( !si->si_schemachecking ) {
2945                         SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
2946                 }
2947                 si->si_be = be;
2948                 LDAP_STAILQ_INSERT_TAIL( &be->be_syncinfo, si, si_next );
2949                 return 0;
2950         }
2951 }
2952
2953 #define IDSTR                   "rid"
2954 #define PROVIDERSTR             "provider"
2955 #define SUFFIXSTR               "suffix"
2956 #define UPDATEDNSTR             "updatedn"
2957 #define BINDMETHSTR             "bindmethod"
2958 #define SIMPLESTR               "simple"
2959 #define SASLSTR                 "sasl"
2960 #define BINDDNSTR               "binddn"
2961 #define CREDSTR                 "credentials"
2962 #define OLDAUTHCSTR             "bindprincipal"
2963 #define AUTHCSTR                "authcID"
2964 #define AUTHZSTR                "authzID"
2965 #define SRVTABSTR               "srvtab"
2966 #define SASLMECHSTR             "saslmech"
2967 #define REALMSTR                "realm"
2968 #define SECPROPSSTR             "secprops"
2969 #define STARTTLSSTR             "starttls"
2970 #define CRITICALSTR             "critical"
2971
2972 #define SCHEMASTR               "schemachecking"
2973 #define FILTERSTR               "filter"
2974 #define SEARCHBASESTR   "searchbase"
2975 #define SCOPESTR                "scope"
2976 #define ATTRSSTR                "attrs"
2977 #define ATTRSONLYSTR    "attrsonly"
2978 #define TYPESTR                 "type"
2979 #define INTERVALSTR             "interval"
2980 #define LASTMODSTR              "lastmod"
2981 #define LMREQSTR                "req"
2982 #define LMGENSTR                "gen"
2983 #define LMNOSTR                 "no"
2984 #define MANAGEDSAITSTR  "manageDSAit"
2985 #define SLIMITSTR               "sizelimit"
2986 #define TLIMITSTR               "timelimit"
2987
2988 #define GOT_ID                  0x0001
2989 #define GOT_PROVIDER    0x0002
2990 #define GOT_METHOD              0x0004
2991 #define GOT_ALL                 0x0007
2992
2993 static int
2994 parse_syncrepl_line(
2995         char            **cargv,
2996         int             cargc,
2997         syncinfo_t      *si
2998 )
2999 {
3000         int     gots = 0;
3001         int     i, j;
3002         char    *hp, *val;
3003         int     nr_attr = 0;
3004
3005         for ( i = 1; i < cargc; i++ ) {
3006                 if ( !strncasecmp( cargv[ i ], IDSTR, sizeof( IDSTR ) - 1 )) {
3007                         int tmp;
3008                         /* '\0' string terminator accounts for '=' */
3009                         val = cargv[ i ] + sizeof( IDSTR );
3010                         tmp= atoi( val );
3011                         if ( tmp >= 1000 || tmp < 0 ) {
3012                                 fprintf( stderr, "Error: parse_syncrepl_line: "
3013                                          "syncrepl id %d is out of range [0..999]\n", tmp );
3014                                 return -1;
3015                         }
3016                         si->si_rid = tmp;
3017                         gots |= GOT_ID;
3018                 } else if ( !strncasecmp( cargv[ i ], PROVIDERSTR,
3019                                         sizeof( PROVIDERSTR ) - 1 )) {
3020                         val = cargv[ i ] + sizeof( PROVIDERSTR );
3021                         si->si_provideruri = ch_strdup( val );
3022                         si->si_provideruri_bv = (BerVarray)
3023                                 ch_calloc( 2, sizeof( struct berval ));
3024                         ber_str2bv( si->si_provideruri, strlen( si->si_provideruri ),
3025                                 0, &si->si_provideruri_bv[0] );
3026                         si->si_provideruri_bv[1].bv_len = 0;
3027                         si->si_provideruri_bv[1].bv_val = NULL;
3028                         gots |= GOT_PROVIDER;
3029                 } else if ( !strncasecmp( cargv[ i ], STARTTLSSTR,
3030                         sizeof(STARTTLSSTR) - 1 ) )
3031                 {
3032                         val = cargv[ i ] + sizeof( STARTTLSSTR );
3033                         if( !strcasecmp( val, CRITICALSTR ) ) {
3034                                 si->si_tls = SYNCINFO_TLS_CRITICAL;
3035                         } else {
3036                                 si->si_tls = SYNCINFO_TLS_ON;
3037                         }
3038                 } else if ( !strncasecmp( cargv[ i ],
3039                         UPDATEDNSTR, sizeof( UPDATEDNSTR ) - 1 ) )
3040                 {
3041                         struct berval updatedn = {0, NULL};
3042                         val = cargv[ i ] + sizeof( UPDATEDNSTR );
3043                         ber_str2bv( val, 0, 0, &updatedn );
3044                         ch_free( si->si_updatedn.bv_val );
3045                         dnNormalize( 0, NULL, NULL, &updatedn, &si->si_updatedn, NULL );
3046                 } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
3047                                 sizeof( BINDMETHSTR ) - 1 ) )
3048                 {
3049                         val = cargv[ i ] + sizeof( BINDMETHSTR );
3050                         if ( !strcasecmp( val, SIMPLESTR )) {
3051                                 si->si_bindmethod = LDAP_AUTH_SIMPLE;
3052                                 gots |= GOT_METHOD;
3053                         } else if ( !strcasecmp( val, SASLSTR )) {
3054 #ifdef HAVE_CYRUS_SASL
3055                                 si->si_bindmethod = LDAP_AUTH_SASL;
3056                                 gots |= GOT_METHOD;
3057 #else /* HAVE_CYRUS_SASL */
3058                                 fprintf( stderr, "Error: parse_syncrepl_line: "
3059                                         "not compiled with SASL support\n" );
3060                                 return 1;
3061 #endif /* HAVE_CYRUS_SASL */
3062                         } else {
3063                                 si->si_bindmethod = -1;
3064                         }
3065                 } else if ( !strncasecmp( cargv[ i ],
3066                                 BINDDNSTR, sizeof( BINDDNSTR ) - 1 ) ) {
3067                         val = cargv[ i ] + sizeof( BINDDNSTR );
3068                         si->si_binddn = ch_strdup( val );
3069                 } else if ( !strncasecmp( cargv[ i ],
3070                                 CREDSTR, sizeof( CREDSTR ) - 1 ) ) {
3071                         val = cargv[ i ] + sizeof( CREDSTR );
3072                         si->si_passwd = ch_strdup( val );
3073                 } else if ( !strncasecmp( cargv[ i ],
3074                                 SASLMECHSTR, sizeof( SASLMECHSTR ) - 1 ) ) {
3075                         val = cargv[ i ] + sizeof( SASLMECHSTR );
3076                         si->si_saslmech = ch_strdup( val );
3077                 } else if ( !strncasecmp( cargv[ i ],
3078                                 SECPROPSSTR, sizeof( SECPROPSSTR ) - 1 ) ) {
3079                         val = cargv[ i ] + sizeof( SECPROPSSTR );
3080                         si->si_secprops = ch_strdup( val );
3081                 } else if ( !strncasecmp( cargv[ i ],
3082                                 REALMSTR, sizeof( REALMSTR ) - 1 ) ) {
3083                         val = cargv[ i ] + sizeof( REALMSTR );
3084                         si->si_realm = ch_strdup( val );
3085                 } else if ( !strncasecmp( cargv[ i ],
3086                                 AUTHCSTR, sizeof( AUTHCSTR ) - 1 ) ) {
3087                         val = cargv[ i ] + sizeof( AUTHCSTR );
3088                         si->si_authcId = ch_strdup( val );
3089                 } else if ( !strncasecmp( cargv[ i ],
3090                                 OLDAUTHCSTR, sizeof( OLDAUTHCSTR ) - 1 ) ) {
3091                         /* Old authcID is provided for some backwards compatibility */
3092                         val = cargv[ i ] + sizeof( OLDAUTHCSTR );
3093                         si->si_authcId = ch_strdup( val );
3094                 } else if ( !strncasecmp( cargv[ i ],
3095                                 AUTHZSTR, sizeof( AUTHZSTR ) - 1 ) ) {
3096                         val = cargv[ i ] + sizeof( AUTHZSTR );
3097                         si->si_authzId = ch_strdup( val );
3098                 } else if ( !strncasecmp( cargv[ i ],
3099                                 SCHEMASTR, sizeof( SCHEMASTR ) - 1 ) )
3100                 {
3101                         val = cargv[ i ] + sizeof( SCHEMASTR );
3102                         if ( !strncasecmp( val, "on", sizeof( "on" ) - 1 )) {
3103                                 si->si_schemachecking = 1;
3104                         } else if ( !strncasecmp( val, "off", sizeof( "off" ) - 1 ) ) {
3105                                 si->si_schemachecking = 0;
3106                         } else {
3107                                 si->si_schemachecking = 1;
3108                         }
3109                 } else if ( !strncasecmp( cargv[ i ],
3110                         FILTERSTR, sizeof( FILTERSTR ) - 1 ) )
3111                 {
3112                         val = cargv[ i ] + sizeof( FILTERSTR );
3113                         ber_str2bv( val, 0, 1, &si->si_filterstr );
3114                 } else if ( !strncasecmp( cargv[ i ],
3115                         SEARCHBASESTR, sizeof( SEARCHBASESTR ) - 1 ) )
3116                 {
3117                         struct berval bv;
3118                         val = cargv[ i ] + sizeof( SEARCHBASESTR );
3119                         if ( si->si_base.bv_val ) {
3120                                 ch_free( si->si_base.bv_val );
3121                         }
3122                         ber_str2bv( val, 0, 0, &bv );
3123                         if ( dnNormalize( 0, NULL, NULL, &bv, &si->si_base, NULL )) {
3124                                 fprintf( stderr, "Invalid base DN \"%s\"\n", val );
3125                                 return 1;
3126                         }
3127                 } else if ( !strncasecmp( cargv[ i ],
3128                         SCOPESTR, sizeof( SCOPESTR ) - 1 ) )
3129                 {
3130                         val = cargv[ i ] + sizeof( SCOPESTR );
3131                         if ( !strncasecmp( val, "base", sizeof( "base" ) - 1 )) {
3132                                 si->si_scope = LDAP_SCOPE_BASE;
3133                         } else if ( !strncasecmp( val, "one", sizeof( "one" ) - 1 )) {
3134                                 si->si_scope = LDAP_SCOPE_ONELEVEL;
3135 #ifdef LDAP_SCOPE_SUBORDINATE
3136                         } else if ( !strcasecmp( val, "subordinate" ) ||
3137                                 !strcasecmp( val, "children" ))
3138                         {
3139                                 si->si_scope = LDAP_SCOPE_SUBORDINATE;
3140 #endif
3141                         } else if ( !strncasecmp( val, "sub", sizeof( "sub" ) - 1 )) {
3142                                 si->si_scope = LDAP_SCOPE_SUBTREE;
3143                         } else {
3144                                 fprintf( stderr, "Error: parse_syncrepl_line: "
3145                                         "unknown scope \"%s\"\n", val);
3146                                 return 1;
3147                         }
3148                 } else if ( !strncasecmp( cargv[ i ],
3149                         ATTRSONLYSTR, sizeof( ATTRSONLYSTR ) - 1 ) )
3150                 {
3151                         si->si_attrsonly = 1;
3152                 } else if ( !strncasecmp( cargv[ i ],
3153                         ATTRSSTR, sizeof( ATTRSSTR ) - 1 ) )
3154                 {
3155                         val = cargv[ i ] + sizeof( ATTRSSTR );
3156                         str2clist( &si->si_attrs, val, "," );
3157                 } else if ( !strncasecmp( cargv[ i ],
3158                         TYPESTR, sizeof( TYPESTR ) - 1 ) )
3159                 {
3160                         val = cargv[ i ] + sizeof( TYPESTR );
3161                         if ( !strncasecmp( val, "refreshOnly", sizeof("refreshOnly")-1 )) {
3162                                 si->si_type = LDAP_SYNC_REFRESH_ONLY;
3163                         } else if ( !strncasecmp( val, "refreshAndPersist",
3164                                 sizeof("refreshAndPersist")-1 ))
3165                         {
3166                                 si->si_type = LDAP_SYNC_REFRESH_AND_PERSIST;
3167                                 si->si_interval = 60;
3168                         } else {
3169                                 fprintf( stderr, "Error: parse_syncrepl_line: "
3170                                         "unknown sync type \"%s\"\n", val);
3171                                 return 1;
3172                         }
3173                 } else if ( !strncasecmp( cargv[ i ],
3174                         INTERVALSTR, sizeof( INTERVALSTR ) - 1 ) )
3175                 {
3176                         val = cargv[ i ] + sizeof( INTERVALSTR );
3177                         if ( si->si_type == LDAP_SYNC_REFRESH_AND_PERSIST ) {
3178                                 si->si_interval = 0;
3179                         } else {
3180                                 char *hstr;
3181                                 char *mstr;
3182                                 char *dstr;
3183                                 char *sstr;
3184                                 int dd, hh, mm, ss;
3185                                 dstr = val;
3186                                 hstr = strchr( dstr, ':' );
3187                                 if ( hstr == NULL ) {
3188                                         fprintf( stderr, "Error: parse_syncrepl_line: "
3189                                                 "invalid interval \"%s\"\n", val );
3190                                         return 1;
3191                                 }
3192                                 *hstr++ = '\0';
3193                                 mstr = strchr( hstr, ':' );
3194                                 if ( mstr == NULL ) {
3195                                         fprintf( stderr, "Error: parse_syncrepl_line: "
3196                                                 "invalid interval \"%s\"\n", val );
3197                                         return 1;
3198                                 }
3199                                 *mstr++ = '\0';
3200                                 sstr = strchr( mstr, ':' );
3201                                 if ( sstr == NULL ) {
3202                                         fprintf( stderr, "Error: parse_syncrepl_line: "
3203                                                 "invalid interval \"%s\"\n", val );
3204                                         return 1;
3205                                 }
3206                                 *sstr++ = '\0';
3207
3208                                 dd = atoi( dstr );
3209                                 hh = atoi( hstr );
3210                                 mm = atoi( mstr );
3211                                 ss = atoi( sstr );
3212                                 if (( hh > 24 ) || ( hh < 0 ) ||
3213                                         ( mm > 60 ) || ( mm < 0 ) ||
3214                                         ( ss > 60 ) || ( ss < 0 ) || ( dd < 0 )) {
3215                                         fprintf( stderr, "Error: parse_syncrepl_line: "
3216                                                 "invalid interval \"%s\"\n", val );
3217                                         return 1;
3218                                 }
3219                                 si->si_interval = (( dd * 24 + hh ) * 60 + mm ) * 60 + ss;
3220                         }
3221                         if ( si->si_interval < 0 ) {
3222                                 fprintf( stderr, "Error: parse_syncrepl_line: "
3223                                         "invalid interval \"%ld\"\n",
3224                                         (long) si->si_interval);
3225                                 return 1;
3226                         }
3227                 } else if ( !strncasecmp( cargv[ i ],
3228                         MANAGEDSAITSTR, sizeof( MANAGEDSAITSTR ) - 1 ) )
3229                 {
3230                         val = cargv[ i ] + sizeof( MANAGEDSAITSTR );
3231                         si->si_manageDSAit = atoi( val );
3232                 } else if ( !strncasecmp( cargv[ i ],
3233                         SLIMITSTR, sizeof( SLIMITSTR ) - 1 ) )
3234                 {
3235                         val = cargv[ i ] + sizeof( SLIMITSTR );
3236                         si->si_slimit = atoi( val );
3237                 } else if ( !strncasecmp( cargv[ i ],
3238                         TLIMITSTR, sizeof( TLIMITSTR ) - 1 ) )
3239                 {
3240                         val = cargv[ i ] + sizeof( TLIMITSTR );
3241                         si->si_tlimit = atoi( val );
3242                 } else {
3243                         fprintf( stderr, "Error: parse_syncrepl_line: "
3244                                 "unknown keyword \"%s\"\n", cargv[ i ] );
3245                 }
3246         }
3247
3248         if ( gots != GOT_ALL ) {
3249                 fprintf( stderr,
3250                         "Error: Malformed \"syncrepl\" line in slapd config file" );
3251                 return -1;
3252         }
3253
3254         return 0;
3255 }
3256
3257 char **
3258 str2clist( char ***out, char *in, const char *brkstr )
3259 {
3260         char    *str;
3261         char    *s;
3262         char    *lasts;
3263         int     i, j;
3264         const char *text;
3265         char    **new;
3266
3267         /* find last element in list */
3268         for (i = 0; *out && *out[i]; i++);
3269
3270         /* protect the input string from strtok */
3271         str = ch_strdup( in );
3272
3273         if ( *str == '\0' ) {
3274                 free( str );
3275                 return( *out );
3276         }
3277
3278         /* Count words in string */
3279         j=1;
3280         for ( s = str; *s; s++ ) {
3281                 if ( strchr( brkstr, *s ) != NULL ) {
3282                         j++;
3283                 }
3284         }
3285
3286         *out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
3287         new = *out + i;
3288         for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
3289                 s != NULL;
3290                 s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
3291         {
3292                 *new = ch_strdup( s );
3293                 new++;
3294         }
3295
3296         *new = NULL;
3297         free( str );
3298         return( *out );
3299 }