From 5596a3cb36c9f0d0b8ecbcd68f82bc3d7b040b55 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 20 Jul 2016 18:42:27 +0200 Subject: [PATCH 3/4] sysdb: add sysdb_get_user_members_recursively() --- src/db/sysdb.h | 5 ++ src/db/sysdb_ops.c | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+) diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 0cc550a4c389b4a1a2b78aff760f4b5cbf94e17f..405f89e2f1ac6fabc06e77c345de8693845f9d92 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -1257,6 +1257,11 @@ errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx, const char ***_dns, size_t *_n); +errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx, + struct sss_domain_info *dom, + struct ldb_dn *group_dn, + struct ldb_result **members); + errno_t sysdb_handle_original_uuid(const char *orig_name, struct sysdb_attrs *src_attrs, const char *src_name, diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c index 19d6be03ede1bcec3bc7a4ed777e326460d80591..b7c04cb4ab64c2767e211d6ead1463a3a3024e68 100644 --- a/src/db/sysdb_ops.c +++ b/src/db/sysdb_ops.c @@ -4711,6 +4711,212 @@ done: return ret; } +static +errno_t sysdb_get_user_members_recursively_int(TALLOC_CTX *mem_ctx, + struct sss_domain_info *dom, + struct ldb_dn *group_dn, + hash_table_t *users, + hash_table_t *groups) +{ + errno_t ret; + size_t c; + size_t m_count; + struct ldb_message **members; + const char *oc; + hash_key_t key; + hash_value_t value; + int hret; + + /* Get all elemets pointed to by group members */ + ret = sysdb_asq_search(mem_ctx, dom, group_dn, NULL, SYSDB_MEMBER, + NULL /* requesting all attributes */, + &m_count, &members); + if (ret != EOK) { + if (ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_asq_search failed.\n"); + } + goto done; + } + + key.type = HASH_KEY_STRING; + + for (c = 0; c < m_count; c++) { + + oc = ldb_msg_find_attr_as_string(members[c], SYSDB_OBJECTCLASS, NULL); + if (oc == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing objectclass in object [%s].\n", + ldb_dn_get_linearized(members[c]->dn)); + ret = EINVAL; + goto done; + } + + if (strcmp(oc, SYSDB_USER_CLASS) == 0) { + key.str = discard_const(ldb_dn_get_linearized(members[c]->dn)); + if (key.str == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized failed.\n"); + ret = EFAULT; + goto done; + } + + value.type = HASH_VALUE_PTR; + value.ptr = members[c]; + + hret = hash_enter(users, &key, &value); + if (hret != HASH_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "hash_enter failed.\n"); + ret = ENOMEM; + goto done; + } + + } else if (strcmp(oc, SYSDB_GROUP_CLASS) == 0) { + key.str = discard_const(ldb_dn_get_linearized(members[c]->dn)); + if (key.str == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized failed.\n"); + ret = EFAULT; + goto done; + } + + hret = hash_lookup(groups, &key, &value); + if (hret == HASH_SUCCESS) { + /* Already seen this group, skipping */ + continue; + } else if (hret != HASH_ERROR_KEY_NOT_FOUND) { + DEBUG(SSSDBG_OP_FAILURE, "hash_lookup failed.\n"); + ret = EFAULT; + goto done; + } + + /* group was not found in the hash, adding and processing it */ + + value.type = HASH_VALUE_PTR; + value.ptr = members[c]; + + hret = hash_enter(groups, &key, &value); + if (hret != HASH_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "hash_enter failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = sysdb_get_user_members_recursively_int(mem_ctx, dom, + members[c]->dn, + users, groups); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_get_user_members_recursively_int failed.\n"); + goto done; + } + + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unexpected objectclass [%s] in object [%s].\n", oc, + ldb_dn_get_linearized(members[c]->dn)); + ret = EINVAL; + goto done; + } + } + + ret = EOK; + +done: + + return ret; +} + +errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx, + struct sss_domain_info *dom, + struct ldb_dn *group_dn, + struct ldb_result **members) +{ + TALLOC_CTX *tmp_ctx; + hash_table_t *users; + hash_table_t *groups; + int ret; + int hret; + size_t c; + unsigned long count; + struct ldb_result *res; + hash_value_t *values; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sss_hash_create(tmp_ctx, 10, &users); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n"); + goto done; + } + + ret = sss_hash_create(tmp_ctx, 10, &groups); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n"); + goto done; + } + + ret = sysdb_get_user_members_recursively_int(tmp_ctx, dom, group_dn, users, + groups); + if (ret != EOK) { + if (ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_get_user_members_recursively_int failed.\n"); + } + goto done; + } + + res = talloc_zero(tmp_ctx, struct ldb_result); + if (res == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + ret = ENOMEM; + goto done; + } + + hret = hash_values(users, &count, &values); + if (hret != HASH_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "hash_values failed.\n"); + ret = ENOMEM; + goto done; + } + if (count <= UINTMAX_MAX) { + res->count = count; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, "More then [%"PRIuMAX"] results.\n", + UINTMAX_MAX); + ret = EINVAL; + goto done; + } + if (res->count == 0) { + ret = EOK; + goto done; + } + + res->msgs = talloc_array(res, struct ldb_message *, res->count); + if (res->msgs == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n"); + ret = ENOMEM; + goto done; + } + + for (c = 0; c < res->count; c++) { + res->msgs[c] = (struct ldb_message *) talloc_steal(res->msgs, + values[c].ptr); + } + + ret = EOK; + +done: + if (ret == EOK) { + *members = talloc_steal(mem_ctx, res); + } else if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_FUNC, "No such entry\n"); + } else { + DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret)); + } + talloc_free(tmp_ctx); + return ret; +} + errno_t sysdb_handle_original_uuid(const char *orig_name, struct sysdb_attrs *src_attrs, const char *src_name, -- 2.1.0