URL: https://github.com/SSSD/sssd/pull/485
Author: justin-stephenson
 Title: #485:  Support alternative sources for the files provider 
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/485/head:pr485
git checkout pr485
From dd3366f37ab5410d39091b4f240f8d7d8627521e Mon Sep 17 00:00:00 2001
From: Justin Stephenson <[email protected]>
Date: Fri, 14 Jul 2017 16:08:37 -0400
Subject: [PATCH 1/2] CONFDB: Add passwd_files and group_files options

Add new options to the files provider allowing an administrator to
configure the files provider to read and monitor multiple or
non-standard passwd and group file sources. These options default to
/etc/passwd and /etc/group when unset.
---
 Makefile.am                               |  3 ++-
 src/confdb/confdb.h                       |  4 ++++
 src/config/SSSDConfig/__init__.py.in      |  6 +++++-
 src/config/cfg_rules.ini                  |  4 ++++
 src/config/etc/sssd.api.d/sssd-files.conf |  3 +++
 src/man/sssd-files.5.xml                  | 36 +++++++++++++++++++++++++++++--
 src/providers/files/files_init.c          |  1 +
 7 files changed, 53 insertions(+), 4 deletions(-)
 create mode 100644 src/config/etc/sssd.api.d/sssd-files.conf

diff --git a/Makefile.am b/Makefile.am
index 5917bd904..e7b1d18e2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4532,7 +4532,8 @@ dist_sssdapiplugin_DATA = \
     src/config/etc/sssd.api.d/sssd-ldap.conf \
     src/config/etc/sssd.api.d/sssd-local.conf \
     src/config/etc/sssd.api.d/sssd-proxy.conf \
-    src/config/etc/sssd.api.d/sssd-simple.conf
+    src/config/etc/sssd.api.d/sssd-simple.conf \
+    src/config/etc/sssd.api.d/sssd-files.conf
 
 edit_cmd = $(SED) \
         -e 's|@sbindir[@]|$(sbindir)|g' \
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 147194962..92dd69f17 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -242,6 +242,10 @@
 #define CONFDB_PROXY_FAST_ALIAS "proxy_fast_alias"
 #define CONFDB_PROXY_MAX_CHILDREN "proxy_max_children"
 
+/* Files Provider */
+#define CONFDB_FILES_PASSWD "passwd_files"
+#define CONFDB_FILES_GROUP "group_files"
+
 /* Secrets Service */
 #define CONFDB_SEC_CONF_ENTRY "config/secrets"
 #define CONFDB_SEC_CONTAINERS_NEST_LEVEL "containers_nest_level"
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index d2bb709d6..f37ccab46 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -473,7 +473,11 @@ option_strings = {
     'proxy_fast_alias' : _('Whether to look up canonical group name from cache if possible'),
 
     # [provider/proxy/auth]
-    'proxy_pam_target' : _('PAM stack to use')
+    'proxy_pam_target' : _('PAM stack to use'),
+
+    # [provider/files]
+    'passwd_files' : _('Path of passwd file sources.'),
+    'group_files' : _('Path of group file sources.')
 }
 
 def striplist(l):
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index 4e70bf7b6..551322780 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -404,6 +404,10 @@ option = dyndns_force_tcp
 option = dyndns_auth
 option = dyndns_server
 
+# files provider specific options
+option = passwd_files
+option = group_files
+
 # local provider specific options
 option = create_homedir
 option = remove_homedir
diff --git a/src/config/etc/sssd.api.d/sssd-files.conf b/src/config/etc/sssd.api.d/sssd-files.conf
new file mode 100644
index 000000000..2444d4924
--- /dev/null
+++ b/src/config/etc/sssd.api.d/sssd-files.conf
@@ -0,0 +1,3 @@
+[provider/files]
+passwd_files = str, None, false
+group_files = str, None, false
diff --git a/src/man/sssd-files.5.xml b/src/man/sssd-files.5.xml
index d44fffc03..59e1b6523 100644
--- a/src/man/sssd-files.5.xml
+++ b/src/man/sssd-files.5.xml
@@ -56,14 +56,46 @@
     <refsect1 id='configuration-options'>
         <title>CONFIGURATION OPTIONS</title>
         <para>
