Blob Blame History Raw
From 8d55e0fffd29184d44cb49eaab2ca3a4226e0123 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 10 Dec 2013 10:14:28 +0100
Subject: [PATCH 26/31] AD: filter domain local groups for trusted/sub domains

In Active Directory groups with a domain local scope should only be used
inside of the specific domain. Since SSSD read the group memberships
from LDAP server of the user's domain the domain local groups are
included in the LDAP result. Those groups should be filtered out if the
domain is a sub/trusted domain, i.e. is not the domain the client
running SSSD is joined to.

The groups will still be in the cache but marked as non-POSIX groups and
no GID will be assigned.

Fixes https://fedorahosted.org/sssd/ticket/2178
---
 src/providers/ldap/sdap.h                     |   8 ++
 src/providers/ldap/sdap_async_groups.c        | 160 ++++++++++++++++----------
 src/providers/ldap/sdap_async_initgroups_ad.c |   6 +-
 src/providers/ldap/sdap_async_nested_groups.c |  28 ++++-
 4 files changed, 138 insertions(+), 64 deletions(-)

diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index fa641730bb78b6a96c0b9640af7612b876f56533..a7ea94eb810a96b61862bd8cc6fcd800c3e8e0cb 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -137,6 +137,14 @@ struct sdap_ppolicy_data {
 #define SDAP_AD_USN "uSNChanged"
 #define SDAP_AD_LAST_USN "highestCommittedUSN"
 
+#define SDAP_AD_GROUP_TYPE_BUILTIN      0x00000001
+#define SDAP_AD_GROUP_TYPE_GLOBAL       0x00000002
+#define SDAP_AD_GROUP_TYPE_DOMAIN_LOCAL 0x00000004
+#define SDAP_AD_GROUP_TYPE_UNIVERSAL    0x00000008
+#define SDAP_AD_GROUP_TYPE_APP_BASIC    0x00000010
+#define SDAP_AD_GROUP_TYPE_APP_QUERY    0x00000020
+#define SDAP_AD_GROUP_TYPE_SECURITY     0x80000000
+
 enum sdap_basic_opt {
     SDAP_URI = 0,
     SDAP_BACKUP_URI,
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index 9f7e3e55d0234e9aa7b9e59456044587bcad88ef..33648c5da367c908d085a71a9a9017cb294bb300 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -451,6 +451,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     bool posix_group;
     bool use_id_mapping;
     char *sid_str;
+    int32_t ad_group_type;
 
     tmpctx = talloc_new(NULL);
     if (!tmpctx) {
@@ -503,74 +504,113 @@ static int sdap_save_group(TALLOC_CTX *memctx,
     }
     DEBUG(SSSDBG_TRACE_FUNC, ("Processing group %s\n", group_name));
 
-    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
-                                                               dom->name,
-                                                               sid_str);
-    if (use_id_mapping) {
-        posix_group = true;
-
-        if (sid_str == NULL) {
-            DEBUG(SSSDBG_MINOR_FAILURE, ("SID not available, cannot map a " \
-                                         "unix ID to group [%s].\n", group_name));
-            ret = ENOENT;
+    posix_group = true;
+    if (opts->schema_type == SDAP_SCHEMA_AD) {
+        ret = sysdb_attrs_get_int32_t(attrs, SYSDB_GROUP_TYPE, &ad_group_type);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_int32_t failed.\n"));
             goto done;
         }
 
-        DEBUG(SSSDBG_TRACE_LIBS,
-              ("Mapping group [%s] objectSID [%s] to unix ID\n",
-               group_name, sid_str));
-
-        /* Convert the SID into a UNIX group ID */
-        ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &gid);
-        if (ret == ENOTSUP) {
-            /* ENOTSUP is returned if built-in SID was provided
-             * => do not store the group, but return EOK */
-            DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n"));
-            ret = EOK;
-            goto done;
-        } else if (ret != EOK) {
-            DEBUG(SSSDBG_MINOR_FAILURE,
-                  ("Could not convert SID string: [%s]\n",
-                   strerror(ret)));
-            goto done;
+        DEBUG(SSSDBG_TRACE_ALL, ("AD group [%s] has type flags %#x.",
+                                 group_name, ad_group_type));
+        /* Only security groups from AD are considered for POSIX groups.
+         * Additionally only global and universal group are taken to account
+         * for trusted domains. */
+        if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY)
+                || (IS_SUBDOMAIN(dom)
+                    && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL)
+                        || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) {
+            posix_group = false;
+            gid = 0;
+            DEBUG(SSSDBG_TRACE_FUNC, ("Filtering AD group [%s].\n",
+                                      group_name));
+            ret = sysdb_attrs_add_uint32(group_attrs,
+                                         opts->group_map[SDAP_AT_GROUP_GID].sys_name, 0);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      ("Failed to add a GID to non-posix group!\n"));
+                return ret;
+            }
+            ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, false);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                      ("Error: Failed to mark group as non-posix!\n"));
+                return ret;
+            }
         }
