From 89eaef025376339ef25d07cdc4748920fceaa968 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 12 Jan 2010 18:16:45 +1100 Subject: s4:heimdal: import lorikeet-heimdal-201001120029 (commit a5e675fed7c5db8a7370b77ed0bfa724196aa84d) --- source4/heimdal/lib/krb5/config_file.c | 265 ++++++++++++++++++++++++++------- 1 file changed, 215 insertions(+), 50 deletions(-) (limited to 'source4/heimdal/lib/krb5/config_file.c') diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index 03c0e335d4..4eb4e12fad 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -3,6 +3,8 @@ * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -35,6 +37,10 @@ #include "krb5_locl.h" +#ifdef __APPLE__ +#include +#endif + /* Gaah! I want a portable funopen */ struct fileptr { const char *s; @@ -233,6 +239,98 @@ parse_binding(struct fileptr *f, unsigned *lineno, char *p, return ret; } +#ifdef __APPLE__ +static char * +cfstring2cstring(CFStringRef string) +{ + CFIndex len; + char *str; + + str = (char *) CFStringGetCStringPtr(string, kCFStringEncodingUTF8); + if (str) + return strdup(str); + + len = CFStringGetLength(string); + len = 1 + CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8); + str = malloc(len); + if (str == NULL) + return NULL; + + if (!CFStringGetCString (string, str, len, kCFStringEncodingUTF8)) { + free (str); + return NULL; + } + return str; +} + +static void +convert_content(const void *key, const void *value, void *context) +{ + krb5_config_section *tmp, **parent = context; + char *k; + + if (CFGetTypeID(key) != CFStringGetTypeID()) + return; + + k = cfstring2cstring(key); + if (k == NULL) + return; + + if (CFGetTypeID(value) == CFStringGetTypeID()) { + tmp = get_entry(parent, k, krb5_config_string); + tmp->u.string = cfstring2cstring(value); + } else if (CFGetTypeID(value) == CFDictionaryGetTypeID()) { + tmp = get_entry(parent, k, krb5_config_list); + CFDictionaryApplyFunction(value, convert_content, &tmp->u.list); + } else { + /* log */ + } + free(k); +} + +static krb5_error_code +parse_plist_config(krb5_context context, const char *path, krb5_config_section **parent) +{ + CFReadStreamRef s; + CFDictionaryRef d; + CFErrorRef e; + CFURLRef url; + + url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)path, strlen(path), FALSE); + if (url == NULL) { + krb5_clear_error_message(context); + return ENOMEM; + } + + s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url); + CFRelease(url); + if (s == NULL) { + krb5_clear_error_message(context); + return ENOMEM; + } + + if (!CFReadStreamOpen(s)) { + CFRelease(s); + krb5_clear_error_message(context); + return ENOENT; + } + + d = (CFDictionaryRef)CFPropertyListCreateWithStream (kCFAllocatorDefault, s, 0, kCFPropertyListImmutable, NULL, &e); + CFRelease(s); + if (d == NULL) { + krb5_clear_error_message(context); + return ENOENT; + } + + CFDictionaryApplyFunction(d, convert_content, parent); + CFRelease(d); + + return 0; +} + +#endif + + /* * Parse the config file `fname', generating the structures into `res' * returning error messages in `error_message' @@ -280,6 +378,18 @@ krb5_config_parse_debug (struct fileptr *f, return 0; } +static int +is_plist_file(const char *fname) +{ + size_t len = strlen(fname); + char suffix[] = ".plist"; + if (len < sizeof(suffix)) + return 0; + if (strcasecmp(&fname[len - (sizeof(suffix) - 1)], suffix) != 0) + return 0; + return 1; +} + /** * Parse a configuration file and add the result into res. This * interface can be used to parse several configuration files into one @@ -293,7 +403,7 @@ krb5_config_parse_debug (struct fileptr *f, * @ingroup krb5_support */ -krb5_error_code KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_config_parse_file_multi (krb5_context context, const char *fname, krb5_config_section **res) @@ -309,9 +419,16 @@ krb5_config_parse_file_multi (krb5_context context, * current users home directory. The behavior can be disabled and * enabled by calling krb5_set_home_dir_access(). */ - if (_krb5_homedir_access(context) && fname[0] == '~' && fname[1] == '/') { + if (fname[0] == '~' && fname[1] == '/') { +#ifndef KRB5_USE_PATH_TOKENS const char *home = NULL; + if (!_krb5_homedir_access(context)) { + krb5_set_error_message(context, EPERM, + "Access to home directory not allowed"); + return EPERM; + } + if(!issuid()) home = getenv("HOME"); @@ -329,33 +446,73 @@ krb5_config_parse_file_multi (krb5_context context, } fname = newfname; } +#else /* KRB5_USE_PATH_TOKENS */ + asprintf(&newfname, "%%{USERCONFIG}/%s", &fname[1]); + if (newfname == NULL) { + krb5_set_error_message(context, ENOMEM, + N_("malloc: out of memory", "")); + return ENOMEM; + } + fname = newfname; +#endif } - f.f = fopen(fname, "r"); - f.s = NULL; - if(f.f == NULL) { - ret = errno; - krb5_set_error_message (context, ret, "open %s: %s", - fname, strerror(ret)); - if (newfname) - free(newfname); - return ret; - } + if (is_plist_file(fname)) { +#ifdef __APPLE__ + ret = parse_plist_config(context, fname, res); + if (ret) { + krb5_set_error_message(context, ret, + "Failed to parse plist %s", fname); + if (newfname) + free(newfname); + return ret; + } +#else + krb5_set_error_message(context, ENOENT, + "no support for plist configuration files"); + return ENOENT; +#endif + } else { +#ifdef KRB5_USE_PATH_TOKENS + char * exp_fname = NULL; - ret = krb5_config_parse_debug (&f, res, &lineno, &str); - fclose(f.f); - if (ret) { - krb5_set_error_message (context, ret, "%s:%u: %s", fname, lineno, str); + ret = _krb5_expand_path_tokens(context, fname, &exp_fname); + if (ret) { + if (newfname) + free(newfname); + return ret; + } + if (newfname) free(newfname); - return ret; + fname = newfname = exp_fname; +#endif + + f.f = fopen(fname, "r"); + f.s = NULL; + if(f.f == NULL) { + ret = errno; + krb5_set_error_message (context, ret, "open %s: %s", + fname, strerror(ret)); + if (newfname) + free(newfname); + return ret; + } + + ret = krb5_config_parse_debug (&f, res, &lineno, &str); + fclose(f.f); + if (ret) { + krb5_set_error_message (context, ret, "%s:%u: %s", + fname, lineno, str); + if (newfname) + free(newfname); + return ret; + } } - if (newfname) - free(newfname); return 0; } -krb5_error_code KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_config_parse_file (krb5_context context, const char *fname, krb5_config_section **res) @@ -397,7 +554,7 @@ free_binding (krb5_context context, krb5_config_binding *b) * @ingroup krb5_support */ -krb5_error_code KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_config_file_free (krb5_context context, krb5_config_section *s) { free_binding (context, s); @@ -406,7 +563,7 @@ krb5_config_file_free (krb5_context context, krb5_config_section *s) #ifndef HEIMDAL_SMALLER -krb5_error_code +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_config_copy(krb5_context context, krb5_config_section *c, krb5_config_section **head) @@ -442,7 +599,7 @@ _krb5_config_copy(krb5_context context, #endif /* HEIMDAL_SMALLER */ -const void * +KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL _krb5_config_get_next (krb5_context context, const krb5_config_section *c, const krb5_config_binding **pointer, @@ -481,7 +638,7 @@ vget_next(krb5_context context, return NULL; } -const void * +KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL _krb5_config_vget_next (krb5_context context, const krb5_config_section *c, const krb5_config_binding **pointer, @@ -517,7 +674,7 @@ _krb5_config_vget_next (krb5_context context, return NULL; } -const void * +KRB5_LIB_FUNCTION const void * KRB5_LIB_CALL _krb5_config_get (krb5_context context, const krb5_config_section *c, int type, @@ -532,6 +689,7 @@ _krb5_config_get (krb5_context context, return ret; } + const void * _krb5_config_vget (krb5_context context, const krb5_config_section *c, @@ -555,7 +713,7 @@ _krb5_config_vget (krb5_context context, * @ingroup krb5_support */ -const krb5_config_binding * +KRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL krb5_config_get_list (krb5_context context, const krb5_config_section *c, ...) @@ -581,7 +739,7 @@ krb5_config_get_list (krb5_context context, * @ingroup krb5_support */ -const krb5_config_binding * +KRB5_LIB_FUNCTION const krb5_config_binding * KRB5_LIB_CALL krb5_config_vget_list (krb5_context context, const krb5_config_section *c, va_list args) @@ -604,7 +762,7 @@ krb5_config_vget_list (krb5_context context, * @ingroup krb5_support */ -const char* KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL krb5_config_get_string (krb5_context context, const krb5_config_section *c, ...) @@ -630,7 +788,7 @@ krb5_config_get_string (krb5_context context, * @ingroup krb5_support */ -const char* KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL krb5_config_vget_string (krb5_context context, const krb5_config_section *c, va_list args) @@ -653,7 +811,7 @@ krb5_config_vget_string (krb5_context context, * @ingroup krb5_support */ -const char* KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL krb5_config_vget_string_default (krb5_context context, const krb5_config_section *c, const char *def_value, @@ -682,7 +840,7 @@ krb5_config_vget_string_default (krb5_context context, * @ingroup krb5_support */ -const char* KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL krb5_config_get_string_default (krb5_context context, const krb5_config_section *c, const char *def_value, @@ -710,7 +868,7 @@ krb5_config_get_string_default (krb5_context context, * @ingroup krb5_support */ -char ** KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION char ** KRB5_LIB_CALL krb5_config_vget_strings(krb5_context context, const krb5_config_section *c, va_list args) @@ -770,7 +928,7 @@ cleanup: * @ingroup krb5_support */ -char** +KRB5_LIB_FUNCTION char** KRB5_LIB_CALL krb5_config_get_strings(krb5_context context, const krb5_config_section *c, ...) @@ -792,7 +950,7 @@ krb5_config_get_strings(krb5_context context, * @ingroup krb5_support */ -void KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_config_free_strings(char **strings) { char **s = strings; @@ -821,7 +979,7 @@ krb5_config_free_strings(char **strings) * @ingroup krb5_support */ -krb5_boolean KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL krb5_config_vget_bool_default (krb5_context context, const krb5_config_section *c, krb5_boolean def_value, @@ -851,7 +1009,7 @@ krb5_config_vget_bool_default (krb5_context context, * @ingroup krb5_support */ -krb5_boolean KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL krb5_config_vget_bool (krb5_context context, const krb5_config_section *c, va_list args) @@ -875,7 +1033,7 @@ krb5_config_vget_bool (krb5_context context, * @ingroup krb5_support */ -krb5_boolean KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL krb5_config_get_bool_default (krb5_context context, const krb5_config_section *c, krb5_boolean def_value, @@ -905,7 +1063,7 @@ krb5_config_get_bool_default (krb5_context context, * @ingroup krb5_support */ -krb5_boolean KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL krb5_config_get_bool (krb5_context context, const krb5_config_section *c, ...) @@ -935,7 +1093,7 @@ krb5_config_get_bool (krb5_context context, * @ingroup krb5_support */ -int KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_config_vget_time_default (krb5_context context, const krb5_config_section *c, int def_value, @@ -964,10 +1122,10 @@ krb5_config_vget_time_default (krb5_context context, * @ingroup krb5_support */ -int KRB5_LIB_FUNCTION -krb5_config_vget_time(krb5_context context, - const krb5_config_section *c, - va_list args) +KRB5_LIB_FUNCTION int KRB5_LIB_CALL +krb5_config_vget_time (krb5_context context, + const krb5_config_section *c, + va_list args) { return krb5_config_vget_time_default (context, c, -1, args); } @@ -986,7 +1144,7 @@ krb5_config_vget_time(krb5_context context, * @ingroup krb5_support */ -int KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_config_get_time_default (krb5_context context, const krb5_config_section *c, int def_value, @@ -1012,7 +1170,7 @@ krb5_config_get_time_default (krb5_context context, * @ingroup krb5_support */ -int KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_config_get_time (krb5_context context, const krb5_config_section *c, ...) @@ -1026,7 +1184,7 @@ krb5_config_get_time (krb5_context context, } -int KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_config_vget_int_default (krb5_context context, const krb5_config_section *c, int def_value, @@ -1047,7 +1205,7 @@ krb5_config_vget_int_default (krb5_context context, } } -int KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_config_vget_int (krb5_context context, const krb5_config_section *c, va_list args) @@ -1055,7 +1213,7 @@ krb5_config_vget_int (krb5_context context, return krb5_config_vget_int_default (context, c, -1, args); } -int KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_config_get_int_default (krb5_context context, const krb5_config_section *c, int def_value, @@ -1069,7 +1227,7 @@ krb5_config_get_int_default (krb5_context context, return ret; } -int KRB5_LIB_FUNCTION +KRB5_LIB_FUNCTION int KRB5_LIB_CALL krb5_config_get_int (krb5_context context, const krb5_config_section *c, ...) @@ -1085,10 +1243,17 @@ krb5_config_get_int (krb5_context context, #ifndef HEIMDAL_SMALLER +/** + * Deprecated: configuration files are not strings + * + * @ingroup krb5_deprecated + */ + +KRB5_DEPRECATED krb5_error_code KRB5_LIB_FUNCTION krb5_config_parse_string_multi(krb5_context context, const char *string, - krb5_config_section **res) KRB5_DEPRECATED + krb5_config_section **res) { const char *str; unsigned lineno = 0; -- cgit