-            The files provider has no specific options of its own, however,
-            generic SSSD domain options can be set where applicable.
+            In addition to the options listed below, generic SSSD domain options
+            can be set where applicable.
             Refer to the section <quote>DOMAIN SECTIONS</quote> of the
             <citerefentry>
                 <refentrytitle>sssd.conf</refentrytitle>
                 <manvolnum>5</manvolnum>
             </citerefentry> manual page for details on the configuration
             of an SSSD domain.
+            <variablelist>
+                <varlistentry>
+                    <term>passwd_files (string)</term>
+                    <listitem>
+                        <para>
+                            Comma-separated list of one or multiple password
+                            filenames to be read and enumerated by the files
+                            provider, inotify monitor watches will be set on
+                            each file to detect changes dynamically.
+                        </para>
+                        <para>
+                            Default: /etc/passwd
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>group_files (string)</term>
+                    <listitem>
+                        <para>
+                            Comma-separated list of one or multiple group
+                            filenames to be read and enumerated by the files
+                            provider, inotify monitor watches will be set on
+                            each file to detect changes dynamically.
+                        </para>
+                        <para>
+                            Default: /etc/group
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+            </variablelist>
         </para>
     </refsect1>
 
diff --git a/src/providers/files/files_init.c b/src/providers/files/files_init.c
index 8e5cd4cf9..b8a051c34 100644
--- a/src/providers/files/files_init.c
+++ b/src/providers/files/files_init.c
@@ -21,6 +21,7 @@
 
 #include "providers/data_provider/dp.h"
 #include "providers/files/files_private.h"
