]> git.sur5r.net Git - openldap/blob - servers/slurpd/config.c
The world compiles and links....
[openldap] / servers / slurpd / config.c
1 /*
2  * Copyright (c) 1996 Regents of the University of Michigan.
3  * All rights reserved.
4  *
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.
11  */
12
13
14 /*
15  * config.c - configuration file handling routines
16  */
17
18 #include "portable.h"
19
20 #include <stdio.h>
21
22 #include <ac/string.h>
23 #include <ac/socket.h>
24
25 #include <lber.h>
26 #include <ldap.h>
27
28 #include "slurp.h"
29 #include "globals.h"
30
31 #define MAXARGS 100
32
33 /* Forward declarations */
34 static void     add_replica LDAP_P(( char **, int ));
35 static int      parse_replica_line LDAP_P(( char **, int, Ri *));
36 static void     parse_line LDAP_P(( char *, int *, char ** ));
37 static char     *getline LDAP_P(( FILE * ));
38 static char     *strtok_quote LDAP_P(( char *, char * ));
39
40 /* current config file line # */
41 static int      lineno;
42
43
44
45 /*
46  * Read the slapd config file, looking only for config options we're
47  * interested in.  Since we haven't detached from the controlling
48  * terminal yet, we just perror() and fprintf here.
49  */
50 int
51 slurpd_read_config(
52     char        *fname
53 )
54 {
55     FILE        *fp;
56     char        buf[BUFSIZ];
57     char        *line, *p;
58     int         cargc;
59     char        *cargv[MAXARGS];
60
61     Debug( LDAP_DEBUG_CONFIG, "Config: opening config file \"%s\"\n",
62             fname, 0, 0 );
63
64     if ( (fp = fopen( fname, "r" )) == NULL ) {
65         perror( fname );
66         exit( 1 );
67     }
68
69     lineno = 0;
70     while ( (line = getline( fp )) != NULL ) {
71         /* skip comments and blank lines */
72         if ( line[0] == '#' || line[0] == '\0' ) {
73             continue;
74         }
75
76         Debug( LDAP_DEBUG_CONFIG, "Config: (%s)\n", line, 0, 0 );
77
78         parse_line( line, &cargc, cargv );
79
80         if ( cargc < 1 ) {
81             fprintf( stderr, "line %d: bad config line (ignored)\n", lineno );
82             continue;
83         }
84
85         /* replication log file to which changes are appended */
86         if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
87             /* 
88              * if slapd_replogfile has a value, the -r option was given,
89              * so use that value.  If slapd_replogfile has length == 0,
90              * then we should use the value in the config file we're reading.
91              */
92             if ( sglob->slapd_replogfile[ 0 ] == '\0' ) {
93                 if ( cargc < 2 ) {
94                     fprintf( stderr,
95                         "line %d: missing filename in \"replogfile ",
96                         lineno );
97                     fprintf( stderr, "<filename>\" line\n" );
98                     exit( 1 );
99                 } else if ( cargc > 2 && *cargv[2] != '#' ) {
100                     fprintf( stderr,
101                         "line %d: extra cruft at the end of \"replogfile %s\"",
102                         lineno, cargv[1] );
103                     fprintf( stderr, "line (ignored)\n" );
104                 }
105                 sprintf( sglob->slapd_replogfile, cargv[1] );
106             }
107         } else if ( strcasecmp( cargv[0], "replica" ) == 0 ) {
108             add_replica( cargv, cargc );
109         }
110     }
111     fclose( fp );
112     Debug( LDAP_DEBUG_CONFIG,
113             "Config: ** configuration file successfully read and parsed\n",
114             0, 0, 0 );
115     return 0;
116 }
117
118
119
120
121 /*
122  * Parse one line of input.
123  */
124 static void
125 parse_line(
126     char        *line,
127     int         *argcp,
128     char        **argv
129 )
130 {
131     char *      token;
132
133     *argcp = 0;
134     for ( token = strtok_quote( line, " \t" ); token != NULL;
135         token = strtok_quote( NULL, " \t" ) ) {
136         argv[(*argcp)++] = token;
137     }
138     argv[*argcp] = NULL;
139 }
140
141
142
143
144 static char *
145 strtok_quote(
146     char *line,
147     char *sep
148 )
149 {
150     int         inquote;
151     char        *tmp;
152     static char *next;
153
154     if ( line != NULL ) {
155         next = line;
156     }
157     while ( *next && strchr( sep, *next ) ) {
158         next++;
159     }
160
161     if ( *next == '\0' ) {
162         next = NULL;
163         return( NULL );
164     }
165     tmp = next;
166
167     for ( inquote = 0; *next; ) {
168         switch ( *next ) {
169         case '"':
170             if ( inquote ) {
171                 inquote = 0;
172             } else {
173                 inquote = 1;
174             }
175             strcpy( next, next + 1 );
176             break;
177
178         case '\\':
179             strcpy( next, next + 1 );
180             break;
181
182         default:
183             if ( ! inquote ) {
184                 if ( strchr( sep, *next ) != NULL ) {
185                     *next++ = '\0';
186                     return( tmp );
187                 }
188             }
189             next++;
190             break;
191         }
192     }
193
194     return( tmp );
195 }
196
197 #define CATLINE( buf )  { \
198     int len; \
199     len = strlen( buf ); \
200     while ( lcur + len + 1 > lmax ) { \
201         lmax += BUFSIZ; \
202         line = (char *) ch_realloc( line, lmax ); \
203     } \
204     strcpy( line + lcur, buf ); \
205     lcur += len; \
206 }
207
208
209
210 /*
211  * Get a line of input.
212  */
213 static char *
214 getline(
215     FILE *fp
216 )
217 {
218     char        *p;
219     static char buf[BUFSIZ];
220     static char *line;
221     static int  lmax, lcur;
222
223     lcur = 0;
224     CATLINE( buf );
225     while ( fgets( buf, sizeof(buf), fp ) != NULL ) {
226         if ( (p = strchr( buf, '\n' )) != NULL ) {
227             *p = '\0';
228         }
229         lineno++;
230         if ( ! isspace( buf[0] ) ) {
231             return( line );
232         }
233
234         CATLINE( buf );
235     }
236     buf[0] = '\0';
237
238     return( line[0] ? line : NULL );
239 }
240
241
242 /*
243  * Add a node to the array of replicas.
244  */
245 static void
246 add_replica(
247     char        **cargv,
248     int         cargc
249 )
250 {
251     int nr;
252
253     nr = ++sglob->num_replicas;
254     sglob->replicas = (Ri **) ch_realloc( sglob->replicas,
255             ( nr + 1 )  * sizeof( Re * ));
256     if ( sglob->replicas == NULL ) {
257         fprintf( stderr, "out of memory, add_replica\n" );
258         exit( 1 );
259     }
260     sglob->replicas[ nr ] = NULL; 
261
262     if ( Ri_init( &(sglob->replicas[ nr - 1 ])) < 0 ) {
263         fprintf( stderr, "out of memory, Ri_init\n" );
264         exit( 1 );
265     }
266     if ( parse_replica_line( cargv, cargc,
267             sglob->replicas[ nr - 1] ) < 0 ) {
268         /* Something bad happened - back out */
269         fprintf( stderr,
270             "Warning: failed to add replica \"%s:%d - ignoring replica\n",
271             sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
272             "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
273             sglob->replicas[ nr - 1 ]->ri_port );
274         sglob->replicas[ nr - 1] = NULL;
275         sglob->num_replicas--;
276     } else {
277         Debug( LDAP_DEBUG_CONFIG,
278                 "Config: ** successfully added replica \"%s:%d\"\n",
279                 sglob->replicas[ nr - 1 ]->ri_hostname == NULL ?
280                 "(null)" : sglob->replicas[ nr - 1 ]->ri_hostname,
281                 sglob->replicas[ nr - 1 ]->ri_port, 0 );
282         sglob->replicas[ nr - 1]->ri_stel =
283                 sglob->st->st_add( sglob->st,
284                 sglob->replicas[ nr - 1 ] );
285         if ( sglob->replicas[ nr - 1]->ri_stel == NULL ) {
286             fprintf( stderr, "Failed to add status element structure\n" );
287             exit( 1 );
288         }
289     }
290 }
291
292
293
294 /* 
295  * Parse a "replica" line from the config file.  replica lines should be
296  * in the following format:
297  * replica    host=<hostname:portnumber> binddn=<binddn>
298  *            bindmethod="simple|kerberos" credentials=<creds>
299  *
300  * where:
301  * <hostname:portnumber> describes the host name and port number where the
302  * replica is running,
303  *
304  * <binddn> is the DN to bind to the replica slapd as,
305  *
306  * bindmethod is either "simple" or "kerberos", and
307  *
308  * <creds> are the credentials (e.g. password) for binddn.  <creds> are
309  * only used for bindmethod=simple.  For bindmethod=kerberos, the
310  * credentials= option should be omitted.  Credentials for kerberos
311  * authentication are in the system srvtab file.
312  *
313  * The "replica" config file line may be split across multiple lines.  If
314  * a line begins with whitespace, it is considered a continuation of the
315  * previous line.
316  */
317 #define GOT_HOST        1
318 #define GOT_DN          2
319 #define GOT_METHOD      4
320 #define GOT_ALL         ( GOT_HOST | GOT_DN | GOT_METHOD )
321 static int
322 parse_replica_line( 
323     char        **cargv,
324     int         cargc,
325     Ri          *ri
326 )
327 {
328     int         gots = 0;
329     int         i;
330     char        *hp, *val;
331
332     for ( i = 1; i < cargc; i++ ) {
333         if ( !strncasecmp( cargv[ i ], HOSTSTR, strlen( HOSTSTR ))) {
334             val = cargv[ i ] + strlen( HOSTSTR ) + 1;
335             if (( hp = strchr( val, ':' )) != NULL ) {
336                 *hp = '\0';
337                 hp++;
338                 ri->ri_port = atoi( hp );
339             }
340             if ( ri->ri_port <= 0 ) {
341                 ri->ri_port = LDAP_PORT;
342             }
343             ri->ri_hostname = strdup( val );
344             gots |= GOT_HOST;
345         } else if ( !strncasecmp( cargv[ i ],
346                 BINDDNSTR, strlen( BINDDNSTR ))) { 
347             val = cargv[ i ] + strlen( BINDDNSTR ) + 1;
348             ri->ri_bind_dn = strdup( val );
349             gots |= GOT_DN;
350         } else if ( !strncasecmp( cargv[ i ], BINDMETHSTR,
351                 strlen( BINDMETHSTR ))) {
352             val = cargv[ i ] + strlen( BINDMETHSTR ) + 1;
353             if ( !strcasecmp( val, KERBEROSSTR )) {
354 #ifdef HAVE_KERBEROS
355                 ri->ri_bind_method = AUTH_KERBEROS;
356                 if ( ri->ri_srvtab == NULL ) {
357                     ri->ri_srvtab = strdup( sglob->default_srvtab );
358                 }
359                 gots |= GOT_METHOD;
360 #else /* HAVE_KERBEROS */
361             fprintf( stderr, "Error: a bind method of \"kerberos\" was\n" );
362             fprintf( stderr, "specified in the slapd configuration file,\n" );
363             fprintf( stderr, "but slurpd was not built with kerberos.\n" );
364             fprintf( stderr, "You must rebuild the LDAP release with\n" );
365             fprintf( stderr, "kerberos support if you wish to use\n" );
366             fprintf( stderr, "bindmethod=kerberos\n" );
367             exit( 1 );
368 #endif /* HAVE_KERBEROS */
369             } else if ( !strcasecmp( val, SIMPLESTR )) {
370                 ri->ri_bind_method = AUTH_SIMPLE;
371                 gots |= GOT_METHOD;
372             } else {
373                 ri->ri_bind_method = -1;
374             }
375         } else if ( !strncasecmp( cargv[ i ], CREDSTR, strlen( CREDSTR ))) {
376             val = cargv[ i ] + strlen( CREDSTR ) + 1;
377             ri->ri_password = strdup( val );
378         } else if ( !strncasecmp( cargv[ i ], BINDPSTR, strlen( BINDPSTR ))) {
379             val = cargv[ i ] + strlen( BINDPSTR ) + 1;
380             ri->ri_principal = strdup( val );
381         } else if ( !strncasecmp( cargv[ i ], SRVTABSTR, strlen( SRVTABSTR ))) {
382             val = cargv[ i ] + strlen( SRVTABSTR ) + 1;
383             if ( ri->ri_srvtab != NULL ) {
384                 free( ri->ri_srvtab );
385             }
386             ri->ri_srvtab = strdup( val );
387         } else {
388             fprintf( stderr, 
389                     "Error: parse_replica_line: unknown keyword \"%s\"\n",
390                     cargv[ i ] );
391         }
392     }
393     if ( gots != GOT_ALL ) {
394             fprintf( stderr, "Error: Malformed \"replica\" line in slapd " );
395             fprintf( stderr, "config file, line %d\n", lineno );
396         return -1;
397     }
398     return 0;
399 }
400