+    }
 
-        /* Store the GID in the ldap_attrs so it doesn't get
-         * treated as a missing attribute from LDAP and removed.
-         */
-        ret = sdap_replace_id(attrs, SYSDB_GIDNUM, gid);
-        if (ret) {
-            DEBUG(SSSDBG_OP_FAILURE, ("Cannot set the id-mapped GID\n"));
-            goto done;
-        }
-    } else {
-        ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix_group);
-        if (ret == ENOENT) {
+    if (posix_group) {
+        use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx,
+                                                                   dom->name,
+                                                                   sid_str);
+        if (use_id_mapping) {
             posix_group = true;
-        } else if (ret != EOK) {
-            DEBUG(SSSDBG_MINOR_FAILURE,
-                  ("Error reading posix attribute: [%s]\n",
-                   strerror(ret)));
-            goto done;
-        }
 
-        DEBUG(8, ("This is%s a posix group\n", (posix_group)?"":" not"));
-        ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, posix_group);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_MINOR_FAILURE,
-                  ("Error setting posix attribute: [%s]\n",
-                   strerror(ret)));
-            goto done;
-        }
+            if (sid_str == NULL) {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("SID not available, cannot map a " \
+                                             "unix ID to group [%s].\n", group_name));
+                ret = ENOENT;
+                goto done;
+            }
 
-        ret = sysdb_attrs_get_uint32_t(attrs,
-                                       opts->group_map[SDAP_AT_GROUP_GID].sys_name,
-                                       &gid);
-        if (ret != EOK) {
-            DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",
-                      group_name, dom->name));
-            ret = EINVAL;
-            goto done;
+            DEBUG(SSSDBG_TRACE_LIBS,
+                  ("Mapping group [%s] objectSID [%s] to unix ID\n",
+                   group_name, sid_str));
+
+            /* Convert the SID into a UNIX group ID */
+            ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &gid);
+            if (ret == ENOTSUP) {
+                /* ENOTSUP is returned if built-in SID was provided
+                 * => do not store the group, but return EOK */
+                DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n"));
+                ret = EOK;
+                goto done;
+            } else if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Could not convert SID string: [%s]\n",
+                       strerror(ret)));
+                goto done;
+            }
+
+            /* Store the GID in the ldap_attrs so it doesn't get
+             * treated as a missing attribute from LDAP and removed.
+             */
+            ret = sdap_replace_id(attrs, SYSDB_GIDNUM, gid);
+            if (ret) {
+                DEBUG(SSSDBG_OP_FAILURE, ("Cannot set the id-mapped GID\n"));
+                goto done;
+            }
+        } else {
+            ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix_group);
+            if (ret == ENOENT) {
+                posix_group = true;
+            } else if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Error reading posix attribute: [%s]\n",
+                       strerror(ret)));
+                goto done;
+            }
+
+            DEBUG(8, ("This is%s a posix group\n", (posix_group)?"":" not"));
+            ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, posix_group);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Error setting posix attribute: [%s]\n",
+                       strerror(ret)));
+                goto done;
+            }
+
+            ret = sysdb_attrs_get_uint32_t(attrs,
+                                           opts->group_map[SDAP_AT_GROUP_GID].sys_name,
+                                           &gid);
+            if (ret != EOK) {
+                DEBUG(1, ("no gid provided for [%s] in domain [%s].\n",
+                          group_name, dom->name));
+                ret = EINVAL;
+                goto done;
+            }
         }
     }
 
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
index 8e0506831cb189415b62efaa378d3dc7ec350cde..f1bf77e8614c30b214118140e380c23c40c1195b 100644
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
@@ -1145,6 +1145,7 @@ static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req)
 
 struct sdap_ad_tokengroups_initgroups_state {
     bool use_id_mapping;
+    struct sss_domain_info *domain;
 };
 
 static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq);
