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"
36 /* Gaah! I want a portable funopen */
43 config_fgets(char *str
, size_t len
, struct fileptr
*ptr
)
45 /* XXX this is not correct, in that they don't do the same if the
46 line is longer than len */
48 return fgets(str
, len
, ptr
->f
);
50 /* this is almost strsep_copy */
55 p
= ptr
->s
+ strcspn(ptr
->s
, "\n");
58 l
= min(len
, p
- ptr
->s
);
60 memcpy(str
, ptr
->s
, l
);
68 static krb5_error_code
parse_section(char *p
, krb5_config_section
**s
,
69 krb5_config_section
**res
,
70 const char **error_message
);
71 static krb5_error_code
parse_binding(struct fileptr
*f
, unsigned *lineno
, char *p
,
72 krb5_config_binding
**b
,
73 krb5_config_binding
**parent
,
74 const char **error_message
);
75 static krb5_error_code
parse_list(struct fileptr
*f
, unsigned *lineno
,
76 krb5_config_binding
**parent
,
77 const char **error_message
);
79 static krb5_config_section
*
80 get_entry(krb5_config_section
**parent
, const char *name
, int type
)
82 krb5_config_section
**q
;
84 for(q
= parent
; *q
!= NULL
; q
= &(*q
)->next
)
85 if(type
== krb5_config_list
&&
87 strcmp(name
, (*q
)->name
) == 0)
89 *q
= calloc(1, sizeof(**q
));
92 (*q
)->name
= strdup(name
);
94 if((*q
)->name
== NULL
) {
112 * starting at the line in `p', storing the resulting structure in
113 * `s' and hooking it into `parent'.
114 * Store the error message in `error_message'.
117 static krb5_error_code
118 parse_section(char *p
, krb5_config_section
**s
, krb5_config_section
**parent
,
119 const char **error_message
)
122 krb5_config_section
*tmp
;
124 p1
= strchr (p
+ 1, ']');
126 *error_message
= "missing ]";
127 return KRB5_CONFIG_BADFORMAT
;
130 tmp
= get_entry(parent
, p
+ 1, krb5_config_list
);
132 *error_message
= "out of memory";
133 return KRB5_CONFIG_BADFORMAT
;
140 * Parse a brace-enclosed list from `f', hooking in the structure at
142 * Store the error message in `error_message'.
145 static krb5_error_code
146 parse_list(struct fileptr
*f
, unsigned *lineno
, krb5_config_binding
**parent
,
147 const char **error_message
)
151 krb5_config_binding
*b
= NULL
;
152 unsigned beg_lineno
= *lineno
;
154 while(config_fgets(buf
, sizeof(buf
), f
) != NULL
) {
158 buf
[strcspn(buf
, "\r\n")] = '\0';
160 while(isspace((unsigned char)*p
))
162 if (*p
== '#' || *p
== ';' || *p
== '\0')
164 while(isspace((unsigned char)*p
))
170 ret
= parse_binding (f
, lineno
, p
, &b
, parent
, error_message
);
174 *lineno
= beg_lineno
;
175 *error_message
= "unclosed {";
176 return KRB5_CONFIG_BADFORMAT
;
183 static krb5_error_code
184 parse_binding(struct fileptr
*f
, unsigned *lineno
, char *p
,
185 krb5_config_binding
**b
, krb5_config_binding
**parent
,
186 const char **error_message
)
188 krb5_config_binding
*tmp
;
190 krb5_error_code ret
= 0;
193 while (*p
&& *p
!= '=' && !isspace((unsigned char)*p
))
196 *error_message
= "missing =";
197 return KRB5_CONFIG_BADFORMAT
;
200 while (isspace((unsigned char)*p
))
203 *error_message
= "missing =";
204 return KRB5_CONFIG_BADFORMAT
;
207 while(isspace((unsigned char)*p
))
211 tmp
= get_entry(parent
, p1
, krb5_config_list
);
213 *error_message
= "out of memory";
214 return KRB5_CONFIG_BADFORMAT
;
216 ret
= parse_list (f
, lineno
, &tmp
->u
.list
, error_message
);
218 tmp
= get_entry(parent
, p1
, krb5_config_string
);
220 *error_message
= "out of memory";
221 return KRB5_CONFIG_BADFORMAT
;
225 while(p
> p1
&& isspace((unsigned char)*(p
-1)))
228 tmp
->u
.string
= strdup(p1
);
235 * Parse the config file `fname', generating the structures into `res'
236 * returning error messages in `error_message'
239 static krb5_error_code
240 krb5_config_parse_debug (struct fileptr
*f
,
241 krb5_config_section
**res
,
243 const char **error_message
)
245 krb5_config_section
*s
= NULL
;
246 krb5_config_binding
*b
= NULL
;
250 while (config_fgets(buf
, sizeof(buf
), f
) != NULL
) {
254 buf
[strcspn(buf
, "\r\n")] = '\0';
256 while(isspace((unsigned char)*p
))
258 if (*p
== '#' || *p
== ';')
261 ret
= parse_section(p
, &s
, res
, error_message
);
265 } else if (*p
== '}') {
266 *error_message
= "unmatched }";
267 return EINVAL
; /* XXX */
268 } else if(*p
!= '\0') {
270 *error_message
= "binding before section";
273 ret
= parse_binding(f
, lineno
, p
, &b
, &s
->u
.list
, error_message
);
281 krb5_error_code KRB5_LIB_FUNCTION
282 krb5_config_parse_string_multi(krb5_context context
,
284 krb5_config_section
**res
)
293 ret
= krb5_config_parse_debug (&f
, res
, &lineno
, &str
);
295 krb5_set_error_message (context
, ret
, "%s:%u: %s",
296 "<constant>", lineno
, str
);
303 * Parse a configuration file and add the result into res. This
304 * interface can be used to parse several configuration files into one
305 * resulting krb5_config_section by calling it repeatably.
307 * @param context a Kerberos 5 context.
308 * @param fname a file name to a Kerberos configuration file
309 * @param res the returned result, must be free with krb5_free_config_files().
310 * @return Return an error code or 0, see krb5_get_error_message().
312 * @ingroup krb5_support
315 krb5_error_code KRB5_LIB_FUNCTION
316 krb5_config_parse_file_multi (krb5_context context
,
318 krb5_config_section
**res
)
321 char *newfname
= NULL
;
327 * If the fname starts with "~/" parse configuration file in the
328 * current users home directory. The behavior can be disabled and
329 * enabled by calling krb5_set_home_dir_access().
331 if (_krb5_homedir_access(context
) && fname
[0] == '~' && fname
[1] == '/') {
332 const char *home
= NULL
;
335 home
= getenv("HOME");
338 struct passwd
*pw
= getpwuid(getuid());
343 asprintf(&newfname
, "%s%s", home
, &fname
[1]);
344 if (newfname
== NULL
) {
345 krb5_set_error_message(context
, ENOMEM
,
346 N_("malloc: out of memory", ""));
353 f
.f
= fopen(fname
, "r");
357 krb5_set_error_message (context
, ret
, "open %s: %s",
358 fname
, strerror(ret
));
364 ret
= krb5_config_parse_debug (&f
, res
, &lineno
, &str
);
367 krb5_set_error_message (context
, ret
, "%s:%u: %s", fname
, lineno
, str
);
377 krb5_error_code KRB5_LIB_FUNCTION
378 krb5_config_parse_file (krb5_context context
,
380 krb5_config_section
**res
)
383 return krb5_config_parse_file_multi(context
, fname
, res
);
387 free_binding (krb5_context context
, krb5_config_binding
*b
)
389 krb5_config_binding
*next_b
;
393 if (b
->type
== krb5_config_string
)
395 else if (b
->type
== krb5_config_list
)
396 free_binding (context
, b
->u
.list
);
398 krb5_abortx(context
, "unknown binding type (%d) in free_binding",
407 * Free configuration file section, the result of
408 * krb5_config_parse_file() and krb5_config_parse_file_multi().
410 * @param context A Kerberos 5 context
411 * @param s the configuration section to free
413 * @return returns 0 on successes, otherwise an error code, see
414 * krb5_get_error_message()
416 * @ingroup krb5_support
419 krb5_error_code KRB5_LIB_FUNCTION
420 krb5_config_file_free (krb5_context context
, krb5_config_section
*s
)
422 free_binding (context
, s
);
426 #ifndef HEIMDAL_SMALLER
429 _krb5_config_copy(krb5_context context
,
430 krb5_config_section
*c
,
431 krb5_config_section
**head
)
433 krb5_config_binding
*d
, *previous
= NULL
;
438 d
= calloc(1, sizeof(*d
));
443 d
->name
= strdup(c
->name
);
445 if (d
->type
== krb5_config_string
)
446 d
->u
.string
= strdup(c
->u
.string
);
447 else if (d
->type
== krb5_config_list
)
448 _krb5_config_copy (context
, c
->u
.list
, &d
->u
.list
);
451 "unknown binding type (%d) in krb5_config_copy",
462 #endif /* HEIMDAL_SMALLER */
465 _krb5_config_get_next (krb5_context context
,
466 const krb5_config_section
*c
,
467 const krb5_config_binding
**pointer
,
474 va_start(args
, type
);
475 ret
= _krb5_config_vget_next (context
, c
, pointer
, type
, args
);
481 vget_next(krb5_context context
,
482 const krb5_config_binding
*b
,
483 const krb5_config_binding
**pointer
,
488 const char *p
= va_arg(args
, const char *);
490 if(strcmp(b
->name
, name
) == 0) {
491 if(b
->type
== type
&& p
== NULL
) {
494 } else if(b
->type
== krb5_config_list
&& p
!= NULL
) {
495 return vget_next(context
, b
->u
.list
, pointer
, type
, p
, args
);
504 _krb5_config_vget_next (krb5_context context
,
505 const krb5_config_section
*c
,
506 const krb5_config_binding
**pointer
,
510 const krb5_config_binding
*b
;
519 if (*pointer
== NULL
) {
520 /* first time here, walk down the tree looking for the right
522 p
= va_arg(args
, const char *);
525 return vget_next(context
, c
, pointer
, type
, p
, args
);
528 /* we were called again, so just look for more entries with the
529 same name and type */
530 for (b
= (*pointer
)->next
; b
!= NULL
; b
= b
->next
) {
531 if(strcmp(b
->name
, (*pointer
)->name
) == 0 && b
->type
== type
) {
540 _krb5_config_get (krb5_context context
,
541 const krb5_config_section
*c
,
548 va_start(args
, type
);
549 ret
= _krb5_config_vget (context
, c
, type
, args
);
555 _krb5_config_vget (krb5_context context
,
556 const krb5_config_section
*c
,
560 const krb5_config_binding
*foo
= NULL
;
562 return _krb5_config_vget_next (context
, c
, &foo
, type
, args
);
566 * Get a list of configuration binding list for more processing
568 * @param context A Kerberos 5 context.
569 * @param c a configuration section, or NULL to use the section from context
570 * @param ... a list of names, terminated with NULL.
572 * @return NULL if configuration list is not found, a list otherwise
574 * @ingroup krb5_support
577 const krb5_config_binding
*
578 krb5_config_get_list (krb5_context context
,
579 const krb5_config_section
*c
,
582 const krb5_config_binding
*ret
;
586 ret
= krb5_config_vget_list (context
, c
, args
);
592 * Get a list of configuration binding list for more processing
594 * @param context A Kerberos 5 context.
595 * @param c a configuration section, or NULL to use the section from context
596 * @param args a va_list of arguments
598 * @return NULL if configuration list is not found, a list otherwise
600 * @ingroup krb5_support
603 const krb5_config_binding
*
604 krb5_config_vget_list (krb5_context context
,
605 const krb5_config_section
*c
,
608 return _krb5_config_vget (context
, c
, krb5_config_list
, args
);
612 * Returns a "const char *" to a string in the configuration database.
613 * The string may not be valid after a reload of the configuration
614 * database so a caller should make a local copy if it needs to keep
617 * @param context A Kerberos 5 context.
618 * @param c a configuration section, or NULL to use the section from context
619 * @param ... a list of names, terminated with NULL.
621 * @return NULL if configuration string not found, a string otherwise
623 * @ingroup krb5_support
626 const char* KRB5_LIB_FUNCTION
627 krb5_config_get_string (krb5_context context
,
628 const krb5_config_section
*c
,
635 ret
= krb5_config_vget_string (context
, c
, args
);
641 * Like krb5_config_get_string(), but uses a va_list instead of ...
643 * @param context A Kerberos 5 context.
644 * @param c a configuration section, or NULL to use the section from context
645 * @param args a va_list of arguments
647 * @return NULL if configuration string not found, a string otherwise
649 * @ingroup krb5_support
652 const char* KRB5_LIB_FUNCTION
653 krb5_config_vget_string (krb5_context context
,
654 const krb5_config_section
*c
,
657 return _krb5_config_vget (context
, c
, krb5_config_string
, args
);
661 * Like krb5_config_vget_string(), but instead of returning NULL,
662 * instead return a default value.
664 * @param context A Kerberos 5 context.
665 * @param c a configuration section, or NULL to use the section from context
666 * @param def_value the default value to return if no configuration
667 * found in the database.
668 * @param args a va_list of arguments
670 * @return a configuration string
672 * @ingroup krb5_support
675 const char* KRB5_LIB_FUNCTION
676 krb5_config_vget_string_default (krb5_context context
,
677 const krb5_config_section
*c
,
678 const char *def_value
,
683 ret
= krb5_config_vget_string (context
, c
, args
);
690 * Like krb5_config_get_string(), but instead of returning NULL,
691 * instead return a default value.
693 * @param context A Kerberos 5 context.
694 * @param c a configuration section, or NULL to use the section from context
695 * @param def_value the default value to return if no configuration
696 * found in the database.
697 * @param ... a list of names, terminated with NULL.
699 * @return a configuration string
701 * @ingroup krb5_support
704 const char* KRB5_LIB_FUNCTION
705 krb5_config_get_string_default (krb5_context context
,
706 const krb5_config_section
*c
,
707 const char *def_value
,
713 va_start(args
, def_value
);
714 ret
= krb5_config_vget_string_default (context
, c
, def_value
, args
);
720 * Get a list of configuration strings, free the result with
721 * krb5_config_free_strings().
723 * @param context A Kerberos 5 context.
724 * @param c a configuration section, or NULL to use the section from context
725 * @param args a va_list of arguments
727 * @return TRUE or FALSE
729 * @ingroup krb5_support
732 char ** KRB5_LIB_FUNCTION
733 krb5_config_vget_strings(krb5_context context
,
734 const krb5_config_section
*c
,
737 char **strings
= NULL
;
739 const krb5_config_binding
*b
= NULL
;
742 while((p
= _krb5_config_vget_next(context
, c
, &b
,
743 krb5_config_string
, args
))) {
744 char *tmp
= strdup(p
);
749 s
= strtok_r(tmp
, " \t", &pos
);
751 char **tmp2
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
755 strings
[nstr
] = strdup(s
);
757 if(strings
[nstr
-1] == NULL
)
759 s
= strtok_r(NULL
, " \t", &pos
);
764 char **tmp
= realloc(strings
, (nstr
+ 1) * sizeof(*strings
));
768 strings
[nstr
] = NULL
;
780 * Get a list of configuration strings, free the result with
781 * krb5_config_free_strings().
783 * @param context A Kerberos 5 context.
784 * @param c a configuration section, or NULL to use the section from context
785 * @param args a va_list of arguments
787 * @return TRUE or FALSE
789 * @ingroup krb5_support
793 krb5_config_get_strings(krb5_context context
,
794 const krb5_config_section
*c
,
800 ret
= krb5_config_vget_strings(context
, c
, ap
);
806 * Free the resulting strings from krb5_config-get_strings() and
807 * krb5_config_vget_strings().
809 * @param strings strings to free
811 * @ingroup krb5_support
814 void KRB5_LIB_FUNCTION
815 krb5_config_free_strings(char **strings
)
826 * Like krb5_config_get_bool_default() but with a va_list list of
827 * configuration selection.
829 * Configuration value to a boolean value, where yes/true and any
830 * non-zero number means TRUE and other value is FALSE.
832 * @param context A Kerberos 5 context.
833 * @param c a configuration section, or NULL to use the section from context
834 * @param def_value the default value to return if no configuration
835 * found in the database.
836 * @param args a va_list of arguments
838 * @return TRUE or FALSE
840 * @ingroup krb5_support
843 krb5_boolean KRB5_LIB_FUNCTION
844 krb5_config_vget_bool_default (krb5_context context
,
845 const krb5_config_section
*c
,
846 krb5_boolean def_value
,
850 str
= krb5_config_vget_string (context
, c
, args
);
853 if(strcasecmp(str
, "yes") == 0 ||
854 strcasecmp(str
, "true") == 0 ||
855 atoi(str
)) return TRUE
;
860 * krb5_config_get_bool() will convert the configuration
861 * option value to a boolean value, where yes/true and any non-zero
862 * number means TRUE and other value is FALSE.
864 * @param context A Kerberos 5 context.
865 * @param c a configuration section, or NULL to use the section from context
866 * @param args a va_list of arguments
868 * @return TRUE or FALSE
870 * @ingroup krb5_support
873 krb5_boolean KRB5_LIB_FUNCTION
874 krb5_config_vget_bool (krb5_context context
,
875 const krb5_config_section
*c
,
878 return krb5_config_vget_bool_default (context
, c
, FALSE
, args
);
882 * krb5_config_get_bool_default() will convert the configuration
883 * option value to a boolean value, where yes/true and any non-zero
884 * number means TRUE and other value is FALSE.
886 * @param context A Kerberos 5 context.
887 * @param c a configuration section, or NULL to use the section from context
888 * @param def_value the default value to return if no configuration
889 * found in the database.
890 * @param ... a list of names, terminated with NULL.
892 * @return TRUE or FALSE
894 * @ingroup krb5_support
897 krb5_boolean KRB5_LIB_FUNCTION
898 krb5_config_get_bool_default (krb5_context context
,
899 const krb5_config_section
*c
,
900 krb5_boolean def_value
,
905 va_start(ap
, def_value
);
906 ret
= krb5_config_vget_bool_default(context
, c
, def_value
, ap
);
912 * Like krb5_config_get_bool() but with a va_list list of
913 * configuration selection.
915 * Configuration value to a boolean value, where yes/true and any
916 * non-zero number means TRUE and other value is FALSE.
918 * @param context A Kerberos 5 context.
919 * @param c a configuration section, or NULL to use the section from context
920 * @param ... a list of names, terminated with NULL.
922 * @return TRUE or FALSE
924 * @ingroup krb5_support
927 krb5_boolean KRB5_LIB_FUNCTION
928 krb5_config_get_bool (krb5_context context
,
929 const krb5_config_section
*c
,
935 ret
= krb5_config_vget_bool (context
, c
, ap
);
940 int KRB5_LIB_FUNCTION
941 krb5_config_vget_time_default (krb5_context context
,
942 const krb5_config_section
*c
,
949 str
= krb5_config_vget_string (context
, c
, args
);
952 if (krb5_string_to_deltat(str
, &t
))
957 int KRB5_LIB_FUNCTION
958 krb5_config_vget_time (krb5_context context
,
959 const krb5_config_section
*c
,
962 return krb5_config_vget_time_default (context
, c
, -1, args
);
965 int KRB5_LIB_FUNCTION
966 krb5_config_get_time_default (krb5_context context
,
967 const krb5_config_section
*c
,
973 va_start(ap
, def_value
);
974 ret
= krb5_config_vget_time_default(context
, c
, def_value
, ap
);
979 int KRB5_LIB_FUNCTION
980 krb5_config_get_time (krb5_context context
,
981 const krb5_config_section
*c
,
987 ret
= krb5_config_vget_time (context
, c
, ap
);
993 int KRB5_LIB_FUNCTION
994 krb5_config_vget_int_default (krb5_context context
,
995 const krb5_config_section
*c
,
1000 str
= krb5_config_vget_string (context
, c
, args
);
1006 l
= strtol(str
, &endptr
, 0);
1014 int KRB5_LIB_FUNCTION
1015 krb5_config_vget_int (krb5_context context
,
1016 const krb5_config_section
*c
,
1019 return krb5_config_vget_int_default (context
, c
, -1, args
);
1022 int KRB5_LIB_FUNCTION
1023 krb5_config_get_int_default (krb5_context context
,
1024 const krb5_config_section
*c
,
1030 va_start(ap
, def_value
);
1031 ret
= krb5_config_vget_int_default(context
, c
, def_value
, ap
);
1036 int KRB5_LIB_FUNCTION
1037 krb5_config_get_int (krb5_context context
,
1038 const krb5_config_section
*c
,
1044 ret
= krb5_config_vget_int (context
, c
, ap
);