summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb')
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c380
1 files changed, 71 insertions, 309 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 4d1659df0b..a07dec961c 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -68,20 +68,6 @@ struct samldb_ctx {
/* used in conjunction with "sid" in "samldb_dn_from_sid" */
struct ldb_dn *res_dn;
- /* used in conjunction with "dn" in "samldb_sid_from_dn" */
- struct dom_sid *res_sid;
-
- /* used in "samldb_user_dn_to_prim_group_rid" */
- uint32_t prim_group_rid;
-
- /* used in "samldb_group_add_member" and "samldb_group_del_member" */
- struct ldb_dn *group_dn;
- struct ldb_dn *member_dn;
-
- /* used in "samldb_primary_group_change" */
- struct ldb_dn *user_dn;
- struct ldb_dn *old_prim_group_dn, *new_prim_group_dn;
-
/* all the async steps necessary to complete the operation */
struct samldb_step *steps;
struct samldb_step *curstep;
@@ -1133,339 +1119,115 @@ static int samldb_schema_info_update(struct samldb_ctx *ac)
return LDB_SUCCESS;
}
-/*
- * samldb_user_dn_to_prim_group_rid (async)
- */
-
-static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac);
-static int samldb_user_dn_to_prim_group_rid_callback(struct ldb_request *req,
- struct ldb_reply *ares)
+static int samldb_prim_group_change(struct samldb_ctx *ac)
{
struct ldb_context *ldb;
- struct samldb_ctx *ac;
+ const char * attrs[] = { "primaryGroupID", "memberOf", NULL };
+ struct ldb_result *res;
+ struct ldb_message_element *el;
+ struct ldb_message *msg;
+ uint32_t rid;
+ struct dom_sid *sid;
+ struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
int ret;
- ac = talloc_get_type(req->context, struct samldb_ctx);
ldb = ldb_module_get_ctx(ac->module);
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
+ /* Fetch informations from the existing object */
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* save entry */
- if (ac->prim_group_rid != 0) {
- /* one too many! */
- ldb_set_errstring(ldb,
- "Invalid number of results while searching "
- "for domain objects!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
- ac->prim_group_rid = samdb_result_uint(ares->message,
- "primaryGroupID", ~0);
-
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_REFERRAL:
- /* ignore */
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_DONE:
- talloc_free(ares);
- if (ac->prim_group_rid == 0) {
- ldb_asprintf_errstring(ldb,
- "Unable to get the primary group RID!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- /* found, go on */
- ret = samldb_next_step(ac);
- break;
- }
-
-done:
+ ret = ldb_search(ldb, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
+ NULL);
if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
- }
-
- return LDB_SUCCESS;
-}
-
-/* Locates the "primaryGroupID" attribute from a certain user specified as
- * "user_dn". Saves the result in "prim_group_rid". */
-static int samldb_user_dn_to_prim_group_rid(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- static const char * const attrs[] = { "primaryGroupID", NULL };
- struct ldb_request *req;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
-
- if (ac->user_dn == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
-
- ret = ldb_build_search_req(&req, ldb, ac,
- ac->user_dn,
- LDB_SCOPE_BASE,
- NULL, attrs,
- NULL,
- ac, samldb_user_dn_to_prim_group_rid_callback,
- ac->req);
- if (ret != LDB_SUCCESS)
return ret;
-
- return ldb_next_request(ac->module, req);
-}
-
-/*
- * samldb_group_add_member (async)
- * samldb_group_del_member (async)
- */
-
-static int samldb_group_add_del_member_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
}
- if (ares->type == LDB_REPLY_REFERRAL) {
- return ldb_module_send_referral(ac->req, ares->referral);
- }
-
- if (ares->error != LDB_SUCCESS) {
- if (ares->error == LDB_ERR_NO_SUCH_ATTRIBUTE) {
- /* On error "NO_SUCH_ATTRIBUTE" (delete of an invalid
- * "member" attribute) return "UNWILLING_TO_PERFORM" */
- ares->error = LDB_ERR_UNWILLING_TO_PERFORM;
- }
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
- if (ares->type != LDB_REPLY_DONE) {
- ldb_set_errstring(ldb,
- "Invalid reply type!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
-
- ret = samldb_next_step(ac);
+ /* Finds out the DN of the old primary group */
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
+ rid = samdb_result_uint(res->msgs[0], "primaryGroupID", (uint32_t) -1);
+ if (rid == (uint32_t) -1) {
+ /* User objects do always have a mandatory "primaryGroupID"
+ * attribute. If this doesn't exist then the object is of the
+ * wrong type. This is the exact Windows error code */
+ return LDB_ERR_OBJECT_CLASS_VIOLATION;
}
- return LDB_SUCCESS;
-}
-
-/* Adds a member with DN "member_dn" to a group with DN "group_dn" */
-static int samldb_group_add_member(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- struct ldb_request *req;
- struct ldb_message *msg;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
-
- if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
+ sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
+ if (sid == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
+ }
- msg = ldb_msg_new(ac);
- msg->dn = ac->group_dn;
- samdb_msg_add_addval(ldb, ac, msg, "member",
- ldb_dn_get_linearized(ac->member_dn));
-
- ret = ldb_build_mod_req(&req, ldb, ac,
- msg, NULL,
- ac, samldb_group_add_del_member_callback,
- ac->req);
- if (ret != LDB_SUCCESS)
- return ret;
-
- return ldb_next_request(ac->module, req);
-}
-
-/* Removes a member with DN "member_dn" from a group with DN "group_dn" */
-static int samldb_group_del_member(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- struct ldb_request *req;
- struct ldb_message *msg;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
-
- if ((ac->group_dn == NULL) || (ac->member_dn == NULL))
+ prev_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
+ dom_sid_string(ac, sid));
+ if (prev_prim_group_dn == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
+ }
- msg = ldb_msg_new(ac);
- msg->dn = ac->group_dn;
- samdb_msg_add_delval(ldb, ac, msg, "member",
- ldb_dn_get_linearized(ac->member_dn));
-
- ret = ldb_build_mod_req(&req, ldb, ac,
- msg, NULL,
- ac, samldb_group_add_del_member_callback,
- ac->req);
- if (ret != LDB_SUCCESS)
- return ret;
-
- return ldb_next_request(ac->module, req);
-}
-
-
-static int samldb_prim_group_change_1(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- uint32_t rid;
-
- ldb = ldb_module_get_ctx(ac->module);
+ /* Finds out the DN of the new primary group */
- ac->user_dn = ac->msg->dn;
+ rid = samdb_result_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
+ if (rid == (uint32_t) -1) {
+ /* we aren't affected of any primary group change */
+ return ldb_next_request(ac->module, ac->req);
+ }
- rid = samdb_result_uint(ac->msg, "primaryGroupID", ~0);
- ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
- if (ac->sid == NULL)
+ sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
+ if (sid == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
- ac->res_dn = NULL;
-
- ac->prim_group_rid = 0;
-
- return samldb_next_step(ac);
-}
-
-static int samldb_prim_group_change_2(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
-
- ldb = ldb_module_get_ctx(ac->module);
+ }
- if (ac->res_dn != NULL)
- ac->new_prim_group_dn = ac->res_dn;
- else
+ new_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
+ dom_sid_string(ac, sid));
+ if (new_prim_group_dn == NULL) {
+ /* Here we know if the specified new primary group candidate is
+ * valid or not. */
return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
- ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
- ac->prim_group_rid);
- if (ac->sid == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
- ac->res_dn = NULL;
-
- return samldb_next_step(ac);
-}
-
-static int samldb_prim_group_change_4(struct samldb_ctx *ac);
-static int samldb_prim_group_change_5(struct samldb_ctx *ac);
-static int samldb_prim_group_change_6(struct samldb_ctx *ac);
-
-static int samldb_prim_group_change_3(struct samldb_ctx *ac)
-{
- int ret;
-
- if (ac->res_dn != NULL)
- ac->old_prim_group_dn = ac->res_dn;
- else
+ el = samdb_find_attribute(ldb, res->msgs[0], "memberOf",
+ ldb_dn_get_linearized(new_prim_group_dn));
+ if (el == NULL) {
+ /* We need to be already a normal member of the new primary
+ * group in order to be successful. */
return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
- /* Only update when the primary group changed */
- if (ldb_dn_compare(ac->old_prim_group_dn, ac->new_prim_group_dn) != 0) {
- ac->member_dn = ac->user_dn;
- /* Remove the "member" attribute of the actual (new) primary
- * group */
+ /* Only update the "member" attributes when we really do have a change */
+ if (ldb_dn_compare(new_prim_group_dn, prev_prim_group_dn) != 0) {
+ /* Remove the "member" attribute on the new primary group */
+ msg = talloc_zero(ac, struct ldb_message);
+ msg->dn = new_prim_group_dn;
- ret = samldb_add_step(ac, samldb_prim_group_change_4);
- if (ret != LDB_SUCCESS) return ret;
+ ret = samdb_msg_add_delval(ldb, ac, msg, "member",
+ ldb_dn_get_linearized(ac->msg->dn));
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- ret = samldb_add_step(ac, samldb_group_del_member);
- if (ret != LDB_SUCCESS) return ret;
+ ret = dsdb_module_modify(ac->module, msg, 0);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
/* Add a "member" attribute for the previous primary group */
+ msg = talloc_zero(ac, struct ldb_message);
+ msg->dn = prev_prim_group_dn;
- ret = samldb_add_step(ac, samldb_prim_group_change_5);
- if (ret != LDB_SUCCESS) return ret;
+ ret = samdb_msg_add_addval(ldb, ac, msg, "member",
+ ldb_dn_get_linearized(ac->msg->dn));
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- ret = samldb_add_step(ac, samldb_group_add_member);
- if (ret != LDB_SUCCESS) return ret;
+ ret = dsdb_module_modify(ac->module, msg, 0);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
}
- ret = samldb_add_step(ac, samldb_prim_group_change_6);
- if (ret != LDB_SUCCESS) return ret;
-
- return samldb_next_step(ac);
-}
-
-static int samldb_prim_group_change_4(struct samldb_ctx *ac)
-{
- ac->group_dn = ac->new_prim_group_dn;
-
- return samldb_next_step(ac);
-}
-
-static int samldb_prim_group_change_5(struct samldb_ctx *ac)
-{
- ac->group_dn = ac->old_prim_group_dn;
-
- return samldb_next_step(ac);
-}
-
-static int samldb_prim_group_change_6(struct samldb_ctx *ac)
-{
return ldb_next_request(ac->module, ac->req);
}
-static int samldb_prim_group_change(struct samldb_ctx *ac)
-{
- int ret;
-
- /* Finds out the DN of the new primary group */
-
- ret = samldb_add_step(ac, samldb_prim_group_change_1);
- if (ret != LDB_SUCCESS) return ret;
-
- ret = samldb_add_step(ac, samldb_dn_from_sid);
- if (ret != LDB_SUCCESS) return ret;
-
- ret = samldb_add_step(ac, samldb_user_dn_to_prim_group_rid);
- if (ret != LDB_SUCCESS) return ret;
-
- /* Finds out the DN of the old primary group */
-
- ret = samldb_add_step(ac, samldb_prim_group_change_2);
- if (ret != LDB_SUCCESS) return ret;
-
- ret = samldb_add_step(ac, samldb_dn_from_sid);
- if (ret != LDB_SUCCESS) return ret;
-
- ret = samldb_add_step(ac, samldb_prim_group_change_3);
- if (ret != LDB_SUCCESS) return ret;
-
- return samldb_first_step(ac);
-}
-
static int samldb_member_check(struct samldb_ctx *ac)
{