[Freeipa-devel] [PATCH] Serialize access to sysdb and also exposes ldb transactions.

Simo Sorce ssorce at redhat.com
Fri Feb 27 00:18:25 UTC 2009


---
 server/db/sysdb.c                 |  745 +------------------------------------
 server/db/sysdb.h                 |   14 +-
 server/db/sysdb_internal.h        |   70 ----
 server/db/sysdb_private.h         |   95 +++++
 server/db/sysdb_req.c             |  241 ++++++++++++
 server/db/sysdb_search.c          |  731 ++++++++++++++++++++++++++++++++++++
 server/db/sysdb_sync.c            |    2 +-
 server/responder/nss/nsssrv.c     |   10 +-
 server/responder/nss/nsssrv_cmd.c |   73 +++--
 server/server.mk                  |    2 +
 10 files changed, 1133 insertions(+), 850 deletions(-)
 delete mode 100644 server/db/sysdb_internal.h
 create mode 100644 server/db/sysdb_private.h
 create mode 100644 server/db/sysdb_req.c
 create mode 100644 server/db/sysdb_search.c

diff --git a/server/db/sysdb.c b/server/db/sysdb.c
index ddd7fbe..1c91f12 100644
--- a/server/db/sysdb.c
+++ b/server/db/sysdb.c
@@ -20,743 +20,13 @@
 */
 
 #include "util/util.h"
-#include "db/sysdb.h"
-#include "db/sysdb_internal.h"
+#include "db/sysdb_private.h"
 #include "confdb/confdb.h"
 #include <time.h>
 
