struct replace_context *rc;
struct la_op_store *ops;
struct la_op_store *cur;
+ struct ldb_extended *op_response;
+ struct ldb_control **op_controls;
};
static struct la_context *linked_attributes_init(struct ldb_module *module,
static int la_mod_callback(struct ldb_request *req,
struct ldb_reply *ares);
static int la_down_req(struct la_context *ac);
-static int la_down_callback(struct ldb_request *req,
- struct ldb_reply *ares);
}
break;
case LDB_RENAME:
- /* If we have modfies to make, then run them */
- return la_do_mod_request(ac);
+
+ ret = la_do_mod_request(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ ret);
+ }
+
+ return ret;
+
default:
talloc_free(ares);
return ldb_module_done(ac->req, NULL, NULL,
struct ldb_context *ldb;
int ret;
+ /* If we have no modifies in the queue, we are done! */
+ if (!ac->ops) {
+ return ldb_module_done(ac->req, ac->op_controls,
+ ac->op_response, LDB_SUCCESS);
+ }
+
ldb = ac->module->ldb;
/* Create the modify request */
{
struct la_context *ac;
struct la_op_store *os;
- int ret;
ac = talloc_get_type(req->context, struct la_context);
talloc_free(os);
}
- /* If we still have modifies in the queue, then run them */
- if (ac->ops) {
- ret = la_do_mod_request(ac);
- } else {
- /* Otherwise, we are done! */
- ret = ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
+ return la_do_mod_request(ac);
+}
+
+/* Having done the original operation, then try to fix up all the linked attributes for modify and delete */
+static int la_mod_del_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ int ret;
+ struct la_context *ac;
+ ac = talloc_get_type(req->context, struct la_context);
+
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
+ }
+
+ if (ares->type != LDB_REPLY_DONE) {
+ ldb_set_errstring(ac->module->ldb,
+ "invalid ldb_reply_type in callback");
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ac->op_controls = talloc_steal(ac, ares->controls);
+ ac->op_response = talloc_steal(ac, ares->response);
+ /* If we have modfies to make, this is the time to do them for modify and delete */
+ ret = la_do_mod_request(ac);
+
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
}
+ talloc_free(ares);
+
+ /* la_do_mod_request has already sent the callbacks */
return LDB_SUCCESS;
+
}
-static int la_down_req(struct la_context *ac)
+/* Having done the original rename try to fix up all the linked attributes */
+static int la_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
{
- struct ldb_request *down_req;
int ret;
+ struct la_context *ac;
+ struct ldb_request *search_req;
+ const char **attrs;
+ WERROR werr;
+ ac = talloc_get_type(req->context, struct la_context);
- switch (ac->req->operation) {
- case LDB_ADD:
- ret = ldb_build_add_req(&down_req, ac->module->ldb, ac,
- ac->req->op.add.message,
- ac->req->controls,
- ac, la_down_callback,
- ac->req);
- break;
- case LDB_MODIFY:
- ret = ldb_build_mod_req(&down_req, ac->module->ldb, ac,
- ac->req->op.mod.message,
- ac->req->controls,
- ac, la_down_callback,
- ac->req);
- break;
- case LDB_DELETE:
- ret = ldb_build_del_req(&down_req, ac->module->ldb, ac,
- ac->req->op.del.dn,
- ac->req->controls,
- ac, la_down_callback,
- ac->req);
- break;
- case LDB_RENAME:
- ret = ldb_build_rename_req(&down_req, ac->module->ldb, ac,
- ac->req->op.rename.olddn,
- ac->req->op.rename.newdn,
- ac->req->controls,
- ac, la_down_callback,
- ac->req);
- break;
- default:
- ret = LDB_ERR_OPERATIONS_ERROR;
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
+
+ if (ares->type != LDB_REPLY_DONE) {
+ ldb_set_errstring(ac->module->ldb,
+ "invalid ldb_reply_type in callback");
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ werr = dsdb_linked_attribute_lDAPDisplayName_list(ac->schema, ac, &attrs);
+ if (!W_ERROR_IS_OK(werr)) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_build_search_req(&search_req, ac->module->ldb, req,
+ ac->req->op.rename.newdn, LDB_SCOPE_BASE,
+ "(objectClass=*)", attrs,
+ NULL,
+ ac, la_op_search_callback,
+ req);
+
if (ret != LDB_SUCCESS) {
return ret;
}
+
+ talloc_steal(search_req, attrs);
- return ldb_next_request(ac->module, down_req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_request_add_control(search_req,
+ LDB_CONTROL_EXTENDED_DN_OID,
+ false, NULL);
+ }
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ ret);
+ }
+
+ ac->op_controls = talloc_steal(ac, ares->controls);
+ ac->op_response = talloc_steal(ac, ares->response);
+
+ return ldb_next_request(ac->module, search_req);
}
-/* Having done the original operation, then try to fix up all the linked attributes */
-static int la_down_callback(struct ldb_request *req, struct ldb_reply *ares)
+/* Having done the original add, then try to fix up all the linked attributes
+
+ This is done after the add so the links can get the extended DNs correctly.
+ */
+static int la_add_callback(struct ldb_request *req, struct ldb_reply *ares)
{
int ret;
struct la_context *ac;
if (ac->ops) {
struct ldb_request *search_req;
- if (ac->req->operation == LDB_ADD) {
- static const char *attrs[] = { NULL };
-
- /* The callback does all the hard work here - we need
- * the objectGUID and SID of the added record */
- ret = ldb_build_search_req(&search_req, ac->module->ldb, ac,
- ac->req->op.add.message->dn,
- LDB_SCOPE_BASE,
- "(objectClass=*)", attrs,
- NULL,
- ac, la_mod_search_callback,
- ac->req);
-
- } else if (ac->req->operation == LDB_RENAME) {
- const char **attrs;
- WERROR werr;
- werr = dsdb_linked_attribute_lDAPDisplayName_list(ac->schema, ac, &attrs);
- if (!W_ERROR_IS_OK(werr)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = ldb_build_search_req(&search_req, ac->module->ldb, req,
- ac->req->op.rename.newdn, LDB_SCOPE_BASE,
- "(objectClass=*)", attrs,
- NULL,
- ac, la_op_search_callback,
- req);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- talloc_steal(search_req, attrs);
-
-
- } else {
- /* If we have modfies to make, this is the time to do them for modify and delete */
- ret = la_do_mod_request(ac);
-
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL,
- ret);
- }
- return LDB_SUCCESS;
- }
+ static const char *attrs[] = { NULL };
+
+ /* The callback does all the hard work here - we need
+ * the objectGUID and SID of the added record */
+ ret = ldb_build_search_req(&search_req, ac->module->ldb, ac,
+ ac->req->op.add.message->dn,
+ LDB_SCOPE_BASE,
+ "(objectClass=*)", attrs,
+ NULL,
+ ac, la_mod_search_callback,
+ ac->req);
+
if (ret == LDB_SUCCESS) {
ret = ldb_request_add_control(search_req,
LDB_CONTROL_EXTENDED_DN_OID,
return ldb_module_done(ac->req, NULL, NULL,
ret);
}
+
+ ac->op_controls = talloc_steal(ac, ares->controls);
+ ac->op_response = talloc_steal(ac, ares->response);
+
return ldb_next_request(ac->module, search_req);
+
} else {
return ldb_module_done(ac->req, ares->controls,
ares->response, ares->error);
}
}
+/* Reconstruct the original request, but pointing at our local callback to finish things off */
+static int la_down_req(struct la_context *ac)
+{
+ struct ldb_request *down_req;
+ int ret;
+
+ switch (ac->req->operation) {
+ case LDB_ADD:
+ ret = ldb_build_add_req(&down_req, ac->module->ldb, ac,
+ ac->req->op.add.message,
+ ac->req->controls,
+ ac, la_add_callback,
+ ac->req);
+ break;
+ case LDB_MODIFY:
+ ret = ldb_build_mod_req(&down_req, ac->module->ldb, ac,
+ ac->req->op.mod.message,
+ ac->req->controls,
+ ac, la_mod_del_callback,
+ ac->req);
+ break;
+ case LDB_DELETE:
+ ret = ldb_build_del_req(&down_req, ac->module->ldb, ac,
+ ac->req->op.del.dn,
+ ac->req->controls,
+ ac, la_mod_del_callback,
+ ac->req);
+ break;
+ case LDB_RENAME:
+ ret = ldb_build_rename_req(&down_req, ac->module->ldb, ac,
+ ac->req->op.rename.olddn,
+ ac->req->op.rename.newdn,
+ ac->req->controls,
+ ac, la_rename_callback,
+ ac->req);
+ break;
+ default:
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_next_request(ac->module, down_req);
+}
+
+
_PUBLIC_ const struct ldb_module_ops ldb_linked_attributes_module_ops = {
.name = "linked_attributes",
.add = linked_attributes_add,