diff options
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; +} |