@@ -1175,8 +1176,9 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
     }
 
     state->use_id_mapping = use_id_mapping;
+    state->domain = domain;
 
-    if (state->use_id_mapping) {
+    if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) {
         subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts,
                                                          sysdb, domain, sh,
                                                          name, orig_dn,
@@ -1216,7 +1218,7 @@ static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq)
     req = tevent_req_callback_data(subreq, struct tevent_req);
     state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state);
 
-    if (state->use_id_mapping) {
+    if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) {
         ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq);
     } else {
         ret = sdap_ad_tokengroups_initgr_posix_recv(subreq);
diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c
index c107b700b84b8c178051fd4505f3947be8373de2..f58564aec0628c827672950f767401ee32051b59 100644
--- a/src/providers/ldap/sdap_async_nested_groups.c
+++ b/src/providers/ldap/sdap_async_nested_groups.c
@@ -239,15 +239,39 @@ sdap_nested_group_hash_group(struct sdap_nested_group_ctx *group_ctx,
     struct sdap_attr_map *map = group_ctx->opts->group_map;
     gid_t gid;
     errno_t ret;
+    int32_t ad_group_type;
+    bool posix_group = true;
+
+    if (group_ctx->opts->schema_type == SDAP_SCHEMA_AD) {
+        ret = sysdb_attrs_get_int32_t(group, SYSDB_GROUP_TYPE, &ad_group_type);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_int32_t failed.\n"));
+            return ret;
+        }
+
+        DEBUG(SSSDBG_TRACE_ALL, ("AD group has type flags %#x.\n",
+                                 ad_group_type));
+        /* Only security groups from AD are considered for POSIX groups.
+         * Additionally only global and universal group are taken to account
+         * for trusted domains. */
+        if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY)
+                || (IS_SUBDOMAIN(group_ctx->domain)
+                    && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL)
+                        || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) {
+            posix_group = false;
+            gid = 0;
+            DEBUG(SSSDBG_TRACE_FUNC, ("Filtering AD group.\n"));
+        }
+    }
 
     ret = sysdb_attrs_get_uint32_t(group, map[SDAP_AT_GROUP_GID].sys_name,
                                    &gid);
-    if (ret == ENOENT || (ret == EOK && gid == 0)) {
+    if (ret == ENOENT || (ret == EOK && gid == 0) || !posix_group) {
         DEBUG(SSSDBG_TRACE_ALL,
              ("The group's gid was %s\n", ret == ENOENT ? "missing" : "zero"));
         DEBUG(SSSDBG_TRACE_INTERNAL,
              ("Marking group as non-posix and setting GID=0!\n"));
-        if (ret == ENOENT) {
+        if (ret == ENOENT || !posix_group) {
             ret = sysdb_attrs_add_uint32(group,
                                          map[SDAP_AT_GROUP_GID].sys_name, 0);
             if (ret != EOK) {
-- 
1.8.4.2