d738b9
From f1f6eabb88391b796ee0eec1bb5d207002696f3e Mon Sep 17 00:00:00 2001
d738b9
From: Greg Hudson <ghudson@mit.edu>
d738b9
Date: Wed, 6 Jun 2018 17:58:41 -0400
d738b9
Subject: [PATCH] Process profile includedir in sorted order
d738b9
d738b9
In the profile library, use k5_dir_filenames() so that files within an
d738b9
included directory are read in a predictable order (alphanumeric
d738b9
within the C locale).
d738b9
d738b9
ticket: 8686
d738b9
(cherry picked from commit f574eda48740ad192f51e9a382a205e2ea0e60ad)
d738b9
(cherry picked from commit 5d868264bca1771aa16abbc8cc0aefb0e1750a73)
d738b9
---
d738b9
 doc/admin/conf_files/krb5_conf.rst |  4 ++-
d738b9
 src/util/profile/prof_parse.c      | 56 +++++-------------------------
d738b9
 2 files changed, 12 insertions(+), 48 deletions(-)
d738b9
d738b9
diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
d738b9
index 1d9bc9e34..a959e0e60 100644
d738b9
--- a/doc/admin/conf_files/krb5_conf.rst
d738b9
+++ b/doc/admin/conf_files/krb5_conf.rst
d738b9
@@ -58,7 +58,9 @@ alphanumeric characters, dashes, or underscores.  Starting in release
d738b9
 1.15, files with names ending in ".conf" are also included, unless the
d738b9
 name begins with ".".  Included profile files are syntactically
d738b9
 independent of their parents, so each included file must begin with a
d738b9
-section header.
d738b9
+section header.  Starting in release 1.17, files are read in
d738b9
+alphanumeric order; in previous releases, they may be read in any
d738b9
+order.
d738b9
 
d738b9
 The krb5.conf file can specify that configuration should be obtained
d738b9
 from a loadable module, rather than the file itself, using the
d738b9
diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c
d738b9
index 1baceea9e..531e4a099 100644
d738b9
--- a/src/util/profile/prof_parse.c
d738b9
+++ b/src/util/profile/prof_parse.c
d738b9
@@ -246,59 +246,22 @@ static int valid_name(const char *filename)
d738b9
  * Include files within dirname.  Only files with names ending in ".conf", or
d738b9
  * consisting entirely of alphanumeric characters, dashes, and underscores are
d738b9
  * included.  This restriction avoids including editor backup files, .rpmsave
d738b9
- * files, and the like.
d738b9
+ * files, and the like.  Files are processed in alphanumeric order.
d738b9
  */
d738b9
 static errcode_t parse_include_dir(const char *dirname,
d738b9
                                    struct profile_node *root_section)
d738b9
 {
d738b9
-#ifdef _WIN32
d738b9
-    char *wildcard = NULL, *pathname;
d738b9
-    WIN32_FIND_DATA ffd;
d738b9
-    HANDLE handle;
d738b9
     errcode_t retval = 0;
d738b9
+    char **fnames, *pathname;
d738b9
+    int i;
d738b9
 
d738b9
-    if (asprintf(&wildcard, "%s\\*", dirname) < 0)
d738b9
-        return ENOMEM;
d738b9
-
d738b9
-    handle = FindFirstFile(wildcard, &ffd;;
d738b9
-    if (handle == INVALID_HANDLE_VALUE) {
d738b9
-        retval = PROF_FAIL_INCLUDE_DIR;
d738b9
-        goto cleanup;
d738b9
-    }
d738b9
-
d738b9
-    do {
d738b9
-        if (!valid_name(ffd.cFileName))
d738b9
-            continue;
d738b9
-        if (asprintf(&pathname, "%s\\%s", dirname, ffd.cFileName) < 0) {
d738b9
-            retval = ENOMEM;
d738b9
-            break;
d738b9
-        }
d738b9
-        retval = parse_include_file(pathname, root_section);
d738b9
-        free(pathname);
d738b9
-        if (retval)
d738b9
-            break;
d738b9
-    } while (FindNextFile(handle, &ffd) != 0);
d738b9
-
d738b9
-    FindClose(handle);
d738b9
-
d738b9
-cleanup:
d738b9
-    free(wildcard);
d738b9
-    return retval;
d738b9
-
d738b9
-#else /* not _WIN32 */
d738b9
-
d738b9
-    DIR     *dir;
d738b9
-    char    *pathname;
d738b9
-    errcode_t retval = 0;
d738b9
-    struct dirent *ent;
d738b9
-
d738b9
-    dir = opendir(dirname);
d738b9
-    if (dir == NULL)
d738b9
+    if (k5_dir_filenames(dirname, &fnames) != 0)
d738b9
         return PROF_FAIL_INCLUDE_DIR;
d738b9
-    while ((ent = readdir(dir)) != NULL) {
d738b9
-        if (!valid_name(ent->d_name))
d738b9
+
d738b9
+    for (i = 0; fnames != NULL && fnames[i] != NULL; i++) {
d738b9
+        if (!valid_name(fnames[i]))
d738b9
             continue;
d738b9
-        if (asprintf(&pathname, "%s/%s", dirname, ent->d_name) < 0) {
d738b9
+        if (asprintf(&pathname, "%s/%s", dirname, fnames[i]) < 0) {
d738b9
             retval = ENOMEM;
d738b9
             break;
d738b9
         }
d738b9
@@ -307,9 +270,8 @@ cleanup:
d738b9
         if (retval)
d738b9
             break;
d738b9
     }
d738b9
-    closedir(dir);
d738b9
+    k5_free_filenames(fnames);
d738b9
     return retval;
d738b9
-#endif /* not _WIN32 */
d738b9
 }
d738b9
 
d738b9
 static errcode_t parse_line(char *line, struct parse_state *state,