summaryrefslogtreecommitdiff
path: root/server/db
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-06-24 16:40:56 -0400
committerSimo Sorce <ssorce@redhat.com>2009-07-03 11:07:36 -0400
commit94ec51d8b53f636d41a879ed1d0d39127168cb21 (patch)
treee6984ad304bf81781de2b118dac189db4bb0a582 /server/db
parent6aca93fb4d5d39a100b900a8c297d08629407960 (diff)
downloadsssd-94ec51d8b53f636d41a879ed1d0d39127168cb21.tar.gz
sssd-94ec51d8b53f636d41a879ed1d0d39127168cb21.tar.bz2
sssd-94ec51d8b53f636d41a879ed1d0d39127168cb21.zip
Rework transaction code to use tevent_req
This is part of a set of patches to rewrite sysdb to a hopefully better API, that will also let use use tevent_req async style calls to manipulate our cache.
Diffstat (limited to 'server/db')
-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
6 files changed, 3137 insertions, 1630 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c
index a86a966b..bb39c064 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 6da83318..2696dfaf 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 9b3f2828..785ce15e 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 8c10d951..d15ec370 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 a768fefb..00000000
--- 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 7e0aed8f..5ee9f8c0 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;
}