From ca49ae1eee321751681e99f3ebe2547211db3bf6 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 22 Sep 2014 12:45:49 +0200 Subject: sysdb: add sysdb_store_override MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Pavel Březina --- src/db/sysdb.h | 8 ++ src/db/sysdb_views.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 290 insertions(+) (limited to 'src') diff --git a/src/db/sysdb.h b/src/db/sysdb.h index c2de00892..b039a673a 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -154,6 +154,8 @@ #define SYSDB_OVERRIDE_ANCHOR_UUID "overrideAnchorUUID" #define SYSDB_OVERRIDE_USER_CLASS "userOverride" #define SYSDB_OVERRIDE_GROUP_CLASS "groupOverride" +#define SYSDB_OVERRIDE_DN "overrideDN" +#define SYSDB_OVERRIDE_OBJECT_DN "overrideObjectDN" #define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)" @@ -224,6 +226,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_MOD_ADD LDB_FLAG_MOD_ADD #define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE @@ -732,6 +735,11 @@ errno_t sysdb_update_members_dn(struct sss_domain_info *member_domain, const char *const *add_groups, const char *const *del_groups); +errno_t sysdb_store_override(struct sss_domain_info *domain, + const char *view_name, + enum sysdb_member_type type, + struct sysdb_attrs *attrs, struct ldb_dn *obj_dn); + /* Password caching function. * If you are in a transaction ignore sysdb and pass in the handle. * If you are not in a transaction pass NULL in handle and provide sysdb, diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c index c0ca269aa..33d63ad50 100644 --- a/src/db/sysdb_views.c +++ b/src/db/sysdb_views.c @@ -179,3 +179,285 @@ done: talloc_free(tmp_ctx); return ret; } + +static errno_t add_aliases_for_name_override(struct sss_domain_info *domain, + struct sysdb_attrs *attrs, + const char *name_override) +{ + char *fq_name = NULL; + int ret; + + if (strchr(name_override, '@') == NULL) { + fq_name = sss_tc_fqname(attrs, domain->names, domain, name_override); + if (fq_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sss_tc_fqname failed.\n"); + return ENOMEM; + } + + if (!domain->case_sensitive) { + ret = sysdb_attrs_add_lc_name_alias(attrs, fq_name); + } else { + 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; + } + } + + if (!domain->case_sensitive) { + ret = sysdb_attrs_add_lc_name_alias(attrs, name_override); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_attrs_add_lc_name_alias failed.\n"); + return ret; + } + } + + return EOK; +} + +errno_t sysdb_store_override(struct sss_domain_info *domain, + const char *view_name, + enum sysdb_member_type type, + struct sysdb_attrs *attrs, struct ldb_dn *obj_dn) +{ + TALLOC_CTX *tmp_ctx; + const char *anchor; + int ret; + struct ldb_dn *override_dn; + const char *override_dn_str; + const char *obj_dn_str; + const char *obj_attrs[] = { SYSDB_OBJECTCLASS, + SYSDB_OVERRIDE_DN, + NULL}; + size_t count = 0; + struct ldb_message **msgs; + struct ldb_message *msg = NULL; + const char *obj_override_dn; + bool add_ref = true; + size_t c; + bool in_transaction = false; + bool has_override = true; + const char *name_override; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + if (attrs != NULL) { + has_override = true; + ret = sysdb_attrs_get_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, + &anchor); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Missing anchor in override attributes.\n"); + ret = EINVAL; + goto done; + } + + override_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, + SYSDB_TMPL_OVERRIDE, anchor, view_name); + if (override_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n"); + ret = ENOMEM; + goto done; + } + } else { + /* if there is no override for the given object, just store the DN of + * the object iself in the SYSDB_OVERRIDE_DN attribute to indicate + * that it was checked if an override exists and none was found. */ + has_override = false; + override_dn = obj_dn; + } + + override_dn_str = ldb_dn_get_linearized(override_dn); + obj_dn_str = ldb_dn_get_linearized(obj_dn); + if (override_dn_str == NULL || obj_dn_str == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_get_linearized failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = sysdb_search_entry(tmp_ctx, domain->sysdb, obj_dn, LDB_SCOPE_BASE, + NULL, obj_attrs, &count, &msgs); + if (ret != EOK) { + if (ret == ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, "Object to override does not exists.\n"); + } else { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n"); + } + goto done; + } + if (count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, "Base searched returned more than one object.\n"); + ret = EINVAL; + goto done; + } + + obj_override_dn = ldb_msg_find_attr_as_string(msgs[0], SYSDB_OVERRIDE_DN, + NULL); + if (obj_override_dn != NULL) { + if (strcmp(obj_override_dn, override_dn_str) != 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Existing [%s] and new [%s] override DN do not match.\n", + obj_override_dn, override_dn_str); + ret = EINVAL; + goto done; + } + + add_ref = false; + } + + ret = ldb_transaction_start(domain->sysdb->ldb); + if (ret != EOK) { + return sysdb_error_to_errno(ret); + } + in_transaction = true; + + if (has_override) { + ret = ldb_delete(domain->sysdb->ldb, override_dn); + if (ret != EOK) { + DEBUG(SSSDBG_TRACE_ALL, + "ldb_delete failed, maybe object did not exist. Ignoring.\n"); + } + + ret = sysdb_attrs_get_string(attrs, SYSDB_NAME, &name_override); + if (ret == EOK) { + ret = add_aliases_for_name_override(domain, attrs, name_override); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "add_aliases_for_name_override failed.\n"); + goto done; + } + } else if (ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); + goto done; + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = override_dn; + + msg->elements = talloc_array(msg, struct ldb_message_element, + attrs->num); + if (msg->elements == NULL) { + ret = ENOMEM; + goto done; + } + + for (c = 0; c < attrs->num; c++) { + msg->elements[c] = attrs->a[c]; + msg->elements[c].flags = LDB_FLAG_MOD_ADD; + } + msg->num_elements = attrs->num; + + ret = ldb_msg_add_empty(msg, SYSDB_OBJECTCLASS, LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + switch(type) { + case SYSDB_MEMBER_USER: + ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS, + SYSDB_OVERRIDE_USER_CLASS); + break; + case SYSDB_MEMBER_GROUP: + ret = ldb_msg_add_string(msg, SYSDB_OBJECTCLASS, + SYSDB_OVERRIDE_GROUP_CLASS); + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected object type.\n"); + ret = EINVAL; + goto done; + } + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_OBJECT_DN, LDB_FLAG_MOD_ADD, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_string(msg, SYSDB_OVERRIDE_OBJECT_DN, obj_dn_str); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_add(domain->sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to store override entry: %s(%d)[%s]\n", + ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb)); + ret = sysdb_error_to_errno(ret); + goto done; + } + } + + if (add_ref) { + talloc_free(msg); + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + + msg->dn = obj_dn; + + ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_ADD, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_string(msg, SYSDB_OVERRIDE_DN, override_dn_str); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_modify(domain->sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to store override DN: %s(%d)[%s]\n", + ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb)); + ret = sysdb_error_to_errno(ret); + goto done; + } + } + + ret = EOK; + +done: + if (in_transaction) { + if (ret != EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, strerror(ret)); + ldb_transaction_cancel(domain->sysdb->ldb); + } else { + ret = ldb_transaction_commit(domain->sysdb->ldb); + ret = sysdb_error_to_errno(ret); + } + } + + talloc_zfree(tmp_ctx); + return ret; +} -- cgit