summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-02-27 17:04:11 -0500
committerSimo Sorce <ssorce@redhat.com>2009-02-28 18:55:49 -0500
commitf0cefca80767664b876d10126f7f79fc36dc1993 (patch)
tree1cc4792533b512da6f16cdce77f171de6aa804ae /server
parent60398e684b6d4f8880fcda357c8077ccca481041 (diff)
downloadsssd-f0cefca80767664b876d10126f7f79fc36dc1993.tar.gz
sssd-f0cefca80767664b876d10126f7f79fc36dc1993.tar.bz2
sssd-f0cefca80767664b876d10126f7f79fc36dc1993.zip
Convert sync calls in sysdb to async, transaction dependent, calls.
Diffstat (limited to 'server')
-rw-r--r--server/db/sysdb.c13
-rw-r--r--server/db/sysdb.h109
-rw-r--r--server/db/sysdb_ops.c938
-rw-r--r--server/db/sysdb_private.h12
-rw-r--r--server/db/sysdb_req.c11
-rw-r--r--server/db/sysdb_search.c40
-rw-r--r--server/db/sysdb_sync.c880
-rw-r--r--server/providers/proxy.c960
-rw-r--r--server/server.mk2
9 files changed, 1652 insertions, 1313 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c
index 1c91f122..84d580a8 100644
--- a/server/db/sysdb.c
+++ b/server/db/sysdb.c
@@ -24,6 +24,19 @@
#include "confdb/confdb.h"
#include <time.h>
+struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx,
+ const char *domain, const char *name)
+{
+ return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_USER, name, domain);
+}
+
+struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
+ const char *domain, const char *name)
+{
+ return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_GROUP, name, domain);
+}
+
+
/************************************************
* Initialiazation stuff
*/
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index c0ef361b..b8393ffe 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -32,18 +32,8 @@
#define SYSDB_TMPL_USER_BASE "cn=users,cn=%s,"SYSDB_BASE
#define SYSDB_TMPL_GROUP_BASE "cn=groups,cn=%s,"SYSDB_BASE
-#define SYSDB_PWNAM_FILTER "(&(objectclass=user)(uid=%s))"
-#define SYSDB_PWUID_FILTER "(&(objectclass=user)(uidNumber=%lu))"
-#define SYSDB_PWENT_FILTER "(objectclass=user)"
-
-#define SYSDB_GRNAM_FILTER "(&(objectclass=group)(gid=%s))"
-#define SYSDB_GRNA2_FILTER "(&(objectclass=user)(memberof=%s))"
-#define SYSDB_GRGID_FILTER "(&(objectclass=group)(gidNumber=%lu))"
-#define SYSDB_GRENT_FILTER "(objectclass=group)"
-
-#define SYSDB_INITGR_FILTER "(&(objectclass=group)(gidNumber=*))"
-
-#define SYSDB_INITGR_LEGACY_FILTER "(&(objectclass=group)(memberUid=%s))"
+#define SYSDB_USER_CLASS "user"
+#define SYSDB_GROUP_CLASS "group"
#define SYSDB_PW_NAME "uid"
#define SYSDB_PW_PWD "userPassword"
@@ -61,6 +51,19 @@
#define SYSDB_LAST_UPDATE "lastUpdate"
+#define SYSDB_PWNAM_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_PW_NAME"=%s))"
+#define SYSDB_PWUID_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_PW_UIDNUM"=%lu))"
+#define SYSDB_PWENT_FILTER "(objectclass="SYSDB_USER_CLASS")"
+
+#define SYSDB_GRNAM_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_GR_NAME"=%s))"
+#define SYSDB_GRNA2_FILTER "(&(objectclass="SYSDB_USER_CLASS")("SYSDB_PW_MEMBEROF"=%s))"
+#define SYSDB_GRGID_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_GR_GIDNUM"=%lu))"
+#define SYSDB_GRENT_FILTER "(objectclass="SYSDB_GROUP_CLASS")"
+
+#define SYSDB_INITGR_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_GR_GIDNUM"=*))"
+
+#define SYSDB_INITGR_LEGACY_FILTER "(&(objectclass="SYSDB_GROUP_CLASS")("SYSDB_LEGACY_MEMBER"=%s))"
+
#define SYSDB_PW_ATTRS {SYSDB_PW_NAME, SYSDB_PW_UIDNUM, \
SYSDB_PW_GIDNUM, SYSDB_PW_FULLNAME, \
SYSDB_PW_HOMEDIR, SYSDB_PW_SHELL, \
@@ -76,10 +79,15 @@
#define SYSDB_INITGR_ATTRS {SYSDB_GR_GIDNUM, SYSDB_LAST_UPDATE, \
NULL}
+#define SYSDB_TMPL_USER SYSDB_PW_NAME"=%s,"SYSDB_TMPL_USER_BASE
+#define SYSDB_TMPL_GROUP SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE
+
struct confdb_ctx;
struct sysdb_ctx;
+struct sysdb_req;
typedef void (*sysdb_callback_t)(void *, int, struct ldb_result *);
+typedef void (*sysdb_req_fn_t)(struct sysdb_req *, void *pvt);
int sysdb_init(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -135,60 +143,59 @@ int sysdb_initgroups(TALLOC_CTX *mem_ctx,
sysdb_callback_t fn, void *ptr);
-/* the following are all SYNCHRONOUS calls
- * TODO: make these asynchronous */
+struct sysdb_ctx *sysdb_req_get_ctx(struct sysdb_req *req);
-int sysdb_add_group_member(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn);
+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_remove_group_member(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn);
+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);
-int sysdb_delete_user(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, const char *name);
+struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx,
+ const char *domain, const char *name);
-int sysdb_delete_user_by_uid(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, uid_t uid);
+struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
+ const char *domain, const char *name);
-int sysdb_add_user_to_group(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain,
- const char *group,
- const char *username);
+int sysdb_add_group_member(struct sysdb_req *sysreq,
+ struct ldb_dn *member_dn,
+ struct ldb_dn *group_dn,
+ sysdb_callback_t fn, void *pvt);
+
+int sysdb_remove_group_member(struct sysdb_req *sysreq,
+ struct ldb_dn *member_dn,
+ struct ldb_dn *group_dn,
+ sysdb_callback_t fn, void *pvt);
-int sysdb_remove_user_from_group(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain,
- const char *group,
- const char *username);
+int sysdb_delete_entry(struct sysdb_req *sysreq,
+ struct ldb_dn *dn,
+ sysdb_callback_t fn, void *pvt);
-int sysdb_delete_group(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, const char *name);
+int sysdb_delete_user_by_uid(struct sysdb_req *sysreq,
+ const char *domain, uid_t uid,
+ sysdb_callback_t fn, void *pvt);
-int sysdb_delete_group_by_gid(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, gid_t gid);
+int sysdb_delete_group_by_gid(struct sysdb_req *sysreq,
+ const char *domain, gid_t gid,
+ sysdb_callback_t fn, void *pvt);
-/* legacy synchronous functions for proxy providers */
+/* legacy functions for proxy providers */
-int sysdb_legacy_store_user(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
+int sysdb_legacy_store_user(struct sysdb_req *sysreq,
const char *domain,
const char *name, const char *pwd,
uid_t uid, gid_t gid, const char *gecos,
- const char *homedir, const char *shell);
+ const char *homedir, const char *shell,
+ sysdb_callback_t fn, void *pvt);
-int sysdb_legacy_store_group(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
+int sysdb_legacy_store_group(struct sysdb_req *sysreq,
const char *domain,
const char *name, gid_t gid,
- char **members);
+ const char **members,
+ sysdb_callback_t fn, void *pvt);
#endif /* __SYS_DB_H__ */
diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c
new file mode 100644
index 00000000..267771b5
--- /dev/null
+++ b/server/db/sysdb_ops.c
@@ -0,0 +1,938 @@
+/*
+ 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 <time.h>
+
+#define return_error(ctx, ret) ctx->fn(ctx->pvt, ret, NULL)
+#define return_done(ctx) ctx->fn(ctx->pvt, EOK, NULL)
+
+static int add_string(struct ldb_message *msg, int flags,
+ const char *attr, const char *value)
+{
+ int ret;
+
+ ret = ldb_msg_add_empty(msg, attr, flags, NULL);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_msg_add_string(msg, attr, value);
+ }
+ return ret;
+}
+
+static int add_ulong(struct ldb_message *msg, int flags,
+ const char *attr, unsigned long value)
+{
+ int ret;
+
+ ret = ldb_msg_add_empty(msg, attr, flags, NULL);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_msg_add_fmt(msg, attr, "%lu", value);
+ }
+ return ret;
+}
+
+/* the following are all SYNCHRONOUS calls
+ * TODO: make these asynchronous */
+
+struct sysdb_cb_ctx {
+ sysdb_callback_t fn;
+ void *pvt;
+
+ bool ignore_not_found;
+};
+
+static int sysdb_op_callback(struct ldb_request *req, struct ldb_reply *rep)
+{
+ struct sysdb_cb_ctx *cbctx;
+
+ cbctx = talloc_get_type(req->context, struct sysdb_cb_ctx);
+
+ if (!rep) {
+ return_error(cbctx, EIO);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (rep->error != LDB_SUCCESS) {
+ if (! (cbctx->ignore_not_found &&
+ rep->error == LDB_ERR_NO_SUCH_OBJECT)) {
+ return_error(cbctx, sysdb_error_to_errno(rep->error));
+ return rep->error;
+ }
+ }
+
+ talloc_free(rep);
+
+ if (rep->type != LDB_REPLY_DONE) {
+ return_error(cbctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return_done(cbctx);
+ return LDB_SUCCESS;
+}
+
+int sysdb_add_group_member(struct sysdb_req *sysreq,
+ struct ldb_dn *member_dn,
+ struct ldb_dn *group_dn,
+ sysdb_callback_t fn, void *pvt)
+{
+ struct sysdb_ctx *ctx;
+ struct sysdb_cb_ctx *cbctx;
+ struct ldb_request *req;
+ struct ldb_message *msg;
+ const char *dn;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ cbctx = talloc_zero(sysreq, struct sysdb_cb_ctx);
+ if (!cbctx) return ENOMEM;
+
+ cbctx->fn = fn;
+ cbctx->pvt = pvt;
+
+ /* Add the member_dn as a member of the group */
+ msg = ldb_msg_new(cbctx);
+ if(msg == NULL) return ENOMEM;
+
+ msg->dn = group_dn;
+ ret = ldb_msg_add_empty(msg, SYSDB_GR_MEMBER,
+ LDB_FLAG_MOD_ADD, NULL);
+ if (ret != LDB_SUCCESS) return ENOMEM;
+
+ dn = ldb_dn_get_linearized(member_dn);
+ if (!dn) return EINVAL;
+
+ ret = ldb_msg_add_fmt(msg, SYSDB_GR_MEMBER, "%s", dn);
+ if (ret != LDB_SUCCESS) return EINVAL;
+
+ ret = ldb_build_mod_req(&req, ctx->ldb, cbctx, msg,
+ NULL, cbctx, sysdb_op_callback, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+int sysdb_remove_group_member(struct sysdb_req *sysreq,
+ struct ldb_dn *member_dn,
+ struct ldb_dn *group_dn,
+ sysdb_callback_t fn, void *pvt)
+{
+ struct sysdb_ctx *ctx;
+ struct sysdb_cb_ctx *cbctx;
+ struct ldb_request *req;
+ struct ldb_message *msg;
+ const char *dn;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ cbctx = talloc_zero(sysreq, struct sysdb_cb_ctx);
+ if (!cbctx) return ENOMEM;
+
+ cbctx->fn = fn;
+ cbctx->pvt = pvt;
+
+ /* Add the member_dn as a member of the group */
+ msg = ldb_msg_new(cbctx);
+ if(msg == NULL) return ENOMEM;
+
+ msg->dn = group_dn;
+ ret = ldb_msg_add_empty(msg, SYSDB_GR_MEMBER,
+ LDB_FLAG_MOD_DELETE, NULL);
+ if (ret != LDB_SUCCESS) return ENOMEM;
+
+ dn = ldb_dn_get_linearized(member_dn);
+ if (!dn) return EINVAL;
+
+ ret = ldb_msg_add_fmt(msg, SYSDB_GR_MEMBER, "%s", dn);
+ if (ret != LDB_SUCCESS) return EINVAL;
+
+ ret = ldb_build_mod_req(&req, ctx->ldb, cbctx, msg,
+ NULL, cbctx, sysdb_op_callback, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+int sysdb_delete_entry(struct sysdb_req *sysreq,
+ struct ldb_dn *dn,
+ sysdb_callback_t fn, void *pvt)
+{
+ struct sysdb_ctx *ctx;
+ struct sysdb_cb_ctx *cbctx;
+ struct ldb_request *req;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ cbctx = talloc_zero(sysreq, struct sysdb_cb_ctx);
+ if (!cbctx) return ENOMEM;
+
+ cbctx->fn = fn;
+ cbctx->pvt = pvt;
+ cbctx->ignore_not_found = true;
+
+ ret = ldb_build_del_req(&req, ctx->ldb, cbctx, dn, NULL,
+ cbctx, sysdb_op_callback, NULL);
+
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+struct delete_ctx {
+ struct sysdb_req *sysreq;
+ struct sysdb_cb_ctx *cbctx;
+
+ struct ldb_result *res;
+};
+
+static int delete_callback(struct ldb_request *req, struct ldb_reply *rep)
+{
+ struct delete_ctx *del_ctx;
+ struct sysdb_cb_ctx *cbctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_request *delreq;
+ struct ldb_result *res;
+ struct ldb_dn *dn;
+ int ret;
+
+ del_ctx = talloc_get_type(req->context, struct delete_ctx);
+ ctx = sysdb_req_get_ctx(del_ctx->sysreq);
+ cbctx = del_ctx->cbctx;
+ res = del_ctx->res;
+
+ if (!rep) {
+ return_error(cbctx, EIO);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (rep->error != LDB_SUCCESS) {
+ return_error(cbctx, sysdb_error_to_errno(rep->error));
+ return rep->error;
+ }
+
+ switch (rep->type) {
+ case LDB_REPLY_ENTRY:
+ res->msgs = talloc_realloc(res, res->msgs,
+ struct ldb_message *,
+ res->count + 2);
+ if (!res->msgs) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ return_error(cbctx, sysdb_error_to_errno(ret));
+ return ret;
+ }
+
+ res->msgs[res->count + 1] = NULL;
+
+ res->msgs[res->count] = talloc_steal(res->msgs, rep->message);
+ res->count++;
+
+ break;
+
+ case LDB_REPLY_DONE:
+
+ if (res->count == 0) {
+ DEBUG(7, ("Base search returned no results\n"));
+ return_done(cbctx);
+ break;
+ }
+ if (res->count > 1) {
+ DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
+ res->count));
+ return_error(cbctx, EFAULT);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ dn = ldb_dn_copy(del_ctx, res->msgs[0]->dn);
+ if (!dn) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(res);
+ del_ctx->res = res = NULL;
+
+ ret = ldb_build_del_req(&delreq, ctx->ldb, cbctx, dn, NULL,
+ cbctx, sysdb_op_callback, NULL);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_request(ctx->ldb, delreq);
+ }
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, sysdb_error_to_errno(ret));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ break;
+
+ default:
+ return_error(cbctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(rep);
+ return LDB_SUCCESS;
+}
+
+int sysdb_delete_user_by_uid(struct sysdb_req *sysreq,
+ const char *domain, uid_t uid,
+ sysdb_callback_t fn, void *pvt)
+{
+ static const char *attrs[] = { SYSDB_PW_NAME, SYSDB_PW_UIDNUM, NULL };
+ struct delete_ctx *del_ctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_dn *base_dn;
+ struct ldb_request *req;
+ char *filter;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ del_ctx = talloc_zero(sysreq, struct delete_ctx);
+ if (!del_ctx) return ENOMEM;
+
+ del_ctx->cbctx = talloc_zero(del_ctx, struct sysdb_cb_ctx);
+ if (!del_ctx->cbctx) return ENOMEM;
+
+ del_ctx->sysreq = sysreq;
+ del_ctx->cbctx->fn = fn;
+ del_ctx->cbctx->pvt = pvt;
+ del_ctx->cbctx->ignore_not_found = true;
+
+ del_ctx->res = talloc_zero(del_ctx, struct ldb_result);
+ if (!del_ctx->res) return ENOMEM;
+
+ base_dn = ldb_dn_new_fmt(del_ctx, ctx->ldb, SYSDB_TMPL_USER_BASE, domain);
+ if (!base_dn) return ENOMEM;
+
+ filter = talloc_asprintf(del_ctx, SYSDB_PWUID_FILTER, (unsigned long)uid);
+ if (!filter) return ENOMEM;
+
+ ret = ldb_build_search_req(&req, ctx->ldb, del_ctx,
+ base_dn, LDB_SCOPE_ONELEVEL,
+ filter, attrs, NULL,
+ del_ctx, delete_callback, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+int sysdb_delete_group_by_gid(struct sysdb_req *sysreq,
+ const char *domain, gid_t gid,
+ sysdb_callback_t fn, void *pvt)
+{
+ static const char *attrs[] = { SYSDB_GR_NAME, SYSDB_GR_GIDNUM, NULL };
+ struct delete_ctx *del_ctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_dn *base_dn;
+ struct ldb_request *req;
+ char *filter;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ del_ctx = talloc_zero(sysreq, struct delete_ctx);
+ if (!del_ctx) return ENOMEM;
+
+ del_ctx->cbctx = talloc_zero(del_ctx, struct sysdb_cb_ctx);
+ if (!del_ctx->cbctx) return ENOMEM;
+
+ del_ctx->sysreq = sysreq;
+ del_ctx->cbctx->fn = fn;
+ del_ctx->cbctx->pvt = pvt;
+ del_ctx->cbctx->ignore_not_found = true;
+
+ del_ctx->res = talloc_zero(del_ctx, struct ldb_result);
+ if (!del_ctx->res) return ENOMEM;
+
+ base_dn = ldb_dn_new_fmt(del_ctx, ctx->ldb, SYSDB_TMPL_GROUP_BASE, domain);
+ if (!base_dn) return ENOMEM;
+
+ filter = talloc_asprintf(del_ctx, SYSDB_GRGID_FILTER, (unsigned long)gid);
+ if (!filter) return ENOMEM;
+
+ ret = ldb_build_search_req(&req, ctx->ldb, del_ctx,
+ base_dn, LDB_SCOPE_ONELEVEL,
+ filter, attrs, NULL,
+ del_ctx, delete_callback, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+/* "sysdb_legacy_" functions
+ * the set of functions named sysdb_legacy_* are used by modules
+ * that only have access to strictly posix like databases where
+ * user and groups names are retrieved as strings, groups can't
+ * be nested and can't reference foreign sources */
+
+struct legacy_user_ctx {
+ struct sysdb_req *sysreq;
+ struct sysdb_cb_ctx *cbctx;
+
+ struct ldb_dn *dn;
+
+ const char *domain;
+ const char *name;
+ const char *pwd;
+ uid_t uid;
+ gid_t gid;
+ const char *gecos;
+ const char *homedir;
+ const char *shell;
+
+ struct ldb_result *res;
+};
+
+static int legacy_user_callback(struct ldb_request *req,
+ struct ldb_reply *rep);
+
+int sysdb_legacy_store_user(struct sysdb_req *sysreq,
+ const char *domain,
+ const char *name, const char *pwd,
+ uid_t uid, gid_t gid, const char *gecos,
+ const char *homedir, const char *shell,
+ sysdb_callback_t fn, void *pvt)
+{
+ static const char *attrs[] = { SYSDB_PW_NAME, NULL };
+ struct legacy_user_ctx *user_ctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_request *req;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ user_ctx = talloc(sysreq, struct legacy_user_ctx);
+ if (!user_ctx) return ENOMEM;
+
+ user_ctx->cbctx = talloc_zero(user_ctx, struct sysdb_cb_ctx);
+ if (!user_ctx->cbctx) return ENOMEM;
+
+ user_ctx->dn = sysdb_user_dn(ctx, user_ctx, domain, name);
+ if (!user_ctx->dn) return ENOMEM;
+
+ user_ctx->sysreq = sysreq;
+ user_ctx->cbctx->fn = fn;
+ user_ctx->cbctx->pvt = pvt;
+ user_ctx->domain = domain;
+ user_ctx->name = name;
+ user_ctx->pwd = pwd;
+ user_ctx->uid = uid;
+ user_ctx->gid = gid;
+ user_ctx->gecos = gecos;
+ user_ctx->homedir = homedir;
+ user_ctx->shell = shell;
+
+ user_ctx->res = talloc_zero(user_ctx, struct ldb_result);
+ if (!user_ctx->res) return ENOMEM;
+
+ ret = ldb_build_search_req(&req, ctx->ldb, user_ctx,
+ user_ctx->dn, LDB_SCOPE_BASE,
+ SYSDB_PWENT_FILTER, attrs, NULL,
+ user_ctx, legacy_user_callback, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+static int legacy_user_callback(struct ldb_request *req,
+ struct ldb_reply *rep)
+{
+ struct legacy_user_ctx *user_ctx;
+ struct sysdb_cb_ctx *cbctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_message *msg;
+ struct ldb_request *ureq;
+ struct ldb_result *res;
+ int flags;
+ int ret;
+
+ user_ctx = talloc_get_type(req->context, struct legacy_user_ctx);
+ ctx = sysdb_req_get_ctx(user_ctx->sysreq);
+ cbctx = user_ctx->cbctx;
+ res = user_ctx->res;
+
+ if (!rep) {
+ return_error(cbctx, EIO);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (rep->error != LDB_SUCCESS) {
+ return_error(cbctx, sysdb_error_to_errno(rep->error));
+ return rep->error;
+ }
+
+ switch (rep->type) {
+ case LDB_REPLY_ENTRY:
+ res->msgs = talloc_realloc(res, res->msgs,
+ struct ldb_message *,
+ res->count + 2);
+ if (!res->msgs) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ return_error(cbctx, sysdb_error_to_errno(ret));
+ return ret;
+ }
+
+ res->msgs[res->count + 1] = NULL;
+
+ res->msgs[res->count] = talloc_steal(res->msgs, rep->message);
+ res->count++;
+
+ break;
+
+ case LDB_REPLY_DONE:
+
+ msg = ldb_msg_new(cbctx);
+ if (!msg) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ msg->dn = user_ctx->dn;
+
+ switch (res->count) {
+ case 0:
+ flags = LDB_FLAG_MOD_ADD;
+ break;
+ case 1:
+ flags = LDB_FLAG_MOD_REPLACE;
+ break;
+ default:
+ DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
+ res->count));
+
+ return_error(cbctx, EFAULT);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(res);
+ user_ctx->res = res = NULL;
+
+ if (flags == LDB_FLAG_MOD_ADD) {
+ ret = add_string(msg, flags, "objectClass", SYSDB_USER_CLASS);
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = add_string(msg, flags, SYSDB_PW_NAME, user_ctx->name);
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ if (user_ctx->pwd && *user_ctx->pwd) {
+ ret = add_string(msg, flags, SYSDB_PW_PWD, user_ctx->pwd);
+ } else {
+ ret = ldb_msg_add_empty(msg, SYSDB_PW_PWD,
+ LDB_FLAG_MOD_DELETE, NULL);
+ }
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (user_ctx->uid) {
+ ret = add_ulong(msg, flags, SYSDB_PW_UIDNUM,
+ (unsigned long)(user_ctx->uid));
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ } else {
+ DEBUG(0, ("Cached users can't have UID == 0\n"));
+ return_error(cbctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (user_ctx->gid) {
+ ret = add_ulong(msg, flags, SYSDB_PW_GIDNUM,
+ (unsigned long)(user_ctx->gid));
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ } else {
+ DEBUG(0, ("Cached users can't have GID == 0\n"));
+ return_error(cbctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (user_ctx->gecos && *user_ctx->gecos) {
+ ret = add_string(msg, flags, SYSDB_PW_FULLNAME, user_ctx->gecos);
+ } else {
+ ret = ldb_msg_add_empty(msg, SYSDB_PW_FULLNAME,
+ LDB_FLAG_MOD_DELETE, NULL);
+ }
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (user_ctx->homedir && *user_ctx->homedir) {
+ ret = add_string(msg, flags, SYSDB_PW_HOMEDIR, user_ctx->homedir);
+ } else {
+ ret = ldb_msg_add_empty(msg, SYSDB_PW_HOMEDIR,
+ LDB_FLAG_MOD_DELETE, NULL);
+ }
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (user_ctx->shell && *user_ctx->shell) {
+ ret = add_string(msg, flags, SYSDB_PW_SHELL, user_ctx->shell);
+ } else {
+ ret = ldb_msg_add_empty(msg, SYSDB_PW_SHELL,
+ LDB_FLAG_MOD_DELETE, NULL);
+ }
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* modification time */
+ ret = add_ulong(msg, flags, SYSDB_LAST_UPDATE,
+ (unsigned long)time(NULL));
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (flags == LDB_FLAG_MOD_ADD) {
+ ret = ldb_build_add_req(&ureq, ctx->ldb, cbctx, msg, NULL,
+ cbctx, sysdb_op_callback, NULL);
+ } else {
+ ret = ldb_build_mod_req(&ureq, ctx->ldb, cbctx, msg, NULL,
+ cbctx, sysdb_op_callback, NULL);
+ }
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_request(ctx->ldb, ureq);
+ }
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, sysdb_error_to_errno(ret));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ break;
+
+ default:
+ return_error(cbctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(rep);
+ return LDB_SUCCESS;
+}
+
+
+
+/* this function does not check that all user members are actually present */
+
+struct legacy_group_ctx {
+ struct sysdb_req *sysreq;
+ struct sysdb_cb_ctx *cbctx;
+
+ struct ldb_dn *dn;
+
+ const char *domain;
+ const char *name;
+ gid_t gid;
+ const char **members;
+
+ struct ldb_result *res;
+};
+
+static int legacy_group_callback(struct ldb_request *req,
+ struct ldb_reply *rep);
+
+int sysdb_legacy_store_group(struct sysdb_req *sysreq,
+ const char *domain,
+ const char *name, gid_t gid,
+ const char **members,
+ sysdb_callback_t fn, void *pvt)
+{
+ static const char *attrs[] = { SYSDB_GR_NAME, NULL };
+ struct legacy_group_ctx *group_ctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_request *req;
+ int ret;
+
+ if (!sysdb_req_check_running(sysreq)) {
+ DEBUG(2, ("Invalid request! Not running at this time.\n"));
+ return EINVAL;
+ }
+
+ ctx = sysdb_req_get_ctx(sysreq);
+
+ group_ctx = talloc(sysreq, struct legacy_group_ctx);
+ if (!group_ctx) return ENOMEM;
+
+ group_ctx->cbctx = talloc_zero(group_ctx, struct sysdb_cb_ctx);
+ if (!group_ctx->cbctx) return ENOMEM;
+
+ group_ctx->dn = sysdb_group_dn(ctx, group_ctx, domain, name);
+ if (!group_ctx->dn) return ENOMEM;
+
+ group_ctx->sysreq = sysreq;
+ group_ctx->cbctx->fn = fn;
+ group_ctx->cbctx->pvt = pvt;
+ group_ctx->domain = domain;
+ group_ctx->name = name;
+ group_ctx->gid = gid;
+ group_ctx->members = members;
+
+ group_ctx->res = talloc_zero(group_ctx, struct ldb_result);
+ if (!group_ctx->res) return ENOMEM;
+
+ ret = ldb_build_search_req(&req, ctx->ldb, group_ctx,
+ group_ctx->dn, LDB_SCOPE_BASE,
+ SYSDB_GRENT_FILTER, attrs, NULL,
+ group_ctx, legacy_group_callback, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
+ ldb_strerror(ret), ret, ldb_errstring(ctx->ldb)));
+ return sysdb_error_to_errno(ret);
+ }
+
+ ret = ldb_request(ctx->ldb, req);
+ if (ret != LDB_SUCCESS) return sysdb_error_to_errno(ret);
+
+ return EOK;
+}
+
+static int legacy_group_callback(struct ldb_request *req,
+ struct ldb_reply *rep)
+{
+ struct legacy_group_ctx *group_ctx;
+ struct sysdb_cb_ctx *cbctx;
+ struct sysdb_ctx *ctx;
+ struct ldb_message *msg;
+ struct ldb_request *greq;
+ struct ldb_result *res;
+ int flags;
+ int i, ret;
+
+ group_ctx = talloc_get_type(req->context, struct legacy_group_ctx);
+ ctx = sysdb_req_get_ctx(group_ctx->sysreq);
+ cbctx = group_ctx->cbctx;
+ res = group_ctx->res;
+
+ if (!rep) {
+ return_error(cbctx, EIO);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ if (rep->error != LDB_SUCCESS) {
+ return_error(cbctx, sysdb_error_to_errno(rep->error));
+ return rep->error;
+ }
+
+ switch (rep->type) {
+ case LDB_REPLY_ENTRY:
+ res->msgs = talloc_realloc(res, res->msgs,
+ struct ldb_message *,
+ res->count + 2);
+ if (!res->msgs) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ return_error(cbctx, sysdb_error_to_errno(ret));
+ return ret;
+ }
+
+ res->msgs[res->count + 1] = NULL;
+
+ res->msgs[res->count] = talloc_steal(res->msgs, rep->message);
+ res->count++;
+
+ break;
+
+ case LDB_REPLY_DONE:
+
+ msg = ldb_msg_new(cbctx);
+ if (!msg) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ msg->dn = group_ctx->dn;
+
+ switch (res->count) {
+ case 0:
+ flags = LDB_FLAG_MOD_ADD;
+ break;
+ case 1:
+ flags = LDB_FLAG_MOD_REPLACE;
+ break;
+ default:
+ DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
+ res->count));
+
+ return_error(cbctx, EFAULT);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(res);
+ group_ctx->res = res = NULL;
+
+ if (flags == LDB_FLAG_MOD_ADD) {
+ ret = add_string(msg, flags, "objectClass", SYSDB_GROUP_CLASS);
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = add_string(msg, flags, SYSDB_GR_NAME, group_ctx->name);
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ if (group_ctx->gid) {
+ ret = add_ulong(msg, flags, SYSDB_GR_GIDNUM,
+ (unsigned long)(group_ctx->gid));
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ } else {
+ DEBUG(0, ("Cached groups can't have GID == 0\n"));
+ return_error(cbctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* members */
+ if (group_ctx->members && group_ctx->members[0]) {
+ ret = ldb_msg_add_empty(msg, SYSDB_LEGACY_MEMBER, flags, NULL);
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ for (i = 0; group_ctx->members[i]; i++) {
+ ret = ldb_msg_add_string(msg, SYSDB_LEGACY_MEMBER,
+ group_ctx->members[i]);
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+ }
+
+ /* modification time */
+ ret = add_ulong(msg, flags, SYSDB_LAST_UPDATE,
+ (unsigned long)time(NULL));
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, ENOMEM);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (flags == LDB_FLAG_MOD_ADD) {
+ ret = ldb_build_add_req(&greq, ctx->ldb, cbctx, msg, NULL,
+ cbctx, sysdb_op_callback, NULL);
+ } else {
+ ret = ldb_build_mod_req(&greq, ctx->ldb, cbctx, msg, NULL,
+ cbctx, sysdb_op_callback, NULL);
+ }
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_request(ctx->ldb, greq);
+ }
+ if (ret != LDB_SUCCESS) {
+ return_error(cbctx, sysdb_error_to_errno(ret));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ break;
+
+ default:
+ return_error(cbctx, EINVAL);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(rep);
+ return LDB_SUCCESS;
+}
+
diff --git a/server/db/sysdb_private.h b/server/db/sysdb_private.h
index c649af4a..35cafb0d 100644
--- a/server/db/sysdb_private.h
+++ b/server/db/sysdb_private.h
@@ -78,18 +78,8 @@ struct sysdb_ctx {
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);
+bool sysdb_req_check_running(struct sysdb_req *req);
#endif /* __INT_SYS_DB_H__ */
diff --git a/server/db/sysdb_req.c b/server/db/sysdb_req.c
index fcbd17b8..161431cc 100644
--- a/server/db/sysdb_req.c
+++ b/server/db/sysdb_req.c
@@ -34,6 +34,17 @@ struct sysdb_req {
bool transaction_active;
};
+bool sysdb_req_check_running(struct sysdb_req *req)
+{
+ if (req->ctx->queue == req) return true;
+ return false;
+}
+
+struct sysdb_ctx *sysdb_req_get_ctx(struct sysdb_req *req)
+{
+ return req->ctx;
+}
+
static void sysdb_req_run(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv, void *ptr)
diff --git a/server/db/sysdb_search.c b/server/db/sysdb_search.c
index 5a355a0f..bb71079b 100644
--- a/server/db/sysdb_search.c
+++ b/server/db/sysdb_search.c
@@ -102,7 +102,7 @@ static void request_done(struct sysdb_search_ctx *sctx)
}
static int get_gen_callback(struct ldb_request *req,
- struct ldb_reply *ares)
+ struct ldb_reply *rep)
{
struct sysdb_search_ctx *sctx;
struct ldb_result *res;
@@ -111,16 +111,16 @@ static int get_gen_callback(struct ldb_request *req,
sctx = talloc_get_type(req->context, struct sysdb_search_ctx);
res = sctx->res;
- if (!ares) {
+ if (!rep) {
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;
+ if (rep->error != LDB_SUCCESS) {
+ request_ldberror(sctx, rep->error);
+ return rep->error;
}
- switch (ares->type) {
+ switch (rep->type) {
case LDB_REPLY_ENTRY:
res->msgs = talloc_realloc(res, res->msgs,
struct ldb_message *,
@@ -132,7 +132,7 @@ static int get_gen_callback(struct ldb_request *req,
res->msgs[res->count + 1] = NULL;
- res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+ res->msgs[res->count] = talloc_steal(res->msgs, rep->message);
res->count++;
break;
@@ -149,12 +149,12 @@ static int get_gen_callback(struct ldb_request *req,
return LDB_ERR_OPERATIONS_ERROR;
}
- res->refs[n] = talloc_steal(res->refs, ares->referral);
+ res->refs[n] = talloc_steal(res->refs, rep->referral);
res->refs[n + 1] = NULL;
break;
case LDB_REPLY_DONE:
- res->controls = talloc_steal(res, ares->controls);
+ res->controls = talloc_steal(res, rep->controls);
/* check if we need to call any aux function */
if (sctx->gen_aux_fn) {
@@ -166,7 +166,7 @@ static int get_gen_callback(struct ldb_request *req,
return LDB_SUCCESS;
}
- talloc_free(ares);
+ talloc_free(rep);
return LDB_SUCCESS;
}
@@ -351,7 +351,7 @@ static void get_members(struct sysdb_search_ctx *sctx)
}
static int get_grp_callback(struct ldb_request *req,
- struct ldb_reply *ares)
+ struct ldb_reply *rep)
{
struct sysdb_search_ctx *sctx;
struct sysdb_ctx *ctx;
@@ -362,16 +362,16 @@ static int get_grp_callback(struct ldb_request *req,
ctx = sctx->ctx;
res = sctx->res;
- if (!ares) {
+ if (!rep) {
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;
+ if (rep->error != LDB_SUCCESS) {
+ request_ldberror(sctx, rep->error);
+ return rep->error;
}
- switch (ares->type) {
+ switch (rep->type) {
case LDB_REPLY_ENTRY:
res->msgs = talloc_realloc(res, res->msgs,
struct ldb_message *,
@@ -383,7 +383,7 @@ static int get_grp_callback(struct ldb_request *req,
res->msgs[res->count + 1] = NULL;
- res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+ res->msgs[res->count] = talloc_steal(res->msgs, rep->message);
res->count++;
break;
@@ -400,12 +400,12 @@ static int get_grp_callback(struct ldb_request *req,
return LDB_ERR_OPERATIONS_ERROR;
}
- res->refs[n] = talloc_steal(res->refs, ares->referral);
+ res->refs[n] = talloc_steal(res->refs, rep->referral);
res->refs[n + 1] = NULL;
break;
case LDB_REPLY_DONE:
- res->controls = talloc_steal(res, ares->controls);
+ res->controls = talloc_steal(res, rep->controls);
/* no results, return */
if (res->count == 0) {
@@ -434,7 +434,7 @@ static int get_grp_callback(struct ldb_request *req,
return LDB_ERR_OPERATIONS_ERROR;
}
- talloc_free(ares);
+ talloc_free(rep);
return LDB_SUCCESS;
}
diff --git a/server/db/sysdb_sync.c b/server/db/sysdb_sync.c
deleted file mode 100644
index 1910e9fc..00000000
--- a/server/db/sysdb_sync.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- 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 <time.h>
-
-/* the following are all SYNCHRONOUS calls
- * TODO: make these asynchronous */
-
-int sysdb_add_group_member(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn)
-{
- TALLOC_CTX *tmp_ctx;
- int ret, lret;
- struct ldb_message *msg;
-
- tmp_ctx = talloc_new(mem_ctx);
- if (!tmp_ctx) return ENOMEM;
-
- /* Add the member_dn as a member of the group */
- msg = ldb_msg_new(tmp_ctx);
- if(msg == NULL) {
- ret = ENOMEM;
- goto done;
- }
- msg->dn = group_dn;
- lret = ldb_msg_add_empty(msg, SYSDB_GR_MEMBER,
- LDB_FLAG_MOD_ADD, NULL);
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- lret = ldb_msg_add_fmt(msg, SYSDB_GR_MEMBER, "%s",
- ldb_dn_get_linearized(member_dn));
- if (lret != LDB_SUCCESS) {
- ret = EINVAL;
- goto done;
- }
-
- lret = ldb_modify(sysdb->ldb, msg);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make modify request: %s(%d)[%s]\n",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-int sysdb_remove_group_member(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- struct ldb_dn *member_dn,
- struct ldb_dn *group_dn)
-{
- TALLOC_CTX *tmp_ctx;
- int ret, lret;
- struct ldb_message *msg;
-
- tmp_ctx = talloc_new(mem_ctx);
- if (!tmp_ctx) return ENOMEM;
-
- /* Add the member_dn as a member of the group */
- msg = ldb_msg_new(tmp_ctx);
- if(msg == NULL) {
- ret = ENOMEM;
- goto done;
- }
- msg->dn = group_dn;
- lret = ldb_msg_add_empty(msg, SYSDB_GR_MEMBER,
- LDB_FLAG_MOD_DELETE, NULL);
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- lret = ldb_msg_add_fmt(msg, SYSDB_GR_MEMBER, "%s",
- ldb_dn_get_linearized(member_dn));
- if (lret != LDB_SUCCESS) {
- ret = EINVAL;
- goto done;
- }
-
- lret = ldb_modify(sysdb->ldb, msg);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make modify request: %s(%d)[%s]\n",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/* "sysdb_legacy_" functions
- * the set of functions named sysdb_legacy_* are used by modules
- * that only have access to strictly posix like databases where
- * user and groups names are retrieved as strings, groups can't
- * be nested and can't reference foreign sources */
-
-int sysdb_legacy_store_user(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain,
- const char *name, const char *pwd,
- uid_t uid, gid_t gid, const char *gecos,
- const char *homedir, const char *shell)
-{
- TALLOC_CTX *tmp_ctx;
- const char *attrs[] = { SYSDB_PW_NAME, NULL };
- struct ldb_dn *user_dn;
- struct ldb_message *msg;
- struct ldb_request *req;
- struct ldb_result *res;
- int lret, ret;
- int flags;
-
- tmp_ctx = talloc_new(memctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- user_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_PW_NAME"=%s,"SYSDB_TMPL_USER_BASE,
- name, domain);
- if (!user_dn) {
- talloc_free(tmp_ctx);
- return ENOMEM;
- }
-
- lret = ldb_transaction_start(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret));
- ret = EIO;
- goto done;
- }
-
- lret = ldb_search(sysdb->ldb, tmp_ctx, &res, user_dn,
- LDB_SCOPE_BASE, attrs, SYSDB_PWENT_FILTER);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make search request: %s(%d)[%s]\n",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- req = NULL;
-
- msg = ldb_msg_new(tmp_ctx);
- if (!msg) {
- ret = ENOMEM;
- goto done;
- }
- msg->dn = user_dn;
-
- switch (res->count) {
- case 0:
- flags = LDB_FLAG_MOD_ADD;
- break;
- case 1:
- flags = LDB_FLAG_MOD_REPLACE;
- break;
- default:
- DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
- res->count));
- ret = EIO;
- goto done;
- }
-
- talloc_free(res);
- res = NULL;
-
- if (flags == LDB_FLAG_MOD_ADD) {
- /* TODO: retrieve user objectclass list from configuration */
- lret = ldb_msg_add_empty(msg, "objectClass", flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, "objectClass", "user");
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- /* TODO: retrieve user name attribute from configuration */
- lret = ldb_msg_add_empty(msg, SYSDB_PW_NAME, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, SYSDB_PW_NAME, name);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- /* TODO: retrieve attribute name mappings from configuration */
-
- /* pwd */
- if (pwd && *pwd) {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_PWD, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, SYSDB_PW_PWD, pwd);
- }
- } else {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_PWD,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- /* uid */
- if (uid) {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_UIDNUM, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_fmt(msg, SYSDB_PW_UIDNUM,
- "%lu", (unsigned long)uid);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- } else {
- DEBUG(0, ("Cached users can't have UID == 0\n"));
- ret = EINVAL;
- goto done;
- }
-
- /* gid */
- if (gid) {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_GIDNUM, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_fmt(msg, SYSDB_PW_GIDNUM,
- "%lu", (unsigned long)gid);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- } else {
- DEBUG(0, ("Cached users can't have GID == 0\n"));
- ret = EINVAL;
- goto done;
- }
-
- /* gecos */
- if (gecos && *gecos) {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_FULLNAME, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, SYSDB_PW_FULLNAME, gecos);
- }
- } else {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_FULLNAME,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- /* homedir */
- if (homedir && *homedir) {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_HOMEDIR, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, SYSDB_PW_HOMEDIR, homedir);
- }
- } else {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_HOMEDIR,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- /* shell */
- if (shell && *shell) {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_SHELL, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, SYSDB_PW_SHELL, shell);
- }
- } else {
- lret = ldb_msg_add_empty(msg, SYSDB_PW_SHELL,
- LDB_FLAG_MOD_DELETE, NULL);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- /* modification time */
- lret = ldb_msg_add_empty(msg, SYSDB_LAST_UPDATE, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_fmt(msg, SYSDB_LAST_UPDATE,
- "%ld", (long int)time(NULL));
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- if (flags == LDB_FLAG_MOD_ADD) {
- lret = ldb_build_add_req(&req, sysdb->ldb, tmp_ctx, msg, NULL,
- NULL, ldb_op_default_callback, NULL);
- } else {
- lret = ldb_build_mod_req(&req, sysdb->ldb, tmp_ctx, msg, NULL,
- NULL, ldb_op_default_callback, NULL);
- }
- if (lret == LDB_SUCCESS) {
- lret = ldb_request(sysdb->ldb, req);
- if (lret == LDB_SUCCESS) {
- lret = ldb_wait(req->handle, LDB_WAIT_ALL);
- }
- }
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make modify request: %s(%d)[%s]\n",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- ret = EOK;
-
-done:
- if (ret == EOK) {
- lret = ldb_transaction_commit(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret));
- ret = EIO;
- }
- } else {
- lret = ldb_transaction_cancel(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to cancel ldb transaction (%d)\n", lret));
- ret = EIO;
- }
- }
-
- talloc_free(tmp_ctx);
- return ret;
-}
-
-int sysdb_delete_user(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, const char *name)
-{
- TALLOC_CTX *tmp_ctx;
- struct ldb_dn *user_dn;
- int lret, ret = EOK;
-
- tmp_ctx = talloc_new(memctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- user_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_PW_NAME"=%s,"SYSDB_TMPL_USER_BASE,
- name, domain);
- if (!user_dn) {
- talloc_free(tmp_ctx);
- return ENOMEM;
- }
-
- lret = ldb_delete(sysdb->ldb, user_dn);
-
- if (lret != LDB_SUCCESS && lret != LDB_ERR_NO_SUCH_OBJECT) {
- DEBUG(2, ("LDB Error: %s(%d)\nError Message: [%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- }
-
- talloc_free(tmp_ctx);
- return ret;
-}
-
-int sysdb_delete_user_by_uid(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, uid_t uid)
-{
- TALLOC_CTX *tmp_ctx;
- const char *attrs[] = { SYSDB_PW_NAME, SYSDB_PW_UIDNUM, NULL };
- struct ldb_dn *base_dn;
- struct ldb_dn *user_dn;
- struct ldb_result *res;
- int lret, ret;
-
- tmp_ctx = talloc_new(memctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- base_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_TMPL_USER_BASE, domain);
- if (!base_dn) {
- talloc_free(tmp_ctx);
- return ENOMEM;
- }
-
- lret = ldb_transaction_start(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret));
- ret = EIO;
- goto done;
- }
-
- lret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
- LDB_SCOPE_ONELEVEL, attrs,
- SYSDB_PWUID_FILTER,
- (unsigned long)uid);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make search request: %s(%d)[%s]\n",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- if (res->count == 0) {
- DEBUG(7, ("Base search returned no results\n"));
- ret = EOK;
- goto done;
- }
- if (res->count > 1) {
- DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
- res->count));
- ret = EIO;
- goto done;
- }
-
- user_dn = ldb_dn_copy(tmp_ctx, res->msgs[0]->dn);
- if (!user_dn) {
- ret = ENOMEM;
- goto done;
- }
-
- talloc_free(res);
- res = NULL;
-
- lret = ldb_delete(sysdb->ldb, user_dn);
-
- if (lret != LDB_SUCCESS && lret != LDB_ERR_NO_SUCH_OBJECT) {
- DEBUG(2, ("LDB Error: %s(%d)\nError Message: [%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- ret = EOK;
-
-done:
- if (ret == EOK) {
- lret = ldb_transaction_commit(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction commit !! (%d)\n", lret));
- ret = EIO;
- }
- } else {
- lret = ldb_transaction_cancel(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to cancel ldb transaction (%d)\n", lret));
- ret = EIO;
- }
- }
-
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/* this function does not check that all user members are actually present */
-
-int sysdb_legacy_store_group(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain,
- const char *name, gid_t gid,
- char **members)
-{
- TALLOC_CTX *tmp_ctx;
- const char *attrs[] = { SYSDB_GR_NAME, NULL };
- struct ldb_dn *group_dn;
- struct ldb_result *res;
- struct ldb_message *msg;
- int i, ret, lret;
- int flags;
-
- tmp_ctx = talloc_new(memctx);
- if (tmp_ctx == NULL) {
- return ENOMEM;
- }
-
- group_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE,
- name, domain);
- if (group_dn == NULL) {
- talloc_free(tmp_ctx);
- return ENOMEM;
- }
-
- /* Start a transaction to ensure that nothing changes
- * underneath us while we're working
- */
- lret = ldb_transaction_start(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret));
- talloc_free(tmp_ctx);
- return EIO;
- }
-
- /* Determine if the group already exists */
- lret = ldb_search(sysdb->ldb, tmp_ctx, &res, group_dn,
- LDB_SCOPE_BASE, attrs, SYSDB_GRENT_FILTER);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make search request: %s(%d)[%s]\b",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- switch(res->count) {
- case 0:
- flags = LDB_FLAG_MOD_ADD;
- DEBUG(7, ("Adding new entry\n"));
- break;
- case 1:
- flags = LDB_FLAG_MOD_REPLACE;
- DEBUG(7, ("Replacing existing entry\n"));
- break;
- default:
- DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
- res->count));
- ret = EIO;
- goto done;
- }
- talloc_free(res);
- res = NULL;
-
- /* Set up the add/replace request */
- msg = ldb_msg_new(tmp_ctx);
- if (msg == NULL) {
- ret = ENOMEM;
- goto done;
- }
- msg->dn = group_dn;
-
- if (flags == LDB_FLAG_MOD_ADD) {
- lret = ldb_msg_add_empty(msg, "objectClass", flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, "objectClass", "group");
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- lret = ldb_msg_add_empty(msg, SYSDB_GR_NAME, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_string(msg, SYSDB_GR_NAME, name);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- /* gid */
- if (gid) {
- lret = ldb_msg_add_empty(msg, SYSDB_GR_GIDNUM, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_fmt(msg, SYSDB_GR_GIDNUM,
- "%lu", (unsigned long)gid);
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- } else {
- DEBUG(0, ("Cached groups can't have GID == 0\n"));
- ret = EINVAL;
- goto done;
- }
-
- /* modification time */
- lret = ldb_msg_add_empty(msg, SYSDB_LAST_UPDATE, flags, NULL);
- if (lret == LDB_SUCCESS) {
- lret = ldb_msg_add_fmt(msg, SYSDB_LAST_UPDATE,
- "%ld", (long int)time(NULL));
- }
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
-
- /* members */
- if (members && members[0]) {
- lret = ldb_msg_add_empty(msg, SYSDB_LEGACY_MEMBER, flags, NULL);
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- for (i = 0; members[i]; i++) {
- lret = ldb_msg_add_string(msg, SYSDB_LEGACY_MEMBER, members[i]);
- if (lret != LDB_SUCCESS) {
- ret = ENOMEM;
- goto done;
- }
- }
- }
-
- if (flags == LDB_FLAG_MOD_ADD) {
- lret = ldb_add(sysdb->ldb, msg);
- } else {
- lret = ldb_modify(sysdb->ldb, msg);
- }
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make modify request: %s(%d)[%s]\n",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- ret = EOK;
-
-done:
- if (ret == EOK) {
- lret = ldb_transaction_commit(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret));
- ret = EIO;
- }
- } else {
- lret = ldb_transaction_cancel(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to cancel ldb transaction (%d)\n", lret));
- ret = EIO;
- }
- }
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/* Wrapper around adding a user to a POSIX group */
-int sysdb_add_user_to_group(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain,
- const char *group,
- const char *username)
-{
- TALLOC_CTX *tmp_ctx;
- int ret;
- struct ldb_dn *user_dn;
- struct ldb_dn *group_dn;
-
-
- if (!sysdb || !domain || !group || !username) {
- return EINVAL;
- }
-
- tmp_ctx = talloc_new(mem_ctx);
- if (tmp_ctx == NULL) {
- return ENOMEM;
- }
-
- user_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_PW_NAME"=%s,"SYSDB_TMPL_USER_BASE,
- username, domain);
- if (!user_dn) {
- ret = ENOMEM;
- goto done;
- }
-
- group_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE,
- group, domain);
- if (group_dn == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- ret = sysdb_add_group_member(tmp_ctx, sysdb, user_dn, group_dn);
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/* Wrapper around adding a user to a POSIX group */
-int sysdb_remove_user_from_group(TALLOC_CTX *mem_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain,
- const char *group,
- const char *username)
-{
- TALLOC_CTX *tmp_ctx;
- int ret;
- struct ldb_dn *user_dn;
- struct ldb_dn *group_dn;
-
-
- if (!sysdb || !domain || !group || !username) {
- return EINVAL;
- }
-
- tmp_ctx = talloc_new(mem_ctx);
- if (tmp_ctx == NULL) {
- return ENOMEM;
- }
-
- user_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_PW_NAME"=%s,"SYSDB_TMPL_USER_BASE,
- username, domain);
- if (!user_dn) {
- ret = ENOMEM;
- goto done;
- }
-
- group_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE,
- group, domain);
- if (group_dn == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- ret = sysdb_remove_group_member(tmp_ctx, sysdb, user_dn, group_dn);
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-int sysdb_delete_group(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, const char *name)
-{
- TALLOC_CTX *tmp_ctx;
- struct ldb_dn *group_dn;
- int lret, ret = EOK;
-
- tmp_ctx = talloc_new(memctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- group_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE,
- name, domain);
- if (!group_dn) {
- talloc_free(tmp_ctx);
- return ENOMEM;
- }
-
- lret = ldb_delete(sysdb->ldb, group_dn);
-
- if (lret != LDB_SUCCESS && lret != LDB_ERR_NO_SUCH_OBJECT) {
- DEBUG(2, ("LDB Error: %s(%d)\nError Message: [%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- }
-
- talloc_free(tmp_ctx);
- return ret;
-}
-
-int sysdb_delete_group_by_gid(TALLOC_CTX *memctx,
- struct sysdb_ctx *sysdb,
- const char *domain, gid_t gid)
-{
- TALLOC_CTX *tmp_ctx;
- const char *attrs[] = { SYSDB_GR_NAME, SYSDB_GR_GIDNUM, NULL };
- struct ldb_dn *base_dn;
- struct ldb_dn *group_dn;
- struct ldb_result *res;
- int lret, ret;
-
- tmp_ctx = talloc_new(memctx);
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- base_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
- SYSDB_TMPL_GROUP_BASE, domain);
- if (!base_dn) {
- talloc_free(tmp_ctx);
- return ENOMEM;
- }
-
- lret = ldb_transaction_start(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret));
- ret = EIO;
- goto done;
- }
-
- lret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn,
- LDB_SCOPE_ONELEVEL, attrs,
- SYSDB_GRGID_FILTER,
- (unsigned long)gid);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to make search request: %s(%d)[%s]\n",
- ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- if (res->count == 0) {
- DEBUG(7, ("Base search returned no results\n"));
- ret = EOK;
- goto done;
- }
- if (res->count > 1) {
- DEBUG(0, ("Cache DB corrupted, base search returned %d results\n",
- res->count));
- ret = EIO;
- goto done;
- }
-
- group_dn = ldb_dn_copy(tmp_ctx, res->msgs[0]->dn);
- if (!group_dn) {
- ret = ENOMEM;
- goto done;
- }
-
- talloc_free(res);
- res = NULL;
-
- lret = ldb_delete(sysdb->ldb, group_dn);
-
- if (lret != LDB_SUCCESS && lret != LDB_ERR_NO_SUCH_OBJECT) {
- DEBUG(2, ("LDB Error: %s(%d)\nError Message: [%s]\n",
- ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
- ret = EIO;
- goto done;
- }
-
- ret = EOK;
-
-done:
- if (ret == EOK) {
- lret = ldb_transaction_commit(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed ldb transaction commit !! (%d)\n", lret));
- ret = EIO;
- }
- } else {
- lret = ldb_transaction_cancel(sysdb->ldb);
- if (lret != LDB_SUCCESS) {
- DEBUG(1, ("Failed to cancel ldb transaction (%d)\n", lret));
- ret = EIO;
- }
- }
-
- talloc_free(tmp_ctx);
- return ret;
-}
-
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index 3c39c8f8..30f5f5c1 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -61,105 +61,6 @@ struct proxy_ctx {
struct proxy_nss_ops ops;
};
-static void proxy_reply(struct be_req *req, int error, const char *errstr)
-{
- return req->fn(req, error, errstr);
-}
-
-static void get_pw_name(struct be_req *req, char *name)
-{
- struct proxy_ctx *ctx;
- enum nss_status status;
- struct passwd result;
- char *buffer;
- int ret;
-
- ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
-
- buffer = talloc_size(req, 4096);
- if (!buffer)
- return proxy_reply(req, ENOMEM, "Out of memory");
-
- status = ctx->ops.getpwnam_r(name, &result, buffer, 4096, &ret);
-
- switch (status) {
- case NSS_STATUS_NOTFOUND:
- ret = sysdb_delete_user(req, req->be_ctx->sysdb,
- req->be_ctx->domain, name);
- break;
- case NSS_STATUS_SUCCESS:
- ret = sysdb_legacy_store_user(req, req->be_ctx->sysdb,
- req->be_ctx->domain,
- result.pw_name, result.pw_passwd,
- result.pw_uid, result.pw_gid,
- result.pw_gecos, result.pw_dir,
- result.pw_shell);
- break;
- default:
- DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n",
- name, ret, strerror(ret)));
- talloc_free(buffer);
- return proxy_reply(req, ret, "Operation failed");
- }
-
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n",
- name, ret));
- talloc_free(buffer);
- return proxy_reply(req, ret, "Operation failed");
- }
-
- talloc_free(buffer);
- return proxy_reply(req, EOK, NULL);
-}
-
-static void get_pw_uid(struct be_req *req, uid_t uid)
-{
- struct proxy_ctx *ctx;
- enum nss_status status;
- struct passwd result;
- char *buffer;
- int ret;
-
- ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
-
- buffer = talloc_size(req, 4096);
- if (!buffer)
- return proxy_reply(req, ENOMEM, "Out of memory");
-
- status = ctx->ops.getpwuid_r(uid, &result, buffer, 4096, &ret);
-
- switch (status) {
- case NSS_STATUS_NOTFOUND:
- ret = sysdb_delete_user_by_uid(req, req->be_ctx->sysdb,
- req->be_ctx->domain,uid);
- break;
- case NSS_STATUS_SUCCESS:
- ret = sysdb_legacy_store_user(req, req->be_ctx->sysdb,
- req->be_ctx->domain,
- result.pw_name, result.pw_passwd,
- result.pw_uid, result.pw_gid,
- result.pw_gecos, result.pw_dir,
- result.pw_shell);
- break;
- default:
- DEBUG(2, ("proxy -> getpwuid_r failed for '%lu' (%d)[%s]\n",
- (unsigned long)uid, ret, strerror(ret)));
- talloc_free(buffer);
- return proxy_reply(req, ret, "Operation failed");
- }
-
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%lu' (%d) !?\n",
- (unsigned long)uid, ret));
- talloc_free(buffer);
- return proxy_reply(req, ret, "Operation failed");
- }
-
- talloc_free(buffer);
- return proxy_reply(req, EOK, NULL);
-}
-
struct authtok_conv {
char *authtok;
char *oldauthtok;
@@ -284,395 +185,754 @@ static void proxy_pam_handler(struct be_req *req) {
req->fn(req, EOK, NULL);
}
+static void proxy_reply(struct be_req *req, int error, const char *errstr)
+{
+ return req->fn(req, error, errstr);
+}
+
+struct proxy_data {
+ struct sysdb_req *sysreq;
+ struct proxy_ctx *ctx;
+ struct be_req *req;
+
+ char *buffer;
+ size_t buflen;
+
+ struct passwd *pwd;
+ struct group *grp;
+
+ gid_t *groups;
+ long int num;
+ long int cur;
+
+ struct ldb_dn *dn;
+
+ sysdb_callback_t next_fn;
+};
+
+static void proxy_return(void *pvt, int error, struct ldb_result *ignore)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ const char *err = "Success";
+
+ if (error != EOK) err = "Operation failed";
+
+ sysdb_transaction_done(data->sysreq, error);
+ return proxy_reply(data->req, error, err);
+}
+
+static void del_db_entry(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct sysdb_ctx *ctx;
+ int ret;
+
+ data->sysreq = req;
+ ctx = sysdb_req_get_ctx(req);
+
+ ret = sysdb_delete_entry(req, data->dn, data->next_fn, data);
+ if (ret != EOK) {
+ proxy_return(data, ret, NULL);
+ }
+}
+
+static void del_pw_uid(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct sysdb_ctx *ctx;
+ int ret;
+
+ data->sysreq = req;
+ ctx = sysdb_req_get_ctx(req);
+
+ ret = sysdb_delete_user_by_uid(req,
+ data->req->be_ctx->domain,
+ data->pwd->pw_uid,
+ data->next_fn, data);
+ if (ret != EOK) {
+ proxy_return(data, ret, NULL);
+ }
+}
+
+static void set_pw_name(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct sysdb_ctx *ctx;
+ int ret;
+
+ data->sysreq = req;
+ ctx = sysdb_req_get_ctx(req);
+
+ ret = sysdb_legacy_store_user(req, data->req->be_ctx->domain,
+ data->pwd->pw_name, data->pwd->pw_passwd,
+ data->pwd->pw_uid, data->pwd->pw_gid,
+ data->pwd->pw_gecos, data->pwd->pw_dir,
+ data->pwd->pw_shell,
+ data->next_fn, data);
+ if (ret != EOK) {
+ proxy_return(data, ret, NULL);
+ }
+}
+
+static void get_pw_name(struct be_req *req, char *name)
+{
+ struct proxy_ctx *ctx;
+ enum nss_status status;
+ struct proxy_data *data;
+ int ret;
+
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->next_fn = proxy_return;
+ data->pwd = talloc(data, struct passwd);
+ if (!data->pwd)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ data->buflen = 4096;
+ data->buffer = talloc_size(data, data->buflen);
+ if (!data->buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.getpwnam_r(name, data->pwd,
+ data->buffer, data->buflen, &ret);
+
+ switch (status) {
+ case NSS_STATUS_NOTFOUND:
+ data->dn = sysdb_user_dn(req->be_ctx->sysdb, data,
+ req->be_ctx->domain, name);
+ if (!data->dn)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+ break;
+
+ case NSS_STATUS_SUCCESS:
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data);
+ break;
+
+ default:
+ DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n",
+ name, ret, strerror(ret)));
+ return proxy_reply(req, ret, "Operation failed");
+ }
+
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
+ return proxy_reply(req, ret, "Operation failed");
+ }
+}
+
+static void get_pw_uid(struct be_req *req, uid_t uid)
+{
+ struct proxy_ctx *ctx;
+ enum nss_status status;
+ struct proxy_data *data;
+ int ret;
+
+ ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->next_fn = proxy_return;
+ data->pwd = talloc(data, struct passwd);
+ if (!data->pwd)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ data->buflen = 4096;
+ data->buffer = talloc_size(data, data->buflen);
+ if (!data->buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.getpwuid_r(uid, data->pwd,
+ data->buffer, data->buflen, &ret);
+
+ switch (status) {
+ case NSS_STATUS_NOTFOUND:
+ data->pwd->pw_uid = uid;
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, del_pw_uid, data);
+ break;
+
+ case NSS_STATUS_SUCCESS:
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data);
+ break;
+
+ default:
+ DEBUG(2, ("proxy -> getpwuid_r failed for '%lu' (%d)[%s]\n",
+ (unsigned long)uid, ret, strerror(ret)));
+ return proxy_reply(req, ret, "Operation failed");
+ }
+
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
+ return proxy_reply(req, ret, "Operation failed");
+ }
+}
+
#define MAX_BUF_SIZE 1024*1024 /* max 1MiB */
+static void get_pw_entry(struct sysdb_req *req, void *pvt);
+
+static void get_next_pw_entry(void *pvt, int error, struct ldb_result *ignore)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+
+ if (error != EOK) proxy_return(data, error, NULL);
+
+ get_pw_entry(data->sysreq, data);
+}
+
+static void get_pw_entry(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ enum nss_status status;
+ struct sysdb_ctx *ctx;
+ char *newb;
+ int ret;
+
+ data->sysreq = req;
+ ctx = sysdb_req_get_ctx(req);
+
+retry:
+ status = data->ctx->ops.getpwent_r(data->pwd,
+ data->buffer, data->buflen, &ret);
+
+ switch (status) {
+ case NSS_STATUS_TRYAGAIN:
+ /* buffer too small ? */
+ if (data->buflen < MAX_BUF_SIZE) {
+ data->buflen *= 2;
+ }
+ if (data->buflen > MAX_BUF_SIZE) {
+ data->buflen = MAX_BUF_SIZE;
+ }
+ newb = talloc_realloc_size(data, data->buffer, data->buflen);
+ if (!newb) {
+ return proxy_return(data, ENOMEM, NULL);
+ }
+ data->buffer = newb;
+ goto retry;
+
+ case NSS_STATUS_NOTFOUND:
+
+ data->ctx->ops.endpwent();
+ data->next_fn(data, EOK, NULL);
+ break;
+
+ case NSS_STATUS_SUCCESS:
+ ret = sysdb_legacy_store_user(req, data->req->be_ctx->domain,
+ data->pwd->pw_name,
+ data->pwd->pw_passwd,
+ data->pwd->pw_uid,
+ data->pwd->pw_gid,
+ data->pwd->pw_gecos,
+ data->pwd->pw_dir,
+ data->pwd->pw_shell,
+ get_next_pw_entry, data);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->pwd->pw_name, ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ }
+ break;
+
+ default:
+ DEBUG(2, ("proxy -> getpwent_r failed (%d)[%s]\n",
+ ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ }
+}
+
static void enum_users(struct be_req *req)
{
struct proxy_ctx *ctx;
enum nss_status status;
- struct passwd result;
- char *buffer, *newb;
- size_t buflen;
- const char *errstr;
+ struct proxy_data *data;
int ret;
ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
- buflen = 4096;
- buffer = talloc_size(req, buflen);
- if (!buffer)
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->next_fn = proxy_return;
+ data->pwd = talloc(data, struct passwd);
+ if (!data->pwd)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ data->buflen = 4096;
+ data->buffer = talloc_size(data, data->buflen);
+ if (!data->buffer)
return proxy_reply(req, ENOMEM, "Out of memory");
status = ctx->ops.setpwent();
if (status != NSS_STATUS_SUCCESS)
return proxy_reply(req, EIO, "Operation failed");
- while (status == NSS_STATUS_SUCCESS) {
-
- status = ctx->ops.getpwent_r(&result, buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- /* buffer too small ? */
- if (buflen < MAX_BUF_SIZE) {
- buflen *= 2;
- }
- if (buflen > MAX_BUF_SIZE) {
- buflen = MAX_BUF_SIZE;
- }
- newb = talloc_realloc_size(NULL, buffer, buflen);
- if (!newb) {
- errstr = "Out of memory";
- ret = ENOMEM;
- goto done;
- }
- buffer = newb;
- status = NSS_STATUS_SUCCESS;
- break;
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, get_pw_entry, data);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
+ return proxy_reply(req, ret, "Operation failed");
+ }
+}
- case NSS_STATUS_NOTFOUND:
- /* we got last one */
- break;
+static void del_gr_uid(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct sysdb_ctx *ctx;
+ int ret;
- case NSS_STATUS_SUCCESS:
- ret = sysdb_legacy_store_user(req, req->be_ctx->sysdb,
- req->be_ctx->domain,
- result.pw_name, result.pw_passwd,
- result.pw_uid, result.pw_gid,
- result.pw_gecos, result.pw_dir,
- result.pw_shell);
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
- (unsigned long)result.pw_name, ret, strerror(ret)));
- }
- break;
+ data->sysreq = req;
+ ctx = sysdb_req_get_ctx(req);
- default:
- DEBUG(2, ("proxy -> getpwent_r failed (%d)[%s]\n",
- ret, strerror(ret)));
- errstr = "Operation failed";
- goto done;
- }
+ ret = sysdb_delete_group_by_gid(req,
+ data->req->be_ctx->domain,
+ data->grp->gr_gid,
+ data->next_fn, data);
+ if (ret != EOK) {
+ proxy_return(data, ret, NULL);
}
+}
- errstr = NULL;
- ret = EOK;
+static void set_gr_name(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ struct sysdb_ctx *ctx;
+ int ret;
-done:
- talloc_free(buffer);
- ctx->ops.endpwent();
- return proxy_reply(req, ret, errstr);
+ data->sysreq = req;
+ ctx = sysdb_req_get_ctx(req);
+
+ ret = sysdb_legacy_store_group(req, data->req->be_ctx->domain,
+ data->grp->gr_name,
+ data->grp->gr_gid,
+ (const char **)data->grp->gr_mem,
+ data->next_fn, data);
+ if (ret != EOK) {
+ proxy_return(data, ret, NULL);
+ }
}
static void get_gr_name(struct be_req *req, char *name)
{
struct proxy_ctx *ctx;
enum nss_status status;
- struct group result;
- char *buffer;
+ struct proxy_data *data;
int ret;
ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
- buffer = talloc_size(NULL, 4096);
- if (!buffer)
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->next_fn = proxy_return;
+ data->grp = talloc(data, struct group);
+ if (!data->grp)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ data->buflen = 4096;
+ data->buffer = talloc_size(data, data->buflen);
+ if (!data->buffer)
return proxy_reply(req, ENOMEM, "Out of memory");
- status = ctx->ops.getgrnam_r(name, &result, buffer, 4096, &ret);
+ status = ctx->ops.getgrnam_r(name, data->grp,
+ data->buffer, data->buflen, &ret);
switch (status) {
case NSS_STATUS_NOTFOUND:
- ret = sysdb_delete_group(req, req->be_ctx->sysdb,
- req->be_ctx->domain, name);
+ data->dn = sysdb_group_dn(req->be_ctx->sysdb, data,
+ req->be_ctx->domain, name);
+ if (!data->dn)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
break;
+
case NSS_STATUS_SUCCESS:
- ret = sysdb_legacy_store_group(req, req->be_ctx->sysdb,
- req->be_ctx->domain, result.gr_name,
- result.gr_gid, result.gr_mem);
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, set_gr_name, data);
break;
+
default:
DEBUG(2, ("proxy -> getgrnam_r failed for '%s' (%d)[%s]\n",
name, ret, strerror(ret)));
- talloc_free(buffer);
return proxy_reply(req, ret, "Operation failed");
}
if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n",
- name, ret));
- talloc_free(buffer);
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
return proxy_reply(req, ret, "Operation failed");
}
-
- talloc_free(buffer);
- return proxy_reply(req, EOK, NULL);
}
static void get_gr_gid(struct be_req *req, gid_t gid)
{
struct proxy_ctx *ctx;
enum nss_status status;
- struct group result;
- char *buffer;
+ struct proxy_data *data;
int ret;
ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
- buffer = talloc_size(req, 4096);
- if (!buffer)
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->next_fn = proxy_return;
+ data->grp = talloc(data, struct group);
+ if (!data->grp)
return proxy_reply(req, ENOMEM, "Out of memory");
- status = ctx->ops.getgrgid_r(gid, &result, buffer, 4096, &ret);
+ data->buflen = 4096;
+ data->buffer = talloc_size(data, data->buflen);
+ if (!data->buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.getgrgid_r(gid, data->grp,
+ data->buffer, data->buflen, &ret);
switch (status) {
case NSS_STATUS_NOTFOUND:
- ret = sysdb_delete_group_by_gid(req, req->be_ctx->sysdb,
- req->be_ctx->domain, gid);
+ data->grp->gr_gid = gid;
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, del_gr_uid, data);
break;
+
case NSS_STATUS_SUCCESS:
- ret = sysdb_legacy_store_group(req, req->be_ctx->sysdb,
- req->be_ctx->domain, result.gr_name,
- result.gr_gid, result.gr_mem);
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, set_gr_name, data);
break;
+
default:
DEBUG(2, ("proxy -> getgrgid_r failed for '%lu' (%d)[%s]\n",
(unsigned long)gid, ret, strerror(ret)));
- talloc_free(buffer);
return proxy_reply(req, ret, "Operation failed");
}
if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%lu' (%d) !?\n",
- (unsigned long)gid, ret));
- talloc_free(buffer);
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
return proxy_reply(req, ret, "Operation failed");
}
+}
- talloc_free(buffer);
- return proxy_reply(req, EOK, NULL);
+static void get_gr_entry(struct sysdb_req *req, void *pvt);
+
+static void get_next_gr_entry(void *pvt, int error, struct ldb_result *ignore)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+
+ if (error != EOK) proxy_return(data, error, NULL);
+
+ get_gr_entry(data->sysreq, data);
+}
+
+static void get_gr_entry(struct sysdb_req *req, void *pvt)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
+ enum nss_status status;
+ struct sysdb_ctx *ctx;
+ char *newb;
+ int ret;
+
+ data->sysreq = req;
+ ctx = sysdb_req_get_ctx(req);
+
+retry:
+ status = data->ctx->ops.getgrent_r(data->grp,
+ data->buffer, data->buflen, &ret);
+
+ switch (status) {
+ case NSS_STATUS_TRYAGAIN:
+ /* buffer too small ? */
+ if (data->buflen < MAX_BUF_SIZE) {
+ data->buflen *= 2;
+ }
+ if (data->buflen > MAX_BUF_SIZE) {
+ data->buflen = MAX_BUF_SIZE;
+ }
+ newb = talloc_realloc_size(data, data->buffer, data->buflen);
+ if (!newb) {
+ return proxy_return(data, ENOMEM, NULL);
+ }
+ data->buffer = newb;
+ goto retry;
+
+ case NSS_STATUS_NOTFOUND:
+
+ data->ctx->ops.endgrent();
+ data->next_fn(data, EOK, NULL);
+ break;
+
+ case NSS_STATUS_SUCCESS:
+ ret = sysdb_legacy_store_group(req, data->req->be_ctx->domain,
+ data->grp->gr_name,
+ data->grp->gr_gid,
+ (const char **)data->grp->gr_mem,
+ get_next_gr_entry, data);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->grp->gr_name, ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ }
+ break;
+
+ default:
+ DEBUG(2, ("proxy -> getgrent_r failed (%d)[%s]\n",
+ ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ }
}
static void enum_groups(struct be_req *req)
{
struct proxy_ctx *ctx;
enum nss_status status;
- struct group result;
- char *buffer, *newb;
- size_t buflen;
- const char * errstr;
- int ret, c;
+ struct proxy_data *data;
+ int ret;
ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
- buflen = 4096;
- buffer = talloc_size(req, buflen);
- if (!buffer)
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->next_fn = proxy_return;
+ data->grp = talloc(data, struct group);
+ if (!data->grp)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ data->buflen = 4096;
+ data->buffer = talloc_size(data, data->buflen);
+ if (!data->buffer)
return proxy_reply(req, ENOMEM, "Out of memory");
status = ctx->ops.setgrent();
if (status != NSS_STATUS_SUCCESS)
return proxy_reply(req, EIO, "Operation failed");
- c = 0;
- while (status == NSS_STATUS_SUCCESS) {
-
- status = ctx->ops.getgrent_r(&result, buffer, buflen, &ret);
-
- switch (status) {
- case NSS_STATUS_TRYAGAIN:
- DEBUG(20, ("Try Again\n"));
-
- if (ret != ERANGE) {
- DEBUG(2, ("getgrent_r failed (TRYAGAIN)(%d)[%s]\n",
- ret, strerror(ret)));
- errstr = "Operation failed";
- goto done;
- }
- /* buffer too small ? */
- if (buflen < MAX_BUF_SIZE) {
- buflen *= 2;
- }
- if (buflen > MAX_BUF_SIZE) {
- buflen = MAX_BUF_SIZE;
- }
- newb = talloc_realloc_size(req, buffer, buflen);
- if (!newb) {
- DEBUG(4, ("Out of memory\n"));
- errstr = "Out of memory";
- ret = ENOMEM;
- goto done;
- }
- buffer = newb;
- status = NSS_STATUS_SUCCESS;
- break;
-
- case NSS_STATUS_NOTFOUND:
- DEBUG(6, ("No more entries\n"));
- /* we got last one */
- break;
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, get_gr_entry, data);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
+ return proxy_reply(req, ret, "Operation failed");
+ }
+}
- case NSS_STATUS_SUCCESS:
- c++;
- DEBUG(20, ("Storing group [%s](%d)\n", result.gr_name, c));
- ret = sysdb_legacy_store_group(req, req->be_ctx->sysdb,
- req->be_ctx->domain, result.gr_name,
- result.gr_gid, result.gr_mem);
- if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
- (unsigned long)result.gr_name, ret, strerror(ret)));
- }
- break;
+static void get_gid_entry(struct sysdb_req *req, void *pvt);
- default:
- DEBUG(2, ("getgrent_r failed (%d)[%s]\n", ret, strerror(ret)));
- errstr = "Operation failed";
- goto done;
- }
- }
+static void get_next_gid_entry(void *pvt, int error, struct ldb_result *ignore)
+{
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
- errstr = NULL;
- ret = EOK;
+ if (error != EOK) proxy_return(data, error, NULL);
-done:
- talloc_free(buffer);
- ctx->ops.endgrent();
- return proxy_reply(req, ret, errstr);
+ get_gid_entry(data->sysreq, data);
}
-static int save_initgroups(struct be_req *req, gid_t *gids, long int num)
+static void get_gid_entry(struct sysdb_req *req, void *pvt)
{
- struct proxy_ctx *ctx;
- struct sysdb_ctx *sysdb;
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
enum nss_status status;
- struct group result;
- char *buffer;
- int i, ret;
-
- ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
- sysdb = req->be_ctx->sysdb;
+ struct sysdb_ctx *ctx;
+ char *newb;
+ int ret;
- buffer = talloc_size(req, 4096);
- if (!buffer) {
- return ENOMEM;
- }
+ ctx = sysdb_req_get_ctx(req);
- for (i = 0; i < num; i++) {
+ /* all done */
+ if (data->cur == data->num)
+ return data->next_fn(data, EOK, NULL);
- status = ctx->ops.getgrgid_r(gids[i], &result, buffer, 4096, &ret);
+retry:
+ status = data->ctx->ops.getgrgid_r(data->groups[data->cur], data->grp,
+ data->buffer, data->buflen, &ret);
- switch (status) {
- case NSS_STATUS_NOTFOUND:
- DEBUG(4, ("gid [%lu] not found, removing group\n"));
- ret = sysdb_delete_group_by_gid(req, sysdb,
- req->be_ctx->domain,
- gids[i]);
- break;
+ switch (status) {
+ case NSS_STATUS_TRYAGAIN:
+ /* buffer too small ? */
+ if (data->buflen < MAX_BUF_SIZE) {
+ data->buflen *= 2;
+ }
+ if (data->buflen > MAX_BUF_SIZE) {
+ data->buflen = MAX_BUF_SIZE;
+ }
+ newb = talloc_realloc_size(data, data->buffer, data->buflen);
+ if (!newb) {
+ return proxy_return(data, ENOMEM, NULL);
+ }
+ data->buffer = newb;
+ goto retry;
- case NSS_STATUS_SUCCESS:
- ret = sysdb_legacy_store_group(req, sysdb,
- req->be_ctx->domain,
- result.gr_name,
- result.gr_gid,
- result.gr_mem);
- break;
+ case NSS_STATUS_NOTFOUND:
+ data->cur++;
+ DEBUG(4, ("gid [%lu] not found, removing group\n",
+ (unsigned long)(data->groups[data->cur])));
+ ret = sysdb_delete_group_by_gid(req, data->req->be_ctx->domain,
+ data->groups[data->cur-1],
+ get_next_gid_entry, data);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->grp->gr_name, ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ }
+ break;
- default:
- DEBUG(2, ("proxy -> getgrgid_r failed for '%lu' (%d)[%s]\n",
- (unsigned long)(gids[i]), ret, strerror(ret)));
- break;
+ case NSS_STATUS_SUCCESS:
+ data->cur++;
+ ret = sysdb_legacy_store_group(req, data->req->be_ctx->domain,
+ data->grp->gr_name,
+ data->grp->gr_gid,
+ (const char **)data->grp->gr_mem,
+ get_next_gid_entry, data);
+ if (ret != EOK) {
+ DEBUG(1, ("Failed to update LDB Cache for '%s' (%d)[%s] !?\n",
+ data->grp->gr_name, ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
}
- }
+ break;
- talloc_free(buffer);
- return EOK;
+ default:
+ DEBUG(2, ("proxy -> getgrgid_r failed (%d)[%s]\n",
+ ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ }
}
-static void get_user_groups(struct be_req *req, char *name)
+static void get_user_groups(void *pvt, int error, struct ldb_result *ignore)
{
- struct proxy_ctx *ctx;
+ struct proxy_data *data = talloc_get_type(pvt, struct proxy_data);
enum nss_status status;
- struct passwd result;
- char *buffer;
- gid_t *groups;
long int limit;
long int start;
long int size;
long int num;
+ char *name;
+ gid_t gid;
+ int ret;
+
+ if (error != EOK) proxy_return(data, error, NULL);
+ data->next_fn = proxy_return;
+
+ start = 0;
+ limit = 4096;
+ num = 4096;
+ size = num*sizeof(gid_t);
+ data->groups = talloc_size(data, size);
+ if (!data->groups)
+ return proxy_return(data, ENOMEM, NULL);
+
+ gid = data->pwd->pw_gid;
+ name = talloc_strdup(data, data->pwd->pw_name);
+ if (!name)
+ return proxy_return(data, ENOMEM, NULL);
+
+retry:
+ status = data->ctx->ops.initgroups_dyn(name, gid,
+ &start, &num,
+ &data->groups, limit, &ret);
+ switch (status) {
+ case NSS_STATUS_TRYAGAIN:
+ /* buffer too small ? */
+ if (size < MAX_BUF_SIZE) {
+ num *= 2;
+ size = num*sizeof(gid_t);
+ }
+ if (size > MAX_BUF_SIZE) {
+ size = MAX_BUF_SIZE;
+ num = size/sizeof(gid_t);
+ }
+ limit = num;
+ data->groups = talloc_realloc_size(data, data->groups, size);
+ if (!data->groups) {
+ return proxy_return(data, ENOMEM, NULL);
+ }
+ goto retry;
+
+ case NSS_STATUS_SUCCESS:
+ data->num = start;
+ DEBUG(4, ("User [%s] appears to be member of %lu groups\n",
+ name, data->num));
+ get_gid_entry(data->sysreq, data);
+ break;
+
+ default:
+ DEBUG(2, ("proxy -> getgrent_r failed (%d)[%s]\n",
+ ret, strerror(ret)));
+ proxy_return(data, ret, NULL);
+ }
+}
+
+static void get_initgr_user(struct be_req *req, char *name)
+{
+ struct proxy_ctx *ctx;
+ enum nss_status status;
+ struct proxy_data *data;
int ret;
ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
- buffer = talloc_size(req, 4096);
- if (!buffer)
+ data = talloc_zero(req, struct proxy_data);
+ if (!data)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->req = req;
+ data->ctx = ctx;
+ data->next_fn = proxy_return;
+ data->pwd = talloc(data, struct passwd);
+ if (!data->pwd)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+ data->grp = talloc(data, struct group);
+ if (!data->grp)
return proxy_reply(req, ENOMEM, "Out of memory");
- status = ctx->ops.getpwnam_r(name, &result, buffer, 4096, &ret);
+ data->buflen = 4096;
+ data->buffer = talloc_size(data, data->buflen);
+ if (!data->buffer)
+ return proxy_reply(req, ENOMEM, "Out of memory");
+
+ status = ctx->ops.getpwnam_r(name, data->pwd,
+ data->buffer, data->buflen, &ret);
switch (status) {
case NSS_STATUS_NOTFOUND:
- ret = sysdb_delete_user(req, req->be_ctx->sysdb,
- req->be_ctx->domain, name);
- break;
- case NSS_STATUS_SUCCESS:
- ret = sysdb_legacy_store_user(req, req->be_ctx->sysdb,
- req->be_ctx->domain,
- result.pw_name, result.pw_passwd,
- result.pw_uid, result.pw_gid,
- result.pw_gecos, result.pw_dir,
- result.pw_shell);
- if (ret != EOK) break;
-
- /* FIXME: let's start with 4k entries */
- start = 0;
- limit = 4096;
- num = 4096;
-
- size = num*sizeof(gid_t);
- groups = talloc_size(req, size);
- if (!groups) {
- talloc_free(buffer);
+ data->dn = sysdb_user_dn(req->be_ctx->sysdb, data,
+ req->be_ctx->domain, name);
+ if (!data->dn)
return proxy_reply(req, ENOMEM, "Out of memory");
- }
- status = ctx->ops.initgroups_dyn(result.pw_name, result.pw_gid,
- &start, &num, &groups, limit, &ret);
- switch (status) {
- case NSS_STATUS_SUCCESS:
-
- if (ret == EOK) {
- DEBUG(4, ("User [%s] appears to be member of %lu groups\n",
- result.pw_name, start));
- /* start is moved up by the number of groups retrieved,
- * therefore represents the number of users to pass on */
- ret = save_initgroups(req, groups, start);
- }
-
- break;
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, del_db_entry, data);
+ break;
- default:
- DEBUG(2, ("proxy -> initgroups_dyn failed for '%s' (%d)[%s]\n",
- name, ret, strerror(ret)));
- talloc_free(buffer);
- return proxy_reply(req, ret, "Operation failed");
- }
+ case NSS_STATUS_SUCCESS:
+ data->next_fn = get_user_groups;
+ ret = sysdb_transaction(data, req->be_ctx->sysdb, set_pw_name, data);
break;
default:
DEBUG(2, ("proxy -> getpwnam_r failed for '%s' (%d)[%s]\n",
name, ret, strerror(ret)));
- talloc_free(buffer);
return proxy_reply(req, ret, "Operation failed");
}
if (ret != EOK) {
- DEBUG(1, ("Failed to update LDB Cache for '%s' (%d) !?\n",
- name, ret));
- talloc_free(buffer);
+ DEBUG(1, ("Failed to start transaction (%d)[%s]!?\n",
+ ret, strerror(ret)));
return proxy_reply(req, ret, "Operation failed");
}
-
- talloc_free(buffer);
- return proxy_reply(req, EOK, NULL);
}
/* TODO: actually do check something */
@@ -785,7 +1045,7 @@ static void proxy_get_account_info(struct be_req *req)
if (strchr(ar->filter_value, '*')) {
return proxy_reply(req, EINVAL, "Invalid filter value");
}
- return get_user_groups(req, ar->filter_value);
+ return get_initgr_user(req, ar->filter_value);
default: /*fail*/
return proxy_reply(req, EINVAL, "Invalid request type");
diff --git a/server/server.mk b/server/server.mk
index e029d4a5..77f805ca 100644
--- a/server/server.mk
+++ b/server/server.mk
@@ -15,7 +15,7 @@ UTIL_OBJ = \
db/sysdb.o \
db/sysdb_req.o \
db/sysdb_search.o \
- db/sysdb_sync.o
+ db/sysdb_ops.o
RESPONDER_UTIL_OBJ = \
responder/common/responder_dp.o \