diff options
author | Sumit Bose <sbose@redhat.com> | 2014-09-22 18:37:44 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-10-16 17:56:11 +0200 |
commit | 9da27cbc7532f775afc411d809735760dd5294a7 (patch) | |
tree | 20e31189b2df933fe27cf0d871270edb7c874d10 /src | |
parent | 8a2a503fa5c01ea037d28b7c902b8821a11084bd (diff) | |
download | sssd-9da27cbc7532f775afc411d809735760dd5294a7.tar.gz sssd-9da27cbc7532f775afc411d809735760dd5294a7.tar.xz sssd-9da27cbc7532f775afc411d809735760dd5294a7.zip |
sysdb: sysdb_apply_default_override
The default view is special in the sense that it is the baseline for
every other view and that it always applies even if there is no view
defined. To avoid useless additional processing the default view
overrides are written directly to the corresponding cached object.
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/db/sysdb.h | 4 | ||||
-rw-r--r-- | src/db/sysdb_views.c | 208 |
2 files changed, 199 insertions, 13 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 602db2c04..6bb25de14 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -434,6 +434,10 @@ errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb, const char *view_name); errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, char **view_name); +errno_t sysdb_apply_default_override(struct sss_domain_info *domain, + struct sysdb_attrs *override_attrs, + struct ldb_dn *obj_dn); + /* 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 33d63ad50..c0fb9158e 100644 --- a/src/db/sysdb_views.c +++ b/src/db/sysdb_views.c @@ -180,9 +180,11 @@ done: return ret; } -static errno_t add_aliases_for_name_override(struct sss_domain_info *domain, - struct sysdb_attrs *attrs, - const char *name_override) +static errno_t +add_name_and_aliases_for_name_override(struct sss_domain_info *domain, + struct sysdb_attrs *attrs, + bool add_name, + const char *name_override) { char *fq_name = NULL; int ret; @@ -200,24 +202,37 @@ static errno_t add_aliases_for_name_override(struct sss_domain_info *domain, ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, fq_name); } - talloc_free(fq_name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_lc_name_alias failed.\n"); - return ret; + goto done; } } - if (!domain->case_sensitive) { - ret = sysdb_attrs_add_lc_name_alias(attrs, name_override); + if (add_name) { + ret = sysdb_attrs_add_string(attrs, SYSDB_DEFAULT_OVERRIDE_NAME, + fq_name == NULL ? name_override : fq_name); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_attrs_add_lc_name_alias failed.\n"); - return ret; + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_lc_name_alias failed.\n"); + goto done; } } - return EOK; + if (!domain->case_sensitive) { + ret = sysdb_attrs_add_lc_name_alias(attrs, name_override); + } else { + ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, name_override); + } + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_lc_name_alias failed.\n"); + goto done; + } + + ret = EOK; + +done: + talloc_free(fq_name); + return ret; } errno_t sysdb_store_override(struct sss_domain_info *domain, @@ -329,10 +344,11 @@ errno_t sysdb_store_override(struct sss_domain_info *domain, ret = sysdb_attrs_get_string(attrs, SYSDB_NAME, &name_override); if (ret == EOK) { - ret = add_aliases_for_name_override(domain, attrs, name_override); + ret = add_name_and_aliases_for_name_override(domain, attrs, false, + name_override); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, - "add_aliases_for_name_override failed.\n"); + "add_name_and_aliases_for_name_override failed.\n"); goto done; } } else if (ret != ENOENT) { @@ -461,3 +477,169 @@ done: talloc_zfree(tmp_ctx); return ret; } + +static errno_t safe_original_attributes(struct sss_domain_info *domain, + struct sysdb_attrs *attrs, + struct ldb_dn *obj_dn, + const char **allowed_attrs) +{ + int ret; + size_t c; + TALLOC_CTX *tmp_ctx; + struct ldb_result *orig_obj; + char *orig_attr_name; + struct ldb_message_element *el = NULL; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &orig_obj, obj_dn, + LDB_SCOPE_BASE, NULL, NULL); + if (ret != EOK || orig_obj->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, "Original object not found.\n"); + goto done; + } + + /* Safe orginal values in attributes prefixed by OriginalAD. */ + for (c = 0; allowed_attrs[c] != NULL; c++) { + el = ldb_msg_find_element(orig_obj->msgs[0], allowed_attrs[c]); + if (el != NULL) { + orig_attr_name = talloc_asprintf(tmp_ctx, "%s%s", + ORIGINALAD_PREFIX, + allowed_attrs[c]); + if (orig_attr_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_add_val(attrs, orig_attr_name, + &el->values[0]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_attrs_add_val failed.\n"); + goto done; + } + } else { + DEBUG(SSSDBG_TRACE_ALL, + "Original object does not have [%s] set.\n", + allowed_attrs[c]); + } + } + + /* Add existing aliases to new ones */ + el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_NAME_ALIAS); + if (el != NULL) { + for (c = 0; c < el->num_values; c++) { + /* To avoid issue with ldb_modify if e.g. the orginal and the + * override name are the same, we use the *_safe version here. */ + ret = sysdb_attrs_add_val_safe(attrs, SYSDB_NAME_ALIAS, + &el->values[c]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n"); + goto done; + } + } + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + +errno_t sysdb_apply_default_override(struct sss_domain_info *domain, + struct sysdb_attrs *override_attrs, + struct ldb_dn *obj_dn) +{ + int ret; + TALLOC_CTX *tmp_ctx; + struct sysdb_attrs *attrs; + size_t c; + struct ldb_message_element *el = NULL; + const char *allowed_attrs[] = { SYSDB_UIDNUM, + SYSDB_GIDNUM, + SYSDB_GECOS, + SYSDB_HOMEDIR, + SYSDB_SHELL, + SYSDB_NAME, + NULL }; + bool override_attrs_found = false; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + attrs = sysdb_new_attrs(tmp_ctx); + if (attrs == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n"); + ret = ENOMEM; + goto done; + } + + for (c = 0; allowed_attrs[c] != NULL; c++) { + ret = sysdb_attrs_get_el_ext(override_attrs, allowed_attrs[c], false, + &el); + if (ret == EOK) { + override_attrs_found = true; + + if (strcmp(allowed_attrs[c], SYSDB_NAME) == 0) { + if (el->values[0].data[el->values[0].length] != '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "String attribute does not end with \\0.\n"); + ret = EINVAL; + goto done; + } + + ret = add_name_and_aliases_for_name_override(domain, attrs, + true, + (char *) el->values[0].data); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "add_name_and_aliases_for_name_override failed.\n"); + goto done; + } + } else { + ret = sysdb_attrs_add_val(attrs, allowed_attrs[c], + &el->values[0]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n"); + goto done; + } + DEBUG(SSSDBG_TRACE_ALL, "Override [%s] with [%.*s] for [%s].\n", + allowed_attrs[c], + (int) el->values[0].length, + el->values[0].data, + ldb_dn_get_linearized(obj_dn)); + } + } else if (ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el_ext failed.\n"); + goto done; + } + } + + if (override_attrs_found) { + ret = safe_original_attributes(domain, attrs, obj_dn, allowed_attrs); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "safe_original_attributes failed.\n"); + goto done; + } + + ret = sysdb_set_entry_attr(domain->sysdb, obj_dn, attrs, SYSDB_MOD_REP); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed.\n"); + goto done; + } + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} |