summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/ldb_modules/password_hash.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/password_hash.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/password_hash.c')
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c731
1 files changed, 286 insertions, 445 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 6faef63c3d..e36de3c5c4 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.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
Copyright (C) Stefan Metzmacher 2007
@@ -73,23 +73,16 @@
struct ph_context {
- enum ph_type {PH_ADD, PH_MOD} type;
- enum ph_step {PH_ADD_SEARCH_DOM, PH_ADD_DO_ADD, PH_MOD_DO_REQ, PH_MOD_SEARCH_SELF, PH_MOD_SEARCH_DOM, PH_MOD_DO_MOD} step;
-
struct ldb_module *module;
- struct ldb_request *orig_req;
+ struct ldb_request *req;
struct ldb_request *dom_req;
struct ldb_reply *dom_res;
- struct ldb_request *down_req;
-
- struct ldb_request *search_req;
struct ldb_reply *search_res;
- struct ldb_request *mod_req;
-
struct dom_sid *domain_sid;
+ struct domain_data *domain;
};
struct domain_data {
@@ -1378,168 +1371,193 @@ static int setup_password_fields(struct setup_password_fields_io *io)
return LDB_SUCCESS;
}
-static struct ldb_handle *ph_init_handle(struct ldb_request *req, struct ldb_module *module, enum ph_type type)
+static struct ph_context *ph_init_context(struct ldb_module *module,
+ struct ldb_request *req)
{
struct ph_context *ac;
- struct ldb_handle *h;
- h = talloc_zero(req, struct ldb_handle);
- if (h == NULL) {
- ldb_set_errstring(module->ldb, "Out of Memory");
- return NULL;
- }
-
- h->module = module;
-
- ac = talloc_zero(h, struct ph_context);
+ ac = talloc_zero(req, struct ph_context);
if (ac == NULL) {
ldb_set_errstring(module->ldb, "Out of Memory");
- talloc_free(h);
return NULL;
}
- h->private_data = (void *)ac;
-
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->type = type;
ac->module = module;
- ac->orig_req = req;
+ ac->req = req;
- return h;
+ return ac;
}
-static int get_domain_data_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct ph_context *ac;
- ac = talloc_get_type(context, struct ph_context);
+ ac = talloc_get_type(req->context, struct ph_context);
- /* we are interested only in the single reply (base search) we receive here */
- if (ares->type == LDB_REPLY_ENTRY) {
- if (ac->dom_res != NULL) {
- ldb_set_errstring(ldb, "Too many results");
- talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ac->dom_res = talloc_steal(ac, ares);
- } else {
- talloc_free(ares);
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
-
- return LDB_SUCCESS;
-}
-
-static int build_domain_data_request(struct ph_context *ac)
-{
- /* attrs[] is returned from this function in
- ac->dom_req->op.search.attrs, so it must be static, as
- otherwise the compiler can put it on the stack */
- static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL };
- char *filter;
-
- ac->dom_req = talloc_zero(ac, struct ldb_request);
- if (ac->dom_req == NULL) {
- ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");
- return LDB_ERR_OPERATIONS_ERROR;
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
- ac->dom_req->operation = LDB_SEARCH;
- ac->dom_req->op.search.base = ldb_get_default_basedn(ac->module->ldb);
- ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE;
- filter = talloc_asprintf(ac->dom_req,
- "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))",
- ldap_encode_ndr_dom_sid(ac->dom_req, ac->domain_sid));
- if (filter == NULL) {
- ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");
- talloc_free(ac->dom_req);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac->dom_req->op.search.tree = ldb_parse_tree(ac->dom_req, filter);
- if (ac->dom_req->op.search.tree == NULL) {
- ldb_set_errstring(ac->module->ldb, "Invalid search filter");
- talloc_free(ac->dom_req);
- return LDB_ERR_OPERATIONS_ERROR;
+ if (ares->type != LDB_REPLY_DONE) {
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
- ac->dom_req->op.search.attrs = attrs;
- ac->dom_req->controls = NULL;
- ac->dom_req->context = ac;
- ac->dom_req->callback = get_domain_data_callback;
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->dom_req);
- return LDB_SUCCESS;
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
-static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, struct ldb_reply *res)
+static int password_hash_add_do_add(struct ph_context *ac);
+static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares);
+static int password_hash_mod_search_self(struct ph_context *ac);
+static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares);
+static int password_hash_mod_do_mod(struct ph_context *ac);
+
+static int get_domain_data_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
{
struct domain_data *data;
- const char *tmp;
struct ph_context *ac;
+ int ret;
+ char *tmp;
char *p;
- ac = talloc_get_type(ctx, struct ph_context);
+ ac = talloc_get_type(req->context, struct ph_context);
- data = talloc_zero(ac, struct domain_data);
- if (data == NULL) {
- return NULL;
+ if (!ares) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
-
- if (res == NULL) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Could not find this user's domain: %s!\n", dom_sid_string(data, ac->domain_sid));
- talloc_free(data);
- return NULL;
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, ares->controls,
+ ares->response, ares->error);
}
- data->pwdProperties= samdb_result_uint(res->message, "pwdProperties", 0);
- data->store_cleartext = data->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
- data->pwdHistoryLength = samdb_result_uint(res->message, "pwdHistoryLength", 0);
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
+ if (ac->domain != NULL) {
+ ldb_set_errstring(ac->module->ldb, "Too many results");
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
- /* For a domain DN, this puts things in dotted notation */
- /* For builtin domains, this will give details for the host,
- * but that doesn't really matter, as it's just used for salt
- * and kerberos principals, which don't exist here */
+ data = talloc_zero(ac, struct domain_data);
+ if (data == NULL) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
- tmp = ldb_dn_canonical_string(ctx, res->message->dn);
- if (!tmp) {
- return NULL;
- }
-
- /* But it puts a trailing (or just before 'builtin') / on things, so kill that */
- p = strchr(tmp, '/');
- if (p) {
- p[0] = '\0';
- }
+ data->pwdProperties = samdb_result_uint(ares->message, "pwdProperties", 0);
+ data->store_cleartext = data->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;
+ data->pwdHistoryLength = samdb_result_uint(ares->message, "pwdHistoryLength", 0);
+
+ /* For a domain DN, this puts things in dotted notation */
+ /* For builtin domains, this will give details for the host,
+ * but that doesn't really matter, as it's just used for salt
+ * and kerberos principals, which don't exist here */
+
+ tmp = ldb_dn_canonical_string(data, ares->message->dn);
+ if (!tmp) {
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ /* But it puts a trailing (or just before 'builtin') / on things, so kill that */
+ p = strchr(tmp, '/');
+ if (p) {
+ p[0] = '\0';
+ }
- if (tmp != NULL) {
data->dns_domain = strlower_talloc(data, tmp);
if (data->dns_domain == NULL) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n");
- return NULL;
+ ldb_oom(ac->module->ldb);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
data->realm = strupper_talloc(data, tmp);
if (data->realm == NULL) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n");
- return NULL;
+ ldb_oom(ac->module->ldb);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
}
+ /* FIXME: NetbIOS name is *always* the first domain component ?? -SSS */
p = strchr(tmp, '.');
if (p) {
p[0] = '\0';
}
data->netbios_domain = strupper_talloc(data, tmp);
if (data->netbios_domain == NULL) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n");
- return NULL;
+ ldb_oom(ac->module->ldb);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ talloc_free(tmp);
+ ac->domain = data;
+ break;
+
+ case LDB_REPLY_DONE:
+
+ /* call the next step */
+ switch (ac->req->operation) {
+ case LDB_ADD:
+ ret = password_hash_add_do_add(ac);
+ break;
+
+ case LDB_MODIFY:
+ ret = password_hash_mod_do_mod(ac);
+ break;
+
+ default:
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ break;
+ }
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
}
+
+ case LDB_REPLY_REFERRAL:
+ /* ignore */
+ break;
}
- return data;
+ talloc_free(ares);
+ return LDB_SUCCESS;
+}
+
+static int build_domain_data_request(struct ph_context *ac)
+{
+ /* attrs[] is returned from this function in
+ ac->dom_req->op.search.attrs, so it must be static, as
+ otherwise the compiler can put it on the stack */
+ static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL };
+ char *filter;
+
+ filter = talloc_asprintf(ac,
+ "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))",
+ ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
+ if (filter == NULL) {
+ ldb_oom(ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return ldb_build_search_req(&ac->dom_req, ac->module->ldb, ac,
+ ldb_get_default_basedn(ac->module->ldb),
+ LDB_SCOPE_SUBTREE,
+ filter, attrs,
+ NULL,
+ ac, get_domain_data_callback,
+ ac->req);
}
static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_handle *h;
struct ph_context *ac;
struct ldb_message_element *sambaAttr;
struct ldb_message_element *ntAttr;
@@ -1558,7 +1576,7 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
- /* nobody must touch this fields */
+ /* nobody must touch these fields */
if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {
return LDB_ERR_UNWILLING_TO_PERFORM;
}
@@ -1617,16 +1635,16 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_CONSTRAINT_VIOLATION;
}
- h = ph_init_handle(req, module, PH_ADD);
- if (!h) {
+ ac = ph_init_context(module, req);
+ if (ac == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(h->private_data, struct ph_context);
/* get user domain data */
ac->domain_sid = samdb_result_sid_prefix(ac, req->op.add.message, "objectSid");
if (ac->domain_sid == NULL) {
- ldb_debug(module->ldb, LDB_DEBUG_ERROR, "can't handle entry with missing objectSid!\n");
+ ldb_debug(module->ldb, LDB_DEBUG_ERROR,
+ "can't handle entry with missing objectSid!\n");
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -1635,51 +1653,33 @@ static int password_hash_add(struct ldb_module *module, struct ldb_request *req)
return ret;
}
- ac->step = PH_ADD_SEARCH_DOM;
-
- req->handle = h;
-
return ldb_next_request(module, ac->dom_req);
}
-static int password_hash_add_do_add(struct ldb_handle *h) {
+static int password_hash_add_do_add(struct ph_context *ac) {
- struct ph_context *ac;
- struct domain_data *domain;
+ struct ldb_request *down_req;
struct smb_krb5_context *smb_krb5_context;
struct ldb_message *msg;
struct setup_password_fields_io io;
int ret;
- ac = talloc_get_type(h->private_data, struct ph_context);
-
- domain = get_domain_data(ac->module, ac, ac->dom_res);
- if (domain == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac->down_req = talloc(ac, struct ldb_request);
- if (ac->down_req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *(ac->down_req) = *(ac->orig_req);
- ac->down_req->op.add.message = msg = ldb_msg_copy_shallow(ac->down_req, ac->orig_req->op.add.message);
- if (ac->down_req->op.add.message == NULL) {
+ msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
+ if (msg == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
/* Some operations below require kerberos contexts */
- if (smb_krb5_init_context(ac->down_req,
- ldb_get_opaque(h->module->ldb, "EventContext"),
- (struct loadparm_context *)ldb_get_opaque(h->module->ldb, "loadparm"),
+ if (smb_krb5_init_context(ac,
+ ldb_get_event_context(ac->module->ldb),
+ (struct loadparm_context *)ldb_get_opaque(ac->module->ldb, "loadparm"),
&smb_krb5_context) != 0) {
return LDB_ERR_OPERATIONS_ERROR;
}
ZERO_STRUCT(io);
io.ac = ac;
- io.domain = domain;
+ io.domain = ac->domain;
io.smb_krb5_context = smb_krb5_context;
io.u.user_account_control = samdb_result_uint(msg, "userAccountControl", 0);
@@ -1756,27 +1756,27 @@ static int password_hash_add_do_add(struct ldb_handle *h) {
return ret;
}
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->step = PH_ADD_DO_ADD;
-
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->down_req);
+ ret = ldb_build_add_req(&down_req, ac->module->ldb, ac,
+ msg,
+ ac->req->controls,
+ ac, ph_op_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- /* perform the operation */
- return ldb_next_request(ac->module, ac->down_req);
+ return ldb_next_request(ac->module, down_req);
}
-static int password_hash_mod_search_self(struct ldb_handle *h);
-
static int password_hash_modify(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_handle *h;
struct ph_context *ac;
struct ldb_message_element *sambaAttr;
struct ldb_message_element *ntAttr;
struct ldb_message_element *lmAttr;
struct ldb_message *msg;
+ struct ldb_request *down_req;
+ int ret;
ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_modify\n");
@@ -1824,83 +1824,143 @@ static int password_hash_modify(struct ldb_module *module, struct ldb_request *r
return LDB_ERR_CONSTRAINT_VIOLATION;
}
- h = ph_init_handle(req, module, PH_MOD);
- if (!h) {
+ ac = ph_init_context(module, req);
+ if (!ac) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ac = talloc_get_type(h->private_data, struct ph_context);
- /* return or own handle to deal with this call */
- req->handle = h;
-
- /* prepare the first operation */
- ac->down_req = talloc_zero(ac, struct ldb_request);
- if (ac->down_req == NULL) {
- ldb_set_errstring(module->ldb, "Out of memory!");
+ /* use a new message structure so that we can modify it */
+ msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
+ if (msg == NULL) {
+ ldb_oom(module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- *(ac->down_req) = *req; /* copy the request */
-
- /* use a new message structure so that we can modify it */
- ac->down_req->op.mod.message = msg = ldb_msg_copy_shallow(ac->down_req, req->op.mod.message);
-
- /* - remove any imodification to the password from the first commit
+ /* - remove any modification to the password from the first commit
* we will make the real modification later */
if (sambaAttr) ldb_msg_remove_attr(msg, "userPassword");
if (ntAttr) ldb_msg_remove_attr(msg, "unicodePwd");
if (lmAttr) ldb_msg_remove_attr(msg, "dBCSPwd");
- /* if there was nothing else to be modify skip to next step */
+ /* if there was nothing else to be modified skip to next step */
if (msg->num_elements == 0) {
- talloc_free(ac->down_req);
- ac->down_req = NULL;
- return password_hash_mod_search_self(h);
+ return password_hash_mod_search_self(ac);
}
-
- ac->down_req->context = NULL;
- ac->down_req->callback = NULL;
- ac->step = PH_MOD_DO_REQ;
+ ret = ldb_build_mod_req(&down_req, module->ldb, ac,
+ msg,
+ req->controls,
+ ac, ph_modify_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
- ldb_set_timeout_from_prev_req(module->ldb, req, ac->down_req);
+ return ldb_next_request(module, down_req);
+}
- return ldb_next_request(module, ac->down_req);
+static int ph_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct ph_context *ac;
+ int ret;
+
+ ac = talloc_get_type(req->context, struct ph_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) {
+ talloc_free(ares);
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ ret = password_hash_mod_search_self(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL, ret);
+ }
+
+ talloc_free(ares);
+ return LDB_SUCCESS;
}
-static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int ph_mod_search_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct ph_context *ac;
+ int ret;
+
+ ac = talloc_get_type(req->context, struct ph_context);
- ac = talloc_get_type(context, struct ph_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) */
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
- /* 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");
+ 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);
}
/* if it is not an entry of type person this is an error */
- /* TODO: remove this when userPassword will be in schema */
+ /* TODO: remove this when sambaPassword will be in schema */
if (!ldb_msg_check_string_attribute(ares->message, "objectClass", "person")) {
- ldb_set_errstring(ldb, "Object class violation");
+ ldb_set_errstring(ac->module->ldb, "Object class violation");
talloc_free(ares);
- return LDB_ERR_OBJECT_CLASS_VIOLATION;
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OBJECT_CLASS_VIOLATION);
}
ac->search_res = talloc_steal(ac, ares);
- } else {
- talloc_free(ares);
+ return LDB_SUCCESS;
+
+ case LDB_REPLY_DONE:
+
+ /* get object domain sid */
+ ac->domain_sid = samdb_result_sid_prefix(ac,
+ ac->search_res->message,
+ "objectSid");
+ if (ac->domain_sid == NULL) {
+ ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR,
+ "can't handle entry without objectSid!\n");
+ return ldb_module_done(ac->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+
+ /* get user domain data */
+ ret = build_domain_data_request(ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ac->req, NULL, NULL,ret);
+ }
+
+ return ldb_next_request(ac->module, ac->dom_req);
+
+ case LDB_REPLY_REFERRAL:
+ /*ignore anything else for now */
+ break;
}
+ talloc_free(ares);
return LDB_SUCCESS;
}
-static int password_hash_mod_search_self(struct ldb_handle *h) {
+static int password_hash_mod_search_self(struct ph_context *ac) {
- struct ph_context *ac;
static const char * const attrs[] = { "userAccountControl", "lmPwdHistory",
"ntPwdHistory",
"objectSid", "msDS-KeyVersionNumber",
@@ -1909,64 +1969,28 @@ static int password_hash_mod_search_self(struct ldb_handle *h) {
"dBCSPwd", "unicodePwd",
"supplementalCredentials",
NULL };
-
- ac = talloc_get_type(h->private_data, struct ph_context);
-
- /* 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;
- }
-
- 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->search_req, NULL);
- if (ac->search_req->op.search.tree == NULL) {
- ldb_set_errstring(ac->module->ldb, "Invalid search filter");
- 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 = PH_MOD_SEARCH_SELF;
-
- return ldb_next_request(ac->module, ac->search_req);
-}
-
-static int password_hash_mod_search_dom(struct ldb_handle *h) {
-
- struct ph_context *ac;
+ struct ldb_request *search_req;
int ret;
- ac = talloc_get_type(h->private_data, struct ph_context);
+ ret = ldb_build_search_req(&search_req, ac->module->ldb, ac,
+ ac->req->op.mod.message->dn,
+ LDB_SCOPE_BASE,
+ "(objectclass=*)",
+ attrs,
+ NULL,
+ ac, ph_mod_search_callback,
+ ac->req);
- /* get object domain sid */
- ac->domain_sid = samdb_result_sid_prefix(ac, ac->search_res->message, "objectSid");
- if (ac->domain_sid == NULL) {
- ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "can't handle entry with missing objectSid!\n");
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- /* get user domain data */
- ret = build_domain_data_request(ac);
if (ret != LDB_SUCCESS) {
return ret;
}
- ac->step = PH_MOD_SEARCH_DOM;
-
- return ldb_next_request(ac->module, ac->dom_req);
+ return ldb_next_request(ac->module, search_req);
}
-static int password_hash_mod_do_mod(struct ldb_handle *h) {
+static int password_hash_mod_do_mod(struct ph_context *ac) {
- struct ph_context *ac;
- struct domain_data *domain;
+ struct ldb_request *mod_req;
struct smb_krb5_context *smb_krb5_context;
struct ldb_message *msg;
struct ldb_message *orig_msg;
@@ -1974,43 +1998,29 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) {
struct setup_password_fields_io io;
int ret;
- ac = talloc_get_type(h->private_data, struct ph_context);
-
- domain = get_domain_data(ac->module, ac, ac->dom_res);
- if (domain == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac->mod_req = talloc(ac, struct ldb_request);
- if (ac->mod_req == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *(ac->mod_req) = *(ac->orig_req);
-
/* use a new message structure so that we can modify it */
- ac->mod_req->op.mod.message = msg = ldb_msg_new(ac->mod_req);
+ msg = ldb_msg_new(ac);
if (msg == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
/* modify dn */
- msg->dn = ac->orig_req->op.mod.message->dn;
+ msg->dn = ac->req->op.mod.message->dn;
/* Some operations below require kerberos contexts */
- if (smb_krb5_init_context(ac->mod_req,
- ldb_get_opaque(h->module->ldb, "EventContext"),
- (struct loadparm_context *)ldb_get_opaque(h->module->ldb, "loadparm"),
+ if (smb_krb5_init_context(ac,
+ ldb_get_event_context(ac->module->ldb),
+ (struct loadparm_context *)ldb_get_opaque(ac->module->ldb, "loadparm"),
&smb_krb5_context) != 0) {
return LDB_ERR_OPERATIONS_ERROR;
}
- orig_msg = discard_const(ac->orig_req->op.mod.message);
+ orig_msg = discard_const(ac->req->op.mod.message);
searched_msg = ac->search_res->message;
ZERO_STRUCT(io);
io.ac = ac;
- io.domain = domain;
+ io.domain = ac->domain;
io.smb_krb5_context = smb_krb5_context;
io.u.user_account_control = samdb_result_uint(searched_msg, "userAccountControl", 0);
@@ -2093,189 +2103,20 @@ static int password_hash_mod_do_mod(struct ldb_handle *h) {
return ret;
}
- h->state = LDB_ASYNC_INIT;
- h->status = LDB_SUCCESS;
-
- ac->step = PH_MOD_DO_MOD;
-
- ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->mod_req);
-
- /* perform the search */
- return ldb_next_request(ac->module, ac->mod_req);
-}
-
-static int ph_wait(struct ldb_handle *handle) {
- struct ph_context *ac;
- int ret;
-
- if (!handle || !handle->private_data) {
- 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 ph_context);
-
- switch (ac->step) {
- case PH_ADD_SEARCH_DOM:
- ret = ldb_wait(ac->dom_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->dom_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->dom_req->handle->status;
- goto done;
- }
-
- if (ac->dom_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* domain search done, go on */
- return password_hash_add_do_add(handle);
-
- case PH_ADD_DO_ADD:
- ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->down_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->down_req->handle->status;
- goto done;
- }
-
- if (ac->down_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- break;
-
- case PH_MOD_DO_REQ:
- ret = ldb_wait(ac->down_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->down_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->down_req->handle->status;
- goto done;
- }
-
- if (ac->down_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* non-password mods done, go on */
- return password_hash_mod_search_self(handle);
-
- case PH_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;
- }
-
- if (ac->search_res == NULL) {
- return LDB_ERR_NO_SUCH_OBJECT;
- }
-
- /* self search done, go on */
- return password_hash_mod_search_dom(handle);
-
- case PH_MOD_SEARCH_DOM:
- ret = ldb_wait(ac->dom_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->dom_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->dom_req->handle->status;
- goto done;
- }
-
- if (ac->dom_req->handle->state != LDB_ASYNC_DONE) {
- return LDB_SUCCESS;
- }
-
- /* domain search done, go on */
- return password_hash_mod_do_mod(handle);
-
- case PH_MOD_DO_MOD:
- ret = ldb_wait(ac->mod_req->handle, LDB_WAIT_NONE);
-
- if (ret != LDB_SUCCESS) {
- handle->status = ret;
- goto done;
- }
- if (ac->mod_req->handle->status != LDB_SUCCESS) {
- handle->status = ac->mod_req->handle->status;
- goto done;
- }
-
- if (ac->mod_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 ph_wait_all(struct ldb_handle *handle) {
-
- int ret;
-
- while (handle->state != LDB_ASYNC_DONE) {
- ret = ph_wait(handle);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
+ ret = ldb_build_mod_req(&mod_req, ac->module->ldb, ac,
+ msg,
+ ac->req->controls,
+ ac, ph_op_callback,
+ ac->req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- return handle->status;
-}
-
-static int password_hash_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
- if (type == LDB_WAIT_ALL) {
- return ph_wait_all(handle);
- } else {
- return ph_wait(handle);
- }
+ return ldb_next_request(ac->module, mod_req);
}
_PUBLIC_ const struct ldb_module_ops ldb_password_hash_module_ops = {
.name = "password_hash",
.add = password_hash_add,
.modify = password_hash_modify,
- .wait = password_hash_wait
};