+#include "util/util.h"
 
 int sssm_files_init(TALLOC_CTX *mem_ctx,
                     struct be_ctx *be_ctx,

From 62f1cce65c160f1441bd0232be5daed4943940fb Mon Sep 17 00:00:00 2001
From: Justin Stephenson <[email protected]>
Date: Mon, 17 Jul 2017 15:01:36 -0400
Subject: [PATCH 2/2] FILES: Handle files provider sources

Setup watches on passwd and group files provided with the files provider
options passwd_files and group_files lists

Resolves:
https://pagure.io/SSSD/sssd/issue/3402
---
 src/providers/files/files_init.c    | 183 ++++++++++++++++++++++++++++++++----
 src/providers/files/files_ops.c     | 146 +++++++++++++++-------------
 src/providers/files/files_private.h |  12 ++-
 3 files changed, 257 insertions(+), 84 deletions(-)

diff --git a/src/providers/files/files_init.c b/src/providers/files/files_init.c
index b8a051c34..3b93b7036 100644
--- a/src/providers/files/files_init.c
+++ b/src/providers/files/files_init.c
@@ -23,6 +23,156 @@
 #include "providers/files/files_private.h"
 #include "util/util.h"
 
+#define DEFAULT_PASSWD_FILE "/etc/passwd"
+#define DEFAULT_GROUP_FILE "/etc/group"
+
+
+static errno_t files_init_file_sources(TALLOC_CTX *mem_ctx,
+                                    struct be_ctx *be_ctx,
+                                    const char ***_passwd_files,
+                                    const char ***_group_files,
+                                    int *_num_passwd_files,
+                                    int *_num_group_files)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    char *conf_passwd_files;
+    char *conf_group_files;
+    char **passwd_list = NULL;
+    char **group_list = NULL;
+    int num_passwd_files = 0;
+    int num_group_files = 0;
+    const char **passwd_files = NULL;
+    const char **group_files = NULL;
+    int i;
+    errno_t ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path,
+                            CONFDB_FILES_PASSWD, NULL, &conf_passwd_files);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to retrieve confdb passwd files!\n");
+        goto done;
+    }
+
+    ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path,
+                            CONFDB_FILES_GROUP, NULL, &conf_group_files);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to retrieve confdb group files!\n");
+        goto done;
+    }
+
+    /* Default to /etc/passwd standard */
+    if (conf_passwd_files == NULL) {
+        num_passwd_files = 1;
+
+        passwd_files = talloc_zero_array(tmp_ctx, const char *, 2);
+        if (passwd_files == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "Using default passwd file: [%s].\n", DEFAULT_PASSWD_FILE);
+        passwd_files[0] = talloc_strdup(passwd_files, DEFAULT_PASSWD_FILE);
+        if (passwd_files[0] == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+    /* Retrieve list of passwd files */
+    } else {
+        ret = split_on_separator(tmp_ctx, conf_passwd_files, ',', true, true,
+                                 &passwd_list, &num_passwd_files);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Failed to parse passwd list!\n");
+            goto done;
+        }
+
+        passwd_files = talloc_zero_array(tmp_ctx, const char *,
+                                         num_passwd_files + 1);
+        if (passwd_files == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        for (i = 0; i < num_passwd_files; i++) {
+            DEBUG(SSSDBG_TRACE_FUNC,
+                  "Using passwd file: [%s].\n", passwd_list[i]);
+
+            passwd_files[i] = talloc_strdup(passwd_files, passwd_list[i]);
+                if (passwd_files[i] == NULL) {
+                    ret = ENOMEM;
+                    goto done;
+                }
+        }
+    }
+
+    /* Default to /etc/group standard */
+    if (conf_group_files == NULL) {
+        num_group_files = 1;
+
+        group_files = talloc_zero_array(tmp_ctx, const char *, 2);
+        if (group_files == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "Using default group file: [%s].\n", DEFAULT_GROUP_FILE);
+        group_files[0] = talloc_strdup(group_files, DEFAULT_GROUP_FILE);
+        if (group_files[0] == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+    /* Retrieve list of group files */
+    } else {
+        ret = split_on_separator(tmp_ctx, conf_group_files, ',', true, true,
+                                 &group_list, &num_group_files);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Failed to parse group files!\n");
+            goto done;
+        }
+
+        group_files = talloc_zero_array(tmp_ctx, const char *,
+                                         num_group_files + 1);
+        if (group_files == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+            ret = ENOMEM;
+            goto done;
+        }
+
+        for (i = 0; i < num_group_files; i++) {
+            DEBUG(SSSDBG_TRACE_FUNC,
+                  "Using group file: [%s].\n", group_list[i]);
+            group_files[i] = talloc_strdup(group_files, group_list[i]);
+                if (group_files[i] == NULL) {
+                    ret = ENOMEM;
+                    goto done;
+                }
+        }
+    }
+
+    *_passwd_files = talloc_steal(mem_ctx, passwd_files);
+    *_group_files = talloc_steal(mem_ctx, group_files);
+    *_num_passwd_files = num_passwd_files;
+    *_num_group_files = num_group_files;
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 int sssm_files_init(TALLOC_CTX *mem_ctx,
                     struct be_ctx *be_ctx,
                     struct data_provider *provider,
@@ -30,32 +180,33 @@ int sssm_files_init(TALLOC_CTX *mem_ctx,
                     void **_module_data)
 {
     struct files_id_ctx *ctx;
-    int ret;
-    const char *passwd_file = NULL;
-    const char *group_file = NULL;
-
-    /* So far this is mostly useful for tests */
-    passwd_file = getenv("SSS_FILES_PASSWD");
-    if (passwd_file == NULL) {
-        passwd_file = "/etc/passwd";
-    }
+    const char **passwd_files = NULL;
+    const char **group_files = NULL;
+    int num_passwd_files = 0;
+    int num_group_files = 0;
+    errno_t ret;
 
-    group_file = getenv("SSS_FILES_GROUP");
-    if (group_file == NULL) {
-        group_file = "/etc/group";
-    }
+    ret = files_init_file_sources(mem_ctx, be_ctx, &passwd_files,
+                               &group_files, &num_passwd_files,
+                               &num_group_files);
 
     ctx = talloc_zero(mem_ctx, struct files_id_ctx);
     if (ctx == NULL) {
         return ENOMEM;
     }
+
     ctx->be = be_ctx;
     ctx->domain = be_ctx->domain;
-    ctx->passwd_file = passwd_file;
-    ctx->group_file = group_file;
+    ctx->passwd_files = passwd_files;
+    ctx->group_files = group_files;
+    ctx->num_passwd_files = num_passwd_files;
+    ctx->num_group_files = num_group_files;
 
     ctx->fctx = sf_init(ctx, be_ctx->ev,
-                        ctx->passwd_file, ctx->group_file,
+                        ctx->passwd_files,
+                        ctx->group_files,
+                        ctx->num_passwd_files,
+                        ctx->num_group_files,
                         ctx);
     if (ctx->fctx == NULL) {
         ret = ENOMEM;
diff --git a/src/providers/files/files_ops.c b/src/providers/files/files_ops.c
index b59a94252..2f35f8e81 100644
--- a/src/providers/files/files_ops.c
+++ b/src/providers/files/files_ops.c
@@ -44,6 +44,7 @@ struct files_ctx {
 
 static errno_t enum_files_users(TALLOC_CTX *mem_ctx,
                                 struct files_id_ctx *id_ctx,
+                                const char *passwd_file,
                                 struct passwd ***_users)
 {
     errno_t ret, close_ret;
@@ -53,12 +54,12 @@ static errno_t enum_files_users(TALLOC_CTX *mem_ctx,
     FILE *pwd_handle = NULL;
     size_t n_users = 0;
 
-    pwd_handle = fopen(id_ctx->passwd_file, "r");
+    pwd_handle = fopen(passwd_file, "r");
     if (pwd_handle == NULL) {
         ret = errno;
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Cannot open passwd file %s [%d]\n",
-              id_ctx->passwd_file, ret);
+              passwd_file, ret);
         goto done;
     }
 
@@ -133,7 +134,7 @@ static errno_t enum_files_users(TALLOC_CTX *mem_ctx,
             close_ret = errno;
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Cannot close passwd file %s [%d]\n",
-                  id_ctx->passwd_file, close_ret);
+                  passwd_file, close_ret);
         }
     }
     return ret;
@@ -141,6 +142,7 @@ static errno_t enum_files_users(TALLOC_CTX *mem_ctx,
 
 static errno_t enum_files_groups(TALLOC_CTX *mem_ctx,
                                  struct files_id_ctx *id_ctx,
+                                 const char *group_file,
                                  struct group ***_groups)
 {
     errno_t ret, close_ret;
@@ -150,12 +152,12 @@ static errno_t enum_files_groups(TALLOC_CTX *mem_ctx,
     size_t n_groups = 0;
     FILE *grp_handle = NULL;
 
-    grp_handle = fopen(id_ctx->group_file, "r");
+    grp_handle = fopen(group_file, "r");
     if (grp_handle == NULL) {
         ret = errno;
         DEBUG(SSSDBG_CRIT_FAILURE,
               "Cannot open group file %s [%d]\n",
-              id_ctx->group_file, ret);
+              group_file, ret);
         goto done;
     }
 
@@ -237,7 +239,7 @@ static errno_t enum_files_groups(TALLOC_CTX *mem_ctx,
             close_ret = errno;
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Cannot close group file %s [%d]\n",
-                  id_ctx->group_file, close_ret);
+                  group_file, close_ret);
         }
     }
     return ret;
@@ -446,9 +448,11 @@ static errno_t refresh_override_attrs(struct files_id_ctx *id_ctx,
     return ret;
 }
 
-static errno_t sf_enum_groups(struct files_id_ctx *id_ctx);
+static errno_t sf_enum_groups(struct files_id_ctx *id_ctx,
+                              const char *group_file);
 
-errno_t sf_enum_users(struct files_id_ctx *id_ctx)
+errno_t sf_enum_users(struct files_id_ctx *id_ctx,
+                      const char *passwd_file)
 {
     errno_t ret;
     errno_t tret;
@@ -461,7 +465,8 @@ errno_t sf_enum_users(struct files_id_ctx *id_ctx)
         return ENOMEM;
     }
 
-    ret = enum_files_users(tmp_ctx, id_ctx, &users);
+    ret = enum_files_users(tmp_ctx, id_ctx, passwd_file,
+                           &users);
     if (ret != EOK) {
         goto done;
     }
@@ -472,13 +477,6 @@ errno_t sf_enum_users(struct files_id_ctx *id_ctx)
     }
     in_transaction = true;
 
