From eba0e62f47c43496a0d2fba32b99b3a65558e4a9 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Wed, 3 Mar 2010 16:23:50 +0100
Subject: [PATCH] Make filter_users and filter_groups also per-domain

Fixes: 290
---
 src/config/SSSDConfigTest.py |    4 ++
 src/config/etc/sssd.api.conf |    2 +
 src/man/sssd.conf.5.xml      |    4 +-
 src/responder/nss/nsssrv.c   |   90 ++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
index 9f9e75f..ef761a2 100755
--- a/src/config/SSSDConfigTest.py
+++ b/src/config/SSSDConfigTest.py
@@ -413,6 +413,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
             'cache_credentials',
             'store_legacy_passwords',
             'use_fully_qualified_names',
+            'filter_users',
+            'filter_groups',
             'entry_cache_timeout',
             'lookup_family_order',
             'account_cache_expiration',
@@ -725,6 +727,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
             'cache_credentials',
             'store_legacy_passwords',
             'use_fully_qualified_names',
+            'filter_users',
+            'filter_groups',
             'entry_cache_timeout',
             'account_cache_expiration',
             'lookup_family_order',
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index 14ec308..3347d9f 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -56,6 +56,8 @@ use_fully_qualified_names = bool, None, false
 entry_cache_timeout = int, None, false
 lookup_family_order = str, None, false
 account_cache_expiration = int, None, false
+filter_users = list, str, false
+filter_groups = list, str, false
 
 # Special providers
 [provider/permit]
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index a3ec028..6303fcb 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -305,7 +305,9 @@
                         <para>
                             Exclude certain users from being fetched from the sss
                             NSS database. This is particulary useful for system
-                            accounts.
+                            accounts. This option can also be set per-domain or
+                            include fully-qualified names to filter only users from
+                            the particular domain.
                         </para>
                         <para>
                             Default: root
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 02150c9..7629ac0 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -68,9 +68,11 @@ static int nss_get_config(struct nss_ctx *nctx,
 {
     TALLOC_CTX *tmpctx;
     struct sss_domain_info *dom;
+    const char *conf_path;
     char *domain, *name;
-    char **filter_list;
+    char **filter_list = NULL;
     int ret, i;
+    bool filter_set;
 
     tmpctx = talloc_new(nctx);
     if (!tmpctx) return ENOMEM;
@@ -102,9 +104,50 @@ static int nss_get_config(struct nss_ctx *nctx,
         nctx->cache_refresh_percent = 0;
     }
 
+    filter_set = false;
+    for (dom = rctx->domains; dom; dom = dom->next) {
+        conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, dom->name);
+        if (!conf_path) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        talloc_zfree(filter_list);
+        ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
+                                        CONFDB_NSS_FILTER_USERS, &filter_list);
+        if (ret == ENOENT) continue;
+        if (ret != EOK) goto done;
+        filter_set = true;
+
+        for (i = 0; (filter_list && filter_list[i]); i++) {
+            ret = sss_parse_name(tmpctx, nctx->rctx->names,
+                                 filter_list[i], &domain, &name);
+            if (ret != EOK) {
+                DEBUG(1, ("Invalid name in filterUsers list: [%s] (%d)\n",
+                         filter_list[i], ret));
+                continue;
+            }
+
+            if (domain && strcmp(domain, dom->name)) {
+                DEBUG(1, ("Mismatch betwen domain name (%s) and name "
+                          "set in FQN  (%s), skipping user %s\n",
+                          dom->name, domain, name));
+                continue;
+            }
+
+            ret = nss_ncache_set_user(nctx->ncache, true, dom->name, name);
+            if (ret != EOK) {
+                DEBUG(1, ("Failed to store permanent user filter for [%s]"
+                          " (%d [%s])\n", filter_list[i],
+                          ret, strerror(ret)));
+                continue;
+            }
+        }
+    }
+
     ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
                                     CONFDB_NSS_FILTER_USERS, &filter_list);
-    if (ret == ENOENT) {
+    if (ret == ENOENT && !filter_set) {
         filter_list = talloc_array(tmpctx, char *, 2);
         filter_list[0] = talloc_strdup(tmpctx, "root");
         filter_list[1] = NULL;
@@ -146,9 +189,50 @@ static int nss_get_config(struct nss_ctx *nctx,
         }
     }
 
+    filter_set = false;
+    for (dom = rctx->domains; dom; dom = dom->next) {
+        conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL, dom->name);
+        if (!conf_path) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        talloc_zfree(filter_list);
+        ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
+                                        CONFDB_NSS_FILTER_GROUPS, &filter_list);
+        if (ret == ENOENT) continue;
+        if (ret != EOK) goto done;
+        filter_set = true;
+
+        for (i = 0; (filter_list && filter_list[i]); i++) {
+            ret = sss_parse_name(tmpctx, nctx->rctx->names,
+                                 filter_list[i], &domain, &name);
+            if (ret != EOK) {
+                DEBUG(1, ("Invalid name in filterGroups list: [%s] (%d)\n",
+                         filter_list[i], ret));
+                continue;
+            }
+
+            if (domain && strcmp(domain, dom->name)) {
+                DEBUG(1, ("Mismatch betwen domain name (%s) and name "
+                          "set in FQN  (%s), skipping group %s\n",
+                          dom->name, domain, name));
+                continue;
+            }
+
+            ret = nss_ncache_set_group(nctx->ncache, true, dom->name, name);
+            if (ret != EOK) {
+                DEBUG(1, ("Failed to store permanent group filter for [%s]"
+                          " (%d [%s])\n", filter_list[i],
+                          ret, strerror(ret)));
+                continue;
+            }
+        }
+    }
+
     ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
                                     CONFDB_NSS_FILTER_GROUPS, &filter_list);
-    if (ret == ENOENT) {
+    if (ret == ENOENT && !filter_set) {
         filter_list = talloc_array(tmpctx, char *, 2);
         filter_list[0] = talloc_strdup(tmpctx, "root");
         filter_list[1] = NULL;
-- 
1.6.6

