diff options
| author | Matthias Dieter Wallnöfer <mdw@samba.org> | 2010-05-30 21:08:05 +0200 | 
|---|---|---|
| committer | Matthias Dieter Wallnöfer <mdw@samba.org> | 2010-05-30 23:13:08 +0200 | 
| commit | 08653ac9c26a4456d9ca7365c1773d021e5be51c (patch) | |
| tree | 91534c24a2400cf4651c2681db247d0e7c6d986b | |
| parent | c30c4529f59f25e2846e33bdd3676aed51c10dcc (diff) | |
| download | samba-08653ac9c26a4456d9ca7365c1773d021e5be51c.tar.gz samba-08653ac9c26a4456d9ca7365c1773d021e5be51c.tar.bz2 samba-08653ac9c26a4456d9ca7365c1773d021e5be51c.zip  | |
s4:samldb LDB module - rework the group change code to be again synchronous
| -rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 380 | 
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)  {  | 