-struct sysdb_search_ctx {
-    struct sysdb_ctx *dbctx;
-    const char *domain;
-    bool legacy;
-    sysdb_callback_t callback;
-    void *ptr;
-    struct ldb_result *res;
-};
-
-static int sysdb_error_to_errno(int lerr)
-{
-    /* fake it up for now, requires a mapping table */
-    return EIO;
-}
-
-static void request_error(struct sysdb_search_ctx *sctx, int ldb_error)
-{
-    sctx->callback(sctx->ptr, sysdb_error_to_errno(ldb_error), sctx->res);
-}
-
-static void request_done(struct sysdb_search_ctx *sctx)
-{
-    sctx->callback(sctx->ptr, EOK, sctx->res);
-}
-
-static int get_gen_callback(struct ldb_request *req,
-                            struct ldb_reply *ares)
-{
-    struct sysdb_search_ctx *sctx;
-    struct ldb_result *res;
-    int n;
-
-    sctx = talloc_get_type(req->context, struct sysdb_search_ctx);
-    res = sctx->res;
-
-    if (!ares) {
-        request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-        return LDB_ERR_OPERATIONS_ERROR;
-    }
-    if (ares->error != LDB_SUCCESS) {
-        request_error(sctx, ares->error);
-        return ares->error;
-    }
-
-    switch (ares->type) {
-    case LDB_REPLY_ENTRY:
-        res->msgs = talloc_realloc(res, res->msgs,
-                                   struct ldb_message *,
-                                   res->count + 2);
-        if (!res->msgs) {
-            request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-            return LDB_ERR_OPERATIONS_ERROR;
-        }
-
-        res->msgs[res->count + 1] = NULL;
-
-        res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
-        res->count++;
-        break;
-
-    case LDB_REPLY_REFERRAL:
-        if (res->refs) {
-            for (n = 0; res->refs[n]; n++) /*noop*/ ;
-        } else {
-            n = 0;
-        }
-
-        res->refs = talloc_realloc(res, res->refs, char *, n + 2);
-        if (! res->refs) {
-            request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-            return LDB_ERR_OPERATIONS_ERROR;
-        }
-
-        res->refs[n] = talloc_steal(res->refs, ares->referral);
-        res->refs[n + 1] = NULL;
-        break;
-
-    case LDB_REPLY_DONE:
-        res->controls = talloc_steal(res, ares->controls);
-
-        /* this is the last message, and means the request is done */
-        request_done(sctx);
-        return LDB_SUCCESS;
-    }
-
-    talloc_free(ares);
-    return LDB_SUCCESS;
-}
-
-static struct sysdb_search_ctx *init_src_ctx(TALLOC_CTX *mem_ctx,
-                                             const char *domain,
-                                             bool legacy,
-                                             struct sysdb_ctx *ctx,
-                                             sysdb_callback_t fn,
-                                             void *ptr)
-{
-    struct sysdb_search_ctx *sctx;
-
-    sctx = talloc(mem_ctx, struct sysdb_search_ctx);
-    if (!sctx) {
-        return NULL;
-    }
-    sctx->dbctx = ctx;
-    sctx->callback = fn;
-    sctx->ptr = ptr;
-    sctx->res = talloc_zero(sctx, struct ldb_result);
-    if (!sctx->res) {
-        talloc_free(sctx);
-        return NULL;
-    }
-    sctx->domain = talloc_strdup(sctx, domain);
-    if (!sctx->domain) {
-        talloc_free(sctx);
-        return NULL;
-    }
-    sctx->legacy = legacy;
-
-    return sctx;
-}
-
-/* users */
-
-static int pwd_search(struct sysdb_search_ctx *sctx,
-                      struct sysdb_ctx *ctx,
-                      const char *expression)
-{
-    static const char *attrs[] = SYSDB_PW_ATTRS;
-    struct ldb_request *req;
-    struct ldb_dn *base_dn;
-    int ret;
-
-    base_dn = ldb_dn_new_fmt(sctx, ctx->ldb,
-                             SYSDB_TMPL_USER_BASE, sctx->domain);
-    if (!base_dn) {
-        return ENOMEM;
-    }
-
-    ret = ldb_build_search_req(&req, ctx->ldb, sctx,
-                               base_dn, LDB_SCOPE_SUBTREE,
-                               expression, attrs, NULL,
-                               sctx, get_gen_callback,
-                               NULL);
-    if (ret != LDB_SUCCESS) {
-        return sysdb_error_to_errno(ret);
-    }
-
-    ret = ldb_request(ctx->ldb, req);
-    if (ret != LDB_SUCCESS) {
-        return sysdb_error_to_errno(ret);
-    }
-
-    return EOK;
-}
-
-int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
-                   struct sysdb_ctx *ctx,
-                   const char *domain,
-                   const char *name,
-                   bool legacy,
-                   sysdb_callback_t fn, void *ptr)
-{
-    struct sysdb_search_ctx *sctx;
-    char *expression;
-
-    if (!domain) {
-        return EINVAL;
-    }
-
-    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
-    if (!sctx) {
-        return ENOMEM;
-    }
-
-    expression = talloc_asprintf(sctx, SYSDB_PWNAM_FILTER, name);
-    if (!expression) {
-        talloc_free(sctx);
-        return ENOMEM;
-    }
-
-    return pwd_search(sctx, ctx, expression);
-}
-
-int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
-                   struct sysdb_ctx *ctx,
-                   const char *domain,
-                   uid_t uid,
-                   bool legacy,
-                   sysdb_callback_t fn, void *ptr)
-{
-    struct sysdb_search_ctx *sctx;
-    unsigned long int filter_uid = uid;
-    char *expression;
-
-    if (!domain) {
-        return EINVAL;
-    }
-
-    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
-    if (!sctx) {
-        return ENOMEM;
-    }
-
-    expression = talloc_asprintf(sctx, SYSDB_PWUID_FILTER, filter_uid);
-    if (!expression) {
-        talloc_free(sctx);
-        return ENOMEM;
-    }
-
-    return pwd_search(sctx, ctx, expression);
-}
-
-int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
-                    struct tevent_context *ev,
-                    struct sysdb_ctx *ctx,
-                    const char *domain,
-                    bool legacy,
-                    sysdb_callback_t fn, void *ptr)
-{
-    struct sysdb_search_ctx *sctx;
-
-    if (!domain) {
-        return EINVAL;
-    }
-
-    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
-    if (!sctx) {
-        return ENOMEM;
-    }
-
-    return pwd_search(sctx, ctx, SYSDB_PWENT_FILTER);
-}
-
-/* groups */
-
-struct get_mem_ctx {
-    struct sysdb_search_ctx *ret_sctx;
-    struct ldb_message **grps;
-    int num_grps;
-};
-
-static void get_members(void *ptr, int status, struct ldb_result *res)
-{
-    struct sysdb_ctx *ctx;
-    struct sysdb_search_ctx *sctx;
-    struct get_mem_ctx *gmctx;
-    struct sysdb_search_ctx *mem_sctx;
-    struct ldb_request *req;
-    struct ldb_message *msg;
-    struct ldb_result *ret_res;
-    struct ldb_dn *dn;
-    static const char *attrs[] = SYSDB_GRPW_ATTRS;
-    const char *expression;
-    int ret, i;
-
-    sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
-    gmctx = talloc_get_type(sctx->ptr, struct get_mem_ctx);
-    ctx = sctx->dbctx;
-
-    if (status != LDB_SUCCESS) {
-        return request_error(gmctx->ret_sctx, status);
-    }
-
-    ret_res = gmctx->ret_sctx->res;
-
-    /* append previous search results to final (if any) */
-    if (res && res->count != 0) {
-        ret_res->msgs = talloc_realloc(ret_res, ret_res->msgs,
-                                       struct ldb_message *,
-                                       ret_res->count + res->count + 1);
-        for(i = 0; i < res->count; i++) {
-            ret_res->msgs[ret_res->count] = talloc_steal(ret_res, res->msgs[i]);
-            ret_res->count++;
-        }
-        ret_res->msgs[ret_res->count] = NULL;
-    }
-
-    if (gmctx->grps[0] == NULL) {
-        return request_done(gmctx->ret_sctx);
-    }
-
-    mem_sctx = init_src_ctx(gmctx, sctx->domain, sctx->legacy,
-                            ctx, get_members, sctx);
-    if (!mem_sctx) {
-        return request_error(gmctx->ret_sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    /* fetch next group to search for members */
-    gmctx->num_grps--;
-    msg = gmctx->grps[gmctx->num_grps];
-    gmctx->grps[gmctx->num_grps] = NULL;
-
-    /* queue the group entry on the final result structure */
-    ret_res->msgs = talloc_realloc(ret_res, ret_res->msgs,
-                                   struct ldb_message *,
-                                   ret_res->count + 2);
-    if (!ret_res->msgs) {
-        return request_error(gmctx->ret_sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-    ret_res->msgs[ret_res->count + 1] = NULL;
-    ret_res->msgs[ret_res->count] = talloc_steal(ret_res->msgs, msg);
-    ret_res->count++;
-
-    /* search for this group members */
-    expression = talloc_asprintf(mem_sctx, SYSDB_GRNA2_FILTER,
-                                 ldb_dn_get_linearized(msg->dn));
-    if (!expression) {
-        return request_error(gmctx->ret_sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    dn = ldb_dn_new_fmt(mem_sctx, ctx->ldb,
-                        SYSDB_TMPL_USER_BASE, sctx->domain);
-    if (!dn) {
-        return request_error(gmctx->ret_sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    ret = ldb_build_search_req(&req, ctx->ldb, mem_sctx,
-                               dn, LDB_SCOPE_SUBTREE,
-                               expression, attrs, NULL,
-                               mem_sctx, get_gen_callback,
-                               NULL);
-    if (ret != LDB_SUCCESS) {
-        return request_error(gmctx->ret_sctx, ret);
-    }
-
-    ret = ldb_request(ctx->ldb, req);
-    if (ret != LDB_SUCCESS) {
-        return request_error(gmctx->ret_sctx, ret);
-    }
-}
-
-static int get_grp_callback(struct ldb_request *req,
-                            struct ldb_reply *ares)
-{
-    struct sysdb_search_ctx *sctx;
-    struct sysdb_ctx *ctx;
-    struct ldb_result *res;
-    int n;
-
-    sctx = talloc_get_type(req->context, struct sysdb_search_ctx);
-    ctx = sctx->dbctx;
-    res = sctx->res;
-
-    if (!ares) {
-        request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-        return LDB_ERR_OPERATIONS_ERROR;
-    }
-    if (ares->error != LDB_SUCCESS) {
-        request_error(sctx, ares->error);
-        return ares->error;
-    }
-
-    switch (ares->type) {
-    case LDB_REPLY_ENTRY:
-        res->msgs = talloc_realloc(res, res->msgs,
-                                   struct ldb_message *,
-                                   res->count + 2);
-        if (!res->msgs) {
-            request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-            return LDB_ERR_OPERATIONS_ERROR;
-        }
-
-        res->msgs[res->count + 1] = NULL;
-
-        res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
-        res->count++;
-        break;
-
-    case LDB_REPLY_REFERRAL:
-        if (res->refs) {
-            for (n = 0; res->refs[n]; n++) /*noop*/ ;
-        } else {
-            n = 0;
-        }
-
-        res->refs = talloc_realloc(res, res->refs, char *, n + 2);
-        if (! res->refs) {
-            request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-            return LDB_ERR_OPERATIONS_ERROR;
-        }
-
-        res->refs[n] = talloc_steal(res->refs, ares->referral);
-        res->refs[n + 1] = NULL;
-        break;
-
-    case LDB_REPLY_DONE:
-        res->controls = talloc_steal(res, ares->controls);
-
-        /* no results, return */
-        if (res->count == 0) {
-            request_done(sctx);
-            return LDB_SUCCESS;
-        }
-        if (res->count > 0) {
-            struct get_mem_ctx *gmctx;
-
-            gmctx = talloc_zero(req, struct get_mem_ctx);
-            if (!gmctx) {
-                request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-                return LDB_ERR_OPERATIONS_ERROR;
-            }
-            gmctx->ret_sctx = sctx;
-            gmctx->grps = talloc_steal(gmctx, res->msgs);
-            gmctx->num_grps = res->count;
-            res->msgs = NULL;
-            res->count = 0;
-
-            /* re-use sctx to create a fake handler for the first call to
-             * get_members() */
-            sctx = init_src_ctx(gmctx,
-                                sctx->domain, sctx->legacy,
-                                ctx, get_members, gmctx);
-
-            get_members(sctx, LDB_SUCCESS, NULL);
-            return LDB_SUCCESS;
-        }
-
-        /* anything else is an error */
-        request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-        return LDB_ERR_OPERATIONS_ERROR;
-    }
-
-    talloc_free(ares);
-    return LDB_SUCCESS;
-}
-
-static int grp_search(struct sysdb_search_ctx *sctx,
-                      struct sysdb_ctx *ctx,
-                      const char *expression)
-{
-    ldb_request_callback_t callback;
-    static const char *attrs[] = SYSDB_GRNAM_ATTRS;
-    struct ldb_request *req;
-    struct ldb_dn *base_dn;
-    int ret;
-
-    if (sctx->legacy) {
-        callback = get_gen_callback;
-    } else {
-        callback = get_grp_callback;
-    }
-
-    base_dn = ldb_dn_new_fmt(sctx, ctx->ldb,
-                             SYSDB_TMPL_GROUP_BASE, sctx->domain);
-    if (!base_dn) {
-        return ENOMEM;
-    }
-
-    ret = ldb_build_search_req(&req, ctx->ldb, sctx,
-                               base_dn, LDB_SCOPE_SUBTREE,
-                               expression, attrs, NULL,
-                               sctx, callback,
-                               NULL);
-    if (ret != LDB_SUCCESS) {
-        return sysdb_error_to_errno(ret);
-    }
-
-    ret = ldb_request(ctx->ldb, req);
-    if (ret != LDB_SUCCESS) {
-        return sysdb_error_to_errno(ret);
-    }
-
-    return EOK;
-}
-
-int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
-                   struct sysdb_ctx *ctx,
-                   const char *domain,
-                   const char *name,
-                   bool legacy,
-                   sysdb_callback_t fn, void *ptr)
-{
-    struct sysdb_search_ctx *sctx;
-    char *expression;
-
-    if (!domain) {
-        return EINVAL;
-    }
-
-    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
-    if (!sctx) {
-        return ENOMEM;
-    }
-
-    expression = talloc_asprintf(sctx, SYSDB_GRNAM_FILTER, name);
-    if (!expression) {
-        talloc_free(sctx);
-        return ENOMEM;
-    }
-
-    return grp_search(sctx, ctx, expression);
-}
-
-int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
-                   struct sysdb_ctx *ctx,
-                   const char *domain,
-                   gid_t gid,
-                   bool legacy,
-                   sysdb_callback_t fn, void *ptr)
-{
-    struct sysdb_search_ctx *sctx;
-    unsigned long int filter_gid = gid;
-    char *expression;
-
-    if (!domain) {
-        return EINVAL;
-    }
-
-    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
-    if (!sctx) {
-        return ENOMEM;
-    }
-
-    expression = talloc_asprintf(sctx, SYSDB_GRGID_FILTER, filter_gid);
-    if (!expression) {
-        talloc_free(sctx);
-        return ENOMEM;
-    }
-
-    return grp_search(sctx, ctx, expression);
-}
-
-int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
-                    struct tevent_context *ev,
-                    struct sysdb_ctx *ctx,
-                    const char *domain,
-                    bool legacy,
-                    sysdb_callback_t fn, void *ptr)
-{
-    struct sysdb_search_ctx *sctx;
-
-    if (!domain) {
-        return EINVAL;
-    }
-
-    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
-    if (!sctx) {
-        return ENOMEM;
-    }
-
-    return grp_search(sctx, ctx, SYSDB_GRENT_FILTER);
-}
-
-static void sysdb_initgr_legacy(void *ptr, int status,
-                                struct ldb_result *res)
-{
-    struct sysdb_ctx *ctx;
-    struct sysdb_search_ctx *sctx;
-    char *expression;
-    struct ldb_request *req;
-    struct ldb_dn *base_dn;
-    static const char *attrs[] = SYSDB_INITGR_ATTRS;
-    const char *userid;
-    int ret;
-
-    sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
-    ctx = sctx->dbctx;
-
-    if (res->count == 0) {
-        return request_done(sctx);
-    }
-    if (res->count > 1) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    userid = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PW_NAME, NULL);
-    if (!userid) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    expression = talloc_asprintf(sctx, SYSDB_INITGR_LEGACY_FILTER, userid);
-    if (!expression) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    base_dn = ldb_dn_new_fmt(sctx, ctx->ldb,
-                             SYSDB_TMPL_GROUP_BASE, sctx->domain);
-    if (!base_dn) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    ret = ldb_build_search_req(&req, ctx->ldb, sctx,
-                               base_dn, LDB_SCOPE_SUBTREE,
-                               expression, attrs, NULL,
-                               sctx, get_gen_callback,
-                               NULL);
-    if (ret != LDB_SUCCESS) {
-        return request_error(sctx, ret);
-    }
-
-    ret = ldb_request(ctx->ldb, req);
-    if (ret != LDB_SUCCESS) {
-        return request_error(sctx, ret);
-    }
-}
-
-static void sysdb_initgr_search(void *ptr, int status,
-                                struct ldb_result *res)
-{
-    struct sysdb_ctx *ctx;
-    struct sysdb_search_ctx *sctx;
-    char *expression;
-    struct ldb_request *req;
-    struct ldb_control **ctrl;
-    struct ldb_asq_control *control;
-    static const char *attrs[] = SYSDB_INITGR_ATTRS;
-    int ret;
-
-    sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
-    ctx = sctx->dbctx;
-
-    if (res->count == 0) {
-        return request_done(sctx);
-    }
-    if (res->count > 1) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    expression = talloc_asprintf(sctx, SYSDB_INITGR_FILTER);
-    if (!expression) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-
-    ctrl = talloc_array(sctx, struct ldb_control *, 2);
-    if (!ctrl) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-    ctrl[1] = NULL;
-    ctrl[0] = talloc(ctrl, struct ldb_control);
-    if (!ctrl[0]) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-    ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
-    ctrl[0]->critical = 1;
-    control = talloc(ctrl[0], struct ldb_asq_control);
-    if (!control) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-    control->request = 1;
-    control->source_attribute = talloc_strdup(control, SYSDB_INITGR_ATTR);
-    if (!control->source_attribute) {
-        return request_error(sctx, LDB_ERR_OPERATIONS_ERROR);
-    }
-    control->src_attr_len = strlen(control->source_attribute);
-    ctrl[0]->data = control;
-
-    ret = ldb_build_search_req(&req, ctx->ldb, sctx,
-                               res->msgs[0]->dn,
-                               LDB_SCOPE_BASE,
-                               expression, attrs, ctrl,
-                               sctx, get_gen_callback,
-                               NULL);
-    if (ret != LDB_SUCCESS) {
-        return request_error(sctx, ret);
-    }
-
-    ret = ldb_request(ctx->ldb, req);
-    if (ret != LDB_SUCCESS) {
-        return request_error(sctx, ret);
-    }
-}
-
-int sysdb_initgroups(TALLOC_CTX *mem_ctx,
-                     struct tevent_context *ev,
-                     struct sysdb_ctx *ctx,
-                     const char *domain,
-                     const char *name,
-                     bool legacy,
-                     sysdb_callback_t fn, void *ptr)
-{
-    sysdb_callback_t second_callback;
-    static const char *attrs[] = SYSDB_PW_ATTRS;
-    struct sysdb_search_ctx *ret_sctx;
-    struct sysdb_search_ctx *sctx;
-    char *expression;
-    struct ldb_request *req;
-    struct ldb_dn *base_dn;
-    int ret;
-
-    if (!domain) {
-        return EINVAL;
-    }
-
-    ret_sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
-    if (!ret_sctx) {
-        return ENOMEM;
-    }
-
-    if (legacy) {
-        second_callback = sysdb_initgr_legacy;
-    } else {
-        second_callback = sysdb_initgr_search;
-    }
-
-    sctx = init_src_ctx(ret_sctx, domain, legacy,
-                        ctx, second_callback, ret_sctx);
-    if (!sctx) {
-        talloc_free(ret_sctx);
-        return ENOMEM;
-    }
-
-    expression = talloc_asprintf(sctx, SYSDB_PWNAM_FILTER, name);
-    if (!expression) {
-        talloc_free(ret_sctx);
-        return ENOMEM;
-    }
-
-    base_dn = ldb_dn_new_fmt(sctx, ctx->ldb, SYSDB_TMPL_USER_BASE, domain);
-    if (!base_dn) {
-        talloc_free(ret_sctx);
-        return ENOMEM;
-    }
-
-    ret = ldb_build_search_req(&req, ctx->ldb, sctx,
-                               base_dn, LDB_SCOPE_SUBTREE,
-                               expression, attrs, NULL,
-                               sctx, get_gen_callback,
-                               NULL);
-    if (ret != LDB_SUCCESS) {
-        return sysdb_error_to_errno(ret);
-    }
-
-    ret = ldb_request(ctx->ldb, req);
-    if (ret != LDB_SUCCESS) {
-        return sysdb_error_to_errno(ret);
-    }
-
-    return LDB_SUCCESS;
-}
+/************************************************
+ * Initialiazation stuff
+ */
 
 static int sysdb_read_var(TALLOC_CTX *mem_ctx,
                           struct confdb_ctx *cdb,
@@ -896,15 +166,18 @@ int sysdb_init(TALLOC_CTX *mem_ctx,
                struct tevent_context *ev,
                struct confdb_ctx *cdb,
                const char *alt_db_path,
-               struct sysdb_ctx **dbctx)
+               struct sysdb_ctx **_ctx)
 {
     struct sysdb_ctx *ctx;
     int ret;
 
+    if (!ev) return EINVAL;
+
     ctx = talloc_zero(mem_ctx, struct sysdb_ctx);
     if (!ctx) {
         return ENOMEM;
     }
+    ctx->ev = ev;
 
     if (!alt_db_path) {
         ret = sysdb_get_db_path(ctx, cdb, &ctx->ldb_file);
@@ -938,7 +211,7 @@ int sysdb_init(TALLOC_CTX *mem_ctx,
         return ret;
     }
 
-    *dbctx = ctx;
+    *_ctx = ctx;
 
     return EOK;
 }
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index c6cc4de..c0ef361 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -23,7 +23,6 @@
 #define __SYS_DB_H__
 
 #include "ldb.h"
-#include "ldb_errors.h"
 
 #define SYSDB_CONF_SECTION "config/sysdb"
 #define SYSDB_FILE "sssd.ldb"
@@ -77,12 +76,8 @@
 #define SYSDB_INITGR_ATTRS {SYSDB_GR_GIDNUM, SYSDB_LAST_UPDATE, \
                             NULL}
 
-struct sysdb_ctx {
-    struct ldb_context *ldb;
-    char *ldb_file;
-};
-
 struct confdb_ctx;
+struct sysdb_ctx;
 
 typedef void (*sysdb_callback_t)(void *, int, struct ldb_result *);
 
@@ -93,7 +88,6 @@ int sysdb_init(TALLOC_CTX *mem_ctx,
                struct sysdb_ctx **dbctx);
 
 int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
                    struct sysdb_ctx *ctx,
                    const char *domain,
                    const char *name,
@@ -101,7 +95,6 @@ int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
                    sysdb_callback_t fn, void *ptr);
 
 int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
                    struct sysdb_ctx *ctx,
                    const char *domain,
                    uid_t uid,
@@ -109,14 +102,12 @@ int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
                    sysdb_callback_t fn, void *ptr);
 
 int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
-                    struct tevent_context *ev,
                     struct sysdb_ctx *ctx,
                     const char *domain,
                     bool legacy,
                     sysdb_callback_t fn, void *ptr);
 
 int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
                    struct sysdb_ctx *ctx,
                    const char *domain,
                    const char *name,
@@ -124,7 +115,6 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
                    sysdb_callback_t fn, void *ptr);
 
 int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
