summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules/local_password.c
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2008-09-11 18:36:28 -0400
committerStefan Metzmacher <metze@samba.org>2008-09-29 04:22:20 +0200
commit51baa8deec00244cc0a6e3d29c53932427800610 (patch)
treee4a63113b3e39120259c5ac3dc80ed2199d749fe /source4/dsdb/samdb/ldb_modules/local_password.c
parent4f40ee2b86007f7dc631e93e59f24f970bc25ea2 (diff)
downloadsamba-51baa8deec00244cc0a6e3d29c53932427800610.tar.gz
samba-51baa8deec00244cc0a6e3d29c53932427800610.tar.bz2
samba-51baa8deec00244cc0a6e3d29c53932427800610.zip
LDB ASYNC: samba4 modules
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules/local_password.c')
-rw-r--r--source4/dsdb/samdb/ldb_modules/local_password.c1124
1 files changed, 670 insertions, 454 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/local_password.c b/source4/dsdb/samdb/ldb_modules/local_password.c
index a411c01513..622e444166 100644
--- a/source4/dsdb/samdb/ldb_modules/local_password.c
+++ b/source4/dsdb/samdb/ldb_modules/local_password.c
@@ -1,7 +1,7 @@
/*
ldb database module
- Copyright (C) Simo Sorce 2004-2006
+ Copyright (C) Simo Sorce 2004-2008
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
Copyright (C) Andrew Tridgell 2004
@@ -44,7 +44,7 @@
This allows the password database to be syncronised in a multi-master
fashion, seperate to the more difficult concerns of the main
database. (With passwords, the last writer always wins)
-
+
Each incoming add/modify is split into a remote, and a local request, done in that order.
We maintain a list of attributes that are kept locally:
@@ -62,73 +62,89 @@ static const char * const password_attrs[] = {
/* And we merge them back into search requests when asked to do so */
-struct lpdb_context {
+struct lpdb_reply {
+ struct lpdb_reply *next;
+ struct ldb_reply *remote;
+ struct ldb_dn *local_dn;
+};
- enum lpdb_type {LPDB_ADD, LPDB_MOD, LPDB_SEARCH} type;
- enum lpdb_step {LPDB_ADD_REMOTE, LPDB_MOD_REMOTE, LPDB_MOD_SEARCH_SELF, LPDB_LOCAL, LPDB_SEARCH_REMOTE} step;
+struct lpdb_context {
struct ldb_module *module;
- struct ldb_request *orig_req;
- struct ldb_request *remote_req;
- struct ldb_request *search_req;
- struct ldb_request *local_req;
+ struct ldb_request *req;
struct ldb_message *local_message;
+ struct lpdb_reply *list;
+ struct lpdb_reply *current;
+ struct ldb_reply *remote_done;
+ struct ldb_reply *remote;
+
bool added_objectGUID;
bool added_objectClass;
- struct ldb_reply *search_res;
-};
-
-struct lpdb_local_search_context {
- struct lpdb_context *ac;
- struct ldb_reply *remote_res;
- struct ldb_reply *local_res;
};
-static struct ldb_handle *lpdb_init_handle(struct ldb_request *req, struct ldb_module *module, enum lpdb_type type)
+static struct lpdb_context *lpdb_init_context(struct ldb_module *module,
+ struct ldb_request *req)
{
struct lpdb_context *ac;
- struct ldb_handle *h;
- h = talloc_zero(req, struct ldb_handle);
- if (h == NULL) {
+ ac = talloc_zero(req, struct lpdb_context);
+ if (ac == NULL) {
ldb_set_errstring(module->ldb, "Out of Memory");
return NULL;
}
- h->module = module;
+ ac->module = module;
+ ac->req = req;
- ac = talloc_zero(h, struct lpdb_context);
- if (ac == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- talloc_free(h);
- return NULL;
- }
+ return ac;
+}
- h->private_data = (void *)ac;
+static int lpdb_local_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct lpdb_context *ac;
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
+ ac = talloc_get_type(req->context, struct lpdb_context);
- ac->type = type;
- ac->module = module;
- ac->orig_req = req;
+ 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, "Unexpected reply type");
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
- return h;
+ talloc_free(ares);
+ return ldb_module_done(ac->req,
+ ac->remote_done->controls,
+ ac->remote_done->response,
+ ac->remote_done->error);
}
-/* Add a record, splitting password attributes from the user's main
- * record */
+/*****************************************************************************
+ * ADD
+ ****************************************************************************/
+
+static int lpdb_add_callback(struct ldb_request *req,
+ struct ldb_reply *ares);
static int local_password_add(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_handle *h;
- struct lpdb_context *ac;
struct ldb_message *remote_message;
- struct ldb_message *local_message;
+ struct ldb_request *remote_req;
+ struct lpdb_context *ac;
struct GUID objectGUID;
+ int ret;
int i;
ldb_debug(module->ldb, LDB_DEBUG_TRACE, "local_password_add\n");
@@ -163,22 +179,12 @@ static int local_password_add(struct ldb_module *module, struct ldb_request *req
}
/* From here, we assume we have password attributes to split off */
- h = lpdb_init_handle(req, module, LPDB_ADD);
- if (!h) {
+ ac = lpdb_init_context(module, req);
+ if (!ac) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(h->private_data, struct lpdb_context);
- ac->orig_req = req;
-
- ac->remote_req = talloc(ac, struct ldb_request);
- if (ac->remote_req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *(ac->remote_req) = *(ac->orig_req);
-
- remote_message = ldb_msg_copy_shallow(ac->remote_req, ac->orig_req->op.add.message);
+ remote_message = ldb_msg_copy_shallow(remote_req, req->op.add.message);
if (remote_message == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -188,81 +194,113 @@ static int local_password_add(struct ldb_module *module, struct ldb_request *req
ldb_msg_remove_attr(remote_message, password_attrs[i]);
}
- ac->remote_req->op.add.message = remote_message;
-
- ac->remote_req->context = NULL;
- ac->remote_req->callback = NULL;
-
- ac->local_req = talloc(ac, struct ldb_request);
- if (ac->local_req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
+ /* Find the objectGUID to use as the key */
+ objectGUID = samdb_result_guid(ac->req->op.add.message, "objectGUID");
- *(ac->local_req) = *(ac->orig_req);
- local_message = ldb_msg_copy_shallow(ac->local_req, ac->orig_req->op.add.message);
- if (local_message == NULL) {
+ ac->local_message = ldb_msg_copy_shallow(ac, req->op.add.message);
+ if (ac->local_message == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
/* Remove anything seen in the remote message from the local
* message (leaving only password attributes) */
- for (i=0;i<ac->remote_req->op.add.message->num_elements;i++) {
- ldb_msg_remove_attr(local_message, ac->remote_req->op.add.message->elements[i].name);
+ for (i=0; i < remote_message->num_elements; i++) {
+ ldb_msg_remove_attr(ac->local_message, remote_message->elements[i].name);
}
/* We must have an objectGUID already, or we don't know where
* to add the password. This may be changed to an 'add and
* search', to allow the directory to create the objectGUID */
- if (ldb_msg_find_ldb_val(ac->orig_req->op.add.message, "objectGUID") == NULL) {
- ldb_set_errstring(module->ldb,
- "no objectGUID found in search: local_password module must be configured below objectGUID module!\n");
+ if (ldb_msg_find_ldb_val(req->op.add.message, "objectGUID") == NULL) {
+ ldb_set_errstring(module->ldb,
+ "no objectGUID found in search: "
+ "local_password module must be "
+ "onfigured below objectGUID module!\n");
return LDB_ERR_CONSTRAINT_VIOLATION;
}
- /* Find the objectGUID to use as the key */
- objectGUID = samdb_result_guid(ac->orig_req->op.add.message, "objectGUID");
-
- local_message->dn = ldb_dn_new(local_message, module->ldb, LOCAL_BASE);
- ldb_dn_add_child_fmt(local_message->dn, PASSWORD_GUID_ATTR "=%s", GUID_string(local_message, &objectGUID));
-
- ac->local_req->op.add.message = local_message;
-
- ac->local_req->context = NULL;
- ac->local_req->callback = NULL;
-
- ac->step = LPDB_ADD_REMOTE;
+ ac->local_message->dn = ldb_dn_new(ac->local_message,
+ module->ldb, LOCAL_BASE);
+ if ((ac->local_message->dn == NULL) ||
+ ( ! ldb_dn_add_child_fmt(ac->local_message->dn,
+ PASSWORD_GUID_ATTR "=%s",
+ GUID_string(ac->local_message,
+ &objectGUID)))) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
- /* Return our own handle do deal with this call */
- req->handle = h;
+ ret = ldb_build_add_req(&remote_req, module->ldb, ac,
+ remote_message,
+ req->controls,
+ ac, lpdb_add_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- return ldb_next_request(module, ac->remote_req);
+ return ldb_next_request(module, remote_req);
}
-/* After adding the remote entry, add the local one */
-static int local_password_add_local(struct ldb_handle *h) {
-
+/* Add a record, splitting password attributes from the user's main
+ * record */
+static int lpdb_add_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ struct ldb_request *local_req;
struct lpdb_context *ac;
- ac = talloc_get_type(h->private_data, struct lpdb_context);
+ int ret;
+
+ ac = talloc_get_type(req->context, struct lpdb_context);
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
+ 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);
+ }
- ac->step = LPDB_LOCAL;
+ if (ares->type != LDB_REPLY_DONE) {
+ ldb_set_errstring(ac->module->ldb, "Unexpected reply type");
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->local_req);
+ ac->remote_done = talloc_steal(ac, ares);
- /* perform the local add */
- return ldb_next_request(ac->module, ac->local_req);
+ ret = ldb_build_add_req(&local_req, ac->module->ldb, ac,
+ ac->local_message,
+ NULL,
+ ac, lpdb_local_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+
+ ret = ldb_next_request(ac->module, local_req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+ return LDB_SUCCESS;
}
-static int local_password_mod_search_self(struct ldb_handle *h);
+/*****************************************************************************
+ * MODIFY
+ ****************************************************************************/
+
+static int lpdb_modify_callabck(struct ldb_request *req,
+ struct ldb_reply *ares);
+static int lpdb_mod_search_callback(struct ldb_request *req,
+ struct ldb_reply *ares);
static int local_password_modify(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_handle *h;
struct lpdb_context *ac;
struct ldb_message *remote_message;
- struct ldb_message *local_message;
+ struct ldb_request *remote_req;
+ int ret;
int i;
ldb_debug(module->ldb, LDB_DEBUG_TRACE, "local_password_modify\n");
@@ -289,243 +327,565 @@ static int local_password_modify(struct ldb_module *module, struct ldb_request *
}
/* From here, we assume we have password attributes to split off */
- h = lpdb_init_handle(req, module, LPDB_MOD);
- if (!h) {
+ ac = lpdb_init_context(module, req);
+ if (!ac) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(h->private_data, struct lpdb_context);
- ac->orig_req = req;
-
- ac->remote_req = talloc(ac, struct ldb_request);
- if (ac->remote_req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *(ac->remote_req) = *(ac->orig_req);
- remote_message = ldb_msg_copy_shallow(ac->remote_req, ac->orig_req->op.mod.message);
+ remote_message = ldb_msg_copy_shallow(ac, ac->req->op.mod.message);
if (remote_message == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
-
+
/* Remove any password attributes from the remote message */
for (i=0; i < ARRAY_SIZE(password_attrs); i++) {
ldb_msg_remove_attr(remote_message, password_attrs[i]);
}
- ac->remote_req->op.mod.message = remote_message;
-
- ac->remote_req->context = NULL;
- ac->remote_req->callback = NULL;
-
- ac->local_req = talloc(ac, struct ldb_request);
- if (ac->local_req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *(ac->local_req) = *(ac->orig_req);
- local_message = ldb_msg_copy_shallow(ac->local_req, ac->orig_req->op.mod.message);
- if (local_message == NULL) {
+ ac->local_message = ldb_msg_copy_shallow(ac, ac->req->op.mod.message);
+ if (ac->local_message == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
/* Remove anything seen in the remote message from the local
* message (leaving only password attributes) */
- for (i=0;i<ac->remote_req->op.mod.message->num_elements;i++) {
- ldb_msg_remove_attr(local_message, ac->remote_req->op.mod.message->elements[i].name);
+ for (i=0; i < remote_message->num_elements;i++) {
+ ldb_msg_remove_attr(ac->local_message, remote_message->elements[i].name);
}
- ac->local_req->op.mod.message = local_message;
- ac->local_message = local_message;
+ ret = ldb_build_mod_req(&remote_req, module->ldb, ac,
+ remote_message,
+ req->controls,
+ ac, lpdb_modify_callabck,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- ac->local_req->context = NULL;
- ac->local_req->callback = NULL;
+ return ldb_next_request(module, remote_req);
+}
- ac->step = LPDB_MOD_REMOTE;
+/* On a modify, we don't have the objectGUID handy, so we need to
+ * search our DN for it */
+static int lpdb_modify_callabck(struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ static const char * const attrs[] = { "objectGUID", "objectClass", NULL };
+ struct ldb_request *search_req;
+ struct lpdb_context *ac;
+ int ret;
+
+ ac = talloc_get_type(req->context, struct lpdb_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, "Unexpected reply type");
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ac->remote_done = talloc_steal(ac, ares);
- /* Return our own handle do deal with this call */
- req->handle = h;
+ /* prepare the search operation */
+ ret = ldb_build_search_req(&search_req, ac->module->ldb, ac,
+ ac->req->op.mod.message->dn, LDB_SCOPE_BASE,
+ "(objectclass=*)", attrs,
+ NULL,
+ ac, lpdb_mod_search_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
- return ldb_next_request(module, ac->remote_req);
+ ret = ldb_next_request(ac->module, search_req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ return LDB_SUCCESS;
}
-/* Called when we search for our oen entry. Stores the one entry we
+/* Called when we search for our own entry. Stores the one entry we
* expect (as it is a base search) on the context pointer */
-static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int lpdb_mod_search_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
{
+ struct ldb_request *local_req;
struct lpdb_context *ac;
+ struct ldb_dn *local_dn;
+ struct GUID objectGUID;
+ int ret = LDB_SUCCESS;
- ac = talloc_get_type(context, struct lpdb_context);
+ ac = talloc_get_type(req->context, struct lpdb_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);
+ }
- /* we are interested only in the single reply (base search) we receive here */
- if (ares->type == LDB_REPLY_ENTRY) {
- if (ac->search_res != NULL) {
- ldb_set_errstring(ldb, "Too many results");
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
+ if (ac->remote != NULL) {
+ ldb_set_errstring(ac->module->ldb, "Too many results");
talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
- ac->search_res = talloc_steal(ac, ares);
- } else {
+ ac->remote = talloc_steal(ac, ares);
+ break;
+
+ case LDB_REPLY_REFERRAL:
+
+ /* ignore */
+ talloc_free(ares);
+ break;
+
+ case LDB_REPLY_DONE:
+ /* After we find out the objectGUID for the entry, modify the local
+ * password database as required */
+
talloc_free(ares);
+
+ /* if it is not an entry of type person this is an error */
+ /* TODO: remove this when sambaPassword will be in schema */
+ if (ac->remote == NULL) {
+ ldb_asprintf_errstring(ac->module->ldb,
+ "entry just modified (%s) not found!",
+ ldb_dn_get_linearized(req->op.search.base));
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (!ldb_msg_check_string_attribute(ac->remote->message,
+ "objectClass", "person")) {
+ /* Not relevent to us */
+ return ldb_module_done(ac->req,
+ ac->remote_done->controls,
+ ac->remote_done->response,
+ ac->remote_done->error);
+ }
+
+ if (ldb_msg_find_ldb_val(ac->remote->message,
+ "objectGUID") == NULL) {
+ ldb_set_errstring(ac->module->ldb,
+ "no objectGUID found in search: "
+ "local_password module must be "
+ "configured below objectGUID "
+ "module!\n");
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OBJECT_CLASS_VIOLATION);
+ }
+
+ objectGUID = samdb_result_guid(ac->remote->message,
+ "objectGUID");
+
+ local_dn = ldb_dn_new(ac, ac->module->ldb, LOCAL_BASE);
+ if ((local_dn == NULL) ||
+ ( ! ldb_dn_add_child_fmt(local_dn,
+ PASSWORD_GUID_ATTR "=%s",
+ GUID_string(ac, &objectGUID)))) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ ac->local_message->dn = local_dn;
+
+ ret = ldb_build_mod_req(&local_req, ac->module->ldb, ac,
+ ac->local_message,
+ NULL,
+ ac, lpdb_local_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+
+ /* perform the local update */
+ ret = ldb_next_request(ac->module, local_req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
}
return LDB_SUCCESS;
}
-/* On a modify, we don't have the objectGUID handy, so we need to
- * search our DN for it */
-static int local_password_mod_search_self(struct ldb_handle *h) {
+/*****************************************************************************
+ * DELETE
+ ****************************************************************************/
+static int lpdb_delete_callabck(struct ldb_request *req,
+ struct ldb_reply *ares);
+static int lpdb_del_search_callback(struct ldb_request *req,
+ struct ldb_reply *ares);
+
+static int local_password_delete(struct ldb_module *module,
+ struct ldb_request *req)
+{
+ struct ldb_request *remote_req;
struct lpdb_context *ac;
- static const char * const attrs[] = { "objectGUID", "objectClass", NULL };
+ int ret;
- ac = talloc_get_type(h->private_data, struct lpdb_context);
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "local_password_delete\n");
- /* prepare the search operation */
- ac->search_req = talloc_zero(ac, struct ldb_request);
- if (ac->search_req == NULL) {
- ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");
- return LDB_ERR_OPERATIONS_ERROR;
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.mod.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ /* If the caller is manipulating the local passwords directly,
+ * let them pass */
+ if (ldb_dn_compare_base(ldb_dn_new(req, module->ldb, LOCAL_BASE),
+ req->op.del.dn) == 0) {
+ return ldb_next_request(module, req);
}
- ac->search_req->operation = LDB_SEARCH;
- ac->search_req->op.search.base = ac->orig_req->op.mod.message->dn;
- ac->search_req->op.search.scope = LDB_SCOPE_BASE;
- ac->search_req->op.search.tree = ldb_parse_tree(ac->orig_req, NULL);
- if (ac->search_req->op.search.tree == NULL) {
- ldb_set_errstring(ac->module->ldb, "Invalid search filter");
+ /* From here, we assume we have password attributes to split off */
+ ac = lpdb_init_context(module, req);
+ if (!ac) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac->search_req->op.search.attrs = attrs;
- ac->search_req->controls = NULL;
- ac->search_req->context = ac;
- ac->search_req->callback = get_self_callback;
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
- ac->step = LPDB_MOD_SEARCH_SELF;
+ ret = ldb_build_del_req(&remote_req, module->ldb, ac,
+ req->op.del.dn,
+ req->controls,
+ ac, lpdb_delete_callabck,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- return ldb_next_request(ac->module, ac->search_req);
+ return ldb_next_request(module, remote_req);
}
-/* After we find out the objectGUID for the entry, modify the local
- * password database as required */
-static int local_password_mod_local(struct ldb_handle *h) {
+/* On a modify, we don't have the objectGUID handy, so we need to
+ * search our DN for it */
+static int lpdb_delete_callabck(struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ static const char * const attrs[] = { "objectGUID", "objectClass", NULL };
+ struct ldb_request *search_req;
+ struct lpdb_context *ac;
+ int ret;
+ ac = talloc_get_type(req->context, struct lpdb_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, "Unexpected reply type");
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ac->remote_done = talloc_steal(ac, ares);
+
+ /* prepare the search operation */
+ ret = ldb_build_search_req(&search_req, ac->module->ldb, ac,
+ ac->req->op.del.dn, LDB_SCOPE_BASE,
+ "(objectclass=*)", attrs,
+ NULL,
+ ac, lpdb_del_search_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ret = ldb_next_request(ac->module, search_req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ return LDB_SUCCESS;
+}
+
+/* Called when we search for our own entry. Stores the one entry we
+ * expect (as it is a base search) on the context pointer */
+static int lpdb_del_search_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ struct ldb_request *local_req;
struct lpdb_context *ac;
+ struct ldb_dn *local_dn;
struct GUID objectGUID;
- ac = talloc_get_type(h->private_data, struct lpdb_context);
-
- /* if it is not an entry of type person this is an error */
- /* TODO: remove this when these things are checked in the schema */
- if (!ac->search_res) {
- ldb_asprintf_errstring(ac->module->ldb,
- "entry just modified (%s) not found!",
- ldb_dn_get_linearized(ac->remote_req->op.mod.message->dn));
- return LDB_ERR_OPERATIONS_ERROR;
- }
- if (!ldb_msg_check_string_attribute(ac->search_res->message, "objectClass", "person")) {
- /* Not relevent to us */
- return LDB_SUCCESS;
+ int ret = LDB_SUCCESS;
+
+ ac = talloc_get_type(req->context, struct lpdb_context);
+
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
-
- if (ldb_msg_find_ldb_val(ac->search_res->message, "objectGUID") == NULL) {
- ldb_set_errstring(ac->module->ldb,
- "no objectGUID found in search: local_password module must be configured below objectGUID module!\n");
- return LDB_ERR_OBJECT_CLASS_VIOLATION;
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
-
- objectGUID = samdb_result_guid(ac->search_res->message, "objectGUID");
- ac->local_message->dn = ldb_dn_new(ac, ac->module->ldb, LOCAL_BASE);
- ldb_dn_add_child_fmt(ac->local_message->dn, PASSWORD_GUID_ATTR "=%s", GUID_string(ac, &objectGUID));
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
+ if (ac->remote != NULL) {
+ ldb_set_errstring(ac->module->ldb, "Too many results");
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ac->remote = talloc_steal(ac, ares);
+ break;
+
+ case LDB_REPLY_REFERRAL:
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
+ /* ignore */
+ talloc_free(ares);
+ break;
- ac->step = LPDB_LOCAL;
+ case LDB_REPLY_DONE:
+ /* After we find out the objectGUID for the entry, modify the local
+ * password database as required */
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->local_req);
+ talloc_free(ares);
+
+ /* if it is not an entry of type person this is NOT an error */
+ /* TODO: remove this when sambaPassword will be in schema */
+ if (ac->remote == NULL) {
+ return ldb_module_done(ac->req,
+ ac->remote_done->controls,
+ ac->remote_done->response,
+ ac->remote_done->error);
+ }
+ if (!ldb_msg_check_string_attribute(ac->remote->message,
+ "objectClass", "person")) {
+ /* Not relevent to us */
+ return ldb_module_done(ac->req,
+ ac->remote_done->controls,
+ ac->remote_done->response,
+ ac->remote_done->error);
+ }
+
+ if (ldb_msg_find_ldb_val(ac->remote->message,
+ "objectGUID") == NULL) {
+ ldb_set_errstring(ac->module->ldb,
+ "no objectGUID found in search: "
+ "local_password module must be "
+ "configured below objectGUID "
+ "module!\n");
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OBJECT_CLASS_VIOLATION);
+ }
+
+ objectGUID = samdb_result_guid(ac->remote->message,
+ "objectGUID");
+
+ local_dn = ldb_dn_new(ac, ac->module->ldb, LOCAL_BASE);
+ if ((local_dn == NULL) ||
+ ( ! ldb_dn_add_child_fmt(local_dn,
+ PASSWORD_GUID_ATTR "=%s",
+ GUID_string(ac, &objectGUID)))) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ret = ldb_build_del_req(&local_req, ac->module->ldb, ac,
+ local_dn,
+ NULL,
+ ac, lpdb_local_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
- /* perform the local update */
- return ldb_next_request(ac->module, ac->local_req);
+ /* perform the local update */
+ ret = ldb_next_request(ac->module, local_req);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+ }
+
+ return LDB_SUCCESS;
}
-static int lpdb_local_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+/*****************************************************************************
+ * SEARCH
+ ****************************************************************************/
+
+static int lpdb_local_search_callback(struct ldb_request *req,
+ struct ldb_reply *ares);
+
+static int lpdb_local_search(struct lpdb_context *ac)
+{
+ struct ldb_request *local_req;
+ int ret;
+
+ ret = ldb_build_search_req(&local_req, ac->module->ldb, ac,
+ ac->current->local_dn,
+ LDB_SCOPE_BASE,
+ "(objectclass=*)",
+ ac->req->op.search.attrs,
+ NULL,
+ ac, lpdb_local_search_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return ldb_next_request(ac->module, local_req);
+}
+
+static int lpdb_local_search_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
{
- struct lpdb_local_search_context *local_context;
+ struct lpdb_context *ac;
+ struct ldb_reply *merge;
+ struct lpdb_reply *lr;
+ int ret;
+ int i;
+
+ ac = talloc_get_type(req->context, struct lpdb_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);
+ }
- local_context = talloc_get_type(context, struct lpdb_local_search_context);
+ lr = ac->current;
- /* we are interested only in the single reply (base search) we receive here */
+ /* we are interested only in a single reply (base search) */
switch (ares->type) {
case LDB_REPLY_ENTRY:
- {
- int i;
- if (local_context->local_res != NULL) {
- ldb_set_errstring(ldb, "Too many results to base search for password entry!");
+
+ if (lr->remote == NULL) {
+ ldb_set_errstring(ac->module->ldb,
+ "Too many results for password entry search!");
talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
-
- local_context->local_res = ares;
- /* Make sure never to return the internal key attribute to the caller */
+ merge = lr->remote;
+ lr->remote = NULL;
+
+ /* steal the local results on the remote results to be
+ * returned all together */
+ talloc_steal(merge, ares->message->elements);
+
+ /* Make sure never to return the internal key attribute */
ldb_msg_remove_attr(ares->message, PASSWORD_GUID_ATTR);
- talloc_steal(local_context->remote_res->message->elements, ares->message->elements);
for (i=0; i < ares->message->num_elements; i++) {
struct ldb_message_element *el;
- el = ldb_msg_find_element(local_context->remote_res->message,
+ el = ldb_msg_find_element(merge->message,
ares->message->elements[i].name);
if (!el) {
- if (ldb_msg_add_empty(local_context->remote_res->message,
- ares->message->elements[i].name, 0, &el) != LDB_SUCCESS) {
+ ret = ldb_msg_add_empty(merge->message,
+ ares->message->elements[i].name,
+ 0, &el);
+ if (ret != LDB_SUCCESS) {
talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
+ return ldb_module_done(ac->req,
+ NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
*el = ares->message->elements[i];
}
}
- return local_context->ac->orig_req->callback(ldb,
- local_context->ac->orig_req->context,
- local_context->remote_res);
- }
- case LDB_REPLY_DONE:
- {
- /* Fire off the callback if there was no local entry, so we get the rest returned */
- if (local_context->local_res == NULL) {
- return local_context->ac->orig_req->callback(ldb,
- local_context->ac->orig_req->context,
- local_context->remote_res);
- }
- return LDB_SUCCESS;
+
+ /* free the rest */
+ talloc_free(ares);
+
+ return ldb_module_send_entry(ac->req, merge->message);
+
+ case LDB_REPLY_REFERRAL:
+ /* ignore */
+ talloc_free(ares);
break;
- }
- default:
- {
+
+ case LDB_REPLY_DONE:
+
talloc_free(ares);
- ldb_set_errstring(ldb, "Unexpected result type in base search for password entry!");
- return LDB_ERR_OPERATIONS_ERROR;
- }
+
+ /* if this entry was not returned yet, return it now */
+ if (lr->remote) {
+ ret = ldb_module_send_entry(ac->req, ac->remote->message);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req,
+ NULL, NULL, ret);
+ }
+ lr->remote = NULL;
+ }
+
+ if (lr->next->remote->type == LDB_REPLY_DONE) {
+ /* this was the last one */
+ return ldb_module_done(ac->req,
+ lr->next->remote->controls,
+ lr->next->remote->response,
+ lr->next->remote->error);
+ } else {
+ /* next one */
+ ac->current = lr->next;
+ talloc_free(lr);
+
+ ret = lpdb_local_search(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req,
+ NULL, NULL, ret);
+ }
+ }
}
+
+ return LDB_SUCCESS;
}
/* For each entry returned in a remote search, do a local base search,
* based on the objectGUID we asked for as an additional attribute */
-static int lpdb_remote_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int lpdb_remote_search_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
{
struct lpdb_context *ac;
+ struct ldb_dn *local_dn;
+ struct GUID objectGUID;
+ struct lpdb_reply *lr;
+ int ret;
- ac = talloc_get_type(context, struct lpdb_context);
+ ac = talloc_get_type(req->context, struct lpdb_context);
- if (ares->type == LDB_REPLY_ENTRY) {
- struct ldb_request *req;
- struct lpdb_local_search_context *local_context;
- struct GUID objectGUID;
+ 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);
+ }
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
/* No point searching further if it's not a 'person' entry */
if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) {
@@ -538,13 +898,14 @@ static int lpdb_remote_search_callback(struct ldb_context *ldb, void *context, s
ldb_msg_remove_attr(ares->message, "objectClass");
}
- return ac->orig_req->callback(ldb, ac->orig_req->context, ares);
+ return ldb_module_send_entry(ac->req, ares->message);
}
if (ldb_msg_find_ldb_val(ares->message, "objectGUID") == NULL) {
ldb_set_errstring(ac->module->ldb,
"no objectGUID found in search: local_password module must be configured below objectGUID module!\n");
- return LDB_ERR_OPERATIONS_ERROR;
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
objectGUID = samdb_result_guid(ares->message, "objectGUID");
@@ -557,44 +918,63 @@ static int lpdb_remote_search_callback(struct ldb_context *ldb, void *context, s
ldb_msg_remove_attr(ares->message, "objectClass");
}
- req = talloc_zero(ac, struct ldb_request);
- if (!req) {
- return LDB_ERR_OPERATIONS_ERROR;
+ local_dn = ldb_dn_new(ac, ac->module->ldb, LOCAL_BASE);
+ if ((local_dn == NULL) ||
+ (! ldb_dn_add_child_fmt(local_dn,
+ PASSWORD_GUID_ATTR "=%s",
+ GUID_string(ac, &objectGUID)))) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ lr = talloc_zero(ac, struct lpdb_reply);
+ if (lr == NULL) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
+ lr->local_dn = talloc_steal(lr, local_dn);
+ lr->remote = talloc_steal(lr, ares);
- local_context = talloc(ac, struct lpdb_local_search_context);
- if (!local_context) {
- return LDB_ERR_OPERATIONS_ERROR;
+ if (ac->list) {
+ ac->current->next = lr;
+ } else {
+ ac->list = lr;
}
- local_context->ac = ac;
- local_context->remote_res = ares;
- local_context->local_res = NULL;
+ ac->current= lr;
+
+ break;
- req->op.search.base = ldb_dn_new(ac, ac->module->ldb, LOCAL_BASE);
- if ( ! ldb_dn_add_child_fmt(req->op.search.base, PASSWORD_GUID_ATTR "=%s", GUID_string(ac, &objectGUID))) {
- return LDB_ERR_OPERATIONS_ERROR;
+ case LDB_REPLY_REFERRAL:
+
+ return ldb_module_send_referral(ac->req, ares->referral);
+
+ case LDB_REPLY_DONE:
+
+ if (ac->list == NULL) {
+ /* found nothing */
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
- req->operation = LDB_SEARCH;
- req->op.search.scope = LDB_SCOPE_BASE;
- req->op.search.tree = ldb_parse_tree(req, NULL);
- if (req->op.search.tree == NULL) {
- ldb_set_errstring(ac->module->ldb, "Out of Memory");
- return LDB_ERR_OPERATIONS_ERROR;
+
+ lr = talloc_zero(ac, struct lpdb_reply);
+ if (lr == NULL) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
- req->op.search.attrs = ac->orig_req->op.search.attrs;
- req->controls = NULL;
- req->context = ac;
- req->callback = get_self_callback;
+ lr->remote = talloc_steal(lr, ares);
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, req);
-
- req->context = local_context;
- req->callback = lpdb_local_search_callback;
+ ac->current->next = lr;
- return ldb_next_request(ac->module, req);
- } else {
- return ac->orig_req->callback(ldb, ac->orig_req->context, ares);
+ /* rewind current and start local searches */
+ ac->current= ac->list;
+
+ ret = lpdb_local_search(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
}
+
+ return LDB_SUCCESS;
}
/* Search for passwords and other attributes. The passwords are
@@ -603,7 +983,7 @@ static int lpdb_remote_search_callback(struct ldb_context *ldb, void *context, s
static int local_password_search(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_handle *h;
+ struct ldb_request *remote_req;
struct lpdb_context *ac;
int i;
int ret;
@@ -615,6 +995,8 @@ static int local_password_search(struct ldb_module *module, struct ldb_request *
return ldb_next_request(module, req);
}
+ search_attrs = NULL;
+
/* If the caller is searching for the local passwords directly, let them pass */
if (ldb_dn_compare_base(ldb_dn_new(req, module->ldb, LOCAL_BASE),
req->op.search.base) == 0) {
@@ -634,32 +1016,15 @@ static int local_password_search(struct ldb_module *module, struct ldb_request *
}
}
- h = lpdb_init_handle(req, module, LPDB_SEARCH);
- if (!h) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac = talloc_get_type(h->private_data, struct lpdb_context);
-
- ac->orig_req = req;
-
- ac->remote_req = talloc(ac, struct ldb_request);
- if (ac->remote_req == NULL) {
+ ac = lpdb_init_context(module, req);
+ if (!ac) {
return LDB_ERR_OPERATIONS_ERROR;
}
/* Remote search is for all attributes: if the remote LDAP server has these attributes, then it overrides the local database */
- *(ac->remote_req) = *(ac->orig_req);
-
- /* Return our own handle do deal with this call */
- ac->remote_req->handle = h;
-
- ac->remote_req->context = ac;
- ac->remote_req->callback = lpdb_remote_search_callback;
-
if (req->op.search.attrs && !ldb_attr_in_list(req->op.search.attrs, "*")) {
if (!ldb_attr_in_list(req->op.search.attrs, "objectGUID")) {
- search_attrs = ldb_attr_list_copy_add(req, req->op.search.attrs, "objectGUID");
+ search_attrs = ldb_attr_list_copy_add(ac, req->op.search.attrs, "objectGUID");
ac->added_objectGUID = true;
if (!search_attrs) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -668,7 +1033,7 @@ static int local_password_search(struct ldb_module *module, struct ldb_request *
search_attrs = req->op.search.attrs;
}
if (!ldb_attr_in_list(search_attrs, "objectClass")) {
- search_attrs = ldb_attr_list_copy_add(req, search_attrs, "objectClass");
+ search_attrs = ldb_attr_list_copy_add(ac, search_attrs, "objectClass");
ac->added_objectClass = true;
if (!search_attrs) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -678,175 +1043,26 @@ static int local_password_search(struct ldb_module *module, struct ldb_request *
search_attrs = req->op.search.attrs;
}
- ac->remote_req->op.search.attrs = search_attrs;
-
- ldb_set_timeout_from_prev_req(module->ldb, ac->orig_req, ac->remote_req);
-
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->step = LPDB_SEARCH_REMOTE;
-
- /* perform the search */
- ret = ldb_next_request(module, ac->remote_req);
-
- if (ret == LDB_SUCCESS) {
- req->handle = ac->remote_req->handle;
- }
-
- return ret;
-}
-
-static int lpdb_wait(struct ldb_handle *handle) {
- struct lpdb_context *ac;
- int ret;
-
- if (!handle || !handle->private_data) {
+ ret = ldb_build_search_req_ex(&remote_req, module->ldb, ac,
+ req->op.search.base,
+ req->op.search.scope,
+ req->op.search.tree,
+ search_attrs,
+ req->controls,
+ ac, lpdb_remote_search_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
return LDB_ERR_OPERATIONS_ERROR;
}
- if (handle->state == LDB_ASYNC_DONE) {
- return handle->status;
- }
-
- handle->state = LDB_ASYNC_PENDING;
- handle->status = LDB_SUCCESS;
-
- ac = talloc_get_type(handle->private_data, struct lpdb_context);
-
- switch (ac->step) {
- case LPDB_ADD_REMOTE:
- ret = ldb_wait(ac->remote_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->remote_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->remote_req->handle->status;
- goto done;
- }
-
- if (ac->remote_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* original request done, go on */
- return local_password_add_local(handle);
-
- case LPDB_MOD_REMOTE:
- ret = ldb_wait(ac->remote_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->remote_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->remote_req->handle->status;
- goto done;
- }
-
- if (ac->remote_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* original request done, go on */
- return local_password_mod_search_self(handle);
-
- case LPDB_MOD_SEARCH_SELF:
- ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->search_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->search_req->handle->status;
- goto done;
- }
-
- if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* original request done, go on */
- return local_password_mod_local(handle);
-
- case LPDB_LOCAL:
- ret = ldb_wait(ac->local_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->local_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->local_req->handle->status;
- goto done;
- }
-
- if (ac->local_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- break;
-
- case LPDB_SEARCH_REMOTE:
- ret = ldb_wait(ac->remote_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->remote_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->remote_req->handle->status;
- goto done;
- }
-
- if (ac->remote_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- break;
-
- default:
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
-
- ret = LDB_SUCCESS;
-
-done:
- handle->state = LDB_ASYNC_DONE;
- return ret;
-}
-
-static int lpdb_wait_all(struct ldb_handle *handle) {
-
- int ret;
-
- while (handle->state != LDB_ASYNC_DONE) {
- ret = lpdb_wait(handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- return handle->status;
-}
-
-static int local_password_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
- if (type == LDB_WAIT_ALL) {
- return lpdb_wait_all(handle);
- } else {
- return lpdb_wait(handle);
- }
+ /* perform the search */
+ return ldb_next_request(module, remote_req);
}
_PUBLIC_ const struct ldb_module_ops ldb_local_password_module_ops = {
.name = "local_password",
.add = local_password_add,
.modify = local_password_modify,
- .search = local_password_search,
- .wait = local_password_wait
+ .del = local_password_delete,
+ .search = local_password_search
};