summaryrefslogtreecommitdiffstats
path: root/src/db
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2014-09-22 12:45:49 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-10-16 17:56:05 +0200
commitca49ae1eee321751681e99f3ebe2547211db3bf6 (patch)
tree43bb197bc1f4eb2f33ac7e93b2b5e051592826b9 /src/db
parent0f3df54840ec9a050cc0b1b68269c3f28c859e64 (diff)
downloadsssd-ca49ae1eee321751681e99f3ebe2547211db3bf6.tar.gz
sssd-ca49ae1eee321751681e99f3ebe2547211db3bf6.tar.xz
sssd-ca49ae1eee321751681e99f3ebe2547211db3bf6.zip
sysdb: add sysdb_store_override
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src/db')
-rw-r--r--src/db/sysdb.h8
-rw-r--r--src/db/sysdb_views.c282
2 files changed, 290 insertions, 0 deletions
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;
+}