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