-                   struct tevent_context *ev,
                    struct sysdb_ctx *ctx,
                    const char *domain,
                    gid_t gid,
@@ -132,14 +122,12 @@ int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
                    sysdb_callback_t fn, void *ptr);
 
 int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
-                    struct tevent_context *ev,
                     struct sysdb_ctx *ctx,
                     const char *domain,
                     bool legacy,
                     sysdb_callback_t fn, void *ptr);
 
 int sysdb_initgroups(TALLOC_CTX *mem_ctx,
-                     struct tevent_context *ev,
                      struct sysdb_ctx *ctx,
                      const char *domain,
                      const char *name,
diff --git a/server/db/sysdb_internal.h b/server/db/sysdb_internal.h
deleted file mode 100644
index 719f660..0000000
--- a/server/db/sysdb_internal.h
+++ /dev/null
@@ -1,70 +0,0 @@
-
-/*
-   SSSD
-
-   Private System Database Header
-
-   Copyright (C) Simo Sorce <ssorce at redhat.com>	2008
-
-   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/>.
-*/
-
-#ifndef __INT_SYS_DB_H__
-#define __INT_SYS_DB_H__
-
-#define SYSDB_VERSION "0.1"
-
-#define SYSDB_BASE_LDIF \
-     "dn: @ATTRIBUTES\n" \
-     "userPrincipalName: CASE_INSENSITIVE\n" \
-     "cn: CASE_INSENSITIVE\n" \
-     "dc: CASE_INSENSITIVE\n" \
-     "dn: CASE_INSENSITIVE\n" \
-     "name: CASE_INSENSITIVE\n" \
-     "objectclass: CASE_INSENSITIVE\n" \
-     "\n" \
-     "dn: @INDEXLIST\n" \
-     "@IDXATTR: cn\n" \
-     "@IDXATTR: objectclass\n" \
-     "@IDXATTR: member\n" \
-     "@IDXATTR: memberof\n" \
-     "@IDXATTR: memberuid\n" \
-     "@IDXATTR: uid\n" \
-     "@IDXATTR: gid\n" \
-     "@IDXATTR: uidNumber\n" \
-     "@IDXATTR: gidNumber\n" \
-     "@IDXATTR: lastUpdate\n" \
-     "\n" \
-     "dn: @MODULES\n" \
-     "@LIST: asq,memberof\n" \
-     "\n" \
-     "dn: cn=sysdb\n" \
-     "cn: sysdb\n" \
-     "version: 0.1\n" \
-     "description: base object\n" \
-     "\n" \
-     "dn: cn=LOCAL,cn=sysdb\n" \
-     "cn: local\n" \
-     "description: Local system data\n" \
-     "\n" \
-     "dn: cn=Users,cn=LOCAL,cn=sysdb\n" \
-     "cn: users\n" \
-     "description: Local POSIX users\n" \
-     "\n" \
-     "dn: cn=Groups,cn=LOCAL,cn=sysdb\n" \
-     "cn: groups\n" \
-     "description: Local POSIX groups\n" \
-     "\n"
-
-#endif /* __INT_SYS_DB_H__ */
diff --git a/server/db/sysdb_private.h b/server/db/sysdb_private.h
new file mode 100644
index 0000000..c649af4
--- /dev/null
+++ b/server/db/sysdb_private.h
@@ -0,0 +1,95 @@
+
+/*
+   SSSD
+
+   Private System Database Header
+
+   Copyright (C) Simo Sorce <ssorce at redhat.com>	2008
+
+   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/>.
+*/
+
+#ifndef __INT_SYS_DB_H__
+#define __INT_SYS_DB_H__
+
+#define SYSDB_VERSION "0.1"
+
+#define SYSDB_BASE_LDIF \
+     "dn: @ATTRIBUTES\n" \
+     "userPrincipalName: CASE_INSENSITIVE\n" \
+     "cn: CASE_INSENSITIVE\n" \
+     "dc: CASE_INSENSITIVE\n" \
+     "dn: CASE_INSENSITIVE\n" \
+     "name: CASE_INSENSITIVE\n" \
+     "objectclass: CASE_INSENSITIVE\n" \
+     "\n" \
+     "dn: @INDEXLIST\n" \
+     "@IDXATTR: cn\n" \
+     "@IDXATTR: objectclass\n" \
+     "@IDXATTR: member\n" \
+     "@IDXATTR: memberof\n" \
+     "@IDXATTR: memberuid\n" \
+     "@IDXATTR: uid\n" \
+     "@IDXATTR: gid\n" \
+     "@IDXATTR: uidNumber\n" \
+     "@IDXATTR: gidNumber\n" \
+     "@IDXATTR: lastUpdate\n" \
+     "\n" \
+     "dn: @MODULES\n" \
+     "@LIST: asq,memberof\n" \
+     "\n" \
+     "dn: cn=sysdb\n" \
+     "cn: sysdb\n" \
+     "version: 0.1\n" \
+     "description: base object\n" \
+     "\n" \
+     "dn: cn=LOCAL,cn=sysdb\n" \
+     "cn: local\n" \
+     "description: Local system data\n" \
+     "\n" \
+     "dn: cn=Users,cn=LOCAL,cn=sysdb\n" \
+     "cn: users\n" \
+     "description: Local POSIX users\n" \
+     "\n" \
+     "dn: cn=Groups,cn=LOCAL,cn=sysdb\n" \
+     "cn: groups\n" \
+     "description: Local POSIX groups\n" \
+     "\n"
+
+#include "db/sysdb.h"
+
+struct sysdb_req;
+
+struct sysdb_ctx {
+    struct tevent_context *ev;
+    struct ldb_context *ldb;
+    char *ldb_file;
+    struct sysdb_req *queue;
+};
+
+typedef void (*sysdb_req_fn_t)(struct sysdb_req *, void *pvt);
+
+int sysdb_error_to_errno(int ldberr);
+
+int sysdb_transaction(TALLOC_CTX *mem_ctx,
+                      struct sysdb_ctx *ctx,
+                      sysdb_req_fn_t fn, void *pvt);
+void sysdb_transaction_done(struct sysdb_req *req, int status);
+
+int sysdb_operation(TALLOC_CTX *mem_ctx,
+                      struct sysdb_ctx *ctx,
+                      sysdb_req_fn_t fn, void *pvt);
+void sysdb_operation_done(struct sysdb_req *req);
+
+#endif /* __INT_SYS_DB_H__ */
diff --git a/server/db/sysdb_req.c b/server/db/sysdb_req.c
new file mode 100644
index 0000000..fcbd17b
--- /dev/null
+++ b/server/db/sysdb_req.c
@@ -0,0 +1,241 @@
+/*
+   SSSD
+
+   System Database
+
+   Copyright (C) Simo Sorce <ssorce at 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_req {
+    struct sysdb_req *next, *prev;
+    struct sysdb_ctx *ctx;
+    sysdb_req_fn_t fn;
+    void *pvt;
+    int status;
+    bool transaction_active;
+};
+
+static void sysdb_req_run(struct tevent_context *ev,
+                          struct tevent_timer *te,
+                          struct timeval tv, void *ptr)
+{
+    struct sysdb_req *req = talloc_get_type(ptr, struct sysdb_req);
+
+    if (req != req->ctx->queue) abort();
+
+    req->fn(req, req->pvt);
+}
+
+static int sysdb_req_schedule(struct sysdb_req *req)
+{
+    struct tevent_timer *te = NULL;
+    struct timeval tv;
+
+    /* call it asap */
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    te = tevent_add_timer(req->ctx->ev, req, tv, sysdb_req_run, req);
+    if (te == NULL) {
+        return EIO;
+    }
+
+    return EOK;
+}
+
+static int sysdb_req_enqueue(struct sysdb_req *req)
+{
+    int ret = EOK;
+
+    DLIST_ADD_END(req->ctx->queue, req, struct sysdb_req *);
+
+    if (req->ctx->queue == req) {
+        ret = sysdb_req_schedule(req);
+    }
+
+    return ret;
+}
+
+static void sysdb_transaction_end(struct sysdb_req *req);
+
+static int sysdb_req_destructor(void *ptr)
+{
+    struct sysdb_req *req;
+    int ret;
+
+    req = talloc_get_type(ptr, struct sysdb_req);
+
+    if (req->ctx->queue != req) {
+        DLIST_REMOVE(req->ctx->queue, req);
+        return 0;
+    }
+
+    /* req is the currently running operation or
+     * scheduled to run operation */
+
+    if (req->transaction_active) {
+        /* freeing before the transaction is complete */
+        req->status = ETIMEDOUT;
+        sysdb_transaction_end(req);
+    }
+
+    DLIST_REMOVE(req->ctx->queue, req);
+
+    /* make sure we schedule the next in line if any */
+    if (req->ctx->queue) {
+        ret = sysdb_req_schedule(req->ctx->queue);
+        if (ret != EOK) abort();
+    }
+
+    return 0;
+}
+
+static struct sysdb_req *sysdb_new_req(TALLOC_CTX *memctx,
+                                       struct sysdb_ctx *ctx,
+                                       sysdb_req_fn_t fn, void *pvt)
+{
+    struct sysdb_req *req;
+
+    req = talloc_zero(memctx, struct sysdb_req);
+    if (!req) return NULL;
+
+    req->ctx = ctx;
+    req->fn = fn;
+    req->pvt = pvt;
+
+    talloc_set_destructor((TALLOC_CTX *)req, sysdb_req_destructor);
+
+    return req;
+}
+
+static void sysdb_transaction_int(struct sysdb_req *intreq, void *pvt)
+{
+    struct sysdb_req *req = talloc_get_type(pvt, struct sysdb_req);
+    int ret;
+
+    /* first of all swap this internal request with the real one on the queue
+     * otherwise request_done() will later abort */
+    DLIST_REMOVE(req->ctx->queue, intreq);
+    DLIST_ADD(req->ctx->queue, req);
+
+    if (intreq->status != EOK) {
+        req->status = intreq->status;
+        req->fn(req, req->pvt);
+        return;
+    }
+
+    ret = ldb_transaction_start(req->ctx->ldb);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
+        req->status = sysdb_error_to_errno(ret);
+    }
+    req->transaction_active = true;
+
+    req->fn(req, req->pvt);
+}
+
+static void sysdb_transaction_end(struct sysdb_req *req)
+{
+    int ret;
+
+    if (req->status == EOK) {
+        ret = ldb_transaction_commit(req->ctx->ldb);
+        if (ret != LDB_SUCCESS) {
+            DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
+        }
+    } else {
+        DEBUG(4, ("Canceling transaction (%d[%s)\n",
+                  req->status, strerror(req->status)));
+        ret = ldb_transaction_cancel(req->ctx->ldb);
+        if (ret != LDB_SUCCESS) {
+            DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
+            /* FIXME: abort() ? */
+        }
+    }
+    req->transaction_active = false;
+}
+
+int sysdb_transaction(TALLOC_CTX *memctx, struct sysdb_ctx *ctx,
+                      sysdb_req_fn_t fn, void *pvt)
+{
+    struct sysdb_req *req, *intreq;
+
+    req = sysdb_new_req(memctx, ctx, fn, pvt);
+    if (!req) return ENOMEM;
+
+    intreq = sysdb_new_req(req, ctx, sysdb_transaction_int, req);
+    if (!intreq) {
+        talloc_free(intreq);
+        return ENOMEM;
+    }
+
+    return sysdb_req_enqueue(intreq);
+}
+
+void sysdb_transaction_done(struct sysdb_req *req, int status)
+{
+    int ret;
+
+    if (req->ctx->queue != req) abort();
+    if (!req->transaction_active) abort();
+
+    req->status = status;
+
+    sysdb_transaction_end(req);
+
+    DLIST_REMOVE(req->ctx->queue, req);
+
+    if (req->ctx->queue) {
+        ret = sysdb_req_schedule(req->ctx->queue);
+        if (ret != EOK) abort();
+    }
+
+    talloc_free(req);
+}
+
+int sysdb_operation(TALLOC_CTX *memctx, struct sysdb_ctx *ctx,
+                    sysdb_req_fn_t fn, void *pvt)
+{
+    struct sysdb_req *req;
+
+    req = sysdb_new_req(memctx, ctx, fn, pvt);
+    if (!req) return ENOMEM;
+
+    return sysdb_req_enqueue(req);
+}
+
+void sysdb_operation_done(struct sysdb_req *req)
+{
+    int ret;
+
+    if (req->ctx->queue != req) abort();
+
+    DLIST_REMOVE(req->ctx->queue, req);
+
+    if (req->ctx->queue) {
+        ret = sysdb_req_schedule(req->ctx->queue);
+        if (ret != EOK) abort();
+    }
+
+    talloc_free(req);
+}
+
diff --git a/server/db/sysdb_search.c b/server/db/sysdb_search.c
new file mode 100644
index 0000000..5a355a0
--- /dev/null
+++ b/server/db/sysdb_search.c
@@ -0,0 +1,731 @@
+/*
+   SSSD
+
+   System Database
+
+   Copyright (C) Simo Sorce <ssorce at redhat.com>	2008
+
+   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 "util/util.h"
+#include "db/sysdb_private.h"
+#include "confdb/confdb.h"
+#include <time.h>
+
+struct sysdb_search_ctx;
+
+typedef void (*gen_callback)(struct sysdb_search_ctx *);
+
+struct sysdb_search_ctx {
+    struct sysdb_ctx *ctx;
+    struct sysdb_req *req;
+
+    const char *expression;
+    const char *domain;
+    bool legacy;
+
+    sysdb_callback_t callback;
+    void *ptr;
+
+    gen_callback gen_aux_fn;
+
+    struct get_mem_ctx *gmctx;
+
+    struct ldb_result *res;
+};
+
+static struct sysdb_search_ctx *init_src_ctx(TALLOC_CTX *mem_ctx,
+                                             const char *domain,
+                                             bool legacy,
+                                             struct sysdb_ctx *ctx,
+                                             sysdb_callback_t fn,
+                                             void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+
+    sctx = talloc_zero(mem_ctx, struct sysdb_search_ctx);
+    if (!sctx) {
+        return NULL;
+    }
+    sctx->ctx = ctx;
+    sctx->callback = fn;
+    sctx->ptr = ptr;
+    sctx->res = talloc_zero(sctx, struct ldb_result);
+    if (!sctx->res) {
+        talloc_free(sctx);
+        return NULL;
+    }
+    sctx->domain = talloc_strdup(sctx, domain);
+    if (!sctx->domain) {
+        talloc_free(sctx);
+        return NULL;
+    }
+    sctx->legacy = legacy;
+
+    return sctx;
+}
+
+int sysdb_error_to_errno(int ldberr)
+{
+    /* fake it up for now, requires a mapping table */
+    return EIO;
+}
+
+static void request_ldberror(struct sysdb_search_ctx *sctx, int error)
+{
+    sysdb_operation_done(sctx->req);
+    sctx->callback(sctx->ptr, sysdb_error_to_errno(error), NULL);
+}
+
+static void request_error(struct sysdb_search_ctx *sctx, int error)
+{
+    sysdb_operation_done(sctx->req);
+    sctx->callback(sctx->ptr, error, NULL);
+}
+
+static void request_done(struct sysdb_search_ctx *sctx)
+{
+    sysdb_operation_done(sctx->req);
+    sctx->callback(sctx->ptr, EOK, sctx->res);
+}
+
+static int get_gen_callback(struct ldb_request *req,
+                            struct ldb_reply *ares)
+{
+    struct sysdb_search_ctx *sctx;
+    struct ldb_result *res;
+    int n;
+
+    sctx = talloc_get_type(req->context, struct sysdb_search_ctx);
+    res = sctx->res;
+
+    if (!ares) {
+        request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+        return LDB_ERR_OPERATIONS_ERROR;
+    }
+    if (ares->error != LDB_SUCCESS) {
+        request_ldberror(sctx, ares->error);
+        return ares->error;
+    }
+
+    switch (ares->type) {
+    case LDB_REPLY_ENTRY:
+        res->msgs = talloc_realloc(res, res->msgs,
+                                   struct ldb_message *,
+                                   res->count + 2);
+        if (!res->msgs) {
+            request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+            return LDB_ERR_OPERATIONS_ERROR;
+        }
+
+        res->msgs[res->count + 1] = NULL;
+
+        res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+        res->count++;
+        break;
+
+    case LDB_REPLY_REFERRAL:
+        if (res->refs) {
+            for (n = 0; res->refs[n]; n++) /*noop*/ ;
+        } else {
+            n = 0;
+        }
+
+        res->refs = talloc_realloc(res, res->refs, char *, n + 2);
+        if (! res->refs) {
+            request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+            return LDB_ERR_OPERATIONS_ERROR;
+        }
+
+        res->refs[n] = talloc_steal(res->refs, ares->referral);
+        res->refs[n + 1] = NULL;
+        break;
+
+    case LDB_REPLY_DONE:
+        res->controls = talloc_steal(res, ares->controls);
+
+        /* check if we need to call any aux function */
+        if (sctx->gen_aux_fn) {
+            sctx->gen_aux_fn(sctx);
+        } else {
+            /* no aux functions, this means the request is done */
+            request_done(sctx);
+        }
+        return LDB_SUCCESS;
+    }
+
+    talloc_free(ares);
+    return LDB_SUCCESS;
+}
+
+/* users */
+
+static void pwd_search(struct sysdb_req *sysreq, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+    static const char *attrs[] = SYSDB_PW_ATTRS;
+    struct ldb_request *req;
+    struct ldb_dn *base_dn;
+    int ret;
+
+    sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
+    sctx->req = sysreq;
+
+    base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
+                             SYSDB_TMPL_USER_BASE, sctx->domain);
+    if (!base_dn) {
+        return request_error(sctx, ENOMEM);
+    }
+
+    ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx,
+                               base_dn, LDB_SCOPE_SUBTREE,
+                               sctx->expression, attrs, NULL,
+                               sctx, get_gen_callback,
+                               NULL);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+
+    ret = ldb_request(sctx->ctx->ldb, req);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+}
+
+int sysdb_getpwnam(TALLOC_CTX *mem_ctx,
+                   struct sysdb_ctx *ctx,
+                   const char *domain,
+                   const char *name,
+                   bool legacy,
+                   sysdb_callback_t fn, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+
+    if (!domain) {
+        return EINVAL;
+    }
+
+    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
+    if (!sctx) {
+        return ENOMEM;
+    }
+
+    sctx->expression = talloc_asprintf(sctx, SYSDB_PWNAM_FILTER, name);
+    if (!sctx->expression) {
+        talloc_free(sctx);
+        return ENOMEM;
+    }
+
+    return sysdb_operation(mem_ctx, ctx, pwd_search, sctx);
+}
+
+int sysdb_getpwuid(TALLOC_CTX *mem_ctx,
+                   struct sysdb_ctx *ctx,
+                   const char *domain,
+                   uid_t uid,
+                   bool legacy,
+                   sysdb_callback_t fn, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+    unsigned long int filter_uid = uid;
+
+    if (!domain) {
+        return EINVAL;
+    }
+
+    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
+    if (!sctx) {
+        return ENOMEM;
+    }
+
+    sctx->expression = talloc_asprintf(sctx, SYSDB_PWUID_FILTER, filter_uid);
+    if (!sctx->expression) {
+        talloc_free(sctx);
+        return ENOMEM;
+    }
+
+    return sysdb_operation(mem_ctx, ctx, pwd_search, sctx);
+}
+
+int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
+                    struct sysdb_ctx *ctx,
+                    const char *domain,
+                    bool legacy,
+                    sysdb_callback_t fn, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+
+    if (!domain) {
+        return EINVAL;
+    }
+
+    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
+    if (!sctx) {
+        return ENOMEM;
+    }
+
+    sctx->expression = SYSDB_PWENT_FILTER;
+
+    return sysdb_operation(mem_ctx, ctx, pwd_search, sctx);
+}
+
+/* groups */
+
+struct get_mem_ctx {
+    struct sysdb_search_ctx *ret_sctx;
+    struct ldb_message **grps;
+    int num_grps;
+};
+
+static void get_members(struct sysdb_search_ctx *sctx)
+{
+    struct get_mem_ctx *gmctx;
+    struct ldb_request *req;
+    struct ldb_message *msg;
+    struct ldb_dn *dn;
+    static const char *attrs[] = SYSDB_GRPW_ATTRS;
+    int ret;
+
+    gmctx = sctx->gmctx;
+
+    if (gmctx->grps[0] == NULL) {
+        return request_done(sctx);
+    }
+
+    /* fetch next group to search for members */
+    gmctx->num_grps--;
+    msg = gmctx->grps[gmctx->num_grps];
+    gmctx->grps[gmctx->num_grps] = NULL;
+
+    /* queue the group entry on the final result structure */
+    sctx->res->msgs = talloc_realloc(sctx->res, sctx->res->msgs,
+                                     struct ldb_message *,
+                                     sctx->res->count + 2);
+    if (!sctx->res->msgs) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+    sctx->res->msgs[sctx->res->count + 1] = NULL;
+    sctx->res->msgs[sctx->res->count] = talloc_steal(sctx->res->msgs, msg);
+    sctx->res->count++;
+
+    /* search for this group members */
+    sctx->expression = talloc_asprintf(sctx, SYSDB_GRNA2_FILTER,
+                                       ldb_dn_get_linearized(msg->dn));
+    if (!sctx->expression) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
+                        SYSDB_TMPL_USER_BASE, sctx->domain);
+    if (!dn) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    sctx->gen_aux_fn = get_members;
+
+    ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx,
+                               dn, LDB_SCOPE_SUBTREE,
+                               sctx->expression, attrs, NULL,
+                               sctx, get_gen_callback,
+                               NULL);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+
+    ret = ldb_request(sctx->ctx->ldb, req);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+}
+
+static int get_grp_callback(struct ldb_request *req,
+                            struct ldb_reply *ares)
+{
+    struct sysdb_search_ctx *sctx;
+    struct sysdb_ctx *ctx;
+    struct ldb_result *res;
+    int n;
+
+    sctx = talloc_get_type(req->context, struct sysdb_search_ctx);
+    ctx = sctx->ctx;
+    res = sctx->res;
+
+    if (!ares) {
+        request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+        return LDB_ERR_OPERATIONS_ERROR;
+    }
+    if (ares->error != LDB_SUCCESS) {
+        request_ldberror(sctx, ares->error);
+        return ares->error;
+    }
+
+    switch (ares->type) {
+    case LDB_REPLY_ENTRY:
+        res->msgs = talloc_realloc(res, res->msgs,
+                                   struct ldb_message *,
+                                   res->count + 2);
+        if (!res->msgs) {
+            request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+            return LDB_ERR_OPERATIONS_ERROR;
+        }
+
+        res->msgs[res->count + 1] = NULL;
+
+        res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+        res->count++;
+        break;
+
+    case LDB_REPLY_REFERRAL:
+        if (res->refs) {
+            for (n = 0; res->refs[n]; n++) /*noop*/ ;
+        } else {
+            n = 0;
+        }
+
+        res->refs = talloc_realloc(res, res->refs, char *, n + 2);
+        if (! res->refs) {
+            request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+            return LDB_ERR_OPERATIONS_ERROR;
+        }
+
+        res->refs[n] = talloc_steal(res->refs, ares->referral);
+        res->refs[n + 1] = NULL;
+        break;
+
+    case LDB_REPLY_DONE:
+        res->controls = talloc_steal(res, ares->controls);
+
+        /* no results, return */
+        if (res->count == 0) {
+            request_done(sctx);
+            return LDB_SUCCESS;
+        }
+        if (res->count > 0) {
+
+            sctx->gmctx = talloc_zero(req, struct get_mem_ctx);
+            if (!sctx->gmctx) {
+                request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+                return LDB_ERR_OPERATIONS_ERROR;
+            }
+            sctx->gmctx->grps = res->msgs;
+            sctx->gmctx->num_grps = res->count;
+            res->msgs = NULL;
+            res->count = 0;
+
+            /* now get members */
+            get_members(sctx);
+            return LDB_SUCCESS;
+        }
+
+        /* anything else is an error */
+        request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+        return LDB_ERR_OPERATIONS_ERROR;
+    }
+
+    talloc_free(ares);
+    return LDB_SUCCESS;
+}
+
+static void grp_search(struct sysdb_req *sysreq, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+    ldb_request_callback_t callback;
+    static const char *attrs[] = SYSDB_GRNAM_ATTRS;
+    struct ldb_request *req;
+    struct ldb_dn *base_dn;
+    int ret;
+
+    sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
+    sctx->req = sysreq;
+
+    if (sctx->legacy) {
+        callback = get_gen_callback;
+    } else {
+        callback = get_grp_callback;
+    }
+
+    base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
+                             SYSDB_TMPL_GROUP_BASE, sctx->domain);
+    if (!base_dn) {
+        return request_error(sctx, ENOMEM);
+    }
+
+    ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx,
+                               base_dn, LDB_SCOPE_SUBTREE,
+                               sctx->expression, attrs, NULL,
+                               sctx, callback,
+                               NULL);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+
+    ret = ldb_request(sctx->ctx->ldb, req);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+}
+
+int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
+                   struct sysdb_ctx *ctx,
+                   const char *domain,
+                   const char *name,
+                   bool legacy,
+                   sysdb_callback_t fn, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+
+    if (!domain) {
+        return EINVAL;
+    }
+
+    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
+    if (!sctx) {
+        return ENOMEM;
+    }
+
+    sctx->expression = talloc_asprintf(sctx, SYSDB_GRNAM_FILTER, name);
+    if (!sctx->expression) {
+        talloc_free(sctx);
+        return ENOMEM;
+    }
+
+    return sysdb_operation(mem_ctx, ctx, grp_search, sctx);
+}
+
+int sysdb_getgrgid(TALLOC_CTX *mem_ctx,
+                   struct sysdb_ctx *ctx,
+                   const char *domain,
+                   gid_t gid,
+                   bool legacy,
+                   sysdb_callback_t fn, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+    unsigned long int filter_gid = gid;
+
+    if (!domain) {
+        return EINVAL;
+    }
+
+    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
+    if (!sctx) {
+        return ENOMEM;
+    }
+
+    sctx->expression = talloc_asprintf(sctx, SYSDB_GRGID_FILTER, filter_gid);
+    if (!sctx->expression) {
+        talloc_free(sctx);
+        return ENOMEM;
+    }
+
+    return sysdb_operation(mem_ctx, ctx, grp_search, sctx);
+}
+
+int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
+                    struct sysdb_ctx *ctx,
+                    const char *domain,
+                    bool legacy,
+                    sysdb_callback_t fn, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+
+    if (!domain) {
+        return EINVAL;
+    }
+
+    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
+    if (!sctx) {
+        return ENOMEM;
+    }
+
+    sctx->expression = SYSDB_GRENT_FILTER;
+
+    return sysdb_operation(mem_ctx, ctx, grp_search, sctx);
+}
+
+static void initgr_mem_legacy(struct sysdb_search_ctx *sctx)
+{
+    struct sysdb_ctx *ctx = sctx->ctx;
+    struct ldb_result *res = sctx->res;
+    struct ldb_request *req;
+    struct ldb_dn *base_dn;
+    static const char *attrs[] = SYSDB_INITGR_ATTRS;
+    const char *userid;
+    int ret;
+
+    if (res->count == 0) {
+        return request_done(sctx);
+    }
+    if (res->count > 1) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    userid = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_PW_NAME, NULL);
+    if (!userid) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    sctx->expression = talloc_asprintf(sctx,
+                                       SYSDB_INITGR_LEGACY_FILTER, userid);
+    if (!sctx->expression) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    base_dn = ldb_dn_new_fmt(sctx, ctx->ldb,
+                             SYSDB_TMPL_GROUP_BASE, sctx->domain);
+    if (!base_dn) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    ret = ldb_build_search_req(&req, ctx->ldb, sctx,
+                               base_dn, LDB_SCOPE_SUBTREE,
+                               sctx->expression, attrs, NULL,
+                               sctx, get_gen_callback,
+                               NULL);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+
+    ret = ldb_request(ctx->ldb, req);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+}
+
+static void initgr_mem_search(struct sysdb_search_ctx *sctx)
+{
+    struct sysdb_ctx *ctx = sctx->ctx;
+    struct ldb_result *res = sctx->res;
+    struct ldb_request *req;
+    struct ldb_control **ctrl;
+    struct ldb_asq_control *control;
+    static const char *attrs[] = SYSDB_INITGR_ATTRS;
+    int ret;
+
+    if (res->count == 0) {
+        return request_done(sctx);
+    }
+    if (res->count > 1) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    sctx->expression = talloc_asprintf(sctx, SYSDB_INITGR_FILTER);
+    if (!sctx->expression) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+
+    ctrl = talloc_array(sctx, struct ldb_control *, 2);
+    if (!ctrl) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+    ctrl[1] = NULL;
+    ctrl[0] = talloc(ctrl, struct ldb_control);
+    if (!ctrl[0]) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+    ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
+    ctrl[0]->critical = 1;
+    control = talloc(ctrl[0], struct ldb_asq_control);
+    if (!control) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+    control->request = 1;
+    control->source_attribute = talloc_strdup(control, SYSDB_INITGR_ATTR);
+    if (!control->source_attribute) {
+        return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR);
+    }
+    control->src_attr_len = strlen(control->source_attribute);
+    ctrl[0]->data = control;
+
+    ret = ldb_build_search_req(&req, ctx->ldb, sctx,
+                               res->msgs[0]->dn,
+                               LDB_SCOPE_BASE,
+                               sctx->expression, attrs, ctrl,
+                               sctx, get_gen_callback,
+                               NULL);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+
+    ret = ldb_request(ctx->ldb, req);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+}
+
+static void initgr_search(struct sysdb_req *sysreq, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+    static const char *attrs[] = SYSDB_PW_ATTRS;
+    struct ldb_request *req;
+    struct ldb_dn *base_dn;
+    int ret;
+
+    sctx = talloc_get_type(ptr, struct sysdb_search_ctx);
+    sctx->req = sysreq;
+
+    if (sctx->legacy) {
+        sctx->gen_aux_fn = initgr_mem_legacy;
+    } else {
+        sctx->gen_aux_fn = initgr_mem_search;
+    }
+
+    base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb,
+                             SYSDB_TMPL_USER_BASE, sctx->domain);
+    if (!base_dn) {
+        return request_error(sctx, ENOMEM);
+    }
+
+    ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx,
+                               base_dn, LDB_SCOPE_SUBTREE,
+                               sctx->expression, attrs, NULL,
+                               sctx, get_gen_callback,
+                               NULL);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+
+    ret = ldb_request(sctx->ctx->ldb, req);
+    if (ret != LDB_SUCCESS) {
+        return request_ldberror(sctx, ret);
+    }
+}
+
+int sysdb_initgroups(TALLOC_CTX *mem_ctx,
+                     struct sysdb_ctx *ctx,
+                     const char *domain,
+                     const char *name,
+                     bool legacy,
+                     sysdb_callback_t fn, void *ptr)
+{
+    struct sysdb_search_ctx *sctx;
+
+    if (!domain) {
+        return EINVAL;
+    }
+
+    sctx = init_src_ctx(mem_ctx, domain, legacy, ctx, fn, ptr);
+    if (!sctx) {
+        return ENOMEM;
+    }
+
+    sctx->expression = talloc_asprintf(sctx, SYSDB_PWNAM_FILTER, name);
+    if (!sctx->expression) {
+        talloc_free(sctx);
+        return ENOMEM;
+    }
+
+    return sysdb_operation(mem_ctx, ctx, initgr_search, sctx);
+}
+
diff --git a/server/db/sysdb_sync.c b/server/db/sysdb_sync.c
index f2c992f..1910e9f 100644
--- a/server/db/sysdb_sync.c
+++ b/server/db/sysdb_sync.c
@@ -20,7 +20,7 @@
 */
 
 #include "util/util.h"
