Blame SOURCES/0147-LDAP-retain-external-members.patch

905b4d
From 6fac5e5f0c54a0f92872ce1450606cfcb577a920 Mon Sep 17 00:00:00 2001
905b4d
From: Pavel Reichl <preichl@redhat.com>
905b4d
Date: Thu, 20 Nov 2014 18:27:04 +0000
905b4d
Subject: [PATCH] LDAP: retain external members
905b4d
MIME-Version: 1.0
905b4d
Content-Type: text/plain; charset=UTF-8
905b4d
Content-Transfer-Encoding: 8bit
905b4d
905b4d
When processing group membership check sysdb for group members from
905b4d
extern domain and include them in newly processed group membership as
905b4d
extern members are curently found only when initgroups() is called.
905b4d
905b4d
Resolves:
905b4d
https://fedorahosted.org/sssd/ticket/2492
905b4d
905b4d
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
905b4d
Reviewed-by: Sumit Bose <sbose@redhat.com>
905b4d
---
905b4d
 src/db/sysdb.h                         |   6 ++
905b4d
 src/db/sysdb_ops.c                     |  83 ++++++++++++++++++++++++++
905b4d
 src/providers/ldap/sdap_async_groups.c | 104 +++++++++++++++++++++++++++++++++
905b4d
 3 files changed, 193 insertions(+)
905b4d
905b4d
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
905b4d
index 5bd7f90acb685bbaff5c98f433c7dce8175c33ca..cdcdfd51d6146bee5b212e6acfe98c831b635d33 100644
905b4d
--- a/src/db/sysdb.h
905b4d
+++ b/src/db/sysdb.h
905b4d
@@ -1103,4 +1103,10 @@ errno_t sysdb_gpo_get_gpo_result_setting(TALLOC_CTX *mem_ctx,
905b4d
                                          const char *policy_setting_key,
905b4d
                                          const char **policy_setting_value);
905b4d
 
905b4d
+errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
905b4d
+                                  struct sss_domain_info *dom,
905b4d
+                                  const char *group_name,
905b4d
+                                  const char ***_sids,
905b4d
+                                  const char ***_dns,
905b4d
+                                  size_t *_n);
905b4d
 #endif /* __SYS_DB_H__ */
905b4d
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
905b4d
index 998046a2ca1c746b2032f430e5f9c4a7151e1dbc..768f9455329b136b3de9794ad127dd349f1eaa43 100644
905b4d
--- a/src/db/sysdb_ops.c
905b4d
+++ b/src/db/sysdb_ops.c
905b4d
@@ -3630,3 +3630,86 @@ errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx,
905b4d
     return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_UUID_FILTER,
905b4d
                                            uuid_str, attrs, res);
905b4d
 }
