summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/Makefile.am1
-rw-r--r--server/db/sysdb.c364
-rw-r--r--server/db/sysdb.h371
-rw-r--r--server/db/sysdb_ops.c3633
-rw-r--r--server/db/sysdb_private.h25
-rw-r--r--server/db/sysdb_req.c252
-rw-r--r--server/db/sysdb_search.c122
-rw-r--r--server/ldb_modules/memberof.c2
-rw-r--r--server/providers/ldap/ldap_auth.c86
-rw-r--r--server/providers/proxy.c717
-rw-r--r--server/responder/pam/pam_LOCAL_domain.c115
-rw-r--r--server/tests/sysdb-tests.c1036
-rw-r--r--server/tools/sss_groupadd.c82
-rw-r--r--server/tools/sss_groupdel.c79
-rw-r--r--server/tools/sss_groupmod.c266
-rw-r--r--server/tools/sss_useradd.c166
-rw-r--r--server/tools/sss_userdel.c82
-rw-r--r--server/tools/sss_usermod.c256
18 files changed, 4893 insertions, 2762 deletions
diff --git a/server/Makefile.am b/server/Makefile.am
index 01f3037c9..ab7027f30 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -144,7 +144,6 @@ SSSD_UTIL_OBJ = \
confdb/confdb.c \
db/sysdb.c \
db/sysdb_ops.c \
- db/sysdb_req.c \
db/sysdb_search.c \
monitor/monitor_sbus.c \
providers/dp_auth_util.c \
diff --git a/server/db/sysdb.c b/server/db/sysdb.c
index a86a966b3..bb39c0643 100644
--- a/server/db/sysdb.c
+++ b/server/db/sysdb.c
@@ -140,6 +140,46 @@ int sysdb_attrs_add_long(struct sysdb_attrs *attrs,
return ret;
}
+int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs,
+ const char *name, uint32_t value)
+{
+ unsigned long val = value;
+ struct ldb_val v;
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(attrs, "%lu", val);
+ if (!str) return ENOMEM;
+
+ v.data = (uint8_t *)str;
+ v.length = strlen(str);
+
+ ret = sysdb_attrs_add_val(attrs, name, &v);
+ talloc_free(str);
+
+ return ret;
+}
+
+int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs,
+ const char *name, time_t value)
+{
+ long long val = value;
+ struct ldb_val v;
+ char *str;
+ int ret;
+
+ str = talloc_asprintf(attrs, "%lld", val);
+ if (!str) return ENOMEM;
+
+ v.data = (uint8_t *)str;
+ v.length = strlen(str);
+
+ ret = sysdb_attrs_add_val(attrs, name, &v);
+ talloc_free(str);
+
+ return ret;
+}
+
/* TODO: make a more complete and precise mapping */
int sysdb_error_to_errno(int ldberr)
{
@@ -159,9 +199,327 @@ int sysdb_error_to_errno(int ldberr)
}
}
-/************************************************
- * Initialiazation stuff
- */
+/* =Internal-Operations-Queue============================================= */
+
+static void sysdb_run_operation(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv, void *pvt)
+{
+ struct sysdb_handle *handle = talloc_get_type(pvt, struct sysdb_handle);
+
+ tevent_req_done(handle->subreq);
+}
+
+static void sysdb_schedule_operation(struct sysdb_handle *handle)
+{
+ struct timeval tv = { 0, 0 };
+ struct tevent_timer *te;
+
+ te = tevent_add_timer(handle->ctx->ev, handle, tv,
+ sysdb_run_operation, handle);
+ if (!te) {
+ DEBUG(1, ("Failed to add critical timer to run next handle!\n"));
+ }
+}
+
+static int sysdb_handle_destructor(void *mem)
+{
+ struct sysdb_handle *handle = talloc_get_type(mem, struct sysdb_handle);
+ bool start_next = false;
+ int ret;
+
+ /* if this was the current op start next */
+ if (handle->ctx->queue == handle) {
+ start_next = true;
+ }
+
+ DLIST_REMOVE(handle->ctx->queue, handle);
+
+ if (start_next && handle->ctx->queue) {
+ /* run next */
+ sysdb_schedule_operation(handle->ctx->queue);
+ }
+
+ if (handle->transaction_active) {
+ ret = ldb_transaction_cancel(handle->ctx->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
+ }
+ /* FIXME: abort() ? */
+ handle->transaction_active = false;
+ }
+
+ return 0;
+}
+
+struct sysdb_get_handle_state {
+ struct tevent_context *ev;
+ struct sysdb_ctx *ctx;
+
+ struct sysdb_handle *handle;
+};
+
+struct tevent_req *sysdb_get_handle_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_ctx *ctx)
+{
+ struct tevent_req *req;
+ struct sysdb_get_handle_state *state;
+ struct sysdb_handle *handle;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_get_handle_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->ctx = ctx;
+
+ handle = talloc_zero(state, struct sysdb_handle);
+ if (!handle) {
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ handle->ctx = ctx;
+ handle->subreq = req;
+
+ talloc_set_destructor((TALLOC_CTX *)handle, sysdb_handle_destructor);
+
+ DLIST_ADD_END(ctx->queue, handle, struct sysdb_handle *);
+
+ if (ctx->queue == handle) {
+ /* this is the first in the queue, schedule an immediate run */
+ sysdb_schedule_operation(handle);
+ }
+
+ state->handle = handle;
+
+ return req;
+}
+
+static int sysdb_get_handle_recv(struct tevent_req *req, TALLOC_CTX *memctx,
+ struct sysdb_handle **handle)
+{
+ struct sysdb_get_handle_state *state = tevent_req_data(req,
+ struct sysdb_get_handle_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
+ }
+
+ *handle = talloc_steal(memctx, state->handle);
+ if (!*handle) return ENOMEM;
+
+ return EOK;
+}
+
+/* =Transactions========================================================== */
+
+struct sysdb_transaction_state {
+ struct tevent_context *ev;
+ struct sysdb_ctx *ctx;
+
+ struct sysdb_handle *handle;
+};
+
+static void sysdb_transaction_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_transaction_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_ctx *ctx)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_transaction_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_transaction_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->ctx = ctx;
+
+ subreq = sysdb_get_handle_send(state, ev, ctx);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ tevent_req_set_callback(subreq, sysdb_transaction_done, req);
+
+ return req;
+}
+
+static void sysdb_transaction_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_transaction_state *state = tevent_req_data(req,
+ struct sysdb_transaction_state);
+ int ret;
+
+ ret = sysdb_get_handle_recv(subreq, state, &state->handle);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ ret = ldb_transaction_start(state->ctx->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
+ tevent_req_error(req, sysdb_error_to_errno(ret));
+ return;
+ }
+ state->handle->transaction_active = true;
+
+ tevent_req_done(req);
+}
+
+int sysdb_transaction_recv(struct tevent_req *req, TALLOC_CTX *memctx,
+ struct sysdb_handle **handle)
+{
+ struct sysdb_transaction_state *state = tevent_req_data(req,
+ struct sysdb_transaction_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
+ }
+
+ *handle = talloc_steal(memctx, state->handle);
+ if (!*handle) return ENOMEM;
+
+ return EOK;
+}
+
+struct tevent_req *sysdb_transaction_commit_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle)
+{
+ struct tevent_req *req;
+ struct sysdb_transaction_state *state;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_transaction_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->ctx = handle->ctx;
+ state->handle = handle;
+
+ ret = ldb_transaction_commit(handle->ctx->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
+ tevent_req_error(req, sysdb_error_to_errno(ret));
+ }
+ handle->transaction_active = false;
+
+ /* the following may seem weird but it is actually fine.
+ * _done() will not actually call the callback as it will not be set
+ * until we return. But it will mark the request as done.
+ * _post() will trigger the callback as it schedules after we returned
+ * and actually set the callback */
+ tevent_req_done(req);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+int sysdb_transaction_commit_recv(struct tevent_req *req)
+{
+ struct sysdb_transaction_state *state = tevent_req_data(req,
+ struct sysdb_transaction_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ /* finally free handle
+ * this will also trigger the next transaction in the queue if any */
+ talloc_free(state->handle);
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
+ }
+
+ return EOK;
+}
+
+/* =Operations============================================================ */
+
+struct sysdb_operation_state {
+ struct tevent_context *ev;
+ struct sysdb_ctx *ctx;
+
+ struct sysdb_handle *handle;
+};
+
+static void sysdb_operation_process(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_operation_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_ctx *ctx)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_operation_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_operation_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->ctx = ctx;
+
+ subreq = sysdb_get_handle_send(state, ev, ctx);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+
+ tevent_req_set_callback(subreq, sysdb_operation_process, req);
+
+ return req;
+}
+
+static void sysdb_operation_process(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_operation_state *state = tevent_req_data(req,
+ struct sysdb_operation_state);
+ int ret;
+
+ ret = sysdb_get_handle_recv(subreq, state, &state->handle);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_operation_recv(struct tevent_req *req, TALLOC_CTX *memctx,
+ struct sysdb_handle **handle)
+{
+ struct sysdb_operation_state *state = tevent_req_data(req,
+ struct sysdb_operation_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
+ }
+
+ *handle = talloc_steal(memctx, state->handle);
+ if (!*handle) return ENOMEM;
+
+ return EOK;
+}
+
+void sysdb_operation_done(struct sysdb_handle *handle)
+{
+ talloc_free(handle);
+}
+
+/* =Initialization======================================================== */
static int sysdb_read_var(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index 6da833187..2696dfaf9 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -23,6 +23,7 @@
#define __SYS_DB_H__
#include "confdb/confdb.h"
+#include <tevent.h>
#define SYSDB_CONF_SECTION "config/sysdb"
#define SYSDB_FILE "sssd.ldb"
@@ -88,8 +89,6 @@
#define SYSDB_GETCACHED_FILTER "(&"SYSDB_UC")("SYSDB_LAST_LOGIN">=%lu))"
-#define SYSDB_CHECK_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_NAME"=%s))"
-
#define SYSDB_PW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
SYSDB_GIDNUM, SYSDB_GECOS, \
SYSDB_HOMEDIR, SYSDB_SHELL, \
@@ -125,6 +124,10 @@
#define SYSDB_TMPL_USER SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE
#define SYSDB_TMPL_GROUP SYSDB_NAME"=%s,"SYSDB_TMPL_GROUP_BASE
+#define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD
+#define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE
+#define SYSDB_MOD_REP LDB_FLAG_MOD_REPLACE
+
struct confdb_ctx;
struct sysdb_ctx;
struct sysdb_handle;
@@ -142,40 +145,15 @@ int sysdb_attrs_add_string(struct sysdb_attrs *attrs,
const char *name, const char *str);
int sysdb_attrs_add_long(struct sysdb_attrs *attrs,
const char *name, long value);
+int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs,
+ const char *name, uint32_t value);
+int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs,
+ const char *name, time_t value);
/* convert an ldb error into an errno error */
int sysdb_error_to_errno(int ldberr);
-/* callbacks */
-typedef void (*sysdb_callback_t)(void *, int, struct ldb_result *);
-typedef void (*sysdb_fn_t)(struct sysdb_handle *, void *pvt);
-
-/* service functions */
-struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx);
-struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *req);
-
-/* function to start and finish a transaction
- * After sysdb_transaction() is successfully called,
- * it *MUST* be closed with a call to sysdb_transaction_done()
- * if error is == 0 the transaction is committed otherwise it
- * is canceled and all modifications to the db are thrown away
- *
- * Transactions are serialized, no other transaction or operation can be
- * performed while a transaction is active.
- */
-int sysdb_transaction(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *ctx,
- sysdb_fn_t fn, void *pvt);
-void sysdb_transaction_done(struct sysdb_handle *req, int error);
-
-/* An operation blocks the transaction queue as well, but does not
- * start a transaction, normally useful only for search type calls.
- * Cannot be called within a transaction */
-int sysdb_operation(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *ctx,
- sysdb_fn_t fn, void *pvt);
-void sysdb_operation_done(struct sysdb_handle *req);
-
+/* DNs related helper functions */
struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx,
const char *domain, const char *name);
struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
@@ -183,12 +161,44 @@ struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx,
const char *domain);
+/* function to start and finish a transaction
+ * sysdb_transaction_send() will queue a request for a transaction
+ * when it is done it will call the tevent_req callback, which must
+ * retrieve the transaction handle using sysdb_transaction_recv()
+ *
+ * A transaction must be completed either by sending a commit:
+ * sysdb_transaction_commit_send()/sysdb_transaction_commit_recv()
+ * or by freeing the transaction handle (this will implicitly cause
+ * a transaction cancelation).
+ *
+ * Transactions are serialized, no other transaction or operation can be
+ * performed while a transaction is active. Multiple transaction request
+ * are queued internally and served in order.
+ */
+
+struct tevent_req *sysdb_transaction_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_ctx *ctx);
+int sysdb_transaction_recv(struct tevent_req *req, TALLOC_CTX *memctx,
+ struct sysdb_handle **handle);
+
+struct tevent_req *sysdb_transaction_commit_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle);
+int sysdb_transaction_commit_recv(struct tevent_req *req);
+
+/* Sysdb initialization.
+ * call this function *only* once to initialize the database and get
+ * the sysdb ctx */
int sysdb_init(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct confdb_ctx *cdb,
const char *alt_db_path,
struct sysdb_ctx **dbctx);
+/* FIXME: REMOVE */
+typedef void (*sysdb_callback_t)(void *, int, struct ldb_result *);
+
/* functions to retrieve information from sysdb
* These functions automatically starts an operation
* therefore they cannot be called within a transaction */
@@ -243,84 +253,233 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
/* functions that modify the databse
* they have to be called within a transaction
- * See sysdb_transaction() */
-int sysdb_add_group_member(struct sysdb_handle *handle,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_remove_group_member(struct sysdb_handle *handle,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_delete_entry(struct sysdb_handle *handle,
- struct ldb_dn *dn,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_delete_user_by_uid(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- uid_t uid,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_delete_group_by_gid(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- gid_t gid,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_set_user_attr(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name,
- struct sysdb_attrs *attributes,
- sysdb_callback_t fn, void *ptr);
-
-int sysdb_add_user(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name,
- uid_t uid, gid_t gid, const char *fullname,
- const char *homedir, const char *shell,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_add_group(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name, gid_t gid,
- sysdb_callback_t fn, void *pvt);
+ * See sysdb_transaction_send()/_recv() */
+
+/* Delete Entry */
+struct tevent_req *sysdb_delete_entry_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *dn);
+int sysdb_delete_entry_recv(struct tevent_req *req);
+
+/* Search Entry */
+struct tevent_req *sysdb_search_entry_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *base_dn,
+ const char *filter,
+ const char **attrs);
+int sysdb_search_entry_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **msg);
+
+/* Search User (by uid or name) */
+struct tevent_req *sysdb_search_user_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name);
+struct tevent_req *sysdb_search_user_by_uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ uid_t uid);
+int sysdb_search_user_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **msg);
+
+/* Delete User by uid */
+struct tevent_req *sysdb_delete_user_by_uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ uid_t uid);
+int sysdb_delete_user_by_uid_recv(struct tevent_req *req);
+
+/* Search Group (gy gid or name) */
+struct tevent_req *sysdb_search_group_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name);
+struct tevent_req *sysdb_search_group_by_gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ gid_t gid);
+int sysdb_search_group_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **msg);
+
+/* Delete group by gid */
+struct tevent_req *sysdb_delete_group_by_gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ gid_t gid);
+int sysdb_delete_group_by_gid_recv(struct tevent_req *req);
+
+/* Replace entry attrs */
+struct tevent_req *sysdb_set_entry_attr_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *entry_dn,
+ struct sysdb_attrs *attrs,
+ int mod_op);
+int sysdb_set_entry_attr_recv(struct tevent_req *req);
+
+/* Replace user attrs */
+struct tevent_req *sysdb_set_user_attr_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ struct sysdb_attrs *attrs,
+ int mod_op);
+int sysdb_set_user_attr_recv(struct tevent_req *req);
+
+/* Replace group attrs */
+struct tevent_req *sysdb_set_group_attr_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ struct sysdb_attrs *attrs,
+ int mod_op);
+int sysdb_set_group_attr_recv(struct tevent_req *req);
+
+/* Allocate a new id */
+struct tevent_req *sysdb_get_new_id_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain);
+int sysdb_get_new_id_recv(struct tevent_req *req, uint32_t *id);
+
+/* Add user (only basic attrs and w/o checks) */
+struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ uid_t uid, gid_t gid,
+ const char *gecos,
+ const char *homedir,
+ const char *shell);
+int sysdb_add_basic_user_recv(struct tevent_req *req);
+
+/* Add user (all checks) */
+struct tevent_req *sysdb_add_user_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ uid_t uid, gid_t gid,
+ const char *gecos,
+ const char *homedir,
+ const char *shell,
+ struct sysdb_attrs *attrs);
+int sysdb_add_user_recv(struct tevent_req *req);
+
+/* Add group (only basic attrs and w/o checks) */
+struct tevent_req *sysdb_add_basic_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name, gid_t gid);
+int sysdb_add_basic_group_recv(struct tevent_req *req);
+
+/* Add group (all checks) */
+struct tevent_req *sysdb_add_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name, gid_t gid,
+ struct sysdb_attrs *attrs);
+int sysdb_add_group_recv(struct tevent_req *req);
+
+/* mod_op must be either LDB_FLAG_MOD_ADD or LDB_FLAG_MOD_DELETE */
+struct tevent_req *sysdb_mod_group_member_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *member_dn,
+ struct ldb_dn *group_dn,
+ int mod_op);
+int sysdb_mod_group_member_recv(struct tevent_req *req);
int sysdb_set_group_gid(struct sysdb_handle *handle,
struct sss_domain_info *domain,
const char *name, gid_t gid,
sysdb_callback_t fn, void *pvt);
-/* legacy functions for proxy providers */
-
-int sysdb_legacy_store_user(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name, const char *pwd,
- uid_t uid, gid_t gid, const char *gecos,
- const char *homedir, const char *shell,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_legacy_store_group(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name, gid_t gid,
- const char **members,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_legacy_add_group_member(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *group,
- const char *member,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_legacy_remove_group_member(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *group,
- const char *member,
- sysdb_callback_t fn, void *pvt);
-
-int sysdb_set_cached_password(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *user,
- const char *password,
- sysdb_callback_t fn, void *pvt);
+struct tevent_req *sysdb_store_user_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ const char *pwd,
+ uid_t uid, gid_t gid,
+ const char *gecos,
+ const char *homedir,
+ const char *shell);
+int sysdb_store_user_recv(struct tevent_req *req);
+
+struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ gid_t gid,
+ const char **members);
+int sysdb_store_group_recv(struct tevent_req *req);
+
+struct tevent_req *sysdb_add_group_member_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *group,
+ const char *member);
+int sysdb_add_group_member_recv(struct tevent_req *req);
+
+struct tevent_req *sysdb_remove_group_member_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *group,
+ const char *member);
+int sysdb_remove_group_member_recv(struct tevent_req *req);
+
+struct tevent_req *sysdb_set_cached_password_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *user,
+ const char *password);
+int sysdb_set_cached_password_recv(struct tevent_req *req);
+
+/* TODO: remove later
+ * These functions are available in the latest tevent and are the ones that
+ * should be used as tevent_req is rightfully opaque there */
+#ifndef tevent_req_data
+#define tevent_req_data(req, type) ((type *)req->private_state)
+#endif
+
+#ifndef tevent_req_set_callback
+#define tevent_req_set_callback(req, func, data) \
+ do { req->async.fn = func; req->async.private_data = data; } while(0)
+#endif
+
+#ifndef tevent_req_callback_data
+#define tevent_req_callback_data(req, type) ((type *)req->async.private_data)
+#endif
+
+#ifndef tevent_req_notify_callback
+#define tevent_req_notify_callback(req) \
+ do { \
+ if (req->async.fn != NULL) { \
+ req->async.fn(req); \
+ } \
+ } while(0)
+#endif
+
+
#endif /* __SYS_DB_H__ */
diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c
index 9b3f28283..785ce15e0 100644
--- a/server/db/sysdb_ops.c
+++ b/server/db/sysdb_ops.c
@@ -24,25 +24,6 @@
#include "util/nss_sha512crypt.h"
#include <time.h>
-struct sysdb_cb_ctx {
- sysdb_callback_t fn;
- void *pvt;
-
- bool ignore_not_found;
-};
-
-static int sysdb_ret_error(struct sysdb_cb_ctx *ctx, int ret, int lret)
-{
- ctx->fn(ctx->pvt, ret, NULL);
- return lret;
-};
-
-static int sysdb_ret_done(struct sysdb_cb_ctx *ctx)
-{
- ctx->fn(ctx->pvt, EOK, NULL);
- return LDB_SUCCESS;
-};
-
static int add_string(struct ldb_message *msg, int flags,
const char *attr, const char *value)
{
@@ -51,8 +32,9 @@ static int add_string(struct ldb_message *msg, int flags,
ret = ldb_msg_add_empty(msg, attr, flags, NULL);
if (ret == LDB_SUCCESS) {
ret = ldb_msg_add_string(msg, attr, value);
+ if (ret == LDB_SUCCESS) return EOK;
}
- return ret;
+ return ENOMEM;
}
static int add_ulong(struct ldb_message *msg, int flags,
@@ -63,8 +45,9 @@ static int add_ulong(struct ldb_message *msg, int flags,
ret = ldb_msg_add_empty(msg, attr, flags, NULL);
if (ret == LDB_SUCCESS) {
ret = ldb_msg_add_fmt(msg, attr, "%lu", value);
+ if (ret == LDB_SUCCESS) return EOK;
}
- return ret;
+ return ENOMEM;
}
static uint32_t get_attr_as_uint32(struct ldb_message *msg, const char *attr)
@@ -89,1798 +72,2948 @@ static uint32_t get_attr_as_uint32(struct ldb_message *msg, const char *attr)
return l;
}
-static int sysdb_op_callback(struct ldb_request *req, struct ldb_reply *rep)
+#define ERROR_OUT(v, r, l) do { v = r; goto l; } while(0);
+
+/* =LDB-Request-(tevent_req-style)======================================== */
+
+struct sldb_request_state {
+ struct tevent_context *ev;
+ struct ldb_context *ldbctx;
+ struct ldb_request *ldbreq;
+ struct ldb_reply *ldbreply;
+};
+
+static void sldb_request_wakeup(struct tevent_req *subreq);
+static int sldb_request_callback(struct ldb_request *ldbreq,
+ struct ldb_reply *ldbreply);
+
+static struct tevent_req *sldb_request_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct ldb_context *ldbctx,
+ struct ldb_request *ldbreq)
{
- struct sysdb_cb_ctx *cbctx;
- int err;
+ struct tevent_req *req, *subreq;
+ struct sldb_request_state *state;
+ struct timeval tv = { 0, 0 };
- cbctx = talloc_get_type(req->context, struct sysdb_cb_ctx);
+ req = tevent_req_create(mem_ctx, &state, struct sldb_request_state);
+ if (!req) return NULL;
- if (!rep) {
- return sysdb_ret_error(cbctx, EIO, LDB_ERR_OPERATIONS_ERROR);
- }
- if (rep->error != LDB_SUCCESS) {
- if (! (cbctx->ignore_not_found &&
- rep->error == LDB_ERR_NO_SUCH_OBJECT)) {
- err = sysdb_error_to_errno(rep->error);
- return sysdb_ret_error(cbctx, err, rep->error);
- }
- }
+ state->ev = ev;
+ state->ldbctx = ldbctx;
+ state->ldbreq = ldbreq;
+ state->ldbreply = NULL;
- if (rep->type != LDB_REPLY_DONE) {
- sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ subreq = tevent_wakeup_send(state, ev, tv);
+ if (!subreq) {
+ DEBUG(1, ("Failed to add critical timer to run next ldb operation!\n"));
+ talloc_zfree(req);
+ return NULL;
}
+ tevent_req_set_callback(subreq, sldb_request_wakeup, req);
- return sysdb_ret_done(cbctx);
+ return req;
}
-int sysdb_add_group_member(struct sysdb_handle *handle,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn,
- sysdb_callback_t fn, void *pvt)
+static void sldb_request_wakeup(struct tevent_req *subreq)
{
- struct sysdb_ctx *ctx;
- struct sysdb_cb_ctx *cbctx;
- struct ldb_request *req;
- struct ldb_message *msg;
- const char *dn;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sldb_request_state *state = tevent_req_data(req,
+ struct sldb_request_state);
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
- }
-
- ctx = sysdb_handle_get_ctx(handle);
+ if (!tevent_wakeup_recv(subreq)) return;
+ talloc_zfree(subreq);
- cbctx = talloc_zero(handle, struct sysdb_cb_ctx);
- if (!cbctx) return ENOMEM;
+ state->ldbreq->callback = sldb_request_callback;
+ state->ldbreq->context = req;
- cbctx->fn = fn;
- cbctx->pvt = pvt;
+ ret = ldb_request(state->ldbctx, state->ldbreq);
+ if (ret != LDB_SUCCESS) {
+ tevent_req_error(req, sysdb_error_to_errno(ret));
+ }
+}
- /* Add the member_dn as a member of the group */
- msg = ldb_msg_new(cbctx);
- if(msg == NULL) return ENOMEM;
+static int sldb_request_callback(struct ldb_request *ldbreq,
+ struct ldb_reply *ldbreply)
+{
+ struct tevent_req *req = talloc_get_type(ldbreq->context,
+ struct tevent_req);
+ struct sldb_request_state *state = tevent_req_data(req,
+ struct sldb_request_state);
+ int err;
- msg->dn = group_dn;
- ret = ldb_msg_add_empty(msg, SYSDB_MEMBER,
- LDB_FLAG_MOD_ADD, NULL);
- if (ret != LDB_SUCCESS) return ENOMEM;
+ if (!ldbreply) {
+ ERROR_OUT(err, EIO, fail);
+ }
- dn = ldb_dn_get_linearized(member_dn);
- if (!dn) return EINVAL;
+ state->ldbreply = talloc_steal(state, ldbreply);
- ret = ldb_msg_add_fmt(msg, SYSDB_MEMBER, "%s", dn);
- if (ret != LDB_SUCCESS) return EINVAL;
+ if (ldbreply->error != LDB_SUCCESS) {
+ ERROR_OUT(err, sysdb_error_to_errno(ldbreply->error), fail);
+ }
- ret = ldb_build_mod_req(&req, ctx->ldb, cbctx, msg,
- NULL, cbctx, sysdb_op_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ if (ldbreply->type == LDB_REPLY_DONE) {
+ tevent_req_done(req);
+ return EOK;
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ tevent_req_notify_callback(req);
+ return EOK;
+fail:
+ tevent_req_error(req, err);
return EOK;
}
-int sysdb_remove_group_member(struct sysdb_handle *handle,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn,
- sysdb_callback_t fn, void *pvt)
+static int sldb_request_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_reply **ldbreply)
{
- struct sysdb_ctx *ctx;
- struct sysdb_cb_ctx *cbctx;
- struct ldb_request *req;
- struct ldb_message *msg;
- const char *dn;
- int ret;
+ struct sldb_request_state *state = tevent_req_data(req,
+ struct sldb_request_state);
+ enum tevent_req_state tstate;
+ uint64_t err = 0;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ if (state->ldbreply) {
+ *ldbreply = talloc_move(mem_ctx, &state->ldbreply);
}
- ctx = sysdb_handle_get_ctx(handle);
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ if (err != 0) return err;
+ if (tstate == TEVENT_REQ_IN_PROGRESS) return EOK;
+ return EIO;
+ }
- cbctx = talloc_zero(handle, struct sysdb_cb_ctx);
- if (!cbctx) return ENOMEM;
+ return EOK;
+}
- cbctx->fn = fn;
- cbctx->pvt = pvt;
+/* =Standard-Sysdb-Operations-utility-functions=========================== */
- /* Add the member_dn as a member of the group */
- msg = ldb_msg_new(cbctx);
- if(msg == NULL) return ENOMEM;
+struct sysdb_op_state {
+ struct tevent_context *ev;
+ struct sysdb_handle *handle;
- msg->dn = group_dn;
- ret = ldb_msg_add_empty(msg, SYSDB_MEMBER,
- LDB_FLAG_MOD_DELETE, NULL);
- if (ret != LDB_SUCCESS) return ENOMEM;
+ bool ignore_not_found;
- dn = ldb_dn_get_linearized(member_dn);
- if (!dn) return EINVAL;
+ struct ldb_reply *ldbreply;
+};
- ret = ldb_msg_add_fmt(msg, SYSDB_MEMBER, "%s", dn);
- if (ret != LDB_SUCCESS) return EINVAL;
+static void sysdb_op_default_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_op_state *state = tevent_req_data(req,
+ struct sysdb_op_state);
+ int ret;
- ret = ldb_build_mod_req(&req, ctx->ldb, cbctx, msg,
- NULL, cbctx, sysdb_op_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ ret = sldb_request_recv(subreq, state, &state->ldbreply);
+ talloc_zfree(subreq);
+ if (ret) {
+ if (state->ignore_not_found && ret == ENOENT) {
+ goto done;
+ }
+ tevent_req_error(req, ret);
+ return;
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ if (state->ldbreply->type != LDB_REPLY_DONE) {
+ tevent_req_error(req, EIO);
+ return;
+ }
- return EOK;
+done:
+ tevent_req_done(req);
}
-int sysdb_delete_entry(struct sysdb_handle *handle,
- struct ldb_dn *dn,
- sysdb_callback_t fn, void *pvt)
+static int sysdb_op_default_recv(struct tevent_req *req)
{
- struct sysdb_ctx *ctx;
- struct sysdb_cb_ctx *cbctx;
- struct ldb_request *req;
- int ret;
+ enum tevent_req_state tstate;
+ uint64_t err;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
}
- ctx = sysdb_handle_get_ctx(handle);
+ return EOK;
+}
+
- cbctx = talloc_zero(handle, struct sysdb_cb_ctx);
- if (!cbctx) return ENOMEM;
+/* =Remove-Entry-From-Sysdb=============================================== */
- cbctx->fn = fn;
- cbctx->pvt = pvt;
- cbctx->ignore_not_found = true;
+struct tevent_req *sysdb_delete_entry_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *dn)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_request *ldbreq;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = true;
+ state->ldbreply = NULL;
- ret = ldb_build_del_req(&req, ctx->ldb, cbctx, dn, NULL,
- cbctx, sysdb_op_callback, NULL);
+ ret = ldb_build_del_req(&ldbreq, handle->ctx->ldb, state, dn,
+ NULL, NULL, NULL, NULL);
if (ret != LDB_SUCCESS) {
DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
+ ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_op_default_done, req);
- return EOK;
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
-struct delete_ctx {
- struct sysdb_handle *handle;
- struct sysdb_cb_ctx *cbctx;
+int sysdb_delete_entry_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
- struct ldb_result *res;
-};
-static int delete_callback(struct ldb_request *req, struct ldb_reply *rep)
+/* =Search-Entry========================================================== */
+
+static void sysdb_search_entry_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_search_entry_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *base_dn,
+ const char *filter,
+ const char **attrs)
{
- struct delete_ctx *del_ctx;
- struct sysdb_cb_ctx *cbctx;
- struct sysdb_ctx *ctx;
- struct ldb_request *delreq;
- struct ldb_result *res;
- struct ldb_dn *dn;
- int ret, err;
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_request *ldbreq;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
- del_ctx = talloc_get_type(req->context, struct delete_ctx);
- ctx = sysdb_handle_get_ctx(del_ctx->handle);
- cbctx = del_ctx->cbctx;
- res = del_ctx->res;
+ ret = ldb_build_search_req(&ldbreq, handle->ctx->ldb, state,
+ base_dn, LDB_SCOPE_SUBTREE,
+ filter, attrs, NULL, NULL, NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
+ ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
+ }
- if (!rep) {
- return sysdb_ret_error(cbctx, EIO, LDB_ERR_OPERATIONS_ERROR);
+ subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- if (rep->error != LDB_SUCCESS) {
- err = sysdb_error_to_errno(rep->error);
- return sysdb_ret_error(cbctx, err, rep->error);
+ tevent_req_set_callback(subreq, sysdb_search_entry_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sysdb_search_entry_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_op_state *state = tevent_req_data(req,
+ struct sysdb_op_state);
+ struct ldb_reply *ldbreply;
+ int ret;
+
+ ret = sldb_request_recv(subreq, state, &ldbreply);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- switch (rep->type) {
+ switch (ldbreply->type) {
case LDB_REPLY_ENTRY:
- if (res->msgs != NULL) {
+ if (state->ldbreply) {
DEBUG(1, ("More than one reply for a base search ?! "
"DB seems corrupted, aborting."));
- return sysdb_ret_error(cbctx, EFAULT, LDB_ERR_OPERATIONS_ERROR);
- }
- res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, 2);
- if (!res->msgs) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
+ tevent_req_error(req, EFAULT);
+ return;
}
- res->msgs[0] = talloc_steal(res->msgs, rep->message);
- res->msgs[1] = NULL;
- res->count = 1;
+ /* save the entry so that it can be retrieved by the caller */
+ state->ldbreply = ldbreply;
- break;
+ /* just return, wait for a LDB_REPLY_DONE entry */
+ return;
case LDB_REPLY_DONE:
-
- if (res->count == 0) {
- DEBUG(7, ("Base search returned no results\n"));
- return sysdb_ret_done(cbctx);
+ if (!state->ldbreply) {
+ talloc_zfree(ldbreply);
+ tevent_req_error(req, ENOENT);
+ return;
}
+ talloc_zfree(ldbreply);
+ return tevent_req_done(req);
- dn = ldb_dn_copy(del_ctx, res->msgs[0]->dn);
- if (!dn) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
-
- talloc_free(res);
- del_ctx->res = res = NULL;
+ default:
+ /* unexpected stuff */
+ talloc_zfree(ldbreply);
+ tevent_req_error(req, EIO);
+ return;
+ }
+}
- ret = ldb_build_del_req(&delreq, ctx->ldb, cbctx, dn, NULL,
- cbctx, sysdb_op_callback, NULL);
- if (ret == LDB_SUCCESS) {
- ret = ldb_request(ctx->ldb, delreq);
- }
- if (ret != LDB_SUCCESS) {
- err = sysdb_error_to_errno(ret);
- return sysdb_ret_error(cbctx, err, ret);
- }
- break;
+int sysdb_search_entry_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **msg)
+{
+ struct sysdb_op_state *state = tevent_req_data(req,
+ struct sysdb_op_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
- default:
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
}
- talloc_free(rep);
- return LDB_SUCCESS;
+ *msg = talloc_move(mem_ctx, &state->ldbreply->message);
+
+ return EOK;
}
-int sysdb_delete_user_by_uid(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- uid_t uid,
- sysdb_callback_t fn, void *pvt)
+
+/* =Search-User-by-[UID/NAME]============================================= */
+
+struct sysdb_search_user_state {
+ struct tevent_context *ev;
+ struct sysdb_handle *handle;
+
+ struct ldb_message *msg;
+};
+
+static void sysdb_search_user_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_search_user_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name)
{
+ struct tevent_req *req, *subreq;
+ struct sysdb_search_user_state *state;
static const char *attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
- struct delete_ctx *del_ctx;
- struct sysdb_ctx *ctx;
struct ldb_dn *base_dn;
- struct ldb_request *req;
char *filter;
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_search_user_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->msg = NULL;
+
+ base_dn = ldb_dn_new_fmt(state, handle->ctx->ldb,
+ SYSDB_TMPL_USER_BASE, domain->name);
+ if (!base_dn)
+ ERROR_OUT(ret, ENOMEM, fail);
+
+ filter = talloc_asprintf(state, SYSDB_PWNAM_FILTER, name);
+ if (!filter)
+ ERROR_OUT(ret, ENOMEM, fail);
+
+ subreq = sysdb_search_entry_send(state, ev, handle,
+ base_dn, filter, attrs);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
+ tevent_req_set_callback(subreq, sysdb_search_user_done, req);
- ctx = sysdb_handle_get_ctx(handle);
+ return req;
- del_ctx = talloc_zero(handle, struct delete_ctx);
- if (!del_ctx) return ENOMEM;
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
- del_ctx->cbctx = talloc_zero(del_ctx, struct sysdb_cb_ctx);
- if (!del_ctx->cbctx) return ENOMEM;
+struct tevent_req *sysdb_search_user_by_uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ uid_t uid)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_search_user_state *state;
+ static const char *attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
+ struct ldb_dn *base_dn;
+ char *filter;
+ int ret;
- del_ctx->handle = handle;
- del_ctx->cbctx->fn = fn;
- del_ctx->cbctx->pvt = pvt;
- del_ctx->cbctx->ignore_not_found = true;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_search_user_state);
+ if (!req) return NULL;
- del_ctx->res = talloc_zero(del_ctx, struct ldb_result);
- if (!del_ctx->res) return ENOMEM;
+ state->ev = ev;
+ state->handle = handle;
+ state->msg = NULL;
- base_dn = ldb_dn_new_fmt(del_ctx, ctx->ldb,
+ base_dn = ldb_dn_new_fmt(state, handle->ctx->ldb,
SYSDB_TMPL_USER_BASE, domain->name);
- if (!base_dn) return ENOMEM;
+ if (!base_dn)
+ ERROR_OUT(ret, ENOMEM, fail);
- filter = talloc_asprintf(del_ctx, SYSDB_PWUID_FILTER, (unsigned long)uid);
- if (!filter) return ENOMEM;
+ filter = talloc_asprintf(state, SYSDB_PWUID_FILTER, (unsigned long)uid);
+ if (!filter)
+ ERROR_OUT(ret, ENOMEM, fail);
- ret = ldb_build_search_req(&req, ctx->ldb, del_ctx,
- base_dn, LDB_SCOPE_ONELEVEL,
- filter, attrs, NULL,
- del_ctx, delete_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ subreq = sysdb_search_entry_send(state, ev, handle,
+ base_dn, filter, attrs);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_search_user_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sysdb_search_user_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_search_user_state *state = tevent_req_data(req,
+ struct sysdb_search_user_state);
+ int ret;
+
+ ret = sysdb_search_entry_recv(subreq, state, &state->msg);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_search_user_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **msg)
+{
+ struct sysdb_search_user_state *state = tevent_req_data(req,
+ struct sysdb_search_user_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ *msg = talloc_move(mem_ctx, &state->msg);
return EOK;
}
-int sysdb_delete_group_by_gid(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- gid_t gid,
- sysdb_callback_t fn, void *pvt)
+
+/* =Delete-User-by-UID==================================================== */
+
+static void sysdb_delete_user_by_uid_found(struct tevent_req *subreq);
+static void sysdb_delete_user_by_uid_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_delete_user_by_uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ uid_t uid)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = true;
+ state->ldbreply = NULL;
+
+ subreq = sysdb_search_user_by_uid_send(state, ev, handle, domain, uid);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, sysdb_delete_user_by_uid_found, req);
+
+ return req;
+}
+
+static void sysdb_delete_user_by_uid_found(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_op_state *state = tevent_req_data(req,
+ struct sysdb_op_state);
+ struct ldb_message *msg;
+ int ret;
+
+ ret = sysdb_search_user_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret) {
+ if (state->ignore_not_found && ret == ENOENT) {
+ return tevent_req_done(req);
+ }
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ subreq = sysdb_delete_entry_send(state, state->ev, state->handle, msg->dn);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_delete_user_by_uid_done, req);
+}
+
+static void sysdb_delete_user_by_uid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+
+ ret = sysdb_delete_entry_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_delete_user_by_uid_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
+
+/* =Search-Group-by-[GID/NAME]============================================ */
+
+struct sysdb_search_group_state {
+ struct tevent_context *ev;
+ struct sysdb_handle *handle;
+
+ struct ldb_message *msg;
+};
+
+static void sysdb_search_group_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_search_group_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name)
{
+ struct tevent_req *req, *subreq;
+ struct sysdb_search_group_state *state;
static const char *attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
- struct delete_ctx *del_ctx;
- struct sysdb_ctx *ctx;
struct ldb_dn *base_dn;
- struct ldb_request *req;
char *filter;
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_search_group_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->msg = NULL;
+
+ base_dn = ldb_dn_new_fmt(state, handle->ctx->ldb,
+ SYSDB_TMPL_GROUP_BASE, domain->name);
+ if (!base_dn)
+ ERROR_OUT(ret, ENOMEM, fail);
+
+ filter = talloc_asprintf(state, SYSDB_GRNAM_FILTER, name);
+ if (!filter)
+ ERROR_OUT(ret, ENOMEM, fail);
+
+ subreq = sysdb_search_entry_send(state, ev, handle,
+ base_dn, filter, attrs);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
+ tevent_req_set_callback(subreq, sysdb_search_group_done, req);
- ctx = sysdb_handle_get_ctx(handle);
+ return req;
- del_ctx = talloc_zero(handle, struct delete_ctx);
- if (!del_ctx) return ENOMEM;
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
- del_ctx->cbctx = talloc_zero(del_ctx, struct sysdb_cb_ctx);
- if (!del_ctx->cbctx) return ENOMEM;
+struct tevent_req *sysdb_search_group_by_gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ gid_t gid)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_search_group_state *state;
+ static const char *attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
+ struct ldb_dn *base_dn;
+ char *filter;
+ int ret;
- del_ctx->handle = handle;
- del_ctx->cbctx->fn = fn;
- del_ctx->cbctx->pvt = pvt;
- del_ctx->cbctx->ignore_not_found = true;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_search_group_state);
+ if (!req) return NULL;
- del_ctx->res = talloc_zero(del_ctx, struct ldb_result);
- if (!del_ctx->res) return ENOMEM;
+ state->ev = ev;
+ state->handle = handle;
+ state->msg = NULL;
- base_dn = ldb_dn_new_fmt(del_ctx, ctx->ldb,
+ base_dn = ldb_dn_new_fmt(state, handle->ctx->ldb,
SYSDB_TMPL_GROUP_BASE, domain->name);
- if (!base_dn) return ENOMEM;
+ if (!base_dn)
+ ERROR_OUT(ret, ENOMEM, fail);
- filter = talloc_asprintf(del_ctx, SYSDB_GRGID_FILTER, (unsigned long)gid);
- if (!filter) return ENOMEM;
+ filter = talloc_asprintf(state, SYSDB_GRGID_FILTER, (unsigned long)gid);
+ if (!filter)
+ ERROR_OUT(ret, ENOMEM, fail);
- ret = ldb_build_search_req(&req, ctx->ldb, del_ctx,
- base_dn, LDB_SCOPE_ONELEVEL,
- filter, attrs, NULL,
- del_ctx, delete_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ subreq = sysdb_search_entry_send(state, ev, handle,
+ base_dn, filter, attrs);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_search_group_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sysdb_search_group_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_search_group_state *state = tevent_req_data(req,
+ struct sysdb_search_group_state);
+ int ret;
+
+ ret = sysdb_search_entry_recv(subreq, state, &state->msg);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_search_group_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **msg)
+{
+ struct sysdb_search_group_state *state = tevent_req_data(req,
+ struct sysdb_search_group_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ *msg = talloc_move(mem_ctx, &state->msg);
return EOK;
}
-int sysdb_set_user_attr(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name,
- struct sysdb_attrs *attrs,
- sysdb_callback_t fn, void *pvt)
+
+/* =Delete-Group-by-GID=================================================== */
+
+static void sysdb_delete_group_by_gid_found(struct tevent_req *subreq);
+static void sysdb_delete_group_by_gid_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_delete_group_by_gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ gid_t gid)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = true;
+ state->ldbreply = NULL;
+
+ subreq = sysdb_search_group_by_gid_send(state, ev, handle, domain, gid);
+ if (!subreq) {
+ talloc_zfree(req);
+ return NULL;
+ }
+ tevent_req_set_callback(subreq, sysdb_delete_group_by_gid_found, req);
+
+ return req;
+}
+
+static void sysdb_delete_group_by_gid_found(struct tevent_req *subreq)
{
- struct sysdb_ctx *ctx;
- struct sysdb_cb_ctx *cbctx;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_op_state *state = tevent_req_data(req,
+ struct sysdb_op_state);
struct ldb_message *msg;
- struct ldb_request *req;
- int i, ret;
+ int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ ret = sysdb_search_group_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret) {
+ if (state->ignore_not_found && ret == ENOENT) {
+ return tevent_req_done(req);
+ }
+ tevent_req_error(req, ret);
+ return;
}
- if (attrs->num == 0) return EINVAL;
+ subreq = sysdb_delete_entry_send(state, state->ev, state->handle, msg->dn);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_delete_group_by_gid_done, req);
+}
- ctx = sysdb_handle_get_ctx(handle);
+static void sysdb_delete_group_by_gid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
- cbctx = talloc_zero(handle, struct sysdb_cb_ctx);
- if (!cbctx) return ENOMEM;
+ ret = sysdb_delete_entry_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- cbctx->fn = fn;
- cbctx->pvt = pvt;
+ tevent_req_done(req);
+}
- msg = ldb_msg_new(cbctx);
- if (!msg) return ENOMEM;
+int sysdb_delete_group_by_gid_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
+
+/* =Replace-Attributes-On-Entry=========================================== */
+
+struct tevent_req *sysdb_set_entry_attr_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *entry_dn,
+ struct sysdb_attrs *attrs,
+ int mod_op)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_request *ldbreq;
+ struct ldb_message *msg;
+ int i, ret;
- msg->dn = sysdb_user_dn(ctx, msg, domain->name, name);
- if (!msg->dn) return ENOMEM;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
+
+ if (!entry_dn) {
+ ERROR_OUT(ret, EINVAL, fail);
+ }
+
+ if (attrs->num == 0) {
+ ERROR_OUT(ret, EINVAL, fail);
+ }
+
+ msg = ldb_msg_new(state);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ msg->dn = entry_dn;
msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num);
- if (!msg->elements) return ENOMEM;
+ if (!msg->elements) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
for (i = 0; i < attrs->num; i++) {
msg->elements[i] = attrs->a[i];
- msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
+ msg->elements[i].flags = mod_op;
}
msg->num_elements = attrs->num;
- ret = ldb_build_mod_req(&req, ctx->ldb, cbctx, msg, NULL,
- cbctx, sysdb_op_callback, NULL);
- if (ret == LDB_SUCCESS) {
- ret = ldb_request(ctx->ldb, req);
- }
+ ret = ldb_build_mod_req(&ldbreq, handle->ctx->ldb, state, msg,
+ NULL, NULL, NULL, NULL);
if (ret != LDB_SUCCESS) {
- return sysdb_error_to_errno(ret);
+ DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
+ ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
}
- return EOK;
+ subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_op_default_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
-struct next_id {
- uint32_t id;
-};
+int sysdb_set_entry_attr_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
-struct next_id_ctx {
- struct sysdb_handle *handle;
- struct sss_domain_info *domain;
- struct sysdb_cb_ctx *cbctx;
- struct ldb_dn *base_dn;
- struct ldb_result *res;
- uint32_t tmp_id;
+/* =Replace-Attributes-On-User============================================ */
- enum next_step { NEXTID_SEARCH=0, NEXTID_VERIFY, NEXTID_STORE } step;
+static void sysdb_set_user_attr_done(struct tevent_req *subreq);
- struct next_id *result;
-};
+struct tevent_req *sysdb_set_user_attr_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ struct sysdb_attrs *attrs,
+ int mod_op)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_dn *dn;
+ int ret;
-static int nextid_callback(struct ldb_request *req, struct ldb_reply *rep);
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
-static int sysdb_get_next_available_id(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- struct next_id *result,
- sysdb_callback_t fn, void *pvt)
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
+
+ dn = sysdb_user_dn(handle->ctx, state, domain->name, name);
+ if (!dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ subreq = sysdb_set_entry_attr_send(state, ev, handle, dn, attrs, mod_op);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_set_user_attr_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sysdb_set_user_attr_done(struct tevent_req *subreq)
{
- static const char *attrs[] = { SYSDB_NEXTID, NULL };
- struct sysdb_ctx *ctx;
- struct next_id_ctx *idctx;
- struct ldb_request *req;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+
+ ret = sysdb_set_entry_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_set_user_attr_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
+
+/* =Replace-Attributes-On-Group=========================================== */
+
+static void sysdb_set_group_attr_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_set_group_attr_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ struct sysdb_attrs *attrs,
+ int mod_op)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_dn *dn;
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
+
+ dn = sysdb_group_dn(handle->ctx, state, domain->name, name);
+ if (!dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- ctx = sysdb_handle_get_ctx(handle);
+ subreq = sysdb_set_entry_attr_send(state, ev, handle, dn, attrs, mod_op);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_set_group_attr_done, req);
- idctx = talloc_zero(handle, struct next_id_ctx);
- if (!idctx) return ENOMEM;
+ return req;
- idctx->handle = handle;
- idctx->domain = domain;
- idctx->result = result;
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
- idctx->cbctx = talloc_zero(handle, struct sysdb_cb_ctx);
- if (!idctx->cbctx) return ENOMEM;
+static void sysdb_set_group_attr_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
- idctx->cbctx->fn = fn;
- idctx->cbctx->pvt = pvt;
+ ret = sysdb_set_entry_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- idctx->base_dn = sysdb_domain_dn(ctx, idctx, domain->name);
- if (!idctx->base_dn) return ENOMEM;
+ tevent_req_done(req);
+}
- idctx->res = talloc_zero(idctx, struct ldb_result);
- if (!idctx->res) return ENOMEM;
+int sysdb_set_group_attr_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
- ret = ldb_build_search_req(&req, ctx->ldb, idctx,
- idctx->base_dn, LDB_SCOPE_BASE,
- SYSDB_NEXTID_FILTER, attrs, NULL,
- idctx, nextid_callback, NULL);
+
+/* =Get-New-ID============================================================ */
+
+struct sysdb_get_new_id_state {
+ struct tevent_context *ev;
+ struct sysdb_handle *handle;
+ struct sss_domain_info *domain;
+
+ struct ldb_dn *base_dn;
+ struct ldb_message *base;
+
+ struct ldb_message **v_msgs;
+ int v_count;
+
+ uint32_t new_id;
+};
+
+static void sysdb_get_new_id_base(struct tevent_req *subreq);
+static void sysdb_get_new_id_verify(struct tevent_req *subreq);
+static void sysdb_get_new_id_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_get_new_id_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_get_new_id_state *state;
+ static const char *attrs[] = { SYSDB_NEXTID, NULL };
+ struct ldb_request *ldbreq;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_get_new_id_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->domain = domain;
+ state->base = NULL;
+ state->v_msgs = NULL;
+ state->v_count = 0;
+ state->new_id = 0;
+
+ state->base_dn = sysdb_domain_dn(handle->ctx, state, domain->name);
+ if (!state->base_dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ ret = ldb_build_search_req(&ldbreq, handle->ctx->ldb, state,
+ state->base_dn, LDB_SCOPE_BASE,
+ SYSDB_NEXTID_FILTER, attrs,
+ NULL, NULL, NULL, NULL);
if (ret != LDB_SUCCESS) {
DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
+ ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_get_new_id_base, req);
- return EOK;
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
-static int nextid_callback(struct ldb_request *req, struct ldb_reply *rep)
+static void sysdb_get_new_id_base(struct tevent_req *subreq)
{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_get_new_id_state *state = tevent_req_data(req,
+ struct sysdb_get_new_id_state);
static const char *attrs[] = { SYSDB_UIDNUM, SYSDB_GIDNUM, NULL };
- struct next_id_ctx *idctx;
- struct sysdb_cb_ctx *cbctx;
- struct sysdb_ctx *ctx;
- struct ldb_request *nreq;
- struct ldb_message *msg;
- struct ldb_result *res;
+ struct ldb_reply *ldbreply;
+ struct ldb_request *ldbreq;
char *filter;
- int ret, err;
-
- idctx = talloc_get_type(req->context, struct next_id_ctx);
- ctx = sysdb_handle_get_ctx(idctx->handle);
- cbctx = idctx->cbctx;
- res = idctx->res;
+ int ret;
- if (!rep) {
- return sysdb_ret_error(cbctx, EIO, LDB_ERR_OPERATIONS_ERROR);
- }
- if (rep->error != LDB_SUCCESS) {
- err = sysdb_error_to_errno(rep->error);
- return sysdb_ret_error(cbctx, err, rep->error);
+ ret = sldb_request_recv(subreq, state, &ldbreply);
+ if (ret) {
+ talloc_zfree(subreq);
+ tevent_req_error(req, ret);
+ return;
}
- switch (rep->type) {
+ switch (ldbreply->type) {
case LDB_REPLY_ENTRY:
-
- if (idctx->step == NEXTID_VERIFY) {
- res->count++;
- break;
- }
-
- /* NEXTID_SEARCH */
- if (res->msgs != NULL) {
+ if (state->base) {
DEBUG(1, ("More than one reply for a base search ?! "
"DB seems corrupted, aborting."));
- return sysdb_ret_error(cbctx, EFAULT, LDB_ERR_OPERATIONS_ERROR);
+ tevent_req_error(req, EFAULT);
+ return;
}
- res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, 2);
- if (!res->msgs) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
+ state->base = talloc_move(state, &ldbreply->message);
+ if (!state->base) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
- res->msgs[0] = talloc_steal(res->msgs, rep->message);
- res->msgs[1] = NULL;
- res->count = 1;
+ /* just return, wait for a LDB_REPLY_DONE entry */
+ talloc_zfree(ldbreply);
+ return;
+ case LDB_REPLY_DONE:
break;
- case LDB_REPLY_DONE:
+ default:
+ /* unexpected stuff */
+ tevent_req_error(req, EIO);
+ talloc_zfree(ldbreply);
+ return;
+ }
- switch (idctx->step) {
- case NEXTID_SEARCH:
- if (res->count != 0) {
- idctx->tmp_id = get_attr_as_uint32(res->msgs[0], SYSDB_NEXTID);
- if (idctx->tmp_id == (uint32_t)(-1)) {
- DEBUG(1, ("Invalid Next ID in domain %s\n",
- idctx->domain->name));
- return sysdb_ret_error(cbctx, ERANGE, LDB_ERR_OPERATIONS_ERROR);
- }
- } else {
- DEBUG(4, ("Base search returned no results, adding min id!\n"));
- }
+ talloc_zfree(subreq);
- if (idctx->tmp_id < idctx->domain->id_min) {
- DEBUG(2, ("Initializing domain next id to id min %u\n",
- idctx->domain->id_min));
- idctx->tmp_id = idctx->domain->id_min;
- }
- if ((idctx->domain->id_max != 0) &&
- (idctx->tmp_id > idctx->domain->id_max)) {
- DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
- idctx->tmp_id, idctx->domain->id_max));
- return sysdb_ret_error(cbctx, ERANGE, LDB_ERR_OPERATIONS_ERROR);
- }
+ if (state->base) {
+ state->new_id = get_attr_as_uint32(state->base, SYSDB_NEXTID);
+ if (state->new_id == (uint32_t)(-1)) {
+ DEBUG(1, ("Invalid Next ID in domain %s\n", state->domain->name));
+ tevent_req_error(req, ERANGE);
+ return;
+ }
- talloc_free(res->msgs);
- res->msgs = NULL;
- res->count = 0;
+ if (state->new_id < state->domain->id_min) {
+ state->new_id = state->domain->id_min;
+ }
- idctx->step = NEXTID_VERIFY;
- break;
+ if ((state->domain->id_max != 0) &&
+ (state->new_id > state->domain->id_max)) {
+ DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
+ state->new_id, state->domain->id_max));
+ tevent_req_error(req, ERANGE);
+ return;
+ }
- case NEXTID_VERIFY:
- if (res->count) {
- /* actually something's using the id, try next */
- idctx->tmp_id++;
- } else {
- /* ok store new next_id */
- idctx->result->id = idctx->tmp_id;
- idctx->tmp_id++;
- idctx->step = NEXTID_STORE;
- }
- break;
+ } else {
+ /* looks like the domain is not initialized yet, use min_id */
+ state->new_id = state->domain->id_min;
+ }
+
+ /* verify the id is actually really free.
+ * search all entries with id >= new_id and < max_id */
+ filter = talloc_asprintf(state,
+ "(|(&(%s>=%u)(%s<=%u))(&(%s>=%u)(%s<=%u)))",
+ SYSDB_UIDNUM, state->new_id,
+ SYSDB_UIDNUM, state->domain->id_max,
+ SYSDB_GIDNUM, state->new_id,
+ SYSDB_GIDNUM, state->domain->id_max);
+ if (!filter) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
- default:
- DEBUG(1, ("Invalid step, aborting.\n"));
- return sysdb_ret_error(cbctx, EFAULT, LDB_ERR_OPERATIONS_ERROR);
- }
+ ret = ldb_build_search_req(&ldbreq, state->handle->ctx->ldb, state,
+ state->base_dn, LDB_SCOPE_SUBTREE,
+ filter, attrs,
+ NULL, NULL, NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret,
+ ldb_errstring(state->handle->ctx->ldb)));
+ tevent_req_error(req, sysdb_error_to_errno(ret));
+ return;
+ }
- switch (idctx->step) {
- case NEXTID_VERIFY:
- filter = talloc_asprintf(idctx, "(|(%s=%u)(%s=%u))",
- SYSDB_UIDNUM, idctx->tmp_id,
- SYSDB_GIDNUM, idctx->tmp_id);
- if (!filter) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- ret = ldb_build_search_req(&nreq, ctx->ldb, idctx,
- idctx->base_dn, LDB_SCOPE_SUBTREE,
- filter, attrs, NULL,
- idctx, nextid_callback, NULL);
- break;
-
- case NEXTID_STORE:
- msg = ldb_msg_new(idctx);
- if (!msg) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+ subreq = sldb_request_send(state, state->ev,
+ state->handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_get_new_id_verify, req);
- msg->dn = idctx->base_dn;
+ return;
+}
- ret = add_ulong(msg, LDB_FLAG_MOD_REPLACE,
- SYSDB_NEXTID, idctx->tmp_id);
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+static void sysdb_get_new_id_verify(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_get_new_id_state *state = tevent_req_data(req,
+ struct sysdb_get_new_id_state);
+ struct ldb_reply *ldbreply;
+ struct ldb_request *ldbreq;
+ struct ldb_message *msg;
+ int ret, i;
- ret = ldb_build_mod_req(&nreq, ctx->ldb, idctx, msg, NULL,
- cbctx, sysdb_op_callback, NULL);
- break;
+ ret = sldb_request_recv(subreq, state, &ldbreply);
+ if (ret) {
+ talloc_zfree(subreq);
+ tevent_req_error(req, ret);
+ return;
+ }
- default:
- DEBUG(1, ("Invalid step, aborting.\n"));
- return sysdb_ret_error(cbctx, EFAULT, LDB_ERR_OPERATIONS_ERROR);
+ switch (ldbreply->type) {
+ case LDB_REPLY_ENTRY:
+ state->v_msgs = talloc_realloc(state, state->v_msgs,
+ struct ldb_message *,
+ state->v_count + 2);
+ if (!state->v_msgs) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- err = sysdb_error_to_errno(ret);
- return sysdb_ret_error(cbctx, err, ret);
+ state->v_msgs[state->v_count] = talloc_move(state, &ldbreply->message);
+ if (!state->v_msgs[state->v_count]) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
+ state->v_count++;
- ret = ldb_request(ctx->ldb, nreq);
- if (ret != LDB_SUCCESS) {
- err = sysdb_error_to_errno(ret);
- return sysdb_ret_error(cbctx, err, ret);
- }
+ /* just return, wait for a LDB_REPLY_DONE entry */
+ talloc_zfree(ldbreply);
+ return;
+ case LDB_REPLY_DONE:
break;
default:
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ /* unexpected stuff */
+ tevent_req_error(req, EIO);
+ talloc_zfree(ldbreply);
+ return;
}
- talloc_free(rep);
- return LDB_SUCCESS;
-}
+ talloc_zfree(subreq);
-static int check_name_callback(struct ldb_request *req, struct ldb_reply *rep);
+ /* if anything was found, find the maximum and increment past it */
+ if (state->v_count) {
+ uint32_t id;
-int sysdb_check_name_unique(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- TALLOC_CTX *mem_ctx, const char *name,
- sysdb_callback_t fn, void *pvt)
-{
- static const char *attrs[] = { SYSDB_NAME, NULL };
- struct sysdb_cb_ctx *cbctx;
- struct sysdb_ctx *ctx;
- struct ldb_dn *base_dn;
- struct ldb_request *req;
- char *filter;
- int ret;
+ for (i = 0; i < state->v_count; i++) {
+ id = get_attr_as_uint32(state->v_msgs[i], SYSDB_UIDNUM);
+ if (id != (uint32_t)(-1)) {
+ if (id > state->new_id) state->new_id = id;
+ }
+ id = get_attr_as_uint32(state->v_msgs[i], SYSDB_GIDNUM);
+ if (id != (uint32_t)(-1)) {
+ if (id > state->new_id) state->new_id = id;
+ }
+ }
+
+ state->new_id++;
+
+ /* check again we are not falling out of range */
+ if ((state->domain->id_max != 0) &&
+ (state->new_id > state->domain->id_max)) {
+ DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
+ state->new_id, state->domain->id_max));
+ tevent_req_error(req, ERANGE);
+ return;
+ }
+
+ talloc_zfree(state->v_msgs);
+ state->v_count = 0;
+ }
+
+ /* finally store the new next id */
+ msg = ldb_msg_new(state);
+ if (!msg) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ msg->dn = state->base->dn;
+
+ ret = add_ulong(msg, LDB_FLAG_MOD_REPLACE,
+ SYSDB_NEXTID, state->new_id + 1);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ ret = ldb_build_mod_req(&ldbreq, state->handle->ctx->ldb, state, msg,
+ NULL, NULL, NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret,
+ ldb_errstring(state->handle->ctx->ldb)));
+ tevent_req_error(req, ret);
+ return;
}
- ctx = sysdb_handle_get_ctx(handle);
+ subreq = sldb_request_send(state, state->ev,
+ state->handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_get_new_id_done, req);
+}
- cbctx = talloc_zero(mem_ctx, struct sysdb_cb_ctx);
- if (!cbctx) return ENOMEM;
+static void sysdb_get_new_id_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_get_new_id_state *state = tevent_req_data(req,
+ struct sysdb_get_new_id_state);
+ struct ldb_reply *ldbreply;
+ int ret;
- cbctx->fn = fn;
- cbctx->pvt = pvt;
+ ret = sldb_request_recv(subreq, state, &ldbreply);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- base_dn = sysdb_domain_dn(ctx, cbctx, domain->name);
- if (!base_dn) return ENOMEM;
+ if (ldbreply->type != LDB_REPLY_DONE) {
+ tevent_req_error(req, EIO);
+ return;
+ }
- filter = talloc_asprintf(cbctx, SYSDB_CHECK_FILTER, name);
- if (!filter) return ENOMEM;
+ tevent_req_done(req);
+}
- ret = ldb_build_search_req(&req, ctx->ldb, mem_ctx,
- base_dn, LDB_SCOPE_SUBTREE,
- filter, attrs, NULL,
- cbctx, check_name_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+int sysdb_get_new_id_recv(struct tevent_req *req, uint32_t *id)
+{
+ struct sysdb_get_new_id_state *state = tevent_req_data(req,
+ struct sysdb_get_new_id_state);
+ enum tevent_req_state tstate;
+ uint64_t err;
+
+ if (tevent_req_is_error(req, &tstate, &err)) {
+ return err;
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ *id = state->new_id;
return EOK;
}
-static int check_name_callback(struct ldb_request *req, struct ldb_reply *rep)
+
+/* =Add-Basic-User-NO-CHECKS============================================== */
+
+struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ uid_t uid, gid_t gid,
+ const char *gecos,
+ const char *homedir,
+ const char *shell)
{
- struct sysdb_cb_ctx *cbctx;
- int err;
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_request *ldbreq;
+ struct ldb_message *msg;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
- cbctx = talloc_get_type(req->context, struct sysdb_cb_ctx);
+ msg = ldb_msg_new(state);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
- if (!rep) {
- return sysdb_ret_error(cbctx, EIO, LDB_ERR_OPERATIONS_ERROR);
+ /* user dn */
+ msg->dn = sysdb_user_dn(handle->ctx, msg, domain->name, name);
+ if (!msg->dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- if (rep->error != LDB_SUCCESS) {
- err = sysdb_error_to_errno(rep->error);
- return sysdb_ret_error(cbctx, err, rep->error);
+
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, "objectClass", SYSDB_USER_CLASS);
+ if (ret) goto fail;
+
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
+ if (ret) goto fail;
+
+ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_UIDNUM, (unsigned long)uid);
+ if (ret) goto fail;
+
+ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
+ if (ret) goto fail;
+
+ /* We set gecos to be the same as fullname on user creation,
+ * But we will not enforce coherency after that, it's up to
+ * admins to decide if they want to keep it in sync if they change
+ * one of the 2 */
+ if (gecos && *gecos) {
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_FULLNAME, gecos);
+ if (ret) goto fail;
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_GECOS, gecos);
+ if (ret) goto fail;
}
- switch (rep->type) {
- case LDB_REPLY_ENTRY:
+ if (homedir && *homedir) {
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_HOMEDIR, homedir);
+ if (ret) goto fail;
+ }
- /* one found, that means name is not available */
- /* return EEXIST */
- return sysdb_ret_error(cbctx, EEXIST, LDB_ERR_ENTRY_ALREADY_EXISTS);
+ if (shell && *shell) {
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_SHELL, shell);
+ if (ret) goto fail;
+ }
- case LDB_REPLY_DONE:
+ /* creation time */
+ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
+ (unsigned long)time(NULL));
+ if (ret) goto fail;
- return sysdb_ret_done(cbctx);
- default:
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ ret = ldb_build_add_req(&ldbreq, handle->ctx->ldb, state, msg,
+ NULL, NULL, NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
+ ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
}
- return LDB_SUCCESS;
+ subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_op_default_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
+int sysdb_add_basic_user_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
+
+/* =Add-User-Function===================================================== */
-struct user_add_ctx {
+struct sysdb_add_user_state {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
- struct sysdb_cb_ctx *cbctx;
struct sss_domain_info *domain;
const char *name;
uid_t uid;
gid_t gid;
- const char *fullname;
+ const char *gecos;
const char *homedir;
const char *shell;
-
- struct next_id id;
+ struct sysdb_attrs *attrs;
};
-static void user_check_callback(void *pvt, int error, struct ldb_result *res);
-static int user_add_id(struct user_add_ctx *user_ctx);
-static void user_add_id_callback(void *pvt, int error, struct ldb_result *res);
-static int user_add_call(struct user_add_ctx *user_ctx);
+static void sysdb_add_user_group_check(struct tevent_req *subreq);
+static void sysdb_add_user_uid_check(struct tevent_req *subreq);
+static void sysdb_add_user_basic_done(struct tevent_req *subreq);
+static void sysdb_add_user_get_id_done(struct tevent_req *subreq);
+static void sysdb_add_user_set_id_done(struct tevent_req *subreq);
+static void sysdb_add_user_set_attrs_done(struct tevent_req *subreq);
-int sysdb_add_user(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name,
- uid_t uid, gid_t gid, const char *fullname,
- const char *homedir, const char *shell,
- sysdb_callback_t fn, void *pvt)
+struct tevent_req *sysdb_add_user_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ uid_t uid, gid_t gid,
+ const char *gecos,
+ const char *homedir,
+ const char *shell,
+ struct sysdb_attrs *attrs)
{
- struct user_add_ctx *user_ctx;
+ struct tevent_req *req, *subreq;
+ struct sysdb_add_user_state *state;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_add_user_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->domain = domain;
+ state->name = name;
+ state->uid = uid;
+ state->gid = gid;
+ state->gecos = gecos;
+ state->homedir = homedir;
+ state->shell = shell;
+ state->attrs = attrs;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ if (domain->mpg) {
+ if (gid != 0) {
+ DEBUG(0, ("Cannot add user with arbitrary GID in MPG domain!\n"));
+ ERROR_OUT(ret, EINVAL, fail);
+ }
+ state->gid = state->uid;
}
if (domain->id_max != 0 && uid != 0 &&
(uid < domain->id_min || uid > domain->id_max)) {
DEBUG(2, ("Supplied uid [%d] is not in the allowed range [%d-%d].\n",
uid, domain->id_min, domain->id_max));
- return EINVAL;
+ ERROR_OUT(ret, EINVAL, fail);
}
if (domain->id_max != 0 && gid != 0 &&
(gid < domain->id_min || gid > domain->id_max)) {
DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
gid, domain->id_min, domain->id_max));
- return EINVAL;
+ ERROR_OUT(ret, EINVAL, fail);
}
+ if (domain->mpg) {
+ /* In MPG domains you can't have groups with the same name as users,
+ * search if a group with the same name exists.
+ * Don't worry about users, if we try to add a user with the same
+ * name the operation will fail */
+
+ subreq = sysdb_search_group_by_name_send(state, ev, handle,
+ domain, name);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_group_check, req);
+ return req;
+ }
- user_ctx = talloc(handle, struct user_add_ctx);
- if (!user_ctx) return ENOMEM;
+ /* check no other user with the same uid exist */
+ if (state->uid != 0) {
+ subreq = sysdb_search_user_by_uid_send(state, ev, handle, domain, uid);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_uid_check, req);
+ return req;
+ }
- user_ctx->cbctx = talloc_zero(user_ctx, struct sysdb_cb_ctx);
- if (!user_ctx->cbctx) return ENOMEM;
+ /* try to add the user */
+ subreq = sysdb_add_basic_user_send(state, ev, handle,
+ domain, name, uid, gid,
+ gecos, homedir, shell);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req);
+ return req;
- user_ctx->handle = handle;
- user_ctx->domain = domain;
- user_ctx->cbctx->fn = fn;
- user_ctx->cbctx->pvt = pvt;
- user_ctx->name = name;
- user_ctx->uid = uid;
- user_ctx->gid = gid;
- user_ctx->fullname = fullname;
- user_ctx->homedir = homedir;
- user_ctx->shell = shell;
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
- if (domain->mpg) {
- /* if the domain is mpg we need to check we do not have there are no
- * name conflicts */
+static void sysdb_add_user_group_check(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_user_state *state = tevent_req_data(req,
+ struct sysdb_add_user_state);
+ struct ldb_message *msg;
+ int ret;
- return sysdb_check_name_unique(handle, domain, user_ctx, name,
- user_check_callback, user_ctx);
+ /* We can succeed only if we get an ENOENT error, which means no groups
+ * with the same name exist.
+ * If any other error is returned fail as well. */
+ ret = sysdb_search_group_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret != ENOENT) {
+ if (ret == EOK) ret = EEXIST;
+ tevent_req_error(req, ret);
+ return;
}
- return user_add_id(user_ctx);
+ /* check no other user with the same uid exist */
+ if (state->uid != 0) {
+ subreq = sysdb_search_user_by_uid_send(state,
+ state->ev, state->handle,
+ state->domain, state->uid);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_uid_check, req);
+ return;
+ }
+
+ /* try to add the user */
+ subreq = sysdb_add_basic_user_send(state, state->ev, state->handle,
+ state->domain, state->name,
+ state->uid, state->gid,
+ state->gecos,
+ state->homedir,
+ state->shell);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req);
}
-static void user_check_callback(void *pvt, int error, struct ldb_result *res)
+static void sysdb_add_user_uid_check(struct tevent_req *subreq)
{
- struct user_add_ctx *user_ctx;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_user_state *state = tevent_req_data(req,
+ struct sysdb_add_user_state);
+ struct ldb_message *msg;
int ret;
- user_ctx = talloc_get_type(pvt, struct user_add_ctx);
- if (error != EOK) {
- sysdb_ret_error(user_ctx->cbctx, error, LDB_ERR_OPERATIONS_ERROR);
+ /* We can succeed only if we get an ENOENT error, which means no user
+ * with the same uid exist.
+ * If any other error is returned fail as well. */
+ ret = sysdb_search_user_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret != ENOENT) {
+ if (ret == EOK) ret = EEXIST;
+ tevent_req_error(req, ret);
return;
}
- ret = user_add_id(user_ctx);
- if (ret != EOK) {
- sysdb_ret_error(user_ctx->cbctx, ret, LDB_ERR_OPERATIONS_ERROR);
+ /* try to add the user */
+ subreq = sysdb_add_basic_user_send(state, state->ev, state->handle,
+ state->domain, state->name,
+ state->uid, state->gid,
+ state->gecos,
+ state->homedir,
+ state->shell);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
+ tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req);
}
-static int user_add_id(struct user_add_ctx *user_ctx)
+static void sysdb_add_user_basic_done(struct tevent_req *subreq)
{
- if (user_ctx->uid != 0 && user_ctx->gid == 0) {
- if(user_ctx->domain->mpg) {
- user_ctx->gid = user_ctx->uid;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_user_state *state = tevent_req_data(req,
+ struct sysdb_add_user_state);
+ int ret;
+
+ ret = sysdb_add_basic_user_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ if (state->uid == 0) {
+ subreq = sysdb_get_new_id_send(state,
+ state->ev, state->handle,
+ state->domain);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
+ tevent_req_set_callback(subreq, sysdb_add_user_get_id_done, req);
+ return;
}
- if (user_ctx->uid == 0 || user_ctx->gid == 0) {
- /* Must generate uid/gid pair */
- return sysdb_get_next_available_id(user_ctx->handle,
- user_ctx->domain,
- &(user_ctx->id),
- user_add_id_callback, user_ctx);
+ if (state->attrs) {
+ subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
+ state->domain, state->name,
+ state->attrs, SYSDB_MOD_ADD);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_set_attrs_done, req);
+ return;
}
- return user_add_call(user_ctx);
+ tevent_req_done(req);
}
-static void user_add_id_callback(void *pvt, int error, struct ldb_result *res)
+static void sysdb_add_user_get_id_done(struct tevent_req *subreq)
{
- struct user_add_ctx *user_ctx;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_user_state *state = tevent_req_data(req,
+ struct sysdb_add_user_state);
+ struct sysdb_attrs *id_attrs;
+ uint32_t id;
int ret;
- user_ctx = talloc_get_type(pvt, struct user_add_ctx);
- if (error != EOK) {
- sysdb_ret_error(user_ctx->cbctx, error, LDB_ERR_OPERATIONS_ERROR);
+ ret = sysdb_get_new_id_recv(subreq, &id);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
return;
}
- /* ok id has been allocated, fill in uid and gid fields if not
- * already set */
- if (user_ctx->uid == 0) {
- user_ctx->uid = user_ctx->id.id;
+ if (state->uid == 0) {
+ id_attrs = sysdb_new_attrs(state);
+ if (!id_attrs) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_UIDNUM, id);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ if (state->domain->mpg) {
+ ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ }
+
+ subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
+ state->domain, state->name,
+ id_attrs, SYSDB_MOD_REP);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_set_id_done, req);
+ return;
+ }
+
+ if (state->attrs) {
+ subreq = sysdb_set_user_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->attrs,
+ SYSDB_MOD_REP);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_set_attrs_done, req);
+ return;
}
- if (user_ctx->gid == 0) {
- user_ctx->gid = user_ctx->id.id;
+
+ tevent_req_done(req);
+}
+
+static void sysdb_add_user_set_id_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_user_state *state = tevent_req_data(req,
+ struct sysdb_add_user_state);
+ int ret;
+
+ ret = sysdb_set_user_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- ret = user_add_call(user_ctx);
- if (ret != EOK) {
- sysdb_ret_error(user_ctx->cbctx, ret, LDB_ERR_OPERATIONS_ERROR);
+ if (state->attrs) {
+ subreq = sysdb_set_user_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->attrs,
+ SYSDB_MOD_REP);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_user_set_attrs_done, req);
+ return;
}
+
+ tevent_req_done(req);
}
-static int user_add_call(struct user_add_ctx *user_ctx)
+static void sysdb_add_user_set_attrs_done(struct tevent_req *subreq)
{
- struct sysdb_ctx *ctx;
- struct ldb_message *msg;
- struct ldb_request *req;
- int flags = LDB_FLAG_MOD_ADD;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
int ret;
- ctx = sysdb_handle_get_ctx(user_ctx->handle);
+ ret = sysdb_set_user_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- msg = ldb_msg_new(user_ctx);
- if (!msg) return ENOMEM;
+ tevent_req_done(req);
+}
- msg->dn = sysdb_user_dn(ctx, msg, user_ctx->domain->name, user_ctx->name);
- if (!msg->dn) return ENOMEM;
+int sysdb_add_user_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
- ret = add_string(msg, flags, "objectClass", SYSDB_USER_CLASS);
- if (ret != LDB_SUCCESS) return ENOMEM;
- ret = add_string(msg, flags, SYSDB_NAME, user_ctx->name);
- if (ret != LDB_SUCCESS) return ENOMEM;
+/* =Add-Basic-Group-NO-CHECKS============================================= */
- if (user_ctx->uid) {
- ret = add_ulong(msg, flags, SYSDB_UIDNUM,
- (unsigned long)(user_ctx->uid));
- if (ret != LDB_SUCCESS) return ENOMEM;
- } else {
- DEBUG(0, ("Cached users can't have UID == 0\n"));
- return EINVAL;
- }
+struct tevent_req *sysdb_add_basic_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name, gid_t gid)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_request *ldbreq;
+ struct ldb_message *msg;
+ int ret;
- if (user_ctx->gid) {
- ret = add_ulong(msg, flags, SYSDB_GIDNUM,
- (unsigned long)(user_ctx->gid));
- if (ret != LDB_SUCCESS) return ENOMEM;
- } else {
- DEBUG(0, ("Cached users can't have GID == 0\n"));
- return EINVAL;
- }
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
- /* We set gecos to be the same as fullname on user creation,
- * But we will not enforce coherency after that, it's up to
- * admins to decide if they want to keep it in sync if they change
- * one of the 2 */
- if (user_ctx->fullname && *user_ctx->fullname) {
- ret = add_string(msg, flags, SYSDB_FULLNAME, user_ctx->fullname);
- if (ret != LDB_SUCCESS) return ENOMEM;
- ret = add_string(msg, flags, SYSDB_GECOS, user_ctx->fullname);
- if (ret != LDB_SUCCESS) return ENOMEM;
- }
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
- if (user_ctx->homedir && *user_ctx->homedir) {
- ret = add_string(msg, flags, SYSDB_HOMEDIR, user_ctx->homedir);
- if (ret != LDB_SUCCESS) return ENOMEM;
+ msg = ldb_msg_new(state);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- if (user_ctx->shell && *user_ctx->shell) {
- ret = add_string(msg, flags, SYSDB_SHELL, user_ctx->shell);
- if (ret != LDB_SUCCESS) return ENOMEM;
+ /* user dn */
+ msg->dn = sysdb_group_dn(handle->ctx, msg, domain->name, name);
+ if (!msg->dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, "objectClass", SYSDB_GROUP_CLASS);
+ if (ret) goto fail;
+
+ ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
+ if (ret) goto fail;
+
+ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
+ if (ret) goto fail;
+
/* creation time */
- ret = add_ulong(msg, flags, SYSDB_CREATE_TIME, (unsigned long)time(NULL));
- if (ret != LDB_SUCCESS) return ENOMEM;
+ ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
+ (unsigned long)time(NULL));
+ if (ret) goto fail;
- ret = ldb_build_add_req(&req, ctx->ldb, user_ctx, msg, NULL,
- user_ctx->cbctx, sysdb_op_callback, NULL);
- if (ret == LDB_SUCCESS) {
- ret = ldb_request(ctx->ldb, req);
- }
+
+ ret = ldb_build_add_req(&ldbreq, handle->ctx->ldb, state, msg,
+ NULL, NULL, NULL, NULL);
if (ret != LDB_SUCCESS) {
- return sysdb_error_to_errno(ret);
+ DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
+ ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
}
- return EOK;
+ subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_op_default_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+int sysdb_add_basic_group_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
}
-struct group_add_ctx {
+
+/* =Add-Group-Function==================================================== */
+
+struct sysdb_add_group_state {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
- struct sysdb_cb_ctx *cbctx;
struct sss_domain_info *domain;
const char *name;
gid_t gid;
-
- struct next_id id;
+ struct sysdb_attrs *attrs;
};
-static void group_check_callback(void *pvt, int error, struct ldb_result *res);
-static int group_add_id(struct group_add_ctx *group_ctx);
-static void group_add_id_callback(void *pvt, int error, struct ldb_result *res);
-static int group_add_call(struct group_add_ctx *group_ctx);
-
-int sysdb_add_group(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name, gid_t gid,
- sysdb_callback_t fn, void *pvt)
+static void sysdb_add_group_user_check(struct tevent_req *subreq);
+static void sysdb_add_group_gid_check(struct tevent_req *subreq);
+static void sysdb_add_group_basic_done(struct tevent_req *subreq);
+static void sysdb_add_group_get_id_done(struct tevent_req *subreq);
+static void sysdb_add_group_set_id_done(struct tevent_req *subreq);
+static void sysdb_add_group_set_attrs_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_add_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name, gid_t gid,
+ struct sysdb_attrs *attrs)
{
- struct group_add_ctx *group_ctx;
+ struct tevent_req *req, *subreq;
+ struct sysdb_add_group_state *state;
+ int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
- }
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_add_group_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->domain = domain;
+ state->name = name;
+ state->gid = gid;
+ state->attrs = attrs;
if (domain->id_max != 0 && gid != 0 &&
(gid < domain->id_min || gid > domain->id_max)) {
DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
gid, domain->id_min, domain->id_max));
- return EINVAL;
+ ERROR_OUT(ret, EINVAL, fail);
}
- group_ctx = talloc(handle, struct group_add_ctx);
- if (!group_ctx) return ENOMEM;
-
- group_ctx->cbctx = talloc_zero(group_ctx, struct sysdb_cb_ctx);
- if (!group_ctx->cbctx) return ENOMEM;
-
- group_ctx->handle = handle;
- group_ctx->domain = domain;
- group_ctx->cbctx->fn = fn;
- group_ctx->cbctx->pvt = pvt;
- group_ctx->name = name;
- group_ctx->gid = gid;
-
if (domain->mpg) {
- /* if the domain is mpg we need to check we do not have there are no
- * name conflicts */
+ /* In MPG domains you can't have groups with the same name as users,
+ * search if a group with the same name exists.
+ * Don't worry about users, if we try to add a user with the same
+ * name the operation will fail */
+
+ subreq = sysdb_search_user_by_name_send(state, ev, handle,
+ domain, name);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_user_check, req);
+ return req;
+ }
+
+ /* check no other groups with the same gid exist */
+ if (state->gid != 0) {
+ subreq = sysdb_search_group_by_gid_send(state, ev, handle,
+ domain, gid);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_gid_check, req);
+ return req;
+ }
- return sysdb_check_name_unique(handle, domain, group_ctx, name,
- group_check_callback, group_ctx);
+ /* try to add the group */
+ subreq = sysdb_add_basic_group_send(state, ev, handle,
+ domain, name, gid);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
+ tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req);
+ return req;
- return group_add_id(group_ctx);
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
-static void group_check_callback(void *pvt, int error, struct ldb_result *res)
+static void sysdb_add_group_user_check(struct tevent_req *subreq)
{
- struct group_add_ctx *group_ctx;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_group_state *state = tevent_req_data(req,
+ struct sysdb_add_group_state);
+ struct ldb_message *msg;
int ret;
- group_ctx = talloc_get_type(pvt, struct group_add_ctx);
- if (error != EOK) {
- sysdb_ret_error(group_ctx->cbctx, error, LDB_ERR_OPERATIONS_ERROR);
+ /* We can succeed only if we get an ENOENT error, which means no users
+ * with the same name exist.
+ * If any other error is returned fail as well. */
+ ret = sysdb_search_user_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret != ENOENT) {
+ if (ret == EOK) ret = EEXIST;
+ tevent_req_error(req, ret);
return;
}
- ret = group_add_id(group_ctx);
- if (ret != EOK) {
- sysdb_ret_error(group_ctx->cbctx, ret, LDB_ERR_OPERATIONS_ERROR);
+ /* check no other group with the same gid exist */
+ if (state->gid != 0) {
+ subreq = sysdb_search_group_by_gid_send(state,
+ state->ev, state->handle,
+ state->domain, state->gid);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_gid_check, req);
+ return;
}
+
+ /* try to add the group */
+ subreq = sysdb_add_basic_group_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->gid);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req);
}
-static int group_add_id(struct group_add_ctx *group_ctx)
+static void sysdb_add_group_gid_check(struct tevent_req *subreq)
{
- if (group_ctx->gid == 0) {
- /* Must generate uid/gid pair */
- return sysdb_get_next_available_id(group_ctx->handle,
- group_ctx->domain,
- &(group_ctx->id),
- group_add_id_callback, group_ctx);
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_group_state *state = tevent_req_data(req,
+ struct sysdb_add_group_state);
+ struct ldb_message *msg;
+ int ret;
+
+ /* We can succeed only if we get an ENOENT error, which means no group
+ * with the same gid exist.
+ * If any other error is returned fail as well. */
+ ret = sysdb_search_group_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret != ENOENT) {
+ if (ret == EOK) ret = EEXIST;
+ tevent_req_error(req, ret);
+ return;
}
- return group_add_call(group_ctx);
+ /* try to add the group */
+ subreq = sysdb_add_basic_group_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->gid);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req);
}
-static void group_add_id_callback(void *pvt, int error, struct ldb_result *res)
+static void sysdb_add_group_basic_done(struct tevent_req *subreq)
{
- struct group_add_ctx *group_ctx;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_group_state *state = tevent_req_data(req,
+ struct sysdb_add_group_state);
int ret;
- group_ctx = talloc_get_type(pvt, struct group_add_ctx);
- if (error != EOK) {
- sysdb_ret_error(group_ctx->cbctx, error, LDB_ERR_OPERATIONS_ERROR);
+ ret = sysdb_add_basic_group_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
return;
}
- /* ok id has been allocated, fill in uid and gid fields */
- group_ctx->gid = group_ctx->id.id;
+ if (state->gid == 0) {
+ subreq = sysdb_get_new_id_send(state,
+ state->ev, state->handle,
+ state->domain);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_get_id_done, req);
+ return;
+ }
- ret = group_add_call(group_ctx);
- if (ret != EOK) {
- sysdb_ret_error(group_ctx->cbctx, ret, LDB_ERR_OPERATIONS_ERROR);
+ if (state->attrs) {
+ subreq = sysdb_set_group_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->attrs,
+ SYSDB_MOD_ADD);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_set_attrs_done, req);
+ return;
}
+
+ tevent_req_done(req);
}
-static int group_add_call(struct group_add_ctx *group_ctx)
+static void sysdb_add_group_get_id_done(struct tevent_req *subreq)
{
- struct sysdb_ctx *ctx;
- struct ldb_message *msg;
- struct ldb_request *req;
- int flags = LDB_FLAG_MOD_ADD;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_group_state *state = tevent_req_data(req,
+ struct sysdb_add_group_state);
+ struct sysdb_attrs *id_attrs;
+ uint32_t id;
int ret;
- ctx = sysdb_handle_get_ctx(group_ctx->handle);
-
- msg = ldb_msg_new(group_ctx);
- if (!msg) return ENOMEM;
-
- msg->dn = sysdb_group_dn(ctx, msg, group_ctx->domain->name, group_ctx->name);
- if (!msg->dn) return ENOMEM;
+ ret = sysdb_get_new_id_recv(subreq, &id);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- ret = add_string(msg, flags, "objectClass", SYSDB_GROUP_CLASS);
- if (ret != LDB_SUCCESS) return ENOMEM;
+ if (state->gid == 0) {
+ id_attrs = sysdb_new_attrs(state);
+ if (!id_attrs) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- ret = add_string(msg, flags, SYSDB_NAME, group_ctx->name);
- if (ret != LDB_SUCCESS) return ENOMEM;
+ subreq = sysdb_set_group_attr_send(state, state->ev, state->handle,
+ state->domain, state->name,
+ id_attrs, SYSDB_MOD_REP);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_set_id_done, req);
+ return;
+ }
- if (group_ctx->gid) {
- ret = add_ulong(msg, flags, SYSDB_GIDNUM,
- (unsigned long)(group_ctx->gid));
- if (ret != LDB_SUCCESS) return ENOMEM;
- } else {
- DEBUG(0, ("Cached groups can't have GID == 0\n"));
- return EINVAL;
+ if (state->attrs) {
+ subreq = sysdb_set_group_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->attrs,
+ SYSDB_MOD_ADD);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_set_attrs_done, req);
+ return;
}
- /* creation time */
- ret = add_ulong(msg, flags, SYSDB_CREATE_TIME, (unsigned long)time(NULL));
- if (ret != LDB_SUCCESS) return ENOMEM;
+ tevent_req_done(req);
+}
- ret = ldb_build_add_req(&req, ctx->ldb, group_ctx, msg, NULL,
- group_ctx->cbctx, sysdb_op_callback, NULL);
- if (ret == LDB_SUCCESS) {
- ret = ldb_request(ctx->ldb, req);
+static void sysdb_add_group_set_id_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_group_state *state = tevent_req_data(req,
+ struct sysdb_add_group_state);
+ int ret;
+
+ ret = sysdb_set_group_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- if (ret != LDB_SUCCESS) {
- return sysdb_error_to_errno(ret);
+
+ if (state->attrs) {
+ subreq = sysdb_set_group_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->attrs,
+ SYSDB_MOD_ADD);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_group_set_attrs_done, req);
+ return;
}
- return EOK;
+ tevent_req_done(req);
}
-/* This function is not safe, but is included for completeness
- * It is much better to allow SSSD to internally manage the
- * group GID values. sysdb_set_group_gid() will perform no
- * validation that the new GID is unused. The only check it
- * will perform is whether the requested GID is in the range
- * of IDs allocated for the domain.
- */
-int sysdb_set_group_gid(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name, gid_t gid,
- sysdb_callback_t fn, void *pvt)
-{
- struct group_add_ctx *group_ctx;
- struct sysdb_ctx *sysdb;
- struct ldb_message *msg;
- struct ldb_request *req;
- int flags = LDB_FLAG_MOD_REPLACE;
+static void sysdb_add_group_set_attrs_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ ret = sysdb_set_group_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- /* Validate that the target GID is within the domain range */
- if((gid < domain->id_min) ||
- (domain->id_max && (gid > domain->id_max))) {
- DEBUG(2, ("Invalid request. Domain ID out of range"));
- return EDOM;
- }
+ tevent_req_done(req);
+}
+
+int sysdb_add_group_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
- group_ctx = talloc(handle, struct group_add_ctx);
- if (!group_ctx) return ENOMEM;
- group_ctx->cbctx = talloc_zero(group_ctx, struct sysdb_cb_ctx);
- if (!group_ctx->cbctx) return ENOMEM;
+/* =Add-Or-Remove-Group-Memeber=========================================== */
- group_ctx->handle = handle;
- group_ctx->domain = domain;
- group_ctx->cbctx->fn = fn;
- group_ctx->cbctx->pvt = pvt;
- group_ctx->name = name;
- group_ctx->gid = gid;
+/* mod_op must be either SYSDB_MOD_ADD or SYSDB_MOD_DEL */
+struct tevent_req *sysdb_mod_group_member_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct ldb_dn *member_dn,
+ struct ldb_dn *group_dn,
+ int mod_op)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_request *ldbreq;
+ struct ldb_message *msg;
+ const char *dn;
+ int ret;
- sysdb = sysdb_handle_get_ctx(group_ctx->handle);
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
- msg = ldb_msg_new(group_ctx);
- if (!msg) return ENOMEM;
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
- msg->dn = sysdb_group_dn(sysdb, msg,
- group_ctx->domain->name,
- group_ctx->name);
- if (!msg->dn) return ENOMEM;
+ msg = ldb_msg_new(state);
+ if (!msg) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
- ret = add_ulong(msg, flags, SYSDB_GIDNUM,
- (unsigned long)(group_ctx->gid));
+ msg->dn = group_dn;
+ ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, mod_op, NULL);
+ if (ret != LDB_SUCCESS) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
- ret = ldb_build_mod_req(&req, sysdb->ldb, group_ctx, msg, NULL,
- group_ctx->cbctx, sysdb_op_callback, NULL);
- if (ret == LDB_SUCCESS) {
- ret = ldb_request(sysdb->ldb, req);
+ dn = ldb_dn_get_linearized(member_dn);
+ if (!dn) {
+ ERROR_OUT(ret, EINVAL, fail);
}
+
+ ret = ldb_msg_add_fmt(msg, SYSDB_MEMBER, "%s", dn);
if (ret != LDB_SUCCESS) {
- return sysdb_error_to_errno(ret);
+ ERROR_OUT(ret, EINVAL, fail);
}
- return EOK;
+ ret = ldb_build_mod_req(&ldbreq, handle->ctx->ldb, state, msg,
+ NULL, NULL, NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
+ ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
+ }
+
+ subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_op_default_done, req);
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+int sysdb_mod_group_member_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
}
-/* "sysdb_legacy_" functions
- * the set of functions named sysdb_legacy_* are used by modules
- * that only have access to strictly posix like databases where
- * user and groups names are retrieved as strings, groups can't
- * be nested and can't reference foreign sources */
-struct legacy_user_ctx {
+/* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */
+
+/* if one of the basic attributes is empty ("") as opposed to NULL,
+ * this will just remove it */
+
+struct sysdb_store_user_state {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
- struct sysdb_cb_ctx *cbctx;
struct sss_domain_info *domain;
- struct ldb_dn *dn;
-
const char *name;
- const char *pwd;
uid_t uid;
gid_t gid;
const char *gecos;
const char *homedir;
const char *shell;
-
- struct ldb_result *res;
+ struct sysdb_attrs *attrs;
};
-static int legacy_user_callback(struct ldb_request *req,
- struct ldb_reply *rep);
-
-int sysdb_legacy_store_user(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name, const char *pwd,
- uid_t uid, gid_t gid, const char *gecos,
- const char *homedir, const char *shell,
- sysdb_callback_t fn, void *pvt)
+static void sysdb_store_user_check(struct tevent_req *subreq);
+static void sysdb_store_user_add_done(struct tevent_req *subreq);
+static void sysdb_store_user_attr_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_store_user_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ const char *pwd,
+ uid_t uid, gid_t gid,
+ const char *gecos,
+ const char *homedir,
+ const char *shell)
{
- static const char *attrs[] = { SYSDB_NAME, NULL };
- struct legacy_user_ctx *user_ctx;
- struct sysdb_ctx *ctx;
- struct ldb_request *req;
+ struct tevent_req *req, *subreq;
+ struct sysdb_store_user_state *state;
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
- }
-
- ctx = sysdb_handle_get_ctx(handle);
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_store_user_state);
+ if (!req) return NULL;
- user_ctx = talloc(handle, struct legacy_user_ctx);
- if (!user_ctx) return ENOMEM;
+ state->ev = ev;
+ state->handle = handle;
+ state->domain = domain;
+ state->name = name;
+ state->uid = uid;
+ state->gid = gid;
+ state->gecos = gecos;
+ state->homedir = homedir;
+ state->shell = shell;
+ state->attrs = NULL;
- user_ctx->cbctx = talloc_zero(user_ctx, struct sysdb_cb_ctx);
- if (!user_ctx->cbctx) return ENOMEM;
-
- user_ctx->dn = sysdb_user_dn(ctx, user_ctx, domain->name, name);
- if (!user_ctx->dn) return ENOMEM;
-
- user_ctx->handle = handle;
- user_ctx->cbctx->fn = fn;
- user_ctx->cbctx->pvt = pvt;
- user_ctx->domain = domain;
- user_ctx->name = name;
- user_ctx->pwd = pwd;
- user_ctx->uid = uid;
- user_ctx->gid = gid;
- user_ctx->gecos = gecos;
- user_ctx->homedir = homedir;
- user_ctx->shell = shell;
-
- user_ctx->res = talloc_zero(user_ctx, struct ldb_result);
- if (!user_ctx->res) return ENOMEM;
+ if (pwd && (domain->legacy_passwords || !*pwd)) {
+ ret = sysdb_attrs_add_string(state->attrs, SYSDB_PWD, pwd);
+ if (ret) goto fail;
+ }
- ret = ldb_build_search_req(&req, ctx->ldb, user_ctx,
- user_ctx->dn, LDB_SCOPE_BASE,
- SYSDB_PWENT_FILTER, attrs, NULL,
- user_ctx, legacy_user_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ subreq = sysdb_search_user_by_name_send(state, ev, handle, domain, name);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
+ tevent_req_set_callback(subreq, sysdb_store_user_check, req);
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ return req;
- return EOK;
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
-static int legacy_user_callback(struct ldb_request *req,
- struct ldb_reply *rep)
+static void sysdb_store_user_check(struct tevent_req *subreq)
{
- struct legacy_user_ctx *user_ctx;
- struct sysdb_cb_ctx *cbctx;
- struct sysdb_ctx *ctx;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_store_user_state *state = tevent_req_data(req,
+ struct sysdb_store_user_state);
struct ldb_message *msg;
- struct ldb_request *ureq;
- struct ldb_result *res;
- int flags;
- int ret, err;
-
- user_ctx = talloc_get_type(req->context, struct legacy_user_ctx);
- ctx = sysdb_handle_get_ctx(user_ctx->handle);
- cbctx = user_ctx->cbctx;
- res = user_ctx->res;
+ int ret;
- if (!rep) {
- return sysdb_ret_error(cbctx, EIO, LDB_ERR_OPERATIONS_ERROR);
- }
- if (rep->error != LDB_SUCCESS) {
- err = sysdb_error_to_errno(rep->error);
- return sysdb_ret_error(cbctx, err, rep->error);
+ ret = sysdb_search_user_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret && ret != ENOENT) {
+ tevent_req_error(req, ret);
+ return;
}
- switch (rep->type) {
- case LDB_REPLY_ENTRY:
- res->msgs = talloc_realloc(res, res->msgs,
- struct ldb_message *,
- res->count + 2);
- if (!res->msgs) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
+ if (ret == ENOENT) {
+ /* users doesn't exist, turn into adding a user */
+ subreq = sysdb_add_user_send(state, state->ev, state->handle,
+ state->domain, state->name,
+ state->uid, state->gid,
+ state->gecos, state->homedir,
+ state->shell, state->attrs);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
+ tevent_req_set_callback(subreq, sysdb_store_user_add_done, req);
+ return;
+ }
- res->msgs[res->count + 1] = NULL;
-
- res->msgs[res->count] = talloc_steal(res->msgs, rep->message);
- res->count++;
-
- break;
-
- case LDB_REPLY_DONE:
-
- msg = ldb_msg_new(cbctx);
- if (!msg) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- msg->dn = user_ctx->dn;
-
- switch (res->count) {
- case 0:
- flags = LDB_FLAG_MOD_ADD;
- break;
- case 1:
- flags = LDB_FLAG_MOD_REPLACE;
- break;
- default:
- DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
- res->count));
-
- return sysdb_ret_error(cbctx, EFAULT, LDB_ERR_OPERATIONS_ERROR);
+ /* the user exists, let's just replace attributes when set */
+ if (!state->attrs) {
+ state->attrs = sysdb_new_attrs(state);
+ if (!state->attrs) {
+ tevent_req_error(req, ENOMEM);
+ return;
}
+ }
- talloc_free(res);
- user_ctx->res = res = NULL;
-
- if (flags == LDB_FLAG_MOD_ADD) {
- ret = add_string(msg, flags, "objectClass", SYSDB_USER_CLASS);
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
-
- ret = add_string(msg, flags, SYSDB_NAME, user_ctx->name);
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+ if (state->uid) {
+ ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_UIDNUM, state->uid);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
+ }
- if (user_ctx->domain->legacy_passwords &&
- user_ctx->pwd && *user_ctx->pwd) {
- ret = add_string(msg, flags, SYSDB_PWD, user_ctx->pwd);
- } else {
- ret = ldb_msg_add_empty(msg, SYSDB_PWD,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
+ if (state->gid) {
+ ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->gid);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
+ }
- if (user_ctx->uid) {
- ret = add_ulong(msg, flags, SYSDB_UIDNUM,
- (unsigned long)(user_ctx->uid));
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- } else {
- DEBUG(0, ("Cached users can't have UID == 0\n"));
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ if (state->uid && !state->gid && state->domain->mpg) {
+ ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->uid);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
+ }
- if (user_ctx->gid) {
- ret = add_ulong(msg, flags, SYSDB_GIDNUM,
- (unsigned long)(user_ctx->gid));
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- } else {
- DEBUG(0, ("Cached users can't have GID == 0\n"));
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ if (state->gecos) {
+ ret = sysdb_attrs_add_string(state->attrs, SYSDB_GECOS, state->gecos);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
+ }
- if (user_ctx->gecos && *user_ctx->gecos) {
- ret = add_string(msg, flags, SYSDB_GECOS, user_ctx->gecos);
- } else {
- ret = ldb_msg_add_empty(msg, SYSDB_GECOS,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
+ if (state->homedir) {
+ ret = sysdb_attrs_add_string(state->attrs,
+ SYSDB_HOMEDIR, state->homedir);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
+ }
- if (user_ctx->homedir && *user_ctx->homedir) {
- ret = add_string(msg, flags, SYSDB_HOMEDIR, user_ctx->homedir);
- } else {
- ret = ldb_msg_add_empty(msg, SYSDB_HOMEDIR,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
+ if (state->shell) {
+ ret = sysdb_attrs_add_string(state->attrs, SYSDB_SHELL, state->shell);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
+ }
- if (user_ctx->shell && *user_ctx->shell) {
- ret = add_string(msg, flags, SYSDB_SHELL, user_ctx->shell);
- } else {
- ret = ldb_msg_add_empty(msg, SYSDB_SHELL,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+ ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, time(NULL));
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- /* modification time */
- ret = add_ulong(msg, flags, SYSDB_LAST_UPDATE,
- (unsigned long)time(NULL));
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+ subreq = sysdb_set_user_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->attrs,
+ SYSDB_MOD_REP);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_store_user_attr_done, req);
+}
- if (flags == LDB_FLAG_MOD_ADD) {
- ret = ldb_build_add_req(&ureq, ctx->ldb, cbctx, msg, NULL,
- cbctx, sysdb_op_callback, NULL);
- } else {
- ret = ldb_build_mod_req(&ureq, ctx->ldb, cbctx, msg, NULL,
- cbctx, sysdb_op_callback, NULL);
- }
- if (ret == LDB_SUCCESS) {
- ret = ldb_request(ctx->ldb, ureq);
- }
- if (ret != LDB_SUCCESS) {
- err = sysdb_error_to_errno(ret);
- return sysdb_ret_error(cbctx, err, ret);
- }
- break;
+static void sysdb_store_user_add_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
- default:
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ ret = sysdb_add_user_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- talloc_free(rep);
- return LDB_SUCCESS;
+ tevent_req_done(req);
}
+static void sysdb_store_user_attr_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+ ret = sysdb_set_user_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_store_user_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
+
+/* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */
/* this function does not check that all user members are actually present */
-struct legacy_group_ctx {
+struct sysdb_store_group_state {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
- struct sysdb_cb_ctx *cbctx;
struct sss_domain_info *domain;
- struct ldb_dn *dn;
-
const char *name;
gid_t gid;
const char **members;
- struct ldb_result *res;
+ struct sysdb_attrs *attrs;
};
-static int legacy_group_callback(struct ldb_request *req,
- struct ldb_reply *rep);
-
-int sysdb_legacy_store_group(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *name, gid_t gid,
- const char **members,
- sysdb_callback_t fn, void *pvt)
+static void sysdb_store_group_check(struct tevent_req *subreq);
+static void sysdb_store_group_add_done(struct tevent_req *subreq);
+static void sysdb_store_group_attr_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name,
+ gid_t gid,
+ const char **members)
{
- static const char *attrs[] = { SYSDB_NAME, NULL };
- struct legacy_group_ctx *group_ctx;
- struct sysdb_ctx *ctx;
- struct ldb_request *req;
- int ret;
+ struct tevent_req *req, *subreq;
+ struct sysdb_store_group_state *state;
+ int ret, i;
+
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_store_group_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->domain = domain;
+ state->name = name;
+ state->gid = gid;
+ state->members = members;
+ state->attrs = NULL;
+
+ if (state->members) {
+ state->attrs = sysdb_new_attrs(state);
+ if (!state->attrs) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ for (i = 0; state->members[i]; i++) {
+ if (domain->legacy) {
+/*
+ const char *member;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ member = talloc_asprintf(state, SYSDB_TMPL_USER,
+ domain->name, state->members[i]);
+ if (!member) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+*/
+ ret = sysdb_attrs_add_string(state->attrs, SYSDB_LEGACY_MEMBER,
+ state->members[i]);
+ if (ret) goto fail;
+ } else {
+ ret = sysdb_attrs_add_string(state->attrs, SYSDB_MEMBER,
+ state->members[i]);
+ if (ret) goto fail;
+ }
+ }
+
+ state->members = NULL;
}
- ctx = sysdb_handle_get_ctx(handle);
+ subreq = sysdb_search_group_by_name_send(state, ev, handle, domain, name);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_store_group_check, req);
- group_ctx = talloc(handle, struct legacy_group_ctx);
- if (!group_ctx) return ENOMEM;
+ return req;
- group_ctx->cbctx = talloc_zero(group_ctx, struct sysdb_cb_ctx);
- if (!group_ctx->cbctx) return ENOMEM;
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
- group_ctx->dn = sysdb_group_dn(ctx, group_ctx, domain->name, name);
- if (!group_ctx->dn) return ENOMEM;
+static void sysdb_store_group_check(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_store_group_state *state = tevent_req_data(req,
+ struct sysdb_store_group_state);
+ struct ldb_message *msg;
+ int ret;
- group_ctx->handle = handle;
- group_ctx->cbctx->fn = fn;
- group_ctx->cbctx->pvt = pvt;
- group_ctx->domain = domain;
- group_ctx->name = name;
- group_ctx->gid = gid;
- group_ctx->members = members;
+ ret = sysdb_search_group_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret && ret != ENOENT) {
+ tevent_req_error(req, ret);
+ return;
+ }
- group_ctx->res = talloc_zero(group_ctx, struct ldb_result);
- if (!group_ctx->res) return ENOMEM;
+ if (ret == ENOENT) {
+ /* groups doesn't exist, turn into adding a group */
+ subreq = sysdb_add_group_send(state, state->ev, state->handle,
+ state->domain, state->name,
+ state->gid, state->attrs);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_store_group_add_done, req);
+ return;
+ }
- ret = ldb_build_search_req(&req, ctx->ldb, group_ctx,
- group_ctx->dn, LDB_SCOPE_BASE,
- SYSDB_GRENT_FILTER, attrs, NULL,
- group_ctx, legacy_group_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ /* the group exists, let's just replace attributes when set */
+ if (!state->attrs) {
+ state->attrs = sysdb_new_attrs(state);
+ if (!state->attrs) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ if (state->gid) {
+ ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->gid);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ }
- return EOK;
+ /* FIXME: handle non legacy groups */
+
+ ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, time(NULL));
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ subreq = sysdb_set_group_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->attrs,
+ SYSDB_MOD_REP);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_store_group_attr_done, req);
}
-static int legacy_group_callback(struct ldb_request *req,
- struct ldb_reply *rep)
+static void sysdb_store_group_add_done(struct tevent_req *subreq)
{
- struct legacy_group_ctx *group_ctx;
- struct sysdb_cb_ctx *cbctx;
- struct sysdb_ctx *ctx;
- struct ldb_message *msg;
- struct ldb_request *greq;
- struct ldb_result *res;
- int flags;
- int i, ret, err;
-
- group_ctx = talloc_get_type(req->context, struct legacy_group_ctx);
- ctx = sysdb_handle_get_ctx(group_ctx->handle);
- cbctx = group_ctx->cbctx;
- res = group_ctx->res;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
- if (!rep) {
- return sysdb_ret_error(cbctx, EIO, LDB_ERR_OPERATIONS_ERROR);
+ ret = sysdb_add_group_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- if (rep->error != LDB_SUCCESS) {
- err = sysdb_error_to_errno(rep->error);
- return sysdb_ret_error(cbctx, err, rep->error);
+
+ tevent_req_done(req);
+}
+
+static void sysdb_store_group_attr_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+
+ ret = sysdb_set_group_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- switch (rep->type) {
- case LDB_REPLY_ENTRY:
- res->msgs = talloc_realloc(res, res->msgs,
- struct ldb_message *,
- res->count + 2);
- if (!res->msgs) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+ tevent_req_done(req);
+}
- res->msgs[res->count + 1] = NULL;
+int sysdb_store_group_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
- res->msgs[res->count] = talloc_steal(res->msgs, rep->message);
- res->count++;
- break;
+/* =Add-User-to-Group(Native/Legacy)====================================== */
- case LDB_REPLY_DONE:
+static void sysdb_add_group_member_done(struct tevent_req *subreq);
+static void sysdb_add_group_member_l_done(struct tevent_req *subreq);
- msg = ldb_msg_new(cbctx);
- if (!msg) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- msg->dn = group_ctx->dn;
-
- switch (res->count) {
- case 0:
- flags = LDB_FLAG_MOD_ADD;
- break;
- case 1:
- flags = LDB_FLAG_MOD_REPLACE;
- break;
- default:
- DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
- res->count));
-
- return sysdb_ret_error(cbctx, EFAULT, LDB_ERR_OPERATIONS_ERROR);
- }
+struct tevent_req *sysdb_add_group_member_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *group,
+ const char *user)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_dn *group_dn, *user_dn;
+ struct sysdb_attrs *attrs;
+ int ret;
- talloc_free(res);
- group_ctx->res = res = NULL;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
- if (flags == LDB_FLAG_MOD_ADD) {
- ret = add_string(msg, flags, "objectClass", SYSDB_GROUP_CLASS);
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
- ret = add_string(msg, flags, SYSDB_NAME, group_ctx->name);
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
+ if (domain->legacy) {
+ attrs = sysdb_new_attrs(state);
+ if (!attrs) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- if (group_ctx->gid) {
- ret = add_ulong(msg, flags, SYSDB_GIDNUM,
- (unsigned long)(group_ctx->gid));
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- } else {
- DEBUG(0, ("Cached groups can't have GID == 0\n"));
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
- }
+ ret = sysdb_attrs_add_string(attrs, SYSDB_LEGACY_MEMBER, user);
+ if (ret) goto fail;
- /* members */
- if (group_ctx->members && group_ctx->members[0]) {
- ret = ldb_msg_add_empty(msg, SYSDB_LEGACY_MEMBER, flags, NULL);
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- for (i = 0; group_ctx->members[i]; i++) {
- ret = ldb_msg_add_string(msg, SYSDB_LEGACY_MEMBER,
- group_ctx->members[i]);
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
- }
- }
+ subreq = sysdb_set_group_attr_send(state, ev, handle,
+ domain, group, attrs,
+ SYSDB_MOD_ADD);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
+ tevent_req_set_callback(subreq, sysdb_add_group_member_l_done, req);
- /* modification time */
- ret = add_ulong(msg, flags, SYSDB_LAST_UPDATE,
- (unsigned long)time(NULL));
- if (ret != LDB_SUCCESS) {
- return sysdb_ret_error(cbctx, ENOMEM, LDB_ERR_OPERATIONS_ERROR);
+ } else {
+ group_dn = sysdb_group_dn(handle->ctx, state, domain->name, group);
+ if (!group_dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- if (flags == LDB_FLAG_MOD_ADD) {
- ret = ldb_build_add_req(&greq, ctx->ldb, cbctx, msg, NULL,
- cbctx, sysdb_op_callback, NULL);
- } else {
- ret = ldb_build_mod_req(&greq, ctx->ldb, cbctx, msg, NULL,
- cbctx, sysdb_op_callback, NULL);
- }
- if (ret == LDB_SUCCESS) {
- ret = ldb_request(ctx->ldb, greq);
+ user_dn = sysdb_user_dn(handle->ctx, state, domain->name, user);
+ if (!user_dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- if (ret != LDB_SUCCESS) {
- err = sysdb_error_to_errno(ret);
- return sysdb_ret_error(cbctx, err, ret);
+
+ subreq = sysdb_mod_group_member_send(state, ev, handle,
+ user_dn, group_dn,
+ SYSDB_MOD_ADD);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
}
- break;
+ tevent_req_set_callback(subreq, sysdb_add_group_member_done, req);
+ }
- default:
- return sysdb_ret_error(cbctx, EINVAL, LDB_ERR_OPERATIONS_ERROR);
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sysdb_add_group_member_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+
+ ret = sysdb_mod_group_member_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- talloc_free(rep);
- return LDB_SUCCESS;
+ tevent_req_done(req);
}
-int sysdb_legacy_add_group_member(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *group,
- const char *member,
- sysdb_callback_t fn, void *pvt)
+static void sysdb_add_group_member_l_done(struct tevent_req *subreq)
{
- struct sysdb_ctx *ctx;
- struct sysdb_cb_ctx *cbctx;
- struct ldb_request *req;
- struct ldb_message *msg;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ ret = sysdb_set_group_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- ctx = sysdb_handle_get_ctx(handle);
+ tevent_req_done(req);
+}
+
+int sysdb_add_group_member_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
- cbctx = talloc_zero(handle, struct sysdb_cb_ctx);
- if (!cbctx) return ENOMEM;
+/* =Remove-member-from-Group(Native/Legacy)=============================== */
- cbctx->fn = fn;
- cbctx->pvt = pvt;
+static void sysdb_remove_group_member_done(struct tevent_req *subreq);
+static void sysdb_remove_group_member_l_done(struct tevent_req *subreq);
- /* Add the member_dn as a member of the group */
- msg = ldb_msg_new(cbctx);
- if(msg == NULL) return ENOMEM;
+struct tevent_req *sysdb_remove_group_member_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *group,
+ const char *user)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
+ struct ldb_dn *group_dn, *user_dn;
+ struct sysdb_attrs *attrs;
+ int ret;
- msg->dn = sysdb_group_dn(ctx, cbctx, domain->name, group);
- if (!msg->dn) return ENOMEM;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
- ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_LEGACY_MEMBER, member);
- if (ret != LDB_SUCCESS) return ENOMEM;
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
- ret = ldb_build_mod_req(&req, ctx->ldb, cbctx, msg,
- NULL, cbctx, sysdb_op_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
+ if (domain->legacy) {
+ attrs = sysdb_new_attrs(state);
+ if (!attrs) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ ret = sysdb_attrs_add_string(attrs, SYSDB_LEGACY_MEMBER, user);
+ if (ret) goto fail;
+
+ subreq = sysdb_set_group_attr_send(state, ev, handle,
+ domain, group, attrs,
+ SYSDB_MOD_DEL);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_remove_group_member_l_done, req);
+
+ } else {
+ group_dn = sysdb_group_dn(handle->ctx, state, domain->name, group);
+ if (!group_dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ user_dn = sysdb_user_dn(handle->ctx, state, domain->name, user);
+ if (!user_dn) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+
+ subreq = sysdb_mod_group_member_send(state, ev, handle,
+ user_dn, group_dn,
+ SYSDB_MOD_DEL);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_remove_group_member_done, req);
}
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+ return req;
- return EOK;
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
-int sysdb_legacy_remove_group_member(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *group,
- const char *member,
- sysdb_callback_t fn, void *pvt)
+static void sysdb_remove_group_member_done(struct tevent_req *subreq)
{
- struct sysdb_ctx *ctx;
- struct sysdb_cb_ctx *cbctx;
- struct ldb_request *req;
- struct ldb_message *msg;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
int ret;
- if (!sysdb_handle_check_running(handle)) {
- DEBUG(2, ("Invalid request! Not running at this time.\n"));
- return EINVAL;
+ ret = sysdb_mod_group_member_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
}
- ctx = sysdb_handle_get_ctx(handle);
-
- cbctx = talloc_zero(handle, struct sysdb_cb_ctx);
- if (!cbctx) return ENOMEM;
+ tevent_req_done(req);
+}
- cbctx->fn = fn;
- cbctx->pvt = pvt;
+static void sysdb_remove_group_member_l_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
- /* Add the member_dn as a member of the group */
- msg = ldb_msg_new(cbctx);
- if(msg == NULL) return ENOMEM;
+ ret = sysdb_set_group_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
- msg->dn = sysdb_group_dn(ctx, cbctx, domain->name, group);
- if (!msg->dn) return ENOMEM;
+ tevent_req_done(req);
+}
- ret = add_string(msg, LDB_FLAG_MOD_DELETE, SYSDB_LEGACY_MEMBER, member);
- if (ret != LDB_SUCCESS) return ENOMEM;
+int sysdb_remove_group_member_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
- ret = ldb_build_mod_req(&req, ctx->ldb, cbctx, msg,
- NULL, cbctx, sysdb_op_callback, NULL);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
- return sysdb_error_to_errno(ret);
- }
- ret = ldb_request(ctx->ldb, req);
- if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+/* ======================================================================= */
- return EOK;
-}
+static void sysdb_set_cached_password_done(struct tevent_req *subreq);
-int sysdb_set_cached_password(struct sysdb_handle *handle,
- struct sss_domain_info *domain,
- const char *user,
- const char *password,
- sysdb_callback_t fn, void *pvt)
+struct tevent_req *sysdb_set_cached_password_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *user,
+ const char *password)
{
- struct sysdb_ctx *ctx;
+ struct tevent_req *req, *subreq;
+ struct sysdb_op_state *state;
struct sysdb_attrs *attrs;
char *hash = NULL;
char *salt;
int ret;
- ctx = sysdb_handle_get_ctx(handle);
- if (!ctx) return EFAULT;
+ req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->ignore_not_found = false;
+ state->ldbreply = NULL;
- ret = s3crypt_gen_salt(handle, &salt);
+ ret = s3crypt_gen_salt(state, &salt);
if (ret) {
DEBUG(4, ("Failed to generate random salt.\n"));
- return ret;
+ goto fail;
}
- ret = s3crypt_sha512(handle, password, salt, &hash);
+ ret = s3crypt_sha512(state, password, salt, &hash);
if (ret) {
DEBUG(4, ("Failed to create password hash.\n"));
- return ret;
+ goto fail;
}
- attrs = sysdb_new_attrs(handle);
+ attrs = sysdb_new_attrs(state);
if (!attrs) {
- return ENOMEM;
+ ERROR_OUT(ret, ENOMEM, fail);
}
ret = sysdb_attrs_add_string(attrs, SYSDB_CACHEDPWD, hash);
- if (ret) return ret;
+ if (ret) goto fail;
/* FIXME: should we use a different attribute for chache passwords ?? */
ret = sysdb_attrs_add_long(attrs, "lastCachedPasswordChange",
(long)time(NULL));
- if (ret) return ret;
+ if (ret) goto fail;
- ret = sysdb_set_user_attr(handle, domain, user, attrs, fn, pvt);
- if (ret) return ret;
+ subreq = sysdb_set_user_attr_send(state, ev, handle, domain,
+ user, attrs, SYSDB_MOD_REP);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_set_cached_password_done, req);
- return EOK;
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
}
+
+static void sysdb_set_cached_password_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+
+ ret = sysdb_set_user_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_set_cached_password_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
diff --git a/server/db/sysdb_private.h b/server/db/sysdb_private.h
index 8c10d9519..d15ec370a 100644
--- a/server/db/sysdb_private.h
+++ b/server/db/sysdb_private.h
@@ -68,15 +68,36 @@
#include "db/sysdb.h"
-struct sysdb_handle;
+struct sysdb_handle {
+ struct sysdb_handle *prev;
+ struct sysdb_handle *next;
+
+ struct sysdb_ctx *ctx;
+ struct tevent_req *subreq;
+
+ bool transaction_active;
+};
struct sysdb_ctx {
struct tevent_context *ev;
struct ldb_context *ldb;
char *ldb_file;
+
struct sysdb_handle *queue;
};
-bool sysdb_handle_check_running(struct sysdb_handle *handle);
+/* An operation blocks the transaction queue as well, but does not
+ * start a transaction, normally useful only for search type calls.
+ * do *NOT* call within a transaction you'll deadlock sysdb.
+ * Also make sure to free the handle as soon as the operation is
+ * finished to avoid stalling or potentially deadlocking sysdb */
+
+struct tevent_req *sysdb_operation_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_ctx *ctx);
+int sysdb_operation_recv(struct tevent_req *req, TALLOC_CTX *memctx,
+ struct sysdb_handle **handle);
+
+void sysdb_operation_done(struct sysdb_handle *handle);
#endif /* __INT_SYS_DB_H__ */
diff --git a/server/db/sysdb_req.c b/server/db/sysdb_req.c
deleted file mode 100644
index a768fefb2..000000000
--- a/server/db/sysdb_req.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- SSSD
-
- System Database
-
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <time.h>
-#include "util/util.h"
-#include "util/dlinklist.h"
-#include "db/sysdb_private.h"
-#include "ldb.h"
-
-struct sysdb_handle {
- struct sysdb_handle *next, *prev;
- struct sysdb_ctx *ctx;
- sysdb_fn_t fn;
- void *pvt;
- int status;
- bool transaction_active;
-};
-
-bool sysdb_handle_check_running(struct sysdb_handle *handle)
-{
- if (handle->ctx->queue == handle) return true;
- return false;
-}
-
-struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *handle)
-{
- return handle->ctx;
-}
-
-static void sysdb_queue_run(struct tevent_context *ev,
- struct tevent_timer *te,
- struct timeval tv, void *ptr)
-{
- struct sysdb_handle *handle = talloc_get_type(ptr, struct sysdb_handle);
-
- if (handle != handle->ctx->queue) abort();
-
- handle->fn(handle, handle->pvt);
-}
-
-static int sysdb_queue_schedule(struct sysdb_handle *handle)
-{
- struct tevent_timer *te = NULL;
- struct timeval tv;
-
- /* call it asap */
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- te = tevent_add_timer(handle->ctx->ev, handle, tv, sysdb_queue_run, handle);
- if (te == NULL) {
- return EIO;
- }
-
- return EOK;
-}
-
-static int sysdb_enqueue(struct sysdb_handle *handle)
-{
- int ret = EOK;
-
- DLIST_ADD_END(handle->ctx->queue, handle, struct sysdb_handle *);
-
- if (handle->ctx->queue == handle) {
- ret = sysdb_queue_schedule(handle);
- }
-
- return ret;
-}
-
-static void sysdb_transaction_end(struct sysdb_handle *handle);
-
-static int sysdb_handle_destructor(void *ptr)
-{
- struct sysdb_handle *handle;
- int ret;
-
- handle = talloc_get_type(ptr, struct sysdb_handle);
-
- if (handle->ctx->queue != handle) {
- DLIST_REMOVE(handle->ctx->queue, handle);
- return 0;
- }
-
- /* handle is the currently running operation or
- * scheduled to run operation */
-
- if (handle->transaction_active) {
- /* freeing before the transaction is complete */
- handle->status = ETIMEDOUT;
- sysdb_transaction_end(handle);
- }
-
- DLIST_REMOVE(handle->ctx->queue, handle);
-
- /* make sure we schedule the next in line if any */
- if (handle->ctx->queue) {
- ret = sysdb_queue_schedule(handle->ctx->queue);
- if (ret != EOK) abort();
- }
-
- return 0;
-}
-
-static struct sysdb_handle *sysdb_new_req(TALLOC_CTX *memctx,
- struct sysdb_ctx *ctx,
- sysdb_fn_t fn, void *pvt)
-{
- struct sysdb_handle *handle;
-
- handle = talloc_zero(memctx, struct sysdb_handle);
- if (!handle) return NULL;
-
- handle->ctx = ctx;
- handle->fn = fn;
- handle->pvt = pvt;
-
- talloc_set_destructor((TALLOC_CTX *)handle, sysdb_handle_destructor);
-
- return handle;
-}
-
-static void sysdb_transaction_int(struct sysdb_handle *ihandle, void *pvt)
-{
- struct sysdb_handle *handle = talloc_get_type(pvt, struct sysdb_handle);
- int ret;
-
- /* first of all swap this internal handle with the real one on the queue
- * otherwise request_done() will later abort */
- DLIST_REMOVE(handle->ctx->queue, ihandle);
- DLIST_ADD(handle->ctx->queue, handle);
-
- if (ihandle->status != EOK) {
- handle->status = ihandle->status;
- handle->fn(handle, handle->pvt);
- return;
- }
-
- ret = ldb_transaction_start(handle->ctx->ldb);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
- handle->status = sysdb_error_to_errno(ret);
- }
- handle->transaction_active = true;
-
- handle->fn(handle, handle->pvt);
-}
-
-static void sysdb_transaction_end(struct sysdb_handle *handle)
-{
- int ret;
-
- if (handle->status == EOK) {
- ret = ldb_transaction_commit(handle->ctx->ldb);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
- }
- } else {
- DEBUG(4, ("Canceling transaction (%d[%s])\n",
- handle->status, strerror(handle->status)));
- ret = ldb_transaction_cancel(handle->ctx->ldb);
- if (ret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
- /* FIXME: abort() ? */
- }
- }
- handle->transaction_active = false;
-}
-
-int sysdb_transaction(TALLOC_CTX *memctx, struct sysdb_ctx *ctx,
- sysdb_fn_t fn, void *pvt)
-{
- struct sysdb_handle *handle, *ihandle;
-
- handle = sysdb_new_req(memctx, ctx, fn, pvt);
- if (!handle) return ENOMEM;
-
- ihandle = sysdb_new_req(handle, ctx, sysdb_transaction_int, handle);
- if (!ihandle) {
- talloc_free(ihandle);
- return ENOMEM;
- }
-
- return sysdb_enqueue(ihandle);
-}
-
-void sysdb_transaction_done(struct sysdb_handle *handle, int status)
-{
- int ret;
-
- if (handle->ctx->queue != handle) abort();
- if (!handle->transaction_active) abort();
-
- handle->status = status;
-
- sysdb_transaction_end(handle);
-
- DLIST_REMOVE(handle->ctx->queue, handle);
-
- if (handle->ctx->queue) {
- ret = sysdb_queue_schedule(handle->ctx->queue);
- if (ret != EOK) abort();
- }
-
- talloc_free(handle);
-}
-
-int sysdb_operation(TALLOC_CTX *memctx, struct sysdb_ctx *ctx,
- sysdb_fn_t fn, void *pvt)
-{
- struct sysdb_handle *handle;
-
- handle = sysdb_new_req(memctx, ctx, fn, pvt);
- if (!handle) return ENOMEM;
-
- return sysdb_enqueue(handle);
-}
-
-void sysdb_operation_done(struct sysdb_handle *handle)
-{
- int ret;
-
- if (handle->ctx->queue != handle) abort();
-
- DLIST_REMOVE(handle->ctx->queue, handle);
-
- if (handle->ctx->queue) {
- ret = sysdb_queue_schedule(handle->ctx->queue);
- if (ret != EOK) abort();
- }
-
- talloc_free(handle);
-}
-
diff --git a/server/db/sysdb_search.c b/server/db/sysdb_search.c
index 7e0aed8f2..5ee9f8c0d 100644
--- a/server/db/sysdb_search.c
+++ b/server/db/sysdb_search.c
@@ -29,6 +29,7 @@ struct sysdb_search_ctx;
typedef void (*gen_callback)(struct sysdb_search_ctx *);
struct sysdb_search_ctx {
+ struct tevent_context *ev;
struct sysdb_ctx *ctx;
struct sysdb_handle *handle;
@@ -46,6 +47,8 @@ struct sysdb_search_ctx {
struct ldb_result *res;
const char **attrs;
+
+ int error;
};
static struct sysdb_search_ctx *init_src_ctx(TALLOC_CTX *mem_ctx,
@@ -61,6 +64,7 @@ static struct sysdb_search_ctx *init_src_ctx(TALLOC_CTX *mem_ctx,
return NULL;
}
sctx->ctx = ctx;
+ sctx->ev = ctx->ev;
sctx->callback = fn;
sctx->ptr = ptr;
sctx->res = talloc_zero(sctx, struct ldb_result);
@@ -162,15 +166,19 @@ static int get_gen_callback(struct ldb_request *req,
/* users */
-static void user_search(struct sysdb_handle *handle, void *ptr)
+static void user_search(struct tevent_req *treq)
{
struct sysdb_search_ctx *sctx;
struct ldb_request *req;
struct ldb_dn *base_dn;
int ret;
- sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
- sctx->handle = handle;
+ sctx = tevent_req_callback_data(treq, struct sysdb_search_ctx);
+
+ ret = sysdb_operation_recv(treq, sctx, &sctx->handle);
+ if (ret) {
+ return request_error(sctx, ret);
+ }
base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
SYSDB_TMPL_USER_BASE, sctx->domain->name);
@@ -201,6 +209,7 @@ int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
{
static const char *attrs[] = SYSDB_PW_ATTRS;
struct sysdb_search_ctx *sctx;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -219,7 +228,15 @@ int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
sctx->attrs = attrs;
- return sysdb_operation(mem_ctx, ctx, user_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, user_search, sctx);
+
+ return EOK;
}
int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
@@ -231,6 +248,7 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
static const char *attrs[] = SYSDB_PW_ATTRS;
struct sysdb_search_ctx *sctx;
unsigned long int filter_uid = uid;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -249,7 +267,15 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
sctx->attrs = attrs;
- return sysdb_operation(mem_ctx, ctx, user_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, user_search, sctx);
+
+ return EOK;
}
int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
@@ -260,6 +286,7 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
{
static const char *attrs[] = SYSDB_PW_ATTRS;
struct sysdb_search_ctx *sctx;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -277,7 +304,15 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
sctx->attrs = attrs;
- return sysdb_operation(mem_ctx, ctx, user_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, user_search, sctx);
+
+ return EOK;
}
/* groups */
@@ -478,7 +513,7 @@ static int get_grp_callback(struct ldb_request *req,
return LDB_SUCCESS;
}
-static void grp_search(struct sysdb_handle *handle, void *ptr)
+static void grp_search(struct tevent_req *treq)
{
struct sysdb_search_ctx *sctx;
static const char *attrs[] = SYSDB_GRSRC_ATTRS;
@@ -486,8 +521,12 @@ static void grp_search(struct sysdb_handle *handle, void *ptr)
struct ldb_dn *base_dn;
int ret;
- sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
- sctx->handle = handle;
+ sctx = tevent_req_callback_data(treq, struct sysdb_search_ctx);
+
+ ret = sysdb_operation_recv(treq, sctx, &sctx->handle);
+ if (ret) {
+ return request_error(sctx, ret);
+ }
if (sctx->domain->mpg) {
base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
@@ -522,6 +561,7 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
sysdb_callback_t fn, void *ptr)
{
struct sysdb_search_ctx *sctx;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -542,7 +582,15 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- return sysdb_operation(mem_ctx, ctx, grp_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, grp_search, sctx);
+
+ return EOK;
}
int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
@@ -552,6 +600,7 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
sysdb_callback_t fn, void *ptr)
{
struct sysdb_search_ctx *sctx;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -576,7 +625,15 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- return sysdb_operation(mem_ctx, ctx, grp_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, grp_search, sctx);
+
+ return EOK;
}
int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
@@ -585,6 +642,7 @@ int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
sysdb_callback_t fn, void *ptr)
{
struct sysdb_search_ctx *sctx;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -601,7 +659,15 @@ int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
sctx->expression = SYSDB_GRENT_FILTER;
}
- return sysdb_operation(mem_ctx, ctx, grp_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, grp_search, sctx);
+
+ return EOK;
}
static void initgr_mem_legacy(struct sysdb_search_ctx *sctx)
@@ -720,7 +786,7 @@ static void initgr_mem_search(struct sysdb_search_ctx *sctx)
}
}
-static void initgr_search(struct sysdb_handle *handle, void *ptr)
+static void initgr_search(struct tevent_req *treq)
{
struct sysdb_search_ctx *sctx;
static const char *attrs[] = SYSDB_PW_ATTRS;
@@ -728,8 +794,12 @@ static void initgr_search(struct sysdb_handle *handle, void *ptr)
struct ldb_dn *base_dn;
int ret;
- sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
- sctx->handle = handle;
+ sctx = tevent_req_callback_data(treq, struct sysdb_search_ctx);
+
+ ret = sysdb_operation_recv(treq, sctx, &sctx->handle);
+ if (ret) {
+ return request_error(sctx, ret);
+ }
if (sctx->domain->legacy) {
sctx->gen_aux_fn = initgr_mem_legacy;
@@ -765,6 +835,7 @@ int sysdb_initgroups(TALLOC_CTX *mem_ctx,
sysdb_callback_t fn, void *ptr)
{
struct sysdb_search_ctx *sctx;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -781,7 +852,15 @@ int sysdb_initgroups(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- return sysdb_operation(mem_ctx, ctx, initgr_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, initgr_search, sctx);
+
+ return EOK;
}
int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
@@ -792,6 +871,7 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
sysdb_callback_t fn, void *ptr)
{
struct sysdb_search_ctx *sctx;
+ struct tevent_req *req;
if (!domain) {
return EINVAL;
@@ -810,5 +890,13 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx,
sctx->attrs = attributes;
- return sysdb_operation(mem_ctx, ctx, user_search, sctx);
+ req = sysdb_operation_send(mem_ctx, ctx->ev, ctx);
+ if (!req) {
+ talloc_free(sctx);
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, user_search, sctx);
+
+ return EOK;
}
diff --git a/server/ldb_modules/memberof.c b/server/ldb_modules/memberof.c
index 8b61549a9..bf1760bb0 100644
--- a/server/ldb_modules/memberof.c
+++ b/server/ldb_modules/memberof.c
@@ -1487,6 +1487,7 @@ static int mbof_del_mod_callback(struct ldb_request *req,
LDB_ERR_OPERATIONS_ERROR);
case LDB_REPLY_REFERRAL:
/* ignore */
+ talloc_free(ares);
break;
case LDB_REPLY_DONE:
@@ -1499,7 +1500,6 @@ static int mbof_del_mod_callback(struct ldb_request *req,
}
}
- talloc_free(ares);
return LDB_SUCCESS;
}
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index 89e301aae..5d1a81f08 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -656,6 +656,7 @@ done:
}
struct sdap_pw_cache {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
struct sdap_req *lr;
};
@@ -665,30 +666,72 @@ static void sdap_reply(struct be_req *req, int ret, char *errstr)
req->fn(req, ret, errstr);
}
-static void sdap_cache_pw_callback(void *pvt, int error,
- struct ldb_result *ignore)
+
+static void sdap_cache_pw_done(struct tevent_req *req)
{
- struct sdap_pw_cache *data = talloc_get_type(pvt, struct sdap_pw_cache);
- if (error != EOK) {
+ struct sdap_pw_cache *data = tevent_req_callback_data(req,
+ struct sdap_pw_cache);
+ int ret;
+
+ ret = sysdb_transaction_commit_recv(req);
+ if (ret) {
DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
- error, strerror(error)));
+ ret, strerror(ret)));
+ }
+
+ /* password caching failures are not fatal errors */
+ sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
+}
+
+static void sdap_cache_pw_callback(struct tevent_req *subreq)
+{
+ struct sdap_pw_cache *data = tevent_req_callback_data(subreq,
+ struct sdap_pw_cache);
+ struct tevent_req *req;
+ int ret;
+
+ ret = sysdb_set_cached_password_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ ret = ENOMEM;
+ goto fail;
}
+ tevent_req_set_callback(req, sdap_cache_pw_done, data);
+
+ return;
+
+fail:
+ DEBUG(2, ("Failed to cache password (%d)[%s]!?\n", ret, strerror(ret)));
- sysdb_transaction_done(data->handle, error);
+ /* free transaction */
+ talloc_zfree(data->handle);
/* password caching failures are not fatal errors */
sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
}
-static void sdap_cache_pw_op(struct sysdb_handle *handle, void *pvt)
+static void sdap_cache_pw_op(struct tevent_req *req)
{
- struct sdap_pw_cache *data = talloc_get_type(pvt, struct sdap_pw_cache);
+ struct sdap_pw_cache *data = tevent_req_callback_data(req,
+ struct sdap_pw_cache);
+ struct tevent_req *subreq;
struct pam_data *pd;
const char *username;
char *password;
int ret;
- data->handle = handle;
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
+ sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
+ return;
+ }
pd = data->lr->pd;
username = pd->user;
@@ -715,21 +758,20 @@ static void sdap_cache_pw_op(struct sysdb_handle *handle, void *pvt)
return;
}
- ret = sysdb_set_cached_password(handle,
- data->lr->req->be_ctx->domain,
- username,
- password,
- sdap_cache_pw_callback, data);
- if (ret != EOK) {
+ subreq = sysdb_set_cached_password_send(data, data->ev, data->handle,
+ data->lr->req->be_ctx->domain,
+ username, password);
+ if (!subreq) {
/* password caching failures are not fatal errors */
sdap_reply(data->lr->req, data->lr->pd->pam_status, NULL);
}
+ tevent_req_set_callback(subreq, sdap_cache_pw_callback, data);
}
static void sdap_cache_password(struct sdap_req *lr)
{
struct sdap_pw_cache *data;
- int ret;
+ struct tevent_req *req;
data = talloc_zero(lr, struct sdap_pw_cache);
if (!data) {
@@ -739,16 +781,18 @@ static void sdap_cache_password(struct sdap_req *lr)
return;
}
data->lr = lr;
+ data->ev = lr->req->be_ctx->ev;
- ret = sysdb_transaction(data, lr->req->be_ctx->sysdb,
- sdap_cache_pw_op, data);
-
- if (ret != EOK) {
+ req = sysdb_transaction_send(data, data->ev,
+ lr->req->be_ctx->sysdb);
+ if (!req) {
DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
+ ENOMEM, strerror(ENOMEM)));
/* password caching failures are not fatal errors */
sdap_reply(data->lr->req, lr->pd->pam_status, NULL);
}
+
+ tevent_req_set_callback(req, sdap_cache_pw_op, data);
}
static void sdap_shutdown(struct be_req *req)
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index 6870cef16..9bbfdbd6f 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -261,6 +261,10 @@ static void proxy_pam_handler(struct be_req *req) {
}
struct proxy_data {
+ struct tevent_context *ev;
+ /* FIXME: should not store it here */
+ struct tevent_req *treq;
+
struct sysdb_handle *handle;
struct proxy_ctx *ctx;
struct be_req *req;
@@ -278,44 +282,85 @@ struct proxy_data {
struct ldb_dn *dn;
sysdb_callback_t next_fn;
+
+ const char *err;
};
static void proxy_reply(struct be_req *req, int error, const char *errstr)
{
+ if (error && !errstr) errstr = "Operation failed";
return req->fn(req, error, errstr);
}
-static void cache_pw_return(void *pvt, int error, struct ldb_result *ignore)
+static void proxy_req_done(struct tevent_req *req)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct proxy_data *data = tevent_req_callback_data(req, struct proxy_data);
+ int ret;
- if (error != EOK) {
+ ret = sysdb_transaction_commit_recv(req);
+ if (ret) {
DEBUG(2, ("Failed to cache password (%d)[%s]!?\n",
- error, strerror(error)));
+ ret, strerror(ret)));
}
- sysdb_transaction_done(data->handle, error);
+ /* password caching failures are not fatal errors */
+ proxy_reply(data->req, EOK, data->err);
+}
+
+static void cache_pw_return(struct tevent_req *subreq)
+{
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
+ struct tevent_req *req;
+ int ret;
+
+ ret = sysdb_set_cached_password_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, proxy_req_done, data);
+
+ return;
+
+fail:
+ DEBUG(2, ("Failed to cache password (%d)[%s]!?\n", ret, strerror(ret)));
+
+ /* free transaction */
+ talloc_zfree(data->handle);
/* password caching failures are not fatal errors */
- return proxy_reply(data->req, EOK, NULL);
+ proxy_reply(data->req, EOK, NULL);
}
-static void cache_pw_op(struct sysdb_handle *handle, void *pvt)
+static void cache_pw_op(struct tevent_req *req)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
+ struct tevent_req *subreq;
int ret;
- data->handle = handle;
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ /* password caching failures are not fatal errors */
+ return proxy_reply(data->req, EOK, NULL);
+ }
- ret = sysdb_set_cached_password(handle,
- data->req->be_ctx->domain,
- data->pwd->pw_name,
- data->pwd->pw_passwd,
- cache_pw_return, data);
- if (ret != EOK) {
+ subreq = sysdb_set_cached_password_send(data, data->ev, data->handle,
+ data->req->be_ctx->domain,
+ data->pwd->pw_name,
+ data->pwd->pw_passwd);
+ if (!subreq) {
/* password caching failures are not fatal errors */
proxy_reply(data->req, EOK, NULL);
}
+ tevent_req_set_callback(subreq, cache_pw_return, data);
}
static void cache_password(struct be_req *req,
@@ -324,7 +369,7 @@ static void cache_password(struct be_req *req,
{
struct proxy_data *data;
struct proxy_ctx *ctx;
- int ret;
+ struct tevent_req *treq;
ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
@@ -348,82 +393,165 @@ static void cache_password(struct be_req *req,
talloc_set_destructor((TALLOC_CTX *)data->pwd->pw_passwd,
password_destructor);
- ret = sysdb_transaction(data, req->be_ctx->sysdb, cache_pw_op, data);
+ data->ev = req->be_ctx->ev;
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
/* password caching failures are not fatal errors */
return proxy_reply(req, EOK, NULL);
}
+
+ tevent_req_set_callback(treq, cache_pw_op, data);
}
static void proxy_return(void *pvt, int error, struct ldb_result *ignore)
{
struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- const char *err = "Success";
+ struct tevent_req *req;
+ int ret;
- if (error != EOK) err = "Operation failed";
+ if (error != EOK) {
+ data->err = "Operation failed";
+ ret = error;
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ data->err = "Operation failed";
+ ret = ENOMEM;
+ goto fail;
+ }
- sysdb_transaction_done(data->handle, error);
- return proxy_reply(data->req, error, err);
+ tevent_req_set_callback(req, proxy_req_done, data);
+
+ return;
+
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
+
+ /* password caching failures are not fatal errors */
+ proxy_reply(data->req, EOK, NULL);
}
-static void del_db_entry(struct sysdb_handle *handle, void *pvt)
+static void del_db_entry_done(struct tevent_req *subreq);
+static void del_db_entry(struct tevent_req *req)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- struct sysdb_ctx *ctx;
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
+ struct tevent_req *subreq;
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
+ }
- ret = sysdb_delete_entry(handle, data->dn, data->next_fn, data);
- if (ret != EOK) {
- proxy_return(data, ret, NULL);
+ subreq = sysdb_delete_entry_send(data, data->ev, data->handle, data->dn);
+ if (!subreq) {
+ proxy_return(data, ENOMEM, NULL);
}
+ tevent_req_set_callback(subreq, del_db_entry_done, data);
}
-static void del_pw_uid(struct sysdb_handle *handle, void *pvt)
+static void del_db_entry_done(struct tevent_req *subreq)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- struct sysdb_ctx *ctx;
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_delete_entry_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ return proxy_return(data, ret, NULL);
+ }
- ret = sysdb_delete_user_by_uid(handle,
- data->req->be_ctx->domain,
- data->pwd->pw_uid,
- data->next_fn, data);
- if (ret != EOK) {
- proxy_return(data, ret, NULL);
+ data->next_fn(data, EOK, NULL);
+}
+
+static void del_pw_uid_done(struct tevent_req *subreq);
+static void del_pw_uid(struct tevent_req *req)
+{
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
+ struct tevent_req *subreq;
+ int ret;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
}
+
+ subreq = sysdb_delete_user_by_uid_send(data, data->ev, data->handle,
+ data->req->be_ctx->domain,
+ data->pwd->pw_uid);
+ if (!subreq) {
+ proxy_return(data, ENOMEM, NULL);
+ }
+ tevent_req_set_callback(subreq, del_pw_uid_done, data);
}
-static void set_pw_name(struct sysdb_handle *handle, void *pvt)
+static void del_pw_uid_done(struct tevent_req *subreq)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- struct sysdb_ctx *ctx;
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_delete_user_by_uid_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ return proxy_return(data, ret, NULL);
+ }
- ret = sysdb_legacy_store_user(handle, data->req->be_ctx->domain,
- data->pwd->pw_name, data->pwd->pw_passwd,
- data->pwd->pw_uid, data->pwd->pw_gid,
- data->pwd->pw_gecos, data->pwd->pw_dir,
- data->pwd->pw_shell,
- data->next_fn, data);
- if (ret != EOK) {
+ data->next_fn(data, EOK, NULL);
+}
+
+static void set_pw_name_done(struct tevent_req *subreq);
+
+static void set_pw_name(struct tevent_req *req)
+{
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
+ struct tevent_req *subreq;
+ int ret;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
+ }
+
+ subreq = sysdb_store_user_send(data, data->ev, data->handle,
+ data->req->be_ctx->domain,
+ data->pwd->pw_name, data->pwd->pw_passwd,
+ data->pwd->pw_uid, data->pwd->pw_gid,
+ data->pwd->pw_gecos, data->pwd->pw_dir,
+ data->pwd->pw_shell);
+ if (!subreq) {
proxy_return(data, ret, NULL);
+ return;
}
+ tevent_req_set_callback(subreq, set_pw_name_done, data);
}
+static void set_pw_name_done(struct tevent_req *subreq)
+{
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
+ int ret;
+
+ ret = sysdb_store_user_recv(subreq);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
+ }
+
+ data->next_fn(data, EOK, NULL);
+}
+
+
static void get_pw_name(struct be_req *req, char *name)
{
+ struct tevent_req *treq = NULL;
struct proxy_ctx *ctx;
enum nss_status status;
struct proxy_data *data;
@@ -436,6 +564,7 @@ static void get_pw_name(struct be_req *req, char *name)
return proxy_reply(req, ENOMEM, "Out of memory");
data->req = req;
data->ctx = ctx;
+ data->ev = req->be_ctx->ev;
data->next_fn = proxy_return;
data->pwd = talloc(data, struct passwd);
if (!data->pwd)
@@ -456,18 +585,29 @@ static void get_pw_name(struct be_req *req, char *name)
if (!data->dn)
return proxy_reply(req, ENOMEM, "Out of memory");
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
case NSS_STATUS_SUCCESS:
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
/* FIXME: verify user does not have uid=0 or gid=0 as these are invalid
* values */
if (data->pwd->pw_uid == 0 || data->pwd->pw_gid == 0) {
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
}
- ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data);
+ tevent_req_set_callback(treq, set_pw_name, data);
break;
case NSS_STATUS_UNAVAIL:
@@ -480,16 +620,11 @@ static void get_pw_name(struct be_req *req, char *name)
DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n", name, status));
return proxy_reply(req, EOK, "Operation failed");
}
-
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
- return proxy_reply(req, ret, "Operation failed");
- }
}
static void get_pw_uid(struct be_req *req, uid_t uid)
{
+ struct tevent_req *treq = NULL;
struct proxy_ctx *ctx;
enum nss_status status;
struct proxy_data *data;
@@ -502,6 +637,7 @@ static void get_pw_uid(struct be_req *req, uid_t uid)
return proxy_reply(req, ENOMEM, "Out of memory");
data->req = req;
data->ctx = ctx;
+ data->ev = req->be_ctx->ev;
data->next_fn = proxy_return;
data->pwd = talloc(data, struct passwd);
if (!data->pwd)
@@ -518,21 +654,32 @@ static void get_pw_uid(struct be_req *req, uid_t uid)
switch (status) {
case NSS_STATUS_NOTFOUND:
data->pwd->pw_uid = uid;
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_pw_uid, data);
+
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
+ tevent_req_set_callback(treq, del_pw_uid, data);
break;
case NSS_STATUS_SUCCESS:
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
/* FIXME: verify user does not have gid=0 as these are invalid values */
if (data->pwd->pw_gid == 0) {
data->dn = sysdb_user_dn(req->be_ctx->sysdb, data,
req->be_ctx->domain->name,
data->pwd->pw_name);
- ret = sysdb_transaction(data, req->be_ctx->sysdb,
- del_db_entry, data);
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
}
- ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data);
+ tevent_req_set_callback(treq, set_pw_name, data);
break;
case NSS_STATUS_UNAVAIL:
@@ -546,37 +693,26 @@ static void get_pw_uid(struct be_req *req, uid_t uid)
(unsigned long)uid, ret, strerror(ret)));
return proxy_reply(req, ret, "Operation failed");
}
-
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
- return proxy_reply(req, ret, "Operation failed");
- }
}
#define MAX_BUF_SIZE 1024*1024 /* max 1MiB */
-static void get_pw_entry(struct sysdb_handle *handle, void *pvt);
-
-static void get_next_pw_entry(void *pvt, int error, struct ldb_result *ignore)
+static void get_pw_entry_store_done(struct tevent_req *subreq);
+static void get_pw_entry(struct tevent_req *req)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
-
- if (error != EOK) proxy_return(data, error, NULL);
-
- get_pw_entry(data->handle, data);
-}
-
-static void get_pw_entry(struct sysdb_handle *handle, void *pvt)
-{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
enum nss_status status;
- struct sysdb_ctx *ctx;
+ struct tevent_req *subreq;
char *newb;
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ data->treq = req;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
+ }
retry:
status = data->ctx->ops.getpwent_r(data->pwd,
@@ -611,20 +747,20 @@ retry:
goto retry; /* skip */
}
- ret = sysdb_legacy_store_user(handle, data->req->be_ctx->domain,
- data->pwd->pw_name,
- data->pwd->pw_passwd,
- data->pwd->pw_uid,
- data->pwd->pw_gid,
- data->pwd->pw_gecos,
- data->pwd->pw_dir,
- data->pwd->pw_shell,
- get_next_pw_entry, data);
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
- data->pwd->pw_name, ret, strerror(ret)));
- proxy_return(data, ret, NULL);
+ subreq = sysdb_store_user_send(data, data->ev, data->handle,
+ data->req->be_ctx->domain,
+ data->pwd->pw_name,
+ data->pwd->pw_passwd,
+ data->pwd->pw_uid,
+ data->pwd->pw_gid,
+ data->pwd->pw_gecos,
+ data->pwd->pw_dir,
+ data->pwd->pw_shell);
+ if (!subreq) {
+ proxy_return(data, ENOMEM, NULL);
+ return;
}
+ tevent_req_set_callback(subreq, get_pw_entry_store_done, data);
break;
case NSS_STATUS_UNAVAIL:
@@ -640,12 +776,30 @@ retry:
}
}
+static void get_pw_entry_store_done(struct tevent_req *subreq)
+{
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
+ int ret;
+
+ ret = sysdb_store_user_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->pwd->pw_name, ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ return;
+ }
+
+ get_pw_entry(data->treq);
+}
+
static void enum_users(struct be_req *req)
{
+ struct tevent_req *treq = NULL;
struct proxy_ctx *ctx;
enum nss_status status;
struct proxy_data *data;
- int ret;
ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
@@ -654,6 +808,7 @@ static void enum_users(struct be_req *req)
return proxy_reply(req, ENOMEM, "Out of memory");
data->req = req;
data->ctx = ctx;
+ data->ev = req->be_ctx->ev;
data->next_fn = proxy_return;
data->pwd = talloc(data, struct passwd);
if (!data->pwd)
@@ -668,53 +823,96 @@ static void enum_users(struct be_req *req)
if (status != NSS_STATUS_SUCCESS)
return proxy_reply(req, EIO, "Operation failed");
- ret = sysdb_transaction(data, req->be_ctx->sysdb, get_pw_entry, data);
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
- return proxy_reply(req, ret, "Operation failed");
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, "Operation failed");
}
+
+ tevent_req_set_callback(treq, get_pw_entry, data);
}
-static void del_gr_gid(struct sysdb_handle *handle, void *pvt)
+static void del_gr_gid_done(struct tevent_req *subreq);
+static void del_gr_gid(struct tevent_req *req)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- struct sysdb_ctx *ctx;
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
+ struct tevent_req *subreq;
+ int ret;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
+ }
+
+ subreq = sysdb_delete_group_by_gid_send(data, data->ev, data->handle,
+ data->req->be_ctx->domain,
+ data->grp->gr_gid);
+ if (!subreq) {
+ proxy_return(data, ENOMEM, NULL);
+ }
+ tevent_req_set_callback(subreq, del_gr_gid_done, data);
+}
+
+static void del_gr_gid_done(struct tevent_req *subreq)
+{
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
+ int ret;
+
+ ret = sysdb_delete_group_by_gid_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ return proxy_return(data, ret, NULL);
+ }
+
+ data->next_fn(data, EOK, NULL);
+}
+
+static void set_gr_name_done(struct tevent_req *subreq);
+
+static void set_gr_name(struct tevent_req *req)
+{
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
+ struct tevent_req *subreq;
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
+ }
- ret = sysdb_delete_group_by_gid(handle,
+ subreq = sysdb_store_group_send(data, data->ev, data->handle,
data->req->be_ctx->domain,
+ data->grp->gr_name,
data->grp->gr_gid,
- data->next_fn, data);
- if (ret != EOK) {
+ (const char **)data->grp->gr_mem);
+ if (!subreq) {
proxy_return(data, ret, NULL);
+ return;
}
+ tevent_req_set_callback(subreq, set_gr_name_done, data);
}
-static void set_gr_name(struct sysdb_handle *handle, void *pvt)
+static void set_gr_name_done(struct tevent_req *subreq)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- struct sysdb_ctx *ctx;
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
-
- ret = sysdb_legacy_store_group(handle, data->req->be_ctx->domain,
- data->grp->gr_name,
- data->grp->gr_gid,
- (const char **)data->grp->gr_mem,
- data->next_fn, data);
- if (ret != EOK) {
+ ret = sysdb_store_group_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
proxy_return(data, ret, NULL);
+ return;
}
+
+ data->next_fn(data, EOK, NULL);
}
static void get_gr_name(struct be_req *req, char *name)
{
+ struct tevent_req *treq = NULL;
struct proxy_ctx *ctx;
enum nss_status status;
struct proxy_data *data;
@@ -727,6 +925,7 @@ static void get_gr_name(struct be_req *req, char *name)
return proxy_reply(req, ENOMEM, "Out of memory");
data->req = req;
data->ctx = ctx;
+ data->ev = req->be_ctx->ev;
data->next_fn = proxy_return;
data->grp = talloc(data, struct group);
if (!data->grp)
@@ -747,17 +946,28 @@ static void get_gr_name(struct be_req *req, char *name)
if (!data->dn)
return proxy_reply(req, ENOMEM, "Out of memory");
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
case NSS_STATUS_SUCCESS:
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
/* FIXME: verify group does not have gid=0 as this is invalid */
if (data->grp->gr_gid == 0) {
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
}
- ret = sysdb_transaction(data, req->be_ctx->sysdb, set_gr_name, data);
+ tevent_req_set_callback(treq, set_gr_name, data);
break;
case NSS_STATUS_UNAVAIL:
@@ -771,16 +981,11 @@ static void get_gr_name(struct be_req *req, char *name)
name, ret, strerror(ret)));
return proxy_reply(req, ret, "Operation failed");
}
-
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
- return proxy_reply(req, ret, "Operation failed");
- }
}
static void get_gr_gid(struct be_req *req, gid_t gid)
{
+ struct tevent_req *treq = NULL;
struct proxy_ctx *ctx;
enum nss_status status;
struct proxy_data *data;
@@ -793,6 +998,7 @@ static void get_gr_gid(struct be_req *req, gid_t gid)
return proxy_reply(req, ENOMEM, "Out of memory");
data->req = req;
data->ctx = ctx;
+ data->ev = req->be_ctx->ev;
data->next_fn = proxy_return;
data->grp = talloc(data, struct group);
if (!data->grp)
@@ -809,21 +1015,32 @@ static void get_gr_gid(struct be_req *req, gid_t gid)
switch (status) {
case NSS_STATUS_NOTFOUND:
data->grp->gr_gid = gid;
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_gr_gid, data);
+
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
+ tevent_req_set_callback(treq, del_gr_gid, data);
break;
case NSS_STATUS_SUCCESS:
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
/* FIXME: verify group does not have gid=0 as this is invalid */
if (data->grp->gr_gid == 0) {
data->dn = sysdb_group_dn(req->be_ctx->sysdb, data,
req->be_ctx->domain->name,
data->grp->gr_name);
- ret = sysdb_transaction(data, req->be_ctx->sysdb,
- del_db_entry, data);
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
}
- ret = sysdb_transaction(data, req->be_ctx->sysdb, set_gr_name, data);
+ tevent_req_set_callback(treq, set_gr_name, data);
break;
case NSS_STATUS_UNAVAIL:
@@ -837,35 +1054,25 @@ static void get_gr_gid(struct be_req *req, gid_t gid)
(unsigned long)gid, ret, strerror(ret)));
return proxy_reply(req, ret, "Operation failed");
}
-
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
- return proxy_reply(req, ret, "Operation failed");
- }
}
-static void get_gr_entry(struct sysdb_handle *handle, void *pvt);
+static void get_gr_entry_store_done(struct tevent_req *subreq);
-static void get_next_gr_entry(void *pvt, int error, struct ldb_result *ignore)
+static void get_gr_entry(struct tevent_req *req)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
-
- if (error != EOK) proxy_return(data, error, NULL);
-
- get_gr_entry(data->handle, data);
-}
-
-static void get_gr_entry(struct sysdb_handle *handle, void *pvt)
-{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct proxy_data *data = tevent_req_callback_data(req,
+ struct proxy_data);
enum nss_status status;
- struct sysdb_ctx *ctx;
+ struct tevent_req *subreq;
char *newb;
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ data->treq = req;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret) {
+ return proxy_reply(data->req, ret, NULL);
+ }
retry:
status = data->ctx->ops.getgrent_r(data->grp,
@@ -898,16 +1105,15 @@ retry:
if (data->grp->gr_gid == 0) {
goto retry;
}
- ret = sysdb_legacy_store_group(handle, data->req->be_ctx->domain,
- data->grp->gr_name,
- data->grp->gr_gid,
- (const char **)data->grp->gr_mem,
- get_next_gr_entry, data);
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
- data->grp->gr_name, ret, strerror(ret)));
- proxy_return(data, ret, NULL);
+ subreq = sysdb_store_group_send(data, data->ev, data->handle,
+ data->req->be_ctx->domain,
+ data->grp->gr_name,
+ data->grp->gr_gid,
+ (const char **)data->grp->gr_mem);
+ if (!subreq) {
+ proxy_return(data, ENOMEM, NULL);
}
+ tevent_req_set_callback(subreq, get_gr_entry_store_done, data);
break;
case NSS_STATUS_UNAVAIL:
@@ -923,12 +1129,30 @@ retry:
}
}
+static void get_gr_entry_store_done(struct tevent_req *subreq)
+{
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
+ int ret;
+
+ ret = sysdb_store_group_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->grp->gr_name, ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ return;
+ }
+
+ get_gr_entry(data->treq);
+}
+
static void enum_groups(struct be_req *req)
{
+ struct tevent_req *treq = NULL;
struct proxy_ctx *ctx;
enum nss_status status;
struct proxy_data *data;
- int ret;
ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
@@ -937,6 +1161,7 @@ static void enum_groups(struct be_req *req)
return proxy_reply(req, ENOMEM, "Out of memory");
data->req = req;
data->ctx = ctx;
+ data->ev = req->be_ctx->ev;
data->next_fn = proxy_return;
data->grp = talloc(data, struct group);
if (!data->grp)
@@ -951,39 +1176,23 @@ static void enum_groups(struct be_req *req)
if (status != NSS_STATUS_SUCCESS)
return proxy_reply(req, EIO, "Operation failed");
- ret = sysdb_transaction(data, req->be_ctx->sysdb, get_gr_entry, data);
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
- return proxy_reply(req, ret, "Operation failed");
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, "Operation failed");
}
-}
-
-static void get_gid_entry(struct sysdb_handle *handle, void *pvt);
-
-static void get_next_gid_entry(void *pvt, int error, struct ldb_result *ignore)
-{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- if (error != EOK) proxy_return(data, error, NULL);
-
- get_gid_entry(data->handle, data);
+ tevent_req_set_callback(treq, get_gr_entry, data);
}
-static void get_gid_entry(struct sysdb_handle *handle, void *pvt)
+static void get_gid_entry_store_done(struct tevent_req *subreq);
+static void get_gid_entry_del_done(struct tevent_req *subreq);
+static void get_gid_entry(struct proxy_data *data)
{
- struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct tevent_req *subreq;
enum nss_status status;
- struct sysdb_ctx *ctx;
char *newb;
int ret;
- ctx = sysdb_handle_get_ctx(handle);
-
- /* all done */
- if (data->cur == data->num)
- return data->next_fn(data, EOK, NULL);
-
retry:
status = data->ctx->ops.getgrgid_r(data->groups[data->cur], data->grp,
data->buffer, data->buflen, &ret);
@@ -1005,31 +1214,29 @@ retry:
goto retry;
case NSS_STATUS_NOTFOUND:
- data->cur++;
DEBUG(4, ("gid [%lu] not found, removing group\n",
(unsigned long)(data->groups[data->cur])));
- ret = sysdb_delete_group_by_gid(handle, data->req->be_ctx->domain,
- data->groups[data->cur-1],
- get_next_gid_entry, data);
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
- data->grp->gr_name, ret, strerror(ret)));
- proxy_return(data, ret, NULL);
+ subreq = sysdb_delete_group_by_gid_send(data, data->ev,
+ data->handle,
+ data->req->be_ctx->domain,
+ data->groups[data->cur]);
+ if (!subreq) {
+ proxy_return(data, ENOMEM, NULL);
}
+ tevent_req_set_callback(subreq, get_gid_entry_del_done, data);
break;
case NSS_STATUS_SUCCESS:
data->cur++;
- ret = sysdb_legacy_store_group(handle, data->req->be_ctx->domain,
- data->grp->gr_name,
- data->grp->gr_gid,
- (const char **)data->grp->gr_mem,
- get_next_gid_entry, data);
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
- data->grp->gr_name, ret, strerror(ret)));
- proxy_return(data, ret, NULL);
+ subreq = sysdb_store_group_send(data, data->ev, data->handle,
+ data->req->be_ctx->domain,
+ data->grp->gr_name,
+ data->grp->gr_gid,
+ (const char **)data->grp->gr_mem);
+ if (!subreq) {
+ proxy_return(data, ENOMEM, NULL);
}
+ tevent_req_set_callback(subreq, get_gid_entry_store_done, data);
break;
default:
@@ -1039,6 +1246,56 @@ retry:
}
}
+static void get_gid_entry_del_done(struct tevent_req *subreq)
+{
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
+ int ret;
+
+ ret = sysdb_delete_group_by_gid_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->grp->gr_name, ret, strerror(ret)));
+ return proxy_return(data, ret, NULL);
+ }
+
+ data->cur++;
+
+ /* all done */
+ if (data->cur == data->num) {
+ return data->next_fn(data, EOK, NULL);
+ }
+
+ /* next item */
+ get_gid_entry(data);
+}
+
+static void get_gid_entry_store_done(struct tevent_req *subreq)
+{
+ struct proxy_data *data = tevent_req_callback_data(subreq,
+ struct proxy_data);
+ int ret;
+
+ ret = sysdb_store_group_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->grp->gr_name, ret, strerror(ret)));
+ return proxy_return(data, ret, NULL);
+ }
+
+ data->cur++;
+
+ /* all done */
+ if (data->cur == data->num) {
+ return data->next_fn(data, EOK, NULL);
+ }
+
+ /* next item */
+ get_gid_entry(data);
+}
+
static void get_user_groups(void *pvt, int error, struct ldb_result *ignore)
{
struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
@@ -1092,7 +1349,7 @@ retry:
data->num = start;
DEBUG(4, ("User [%s] appears to be member of %lu groups\n",
name, data->num));
- get_gid_entry(data->handle, data);
+ get_gid_entry(data);
break;
default:
@@ -1104,6 +1361,7 @@ retry:
static void get_initgr_user(struct be_req *req, char *name)
{
+ struct tevent_req *treq = NULL;
struct proxy_ctx *ctx;
enum nss_status status;
struct proxy_data *data;
@@ -1116,6 +1374,7 @@ static void get_initgr_user(struct be_req *req, char *name)
return proxy_reply(req, ENOMEM, "Out of memory");
data->req = req;
data->ctx = ctx;
+ data->ev = req->be_ctx->ev;
data->next_fn = proxy_return;
data->pwd = talloc(data, struct passwd);
if (!data->pwd)
@@ -1139,28 +1398,40 @@ static void get_initgr_user(struct be_req *req, char *name)
if (!data->dn)
return proxy_reply(req, ENOMEM, "Out of memory");
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
case NSS_STATUS_SUCCESS:
+ treq = sysdb_transaction_send(data, data->ev, req->be_ctx->sysdb);
+ if (!treq) {
+ return proxy_reply(req, ENOMEM, NULL);
+ }
+
/* FIXME: verify user does not have uid=0 or gid=0 as these are invalid
* values */
if (data->pwd->pw_uid == 0 || data->pwd->pw_gid == 0) {
- ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+
+ tevent_req_set_callback(treq, del_db_entry, data);
break;
}
if (ctx->ops.initgroups_dyn) {
data->next_fn = get_user_groups;
- ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data);
+
+ tevent_req_set_callback(treq, set_pw_name, data);
} else {
status = ctx->ops.setgrent();
if (status != NSS_STATUS_SUCCESS)
return proxy_reply(req, EIO, "Operation failed");
- ret = sysdb_transaction(data, req->be_ctx->sysdb, get_gr_entry, data);
- break;
+ tevent_req_set_callback(treq, get_gr_entry, data);
}
+ break;
case NSS_STATUS_UNAVAIL:
/* "remote" backend unavailable. Enter offline mode */
@@ -1173,12 +1444,6 @@ static void get_initgr_user(struct be_req *req, char *name)
name, ret, strerror(ret)));
return proxy_reply(req, ret, "Operation failed");
}
-
- if (ret != EOK) {
- DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
- ret, strerror(ret)));
- return proxy_reply(req, ret, "Operation failed");
- }
}
/* TODO: actually do check something */
diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c
index 15116a5e2..5c1fea993 100644
--- a/server/responder/pam/pam_LOCAL_domain.c
+++ b/server/responder/pam/pam_LOCAL_domain.c
@@ -47,6 +47,7 @@
struct LOCAL_request {
+ struct tevent_context *ev;
struct sysdb_ctx *dbctx;
struct sysdb_attrs *mod_attrs;
struct sysdb_handle *handle;
@@ -86,51 +87,89 @@ static void prepare_reply(struct LOCAL_request *lreq)
lreq->preq->callback(lreq->preq);
}
-static void set_user_attr_callback(void *pvt, int ldb_status, struct ldb_result *res)
+static void set_user_attr_done(struct tevent_req *req)
{
struct LOCAL_request *lreq;
+ int ret;
- DEBUG(4, ("entering set_user_attr_callback, status [%d][%s]\n",
- ldb_status, ldb_strerror(ldb_status)));
-
- lreq = talloc_get_type(pvt, struct LOCAL_request);
-
- sysdb_transaction_done(lreq->handle, sysdb_error_to_errno(ldb_status));
+ lreq = tevent_req_callback_data(req, struct LOCAL_request);
- NEQ_CHECK_OR_JUMP(ldb_status, LDB_SUCCESS, ("set_user_attr failed.\n"),
- lreq->error, sysdb_error_to_errno(ldb_status), done);
+ ret = sysdb_transaction_commit_recv(req);
+ if (ret) {
+ DEBUG(2, ("set_user_attr failed.\n"));
+ lreq->error =ret;
+ }
-done:
prepare_reply(lreq);
}
-static void set_user_attr_req(struct sysdb_handle *handle, void *pvt)
+static void set_user_attr_req_done(struct tevent_req *subreq);
+static void set_user_attr_req(struct tevent_req *req)
{
+ struct LOCAL_request *lreq = tevent_req_callback_data(req,
+ struct LOCAL_request);
+ struct tevent_req *subreq;
int ret;
- struct LOCAL_request *lreq;
DEBUG(4, ("entering set_user_attr_req\n"));
- lreq = talloc_get_type(pvt, struct LOCAL_request);
+ ret = sysdb_transaction_recv(req, lreq, &lreq->handle);
+ if (ret) {
+ lreq->error = ret;
+ return prepare_reply(lreq);
+ }
- lreq->handle = handle;
+ subreq = sysdb_set_user_attr_send(lreq, lreq->ev, lreq->handle,
+ lreq->preq->domain,
+ lreq->preq->pd->user,
+ lreq->mod_attrs, SYSDB_MOD_REP);
+ if (!subreq) {
+ /* cancel transaction */
+ talloc_zfree(lreq->handle);
+ lreq->error = ret;
+ return prepare_reply(lreq);
+ }
+ tevent_req_set_callback(subreq, set_user_attr_req_done, lreq);
+}
- ret = sysdb_set_user_attr(handle, lreq->preq->domain,
- lreq->preq->pd->user, lreq->mod_attrs,
- set_user_attr_callback, lreq);
- if (ret != EOK)
- sysdb_transaction_done(lreq->handle, ret);
+static void set_user_attr_req_done(struct tevent_req *subreq)
+{
+ struct LOCAL_request *lreq = tevent_req_callback_data(subreq,
+ struct LOCAL_request);
+ struct tevent_req *req;
+ int ret;
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_set_user_attr failed.\n"),
- lreq->error, ret, done);
+ ret = sysdb_set_user_attr_recv(subreq);
+ talloc_zfree(subreq);
+
+ DEBUG(4, ("set_user_attr_callback, status [%d][%s]\n", ret, strerror(ret)));
+
+ if (ret) {
+ lreq->error = ret;
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(lreq, lreq->ev, lreq->handle);
+ if (!req) {
+ lreq->error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, set_user_attr_done, lreq);
return;
-done:
+
+fail:
+ DEBUG(2, ("set_user_attr failed.\n"));
+
+ /* cancel transaction */
+ talloc_zfree(lreq->handle);
+
prepare_reply(lreq);
}
static void do_successful_login(struct LOCAL_request *lreq)
{
+ struct tevent_req *req;
int ret;
lreq->mod_attrs = sysdb_new_attrs(lreq);
@@ -146,9 +185,12 @@ static void do_successful_login(struct LOCAL_request *lreq)
NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
lreq->error, ret, done);
- ret = sysdb_transaction(lreq, lreq->dbctx, set_user_attr_req, lreq);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_transaction failed.\n"),
- lreq->error, ret, done);
+ req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
+ if (!req) {
+ lreq->error = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(req, set_user_attr_req, lreq);
return;
@@ -159,6 +201,7 @@ done:
static void do_failed_login(struct LOCAL_request *lreq)
{
+ struct tevent_req *req;
int ret;
int failedLoginAttempts;
struct pam_data *pd;
@@ -187,9 +230,13 @@ static void do_failed_login(struct LOCAL_request *lreq)
NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
lreq->error, ret, done);
- ret = sysdb_transaction(lreq, lreq->dbctx, set_user_attr_req, lreq);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_transaction failed.\n"),
- lreq->error, ret, done);
+ req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
+ if (!req) {
+ lreq->error = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(req, set_user_attr_req, lreq);
+
return;
done:
@@ -217,6 +264,7 @@ static void do_pam_acct_mgmt(struct LOCAL_request *lreq)
static void do_pam_chauthtok(struct LOCAL_request *lreq)
{
+ struct tevent_req *req;
int ret;
char *newauthtok;
char *salt;
@@ -261,9 +309,13 @@ static void do_pam_chauthtok(struct LOCAL_request *lreq)
NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
lreq->error, ret, done);
- ret = sysdb_transaction(lreq, lreq->dbctx, set_user_attr_req, lreq);
- NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_transaction failed.\n"),
- lreq->error, ret, done);
+ req = sysdb_transaction_send(lreq, lreq->ev, lreq->dbctx);
+ if (!req) {
+ lreq->error = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(req, set_user_attr_req, lreq);
+
return;
done:
@@ -408,6 +460,7 @@ int LOCAL_pam_handler(struct pam_auth_req *preq)
}
lreq->dbctx = preq->cctx->rctx->sysdb;
+ lreq->ev = preq->cctx->ev;
lreq->preq = preq;
preq->pd->pam_status = PAM_SUCCESS;
diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c
index bc8949620..ef7145cdd 100644
--- a/server/tests/sysdb-tests.c
+++ b/server/tests/sysdb-tests.c
@@ -26,7 +26,7 @@
#include <popt.h>
#include "util/util.h"
#include "confdb/confdb_setup.h"
-#include "db/sysdb.h"
+#include "db/sysdb_private.h"
struct sysdb_test_ctx {
struct sysdb_ctx *sysdb;
@@ -84,6 +84,23 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx)
return ret;
}
+ val[0] = "foo";
+ ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "provider", val);
+ if (ret != EOK) {
+ fail("Could not initialize domains placeholder");
+ talloc_free(test_ctx);
+ return ret;
+ }
+/*
+ val[0] = "TRUE";
+ ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "legacy", val);
+ if (ret != EOK) {
+ fail("Could not initialize LOCAL domain");
+ talloc_free(test_ctx);
+ return ret;
+ }
+*/
+/*
val[0] = "TRUE";
ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "magicPrivateGroups", val);
if (ret != EOK) {
@@ -91,7 +108,7 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx)
talloc_free(test_ctx);
return ret;
}
-
+*/
val[0] = "3";
ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "enumerate", val);
if (ret != EOK) {
@@ -121,6 +138,7 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx)
}
struct test_data {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
struct sss_domain_info *domain;
struct sysdb_test_ctx *ctx;
@@ -130,8 +148,6 @@ struct test_data {
uid_t uid;
gid_t gid;
- sysdb_callback_t next_fn;
-
bool finished;
int error;
@@ -166,191 +182,319 @@ static int test_loop(struct test_data *data)
return data->error;
}
-static void test_return(void *pvt, int error, struct ldb_result *ignore)
+static void test_req_done(struct tevent_req *req)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- const char *err = "Success";
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+
+ data->error = sysdb_transaction_commit_recv(req);
+ data->finished = true;
+}
+
+static void test_return(struct test_data *data, int error)
+{
+ struct tevent_req *req;
- if (error != EOK) err = "Operation failed";
+ if (error != EOK) {
+ goto fail;
+ }
- sysdb_transaction_done(data->handle, error);
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, test_req_done, data);
+
+ return;
+
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
data->error = error;
data->finished = true;
}
-static void test_add_user(struct sysdb_handle *handle, void *pvt)
+static void test_add_user_done(struct tevent_req *subreq);
+
+static void test_add_user(struct tevent_req *subreq)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
char *homedir;
char *gecos;
int ret;
+ ret = sysdb_transaction_recv(subreq, data, &data->handle);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ return test_return(data, ret);
+ }
+
homedir = talloc_asprintf(data, "/home/testuser%d", data->uid);
gecos = talloc_asprintf(data, "Test User %d", data->uid);
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ subreq = sysdb_add_user_send(data, data->ev, data->handle,
+ data->domain, data->username,
+ data->uid, data->gid,
+ gecos, homedir, "/bin/bash",
+ NULL);
+ if (!subreq) {
+ return test_return(data, ENOMEM);
+ }
+ tevent_req_set_callback(subreq, test_add_user_done, data);
+}
+
+static void test_add_user_done(struct tevent_req *subreq)
+{
+ struct test_data *data = tevent_req_callback_data(subreq, struct test_data);
+ int ret;
+
+ ret = sysdb_add_user_recv(subreq);
+ talloc_zfree(subreq);
- ret = sysdb_add_user(handle, data->domain,
- data->username, data->uid, data->gid,
- gecos, homedir, "/bin/bash",
- data->next_fn, data);
- if (ret != EOK) test_return(data, ret, NULL);
+ return test_return(data, ret);
}
-static void test_add_legacy_user(struct sysdb_handle *handle, void *pvt)
+static void test_store_user_done(struct tevent_req *subreq);
+
+static void test_store_user(struct tevent_req *req)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
char *homedir;
char *gecos;
int ret;
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return test_return(data, ret);
+ }
+
homedir = talloc_asprintf(data, "/home/testuser%d", data->uid);
gecos = talloc_asprintf(data, "Test User %d", data->uid);
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ subreq = sysdb_store_user_send(data, data->ev, data->handle,
+ data->domain, data->username, "x",
+ data->uid, data->gid,
+ gecos, homedir, "/bin/bash");
+ if (!subreq) {
+ test_return(data, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, test_store_user_done, data);
+}
- ret = sysdb_legacy_store_user(handle, data->domain, data->username, "x",
- data->uid, data->gid, gecos, homedir,
- "/bin/bash", data->next_fn, data);
- if (ret != EOK) test_return(data, ret, NULL);
+static void test_store_user_done(struct tevent_req *subreq)
+{
+ struct test_data *data = tevent_req_callback_data(subreq, struct test_data);
+ int ret;
+
+ ret = sysdb_store_user_recv(subreq);
+ talloc_zfree(subreq);
+
+ return test_return(data, ret);
}
-static void test_remove_user(struct sysdb_handle *handle, void *pvt)
+static void test_remove_user_done(struct tevent_req *subreq);
+
+static void test_remove_user(struct tevent_req *req)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
struct ldb_dn *user_dn;
+ struct tevent_req *subreq;
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return test_return(data, ret);
+ }
- user_dn = sysdb_user_dn(ctx, data, "LOCAL", data->username);
- if (!user_dn) return test_return(data, ENOMEM, NULL);
+ user_dn = sysdb_user_dn(data->ctx->sysdb, data, "LOCAL", data->username);
+ if (!user_dn) return test_return(data, ENOMEM);
- ret = sysdb_delete_entry(handle, user_dn, data->next_fn, data);
- if (ret != EOK) test_return(data, ret, NULL);
+ subreq = sysdb_delete_entry_send(data, data->ev, data->handle, user_dn);
+ if (!subreq) return test_return(data, ENOMEM);
+
+ tevent_req_set_callback(subreq, test_remove_user_done, data);
}
-static void test_remove_user_by_uid(struct sysdb_handle *handle, void *pvt)
+static void test_remove_user_done(struct tevent_req *subreq)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_delete_entry_recv(subreq);
+ talloc_zfree(subreq);
- ret = sysdb_delete_user_by_uid(handle, data->domain, data->uid,
- data->next_fn, data);
- if (ret != EOK) test_return(data, ret, NULL);
+ return test_return(data, ret);
}
-static void test_add_group(struct sysdb_handle *handle, void *pvt)
+static void test_remove_user_by_uid_done(struct tevent_req *subreq);
+
+static void test_remove_user_by_uid(struct tevent_req *req)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
-
- ret = sysdb_add_group(handle, data->domain,
- data->groupname, data->gid,
- data->next_fn, data);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
if (ret != EOK) {
- test_return(data, ret, NULL);
+ return test_return(data, ret);
}
+
+ subreq = sysdb_delete_user_by_uid_send(data,
+ data->ev, data->handle,
+ data->domain, data->uid);
+ if (!subreq) return test_return(data, ENOMEM);
+
+ tevent_req_set_callback(subreq, test_remove_user_by_uid_done, data);
}
-static void test_add_legacy_group(struct sysdb_handle *handle, void *pvt)
+static void test_remove_user_by_uid_done(struct tevent_req *subreq)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_delete_user_by_uid_recv(subreq);
+ talloc_zfree(subreq);
+
+ return test_return(data, ret);
+}
+
+static void test_add_group_done(struct tevent_req *subreq);
+
+static void test_add_group(struct tevent_req *req)
+{
+ struct test_data *data = tevent_req_callback_data(req,
+ struct test_data);
+ struct tevent_req *subreq;
+ int ret;
- ret = sysdb_legacy_store_group(handle, data->domain,
- data->groupname,
- data->gid, NULL,
- data->next_fn, data);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
if (ret != EOK) {
- test_return(data, ret, NULL);
+ return test_return(data, ret);
}
+
+ subreq = sysdb_add_group_send(data, data->ev, data->handle,
+ data->domain, data->groupname,
+ data->gid, NULL);
+ if (!subreq) {
+ test_return(data, ret);
+ }
+ tevent_req_set_callback(subreq, test_add_group_done, data);
}
-static void test_remove_group(struct sysdb_handle *handle, void *pvt)
+static void test_add_group_done(struct tevent_req *subreq)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
- struct ldb_dn *group_dn;
+ struct test_data *data = tevent_req_callback_data(subreq, struct test_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
-
- group_dn = sysdb_group_dn(ctx, data, "LOCAL", data->groupname);
- if (!group_dn) return test_return(data, ENOMEM, NULL);
+ ret = sysdb_add_group_recv(subreq);
+ talloc_zfree(subreq);
- ret = sysdb_delete_entry(handle, group_dn, data->next_fn, data);
- if (ret != EOK) test_return(data, ret, NULL);
+ return test_return(data, ret);
}
-static void test_remove_group_by_gid(struct sysdb_handle *handle, void *pvt)
+static void test_store_group_done(struct tevent_req *subreq);
+
+static void test_store_group(struct tevent_req *req)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return test_return(data, ret);
+ }
- ret = sysdb_delete_group_by_gid(handle, data->domain, data->gid,
- data->next_fn, data);
- if (ret != EOK) test_return(data, ret, NULL);
+ subreq = sysdb_store_group_send(data, data->ev, data->handle,
+ data->domain, data->groupname,
+ data->gid, NULL);
+ if (!subreq) {
+ test_return(data, ret);
+ }
+ tevent_req_set_callback(subreq, test_store_group_done, data);
}
-static void test_add_legacy_group_member(struct sysdb_handle *handle, void *pvt)
+static void test_store_group_done(struct tevent_req *subreq)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(subreq, struct test_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_store_group_recv(subreq);
+ talloc_zfree(subreq);
+
+ return test_return(data, ret);
+}
- ret = sysdb_legacy_add_group_member(handle, data->domain,
- data->groupname,
- data->username,
- data->next_fn, data);
+static void test_remove_group_done(struct tevent_req *subreq);
+
+static void test_remove_group(struct tevent_req *req)
+{
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
+ struct ldb_dn *group_dn;
+ int ret;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
if (ret != EOK) {
- test_return(data, ret, NULL);
+ return test_return(data, ret);
}
+
+ group_dn = sysdb_group_dn(data->ctx->sysdb, data, "LOCAL", data->groupname);
+ if (!group_dn) return test_return(data, ENOMEM);
+
+ subreq = sysdb_delete_entry_send(data, data->ev, data->handle, group_dn);
+ if (!subreq) return test_return(data, ENOMEM);
+
+ tevent_req_set_callback(subreq, test_remove_group_done, data);
}
-static void test_remove_legacy_group_member(struct sysdb_handle *handle, void *pvt)
+static void test_remove_group_done(struct tevent_req *subreq)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct sysdb_ctx *ctx;
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
int ret;
- data->handle = handle;
- ctx = sysdb_handle_get_ctx(handle);
+ ret = sysdb_delete_entry_recv(subreq);
+ talloc_zfree(subreq);
+
+ return test_return(data, ret);
+}
- ret = sysdb_legacy_remove_group_member(handle, data->domain,
- data->groupname,
- data->username,
- data->next_fn, data);
+static void test_remove_group_by_gid_done(struct tevent_req *subreq);
+static void test_remove_group_by_gid(struct tevent_req *req)
+{
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
+ int ret;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
if (ret != EOK) {
- test_return(data, ret, NULL);
+ return test_return(data, ret);
}
+
+ subreq = sysdb_delete_group_by_gid_send(data, data->ev, data->handle,
+ data->domain, data->gid);
+ if (!subreq) return test_return(data, ENOMEM);
+
+ tevent_req_set_callback(subreq, test_remove_group_by_gid_done, data);
+}
+
+static void test_remove_group_by_gid_done(struct tevent_req *subreq)
+{
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
+ int ret;
+
+ ret = sysdb_delete_group_by_gid_recv(subreq);
+ talloc_zfree(subreq);
+
+ return test_return(data, ret);
}
static void test_getpwent(void *pvt, int error, struct ldb_result *res)
@@ -456,7 +600,8 @@ static void test_getpwuid(void *pvt, int error, struct ldb_result *res)
static void test_enumgrent(void *pvt, int error, struct ldb_result *res)
{
struct test_data *data = talloc_get_type(pvt, struct test_data);
- const int expected = 30; /* 15 groups + 15 users (we're MPG) */
+/* const int expected = 30; /* 15 groups + 15 users (we're MPG) */
+ const int expected = 15;
data->finished = true;
@@ -493,20 +638,36 @@ static void test_enumpwent(void *pvt, int error, struct ldb_result *res)
data->error = EOK;
}
-static void test_set_user_attr(struct sysdb_handle *handle, void *pvt)
+static void test_set_user_attr_done(struct tevent_req *subreq);
+static void test_set_user_attr(struct tevent_req *req)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
int ret;
- data->handle = handle;
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return test_return(data, ret);
+ }
- ret = sysdb_set_user_attr(handle,
- data->domain,
- data->username,
- data->attrs,
- data->next_fn,
- data);
- if (ret != EOK) test_return(data, ret, NULL);
+ subreq = sysdb_set_user_attr_send(data, data->ev, data->handle,
+ data->domain, data->username,
+ data->attrs, SYSDB_MOD_REP);
+ if (!subreq) return test_return(data, ENOMEM);
+
+ tevent_req_set_callback(subreq, test_set_user_attr_done, data);
+}
+
+static void test_set_user_attr_done(struct tevent_req *subreq)
+{
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
+ int ret;
+
+ ret = sysdb_set_user_attr_recv(subreq);
+ talloc_zfree(subreq);
+
+ return test_return(data, ret);
}
static void test_get_user_attr(void *pvt, int error, struct ldb_result *res)
@@ -534,248 +695,87 @@ static void test_get_user_attr(void *pvt, int error, struct ldb_result *res)
}
}
-static void test_add_group_member(struct sysdb_handle *handle, void *pvt)
-{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct ldb_dn *user_dn;
- struct ldb_dn *group_dn;
- const char *username;
- int ret;
- TALLOC_CTX *tmp_ctx;
-
- tmp_ctx = talloc_new(NULL);
- if (!tmp_ctx) {
- test_return(data, ENOMEM, NULL);
- }
+static void test_add_group_member_done(struct tevent_req *subreq);
- username = talloc_asprintf(tmp_ctx, "testuser%d", data->uid);
- if (username == NULL) {
- test_return(data, ENOMEM, NULL);
- }
- user_dn = sysdb_user_dn(data->ctx->sysdb,
- data,
- data->domain->name,
- username);
- if (user_dn == NULL) {
- test_return(data, ENOMEM, NULL);
- }
- group_dn = sysdb_group_dn(data->ctx->sysdb,
- data,
- data->domain->name,
- data->groupname);
- if (group_dn == NULL) {
- test_return(data, ENOMEM, NULL);
- }
-
- data->handle = handle;
-
- ret = sysdb_add_group_member(handle,
- user_dn,
- group_dn,
- test_return,
- data);
- if (ret != EOK) {
- talloc_free(tmp_ctx);
- test_return(data, ret, NULL);
- }
- talloc_free(tmp_ctx);
-}
-
-static void test_remove_group_member(struct sysdb_handle *handle, void *pvt)
+static void test_add_group_member(struct tevent_req *req)
{
- struct test_data *data = talloc_get_type(pvt, struct test_data);
- struct ldb_dn *user_dn;
- struct ldb_dn *group_dn;
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
const char *username;
int ret;
- TALLOC_CTX *tmp_ctx;
- tmp_ctx = talloc_new(NULL);
- if (!tmp_ctx) {
- test_return(data, ENOMEM, NULL);
- }
-
- username = talloc_asprintf(tmp_ctx, "testuser%d", data->uid);
- if (username == NULL) {
- test_return(data, ENOMEM, NULL);
- }
- user_dn = sysdb_user_dn(data->ctx->sysdb,
- data,
- data->domain->name,
- username);
- if (user_dn == NULL) {
- test_return(data, ENOMEM, NULL);
- }
- group_dn = sysdb_group_dn(data->ctx->sysdb,
- data,
- data->domain->name,
- username);
- if (group_dn == NULL) {
- test_return(data, ENOMEM, NULL);
- }
-
- data->handle = handle;
-
- ret = sysdb_remove_group_member(handle,
- user_dn,
- group_dn,
- test_return,
- data);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
if (ret != EOK) {
- talloc_free(tmp_ctx);
- test_return(data, ret, NULL);
+ return test_return(data, ret);
}
- talloc_free(tmp_ctx);
-}
-
-START_TEST (test_sysdb_store_legacy_user)
-{
- struct sysdb_test_ctx *test_ctx;
- struct test_data *data;
- int ret;
-
- /* Setup */
- ret = setup_sysdb_tests(&test_ctx);
- if (ret != EOK) {
- fail("Could not set up the test");
- return;
+ username = talloc_asprintf(data, "testuser%d", data->uid);
+ if (username == NULL) {
+ test_return(data, ENOMEM);
}
- data = talloc_zero(test_ctx, struct test_data);
- data->ctx = test_ctx;
- data->uid = _i;
- data->gid = _i;
- data->next_fn = test_return;
- data->username = talloc_asprintf(data, "testuser%d", _i);
- data->domain = get_local_domain(test_ctx->domains);
-
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_add_legacy_user, data);
- if (ret == EOK) {
- ret = test_loop(data);
+ subreq = sysdb_add_group_member_send(data, data->ev,
+ data->handle, data->domain,
+ data->groupname, username);
+ if (!subreq) {
+ test_return(data, ENOMEM);
}
- fail_if(ret != EOK, "Could not store legacy user %s", data->username);
- talloc_free(test_ctx);
+ tevent_req_set_callback(subreq, test_add_group_member_done, data);
}
-END_TEST
-START_TEST (test_sysdb_store_legacy_group)
+static void test_add_group_member_done(struct tevent_req *subreq)
{
- struct sysdb_test_ctx *test_ctx;
- struct test_data *data;
- int ret;
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
+ int ret = sysdb_add_group_member_recv(subreq);
- /* Setup */
- ret = setup_sysdb_tests(&test_ctx);
- if (ret != EOK) {
- fail("Could not set up the test");
- return;
- }
-
- data = talloc_zero(test_ctx, struct test_data);
- data->ctx = test_ctx;
- data->gid = _i;
- data->next_fn = test_return;
- data->groupname = talloc_asprintf(data, "testgroup%d", _i);
- data->domain = get_local_domain(test_ctx->domains);
-
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_add_legacy_group, data);
- if (ret == EOK) {
- ret = test_loop(data);
- }
-
- fail_if(ret != EOK, "Could not store POSIX group #%d", _i);
- talloc_free(test_ctx);
+ test_return(data, ret);
}
-END_TEST
-START_TEST (test_sysdb_get_local_group)
+static void test_remove_group_member_done(struct tevent_req *subreq);
+
+static void test_remove_group_member(struct tevent_req *req)
{
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
+ const char *username;
int ret;
- struct sysdb_test_ctx *test_ctx;
- struct ldb_result *res;
- struct ldb_dn *base_group_dn;
- const char *attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
- const char *name;
- char *expected_group;
- gid_t test_gid;
- /* Setup */
- ret = setup_sysdb_tests(&test_ctx);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
if (ret != EOK) {
- fail("Could not set up the test");
- return;
- }
-
- expected_group = talloc_asprintf(test_ctx, "testgroup%d", _i);
- fail_if(expected_group == NULL, "Could not allocate expected_group");
-
- /* Set up the base DN */
- base_group_dn = ldb_dn_new_fmt(test_ctx, sysdb_ctx_get_ldb(test_ctx->sysdb),
- SYSDB_TMPL_GROUP_BASE, "LOCAL");
- if (base_group_dn == NULL) {
- fail("Could not create basedn for LOCAL groups");
- return;
+ return test_return(data, ret);
}
- /* Look up the group by gid */
- ret = ldb_search(sysdb_ctx_get_ldb(test_ctx->sysdb), test_ctx,
- &res, base_group_dn, LDB_SCOPE_ONELEVEL,
- attrs, SYSDB_GRGID_FILTER, (unsigned long)_i);
- if (ret != LDB_SUCCESS) {
- fail("Could not locate group %d", _i);
- return;
- }
-
- if (res->count < 1) {
- fail("Local group %d doesn't exist.\n", _i);
- return;
- }
- else if (res->count > 1) {
- fail("More than one group shared gid %d", _i);
- return;
+ username = talloc_asprintf(data, "testuser%d", data->uid);
+ if (username == NULL) {
+ test_return(data, ENOMEM);
}
- name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
- fail_unless(strcmp(name, expected_group) == 0,
- "Returned group name was %s, expecting %s",
- name, expected_group);
- talloc_free(res);
-
- /* Look up the group by name */
- ret = ldb_search(sysdb_ctx_get_ldb(test_ctx->sysdb), test_ctx,
- &res, base_group_dn, LDB_SCOPE_ONELEVEL,
- attrs, SYSDB_GRNAM_FILTER, expected_group);
- if (ret != LDB_SUCCESS) {
- fail("Could not locate group %d", _i);
- return;
+ subreq = sysdb_remove_group_member_send(data, data->ev,
+ data->handle, data->domain,
+ data->groupname, username);
+ if (!subreq) {
+ test_return(data, ENOMEM);
}
- if (res->count < 1) {
- fail("Local group %s doesn't exist.", expected_group);
- return;
- }
- else if (res->count > 1) {
- fail("More than one group shared name %s", expected_group);
- return;
- }
+ tevent_req_set_callback(subreq, test_remove_group_member_done, data);
+}
- test_gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
- fail_unless(test_gid == _i,
- "Returned group id was %lu, expecting %lu",
- test_gid, _i);
+static void test_remove_group_member_done(struct tevent_req *subreq)
+{
+ struct test_data *data = tevent_req_callback_data(subreq,
+ struct test_data);
+ int ret = sysdb_remove_group_member_recv(subreq);
- talloc_free(test_ctx);
+ test_return(data, ret);
}
-END_TEST
-START_TEST (test_sysdb_add_legacy_group_member)
+START_TEST (test_sysdb_store_user)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -787,191 +787,33 @@ START_TEST (test_sysdb_add_legacy_group_member)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_return;
- data->groupname = talloc_asprintf(data, "testgroup%d", _i);
+ data->ev = test_ctx->ev;
+ data->uid = _i;
+ data->gid = _i;
data->username = talloc_asprintf(data, "testuser%d", _i);
data->domain = get_local_domain(test_ctx->domains);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_add_legacy_group_member, data);
- if (ret == EOK) {
- ret = test_loop(data);
- }
-
- fail_if(ret != EOK, "Failed to add user %s to group %s.",
- data->username, data->groupname);
- talloc_free(test_ctx);
-}
-END_TEST
-
-START_TEST (test_sysdb_verify_legacy_group_members)
-{
- char found_group;
- int ret, i;
- struct sysdb_test_ctx *test_ctx;
- char *username;
- char *groupname;
- struct ldb_dn *group_dn;
- struct ldb_dn *user_dn;
- struct ldb_result *res;
- struct ldb_message_element *el;
- const char *group_attrs[] = { SYSDB_LEGACY_MEMBER, NULL };
-
- /* Setup */
- ret = setup_sysdb_tests(&test_ctx);
- if (ret != EOK) {
- fail("Could not set up the test");
- return;
- }
-
- username = talloc_asprintf(test_ctx, "testuser%d", _i);
- fail_if (username == NULL, "Could not allocate username");
-
- user_dn = sysdb_user_dn(test_ctx->sysdb, test_ctx, "LOCAL", username);
- fail_if(user_dn == NULL, "Could not create user_dn object");
-
- groupname = talloc_asprintf(test_ctx, "testgroup%d", _i);
- fail_if (groupname == NULL, "Could not allocate groupname");
-
- group_dn = sysdb_group_dn(test_ctx->sysdb, test_ctx, "LOCAL", groupname);
- fail_if(group_dn == NULL, "Could not create group_dn object");
-
- /* Look up the group by name */
- ret = ldb_search(sysdb_ctx_get_ldb(test_ctx->sysdb), test_ctx,
- &res, group_dn, LDB_SCOPE_BASE,
- group_attrs, SYSDB_GRNAM_FILTER, groupname);
- if (ret != LDB_SUCCESS) {
- fail("Could not locate group %d", _i);
- return;
- }
-
- if (res->count < 1) {
- fail("Local group %s doesn't exist.", groupname);
- return;
- }
- else if (res->count > 1) {
- fail("More than one group shared name testgroup");
- return;
- }
-
- /* Check the members for the requested user */
- found_group = i = 0;
- el = ldb_msg_find_element(res->msgs[0], SYSDB_LEGACY_MEMBER);
- if (el && el->num_values > 0) {
- while (i < el->num_values && !found_group) {
- struct ldb_val v = el->values[i];
- char *value = talloc_strndup(test_ctx, (char *)v.data, v.length);
- if (strcmp(value, username) == 0) {
- found_group = 1;
- }
- talloc_free(value);
- i++;
- }
- }
- else {
- fail("No member attributes for group testgroup");
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
}
- fail_unless(found_group == 1, "testgroup does not have %s as a member",
- username);
-}
-END_TEST
-
-#if 0
-START_TEST (test_sysdb_add_invalid_member)
-{
- char found_group;
- int ret, i;
- struct sysdb_test_ctx *test_ctx;
- char *username;
- char *member;
- char *group;
- char *group_name;
- struct ldb_dn *group_dn;
- struct ldb_result *res;
- struct ldb_message_element *el;
- const char *group_attrs[] = { SYSDB_MEMBER, NULL };
-
- /* Setup */
- ret = setup_sysdb_tests(&test_ctx);
- if (ret != EOK) {
- fail("Could not set up the test");
- return;
- }
-
- group_name = talloc_asprintf(test_ctx, "testgroup%d", _i);
- group = talloc_asprintf(test_ctx,
- SYSDB_NAME"=%s,"SYSDB_TMPL_GROUP_BASE,
- group_name, "LOCAL");
- fail_if(group == NULL, "Could not allocate group dn");
-
- /* Add nonexistent user to test group */
- username = talloc_asprintf(test_ctx, "nonexistentuser%d", _i);
- ret = sysdb_add_user_to_group(test_ctx,
- test_ctx->sysdb,
- "LOCAL",
- group,
- username);
- fail_if(ret == EOK,
- "Unexpected success adding user %s to group testgroup."
- "Error was: %d", username, ret);
-
-/* Verify that the member wasn't added anyway */
-
- member = talloc_asprintf(test_ctx,
- SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE,
- username, "LOCAL");
- fail_if(member == NULL, "Could not allocate member dn");
-
- group_dn = ldb_dn_new_fmt(test_ctx, sysdb_ctx_get_ldb(test_ctx->sysdb), group);
- fail_if(group_dn == NULL, "Could not create group_dn object");
-
- /* Look up the group by name */
- ret = ldb_search(sysdb_ctx_get_ldb(test_ctx->sysdb), test_ctx,
- &res, group_dn, LDB_SCOPE_BASE,
- group_attrs, SYSDB_GRNAM_FILTER, group_name);
- if (ret != LDB_SUCCESS) {
- fail("Could not locate group %d", _i);
- return;
- }
-
- if (res->count < 1) {
- fail("Local group %s doesn't exist.", group_name);
- return;
- }
- else if (res->count > 1) {
- fail("More than one group shared name %s", group_name);
- return;
- }
+ if (ret == EOK) {
+ tevent_req_set_callback(req, test_store_user, data);
- /* Check the members for the requested user */
- found_group = i = 0;
- el = ldb_msg_find_element(res->msgs[0], SYSDB_MEMBER);
- if (el && el->num_values > 0) {
- while (i < el->num_values && !found_group) {
- struct ldb_val v = el->values[i];
- char *value = talloc_strndup(test_ctx, (char *)v.data, v.length);
- if (strcmp(value, member) == 0) {
- found_group = 1;
- }
- talloc_free(value);
- i++;
- }
- }
- else {
- fail("No member attributes for group testgroup");
+ ret = test_loop(data);
}
- fail_if(found_group == 1, "testgroup has added %s as a member", username);
+ fail_if(ret != EOK, "Could not store legacy user %s", data->username);
talloc_free(test_ctx);
}
END_TEST
-#endif
-START_TEST (test_sysdb_remove_legacy_group_member)
+START_TEST (test_sysdb_store_group)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -983,19 +825,23 @@ START_TEST (test_sysdb_remove_legacy_group_member)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_return;
+ data->ev = test_ctx->ev;
+ data->gid = _i;
data->groupname = talloc_asprintf(data, "testgroup%d", _i);
- data->username = talloc_asprintf(data, "testuser%d", _i);
data->domain = get_local_domain(test_ctx->domains);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_remove_legacy_group_member, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_store_group, data);
+
ret = test_loop(data);
}
- fail_if(ret != EOK, "Failed to remove user %s to group %s.",
- data->username, data->groupname, ret);
+ fail_if(ret != EOK, "Could not store POSIX group #%d", _i);
talloc_free(test_ctx);
}
END_TEST
@@ -1004,6 +850,7 @@ START_TEST (test_sysdb_remove_local_user)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -1015,12 +862,17 @@ START_TEST (test_sysdb_remove_local_user)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_return;
+ data->ev = test_ctx->ev;
data->username = talloc_asprintf(data, "testuser%d", _i);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_remove_user, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_remove_user, data);
+
ret = test_loop(data);
}
@@ -1033,6 +885,7 @@ START_TEST (test_sysdb_remove_local_user_by_uid)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -1044,13 +897,18 @@ START_TEST (test_sysdb_remove_local_user_by_uid)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_return;
+ data->ev = test_ctx->ev;
data->uid = _i;
data->domain = get_local_domain(test_ctx->domains);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_remove_user_by_uid, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_remove_user_by_uid, data);
+
ret = test_loop(data);
}
@@ -1063,6 +921,7 @@ START_TEST (test_sysdb_remove_local_group)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -1074,12 +933,17 @@ START_TEST (test_sysdb_remove_local_group)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_return;
+ data->ev = test_ctx->ev;
data->groupname = talloc_asprintf(data, "testgroup%d", _i);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_remove_group, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_remove_group, data);
+
ret = test_loop(data);
}
@@ -1092,6 +956,7 @@ START_TEST (test_sysdb_remove_local_group_by_gid)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -1103,13 +968,18 @@ START_TEST (test_sysdb_remove_local_group_by_gid)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_return;
+ data->ev = test_ctx->ev;
data->gid = _i;
data->domain = get_local_domain(test_ctx->domains);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_remove_group_by_gid, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_remove_group_by_gid, data);
+
ret = test_loop(data);
}
@@ -1122,6 +992,7 @@ START_TEST (test_sysdb_add_user)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *subreq;
int ret;
/* Setup */
@@ -1133,16 +1004,20 @@ START_TEST (test_sysdb_add_user)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
-
+ data->ev = test_ctx->ev;
data->uid = _i;
data->gid = _i;
- data->next_fn = test_return;
data->username = talloc_asprintf(data, "testuser%d", _i);
data->domain = get_local_domain(test_ctx->domains);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_add_user, data);
+ subreq = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!subreq) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(subreq, test_add_user, data);
+
ret = test_loop(data);
}
@@ -1155,6 +1030,7 @@ START_TEST (test_sysdb_add_group)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *subreq;
int ret;
/* Setup */
@@ -1166,16 +1042,20 @@ START_TEST (test_sysdb_add_group)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
-
+ data->ev = test_ctx->ev;
data->uid = _i;
data->gid = _i;
- data->next_fn = test_return;
data->groupname = talloc_asprintf(data, "testgroup%d", _i);
data->domain = get_local_domain(test_ctx->domains);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_add_group, data);
+ subreq = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!subreq) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(subreq, test_add_group, data);
+
ret = test_loop(data);
}
@@ -1199,7 +1079,6 @@ START_TEST (test_sysdb_getpwnam)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_getpwent;
data->username = talloc_asprintf(data, "testuser%d", _i);
data->domain = get_local_domain(test_ctx->domains);
@@ -1207,18 +1086,20 @@ START_TEST (test_sysdb_getpwnam)
test_ctx->sysdb,
data->domain,
data->username,
- data->next_fn,
+ test_getpwent,
data);
if (ret == EOK) {
ret = test_loop(data);
}
- fail_unless(ret == EOK,
- "sysdb_getpwnam failed for username %d (%s)",
- data->username, ret, strerror(ret));
+ if (ret) {
+ fail("sysdb_getpwnam failed for username %s (%d: %s)",
+ data->username, ret, strerror(ret));
+ goto done;
+ }
fail_unless(data->uid == _i,
"Did not find the expected UID");
-
+done:
talloc_free(test_ctx);
}
END_TEST
@@ -1238,7 +1119,6 @@ START_TEST (test_sysdb_getgrnam)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_getgrent;
data->groupname = talloc_asprintf(data, "testgroup%d", _i);
data->domain = get_local_domain(test_ctx->domains);
@@ -1246,19 +1126,21 @@ START_TEST (test_sysdb_getgrnam)
test_ctx->sysdb,
data->domain,
data->groupname,
- data->next_fn,
+ test_getgrent,
data);
if (ret == EOK) {
ret = test_loop(data);
}
- fail_unless(ret == EOK,
- "sysdb_getgrnam failed for groupname %s (%d: %s)",
- data->groupname, ret, strerror(ret));
+ if (ret) {
+ fail("sysdb_getgrnam failed for groupname %s (%d: %s)",
+ data->groupname, ret, strerror(ret));
+ goto done;
+ }
fail_unless(data->gid == _i,
"Did not find the expected GID (found %d expected %d)",
data->gid, _i);
-
+done:
talloc_free(test_ctx);
}
END_TEST
@@ -1285,7 +1167,6 @@ START_TEST (test_sysdb_getgrgid)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_getgrgid;
data->gid = _i;
data->domain = get_local_domain(test_ctx->domains);
@@ -1293,19 +1174,21 @@ START_TEST (test_sysdb_getgrgid)
test_ctx->sysdb,
data->domain,
data->gid,
- data->next_fn,
+ test_getgrgid,
data);
if (ret == EOK) {
ret = test_loop(data);
}
- fail_unless(ret == EOK,
- "sysdb_getgrgid failed for gid %d (%d: %s)",
- data->gid, ret, strerror(ret));
+ if (ret) {
+ fail("sysdb_getgrgid failed for gid %d (%d: %s)",
+ data->gid, ret, strerror(ret));
+ goto done;
+ }
fail_unless(strcmp(data->groupname, groupname) == 0,
"Did not find the expected groupname (found %s expected %s)",
data->groupname, groupname);
-
+done:
talloc_free(test_ctx);
}
END_TEST
@@ -1332,7 +1215,6 @@ START_TEST (test_sysdb_getpwuid)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_getpwuid;
data->uid = _i;
data->domain = get_local_domain(test_ctx->domains);
@@ -1340,19 +1222,22 @@ START_TEST (test_sysdb_getpwuid)
test_ctx->sysdb,
data->domain,
data->uid,
- data->next_fn,
+ test_getpwuid,
data);
if (ret == EOK) {
ret = test_loop(data);
}
- fail_unless(ret == EOK,
- "sysdb_getpwuid failed for uid %d (%d: %s)",
- data->uid, ret, strerror(ret));
+ if (ret) {
+ fail("sysdb_getpwuid failed for uid %d (%d: %s)",
+ data->uid, ret, strerror(ret));
+ goto done;
+ }
+
fail_unless(strcmp(data->username, username) == 0,
"Did not find the expected username (found %s expected %s)",
data->username, username);
-
+done:
talloc_free(test_ctx);
}
END_TEST
@@ -1372,13 +1257,12 @@ START_TEST (test_sysdb_enumgrent)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_enumgrent;
data->domain = get_local_domain(test_ctx->domains);
ret = sysdb_enumgrent(test_ctx,
test_ctx->sysdb,
data->domain,
- data->next_fn,
+ test_enumgrent,
data);
if (ret == EOK) {
ret = test_loop(data);
@@ -1407,14 +1291,13 @@ START_TEST (test_sysdb_enumpwent)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
- data->next_fn = test_enumpwent;
data->domain = get_local_domain(test_ctx->domains);
ret = sysdb_enumpwent(test_ctx,
test_ctx->sysdb,
data->domain,
NULL,
- data->next_fn,
+ test_enumpwent,
data);
if (ret == EOK) {
ret = test_loop(data);
@@ -1433,6 +1316,7 @@ START_TEST (test_sysdb_set_user_attr)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -1444,9 +1328,9 @@ START_TEST (test_sysdb_set_user_attr)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
+ data->ev = test_ctx->ev;
data->username = talloc_asprintf(data, "testuser%d", _i);
data->domain = get_local_domain(test_ctx->domains);
- data->next_fn = test_return;
data->attrs = sysdb_new_attrs(test_ctx);
if (ret != EOK) {
@@ -1462,9 +1346,14 @@ START_TEST (test_sysdb_set_user_attr)
return;
}
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_set_user_attr, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_set_user_attr, data);
+
ret = test_loop(data);
}
@@ -1492,24 +1381,26 @@ START_TEST (test_sysdb_get_user_attr)
data->ctx = test_ctx;
data->username = talloc_asprintf(data, "testuser%d", _i);
data->domain = get_local_domain(test_ctx->domains);
- data->next_fn = test_get_user_attr;
ret = sysdb_get_user_attr(data,
data->ctx->sysdb,
data->domain,
data->username,
attrs,
- data->next_fn,
+ test_get_user_attr,
data);
if (ret == EOK) {
ret = test_loop(data);
}
- fail_if(ret != EOK, "Could not get attributes for user %s", data->username);
+ if (ret) {
+ fail("Could not get attributes for user %s", data->username);
+ goto done;
+ }
fail_if(strcmp(data->attrval, "/bin/ksh"),
"Got bad attribute value for user %s",
data->username);
-
+done:
talloc_free(test_ctx);
}
END_TEST
@@ -1518,6 +1409,7 @@ START_TEST (test_sysdb_add_group_member)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -1529,14 +1421,19 @@ START_TEST (test_sysdb_add_group_member)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
+ data->ev = test_ctx->ev;
data->groupname = talloc_asprintf(data, "testgroup%d", _i);
data->uid = _i - 1000; /* the UID of user to add */
data->domain = get_local_domain(test_ctx->domains);
- data->next_fn = test_return;
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_add_group_member, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_add_group_member, data);
+
ret = test_loop(data);
}
@@ -1549,6 +1446,7 @@ START_TEST (test_sysdb_remove_group_member)
{
struct sysdb_test_ctx *test_ctx;
struct test_data *data;
+ struct tevent_req *req;
int ret;
/* Setup */
@@ -1560,13 +1458,19 @@ START_TEST (test_sysdb_remove_group_member)
data = talloc_zero(test_ctx, struct test_data);
data->ctx = test_ctx;
+ data->ev = test_ctx->ev;
data->groupname = talloc_asprintf(data, "testgroup%d", _i);
data->uid = _i - 1000; /* the UID of user to add */
data->domain = get_local_domain(test_ctx->domains);
- ret = sysdb_transaction(data, test_ctx->sysdb,
- test_remove_group_member, data);
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
if (ret == EOK) {
+ tevent_req_set_callback(req, test_remove_group_member, data);
+
ret = test_loop(data);
}
@@ -1581,29 +1485,17 @@ Suite *create_sysdb_suite(void)
TCase *tc_sysdb = tcase_create("SYSDB Tests");
/* Create a new user (legacy) */
- tcase_add_loop_test(tc_sysdb, test_sysdb_store_legacy_user,27000,27010);
+ tcase_add_loop_test(tc_sysdb, test_sysdb_store_user,27000,27010);
/* Verify the users were added */
tcase_add_loop_test(tc_sysdb, test_sysdb_getpwnam, 27000, 27010);
/* Create a new group (legacy) */
- tcase_add_loop_test(tc_sysdb, test_sysdb_store_legacy_group,27000,27010);
+ tcase_add_loop_test(tc_sysdb, test_sysdb_store_group,27000,27010);
/* Verify the groups were added */
tcase_add_loop_test(tc_sysdb, test_sysdb_getgrnam, 27000, 27010);
- /* Add users to the group */
- tcase_add_loop_test(tc_sysdb, test_sysdb_add_legacy_group_member, 27000, 27010);
-
- /* Verify member and memberOf */
- tcase_add_loop_test(tc_sysdb, test_sysdb_verify_legacy_group_members, 27000, 27010);
-#if 0
- /* A negative test: add nonexistent users as members of a group */
- tcase_add_loop_test(tc_sysdb, test_sysdb_add_invalid_member, 27000, 27010);
-#endif
- /* Remove users from their groups */
- tcase_add_loop_test(tc_sysdb, test_sysdb_remove_legacy_group_member, 27000, 27010);
-
/* Remove the other half by gid */
tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_group_by_gid, 27000, 27005);
diff --git a/server/tools/sss_groupadd.c b/server/tools/sss_groupadd.c
index acb26f3aa..ea7320161 100644
--- a/server/tools/sss_groupadd.c
+++ b/server/tools/sss_groupadd.c
@@ -44,6 +44,7 @@
#endif
struct group_add_ctx {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
struct sss_domain_info *domain;
@@ -56,36 +57,75 @@ struct group_add_ctx {
bool done;
};
-/* sysdb callback */
-static void add_group_done(void *pvt, int error, struct ldb_result *ignore)
+static void add_group_req_done(struct tevent_req *req)
{
- struct group_add_ctx *data = talloc_get_type(pvt, struct group_add_ctx);
+ struct group_add_ctx *data = tevent_req_callback_data(req,
+ struct group_add_ctx);
+ data->error = sysdb_transaction_commit_recv(req);
data->done = true;
- sysdb_transaction_done(data->handle, error);
+ talloc_zfree(data->handle);
+}
+
+static void add_group_terminate(struct group_add_ctx *data, int error)
+{
+ struct tevent_req *req;
+
+ if (error != EOK) {
+ goto fail;
+ }
- if (error)
- data->error = error;
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, add_group_req_done, data);
+
+ return;
+
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
+
+ data->error = error;
+ data->done = true;
}
-/* sysdb_fn_t */
-static void add_group(struct sysdb_handle *handle, void *pvt)
+static void add_group_done(struct tevent_req *subreq);
+
+static void add_group(struct tevent_req *req)
{
- struct group_add_ctx *group_ctx;
+ struct group_add_ctx *data = tevent_req_callback_data(req,
+ struct group_add_ctx);
+ struct tevent_req *subreq;
int ret;
- group_ctx = talloc_get_type(pvt, struct group_add_ctx);
- group_ctx->handle = handle;
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return add_group_terminate(data, ret);
+ }
- ret = sysdb_add_group(handle, group_ctx->domain,
- group_ctx->groupname,
- group_ctx->gid,
- add_group_done,
- group_ctx);
+ subreq = sysdb_add_group_send(data, data->ev, data->handle,
+ data->domain, data->groupname,
+ data->gid, NULL);
+ if (!subreq) {
+ add_group_terminate(data, ENOMEM);
+ }
+ tevent_req_set_callback(subreq, add_group_done, data);
+}
- if(ret != EOK)
- add_group_done(group_ctx, ret, NULL);
+static void add_group_done(struct tevent_req *subreq)
+{
+ struct group_add_ctx *data = tevent_req_callback_data(subreq,
+ struct group_add_ctx);
+ int ret;
+
+ ret = sysdb_add_group_recv(subreq);
+ talloc_zfree(subreq);
+
+ return add_group_terminate(data, ret);
}
static int groupadd_legacy(struct group_add_ctx *ctx)
@@ -130,6 +170,7 @@ int main(int argc, const char **argv)
struct sss_domain_info *dom;
poptContext pc = NULL;
struct tools_ctx *ctx = NULL;
+ struct tevent_req *req;
struct group_add_ctx *group_ctx = NULL;
int ret = EXIT_SUCCESS;
@@ -202,13 +243,14 @@ int main(int argc, const char **argv)
}
/* add_group */
- ret = sysdb_transaction(ctx, ctx->sysdb, add_group, group_ctx);
- if(ret != EOK) {
+ req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb);
+ if (!req) {
DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret)));
ERROR("Transaction error. Could not add group.\n");
ret = EXIT_FAILURE;
goto fini;
}
+ tevent_req_set_callback(req, add_group, group_ctx);
while (!group_ctx->done) {
tevent_loop_once(ctx->ev);
diff --git a/server/tools/sss_groupdel.c b/server/tools/sss_groupdel.c
index 820cf2520..194285c97 100644
--- a/server/tools/sss_groupdel.c
+++ b/server/tools/sss_groupdel.c
@@ -41,6 +41,7 @@
struct group_del_ctx {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
sysdb_callback_t next_fn;
@@ -55,35 +56,77 @@ struct group_del_ctx {
bool done;
};
+static void groupdel_req_done(struct tevent_req *req)
+{
+ struct group_del_ctx *data = tevent_req_callback_data(req,
+ struct group_del_ctx);
+
+ data->error = sysdb_transaction_commit_recv(req);
+ data->done = true;
+
+ talloc_zfree(data->handle);
+}
+
/* sysdb callback */
static void groupdel_done(void *pvt, int error, struct ldb_result *ignore)
{
struct group_del_ctx *data = talloc_get_type(pvt, struct group_del_ctx);
+ struct tevent_req *req;
- data->done = true;
+ if (error != EOK) {
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, groupdel_req_done, data);
+
+ return;
- sysdb_transaction_done(data->handle, error);
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
- if (error)
- data->error = error;
+ data->error = error;
+ data->done = true;
}
-/* sysdb_fn_t */
-static void group_del(struct sysdb_handle *handle, void *pvt)
+static void group_del_done(struct tevent_req *subreq);
+
+static void group_del(struct tevent_req *req)
{
- struct group_del_ctx *group_ctx;
+ struct group_del_ctx *data = tevent_req_callback_data(req,
+ struct group_del_ctx);
+ struct tevent_req *subreq;
int ret;
- group_ctx = talloc_get_type(pvt, struct group_del_ctx);
- group_ctx->handle = handle;
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return groupdel_done(data, ret, NULL);
+ }
+
+ subreq = sysdb_delete_entry_send(data,
+ data->ev,
+ data->handle,
+ data->group_dn);
+ if (!subreq)
+ return groupdel_done(data, ret, NULL);
+
+ tevent_req_set_callback(subreq, group_del_done, data);
+}
- ret = sysdb_delete_entry(handle,
- group_ctx->group_dn,
- groupdel_done,
- group_ctx);
+static void group_del_done(struct tevent_req *subreq)
+{
+ struct group_del_ctx *data = tevent_req_callback_data(subreq,
+ struct group_del_ctx);
+ int ret;
- if(ret != EOK)
- groupdel_done(group_ctx, ret, NULL);
+ ret = sysdb_delete_entry_recv(subreq);
+
+ return groupdel_done(data, ret, NULL);
}
static int groupdel_legacy(struct group_del_ctx *ctx)
@@ -115,6 +158,7 @@ int main(int argc, const char **argv)
int pc_debug = 0;
struct group_del_ctx *group_ctx = NULL;
struct tools_ctx *ctx = NULL;
+ struct tevent_req *req;
struct sss_domain_info *dom;
struct group *grp_info;
@@ -208,13 +252,14 @@ int main(int argc, const char **argv)
}
/* groupdel */
- ret = sysdb_transaction(ctx, ctx->sysdb, group_del, group_ctx);
- if(ret != EOK) {
+ req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb);
+ if (!req) {
DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret)));
ERROR("Transaction error. Could not remove group.\n");
ret = EXIT_FAILURE;
goto fini;
}
+ tevent_req_set_callback(req, group_del, group_ctx);
while (!group_ctx->done) {
tevent_loop_once(ctx->ev);
diff --git a/server/tools/sss_groupmod.c b/server/tools/sss_groupmod.c
index 0c2abda8f..cc7665d9d 100644
--- a/server/tools/sss_groupmod.c
+++ b/server/tools/sss_groupmod.c
@@ -45,6 +45,7 @@
#endif
struct group_mod_ctx {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
struct sss_domain_info *domain;
@@ -61,132 +62,225 @@ struct group_mod_ctx {
bool done;
};
-/* sysdb callback */
-static void mod_group_done(void *pvt, int error, struct ldb_result *ignore)
+static void mod_group_req_done(struct tevent_req *req)
{
- struct group_mod_ctx *data = talloc_get_type(pvt, struct group_mod_ctx);
+ struct group_mod_ctx *data = tevent_req_callback_data(req,
+ struct group_mod_ctx);
+ data->error = sysdb_transaction_commit_recv(req);
data->done = true;
- sysdb_transaction_done(data->handle, error);
+ talloc_zfree(data->handle);
+}
+
+static void mod_group_done(struct group_mod_ctx *data, int error)
+{
+ struct tevent_req *req;
+
+ if (error != EOK) {
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, mod_group_req_done, data);
+
+ return;
- if (error)
- data->error = error;
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
+
+ data->error = error;
+ data->done = true;
}
-static void add_to_groups(void *, int, struct ldb_result *);
+static void mod_group_attr_done(struct tevent_req *req);
+static void mod_group_cont(struct group_mod_ctx *data);
+static void remove_from_groups(struct group_mod_ctx *data);
+static void remove_from_groups_done(struct tevent_req *req);
+static void add_to_groups(struct group_mod_ctx *data);
+static void add_to_groups_done(struct tevent_req *req);
-/* sysdb_fn_t */
-static void mod_group(struct sysdb_handle *handle, void *pvt)
+static void mod_group(struct tevent_req *req)
{
- struct group_mod_ctx *group_ctx;
+ struct group_mod_ctx *data;
+ struct tevent_req *subreq;
+ struct sysdb_attrs *attrs;
int ret;
- group_ctx = talloc_get_type(pvt, struct group_mod_ctx);
- group_ctx->handle = handle;
-
- if(group_ctx->gid == 0) {
- add_to_groups(group_ctx, EOK, NULL);
- } else {
- ret = sysdb_set_group_gid(handle,
- group_ctx->domain,
- group_ctx->groupname,
- group_ctx->gid,
- mod_group_done,
- group_ctx);
- if (ret != EOK) {
- mod_group_done(group_ctx, ret, NULL);
+ data = tevent_req_callback_data(req, struct group_mod_ctx);
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return mod_group_done(data, ret);
+ }
+ talloc_zfree(req);
+
+ if (data->gid != 0) {
+ attrs = sysdb_new_attrs(data);
+ if (!attrs) {
+ mod_group_done(data, ENOMEM);
+ }
+ ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, data->gid);
+ if (ret) {
+ mod_group_done(data, ret);
}
+
+ subreq = sysdb_set_group_attr_send(data, data->ev, data->handle,
+ data->domain, data->groupname,
+ attrs, SYSDB_MOD_REP);
+ if (!subreq) {
+ return mod_group_done(data, ret);
+ }
+ tevent_req_set_callback(subreq, mod_group_attr_done, data);
+ return;
}
+
+ return mod_group_cont(data);
}
-static void remove_from_groups(void *pvt, int error, struct ldb_result *ignore)
+static void mod_group_attr_done(struct tevent_req *subreq)
{
- struct group_mod_ctx *group_ctx = talloc_get_type(pvt, struct group_mod_ctx);
- struct ldb_dn *group_dn;
- struct ldb_dn *parent_group_dn;
+ struct group_mod_ctx *data = tevent_req_callback_data(subreq,
+ struct group_mod_ctx);
int ret;
- if (error) {
- mod_group_done(pvt, error, NULL);
- return;
+ ret = sysdb_set_group_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ return mod_group_done(data, ret);
}
- /* check if we removed all of them */
- if (group_ctx->rmgroups == NULL ||
- group_ctx->rmgroups[group_ctx->cur] == NULL) {
- mod_group_done(group_ctx, EOK, NULL);
- return;
+ mod_group_cont(data);
+}
+
+static void mod_group_cont(struct group_mod_ctx *data)
+{
+ if (data->rmgroups != NULL) {
+ return remove_from_groups(data);
}
- group_dn = sysdb_group_dn(group_ctx->ctx->sysdb, group_ctx,
- group_ctx->domain->name, group_ctx->groupname);
- if (!group_dn) {
- mod_group_done(pvt, ENOMEM, NULL);
- return;
+ if (data->addgroups != NULL) {
+ return add_to_groups(data);
}
- parent_group_dn = sysdb_group_dn(group_ctx->ctx->sysdb, group_ctx,
- group_ctx->domain->name,
- group_ctx->rmgroups[group_ctx->cur]);
- if (!parent_group_dn) {
- mod_group_done(pvt, ENOMEM, NULL);
- return;
+ return mod_group_done(data, EOK);
+}
+
+static void remove_from_groups(struct group_mod_ctx *data)
+{
+ struct ldb_dn *parent_dn;
+ struct ldb_dn *member_dn;
+ struct tevent_req *req;
+
+ member_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name, data->groupname);
+ if (!member_dn) {
+ return mod_group_done(data, ENOMEM);
}
- ret = sysdb_remove_group_member(group_ctx->handle,
- group_dn, parent_group_dn,
- remove_from_groups, group_ctx);
- if (ret != EOK)
- mod_group_done(group_ctx, ret, NULL);
+ parent_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name,
+ data->rmgroups[data->cur]);
+ if (!parent_dn) {
+ return mod_group_done(data, ENOMEM);
+ }
- /* go on to next group */
- group_ctx->cur++;
+ req = sysdb_mod_group_member_send(data,
+ data->ev,
+ data->handle,
+ member_dn,
+ parent_dn,
+ LDB_FLAG_MOD_DELETE);
+ if (!req) {
+ return mod_group_done(data, ENOMEM);
+ }
+ tevent_req_set_callback(req, remove_from_groups_done, data);
}
-static void add_to_groups(void *pvt, int error, struct ldb_result *ignore)
+static void remove_from_groups_done(struct tevent_req *req)
{
- struct group_mod_ctx *group_ctx = talloc_get_type(pvt, struct group_mod_ctx);
- struct ldb_dn *group_dn;
- struct ldb_dn *parent_group_dn;
+ struct group_mod_ctx *data = tevent_req_callback_data(req,
+ struct group_mod_ctx);
int ret;
- if (error) {
- mod_group_done(pvt, error, NULL);
- return;
+ ret = sysdb_mod_group_member_recv(req);
+ if (ret) {
+ return mod_group_done(data, ret);
}
+ talloc_zfree(req);
+
+ /* go on to next group */
+ data->cur++;
/* check if we added all of them */
- if (group_ctx->addgroups == NULL ||
- group_ctx->addgroups[group_ctx->cur] == NULL) {
- group_ctx->cur = 0;
- remove_from_groups(group_ctx, EOK, NULL);
- return;
+ if (data->rmgroups[data->cur] == NULL) {
+ data->cur = 0;
+ if (data->addgroups != NULL) {
+ return remove_from_groups(data);
+ }
+ return mod_group_done(data, EOK);
}
- group_dn = sysdb_group_dn(group_ctx->ctx->sysdb, group_ctx,
- group_ctx->domain->name, group_ctx->groupname);
- if (!group_dn) {
- mod_group_done(pvt, ENOMEM, NULL);
- return;
+ return remove_from_groups(data);
+}
+
+static void add_to_groups(struct group_mod_ctx *data)
+{
+ struct ldb_dn *parent_dn;
+ struct ldb_dn *member_dn;
+ struct tevent_req *req;
+
+ member_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name, data->groupname);
+ if (!member_dn) {
+ return mod_group_done(data, ENOMEM);
}
- parent_group_dn = sysdb_group_dn(group_ctx->ctx->sysdb, group_ctx,
- group_ctx->domain->name,
- group_ctx->addgroups[group_ctx->cur]);
- if (!parent_group_dn) {
- mod_group_done(pvt, ENOMEM, NULL);
- return;
+ parent_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name,
+ data->addgroups[data->cur]);
+ if (!parent_dn) {
+ return mod_group_done(data, ENOMEM);
+ }
+
+ req = sysdb_mod_group_member_send(data,
+ data->ev,
+ data->handle,
+ member_dn,
+ parent_dn,
+ LDB_FLAG_MOD_ADD);
+ if (!req) {
+ return mod_group_done(data, ENOMEM);
}
+ tevent_req_set_callback(req, add_to_groups_done, data);
+}
+
+static void add_to_groups_done(struct tevent_req *req)
+{
+ struct group_mod_ctx *data = tevent_req_callback_data(req,
+ struct group_mod_ctx);
+ int ret;
- ret = sysdb_add_group_member(group_ctx->handle,
- group_dn, parent_group_dn,
- add_to_groups, group_ctx);
- if (ret != EOK)
- mod_group_done(group_ctx, ret, NULL);
+ ret = sysdb_mod_group_member_recv(req);
+ if (ret) {
+ return mod_group_done(data, ret);
+ }
+ talloc_zfree(req);
/* go on to next group */
- group_ctx->cur++;
+ data->cur++;
+
+ /* check if we added all of them */
+ if (data->addgroups[data->cur] == NULL) {
+ return mod_group_done(data, EOK);
+ }
+
+ return add_to_groups(data);
}
static int groupmod_legacy(struct tools_ctx *tools_ctx, struct group_mod_ctx *ctx, int old_domain)
@@ -247,6 +341,7 @@ int main(int argc, const char **argv)
struct sss_domain_info *dom;
struct group_mod_ctx *group_ctx = NULL;
struct tools_ctx *ctx = NULL;
+ struct tevent_req *req;
char *groups;
int ret;
struct group *grp_info;
@@ -344,13 +439,14 @@ int main(int argc, const char **argv)
goto fini;
}
- ret = sysdb_transaction(ctx, ctx->sysdb, mod_group, group_ctx);
- if (ret != EOK) {
+ req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb);
+ if (!req) {
DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret)));
ERROR("Transaction error. Could not modify group.\n");
ret = EXIT_FAILURE;
goto fini;
}
+ tevent_req_set_callback(req, mod_group, group_ctx);
while (!group_ctx->done) {
tevent_loop_once(ctx->ev);
diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c
index d1d83cf1d..ed9974fe8 100644
--- a/server/tools/sss_useradd.c
+++ b/server/tools/sss_useradd.c
@@ -84,6 +84,7 @@
#define DFL_BASEDIR_VAL "/home"
struct user_add_ctx {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
struct sss_domain_info *domain;
@@ -187,85 +188,137 @@ done:
return ret;
}
-static void add_to_groups(void *, int, struct ldb_result *);
-
-/* sysdb callback */
-static void add_user_done(void *pvt, int error, struct ldb_result *ignore)
+static void add_user_req_done(struct tevent_req *req)
{
- struct user_add_ctx *data = talloc_get_type(pvt, struct user_add_ctx);
+ struct user_add_ctx *data = tevent_req_callback_data(req,
+ struct user_add_ctx);
+ data->error = sysdb_transaction_commit_recv(req);
data->done = true;
- sysdb_transaction_done(data->handle, error);
+ talloc_zfree(data->handle);
+}
- if (error)
- data->error = error;
+static void add_user_terminate(struct user_add_ctx *data, int error)
+{
+ struct tevent_req *req;
+
+ if (error != EOK) {
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, add_user_req_done, data);
+
+ return;
+
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
+
+ data->error = error;
+ data->done = true;
}
-/* sysdb_fn_t */
-static void add_user(struct sysdb_handle *handle, void *pvt)
+static void add_user_done(struct tevent_req *subreq);
+static void add_to_groups(struct user_add_ctx *data);
+static void add_to_groups_done(struct tevent_req *req);
+
+static void add_user(struct tevent_req *req)
{
- struct user_add_ctx *user_ctx;
+ struct user_add_ctx *data = tevent_req_callback_data(req,
+ struct user_add_ctx);
+ struct tevent_req *subreq;
int ret;
- user_ctx = talloc_get_type(pvt, struct user_add_ctx);
- user_ctx->handle = handle;
-
- ret = sysdb_add_user(handle, user_ctx->domain,
- user_ctx->username,
- user_ctx->uid,
- user_ctx->gid,
- user_ctx->gecos,
- user_ctx->home,
- user_ctx->shell,
- add_to_groups, user_ctx);
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return add_user_terminate(data, ret);
+ }
- if (ret != EOK)
- add_user_done(user_ctx, ret, NULL);
+ subreq = sysdb_add_user_send(data, data->ev, data->handle,
+ data->domain, data->username,
+ data->uid, data->gid,
+ data->gecos, data->home,
+ data->shell, NULL);
+ if (!subreq) {
+ add_user_terminate(data, ENOMEM);
+ }
+ tevent_req_set_callback(subreq, add_user_done, data);
}
-static void add_to_groups(void *pvt, int error, struct ldb_result *ignore)
+static void add_user_done(struct tevent_req *subreq)
{
- struct user_add_ctx *user_ctx = talloc_get_type(pvt, struct user_add_ctx);
- struct ldb_dn *group_dn;
- struct ldb_dn *user_dn;
+ struct user_add_ctx *data = tevent_req_callback_data(subreq,
+ struct user_add_ctx);
int ret;
- if (error) {
- add_user_done(pvt, error, NULL);
- return;
+ ret = sysdb_add_user_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ return add_user_terminate(data, ret);
}
- /* check if we added all of them */
- if (user_ctx->groups == NULL ||
- user_ctx->groups[user_ctx->cur] == NULL) {
- add_user_done(user_ctx, EOK, NULL);
- return;
+ if (data->groups) {
+ return add_to_groups(data);
}
- user_dn = sysdb_user_dn(user_ctx->ctx->sysdb, user_ctx,
- user_ctx->domain->name, user_ctx->username);
- if (!user_dn) {
- add_user_done(pvt, ENOMEM, NULL);
- return;
+ return add_user_terminate(data, ret);
+}
+
+static void add_to_groups(struct user_add_ctx *data)
+{
+ struct ldb_dn *parent_dn;
+ struct ldb_dn *member_dn;
+ struct tevent_req *subreq;
+
+ member_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name, data->username);
+ if (!member_dn) {
+ return add_user_terminate(data, ENOMEM);
}
- group_dn = sysdb_group_dn(user_ctx->ctx->sysdb, user_ctx,
- user_ctx->domain->name,
- user_ctx->groups[user_ctx->cur]);
- if (!group_dn) {
- add_user_done(pvt, ENOMEM, NULL);
- return;
+ parent_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name,
+ data->groups[data->cur]);
+ if (!parent_dn) {
+ return add_user_terminate(data, ENOMEM);
}
- ret = sysdb_add_group_member(user_ctx->handle,
- user_dn, group_dn,
- add_to_groups, user_ctx);
- if (ret != EOK)
- add_user_done(user_ctx, ret, NULL);
+ subreq = sysdb_mod_group_member_send(data, data->ev, data->handle,
+ member_dn, parent_dn,
+ LDB_FLAG_MOD_ADD);
+ if (!subreq) {
+ return add_user_terminate(data, ENOMEM);
+ }
+ tevent_req_set_callback(subreq, add_to_groups_done, data);
+}
+
+static void add_to_groups_done(struct tevent_req *subreq)
+{
+ struct user_add_ctx *data = tevent_req_callback_data(subreq,
+ struct user_add_ctx);
+ int ret;
+
+ ret = sysdb_mod_group_member_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ return add_user_terminate(data, ret);
+ }
/* go on to next group */
- user_ctx->cur++;
+ data->cur++;
+
+ /* check if we added all of them */
+ if (data->groups[data->cur] == NULL) {
+ return add_user_terminate(data, EOK);
+ }
+
+ return add_to_groups(data);
}
static int useradd_legacy(struct user_add_ctx *ctx, char *grouplist)
@@ -332,6 +385,7 @@ int main(int argc, const char **argv)
struct sss_domain_info *dom = NULL;
struct user_add_ctx *user_ctx = NULL;
struct tools_ctx *ctx = NULL;
+ struct tevent_req *req;
char *groups = NULL;
int ret;
@@ -352,6 +406,7 @@ int main(int argc, const char **argv)
return ENOMEM;
}
user_ctx->ctx = ctx;
+ user_ctx->ev = ctx->ev;
/* parse user_ctx */
pc = poptGetContext(NULL, argc, argv, long_options, 0);
@@ -478,13 +533,14 @@ int main(int argc, const char **argv)
}
/* useradd */
- ret = sysdb_transaction(ctx, ctx->sysdb, add_user, user_ctx);
- if (ret != EOK) {
+ req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb);
+ if (!req) {
DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret)));
ERROR("Transaction error. Could not modify user.\n");
ret = EXIT_FAILURE;
goto fini;
}
+ tevent_req_set_callback(req, add_user, user_ctx);
while (!user_ctx->done) {
tevent_loop_once(ctx->ev);
diff --git a/server/tools/sss_userdel.c b/server/tools/sss_userdel.c
index 0222d00cc..bb0673b0a 100644
--- a/server/tools/sss_userdel.c
+++ b/server/tools/sss_userdel.c
@@ -40,6 +40,7 @@
#endif
struct user_del_ctx {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
sysdb_callback_t next_fn;
@@ -54,37 +55,81 @@ struct user_del_ctx {
bool done;
};
+static void userdel_req_done(struct tevent_req *req)
+{
+ struct user_del_ctx *data = tevent_req_callback_data(req,
+ struct user_del_ctx);
+
+ data->error = sysdb_transaction_commit_recv(req);
+ data->done = true;
+
+ talloc_zfree(data->handle);
+}
+
/* sysdb callback */
static void userdel_done(void *pvt, int error, struct ldb_result *ignore)
{
struct user_del_ctx *data = talloc_get_type(pvt, struct user_del_ctx);
+ struct tevent_req *req;
- data->done = true;
+ if (error != EOK) {
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, userdel_req_done, data);
+
+ return;
- sysdb_transaction_done(data->handle, error);
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
- if (error)
- data->error = error;
+ data->error = error;
+ data->done = true;
}
-/* sysdb_fn_t */
-static void user_del(struct sysdb_handle *handle, void *pvt)
+static void user_del_done(struct tevent_req *subreq);
+
+static void user_del(struct tevent_req *req)
{
- struct user_del_ctx *user_ctx;
+ struct user_del_ctx *data;
+ struct tevent_req *subreq;
int ret;
- user_ctx = talloc_get_type(pvt, struct user_del_ctx);
- user_ctx->handle = handle;
+ data = tevent_req_callback_data(req, struct user_del_ctx);
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return userdel_done(data, ret, NULL);
+ }
- ret = sysdb_delete_entry(handle,
- user_ctx->user_dn,
- userdel_done,
- user_ctx);
+ subreq = sysdb_delete_entry_send(data,
+ data->ev,
+ data->handle,
+ data->user_dn);
+ if (!subreq)
+ return userdel_done(data, ret, NULL);
- if(ret != EOK)
- userdel_done(user_ctx, ret, NULL);
+ tevent_req_set_callback(subreq, user_del_done, data);
}
+static void user_del_done(struct tevent_req *subreq)
+{
+ struct user_del_ctx *data = tevent_req_callback_data(subreq,
+ struct user_del_ctx);
+ int ret;
+
+ ret = sysdb_delete_entry_recv(subreq);
+
+ return userdel_done(data, ret, NULL);
+}
+
+
static int userdel_legacy(struct user_del_ctx *ctx)
{
int ret = EOK;
@@ -113,6 +158,7 @@ int main(int argc, const char **argv)
int ret = EXIT_SUCCESS;
struct user_del_ctx *user_ctx = NULL;
struct tools_ctx *ctx = NULL;
+ struct tevent_req *req;
struct sss_domain_info *dom;
struct passwd *pwd_info;
@@ -141,6 +187,7 @@ int main(int argc, const char **argv)
return ENOMEM;
}
user_ctx->ctx = ctx;
+ user_ctx->ev = ctx->ev;
/* parse user_ctx */
pc = poptGetContext(NULL, argc, argv, long_options, 0);
@@ -208,13 +255,14 @@ int main(int argc, const char **argv)
/* userdel */
- ret = sysdb_transaction(ctx, ctx->sysdb, user_del, user_ctx);
- if(ret != EOK) {
+ req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb);
+ if (!req) {
DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret)));
ERROR("Transaction error. Could not remove user.\n");
ret = EXIT_FAILURE;
goto fini;
}
+ tevent_req_set_callback(req, user_del, user_ctx);
while (!user_ctx->done) {
tevent_loop_once(ctx->ev);
diff --git a/server/tools/sss_usermod.c b/server/tools/sss_usermod.c
index 7bb8d663a..521c52645 100644
--- a/server/tools/sss_usermod.c
+++ b/server/tools/sss_usermod.c
@@ -82,6 +82,7 @@
#endif
struct user_mod_ctx {
+ struct tevent_context *ev;
struct sysdb_handle *handle;
struct sss_domain_info *domain;
@@ -98,133 +99,214 @@ struct user_mod_ctx {
bool done;
};
-/* sysdb callback */
-static void mod_user_done(void *pvt, int error, struct ldb_result *ignore)
+static void mod_user_req_done(struct tevent_req *req)
{
- struct user_mod_ctx *data = talloc_get_type(pvt, struct user_mod_ctx);
+ struct user_mod_ctx *data = tevent_req_callback_data(req,
+ struct user_mod_ctx);
+ data->error = sysdb_transaction_commit_recv(req);
data->done = true;
- sysdb_transaction_done(data->handle, error);
+ talloc_zfree(data->handle);
+}
+
+static void mod_user_done(struct user_mod_ctx *data, int error)
+{
+ struct tevent_req *req;
+
+ if (error != EOK) {
+ goto fail;
+ }
+
+ req = sysdb_transaction_commit_send(data, data->ev, data->handle);
+ if (!req) {
+ error = ENOMEM;
+ goto fail;
+ }
+ tevent_req_set_callback(req, mod_user_req_done, data);
- if (error)
- data->error = error;
+ return;
+
+fail:
+ /* free transaction */
+ talloc_zfree(data->handle);
+
+ data->error = error;
+ data->done = true;
}
-static void add_to_groups(void *, int, struct ldb_result *);
+static void mod_user_attr_done(struct tevent_req *req);
+static void mod_user_cont(struct user_mod_ctx *data);
+static void remove_from_groups(struct user_mod_ctx *data);
+static void remove_from_groups_done(struct tevent_req *req);
+static void add_to_groups(struct user_mod_ctx *data);
+static void add_to_groups_done(struct tevent_req *req);
-/* sysdb_fn_t */
-static void mod_user(struct sysdb_handle *handle, void *pvt)
+static void mod_user(struct tevent_req *req)
{
- struct user_mod_ctx *user_ctx;
+ struct user_mod_ctx *data;
+ struct tevent_req *subreq;
int ret;
- user_ctx = talloc_get_type(pvt, struct user_mod_ctx);
- user_ctx->handle = handle;
-
- if(user_ctx->attrs->num == 0) {
- add_to_groups(user_ctx, EOK, NULL);
- } else {
- ret = sysdb_set_user_attr(handle,
- user_ctx->domain,
- user_ctx->username,
- user_ctx->attrs,
- add_to_groups,
- user_ctx);
-
- if (ret != EOK) {
- mod_user_done(user_ctx, ret, NULL);
+ data = tevent_req_callback_data(req, struct user_mod_ctx);
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return mod_user_done(data, ret);
+ }
+
+ if (data->attrs->num != 0) {
+ subreq = sysdb_set_user_attr_send(data, data->ev, data->handle,
+ data->domain, data->username,
+ data->attrs, SYSDB_MOD_REP);
+ if (!subreq) {
+ return mod_user_done(data, ret);
}
+ tevent_req_set_callback(subreq, mod_user_attr_done, data);
+ return;
}
+
+ return mod_user_cont(data);
}
-static void remove_from_groups(void *pvt, int error, struct ldb_result *ignore)
+static void mod_user_attr_done(struct tevent_req *subreq)
{
- struct user_mod_ctx *user_ctx = talloc_get_type(pvt, struct user_mod_ctx);
- struct ldb_dn *group_dn;
- struct ldb_dn *user_dn;
+ struct user_mod_ctx *data = tevent_req_callback_data(subreq,
+ struct user_mod_ctx);
int ret;
- if (error) {
- mod_user_done(pvt, error, NULL);
- return;
+ ret = sysdb_set_user_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ return mod_user_done(data, ret);
}
- /* check if we removed all of them */
- if (user_ctx->rmgroups == NULL ||
- user_ctx->rmgroups[user_ctx->cur] == NULL) {
- mod_user_done(user_ctx, EOK, NULL);
- return;
+ mod_user_cont(data);
+}
+
+static void mod_user_cont(struct user_mod_ctx *data)
+{
+ if (data->rmgroups != NULL) {
+ return remove_from_groups(data);
}
- user_dn = sysdb_user_dn(user_ctx->ctx->sysdb, user_ctx,
- user_ctx->domain->name, user_ctx->username);
- if (!user_dn) {
- mod_user_done(pvt, ENOMEM, NULL);
- return;
+ if (data->addgroups != NULL) {
+ return add_to_groups(data);
}
- group_dn = sysdb_group_dn(user_ctx->ctx->sysdb, user_ctx,
- user_ctx->domain->name,
- user_ctx->rmgroups[user_ctx->cur]);
- if (!group_dn) {
- mod_user_done(pvt, ENOMEM, NULL);
- return;
+ return mod_user_done(data, EOK);
+}
+
+static void remove_from_groups(struct user_mod_ctx *data)
+{
+ struct ldb_dn *parent_dn;
+ struct ldb_dn *member_dn;
+ struct tevent_req *req;
+
+ member_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name, data->username);
+ if (!member_dn) {
+ return mod_user_done(data, ENOMEM);
}
- ret = sysdb_remove_group_member(user_ctx->handle,
- user_dn, group_dn,
- remove_from_groups, user_ctx);
- if (ret != EOK)
- mod_user_done(user_ctx, ret, NULL);
+ parent_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name,
+ data->rmgroups[data->cur]);
+ if (!parent_dn) {
+ return mod_user_done(data, ENOMEM);
+ }
- /* go on to next group */
- user_ctx->cur++;
+ req = sysdb_mod_group_member_send(data,
+ data->ev,
+ data->handle,
+ member_dn,
+ parent_dn,
+ LDB_FLAG_MOD_DELETE);
+ if (!req) {
+ return mod_user_done(data, ENOMEM);
+ }
+ tevent_req_set_callback(req, remove_from_groups_done, data);
}
-static void add_to_groups(void *pvt, int error, struct ldb_result *ignore)
+static void remove_from_groups_done(struct tevent_req *req)
{
- struct user_mod_ctx *user_ctx = talloc_get_type(pvt, struct user_mod_ctx);
- struct ldb_dn *group_dn;
- struct ldb_dn *user_dn;
+ struct user_mod_ctx *data = tevent_req_callback_data(req,
+ struct user_mod_ctx);
int ret;
- if (error) {
- mod_user_done(pvt, error, NULL);
- return;
+ ret = sysdb_mod_group_member_recv(req);
+ if (ret) {
+ return mod_user_done(data, ret);
}
+ talloc_zfree(req);
+
+ /* go on to next group */
+ data->cur++;
/* check if we added all of them */
- if (user_ctx->addgroups == NULL ||
- user_ctx->addgroups[user_ctx->cur] == NULL) {
- user_ctx->cur = 0;
- remove_from_groups(user_ctx, EOK, NULL);
- return;
+ if (data->rmgroups[data->cur] == NULL) {
+ data->cur = 0;
+ if (data->addgroups != NULL) {
+ return remove_from_groups(data);
+ }
+ return mod_user_done(data, EOK);
}
- user_dn = sysdb_user_dn(user_ctx->ctx->sysdb, user_ctx,
- user_ctx->domain->name, user_ctx->username);
- if (!user_dn) {
- mod_user_done(pvt, ENOMEM, NULL);
- return;
+ return remove_from_groups(data);
+}
+
+static void add_to_groups(struct user_mod_ctx *data)
+{
+ struct ldb_dn *parent_dn;
+ struct ldb_dn *member_dn;
+ struct tevent_req *req;
+
+ member_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name, data->username);
+ if (!member_dn) {
+ return mod_user_done(data, ENOMEM);
}
- group_dn = sysdb_group_dn(user_ctx->ctx->sysdb, user_ctx,
- user_ctx->domain->name,
- user_ctx->addgroups[user_ctx->cur]);
- if (!group_dn) {
- mod_user_done(pvt, ENOMEM, NULL);
- return;
+ parent_dn = sysdb_group_dn(data->ctx->sysdb, data,
+ data->domain->name,
+ data->addgroups[data->cur]);
+ if (!parent_dn) {
+ return mod_user_done(data, ENOMEM);
+ }
+
+ req = sysdb_mod_group_member_send(data,
+ data->ev,
+ data->handle,
+ member_dn,
+ parent_dn,
+ LDB_FLAG_MOD_ADD);
+ if (!req) {
+ return mod_user_done(data, ENOMEM);
}
+ tevent_req_set_callback(req, add_to_groups_done, data);
+}
+
+static void add_to_groups_done(struct tevent_req *req)
+{
+ struct user_mod_ctx *data = tevent_req_callback_data(req,
+ struct user_mod_ctx);
+ int ret;
- ret = sysdb_add_group_member(user_ctx->handle,
- user_dn, group_dn,
- add_to_groups, user_ctx);
- if (ret != EOK)
- mod_user_done(user_ctx, ret, NULL);
+ ret = sysdb_mod_group_member_recv(req);
+ if (ret) {
+ return mod_user_done(data, ret);
+ }
+ talloc_zfree(req);
/* go on to next group */
- user_ctx->cur++;
+ data->cur++;
+
+ /* check if we added all of them */
+ if (data->addgroups[data->cur] == NULL) {
+ return mod_user_done(data, EOK);
+ }
+
+ return add_to_groups(data);
}
static int usermod_legacy(struct tools_ctx *tools_ctx, struct user_mod_ctx *ctx,
@@ -316,6 +398,7 @@ int main(int argc, const char **argv)
struct sss_domain_info *dom;
struct user_mod_ctx *user_ctx = NULL;
struct tools_ctx *ctx = NULL;
+ struct tevent_req *req;
char *groups;
int ret;
struct passwd *pwd_info;
@@ -494,13 +577,14 @@ int main(int argc, const char **argv)
}
user_ctx->domain = dom;
- ret = sysdb_transaction(ctx, ctx->sysdb, mod_user, user_ctx);
- if (ret != EOK) {
+ req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb);
+ if (!req) {
DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret)));
ERROR("Transaction error. Could not modify user.\n");
ret = EXIT_FAILURE;
goto fini;
}
+ tevent_req_set_callback(req, mod_user, user_ctx);
while (!user_ctx->done) {
tevent_loop_once(ctx->ev);