-#include "db/sysdb.h"
+#include "db/sysdb_private.h"
 #include <time.h>
 
 /* the following are all SYNCHRONOUS calls
diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c
index 0c5fd4c..2fbe397 100644
--- a/server/responder/nss/nsssrv.c
+++ b/server/responder/nss/nsssrv.c
@@ -397,7 +397,15 @@ failed:
  * only ASCII names for now */
 static int _domain_comparator(const void *key1, const void *key2)
 {
-    return strcasecmp((const char *)key1, (const char *)key2);
+    int ret;
+
+    ret = strcasecmp((const char *)key1, (const char *)key2);
+    if (ret) {
+        /* special case LOCAL to be always the first domain */
+        if (strcmp(key1, "LOCAL") == 0) return 1;
+        if (strcmp(key2, "LOCAL") == 0) return -1;
+    }
+    return ret;
 }
 
 static int nss_init_domains(struct nss_ctx *nctx)
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index c61eb4f..1614658 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -97,6 +97,9 @@ static int nss_parse_name(struct nss_dom_ctx *dctx, const char *fullname)
     char *delim;
     char *domain;
 
+    /* TODO: add list of names to filter to configuration */
+    if (strcmp(fullname, "root") == 0) return ECANCELED;
+
     domain_map = nctx->domain_map;
 
     if ((delim = strchr(fullname, NSS_DOMAIN_DELIM)) != NULL) {
@@ -367,7 +370,7 @@ static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_getpwnam(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->name,
                          dctx->legacy,
                          nss_cmd_getpwnam_callback, dctx);
@@ -386,6 +389,7 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
 {
     struct nss_cmd_ctx *cmdctx;
     struct nss_dom_ctx *dctx;
+    const char *rawname;
     uint8_t *body;
     size_t blen;
     int ret;
@@ -407,23 +411,27 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
         talloc_free(cmdctx);
         return EINVAL;
     }
+    rawname = (const char *)body;
 
-    ret = nss_parse_name(dctx, (const char *)body);
+    ret = nss_parse_name(dctx, rawname);
     if (ret != EOK) {
-        DEBUG(1, ("Invalid name received\n"));
-        talloc_free(cmdctx);
-        return ret;
+        DEBUG(2, ("Invalid name received [%s]\n", rawname));
+        goto done;
     }
     DEBUG(4, ("Requesting info for [%s] from [%s]\n",
               cmdctx->name, dctx->domain));
 
-    ret = sysdb_getpwnam(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->name,
                          dctx->legacy,
                          nss_cmd_getpwnam_callback, dctx);
+
     if (ret != EOK) {
         DEBUG(1, ("Failed to make request to our cache!\n"));
+    }
 
+done:
+    if (ret != EOK) {
         ret = nss_cmd_send_error(cmdctx, ret);
         if (ret == EOK) {
             nss_cmd_done(cmdctx);
@@ -586,7 +594,7 @@ static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_getpwuid(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->id,
                          dctx->legacy,
                          nss_cmd_getpwuid_callback, dctx);
@@ -656,7 +664,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx)
         DEBUG(4, ("Requesting info for [%lu@%s]\n",
                   cmdctx->id, dctx->domain));
 
-        ret = sysdb_getpwuid(cmdctx, cctx->ev, cctx->nctx->sysdb,
+        ret = sysdb_getpwuid(cmdctx, cctx->nctx->sysdb,
                              dctx->domain, cmdctx->id,
                              dctx->legacy,
                              nss_cmd_getpwuid_callback, dctx);
@@ -773,7 +781,7 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_enumpwent(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_enumpwent(cmdctx, cctx->nctx->sysdb,
                           dctx->domain, dctx->legacy,
                           nss_cmd_setpwent_callback, cmdctx);
     if (ret != EOK) {
@@ -854,7 +862,7 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
                                        timeout, domains[i], NSS_DP_USER,
                                        NULL, 0);
         } else {
-            ret = sysdb_enumpwent(dctx, cctx->ev, cctx->nctx->sysdb,
+            ret = sysdb_enumpwent(dctx, cctx->nctx->sysdb,
                                   dctx->domain, dctx->legacy,
                                   nss_cmd_setpwent_callback, cmdctx);
         }
@@ -1280,7 +1288,7 @@ static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_getgrnam(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->name,
                          dctx->legacy,
                          nss_cmd_getgrnam_callback, dctx);
@@ -1299,6 +1307,7 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx)
 {
     struct nss_cmd_ctx *cmdctx;
     struct nss_dom_ctx *dctx;
+    const char *rawname;
     uint8_t *body;
     size_t blen;
     int ret;
@@ -1320,23 +1329,26 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx)
         talloc_free(cmdctx);
         return EINVAL;
     }
+    rawname = (const char *)body;
 
-    ret = nss_parse_name(dctx, (const char *)body);
+    ret = nss_parse_name(dctx, rawname);
     if (ret != EOK) {
-        DEBUG(1, ("Invalid name received\n"));
-        talloc_free(cmdctx);
-        return ret;
+        DEBUG(2, ("Invalid name received [%s]\n", rawname));
+        goto done;
     }
     DEBUG(4, ("Requesting info for [%s] from [%s]\n",
               cmdctx->name, dctx->domain));
 
-    ret = sysdb_getgrnam(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getgrnam(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->name,
                          dctx->legacy,
                          nss_cmd_getgrnam_callback, dctx);
     if (ret != EOK) {
         DEBUG(1, ("Failed to make request to our cache!\n"));
+    }
 
+done:
+    if (ret != EOK) {
         ret = nss_cmd_send_error(cmdctx, ret);
         if (ret == EOK) {
             nss_cmd_done(cmdctx);
@@ -1484,7 +1496,7 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_getgrgid(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->id,
                          dctx->legacy,
                          nss_cmd_getgrgid_callback, dctx);
@@ -1549,7 +1561,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx)
         DEBUG(4, ("Requesting info for [%lu@%s]\n",
                   cmdctx->id, dctx->domain));
 
-        ret = sysdb_getgrgid(cmdctx, cctx->ev, cctx->nctx->sysdb,
+        ret = sysdb_getgrgid(cmdctx, cctx->nctx->sysdb,
                              dctx->domain, cmdctx->id,
                              dctx->legacy,
                              nss_cmd_getgrgid_callback, dctx);
@@ -1665,7 +1677,7 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_enumgrent(dctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_enumgrent(dctx, cctx->nctx->sysdb,
                           dctx->domain, dctx->legacy,
                           nss_cmd_setgrent_callback, cmdctx);
     if (ret != EOK) {
@@ -1746,7 +1758,7 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
                                        timeout, domains[i], NSS_DP_GROUP,
                                        NULL, 0);
         } else {
-            ret = sysdb_enumgrent(dctx, cctx->ev, cctx->nctx->sysdb,
+            ret = sysdb_enumgrent(dctx, cctx->nctx->sysdb,
                                   dctx->domain, dctx->legacy,
                                   nss_cmd_setgrent_callback, cmdctx);
         }
@@ -1994,7 +2006,7 @@ static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_initgroups(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_initgroups(cmdctx, cctx->nctx->sysdb,
                            dctx->domain, cmdctx->name,
                            dctx->legacy,
                            nss_cmd_initgr_callback, cmdctx);
@@ -2027,7 +2039,7 @@ static void nss_cmd_getinitnam_callback(uint16_t err_maj, uint32_t err_min,
                   (unsigned int)err_maj, (unsigned int)err_min, err_msg));
     }
 
-    ret = sysdb_getpwnam(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->name,
                          dctx->legacy,
                          nss_cmd_getinit_callback, dctx);
@@ -2155,6 +2167,7 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
 {
     struct nss_cmd_ctx *cmdctx;
     struct nss_dom_ctx *dctx;
+    const char *rawname;
     uint8_t *body;
     size_t blen;
     int ret;
@@ -2171,28 +2184,30 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
 
     /* get user name to query */
     sss_packet_get_body(cctx->creq->in, &body, &blen);
-    cmdctx->name = (const char *)body;
     /* if not terminated fail */
-    if (cmdctx->name[blen -1] != '\0') {
+    if (body[blen -1] != '\0') {
         return EINVAL;
     }
+    rawname = (const char *)body;
 
-    ret = nss_parse_name(dctx, (const char *)body);
+    ret = nss_parse_name(dctx, rawname);
     if (ret != EOK) {
-        DEBUG(1, ("Invalid name received\n"));
-        talloc_free(cmdctx);
-        return ret;
+        DEBUG(2, ("Invalid name received [%s]\n", rawname));
+        goto done;
     }
     DEBUG(4, ("Requesting info for [%s] from [%s]\n",
               cmdctx->name, dctx->domain));
 
-    ret = sysdb_getpwnam(cmdctx, cctx->ev, cctx->nctx->sysdb,
+    ret = sysdb_getpwnam(cmdctx, cctx->nctx->sysdb,
                          dctx->domain, cmdctx->name,
                          dctx->legacy,
                          nss_cmd_getinit_callback, dctx);
     if (ret != EOK) {
         DEBUG(1, ("Failed to make request to our cache!\n"));
+    }
 
+done:
+    if (ret != EOK) {
         ret = nss_cmd_send_error(cmdctx, ret);
         if (ret == EOK) {
             nss_cmd_done(cmdctx);
diff --git a/server/server.mk b/server/server.mk
index 386f56f..e029d4a 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -13,6 +13,8 @@ UTIL_OBJ = \
     sbus/sbus_client.o \
     confdb/confdb.o \
 	db/sysdb.o \
+	db/sysdb_req.o \
+	db/sysdb_search.o \
 	db/sysdb_sync.o
 
 RESPONDER_UTIL_OBJ = \
-- 
1.5.6.6




More information about the Freeipa-devel mailing list