summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/db/sysdb.h6
-rw-r--r--src/db/sysdb_ops.c83
-rw-r--r--src/providers/ldap/sdap_async_groups.c104
3 files changed, 193 insertions, 0 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 5bd7f90ac..cdcdfd51d 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -1103,4 +1103,10 @@ errno_t sysdb_gpo_get_gpo_result_setting(TALLOC_CTX *mem_ctx,
const char *policy_setting_key,
const char **policy_setting_value);
+errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *dom,
+ const char *group_name,
+ const char ***_sids,
+ const char ***_dns,
+ size_t *_n);
#endif /* __SYS_DB_H__ */
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 998046a2c..768f94553 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -3630,3 +3630,86 @@ errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx,
return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_UUID_FILTER,
uuid_str, attrs, res);
}
+
+errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *dom,
+ const char *group_name,
+ const char ***_sids,
+ const char ***_dns,
+ size_t *_n)
+{
+ errno_t ret;
+ size_t i, m_count;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_message *msg;
+ struct ldb_message **members;
+ const char *attrs[] = { SYSDB_SID_STR, NULL };
+ const char **sids = NULL, **dns = NULL;
+ size_t n = 0;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_search_group_by_name(tmp_ctx, dom, group_name, NULL, &msg);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* Get sid_str attribute of all elemets pointed to by group members */
+ ret = sysdb_asq_search(tmp_ctx, dom, msg->dn, NULL, SYSDB_MEMBER, attrs,
+ &m_count, &members);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ sids = talloc_array(tmp_ctx, const char*, m_count);
+ if (sids == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ dns = talloc_array(tmp_ctx, const char*, m_count);
+ if (dns == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (i=0; i < m_count; i++) {
+ const char *sidstr;
+
+ sidstr = ldb_msg_find_attr_as_string(members[i], SYSDB_SID_STR, NULL);
+
+ if (sidstr != NULL) {
+ sids[n] = talloc_steal(sids, sidstr);
+
+ dns[n] = talloc_steal(dns, ldb_dn_get_linearized(members[i]->dn));
+ if (dns[n] == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ n++;
+ }
+ }
+
+ if (n == 0) {
+ ret = ENOENT;
+ goto done;
+ }
+
+ *_n = n;
+ *_sids = talloc_steal(mem_ctx, sids);
+ *_dns = talloc_steal(mem_ctx, dns);
+
+ ret = EOK;
+
+done:
+ if (ret == ENOENT) {
+ DEBUG(SSSDBG_TRACE_FUNC, "No such entry\n");
+ } else if (ret) {
+ DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index 8cf7f7ff1..c86b5c6b5 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -801,6 +801,87 @@ done:
return ret;
}
+static errno_t
+are_sids_from_same_dom(const char *sid1, const char *sid2, bool *_result)
+{
+ size_t len_prefix_sid1;
+ size_t len_prefix_sid2;
+ char *rid1, *rid2;
+ bool result;
+
+ rid1 = strrchr(sid1, '-');
+ if (rid1 == NULL) {
+ return EINVAL;
+ }
+
+ rid2 = strrchr(sid2, '-');
+ if (rid2 == NULL) {
+ return EINVAL;
+ }
+
+ len_prefix_sid1 = rid1 - sid1;
+ len_prefix_sid2 = rid2 - sid2;
+
+ result = (len_prefix_sid1 == len_prefix_sid2) &&
+ (strncmp(sid1, sid2, len_prefix_sid1) == 0);
+
+ *_result = result;
+
+ return EOK;
+}
+
+static errno_t
+retain_extern_members(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *dom,
+ const char *group_name,
+ const char *group_sid,
+ char ***_userdns,
+ size_t *_nuserdns)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char **sids, **dns;
+ bool same_domain;
+ errno_t ret;
+ size_t i, n;
+ size_t nuserdns = 0;
+ const char **userdns = NULL;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_get_sids_of_members(tmp_ctx, dom, group_name, &sids, &dns, &n);
+ if (ret != EOK) {
+ if (ret != ENOENT) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "get_sids_of_members failed: %d [%s]\n",
+ ret, sss_strerror(ret));
+ }
+ goto done;
+ }
+
+ for (i=0; i < n; i++) {
+ ret = are_sids_from_same_dom(group_sid, sids[i], &same_domain);
+ if (ret == EOK && !same_domain) {
+ DEBUG(SSSDBG_TRACE_ALL, "extern member: %s\n", dns[i]);
+ nuserdns++;
+ userdns = talloc_realloc(tmp_ctx, userdns, const char*, nuserdns);
+ if (userdns == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ userdns[nuserdns-1] = talloc_steal(userdns, dns[i]);
+ }
+ }
+ *_nuserdns = nuserdns;
+ *_userdns = discard_const(talloc_steal(mem_ctx, userdns));
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
/* ==Save-Group-Memebrs=================================================== */
@@ -817,6 +898,7 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
{
struct ldb_message_element *el;
struct sysdb_attrs *group_attrs = NULL;
+ const char *group_sid;
const char *group_name;
char **userdns = NULL;
size_t nuserdns = 0;
@@ -843,6 +925,28 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
}
}
+ /* This is a temporal solution until the IPA provider is able to
+ * resolve external group membership.
+ * https://fedorahosted.org/sssd/ticket/2522
+ */
+ if (opts->schema_type == SDAP_SCHEMA_IPA_V1) {
+ ret = sysdb_attrs_get_string(attrs, SYSDB_SID_STR, &group_sid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Failed to get group sid\n");
+ group_sid = NULL;
+ }
+
+ if (group_sid != NULL) {
+ ret = retain_extern_members(memctx, dom, group_name, group_sid,
+ &userdns, &nuserdns);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ "retain_extern_members failed: %d:[%s].\n",
+ ret, sss_strerror(ret));
+ }
+ }
+ }
+
ret = sysdb_attrs_get_el(attrs,
opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el);
if (ret != EOK) {