-    /* remove previous cache contents */
-    /* FIXME - this is terribly inefficient */
-    ret = delete_all_users(id_ctx->domain);
-    if (ret != EOK) {
-        goto done;
-    }
-
     for (size_t i = 0; users[i]; i++) {
         ret = save_file_user(id_ctx, users[i]);
         if (ret != EOK) {
@@ -502,16 +500,6 @@ errno_t sf_enum_users(struct files_id_ctx *id_ctx)
     }
     in_transaction = false;
 
-    /* Covers the case when someone edits /etc/group, adds a group member and
-     * only then edits passwd and adds the user. The reverse is not needed,
-     * because member/memberof links are established when groups are saved.
-     */
-    ret = sf_enum_groups(id_ctx);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, "Cannot refresh groups\n");
-        goto done;
-    }
-
     ret = EOK;
 done:
     if (in_transaction) {
@@ -698,7 +686,8 @@ static errno_t save_file_group(struct files_id_ctx *id_ctx,
     return ret;
 }
 
-static errno_t sf_enum_groups(struct files_id_ctx *id_ctx)
+static errno_t sf_enum_groups(struct files_id_ctx *id_ctx,
+                              const char *group_file)
 {
     errno_t ret;
     errno_t tret;
@@ -712,7 +701,8 @@ static errno_t sf_enum_groups(struct files_id_ctx *id_ctx)
         return ENOMEM;
     }
 
-    ret = enum_files_groups(tmp_ctx, id_ctx, &groups);
+    ret = enum_files_groups(tmp_ctx, id_ctx, group_file,
+                            &groups);
     if (ret != EOK) {
         goto done;
     }
@@ -728,12 +718,6 @@ static errno_t sf_enum_groups(struct files_id_ctx *id_ctx)
     }
     in_transaction = true;
 
