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 ... a list of names, terminated with NULL.
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
);