3 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * Copyright (c) 1996 Regents of the University of Michigan.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that this notice is preserved and that due credit is given
12 * to the University of Michigan at Ann Arbor. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission. This software
15 * is provided ``as is'' without express or implied warranty.
20 * config.c - configuration file handling routines
27 #include <ac/stdlib.h>
28 #include <ac/string.h>
29 #include <ac/socket.h>
39 /* Forward declarations */
40 static void add_replica LDAP_P(( char **, int ));
41 static int parse_replica_line LDAP_P(( char **, int, Ri *));
42 static void parse_line LDAP_P(( char * ));
43 static char *getline LDAP_P(( FILE * ));
44 static char *strtok_quote LDAP_P(( char *, char * ));
46 int cargc = 0, cargv_size = 0;
48 /* current config file line # */
54 * Read the slapd config file, looking only for config options we're
55 * interested in. Since we haven't detached from the controlling
56 * terminal yet, we just perror() and fprintf here.
66 cargv = ch_calloc( ARGS_STEP + 1, sizeof(*cargv) );
67 cargv_size = ARGS_STEP + 1;
70 LDAP_LOG (( "config", LDAP_LEVEL_ARGS,
71 "slurpd_read_config: Config: opening config file \"%s\"\n", fname ));
73 Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
77 if ( (fp = fopen( fname, "r" )) == NULL ) {
83 while ( (line = getline( fp )) != NULL ) {
84 /* skip comments and blank lines */
85 if ( line[0] == '#' || line[0] == '\0' ) {
90 LDAP_LOG (( "config", LDAP_LEVEL_DETAIL1,
91 "slurpd_read_config: Config: (%s)\n", line ));
93 Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
99 fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
103 /* replication log file to which changes are appended */
104 if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
106 * if slapd_replogfile has a value, the -r option was given,
107 * so use that value. If slapd_replogfile has length == 0,
108 * then we should use the value in the config file we're reading.
110 if ( sglob->slapd_replogfile[ 0 ] == '\0' ) {
113 "line %d: missing filename in \"replogfile ",
115 fprintf( stderr, "<filename>\" line\n" );
116 exit( EXIT_FAILURE );
117 } else if ( cargc > 2 && *cargv[2] != '#' ) {
119 "line %d: extra cruft at the end of \"replogfile %s\"",
121 fprintf( stderr, "line (ignored)\n" );
123 strcpy( sglob->slapd_replogfile, cargv[1] );
125 } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
126 add_replica( cargv, cargc );
128 /* include another config file */
129 } else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
135 LDAP_LOG(( "config", LDAP_LEVEL_CRIT,
136 "%s: line %d: missing filename in \"include "
137 "<filename>\" line.\n", fname, lineno ));
139 Debug( LDAP_DEBUG_ANY,
140 "%s: line %d: missing filename in \"include <filename>\" line\n",
146 savefname = strdup( cargv[1] );
149 if ( slurpd_read_config( savefname ) != 0 ) {
154 lineno = savelineno - 1;
159 LDAP_LOG (( "config", LDAP_LEVEL_RESULTS,
160 "slurpd_read_config: Config: "
161 "** configuration file successfully read and parsed\n" ));
163 Debug( LDAP_DEBUG_CONFIG,
164 "Config: ** configuration file successfully read and parsed\n",
174 * Parse one line of input.
184 for ( token = strtok_quote( line, " \t" ); token != NULL;
185 token = strtok_quote( NULL, " \t" ) )
187 if ( cargc == cargv_size - 1 ) {
189 tmp = ch_realloc( cargv, (cargv_size + ARGS_STEP) *
196 cargv_size += ARGS_STEP;
199 cargv[cargc++] = token;
217 if ( line != NULL ) {
220 while ( *next && strchr( sep, *next ) ) {
224 if ( *next == '\0' ) {
230 for ( inquote = 0; *next; ) {
238 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
243 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
244 next++; /* dont parse the escaped character */
249 if ( strchr( sep, *next ) != NULL ) {
262 #define CATLINE( buf ) { \
264 len = strlen( buf ); \
265 while ( lcur + len + 1 > lmax ) { \
267 line = (char *) ch_realloc( line, lmax ); \
269 strcpy( line + lcur, buf ); \
276 * Get a line of input.
284 static char buf[BUFSIZ];
286 static int lmax, lcur;
290 while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
291 if ( (p = strchr( buf, '\n' )) != NULL ) {
292 if( p > buf && p[-1] == '\r' ) --p;
296 if ( ! isspace( (unsigned char) buf[0] ) ) {
300 /* change leading whitespace to space */
307 return( line[0] ? line : NULL );
312 * Add a node to the array of replicas.
322 nr = ++sglob->num_replicas;
323 sglob->replicas = (Ri **) ch_realloc( sglob->replicas,
324 ( nr + 1 ) * sizeof( Re * ));
325 if ( sglob->replicas == NULL ) {
326 fprintf( stderr, "out of memory, add_replica\n" );
327 exit( EXIT_FAILURE );
329 sglob->replicas[ nr ] = NULL;
331 if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) {
332 fprintf( stderr, "out of memory, Ri_init\n" );
333 exit( EXIT_FAILURE );
335 if ( parse_replica_line( cargv, cargc,
336 sglob->replicas[ nr - 1] ) < 0 ) {
337 /* Something bad happened - back out */
339 "Warning: failed to add replica \"%s:%d - ignoring replica\n",
340 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
341 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
342 sglob->replicas[ nr - 1 ]->ri_port );
343 sglob->replicas[ nr - 1] = NULL;
344 sglob->num_replicas--;
347 LDAP_LOG (( "config", LDAP_LEVEL_RESULTS,
348 "add_replica: Config: ** successfully added replica \"%s%d\"\n",
349 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
350 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
351 sglob->replicas[ nr - 1 ]->ri_port, 0 ));
353 Debug( LDAP_DEBUG_CONFIG,
354 "Config: ** successfully added replica \"%s:%d\"\n",
355 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
356 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
357 sglob->replicas[ nr - 1 ]->ri_port, 0 );
359 sglob->replicas[ nr - 1]->ri_stel =
360 sglob->st->st_add( sglob->st,
361 sglob->replicas[ nr - 1 ] );
362 if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) {
363 fprintf( stderr, "Failed to add status element structure\n" );
364 exit( EXIT_FAILURE );
372 * Parse a "replica" line from the config file. replica lines should be
373 * in the following format:
374 * replica host=<hostname:portnumber> binddn=<binddn>
375 * bindmethod="simple" credentials=<creds>
378 * <hostname:portnumber> describes the host name and port number where the
379 * replica is running,
381 * <binddn> is the DN to bind to the replica slapd as,
383 * bindmethod is "simple", and
385 * <creds> are the credentials (e.g. password) for binddn. <creds> are
386 * only used for bindmethod=simple.
388 * The "replica" config file line may be split across multiple lines. If
389 * a line begins with whitespace, it is considered a continuation of the
395 #define GOT_ALL ( GOT_HOST | GOT_DN | GOT_METHOD )
409 for ( i = 1; i < cargc; i++ ) {
410 if ( !strncasecmp( cargv[ i ], HOSTSTR, sizeof( HOSTSTR ) - 1 ) ) {
411 val = cargv[ i ] + sizeof( HOSTSTR ); /* '\0' string terminator accounts for '=' */
412 if (( hp = strchr( val, ':' )) != NULL ) {
415 ri->ri_port = atoi( hp );
417 if ( ri->ri_port <= 0 ) {
420 ri->ri_hostname = strdup( val );
422 } else if ( !strncasecmp( cargv[ i ],
423 ATTRSTR, sizeof( ATTRSTR ) - 1 ) ) {
425 } else if ( !strncasecmp( cargv[ i ],
426 SUFFIXSTR, sizeof( SUFFIXSTR ) - 1 ) ) {
428 } else if ( !strncasecmp( cargv[ i ], TLSSTR, sizeof( TLSSTR ) - 1 ) ) {
429 val = cargv[ i ] + sizeof( TLSSTR );
430 if( !strcasecmp( val, TLSCRITICALSTR ) ) {
431 ri->ri_tls = TLS_CRITICAL;
435 } else if ( !strncasecmp( cargv[ i ],
436 BINDDNSTR, sizeof( BINDDNSTR ) - 1 ) ) {
437 val = cargv[ i ] + sizeof( BINDDNSTR );
438 ri->ri_bind_dn = strdup( val );
440 } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
441 sizeof( BINDMETHSTR ) - 1 ) ) {
442 val = cargv[ i ] + sizeof( BINDMETHSTR );
443 if ( !strcasecmp( val, KERBEROSSTR )) {
444 fprintf( stderr, "Error: a bind method of \"kerberos\" was\n" );
445 fprintf( stderr, "specified in the slapd configuration file.\n" );
446 fprintf( stderr, "slurpd no longer supports Kerberos.\n" );
447 exit( EXIT_FAILURE );
448 } else if ( !strcasecmp( val, SIMPLESTR )) {
449 ri->ri_bind_method = AUTH_SIMPLE;
451 } else if ( !strcasecmp( val, SASLSTR )) {
452 ri->ri_bind_method = AUTH_SASL;
455 ri->ri_bind_method = -1;
457 } else if ( !strncasecmp( cargv[ i ],
458 SASLMECHSTR, sizeof( SASLMECHSTR ) - 1 ) ) {
459 val = cargv[ i ] + sizeof( SASLMECHSTR );
461 ri->ri_saslmech = strdup( val );
462 } else if ( !strncasecmp( cargv[ i ],
463 CREDSTR, sizeof( CREDSTR ) - 1 ) ) {
464 val = cargv[ i ] + sizeof( CREDSTR );
465 ri->ri_password = strdup( val );
466 } else if ( !strncasecmp( cargv[ i ],
467 SECPROPSSTR, sizeof( SECPROPSSTR ) - 1 ) ) {
468 val = cargv[ i ] + sizeof( SECPROPSSTR );
469 ri->ri_secprops = strdup( val );
470 } else if ( !strncasecmp( cargv[ i ],
471 REALMSTR, sizeof( REALMSTR ) - 1 ) ) {
472 val = cargv[ i ] + sizeof( REALMSTR );
473 ri->ri_realm = strdup( val );
474 } else if ( !strncasecmp( cargv[ i ],
475 AUTHCSTR, sizeof( AUTHCSTR ) - 1 ) ) {
476 val = cargv[ i ] + sizeof( AUTHCSTR );
477 ri->ri_authcId = strdup( val );
478 } else if ( !strncasecmp( cargv[ i ],
479 OLDAUTHCSTR, sizeof( OLDAUTHCSTR ) - 1 ) ) {
480 /* Old authcID is provided for some backwards compatibility */
481 val = cargv[ i ] + sizeof( OLDAUTHCSTR );
482 ri->ri_authcId = strdup( val );
483 } else if ( !strncasecmp( cargv[ i ],
484 AUTHZSTR, sizeof( AUTHZSTR ) - 1 ) ) {
485 val = cargv[ i ] + sizeof( AUTHZSTR );
486 ri->ri_authzId = strdup( val );
487 } else if ( !strncasecmp( cargv[ i ],
488 SRVTABSTR, sizeof( SRVTABSTR ) - 1 ) ) {
489 val = cargv[ i ] + sizeof( SRVTABSTR );
490 if ( ri->ri_srvtab != NULL ) {
491 free( ri->ri_srvtab );
493 ri->ri_srvtab = strdup( val );
496 "Error: parse_replica_line: unknown keyword \"%s\"\n",
501 if ( ri->ri_bind_method == AUTH_SASL) {
502 if ((gots & GOT_MECH) == 0) {
503 fprintf( stderr, "Error: \"replica\" line needs SASLmech flag in " );
504 fprintf( stderr, "slapd config file, line %d\n", lineno );
508 else if ( gots != GOT_ALL ) {
509 fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
510 fprintf( stderr, "config file, line %d\n", lineno );