diff options
author | Simo Sorce <ssorce@redhat.com> | 2009-02-27 17:04:11 -0500 |
---|---|---|
committer | Simo Sorce <ssorce@redhat.com> | 2009-02-28 18:55:49 -0500 |
commit | f0cefca80767664b876d10126f7f79fc36dc1993 (patch) | |
tree | 1cc4792533b512da6f16cdce77f171de6aa804ae /server/db | |
parent | 60398e684b6d4f8880fcda357c8077ccca481041 (diff) | |
download | sssd-f0cefca80767664b876d10126f7f79fc36dc1993.tar.gz sssd-f0cefca80767664b876d10126f7f79fc36dc1993.tar.bz2 sssd-f0cefca80767664b876d10126f7f79fc36dc1993.zip |
Convert sync calls in sysdb to async, transaction dependent, calls.
Diffstat (limited to 'server/db')
-rw-r--r-- | server/db/sysdb.c | 13 | ||||
-rw-r--r-- | server/db/sysdb.h | 109 | ||||
-rw-r--r-- | server/db/sysdb_ops.c | 938 | ||||
-rw-r--r-- | server/db/sysdb_private.h | 12 | ||||
-rw-r--r-- | server/db/sysdb_req.c | 11 | ||||
-rw-r--r-- | server/db/sysdb_search.c | 40 | ||||
-rw-r--r-- | server/db/sysdb_sync.c | 880 |
7 files changed, 1041 insertions, 962 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; -} - |