2 * Copyright (c) 1996 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
15 * config.c - configuration file handling routines
22 #include <sys/types.h>
23 #include <sys/socket.h>
33 /* Forward declarations */
35 static void add_replica( char **, int );
36 static int parse_replica_line( char **, int, Ri *);
37 static void parse_line( char *, int *, char ** );
38 static char *getline( FILE * );
39 static char *strtok_quote( char *, char * );
40 #else /* NEEDPROTOS */
41 static void add_replica();
42 static int parse_replica_line();
43 static void parse_line();
44 static char *getline();
45 static char *strtok_quote();
46 #endif /* NEEDPROTOS */
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.
69 Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
72 if ( (fp = fopen( fname, "r" )) == NULL ) {
78 while ( (line = getline( fp )) != NULL ) {
79 /* skip comments and blank lines */
80 if ( line[0] == '#' || line[0] == '\0' ) {
84 Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
86 parse_line( line, &cargc, cargv );
89 fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
93 /* replication log file to which changes are appended */
94 if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
96 * if slapd_replogfile has a value, the -r option was given,
97 * so use that value. If slapd_replogfile has length == 0,
98 * then we should use the value in the config file we're reading.
100 if ( sglob->slapd_replogfile[ 0 ] == '\0' ) {
103 "line %d: missing filename in \"replogfile ",
105 fprintf( stderr, "<filename>\" line\n" );
107 } else if ( cargc > 2 && *cargv[2] != '#' ) {
109 "line %d: extra cruft at the end of \"replogfile %s\"",
111 fprintf( stderr, "line (ignored)\n" );
113 sprintf( sglob->slapd_replogfile, cargv[1] );
115 } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
116 add_replica( cargv, cargc );
120 Debug( LDAP_DEBUG_CONFIG,
121 "Config: ** configuration file successfully read and parsed\n",
130 * Parse one line of input.
142 for ( token = strtok_quote( line, " \t" ); token != NULL;
143 token = strtok_quote( NULL, " \t" ) ) {
144 argv[(*argcp)++] = token;
162 if ( line != NULL ) {
165 while ( *next && strchr( sep, *next ) ) {
169 if ( *next == '\0' ) {
175 for ( inquote = 0; *next; ) {
183 strcpy( next, next + 1 );
187 strcpy( next, next + 1 );
192 if ( strchr( sep, *next ) != NULL ) {
205 #define CATLINE( buf ) { \
207 len = strlen( buf ); \
208 while ( lcur + len + 1 > lmax ) { \
210 line = (char *) ch_realloc( line, lmax ); \
212 strcpy( line + lcur, buf ); \
219 * Get a line of input.
227 static char buf[BUFSIZ];
229 static int lmax, lcur;
233 while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
234 if ( (p = strchr( buf, '\n' )) != NULL ) {
238 if ( ! isspace( buf[0] ) ) {
246 return( line[0] ? line : NULL );
251 * Add a node to the array of replicas.
261 nr = ++sglob->num_replicas;
262 sglob->replicas = (Ri **) ch_realloc( sglob->replicas,
263 ( nr + 1 ) * sizeof( Re * ));
264 if ( sglob->replicas == NULL ) {
265 fprintf( stderr, "out of memory, add_replica\n" );
268 sglob->replicas[ nr ] = NULL;
270 if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) {
271 fprintf( stderr, "out of memory, Ri_init\n" );
274 if ( parse_replica_line( cargv, cargc,
275 sglob->replicas[ nr - 1] ) < 0 ) {
276 /* Something bad happened - back out */
278 "Warning: failed to add replica \"%s:%d - ignoring replica\n",
279 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
280 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
281 sglob->replicas[ nr - 1 ]->ri_port );
282 sglob->replicas[ nr - 1] = NULL;
283 sglob->num_replicas--;
285 Debug( LDAP_DEBUG_CONFIG,
286 "Config: ** successfully added replica \"%s:%d\"\n",
287 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
288 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
289 sglob->replicas[ nr - 1 ]->ri_port, 0 );
290 sglob->replicas[ nr - 1]->ri_stel =
291 sglob->st->st_add( sglob->st,
292 sglob->replicas[ nr - 1 ] );
293 if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) {
294 fprintf( stderr, "Failed to add status element structure\n" );
303 * Parse a "replica" line from the config file. replica lines should be
304 * in the following format:
305 * replica host=<hostname:portnumber> binddn=<binddn>
306 * bindmethod="simple|kerberos" credentials=<creds>
309 * <hostname:portnumber> describes the host name and port number where the
310 * replica is running,
312 * <binddn> is the DN to bind to the replica slapd as,
314 * bindmethod is either "simple" or "kerberos", and
316 * <creds> are the credentials (e.g. password) for binddn. <creds> are
317 * only used for bindmethod=simple. For bindmethod=kerberos, the
318 * credentials= option should be omitted. Credentials for kerberos
319 * authentication are in the system srvtab file.
321 * The "replica" config file line may be split across multiple lines. If
322 * a line begins with whitespace, it is considered a continuation of the
328 #define GOT_ALL ( GOT_HOST | GOT_DN | GOT_METHOD )
340 for ( i = 1; i < cargc; i++ ) {
341 if ( !strncasecmp( cargv[ i ], HOSTSTR, strlen( HOSTSTR ))) {
342 val = cargv[ i ] + strlen( HOSTSTR ) + 1;
343 if (( hp = strchr( val, ':' )) != NULL ) {
346 ri->ri_port = atoi( hp );
348 if ( ri->ri_port <= 0 ) {
349 ri->ri_port = LDAP_PORT;
351 ri->ri_hostname = strdup( val );
353 } else if ( !strncasecmp( cargv[ i ],
354 BINDDNSTR, strlen( BINDDNSTR ))) {
355 val = cargv[ i ] + strlen( BINDDNSTR ) + 1;
356 ri->ri_bind_dn = strdup( val );
358 } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
359 strlen( BINDMETHSTR ))) {
360 val = cargv[ i ] + strlen( BINDMETHSTR ) + 1;
361 if ( !strcasecmp( val, KERBEROSSTR )) {
363 ri->ri_bind_method = AUTH_KERBEROS;
364 if ( ri->ri_srvtab == NULL ) {
365 ri->ri_srvtab = strdup( sglob->default_srvtab );
369 fprintf( stderr, "Error: a bind method of \"kerberos\" was\n" );
370 fprintf( stderr, "specified in the slapd configuration file,\n" );
371 fprintf( stderr, "but slurpd was not built with kerberos.\n" );
372 fprintf( stderr, "You must rebuild the LDAP release with\n" );
373 fprintf( stderr, "kerberos support if you wish to use\n" );
374 fprintf( stderr, "bindmethod=kerberos\n" );
376 #endif /* KERBEROS */
377 } else if ( !strcasecmp( val, SIMPLESTR )) {
378 ri->ri_bind_method = AUTH_SIMPLE;
381 ri->ri_bind_method = -1;
383 } else if ( !strncasecmp( cargv[ i ], CREDSTR, strlen( CREDSTR ))) {
384 val = cargv[ i ] + strlen( CREDSTR ) + 1;
385 ri->ri_password = strdup( val );
386 } else if ( !strncasecmp( cargv[ i ], BINDPSTR, strlen( BINDPSTR ))) {
387 val = cargv[ i ] + strlen( BINDPSTR ) + 1;
388 ri->ri_principal = strdup( val );
389 } else if ( !strncasecmp( cargv[ i ], SRVTABSTR, strlen( SRVTABSTR ))) {
390 val = cargv[ i ] + strlen( SRVTABSTR ) + 1;
391 if ( ri->ri_srvtab != NULL ) {
392 free( ri->ri_srvtab );
394 ri->ri_srvtab = strdup( val );
397 "Error: parse_replica_line: unknown keyword \"%s\"\n",
401 if ( gots != GOT_ALL ) {
402 fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
403 fprintf( stderr, "config file, line %d\n", lineno );