From 81c5978ad8c9ed2edc73fbbcf7fac1fedbb9125d Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Thu, 25 Sep 2014 09:36:51 +0200 Subject: [PATCH 04/15] sysdb: add overide lookup calls sysdb_search_user_override_by_name() and sysdb_search_group_override_by_name() search for overrides in the given view. sysdb_add_overrides_to_object() adds the data from the override object to the original object and makes them available for further processing. --- src/db/sysdb.h | 24 ++++- src/db/sysdb_views.c | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/util.h | 3 + 3 files changed, 312 insertions(+), 1 deletion(-) diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 6bb25de..8d4759e 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -43,6 +43,7 @@ #define SYSDB_TMPL_NETGROUP_BASE SYSDB_NETGROUP_CONTAINER","SYSDB_DOM_BASE #define SYSDB_TMPL_RANGE_BASE SYSDB_RANGE_CONTAINER","SYSDB_BASE #define SYSDB_TMPL_VIEW_BASE SYSDB_VIEW_CONTAINER","SYSDB_BASE +#define SYSDB_TMPL_VIEW_SEARCH_BASE "cn=%s,"SYSDB_TMPL_VIEW_BASE #define SYSDB_SUBDOMAIN_CLASS "subdomain" #define SYSDB_USER_CLASS "user" @@ -199,12 +200,17 @@ SYSDB_PRIMARY_GROUP_GIDNUM, \ SYSDB_SID_STR, \ SYSDB_UPN, \ + SYSDB_OVERRIDE_DN, \ + SYSDB_DEFAULT_OVERRIDE_NAME, \ NULL} #define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \ SYSDB_MEMBERUID, \ SYSDB_GHOST, \ SYSDB_DEFAULT_ATTRS, \ + SYSDB_SID_STR, \ + SYSDB_OVERRIDE_DN, \ + SYSDB_DEFAULT_OVERRIDE_NAME, \ NULL} #define SYSDB_NETGR_ATTRS {SYSDB_NAME, SYSDB_NETGROUP_TRIPLE, \ @@ -226,7 +232,7 @@ #define SYSDB_TMPL_CUSTOM_SUBTREE "cn=%s,"SYSDB_TMPL_CUSTOM_BASE #define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE #define SYSDB_TMPL_RANGE SYSDB_NAME"=%s,"SYSDB_TMPL_RANGE_BASE -#define SYSDB_TMPL_OVERRIDE SYSDB_OVERRIDE_ANCHOR_UUID"=%s,cn=%s,"SYSDB_TMPL_VIEW_BASE +#define SYSDB_TMPL_OVERRIDE SYSDB_OVERRIDE_ANCHOR_UUID"=%s,"SYSDB_TMPL_VIEW_SEARCH_BASE #define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD #define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE @@ -438,6 +444,22 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain, struct sysdb_attrs *override_attrs, struct ldb_dn *obj_dn); +errno_t sysdb_search_user_override_by_name(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **override_obj, + struct ldb_result **orig_obj); + +errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + 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); + /* Sysdb initialization. * call this function *only* once to initialize the database and get * the sysdb ctx */ diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c index c0fb915..92f4b47 100644 --- a/src/db/sysdb_views.c +++ b/src/db/sysdb_views.c @@ -371,6 +371,7 @@ errno_t sysdb_store_override(struct sss_domain_info *domain, goto done; } + /* TODO: add nameAlias for case-insentitive searches */ for (c = 0; c < attrs->num; c++) { msg->elements[c] = attrs->a[c]; msg->elements[c].flags = LDB_FLAG_MOD_ADD; @@ -583,6 +584,7 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain, } for (c = 0; allowed_attrs[c] != NULL; c++) { + /* TODO: add nameAlias for case-insentitive searches */ ret = sysdb_attrs_get_el_ext(override_attrs, allowed_attrs[c], false, &el); if (ret == EOK) { @@ -643,3 +645,287 @@ done: talloc_free(tmp_ctx); return ret; } + + +#define SYSDB_USER_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_USER_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" +#define SYSDB_GROUP_NAME_OVERRIDE_FILTER "(&(objectClass="SYSDB_OVERRIDE_GROUP_CLASS")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" + +enum override_object_type { + OO_TYPE_UNDEF = 0, + OO_TYPE_USER, + OO_TYPE_GROUP +}; + +static errno_t sysdb_search_override_by_name(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + 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; + char *sanitized_name; + char *lc_sanitized_name; + const char *src_name; + 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; + } + + /* If this is a subdomain we need to use fully qualified names for the + * search as well by default */ + src_name = sss_get_domain_name(tmp_ctx, name, domain); + if (src_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sss_get_domain_name failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain, + &sanitized_name, &lc_sanitized_name); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize_for_dom failed.\n"); + goto done; + } + + switch(type) { + case OO_TYPE_USER: + filter = SYSDB_USER_NAME_OVERRIDE_FILTER; + attrs = user_attrs; + break; + case OO_TYPE_GROUP: + filter = SYSDB_GROUP_NAME_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, + lc_sanitized_name, + sanitized_name, sanitized_name); + 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 name [%s].\n", + name); + ret = ENOENT; + goto done; + } else if (override_res->count > 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Found more than one override for name [%s]\n.", name); + 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_name(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **override_obj, + struct ldb_result **orig_obj) +{ + return sysdb_search_override_by_name(mem_ctx, domain, name, OO_TYPE_USER, + override_obj, orig_obj); +} + +errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + struct ldb_result **override_obj, + struct ldb_result **orig_obj) +{ + return sysdb_search_override_by_name(mem_ctx, domain, name, OO_TYPE_GROUP, + override_obj, orig_obj); +} + +/** + * @brief Add override data to the original object + * + * @param[in] domain Domain struct, needed to access the cache + * @oaram[in] obj The original object + * @param[in] override_obj The object with the override data, may be NULL + * + * @return EOK - Override data was added successfully + * @return ENOMEM - There was insufficient memory to complete the operation + * @return ENOENT - The original object did not have the SYSDB_OVERRIDE_DN + * attribute or the value of the attribute points an object + * which does not exists. Both conditions indicate that the + * cache must be refreshed. + */ +errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain, + struct ldb_message *obj, + struct ldb_message *override_obj) +{ + int ret; + const char *override_dn_str; + struct ldb_dn *override_dn; + TALLOC_CTX *tmp_ctx; + struct ldb_result *res; + struct ldb_message *override; + uint64_t uid; + static const char *user_attrs[] = SYSDB_PW_ATTRS; + static const char *group_attrs[] = SYSDB_GRSRC_ATTRS; + const char **attrs; + struct attr_map { + const char *attr; + const char *new_attr; + } attr_map[] = { + {SYSDB_UIDNUM, OVERRIDE_PREFIX SYSDB_UIDNUM}, + {SYSDB_GIDNUM, OVERRIDE_PREFIX SYSDB_GIDNUM}, + {SYSDB_GECOS, OVERRIDE_PREFIX SYSDB_GECOS}, + {SYSDB_HOMEDIR, OVERRIDE_PREFIX SYSDB_HOMEDIR}, + {SYSDB_SHELL, OVERRIDE_PREFIX SYSDB_SHELL}, + {SYSDB_NAME, OVERRIDE_PREFIX SYSDB_NAME}, + {NULL, NULL} + }; + size_t c; + const char *tmp_str; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + if (override_obj == NULL) { + override_dn_str = ldb_msg_find_attr_as_string(obj, + SYSDB_OVERRIDE_DN, NULL); + if (override_dn_str == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Missing override DN for objext [%s].\n", + ldb_dn_get_linearized(obj->dn)); + ret = ENOENT; + goto done; + } + + override_dn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, override_dn_str); + if (override_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); + ret = ENOMEM; + goto done; + } + + if (ldb_dn_compare(obj->dn, override_dn) == 0) { + DEBUG(SSSDBG_TRACE_ALL, "Object [%s] has no overrides.\n", + ldb_dn_get_linearized(obj->dn)); + ret = EOK; + goto done; + } + + uid = ldb_msg_find_attr_as_uint64(obj, SYSDB_UIDNUM, 0); + if (uid == 0) { + /* No UID hence group object */ + attrs = group_attrs; + } else { + attrs = user_attrs; + } + + ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, override_dn, + LDB_SCOPE_BASE, attrs, NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + if (res->count == 1) { + override = res->msgs[0]; + } else if (res->count == 0) { + DEBUG(SSSDBG_TRACE_FUNC, "Override object [%s] does not exists.\n", + override_dn_str); + ret = ENOENT; + goto done; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, + "Base search for override object returned [%d] results.\n", + res->count); + ret = EINVAL; + goto done; + } + } else { + override = override_obj; + } + + for (c = 0; attr_map[c].attr != NULL; c++) { + tmp_str = ldb_msg_find_attr_as_string(override, attr_map[c].attr, NULL); + if (tmp_str != NULL) { + talloc_steal(obj, tmp_str); + ret = ldb_msg_add_string(obj, attr_map[c].new_attr, tmp_str); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + } + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + + return ret; +} + diff --git a/src/util/util.h b/src/util/util.h index 2b9f499..0ac9b01 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -546,6 +546,9 @@ errno_t sssd_domain_init(TALLOC_CTX *mem_ctx, #define IS_SUBDOMAIN(dom) ((dom)->parent != NULL) +/* Currently views are only supported for subdomains */ +#define DOM_HAS_VIEWS(dom) ((dom)->has_views && IS_SUBDOMAIN(dom)) + errno_t sss_write_domain_mappings(struct sss_domain_info *domain); errno_t get_dom_names(TALLOC_CTX *mem_ctx, -- 1.8.3.1