905b4d
+
905b4d
+errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
905b4d
+                                  struct sss_domain_info *dom,
905b4d
+                                  const char *group_name,
905b4d
+                                  const char ***_sids,
905b4d
+                                  const char ***_dns,
905b4d
+                                  size_t *_n)
905b4d
+{
905b4d
+    errno_t ret;
905b4d
+    size_t i, m_count;
905b4d
+    TALLOC_CTX *tmp_ctx;
905b4d
+    struct ldb_message *msg;
905b4d
+    struct ldb_message **members;
905b4d
+    const char *attrs[] = { SYSDB_SID_STR, NULL };
905b4d
+    const char **sids = NULL, **dns = NULL;
905b4d
+    size_t n = 0;
905b4d
+
905b4d
+    tmp_ctx = talloc_new(NULL);
905b4d
+    if (tmp_ctx == NULL) {
905b4d
+        return ENOMEM;
905b4d
+    }
905b4d
+
905b4d
+    ret = sysdb_search_group_by_name(tmp_ctx, dom, group_name, NULL, &msg;;
905b4d
+    if (ret != EOK) {
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    /* Get sid_str attribute of all elemets pointed to by group members */
905b4d
+    ret = sysdb_asq_search(tmp_ctx, dom, msg->dn, NULL, SYSDB_MEMBER, attrs,
905b4d
+                           &m_count, &members);
905b4d
+    if (ret != EOK) {
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    sids = talloc_array(tmp_ctx, const char*, m_count);
905b4d
+    if (sids == NULL) {
905b4d
+        ret = ENOMEM;
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    dns = talloc_array(tmp_ctx, const char*, m_count);
905b4d
+    if (dns == NULL) {
905b4d
+        ret = ENOMEM;
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    for (i=0; i < m_count; i++) {
905b4d
+        const char *sidstr;
905b4d
+
905b4d
+        sidstr = ldb_msg_find_attr_as_string(members[i], SYSDB_SID_STR, NULL);
905b4d
+
905b4d
+        if (sidstr != NULL) {
905b4d
+            sids[n] = talloc_steal(sids, sidstr);
905b4d
+
905b4d
+            dns[n] = talloc_steal(dns, ldb_dn_get_linearized(members[i]->dn));
905b4d
+            if (dns[n] == NULL) {
905b4d
+                ret = ENOMEM;
905b4d
+                goto done;
905b4d
+            }
905b4d
+            n++;
905b4d
+        }
905b4d
+    }
905b4d
+
905b4d
+    if (n == 0) {
905b4d
+        ret = ENOENT;
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    *_n = n;
905b4d
+    *_sids = talloc_steal(mem_ctx, sids);
905b4d
+    *_dns = talloc_steal(mem_ctx, dns);
905b4d
+
905b4d
+    ret = EOK;
905b4d
+
905b4d
+done:
905b4d
+    if (ret == ENOENT) {
905b4d
+        DEBUG(SSSDBG_TRACE_FUNC, "No such entry\n");
905b4d
+    } else if (ret) {
905b4d
+        DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
905b4d
+    }
905b4d
+    talloc_free(tmp_ctx);
905b4d
+    return ret;
905b4d
+}
905b4d
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
905b4d
index 8cf7f7ff1d414049f0694c7d2873556fc9dad741..c86b5c6b59a4de7e945b95cafae9149f681e2e18 100644
905b4d
--- a/src/providers/ldap/sdap_async_groups.c
905b4d
+++ b/src/providers/ldap/sdap_async_groups.c
905b4d
@@ -801,6 +801,87 @@ done:
905b4d
     return ret;
905b4d
 }
905b4d
 
905b4d
+static errno_t
905b4d
+are_sids_from_same_dom(const char *sid1, const char *sid2, bool *_result)
905b4d
+{
905b4d
+    size_t len_prefix_sid1;
905b4d
+    size_t len_prefix_sid2;
905b4d
+    char *rid1, *rid2;
905b4d
+    bool result;
905b4d
+
905b4d
+    rid1 = strrchr(sid1, '-');
905b4d
+    if (rid1 == NULL) {
905b4d
+        return EINVAL;
905b4d
+    }
905b4d
+
905b4d
+    rid2 = strrchr(sid2, '-');
905b4d
+    if (rid2 == NULL) {
905b4d
+        return EINVAL;
905b4d
+    }
905b4d
+
905b4d
+    len_prefix_sid1 = rid1 - sid1;
905b4d
+    len_prefix_sid2 = rid2 - sid2;
905b4d
+
905b4d
+    result = (len_prefix_sid1 == len_prefix_sid2) &&
905b4d
+        (strncmp(sid1, sid2, len_prefix_sid1) == 0);
905b4d
+
905b4d
+    *_result = result;
905b4d
+
905b4d
+    return EOK;
905b4d
+}
905b4d
+
905b4d
+static errno_t
905b4d
+retain_extern_members(TALLOC_CTX *mem_ctx,
905b4d
+                      struct sss_domain_info *dom,
905b4d
+                      const char *group_name,
905b4d
+                      const char *group_sid,
905b4d
+                      char ***_userdns,
905b4d
+                      size_t *_nuserdns)
905b4d
+{
905b4d
+    TALLOC_CTX *tmp_ctx;
905b4d
+    const char **sids, **dns;
905b4d
+    bool same_domain;
905b4d
+    errno_t ret;
905b4d
+    size_t i, n;
905b4d
+    size_t nuserdns = 0;
905b4d
+    const char **userdns = NULL;
905b4d
+
905b4d
+    tmp_ctx = talloc_new(NULL);
905b4d
+    if (tmp_ctx == NULL) {
905b4d
+        return ENOMEM;
905b4d
+    }
905b4d
+
905b4d
+    ret = sysdb_get_sids_of_members(tmp_ctx, dom, group_name, &sids, &dns, &n);
905b4d
+    if (ret != EOK) {
905b4d
+        if (ret != ENOENT) {
905b4d
+            DEBUG(SSSDBG_TRACE_ALL,
905b4d
+                  "get_sids_of_members failed: %d [%s]\n",
905b4d
+                  ret, sss_strerror(ret));
905b4d
+        }
905b4d
+        goto done;
905b4d
+    }
905b4d
+
905b4d
+    for (i=0; i < n; i++) {
905b4d
+        ret = are_sids_from_same_dom(group_sid, sids[i], &same_domain);
905b4d
+        if (ret == EOK && !same_domain) {
905b4d
+            DEBUG(SSSDBG_TRACE_ALL, "extern member: %s\n", dns[i]);
905b4d
+            nuserdns++;
905b4d
+            userdns = talloc_realloc(tmp_ctx, userdns, const char*, nuserdns);
905b4d
+            if (userdns == NULL) {
905b4d
+                ret = ENOMEM;
905b4d
+                goto done;
905b4d
+            }
905b4d
+            userdns[nuserdns-1] = talloc_steal(userdns, dns[i]);
905b4d
+        }
905b4d
+    }
905b4d
+    *_nuserdns = nuserdns;
905b4d
+    *_userdns = discard_const(talloc_steal(mem_ctx, userdns));
905b4d
+    ret = EOK;
905b4d
+
905b4d
+done:
905b4d
+    talloc_free(tmp_ctx);
905b4d
+    return ret;
905b4d
+}
905b4d
 
905b4d
 /* ==Save-Group-Memebrs=================================================== */
905b4d
 
905b4d
@@ -817,6 +898,7 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
905b4d
 {
905b4d
     struct ldb_message_element *el;
905b4d
     struct sysdb_attrs *group_attrs = NULL;
905b4d
+    const char *group_sid;
905b4d
     const char *group_name;
905b4d
     char **userdns = NULL;
905b4d
     size_t nuserdns = 0;
905b4d
@@ -843,6 +925,28 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
905b4d
         }
905b4d
     }
905b4d
 
905b4d
+    /* This is a temporal solution until the IPA provider is able to
905b4d
+     * resolve external group membership.
905b4d
+     * https://fedorahosted.org/sssd/ticket/2522
905b4d
+     */
905b4d
+    if (opts->schema_type == SDAP_SCHEMA_IPA_V1) {
905b4d
+        ret = sysdb_attrs_get_string(attrs, SYSDB_SID_STR, &group_sid);
905b4d
+        if (ret != EOK) {
905b4d
+            DEBUG(SSSDBG_TRACE_FUNC, "Failed to get group sid\n");
905b4d
+            group_sid = NULL;
905b4d
+        }
905b4d
+
905b4d
+        if (group_sid != NULL) {
905b4d
+            ret = retain_extern_members(memctx, dom, group_name, group_sid,
905b4d
+                                        &userdns, &nuserdns);
905b4d
+            if (ret != EOK) {
905b4d
+                DEBUG(SSSDBG_TRACE_INTERNAL,
905b4d
+                      "retain_extern_members failed: %d:[%s].\n",
905b4d
+                      ret, sss_strerror(ret));
905b4d
+            }
905b4d
+        }
905b4d
+    }
905b4d
+
905b4d
     ret = sysdb_attrs_get_el(attrs,
905b4d
                     opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el);
905b4d
     if (ret != EOK) {
905b4d
-- 
905b4d
1.9.3
905b4d