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) {
/* 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;
}
}
}
/* 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;
}
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
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);
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;
}
}
/* 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;
}
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;
}
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
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
/*
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.
*/
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 ||
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,
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) {
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;
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
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;
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;
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;
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;