From 47c866000c64e8609d40148d498cabd1fd84512f Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 25 Sep 2014 09:38:26 +0200 Subject: [PATCH 05/15] sysdb: add sysdb_getpwnam/uid_with_views() View-aware drop-in replacements for sysdb_getpwnam() and sysdb_getpwuid(). --- src/db/sysdb.h | 24 +++++++++ src/db/sysdb_search.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/db/sysdb_views.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 286 insertions(+) diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 8d4759e..2db1a1c 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -201,6 +201,7 @@ SYSDB_SID_STR, \ SYSDB_UPN, \ SYSDB_OVERRIDE_DN, \ + SYSDB_OVERRIDE_OBJECT_DN, \ SYSDB_DEFAULT_OVERRIDE_NAME, \ NULL} @@ -210,6 +211,7 @@ SYSDB_DEFAULT_ATTRS, \ SYSDB_SID_STR, \ SYSDB_OVERRIDE_DN, \ + SYSDB_OVERRIDE_OBJECT_DN, \ SYSDB_DEFAULT_OVERRIDE_NAME, \ NULL} @@ -456,10 +458,32 @@ errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx, struct ldb_result **override_obj, struct ldb_result **orig_obj); +errno_t sysdb_search_user_override_by_uid(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + uid_t uid, + struct ldb_result **override_obj, + struct ldb_result **orig_obj); + +errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + gid_t gid, + struct ldb_result **override_obj, + struct ldb_result **orig_obj); + errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain, struct ldb_message *obj, struct ldb_message *override_obj); +errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **res); + +errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + uid_t uid, + struct ldb_result **res); + /* Sysdb initialization. * call this function *only* once to initialize the database and get * the sysdb ctx */ diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c index d51d213..8860719 100644 --- a/src/db/sysdb_search.c +++ b/src/db/sysdb_search.c @@ -83,6 +83,73 @@ done: return ret; } +errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **res) +{ + int ret; + struct ldb_result *orig_obj = NULL; + struct ldb_result *override_obj = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + /* If there are views we first have to search the overrides for matches */ + if (DOM_HAS_VIEWS(domain)) { + ret = sysdb_search_user_override_by_name(tmp_ctx, domain, name, + &override_obj, &orig_obj); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_search_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_getpwnam(tmp_ctx, domain, name, &orig_obj); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_getpwnam 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) { + ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], + override_obj == NULL ? NULL : override_obj ->msgs[0]); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n"); + goto done; + } + + if (ret == ENOENT) { + *res = talloc_zero(mem_ctx, struct ldb_result); + if (*res == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + ret = ENOMEM; + } else { + ret = EOK; + } + goto done; + } + } + + *res = talloc_steal(mem_ctx, orig_obj); + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + int sysdb_getpwuid(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, uid_t uid, @@ -121,6 +188,73 @@ done: return ret; } +errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + uid_t uid, + struct ldb_result **res) +{ + int ret; + struct ldb_result *orig_obj = NULL; + struct ldb_result *override_obj = NULL; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + /* If there are views we first have to search the overrides for matches */ + if (DOM_HAS_VIEWS(domain)) { + ret = sysdb_search_user_override_by_uid(tmp_ctx, domain, uid, + &override_obj, &orig_obj); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_search_user_override_by_uid 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_getpwuid(tmp_ctx, domain, uid, &orig_obj); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_getpwuid 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) { + ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], + override_obj == NULL ? NULL : override_obj->msgs[0]); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n"); + goto done; + } + + if (ret == ENOENT) { + *res = talloc_zero(mem_ctx, struct ldb_result); + if (*res == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + ret = ENOMEM; + } else { + ret = EOK; + } + goto done; + } + } + + *res = talloc_steal(mem_ctx, orig_obj); + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + int sysdb_enumpwent(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, struct ldb_result **_res) diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c index 92f4b47..4634181 100644 --- a/src/db/sysdb_views.c +++ b/src/db/sysdb_views.c @@ -648,7 +648,9 @@ done: #define SYSDB_USER_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" +#define SYSDB_USER_UID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")("SYSDB_UIDNUM"=%lu))" #define SYSDB_GROUP_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" +#define SYSDB_GROUP_GID_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")("SYSDB_GIDNUM"=%lu))" enum override_object_type { OO_TYPE_UNDEF = 0, @@ -802,6 +804,132 @@ errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx, override_obj, orig_obj); } +static errno_t sysdb_search_override_by_id(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + unsigned long int id, + enum override_object_type type, + struct ldb_result **override_obj, + struct ldb_result **orig_obj) +{ + TALLOC_CTX *tmp_ctx; + static const char *user_attrs[] = SYSDB_PW_ATTRS; + static const char *group_attrs[] = SYSDB_GRSRC_ATTRS; + const char **attrs; + struct ldb_dn *base_dn; + struct ldb_result *override_res; + struct ldb_result *orig_res; + int ret; + const char *orig_obj_dn; + const char *filter; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, + SYSDB_TMPL_VIEW_SEARCH_BASE, domain->view_name); + if (base_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n"); + ret = ENOMEM; + goto done; + } + + switch(type) { + case OO_TYPE_USER: + filter = SYSDB_USER_UID_OVERRIDE_FILTER; + attrs = user_attrs; + break; + case OO_TYPE_GROUP: + filter = SYSDB_GROUP_GID_OVERRIDE_FILTER; + attrs = group_attrs; + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected override object type [%d].\n", + type); + ret = EINVAL; + goto done; + } + + ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &override_res, base_dn, + LDB_SCOPE_SUBTREE, attrs, filter, id); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + if (override_res->count == 0) { + DEBUG(SSSDBG_TRACE_FUNC, + "No user override found for %s with id [%lu].\n", + (type == OO_TYPE_USER ? "user" : "group"), id); + ret = ENOENT; + goto done; + } else if (override_res->count > 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Found more than one override for id [%lu]\n.", id); + ret = EINVAL; + goto done; + } + + if (orig_obj != NULL) { + orig_obj_dn = ldb_msg_find_attr_as_string(override_res->msgs[0], + SYSDB_OVERRIDE_OBJECT_DN, + NULL); + if (orig_obj_dn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Missing link to original object in override [%s].\n", + ldb_dn_get_linearized(override_res->msgs[0]->dn)); + ret = EINVAL; + goto done; + } + + base_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, orig_obj_dn); + if (base_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_res, base_dn, + LDB_SCOPE_BASE, attrs, NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + *orig_obj = talloc_steal(mem_ctx, orig_res); + } + + + *override_obj = talloc_steal(mem_ctx, override_res); + + ret = EOK; + +done: + talloc_zfree(tmp_ctx); + return ret; +} + +errno_t sysdb_search_user_override_by_uid(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + uid_t uid, + struct ldb_result **override_obj, + struct ldb_result **orig_obj) +{ + return sysdb_search_override_by_id(mem_ctx, domain, uid, OO_TYPE_USER, + override_obj, orig_obj); +} + +errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + gid_t gid, + struct ldb_result **override_obj, + struct ldb_result **orig_obj) +{ + return sysdb_search_override_by_id(mem_ctx, domain, gid, OO_TYPE_GROUP, + override_obj, orig_obj); +} + /** * @brief Add override data to the original object * -- 1.8.3.1