summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/db/sysdb.c745
-rw-r--r--server/db/sysdb.h14
-rw-r--r--server/db/sysdb_private.h (renamed from server/db/sysdb_internal.h)25
-rw-r--r--server/db/sysdb_req.c241
-rw-r--r--server/db/sysdb_search.c731
-rw-r--r--server/db/sysdb_sync.c2
-rw-r--r--server/responder/nss/nsssrv.c10
-rw-r--r--server/responder/nss/nsssrv_cmd.c73
-rw-r--r--server/server.mk2
9 files changed, 1063 insertions, 780 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c
index ddd7fbe4..1c91f122 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 c6cc4deb..c0ef361b 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_private.h
index 719f6606..c649af4a 100644
--- a/server/db/sysdb_internal.h
+++ b/server/db/sysdb_private.h
@@ -67,4 +67,29 @@
"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 00000000..fcbd17b8
--- /dev/null
+++ b/server/db/sysdb_req.c
@@ -0,0 +1,241 @@
+/*
+ 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_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 00000000..5a355a0f
--- /dev/null
+++ b/server/db/sysdb_search.c
@@ -0,0 +1,731 @@
+/*
+ SSSD
+
+ System Database
+
+ Copyright (C) Simo Sorce <ssorce@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 f2c992fc..1910e9fc 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 0c5fd4cc..2fbe3970 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 c61eb4f2..16146585 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 386f56f1..e029d4a5 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 = \