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 #define KRB5_DEPRECATED
36 #include "krb5_locl.h"
38 /* Gaah! I want a portable funopen */
45 config_fgets(char *str, size_t len, struct fileptr *ptr)
47 /* XXX this is not correct, in that they don't do the same if the
48 line is longer than len */
50 return fgets(str, len, ptr->f);
52 /* this is almost strsep_copy */
57 p = ptr->s + strcspn(ptr->s, "\n");
60 l = min(len, p - ptr->s);
62 memcpy(str, ptr->s, l);
70 static krb5_error_code parse_section(char *p, krb5_config_section **s,
71 krb5_config_section **res,
72 const char **error_message);
73 static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
74 krb5_config_binding **b,
75 krb5_config_binding **parent,
76 const char **error_message);
77 static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno,
78 krb5_config_binding **parent,
79 const char **error_message);
81 static krb5_config_section *
82 get_entry(krb5_config_section **parent, const char *name, int type)
84 krb5_config_section **q;
86 for(q = parent; *q != NULL; q = &(*q)->next)
87 if(type == krb5_config_list &&
89 strcmp(name, (*q)->name) == 0)
91 *q = calloc(1, sizeof(**q));
94 (*q)->name = strdup(name);
96 if((*q)->name == NULL) {
114 * starting at the line in `p', storing the resulting structure in
115 * `s' and hooking it into `parent'.
116 * Store the error message in `error_message'.
119 static krb5_error_code
120 parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
121 const char **error_message)
124 krb5_config_section *tmp;
126 p1 = strchr (p + 1, ']');
128 *error_message = "missing ]";
129 return KRB5_CONFIG_BADFORMAT;
132 tmp = get_entry(parent, p + 1, krb5_config_list);
134 *error_message = "out of memory";
135 return KRB5_CONFIG_BADFORMAT;
142 * Parse a brace-enclosed list from `f', hooking in the structure at
144 * Store the error message in `error_message'.
147 static krb5_error_code
148 parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent,
149 const char **error_message)
153 krb5_config_binding *b = NULL;
154 unsigned beg_lineno = *lineno;
156 while(config_fgets(buf, sizeof(buf), f) != NULL) {
160 buf[strcspn(buf, "\r\n")] = '\0';
162 while(isspace((unsigned char)*p))
164 if (*p == '#' || *p == ';' || *p == '\0')
166 while(isspace((unsigned char)*p))
172 ret = parse_binding (f, lineno, p, &b, parent, error_message);
176 *lineno = beg_lineno;
177 *error_message = "unclosed {";
178 return KRB5_CONFIG_BADFORMAT;
185 static krb5_error_code
186 parse_binding(struct fileptr *f, unsigned *lineno, char *p,
187 krb5_config_binding **b, krb5_config_binding **parent,
188 const char **error_message)
190 krb5_config_binding *tmp;
192 krb5_error_code ret = 0;
195 while (*p && *p != '=' && !isspace((unsigned char)*p))
198 *error_message = "missing =";
199 return KRB5_CONFIG_BADFORMAT;
202 while (isspace((unsigned char)*p))
205 *error_message = "missing =";
206 return KRB5_CONFIG_BADFORMAT;
209 while(isspace((unsigned char)*p))
213 tmp = get_entry(parent, p1, krb5_config_list);
215 *error_message = "out of memory";
216 return KRB5_CONFIG_BADFORMAT;
218 ret = parse_list (f, lineno, &tmp->u.list, error_message);
220 tmp = get_entry(parent, p1, krb5_config_string);
222 *error_message = "out of memory";
223 return KRB5_CONFIG_BADFORMAT;
227 while(p > p1 && isspace((unsigned char)*(p-1)))
230 tmp->u.string = strdup(p1);
237 * Parse the config file `fname', generating the structures into `res'
238 * returning error messages in `error_message'
241 static krb5_error_code
242 krb5_config_parse_debug (struct fileptr *f,
243 krb5_config_section **res,
245 const char **error_message)
247 krb5_config_section *s = NULL;
248 krb5_config_binding *b = NULL;
252 while (config_fgets(buf, sizeof(buf), f) != NULL) {
256 buf[strcspn(buf, "\r\n")] = '\0';
258 while(isspace((unsigned char)*p))
260 if (*p == '#' || *p == ';')
263 ret = parse_section(p, &s, res, error_message);
267 } else if (*p == '}') {
268 *error_message = "unmatched }";
269 return EINVAL; /* XXX */
270 } else if(*p != '\0') {
272 *error_message = "binding before section";
275 ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message);
284 * Parse a configuration file and add the result into res. This
285 * interface can be used to parse several configuration files into one
286 * resulting krb5_config_section by calling it repeatably.
288 * @param context a Kerberos 5 context.
289 * @param fname a file name to a Kerberos configuration file
290 * @param res the returned result, must be free with krb5_free_config_files().
291 * @return Return an error code or 0, see krb5_get_error_message().
293 * @ingroup krb5_support
296 krb5_error_code KRB5_LIB_FUNCTION
297 krb5_config_parse_file_multi (krb5_context context,
299 krb5_config_section **res)
302 char *newfname = NULL;
308 * If the fname starts with "~/" parse configuration file in the
309 * current users home directory. The behavior can be disabled and
310 * enabled by calling krb5_set_home_dir_access().
312 if (_krb5_homedir_access(context) && fname[0] == '~' && fname[1] == '/') {
313 const char *home = NULL;
316 home = getenv("HOME");
319 struct passwd *pw = getpwuid(getuid());
324 asprintf(&newfname, "%s%s", home, &fname[1]);
325 if (newfname == NULL) {
326 krb5_set_error_message(context, ENOMEM,
327 N_("malloc: out of memory", ""));
334 f.f = fopen(fname, "r");
338 krb5_set_error_message (context, ret, "open %s: %s",
339 fname, strerror(ret));
345 ret = krb5_config_parse_debug (&f, res, &lineno, &str);
348 krb5_set_error_message (context, ret, "%s:%u: %s", fname, lineno, str);
358 krb5_error_code KRB5_LIB_FUNCTION
359 krb5_config_parse_file (krb5_context context,
361 krb5_config_section **res)
364 return krb5_config_parse_file_multi(context, fname, res);
368 free_binding (krb5_context context, krb5_config_binding *b)
370 krb5_config_binding *next_b;
374 if (b->type == krb5_config_string)
376 else if (b->type == krb5_config_list)
377 free_binding (context, b->u.list);
379 krb5_abortx(context, "unknown binding type (%d) in free_binding",
388 * Free configuration file section, the result of
389 * krb5_config_parse_file() and krb5_config_parse_file_multi().
391 * @param context A Kerberos 5 context
392 * @param s the configuration section to free
394 * @return returns 0 on successes, otherwise an error code, see
395 * krb5_get_error_message()
397 * @ingroup krb5_support
400 krb5_error_code KRB5_LIB_FUNCTION
401 krb5_config_file_free (krb5_context context, krb5_config_section *s)
403 free_binding (context, s);
407 #ifndef HEIMDAL_SMALLER
410 _krb5_config_copy(krb5_context context,
411 krb5_config_section *c,
412 krb5_config_section **head)
414 krb5_config_binding *d, *previous = NULL;
419 d = calloc(1, sizeof(*d));
424 d->name = strdup(c->name);
426 if (d->type == krb5_config_string)
427 d->u.string = strdup(c->u.string);
428 else if (d->type == krb5_config_list)
429 _krb5_config_copy (context, c->u.list, &d->u.list);
432 "unknown binding type (%d) in krb5_config_copy",
443 #endif /* HEIMDAL_SMALLER */
446 _krb5_config_get_next (krb5_context context,
447 const krb5_config_section *c,
448 const krb5_config_binding **pointer,
455 va_start(args, type);
456 ret = _krb5_config_vget_next (context, c, pointer, type, args);
462 vget_next(krb5_context context,
463 const krb5_config_binding *b,
464 const krb5_config_binding **pointer,
469 const char *p = va_arg(args, const char *);
471 if(strcmp(b->name, name) == 0) {
472 if(b->type == type && p == NULL) {
475 } else if(b->type == krb5_config_list && p != NULL) {
476 return vget_next(context, b->u.list, pointer, type, p, args);
485 _krb5_config_vget_next (krb5_context context,
486 const krb5_config_section *c,
487 const krb5_config_binding **pointer,
491 const krb5_config_binding *b;
500 if (*pointer == NULL) {
501 /* first time here, walk down the tree looking for the right
503 p = va_arg(args, const char *);
506 return vget_next(context, c, pointer, type, p, args);
509 /* we were called again, so just look for more entries with the
510 same name and type */
511 for (b = (*pointer)->next; b != NULL; b = b->next) {
512 if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) {
521 _krb5_config_get (krb5_context context,
522 const krb5_config_section *c,
529 va_start(args, type);
530 ret = _krb5_config_vget (context, c, type, args);
536 _krb5_config_vget (krb5_context context,
537 const krb5_config_section *c,
541 const krb5_config_binding *foo = NULL;
543 return _krb5_config_vget_next (context, c, &foo, type, args);
547 * Get a list of configuration binding list for more processing
549 * @param context A Kerberos 5 context.
550 * @param c a configuration section, or NULL to use the section from context
551 * @param ... a list of names, terminated with NULL.
553 * @return NULL if configuration list is not found, a list otherwise
555 * @ingroup krb5_support
558 const krb5_config_binding *
559 krb5_config_get_list (krb5_context context,
560 const krb5_config_section *c,
563 const krb5_config_binding *ret;
567 ret = krb5_config_vget_list (context, c, args);
573 * Get a list of configuration binding list for more processing
575 * @param context A Kerberos 5 context.
576 * @param c a configuration section, or NULL to use the section from context
577 * @param args a va_list of arguments
579 * @return NULL if configuration list is not found, a list otherwise
581 * @ingroup krb5_support
584 const krb5_config_binding *
585 krb5_config_vget_list (krb5_context context,
586 const krb5_config_section *c,
589 return _krb5_config_vget (context, c, krb5_config_list, args);
593 * Returns a "const char *" to a string in the configuration database.
594 * The string may not be valid after a reload of the configuration
595 * database so a caller should make a local copy if it needs to keep
598 * @param context A Kerberos 5 context.
599 * @param c a configuration section, or NULL to use the section from context
600 * @param ... a list of names, terminated with NULL.
602 * @return NULL if configuration string not found, a string otherwise
604 * @ingroup krb5_support
607 const char* KRB5_LIB_FUNCTION
608 krb5_config_get_string (krb5_context context,
609 const krb5_config_section *c,
616 ret = krb5_config_vget_string (context, c, args);
622 * Like krb5_config_get_string(), but uses a va_list instead of ...
624 * @param context A Kerberos 5 context.
625 * @param c a configuration section, or NULL to use the section from context
626 * @param args a va_list of arguments
628 * @return NULL if configuration string not found, a string otherwise
630 * @ingroup krb5_support
633 const char* KRB5_LIB_FUNCTION
634 krb5_config_vget_string (krb5_context context,
635 const krb5_config_section *c,
638 return _krb5_config_vget (context, c, krb5_config_string, args);
642 * Like krb5_config_vget_string(), but instead of returning NULL,
643 * instead return a default value.
645 * @param context A Kerberos 5 context.
646 * @param c a configuration section, or NULL to use the section from context
647 * @param def_value the default value to return if no configuration
648 * found in the database.
649 * @param args a va_list of arguments
651 * @return a configuration string
653 * @ingroup krb5_support
656 const char* KRB5_LIB_FUNCTION
657 krb5_config_vget_string_default (krb5_context context,
658 const krb5_config_section *c,
659 const char *def_value,
664 ret = krb5_config_vget_string (context, c, args);
671 * Like krb5_config_get_string(), but instead of returning NULL,
672 * instead return a default value.
674 * @param context A Kerberos 5 context.
675 * @param c a configuration section, or NULL to use the section from context
676 * @param def_value the default value to return if no configuration
677 * found in the database.
678 * @param ... a list of names, terminated with NULL.
680 * @return a configuration string
682 * @ingroup krb5_support
685 const char* KRB5_LIB_FUNCTION
686 krb5_config_get_string_default (krb5_context context,
687 const krb5_config_section *c,
688 const char *def_value,
694 va_start(args, def_value);
695 ret = krb5_config_vget_string_default (context, c, def_value, args);
701 * Get a list of configuration strings, free the result with
702 * krb5_config_free_strings().
704 * @param context A Kerberos 5 context.
705 * @param c a configuration section, or NULL to use the section from context
706 * @param args a va_list of arguments
708 * @return TRUE or FALSE
710 * @ingroup krb5_support
713 char ** KRB5_LIB_FUNCTION
714 krb5_config_vget_strings(krb5_context context,
715 const krb5_config_section *c,
718 char **strings = NULL;
720 const krb5_config_binding *b = NULL;
723 while((p = _krb5_config_vget_next(context, c, &b,
724 krb5_config_string, args))) {
725 char *tmp = strdup(p);
730 s = strtok_r(tmp, " \t", &pos);
732 char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
736 strings[nstr] = strdup(s);
738 if(strings[nstr-1] == NULL)
740 s = strtok_r(NULL, " \t", &pos);
745 char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
749 strings[nstr] = NULL;
761 * Get a list of configuration strings, free the result with
762 * krb5_config_free_strings().
764 * @param context A Kerberos 5 context.
765 * @param c a configuration section, or NULL to use the section from context
766 * @param ... a list of names, terminated with NULL.
768 * @return TRUE or FALSE
770 * @ingroup krb5_support
774 krb5_config_get_strings(krb5_context context,
775 const krb5_config_section *c,
781 ret = krb5_config_vget_strings(context, c, ap);
787 * Free the resulting strings from krb5_config-get_strings() and
788 * krb5_config_vget_strings().
790 * @param strings strings to free
792 * @ingroup krb5_support
795 void KRB5_LIB_FUNCTION
796 krb5_config_free_strings(char **strings)
807 * Like krb5_config_get_bool_default() but with a va_list list of
808 * configuration selection.
810 * Configuration value to a boolean value, where yes/true and any
811 * non-zero number means TRUE and other value is FALSE.
813 * @param context A Kerberos 5 context.
814 * @param c a configuration section, or NULL to use the section from context
815 * @param def_value the default value to return if no configuration
816 * found in the database.
817 * @param args a va_list of arguments
819 * @return TRUE or FALSE
821 * @ingroup krb5_support
824 krb5_boolean KRB5_LIB_FUNCTION
825 krb5_config_vget_bool_default (krb5_context context,
826 const krb5_config_section *c,
827 krb5_boolean def_value,
831 str = krb5_config_vget_string (context, c, args);
834 if(strcasecmp(str, "yes") == 0 ||
835 strcasecmp(str, "true") == 0 ||
836 atoi(str)) return TRUE;
841 * krb5_config_get_bool() will convert the configuration
842 * option value to a boolean value, where yes/true and any non-zero
843 * number means TRUE and other value is FALSE.
845 * @param context A Kerberos 5 context.
846 * @param c a configuration section, or NULL to use the section from context
847 * @param args a va_list of arguments
849 * @return TRUE or FALSE
851 * @ingroup krb5_support
854 krb5_boolean KRB5_LIB_FUNCTION
855 krb5_config_vget_bool (krb5_context context,
856 const krb5_config_section *c,
859 return krb5_config_vget_bool_default (context, c, FALSE, args);
863 * krb5_config_get_bool_default() will convert the configuration
864 * option value to a boolean value, where yes/true and any non-zero
865 * number means TRUE and other value is FALSE.
867 * @param context A Kerberos 5 context.
868 * @param c a configuration section, or NULL to use the section from context
869 * @param def_value the default value to return if no configuration
870 * found in the database.
871 * @param ... a list of names, terminated with NULL.
873 * @return TRUE or FALSE
875 * @ingroup krb5_support
878 krb5_boolean KRB5_LIB_FUNCTION
879 krb5_config_get_bool_default (krb5_context context,
880 const krb5_config_section *c,
881 krb5_boolean def_value,
886 va_start(ap, def_value);
887 ret = krb5_config_vget_bool_default(context, c, def_value, ap);
893 * Like krb5_config_get_bool() but with a va_list list of
894 * configuration selection.
896 * Configuration value to a boolean value, where yes/true and any
897 * non-zero number means TRUE and other value is FALSE.
899 * @param context A Kerberos 5 context.
900 * @param c a configuration section, or NULL to use the section from context
901 * @param ... a list of names, terminated with NULL.
903 * @return TRUE or FALSE
905 * @ingroup krb5_support
908 krb5_boolean KRB5_LIB_FUNCTION
909 krb5_config_get_bool (krb5_context context,
910 const krb5_config_section *c,
916 ret = krb5_config_vget_bool (context, c, ap);
922 * Get the time from the configuration file using a relative time.
924 * Like krb5_config_get_time_default() but with a va_list list of
925 * configuration selection.
927 * @param context A Kerberos 5 context.
928 * @param c a configuration section, or NULL to use the section from context
929 * @param def_value the default value to return if no configuration
930 * found in the database.
931 * @param args a va_list of arguments
933 * @return parsed the time (or def_value on parse error)
935 * @ingroup krb5_support
938 int KRB5_LIB_FUNCTION
939 krb5_config_vget_time_default (krb5_context context,
940 const krb5_config_section *c,
947 str = krb5_config_vget_string (context, c, args);
950 if (krb5_string_to_deltat(str, &t))
956 * Get the time from the configuration file using a relative time, for example: 1h30s
958 * @param context A Kerberos 5 context.
959 * @param c a configuration section, or NULL to use the section from context
960 * @param args a va_list of arguments
962 * @return parsed the time or -1 on error
964 * @ingroup krb5_support
967 int KRB5_LIB_FUNCTION
968 krb5_config_vget_time(krb5_context context,
969 const krb5_config_section *c,
972 return krb5_config_vget_time_default (context, c, -1, args);
976 * Get the time from the configuration file using a relative time, for example: 1h30s
978 * @param context A Kerberos 5 context.
979 * @param c a configuration section, or NULL to use the section from context
980 * @param def_value the default value to return if no configuration
981 * found in the database.
982 * @param ... a list of names, terminated with NULL.
984 * @return parsed the time (or def_value on parse error)
986 * @ingroup krb5_support
989 int KRB5_LIB_FUNCTION
990 krb5_config_get_time_default (krb5_context context,
991 const krb5_config_section *c,
997 va_start(ap, def_value);
998 ret = krb5_config_vget_time_default(context, c, def_value, ap);
1004 * Get the time from the configuration file using a relative time, for example: 1h30s
1006 * @param context A Kerberos 5 context.
1007 * @param c a configuration section, or NULL to use the section from context
1008 * @param ... a list of names, terminated with NULL.
1010 * @return parsed the time or -1 on error
1012 * @ingroup krb5_support
1015 int KRB5_LIB_FUNCTION
1016 krb5_config_get_time (krb5_context context,
1017 const krb5_config_section *c,
1023 ret = krb5_config_vget_time (context, c, ap);
1029 int KRB5_LIB_FUNCTION
1030 krb5_config_vget_int_default (krb5_context context,
1031 const krb5_config_section *c,
1036 str = krb5_config_vget_string (context, c, args);
1042 l = strtol(str, &endptr, 0);
1050 int KRB5_LIB_FUNCTION
1051 krb5_config_vget_int (krb5_context context,
1052 const krb5_config_section *c,
1055 return krb5_config_vget_int_default (context, c, -1, args);
1058 int KRB5_LIB_FUNCTION
1059 krb5_config_get_int_default (krb5_context context,
1060 const krb5_config_section *c,
1066 va_start(ap, def_value);
1067 ret = krb5_config_vget_int_default(context, c, def_value, ap);
1072 int KRB5_LIB_FUNCTION
1073 krb5_config_get_int (krb5_context context,
1074 const krb5_config_section *c,
1080 ret = krb5_config_vget_int (context, c, ap);
1086 #ifndef HEIMDAL_SMALLER
1088 krb5_error_code KRB5_LIB_FUNCTION
1089 krb5_config_parse_string_multi(krb5_context context,
1091 krb5_config_section **res) KRB5_DEPRECATED
1094 unsigned lineno = 0;
1095 krb5_error_code ret;
1100 ret = krb5_config_parse_debug (&f, res, &lineno, &str);
1102 krb5_set_error_message (context, ret, "%s:%u: %s",
1103 "<constant>", lineno, str);