Blob Blame History Raw
From e7aee44602eb36ee1e1201ad6c7234562b8bb703 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Tue, 5 Dec 2017 21:14:09 +0100
Subject: [PATCH] SYSDB: Properly handle name/gid override when using domain
 resolution order
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When using name/gid override together with domain resolution order the
mpg name/gid may be returned instead of the overridden one.

In order to avoid that, let's add a check in case the domain supports
mpg so we can ensure that the originalADname and originalADgidNumber
attributes are the very same as the ones searched and then normally
proceed with the current flow in the code. In case those are not the
same, we *must* follow the code path for the non-mpg domains and then
return the proper values.

Resolves: https://pagure.io/SSSD/sssd/issue/3595

Signed-off-by: Fabiano FidĂȘncio <fidencio@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
(cherry picked from commit cf4f5e031ecbdfba0b55a4f69a06175a2e718e67)
---
 src/db/sysdb.h        |   2 +
 src/db/sysdb_search.c | 116 ++++++++++++++++++++++++++++++++++--------
 2 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 2660314a7..d9c8fd5d6 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -258,6 +258,8 @@
                            SYSDB_OVERRIDE_OBJECT_DN, \
                            SYSDB_DEFAULT_OVERRIDE_NAME, \
                            SYSDB_UUID, \
+                           ORIGINALAD_PREFIX SYSDB_NAME, \
+                           ORIGINALAD_PREFIX SYSDB_GIDNUM, \
                            NULL}
 
 #define SYSDB_NETGR_ATTRS {SYSDB_NAME, SYSDB_NETGROUP_TRIPLE, \
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
index b7ceb6e59..66c4977b3 100644
--- a/src/db/sysdb_search.c
+++ b/src/db/sysdb_search.c
@@ -893,8 +893,9 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
     const char *fmt_filter;
     char *sanitized_name;
     struct ldb_dn *base_dn;
-    struct ldb_result *res;
+    struct ldb_result *res = NULL;
     char *lc_sanitized_name;
+    const char *originalad_sanitized_name;
     int ret;
 
     tmp_ctx = talloc_new(NULL);
@@ -902,30 +903,67 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
         return ENOMEM;
     }
 
+    ret = sss_filter_sanitize_for_dom(tmp_ctx, name, domain,
+                                      &sanitized_name, &lc_sanitized_name);
+    if (ret != EOK) {
+        goto done;
+    }
+
     if (domain->mpg) {
+        /* In case the domain supports magic private groups we *must*
+         * check whether the searched name is the very same as the
+         * originalADname attribute.
+         *
+         * In case those are not the same, we're dealing with an
+         * override and in order to return the proper overridden group
+         * we must use the very same search used by a non-mpg domain
+         */
         fmt_filter = SYSDB_GRNAM_MPG_FILTER;
         base_dn = sysdb_domain_dn(tmp_ctx, domain);
+        if (base_dn == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+                         LDB_SCOPE_SUBTREE, attrs, fmt_filter,
+                         lc_sanitized_name, sanitized_name, sanitized_name);
+        if (ret != EOK) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        if (res->count > 0) {
+            originalad_sanitized_name = ldb_msg_find_attr_as_string(
+                    res->msgs[0], ORIGINALAD_PREFIX SYSDB_NAME, NULL);
+
+            if (originalad_sanitized_name != NULL
+                    && strcmp(originalad_sanitized_name, sanitized_name) != 0) {
+                fmt_filter = SYSDB_GRNAM_FILTER;
+                base_dn = sysdb_group_base_dn(tmp_ctx, domain);
+                res = NULL;
+            }
+        }
     } else {
         fmt_filter = SYSDB_GRNAM_FILTER;
         base_dn = sysdb_group_base_dn(tmp_ctx, domain);
     }
-    if (!base_dn) {
+    if (base_dn == NULL) {
         ret = ENOMEM;
         goto done;
     }
 
-    ret = sss_filter_sanitize_for_dom(tmp_ctx, name, domain,
-                                      &sanitized_name, &lc_sanitized_name);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
-                     LDB_SCOPE_SUBTREE, attrs, fmt_filter,
-                     lc_sanitized_name, sanitized_name, sanitized_name);
-    if (ret) {
-        ret = sysdb_error_to_errno(ret);
-        goto done;
+    /* We just do the ldb_search here in case domain is *not* a MPG *or*
+     * it's a MPG and we're dealing with a overriden group, which has to
+     * use the very same filter as a non MPG domain. */
+    if (res == NULL) {
+        ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+                         LDB_SCOPE_SUBTREE, attrs, fmt_filter,
+                         lc_sanitized_name, sanitized_name, sanitized_name);
+        if (ret != EOK) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
     }
 
     ret = mpg_res_convert(res);
@@ -1045,10 +1083,11 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
 {
     TALLOC_CTX *tmp_ctx;
     unsigned long int ul_gid = gid;
+    unsigned long int ul_originalad_gid;
     static const char *attrs[] = SYSDB_GRSRC_ATTRS;
     const char *fmt_filter;
     struct ldb_dn *base_dn;
-    struct ldb_result *res;
+    struct ldb_result *res = NULL;
     int ret;
 
     tmp_ctx = talloc_new(NULL);
@@ -1057,22 +1096,57 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
     }
 
     if (domain->mpg) {
+        /* In case the domain supports magic private groups we *must*
+         * check whether the searched gid is the very same as the
+         * originalADgidNumber attribute.
+         *
+         * In case those are not the same, we're dealing with an
+         * override and in order to return the proper overridden group
+         * we must use the very same search used by a non-mpg domain
+         */
         fmt_filter = SYSDB_GRGID_MPG_FILTER;
         base_dn = sysdb_domain_dn(tmp_ctx, domain);
+        if (base_dn == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+                         LDB_SCOPE_SUBTREE, attrs, fmt_filter, ul_gid);
+        if (ret != EOK) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+
+        if (res->count > 0) {
+            ul_originalad_gid = ldb_msg_find_attr_as_uint64(
+                    res->msgs[0], ORIGINALAD_PREFIX SYSDB_GIDNUM, 0);
+
+            if (ul_originalad_gid != 0 && ul_originalad_gid != ul_gid) {
+                fmt_filter = SYSDB_GRGID_FILTER;
+                base_dn = sysdb_group_base_dn(tmp_ctx, domain);
+                res = NULL;
+            }
+        }
     } else {
         fmt_filter = SYSDB_GRGID_FILTER;
         base_dn = sysdb_group_base_dn(tmp_ctx, domain);
     }
-    if (!base_dn) {
+    if (base_dn == NULL) {
         ret = ENOMEM;
         goto done;
     }
 
-    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
-                     LDB_SCOPE_SUBTREE, attrs, fmt_filter, ul_gid);
-    if (ret) {
-        ret = sysdb_error_to_errno(ret);
-        goto done;
+    /* We just do the ldb_search here in case domain is *not* a MPG *or*
+     * it's a MPG and we're dealing with a overriden group, which has to
+     * use the very same filter as a non MPG domain. */
+    if (res == NULL) {
+        ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+                         LDB_SCOPE_SUBTREE, attrs, fmt_filter, ul_gid);
+        if (ret != EOK) {
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
     }
 
     ret = mpg_res_convert(res);
-- 
2.17.0