-    /* remove previous cache contents */
-    ret = delete_all_groups(id_ctx->domain);
-    if (ret != EOK) {
-        goto done;
-    }
-
     for (size_t i = 0; groups[i]; i++) {
         ret = save_file_group(id_ctx, groups[i], cached_users);
         if (ret != EOK) {
@@ -791,13 +775,6 @@ static int sf_passwd_cb(const char *filename, uint32_t flags, void *pvt)
 
     DEBUG(SSSDBG_TRACE_FUNC, "passwd notification\n");
 
-    if (strcmp(filename, id_ctx->passwd_file) != 0) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Wrong file, expected %s, got %s\n",
-              id_ctx->passwd_file, filename);
-        return EINVAL;
-    }
-
     id_ctx->updating_passwd = true;
     dp_sbus_domain_inconsistent(id_ctx->be->provider, id_ctx->domain);
 
@@ -805,7 +782,16 @@ static int sf_passwd_cb(const char *filename, uint32_t flags, void *pvt)
     dp_sbus_reset_users_memcache(id_ctx->be->provider);
     dp_sbus_reset_initgr_memcache(id_ctx->be->provider);
 
-    ret = sf_enum_users(id_ctx);
+    ret = delete_all_users(id_ctx->domain);
+    if (ret != EOK) {
+        return ret;
+    }
+
+    /* All users were deleted, therefore we need to enumerate each file again */
+    for (size_t i = 0; i < id_ctx->num_passwd_files; i++)
+    {
+        ret = sf_enum_users(id_ctx, id_ctx->passwd_files[i]);
+    }
 
     id_ctx->updating_passwd = false;
     sf_cb_done(id_ctx);
@@ -825,13 +811,6 @@ static int sf_group_cb(const char *filename, uint32_t flags, void *pvt)
 
     DEBUG(SSSDBG_TRACE_FUNC, "group notification\n");
 
-    if (strcmp(filename, id_ctx->group_file) != 0) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Wrong file, expected %s, got %s\n",
-              id_ctx->group_file, filename);
-        return EINVAL;
-    }
-
     id_ctx->updating_groups = true;
     dp_sbus_domain_inconsistent(id_ctx->be->provider, id_ctx->domain);
 
@@ -839,7 +818,16 @@ static int sf_group_cb(const char *filename, uint32_t flags, void *pvt)
     dp_sbus_reset_groups_memcache(id_ctx->be->provider);
     dp_sbus_reset_initgr_memcache(id_ctx->be->provider);
 
-    ret = sf_enum_groups(id_ctx);
+    ret = delete_all_groups(id_ctx->domain);
+    if (ret != EOK) {
+        return ret;
+    }
+
+    /* All users were deleted, therefore we need to enumerate each file again */
+    for (size_t i = 0; i < id_ctx->num_group_files; i++)
+    {
+        ret = sf_enum_groups(id_ctx, id_ctx->group_files[i]);
+    }
 
     id_ctx->updating_groups = false;
     sf_cb_done(id_ctx);
