From 360e95b128fdd43b5808530541c84f5096344128 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Thu, 16 Jun 2016 16:25:41 -0400 Subject: [PATCH 1/3] heimdal: lib/krb5: do not fail set_config_files due to parse error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow Apple's lead and do not fail krb5_set_config_files() simply because one of the files in the profile list fails to parse correctly. Doing so can lead to hard to find failures and could lead to an end user shooting themselves in the foot and no longer be able to login to their system to fix it. Parse as many of the files as we can. Only fail krb5_set_config_files() if init_context_from_config_file() fails. Change-Id: I122664c6d707a5f926643808ba414bf4f681f8b8 Cherry-pick of Heimdal commit b7cf5e7caf9b270f4d4151d2690177b11a7a1bdf BUG: https://bugzilla.samba.org/show_bug.cgi?id=11573 Signed-off-by: Björn Baumbach Reviewed-by: Alexander Bokovoy (cherry picked from commit f05a1554b770c6a2c905170347bfb41157f4aa78) --- source4/heimdal/lib/krb5/config_file.c | 4 ++-- source4/heimdal/lib/krb5/context.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index 4ac25ae2870..f5ddcc93e72 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -370,11 +370,11 @@ krb5_config_parse_debug (struct fileptr *f, b = NULL; } else if (*p == '}') { *err_message = "unmatched }"; - return EINVAL; /* XXX */ + return KRB5_CONFIG_BADFORMAT; } else if(*p != '\0') { if (s == NULL) { *err_message = "binding before section"; - return EINVAL; + return KRB5_CONFIG_BADFORMAT; } ret = parse_binding(f, lineno, p, &b, &s->u.list, err_message); if (ret) diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 23e3879d6db..770f01278a1 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -646,7 +646,8 @@ krb5_set_config_files(krb5_context context, char **filenames) krb5_config_binding *tmp = NULL; while(filenames != NULL && *filenames != NULL && **filenames != '\0') { ret = krb5_config_parse_file_multi(context, *filenames, &tmp); - if(ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM) { + if (ret != 0 && ret != ENOENT && ret != EACCES && ret != EPERM + && ret != KRB5_CONFIG_BADFORMAT) { krb5_config_file_free(context, tmp); return ret; } -- 2.16.1 From 9ad5828fcddfef9a1a4482ff4bb69483f5e2c2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Baumbach?= Date: Fri, 15 Jun 2018 14:33:40 +0200 Subject: [PATCH 2/3] heimdal: small code adaption to cherry-pick heimdal commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check asprintf() return value. Make use of krb5_enomem(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=11573 Signed-off-by: Björn Baumbach Reviewed-by: Alexander Bokovoy (cherry picked from commit 88cac23e2b767175d94561aaea13ba6200c331df) --- source4/heimdal/lib/krb5/config_file.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index f5ddcc93e72..6630d8ede3f 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -444,22 +444,17 @@ krb5_config_parse_file_multi (krb5_context context, home = pw->pw_dir; } if (home) { - asprintf(&newfname, "%s%s", home, &fname[1]); - if (newfname == NULL) { - krb5_set_error_message(context, ENOMEM, - N_("malloc: out of memory", "")); - return ENOMEM; - } + int aret; + + aret = asprintf(&newfname, "%s%s", home, &fname[1]); + if (aret == -1 || newfname == NULL) + return krb5_enomem(context); fname = newfname; } #else /* KRB5_USE_PATH_TOKENS */ if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 || newfname == NULL) - { - krb5_set_error_message(context, ENOMEM, - N_("malloc: out of memory", "")); - return ENOMEM; - } + return krb5_enomem(context); fname = newfname; #endif } -- 2.16.1 From 6bafda6efc89aaff93bc17161c24f70dcf1cfdad Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Fri, 15 Jun 2018 14:45:38 +0200 Subject: [PATCH 3/3] heimdal: Add include/includedir directives for krb5.conf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick of Heimdal commit fe43be85587f834266623adb0ecf2793d212a7ca Removed tests and documentation from original commit by Björn Baumbach , since we do not ship them. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11573 Signed-off-by: Björn Baumbach Reviewed-by: Alexander Bokovoy Autobuild-User(master): Björn Baumbach Autobuild-Date(master): Mon Jun 18 15:52:26 CEST 2018 on sn-devel-144 (cherry picked from commit 0a6e9b6c0e15fa6fe46acdd357d76b8df447317f) --- source4/heimdal/lib/krb5/config_file.c | 100 ++++++++++++++++++++++++++++++++- source4/heimdal/lib/krb5/krb5_locl.h | 1 + 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index 6630d8ede3f..6cbb8ec5c6f 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -41,6 +41,7 @@ /* Gaah! I want a portable funopen */ struct fileptr { + krb5_context context; const char *s; FILE *f; }; @@ -363,7 +364,7 @@ krb5_config_parse_debug (struct fileptr *f, ++p; if (*p == '#' || *p == ';') continue; - if (*p == '[') { + if (*p == '[') { ret = parse_section(p, &s, res, err_message); if (ret) return ret; @@ -371,6 +372,22 @@ krb5_config_parse_debug (struct fileptr *f, } else if (*p == '}') { *err_message = "unmatched }"; return KRB5_CONFIG_BADFORMAT; + } else if (strncmp(p, "include", sizeof("include") - 1) == 0 && + isspace(p[sizeof("include") - 1])) { + p += sizeof("include"); + while (isspace(*p)) + p++; + ret = krb5_config_parse_file_multi(f->context, p, res); + if (ret) + return ret; + } else if (strncmp(p, "includedir", sizeof("includedir") - 1) == 0 && + isspace(p[sizeof("includedir") - 1])) { + p += sizeof("includedir"); + while (isspace(*p)) + p++; + ret = krb5_config_parse_dir_multi(f->context, p, res); + if (ret) + return ret; } else if(*p != '\0') { if (s == NULL) { *err_message = "binding before section"; @@ -396,6 +413,64 @@ is_plist_file(const char *fname) return 1; } +/** + * Parse configuration files in the given directory and add the result + * into res. Only files whose names consist only of alphanumeric + * characters, hyphen, and underscore, will be parsed, though files + * ending in ".conf" will also be parsed. + * + * This interface can be used to parse several configuration directories + * into one resulting krb5_config_section by calling it repeatably. + * + * @param context a Kerberos 5 context. + * @param dname a directory name to a Kerberos configuration file + * @param res the returned result, must be free with krb5_free_config_files(). + * @return Return an error code or 0, see krb5_get_error_message(). + * + * @ingroup krb5_support + */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_config_parse_dir_multi(krb5_context context, + const char *dname, + krb5_config_section **res) +{ + struct dirent *entry; + krb5_error_code ret; + DIR *d; + + if ((d = opendir(dname)) == NULL) + return errno; + + while ((entry = readdir(d)) != NULL) { + char *p = entry->d_name; + char *path; + int is_valid = 1; + + while (*p) { + if (!isalpha(*p) && *p != '_' && *p != '-' && + strcmp(p, ".conf") != 0) { + is_valid = 0; + break; + } + p++; + } + if (!is_valid) + continue; + + if (asprintf(&path, "%s/%s", dname, entry->d_name) == -1 || + path == NULL) + return krb5_enomem(context); + ret = krb5_config_parse_file_multi(context, path, res); + free(path); + if (ret == ENOMEM) + return krb5_enomem(context);; + /* Ignore malformed config files */ + } + (void) closedir(d); + return 0; +} + /** * Parse a configuration file and add the result into res. This * interface can be used to parse several configuration files into one @@ -420,6 +495,13 @@ krb5_config_parse_file_multi (krb5_context context, krb5_error_code ret; struct fileptr f; + if (context->config_include_depth > 5) { + krb5_warnx(context, "Maximum config file include depth reached; " + "not including %s", fname); + return 0; + } + context->config_include_depth++; + /** * If the fname starts with "~/" parse configuration file in the * current users home directory. The behavior can be disabled and @@ -430,6 +512,7 @@ krb5_config_parse_file_multi (krb5_context context, const char *home = NULL; if (!_krb5_homedir_access(context)) { + context->config_include_depth--; krb5_set_error_message(context, EPERM, "Access to home directory not allowed"); return EPERM; @@ -447,14 +530,18 @@ krb5_config_parse_file_multi (krb5_context context, int aret; aret = asprintf(&newfname, "%s%s", home, &fname[1]); - if (aret == -1 || newfname == NULL) + if (aret == -1 || newfname == NULL) { + context->config_include_depth--; return krb5_enomem(context); + } fname = newfname; } #else /* KRB5_USE_PATH_TOKENS */ if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 || - newfname == NULL) + newfname == NULL) { + context->config_include_depth--; return krb5_enomem(context); + } fname = newfname; #endif } @@ -462,6 +549,7 @@ krb5_config_parse_file_multi (krb5_context context, if (is_plist_file(fname)) { #ifdef __APPLE__ ret = parse_plist_config(context, fname, res); + context->config_include_depth--; if (ret) { krb5_set_error_message(context, ret, "Failed to parse plist %s", fname); @@ -480,6 +568,7 @@ krb5_config_parse_file_multi (krb5_context context, ret = _krb5_expand_path_tokens(context, fname, &exp_fname); if (ret) { + context->config_include_depth--; if (newfname) free(newfname); return ret; @@ -490,9 +579,11 @@ krb5_config_parse_file_multi (krb5_context context, fname = newfname = exp_fname; #endif + f.context = context; f.f = fopen(fname, "r"); f.s = NULL; if(f.f == NULL) { + context->config_include_depth--; ret = errno; krb5_set_error_message (context, ret, "open %s: %s", fname, strerror(ret)); @@ -502,6 +593,7 @@ krb5_config_parse_file_multi (krb5_context context, } ret = krb5_config_parse_debug (&f, res, &lineno, &str); + context->config_include_depth--; fclose(f.f); if (ret) { krb5_set_error_message (context, ret, "%s:%u: %s", @@ -1305,6 +1397,8 @@ krb5_config_parse_string_multi(krb5_context context, unsigned lineno = 0; krb5_error_code ret; struct fileptr f; + + f.context = context; f.f = NULL; f.s = string; diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 49c614d5efe..f9c40e36390 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -262,6 +262,7 @@ typedef struct krb5_context_data { int32_t kdc_sec_offset; int32_t kdc_usec_offset; krb5_config_section *cf; + size_t config_include_depth; struct et_list *et_list; struct krb5_log_facility *warn_dest; struct krb5_log_facility *debug_dest; -- 2.16.1