3 * Copyright 1998-2000 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 *, int *, char ** ));
43 static char *getline LDAP_P(( FILE * ));
44 static char *strtok_quote LDAP_P(( char *, char * ));
46 /* current config file line # */
52 * Read the slapd config file, looking only for config options we're
53 * interested in. Since we haven't detached from the controlling
54 * terminal yet, we just perror() and fprintf here.
66 Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
69 if ( (fp = fopen( fname, "r" )) == NULL ) {
75 while ( (line = getline( fp )) != NULL ) {
76 /* skip comments and blank lines */
77 if ( line[0] == '#' || line[0] == '\0' ) {
81 Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
83 parse_line( line, &cargc, cargv );
86 fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
90 /* replication log file to which changes are appended */
91 if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
93 * if slapd_replogfile has a value, the -r option was given,
94 * so use that value. If slapd_replogfile has length == 0,
95 * then we should use the value in the config file we're reading.
97 if ( sglob->slapd_replogfile[ 0 ] == '\0' ) {
100 "line %d: missing filename in \"replogfile ",
102 fprintf( stderr, "<filename>\" line\n" );
103 exit( EXIT_FAILURE );
104 } else if ( cargc > 2 && *cargv[2] != '#' ) {
106 "line %d: extra cruft at the end of \"replogfile %s\"",
108 fprintf( stderr, "line (ignored)\n" );
110 strcpy( sglob->slapd_replogfile, cargv[1] );
112 } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
113 add_replica( cargv, cargc );
117 Debug( LDAP_DEBUG_CONFIG,
118 "Config: ** configuration file successfully read and parsed\n",
127 * Parse one line of input.
139 for ( token = strtok_quote( line, " \t" ); token != NULL;
140 token = strtok_quote( NULL, " \t" ) ) {
141 argv[(*argcp)++] = token;
159 if ( line != NULL ) {
162 while ( *next && strchr( sep, *next ) ) {
166 if ( *next == '\0' ) {
172 for ( inquote = 0; *next; ) {
180 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
185 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
186 next++; /* dont parse the escaped character */
191 if ( strchr( sep, *next ) != NULL ) {
204 #define CATLINE( buf ) { \
206 len = strlen( buf ); \
207 while ( lcur + len + 1 > lmax ) { \
209 line = (char *) ch_realloc( line, lmax ); \
211 strcpy( line + lcur, buf ); \
218 * Get a line of input.
226 static char buf[BUFSIZ];
228 static int lmax, lcur;
232 while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
233 if ( (p = strchr( buf, '\n' )) != NULL ) {
237 if ( ! isspace( (unsigned char) buf[0] ) ) {
245 return( line[0] ? line : NULL );
250 * Add a node to the array of replicas.
260 nr = ++sglob->num_replicas;
261 sglob->replicas = (Ri **) ch_realloc( sglob->replicas,
262 ( nr + 1 ) * sizeof( Re * ));
263 if ( sglob->replicas == NULL ) {
264 fprintf( stderr, "out of memory, add_replica\n" );
265 exit( EXIT_FAILURE );
267 sglob->replicas[ nr ] = NULL;
269 if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) {
270 fprintf( stderr, "out of memory, Ri_init\n" );
271 exit( EXIT_FAILURE );
273 if ( parse_replica_line( cargv, cargc,
274 sglob->replicas[ nr - 1] ) < 0 ) {
275 /* Something bad happened - back out */
277 "Warning: failed to add replica \"%s:%d - ignoring replica\n",
278 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
279 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
280 sglob->replicas[ nr - 1 ]->ri_port );
281 sglob->replicas[ nr - 1] = NULL;
282 sglob->num_replicas--;
284 Debug( LDAP_DEBUG_CONFIG,
285 "Config: ** successfully added replica \"%s:%d\"\n",
286 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
287 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
288 sglob->replicas[ nr - 1 ]->ri_port, 0 );
289 sglob->replicas[ nr - 1]->ri_stel =
290 sglob->st->st_add( sglob->st,
291 sglob->replicas[ nr - 1 ] );
292 if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) {
293 fprintf( stderr, "Failed to add status element structure\n" );
294 exit( EXIT_FAILURE );
302 * Parse a "replica" line from the config file. replica lines should be
303 * in the following format:
304 * replica host=<hostname:portnumber> binddn=<binddn>
305 * bindmethod="simple" credentials=<creds>
308 * <hostname:portnumber> describes the host name and port number where the
309 * replica is running,
311 * <binddn> is the DN to bind to the replica slapd as,
313 * bindmethod is "simple", and
315 * <creds> are the credentials (e.g. password) for binddn. <creds> are
316 * only used for bindmethod=simple.
318 * The "replica" config file line may be split across multiple lines. If
319 * a line begins with whitespace, it is considered a continuation of the
325 #define GOT_ALL ( GOT_HOST | GOT_DN | GOT_METHOD )
339 for ( i = 1; i < cargc; i++ ) {
340 if ( !strncasecmp( cargv[ i ], HOSTSTR, strlen( HOSTSTR ))) {
341 val = cargv[ i ] + strlen( HOSTSTR ) + 1;
342 if (( hp = strchr( val, ':' )) != NULL ) {
345 ri->ri_port = atoi( hp );
347 if ( ri->ri_port <= 0 ) {
350 ri->ri_hostname = strdup( val );
352 } else if ( !strncasecmp( cargv[ i ], TLSSTR, strlen( TLSSTR ))) {
353 val = cargv[ i ] + strlen( TLSSTR ) + 1;
354 if( !strcasecmp( val, TLSCRITICALSTR ) ) {
355 ri->ri_tls = TLS_CRITICAL;
359 } else if ( !strncasecmp( cargv[ i ],
360 BINDDNSTR, strlen( BINDDNSTR ))) {
361 val = cargv[ i ] + strlen( BINDDNSTR ) + 1;
362 ri->ri_bind_dn = strdup( val );
364 } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
365 strlen( BINDMETHSTR ))) {
366 val = cargv[ i ] + strlen( BINDMETHSTR ) + 1;
367 if ( !strcasecmp( val, KERBEROSSTR )) {
368 fprintf( stderr, "Error: a bind method of \"kerberos\" was\n" );
369 fprintf( stderr, "specified in the slapd configuration file.\n" );
370 fprintf( stderr, "slurpd no longer supports Kerberos.\n" );
371 exit( EXIT_FAILURE );
372 } else if ( !strcasecmp( val, SIMPLESTR )) {
373 ri->ri_bind_method = AUTH_SIMPLE;
375 } else if ( !strcasecmp( val, SASLSTR )) {
376 ri->ri_bind_method = AUTH_SASL;
379 ri->ri_bind_method = -1;
381 } else if ( !strncasecmp( cargv[ i ], SASLMECHSTR, strlen( SASLMECHSTR ))) {
382 val = cargv[ i ] + strlen( SASLMECHSTR ) + 1;
384 ri->ri_saslmech = strdup( val );
385 } else if ( !strncasecmp( cargv[ i ], CREDSTR, strlen( CREDSTR ))) {
386 val = cargv[ i ] + strlen( CREDSTR ) + 1;
387 ri->ri_password = strdup( val );
388 } else if ( !strncasecmp( cargv[ i ], SECPROPSSTR, strlen( SECPROPSSTR ))) {
389 val = cargv[ i ] + strlen( SECPROPSSTR ) + 1;
390 ri->ri_secprops = strdup( val );
391 } else if ( !strncasecmp( cargv[ i ], REALMSTR, strlen( REALMSTR ))) {
392 val = cargv[ i ] + strlen( REALMSTR ) + 1;
393 ri->ri_realm = strdup( val );
394 } else if ( !strncasecmp( cargv[ i ], AUTHCSTR, strlen( AUTHCSTR ))) {
395 val = cargv[ i ] + strlen( AUTHCSTR ) + 1;
396 ri->ri_authcId = strdup( val );
397 } else if ( !strncasecmp( cargv[ i ], OLDAUTHCSTR, strlen( OLDAUTHCSTR ))) {
398 /* Old authcID is provided for some backwards compatibility */
399 val = cargv[ i ] + strlen( OLDAUTHCSTR ) + 1;
400 ri->ri_authcId = strdup( val );
401 } else if ( !strncasecmp( cargv[ i ], AUTHZSTR, strlen( AUTHZSTR ))) {
402 val = cargv[ i ] + strlen( AUTHZSTR ) + 1;
403 ri->ri_authzId = strdup( val );
404 } else if ( !strncasecmp( cargv[ i ], SRVTABSTR, strlen( SRVTABSTR ))) {
405 val = cargv[ i ] + strlen( SRVTABSTR ) + 1;
406 if ( ri->ri_srvtab != NULL ) {
407 free( ri->ri_srvtab );
409 ri->ri_srvtab = strdup( val );
412 "Error: parse_replica_line: unknown keyword \"%s\"\n",
417 if ( ri->ri_bind_method == AUTH_SASL) {
418 if ((gots & GOT_MECH) == 0) {
419 fprintf( stderr, "Error: \"replica\" line needs SASLmech flag in " );
420 fprintf( stderr, "slapd config file, line %d\n", lineno );
424 else if ( gots != GOT_ALL ) {
425 fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
426 fprintf( stderr, "config file, line %d\n", lineno );