2
* Copyright (c) 1997 - 2004 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
/* Gaah! I want a portable funopen */
46
config_fgets(char *str, size_t len, struct fileptr *ptr)
48
/* XXX this is not correct, in that they don't do the same if the
49
line is longer than len */
51
return fgets(str, len, ptr->f);
53
/* this is almost strsep_copy */
58
p = ptr->s + strcspn(ptr->s, "\n");
61
l = min(len, p - ptr->s);
63
memcpy(str, ptr->s, l);
71
static krb5_error_code parse_section(char *p, krb5_config_section **s,
72
krb5_config_section **res,
73
const char **error_message);
74
static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
75
krb5_config_binding **b,
76
krb5_config_binding **parent,
77
const char **error_message);
78
static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno,
79
krb5_config_binding **parent,
80
const char **error_message);
82
static krb5_config_section *
83
get_entry(krb5_config_section **parent, const char *name, int type)
85
krb5_config_section **q;
87
for(q = parent; *q != NULL; q = &(*q)->next)
88
if(type == krb5_config_list &&
90
strcmp(name, (*q)->name) == 0)
92
*q = calloc(1, sizeof(**q));
95
(*q)->name = strdup(name);
97
if((*q)->name == NULL) {
115
* starting at the line in `p', storing the resulting structure in
116
* `s' and hooking it into `parent'.
117
* Store the error message in `error_message'.
120
static krb5_error_code
121
parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
122
const char **error_message)
125
krb5_config_section *tmp;
127
p1 = strchr (p + 1, ']');
129
*error_message = "missing ]";
130
return KRB5_CONFIG_BADFORMAT;
133
tmp = get_entry(parent, p + 1, krb5_config_list);
135
*error_message = "out of memory";
136
return KRB5_CONFIG_BADFORMAT;
143
* Parse a brace-enclosed list from `f', hooking in the structure at
145
* Store the error message in `error_message'.
148
static krb5_error_code
149
parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent,
150
const char **error_message)
154
krb5_config_binding *b = NULL;
155
unsigned beg_lineno = *lineno;
157
while(config_fgets(buf, sizeof(buf), f) != NULL) {
161
buf[strcspn(buf, "\r\n")] = '\0';
163
while(isspace((unsigned char)*p))
165
if (*p == '#' || *p == ';' || *p == '\0')
167
while(isspace((unsigned char)*p))
173
ret = parse_binding (f, lineno, p, &b, parent, error_message);
177
*lineno = beg_lineno;
178
*error_message = "unclosed {";
179
return KRB5_CONFIG_BADFORMAT;
186
static krb5_error_code
187
parse_binding(struct fileptr *f, unsigned *lineno, char *p,
188
krb5_config_binding **b, krb5_config_binding **parent,
189
const char **error_message)
191
krb5_config_binding *tmp;
193
krb5_error_code ret = 0;
196
while (*p && *p != '=' && !isspace((unsigned char)*p))
199
*error_message = "missing =";
200
return KRB5_CONFIG_BADFORMAT;
203
while (isspace((unsigned char)*p))
206
*error_message = "missing =";
207
return KRB5_CONFIG_BADFORMAT;
210
while(isspace((unsigned char)*p))
214
tmp = get_entry(parent, p1, krb5_config_list);
216
*error_message = "out of memory";
217
return KRB5_CONFIG_BADFORMAT;
219
ret = parse_list (f, lineno, &tmp->u.list, error_message);
221
tmp = get_entry(parent, p1, krb5_config_string);
223
*error_message = "out of memory";
224
return KRB5_CONFIG_BADFORMAT;
228
while(p > p1 && isspace((unsigned char)*(p-1)))
231
tmp->u.string = strdup(p1);
238
* Parse the config file `fname', generating the structures into `res'
239
* returning error messages in `error_message'
242
static krb5_error_code
243
krb5_config_parse_debug (struct fileptr *f,
244
krb5_config_section **res,
246
const char **error_message)
248
krb5_config_section *s = NULL;
249
krb5_config_binding *b = NULL;
253
while (config_fgets(buf, sizeof(buf), f) != NULL) {
257
buf[strcspn(buf, "\r\n")] = '\0';
259
while(isspace((unsigned char)*p))
261
if (*p == '#' || *p == ';')
264
ret = parse_section(p, &s, res, error_message);
268
} else if (*p == '}') {
269
*error_message = "unmatched }";
270
return EINVAL; /* XXX */
271
} else if(*p != '\0') {
273
*error_message = "binding before section";
276
ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message);
284
krb5_error_code KRB5_LIB_FUNCTION
285
krb5_config_parse_string_multi(krb5_context context,
287
krb5_config_section **res)
296
ret = krb5_config_parse_debug (&f, res, &lineno, &str);
298
krb5_set_error_message (context, ret, "%s:%u: %s",
299
"<constant>", lineno, str);
305
krb5_error_code KRB5_LIB_FUNCTION
306
krb5_config_parse_file_multi (krb5_context context,
308
krb5_config_section **res)
314
f.f = fopen(fname, "r");
318
krb5_set_error_message (context, ret, "open %s: %s",
319
fname, strerror(ret));
323
ret = krb5_config_parse_debug (&f, res, &lineno, &str);
326
krb5_set_error_message (context, ret, "%s:%u: %s", fname, lineno, str);
332
krb5_error_code KRB5_LIB_FUNCTION
333
krb5_config_parse_file (krb5_context context,
335
krb5_config_section **res)
338
return krb5_config_parse_file_multi(context, fname, res);
341
#endif /* !HAVE_NETINFO */
344
free_binding (krb5_context context, krb5_config_binding *b)
346
krb5_config_binding *next_b;
350
if (b->type == krb5_config_string)
352
else if (b->type == krb5_config_list)
353
free_binding (context, b->u.list);
355
krb5_abortx(context, "unknown binding type (%d) in free_binding",
363
krb5_error_code KRB5_LIB_FUNCTION
364
krb5_config_file_free (krb5_context context, krb5_config_section *s)
366
free_binding (context, s);
371
_krb5_config_copy(krb5_context context,
372
krb5_config_section *c,
373
krb5_config_section **head)
375
krb5_config_binding *d, *previous = NULL;
380
d = calloc(1, sizeof(*d));
385
d->name = strdup(c->name);
387
if (d->type == krb5_config_string)
388
d->u.string = strdup(c->u.string);
389
else if (d->type == krb5_config_list)
390
_krb5_config_copy (context, c->u.list, &d->u.list);
393
"unknown binding type (%d) in krb5_config_copy",
407
krb5_config_get_next (krb5_context context,
408
const krb5_config_section *c,
409
const krb5_config_binding **pointer,
416
va_start(args, type);
417
ret = krb5_config_vget_next (context, c, pointer, type, args);
423
vget_next(krb5_context context,
424
const krb5_config_binding *b,
425
const krb5_config_binding **pointer,
430
const char *p = va_arg(args, const char *);
432
if(strcmp(b->name, name) == 0) {
433
if(b->type == type && p == NULL) {
436
} else if(b->type == krb5_config_list && p != NULL) {
437
return vget_next(context, b->u.list, pointer, type, p, args);
446
krb5_config_vget_next (krb5_context context,
447
const krb5_config_section *c,
448
const krb5_config_binding **pointer,
452
const krb5_config_binding *b;
461
if (*pointer == NULL) {
462
/* first time here, walk down the tree looking for the right
464
p = va_arg(args, const char *);
467
return vget_next(context, c, pointer, type, p, args);
470
/* we were called again, so just look for more entries with the
471
same name and type */
472
for (b = (*pointer)->next; b != NULL; b = b->next) {
473
if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) {
482
krb5_config_get (krb5_context context,
483
const krb5_config_section *c,
490
va_start(args, type);
491
ret = krb5_config_vget (context, c, type, args);
497
krb5_config_vget (krb5_context context,
498
const krb5_config_section *c,
502
const krb5_config_binding *foo = NULL;
504
return krb5_config_vget_next (context, c, &foo, type, args);
507
const krb5_config_binding *
508
krb5_config_get_list (krb5_context context,
509
const krb5_config_section *c,
512
const krb5_config_binding *ret;
516
ret = krb5_config_vget_list (context, c, args);
521
const krb5_config_binding *
522
krb5_config_vget_list (krb5_context context,
523
const krb5_config_section *c,
526
return krb5_config_vget (context, c, krb5_config_list, args);
529
const char* KRB5_LIB_FUNCTION
530
krb5_config_get_string (krb5_context context,
531
const krb5_config_section *c,
538
ret = krb5_config_vget_string (context, c, args);
543
const char* KRB5_LIB_FUNCTION
544
krb5_config_vget_string (krb5_context context,
545
const krb5_config_section *c,
548
return krb5_config_vget (context, c, krb5_config_string, args);
551
const char* KRB5_LIB_FUNCTION
552
krb5_config_vget_string_default (krb5_context context,
553
const krb5_config_section *c,
554
const char *def_value,
559
ret = krb5_config_vget_string (context, c, args);
565
const char* KRB5_LIB_FUNCTION
566
krb5_config_get_string_default (krb5_context context,
567
const krb5_config_section *c,
568
const char *def_value,
574
va_start(args, def_value);
575
ret = krb5_config_vget_string_default (context, c, def_value, args);
580
char ** KRB5_LIB_FUNCTION
581
krb5_config_vget_strings(krb5_context context,
582
const krb5_config_section *c,
585
char **strings = NULL;
587
const krb5_config_binding *b = NULL;
590
while((p = krb5_config_vget_next(context, c, &b,
591
krb5_config_string, args))) {
592
char *tmp = strdup(p);
597
s = strtok_r(tmp, " \t", &pos);
599
char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
603
strings[nstr] = strdup(s);
605
if(strings[nstr-1] == NULL)
607
s = strtok_r(NULL, " \t", &pos);
612
char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
616
strings[nstr] = NULL;
628
krb5_config_get_strings(krb5_context context,
629
const krb5_config_section *c,
635
ret = krb5_config_vget_strings(context, c, ap);
640
void KRB5_LIB_FUNCTION
641
krb5_config_free_strings(char **strings)
651
krb5_boolean KRB5_LIB_FUNCTION
652
krb5_config_vget_bool_default (krb5_context context,
653
const krb5_config_section *c,
654
krb5_boolean def_value,
658
str = krb5_config_vget_string (context, c, args);
661
if(strcasecmp(str, "yes") == 0 ||
662
strcasecmp(str, "true") == 0 ||
663
atoi(str)) return TRUE;
667
krb5_boolean KRB5_LIB_FUNCTION
668
krb5_config_vget_bool (krb5_context context,
669
const krb5_config_section *c,
672
return krb5_config_vget_bool_default (context, c, FALSE, args);
675
krb5_boolean KRB5_LIB_FUNCTION
676
krb5_config_get_bool_default (krb5_context context,
677
const krb5_config_section *c,
678
krb5_boolean def_value,
683
va_start(ap, def_value);
684
ret = krb5_config_vget_bool_default(context, c, def_value, ap);
689
krb5_boolean KRB5_LIB_FUNCTION
690
krb5_config_get_bool (krb5_context context,
691
const krb5_config_section *c,
697
ret = krb5_config_vget_bool (context, c, ap);
702
int KRB5_LIB_FUNCTION
703
krb5_config_vget_time_default (krb5_context context,
704
const krb5_config_section *c,
711
str = krb5_config_vget_string (context, c, args);
714
if (krb5_string_to_deltat(str, &t))
719
int KRB5_LIB_FUNCTION
720
krb5_config_vget_time (krb5_context context,
721
const krb5_config_section *c,
724
return krb5_config_vget_time_default (context, c, -1, args);
727
int KRB5_LIB_FUNCTION
728
krb5_config_get_time_default (krb5_context context,
729
const krb5_config_section *c,
735
va_start(ap, def_value);
736
ret = krb5_config_vget_time_default(context, c, def_value, ap);
741
int KRB5_LIB_FUNCTION
742
krb5_config_get_time (krb5_context context,
743
const krb5_config_section *c,
749
ret = krb5_config_vget_time (context, c, ap);
755
int KRB5_LIB_FUNCTION
756
krb5_config_vget_int_default (krb5_context context,
757
const krb5_config_section *c,
762
str = krb5_config_vget_string (context, c, args);
768
l = strtol(str, &endptr, 0);
776
int KRB5_LIB_FUNCTION
777
krb5_config_vget_int (krb5_context context,
778
const krb5_config_section *c,
781
return krb5_config_vget_int_default (context, c, -1, args);
784
int KRB5_LIB_FUNCTION
785
krb5_config_get_int_default (krb5_context context,
786
const krb5_config_section *c,
792
va_start(ap, def_value);
793
ret = krb5_config_vget_int_default(context, c, def_value, ap);
798
int KRB5_LIB_FUNCTION
799
krb5_config_get_int (krb5_context context,
800
const krb5_config_section *c,
806
ret = krb5_config_vget_int (context, c, ap);