xref: /freebsd/crypto/heimdal/lib/krb5/config_file.c (revision c19800e8cd5640693f36f2040db4ab5e8d738146)
1b528cefcSMark Murray /*
2c19800e8SDoug Rabson  * Copyright (c) 1997 - 2004 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"
35c19800e8SDoug Rabson RCSID("$Id: config_file.c 19213 2006-12-04 23:36:36Z lha $");
36b528cefcSMark Murray 
37b528cefcSMark Murray #ifndef HAVE_NETINFO
38b528cefcSMark Murray 
39c19800e8SDoug Rabson /* Gaah! I want a portable funopen */
40c19800e8SDoug Rabson struct fileptr {
41c19800e8SDoug Rabson     const char *s;
42c19800e8SDoug Rabson     FILE *f;
43c19800e8SDoug Rabson };
44c19800e8SDoug Rabson 
45c19800e8SDoug Rabson static char *
46c19800e8SDoug Rabson config_fgets(char *str, size_t len, struct fileptr *ptr)
47c19800e8SDoug Rabson {
48c19800e8SDoug Rabson     /* XXX this is not correct, in that they don't do the same if the
49c19800e8SDoug Rabson        line is longer than len */
50c19800e8SDoug Rabson     if(ptr->f != NULL)
51c19800e8SDoug Rabson 	return fgets(str, len, ptr->f);
52c19800e8SDoug Rabson     else {
53c19800e8SDoug Rabson 	/* this is almost strsep_copy */
54c19800e8SDoug Rabson 	const char *p;
55c19800e8SDoug Rabson 	ssize_t l;
56c19800e8SDoug Rabson 	if(*ptr->s == '\0')
57c19800e8SDoug Rabson 	    return NULL;
58c19800e8SDoug Rabson 	p = ptr->s + strcspn(ptr->s, "\n");
59c19800e8SDoug Rabson 	if(*p == '\n')
60c19800e8SDoug Rabson 	    p++;
61c19800e8SDoug Rabson 	l = min(len, p - ptr->s);
62c19800e8SDoug Rabson 	if(len > 0) {
63c19800e8SDoug Rabson 	    memcpy(str, ptr->s, l);
64c19800e8SDoug Rabson 	    str[l] = '\0';
65c19800e8SDoug Rabson 	}
66c19800e8SDoug Rabson 	ptr->s = p;
67c19800e8SDoug Rabson 	return str;
68c19800e8SDoug Rabson     }
69c19800e8SDoug Rabson }
70c19800e8SDoug Rabson 
71adb0ddaeSAssar Westerlund static krb5_error_code parse_section(char *p, krb5_config_section **s,
72b528cefcSMark Murray 				     krb5_config_section **res,
738373020dSJacques Vidrine 				     const char **error_message);
74c19800e8SDoug Rabson static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
75b528cefcSMark Murray 				     krb5_config_binding **b,
76b528cefcSMark Murray 				     krb5_config_binding **parent,
778373020dSJacques Vidrine 				     const char **error_message);
78c19800e8SDoug Rabson static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno,
79adb0ddaeSAssar Westerlund 				  krb5_config_binding **parent,
808373020dSJacques Vidrine 				  const char **error_message);
818373020dSJacques Vidrine 
828373020dSJacques Vidrine static krb5_config_section *
838373020dSJacques Vidrine get_entry(krb5_config_section **parent, const char *name, int type)
848373020dSJacques Vidrine {
858373020dSJacques Vidrine     krb5_config_section **q;
868373020dSJacques Vidrine 
878373020dSJacques Vidrine     for(q = parent; *q != NULL; q = &(*q)->next)
888373020dSJacques Vidrine 	if(type == krb5_config_list &&
898373020dSJacques Vidrine 	   type == (*q)->type &&
908373020dSJacques Vidrine 	   strcmp(name, (*q)->name) == 0)
918373020dSJacques Vidrine 	    return *q;
928373020dSJacques Vidrine     *q = calloc(1, sizeof(**q));
938373020dSJacques Vidrine     if(*q == NULL)
948373020dSJacques Vidrine 	return NULL;
958373020dSJacques Vidrine     (*q)->name = strdup(name);
968373020dSJacques Vidrine     (*q)->type = type;
978373020dSJacques Vidrine     if((*q)->name == NULL) {
988373020dSJacques Vidrine 	free(*q);
998373020dSJacques Vidrine 	*q = NULL;
1008373020dSJacques Vidrine 	return NULL;
1018373020dSJacques Vidrine     }
1028373020dSJacques Vidrine     return *q;
1038373020dSJacques Vidrine }
104b528cefcSMark Murray 
105b528cefcSMark Murray /*
106b528cefcSMark Murray  * Parse a section:
107b528cefcSMark Murray  *
108b528cefcSMark Murray  * [section]
109b528cefcSMark Murray  *	foo = bar
110b528cefcSMark Murray  *	b = {
111b528cefcSMark Murray  *		a
112b528cefcSMark Murray  *	    }
113b528cefcSMark Murray  * ...
114b528cefcSMark Murray  *
115b528cefcSMark Murray  * starting at the line in `p', storing the resulting structure in
116b528cefcSMark Murray  * `s' and hooking it into `parent'.
117b528cefcSMark Murray  * Store the error message in `error_message'.
118b528cefcSMark Murray  */
119b528cefcSMark Murray 
120adb0ddaeSAssar Westerlund static krb5_error_code
121b528cefcSMark Murray parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
1228373020dSJacques Vidrine 	      const char **error_message)
123b528cefcSMark Murray {
124b528cefcSMark Murray     char *p1;
125b528cefcSMark Murray     krb5_config_section *tmp;
126b528cefcSMark Murray 
127b528cefcSMark Murray     p1 = strchr (p + 1, ']');
128b528cefcSMark Murray     if (p1 == NULL) {
129b528cefcSMark Murray 	*error_message = "missing ]";
130adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
131b528cefcSMark Murray     }
132b528cefcSMark Murray     *p1 = '\0';
1338373020dSJacques Vidrine     tmp = get_entry(parent, p + 1, krb5_config_list);
134b528cefcSMark Murray     if(tmp == NULL) {
135b528cefcSMark Murray 	*error_message = "out of memory";
136adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
137b528cefcSMark Murray     }
138b528cefcSMark Murray     *s = tmp;
139b528cefcSMark Murray     return 0;
140b528cefcSMark Murray }
141b528cefcSMark Murray 
142b528cefcSMark Murray /*
143b528cefcSMark Murray  * Parse a brace-enclosed list from `f', hooking in the structure at
144b528cefcSMark Murray  * `parent'.
145b528cefcSMark Murray  * Store the error message in `error_message'.
146b528cefcSMark Murray  */
147b528cefcSMark Murray 
1481c43270aSJacques Vidrine static krb5_error_code
149c19800e8SDoug Rabson parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent,
1508373020dSJacques Vidrine 	   const char **error_message)
151b528cefcSMark Murray {
152b528cefcSMark Murray     char buf[BUFSIZ];
1531c43270aSJacques Vidrine     krb5_error_code ret;
154b528cefcSMark Murray     krb5_config_binding *b = NULL;
155b528cefcSMark Murray     unsigned beg_lineno = *lineno;
156b528cefcSMark Murray 
157c19800e8SDoug Rabson     while(config_fgets(buf, sizeof(buf), f) != NULL) {
158b528cefcSMark Murray 	char *p;
159b528cefcSMark Murray 
160b528cefcSMark Murray 	++*lineno;
161c19800e8SDoug Rabson 	buf[strcspn(buf, "\r\n")] = '\0';
162b528cefcSMark Murray 	p = buf;
163b528cefcSMark Murray 	while(isspace((unsigned char)*p))
164b528cefcSMark Murray 	    ++p;
165b528cefcSMark Murray 	if (*p == '#' || *p == ';' || *p == '\0')
166b528cefcSMark Murray 	    continue;
167b528cefcSMark Murray 	while(isspace((unsigned char)*p))
168b528cefcSMark Murray 	    ++p;
169b528cefcSMark Murray 	if (*p == '}')
170b528cefcSMark Murray 	    return 0;
171b528cefcSMark Murray 	if (*p == '\0')
172b528cefcSMark Murray 	    continue;
173b528cefcSMark Murray 	ret = parse_binding (f, lineno, p, &b, parent, error_message);
174b528cefcSMark Murray 	if (ret)
175b528cefcSMark Murray 	    return ret;
176b528cefcSMark Murray     }
177b528cefcSMark Murray     *lineno = beg_lineno;
178b528cefcSMark Murray     *error_message = "unclosed {";
179adb0ddaeSAssar Westerlund     return KRB5_CONFIG_BADFORMAT;
180b528cefcSMark Murray }
181b528cefcSMark Murray 
182b528cefcSMark Murray /*
183b528cefcSMark Murray  *
184b528cefcSMark Murray  */
185b528cefcSMark Murray 
1861c43270aSJacques Vidrine static krb5_error_code
187c19800e8SDoug Rabson parse_binding(struct fileptr *f, unsigned *lineno, char *p,
188b528cefcSMark Murray 	      krb5_config_binding **b, krb5_config_binding **parent,
1898373020dSJacques Vidrine 	      const char **error_message)
190b528cefcSMark Murray {
191b528cefcSMark Murray     krb5_config_binding *tmp;
192b528cefcSMark Murray     char *p1, *p2;
1931c43270aSJacques Vidrine     krb5_error_code ret = 0;
194b528cefcSMark Murray 
195b528cefcSMark Murray     p1 = p;
196b528cefcSMark Murray     while (*p && *p != '=' && !isspace((unsigned char)*p))
197b528cefcSMark Murray 	++p;
198b528cefcSMark Murray     if (*p == '\0') {
1998373020dSJacques Vidrine 	*error_message = "missing =";
200adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
201b528cefcSMark Murray     }
202b528cefcSMark Murray     p2 = p;
203b528cefcSMark Murray     while (isspace((unsigned char)*p))
204b528cefcSMark Murray 	++p;
205b528cefcSMark Murray     if (*p != '=') {
2068373020dSJacques Vidrine 	*error_message = "missing =";
207adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
208b528cefcSMark Murray     }
209b528cefcSMark Murray     ++p;
210b528cefcSMark Murray     while(isspace((unsigned char)*p))
211b528cefcSMark Murray 	++p;
2128373020dSJacques Vidrine     *p2 = '\0';
2138373020dSJacques Vidrine     if (*p == '{') {
2148373020dSJacques Vidrine 	tmp = get_entry(parent, p1, krb5_config_list);
215b528cefcSMark Murray 	if (tmp == NULL) {
216b528cefcSMark Murray 	    *error_message = "out of memory";
217adb0ddaeSAssar Westerlund 	    return KRB5_CONFIG_BADFORMAT;
218b528cefcSMark Murray 	}
219b528cefcSMark Murray 	ret = parse_list (f, lineno, &tmp->u.list, error_message);
220b528cefcSMark Murray     } else {
2218373020dSJacques Vidrine 	tmp = get_entry(parent, p1, krb5_config_string);
2228373020dSJacques Vidrine 	if (tmp == NULL) {
2238373020dSJacques Vidrine 	    *error_message = "out of memory";
2248373020dSJacques Vidrine 	    return KRB5_CONFIG_BADFORMAT;
2258373020dSJacques Vidrine 	}
226b528cefcSMark Murray 	p1 = p;
227b528cefcSMark Murray 	p = p1 + strlen(p1);
228b528cefcSMark Murray 	while(p > p1 && isspace((unsigned char)*(p-1)))
229b528cefcSMark Murray 	    --p;
230b528cefcSMark Murray 	*p = '\0';
231b528cefcSMark Murray 	tmp->u.string = strdup(p1);
232b528cefcSMark Murray     }
233b528cefcSMark Murray     *b = tmp;
234b528cefcSMark Murray     return ret;
235b528cefcSMark Murray }
236b528cefcSMark Murray 
237b528cefcSMark Murray /*
238b528cefcSMark Murray  * Parse the config file `fname', generating the structures into `res'
239b528cefcSMark Murray  * returning error messages in `error_message'
240b528cefcSMark Murray  */
241b528cefcSMark Murray 
242adb0ddaeSAssar Westerlund static krb5_error_code
243c19800e8SDoug Rabson krb5_config_parse_debug (struct fileptr *f,
244b528cefcSMark Murray 			 krb5_config_section **res,
245b528cefcSMark Murray 			 unsigned *lineno,
2468373020dSJacques Vidrine 			 const char **error_message)
247b528cefcSMark Murray {
248c19800e8SDoug Rabson     krb5_config_section *s = NULL;
249c19800e8SDoug Rabson     krb5_config_binding *b = NULL;
250b528cefcSMark Murray     char buf[BUFSIZ];
251c19800e8SDoug Rabson     krb5_error_code ret;
252b528cefcSMark Murray 
253c19800e8SDoug Rabson     while (config_fgets(buf, sizeof(buf), f) != NULL) {
254b528cefcSMark Murray 	char *p;
255b528cefcSMark Murray 
256b528cefcSMark Murray 	++*lineno;
257c19800e8SDoug Rabson 	buf[strcspn(buf, "\r\n")] = '\0';
258b528cefcSMark Murray 	p = buf;
259b528cefcSMark Murray 	while(isspace((unsigned char)*p))
260b528cefcSMark Murray 	    ++p;
261b528cefcSMark Murray 	if (*p == '#' || *p == ';')
262b528cefcSMark Murray 	    continue;
263b528cefcSMark Murray 	if (*p == '[') {
264b528cefcSMark Murray 	    ret = parse_section(p, &s, res, error_message);
265c19800e8SDoug Rabson 	    if (ret)
266c19800e8SDoug Rabson 		return ret;
267b528cefcSMark Murray 	    b = NULL;
268b528cefcSMark Murray 	} else if (*p == '}') {
269b528cefcSMark Murray 	    *error_message = "unmatched }";
270c19800e8SDoug Rabson 	    return EINVAL;	/* XXX */
271b528cefcSMark Murray 	} else if(*p != '\0') {
2721c43270aSJacques Vidrine 	    if (s == NULL) {
2731c43270aSJacques Vidrine 		*error_message = "binding before section";
274c19800e8SDoug Rabson 		return EINVAL;
2751c43270aSJacques Vidrine 	    }
276b528cefcSMark Murray 	    ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message);
277b528cefcSMark Murray 	    if (ret)
2785e9cd1aeSAssar Westerlund 		return ret;
279b528cefcSMark Murray 	}
280c19800e8SDoug Rabson     }
281c19800e8SDoug Rabson     return 0;
282c19800e8SDoug Rabson }
283b528cefcSMark Murray 
284c19800e8SDoug Rabson krb5_error_code KRB5_LIB_FUNCTION
285c19800e8SDoug Rabson krb5_config_parse_string_multi(krb5_context context,
286c19800e8SDoug Rabson 			       const char *string,
287c19800e8SDoug Rabson 			       krb5_config_section **res)
288c19800e8SDoug Rabson {
289c19800e8SDoug Rabson     const char *str;
290c19800e8SDoug Rabson     unsigned lineno = 0;
291c19800e8SDoug Rabson     krb5_error_code ret;
292c19800e8SDoug Rabson     struct fileptr f;
293c19800e8SDoug Rabson     f.f = NULL;
294c19800e8SDoug Rabson     f.s = string;
295c19800e8SDoug Rabson 
296c19800e8SDoug Rabson     ret = krb5_config_parse_debug (&f, res, &lineno, &str);
297c19800e8SDoug Rabson     if (ret) {
298c19800e8SDoug Rabson 	krb5_set_error_string (context, "%s:%u: %s", "<constant>", lineno, str);
299c19800e8SDoug Rabson 	return ret;
300c19800e8SDoug Rabson     }
301c19800e8SDoug Rabson     return 0;
302c19800e8SDoug Rabson }
303c19800e8SDoug Rabson 
304c19800e8SDoug Rabson krb5_error_code KRB5_LIB_FUNCTION
3058373020dSJacques Vidrine krb5_config_parse_file_multi (krb5_context context,
306adb0ddaeSAssar Westerlund 			      const char *fname,
307adb0ddaeSAssar Westerlund 			      krb5_config_section **res)
308b528cefcSMark Murray {
3098373020dSJacques Vidrine     const char *str;
310c19800e8SDoug Rabson     unsigned lineno = 0;
311adb0ddaeSAssar Westerlund     krb5_error_code ret;
312c19800e8SDoug Rabson     struct fileptr f;
313c19800e8SDoug Rabson     f.f = fopen(fname, "r");
314c19800e8SDoug Rabson     f.s = NULL;
315c19800e8SDoug Rabson     if(f.f == NULL) {
316c19800e8SDoug Rabson 	ret = errno;
317c19800e8SDoug Rabson 	krb5_set_error_string (context, "open %s: %s", fname, strerror(ret));
318c19800e8SDoug Rabson 	return ret;
319c19800e8SDoug Rabson     }
320b528cefcSMark Murray 
321c19800e8SDoug Rabson     ret = krb5_config_parse_debug (&f, res, &lineno, &str);
322c19800e8SDoug Rabson     fclose(f.f);
323adb0ddaeSAssar Westerlund     if (ret) {
324adb0ddaeSAssar Westerlund 	krb5_set_error_string (context, "%s:%u: %s", fname, lineno, str);
325adb0ddaeSAssar Westerlund 	return ret;
326adb0ddaeSAssar Westerlund     }
327adb0ddaeSAssar Westerlund     return 0;
328b528cefcSMark Murray }
329b528cefcSMark Murray 
330c19800e8SDoug Rabson krb5_error_code KRB5_LIB_FUNCTION
3318373020dSJacques Vidrine krb5_config_parse_file (krb5_context context,
3328373020dSJacques Vidrine 			const char *fname,
3338373020dSJacques Vidrine 			krb5_config_section **res)
3348373020dSJacques Vidrine {
3358373020dSJacques Vidrine     *res = NULL;
3368373020dSJacques Vidrine     return krb5_config_parse_file_multi(context, fname, res);
3378373020dSJacques Vidrine }
3388373020dSJacques Vidrine 
339b528cefcSMark Murray #endif /* !HAVE_NETINFO */
340b528cefcSMark Murray 
341b528cefcSMark Murray static void
342b528cefcSMark Murray free_binding (krb5_context context, krb5_config_binding *b)
343b528cefcSMark Murray {
344b528cefcSMark Murray     krb5_config_binding *next_b;
345b528cefcSMark Murray 
346b528cefcSMark Murray     while (b) {
347b528cefcSMark Murray 	free (b->name);
348b528cefcSMark Murray 	if (b->type == krb5_config_string)
349b528cefcSMark Murray 	    free (b->u.string);
350b528cefcSMark Murray 	else if (b->type == krb5_config_list)
351b528cefcSMark Murray 	    free_binding (context, b->u.list);
352b528cefcSMark Murray 	else
353b528cefcSMark Murray 	    krb5_abortx(context, "unknown binding type (%d) in free_binding",
354b528cefcSMark Murray 			b->type);
355b528cefcSMark Murray 	next_b = b->next;
356b528cefcSMark Murray 	free (b);
357b528cefcSMark Murray 	b = next_b;
358b528cefcSMark Murray     }
359b528cefcSMark Murray }
360b528cefcSMark Murray 
361c19800e8SDoug Rabson krb5_error_code KRB5_LIB_FUNCTION
362b528cefcSMark Murray krb5_config_file_free (krb5_context context, krb5_config_section *s)
363b528cefcSMark Murray {
364b528cefcSMark Murray     free_binding (context, s);
365b528cefcSMark Murray     return 0;
366b528cefcSMark Murray }
367b528cefcSMark Murray 
368b528cefcSMark Murray const void *
369b528cefcSMark Murray krb5_config_get_next (krb5_context context,
3708373020dSJacques Vidrine 		      const krb5_config_section *c,
3718373020dSJacques Vidrine 		      const krb5_config_binding **pointer,
372b528cefcSMark Murray 		      int type,
373b528cefcSMark Murray 		      ...)
374b528cefcSMark Murray {
375b528cefcSMark Murray     const char *ret;
376b528cefcSMark Murray     va_list args;
377b528cefcSMark Murray 
378b528cefcSMark Murray     va_start(args, type);
379b528cefcSMark Murray     ret = krb5_config_vget_next (context, c, pointer, type, args);
380b528cefcSMark Murray     va_end(args);
381b528cefcSMark Murray     return ret;
382b528cefcSMark Murray }
383b528cefcSMark Murray 
3848373020dSJacques Vidrine static const void *
3858373020dSJacques Vidrine vget_next(krb5_context context,
3868373020dSJacques Vidrine 	  const krb5_config_binding *b,
3878373020dSJacques Vidrine 	  const krb5_config_binding **pointer,
3888373020dSJacques Vidrine 	  int type,
3898373020dSJacques Vidrine 	  const char *name,
3908373020dSJacques Vidrine 	  va_list args)
3918373020dSJacques Vidrine {
3928373020dSJacques Vidrine     const char *p = va_arg(args, const char *);
3938373020dSJacques Vidrine     while(b != NULL) {
3940cadf2f4SJacques Vidrine 	if(strcmp(b->name, name) == 0) {
3958373020dSJacques Vidrine 	    if(b->type == type && p == NULL) {
3968373020dSJacques Vidrine 		*pointer = b;
3978373020dSJacques Vidrine 		return b->u.generic;
3988373020dSJacques Vidrine 	    } else if(b->type == krb5_config_list && p != NULL) {
3998373020dSJacques Vidrine 		return vget_next(context, b->u.list, pointer, type, p, args);
4008373020dSJacques Vidrine 	    }
4018373020dSJacques Vidrine 	}
4028373020dSJacques Vidrine 	b = b->next;
4038373020dSJacques Vidrine     }
4048373020dSJacques Vidrine     return NULL;
4058373020dSJacques Vidrine }
4068373020dSJacques Vidrine 
407b528cefcSMark Murray const void *
408b528cefcSMark Murray krb5_config_vget_next (krb5_context context,
4098373020dSJacques Vidrine 		       const krb5_config_section *c,
4108373020dSJacques Vidrine 		       const krb5_config_binding **pointer,
411b528cefcSMark Murray 		       int type,
412b528cefcSMark Murray 		       va_list args)
413b528cefcSMark Murray {
4148373020dSJacques Vidrine     const krb5_config_binding *b;
415b528cefcSMark Murray     const char *p;
416b528cefcSMark Murray 
417b528cefcSMark Murray     if(c == NULL)
418b528cefcSMark Murray 	c = context->cf;
419b528cefcSMark Murray 
420b528cefcSMark Murray     if (c == NULL)
421b528cefcSMark Murray 	return NULL;
422b528cefcSMark Murray 
423b528cefcSMark Murray     if (*pointer == NULL) {
4248373020dSJacques Vidrine 	/* first time here, walk down the tree looking for the right
4258373020dSJacques Vidrine            section */
426b528cefcSMark Murray 	p = va_arg(args, const char *);
427b528cefcSMark Murray 	if (p == NULL)
428b528cefcSMark Murray 	    return NULL;
4298373020dSJacques Vidrine 	return vget_next(context, c, pointer, type, p, args);
430b528cefcSMark Murray     }
431b528cefcSMark Murray 
4328373020dSJacques Vidrine     /* we were called again, so just look for more entries with the
4338373020dSJacques Vidrine        same name and type */
4348373020dSJacques Vidrine     for (b = (*pointer)->next; b != NULL; b = b->next) {
4358373020dSJacques Vidrine 	if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) {
436b528cefcSMark Murray 	    *pointer = b;
437b528cefcSMark Murray 	    return b->u.generic;
438b528cefcSMark Murray 	}
439b528cefcSMark Murray     }
440b528cefcSMark Murray     return NULL;
441b528cefcSMark Murray }
442b528cefcSMark Murray 
443b528cefcSMark Murray const void *
444b528cefcSMark Murray krb5_config_get (krb5_context context,
4458373020dSJacques Vidrine 		 const krb5_config_section *c,
446b528cefcSMark Murray 		 int type,
447b528cefcSMark Murray 		 ...)
448b528cefcSMark Murray {
449b528cefcSMark Murray     const void *ret;
450b528cefcSMark Murray     va_list args;
451b528cefcSMark Murray 
452b528cefcSMark Murray     va_start(args, type);
453b528cefcSMark Murray     ret = krb5_config_vget (context, c, type, args);
454b528cefcSMark Murray     va_end(args);
455b528cefcSMark Murray     return ret;
456b528cefcSMark Murray }
457b528cefcSMark Murray 
458b528cefcSMark Murray const void *
459b528cefcSMark Murray krb5_config_vget (krb5_context context,
4608373020dSJacques Vidrine 		  const krb5_config_section *c,
461b528cefcSMark Murray 		  int type,
462b528cefcSMark Murray 		  va_list args)
463b528cefcSMark Murray {
4648373020dSJacques Vidrine     const krb5_config_binding *foo = NULL;
465b528cefcSMark Murray 
466b528cefcSMark Murray     return krb5_config_vget_next (context, c, &foo, type, args);
467b528cefcSMark Murray }
468b528cefcSMark Murray 
469b528cefcSMark Murray const krb5_config_binding *
470b528cefcSMark Murray krb5_config_get_list (krb5_context context,
4718373020dSJacques Vidrine 		      const krb5_config_section *c,
472b528cefcSMark Murray 		      ...)
473b528cefcSMark Murray {
474b528cefcSMark Murray     const krb5_config_binding *ret;
475b528cefcSMark Murray     va_list args;
476b528cefcSMark Murray 
477b528cefcSMark Murray     va_start(args, c);
478b528cefcSMark Murray     ret = krb5_config_vget_list (context, c, args);
479b528cefcSMark Murray     va_end(args);
480b528cefcSMark Murray     return ret;
481b528cefcSMark Murray }
482b528cefcSMark Murray 
483b528cefcSMark Murray const krb5_config_binding *
484b528cefcSMark Murray krb5_config_vget_list (krb5_context context,
4858373020dSJacques Vidrine 		       const krb5_config_section *c,
486b528cefcSMark Murray 		       va_list args)
487b528cefcSMark Murray {
488b528cefcSMark Murray     return krb5_config_vget (context, c, krb5_config_list, args);
489b528cefcSMark Murray }
490b528cefcSMark Murray 
491c19800e8SDoug Rabson const char* KRB5_LIB_FUNCTION
492b528cefcSMark Murray krb5_config_get_string (krb5_context context,
4938373020dSJacques Vidrine 			const krb5_config_section *c,
494b528cefcSMark Murray 			...)
495b528cefcSMark Murray {
496b528cefcSMark Murray     const char *ret;
497b528cefcSMark Murray     va_list args;
498b528cefcSMark Murray 
499b528cefcSMark Murray     va_start(args, c);
500b528cefcSMark Murray     ret = krb5_config_vget_string (context, c, args);
501b528cefcSMark Murray     va_end(args);
502b528cefcSMark Murray     return ret;
503b528cefcSMark Murray }
504b528cefcSMark Murray 
505c19800e8SDoug Rabson const char* KRB5_LIB_FUNCTION
506b528cefcSMark Murray krb5_config_vget_string (krb5_context context,
5078373020dSJacques Vidrine 			 const krb5_config_section *c,
508b528cefcSMark Murray 			 va_list args)
509b528cefcSMark Murray {
510b528cefcSMark Murray     return krb5_config_vget (context, c, krb5_config_string, args);
511b528cefcSMark Murray }
512b528cefcSMark Murray 
513c19800e8SDoug Rabson const char* KRB5_LIB_FUNCTION
5145e9cd1aeSAssar Westerlund krb5_config_vget_string_default (krb5_context context,
5158373020dSJacques Vidrine 				 const krb5_config_section *c,
5165e9cd1aeSAssar Westerlund 				 const char *def_value,
5175e9cd1aeSAssar Westerlund 				 va_list args)
5185e9cd1aeSAssar Westerlund {
5195e9cd1aeSAssar Westerlund     const char *ret;
5205e9cd1aeSAssar Westerlund 
5215e9cd1aeSAssar Westerlund     ret = krb5_config_vget_string (context, c, args);
5225e9cd1aeSAssar Westerlund     if (ret == NULL)
5235e9cd1aeSAssar Westerlund 	ret = def_value;
5245e9cd1aeSAssar Westerlund     return ret;
5255e9cd1aeSAssar Westerlund }
5265e9cd1aeSAssar Westerlund 
527c19800e8SDoug Rabson const char* KRB5_LIB_FUNCTION
5285e9cd1aeSAssar Westerlund krb5_config_get_string_default (krb5_context context,
5298373020dSJacques Vidrine 				const krb5_config_section *c,
5305e9cd1aeSAssar Westerlund 				const char *def_value,
5315e9cd1aeSAssar Westerlund 				...)
5325e9cd1aeSAssar Westerlund {
5335e9cd1aeSAssar Westerlund     const char *ret;
5345e9cd1aeSAssar Westerlund     va_list args;
5355e9cd1aeSAssar Westerlund 
5365e9cd1aeSAssar Westerlund     va_start(args, def_value);
5375e9cd1aeSAssar Westerlund     ret = krb5_config_vget_string_default (context, c, def_value, args);
5385e9cd1aeSAssar Westerlund     va_end(args);
5395e9cd1aeSAssar Westerlund     return ret;
5405e9cd1aeSAssar Westerlund }
5415e9cd1aeSAssar Westerlund 
542c19800e8SDoug Rabson char ** KRB5_LIB_FUNCTION
543b528cefcSMark Murray krb5_config_vget_strings(krb5_context context,
5448373020dSJacques Vidrine 			 const krb5_config_section *c,
545b528cefcSMark Murray 			 va_list args)
546b528cefcSMark Murray {
547b528cefcSMark Murray     char **strings = NULL;
548b528cefcSMark Murray     int nstr = 0;
5498373020dSJacques Vidrine     const krb5_config_binding *b = NULL;
550b528cefcSMark Murray     const char *p;
551b528cefcSMark Murray 
552b528cefcSMark Murray     while((p = krb5_config_vget_next(context, c, &b,
553b528cefcSMark Murray 				     krb5_config_string, args))) {
554b528cefcSMark Murray 	char *tmp = strdup(p);
555b528cefcSMark Murray 	char *pos = NULL;
556b528cefcSMark Murray 	char *s;
557b528cefcSMark Murray 	if(tmp == NULL)
558b528cefcSMark Murray 	    goto cleanup;
559b528cefcSMark Murray 	s = strtok_r(tmp, " \t", &pos);
560b528cefcSMark Murray 	while(s){
561c19800e8SDoug Rabson 	    char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
562c19800e8SDoug Rabson 	    if(tmp2 == NULL)
563b528cefcSMark Murray 		goto cleanup;
564c19800e8SDoug Rabson 	    strings = tmp2;
565b528cefcSMark Murray 	    strings[nstr] = strdup(s);
566b528cefcSMark Murray 	    nstr++;
567b528cefcSMark Murray 	    if(strings[nstr-1] == NULL)
568b528cefcSMark Murray 		goto cleanup;
569b528cefcSMark Murray 	    s = strtok_r(NULL, " \t", &pos);
570b528cefcSMark Murray 	}
571b528cefcSMark Murray 	free(tmp);
572b528cefcSMark Murray     }
573b528cefcSMark Murray     if(nstr){
574b528cefcSMark Murray 	char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
575c19800e8SDoug Rabson 	if(tmp == NULL)
576b528cefcSMark Murray 	    goto cleanup;
577b528cefcSMark Murray 	strings = tmp;
578b528cefcSMark Murray 	strings[nstr] = NULL;
579b528cefcSMark Murray     }
580b528cefcSMark Murray     return strings;
581b528cefcSMark Murray cleanup:
582b528cefcSMark Murray     while(nstr--)
583b528cefcSMark Murray 	free(strings[nstr]);
584b528cefcSMark Murray     free(strings);
585b528cefcSMark Murray     return NULL;
586b528cefcSMark Murray 
587b528cefcSMark Murray }
588b528cefcSMark Murray 
589b528cefcSMark Murray char**
590b528cefcSMark Murray krb5_config_get_strings(krb5_context context,
5918373020dSJacques Vidrine 			const krb5_config_section *c,
592b528cefcSMark Murray 			...)
593b528cefcSMark Murray {
594b528cefcSMark Murray     va_list ap;
595b528cefcSMark Murray     char **ret;
596b528cefcSMark Murray     va_start(ap, c);
597b528cefcSMark Murray     ret = krb5_config_vget_strings(context, c, ap);
598b528cefcSMark Murray     va_end(ap);
599b528cefcSMark Murray     return ret;
600b528cefcSMark Murray }
601b528cefcSMark Murray 
602c19800e8SDoug Rabson void KRB5_LIB_FUNCTION
603b528cefcSMark Murray krb5_config_free_strings(char **strings)
604b528cefcSMark Murray {
605b528cefcSMark Murray     char **s = strings;
606b528cefcSMark Murray     while(s && *s){
607b528cefcSMark Murray 	free(*s);
608b528cefcSMark Murray 	s++;
609b528cefcSMark Murray     }
610b528cefcSMark Murray     free(strings);
611b528cefcSMark Murray }
612b528cefcSMark Murray 
613c19800e8SDoug Rabson krb5_boolean KRB5_LIB_FUNCTION
614b528cefcSMark Murray krb5_config_vget_bool_default (krb5_context context,
6158373020dSJacques Vidrine 			       const krb5_config_section *c,
616b528cefcSMark Murray 			       krb5_boolean def_value,
617b528cefcSMark Murray 			       va_list args)
618b528cefcSMark Murray {
619b528cefcSMark Murray     const char *str;
620b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
621b528cefcSMark Murray     if(str == NULL)
622b528cefcSMark Murray 	return def_value;
623b528cefcSMark Murray     if(strcasecmp(str, "yes") == 0 ||
624b528cefcSMark Murray        strcasecmp(str, "true") == 0 ||
625b528cefcSMark Murray        atoi(str)) return TRUE;
626b528cefcSMark Murray     return FALSE;
627b528cefcSMark Murray }
628b528cefcSMark Murray 
629c19800e8SDoug Rabson krb5_boolean KRB5_LIB_FUNCTION
630b528cefcSMark Murray krb5_config_vget_bool  (krb5_context context,
6318373020dSJacques Vidrine 			const krb5_config_section *c,
632b528cefcSMark Murray 			va_list args)
633b528cefcSMark Murray {
634b528cefcSMark Murray     return krb5_config_vget_bool_default (context, c, FALSE, args);
635b528cefcSMark Murray }
636b528cefcSMark Murray 
637c19800e8SDoug Rabson krb5_boolean KRB5_LIB_FUNCTION
638b528cefcSMark Murray krb5_config_get_bool_default (krb5_context context,
6398373020dSJacques Vidrine 			      const krb5_config_section *c,
640b528cefcSMark Murray 			      krb5_boolean def_value,
641b528cefcSMark Murray 			      ...)
642b528cefcSMark Murray {
643b528cefcSMark Murray     va_list ap;
644b528cefcSMark Murray     krb5_boolean ret;
645b528cefcSMark Murray     va_start(ap, def_value);
646b528cefcSMark Murray     ret = krb5_config_vget_bool_default(context, c, def_value, ap);
647b528cefcSMark Murray     va_end(ap);
648b528cefcSMark Murray     return ret;
649b528cefcSMark Murray }
650b528cefcSMark Murray 
651c19800e8SDoug Rabson krb5_boolean KRB5_LIB_FUNCTION
652b528cefcSMark Murray krb5_config_get_bool (krb5_context context,
6538373020dSJacques Vidrine 		      const krb5_config_section *c,
654b528cefcSMark Murray 		      ...)
655b528cefcSMark Murray {
656b528cefcSMark Murray     va_list ap;
657b528cefcSMark Murray     krb5_boolean ret;
658b528cefcSMark Murray     va_start(ap, c);
659b528cefcSMark Murray     ret = krb5_config_vget_bool (context, c, ap);
660b528cefcSMark Murray     va_end(ap);
661b528cefcSMark Murray     return ret;
662b528cefcSMark Murray }
663b528cefcSMark Murray 
664c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
665b528cefcSMark Murray krb5_config_vget_time_default (krb5_context context,
6668373020dSJacques Vidrine 			       const krb5_config_section *c,
667b528cefcSMark Murray 			       int def_value,
668b528cefcSMark Murray 			       va_list args)
669b528cefcSMark Murray {
670b528cefcSMark Murray     const char *str;
671c19800e8SDoug Rabson     krb5_deltat t;
672c19800e8SDoug Rabson 
673b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
674b528cefcSMark Murray     if(str == NULL)
675b528cefcSMark Murray 	return def_value;
676c19800e8SDoug Rabson     if (krb5_string_to_deltat(str, &t))
677c19800e8SDoug Rabson 	return def_value;
678c19800e8SDoug Rabson     return t;
679b528cefcSMark Murray }
680b528cefcSMark Murray 
681c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
682b528cefcSMark Murray krb5_config_vget_time  (krb5_context context,
6838373020dSJacques Vidrine 			const krb5_config_section *c,
684b528cefcSMark Murray 			va_list args)
685b528cefcSMark Murray {
686b528cefcSMark Murray     return krb5_config_vget_time_default (context, c, -1, args);
687b528cefcSMark Murray }
688b528cefcSMark Murray 
689c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
690b528cefcSMark Murray krb5_config_get_time_default (krb5_context context,
6918373020dSJacques Vidrine 			      const krb5_config_section *c,
692b528cefcSMark Murray 			      int def_value,
693b528cefcSMark Murray 			      ...)
694b528cefcSMark Murray {
695b528cefcSMark Murray     va_list ap;
696b528cefcSMark Murray     int ret;
697b528cefcSMark Murray     va_start(ap, def_value);
698b528cefcSMark Murray     ret = krb5_config_vget_time_default(context, c, def_value, ap);
699b528cefcSMark Murray     va_end(ap);
700b528cefcSMark Murray     return ret;
701b528cefcSMark Murray }
702b528cefcSMark Murray 
703c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
704b528cefcSMark Murray krb5_config_get_time (krb5_context context,
7058373020dSJacques Vidrine 		      const krb5_config_section *c,
706b528cefcSMark Murray 		      ...)
707b528cefcSMark Murray {
708b528cefcSMark Murray     va_list ap;
709b528cefcSMark Murray     int ret;
710b528cefcSMark Murray     va_start(ap, c);
711b528cefcSMark Murray     ret = krb5_config_vget_time (context, c, ap);
712b528cefcSMark Murray     va_end(ap);
713b528cefcSMark Murray     return ret;
714b528cefcSMark Murray }
715b528cefcSMark Murray 
716b528cefcSMark Murray 
717c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
718b528cefcSMark Murray krb5_config_vget_int_default (krb5_context context,
7198373020dSJacques Vidrine 			      const krb5_config_section *c,
720b528cefcSMark Murray 			      int def_value,
721b528cefcSMark Murray 			      va_list args)
722b528cefcSMark Murray {
723b528cefcSMark Murray     const char *str;
724b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
725b528cefcSMark Murray     if(str == NULL)
726b528cefcSMark Murray 	return def_value;
727b528cefcSMark Murray     else {
728b528cefcSMark Murray 	char *endptr;
729b528cefcSMark Murray 	long l;
730b528cefcSMark Murray 	l = strtol(str, &endptr, 0);
731b528cefcSMark Murray 	if (endptr == str)
732b528cefcSMark Murray 	    return def_value;
733b528cefcSMark Murray 	else
734b528cefcSMark Murray 	    return l;
735b528cefcSMark Murray     }
736b528cefcSMark Murray }
737b528cefcSMark Murray 
738c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
739b528cefcSMark Murray krb5_config_vget_int  (krb5_context context,
7408373020dSJacques Vidrine 		       const krb5_config_section *c,
741b528cefcSMark Murray 		       va_list args)
742b528cefcSMark Murray {
743b528cefcSMark Murray     return krb5_config_vget_int_default (context, c, -1, args);
744b528cefcSMark Murray }
745b528cefcSMark Murray 
746c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
747b528cefcSMark Murray krb5_config_get_int_default (krb5_context context,
7488373020dSJacques Vidrine 			     const krb5_config_section *c,
749b528cefcSMark Murray 			     int def_value,
750b528cefcSMark Murray 			     ...)
751b528cefcSMark Murray {
752b528cefcSMark Murray     va_list ap;
753b528cefcSMark Murray     int ret;
754b528cefcSMark Murray     va_start(ap, def_value);
755b528cefcSMark Murray     ret = krb5_config_vget_int_default(context, c, def_value, ap);
756b528cefcSMark Murray     va_end(ap);
757b528cefcSMark Murray     return ret;
758b528cefcSMark Murray }
759b528cefcSMark Murray 
760c19800e8SDoug Rabson int KRB5_LIB_FUNCTION
761b528cefcSMark Murray krb5_config_get_int (krb5_context context,
7628373020dSJacques Vidrine 		     const krb5_config_section *c,
763b528cefcSMark Murray 		     ...)
764b528cefcSMark Murray {
765b528cefcSMark Murray     va_list ap;
766b528cefcSMark Murray     int ret;
767b528cefcSMark Murray     va_start(ap, c);
768b528cefcSMark Murray     ret = krb5_config_vget_int (context, c, ap);
769b528cefcSMark Murray     va_end(ap);
770b528cefcSMark Murray     return ret;
771b528cefcSMark Murray }
772