summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2006-05-22 03:55:01 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:08:21 -0500
commit8081e4f40276034c47bd799aca64a7d01ffb1bce (patch)
tree6bdaf99ccc63e7bcba5db25b255844702466a232 /source4
parent79183f68fc2bbe9094f9ab4e1bf7c5a3c8d5dd07 (diff)
downloadsamba-8081e4f40276034c47bd799aca64a7d01ffb1bce.tar.gz
samba-8081e4f40276034c47bd799aca64a7d01ffb1bce.tar.bz2
samba-8081e4f40276034c47bd799aca64a7d01ffb1bce.zip
r15795: Try to use the async code by default
It passess all my tests, but I still need to work on a lot of stuff. Shouldn't impact anybody else work, so I want to commit now and see what happens Will work to remove the old code from modules and backends soon, and make some more restyling in ldb internals. So, if there is something you don't like in this desgin please speak now. Simo. (This used to be commit 8b2a563e716a789ea77cbfbf2f372724de5361ce)
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c21
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c36
-rw-r--r--source4/lib/ldb/common/ldb.c152
-rw-r--r--source4/setup/provision_init.ldif4
4 files changed, 185 insertions, 28 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 0d4f0c6a0f..c1eb244e19 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -975,16 +975,25 @@ static int add_krb5_keys_from_NThash(struct ldb_module *module, struct ldb_messa
return LDB_SUCCESS;
}
-static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg)
+static int set_pwdLastSet(struct ldb_module *module, struct ldb_message *msg, int is_mod)
{
NTTIME now_nt;
/* set it as now */
unix_to_nt_time(&now_nt, time(NULL));
- /* replace or add */
- if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) {
- return LDB_ERR_OPERATIONS_ERROR;
+ if (!is_mod) {
+ /* be sure there isn't a 0 value set (eg. coming from the template) */
+ ldb_msg_remove_attr(msg, "pwdLastSet");
+ /* add */
+ if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_ADD) != 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ } else {
+ /* replace */
+ if (ldb_msg_add_empty(msg, "pwdLastSet", LDB_FLAG_MOD_REPLACE) != 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
}
if (samdb_msg_add_uint64(module->ldb, msg, msg, "pwdLastSet", now_nt) != 0) {
@@ -1326,7 +1335,7 @@ static int password_hash_add_async_do_add(struct ldb_async_handle *h) {
/* don't touch it if a value is set. It could be an incoming samsync */
if (ldb_msg_find_uint64(msg, "pwdLastSet", 0) == 0) {
- if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) {
+ if (set_pwdLastSet(ac->module, msg, 0) != LDB_SUCCESS) {
return LDB_ERR_OPERATIONS_ERROR;
}
}
@@ -1630,7 +1639,7 @@ static int password_hash_mod_async_do_mod(struct ldb_async_handle *h) {
}
/* set change time */
- if (set_pwdLastSet(ac->module, msg) != LDB_SUCCESS) {
+ if (set_pwdLastSet(ac->module, msg, 1) != LDB_SUCCESS) {
return LDB_ERR_OPERATIONS_ERROR;
}
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index e662b2a663..9bf322f384 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -94,14 +94,35 @@ static BOOL samldb_msg_add_sid(struct ldb_module *module, struct ldb_message *ms
return (ldb_msg_add_value(msg, name, &v) == 0);
}
-static BOOL samldb_find_or_add_attribute(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value, const char *set_value)
+static BOOL samldb_find_or_add_value(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value, const char *set_value)
{
+ if (msg == NULL || name == NULL || value == NULL || set_value == NULL) {
+ return False;
+ }
+
if (samldb_find_attribute(msg, name, value) == NULL) {
return samldb_msg_add_string(module, msg, name, set_value);
}
return True;
}
+static BOOL samldb_find_or_add_attribute(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *set_value)
+{
+ int j;
+ struct ldb_message_element *el;
+
+ if (msg == NULL || name == NULL || set_value == NULL) {
+ return False;
+ }
+
+ el = ldb_msg_find_element(msg, name);
+ if (el) {
+ return True;
+ }
+
+ return samldb_msg_add_string(module, msg, name, set_value);
+}
+
/*
allocate a new id, attempting to do it atomically
return 0 on failure, the id on success
@@ -492,16 +513,15 @@ static int samldb_copy_template(struct ldb_module *module, struct ldb_message *m
strcasecmp((char *)el->values[j].data, "secretTemplate") == 0) {
continue;
}
- if ( ! samldb_find_or_add_attribute(module, msg, el->name,
- (char *)el->values[j].data,
- (char *)el->values[j].data)) {
+ if ( ! samldb_find_or_add_value(module, msg, el->name,
+ (char *)el->values[j].data,
+ (char *)el->values[j].data)) {
ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Attribute adding failed...\n");
talloc_free(res);
return -1;
}
} else {
if ( ! samldb_find_or_add_attribute(module, msg, el->name,
- NULL,
(char *)el->values[j].data)) {
ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Attribute adding failed...\n");
talloc_free(res);
@@ -558,7 +578,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, name)) {
+ if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", name)) {
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -620,7 +640,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
}
/* if the only attribute was: "objectclass: computer", then make sure we also add "user" objectclass */
- if ( ! samldb_find_or_add_attribute(module, msg2, "objectclass", "user", "user")) {
+ if ( ! samldb_find_or_add_value(module, msg2, "objectclass", "user", "user")) {
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -633,7 +653,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, name)) {
+ if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", name)) {
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c
index 68e3c116fc..3d5f816fe8 100644
--- a/source4/lib/ldb/common/ldb.c
+++ b/source4/lib/ldb/common/ldb.c
@@ -2,6 +2,7 @@
ldb database library
Copyright (C) Andrew Tridgell 2004
+ Copyright (C) Simo Sorce 2005-2006
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -251,6 +252,7 @@ int ldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type typ
return handle->module->ops->async_wait(handle, type);
}
+
/*
check for an error return from an op
if an op fails, but has not setup an error string, then setup one now
@@ -272,6 +274,7 @@ static int ldb_op_finish(struct ldb_context *ldb, int status)
/*
start an ldb request
autostarts a transacion if none active and the operation is not a search
+ does not work for ASYNC operations
NOTE: the request must be a talloc context.
returns LDB_ERR_* on errors.
*/
@@ -285,7 +288,7 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
req->op.search.res = NULL;
}
- /* start a transaction if needed */
+ /* start a transaction if not async and not search */
if ((!ldb->transaction_active) &&
(req->operation == LDB_REQ_ADD ||
req->operation == LDB_REQ_MODIFY ||
@@ -317,6 +320,71 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
Use talloc_free to free the ldb_message returned in 'res', if successful
*/
+static int ldb_search_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
+{
+ struct ldb_result *res;
+ int n;
+
+ if (!context) {
+ ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context in callback"));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ res = *((struct ldb_result **)context);
+
+ if (!res || !ares) {
+ goto error;
+ }
+
+ if (ares->type == LDB_REPLY_ENTRY) {
+ res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
+ if (! res->msgs) {
+ goto error;
+ }
+
+ res->msgs[res->count + 1] = NULL;
+
+ res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+ if (! res->msgs[res->count]) {
+ goto error;
+ }
+
+ res->count++;
+ }
+
+ if (ares->type == LDB_REPLY_REFERRAL) {
+ if (res->refs) {
+ for (n = 0; res->refs[n]; n++) /*noop*/ ;
+ } else {
+ n = 0;
+ }
+
+ res->refs = talloc_realloc(res, res->refs, char *, n + 2);
+ if (! res->refs) {
+ goto error;
+ }
+
+ res->refs[n] = talloc_steal(res->refs, ares->referral);
+ res->refs[n + 1] = NULL;
+ }
+
+ if (ares->controls) {
+ res->controls = talloc_steal(res, ares->controls);
+ if (! res->controls) {
+ goto error;
+ }
+ }
+
+ talloc_free(ares);
+ return LDB_SUCCESS;
+
+error:
+ talloc_free(ares);
+ talloc_free(res);
+ *((struct ldb_result **)context) = NULL;
+ return LDB_ERR_OPERATIONS_ERROR;
+}
+
int ldb_search(struct ldb_context *ldb,
const struct ldb_dn *base,
enum ldb_scope scope,
@@ -327,7 +395,10 @@ int ldb_search(struct ldb_context *ldb,
struct ldb_request *req;
int ret;
- (*res) = NULL;
+ *res = talloc_zero(ldb, struct ldb_result);
+ if (! *res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
req = talloc(ldb, struct ldb_request);
if (req == NULL) {
@@ -335,7 +406,7 @@ int ldb_search(struct ldb_context *ldb,
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_SEARCH;
+ req->operation = LDB_ASYNC_SEARCH;
req->op.search.base = base;
req->op.search.scope = scope;
@@ -348,16 +419,53 @@ int ldb_search(struct ldb_context *ldb,
req->op.search.attrs = attrs;
req->controls = NULL;
+ req->creds = NULL;
+ req->async.context = res;
+ req->async.callback = ldb_search_callback;
+ req->async.timeout = 600; /* 10 minutes */
ret = ldb_request(ldb, req);
if (ret == LDB_SUCCESS) {
- (*res) = talloc_steal(ldb, req->op.search.res);
+ ret = ldb_async_wait(req->async.handle, LDB_WAIT_ALL);
}
+
+ if (ret != LDB_SUCCESS) {
+ talloc_free(*res);
+ *res = NULL;
+ }
+
talloc_free(req);
return ret;
}
+static int ldb_autotransaction_request(struct ldb_context *ldb, struct ldb_request *req)
+{
+ int ret, close_transaction;
+
+ close_transaction = 0;
+ if (!ldb->transaction_active) {
+ ret = ldb_transaction_start(ldb);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ close_transaction = 1;
+ }
+
+ ret = ldb_request(ldb, req);
+
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_async_wait(req->async.handle, LDB_WAIT_ALL);
+ }
+
+ if (close_transaction) {
+ return ldb_op_finish(ldb, ret);
+ }
+
+ return ret;
+}
+
+
/*
add a record to the database. Will fail if a record with the given class and key
already exists
@@ -377,11 +485,16 @@ int ldb_add(struct ldb_context *ldb,
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_ADD;
+ req->operation = LDB_ASYNC_ADD;
req->op.add.message = message;
req->controls = NULL;
+ req->creds = NULL;
+ req->async.context = NULL;
+ req->async.callback = NULL;
+ req->async.timeout = 600; /* 10 minutes */
- ret = ldb_request(ldb, req);
+ /* do request and autostart a transaction */
+ ret = ldb_autotransaction_request(ldb, req);
talloc_free(req);
return ret;
@@ -405,11 +518,16 @@ int ldb_modify(struct ldb_context *ldb,
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_MODIFY;
+ req->operation = LDB_ASYNC_MODIFY;
req->op.add.message = message;
req->controls = NULL;
+ req->creds = NULL;
+ req->async.context = NULL;
+ req->async.callback = NULL;
+ req->async.timeout = 600; /* 10 minutes */
- ret = ldb_request(ldb, req);
+ /* do request and autostart a transaction */
+ ret = ldb_autotransaction_request(ldb, req);
talloc_free(req);
return ret;
@@ -430,11 +548,16 @@ int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_DELETE;
+ req->operation = LDB_ASYNC_DELETE;
req->op.del.dn = dn;
req->controls = NULL;
+ req->creds = NULL;
+ req->async.context = NULL;
+ req->async.callback = NULL;
+ req->async.timeout = 600; /* 10 minutes */
- ret = ldb_request(ldb, req);
+ /* do request and autostart a transaction */
+ ret = ldb_autotransaction_request(ldb, req);
talloc_free(req);
return ret;
@@ -454,12 +577,17 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct
return LDB_ERR_OPERATIONS_ERROR;
}
- req->operation = LDB_REQ_RENAME;
+ req->operation = LDB_ASYNC_RENAME;
req->op.rename.olddn = olddn;
req->op.rename.newdn = newdn;
req->controls = NULL;
+ req->creds = NULL;
+ req->async.context = NULL;
+ req->async.callback = NULL;
+ req->async.timeout = 600; /* 10 minutes */
- ret = ldb_request(ldb, req);
+ /* do request and autostart a transaction */
+ ret = ldb_autotransaction_request(ldb, req);
talloc_free(req);
return ret;
diff --git a/source4/setup/provision_init.ldif b/source4/setup/provision_init.ldif
index ee09f73340..6698b27e33 100644
--- a/source4/setup/provision_init.ldif
+++ b/source4/setup/provision_init.ldif
@@ -82,8 +82,8 @@ vendorVersion: ${VERSION}
#
# Some Known ordering constraints:
# - rootdse must be first, as it makes redirects from "" -> cn=rootdse
-# - password_hash must be before samldb, or else the template code in samldb breaks setting the pwdLastSet attribute
+# - samldb must be before password_hash, because password_hash checks that the objectclass is of type person (filled in by samldb)
dn: @MODULES
-@LIST: rootdse,kludge_acl,paged_results,server_sort,extended_dn,asq,password_hash,samldb,operational,objectguid,rdn_name,objectclass
+@LIST: rootdse,kludge_acl,paged_results,server_sort,extended_dn,asq,samldb,password_hash,operational,objectguid,rdn_name,objectclass