xref: /freebsd/crypto/heimdal/lib/krb5/config_file.c (revision 5e9cd1ae3e10592ed70e7575551cba1bbab04d84)
1b528cefcSMark Murray /*
25e9cd1aeSAssar Westerlund  * Copyright (c) 1997, 1998, 1999, 2000 Kungliga Tekniska H�gskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34b528cefcSMark Murray #include "krb5_locl.h"
355e9cd1aeSAssar Westerlund RCSID("$Id: config_file.c,v 1.41 2000/08/16 07:40:36 assar Exp $");
36b528cefcSMark Murray 
37b528cefcSMark Murray #ifndef HAVE_NETINFO
38b528cefcSMark Murray 
39b528cefcSMark Murray static int parse_section(char *p, krb5_config_section **s,
40b528cefcSMark Murray 			 krb5_config_section **res,
41b528cefcSMark Murray 			 char **error_message);
42b528cefcSMark Murray static int parse_binding(FILE *f, unsigned *lineno, char *p,
43b528cefcSMark Murray 			 krb5_config_binding **b,
44b528cefcSMark Murray 			 krb5_config_binding **parent,
45b528cefcSMark Murray 			 char **error_message);
46b528cefcSMark Murray static int parse_list(FILE *f, unsigned *lineno, krb5_config_binding **parent,
47b528cefcSMark Murray 		      char **error_message);
48b528cefcSMark Murray 
49b528cefcSMark Murray /*
50b528cefcSMark Murray  * Parse a section:
51b528cefcSMark Murray  *
52b528cefcSMark Murray  * [section]
53b528cefcSMark Murray  *	foo = bar
54b528cefcSMark Murray  *	b = {
55b528cefcSMark Murray  *		a
56b528cefcSMark Murray  *	    }
57b528cefcSMark Murray  * ...
58b528cefcSMark Murray  *
59b528cefcSMark Murray  * starting at the line in `p', storing the resulting structure in
60b528cefcSMark Murray  * `s' and hooking it into `parent'.
61b528cefcSMark Murray  * Store the error message in `error_message'.
62b528cefcSMark Murray  */
63b528cefcSMark Murray 
64b528cefcSMark Murray static int
65b528cefcSMark Murray parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
66b528cefcSMark Murray 	      char **error_message)
67b528cefcSMark Murray {
68b528cefcSMark Murray     char *p1;
69b528cefcSMark Murray     krb5_config_section *tmp;
70b528cefcSMark Murray 
71b528cefcSMark Murray     p1 = strchr (p + 1, ']');
72b528cefcSMark Murray     if (p1 == NULL) {
73b528cefcSMark Murray 	*error_message = "missing ]";
74b528cefcSMark Murray 	return -1;
75b528cefcSMark Murray     }
76b528cefcSMark Murray     *p1 = '\0';
77b528cefcSMark Murray     tmp = malloc(sizeof(*tmp));
78b528cefcSMark Murray     if (tmp == NULL) {
79b528cefcSMark Murray 	*error_message = "out of memory";
80b528cefcSMark Murray 	return -1;
81b528cefcSMark Murray     }
82b528cefcSMark Murray     tmp->name = strdup(p+1);
83b528cefcSMark Murray     if (tmp->name == NULL) {
84b528cefcSMark Murray 	*error_message = "out of memory";
85b528cefcSMark Murray 	return -1;
86b528cefcSMark Murray     }
87b528cefcSMark Murray     tmp->type = krb5_config_list;
88b528cefcSMark Murray     tmp->u.list = NULL;
89b528cefcSMark Murray     tmp->next = NULL;
90b528cefcSMark Murray     if (*s)
91b528cefcSMark Murray 	(*s)->next = tmp;
92b528cefcSMark Murray     else
93b528cefcSMark Murray 	*parent = tmp;
94b528cefcSMark Murray     *s = tmp;
95b528cefcSMark Murray     return 0;
96b528cefcSMark Murray }
97b528cefcSMark Murray 
98b528cefcSMark Murray /*
99b528cefcSMark Murray  * Parse a brace-enclosed list from `f', hooking in the structure at
100b528cefcSMark Murray  * `parent'.
101b528cefcSMark Murray  * Store the error message in `error_message'.
102b528cefcSMark Murray  */
103b528cefcSMark Murray 
104b528cefcSMark Murray static int
105b528cefcSMark Murray parse_list(FILE *f, unsigned *lineno, krb5_config_binding **parent,
106b528cefcSMark Murray 	   char **error_message)
107b528cefcSMark Murray {
108b528cefcSMark Murray     char buf[BUFSIZ];
109b528cefcSMark Murray     int ret;
110b528cefcSMark Murray     krb5_config_binding *b = NULL;
111b528cefcSMark Murray     unsigned beg_lineno = *lineno;
112b528cefcSMark Murray 
113b528cefcSMark Murray     while(fgets(buf, sizeof(buf), f) != NULL) {
114b528cefcSMark Murray 	char *p;
115b528cefcSMark Murray 
116b528cefcSMark Murray 	++*lineno;
117b528cefcSMark Murray 	if (buf[strlen(buf) - 1] == '\n')
118b528cefcSMark Murray 	    buf[strlen(buf) - 1] = '\0';
119b528cefcSMark Murray 	p = buf;
120b528cefcSMark Murray 	while(isspace((unsigned char)*p))
121b528cefcSMark Murray 	    ++p;
122b528cefcSMark Murray 	if (*p == '#' || *p == ';' || *p == '\0')
123b528cefcSMark Murray 	    continue;
124b528cefcSMark Murray 	while(isspace((unsigned char)*p))
125b528cefcSMark Murray 	    ++p;
126b528cefcSMark Murray 	if (*p == '}')
127b528cefcSMark Murray 	    return 0;
128b528cefcSMark Murray 	if (*p == '\0')
129b528cefcSMark Murray 	    continue;
130b528cefcSMark Murray 	ret = parse_binding (f, lineno, p, &b, parent, error_message);
131b528cefcSMark Murray 	if (ret)
132b528cefcSMark Murray 	    return ret;
133b528cefcSMark Murray     }
134b528cefcSMark Murray     *lineno = beg_lineno;
135b528cefcSMark Murray     *error_message = "unclosed {";
136b528cefcSMark Murray     return -1;
137b528cefcSMark Murray }
138b528cefcSMark Murray 
139b528cefcSMark Murray /*
140b528cefcSMark Murray  *
141b528cefcSMark Murray  */
142b528cefcSMark Murray 
143b528cefcSMark Murray static int
144b528cefcSMark Murray parse_binding(FILE *f, unsigned *lineno, char *p,
145b528cefcSMark Murray 	      krb5_config_binding **b, krb5_config_binding **parent,
146b528cefcSMark Murray 	      char **error_message)
147b528cefcSMark Murray {
148b528cefcSMark Murray     krb5_config_binding *tmp;
149b528cefcSMark Murray     char *p1, *p2;
150b528cefcSMark Murray     int ret = 0;
151b528cefcSMark Murray 
152b528cefcSMark Murray     p1 = p;
153b528cefcSMark Murray     while (*p && *p != '=' && !isspace((unsigned char)*p))
154b528cefcSMark Murray 	++p;
155b528cefcSMark Murray     if (*p == '\0') {
156b528cefcSMark Murray 	*error_message = "no =";
157b528cefcSMark Murray 	return -1;
158b528cefcSMark Murray     }
159b528cefcSMark Murray     p2 = p;
160b528cefcSMark Murray     while (isspace((unsigned char)*p))
161b528cefcSMark Murray 	++p;
162b528cefcSMark Murray     if (*p != '=') {
163b528cefcSMark Murray 	*error_message = "no =";
164b528cefcSMark Murray 	return -1;
165b528cefcSMark Murray     }
166b528cefcSMark Murray     ++p;
167b528cefcSMark Murray     while(isspace((unsigned char)*p))
168b528cefcSMark Murray 	++p;
169b528cefcSMark Murray     tmp = malloc(sizeof(*tmp));
170b528cefcSMark Murray     if (tmp == NULL) {
171b528cefcSMark Murray 	*error_message = "out of memory";
172b528cefcSMark Murray 	return -1;
173b528cefcSMark Murray     }
174b528cefcSMark Murray     *p2 = '\0';
175b528cefcSMark Murray     tmp->name = strdup(p1);
176b528cefcSMark Murray     tmp->next = NULL;
177b528cefcSMark Murray     if (*p == '{') {
178b528cefcSMark Murray 	tmp->type = krb5_config_list;
179b528cefcSMark Murray 	tmp->u.list = NULL;
180b528cefcSMark Murray 	ret = parse_list (f, lineno, &tmp->u.list, error_message);
181b528cefcSMark Murray     } else {
182b528cefcSMark Murray 	p1 = p;
183b528cefcSMark Murray 	p = p1 + strlen(p1);
184b528cefcSMark Murray 	while(p > p1 && isspace((unsigned char)*(p-1)))
185b528cefcSMark Murray 	    --p;
186b528cefcSMark Murray 	*p = '\0';
187b528cefcSMark Murray 	tmp->type = krb5_config_string;
188b528cefcSMark Murray 	tmp->u.string = strdup(p1);
189b528cefcSMark Murray     }
190b528cefcSMark Murray     if (*b)
191b528cefcSMark Murray 	(*b)->next = tmp;
192b528cefcSMark Murray     else
193b528cefcSMark Murray 	*parent = tmp;
194b528cefcSMark Murray     *b = tmp;
195b528cefcSMark Murray     return ret;
196b528cefcSMark Murray }
197b528cefcSMark Murray 
198b528cefcSMark Murray /*
199b528cefcSMark Murray  * Parse the config file `fname', generating the structures into `res'
200b528cefcSMark Murray  * returning error messages in `error_message'
201b528cefcSMark Murray  */
202b528cefcSMark Murray 
203b528cefcSMark Murray krb5_error_code
204b528cefcSMark Murray krb5_config_parse_file_debug (const char *fname,
205b528cefcSMark Murray 			      krb5_config_section **res,
206b528cefcSMark Murray 			      unsigned *lineno,
207b528cefcSMark Murray 			      char **error_message)
208b528cefcSMark Murray {
209b528cefcSMark Murray     FILE *f;
210b528cefcSMark Murray     krb5_config_section *s;
211b528cefcSMark Murray     krb5_config_binding *b;
212b528cefcSMark Murray     char buf[BUFSIZ];
2135e9cd1aeSAssar Westerlund     int ret = 0;
214b528cefcSMark Murray 
215b528cefcSMark Murray     s = NULL;
216b528cefcSMark Murray     b = NULL;
217b528cefcSMark Murray     *lineno = 0;
218b528cefcSMark Murray     f = fopen (fname, "r");
219b528cefcSMark Murray     if (f == NULL) {
220b528cefcSMark Murray 	*error_message = "cannot open file";
2215e9cd1aeSAssar Westerlund 	return ENOENT;
222b528cefcSMark Murray     }
223b528cefcSMark Murray     *res = NULL;
224b528cefcSMark Murray     while (fgets(buf, sizeof(buf), f) != NULL) {
225b528cefcSMark Murray 	char *p;
226b528cefcSMark Murray 
227b528cefcSMark Murray 	++*lineno;
228b528cefcSMark Murray 	if(buf[strlen(buf) - 1] == '\n')
229b528cefcSMark Murray 	    buf[strlen(buf) - 1] = '\0';
230b528cefcSMark Murray 	p = buf;
231b528cefcSMark Murray 	while(isspace((unsigned char)*p))
232b528cefcSMark Murray 	    ++p;
233b528cefcSMark Murray 	if (*p == '#' || *p == ';')
234b528cefcSMark Murray 	    continue;
235b528cefcSMark Murray 	if (*p == '[') {
236b528cefcSMark Murray 	    ret = parse_section(p, &s, res, error_message);
2375e9cd1aeSAssar Westerlund 	    if (ret) {
2385e9cd1aeSAssar Westerlund 		goto out;
2395e9cd1aeSAssar Westerlund 	    }
240b528cefcSMark Murray 	    b = NULL;
241b528cefcSMark Murray 	} else if (*p == '}') {
242b528cefcSMark Murray 	    *error_message = "unmatched }";
2435e9cd1aeSAssar Westerlund 	    ret = -1;
2445e9cd1aeSAssar Westerlund 	    goto out;
245b528cefcSMark Murray 	} else if(*p != '\0') {
246b528cefcSMark Murray 	    ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message);
247b528cefcSMark Murray 	    if (ret)
2485e9cd1aeSAssar Westerlund 		goto out;
249b528cefcSMark Murray 	}
250b528cefcSMark Murray     }
2515e9cd1aeSAssar Westerlund out:
252b528cefcSMark Murray     fclose (f);
2535e9cd1aeSAssar Westerlund     return ret;
254b528cefcSMark Murray }
255b528cefcSMark Murray 
256b528cefcSMark Murray krb5_error_code
257b528cefcSMark Murray krb5_config_parse_file (const char *fname, krb5_config_section **res)
258b528cefcSMark Murray {
259b528cefcSMark Murray     char *foo;
260b528cefcSMark Murray     unsigned lineno;
261b528cefcSMark Murray 
262b528cefcSMark Murray     return krb5_config_parse_file_debug (fname, res, &lineno, &foo);
263b528cefcSMark Murray }
264b528cefcSMark Murray 
265b528cefcSMark Murray #endif /* !HAVE_NETINFO */
266b528cefcSMark Murray 
267b528cefcSMark Murray static void
268b528cefcSMark Murray free_binding (krb5_context context, krb5_config_binding *b)
269b528cefcSMark Murray {
270b528cefcSMark Murray     krb5_config_binding *next_b;
271b528cefcSMark Murray 
272b528cefcSMark Murray     while (b) {
273b528cefcSMark Murray 	free (b->name);
274b528cefcSMark Murray 	if (b->type == krb5_config_string)
275b528cefcSMark Murray 	    free (b->u.string);
276b528cefcSMark Murray 	else if (b->type == krb5_config_list)
277b528cefcSMark Murray 	    free_binding (context, b->u.list);
278b528cefcSMark Murray 	else
279b528cefcSMark Murray 	    krb5_abortx(context, "unknown binding type (%d) in free_binding",
280b528cefcSMark Murray 			b->type);
281b528cefcSMark Murray 	next_b = b->next;
282b528cefcSMark Murray 	free (b);
283b528cefcSMark Murray 	b = next_b;
284b528cefcSMark Murray     }
285b528cefcSMark Murray }
286b528cefcSMark Murray 
287b528cefcSMark Murray krb5_error_code
288b528cefcSMark Murray krb5_config_file_free (krb5_context context, krb5_config_section *s)
289b528cefcSMark Murray {
290b528cefcSMark Murray     free_binding (context, s);
291b528cefcSMark Murray     return 0;
292b528cefcSMark Murray }
293b528cefcSMark Murray 
294b528cefcSMark Murray const void *
295b528cefcSMark Murray krb5_config_get_next (krb5_context context,
296b528cefcSMark Murray 		      krb5_config_section *c,
297b528cefcSMark Murray 		      krb5_config_binding **pointer,
298b528cefcSMark Murray 		      int type,
299b528cefcSMark Murray 		      ...)
300b528cefcSMark Murray {
301b528cefcSMark Murray     const char *ret;
302b528cefcSMark Murray     va_list args;
303b528cefcSMark Murray 
304b528cefcSMark Murray     va_start(args, type);
305b528cefcSMark Murray     ret = krb5_config_vget_next (context, c, pointer, type, args);
306b528cefcSMark Murray     va_end(args);
307b528cefcSMark Murray     return ret;
308b528cefcSMark Murray }
309b528cefcSMark Murray 
310b528cefcSMark Murray const void *
311b528cefcSMark Murray krb5_config_vget_next (krb5_context context,
312b528cefcSMark Murray 		       krb5_config_section *c,
313b528cefcSMark Murray 		       krb5_config_binding **pointer,
314b528cefcSMark Murray 		       int type,
315b528cefcSMark Murray 		       va_list args)
316b528cefcSMark Murray {
317b528cefcSMark Murray     krb5_config_binding *b;
318b528cefcSMark Murray     const char *p;
319b528cefcSMark Murray 
320b528cefcSMark Murray     if(c == NULL)
321b528cefcSMark Murray 	c = context->cf;
322b528cefcSMark Murray 
323b528cefcSMark Murray     if (c == NULL)
324b528cefcSMark Murray 	return NULL;
325b528cefcSMark Murray 
326b528cefcSMark Murray     if (*pointer == NULL) {
327b528cefcSMark Murray 	b = (c != NULL) ? c : context->cf;
328b528cefcSMark Murray 	p = va_arg(args, const char *);
329b528cefcSMark Murray 	if (p == NULL)
330b528cefcSMark Murray 	    return NULL;
331b528cefcSMark Murray     } else {
332b528cefcSMark Murray 	b = *pointer;
333b528cefcSMark Murray 	p = b->name;
334b528cefcSMark Murray 	b = b->next;
335b528cefcSMark Murray     }
336b528cefcSMark Murray 
337b528cefcSMark Murray     while (b) {
338b528cefcSMark Murray 	if (strcmp (b->name, p) == 0) {
339b528cefcSMark Murray 	    if (*pointer == NULL)
340b528cefcSMark Murray 		p = va_arg(args, const char *);
341b528cefcSMark Murray 	    else
342b528cefcSMark Murray 		p = NULL;
343b528cefcSMark Murray 	    if (type == b->type && p == NULL) {
344b528cefcSMark Murray 		*pointer = b;
345b528cefcSMark Murray 		return b->u.generic;
346b528cefcSMark Murray 	    } else if(b->type == krb5_config_list && p != NULL) {
347b528cefcSMark Murray 		b = b->u.list;
348b528cefcSMark Murray 	    } else {
349b528cefcSMark Murray 		return NULL;
350b528cefcSMark Murray 	    }
351b528cefcSMark Murray 	} else {
352b528cefcSMark Murray 	    b = b->next;
353b528cefcSMark Murray 	}
354b528cefcSMark Murray     }
355b528cefcSMark Murray     return NULL;
356b528cefcSMark Murray }
357b528cefcSMark Murray 
358b528cefcSMark Murray const void *
359b528cefcSMark Murray krb5_config_get (krb5_context context,
360b528cefcSMark Murray 		 krb5_config_section *c,
361b528cefcSMark Murray 		 int type,
362b528cefcSMark Murray 		 ...)
363b528cefcSMark Murray {
364b528cefcSMark Murray     const void *ret;
365b528cefcSMark Murray     va_list args;
366b528cefcSMark Murray 
367b528cefcSMark Murray     va_start(args, type);
368b528cefcSMark Murray     ret = krb5_config_vget (context, c, type, args);
369b528cefcSMark Murray     va_end(args);
370b528cefcSMark Murray     return ret;
371b528cefcSMark Murray }
372b528cefcSMark Murray 
373b528cefcSMark Murray const void *
374b528cefcSMark Murray krb5_config_vget (krb5_context context,
375b528cefcSMark Murray 		  krb5_config_section *c,
376b528cefcSMark Murray 		  int type,
377b528cefcSMark Murray 		  va_list args)
378b528cefcSMark Murray {
379b528cefcSMark Murray     krb5_config_binding *foo = NULL;
380b528cefcSMark Murray 
381b528cefcSMark Murray     return krb5_config_vget_next (context, c, &foo, type, args);
382b528cefcSMark Murray }
383b528cefcSMark Murray 
384b528cefcSMark Murray const krb5_config_binding *
385b528cefcSMark Murray krb5_config_get_list (krb5_context context,
386b528cefcSMark Murray 		      krb5_config_section *c,
387b528cefcSMark Murray 		      ...)
388b528cefcSMark Murray {
389b528cefcSMark Murray     const krb5_config_binding *ret;
390b528cefcSMark Murray     va_list args;
391b528cefcSMark Murray 
392b528cefcSMark Murray     va_start(args, c);
393b528cefcSMark Murray     ret = krb5_config_vget_list (context, c, args);
394b528cefcSMark Murray     va_end(args);
395b528cefcSMark Murray     return ret;
396b528cefcSMark Murray }
397b528cefcSMark Murray 
398b528cefcSMark Murray const krb5_config_binding *
399b528cefcSMark Murray krb5_config_vget_list (krb5_context context,
400b528cefcSMark Murray 		       krb5_config_section *c,
401b528cefcSMark Murray 		       va_list args)
402b528cefcSMark Murray {
403b528cefcSMark Murray     return krb5_config_vget (context, c, krb5_config_list, args);
404b528cefcSMark Murray }
405b528cefcSMark Murray 
406b528cefcSMark Murray const char *
407b528cefcSMark Murray krb5_config_get_string (krb5_context context,
408b528cefcSMark Murray 			krb5_config_section *c,
409b528cefcSMark Murray 			...)
410b528cefcSMark Murray {
411b528cefcSMark Murray     const char *ret;
412b528cefcSMark Murray     va_list args;
413b528cefcSMark Murray 
414b528cefcSMark Murray     va_start(args, c);
415b528cefcSMark Murray     ret = krb5_config_vget_string (context, c, args);
416b528cefcSMark Murray     va_end(args);
417b528cefcSMark Murray     return ret;
418b528cefcSMark Murray }
419b528cefcSMark Murray 
420b528cefcSMark Murray const char *
421b528cefcSMark Murray krb5_config_vget_string (krb5_context context,
422b528cefcSMark Murray 			 krb5_config_section *c,
423b528cefcSMark Murray 			 va_list args)
424b528cefcSMark Murray {
425b528cefcSMark Murray     return krb5_config_vget (context, c, krb5_config_string, args);
426b528cefcSMark Murray }
427b528cefcSMark Murray 
4285e9cd1aeSAssar Westerlund const char *
4295e9cd1aeSAssar Westerlund krb5_config_vget_string_default (krb5_context context,
4305e9cd1aeSAssar Westerlund 				 krb5_config_section *c,
4315e9cd1aeSAssar Westerlund 				 const char *def_value,
4325e9cd1aeSAssar Westerlund 				 va_list args)
4335e9cd1aeSAssar Westerlund {
4345e9cd1aeSAssar Westerlund     const char *ret;
4355e9cd1aeSAssar Westerlund 
4365e9cd1aeSAssar Westerlund     ret = krb5_config_vget_string (context, c, args);
4375e9cd1aeSAssar Westerlund     if (ret == NULL)
4385e9cd1aeSAssar Westerlund 	ret = def_value;
4395e9cd1aeSAssar Westerlund     return ret;
4405e9cd1aeSAssar Westerlund }
4415e9cd1aeSAssar Westerlund 
4425e9cd1aeSAssar Westerlund const char *
4435e9cd1aeSAssar Westerlund krb5_config_get_string_default (krb5_context context,
4445e9cd1aeSAssar Westerlund 				krb5_config_section *c,
4455e9cd1aeSAssar Westerlund 				const char *def_value,
4465e9cd1aeSAssar Westerlund 				...)
4475e9cd1aeSAssar Westerlund {
4485e9cd1aeSAssar Westerlund     const char *ret;
4495e9cd1aeSAssar Westerlund     va_list args;
4505e9cd1aeSAssar Westerlund 
4515e9cd1aeSAssar Westerlund     va_start(args, def_value);
4525e9cd1aeSAssar Westerlund     ret = krb5_config_vget_string_default (context, c, def_value, args);
4535e9cd1aeSAssar Westerlund     va_end(args);
4545e9cd1aeSAssar Westerlund     return ret;
4555e9cd1aeSAssar Westerlund }
4565e9cd1aeSAssar Westerlund 
457b528cefcSMark Murray char **
458b528cefcSMark Murray krb5_config_vget_strings(krb5_context context,
459b528cefcSMark Murray 			 krb5_config_section *c,
460b528cefcSMark Murray 			 va_list args)
461b528cefcSMark Murray {
462b528cefcSMark Murray     char **strings = NULL;
463b528cefcSMark Murray     int nstr = 0;
464b528cefcSMark Murray     krb5_config_binding *b = NULL;
465b528cefcSMark Murray     const char *p;
466b528cefcSMark Murray 
467b528cefcSMark Murray     while((p = krb5_config_vget_next(context, c, &b,
468b528cefcSMark Murray 				     krb5_config_string, args))) {
469b528cefcSMark Murray 	char *tmp = strdup(p);
470b528cefcSMark Murray 	char *pos = NULL;
471b528cefcSMark Murray 	char *s;
472b528cefcSMark Murray 	if(tmp == NULL)
473b528cefcSMark Murray 	    goto cleanup;
474b528cefcSMark Murray 	s = strtok_r(tmp, " \t", &pos);
475b528cefcSMark Murray 	while(s){
476b528cefcSMark Murray 	    char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
477b528cefcSMark Murray 	    if(tmp == NULL)
478b528cefcSMark Murray 		goto cleanup;
479b528cefcSMark Murray 	    strings = tmp;
480b528cefcSMark Murray 	    strings[nstr] = strdup(s);
481b528cefcSMark Murray 	    nstr++;
482b528cefcSMark Murray 	    if(strings[nstr-1] == NULL)
483b528cefcSMark Murray 		goto cleanup;
484b528cefcSMark Murray 	    s = strtok_r(NULL, " \t", &pos);
485b528cefcSMark Murray 	}
486b528cefcSMark Murray 	free(tmp);
487b528cefcSMark Murray     }
488b528cefcSMark Murray     if(nstr){
489b528cefcSMark Murray 	char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
490b528cefcSMark Murray 	if(strings == NULL)
491b528cefcSMark Murray 	    goto cleanup;
492b528cefcSMark Murray 	strings = tmp;
493b528cefcSMark Murray 	strings[nstr] = NULL;
494b528cefcSMark Murray     }
495b528cefcSMark Murray     return strings;
496b528cefcSMark Murray cleanup:
497b528cefcSMark Murray     while(nstr--)
498b528cefcSMark Murray 	free(strings[nstr]);
499b528cefcSMark Murray     free(strings);
500b528cefcSMark Murray     return NULL;
501b528cefcSMark Murray 
502b528cefcSMark Murray }
503b528cefcSMark Murray 
504b528cefcSMark Murray char**
505b528cefcSMark Murray krb5_config_get_strings(krb5_context context,
506b528cefcSMark Murray 			krb5_config_section *c,
507b528cefcSMark Murray 			...)
508b528cefcSMark Murray {
509b528cefcSMark Murray     va_list ap;
510b528cefcSMark Murray     char **ret;
511b528cefcSMark Murray     va_start(ap, c);
512b528cefcSMark Murray     ret = krb5_config_vget_strings(context, c, ap);
513b528cefcSMark Murray     va_end(ap);
514b528cefcSMark Murray     return ret;
515b528cefcSMark Murray }
516b528cefcSMark Murray 
517b528cefcSMark Murray void
518b528cefcSMark Murray krb5_config_free_strings(char **strings)
519b528cefcSMark Murray {
520b528cefcSMark Murray     char **s = strings;
521b528cefcSMark Murray     while(s && *s){
522b528cefcSMark Murray 	free(*s);
523b528cefcSMark Murray 	s++;
524b528cefcSMark Murray     }
525b528cefcSMark Murray     free(strings);
526b528cefcSMark Murray }
527b528cefcSMark Murray 
528b528cefcSMark Murray krb5_boolean
529b528cefcSMark Murray krb5_config_vget_bool_default (krb5_context context,
530b528cefcSMark Murray 			       krb5_config_section *c,
531b528cefcSMark Murray 			       krb5_boolean def_value,
532b528cefcSMark Murray 			       va_list args)
533b528cefcSMark Murray {
534b528cefcSMark Murray     const char *str;
535b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
536b528cefcSMark Murray     if(str == NULL)
537b528cefcSMark Murray 	return def_value;
538b528cefcSMark Murray     if(strcasecmp(str, "yes") == 0 ||
539b528cefcSMark Murray        strcasecmp(str, "true") == 0 ||
540b528cefcSMark Murray        atoi(str)) return TRUE;
541b528cefcSMark Murray     return FALSE;
542b528cefcSMark Murray }
543b528cefcSMark Murray 
544b528cefcSMark Murray krb5_boolean
545b528cefcSMark Murray krb5_config_vget_bool  (krb5_context context,
546b528cefcSMark Murray 			krb5_config_section *c,
547b528cefcSMark Murray 			va_list args)
548b528cefcSMark Murray {
549b528cefcSMark Murray     return krb5_config_vget_bool_default (context, c, FALSE, args);
550b528cefcSMark Murray }
551b528cefcSMark Murray 
552b528cefcSMark Murray krb5_boolean
553b528cefcSMark Murray krb5_config_get_bool_default (krb5_context context,
554b528cefcSMark Murray 			      krb5_config_section *c,
555b528cefcSMark Murray 			      krb5_boolean def_value,
556b528cefcSMark Murray 			      ...)
557b528cefcSMark Murray {
558b528cefcSMark Murray     va_list ap;
559b528cefcSMark Murray     krb5_boolean ret;
560b528cefcSMark Murray     va_start(ap, def_value);
561b528cefcSMark Murray     ret = krb5_config_vget_bool_default(context, c, def_value, ap);
562b528cefcSMark Murray     va_end(ap);
563b528cefcSMark Murray     return ret;
564b528cefcSMark Murray }
565b528cefcSMark Murray 
566b528cefcSMark Murray krb5_boolean
567b528cefcSMark Murray krb5_config_get_bool (krb5_context context,
568b528cefcSMark Murray 		      krb5_config_section *c,
569b528cefcSMark Murray 		      ...)
570b528cefcSMark Murray {
571b528cefcSMark Murray     va_list ap;
572b528cefcSMark Murray     krb5_boolean ret;
573b528cefcSMark Murray     va_start(ap, c);
574b528cefcSMark Murray     ret = krb5_config_vget_bool (context, c, ap);
575b528cefcSMark Murray     va_end(ap);
576b528cefcSMark Murray     return ret;
577b528cefcSMark Murray }
578b528cefcSMark Murray 
579b528cefcSMark Murray int
580b528cefcSMark Murray krb5_config_vget_time_default (krb5_context context,
581b528cefcSMark Murray 			       krb5_config_section *c,
582b528cefcSMark Murray 			       int def_value,
583b528cefcSMark Murray 			       va_list args)
584b528cefcSMark Murray {
585b528cefcSMark Murray     const char *str;
586b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
587b528cefcSMark Murray     if(str == NULL)
588b528cefcSMark Murray 	return def_value;
589b528cefcSMark Murray     return parse_time (str, NULL);
590b528cefcSMark Murray }
591b528cefcSMark Murray 
592b528cefcSMark Murray int
593b528cefcSMark Murray krb5_config_vget_time  (krb5_context context,
594b528cefcSMark Murray 			krb5_config_section *c,
595b528cefcSMark Murray 			va_list args)
596b528cefcSMark Murray {
597b528cefcSMark Murray     return krb5_config_vget_time_default (context, c, -1, args);
598b528cefcSMark Murray }
599b528cefcSMark Murray 
600b528cefcSMark Murray int
601b528cefcSMark Murray krb5_config_get_time_default (krb5_context context,
602b528cefcSMark Murray 			      krb5_config_section *c,
603b528cefcSMark Murray 			      int def_value,
604b528cefcSMark Murray 			      ...)
605b528cefcSMark Murray {
606b528cefcSMark Murray     va_list ap;
607b528cefcSMark Murray     int ret;
608b528cefcSMark Murray     va_start(ap, def_value);
609b528cefcSMark Murray     ret = krb5_config_vget_time_default(context, c, def_value, ap);
610b528cefcSMark Murray     va_end(ap);
611b528cefcSMark Murray     return ret;
612b528cefcSMark Murray }
613b528cefcSMark Murray 
614b528cefcSMark Murray int
615b528cefcSMark Murray krb5_config_get_time (krb5_context context,
616b528cefcSMark Murray 		      krb5_config_section *c,
617b528cefcSMark Murray 		      ...)
618b528cefcSMark Murray {
619b528cefcSMark Murray     va_list ap;
620b528cefcSMark Murray     int ret;
621b528cefcSMark Murray     va_start(ap, c);
622b528cefcSMark Murray     ret = krb5_config_vget_time (context, c, ap);
623b528cefcSMark Murray     va_end(ap);
624b528cefcSMark Murray     return ret;
625b528cefcSMark Murray }
626b528cefcSMark Murray 
627b528cefcSMark Murray 
628b528cefcSMark Murray int
629b528cefcSMark Murray krb5_config_vget_int_default (krb5_context context,
630b528cefcSMark Murray 			      krb5_config_section *c,
631b528cefcSMark Murray 			      int def_value,
632b528cefcSMark Murray 			      va_list args)
633b528cefcSMark Murray {
634b528cefcSMark Murray     const char *str;
635b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
636b528cefcSMark Murray     if(str == NULL)
637b528cefcSMark Murray 	return def_value;
638b528cefcSMark Murray     else {
639b528cefcSMark Murray 	char *endptr;
640b528cefcSMark Murray 	long l;
641b528cefcSMark Murray 	l = strtol(str, &endptr, 0);
642b528cefcSMark Murray 	if (endptr == str)
643b528cefcSMark Murray 	    return def_value;
644b528cefcSMark Murray 	else
645b528cefcSMark Murray 	    return l;
646b528cefcSMark Murray     }
647b528cefcSMark Murray }
648b528cefcSMark Murray 
649b528cefcSMark Murray int
650b528cefcSMark Murray krb5_config_vget_int  (krb5_context context,
651b528cefcSMark Murray 		       krb5_config_section *c,
652b528cefcSMark Murray 		       va_list args)
653b528cefcSMark Murray {
654b528cefcSMark Murray     return krb5_config_vget_int_default (context, c, -1, args);
655b528cefcSMark Murray }
656b528cefcSMark Murray 
657b528cefcSMark Murray int
658b528cefcSMark Murray krb5_config_get_int_default (krb5_context context,
659b528cefcSMark Murray 			     krb5_config_section *c,
660b528cefcSMark Murray 			     int def_value,
661b528cefcSMark Murray 			     ...)
662b528cefcSMark Murray {
663b528cefcSMark Murray     va_list ap;
664b528cefcSMark Murray     int ret;
665b528cefcSMark Murray     va_start(ap, def_value);
666b528cefcSMark Murray     ret = krb5_config_vget_int_default(context, c, def_value, ap);
667b528cefcSMark Murray     va_end(ap);
668b528cefcSMark Murray     return ret;
669b528cefcSMark Murray }
670b528cefcSMark Murray 
671b528cefcSMark Murray int
672b528cefcSMark Murray krb5_config_get_int (krb5_context context,
673b528cefcSMark Murray 		     krb5_config_section *c,
674b528cefcSMark Murray 		     ...)
675b528cefcSMark Murray {
676b528cefcSMark Murray     va_list ap;
677b528cefcSMark Murray     int ret;
678b528cefcSMark Murray     va_start(ap, c);
679b528cefcSMark Murray     ret = krb5_config_vget_int (context, c, ap);
680b528cefcSMark Murray     va_end(ap);
681b528cefcSMark Murray     return ret;
682b528cefcSMark Murray }
683b528cefcSMark Murray 
684b528cefcSMark Murray #ifdef TEST
685b528cefcSMark Murray 
686b528cefcSMark Murray static int print_list (krb5_context context, FILE *f,
687b528cefcSMark Murray 		       krb5_config_binding *l, unsigned level);
688b528cefcSMark Murray static int print_binding (krb5_context context, FILE *f,
689b528cefcSMark Murray 			  krb5_config_binding *b, unsigned level);
690b528cefcSMark Murray static int print_section (krb5_context context, FILE *f,
691b528cefcSMark Murray 			  krb5_config_section *s, unsigned level);
692b528cefcSMark Murray static int print_config (krb5_context context, FILE *f,
693b528cefcSMark Murray 			 krb5_config_section *c);
694b528cefcSMark Murray 
695b528cefcSMark Murray static void
696b528cefcSMark Murray tab (FILE *f, unsigned count)
697b528cefcSMark Murray {
698b528cefcSMark Murray     while(count--)
699b528cefcSMark Murray 	fprintf (f, "\t");
700b528cefcSMark Murray }
701b528cefcSMark Murray 
702b528cefcSMark Murray static int
703b528cefcSMark Murray print_list (krb5_context context,
704b528cefcSMark Murray 	    FILE *f,
705b528cefcSMark Murray 	    krb5_config_binding *l,
706b528cefcSMark Murray 	    unsigned level)
707b528cefcSMark Murray {
708b528cefcSMark Murray     while(l) {
709b528cefcSMark Murray 	print_binding (context, f, l, level);
710b528cefcSMark Murray 	l = l->next;
711b528cefcSMark Murray     }
712b528cefcSMark Murray     return 0;
713b528cefcSMark Murray }
714b528cefcSMark Murray 
715b528cefcSMark Murray static int
716b528cefcSMark Murray print_binding (krb5_context context,
717b528cefcSMark Murray 	       FILE *f,
718b528cefcSMark Murray 	       krb5_config_binding *b,
719b528cefcSMark Murray 	       unsigned level)
720b528cefcSMark Murray {
721b528cefcSMark Murray     tab (f, level);
722b528cefcSMark Murray     fprintf (f, "%s = ", b->name);
723b528cefcSMark Murray     if (b->type == krb5_config_string)
724b528cefcSMark Murray 	fprintf (f, "%s\n", b->u.string);
725b528cefcSMark Murray     else if (b->type == krb5_config_list) {
726b528cefcSMark Murray 	fprintf (f, "{\n");
727b528cefcSMark Murray 	print_list (f, b->u.list, level + 1);
728b528cefcSMark Murray 	tab (f, level);
729b528cefcSMark Murray 	fprintf (f, "}\n");
730b528cefcSMark Murray     } else
731b528cefcSMark Murray 	krb5_abortx(context, "unknown binding type (%d) in print_binding",
732b528cefcSMark Murray 		    b->type);
733b528cefcSMark Murray     return 0;
734b528cefcSMark Murray }
735b528cefcSMark Murray 
736b528cefcSMark Murray static int
737b528cefcSMark Murray print_section (FILE *f, krb5_config_section *s, unsigned level)
738b528cefcSMark Murray {
739b528cefcSMark Murray     fprintf (f, "[%s]\n", s->name);
740b528cefcSMark Murray     print_list (f, s->u.list, level + 1);
741b528cefcSMark Murray     return 0;
742b528cefcSMark Murray }
743b528cefcSMark Murray 
744b528cefcSMark Murray static int
745b528cefcSMark Murray print_config (FILE *f, krb5_config_section *c)
746b528cefcSMark Murray {
747b528cefcSMark Murray     while (c) {
748b528cefcSMark Murray 	print_section (f, c, 0);
749b528cefcSMark Murray 	c = c->next;
750b528cefcSMark Murray     }
751b528cefcSMark Murray     return 0;
752b528cefcSMark Murray }
753b528cefcSMark Murray 
754b528cefcSMark Murray 
755b528cefcSMark Murray int
756b528cefcSMark Murray main(void)
757b528cefcSMark Murray {
758b528cefcSMark Murray     krb5_config_section *c;
759b528cefcSMark Murray 
760b528cefcSMark Murray     printf ("%d\n", krb5_config_parse_file ("/etc/krb5.conf", &c));
761b528cefcSMark Murray     print_config (stdout, c);
762b528cefcSMark Murray     printf ("[libdefaults]ticket_lifetime = %s\n",
763b528cefcSMark Murray 	    krb5_config_get_string (context, c,
764b528cefcSMark Murray 			       "libdefaults",
765b528cefcSMark Murray 			       "ticket_lifetime",
766b528cefcSMark Murray 			       NULL));
767b528cefcSMark Murray     printf ("[realms]foo = %s\n",
768b528cefcSMark Murray 	    krb5_config_get_string (context, c,
769b528cefcSMark Murray 			       "realms",
770b528cefcSMark Murray 			       "foo",
771b528cefcSMark Murray 			       NULL));
772b528cefcSMark Murray     printf ("[realms]ATHENA.MIT.EDU/v4_instance_convert/lithium = %s\n",
773b528cefcSMark Murray 	    krb5_config_get_string (context, c,
774b528cefcSMark Murray 			       "realms",
775b528cefcSMark Murray 			       "ATHENA.MIT.EDU",
776b528cefcSMark Murray 			       "v4_instance_convert",
777b528cefcSMark Murray 			       "lithium",
778b528cefcSMark Murray 			       NULL));
779b528cefcSMark Murray     return 0;
780b528cefcSMark Murray }
781b528cefcSMark Murray 
782b528cefcSMark Murray #endif /* TEST */
783