diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/db/sysdb.h | 6 | ||||
-rw-r--r-- | src/db/sysdb_ops.c | 83 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_groups.c | 104 |
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) { |