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