From ae947485ccd95196d9e24a4dbedc3e7e9593b07f Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 29 Sep 2014 12:12:01 +0200 Subject: [PATCH 10/15] sysdb: add sysdb_getgrnam_with_views and sysdb_getgrgid_with_views --- src/db/sysdb.h | 13 ++++ src/db/sysdb_search.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/db/sysdb_views.c | 130 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+) diff --git a/src/db/sysdb.h b/src/db/sysdb.h index b65fa1d..f7e507c 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -475,6 +475,9 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain, struct ldb_message *obj, struct ldb_message *override_obj); +errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + struct ldb_message *obj); + errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, @@ -485,6 +488,16 @@ errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx, uid_t uid, struct ldb_result **res); +int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **res); + +int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + gid_t gid, + struct ldb_result **res); + struct ldb_message_element * sss_view_ldb_msg_find_element(struct sss_domain_info *dom, const struct ldb_message *msg, diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c index cbabee9..4077dd4 100644 --- a/src/db/sysdb_search.c +++ b/src/db/sysdb_search.c @@ -339,6 +339,92 @@ static int mpg_res_convert(struct ldb_result *res) return EOK; } +int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **res) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_result *orig_obj = NULL; + struct ldb_result *override_obj = NULL; + struct ldb_message_element *el; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + /* If there are views we first have to search the overrides for matches */ + if (DOM_HAS_VIEWS(domain)) { + ret = sysdb_search_group_override_by_name(tmp_ctx, domain, name, + &override_obj, &orig_obj); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_search_group_override_by_name failed.\n"); + goto done; + } + } + + /* If there are no views or nothing was found in the overrides the + * original objects are searched. */ + if (orig_obj == NULL) { + ret = sysdb_getgrnam(tmp_ctx, domain, name, &orig_obj); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_getgrnam failed.\n"); + goto done; + } + } + + /* If there are views we have to check if override values must be added to + * the original object. */ + if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) { + el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); + if (el != NULL && el->num_values != 0) { + DEBUG(SSSDBG_TRACE_ALL, + "Group object [%s], contains ghost entries which must be " \ + "resolved before overrides can be applied.\n", + ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); + ret = ENOENT; + goto done; + } + + ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], + override_obj == NULL ? NULL : override_obj ->msgs[0]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n"); + goto done; + } + + ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_add_group_member_overrides failed.\n"); + goto done; + } + } + + *res = talloc_steal(mem_ctx, orig_obj); + ret = EOK; + /* TODO: check if EOK is returned even if orig_obj is empty, i.e nothing + * found. */ + +done: + if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_ALL, "Returning empty result.\n"); + *res = talloc_zero(mem_ctx, struct ldb_result); + if (*res == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + ret = ENOMEM; + } else { + ret = EOK; + } + } + + talloc_free(tmp_ctx); + return ret; +} + int sysdb_getgrnam(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, const char *name, @@ -407,6 +493,92 @@ done: return ret; } +int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + gid_t gid, + struct ldb_result **res) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_result *orig_obj = NULL; + struct ldb_result *override_obj = NULL; + struct ldb_message_element *el; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + /* If there are views we first have to search the overrides for matches */ + if (DOM_HAS_VIEWS(domain)) { + ret = sysdb_search_group_override_by_gid(tmp_ctx, domain, gid, + &override_obj, &orig_obj); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_search_group_override_by_gid failed.\n"); + goto done; + } + } + + /* If there are no views or nothing was found in the overrides the + * original objects are searched. */ + if (orig_obj == NULL) { + ret = sysdb_getgrgid(tmp_ctx, domain, gid, &orig_obj); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_getgrgid failed.\n"); + goto done; + } + } + + /* If there are views we have to check if override values must be added to + * the original object. */ + if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) { + el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); + if (el != NULL && el->num_values != 0) { + DEBUG(SSSDBG_TRACE_ALL, + "Group object [%s], contains ghost entries which must be " \ + "resolved before overrides can be applied.\n", + ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); + ret = ENOENT; + goto done; + } + + ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], + override_obj == NULL ? NULL : override_obj ->msgs[0]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n"); + goto done; + } + + ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_add_group_member_overrides failed.\n"); + goto done; + } + } + + *res = talloc_steal(mem_ctx, orig_obj); + ret = EOK; + /* TODO: check if EOK is returned even if orig_obj is empty, i.e nothing + * found. */ + +done: + if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_ALL, "Returning empty result.\n"); + *res = talloc_zero(mem_ctx, struct ldb_result); + if (*res == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + ret = ENOMEM; + } else { + ret = EOK; + } + } + + talloc_free(tmp_ctx); + return ret; +} + int sysdb_getgrgid(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, gid_t gid, diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c index aa6d53c..62b131f 100644 --- a/src/db/sysdb_views.c +++ b/src/db/sysdb_views.c @@ -1057,6 +1057,136 @@ done: return ret; } +errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + struct ldb_message *obj) +{ + int ret; + size_t c; + struct ldb_message_element *members; + TALLOC_CTX *tmp_ctx; + struct ldb_dn *member_dn; + struct ldb_result *member_obj; + struct ldb_result *override_obj; + static const char *member_attrs[] = SYSDB_PW_ATTRS; + const char *override_dn_str; + struct ldb_dn *override_dn; + const char *memberuid; + + members = ldb_msg_find_element(obj, SYSDB_MEMBER); + if (members == NULL || members->num_values == 0) { + DEBUG(SSSDBG_TRACE_ALL, "Group has no members.\n"); + return EOK; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + ret = ENOMEM; + goto done; + } + + for (c = 0; c < members->num_values; c++) { + member_dn = ldb_dn_from_ldb_val(tmp_ctx, domain->sysdb->ldb, + &members->values[c]); + if (member_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_from_ldb_val failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = ldb_search(domain->sysdb->ldb, member_dn, &member_obj, member_dn, + LDB_SCOPE_BASE, member_attrs, NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + if (member_obj->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Base search for member object returned [%d] results.\n", + member_obj->count); + ret = EINVAL; + goto done; + } + + override_dn_str = ldb_msg_find_attr_as_string(member_obj->msgs[0], + SYSDB_OVERRIDE_DN, NULL); + if (override_dn_str == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Missing override DN for objext [%s].\n", + ldb_dn_get_linearized(member_obj->msgs[0]->dn)); + ret = ENOENT; + goto done; + } + + override_dn = ldb_dn_new(member_obj, domain->sysdb->ldb, + override_dn_str); + if (override_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); + ret = ENOMEM; + goto done; + } + + memberuid = NULL; + if (ldb_dn_compare(member_obj->msgs[0]->dn, override_dn) != 0) { + DEBUG(SSSDBG_TRACE_ALL, "Checking override for object [%s].\n", + ldb_dn_get_linearized(member_obj->msgs[0]->dn)); + + ret = ldb_search(domain->sysdb->ldb, member_obj, &override_obj, + override_dn, LDB_SCOPE_BASE, member_attrs, NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + if (override_obj->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Base search for override object returned [%d] results.\n", + member_obj->count); + ret = EINVAL; + goto done; + } + + memberuid = ldb_msg_find_attr_as_string(override_obj->msgs[0], + SYSDB_NAME, + NULL); + } + + if (memberuid == NULL) { + DEBUG(SSSDBG_TRACE_ALL, "No override name available.\n"); + + memberuid = ldb_msg_find_attr_as_string(member_obj->msgs[0], + SYSDB_NAME, + NULL); + if (memberuid == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Object [%s] has no name.\n", + ldb_dn_get_linearized(member_obj->msgs[0]->dn)); + ret = EINVAL; + goto done; + } + } + + ret = ldb_msg_add_string(obj, OVERRIDE_PREFIX SYSDB_MEMBERUID, + memberuid); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + /* Free all temporary data of the current member to avoid memory usage + * spikes. All temporary data should be allocated below member_dn. */ + talloc_free(member_dn); + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} + struct ldb_message_element * sss_view_ldb_msg_find_element(struct sss_domain_info *dom, const struct ldb_message *msg, -- 1.8.3.1