@@ -853,19 +841,40 @@ static void startup_enum_files(struct tevent_context *ev,
 {
     struct files_id_ctx *id_ctx = talloc_get_type(pvt, struct files_id_ctx);
     errno_t ret;
+    int i;
 
     talloc_zfree(imm);
 
-    ret = sf_enum_users(id_ctx);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Enumerating users failed, data might be inconsistent!\n");
+    for (i = 0; i < id_ctx->num_passwd_files; i++) {
+        if (fopen(id_ctx->passwd_files[i], "r") == NULL) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  "Cannot open passwd file [%s]\n", id_ctx->passwd_files[i]);
+            continue;
+        }
+
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "Startup enumeration of [%s]\n", id_ctx->passwd_files[i]);
+        ret = sf_enum_users(id_ctx, id_ctx->passwd_files[i]);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Enumerating users failed, data might be inconsistent!\n");
+        }
     }
 
-    ret = sf_enum_groups(id_ctx);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Enumerating groups failed, data might be inconsistent!\n");
+    for (i = 0; i < id_ctx->num_group_files; i++) {
+        if (fopen(id_ctx->group_files[i], "r") == NULL) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  "Cannot open group file [%s]\n", id_ctx->group_files[i]);
+            continue;
+        }
+
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "Startup enumeration of [%s]\n", id_ctx->group_files[i]);
+        ret = sf_enum_groups(id_ctx, id_ctx->group_files[i]);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Enumerating groups failed, data might be inconsistent!\n");
+        }
     }
 }
 
@@ -884,22 +893,31 @@ static struct snotify_ctx *sf_setup_watch(TALLOC_CTX *mem_ctx,
 
 struct files_ctx *sf_init(TALLOC_CTX *mem_ctx,
                           struct tevent_context *ev,
-                          const char *passwd_file,
-                          const char *group_file,
+                          const char **passwd_files,
+                          const char **group_files,
+                          int num_passwd_files,
+                          int num_group_files,
                           struct files_id_ctx *id_ctx)
 {
     struct files_ctx *fctx;
     struct tevent_immediate *imm;
+    int i;
 
     fctx = talloc(mem_ctx, struct files_ctx);
     if (fctx == NULL) {
         return NULL;
     }
 
-    fctx->pwd_watch = sf_setup_watch(fctx, ev, passwd_file,
-                                     sf_passwd_cb, id_ctx);
-    fctx->grp_watch = sf_setup_watch(fctx, ev, group_file,
-                                     sf_group_cb, id_ctx);
+    for (i = 0; i < num_passwd_files; i++) {
+        fctx->pwd_watch = sf_setup_watch(fctx, ev, passwd_files[i],
+                                         sf_passwd_cb, id_ctx);
+        }
+
+    for (i = 0; i < num_group_files; i++) {
+        fctx->grp_watch = sf_setup_watch(fctx, ev, group_files[i],
+                                         sf_group_cb, id_ctx);
+    }
+
     if (fctx->pwd_watch == NULL || fctx->grp_watch == NULL) {
         talloc_free(fctx);
         return NULL;
diff --git a/src/providers/files/files_private.h b/src/providers/files/files_private.h
index a7d195c90..0dcb772e8 100644
--- a/src/providers/files/files_private.h
+++ b/src/providers/files/files_private.h
@@ -39,8 +39,10 @@ struct files_id_ctx {
     struct sss_domain_info *domain;
     struct files_ctx *fctx;
 
-    const char *passwd_file;
-    const char *group_file;
+    const char **passwd_files;
+    const char **group_files;
+    int num_passwd_files;
+    int num_group_files;
 
     bool updating_passwd;
     bool updating_groups;
@@ -53,8 +55,10 @@ struct files_id_ctx {
 /* files_ops.c */
 struct files_ctx *sf_init(TALLOC_CTX *mem_ctx,
                           struct tevent_context *ev,
-                          const char *passwd_file,
-                          const char *group_file,
+                          const char **passwd_files,
+                          const char **group_files,
+                          int num_passwd_files,
+                          int num_group_files,
                           struct files_id_ctx *id_ctx);
 
 /* files_id.c */
_______________________________________________
sssd-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to