xref: /freebsd/crypto/heimdal/lib/krb5/config_file.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov  * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6*ae771770SStanislav Sedov  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7*ae771770SStanislav Sedov  *
8b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
9b528cefcSMark Murray  * modification, are permitted provided that the following conditions
10b528cefcSMark Murray  * are met:
11b528cefcSMark Murray  *
12b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
13b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
14b528cefcSMark Murray  *
15b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
16b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
17b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
18b528cefcSMark Murray  *
19b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
20b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
21b528cefcSMark Murray  *    without specific prior written permission.
22b528cefcSMark Murray  *
23b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33b528cefcSMark Murray  * SUCH DAMAGE.
34b528cefcSMark Murray  */
35b528cefcSMark Murray 
36b528cefcSMark Murray #include "krb5_locl.h"
37b528cefcSMark Murray 
38*ae771770SStanislav Sedov #ifdef __APPLE__
39*ae771770SStanislav Sedov #include <CoreFoundation/CoreFoundation.h>
40*ae771770SStanislav Sedov #endif
41b528cefcSMark Murray 
42c19800e8SDoug Rabson /* Gaah! I want a portable funopen */
43c19800e8SDoug Rabson struct fileptr {
44c19800e8SDoug Rabson     const char *s;
45c19800e8SDoug Rabson     FILE *f;
46c19800e8SDoug Rabson };
47c19800e8SDoug Rabson 
48c19800e8SDoug Rabson static char *
config_fgets(char * str,size_t len,struct fileptr * ptr)49c19800e8SDoug Rabson config_fgets(char *str, size_t len, struct fileptr *ptr)
50c19800e8SDoug Rabson {
51c19800e8SDoug Rabson     /* XXX this is not correct, in that they don't do the same if the
52c19800e8SDoug Rabson        line is longer than len */
53c19800e8SDoug Rabson     if(ptr->f != NULL)
54c19800e8SDoug Rabson 	return fgets(str, len, ptr->f);
55c19800e8SDoug Rabson     else {
56c19800e8SDoug Rabson 	/* this is almost strsep_copy */
57c19800e8SDoug Rabson 	const char *p;
58c19800e8SDoug Rabson 	ssize_t l;
59c19800e8SDoug Rabson 	if(*ptr->s == '\0')
60c19800e8SDoug Rabson 	    return NULL;
61c19800e8SDoug Rabson 	p = ptr->s + strcspn(ptr->s, "\n");
62c19800e8SDoug Rabson 	if(*p == '\n')
63c19800e8SDoug Rabson 	    p++;
64*ae771770SStanislav Sedov 	l = min(len, (size_t)(p - ptr->s));
65c19800e8SDoug Rabson 	if(len > 0) {
66c19800e8SDoug Rabson 	    memcpy(str, ptr->s, l);
67c19800e8SDoug Rabson 	    str[l] = '\0';
68c19800e8SDoug Rabson 	}
69c19800e8SDoug Rabson 	ptr->s = p;
70c19800e8SDoug Rabson 	return str;
71c19800e8SDoug Rabson     }
72c19800e8SDoug Rabson }
73c19800e8SDoug Rabson 
74adb0ddaeSAssar Westerlund static krb5_error_code parse_section(char *p, krb5_config_section **s,
75b528cefcSMark Murray 				     krb5_config_section **res,
76*ae771770SStanislav Sedov 				     const char **err_message);
77c19800e8SDoug Rabson static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
78b528cefcSMark Murray 				     krb5_config_binding **b,
79b528cefcSMark Murray 				     krb5_config_binding **parent,
80*ae771770SStanislav Sedov 				     const char **err_message);
81c19800e8SDoug Rabson static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno,
82adb0ddaeSAssar Westerlund 				  krb5_config_binding **parent,
83*ae771770SStanislav Sedov 				  const char **err_message);
848373020dSJacques Vidrine 
85*ae771770SStanislav Sedov krb5_config_section *
_krb5_config_get_entry(krb5_config_section ** parent,const char * name,int type)86*ae771770SStanislav Sedov _krb5_config_get_entry(krb5_config_section **parent, const char *name, int type)
878373020dSJacques Vidrine {
888373020dSJacques Vidrine     krb5_config_section **q;
898373020dSJacques Vidrine 
908373020dSJacques Vidrine     for(q = parent; *q != NULL; q = &(*q)->next)
918373020dSJacques Vidrine 	if(type == krb5_config_list &&
92*ae771770SStanislav Sedov 	   (unsigned)type == (*q)->type &&
938373020dSJacques Vidrine 	   strcmp(name, (*q)->name) == 0)
948373020dSJacques Vidrine 	    return *q;
958373020dSJacques Vidrine     *q = calloc(1, sizeof(**q));
968373020dSJacques Vidrine     if(*q == NULL)
978373020dSJacques Vidrine 	return NULL;
988373020dSJacques Vidrine     (*q)->name = strdup(name);
998373020dSJacques Vidrine     (*q)->type = type;
1008373020dSJacques Vidrine     if((*q)->name == NULL) {
1018373020dSJacques Vidrine 	free(*q);
1028373020dSJacques Vidrine 	*q = NULL;
1038373020dSJacques Vidrine 	return NULL;
1048373020dSJacques Vidrine     }
1058373020dSJacques Vidrine     return *q;
1068373020dSJacques Vidrine }
107b528cefcSMark Murray 
108b528cefcSMark Murray /*
109b528cefcSMark Murray  * Parse a section:
110b528cefcSMark Murray  *
111b528cefcSMark Murray  * [section]
112b528cefcSMark Murray  *	foo = bar
113b528cefcSMark Murray  *	b = {
114b528cefcSMark Murray  *		a
115b528cefcSMark Murray  *	    }
116b528cefcSMark Murray  * ...
117b528cefcSMark Murray  *
118b528cefcSMark Murray  * starting at the line in `p', storing the resulting structure in
119b528cefcSMark Murray  * `s' and hooking it into `parent'.
120*ae771770SStanislav Sedov  * Store the error message in `err_message'.
121b528cefcSMark Murray  */
122b528cefcSMark Murray 
123adb0ddaeSAssar Westerlund static krb5_error_code
parse_section(char * p,krb5_config_section ** s,krb5_config_section ** parent,const char ** err_message)124b528cefcSMark Murray parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
125*ae771770SStanislav Sedov 	      const char **err_message)
126b528cefcSMark Murray {
127b528cefcSMark Murray     char *p1;
128b528cefcSMark Murray     krb5_config_section *tmp;
129b528cefcSMark Murray 
130b528cefcSMark Murray     p1 = strchr (p + 1, ']');
131b528cefcSMark Murray     if (p1 == NULL) {
132*ae771770SStanislav Sedov 	*err_message = "missing ]";
133adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
134b528cefcSMark Murray     }
135b528cefcSMark Murray     *p1 = '\0';
136*ae771770SStanislav Sedov     tmp = _krb5_config_get_entry(parent, p + 1, krb5_config_list);
137b528cefcSMark Murray     if(tmp == NULL) {
138*ae771770SStanislav Sedov 	*err_message = "out of memory";
139adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
140b528cefcSMark Murray     }
141b528cefcSMark Murray     *s = tmp;
142b528cefcSMark Murray     return 0;
143b528cefcSMark Murray }
144b528cefcSMark Murray 
145b528cefcSMark Murray /*
146b528cefcSMark Murray  * Parse a brace-enclosed list from `f', hooking in the structure at
147b528cefcSMark Murray  * `parent'.
148*ae771770SStanislav Sedov  * Store the error message in `err_message'.
149b528cefcSMark Murray  */
150b528cefcSMark Murray 
1511c43270aSJacques Vidrine static krb5_error_code
parse_list(struct fileptr * f,unsigned * lineno,krb5_config_binding ** parent,const char ** err_message)152c19800e8SDoug Rabson parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent,
153*ae771770SStanislav Sedov 	   const char **err_message)
154b528cefcSMark Murray {
155*ae771770SStanislav Sedov     char buf[KRB5_BUFSIZ];
1561c43270aSJacques Vidrine     krb5_error_code ret;
157b528cefcSMark Murray     krb5_config_binding *b = NULL;
158b528cefcSMark Murray     unsigned beg_lineno = *lineno;
159b528cefcSMark Murray 
160c19800e8SDoug Rabson     while(config_fgets(buf, sizeof(buf), f) != NULL) {
161b528cefcSMark Murray 	char *p;
162b528cefcSMark Murray 
163b528cefcSMark Murray 	++*lineno;
164c19800e8SDoug Rabson 	buf[strcspn(buf, "\r\n")] = '\0';
165b528cefcSMark Murray 	p = buf;
166b528cefcSMark Murray 	while(isspace((unsigned char)*p))
167b528cefcSMark Murray 	    ++p;
168b528cefcSMark Murray 	if (*p == '#' || *p == ';' || *p == '\0')
169b528cefcSMark Murray 	    continue;
170b528cefcSMark Murray 	while(isspace((unsigned char)*p))
171b528cefcSMark Murray 	    ++p;
172b528cefcSMark Murray 	if (*p == '}')
173b528cefcSMark Murray 	    return 0;
174b528cefcSMark Murray 	if (*p == '\0')
175b528cefcSMark Murray 	    continue;
176*ae771770SStanislav Sedov 	ret = parse_binding (f, lineno, p, &b, parent, err_message);
177b528cefcSMark Murray 	if (ret)
178b528cefcSMark Murray 	    return ret;
179b528cefcSMark Murray     }
180b528cefcSMark Murray     *lineno = beg_lineno;
181*ae771770SStanislav Sedov     *err_message = "unclosed {";
182adb0ddaeSAssar Westerlund     return KRB5_CONFIG_BADFORMAT;
183b528cefcSMark Murray }
184b528cefcSMark Murray 
185b528cefcSMark Murray /*
186b528cefcSMark Murray  *
187b528cefcSMark Murray  */
188b528cefcSMark Murray 
1891c43270aSJacques Vidrine static krb5_error_code
parse_binding(struct fileptr * f,unsigned * lineno,char * p,krb5_config_binding ** b,krb5_config_binding ** parent,const char ** err_message)190c19800e8SDoug Rabson parse_binding(struct fileptr *f, unsigned *lineno, char *p,
191b528cefcSMark Murray 	      krb5_config_binding **b, krb5_config_binding **parent,
192*ae771770SStanislav Sedov 	      const char **err_message)
193b528cefcSMark Murray {
194b528cefcSMark Murray     krb5_config_binding *tmp;
195b528cefcSMark Murray     char *p1, *p2;
1961c43270aSJacques Vidrine     krb5_error_code ret = 0;
197b528cefcSMark Murray 
198b528cefcSMark Murray     p1 = p;
199b528cefcSMark Murray     while (*p && *p != '=' && !isspace((unsigned char)*p))
200b528cefcSMark Murray 	++p;
201b528cefcSMark Murray     if (*p == '\0') {
202*ae771770SStanislav Sedov 	*err_message = "missing =";
203adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
204b528cefcSMark Murray     }
205b528cefcSMark Murray     p2 = p;
206b528cefcSMark Murray     while (isspace((unsigned char)*p))
207b528cefcSMark Murray 	++p;
208b528cefcSMark Murray     if (*p != '=') {
209*ae771770SStanislav Sedov 	*err_message = "missing =";
210adb0ddaeSAssar Westerlund 	return KRB5_CONFIG_BADFORMAT;
211b528cefcSMark Murray     }
212b528cefcSMark Murray     ++p;
213b528cefcSMark Murray     while(isspace((unsigned char)*p))
214b528cefcSMark Murray 	++p;
2158373020dSJacques Vidrine     *p2 = '\0';
2168373020dSJacques Vidrine     if (*p == '{') {
217*ae771770SStanislav Sedov 	tmp = _krb5_config_get_entry(parent, p1, krb5_config_list);
218b528cefcSMark Murray 	if (tmp == NULL) {
219*ae771770SStanislav Sedov 	    *err_message = "out of memory";
220adb0ddaeSAssar Westerlund 	    return KRB5_CONFIG_BADFORMAT;
221b528cefcSMark Murray 	}
222*ae771770SStanislav Sedov 	ret = parse_list (f, lineno, &tmp->u.list, err_message);
223b528cefcSMark Murray     } else {
224*ae771770SStanislav Sedov 	tmp = _krb5_config_get_entry(parent, p1, krb5_config_string);
2258373020dSJacques Vidrine 	if (tmp == NULL) {
226*ae771770SStanislav Sedov 	    *err_message = "out of memory";
2278373020dSJacques Vidrine 	    return KRB5_CONFIG_BADFORMAT;
2288373020dSJacques Vidrine 	}
229b528cefcSMark Murray 	p1 = p;
230b528cefcSMark Murray 	p = p1 + strlen(p1);
231b528cefcSMark Murray 	while(p > p1 && isspace((unsigned char)*(p-1)))
232b528cefcSMark Murray 	    --p;
233b528cefcSMark Murray 	*p = '\0';
234b528cefcSMark Murray 	tmp->u.string = strdup(p1);
235b528cefcSMark Murray     }
236b528cefcSMark Murray     *b = tmp;
237b528cefcSMark Murray     return ret;
238b528cefcSMark Murray }
239b528cefcSMark Murray 
240*ae771770SStanislav Sedov #if defined(__APPLE__)
241*ae771770SStanislav Sedov 
242*ae771770SStanislav Sedov #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
243*ae771770SStanislav Sedov #define HAVE_CFPROPERTYLISTCREATEWITHSTREAM 1
244*ae771770SStanislav Sedov #endif
245*ae771770SStanislav Sedov 
246*ae771770SStanislav Sedov static char *
cfstring2cstring(CFStringRef string)247*ae771770SStanislav Sedov cfstring2cstring(CFStringRef string)
248*ae771770SStanislav Sedov {
249*ae771770SStanislav Sedov     CFIndex len;
250*ae771770SStanislav Sedov     char *str;
251*ae771770SStanislav Sedov 
252*ae771770SStanislav Sedov     str = (char *) CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
253*ae771770SStanislav Sedov     if (str)
254*ae771770SStanislav Sedov 	return strdup(str);
255*ae771770SStanislav Sedov 
256*ae771770SStanislav Sedov     len = CFStringGetLength(string);
257*ae771770SStanislav Sedov     len = 1 + CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8);
258*ae771770SStanislav Sedov     str = malloc(len);
259*ae771770SStanislav Sedov     if (str == NULL)
260*ae771770SStanislav Sedov 	return NULL;
261*ae771770SStanislav Sedov 
262*ae771770SStanislav Sedov     if (!CFStringGetCString (string, str, len, kCFStringEncodingUTF8)) {
263*ae771770SStanislav Sedov 	free (str);
264*ae771770SStanislav Sedov 	return NULL;
265*ae771770SStanislav Sedov     }
266*ae771770SStanislav Sedov     return str;
267*ae771770SStanislav Sedov }
268*ae771770SStanislav Sedov 
269*ae771770SStanislav Sedov static void
convert_content(const void * key,const void * value,void * context)270*ae771770SStanislav Sedov convert_content(const void *key, const void *value, void *context)
271*ae771770SStanislav Sedov {
272*ae771770SStanislav Sedov     krb5_config_section *tmp, **parent = context;
273*ae771770SStanislav Sedov     char *k;
274*ae771770SStanislav Sedov 
275*ae771770SStanislav Sedov     if (CFGetTypeID(key) != CFStringGetTypeID())
276*ae771770SStanislav Sedov 	return;
277*ae771770SStanislav Sedov 
278*ae771770SStanislav Sedov     k = cfstring2cstring(key);
279*ae771770SStanislav Sedov     if (k == NULL)
280*ae771770SStanislav Sedov 	return;
281*ae771770SStanislav Sedov 
282*ae771770SStanislav Sedov     if (CFGetTypeID(value) == CFStringGetTypeID()) {
283*ae771770SStanislav Sedov 	tmp = _krb5_config_get_entry(parent, k, krb5_config_string);
284*ae771770SStanislav Sedov 	tmp->u.string = cfstring2cstring(value);
285*ae771770SStanislav Sedov     } else if (CFGetTypeID(value) == CFDictionaryGetTypeID()) {
286*ae771770SStanislav Sedov 	tmp = _krb5_config_get_entry(parent, k, krb5_config_list);
287*ae771770SStanislav Sedov 	CFDictionaryApplyFunction(value, convert_content, &tmp->u.list);
288*ae771770SStanislav Sedov     } else {
289*ae771770SStanislav Sedov 	/* log */
290*ae771770SStanislav Sedov     }
291*ae771770SStanislav Sedov     free(k);
292*ae771770SStanislav Sedov }
293*ae771770SStanislav Sedov 
294*ae771770SStanislav Sedov static krb5_error_code
parse_plist_config(krb5_context context,const char * path,krb5_config_section ** parent)295*ae771770SStanislav Sedov parse_plist_config(krb5_context context, const char *path, krb5_config_section **parent)
296*ae771770SStanislav Sedov {
297*ae771770SStanislav Sedov     CFReadStreamRef s;
298*ae771770SStanislav Sedov     CFDictionaryRef d;
299*ae771770SStanislav Sedov     CFURLRef url;
300*ae771770SStanislav Sedov 
301*ae771770SStanislav Sedov     url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)path, strlen(path), FALSE);
302*ae771770SStanislav Sedov     if (url == NULL) {
303*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
304*ae771770SStanislav Sedov 	return ENOMEM;
305*ae771770SStanislav Sedov     }
306*ae771770SStanislav Sedov 
307*ae771770SStanislav Sedov     s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
308*ae771770SStanislav Sedov     CFRelease(url);
309*ae771770SStanislav Sedov     if (s == NULL) {
310*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
311*ae771770SStanislav Sedov 	return ENOMEM;
312*ae771770SStanislav Sedov     }
313*ae771770SStanislav Sedov 
314*ae771770SStanislav Sedov     if (!CFReadStreamOpen(s)) {
315*ae771770SStanislav Sedov 	CFRelease(s);
316*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
317*ae771770SStanislav Sedov 	return ENOENT;
318*ae771770SStanislav Sedov     }
319*ae771770SStanislav Sedov 
320*ae771770SStanislav Sedov #ifdef HAVE_CFPROPERTYLISTCREATEWITHSTREAM
321*ae771770SStanislav Sedov     d = (CFDictionaryRef)CFPropertyListCreateWithStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
322*ae771770SStanislav Sedov #else
323*ae771770SStanislav Sedov     d = (CFDictionaryRef)CFPropertyListCreateFromStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
324*ae771770SStanislav Sedov #endif
325*ae771770SStanislav Sedov     CFRelease(s);
326*ae771770SStanislav Sedov     if (d == NULL) {
327*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
328*ae771770SStanislav Sedov 	return ENOENT;
329*ae771770SStanislav Sedov     }
330*ae771770SStanislav Sedov 
331*ae771770SStanislav Sedov     CFDictionaryApplyFunction(d, convert_content, parent);
332*ae771770SStanislav Sedov     CFRelease(d);
333*ae771770SStanislav Sedov 
334*ae771770SStanislav Sedov     return 0;
335*ae771770SStanislav Sedov }
336*ae771770SStanislav Sedov 
337*ae771770SStanislav Sedov #endif
338*ae771770SStanislav Sedov 
339*ae771770SStanislav Sedov 
340b528cefcSMark Murray /*
341b528cefcSMark Murray  * Parse the config file `fname', generating the structures into `res'
342*ae771770SStanislav Sedov  * returning error messages in `err_message'
343b528cefcSMark Murray  */
344b528cefcSMark Murray 
345adb0ddaeSAssar Westerlund static krb5_error_code
krb5_config_parse_debug(struct fileptr * f,krb5_config_section ** res,unsigned * lineno,const char ** err_message)346c19800e8SDoug Rabson krb5_config_parse_debug (struct fileptr *f,
347b528cefcSMark Murray 			 krb5_config_section **res,
348b528cefcSMark Murray 			 unsigned *lineno,
349*ae771770SStanislav Sedov 			 const char **err_message)
350b528cefcSMark Murray {
351c19800e8SDoug Rabson     krb5_config_section *s = NULL;
352c19800e8SDoug Rabson     krb5_config_binding *b = NULL;
353*ae771770SStanislav Sedov     char buf[KRB5_BUFSIZ];
354c19800e8SDoug Rabson     krb5_error_code ret;
355b528cefcSMark Murray 
356c19800e8SDoug Rabson     while (config_fgets(buf, sizeof(buf), f) != NULL) {
357b528cefcSMark Murray 	char *p;
358b528cefcSMark Murray 
359b528cefcSMark Murray 	++*lineno;
360c19800e8SDoug Rabson 	buf[strcspn(buf, "\r\n")] = '\0';
361b528cefcSMark Murray 	p = buf;
362b528cefcSMark Murray 	while(isspace((unsigned char)*p))
363b528cefcSMark Murray 	    ++p;
364b528cefcSMark Murray 	if (*p == '#' || *p == ';')
365b528cefcSMark Murray 	    continue;
366b528cefcSMark Murray 	if (*p == '[') {
367*ae771770SStanislav Sedov 	    ret = parse_section(p, &s, res, err_message);
368c19800e8SDoug Rabson 	    if (ret)
369c19800e8SDoug Rabson 		return ret;
370b528cefcSMark Murray 	    b = NULL;
371b528cefcSMark Murray 	} else if (*p == '}') {
372*ae771770SStanislav Sedov 	    *err_message = "unmatched }";
373c19800e8SDoug Rabson 	    return EINVAL;	/* XXX */
374b528cefcSMark Murray 	} else if(*p != '\0') {
3751c43270aSJacques Vidrine 	    if (s == NULL) {
376*ae771770SStanislav Sedov 		*err_message = "binding before section";
377c19800e8SDoug Rabson 		return EINVAL;
3781c43270aSJacques Vidrine 	    }
379*ae771770SStanislav Sedov 	    ret = parse_binding(f, lineno, p, &b, &s->u.list, err_message);
380b528cefcSMark Murray 	    if (ret)
3815e9cd1aeSAssar Westerlund 		return ret;
382b528cefcSMark Murray 	}
383c19800e8SDoug Rabson     }
384c19800e8SDoug Rabson     return 0;
385c19800e8SDoug Rabson }
386b528cefcSMark Murray 
387*ae771770SStanislav Sedov static int
is_plist_file(const char * fname)388*ae771770SStanislav Sedov is_plist_file(const char *fname)
389c19800e8SDoug Rabson {
390*ae771770SStanislav Sedov     size_t len = strlen(fname);
391*ae771770SStanislav Sedov     char suffix[] = ".plist";
392*ae771770SStanislav Sedov     if (len < sizeof(suffix))
393c19800e8SDoug Rabson 	return 0;
394*ae771770SStanislav Sedov     if (strcasecmp(&fname[len - (sizeof(suffix) - 1)], suffix) != 0)
395*ae771770SStanislav Sedov 	return 0;
396*ae771770SStanislav Sedov     return 1;
397c19800e8SDoug Rabson }
398c19800e8SDoug Rabson 
399*ae771770SStanislav Sedov /**
400*ae771770SStanislav Sedov  * Parse a configuration file and add the result into res. This
401*ae771770SStanislav Sedov  * interface can be used to parse several configuration files into one
402*ae771770SStanislav Sedov  * resulting krb5_config_section by calling it repeatably.
403*ae771770SStanislav Sedov  *
404*ae771770SStanislav Sedov  * @param context a Kerberos 5 context.
405*ae771770SStanislav Sedov  * @param fname a file name to a Kerberos configuration file
406*ae771770SStanislav Sedov  * @param res the returned result, must be free with krb5_free_config_files().
407*ae771770SStanislav Sedov  * @return Return an error code or 0, see krb5_get_error_message().
408*ae771770SStanislav Sedov  *
409*ae771770SStanislav Sedov  * @ingroup krb5_support
410*ae771770SStanislav Sedov  */
411*ae771770SStanislav Sedov 
412*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_config_parse_file_multi(krb5_context context,const char * fname,krb5_config_section ** res)4138373020dSJacques Vidrine krb5_config_parse_file_multi (krb5_context context,
414adb0ddaeSAssar Westerlund 			      const char *fname,
415adb0ddaeSAssar Westerlund 			      krb5_config_section **res)
416b528cefcSMark Murray {
4178373020dSJacques Vidrine     const char *str;
418*ae771770SStanislav Sedov     char *newfname = NULL;
419c19800e8SDoug Rabson     unsigned lineno = 0;
420adb0ddaeSAssar Westerlund     krb5_error_code ret;
421c19800e8SDoug Rabson     struct fileptr f;
422*ae771770SStanislav Sedov 
423*ae771770SStanislav Sedov     /**
424*ae771770SStanislav Sedov      * If the fname starts with "~/" parse configuration file in the
425*ae771770SStanislav Sedov      * current users home directory. The behavior can be disabled and
426*ae771770SStanislav Sedov      * enabled by calling krb5_set_home_dir_access().
427*ae771770SStanislav Sedov      */
428*ae771770SStanislav Sedov     if (fname[0] == '~' && fname[1] == '/') {
429*ae771770SStanislav Sedov #ifndef KRB5_USE_PATH_TOKENS
430*ae771770SStanislav Sedov 	const char *home = NULL;
431*ae771770SStanislav Sedov 
432*ae771770SStanislav Sedov 	if (!_krb5_homedir_access(context)) {
433*ae771770SStanislav Sedov 	    krb5_set_error_message(context, EPERM,
434*ae771770SStanislav Sedov 				   "Access to home directory not allowed");
435*ae771770SStanislav Sedov 	    return EPERM;
436*ae771770SStanislav Sedov 	}
437*ae771770SStanislav Sedov 
438*ae771770SStanislav Sedov 	if(!issuid())
439*ae771770SStanislav Sedov 	    home = getenv("HOME");
440*ae771770SStanislav Sedov 
441*ae771770SStanislav Sedov 	if (home == NULL) {
442*ae771770SStanislav Sedov 	    struct passwd *pw = getpwuid(getuid());
443*ae771770SStanislav Sedov 	    if(pw != NULL)
444*ae771770SStanislav Sedov 		home = pw->pw_dir;
445*ae771770SStanislav Sedov 	}
446*ae771770SStanislav Sedov 	if (home) {
447*ae771770SStanislav Sedov 	    asprintf(&newfname, "%s%s", home, &fname[1]);
448*ae771770SStanislav Sedov 	    if (newfname == NULL) {
449*ae771770SStanislav Sedov 		krb5_set_error_message(context, ENOMEM,
450*ae771770SStanislav Sedov 				       N_("malloc: out of memory", ""));
451*ae771770SStanislav Sedov 		return ENOMEM;
452*ae771770SStanislav Sedov 	    }
453*ae771770SStanislav Sedov 	    fname = newfname;
454*ae771770SStanislav Sedov 	}
455*ae771770SStanislav Sedov #else  /* KRB5_USE_PATH_TOKENS */
456*ae771770SStanislav Sedov 	if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 ||
457*ae771770SStanislav Sedov 	    newfname == NULL)
458*ae771770SStanislav Sedov 	{
459*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ENOMEM,
460*ae771770SStanislav Sedov 				   N_("malloc: out of memory", ""));
461*ae771770SStanislav Sedov 	    return ENOMEM;
462*ae771770SStanislav Sedov 	}
463*ae771770SStanislav Sedov 	fname = newfname;
464*ae771770SStanislav Sedov #endif
465*ae771770SStanislav Sedov     }
466*ae771770SStanislav Sedov 
467*ae771770SStanislav Sedov     if (is_plist_file(fname)) {
468*ae771770SStanislav Sedov #ifdef __APPLE__
469*ae771770SStanislav Sedov 	ret = parse_plist_config(context, fname, res);
470*ae771770SStanislav Sedov 	if (ret) {
471*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
472*ae771770SStanislav Sedov 				   "Failed to parse plist %s", fname);
473*ae771770SStanislav Sedov 	    if (newfname)
474*ae771770SStanislav Sedov 		free(newfname);
475*ae771770SStanislav Sedov 	    return ret;
476*ae771770SStanislav Sedov 	}
477*ae771770SStanislav Sedov #else
478*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOENT,
479*ae771770SStanislav Sedov 			       "no support for plist configuration files");
480*ae771770SStanislav Sedov 	return ENOENT;
481*ae771770SStanislav Sedov #endif
482*ae771770SStanislav Sedov     } else {
483*ae771770SStanislav Sedov #ifdef KRB5_USE_PATH_TOKENS
484*ae771770SStanislav Sedov 	char * exp_fname = NULL;
485*ae771770SStanislav Sedov 
486*ae771770SStanislav Sedov 	ret = _krb5_expand_path_tokens(context, fname, &exp_fname);
487*ae771770SStanislav Sedov 	if (ret) {
488*ae771770SStanislav Sedov 	    if (newfname)
489*ae771770SStanislav Sedov 		free(newfname);
490*ae771770SStanislav Sedov 	    return ret;
491*ae771770SStanislav Sedov 	}
492*ae771770SStanislav Sedov 
493*ae771770SStanislav Sedov 	if (newfname)
494*ae771770SStanislav Sedov 	    free(newfname);
495*ae771770SStanislav Sedov 	fname = newfname = exp_fname;
496*ae771770SStanislav Sedov #endif
497*ae771770SStanislav Sedov 
498c19800e8SDoug Rabson 	f.f = fopen(fname, "r");
499c19800e8SDoug Rabson 	f.s = NULL;
500c19800e8SDoug Rabson 	if(f.f == NULL) {
501c19800e8SDoug Rabson 	    ret = errno;
502*ae771770SStanislav Sedov 	    krb5_set_error_message (context, ret, "open %s: %s",
503*ae771770SStanislav Sedov 				    fname, strerror(ret));
504*ae771770SStanislav Sedov 	    if (newfname)
505*ae771770SStanislav Sedov 		free(newfname);
506c19800e8SDoug Rabson 	    return ret;
507c19800e8SDoug Rabson 	}
508b528cefcSMark Murray 
509c19800e8SDoug Rabson 	ret = krb5_config_parse_debug (&f, res, &lineno, &str);
510c19800e8SDoug Rabson 	fclose(f.f);
511adb0ddaeSAssar Westerlund 	if (ret) {
512*ae771770SStanislav Sedov 	    krb5_set_error_message (context, ret, "%s:%u: %s",
513*ae771770SStanislav Sedov 				    fname, lineno, str);
514*ae771770SStanislav Sedov 	    if (newfname)
515*ae771770SStanislav Sedov 		free(newfname);
516adb0ddaeSAssar Westerlund 	    return ret;
517adb0ddaeSAssar Westerlund 	}
518*ae771770SStanislav Sedov     }
519adb0ddaeSAssar Westerlund     return 0;
520b528cefcSMark Murray }
521b528cefcSMark Murray 
522*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_config_parse_file(krb5_context context,const char * fname,krb5_config_section ** res)5238373020dSJacques Vidrine krb5_config_parse_file (krb5_context context,
5248373020dSJacques Vidrine 			const char *fname,
5258373020dSJacques Vidrine 			krb5_config_section **res)
5268373020dSJacques Vidrine {
5278373020dSJacques Vidrine     *res = NULL;
5288373020dSJacques Vidrine     return krb5_config_parse_file_multi(context, fname, res);
5298373020dSJacques Vidrine }
5308373020dSJacques Vidrine 
531b528cefcSMark Murray static void
free_binding(krb5_context context,krb5_config_binding * b)532b528cefcSMark Murray free_binding (krb5_context context, krb5_config_binding *b)
533b528cefcSMark Murray {
534b528cefcSMark Murray     krb5_config_binding *next_b;
535b528cefcSMark Murray 
536b528cefcSMark Murray     while (b) {
537b528cefcSMark Murray 	free (b->name);
538b528cefcSMark Murray 	if (b->type == krb5_config_string)
539b528cefcSMark Murray 	    free (b->u.string);
540b528cefcSMark Murray 	else if (b->type == krb5_config_list)
541b528cefcSMark Murray 	    free_binding (context, b->u.list);
542b528cefcSMark Murray 	else
543b528cefcSMark Murray 	    krb5_abortx(context, "unknown binding type (%d) in free_binding",
544b528cefcSMark Murray 			b->type);
545b528cefcSMark Murray 	next_b = b->next;
546b528cefcSMark Murray 	free (b);
547b528cefcSMark Murray 	b = next_b;
548b528cefcSMark Murray     }
549b528cefcSMark Murray }
550b528cefcSMark Murray 
551*ae771770SStanislav Sedov /**
552*ae771770SStanislav Sedov  * Free configuration file section, the result of
553*ae771770SStanislav Sedov  * krb5_config_parse_file() and krb5_config_parse_file_multi().
554*ae771770SStanislav Sedov  *
555*ae771770SStanislav Sedov  * @param context A Kerberos 5 context
556*ae771770SStanislav Sedov  * @param s the configuration section to free
557*ae771770SStanislav Sedov  *
558*ae771770SStanislav Sedov  * @return returns 0 on successes, otherwise an error code, see
559*ae771770SStanislav Sedov  *          krb5_get_error_message()
560*ae771770SStanislav Sedov  *
561*ae771770SStanislav Sedov  * @ingroup krb5_support
562*ae771770SStanislav Sedov  */
563*ae771770SStanislav Sedov 
564*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_config_file_free(krb5_context context,krb5_config_section * s)565b528cefcSMark Murray krb5_config_file_free (krb5_context context, krb5_config_section *s)
566b528cefcSMark Murray {
567b528cefcSMark Murray     free_binding (context, s);
568b528cefcSMark Murray     return 0;
569b528cefcSMark Murray }
570b528cefcSMark Murray 
571*ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
572*ae771770SStanislav Sedov 
573*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_krb5_config_copy(krb5_context context,krb5_config_section * c,krb5_config_section ** head)574*ae771770SStanislav Sedov _krb5_config_copy(krb5_context context,
575*ae771770SStanislav Sedov 		  krb5_config_section *c,
576*ae771770SStanislav Sedov 		  krb5_config_section **head)
577*ae771770SStanislav Sedov {
578*ae771770SStanislav Sedov     krb5_config_binding *d, *previous = NULL;
579*ae771770SStanislav Sedov 
580*ae771770SStanislav Sedov     *head = NULL;
581*ae771770SStanislav Sedov 
582*ae771770SStanislav Sedov     while (c) {
583*ae771770SStanislav Sedov 	d = calloc(1, sizeof(*d));
584*ae771770SStanislav Sedov 
585*ae771770SStanislav Sedov 	if (*head == NULL)
586*ae771770SStanislav Sedov 	    *head = d;
587*ae771770SStanislav Sedov 
588*ae771770SStanislav Sedov 	d->name = strdup(c->name);
589*ae771770SStanislav Sedov 	d->type = c->type;
590*ae771770SStanislav Sedov 	if (d->type == krb5_config_string)
591*ae771770SStanislav Sedov 	    d->u.string = strdup(c->u.string);
592*ae771770SStanislav Sedov 	else if (d->type == krb5_config_list)
593*ae771770SStanislav Sedov 	    _krb5_config_copy (context, c->u.list, &d->u.list);
594*ae771770SStanislav Sedov 	else
595*ae771770SStanislav Sedov 	    krb5_abortx(context,
596*ae771770SStanislav Sedov 			"unknown binding type (%d) in krb5_config_copy",
597*ae771770SStanislav Sedov 			d->type);
598*ae771770SStanislav Sedov 	if (previous)
599*ae771770SStanislav Sedov 	    previous->next = d;
600*ae771770SStanislav Sedov 
601*ae771770SStanislav Sedov 	previous = d;
602*ae771770SStanislav Sedov 	c = c->next;
603*ae771770SStanislav Sedov     }
604*ae771770SStanislav Sedov     return 0;
605*ae771770SStanislav Sedov }
606*ae771770SStanislav Sedov 
607*ae771770SStanislav Sedov #endif /* HEIMDAL_SMALLER */
608*ae771770SStanislav Sedov 
609*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL
_krb5_config_get_next(krb5_context context,const krb5_config_section * c,const krb5_config_binding ** pointer,int type,...)610*ae771770SStanislav Sedov _krb5_config_get_next (krb5_context context,
6118373020dSJacques Vidrine 		       const krb5_config_section *c,
6128373020dSJacques Vidrine 		       const krb5_config_binding **pointer,
613b528cefcSMark Murray 		       int type,
614b528cefcSMark Murray 		       ...)
615b528cefcSMark Murray {
616b528cefcSMark Murray     const char *ret;
617b528cefcSMark Murray     va_list args;
618b528cefcSMark Murray 
619b528cefcSMark Murray     va_start(args, type);
620*ae771770SStanislav Sedov     ret = _krb5_config_vget_next (context, c, pointer, type, args);
621b528cefcSMark Murray     va_end(args);
622b528cefcSMark Murray     return ret;
623b528cefcSMark Murray }
624b528cefcSMark Murray 
6258373020dSJacques Vidrine static const void *
vget_next(krb5_context context,const krb5_config_binding * b,const krb5_config_binding ** pointer,int type,const char * name,va_list args)6268373020dSJacques Vidrine vget_next(krb5_context context,
6278373020dSJacques Vidrine 	  const krb5_config_binding *b,
6288373020dSJacques Vidrine 	  const krb5_config_binding **pointer,
6298373020dSJacques Vidrine 	  int type,
6308373020dSJacques Vidrine 	  const char *name,
6318373020dSJacques Vidrine 	  va_list args)
6328373020dSJacques Vidrine {
6338373020dSJacques Vidrine     const char *p = va_arg(args, const char *);
6348373020dSJacques Vidrine     while(b != NULL) {
6350cadf2f4SJacques Vidrine 	if(strcmp(b->name, name) == 0) {
636*ae771770SStanislav Sedov 	    if(b->type == (unsigned)type && p == NULL) {
6378373020dSJacques Vidrine 		*pointer = b;
6388373020dSJacques Vidrine 		return b->u.generic;
6398373020dSJacques Vidrine 	    } else if(b->type == krb5_config_list && p != NULL) {
6408373020dSJacques Vidrine 		return vget_next(context, b->u.list, pointer, type, p, args);
6418373020dSJacques Vidrine 	    }
6428373020dSJacques Vidrine 	}
6438373020dSJacques Vidrine 	b = b->next;
6448373020dSJacques Vidrine     }
6458373020dSJacques Vidrine     return NULL;
6468373020dSJacques Vidrine }
6478373020dSJacques Vidrine 
648*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL
_krb5_config_vget_next(krb5_context context,const krb5_config_section * c,const krb5_config_binding ** pointer,int type,va_list args)649*ae771770SStanislav Sedov _krb5_config_vget_next (krb5_context context,
6508373020dSJacques Vidrine 			const krb5_config_section *c,
6518373020dSJacques Vidrine 			const krb5_config_binding **pointer,
652b528cefcSMark Murray 			int type,
653b528cefcSMark Murray 			va_list args)
654b528cefcSMark Murray {
6558373020dSJacques Vidrine     const krb5_config_binding *b;
656b528cefcSMark Murray     const char *p;
657b528cefcSMark Murray 
658b528cefcSMark Murray     if(c == NULL)
659b528cefcSMark Murray 	c = context->cf;
660b528cefcSMark Murray 
661b528cefcSMark Murray     if (c == NULL)
662b528cefcSMark Murray 	return NULL;
663b528cefcSMark Murray 
664b528cefcSMark Murray     if (*pointer == NULL) {
6658373020dSJacques Vidrine 	/* first time here, walk down the tree looking for the right
6668373020dSJacques Vidrine            section */
667b528cefcSMark Murray 	p = va_arg(args, const char *);
668b528cefcSMark Murray 	if (p == NULL)
669b528cefcSMark Murray 	    return NULL;
6708373020dSJacques Vidrine 	return vget_next(context, c, pointer, type, p, args);
671b528cefcSMark Murray     }
672b528cefcSMark Murray 
6738373020dSJacques Vidrine     /* we were called again, so just look for more entries with the
6748373020dSJacques Vidrine        same name and type */
6758373020dSJacques Vidrine     for (b = (*pointer)->next; b != NULL; b = b->next) {
676*ae771770SStanislav Sedov 	if(strcmp(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) {
677b528cefcSMark Murray 	    *pointer = b;
678b528cefcSMark Murray 	    return b->u.generic;
679b528cefcSMark Murray 	}
680b528cefcSMark Murray     }
681b528cefcSMark Murray     return NULL;
682b528cefcSMark Murray }
683b528cefcSMark Murray 
684*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL
_krb5_config_get(krb5_context context,const krb5_config_section * c,int type,...)685*ae771770SStanislav Sedov _krb5_config_get (krb5_context context,
6868373020dSJacques Vidrine 		  const krb5_config_section *c,
687b528cefcSMark Murray 		  int type,
688b528cefcSMark Murray 		  ...)
689b528cefcSMark Murray {
690b528cefcSMark Murray     const void *ret;
691b528cefcSMark Murray     va_list args;
692b528cefcSMark Murray 
693b528cefcSMark Murray     va_start(args, type);
694*ae771770SStanislav Sedov     ret = _krb5_config_vget (context, c, type, args);
695b528cefcSMark Murray     va_end(args);
696b528cefcSMark Murray     return ret;
697b528cefcSMark Murray }
698b528cefcSMark Murray 
699*ae771770SStanislav Sedov 
700b528cefcSMark Murray const void *
_krb5_config_vget(krb5_context context,const krb5_config_section * c,int type,va_list args)701*ae771770SStanislav Sedov _krb5_config_vget (krb5_context context,
7028373020dSJacques Vidrine 		   const krb5_config_section *c,
703b528cefcSMark Murray 		   int type,
704b528cefcSMark Murray 		   va_list args)
705b528cefcSMark Murray {
7068373020dSJacques Vidrine     const krb5_config_binding *foo = NULL;
707b528cefcSMark Murray 
708*ae771770SStanislav Sedov     return _krb5_config_vget_next (context, c, &foo, type, args);
709b528cefcSMark Murray }
710b528cefcSMark Murray 
711*ae771770SStanislav Sedov /**
712*ae771770SStanislav Sedov  * Get a list of configuration binding list for more processing
713*ae771770SStanislav Sedov  *
714*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
715*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
716*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
717*ae771770SStanislav Sedov  *
718*ae771770SStanislav Sedov  * @return NULL if configuration list is not found, a list otherwise
719*ae771770SStanislav Sedov  *
720*ae771770SStanislav Sedov  * @ingroup krb5_support
721*ae771770SStanislav Sedov  */
722*ae771770SStanislav Sedov 
723*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL
krb5_config_get_list(krb5_context context,const krb5_config_section * c,...)724b528cefcSMark Murray krb5_config_get_list (krb5_context context,
7258373020dSJacques Vidrine 		      const krb5_config_section *c,
726b528cefcSMark Murray 		      ...)
727b528cefcSMark Murray {
728b528cefcSMark Murray     const krb5_config_binding *ret;
729b528cefcSMark Murray     va_list args;
730b528cefcSMark Murray 
731b528cefcSMark Murray     va_start(args, c);
732b528cefcSMark Murray     ret = krb5_config_vget_list (context, c, args);
733b528cefcSMark Murray     va_end(args);
734b528cefcSMark Murray     return ret;
735b528cefcSMark Murray }
736b528cefcSMark Murray 
737*ae771770SStanislav Sedov /**
738*ae771770SStanislav Sedov  * Get a list of configuration binding list for more processing
739*ae771770SStanislav Sedov  *
740*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
741*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
742*ae771770SStanislav Sedov  * @param args a va_list of arguments
743*ae771770SStanislav Sedov  *
744*ae771770SStanislav Sedov  * @return NULL if configuration list is not found, a list otherwise
745*ae771770SStanislav Sedov  *
746*ae771770SStanislav Sedov  * @ingroup krb5_support
747*ae771770SStanislav Sedov  */
748*ae771770SStanislav Sedov 
749*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL
krb5_config_vget_list(krb5_context context,const krb5_config_section * c,va_list args)750b528cefcSMark Murray krb5_config_vget_list (krb5_context context,
7518373020dSJacques Vidrine 		       const krb5_config_section *c,
752b528cefcSMark Murray 		       va_list args)
753b528cefcSMark Murray {
754*ae771770SStanislav Sedov     return _krb5_config_vget (context, c, krb5_config_list, args);
755b528cefcSMark Murray }
756b528cefcSMark Murray 
757*ae771770SStanislav Sedov /**
758*ae771770SStanislav Sedov  * Returns a "const char *" to a string in the configuration database.
759*ae771770SStanislav Sedov  * The string may not be valid after a reload of the configuration
760*ae771770SStanislav Sedov  * database so a caller should make a local copy if it needs to keep
761*ae771770SStanislav Sedov  * the string.
762*ae771770SStanislav Sedov  *
763*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
764*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
765*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
766*ae771770SStanislav Sedov  *
767*ae771770SStanislav Sedov  * @return NULL if configuration string not found, a string otherwise
768*ae771770SStanislav Sedov  *
769*ae771770SStanislav Sedov  * @ingroup krb5_support
770*ae771770SStanislav Sedov  */
771*ae771770SStanislav Sedov 
772*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
krb5_config_get_string(krb5_context context,const krb5_config_section * c,...)773b528cefcSMark Murray krb5_config_get_string (krb5_context context,
7748373020dSJacques Vidrine 			const krb5_config_section *c,
775b528cefcSMark Murray 			...)
776b528cefcSMark Murray {
777b528cefcSMark Murray     const char *ret;
778b528cefcSMark Murray     va_list args;
779b528cefcSMark Murray 
780b528cefcSMark Murray     va_start(args, c);
781b528cefcSMark Murray     ret = krb5_config_vget_string (context, c, args);
782b528cefcSMark Murray     va_end(args);
783b528cefcSMark Murray     return ret;
784b528cefcSMark Murray }
785b528cefcSMark Murray 
786*ae771770SStanislav Sedov /**
787*ae771770SStanislav Sedov  * Like krb5_config_get_string(), but uses a va_list instead of ...
788*ae771770SStanislav Sedov  *
789*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
790*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
791*ae771770SStanislav Sedov  * @param args a va_list of arguments
792*ae771770SStanislav Sedov  *
793*ae771770SStanislav Sedov  * @return NULL if configuration string not found, a string otherwise
794*ae771770SStanislav Sedov  *
795*ae771770SStanislav Sedov  * @ingroup krb5_support
796*ae771770SStanislav Sedov  */
797*ae771770SStanislav Sedov 
798*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
krb5_config_vget_string(krb5_context context,const krb5_config_section * c,va_list args)799b528cefcSMark Murray krb5_config_vget_string (krb5_context context,
8008373020dSJacques Vidrine 			 const krb5_config_section *c,
801b528cefcSMark Murray 			 va_list args)
802b528cefcSMark Murray {
803*ae771770SStanislav Sedov     return _krb5_config_vget (context, c, krb5_config_string, args);
804b528cefcSMark Murray }
805b528cefcSMark Murray 
806*ae771770SStanislav Sedov /**
807*ae771770SStanislav Sedov  * Like krb5_config_vget_string(), but instead of returning NULL,
808*ae771770SStanislav Sedov  * instead return a default value.
809*ae771770SStanislav Sedov  *
810*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
811*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
812*ae771770SStanislav Sedov  * @param def_value the default value to return if no configuration
813*ae771770SStanislav Sedov  *        found in the database.
814*ae771770SStanislav Sedov  * @param args a va_list of arguments
815*ae771770SStanislav Sedov  *
816*ae771770SStanislav Sedov  * @return a configuration string
817*ae771770SStanislav Sedov  *
818*ae771770SStanislav Sedov  * @ingroup krb5_support
819*ae771770SStanislav Sedov  */
820*ae771770SStanislav Sedov 
821*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
krb5_config_vget_string_default(krb5_context context,const krb5_config_section * c,const char * def_value,va_list args)8225e9cd1aeSAssar Westerlund krb5_config_vget_string_default (krb5_context context,
8238373020dSJacques Vidrine 				 const krb5_config_section *c,
8245e9cd1aeSAssar Westerlund 				 const char *def_value,
8255e9cd1aeSAssar Westerlund 				 va_list args)
8265e9cd1aeSAssar Westerlund {
8275e9cd1aeSAssar Westerlund     const char *ret;
8285e9cd1aeSAssar Westerlund 
8295e9cd1aeSAssar Westerlund     ret = krb5_config_vget_string (context, c, args);
8305e9cd1aeSAssar Westerlund     if (ret == NULL)
8315e9cd1aeSAssar Westerlund 	ret = def_value;
8325e9cd1aeSAssar Westerlund     return ret;
8335e9cd1aeSAssar Westerlund }
8345e9cd1aeSAssar Westerlund 
835*ae771770SStanislav Sedov /**
836*ae771770SStanislav Sedov  * Like krb5_config_get_string(), but instead of returning NULL,
837*ae771770SStanislav Sedov  * instead return a default value.
838*ae771770SStanislav Sedov  *
839*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
840*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
841*ae771770SStanislav Sedov  * @param def_value the default value to return if no configuration
842*ae771770SStanislav Sedov  *        found in the database.
843*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
844*ae771770SStanislav Sedov  *
845*ae771770SStanislav Sedov  * @return a configuration string
846*ae771770SStanislav Sedov  *
847*ae771770SStanislav Sedov  * @ingroup krb5_support
848*ae771770SStanislav Sedov  */
849*ae771770SStanislav Sedov 
850*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
krb5_config_get_string_default(krb5_context context,const krb5_config_section * c,const char * def_value,...)8515e9cd1aeSAssar Westerlund krb5_config_get_string_default (krb5_context context,
8528373020dSJacques Vidrine 				const krb5_config_section *c,
8535e9cd1aeSAssar Westerlund 				const char *def_value,
8545e9cd1aeSAssar Westerlund 				...)
8555e9cd1aeSAssar Westerlund {
8565e9cd1aeSAssar Westerlund     const char *ret;
8575e9cd1aeSAssar Westerlund     va_list args;
8585e9cd1aeSAssar Westerlund 
8595e9cd1aeSAssar Westerlund     va_start(args, def_value);
8605e9cd1aeSAssar Westerlund     ret = krb5_config_vget_string_default (context, c, def_value, args);
8615e9cd1aeSAssar Westerlund     va_end(args);
8625e9cd1aeSAssar Westerlund     return ret;
8635e9cd1aeSAssar Westerlund }
8645e9cd1aeSAssar Westerlund 
865*ae771770SStanislav Sedov static char *
next_component_string(char * begin,const char * delims,char ** state)866*ae771770SStanislav Sedov next_component_string(char * begin, const char * delims, char **state)
867*ae771770SStanislav Sedov {
868*ae771770SStanislav Sedov     char * end;
869*ae771770SStanislav Sedov 
870*ae771770SStanislav Sedov     if (begin == NULL)
871*ae771770SStanislav Sedov         begin = *state;
872*ae771770SStanislav Sedov 
873*ae771770SStanislav Sedov     if (*begin == '\0')
874*ae771770SStanislav Sedov         return NULL;
875*ae771770SStanislav Sedov 
876*ae771770SStanislav Sedov     end = begin;
877*ae771770SStanislav Sedov     while (*end == '"') {
878*ae771770SStanislav Sedov         char * t = strchr(end + 1, '"');
879*ae771770SStanislav Sedov 
880*ae771770SStanislav Sedov         if (t)
881*ae771770SStanislav Sedov             end = ++t;
882*ae771770SStanislav Sedov         else
883*ae771770SStanislav Sedov             end += strlen(end);
884*ae771770SStanislav Sedov     }
885*ae771770SStanislav Sedov 
886*ae771770SStanislav Sedov     if (*end != '\0') {
887*ae771770SStanislav Sedov         size_t pos;
888*ae771770SStanislav Sedov 
889*ae771770SStanislav Sedov         pos = strcspn(end, delims);
890*ae771770SStanislav Sedov         end = end + pos;
891*ae771770SStanislav Sedov     }
892*ae771770SStanislav Sedov 
893*ae771770SStanislav Sedov     if (*end != '\0') {
894*ae771770SStanislav Sedov         *end = '\0';
895*ae771770SStanislav Sedov         *state = end + 1;
896*ae771770SStanislav Sedov         if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
897*ae771770SStanislav Sedov             begin++; *(end - 1) = '\0';
898*ae771770SStanislav Sedov         }
899*ae771770SStanislav Sedov         return begin;
900*ae771770SStanislav Sedov     }
901*ae771770SStanislav Sedov 
902*ae771770SStanislav Sedov     *state = end;
903*ae771770SStanislav Sedov     if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
904*ae771770SStanislav Sedov         begin++; *(end - 1) = '\0';
905*ae771770SStanislav Sedov     }
906*ae771770SStanislav Sedov     return begin;
907*ae771770SStanislav Sedov }
908*ae771770SStanislav Sedov 
909*ae771770SStanislav Sedov /**
910*ae771770SStanislav Sedov  * Get a list of configuration strings, free the result with
911*ae771770SStanislav Sedov  * krb5_config_free_strings().
912*ae771770SStanislav Sedov  *
913*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
914*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
915*ae771770SStanislav Sedov  * @param args a va_list of arguments
916*ae771770SStanislav Sedov  *
917*ae771770SStanislav Sedov  * @return TRUE or FALSE
918*ae771770SStanislav Sedov  *
919*ae771770SStanislav Sedov  * @ingroup krb5_support
920*ae771770SStanislav Sedov  */
921*ae771770SStanislav Sedov 
922*ae771770SStanislav Sedov KRB5_LIB_FUNCTION char ** KRB5_LIB_CALL
krb5_config_vget_strings(krb5_context context,const krb5_config_section * c,va_list args)923b528cefcSMark Murray krb5_config_vget_strings(krb5_context context,
9248373020dSJacques Vidrine 			 const krb5_config_section *c,
925b528cefcSMark Murray 			 va_list args)
926b528cefcSMark Murray {
927b528cefcSMark Murray     char **strings = NULL;
928b528cefcSMark Murray     int nstr = 0;
9298373020dSJacques Vidrine     const krb5_config_binding *b = NULL;
930b528cefcSMark Murray     const char *p;
931b528cefcSMark Murray 
932*ae771770SStanislav Sedov     while((p = _krb5_config_vget_next(context, c, &b,
933b528cefcSMark Murray 				      krb5_config_string, args))) {
934b528cefcSMark Murray 	char *tmp = strdup(p);
935b528cefcSMark Murray 	char *pos = NULL;
936b528cefcSMark Murray 	char *s;
937b528cefcSMark Murray 	if(tmp == NULL)
938b528cefcSMark Murray 	    goto cleanup;
939*ae771770SStanislav Sedov 	s = next_component_string(tmp, " \t", &pos);
940b528cefcSMark Murray 	while(s){
941c19800e8SDoug Rabson 	    char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
942c19800e8SDoug Rabson 	    if(tmp2 == NULL)
943b528cefcSMark Murray 		goto cleanup;
944c19800e8SDoug Rabson 	    strings = tmp2;
945b528cefcSMark Murray 	    strings[nstr] = strdup(s);
946b528cefcSMark Murray 	    nstr++;
947b528cefcSMark Murray 	    if(strings[nstr-1] == NULL)
948b528cefcSMark Murray 		goto cleanup;
949*ae771770SStanislav Sedov 	    s = next_component_string(NULL, " \t", &pos);
950b528cefcSMark Murray 	}
951b528cefcSMark Murray 	free(tmp);
952b528cefcSMark Murray     }
953b528cefcSMark Murray     if(nstr){
954b528cefcSMark Murray 	char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
955c19800e8SDoug Rabson 	if(tmp == NULL)
956b528cefcSMark Murray 	    goto cleanup;
957b528cefcSMark Murray 	strings = tmp;
958b528cefcSMark Murray 	strings[nstr] = NULL;
959b528cefcSMark Murray     }
960b528cefcSMark Murray     return strings;
961b528cefcSMark Murray cleanup:
962b528cefcSMark Murray     while(nstr--)
963b528cefcSMark Murray 	free(strings[nstr]);
964b528cefcSMark Murray     free(strings);
965b528cefcSMark Murray     return NULL;
966b528cefcSMark Murray 
967b528cefcSMark Murray }
968b528cefcSMark Murray 
969*ae771770SStanislav Sedov /**
970*ae771770SStanislav Sedov  * Get a list of configuration strings, free the result with
971*ae771770SStanislav Sedov  * krb5_config_free_strings().
972*ae771770SStanislav Sedov  *
973*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
974*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
975*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
976*ae771770SStanislav Sedov  *
977*ae771770SStanislav Sedov  * @return TRUE or FALSE
978*ae771770SStanislav Sedov  *
979*ae771770SStanislav Sedov  * @ingroup krb5_support
980*ae771770SStanislav Sedov  */
981*ae771770SStanislav Sedov 
982*ae771770SStanislav Sedov KRB5_LIB_FUNCTION char** KRB5_LIB_CALL
krb5_config_get_strings(krb5_context context,const krb5_config_section * c,...)983b528cefcSMark Murray krb5_config_get_strings(krb5_context context,
9848373020dSJacques Vidrine 			const krb5_config_section *c,
985b528cefcSMark Murray 			...)
986b528cefcSMark Murray {
987b528cefcSMark Murray     va_list ap;
988b528cefcSMark Murray     char **ret;
989b528cefcSMark Murray     va_start(ap, c);
990b528cefcSMark Murray     ret = krb5_config_vget_strings(context, c, ap);
991b528cefcSMark Murray     va_end(ap);
992b528cefcSMark Murray     return ret;
993b528cefcSMark Murray }
994b528cefcSMark Murray 
995*ae771770SStanislav Sedov /**
996*ae771770SStanislav Sedov  * Free the resulting strings from krb5_config-get_strings() and
997*ae771770SStanislav Sedov  * krb5_config_vget_strings().
998*ae771770SStanislav Sedov  *
999*ae771770SStanislav Sedov  * @param strings strings to free
1000*ae771770SStanislav Sedov  *
1001*ae771770SStanislav Sedov  * @ingroup krb5_support
1002*ae771770SStanislav Sedov  */
1003*ae771770SStanislav Sedov 
1004*ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_config_free_strings(char ** strings)1005b528cefcSMark Murray krb5_config_free_strings(char **strings)
1006b528cefcSMark Murray {
1007b528cefcSMark Murray     char **s = strings;
1008b528cefcSMark Murray     while(s && *s){
1009b528cefcSMark Murray 	free(*s);
1010b528cefcSMark Murray 	s++;
1011b528cefcSMark Murray     }
1012b528cefcSMark Murray     free(strings);
1013b528cefcSMark Murray }
1014b528cefcSMark Murray 
1015*ae771770SStanislav Sedov /**
1016*ae771770SStanislav Sedov  * Like krb5_config_get_bool_default() but with a va_list list of
1017*ae771770SStanislav Sedov  * configuration selection.
1018*ae771770SStanislav Sedov  *
1019*ae771770SStanislav Sedov  * Configuration value to a boolean value, where yes/true and any
1020*ae771770SStanislav Sedov  * non-zero number means TRUE and other value is FALSE.
1021*ae771770SStanislav Sedov  *
1022*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1023*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1024*ae771770SStanislav Sedov  * @param def_value the default value to return if no configuration
1025*ae771770SStanislav Sedov  *        found in the database.
1026*ae771770SStanislav Sedov  * @param args a va_list of arguments
1027*ae771770SStanislav Sedov  *
1028*ae771770SStanislav Sedov  * @return TRUE or FALSE
1029*ae771770SStanislav Sedov  *
1030*ae771770SStanislav Sedov  * @ingroup krb5_support
1031*ae771770SStanislav Sedov  */
1032*ae771770SStanislav Sedov 
1033*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_config_vget_bool_default(krb5_context context,const krb5_config_section * c,krb5_boolean def_value,va_list args)1034b528cefcSMark Murray krb5_config_vget_bool_default (krb5_context context,
10358373020dSJacques Vidrine 			       const krb5_config_section *c,
1036b528cefcSMark Murray 			       krb5_boolean def_value,
1037b528cefcSMark Murray 			       va_list args)
1038b528cefcSMark Murray {
1039b528cefcSMark Murray     const char *str;
1040b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
1041b528cefcSMark Murray     if(str == NULL)
1042b528cefcSMark Murray 	return def_value;
1043b528cefcSMark Murray     if(strcasecmp(str, "yes") == 0 ||
1044b528cefcSMark Murray        strcasecmp(str, "true") == 0 ||
1045b528cefcSMark Murray        atoi(str)) return TRUE;
1046b528cefcSMark Murray     return FALSE;
1047b528cefcSMark Murray }
1048b528cefcSMark Murray 
1049*ae771770SStanislav Sedov /**
1050*ae771770SStanislav Sedov  * krb5_config_get_bool() will convert the configuration
1051*ae771770SStanislav Sedov  * option value to a boolean value, where yes/true and any non-zero
1052*ae771770SStanislav Sedov  * number means TRUE and other value is FALSE.
1053*ae771770SStanislav Sedov  *
1054*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1055*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1056*ae771770SStanislav Sedov  * @param args a va_list of arguments
1057*ae771770SStanislav Sedov  *
1058*ae771770SStanislav Sedov  * @return TRUE or FALSE
1059*ae771770SStanislav Sedov  *
1060*ae771770SStanislav Sedov  * @ingroup krb5_support
1061*ae771770SStanislav Sedov  */
1062*ae771770SStanislav Sedov 
1063*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_config_vget_bool(krb5_context context,const krb5_config_section * c,va_list args)1064b528cefcSMark Murray krb5_config_vget_bool  (krb5_context context,
10658373020dSJacques Vidrine 			const krb5_config_section *c,
1066b528cefcSMark Murray 			va_list args)
1067b528cefcSMark Murray {
1068b528cefcSMark Murray     return krb5_config_vget_bool_default (context, c, FALSE, args);
1069b528cefcSMark Murray }
1070b528cefcSMark Murray 
1071*ae771770SStanislav Sedov /**
1072*ae771770SStanislav Sedov  * krb5_config_get_bool_default() will convert the configuration
1073*ae771770SStanislav Sedov  * option value to a boolean value, where yes/true and any non-zero
1074*ae771770SStanislav Sedov  * number means TRUE and other value is FALSE.
1075*ae771770SStanislav Sedov  *
1076*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1077*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1078*ae771770SStanislav Sedov  * @param def_value the default value to return if no configuration
1079*ae771770SStanislav Sedov  *        found in the database.
1080*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
1081*ae771770SStanislav Sedov  *
1082*ae771770SStanislav Sedov  * @return TRUE or FALSE
1083*ae771770SStanislav Sedov  *
1084*ae771770SStanislav Sedov  * @ingroup krb5_support
1085*ae771770SStanislav Sedov  */
1086*ae771770SStanislav Sedov 
1087*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_config_get_bool_default(krb5_context context,const krb5_config_section * c,krb5_boolean def_value,...)1088b528cefcSMark Murray krb5_config_get_bool_default (krb5_context context,
10898373020dSJacques Vidrine 			      const krb5_config_section *c,
1090b528cefcSMark Murray 			      krb5_boolean def_value,
1091b528cefcSMark Murray 			      ...)
1092b528cefcSMark Murray {
1093b528cefcSMark Murray     va_list ap;
1094b528cefcSMark Murray     krb5_boolean ret;
1095b528cefcSMark Murray     va_start(ap, def_value);
1096b528cefcSMark Murray     ret = krb5_config_vget_bool_default(context, c, def_value, ap);
1097b528cefcSMark Murray     va_end(ap);
1098b528cefcSMark Murray     return ret;
1099b528cefcSMark Murray }
1100b528cefcSMark Murray 
1101*ae771770SStanislav Sedov /**
1102*ae771770SStanislav Sedov  * Like krb5_config_get_bool() but with a va_list list of
1103*ae771770SStanislav Sedov  * configuration selection.
1104*ae771770SStanislav Sedov  *
1105*ae771770SStanislav Sedov  * Configuration value to a boolean value, where yes/true and any
1106*ae771770SStanislav Sedov  * non-zero number means TRUE and other value is FALSE.
1107*ae771770SStanislav Sedov  *
1108*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1109*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1110*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
1111*ae771770SStanislav Sedov  *
1112*ae771770SStanislav Sedov  * @return TRUE or FALSE
1113*ae771770SStanislav Sedov  *
1114*ae771770SStanislav Sedov  * @ingroup krb5_support
1115*ae771770SStanislav Sedov  */
1116*ae771770SStanislav Sedov 
1117*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_config_get_bool(krb5_context context,const krb5_config_section * c,...)1118b528cefcSMark Murray krb5_config_get_bool (krb5_context context,
11198373020dSJacques Vidrine 		      const krb5_config_section *c,
1120b528cefcSMark Murray 		      ...)
1121b528cefcSMark Murray {
1122b528cefcSMark Murray     va_list ap;
1123b528cefcSMark Murray     krb5_boolean ret;
1124b528cefcSMark Murray     va_start(ap, c);
1125b528cefcSMark Murray     ret = krb5_config_vget_bool (context, c, ap);
1126b528cefcSMark Murray     va_end(ap);
1127b528cefcSMark Murray     return ret;
1128b528cefcSMark Murray }
1129b528cefcSMark Murray 
1130*ae771770SStanislav Sedov /**
1131*ae771770SStanislav Sedov  * Get the time from the configuration file using a relative time.
1132*ae771770SStanislav Sedov  *
1133*ae771770SStanislav Sedov  * Like krb5_config_get_time_default() but with a va_list list of
1134*ae771770SStanislav Sedov  * configuration selection.
1135*ae771770SStanislav Sedov  *
1136*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1137*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1138*ae771770SStanislav Sedov  * @param def_value the default value to return if no configuration
1139*ae771770SStanislav Sedov  *        found in the database.
1140*ae771770SStanislav Sedov  * @param args a va_list of arguments
1141*ae771770SStanislav Sedov  *
1142*ae771770SStanislav Sedov  * @return parsed the time (or def_value on parse error)
1143*ae771770SStanislav Sedov  *
1144*ae771770SStanislav Sedov  * @ingroup krb5_support
1145*ae771770SStanislav Sedov  */
1146*ae771770SStanislav Sedov 
1147*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_vget_time_default(krb5_context context,const krb5_config_section * c,int def_value,va_list args)1148b528cefcSMark Murray krb5_config_vget_time_default (krb5_context context,
11498373020dSJacques Vidrine 			       const krb5_config_section *c,
1150b528cefcSMark Murray 			       int def_value,
1151b528cefcSMark Murray 			       va_list args)
1152b528cefcSMark Murray {
1153b528cefcSMark Murray     const char *str;
1154c19800e8SDoug Rabson     krb5_deltat t;
1155c19800e8SDoug Rabson 
1156b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
1157b528cefcSMark Murray     if(str == NULL)
1158b528cefcSMark Murray 	return def_value;
1159c19800e8SDoug Rabson     if (krb5_string_to_deltat(str, &t))
1160c19800e8SDoug Rabson 	return def_value;
1161c19800e8SDoug Rabson     return t;
1162b528cefcSMark Murray }
1163b528cefcSMark Murray 
1164*ae771770SStanislav Sedov /**
1165*ae771770SStanislav Sedov  * Get the time from the configuration file using a relative time, for example: 1h30s
1166*ae771770SStanislav Sedov  *
1167*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1168*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1169*ae771770SStanislav Sedov  * @param args a va_list of arguments
1170*ae771770SStanislav Sedov  *
1171*ae771770SStanislav Sedov  * @return parsed the time or -1 on error
1172*ae771770SStanislav Sedov  *
1173*ae771770SStanislav Sedov  * @ingroup krb5_support
1174*ae771770SStanislav Sedov  */
1175*ae771770SStanislav Sedov 
1176*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_vget_time(krb5_context context,const krb5_config_section * c,va_list args)1177b528cefcSMark Murray krb5_config_vget_time  (krb5_context context,
11788373020dSJacques Vidrine 			const krb5_config_section *c,
1179b528cefcSMark Murray 			va_list args)
1180b528cefcSMark Murray {
1181b528cefcSMark Murray     return krb5_config_vget_time_default (context, c, -1, args);
1182b528cefcSMark Murray }
1183b528cefcSMark Murray 
1184*ae771770SStanislav Sedov /**
1185*ae771770SStanislav Sedov  * Get the time from the configuration file using a relative time, for example: 1h30s
1186*ae771770SStanislav Sedov  *
1187*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1188*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1189*ae771770SStanislav Sedov  * @param def_value the default value to return if no configuration
1190*ae771770SStanislav Sedov  *        found in the database.
1191*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
1192*ae771770SStanislav Sedov  *
1193*ae771770SStanislav Sedov  * @return parsed the time (or def_value on parse error)
1194*ae771770SStanislav Sedov  *
1195*ae771770SStanislav Sedov  * @ingroup krb5_support
1196*ae771770SStanislav Sedov  */
1197*ae771770SStanislav Sedov 
1198*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_get_time_default(krb5_context context,const krb5_config_section * c,int def_value,...)1199b528cefcSMark Murray krb5_config_get_time_default (krb5_context context,
12008373020dSJacques Vidrine 			      const krb5_config_section *c,
1201b528cefcSMark Murray 			      int def_value,
1202b528cefcSMark Murray 			      ...)
1203b528cefcSMark Murray {
1204b528cefcSMark Murray     va_list ap;
1205b528cefcSMark Murray     int ret;
1206b528cefcSMark Murray     va_start(ap, def_value);
1207b528cefcSMark Murray     ret = krb5_config_vget_time_default(context, c, def_value, ap);
1208b528cefcSMark Murray     va_end(ap);
1209b528cefcSMark Murray     return ret;
1210b528cefcSMark Murray }
1211b528cefcSMark Murray 
1212*ae771770SStanislav Sedov /**
1213*ae771770SStanislav Sedov  * Get the time from the configuration file using a relative time, for example: 1h30s
1214*ae771770SStanislav Sedov  *
1215*ae771770SStanislav Sedov  * @param context A Kerberos 5 context.
1216*ae771770SStanislav Sedov  * @param c a configuration section, or NULL to use the section from context
1217*ae771770SStanislav Sedov  * @param ... a list of names, terminated with NULL.
1218*ae771770SStanislav Sedov  *
1219*ae771770SStanislav Sedov  * @return parsed the time or -1 on error
1220*ae771770SStanislav Sedov  *
1221*ae771770SStanislav Sedov  * @ingroup krb5_support
1222*ae771770SStanislav Sedov  */
1223*ae771770SStanislav Sedov 
1224*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_get_time(krb5_context context,const krb5_config_section * c,...)1225b528cefcSMark Murray krb5_config_get_time (krb5_context context,
12268373020dSJacques Vidrine 		      const krb5_config_section *c,
1227b528cefcSMark Murray 		      ...)
1228b528cefcSMark Murray {
1229b528cefcSMark Murray     va_list ap;
1230b528cefcSMark Murray     int ret;
1231b528cefcSMark Murray     va_start(ap, c);
1232b528cefcSMark Murray     ret = krb5_config_vget_time (context, c, ap);
1233b528cefcSMark Murray     va_end(ap);
1234b528cefcSMark Murray     return ret;
1235b528cefcSMark Murray }
1236b528cefcSMark Murray 
1237b528cefcSMark Murray 
1238*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_vget_int_default(krb5_context context,const krb5_config_section * c,int def_value,va_list args)1239b528cefcSMark Murray krb5_config_vget_int_default (krb5_context context,
12408373020dSJacques Vidrine 			      const krb5_config_section *c,
1241b528cefcSMark Murray 			      int def_value,
1242b528cefcSMark Murray 			      va_list args)
1243b528cefcSMark Murray {
1244b528cefcSMark Murray     const char *str;
1245b528cefcSMark Murray     str = krb5_config_vget_string (context, c, args);
1246b528cefcSMark Murray     if(str == NULL)
1247b528cefcSMark Murray 	return def_value;
1248b528cefcSMark Murray     else {
1249b528cefcSMark Murray 	char *endptr;
1250b528cefcSMark Murray 	long l;
1251b528cefcSMark Murray 	l = strtol(str, &endptr, 0);
1252b528cefcSMark Murray 	if (endptr == str)
1253b528cefcSMark Murray 	    return def_value;
1254b528cefcSMark Murray 	else
1255b528cefcSMark Murray 	    return l;
1256b528cefcSMark Murray     }
1257b528cefcSMark Murray }
1258b528cefcSMark Murray 
1259*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_vget_int(krb5_context context,const krb5_config_section * c,va_list args)1260b528cefcSMark Murray krb5_config_vget_int  (krb5_context context,
12618373020dSJacques Vidrine 		       const krb5_config_section *c,
1262b528cefcSMark Murray 		       va_list args)
1263b528cefcSMark Murray {
1264b528cefcSMark Murray     return krb5_config_vget_int_default (context, c, -1, args);
1265b528cefcSMark Murray }
1266b528cefcSMark Murray 
1267*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_get_int_default(krb5_context context,const krb5_config_section * c,int def_value,...)1268b528cefcSMark Murray krb5_config_get_int_default (krb5_context context,
12698373020dSJacques Vidrine 			     const krb5_config_section *c,
1270b528cefcSMark Murray 			     int def_value,
1271b528cefcSMark Murray 			     ...)
1272b528cefcSMark Murray {
1273b528cefcSMark Murray     va_list ap;
1274b528cefcSMark Murray     int ret;
1275b528cefcSMark Murray     va_start(ap, def_value);
1276b528cefcSMark Murray     ret = krb5_config_vget_int_default(context, c, def_value, ap);
1277b528cefcSMark Murray     va_end(ap);
1278b528cefcSMark Murray     return ret;
1279b528cefcSMark Murray }
1280b528cefcSMark Murray 
1281*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_config_get_int(krb5_context context,const krb5_config_section * c,...)1282b528cefcSMark Murray krb5_config_get_int (krb5_context context,
12838373020dSJacques Vidrine 		     const krb5_config_section *c,
1284b528cefcSMark Murray 		     ...)
1285b528cefcSMark Murray {
1286b528cefcSMark Murray     va_list ap;
1287b528cefcSMark Murray     int ret;
1288b528cefcSMark Murray     va_start(ap, c);
1289b528cefcSMark Murray     ret = krb5_config_vget_int (context, c, ap);
1290b528cefcSMark Murray     va_end(ap);
1291b528cefcSMark Murray     return ret;
1292b528cefcSMark Murray }
1293*ae771770SStanislav Sedov 
1294*ae771770SStanislav Sedov 
1295*ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
1296*ae771770SStanislav Sedov 
1297*ae771770SStanislav Sedov /**
1298*ae771770SStanislav Sedov  * Deprecated: configuration files are not strings
1299*ae771770SStanislav Sedov  *
1300*ae771770SStanislav Sedov  * @ingroup krb5_deprecated
1301*ae771770SStanislav Sedov  */
1302*ae771770SStanislav Sedov 
1303*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_config_parse_string_multi(krb5_context context,const char * string,krb5_config_section ** res)1304*ae771770SStanislav Sedov krb5_config_parse_string_multi(krb5_context context,
1305*ae771770SStanislav Sedov 			       const char *string,
1306*ae771770SStanislav Sedov 			       krb5_config_section **res)
1307*ae771770SStanislav Sedov     KRB5_DEPRECATED_FUNCTION("Use X instead")
1308*ae771770SStanislav Sedov {
1309*ae771770SStanislav Sedov     const char *str;
1310*ae771770SStanislav Sedov     unsigned lineno = 0;
1311*ae771770SStanislav Sedov     krb5_error_code ret;
1312*ae771770SStanislav Sedov     struct fileptr f;
1313*ae771770SStanislav Sedov     f.f = NULL;
1314*ae771770SStanislav Sedov     f.s = string;
1315*ae771770SStanislav Sedov 
1316*ae771770SStanislav Sedov     ret = krb5_config_parse_debug (&f, res, &lineno, &str);
1317*ae771770SStanislav Sedov     if (ret) {
1318*ae771770SStanislav Sedov 	krb5_set_error_message (context, ret, "%s:%u: %s",
1319*ae771770SStanislav Sedov 				"<constant>", lineno, str);
1320*ae771770SStanislav Sedov 	return ret;
1321*ae771770SStanislav Sedov     }
1322*ae771770SStanislav Sedov     return 0;
1323*ae771770SStanislav Sedov }
1324*ae771770SStanislav Sedov 
1325*ae771770SStanislav Sedov #endif
1326