2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
39 static krb5_error_code
parse_section(char *p
, krb5_config_section
**s
,
40 krb5_config_section
**res
,
41 const char **error_message
);
42 static krb5_error_code
parse_binding(FILE *f
, unsigned *lineno
, char *p
,
43 krb5_config_binding
**b
,
44 krb5_config_binding
**parent
,
45 const char **error_message
);
46 static krb5_error_code
parse_list(FILE *f
, unsigned *lineno
,
47 krb5_config_binding
**parent
,
48 const char **error_message
);
50 static krb5_config_section
*
51 get_entry(krb5_config_section
**parent
, const char *name
, int type
)
53 krb5_config_section
**q
;
55 for(q
= parent
; *q
!= NULL
; q
= &(*q
)->next
)
56 if(type
== krb5_config_list
&&
58 strcmp(name
, (*q
)->name
) == 0)
60 *q
= calloc(1, sizeof(**q
));
63 (*q
)->name
= strdup(name
);
65 if((*q
)->name
== NULL
) {
83 * starting at the line in `p', storing the resulting structure in
84 * `s' and hooking it into `parent'.
85 * Store the error message in `error_message'.
88 static krb5_error_code
89 parse_section(char *p
, krb5_config_section
**s
, krb5_config_section
**parent
,
90 const char **error_message
)
93 krb5_config_section
*tmp
;
95 p1
= strchr (p
+ 1, ']');
97 *error_message
= "missing ]";
98 return KRB5_CONFIG_BADFORMAT
;
101 tmp
= get_entry(parent
, p
+ 1, krb5_config_list
);
103 *error_message
= "out of memory";
104 return KRB5_CONFIG_BADFORMAT
;
111 * Parse a brace-enclosed list from `f', hooking in the structure at
113 * Store the error message in `error_message'.
116 static krb5_error_code
117 parse_list(FILE *f
, unsigned *lineno
, krb5_config_binding
**parent
,
118 const char **error_message
)
122 krb5_config_binding
*b
= NULL
;
123 unsigned beg_lineno
= *lineno
;
125 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
129 if (buf
[strlen(buf
) - 1] == '\n')
130 buf
[strlen(buf
) - 1] = '\0';
132 while(isspace((unsigned char)*p
))
134 if (*p
== '#' || *p
== ';' || *p
== '\0')
136 while(isspace((unsigned char)*p
))
142 ret
= parse_binding (f
, lineno
, p
, &b
, parent
, error_message
);
146 *lineno
= beg_lineno
;
147 *error_message
= "unclosed {";
148 return KRB5_CONFIG_BADFORMAT
;
155 static krb5_error_code
156 parse_binding(FILE *f
, unsigned *lineno
, char *p
,
157 krb5_config_binding
**b
, krb5_config_binding
**parent
,
158 const char **error_message
)
160 krb5_config_binding
*tmp
;
162 krb5_error_code ret
= 0;
165 while (*p
&& *p
!= '=' && !isspace((unsigned char)*p
))
168 *error_message
= "missing =";
169 return KRB5_CONFIG_BADFORMAT
;
172 while (isspace((unsigned char)*p
))
175 *error_message
= "missing =";
176 return KRB5_CONFIG_BADFORMAT
;
179 while(isspace((unsigned char)*p
))
183 tmp
= get_entry(parent
, p1
, krb5_config_list
);
185 *error_message
= "out of memory";
186 return KRB5_CONFIG_BADFORMAT
;
188 ret
= parse_list (f
, lineno
, &tmp
->u
.list
, error_message
);
190 tmp
= get_entry(parent
, p1
, krb5_config_string
);
192 *error_message
= "out of memory";
193 return KRB5_CONFIG_BADFORMAT
;
197 while(p
> p1
&& isspace((unsigned char)*(p
-1)))
200 tmp
->u
.string
= strdup(p1
);
207 * Parse the config file `fname', generating the structures into `res'
208 * returning error messages in `error_message'
211 static krb5_error_code
212 krb5_config_parse_file_debug (const char *fname
,
213 krb5_config_section
**res
,
215 const char **error_message
)
218 krb5_config_section
*s
;
219 krb5_config_binding
*b
;
221 krb5_error_code ret
= 0;
226 f
= fopen (fname
, "r");
228 *error_message
= "cannot open file";
231 while (fgets(buf
, sizeof(buf
), f
) != NULL
) {
235 if(buf
[strlen(buf
) - 1] == '\n')
236 buf
[strlen(buf
) - 1] = '\0';
238 while(isspace((unsigned char)*p
))
240 if (*p
== '#' || *p
== ';')
243 ret
= parse_section(p
, &s
, res
, error_message
);
248 } else if (*p
== '}') {
249 *error_message
= "unmatched }";
250 ret
= EINVAL
; /* XXX */
252 } else if(*p
!= '\0') {
254 *error_message
= "binding before section";
258 ret
= parse_binding(f
, lineno
, p
, &b
, &s
->u
.list
, error_message
);
269 krb5_config_parse_file_multi (krb5_context context
,
271 krb5_config_section
**res
)
277 ret
= krb5_config_parse_file_debug (fname
, res
, &lineno
, &str
);
279 krb5_set_error_string (context
, "%s:%u: %s", fname
, lineno
, str
);
286 krb5_config_parse_file (krb5_context context
,
288 krb5_config_section
**res
)
291 return krb5_config_parse_file_multi(context
, fname
, res
);
294 #endif /* !HAVE_NETINFO */
297 free_binding (krb5_context context
, krb5_config_binding
*b
)
299 krb5_config_binding
*next_b
;
303 if (b
->type
== krb5_config_string
)
305 else if (b
->type
== krb5_config_list
)
306 free_binding (context
, b
->u
.list
);
308 krb5_abortx(context
, "unknown binding type (%d) in free_binding",
317 krb5_config_file_free (krb5_context context
, krb5_config_section
*s
)
319 free_binding (context
, s
);
324 krb5_config_get_next (krb5_context context
,
325 const krb5_config_section
*c
,
326 const krb5_config_binding
**pointer
,
333 va_start(args
, type
);
334 ret
= krb5_config_vget_next (context
, c
, pointer
, type
, args
);
340 vget_next(krb5_context context
,
341 const krb5_config_binding
*b
,
342 const krb5_config_binding
**pointer
,
347 const char *p
= va_arg(args
, const char *);
349 if(strcmp(b
->name
, name
) == 0) {
350 if(b
->type
== type
&& p
== NULL
) {
353 } else if(b
->type
== krb5_config_list
&& p
!= NULL
) {
354 return vget_next(context
, b
->u
.list
, pointer
, type
, p
, args
);
363 krb5_config_vget_next (krb5_context context
,
364 const krb5_config_section
*c
,
365 const krb5_config_binding
**pointer
,
369 const krb5_config_binding
*b
;
378 if (*pointer
== NULL
) {
379 /* first time here, walk down the tree looking for the right
381 p
= va_arg(args
, const char *);
384 return vget_next(context
, c
, pointer
, type
, p
, args
);
387 /* we were called again, so just look for more entries with the
388 same name and type */
389 for (b
= (*pointer
)->next
; b
!= NULL
; b
= b
->next
) {
390 if(strcmp(b
->name
, (*pointer
)->name
) == 0 && b
->type
== type
) {
399 krb5_config_get (krb5_context context
,
400 const krb5_config_section
*c
,
407 va_start(args
, type
);
408 ret
= krb5_config_vget (context
, c
, type
, args
);
414 krb5_config_vget (krb5_context context
,
415 const krb5_config_section
*c
,
419 const krb5_config_binding
*foo
= NULL
;
421 return krb5_config_vget_next (context
, c
, &foo
, type
, args
);
424 const krb5_config_binding
*
425 krb5_config_get_list (krb5_context context
,
426 const krb5_config_section
*c
,
429 const krb5_config_binding
*ret
;
433 ret
= krb5_config_vget_list (context
, c
, args
);
438 const krb5_config_binding
*
439 krb5_config_vget_list (krb5_context context
,
440 const krb5_config_section
*c
,
443 return krb5_config_vget (context
, c
, krb5_config_list
, args
);
447 krb5_config_get_string (krb5_context context
,
448 const krb5_config_section
*c
,
455 ret
= krb5_config_vget_string (context
, c
, args
);
461 krb5_config_vget_string (krb5_context context
,
462 const krb5_config_section
*c
,
465 return krb5_config_vget (context
, c
, krb5_config_string
, args
);
469 krb5_config_vget_string_default (krb5_context context
,
470 const krb5_config_section
*c
,
471 const char *def_value
,
476 ret
= krb5_config_vget_string (context
, c
, args
);
483 krb5_config_get_string_default (krb5_context context
,
484 const krb5_config_section
*c
,
485 const char *def_value
,
491 va_start(args
, def_value
);
492 ret
= krb5_config_vget_string_default (context
, c
, def_value
, args
);
498 krb5_config_vget_strings(krb5_context context
,
499 const krb5_config_section
*c
,
502 char **strings
= NULL
;
504 const krb5_config_binding
*b
= NULL
;
507 while((p
= krb5_config_vget_next(context
, c
, &b
,
508 krb5_config_string
, args
))) {
509 char *tmp
= strdup(p
);
514 s
= strtok_r(tmp
, " \t", &pos
);
516 char **tmp
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
520 strings
[nstr
] = strdup(s
);
522 if(strings
[nstr
-1] == NULL
)
524 s
= strtok_r(NULL
, " \t", &pos
);
529 char **tmp
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
533 strings
[nstr
] = NULL
;
545 krb5_config_get_strings(krb5_context context
,
546 const krb5_config_section
*c
,
552 ret
= krb5_config_vget_strings(context
, c
, ap
);
558 krb5_config_free_strings(char **strings
)
569 krb5_config_vget_bool_default (krb5_context context
,
570 const krb5_config_section
*c
,
571 krb5_boolean def_value
,
575 str
= krb5_config_vget_string (context
, c
, args
);
578 if(strcasecmp(str
, "yes") == 0 ||
579 strcasecmp(str
, "true") == 0 ||
580 atoi(str
)) return TRUE
;
585 krb5_config_vget_bool (krb5_context context
,
586 const krb5_config_section
*c
,
589 return krb5_config_vget_bool_default (context
, c
, FALSE
, args
);
593 krb5_config_get_bool_default (krb5_context context
,
594 const krb5_config_section
*c
,
595 krb5_boolean def_value
,
600 va_start(ap
, def_value
);
601 ret
= krb5_config_vget_bool_default(context
, c
, def_value
, ap
);
607 krb5_config_get_bool (krb5_context context
,
608 const krb5_config_section
*c
,
614 ret
= krb5_config_vget_bool (context
, c
, ap
);
620 krb5_config_vget_time_default (krb5_context context
,
621 const krb5_config_section
*c
,
626 str
= krb5_config_vget_string (context
, c
, args
);
629 return parse_time (str
, NULL
);
633 krb5_config_vget_time (krb5_context context
,
634 const krb5_config_section
*c
,
637 return krb5_config_vget_time_default (context
, c
, -1, args
);
641 krb5_config_get_time_default (krb5_context context
,
642 const krb5_config_section
*c
,
648 va_start(ap
, def_value
);
649 ret
= krb5_config_vget_time_default(context
, c
, def_value
, ap
);
655 krb5_config_get_time (krb5_context context
,
656 const krb5_config_section
*c
,
662 ret
= krb5_config_vget_time (context
, c
, ap
);
669 krb5_config_vget_int_default (krb5_context context
,
670 const krb5_config_section
*c
,
675 str
= krb5_config_vget_string (context
, c
, args
);
681 l
= strtol(str
, &endptr
, 0);
690 krb5_config_vget_int (krb5_context context
,
691 const krb5_config_section
*c
,
694 return krb5_config_vget_int_default (context
, c
, -1, args
);
698 krb5_config_get_int_default (krb5_context context
,
699 const krb5_config_section
*c
,
705 va_start(ap
, def_value
);
706 ret
= krb5_config_vget_int_default(context
, c
, def_value
, ap
);
712 krb5_config_get_int (krb5_context context
,
713 const krb5_config_section
*c
,
719 ret
= krb5_config_vget_int (context
, c
, ap
);