diff options
Diffstat (limited to 'server/db')
-rw-r--r-- | server/db/sysdb.c | 1883 | ||||
-rw-r--r-- | server/db/sysdb.h | 650 | ||||
-rw-r--r-- | server/db/sysdb_ops.c | 5059 | ||||
-rw-r--r-- | server/db/sysdb_private.h | 107 | ||||
-rw-r--r-- | server/db/sysdb_search.c | 691 |
5 files changed, 0 insertions, 8390 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c deleted file mode 100644 index b3f81a08..00000000 --- a/server/db/sysdb.c +++ /dev/null @@ -1,1883 +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 "confdb/confdb.h" -#include <time.h> - - -struct ldb_dn *sysdb_custom_subtree_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain, - const char *subtree_name) -{ - return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_CUSTOM_SUBTREE, - subtree_name, domain); -} -struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain, const char *object_name, - const char *subtree_name) -{ - return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_CUSTOM, object_name, - subtree_name, domain); -} - -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); -} - -struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain) -{ - return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_DOM_BASE, domain); -} - -struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx) -{ - return ctx->ldb; -} - -struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle) -{ - return handle->ctx->ldb; -} - -struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *handle) -{ - return handle->ctx; -} - -struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *memctx) -{ - return talloc_zero(memctx, struct sysdb_attrs); -} - -static int sysdb_attrs_get_el_int(struct sysdb_attrs *attrs, const char *name, - bool alloc, struct ldb_message_element **el) -{ - struct ldb_message_element *e = NULL; - int i; - - for (i = 0; i < attrs->num; i++) { - if (strcasecmp(name, attrs->a[i].name) == 0) - e = &(attrs->a[i]); - } - - if (!e && alloc) { - e = talloc_realloc(attrs, attrs->a, - struct ldb_message_element, attrs->num+1); - if (!e) return ENOMEM; - attrs->a = e; - - e[attrs->num].name = talloc_strdup(e, name); - if (!e[attrs->num].name) return ENOMEM; - - e[attrs->num].num_values = 0; - e[attrs->num].values = NULL; - e[attrs->num].flags = 0; - - e = &(attrs->a[attrs->num]); - attrs->num++; - } - - if (!e) { - return ENOENT; - } - - *el = e; - - return EOK; -} - -int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name, - struct ldb_message_element **el) -{ - return sysdb_attrs_get_el_int(attrs, name, true, el); -} - -int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name, - const char **string) -{ - struct ldb_message_element *el; - int ret; - - ret = sysdb_attrs_get_el_int(attrs, name, false, &el); - if (ret) { - return ret; - } - - if (el->num_values != 1) { - return ERANGE; - } - - *string = (const char *)el->values[0].data; - return EOK; -} - -int sysdb_attrs_add_val(struct sysdb_attrs *attrs, - const char *name, const struct ldb_val *val) -{ - struct ldb_message_element *el = NULL; - struct ldb_val *vals; - int ret; - - ret = sysdb_attrs_get_el(attrs, name, &el); - - vals = talloc_realloc(attrs->a, el->values, - struct ldb_val, el->num_values+1); - if (!vals) return ENOMEM; - - vals[el->num_values] = ldb_val_dup(vals, val); - if (vals[el->num_values].data == NULL && - vals[el->num_values].length != 0) { - return ENOMEM; - } - - el->values = vals; - el->num_values++; - - return EOK; -} - -int sysdb_attrs_add_string(struct sysdb_attrs *attrs, - const char *name, const char *str) -{ - struct ldb_val v; - - v.data = (uint8_t *)discard_const(str); - v.length = strlen(str); - - return sysdb_attrs_add_val(attrs, name, &v); -} - -int sysdb_attrs_steal_string(struct sysdb_attrs *attrs, - const char *name, char *str) -{ - struct ldb_message_element *el = NULL; - struct ldb_val *vals; - int ret; - - ret = sysdb_attrs_get_el(attrs, name, &el); - - vals = talloc_realloc(attrs->a, el->values, - struct ldb_val, el->num_values+1); - if (!vals) return ENOMEM; - el->values = vals; - - /* now steal and assign the string */ - talloc_steal(el->values, str); - - el->values[el->num_values].data = (uint8_t *)str; - el->values[el->num_values].length = strlen(str); - el->num_values++; - - return EOK; -} - -int sysdb_attrs_add_long(struct sysdb_attrs *attrs, - const char *name, long value) -{ - struct ldb_val v; - char *str; - int ret; - - str = talloc_asprintf(attrs, "%ld", value); - if (!str) return ENOMEM; - - v.data = (uint8_t *)str; - v.length = strlen(str); - - ret = sysdb_attrs_add_val(attrs, name, &v); - talloc_free(str); - - return ret; -} - -int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs, - const char *name, uint32_t value) -{ - unsigned long val = value; - struct ldb_val v; - char *str; - int ret; - - str = talloc_asprintf(attrs, "%lu", val); - if (!str) return ENOMEM; - - v.data = (uint8_t *)str; - v.length = strlen(str); - - ret = sysdb_attrs_add_val(attrs, name, &v); - talloc_free(str); - - return ret; -} - -int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, - const char *name, time_t value) -{ - long long val = value; - struct ldb_val v; - char *str; - int ret; - - str = talloc_asprintf(attrs, "%lld", val); - if (!str) return ENOMEM; - - v.data = (uint8_t *)str; - v.length = strlen(str); - - ret = sysdb_attrs_add_val(attrs, name, &v); - talloc_free(str); - - return ret; -} - -int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs, - const char *attr_name, - const char *domain, - const char **list) -{ - struct ldb_message_element *el = NULL; - struct ldb_val *vals; - int i, j, num; - char *member; - int ret; - - ret = sysdb_attrs_get_el(attrs, attr_name, &el); - if (ret) { - return ret; - } - - for (num = 0; list[num]; num++) /* count */ ; - - vals = talloc_realloc(attrs->a, el->values, - struct ldb_val, el->num_values + num); - if (!vals) { - return ENOMEM; - } - el->values = vals; - - DEBUG(9, ("Adding %d members to existing %d ones\n", - num, el->num_values)); - - for (i = 0, j = el->num_values; i < num; i++) { - - member = sysdb_user_strdn(el->values, domain, list[i]); - if (!member) { - DEBUG(4, ("Failed to get user dn for [%s]\n", list[i])); - continue; - } - el->values[j].data = (uint8_t *)member; - el->values[j].length = strlen(member); - j++; - - DEBUG(7, (" member #%d: [%s]\n", i, member)); - } - el->num_values = j; - - return EOK; -} - -int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs, - const char *attr_name, - const char *domain, - struct ldb_val *values, - int num_values) -{ - struct ldb_message_element *el = NULL; - struct ldb_val *vals; - int i, j; - char *member; - int ret; - - ret = sysdb_attrs_get_el(attrs, attr_name, &el); - if (ret) { - return ret; - } - - vals = talloc_realloc(attrs->a, el->values, struct ldb_val, - el->num_values + num_values); - if (!vals) { - return ENOMEM; - } - el->values = vals; - - DEBUG(9, ("Adding %d members to existing %d ones\n", - num_values, el->num_values)); - - for (i = 0, j = el->num_values; i < num_values; i++) { - member = sysdb_user_strdn(el->values, domain, - (char *)values[i].data); - if (!member) { - DEBUG(4, ("Failed to get user dn for [%s]\n", - (char *)values[i].data)); - return ENOMEM; - } - el->values[j].data = (uint8_t *)member; - el->values[j].length = strlen(member); - j++; - - DEBUG(7, (" member #%d: [%s]\n", i, member)); - } - el->num_values = j; - - return EOK; -} - -static char *build_dom_dn_str_escape(TALLOC_CTX *memctx, const char *template, - const char *domain, const char *name) -{ - char *ret; - int l; - - l = strcspn(name, ",=\n+<>#;\\\""); - if (name[l] != '\0') { - struct ldb_val v; - char *tmp; - - v.data = discard_const_p(uint8_t, name); - v.length = strlen(name); - - tmp = ldb_dn_escape_value(memctx, v); - if (!tmp) { - return NULL; - } - - ret = talloc_asprintf(memctx, template, tmp, domain); - talloc_zfree(tmp); - if (!ret) { - return NULL; - } - - return ret; - } - - ret = talloc_asprintf(memctx, template, name, domain); - if (!ret) { - return NULL; - } - - return ret; -} - -char *sysdb_user_strdn(TALLOC_CTX *memctx, - const char *domain, const char *name) -{ - return build_dom_dn_str_escape(memctx, SYSDB_TMPL_USER, domain, name); -} - -char *sysdb_group_strdn(TALLOC_CTX *memctx, - const char *domain, const char *name) -{ - return build_dom_dn_str_escape(memctx, SYSDB_TMPL_GROUP, domain, name); -} - -/* TODO: make a more complete and precise mapping */ -int sysdb_error_to_errno(int ldberr) -{ - switch (ldberr) { - case LDB_SUCCESS: - return EOK; - case LDB_ERR_OPERATIONS_ERROR: - return EIO; - case LDB_ERR_NO_SUCH_OBJECT: - return ENOENT; - case LDB_ERR_BUSY: - return EBUSY; - case LDB_ERR_ENTRY_ALREADY_EXISTS: - return EEXIST; - default: - return EFAULT; - } -} - -/* =Internal-Operations-Queue============================================= */ - -static void sysdb_run_operation(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct sysdb_handle *handle = talloc_get_type(pvt, struct sysdb_handle); - - tevent_req_done(handle->subreq); -} - -static void sysdb_schedule_operation(struct sysdb_handle *handle) -{ - struct timeval tv = { 0, 0 }; - struct tevent_timer *te; - - te = tevent_add_timer(handle->ctx->ev, handle, tv, - sysdb_run_operation, handle); - if (!te) { - DEBUG(1, ("Failed to add critical timer to run next handle!\n")); - } -} - -static int sysdb_handle_destructor(void *mem) -{ - struct sysdb_handle *handle = talloc_get_type(mem, struct sysdb_handle); - bool start_next = false; - int ret; - - /* if this was the current op start next */ - if (handle->ctx->queue == handle) { - start_next = true; - } - - DLIST_REMOVE(handle->ctx->queue, handle); - - if (start_next && handle->ctx->queue) { - /* run next */ - sysdb_schedule_operation(handle->ctx->queue); - } - - if (handle->transaction_active) { - ret = ldb_transaction_cancel(handle->ctx->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); - } - /* FIXME: abort() ? */ - handle->transaction_active = false; - } - - return 0; -} - -struct sysdb_get_handle_state { - struct tevent_context *ev; - struct sysdb_ctx *ctx; - - struct sysdb_handle *handle; -}; - -struct tevent_req *sysdb_get_handle_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *ctx) -{ - struct tevent_req *req; - struct sysdb_get_handle_state *state; - struct sysdb_handle *handle; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_get_handle_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - handle = talloc_zero(state, struct sysdb_handle); - if (!handle) { - talloc_zfree(req); - return NULL; - } - - handle->ctx = ctx; - handle->subreq = req; - - talloc_set_destructor((TALLOC_CTX *)handle, sysdb_handle_destructor); - - DLIST_ADD_END(ctx->queue, handle, struct sysdb_handle *); - - if (ctx->queue == handle) { - /* this is the first in the queue, schedule an immediate run */ - sysdb_schedule_operation(handle); - } - - state->handle = handle; - - return req; -} - -static int sysdb_get_handle_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sysdb_handle **handle) -{ - struct sysdb_get_handle_state *state = tevent_req_data(req, - struct sysdb_get_handle_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *handle = talloc_steal(memctx, state->handle); - if (!*handle) return ENOMEM; - - return EOK; -} - -/* =Transactions========================================================== */ - -struct sysdb_transaction_state { - struct tevent_context *ev; - struct sysdb_ctx *ctx; - - struct sysdb_handle *handle; -}; - -static void sysdb_transaction_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_transaction_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *ctx) -{ - struct tevent_req *req, *subreq; - struct sysdb_transaction_state *state; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_transaction_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - subreq = sysdb_get_handle_send(state, ev, ctx); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, sysdb_transaction_done, req); - - return req; -} - -static void sysdb_transaction_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_transaction_state *state = tevent_req_data(req, - struct sysdb_transaction_state); - int ret; - - ret = sysdb_get_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - ret = ldb_transaction_start(state->ctx->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); - tevent_req_error(req, sysdb_error_to_errno(ret)); - return; - } - state->handle->transaction_active = true; - - tevent_req_done(req); -} - -int sysdb_transaction_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sysdb_handle **handle) -{ - struct sysdb_transaction_state *state = tevent_req_data(req, - struct sysdb_transaction_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *handle = talloc_steal(memctx, state->handle); - if (!*handle) return ENOMEM; - - return EOK; -} - -struct tevent_req *sysdb_transaction_commit_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle) -{ - struct tevent_req *req; - struct sysdb_transaction_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_transaction_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = handle->ctx; - state->handle = handle; - - ret = ldb_transaction_commit(handle->ctx->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); - tevent_req_error(req, sysdb_error_to_errno(ret)); - } - handle->transaction_active = false; - - /* the following may seem weird but it is actually fine. - * _done() will not actually call the callback as it will not be set - * until we return. But it will mark the request as done. - * _post() will trigger the callback as it schedules after we returned - * and actually set the callback */ - tevent_req_done(req); - tevent_req_post(req, ev); - return req; -} - -int sysdb_transaction_commit_recv(struct tevent_req *req) -{ - struct sysdb_transaction_state *state = tevent_req_data(req, - struct sysdb_transaction_state); - - /* finally free handle - * this will also trigger the next transaction in the queue if any */ - talloc_zfree(state->handle); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -/* default transaction commit receive function. - * This function does not use the request state so it is safe to use - * from any caller */ -void sysdb_transaction_complete(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_transaction_commit_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - - -/* =Operations============================================================ */ - -struct sysdb_operation_state { - struct tevent_context *ev; - struct sysdb_ctx *ctx; - - struct sysdb_handle *handle; -}; - -static void sysdb_operation_process(struct tevent_req *subreq); - -struct tevent_req *sysdb_operation_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *ctx) -{ - struct tevent_req *req, *subreq; - struct sysdb_operation_state *state; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_operation_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - subreq = sysdb_get_handle_send(state, ev, ctx); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, sysdb_operation_process, req); - - return req; -} - -static void sysdb_operation_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_operation_state *state = tevent_req_data(req, - struct sysdb_operation_state); - int ret; - - ret = sysdb_get_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_operation_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sysdb_handle **handle) -{ - struct sysdb_operation_state *state = tevent_req_data(req, - struct sysdb_operation_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *handle = talloc_steal(memctx, state->handle); - if (!*handle) return ENOMEM; - - return EOK; -} - -void sysdb_operation_done(struct sysdb_handle *handle) -{ - talloc_free(handle); -} - -/* =Initialization======================================================== */ - -static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sss_domain_info *domain, - const char *db_path, - bool allow_upgrade, - struct sysdb_ctx **_ctx); - -static int sysdb_get_db_file(TALLOC_CTX *mem_ctx, - const char *provider, const char *name, - const char *base_path, char **_ldb_file) -{ - char *ldb_file; - - /* special case for the local domain */ - if (strcasecmp(provider, "local") == 0) { - ldb_file = talloc_asprintf(mem_ctx, "%s/"LOCAL_SYSDB_FILE, - base_path); - } else { - ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE, - base_path, name); - } - if (!ldb_file) { - return ENOMEM; - } - - *_ldb_file = ldb_file; - return EOK; -} - -/* serach all groups that have a memberUid attribute. - * change it into a member attribute for a user of same domain. - * remove the memberUid attribute - * add the new member attribute - * finally stop indexing memberUid - * upgrade version to 0.2 - */ -static int sysdb_upgrade_01(TALLOC_CTX *mem_ctx, - struct ldb_context *ldb, - const char **ver) -{ - struct ldb_message_element *el; - struct ldb_result *res; - struct ldb_dn *basedn; - struct ldb_dn *mem_dn; - struct ldb_message *msg; - const struct ldb_val *val; - const char *filter = "(&(memberUid=*)(objectclass=group))"; - const char *attrs[] = { "memberUid", NULL }; - const char *mdn; - char *domain; - int ret, i, j; - - basedn = ldb_dn_new(mem_ctx, ldb, "cn=sysdb"); - if (!basedn) { - ret = EIO; - goto done; - } - - ret = ldb_search(ldb, mem_ctx, &res, - basedn, LDB_SCOPE_SUBTREE, - attrs, filter); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - ret = ldb_transaction_start(ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - for (i = 0; i < res->count; i++) { - el = ldb_msg_find_element(res->msgs[i], "memberUid"); - if (!el) { - DEBUG(1, ("memberUid is missing from message [%s], skipping\n", - ldb_dn_get_linearized(res->msgs[i]->dn))); - continue; - } - - /* create modification message */ - msg = ldb_msg_new(mem_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = res->msgs[i]->dn; - - ret = ldb_msg_add_empty(msg, "memberUid", LDB_FLAG_MOD_DELETE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - /* get domain name component value */ - val = ldb_dn_get_component_val(res->msgs[i]->dn, 2); - domain = talloc_strndup(mem_ctx, (const char *)val->data, val->length); - if (!domain) { - ret = ENOMEM; - goto done; - } - - for (j = 0; j < el->num_values; j++) { - mem_dn = ldb_dn_new_fmt(mem_ctx, ldb, SYSDB_TMPL_USER, - (const char *)el->values[j].data, domain); - if (!mem_dn) { - ret = ENOMEM; - goto done; - } - - mdn = talloc_strdup(msg, ldb_dn_get_linearized(mem_dn)); - if (!mdn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, SYSDB_MEMBER, mdn); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - talloc_zfree(mem_dn); - } - - /* ok now we are ready to modify the entry */ - ret = ldb_modify(ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - talloc_zfree(msg); - } - - /* conversion done, upgrade version number */ - msg = ldb_msg_new(mem_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(mem_ctx, ldb, "cn=sysdb"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_2); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - ret = EOK; - -done: - if (ret != EOK) { - ldb_transaction_cancel(ldb); - } else { - ret = ldb_transaction_commit(ldb); - if (ret != LDB_SUCCESS) { - return EIO; - } - - *ver = SYSDB_VERSION_0_2; - } - - return ret; -} - -static int sysdb_check_upgrade_02(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sss_domain_info *domains, - const char *db_path) -{ - TALLOC_CTX *tmp_ctx = NULL; - struct ldb_context *ldb; - char *ldb_file; - struct sysdb_ctx *ctx; - struct sss_domain_info *dom; - struct ldb_message_element *el; - struct ldb_message *msg; - struct ldb_result *res; - struct ldb_dn *verdn; - const char *version = NULL; - bool do_02_upgrade = false; - bool ctx_trans = false; - int ret; - - tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) { - return ENOMEM; - } - - ret = sysdb_get_db_file(mem_ctx, - "local", "UPGRADE", - db_path, &ldb_file); - if (ret != EOK) { - goto exit; - } - - ldb = ldb_init(tmp_ctx, ev); - if (!ldb) { - ret = EIO; - goto exit; - } - - ret = ldb_set_debug(ldb, ldb_debug_messages, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto exit; - } - -#ifdef SYSDB_TEST - ldb_set_modules_dir(ldb, "./.libs"); -#endif - - ret = ldb_connect(ldb, ldb_file, 0, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto exit; - } - - verdn = ldb_dn_new(tmp_ctx, ldb, "cn=sysdb"); - if (!verdn) { - ret = EIO; - goto exit; - } - - ret = ldb_search(ldb, tmp_ctx, &res, - verdn, LDB_SCOPE_BASE, - NULL, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto exit; - } - if (res->count > 1) { - ret = EIO; - goto exit; - } - - if (res->count == 1) { - el = ldb_msg_find_element(res->msgs[0], "version"); - if (el) { - if (el->num_values != 1) { - ret = EINVAL; - goto exit; - } - version = talloc_strndup(tmp_ctx, - (char *)(el->values[0].data), - el->values[0].length); - if (!version) { - ret = ENOMEM; - goto exit; - } - - if (strcmp(version, SYSDB_VERSION) == 0) { - /* all fine, return */ - ret = EOK; - goto exit; - } - - DEBUG(4, ("Upgrading DB from version: %s\n", version)); - - if (strcmp(version, SYSDB_VERSION_0_1) == 0) { - /* convert database */ - ret = sysdb_upgrade_01(tmp_ctx, ldb, &version); - if (ret != EOK) goto exit; - } - - if (strcmp(version, SYSDB_VERSION_0_2) == 0) { - /* need to convert database to split files */ - do_02_upgrade = true; - } - - } - } - - if (!do_02_upgrade) { - /* not a v2 upgrade, return and let the normal code take over any - * further upgrade */ - ret = EOK; - goto exit; - } - - /* == V2->V3 UPGRADE == */ - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_3)); - - /* ldb uses posix locks, - * posix is stupid and kills all locks when you close *any* file - * descriptor associated to the same file. - * Therefore we must close and reopen the ldb file here */ - - /* == Backup and reopen ldb == */ - - /* close */ - talloc_zfree(ldb); - - /* backup*/ - ret = backup_file(ldb_file, 0); - if (ret != EOK) { - goto exit; - } - - /* reopen */ - ldb = ldb_init(tmp_ctx, ev); - if (!ldb) { - ret = EIO; - goto exit; - } - - ret = ldb_set_debug(ldb, ldb_debug_messages, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto exit; - } - - ret = ldb_connect(ldb, ldb_file, 0, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto exit; - } - - /* open a transaction */ - ret = ldb_transaction_start(ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); - ret = EIO; - goto exit; - } - - /* == Upgrade contents == */ - - for (dom = domains; dom; dom = dom->next) { - struct ldb_dn *domain_dn; - struct ldb_dn *users_dn; - struct ldb_dn *groups_dn; - int i; - - /* skip local */ - if (strcasecmp(dom->provider, "local") == 0) { - continue; - } - - /* create new dom db */ - ret = sysdb_domain_init_internal(tmp_ctx, ev, dom, - db_path, false, &ctx); - if (ret != EOK) { - goto done; - } - - ret = ldb_transaction_start(ctx->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret)); - ret = EIO; - goto done; - } - ctx_trans = true; - - /* search all entries for this domain in local, - * copy them all in the new database, - * then remove them from local */ - - domain_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb, - SYSDB_DOM_BASE, ctx->domain->name); - if (!domain_dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_search(ldb, tmp_ctx, &res, - domain_dn, LDB_SCOPE_SUBTREE, - NULL, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - users_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb, - SYSDB_TMPL_USER_BASE, ctx->domain->name); - if (!users_dn) { - ret = ENOMEM; - goto done; - } - groups_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb, - SYSDB_TMPL_GROUP_BASE, ctx->domain->name); - if (!groups_dn) { - ret = ENOMEM; - goto done; - } - - for (i = 0; i < res->count; i++) { - - struct ldb_dn *orig_dn; - - msg = res->msgs[i]; - - /* skip pre-created congtainers */ - if ((ldb_dn_compare(msg->dn, domain_dn) == 0) || - (ldb_dn_compare(msg->dn, users_dn) == 0) || - (ldb_dn_compare(msg->dn, groups_dn) == 0)) { - continue; - } - - /* regenerate the DN against the new ldb as it may have different - * casefolding rules (example: name changing from case insensitive - * to case sensitive) */ - orig_dn = msg->dn; - msg->dn = ldb_dn_new(msg, ctx->ldb, - ldb_dn_get_linearized(orig_dn)); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_add(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("WARNING: Could not add entry %s," - " to new ldb file! (%d [%s])\n", - ldb_dn_get_linearized(msg->dn), - ret, ldb_errstring(ctx->ldb))); - } - - ret = ldb_delete(ldb, orig_dn); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(orig_dn), - ret, ldb_errstring(ldb))); - } - } - - /* now remove the basic containers from local */ - /* these were optional so debug at level 9 in case - * of failure just for tracing */ - ret = ldb_delete(ldb, groups_dn); - if (ret != LDB_SUCCESS) { - DEBUG(9, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(groups_dn), - ret, ldb_errstring(ldb))); - } - ret = ldb_delete(ldb, users_dn); - if (ret != LDB_SUCCESS) { - DEBUG(9, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(users_dn), - ret, ldb_errstring(ldb))); - } - ret = ldb_delete(ldb, domain_dn); - if (ret != LDB_SUCCESS) { - DEBUG(9, ("WARNING: Could not remove entry %s," - " from old ldb file! (%d [%s])\n", - ldb_dn_get_linearized(domain_dn), - ret, ldb_errstring(ldb))); - } - - ret = ldb_transaction_commit(ctx->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); - ret = EIO; - goto done; - } - ctx_trans = false; - - talloc_zfree(domain_dn); - talloc_zfree(groups_dn); - talloc_zfree(users_dn); - talloc_zfree(res); - } - - /* conversion done, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ldb, "cn=sysdb"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_3); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - ret = ldb_transaction_commit(ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret)); - ret = EIO; - goto exit; - } - - ret = EOK; - -done: - if (ret != EOK) { - if (ctx_trans) { - ret = ldb_transaction_cancel(ctx->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); - } - } - ret = ldb_transaction_cancel(ldb); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret)); - } - } - -exit: - talloc_free(tmp_ctx); - return ret; -} - -static int sysdb_upgrade_03(struct sysdb_ctx *ctx, const char **ver) -{ - TALLOC_CTX *tmp_ctx; - int ret; - struct ldb_message *msg; - - tmp_ctx = talloc_new(ctx); - if (!tmp_ctx) { - return ENOMEM; - } - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_4)); - - ret = ldb_transaction_start(ctx->ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - /* Make this database case-sensitive */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "@ATTRIBUTES"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_DELETE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - /* conversion done, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_4); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - ret = EOK; - -done: - talloc_zfree(tmp_ctx); - - if (ret != EOK) { - ret = ldb_transaction_cancel(ctx->ldb); - } else { - ret = ldb_transaction_commit(ctx->ldb); - *ver = SYSDB_VERSION_0_4; - } - if (ret != LDB_SUCCESS) { - ret = EIO; - } - - return ret; -} - -static int sysdb_upgrade_04(struct sysdb_ctx *ctx, const char **ver) -{ - TALLOC_CTX *tmp_ctx; - int ret; - struct ldb_message *msg; - - tmp_ctx = talloc_new(ctx); - if (!tmp_ctx) { - return ENOMEM; - } - - DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_5)); - - ret = ldb_transaction_start(ctx->ldb); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - /* Add new index */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "@INDEXLIST"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "@IDXATTR", "originalDN"); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - /* Rebuild memberuid and memberoif attributes */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "@MEMBEROF-REBUILD"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_add(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - /* conversion done, upgrade version number */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb"); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_5); - if (ret != LDB_SUCCESS) { - ret = ENOMEM; - goto done; - } - - ret = ldb_modify(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto done; - } - - ret = EOK; - -done: - talloc_zfree(tmp_ctx); - - if (ret != EOK) { - ret = ldb_transaction_cancel(ctx->ldb); - } else { - ret = ldb_transaction_commit(ctx->ldb); - *ver = SYSDB_VERSION_0_5; - } - if (ret != LDB_SUCCESS) { - ret = EIO; - } - - return ret; -} - -static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sss_domain_info *domain, - const char *db_path, - bool allow_upgrade, - struct sysdb_ctx **_ctx) -{ - TALLOC_CTX *tmp_ctx = NULL; - struct sysdb_ctx *ctx; - const char *base_ldif; - struct ldb_ldif *ldif; - struct ldb_message *msg; - struct ldb_message_element *el; - struct ldb_result *res; - struct ldb_dn *verdn; - const char *version = NULL; - int ret; - - ctx = talloc_zero(mem_ctx, struct sysdb_ctx); - if (!ctx) { - return ENOMEM; - } - ctx->ev = ev; - ctx->domain = domain; - - /* The local provider s the only true MPG, - * for the other domains, the provider actually unrolls MPGs */ - if (strcasecmp(domain->provider, "local") == 0) { - ctx->mpg = true; - } - - ret = sysdb_get_db_file(ctx, domain->provider, - domain->name, db_path, - &ctx->ldb_file); - if (ret != EOK) { - return ret; - } - DEBUG(5, ("DB File for %s: %s\n", domain->name, ctx->ldb_file)); - - ctx->ldb = ldb_init(ctx, ev); - if (!ctx->ldb) { - return EIO; - } - - ret = ldb_set_debug(ctx->ldb, ldb_debug_messages, NULL); - if (ret != LDB_SUCCESS) { - return EIO; - } - -#ifdef SYSDB_TEST - ldb_set_modules_dir(ctx->ldb, "./.libs"); -#endif - - ret = ldb_connect(ctx->ldb, ctx->ldb_file, 0, NULL); - if (ret != LDB_SUCCESS) { - return EIO; - } - - tmp_ctx = talloc_new(ctx); - if (!tmp_ctx) { - return ENOMEM; - } - - verdn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb"); - if (!verdn) { - ret = EIO; - goto done; - } - - ret = ldb_search(ctx->ldb, tmp_ctx, &res, - verdn, LDB_SCOPE_BASE, - NULL, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - if (res->count > 1) { - ret = EIO; - goto done; - } - - if (res->count == 1) { - el = ldb_msg_find_element(res->msgs[0], "version"); - if (el) { - if (el->num_values != 1) { - ret = EINVAL; - goto done; - } - version = talloc_strndup(tmp_ctx, - (char *)(el->values[0].data), - el->values[0].length); - if (!version) { - ret = ENOMEM; - goto done; - } - - if (strcmp(version, SYSDB_VERSION) == 0) { - /* all fine, return */ - ret = EOK; - goto done; - } - - if (!allow_upgrade) { - DEBUG(0, ("Wrong DB version (got %s expected %s)\n", - version, SYSDB_VERSION)); - ret = EINVAL; - goto done; - } - - DEBUG(4, ("Upgrading DB [%s] from version: %s\n", - domain->name, version)); - - if (strcmp(version, SYSDB_VERSION_0_3) == 0) { - ret = sysdb_upgrade_03(ctx, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_4) == 0) { - ret = sysdb_upgrade_04(ctx, &version); - goto done; - } - } - - DEBUG(0,("Unknown DB version [%s], expected [%s] for domain %s!\n", - version?version:"not found", SYSDB_VERSION, domain->name)); - ret = EINVAL; - goto done; - } - - /* cn=sysdb does not exists, means db is empty, populate */ - - base_ldif = SYSDB_BASE_LDIF; - while ((ldif = ldb_ldif_read_string(ctx->ldb, &base_ldif))) { - ret = ldb_add(ctx->ldb, ldif->msg); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!", - ret, ldb_errstring(ctx->ldb), domain->name)); - ret = EIO; - goto done; - } - ldb_ldif_read_free(ctx->ldb, ldif); - } - - /* == create base domain object == */ - - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new_fmt(msg, ctx->ldb, SYSDB_DOM_BASE, domain->name); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_fmt(msg, "cn", "%s", domain->name); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - /* do a synchronous add */ - ret = ldb_add(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!", - ret, ldb_errstring(ctx->ldb), domain->name)); - ret = EIO; - goto done; - } - talloc_zfree(msg); - - /* == create Users tree == */ - - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new_fmt(msg, ctx->ldb, - SYSDB_TMPL_USER_BASE, domain->name); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_fmt(msg, "cn", "Users"); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - /* do a synchronous add */ - ret = ldb_add(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!", - ret, ldb_errstring(ctx->ldb), domain->name)); - ret = EIO; - goto done; - } - talloc_zfree(msg); - - /* == create Groups tree == */ - - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new_fmt(msg, ctx->ldb, - SYSDB_TMPL_GROUP_BASE, domain->name); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_fmt(msg, "cn", "Groups"); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - /* do a synchronous add */ - ret = ldb_add(ctx->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!", - ret, ldb_errstring(ctx->ldb), domain->name)); - ret = EIO; - goto done; - } - talloc_zfree(msg); - - ret = EOK; - -done: - if (ret == EOK) { - *_ctx = ctx; - } - talloc_free(tmp_ctx); - return ret; -} - -int sysdb_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct confdb_ctx *cdb, - const char *alt_db_path, - bool allow_upgrade, - struct sysdb_ctx_list **_ctx_list) -{ - struct sysdb_ctx_list *ctx_list; - struct sss_domain_info *domains, *dom; - struct sysdb_ctx *ctx; - int ret; - - if (!ev) return EINVAL; - - ctx_list = talloc_zero(mem_ctx, struct sysdb_ctx_list); - if (!ctx_list) { - return ENOMEM; - } - - if (alt_db_path) { - ctx_list->db_path = talloc_strdup(ctx_list, alt_db_path); - } else { - ctx_list->db_path = talloc_strdup(ctx_list, DB_PATH); - } - if (!ctx_list->db_path) { - talloc_zfree(ctx_list); - return ENOMEM; - } - - /* open a db for each backend */ - ret = confdb_get_domains(cdb, &domains); - if (ret != EOK) { - talloc_zfree(ctx_list); - return ret; - } - - if (allow_upgrade) { - /* check if we have an old sssd.ldb to upgrade */ - ret = sysdb_check_upgrade_02(ctx_list, ev, domains, - ctx_list->db_path); - if (ret != EOK) { - talloc_zfree(ctx_list); - return ret; - } - } - - for (dom = domains; dom; dom = dom->next) { - - ctx_list->dbs = talloc_realloc(ctx_list, ctx_list->dbs, - struct sysdb_ctx *, - ctx_list->num_dbs + 1); - if (!ctx_list->dbs) { - talloc_zfree(ctx_list); - return ENOMEM; - } - - ret = sysdb_domain_init_internal(ctx_list, ev, dom, - ctx_list->db_path, - allow_upgrade, &ctx); - if (ret != EOK) { - talloc_zfree(ctx_list); - return ret; - } - - ctx_list->dbs[ctx_list->num_dbs] = ctx; - ctx_list->num_dbs++; - } - if (ctx_list->num_dbs == 0) { - /* what? .. */ - talloc_zfree(ctx_list); - return ENOENT; - } - - *_ctx_list = ctx_list; - - return EOK; -} - -int sysdb_domain_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sss_domain_info *domain, - const char *db_path, - struct sysdb_ctx **_ctx) -{ - return sysdb_domain_init_internal(mem_ctx, ev, domain, - db_path, false, _ctx); -} - -int sysdb_get_ctx_from_list(struct sysdb_ctx_list *ctx_list, - struct sss_domain_info *domain, - struct sysdb_ctx **ctx) -{ - int i; - - for (i = 0; i < ctx_list->num_dbs; i++) { - if (ctx_list->dbs[i]->domain == domain) { - *ctx = ctx_list->dbs[i]; - return EOK; - } - if (strcasecmp(ctx_list->dbs[i]->domain->name, domain->name) == 0) { - *ctx = ctx_list->dbs[i]; - return EOK; - } - } - /* definitely not found */ - return ENOENT; -} - - -int compare_ldb_dn_comp_num(const void *m1, const void *m2) -{ - struct ldb_message *msg1 = talloc_get_type(*(void **) discard_const(m1), - struct ldb_message); - struct ldb_message *msg2 = talloc_get_type(*(void **) discard_const(m2), - struct ldb_message); - - return ldb_dn_get_comp_num(msg2->dn) - ldb_dn_get_comp_num(msg1->dn); -} - -int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname, - const char *newname) -{ - struct ldb_message_element *e = NULL; - int i; - const char *dummy; - - if (attrs == NULL || oldname == NULL || newname == NULL) return EINVAL; - - for (i = 0; i < attrs->num; i++) { - if (strcasecmp(oldname, attrs->a[i].name) == 0) { - e = &(attrs->a[i]); - } - if (strcasecmp(newname, attrs->a[i].name) == 0) { - DEBUG(3, ("New attribute name [%s] already exists.\n", newname)); - return EEXIST; - } - } - - if (e != NULL) { - dummy = talloc_strdup(attrs, newname); - if (dummy == NULL) { - DEBUG(1, ("talloc_strdup failed.\n")); - return ENOMEM; - } - - talloc_free(discard_const(e->name)); - e->name = dummy; - } - - return EOK; -} diff --git a/server/db/sysdb.h b/server/db/sysdb.h deleted file mode 100644 index cf97ed62..00000000 --- a/server/db/sysdb.h +++ /dev/null @@ -1,650 +0,0 @@ -/* - SSSD - - System Database Header - - 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/>. -*/ - -#ifndef __SYS_DB_H__ -#define __SYS_DB_H__ - -#include "util/util.h" -#include "confdb/confdb.h" -#include <tevent.h> - -#define SYSDB_CONF_SECTION "config/sysdb" -#define CACHE_SYSDB_FILE "cache_%s.ldb" -#define LOCAL_SYSDB_FILE "sssd.ldb" - -#define SYSDB_BASE "cn=sysdb" -#define SYSDB_DOM_BASE "cn=%s,cn=sysdb" -#define SYSDB_USERS_CONTAINER "cn=users" -#define SYSDB_GROUPS_CONTAINER "cn=groups" -#define SYSDB_CUSTOM_CONTAINER "cn=custom" -#define SYSDB_TMPL_USER_BASE SYSDB_USERS_CONTAINER",cn=%s,"SYSDB_BASE -#define SYSDB_TMPL_GROUP_BASE SYSDB_GROUPS_CONTAINER",cn=%s,"SYSDB_BASE -#define SYSDB_TMPL_CUSTOM_BASE SYSDB_CUSTOM_CONTAINER",cn=%s,"SYSDB_BASE - -#define SYSDB_USER_CLASS "user" -#define SYSDB_GROUP_CLASS "group" - -#define SYSDB_NAME "name" - -#define SYSDB_NEXTID "nextID" -#define SYSDB_UIDNUM "uidNumber" -#define SYSDB_GIDNUM "gidNumber" -#define SYSDB_CREATE_TIME "createTimestamp" - -#define SYSDB_PWD "userPassword" -#define SYSDB_FULLNAME "fullName" -#define SYSDB_HOMEDIR "homeDirectory" -#define SYSDB_SHELL "loginShell" -#define SYSDB_MEMBEROF "memberOf" -#define SYSDB_DISABLED "disabled" - -#define SYSDB_MEMBER "member" -#define SYSDB_MEMBERUID "memberUid" - -#define SYSDB_DEFAULTGROUP "defaultGroup" -#define SYSDB_GECOS "gecos" -#define SYSDB_LOCALE "locale" -#define SYSDB_KEYBOARD "keyboard" -#define SYSDB_SESSION "session" -#define SYSDB_LAST_LOGIN "lastLogin" -#define SYSDB_LAST_ONLINE_AUTH "lastOnlineAuth" -#define SYSDB_USERPIC "userPicture" -#define SYSDB_LAST_FAILED_LOGIN "lastFailedLogin" -#define SYSDB_FAILED_LOGIN_ATTEMPTS "failedLoginAttempts" - -#define SYSDB_LAST_UPDATE "lastUpdate" -#define SYSDB_CACHE_EXPIRE "dataExpireTimestamp" -#define SYSDB_INITGR_EXPIRE "initgrExpireTimestamp" - -#define SYSDB_CACHEDPWD "cachedPassword" - -#define SYSDB_UUID "uniqueID" -#define SYSDB_UPN "userPrincipalName" -#define SYSDB_CCACHE_FILE "ccacheFile" - -#define SYSDB_ORIG_DN "originalDN" -#define SYSDB_ORIG_MODSTAMP "originalModifyTimestamp" -#define SYSDB_ORIG_MEMBEROF "originalMemberOf" - -#define SYSDB_USN "entryUSN" -#define SYSDB_HIGH_USN "highestUSN" - -#define SYSDB_NEXTID_FILTER "("SYSDB_NEXTID"=*)" - -#define SYSDB_UC "objectclass="SYSDB_USER_CLASS -#define SYSDB_GC "objectclass="SYSDB_GROUP_CLASS -#define SYSDB_MPGC "|("SYSDB_UC")("SYSDB_GC")" - -#define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")("SYSDB_NAME"=%s))" -#define SYSDB_PWUID_FILTER "(&("SYSDB_UC")("SYSDB_UIDNUM"=%lu))" -#define SYSDB_PWENT_FILTER "("SYSDB_UC")" - -#define SYSDB_GRNAM_FILTER "(&("SYSDB_GC")("SYSDB_NAME"=%s))" -#define SYSDB_GRNA2_FILTER "(&("SYSDB_UC")("SYSDB_MEMBEROF"=%s))" -#define SYSDB_GRGID_FILTER "(&("SYSDB_GC")("SYSDB_GIDNUM"=%lu))" -#define SYSDB_GRENT_FILTER "("SYSDB_GC")" -#define SYSDB_GRNAM_MPG_FILTER "(&("SYSDB_MPGC")("SYSDB_NAME"=%s))" -#define SYSDB_GRGID_MPG_FILTER "(&("SYSDB_MPGC")("SYSDB_GIDNUM"=%lu))" -#define SYSDB_GRENT_MPG_FILTER "("SYSDB_MPGC")" - -#define SYSDB_INITGR_FILTER "(&("SYSDB_GC")("SYSDB_GIDNUM"=*))" - -#define SYSDB_GETCACHED_FILTER "(&"SYSDB_UC")("SYSDB_LAST_LOGIN">=%lu))" - -#define SYSDB_DEFAULT_ATTRS SYSDB_LAST_UPDATE, \ - SYSDB_CACHE_EXPIRE, \ - SYSDB_INITGR_EXPIRE, \ - "objectClass" - -#define SYSDB_PW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \ - SYSDB_GIDNUM, SYSDB_GECOS, \ - SYSDB_HOMEDIR, SYSDB_SHELL, \ - SYSDB_DEFAULT_ATTRS, \ - NULL} -#define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \ - SYSDB_MEMBERUID, \ - SYSDB_DEFAULT_ATTRS, \ - NULL} -#define SYSDB_GRPW_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \ - SYSDB_DEFAULT_ATTRS, \ - NULL} -#define SYSDB_GRENT_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, SYSDB_MEMBEROF, \ - SYSDB_DEFAULT_ATTRS, \ - NULL} - -#define SYSDB_INITGR_ATTR SYSDB_MEMBEROF -#define SYSDB_INITGR_ATTRS {SYSDB_GIDNUM, \ - SYSDB_DEFAULT_ATTRS, \ - NULL} - -#define SYSDB_TMPL_USER SYSDB_NAME"=%s,"SYSDB_TMPL_USER_BASE -#define SYSDB_TMPL_GROUP SYSDB_NAME"=%s,"SYSDB_TMPL_GROUP_BASE -#define SYSDB_TMPL_CUSTOM_SUBTREE "cn=%s,"SYSDB_TMPL_CUSTOM_BASE -#define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE - -#define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD -#define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE -#define SYSDB_MOD_REP LDB_FLAG_MOD_REPLACE - -struct confdb_ctx; -struct sysdb_ctx_list; -struct sysdb_ctx; -struct sysdb_handle; - -struct sysdb_attrs { - int num; - struct ldb_message_element *a; -}; - -/* sysdb_attrs helper functions */ -struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *memctx); - -/* values are copied in the structure, allocated on "attrs" */ -int sysdb_attrs_add_val(struct sysdb_attrs *attrs, - const char *name, const struct ldb_val *val); -int sysdb_attrs_add_string(struct sysdb_attrs *attrs, - const char *name, const char *str); -int sysdb_attrs_add_long(struct sysdb_attrs *attrs, - const char *name, long value); -int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs, - const char *name, uint32_t value); -int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, - const char *name, time_t value); -int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name, - struct ldb_message_element **el); -int sysdb_attrs_steal_string(struct sysdb_attrs *attrs, - const char *name, char *str); -int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name, - const char **string); - -int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname, - const char *newname); - -int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs, - const char *attr_name, - const char *domain, - const char **list); -int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs, - const char *attr_name, - const char *domain, - struct ldb_val *values, - int num_values); - -/* convert an ldb error into an errno error */ -int sysdb_error_to_errno(int ldberr); - -/* DNs related helper functions */ -struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain, const char *name); -struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain, const char *name); -struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain); -struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain, const char *object_name, - const char *subtree_name); -struct ldb_dn *sysdb_custom_subtree_dn(struct sysdb_ctx *ctx, void *memctx, - const char *domain, - const char *subtree_name); - -char *sysdb_user_strdn(TALLOC_CTX *memctx, - const char *domain, const char *name); -char *sysdb_group_strdn(TALLOC_CTX *memctx, - const char *domain, const char *name); - - -struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx); -struct ldb_context *sysdb_handle_get_ldb(struct sysdb_handle *handle); -struct sysdb_ctx *sysdb_handle_get_ctx(struct sysdb_handle *handle); - -int compare_ldb_dn_comp_num(const void *m1, const void *m2); - -/* function to start and finish a transaction - * sysdb_transaction_send() will queue a request for a transaction - * when it is done it will call the tevent_req callback, which must - * retrieve the transaction handle using sysdb_transaction_recv() - * - * A transaction must be completed either by sending a commit: - * sysdb_transaction_commit_send()/sysdb_transaction_commit_recv() - * or by freeing the transaction handle (this will implicitly cause - * a transaction cancelation). - * - * Transactions are serialized, no other transaction or operation can be - * performed while a transaction is active. Multiple transaction request - * are queued internally and served in order. - */ - -struct tevent_req *sysdb_transaction_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *ctx); -int sysdb_transaction_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sysdb_handle **handle); - -struct tevent_req *sysdb_transaction_commit_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle); -int sysdb_transaction_commit_recv(struct tevent_req *req); - - -/* default transaction commit receive function. - * This function does not use the request state so it is safe to use - * from any caller */ -void sysdb_transaction_complete(struct tevent_req *subreq); - - -/* Sysdb initialization. - * call this function *only* once to initialize the database and get - * the sysdb ctx */ -int sysdb_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct confdb_ctx *cdb, - const char *alt_db_path, - bool allow_upgrade, - struct sysdb_ctx_list **_ctx_list); -/* used to initialize only one domain database. - * Do NOT use if sysdb_init has already been called */ -int sysdb_domain_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sss_domain_info *domain, - const char *db_path, - struct sysdb_ctx **_ctx); - -int sysdb_get_ctx_from_list(struct sysdb_ctx_list *ctx_list, - struct sss_domain_info *domain, - struct sysdb_ctx **_ctx); - -/* FIXME: REMOVE */ -typedef void (*sysdb_callback_t)(void *, int, struct ldb_result *); - -/* functions to retrieve information from sysdb - * These functions automatically starts an operation - * therefore they cannot be called within a transaction */ -int sysdb_getpwnam(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - sysdb_callback_t fn, void *ptr); - -int sysdb_getpwuid(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - uid_t uid, - sysdb_callback_t fn, void *ptr); - -int sysdb_enumpwent(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *expression, - sysdb_callback_t fn, void *ptr); - -int sysdb_getgrnam(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - sysdb_callback_t fn, void *ptr); - -int sysdb_getgrgid(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - gid_t gid, - sysdb_callback_t fn, void *ptr); - -int sysdb_enumgrent(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - sysdb_callback_t fn, void *ptr); - -int sysdb_initgroups(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - sysdb_callback_t fn, void *ptr); - -int sysdb_get_user_attr(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - const char **attributes, - sysdb_callback_t fn, void *ptr); - - -/* functions that modify the databse - * they have to be called within a transaction - * See sysdb_transaction_send()/_recv() */ - -/* Delete Entry */ -struct tevent_req *sysdb_delete_entry_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *dn, - bool ignore_not_found); -int sysdb_delete_entry_recv(struct tevent_req *req); - - -struct tevent_req *sysdb_delete_recursive_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *dn, - bool ignore_not_found); -int sysdb_delete_recursive_recv(struct tevent_req *req); - -/* Search Entry */ -struct tevent_req *sysdb_search_entry_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *base_dn, - int scope, - const char *filter, - const char **attrs); -int sysdb_search_entry_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - size_t *msgs_size, - struct ldb_message ***msgs); - -/* Search User (by uid or name) */ -struct tevent_req *sysdb_search_user_by_name_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char **attrs); -struct tevent_req *sysdb_search_user_by_uid_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - uid_t uid, - const char **attrs); -int sysdb_search_user_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - struct ldb_message **msg); - -/* Search Group (gy gid or name) */ -struct tevent_req *sysdb_search_group_by_name_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char **attrs); -struct tevent_req *sysdb_search_group_by_gid_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - gid_t gid, - const char **attrs); -int sysdb_search_group_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - struct ldb_message **msg); - -/* Replace entry attrs */ -struct tevent_req *sysdb_set_entry_attr_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *entry_dn, - struct sysdb_attrs *attrs, - int mod_op); -int sysdb_set_entry_attr_recv(struct tevent_req *req); - -/* Replace user attrs */ -struct tevent_req *sysdb_set_user_attr_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - struct sysdb_attrs *attrs, - int mod_op); -int sysdb_set_user_attr_recv(struct tevent_req *req); - -/* Replace group attrs */ -struct tevent_req *sysdb_set_group_attr_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - struct sysdb_attrs *attrs, - int mod_op); -int sysdb_set_group_attr_recv(struct tevent_req *req); - -/* Allocate a new id */ -struct tevent_req *sysdb_get_new_id_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain); -int sysdb_get_new_id_recv(struct tevent_req *req, uint32_t *id); - -/* Add user (only basic attrs and w/o checks) */ -struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell); -int sysdb_add_basic_user_recv(struct tevent_req *req); - -/* Add user (all checks) */ -struct tevent_req *sysdb_add_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - int cache_timeout); -int sysdb_add_user_recv(struct tevent_req *req); - -/* Add group (only basic attrs and w/o checks) */ -struct tevent_req *sysdb_add_basic_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, gid_t gid); -int sysdb_add_basic_group_recv(struct tevent_req *req); - -/* Add group (all checks) */ -struct tevent_req *sysdb_add_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, gid_t gid, - struct sysdb_attrs *attrs, - int cache_timeout); -int sysdb_add_group_recv(struct tevent_req *req); - -/* mod_op must be either LDB_FLAG_MOD_ADD or LDB_FLAG_MOD_DELETE */ -struct tevent_req *sysdb_mod_group_member_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *member_dn, - struct ldb_dn *group_dn, - int mod_op); -int sysdb_mod_group_member_recv(struct tevent_req *req); - -int sysdb_set_group_gid(struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, gid_t gid, - sysdb_callback_t fn, void *pvt); - -struct tevent_req *sysdb_store_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char *pwd, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - uint64_t cache_timeout); -int sysdb_store_user_recv(struct tevent_req *req); - -struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - gid_t gid, - struct sysdb_attrs *attrs, - uint64_t cache_timeout); -int sysdb_store_group_recv(struct tevent_req *req); - -struct tevent_req *sysdb_add_group_member_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *group, - const char *member); -int sysdb_add_group_member_recv(struct tevent_req *req); - -struct tevent_req *sysdb_remove_group_member_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *group, - const char *member); -int sysdb_remove_group_member_recv(struct tevent_req *req); - -/* Password caching function. - * If you are in a transaction ignore sysdb and pass in the handle. - * If you are not in a transaction pass NULL in handle and provide sysdb, - * in this case a transaction will be automatically started and the - * function will be completely wrapped in it's own sysdb transaction */ -struct tevent_req *sysdb_cache_password_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *username, - const char *password); -int sysdb_cache_password_recv(struct tevent_req *req); - - -errno_t check_failed_login_attempts(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, - struct ldb_message *ldb_msg, - uint32_t *failed_login_attempts, - time_t *delayed_until); -struct tevent_req *sysdb_cache_auth_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - const char *name, - const uint8_t *authtok, - size_t authtok_size, - struct confdb_ctx *cdb); -int sysdb_cache_auth_recv(struct tevent_req *req, time_t *expire_date, - time_t *delayed_until); - -struct tevent_req *sysdb_store_custom_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *object_name, - const char *subtree_name, - struct sysdb_attrs *attrs); -int sysdb_store_custom_recv(struct tevent_req *req); - -struct tevent_req *sysdb_search_custom_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *filter, - const char *subtree_name, - const char **attrs); -struct tevent_req *sysdb_search_custom_by_name_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *object_name, - const char *subtree_name, - const char **attrs); -int sysdb_search_custom_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - size_t *msgs_count, - struct ldb_message ***msg); - -struct tevent_req *sysdb_delete_custom_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *object_name, - const char *subtree_name); -int sysdb_delete_custom_recv(struct tevent_req *req); - -struct tevent_req *sysdb_asq_search_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - struct ldb_dn *base_dn, - const char *expression, - const char *asq_attribute, - const char **attrs); -int sysdb_asq_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - size_t *msgs_count, struct ldb_message ***msgs); - -struct tevent_req *sysdb_search_users_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *sub_filter, - const char **attrs); -int sysdb_search_users_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - size_t *msgs_count, struct ldb_message ***msgs); - -struct tevent_req *sysdb_delete_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, uid_t uid); -int sysdb_delete_user_recv(struct tevent_req *req); - -struct tevent_req *sysdb_search_groups_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *sub_filter, - const char **attrs); -int sysdb_search_groups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - size_t *msgs_count, struct ldb_message ***msgs); - -struct tevent_req *sysdb_delete_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, gid_t gid); -int sysdb_delete_group_recv(struct tevent_req *req); - -#endif /* __SYS_DB_H__ */ diff --git a/server/db/sysdb_ops.c b/server/db/sysdb_ops.c deleted file mode 100644 index 33cfd91f..00000000 --- a/server/db/sysdb_ops.c +++ /dev/null @@ -1,5059 +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 "util/sha512crypt.h" -#include <time.h> - -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); - if (ret == LDB_SUCCESS) return EOK; - } - return ENOMEM; -} - -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); - if (ret == LDB_SUCCESS) return EOK; - } - return ENOMEM; -} - -static uint32_t get_attr_as_uint32(struct ldb_message *msg, const char *attr) -{ - const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr); - long long int l; - - if (!v || !v->data) { - return 0; - } - - errno = 0; - l = strtoll((const char *)v->data, NULL, 0); - if (errno) { - return (uint32_t)-1; - } - - if (l < 0 || l > ((uint32_t)(-1))) { - return (uint32_t)-1; - } - - return l; -} - -#define ERROR_OUT(v, r, l) do { v = r; goto l; } while(0); - -/* =LDB-Request-(tevent_req-style)======================================== */ - -struct sldb_request_state { - struct tevent_context *ev; - struct ldb_context *ldbctx; - struct ldb_request *ldbreq; - struct ldb_reply *ldbreply; -}; - -static void sldb_request_wakeup(struct tevent_req *subreq); -static int sldb_request_callback(struct ldb_request *ldbreq, - struct ldb_reply *ldbreply); - -static struct tevent_req *sldb_request_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct ldb_context *ldbctx, - struct ldb_request *ldbreq) -{ - struct tevent_req *req, *subreq; - struct sldb_request_state *state; - struct timeval tv = { 0, 0 }; - - req = tevent_req_create(mem_ctx, &state, struct sldb_request_state); - if (!req) return NULL; - - state->ev = ev; - state->ldbctx = ldbctx; - state->ldbreq = ldbreq; - state->ldbreply = NULL; - - subreq = tevent_wakeup_send(state, ev, tv); - if (!subreq) { - DEBUG(1, ("Failed to add critical timer to run next ldb operation!\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sldb_request_wakeup, req); - - return req; -} - -static void sldb_request_wakeup(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sldb_request_state *state = tevent_req_data(req, - struct sldb_request_state); - int ret; - - if (!tevent_wakeup_recv(subreq)) return; - talloc_zfree(subreq); - - state->ldbreq->callback = sldb_request_callback; - state->ldbreq->context = req; - - ret = ldb_request(state->ldbctx, state->ldbreq); - if (ret != LDB_SUCCESS) { - int err = sysdb_error_to_errno(ret); - DEBUG(6, ("Error: %d (%s)\n", err, strerror(err))); - tevent_req_error(req, err); - } -} - -static int sldb_request_callback(struct ldb_request *ldbreq, - struct ldb_reply *ldbreply) -{ - struct tevent_req *req = talloc_get_type(ldbreq->context, - struct tevent_req); - struct sldb_request_state *state = tevent_req_data(req, - struct sldb_request_state); - int err; - - if (!ldbreply) { - DEBUG(6, ("Error: Missing ldbreply")); - ERROR_OUT(err, EIO, fail); - } - - state->ldbreply = talloc_steal(state, ldbreply); - - if (ldbreply->error != LDB_SUCCESS) { - DEBUG(6, ("LDB Error: %d (%s)\n", - ldbreply->error, ldb_errstring(state->ldbctx))); - ERROR_OUT(err, sysdb_error_to_errno(ldbreply->error), fail); - } - - if (ldbreply->type == LDB_REPLY_DONE) { - tevent_req_done(req); - return EOK; - } - - tevent_req_notify_callback(req); - return EOK; - -fail: - tevent_req_error(req, err); - return EOK; -} - -static int sldb_request_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - struct ldb_reply **ldbreply) -{ - struct sldb_request_state *state = tevent_req_data(req, - struct sldb_request_state); - enum tevent_req_state tstate; - uint64_t err = 0; - - if (state->ldbreply) { - *ldbreply = talloc_move(mem_ctx, &state->ldbreply); - } - - if (tevent_req_is_error(req, &tstate, &err)) { - switch (tstate) { - case TEVENT_REQ_USER_ERROR: - return err; - case TEVENT_REQ_IN_PROGRESS: - return EOK; - default: - return EIO; - } - } - - return EOK; -} - -/* =Standard-Sysdb-Operations-utility-functions=========================== */ - -struct sysdb_op_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - - bool ignore_not_found; - - struct ldb_reply *ldbreply; - size_t msgs_count; - struct ldb_message **msgs; -}; - -static void sysdb_op_default_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_op_state *state = tevent_req_data(req, - struct sysdb_op_state); - int ret; - - ret = sldb_request_recv(subreq, state, &state->ldbreply); - talloc_zfree(subreq); - if (ret) { - if (state->ignore_not_found && ret == ENOENT) { - goto done; - } - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - if (state->ldbreply->type != LDB_REPLY_DONE) { - DEBUG(6, ("Error: %d (%s)\n", EIO, strerror(EIO))); - tevent_req_error(req, EIO); - return; - } - -done: - tevent_req_done(req); -} - -static int sysdb_op_default_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - - -/* =Remove-Entry-From-Sysdb=============================================== */ - -struct tevent_req *sysdb_delete_entry_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *dn, - bool ignore_not_found) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_request *ldbreq; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = ignore_not_found; - state->ldbreply = NULL; - - ret = ldb_build_del_req(&ldbreq, handle->ctx->ldb, state, dn, - NULL, NULL, NULL, NULL); - - if (ret != LDB_SUCCESS) { - DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_op_default_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -int sysdb_delete_entry_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Remove-Subentries-From-Sysdb=============================================== */ - -struct sysdb_delete_recursive_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - - bool ignore_not_found; - - struct ldb_reply *ldbreply; - size_t msgs_count; - struct ldb_message **msgs; - size_t current_item; -}; - -static void sysdb_delete_search_done(struct tevent_req *subreq); -static void sysdb_delete_recursive_prepare_op(struct tevent_req *req); -static void sysdb_delete_recursive_op_done(struct tevent_req *req); - -struct tevent_req *sysdb_delete_recursive_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *dn, - bool ignore_not_found) -{ - struct tevent_req *req, *subreq; - struct sysdb_delete_recursive_state *state; - int ret; - const char **no_attrs; - - req = tevent_req_create(mem_ctx, &state, - struct sysdb_delete_recursive_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = ignore_not_found; - state->ldbreply = NULL; - state->msgs_count = 0; - state->msgs = NULL; - state->current_item = 0; - - no_attrs = talloc_array(state, const char *, 1); - if (no_attrs == NULL) { - ERROR_OUT(ret, ENOMEM, fail); - } - no_attrs[0] = NULL; - - subreq = sysdb_search_entry_send(state, ev, handle, dn, LDB_SCOPE_SUBTREE, - "(distinguishedName=*)", no_attrs); - - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_delete_search_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_delete_search_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_delete_recursive_state *state = tevent_req_data(req, - struct sysdb_delete_recursive_state); - int ret; - - ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count, - &state->msgs); - talloc_zfree(subreq); - if (ret) { - if (state->ignore_not_found && ret == ENOENT) { - tevent_req_done(req); - return; - } - DEBUG(6, ("Search error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - DEBUG(9, ("Found [%d] items to delete.\n", state->msgs_count)); - - qsort(state->msgs, state->msgs_count, sizeof(struct ldb_message *), - compare_ldb_dn_comp_num); - - state->current_item = 0; - sysdb_delete_recursive_prepare_op(req); -} - -static void sysdb_delete_recursive_prepare_op(struct tevent_req *req) -{ - struct sysdb_delete_recursive_state *state = tevent_req_data(req, - struct sysdb_delete_recursive_state); - struct tevent_req *subreq; - int ret; - struct ldb_request *ldbreq; - - if (state->current_item < state->msgs_count) { - DEBUG(9 ,("Trying to delete [%s].\n", - ldb_dn_canonical_string(state, - state->msgs[state->current_item]->dn))); - ret = ldb_build_del_req(&ldbreq, state->handle->ctx->ldb, state, - state->msgs[state->current_item]->dn, NULL, - NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n", - ldb_strerror(ret), ret, - ldb_errstring(state->handle->ctx->ldb))); - ret = sysdb_error_to_errno(ret); - goto fail; - } - - subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb, - ldbreq); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - - state->current_item++; - tevent_req_set_callback(subreq, sysdb_delete_recursive_op_done, req); - return; - } - - tevent_req_done(req); - return; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); -} - -static void sysdb_delete_recursive_op_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_op_default_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Delete error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - sysdb_delete_recursive_prepare_op(req); -} - -int sysdb_delete_recursive_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Search-Entry========================================================== */ - -static void sysdb_search_entry_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_search_entry_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *base_dn, - int scope, - const char *filter, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_request *ldbreq; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - state->msgs_count = 0; - state->msgs = NULL; - - ret = ldb_build_search_req(&ldbreq, handle->ctx->ldb, state, - base_dn, scope, filter, attrs, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_entry_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_search_entry_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_op_state *state = tevent_req_data(req, - struct sysdb_op_state); - struct ldb_reply *ldbreply; - struct ldb_message **dummy; - int ret; - - ret = sldb_request_recv(subreq, state, &ldbreply); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - switch (ldbreply->type) { - case LDB_REPLY_ENTRY: - dummy = talloc_realloc(state, state->msgs, - struct ldb_message *, - state->msgs_count + 2); - if (dummy == NULL) { - tevent_req_error(req, ENOMEM); - return; - } - state->msgs = dummy; - - state->msgs[state->msgs_count + 1] = NULL; - - state->msgs[state->msgs_count] = talloc_steal(state->msgs, - ldbreply->message); - state->msgs_count++; - - talloc_zfree(ldbreply); - return; - - case LDB_REPLY_DONE: - talloc_zfree(subreq); - talloc_zfree(ldbreply); - if (state->msgs_count == 0) { - DEBUG(6, ("Error: Entry not Found!\n")); - tevent_req_error(req, ENOENT); - return; - } - return tevent_req_done(req); - - default: - /* unexpected stuff */ - talloc_zfree(ldbreply); - DEBUG(6, ("Error: Unknown error!\n")); - tevent_req_error(req, EIO); - return; - } -} - -int sysdb_search_entry_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - size_t *msgs_count, - struct ldb_message ***msgs) -{ - struct sysdb_op_state *state = tevent_req_data(req, - struct sysdb_op_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *msgs_count = state->msgs_count; - *msgs = talloc_move(mem_ctx, &state->msgs); - - return EOK; -} - - -/* =Search-User-by-[UID/NAME]============================================= */ - -struct sysdb_search_user_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - - struct ldb_dn *basedn; - const char **attrs; - const char *filter; - int scope; - - size_t msgs_count; - struct ldb_message **msgs; -}; - -static void sysdb_search_user_cont(struct tevent_req *subreq); -static void sysdb_search_user_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_search_user_by_name_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_user_state *state; - static const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL }; - int ret; - - if (!sysdb && !handle) return NULL; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->msgs_count = 0; - state->msgs = NULL; - - state->attrs = attrs ? attrs : def_attrs; - state->filter = NULL; - state->scope = LDB_SCOPE_BASE; - - if (!sysdb) sysdb = handle->ctx; - - state->basedn = sysdb_user_dn(sysdb, state, domain->name, name); - if (!state->basedn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - if (!handle) { - subreq = sysdb_operation_send(state, state->ev, sysdb); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_user_cont, req); - } - else { - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - state->basedn, state->scope, - state->filter, state->attrs); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_user_done, req); - } - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -struct tevent_req *sysdb_search_user_by_uid_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - uid_t uid, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_user_state *state; - static const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL }; - int ret; - - if (!sysdb && !handle) return NULL; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->msgs_count = 0; - state->msgs = NULL; - state->attrs = attrs ? attrs : def_attrs; - - if (!sysdb) sysdb = handle->ctx; - - state->basedn = ldb_dn_new_fmt(state, sysdb->ldb, - SYSDB_TMPL_USER_BASE, domain->name); - if (!state->basedn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - state->filter = talloc_asprintf(state, SYSDB_PWUID_FILTER, - (unsigned long)uid); - if (!state->filter) { - ERROR_OUT(ret, ENOMEM, fail); - } - - state->scope = LDB_SCOPE_ONELEVEL; - - if (!handle) { - subreq = sysdb_operation_send(state, state->ev, sysdb); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_user_cont, req); - } - else { - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - state->basedn, state->scope, - state->filter, state->attrs); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_user_done, req); - } - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_search_user_cont(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_user_state *state = tevent_req_data(req, - struct sysdb_search_user_state); - int ret; - - ret = sysdb_operation_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - state->basedn, state->scope, - state->filter, state->attrs); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_search_user_done, req); -} - -static void sysdb_search_user_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_user_state *state = tevent_req_data(req, - struct sysdb_search_user_state); - int ret; - - ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count, - &state->msgs); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_search_user_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - struct ldb_message **msg) -{ - struct sysdb_search_user_state *state = tevent_req_data(req, - struct sysdb_search_user_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (state->msgs_count > 1) { - DEBUG(1, ("More than one result found.\n")); - return EFAULT; - } - - *msg = talloc_move(mem_ctx, &state->msgs[0]); - - return EOK; -} - - -/* =Search-Group-by-[GID/NAME]============================================ */ - -struct sysdb_search_group_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - - struct ldb_dn *basedn; - const char **attrs; - const char *filter; - int scope; - - size_t msgs_count; - struct ldb_message **msgs; -}; - -static void sysdb_search_group_cont(struct tevent_req *subreq); -static void sysdb_search_group_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_search_group_by_name_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_group_state *state; - static const char *def_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL }; - int ret; - - if (!sysdb && !handle) return NULL; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_group_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->msgs_count = 0; - state->msgs = NULL; - - state->attrs = attrs ? attrs : def_attrs; - state->filter = NULL; - state->scope = LDB_SCOPE_BASE; - - if (!sysdb) sysdb = handle->ctx; - - state->basedn = sysdb_group_dn(sysdb, state, domain->name, name); - if (!state->basedn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - if (!handle) { - subreq = sysdb_operation_send(state, state->ev, sysdb); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_group_cont, req); - } - else { - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - state->basedn, state->scope, - state->filter, state->attrs); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_group_done, req); - } - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -struct tevent_req *sysdb_search_group_by_gid_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - gid_t gid, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_group_state *state; - static const char *def_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL }; - int ret; - - if (!sysdb && !handle) return NULL; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_group_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->msgs_count = 0; - state->msgs = NULL; - state->attrs = attrs ? attrs : def_attrs; - - if (!sysdb) sysdb = handle->ctx; - - state->basedn = ldb_dn_new_fmt(state, sysdb->ldb, - SYSDB_TMPL_GROUP_BASE, domain->name); - if (!state->basedn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - state->filter = talloc_asprintf(state, SYSDB_GRGID_FILTER, - (unsigned long)gid); - if (!state->filter) { - ERROR_OUT(ret, ENOMEM, fail); - } - - state->scope = LDB_SCOPE_ONELEVEL; - - if (!handle) { - subreq = sysdb_operation_send(state, state->ev, sysdb); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_group_cont, req); - } - else { - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - state->basedn, state->scope, - state->filter, state->attrs); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_search_group_done, req); - } - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_search_group_cont(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_group_state *state = tevent_req_data(req, - struct sysdb_search_group_state); - int ret; - - ret = sysdb_operation_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - state->basedn, state->scope, - state->filter, state->attrs); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_search_group_done, req); -} - -static void sysdb_search_group_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_group_state *state = tevent_req_data(req, - struct sysdb_search_group_state); - int ret; - - ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count, - &state->msgs); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_search_group_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - struct ldb_message **msg) -{ - struct sysdb_search_group_state *state = tevent_req_data(req, - struct sysdb_search_group_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - if (state->msgs_count > 1) { - DEBUG(1, ("More than one result found.\n")); - return EFAULT; - } - - *msg = talloc_move(mem_ctx, &state->msgs[0]); - - return EOK; -} - - -/* =Replace-Attributes-On-Entry=========================================== */ - -struct tevent_req *sysdb_set_entry_attr_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *entry_dn, - struct sysdb_attrs *attrs, - int mod_op) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_request *ldbreq; - struct ldb_message *msg; - int i, ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - if (!entry_dn) { - ERROR_OUT(ret, EINVAL, fail); - } - - if (attrs->num == 0) { - ERROR_OUT(ret, EINVAL, fail); - } - - msg = ldb_msg_new(state); - if (!msg) { - ERROR_OUT(ret, ENOMEM, fail); - } - - msg->dn = entry_dn; - - msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num); - if (!msg->elements) { - ERROR_OUT(ret, ENOMEM, fail); - } - - for (i = 0; i < attrs->num; i++) { - msg->elements[i] = attrs->a[i]; - msg->elements[i].flags = mod_op; - } - - msg->num_elements = attrs->num; - - ret = ldb_build_mod_req(&ldbreq, handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_op_default_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -int sysdb_set_entry_attr_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Replace-Attributes-On-User============================================ */ - -static void sysdb_set_user_attr_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_set_user_attr_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - struct sysdb_attrs *attrs, - int mod_op) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_dn *dn; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - dn = sysdb_user_dn(handle->ctx, state, domain->name, name); - if (!dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - subreq = sysdb_set_entry_attr_send(state, ev, handle, dn, attrs, mod_op); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_set_user_attr_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_set_user_attr_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_set_entry_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_set_user_attr_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Replace-Attributes-On-Group=========================================== */ - -static void sysdb_set_group_attr_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_set_group_attr_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - struct sysdb_attrs *attrs, - int mod_op) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_dn *dn; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - dn = sysdb_group_dn(handle->ctx, state, domain->name, name); - if (!dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - subreq = sysdb_set_entry_attr_send(state, ev, handle, dn, attrs, mod_op); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_set_group_attr_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_set_group_attr_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_set_entry_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_set_group_attr_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Get-New-ID============================================================ */ - -struct sysdb_get_new_id_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - struct ldb_dn *base_dn; - struct ldb_message *base; - - struct ldb_message **v_msgs; - int v_count; - - uint32_t new_id; -}; - -static void sysdb_get_new_id_base(struct tevent_req *subreq); -static void sysdb_get_new_id_verify(struct tevent_req *subreq); -static void sysdb_get_new_id_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_get_new_id_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain) -{ - struct tevent_req *req, *subreq; - struct sysdb_get_new_id_state *state; - static const char *attrs[] = { SYSDB_NEXTID, NULL }; - struct ldb_request *ldbreq; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_get_new_id_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->base = NULL; - state->v_msgs = NULL; - state->v_count = 0; - state->new_id = 0; - - state->base_dn = sysdb_domain_dn(handle->ctx, state, domain->name); - if (!state->base_dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - ret = ldb_build_search_req(&ldbreq, handle->ctx->ldb, state, - state->base_dn, LDB_SCOPE_BASE, - SYSDB_NEXTID_FILTER, attrs, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_get_new_id_base, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_get_new_id_base(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_get_new_id_state *state = tevent_req_data(req, - struct sysdb_get_new_id_state); - static const char *attrs[] = { SYSDB_UIDNUM, SYSDB_GIDNUM, NULL }; - struct ldb_reply *ldbreply; - struct ldb_request *ldbreq; - char *filter; - int ret; - - ret = sldb_request_recv(subreq, state, &ldbreply); - if (ret) { - talloc_zfree(subreq); - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - switch (ldbreply->type) { - case LDB_REPLY_ENTRY: - if (state->base) { - DEBUG(1, ("More than one reply for a base search ?! " - "DB seems corrupted, aborting.")); - tevent_req_error(req, EFAULT); - return; - } - - state->base = talloc_move(state, &ldbreply->message); - if (!state->base) { - DEBUG(6, ("Error: Out of memory!\n")); - tevent_req_error(req, ENOMEM); - return; - } - - /* just return, wait for a LDB_REPLY_DONE entry */ - talloc_zfree(ldbreply); - return; - - case LDB_REPLY_DONE: - break; - - default: - /* unexpected stuff */ - DEBUG(6, ("Error: Unknown error\n")); - tevent_req_error(req, EIO); - talloc_zfree(ldbreply); - return; - } - - talloc_zfree(subreq); - - if (state->base) { - state->new_id = get_attr_as_uint32(state->base, SYSDB_NEXTID); - if (state->new_id == (uint32_t)(-1)) { - DEBUG(1, ("Invalid Next ID in domain %s\n", state->domain->name)); - tevent_req_error(req, ERANGE); - return; - } - - if (state->new_id < state->domain->id_min) { - state->new_id = state->domain->id_min; - } - - if ((state->domain->id_max != 0) && - (state->new_id > state->domain->id_max)) { - DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n", - state->new_id, state->domain->id_max)); - tevent_req_error(req, ERANGE); - return; - } - - } else { - /* looks like the domain is not initialized yet, use min_id */ - state->new_id = state->domain->id_min; - } - - /* verify the id is actually really free. - * search all entries with id >= new_id and < max_id */ - if (state->domain->id_max) { - filter = talloc_asprintf(state, - "(|(&(%s>=%u)(%s<=%u))(&(%s>=%u)(%s<=%u)))", - SYSDB_UIDNUM, state->new_id, - SYSDB_UIDNUM, state->domain->id_max, - SYSDB_GIDNUM, state->new_id, - SYSDB_GIDNUM, state->domain->id_max); - } - else { - filter = talloc_asprintf(state, - "(|(%s>=%u)(%s>=%u))", - SYSDB_UIDNUM, state->new_id, - SYSDB_GIDNUM, state->new_id); - } - if (!filter) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - - ret = ldb_build_search_req(&ldbreq, state->handle->ctx->ldb, state, - state->base_dn, LDB_SCOPE_SUBTREE, - filter, attrs, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, - ldb_errstring(state->handle->ctx->ldb))); - tevent_req_error(req, sysdb_error_to_errno(ret)); - return; - } - - subreq = sldb_request_send(state, state->ev, - state->handle->ctx->ldb, ldbreq); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_get_new_id_verify, req); - - return; -} - -static void sysdb_get_new_id_verify(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_get_new_id_state *state = tevent_req_data(req, - struct sysdb_get_new_id_state); - struct ldb_reply *ldbreply; - struct ldb_request *ldbreq; - struct ldb_message *msg; - int ret, i; - - ret = sldb_request_recv(subreq, state, &ldbreply); - if (ret) { - talloc_zfree(subreq); - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - switch (ldbreply->type) { - case LDB_REPLY_ENTRY: - state->v_msgs = talloc_realloc(state, state->v_msgs, - struct ldb_message *, - state->v_count + 2); - if (!state->v_msgs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - - state->v_msgs[state->v_count] = talloc_move(state, &ldbreply->message); - if (!state->v_msgs[state->v_count]) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - state->v_count++; - - /* just return, wait for a LDB_REPLY_DONE entry */ - talloc_zfree(ldbreply); - return; - - case LDB_REPLY_DONE: - break; - - default: - /* unexpected stuff */ - DEBUG(6, ("Error: Unknown error\n")); - tevent_req_error(req, EIO); - talloc_zfree(ldbreply); - return; - } - - talloc_zfree(subreq); - - /* if anything was found, find the maximum and increment past it */ - if (state->v_count) { - uint32_t id; - - for (i = 0; i < state->v_count; i++) { - id = get_attr_as_uint32(state->v_msgs[i], SYSDB_UIDNUM); - if (id != (uint32_t)(-1)) { - if (id > state->new_id) state->new_id = id; - } - id = get_attr_as_uint32(state->v_msgs[i], SYSDB_GIDNUM); - if (id != (uint32_t)(-1)) { - if (id > state->new_id) state->new_id = id; - } - } - - state->new_id++; - - /* check again we are not falling out of range */ - if ((state->domain->id_max != 0) && - (state->new_id > state->domain->id_max)) { - DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n", - state->new_id, state->domain->id_max)); - tevent_req_error(req, ERANGE); - return; - } - - talloc_zfree(state->v_msgs); - state->v_count = 0; - } - - /* finally store the new next id */ - msg = ldb_msg_new(state); - if (!msg) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - msg->dn = state->base_dn; - - ret = add_ulong(msg, LDB_FLAG_MOD_REPLACE, - SYSDB_NEXTID, state->new_id + 1); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - ret = ldb_build_mod_req(&ldbreq, state->handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, - ldb_errstring(state->handle->ctx->ldb))); - tevent_req_error(req, ret); - return; - } - - subreq = sldb_request_send(state, state->ev, - state->handle->ctx->ldb, ldbreq); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_get_new_id_done, req); -} - -static void sysdb_get_new_id_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_get_new_id_state *state = tevent_req_data(req, - struct sysdb_get_new_id_state); - struct ldb_reply *ldbreply; - int ret; - - ret = sldb_request_recv(subreq, state, &ldbreply); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - if (ldbreply->type != LDB_REPLY_DONE) { - DEBUG(6, ("Error: %d (%s)\n", EIO, strerror(EIO))); - tevent_req_error(req, EIO); - return; - } - - tevent_req_done(req); -} - -int sysdb_get_new_id_recv(struct tevent_req *req, uint32_t *id) -{ - struct sysdb_get_new_id_state *state = tevent_req_data(req, - struct sysdb_get_new_id_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *id = state->new_id; - - return EOK; -} - - -/* =Add-Basic-User-NO-CHECKS============================================== */ - -struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_request *ldbreq; - struct ldb_message *msg; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - msg = ldb_msg_new(state); - if (!msg) { - ERROR_OUT(ret, ENOMEM, fail); - } - - /* user dn */ - msg->dn = sysdb_user_dn(handle->ctx, msg, domain->name, name); - if (!msg->dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - ret = add_string(msg, LDB_FLAG_MOD_ADD, "objectClass", SYSDB_USER_CLASS); - if (ret) goto fail; - - ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name); - if (ret) goto fail; - - ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_UIDNUM, (unsigned long)uid); - if (ret) goto fail; - - ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid); - if (ret) goto fail; - - /* We set gecos to be the same as fullname on user creation, - * But we will not enforce coherency after that, it's up to - * admins to decide if they want to keep it in sync if they change - * one of the 2 */ - if (gecos && *gecos) { - ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_FULLNAME, gecos); - if (ret) goto fail; - ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_GECOS, gecos); - if (ret) goto fail; - } - - if (homedir && *homedir) { - ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_HOMEDIR, homedir); - if (ret) goto fail; - } - - if (shell && *shell) { - ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_SHELL, shell); - if (ret) goto fail; - } - - /* creation time */ - ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, - (unsigned long)time(NULL)); - if (ret) goto fail; - - - ret = ldb_build_add_req(&ldbreq, handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_op_default_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -int sysdb_add_basic_user_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Add-User-Function===================================================== */ - -struct sysdb_add_user_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *name; - uid_t uid; - gid_t gid; - const char *gecos; - const char *homedir; - const char *shell; - struct sysdb_attrs *attrs; - - int cache_timeout; -}; - -static void sysdb_add_user_group_check(struct tevent_req *subreq); -static void sysdb_add_user_uid_check(struct tevent_req *subreq); -static void sysdb_add_user_basic_done(struct tevent_req *subreq); -static void sysdb_add_user_get_id_done(struct tevent_req *subreq); -static void sysdb_add_user_set_id_done(struct tevent_req *subreq); -static void sysdb_add_user_set_attrs(struct tevent_req *req); -static void sysdb_add_user_set_attrs_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_add_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - int cache_timeout) -{ - struct tevent_req *req, *subreq; - struct sysdb_add_user_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_add_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->uid = uid; - state->gid = gid; - state->gecos = gecos; - state->homedir = homedir; - state->shell = shell; - state->attrs = attrs; - state->cache_timeout = cache_timeout; - - if (handle->ctx->mpg) { - if (gid != 0) { - DEBUG(0, ("Cannot add user with arbitrary GID in MPG domain!\n")); - ERROR_OUT(ret, EINVAL, fail); - } - state->gid = state->uid; - } - - if (domain->id_max != 0 && uid != 0 && - (uid < domain->id_min || uid > domain->id_max)) { - DEBUG(2, ("Supplied uid [%d] is not in the allowed range [%d-%d].\n", - uid, domain->id_min, domain->id_max)); - ERROR_OUT(ret, ERANGE, fail); - } - - if (domain->id_max != 0 && gid != 0 && - (gid < domain->id_min || gid > domain->id_max)) { - DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n", - gid, domain->id_min, domain->id_max)); - ERROR_OUT(ret, ERANGE, fail); - } - - if (handle->ctx->mpg) { - /* In MPG domains you can't have groups with the same name as users, - * search if a group with the same name exists. - * Don't worry about users, if we try to add a user with the same - * name the operation will fail */ - - subreq = sysdb_search_group_by_name_send(state, ev, NULL, handle, - domain, name, NULL); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_user_group_check, req); - return req; - } - - /* check no other user with the same uid exist */ - if (state->uid != 0) { - subreq = sysdb_search_user_by_uid_send(state, ev, NULL, handle, - domain, uid, NULL); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_user_uid_check, req); - return req; - } - - /* try to add the user */ - subreq = sysdb_add_basic_user_send(state, ev, handle, - domain, name, uid, gid, - gecos, homedir, shell); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req); - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_add_user_group_check(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_user_state *state = tevent_req_data(req, - struct sysdb_add_user_state); - struct ldb_message *msg; - int ret; - - /* We can succeed only if we get an ENOENT error, which means no groups - * with the same name exist. - * If any other error is returned fail as well. */ - ret = sysdb_search_group_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret != ENOENT) { - if (ret == EOK) ret = EEXIST; - tevent_req_error(req, ret); - return; - } - - /* check no other user with the same uid exist */ - if (state->uid != 0) { - subreq = sysdb_search_user_by_uid_send(state, state->ev, - NULL, state->handle, - state->domain, state->uid, - NULL); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_user_uid_check, req); - return; - } - - /* try to add the user */ - subreq = sysdb_add_basic_user_send(state, state->ev, state->handle, - state->domain, state->name, - state->uid, state->gid, - state->gecos, - state->homedir, - state->shell); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req); -} - -static void sysdb_add_user_uid_check(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_user_state *state = tevent_req_data(req, - struct sysdb_add_user_state); - struct ldb_message *msg; - int ret; - - /* We can succeed only if we get an ENOENT error, which means no user - * with the same uid exist. - * If any other error is returned fail as well. */ - ret = sysdb_search_user_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret != ENOENT) { - if (ret == EOK) ret = EEXIST; - tevent_req_error(req, ret); - return; - } - - /* try to add the user */ - subreq = sysdb_add_basic_user_send(state, state->ev, state->handle, - state->domain, state->name, - state->uid, state->gid, - state->gecos, - state->homedir, - state->shell); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req); -} - -static void sysdb_add_user_basic_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_user_state *state = tevent_req_data(req, - struct sysdb_add_user_state); - int ret; - - ret = sysdb_add_basic_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - if (state->uid == 0) { - subreq = sysdb_get_new_id_send(state, - state->ev, state->handle, - state->domain); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_user_get_id_done, req); - return; - } - - sysdb_add_user_set_attrs(req); -} - -static void sysdb_add_user_get_id_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_user_state *state = tevent_req_data(req, - struct sysdb_add_user_state); - struct sysdb_attrs *id_attrs; - uint32_t id; - int ret; - - ret = sysdb_get_new_id_recv(subreq, &id); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->uid == 0) { - id_attrs = sysdb_new_attrs(state); - if (!id_attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_UIDNUM, id); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - if (state->handle->ctx->mpg) { - ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - subreq = sysdb_set_user_attr_send(state, state->ev, state->handle, - state->domain, state->name, - id_attrs, SYSDB_MOD_REP); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_user_set_id_done, req); - return; - } - - sysdb_add_user_set_attrs(req); -} - -static void sysdb_add_user_set_id_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_user_state *state = tevent_req_data(req, - struct sysdb_add_user_state); - int ret; - - ret = sysdb_set_user_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->attrs) { - } - - tevent_req_done(req); -} - -static void sysdb_add_user_set_attrs(struct tevent_req *req) -{ - struct sysdb_add_user_state *state = tevent_req_data(req, - struct sysdb_add_user_state); - struct tevent_req *subreq; - time_t now = time(NULL); - int ret; - - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE, - ((state->cache_timeout) ? - (now + state->cache_timeout) : 0)); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_set_user_attr_send(state, state->ev, - state->handle, state->domain, - state->name, state->attrs, - SYSDB_MOD_REP); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_user_set_attrs_done, req); -} - -static void sysdb_add_user_set_attrs_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_set_user_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_add_user_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Add-Basic-Group-NO-CHECKS============================================= */ - -struct tevent_req *sysdb_add_basic_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, gid_t gid) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_request *ldbreq; - struct ldb_message *msg; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - msg = ldb_msg_new(state); - if (!msg) { - ERROR_OUT(ret, ENOMEM, fail); - } - - /* user dn */ - msg->dn = sysdb_group_dn(handle->ctx, msg, domain->name, name); - if (!msg->dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - ret = add_string(msg, LDB_FLAG_MOD_ADD, "objectClass", SYSDB_GROUP_CLASS); - if (ret) goto fail; - - ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name); - if (ret) goto fail; - - ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid); - if (ret) goto fail; - - /* creation time */ - ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME, - (unsigned long)time(NULL)); - if (ret) goto fail; - - - ret = ldb_build_add_req(&ldbreq, handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_op_default_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -int sysdb_add_basic_group_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Add-Group-Function==================================================== */ - -struct sysdb_add_group_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *name; - gid_t gid; - struct sysdb_attrs *attrs; - - int cache_timeout; -}; - -static void sysdb_add_group_user_check(struct tevent_req *subreq); -static void sysdb_add_group_gid_check(struct tevent_req *subreq); -static void sysdb_add_group_basic_done(struct tevent_req *subreq); -static void sysdb_add_group_get_id_done(struct tevent_req *subreq); -static void sysdb_add_group_set_attrs(struct tevent_req *req); -static void sysdb_add_group_set_attrs_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_add_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, gid_t gid, - struct sysdb_attrs *attrs, - int cache_timeout) -{ - struct tevent_req *req, *subreq; - struct sysdb_add_group_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_add_group_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->gid = gid; - state->attrs = attrs; - state->cache_timeout = cache_timeout; - - if (domain->id_max != 0 && gid != 0 && - (gid < domain->id_min || gid > domain->id_max)) { - DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n", - gid, domain->id_min, domain->id_max)); - ERROR_OUT(ret, ERANGE, fail); - } - - if (handle->ctx->mpg) { - /* In MPG domains you can't have groups with the same name as users, - * search if a group with the same name exists. - * Don't worry about users, if we try to add a user with the same - * name the operation will fail */ - - subreq = sysdb_search_user_by_name_send(state, ev, NULL, handle, - domain, name, NULL); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_group_user_check, req); - return req; - } - - /* check no other groups with the same gid exist */ - if (state->gid != 0) { - subreq = sysdb_search_group_by_gid_send(state, ev, NULL, handle, - domain, gid, NULL); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_group_gid_check, req); - return req; - } - - /* try to add the group */ - subreq = sysdb_add_basic_group_send(state, ev, handle, - domain, name, gid); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req); - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_add_group_user_check(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_group_state *state = tevent_req_data(req, - struct sysdb_add_group_state); - struct ldb_message *msg; - int ret; - - /* We can succeed only if we get an ENOENT error, which means no users - * with the same name exist. - * If any other error is returned fail as well. */ - ret = sysdb_search_user_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret != ENOENT) { - if (ret == EOK) ret = EEXIST; - tevent_req_error(req, ret); - return; - } - - /* check no other group with the same gid exist */ - if (state->gid != 0) { - subreq = sysdb_search_group_by_gid_send(state, state->ev, - NULL, state->handle, - state->domain, state->gid, - NULL); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_group_gid_check, req); - return; - } - - /* try to add the group */ - subreq = sysdb_add_basic_group_send(state, state->ev, - state->handle, state->domain, - state->name, state->gid); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req); -} - -static void sysdb_add_group_gid_check(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_group_state *state = tevent_req_data(req, - struct sysdb_add_group_state); - struct ldb_message *msg; - int ret; - - /* We can succeed only if we get an ENOENT error, which means no group - * with the same gid exist. - * If any other error is returned fail as well. */ - ret = sysdb_search_group_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret != ENOENT) { - if (ret == EOK) ret = EEXIST; - tevent_req_error(req, ret); - return; - } - - /* try to add the group */ - subreq = sysdb_add_basic_group_send(state, state->ev, - state->handle, state->domain, - state->name, state->gid); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req); -} - -static void sysdb_add_group_basic_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_group_state *state = tevent_req_data(req, - struct sysdb_add_group_state); - int ret; - - ret = sysdb_add_basic_group_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - if (state->gid == 0) { - subreq = sysdb_get_new_id_send(state, - state->ev, state->handle, - state->domain); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_group_get_id_done, req); - return; - } - - sysdb_add_group_set_attrs(req); -} - -static void sysdb_add_group_get_id_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_add_group_state *state = tevent_req_data(req, - struct sysdb_add_group_state); - uint32_t id; - int ret; - - ret = sysdb_get_new_id_recv(subreq, &id); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->gid == 0) { - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - } - - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, id); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - sysdb_add_group_set_attrs(req); -} - -static void sysdb_add_group_set_attrs(struct tevent_req *req) -{ - struct sysdb_add_group_state *state = tevent_req_data(req, - struct sysdb_add_group_state); - struct tevent_req *subreq; - time_t now = time(NULL); - int ret; - - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE, - ((state->cache_timeout) ? - (now + state->cache_timeout) : 0)); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_set_group_attr_send(state, state->ev, - state->handle, state->domain, - state->name, state->attrs, - SYSDB_MOD_REP); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_add_group_set_attrs_done, req); -} - -static void sysdb_add_group_set_attrs_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_set_group_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_add_group_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Add-Or-Remove-Group-Memeber=========================================== */ - -/* mod_op must be either SYSDB_MOD_ADD or SYSDB_MOD_DEL */ -struct tevent_req *sysdb_mod_group_member_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct ldb_dn *member_dn, - struct ldb_dn *group_dn, - int mod_op) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_request *ldbreq; - struct ldb_message *msg; - const char *dn; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - msg = ldb_msg_new(state); - if (!msg) { - ERROR_OUT(ret, ENOMEM, fail); - } - - msg->dn = group_dn; - ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, mod_op, NULL); - if (ret != LDB_SUCCESS) { - ERROR_OUT(ret, ENOMEM, fail); - } - - dn = ldb_dn_get_linearized(member_dn); - if (!dn) { - ERROR_OUT(ret, EINVAL, fail); - } - - ret = ldb_msg_add_fmt(msg, SYSDB_MEMBER, "%s", dn); - if (ret != LDB_SUCCESS) { - ERROR_OUT(ret, EINVAL, fail); - } - - ret = ldb_build_mod_req(&ldbreq, handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb))); - ERROR_OUT(ret, sysdb_error_to_errno(ret), fail); - } - - subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_op_default_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -int sysdb_mod_group_member_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */ - -/* if one of the basic attributes is empty ("") as opposed to NULL, - * this will just remove it */ - -struct sysdb_store_user_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *name; - uid_t uid; - gid_t gid; - const char *gecos; - const char *homedir; - const char *shell; - struct sysdb_attrs *attrs; - - uint64_t cache_timeout; -}; - -static void sysdb_store_user_check(struct tevent_req *subreq); -static void sysdb_store_user_add_done(struct tevent_req *subreq); -static void sysdb_store_user_attr_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_store_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - const char *pwd, - uid_t uid, gid_t gid, - const char *gecos, - const char *homedir, - const char *shell, - struct sysdb_attrs *attrs, - uint64_t cache_timeout) -{ - struct tevent_req *req, *subreq; - struct sysdb_store_user_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_store_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->uid = uid; - state->gid = gid; - state->gecos = gecos; - state->homedir = homedir; - state->shell = shell; - state->attrs = attrs; - state->cache_timeout = cache_timeout; - - if (pwd && (domain->legacy_passwords || !*pwd)) { - ret = sysdb_attrs_add_string(state->attrs, SYSDB_PWD, pwd); - if (ret) goto fail; - } - - subreq = sysdb_search_user_by_name_send(state, ev, NULL, handle, - domain, name, NULL); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_store_user_check, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_store_user_check(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_store_user_state *state = tevent_req_data(req, - struct sysdb_store_user_state); - struct ldb_message *msg; - time_t now = time(NULL); - int ret; - - ret = sysdb_search_user_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); - return; - } - - if (ret == ENOENT) { - /* users doesn't exist, turn into adding a user */ - subreq = sysdb_add_user_send(state, state->ev, state->handle, - state->domain, state->name, - state->uid, state->gid, - state->gecos, state->homedir, - state->shell, state->attrs, - state->cache_timeout); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_store_user_add_done, req); - return; - } - - /* the user exists, let's just replace attributes when set */ - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - } - - if (state->uid) { - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_UIDNUM, state->uid); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - if (state->gid) { - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->gid); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - if (state->uid && !state->gid && state->handle->ctx->mpg) { - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->uid); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - if (state->gecos) { - ret = sysdb_attrs_add_string(state->attrs, SYSDB_GECOS, state->gecos); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - if (state->homedir) { - ret = sysdb_attrs_add_string(state->attrs, - SYSDB_HOMEDIR, state->homedir); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - if (state->shell) { - ret = sysdb_attrs_add_string(state->attrs, SYSDB_SHELL, state->shell); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE, - ((state->cache_timeout) ? - (now + state->cache_timeout) : 0)); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_set_user_attr_send(state, state->ev, - state->handle, state->domain, - state->name, state->attrs, - SYSDB_MOD_REP); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_store_user_attr_done, req); -} - -static void sysdb_store_user_add_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_add_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static void sysdb_store_user_attr_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_set_user_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_store_user_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - -/* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */ - -/* this function does not check that all user members are actually present */ - -struct sysdb_store_group_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *name; - gid_t gid; - - struct sysdb_attrs *attrs; - - uint64_t cache_timeout; -}; - -static void sysdb_store_group_check(struct tevent_req *subreq); -static void sysdb_store_group_add_done(struct tevent_req *subreq); -static void sysdb_store_group_attr_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, - gid_t gid, - struct sysdb_attrs *attrs, - uint64_t cache_timeout) -{ - struct tevent_req *req, *subreq; - struct sysdb_store_group_state *state; - static const char *src_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, - SYSDB_ORIG_MODSTAMP, NULL }; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_store_group_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->gid = gid; - state->attrs = attrs; - state->cache_timeout = cache_timeout; - - subreq = sysdb_search_group_by_name_send(state, ev, NULL, handle, - domain, name, src_attrs); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_store_group_check, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_store_group_check(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_store_group_state *state = tevent_req_data(req, - struct sysdb_store_group_state); - struct ldb_message *msg; - time_t now = time(NULL); - bool new_group = false; - int ret; - - ret = sysdb_search_group_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret && ret != ENOENT) { - tevent_req_error(req, ret); - return; - } - if (ret == ENOENT) { - new_group = true; - } - - /* FIXME: use the remote modification timestamp to know if the - * group needs any update */ - - if (new_group) { - /* group doesn't exist, turn into adding a group */ - subreq = sysdb_add_group_send(state, state->ev, state->handle, - state->domain, state->name, - state->gid, state->attrs, - state->cache_timeout); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_store_group_add_done, req); - - return; - } - - /* the group exists, let's just replace attributes when set */ - - if (!state->attrs) { - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - } - - if (state->gid) { - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->gid); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE, - ((state->cache_timeout) ? - (now + state->cache_timeout) : 0)); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_set_group_attr_send(state, state->ev, - state->handle, state->domain, - state->name, state->attrs, - SYSDB_MOD_REP); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_store_group_attr_done, req); -} - -static void sysdb_store_group_add_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_add_group_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -static void sysdb_store_group_attr_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_set_group_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_store_group_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Add-User-to-Group(Native/Legacy)====================================== */ - -static void sysdb_add_group_member_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_add_group_member_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *group, - const char *user) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_dn *group_dn, *user_dn; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - group_dn = sysdb_group_dn(handle->ctx, state, domain->name, group); - if (!group_dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - user_dn = sysdb_user_dn(handle->ctx, state, domain->name, user); - if (!user_dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - subreq = sysdb_mod_group_member_send(state, ev, handle, - user_dn, group_dn, - SYSDB_MOD_ADD); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_add_group_member_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_add_group_member_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_mod_group_member_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_add_group_member_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Remove-member-from-Group(Native/Legacy)=============================== */ - -static void sysdb_remove_group_member_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_remove_group_member_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *group, - const char *user) -{ - struct tevent_req *req, *subreq; - struct sysdb_op_state *state; - struct ldb_dn *group_dn, *user_dn; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->ignore_not_found = false; - state->ldbreply = NULL; - - group_dn = sysdb_group_dn(handle->ctx, state, domain->name, group); - if (!group_dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - user_dn = sysdb_user_dn(handle->ctx, state, domain->name, user); - if (!user_dn) { - ERROR_OUT(ret, ENOMEM, fail); - } - - subreq = sysdb_mod_group_member_send(state, ev, handle, - user_dn, group_dn, - SYSDB_MOD_DEL); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_remove_group_member_done, req); - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_remove_group_member_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_mod_group_member_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_remove_group_member_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Password-Caching====================================================== */ - -struct sysdb_cache_pw_state { - struct tevent_context *ev; - struct sss_domain_info *domain; - - const char *username; - struct sysdb_attrs *attrs; - - struct sysdb_handle *handle; - bool commit; -}; - -static void sysdb_cache_password_trans(struct tevent_req *subreq); -static void sysdb_cache_password_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_cache_password_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *username, - const char *password) -{ - struct tevent_req *req, *subreq; - struct sysdb_cache_pw_state *state; - char *hash = NULL; - char *salt; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_cache_pw_state); - if (!req) return NULL; - - state->ev = ev; - state->domain = domain; - state->username = username; - - ret = s3crypt_gen_salt(state, &salt); - if (ret) { - DEBUG(4, ("Failed to generate random salt.\n")); - goto fail; - } - - ret = s3crypt_sha512(state, password, salt, &hash); - if (ret) { - DEBUG(4, ("Failed to create password hash.\n")); - goto fail; - } - - state->attrs = sysdb_new_attrs(state); - if (!state->attrs) { - ERROR_OUT(ret, ENOMEM, fail); - } - - ret = sysdb_attrs_add_string(state->attrs, SYSDB_CACHEDPWD, hash); - if (ret) goto fail; - - /* FIXME: should we use a different attribute for chache passwords ?? */ - ret = sysdb_attrs_add_long(state->attrs, "lastCachedPasswordChange", - (long)time(NULL)); - if (ret) goto fail; - - ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_FAILED_LOGIN_ATTEMPTS, 0U); - if (ret) goto fail; - - state->handle = NULL; - - if (handle) { - state->handle = handle; - state->commit = false; - - subreq = sysdb_set_user_attr_send(state, state->ev, state->handle, - state->domain, state->username, - state->attrs, SYSDB_MOD_REP); - if (!subreq) { - ERROR_OUT(ret, ENOMEM, fail); - } - tevent_req_set_callback(subreq, sysdb_cache_password_done, req); - } else { - state->commit = true; - - subreq = sysdb_transaction_send(state, state->ev, sysdb); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_cache_password_trans, req); - } - - return req; - -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_cache_password_trans(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_cache_pw_state *state = tevent_req_data(req, - struct sysdb_cache_pw_state); - int ret; - - ret = sysdb_transaction_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_set_user_attr_send(state, state->ev, state->handle, - state->domain, state->username, - state->attrs, SYSDB_MOD_REP); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_cache_password_done, req); -} - -static void sysdb_cache_password_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_cache_pw_state *state = tevent_req_data(req, - struct sysdb_cache_pw_state); - int ret; - - ret = sysdb_set_user_attr_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - if (state->commit) { - subreq = sysdb_transaction_commit_send(state, state->ev, - state->handle); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_transaction_complete, req); - return; - } - - tevent_req_done(req); -} - -int sysdb_cache_password_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - -/* = sysdb_check_handle ================== */ -struct sysdb_check_handle_state { - struct tevent_context *ev; - struct sysdb_handle *handle; -}; - -static void sysdb_check_handle_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_check_handle_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle) -{ - struct tevent_req *req; - struct tevent_req *subreq; - struct sysdb_check_handle_state *state; - - if (sysdb == NULL && handle == NULL) { - DEBUG(1, ("Sysdb context not available.\n")); - return NULL; - } - - req = tevent_req_create(mem_ctx, &state, struct sysdb_check_handle_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - - if (handle != NULL) { - state->handle = talloc_memdup(state, handle, sizeof(struct sysdb_handle)); - if (state->handle == NULL) { - DEBUG(1, ("talloc_memdup failed.\n")); - tevent_req_error(req, ENOMEM); - } else { - tevent_req_done(req); - } - tevent_req_post(req, ev); - return req; - } - - state->handle = NULL; - - subreq = sysdb_operation_send(state, state->ev, sysdb); - if (!subreq) { - DEBUG(1, ("sysdb_operation_send failed.\n")); - tevent_req_error(req, ENOMEM); - tevent_req_post(req, ev); - return req; - } - tevent_req_set_callback(subreq, sysdb_check_handle_done, req); - - return req; -} - -static void sysdb_check_handle_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_check_handle_state *state = tevent_req_data(req, - struct sysdb_check_handle_state); - int ret; - - ret = sysdb_operation_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -int sysdb_check_handle_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sysdb_handle **handle) -{ - struct sysdb_check_handle_state *state = tevent_req_data(req, - struct sysdb_check_handle_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *handle = talloc_move(memctx, &state->handle); - - return EOK; - -} - -/* =Custom Search================== */ -struct sysdb_search_custom_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - - struct ldb_dn *basedn; - const char **attrs; - const char *filter; - int scope; - bool expect_not_more_than_one; - - size_t msgs_count; - struct ldb_message **msgs; -}; - -static void sysdb_search_custom_check_handle_done(struct tevent_req *subreq); -static void sysdb_search_custom_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_search_custom_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *filter, - const char *subtree_name, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_custom_state *state; - int ret; - - if (sysdb == NULL && handle == NULL) return NULL; - - if (filter == NULL || subtree_name == NULL) return NULL; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_custom_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->handle = handle; - state->attrs = attrs; - state->filter = filter; - state->scope = LDB_SCOPE_SUBTREE; - state->expect_not_more_than_one = false; - state->msgs_count = 0; - state->msgs = NULL; - - if (sysdb == NULL) { - sysdb = handle->ctx; - } - state->basedn = sysdb_custom_subtree_dn(sysdb, state, domain->name, - subtree_name); - if (state->basedn == NULL) { - DEBUG(1, ("sysdb_custom_subtree_dn failed.\n")); - ret = ENOMEM; - goto fail; - } - if (!ldb_dn_validate(state->basedn)) { - DEBUG(1, ("Failed to create DN.\n")); - ret = EINVAL; - goto fail; - } - - subreq = sysdb_check_handle_send(state, state->ev, sysdb, state->handle); - if (!subreq) { - DEBUG(1, ("sysdb_check_handle_send failed.\n")); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_search_custom_check_handle_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -struct tevent_req *sysdb_search_custom_by_name_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *object_name, - const char *subtree_name, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_custom_state *state; - int ret; - - if (sysdb == NULL && handle == NULL) return NULL; - - if (object_name == NULL || subtree_name == NULL) return NULL; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_custom_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->handle = handle; - state->attrs = attrs; - state->filter = NULL; - state->scope = LDB_SCOPE_BASE; - state->expect_not_more_than_one = true; - state->msgs_count = 0; - state->msgs = NULL; - - if (sysdb == NULL) { - sysdb = handle->ctx; - } - state->basedn = sysdb_custom_dn(sysdb, state, domain->name, object_name, - subtree_name); - if (state->basedn == NULL) { - DEBUG(1, ("sysdb_custom_dn failed.\n")); - ret = ENOMEM; - goto fail; - } - if (!ldb_dn_validate(state->basedn)) { - DEBUG(1, ("Failed to create DN.\n")); - ret = EINVAL; - goto fail; - } - - subreq = sysdb_check_handle_send(state, state->ev, sysdb, state->handle); - if (!subreq) { - DEBUG(1, ("sysdb_check_handle_send failed.\n")); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_search_custom_check_handle_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_search_custom_check_handle_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_custom_state *state = tevent_req_data(req, - struct sysdb_search_custom_state); - int ret; - - ret = sysdb_check_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - state->basedn, state->scope, - state->filter, state->attrs); - if (!subreq) { - DEBUG(1, ("sysdb_search_entry_send failed.\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_search_custom_done, req); - return; -} - -static void sysdb_search_custom_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_custom_state *state = tevent_req_data(req, - struct sysdb_search_custom_state); - int ret; - - ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count, - &state->msgs); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->expect_not_more_than_one && state->msgs_count > 1) { - DEBUG(1, ("More than one result found.\n")); - tevent_req_error(req, EFAULT); - return; - } - - tevent_req_done(req); -} - -int sysdb_search_custom_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - size_t *msgs_count, - struct ldb_message ***msgs) -{ - struct sysdb_search_custom_state *state = tevent_req_data(req, - struct sysdb_search_custom_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *msgs_count = state->msgs_count; - *msgs = talloc_move(mem_ctx, &state->msgs); - - return EOK; -} - - -/* =Custom Store (replaces-existing-data)================== */ - -struct sysdb_store_custom_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *object_name; - const char *subtree_name; - struct ldb_dn *dn; - struct sysdb_attrs *attrs; - struct ldb_message *msg; -}; - -static void sysdb_store_custom_check_done(struct tevent_req *subreq); -static void sysdb_store_custom_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_store_custom_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *object_name, - const char *subtree_name, - struct sysdb_attrs *attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_store_custom_state *state; - int ret; - const char **search_attrs; - - if (object_name == NULL || subtree_name == NULL) return NULL; - - if (handle == NULL) { - DEBUG(1, ("Sysdb context not available.\n")); - return NULL; - } - - req = tevent_req_create(mem_ctx, &state, struct sysdb_store_custom_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->object_name = object_name; - state->subtree_name = subtree_name; - state->attrs = attrs; - state->msg = NULL; - state->dn = sysdb_custom_dn(handle->ctx, state, domain->name, object_name, - subtree_name); - if (state->dn == NULL) { - DEBUG(1, ("sysdb_custom_dn failed.\n")); - ret = ENOMEM; - goto fail; - } - - search_attrs = talloc_array(state, const char *, 2); - if (search_attrs == NULL) { - DEBUG(1, ("talloc_array failed.\n")); - ret = ENOMEM; - goto fail; - } - search_attrs[0] = "*"; - search_attrs[1] = NULL; - - subreq = sysdb_search_custom_by_name_send(state, state->ev, NULL, - state->handle, - state->domain, - state->object_name, - state->subtree_name, - search_attrs); - if (!subreq) { - DEBUG(1, ("sysdb_search_custom_by_name_send failed.\n")); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_store_custom_check_done, req); - - return req; -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_store_custom_check_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_store_custom_state *state = tevent_req_data(req, - struct sysdb_store_custom_state); - int ret; - int i; - size_t resp_count = 0; - struct ldb_message **resp; - struct ldb_message *msg; - struct ldb_request *ldbreq; - struct ldb_message_element *el; - bool add_object = false; - - ret = sysdb_search_custom_recv(subreq, state, &resp_count, &resp); - talloc_zfree(subreq); - if (ret != EOK && ret != ENOENT) { - tevent_req_error(req, ret); - return; - } - - if (ret == ENOENT) { - add_object = true; - } - - msg = ldb_msg_new(state); - if (msg == NULL) { - tevent_req_error(req, ENOMEM); - return; - } - - msg->dn = state->dn; - - msg->elements = talloc_array(msg, struct ldb_message_element, - state->attrs->num); - if (!msg->elements) { - tevent_req_error(req, ENOMEM); - return; - } - - for (i = 0; i < state->attrs->num; i++) { - msg->elements[i] = state->attrs->a[i]; - if (add_object) { - msg->elements[i].flags = LDB_FLAG_MOD_ADD; - } else { - el = ldb_msg_find_element(resp[0], state->attrs->a[i].name); - if (el == NULL) { - msg->elements[i].flags = LDB_FLAG_MOD_ADD; - } else { - msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; - } - } - } - msg->num_elements = state->attrs->num; - - if (add_object) { - ret = ldb_build_add_req(&ldbreq, state->handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - } else { - ret = ldb_build_mod_req(&ldbreq, state->handle->ctx->ldb, state, msg, - NULL, NULL, NULL, NULL); - } - if (ret != LDB_SUCCESS) { - DEBUG(1, ("Failed to build request: %s(%d)[%s]\n", - ldb_strerror(ret), ret, - ldb_errstring(state->handle->ctx->ldb))); - tevent_req_error(req, sysdb_error_to_errno(ret)); - return; - } - - subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb, - ldbreq); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_store_custom_done, req); - return; -} - -static void sysdb_store_custom_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_op_default_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -int sysdb_store_custom_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -/* = Custom Delete======================================= */ - -struct sysdb_delete_custom_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - const char *object_name; - const char *subtree_name; - struct ldb_dn *dn; -}; -static void sysdb_delete_custom_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_delete_custom_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *object_name, - const char *subtree_name) -{ - struct tevent_req *req, *subreq; - struct sysdb_delete_custom_state *state; - int ret; - - if (object_name == NULL || subtree_name == NULL) return NULL; - - if (handle == NULL) { - DEBUG(1, ("Sysdb context not available.\n")); - return NULL; - } - - req = tevent_req_create(mem_ctx, &state, struct sysdb_store_custom_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->object_name = object_name; - state->subtree_name = subtree_name; - state->dn = sysdb_custom_dn(handle->ctx, state, domain->name, object_name, - subtree_name); - if (state->dn == NULL) { - DEBUG(1, ("sysdb_custom_dn failed.\n")); - ret = ENOMEM; - goto fail; - } - - subreq = sysdb_delete_entry_send(state, state->ev, state->handle, - state->dn, true); - if (!subreq) { - DEBUG(1, ("sysdb_delete_entry_send failed.\n")); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_delete_custom_done, req); - - return req; -fail: - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sysdb_delete_custom_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_delete_entry_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -int sysdb_delete_custom_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -/* = ASQ search request ======================================== */ -struct sysdb_asq_search_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - struct ldb_dn *base_dn; - const char *asq_attribute; - const char **attrs; - const char *expression; - - int msgs_count; - struct ldb_message **msgs; -}; - -void sysdb_asq_search_check_handle_done(struct tevent_req *subreq); -static void sysdb_asq_search_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_asq_search_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - struct ldb_dn *base_dn, - const char *expression, - const char *asq_attribute, - const char **attrs) -{ - struct tevent_req *req; - struct tevent_req *subreq; - struct sysdb_asq_search_state *state; - int ret; - - if (sysdb == NULL && handle == NULL) { - DEBUG(1, ("Sysdb context not available.\n")); - return NULL; - } - - req = tevent_req_create(mem_ctx, &state, struct sysdb_asq_search_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->sysdb = (sysdb == NULL) ? handle->ctx : sysdb; - state->handle = handle; - state->domain = domain; - state->base_dn = base_dn; - state->expression = expression; - state->asq_attribute = asq_attribute; - state->attrs = attrs; - - state->msgs_count = 0; - state->msgs = NULL; - - subreq = sysdb_check_handle_send(state, state->ev, state->sysdb, - state->handle); - if (!subreq) { - DEBUG(1, ("sysdb_check_handle_send failed.\n")); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_asq_search_check_handle_done, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -void sysdb_asq_search_check_handle_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_asq_search_state *state = tevent_req_data(req, - struct sysdb_asq_search_state); - struct ldb_request *ldb_req; - struct ldb_control **ctrl; - struct ldb_asq_control *asq_control; - int ret; - - ret = sysdb_check_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - ctrl = talloc_array(state, struct ldb_control *, 2); - if (ctrl == NULL) { - ret = ENOMEM; - goto fail; - } - - ctrl[0] = talloc(ctrl, struct ldb_control); - if (ctrl[0] == NULL) { - ret = ENOMEM; - goto fail; - } - ctrl[1] = NULL; - - ctrl[0]->oid = LDB_CONTROL_ASQ_OID; - ctrl[0]->critical = 1; - - asq_control = talloc(ctrl[0], struct ldb_asq_control); - if (asq_control == NULL) { - ret = ENOMEM; - goto fail; - } - - asq_control->request = 1; - asq_control->source_attribute = talloc_strdup(asq_control, - state->asq_attribute); - if (asq_control->source_attribute == NULL) { - ret = ENOMEM; - goto fail; - } - asq_control->src_attr_len = strlen(asq_control->source_attribute); - ctrl[0]->data = asq_control; - - ret = ldb_build_search_req(&ldb_req, state->handle->ctx->ldb, state, - state->base_dn, LDB_SCOPE_BASE, - state->expression, state->attrs, ctrl, - NULL, NULL, NULL); - if (ret != LDB_SUCCESS) { - ret = sysdb_error_to_errno(ret); - goto fail; - } - - subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb, - ldb_req); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - - tevent_req_set_callback(subreq, sysdb_asq_search_done, req); - return; - -fail: - tevent_req_error(req, ret); - return; -} - -static void sysdb_asq_search_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_asq_search_state *state = tevent_req_data(req, - struct sysdb_asq_search_state); - struct ldb_reply *ldbreply; - int ret; - - ret = sldb_request_recv(subreq, state, &ldbreply); - /* DO NOT free the subreq here, the subrequest search is not - * finished until we get an ldbreply of type LDB_REPLY_DONE */ - if (ret != EOK) { - DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret))); - tevent_req_error(req, ret); - return; - } - - switch (ldbreply->type) { - case LDB_REPLY_ENTRY: - state->msgs = talloc_realloc(state, state->msgs, - struct ldb_message *, - state->msgs_count + 2); - if (state->msgs == NULL) { - tevent_req_error(req, ENOMEM); - return; - } - - state->msgs[state->msgs_count + 1] = NULL; - - state->msgs[state->msgs_count] = talloc_steal(state->msgs, - ldbreply->message); - state->msgs_count++; - - talloc_zfree(ldbreply); - return; - - case LDB_REPLY_DONE: - /* now it is safe to free the subrequest, the search is complete */ - talloc_zfree(subreq); - break; - - default: - DEBUG(1, ("Unknown ldb reply type [%d].\n", ldbreply->type)); - tevent_req_error(req, EINVAL); - return; - } - - tevent_req_done(req); -} - -int sysdb_asq_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - size_t *msgs_count, struct ldb_message ***msgs) -{ - struct sysdb_asq_search_state *state = tevent_req_data(req, - struct sysdb_asq_search_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *msgs_count = state->msgs_count; - *msgs = talloc_move(mem_ctx, &state->msgs); - - return EOK; -} - -/* =Search-Users-with-Custom-Filter====================================== */ - -struct sysdb_search_users_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - const char *sub_filter; - const char **attrs; - - struct ldb_message **msgs; - size_t msgs_count; -}; - -void sysdb_search_users_check_handle(struct tevent_req *subreq); -static void sysdb_search_users_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_search_users_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *sub_filter, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_users_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_users_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->sub_filter = sub_filter; - state->attrs = attrs; - - state->msgs_count = 0; - state->msgs = NULL; - - subreq = sysdb_check_handle_send(state, ev, sysdb, handle); - if (!subreq) { - DEBUG(1, ("sysdb_check_handle_send failed.\n")); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_search_users_check_handle, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -void sysdb_search_users_check_handle(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_users_state *state = tevent_req_data(req, - struct sysdb_search_users_state); - struct ldb_dn *basedn; - char *filter; - int ret; - - ret = sysdb_check_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - basedn = ldb_dn_new_fmt(state, state->handle->ctx->ldb, - SYSDB_TMPL_USER_BASE, state->domain->name); - if (!basedn) { - DEBUG(2, ("Failed to build base dn\n")); - tevent_req_error(req, ENOMEM); - return; - } - - filter = talloc_asprintf(state, "(&(%s)%s)", - SYSDB_UC, state->sub_filter); - if (!filter) { - DEBUG(2, ("Failed to build filter\n")); - tevent_req_error(req, ENOMEM); - return; - } - - DEBUG(6, ("Search users with filter: %s\n", filter)); - - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - basedn, LDB_SCOPE_SUBTREE, - filter, state->attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_search_users_done, req); -} - -static void sysdb_search_users_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_users_state *state = tevent_req_data(req, - struct sysdb_search_users_state); - int ret; - - ret = sysdb_search_entry_recv(subreq, state, - &state->msgs_count, &state->msgs); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_search_users_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - size_t *msgs_count, struct ldb_message ***msgs) -{ - struct sysdb_search_users_state *state = tevent_req_data(req, - struct sysdb_search_users_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *msgs_count = state->msgs_count; - *msgs = talloc_move(mem_ctx, &state->msgs); - - return EOK; -} - -/* =Delete-User-by-Name-OR-uid============================================ */ - -struct sysdb_delete_user_state { - struct tevent_context *ev; - struct sss_domain_info *domain; - - const char *name; - uid_t uid; - - struct sysdb_handle *handle; -}; - -void sysdb_delete_user_check_handle(struct tevent_req *subreq); -static void sysdb_delete_user_found(struct tevent_req *subreq); -static void sysdb_delete_user_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_delete_user_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, uid_t uid) -{ - struct tevent_req *req, *subreq; - struct sysdb_delete_user_state *state; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_delete_user_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->uid = uid; - - subreq = sysdb_check_handle_send(state, ev, sysdb, handle); - if (!subreq) { - DEBUG(1, ("sysdb_check_handle_send failed.\n")); - tevent_req_error(req, ENOMEM); - tevent_req_post(req, ev); - return req; - } - tevent_req_set_callback(subreq, sysdb_delete_user_check_handle, req); - - return req; -} - -void sysdb_delete_user_check_handle(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_delete_user_state *state = tevent_req_data(req, - struct sysdb_delete_user_state); - static const char *attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL }; - int ret; - - ret = sysdb_check_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - if (state->name) { - subreq = sysdb_search_user_by_name_send(state, state->ev, NULL, - state->handle, state->domain, - state->name, attrs); - } else { - subreq = sysdb_search_user_by_uid_send(state, state->ev, NULL, - state->handle, state->domain, - state->uid, NULL); - } - - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_delete_user_found, req); -} - -static void sysdb_delete_user_found(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_delete_user_state *state = tevent_req_data(req, - struct sysdb_delete_user_state); - struct ldb_message *msg; - int ret; - - ret = sysdb_search_user_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->name && state->uid) { - /* verify name/gid match */ - const char *name; - uint64_t uid; - - name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); - uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0); - if (name == NULL || uid == 0) { - DEBUG(2, ("Attribute is missing but this should never happen!\n")); - tevent_req_error(req, EFAULT); - return; - } - if (strcmp(state->name, name) || state->uid != uid) { - /* this is not the entry we are looking for */ - tevent_req_error(req, EINVAL); - return; - } - } - - subreq = sysdb_delete_entry_send(state, state->ev, - state->handle, msg->dn, false); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_delete_user_done, req); -} - -static void sysdb_delete_user_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_delete_entry_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_delete_user_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - - -/* =Search-Groups-with-Custom-Filter===================================== */ - -struct sysdb_search_groups_state { - struct tevent_context *ev; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - const char *sub_filter; - const char **attrs; - - struct ldb_message **msgs; - size_t msgs_count; -}; - -void sysdb_search_groups_check_handle(struct tevent_req *subreq); -static void sysdb_search_groups_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_search_groups_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *sub_filter, - const char **attrs) -{ - struct tevent_req *req, *subreq; - struct sysdb_search_groups_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_search_groups_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->sub_filter = sub_filter; - state->attrs = attrs; - - state->msgs_count = 0; - state->msgs = NULL; - - subreq = sysdb_check_handle_send(state, ev, sysdb, handle); - if (!subreq) { - DEBUG(1, ("sysdb_check_handle_send failed.\n")); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sysdb_search_groups_check_handle, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -void sysdb_search_groups_check_handle(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_groups_state *state = tevent_req_data(req, - struct sysdb_search_groups_state); - struct ldb_dn *basedn; - char *filter; - int ret; - - ret = sysdb_check_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - basedn = ldb_dn_new_fmt(state, state->handle->ctx->ldb, - SYSDB_TMPL_GROUP_BASE, state->domain->name); - if (!basedn) { - DEBUG(2, ("Failed to build base dn\n")); - tevent_req_error(req, ENOMEM); - return; - } - - filter = talloc_asprintf(state, "(&(%s)%s)", - SYSDB_GC, state->sub_filter); - if (!filter) { - DEBUG(2, ("Failed to build filter\n")); - tevent_req_error(req, ENOMEM); - return; - } - - DEBUG(6, ("Search groups with filter: %s\n", filter)); - - subreq = sysdb_search_entry_send(state, state->ev, state->handle, - basedn, LDB_SCOPE_SUBTREE, - filter, state->attrs); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_search_groups_done, req); -} - -static void sysdb_search_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_search_groups_state *state = tevent_req_data(req, - struct sysdb_search_groups_state); - int ret; - - ret = sysdb_search_entry_recv(subreq, state, - &state->msgs_count, &state->msgs); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_search_groups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - size_t *msgs_count, struct ldb_message ***msgs) -{ - struct sysdb_search_groups_state *state = tevent_req_data(req, - struct sysdb_search_groups_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - - *msgs_count = state->msgs_count; - *msgs = talloc_move(mem_ctx, &state->msgs); - - return EOK; -} - -/* =Delete-Group-by-Name-OR-gid=========================================== */ - -struct sysdb_delete_group_state { - struct tevent_context *ev; - struct sss_domain_info *domain; - - const char *name; - gid_t gid; - - struct sysdb_handle *handle; -}; - -void sysdb_delete_group_check_handle(struct tevent_req *subreq); -static void sysdb_delete_group_found(struct tevent_req *subreq); -static void sysdb_delete_group_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_delete_group_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name, gid_t gid) -{ - struct tevent_req *req, *subreq; - struct sysdb_delete_group_state *state; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_delete_group_state); - if (!req) return NULL; - - state->ev = ev; - state->handle = handle; - state->domain = domain; - state->name = name; - state->gid = gid; - - subreq = sysdb_check_handle_send(state, ev, sysdb, handle); - if (!subreq) { - DEBUG(1, ("sysdb_check_handle_send failed.\n")); - tevent_req_error(req, ENOMEM); - tevent_req_post(req, ev); - return req; - } - tevent_req_set_callback(subreq, sysdb_delete_group_check_handle, req); - - return req; -} - -void sysdb_delete_group_check_handle(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_delete_group_state *state = tevent_req_data(req, - struct sysdb_delete_group_state); - static const char *attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL }; - int ret; - - ret = sysdb_check_handle_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - if (state->name) { - subreq = sysdb_search_group_by_name_send(state, state->ev, NULL, - state->handle, state->domain, - state->name, attrs); - } else { - subreq = sysdb_search_group_by_gid_send(state, state->ev, NULL, - state->handle, state->domain, - state->gid, NULL); - } - - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_delete_group_found, req); -} - -static void sysdb_delete_group_found(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sysdb_delete_group_state *state = tevent_req_data(req, - struct sysdb_delete_group_state); - struct ldb_message *msg; - int ret; - - ret = sysdb_search_group_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->name && state->gid) { - /* verify name/gid match */ - const char *name; - uint64_t gid; - - name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); - gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0); - if (name == NULL || gid == 0) { - DEBUG(2, ("Attribute is missing but this should never happen!\n")); - tevent_req_error(req, EFAULT); - return; - } - if (strcmp(state->name, name) || state->gid != gid) { - /* this is not the entry we are looking for */ - tevent_req_error(req, EINVAL); - return; - } - } - - subreq = sysdb_delete_entry_send(state, state->ev, - state->handle, msg->dn, false); - if (!subreq) { - DEBUG(6, ("Error: Out of memory\n")); - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sysdb_delete_group_done, req); -} - -static void sysdb_delete_group_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_delete_entry_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); -} - -int sysdb_delete_group_recv(struct tevent_req *req) -{ - return sysdb_op_default_recv(req); -} - -/* ========= Authentication against cached password ============ */ - -struct sysdb_cache_auth_state { - struct tevent_context *ev; - const char *name; - const uint8_t *authtok; - size_t authtok_size; - struct sss_domain_info *domain; - struct sysdb_ctx *sysdb; - struct confdb_ctx *cdb; - struct sysdb_attrs *update_attrs; - bool authentication_successful; - struct sysdb_handle *handle; - time_t expire_date; - time_t delayed_until; -}; - -errno_t check_failed_login_attempts(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, - struct ldb_message *ldb_msg, - uint32_t *failed_login_attempts, - time_t *delayed_until) -{ - int ret; - int allowed_failed_login_attempts; - int failed_login_delay; - time_t last_failed_login; - time_t end; - - *delayed_until = -1; - *failed_login_attempts = ldb_msg_find_attr_as_uint(ldb_msg, - SYSDB_FAILED_LOGIN_ATTEMPTS, 0); - last_failed_login = (time_t) ldb_msg_find_attr_as_int64(ldb_msg, - SYSDB_LAST_FAILED_LOGIN, 0); - ret = confdb_get_int(cdb, mem_ctx, CONFDB_PAM_CONF_ENTRY, - CONFDB_PAM_FAILED_LOGIN_ATTEMPTS, - CONFDB_DEFAULT_PAM_FAILED_LOGIN_ATTEMPTS, - &allowed_failed_login_attempts); - if (ret != EOK) { - DEBUG(1, ("Failed to read the number of allowed failed login " - "attempts.\n")); - return EIO; - } - ret = confdb_get_int(cdb, mem_ctx, CONFDB_PAM_CONF_ENTRY, - CONFDB_PAM_FAILED_LOGIN_DELAY, - CONFDB_DEFAULT_PAM_FAILED_LOGIN_DELAY, - &failed_login_delay); - if (ret != EOK) { - DEBUG(1, ("Failed to read the failed login delay.\n")); - return EIO; - } - DEBUG(9, ("Failed login attempts [%d], allowed failed login attempts [%d], " - "failed login delay [%d].\n", *failed_login_attempts, - allowed_failed_login_attempts, failed_login_delay)); - - if (allowed_failed_login_attempts) { - if (*failed_login_attempts >= allowed_failed_login_attempts) { - if (failed_login_delay) { - end = last_failed_login + (failed_login_delay * 60); - if (end < time(NULL)) { - DEBUG(7, ("failed_login_delay has passed, " - "resetting failed_login_attempts.\n")); - *failed_login_attempts = 0; - } else { - DEBUG(7, ("login delayed until %lld.\n", (long long) end)); - *delayed_until = end; - return EACCES; - } - } else { - DEBUG(4, ("Too many failed logins.\n")); - return EACCES; - } - } - } - - return EOK; -} - -static void sysdb_cache_auth_get_attrs_done(struct tevent_req *subreq); -static void sysdb_cache_auth_transaction_start_done(struct tevent_req *subreq); -static void sysdb_cache_auth_attr_update_done(struct tevent_req *subreq); -static void sysdb_cache_auth_done(struct tevent_req *subreq); - -struct tevent_req *sysdb_cache_auth_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - const char *name, - const uint8_t *authtok, - size_t authtok_size, - struct confdb_ctx *cdb) -{ - struct tevent_req *req; - struct tevent_req *subreq; - struct sysdb_cache_auth_state *state; - - if (name == NULL || *name == '\0') { - DEBUG(1, ("Missing user name.\n")); - return NULL; - } - - if (cdb == NULL) { - DEBUG(1, ("Missing config db context.\n")); - return NULL; - } - - if (sysdb == NULL) { - DEBUG(1, ("Missing sysdb db context.\n")); - return NULL; - } - - if (!domain->cache_credentials) { - DEBUG(3, ("Cached credentials not available.\n")); - return NULL; - } - - static const char *attrs[] = {SYSDB_NAME, - SYSDB_CACHEDPWD, - SYSDB_DISABLED, - SYSDB_LAST_LOGIN, - SYSDB_LAST_ONLINE_AUTH, - "lastCachedPasswordChange", - "accountExpires", - SYSDB_FAILED_LOGIN_ATTEMPTS, - SYSDB_LAST_FAILED_LOGIN, - NULL}; - - req = tevent_req_create(mem_ctx, &state, struct sysdb_cache_auth_state); - if (req == NULL) { - DEBUG(1, ("tevent_req_create failed.\n")); - return NULL; - } - - state->ev = ev; - state->name = name; - state->authtok = authtok; - state->authtok_size = authtok_size; - state->domain = domain; - state->sysdb = sysdb; - state->cdb = cdb; - state->update_attrs = NULL; - state->authentication_successful = false; - state->handle = NULL; - state->expire_date = -1; - state->delayed_until = -1; - - subreq = sysdb_search_user_by_name_send(state, ev, sysdb, NULL, domain, - name, attrs); - if (subreq == NULL) { - DEBUG(1, ("sysdb_search_user_by_name_send failed.\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, sysdb_cache_auth_get_attrs_done, req); - - return req; -} - -static void sysdb_cache_auth_get_attrs_done(struct tevent_req *subreq) -{ - struct ldb_message *ldb_msg; - const char *userhash; - char *comphash; - char *password = NULL; - int i; - int ret; - uint64_t lastLogin = 0; - int cred_expiration; - uint32_t failed_login_attempts = 0; - - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - - struct sysdb_cache_auth_state *state = tevent_req_data(req, - struct sysdb_cache_auth_state); - - ret = sysdb_search_user_recv(subreq, state, &ldb_msg); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(1, ("sysdb_search_user_by_name_send failed [%d][%s].\n", - ret, strerror(ret))); - tevent_req_error(req, ENOENT); - return; - } - - /* Check offline_auth_cache_timeout */ - lastLogin = ldb_msg_find_attr_as_uint64(ldb_msg, - SYSDB_LAST_ONLINE_AUTH, - 0); - - ret = confdb_get_int(state->cdb, state, CONFDB_PAM_CONF_ENTRY, - CONFDB_PAM_CRED_TIMEOUT, 0, &cred_expiration); - if (ret != EOK) { - DEBUG(1, ("Failed to read expiration time of offline credentials.\n")); - ret = EACCES; - goto done; - } - DEBUG(9, ("Offline credentials expiration is [%d] days.\n", - cred_expiration)); - - if (cred_expiration) { - state->expire_date = lastLogin + (cred_expiration * 86400); - if (state->expire_date < time(NULL)) { - DEBUG(4, ("Cached user entry is too old.\n")); - state->expire_date = 0; - ret = EACCES; - goto done; - } - } else { - state->expire_date = 0; - } - - ret = check_failed_login_attempts(state, state->cdb, ldb_msg, - &failed_login_attempts, - &state->delayed_until); - if (ret != EOK) { - goto done; - } - - /* TODO: verify user account (disabled, expired ...) */ - - password = talloc_strndup(state, (const char *) state->authtok, - state->authtok_size); - if (password == NULL) { - DEBUG(1, ("talloc_strndup failed.\n")); - ret = ENOMEM; - goto done; - } - - userhash = ldb_msg_find_attr_as_string(ldb_msg, SYSDB_CACHEDPWD, NULL); - if (userhash == NULL || *userhash == '\0') { - DEBUG(4, ("Cached credentials not available.\n")); - ret = ENOENT; - goto done; - } - - ret = s3crypt_sha512(state, password, userhash, &comphash); - if (ret) { - DEBUG(4, ("Failed to create password hash.\n")); - ret = EFAULT; - goto done; - } - - state->update_attrs = sysdb_new_attrs(state); - if (state->update_attrs == NULL) { - DEBUG(1, ("sysdb_new_attrs failed.\n")); - goto done; - } - - if (strcmp(userhash, comphash) == 0) { - /* TODO: probable good point for audit logging */ - DEBUG(4, ("Hashes do match!\n")); - state->authentication_successful = true; - - ret = sysdb_attrs_add_time_t(state->update_attrs, SYSDB_LAST_LOGIN, - time(NULL)); - if (ret != EOK) { - DEBUG(3, ("sysdb_attrs_add_time_t failed, " - "but authentication is successful.\n")); - ret = EOK; - goto done; - } - - ret = sysdb_attrs_add_uint32(state->update_attrs, - SYSDB_FAILED_LOGIN_ATTEMPTS, 0U); - if (ret != EOK) { - DEBUG(3, ("sysdb_attrs_add_uint32 failed, " - "but authentication is successful.\n")); - ret = EOK; - goto done; - } - - - } else { - DEBUG(4, ("Authentication failed.\n")); - state->authentication_successful = false; - - ret = sysdb_attrs_add_time_t(state->update_attrs, - SYSDB_LAST_FAILED_LOGIN, - time(NULL)); - if (ret != EOK) { - DEBUG(3, ("sysdb_attrs_add_time_t failed\n.")); - ret = EINVAL; - goto done; - } - - ret = sysdb_attrs_add_uint32(state->update_attrs, - SYSDB_FAILED_LOGIN_ATTEMPTS, - ++failed_login_attempts); - if (ret != EOK) { - DEBUG(3, ("sysdb_attrs_add_uint32 failed.\n")); - ret = EINVAL; - goto done; - } - } - - subreq = sysdb_transaction_send(state, state->ev, state->sysdb); - if (subreq == NULL) { - DEBUG(1, ("sysdb_transaction_send failed.\n")); - goto done; - } - tevent_req_set_callback(subreq, sysdb_cache_auth_transaction_start_done, - req); - return; - -done: - if (password) for (i = 0; password[i]; i++) password[i] = 0; - if (ret == EOK) { - tevent_req_done(req); - } else { - tevent_req_error(req, ret); - } - return; -} - -static void sysdb_cache_auth_transaction_start_done(struct tevent_req *subreq) -{ - int ret; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - - struct sysdb_cache_auth_state *state = tevent_req_data(req, - struct sysdb_cache_auth_state); - - ret = sysdb_transaction_recv(subreq, state, &state->handle); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(1, ("sysdb_transaction_send failed [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - - subreq = sysdb_set_user_attr_send(state, state->ev, state->handle, - state->domain, state->name, - state->update_attrs, - LDB_FLAG_MOD_REPLACE); - if (subreq == NULL) { - DEBUG(1, ("sysdb_set_user_attr_send failed.\n")); - goto done; - } - tevent_req_set_callback(subreq, sysdb_cache_auth_attr_update_done, - req); - return; - -done: - if (state->authentication_successful) { - tevent_req_done(req); - } else { - tevent_req_error(req, EINVAL); - } - return; -} - -static void sysdb_cache_auth_attr_update_done(struct tevent_req *subreq) -{ - int ret; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - - struct sysdb_cache_auth_state *state = tevent_req_data(req, - struct sysdb_cache_auth_state); - - ret = sysdb_set_user_attr_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(1, ("sysdb_set_user_attr request failed [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - subreq = sysdb_transaction_commit_send(state, state->ev, state->handle); - if (subreq == NULL) { - DEBUG(1, ("sysdb_transaction_commit_send failed.\n")); - goto done; - } - tevent_req_set_callback(subreq, sysdb_cache_auth_done, req); - return; - -done: - if (state->authentication_successful) { - tevent_req_done(req); - } else { - tevent_req_error(req, EINVAL); - } - return; -} - -static void sysdb_cache_auth_done(struct tevent_req *subreq) -{ - int ret; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - - struct sysdb_cache_auth_state *state = tevent_req_data(req, - struct sysdb_cache_auth_state); - - ret = sysdb_transaction_commit_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(1, ("sysdb_transaction_commit_send failed [%d][%s].\n", - ret, strerror(ret))); - } - - if (state->authentication_successful) { - tevent_req_done(req); - } else { - tevent_req_error(req, EINVAL); - } - return; -} - -int sysdb_cache_auth_recv(struct tevent_req *req, time_t *expire_date, - time_t *delayed_until) { - struct sysdb_cache_auth_state *state = tevent_req_data(req, - struct sysdb_cache_auth_state); - *expire_date = state->expire_date; - *delayed_until = state->delayed_until; - - TEVENT_REQ_RETURN_ON_ERROR(req); - - return (state->authentication_successful ? EOK : EINVAL); -} diff --git a/server/db/sysdb_private.h b/server/db/sysdb_private.h deleted file mode 100644 index 270cf360..00000000 --- a/server/db/sysdb_private.h +++ /dev/null @@ -1,107 +0,0 @@ - -/* - SSSD - - Private System Database Header - - 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/>. -*/ - -#ifndef __INT_SYS_DB_H__ -#define __INT_SYS_DB_H__ - -#define SYSDB_VERSION_0_5 "0.5" -#define SYSDB_VERSION_0_4 "0.4" -#define SYSDB_VERSION_0_3 "0.3" -#define SYSDB_VERSION_0_2 "0.2" -#define SYSDB_VERSION_0_1 "0.1" - -#define SYSDB_VERSION SYSDB_VERSION_0_5 - -#define SYSDB_BASE_LDIF \ - "dn: @ATTRIBUTES\n" \ - "userPrincipalName: CASE_INSENSITIVE\n" \ - "cn: CASE_INSENSITIVE\n" \ - "dc: CASE_INSENSITIVE\n" \ - "dn: CASE_INSENSITIVE\n" \ - "objectclass: CASE_INSENSITIVE\n" \ - "\n" \ - "dn: @INDEXLIST\n" \ - "@IDXATTR: cn\n" \ - "@IDXATTR: objectclass\n" \ - "@IDXATTR: member\n" \ - "@IDXATTR: memberof\n" \ - "@IDXATTR: name\n" \ - "@IDXATTR: uidNumber\n" \ - "@IDXATTR: gidNumber\n" \ - "@IDXATTR: lastUpdate\n" \ - "@IDXATTR: originalDN\n" \ - "\n" \ - "dn: @MODULES\n" \ - "@LIST: asq,memberof\n" \ - "\n" \ - "dn: cn=sysdb\n" \ - "cn: sysdb\n" \ - "version: " SYSDB_VERSION "\n" \ - "description: base object\n" \ - "\n" - -#include "db/sysdb.h" - -struct sysdb_handle { - struct sysdb_handle *prev; - struct sysdb_handle *next; - - struct sysdb_ctx *ctx; - struct tevent_req *subreq; - - bool transaction_active; -}; - -struct sysdb_ctx { - struct tevent_context *ev; - - struct sss_domain_info *domain; - bool mpg; - - struct ldb_context *ldb; - char *ldb_file; - - struct sysdb_handle *queue; -}; - -struct sysdb_ctx_list { - struct sysdb_ctx **dbs; - size_t num_dbs; - - char *db_path; -}; - -/* An operation blocks the transaction queue as well, but does not - * start a transaction, normally useful only for search type calls. - * do *NOT* call within a transaction you'll deadlock sysdb. - * Also make sure to free the handle as soon as the operation is - * finished to avoid stalling or potentially deadlocking sysdb */ - -struct tevent_req *sysdb_operation_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *ctx); -int sysdb_operation_recv(struct tevent_req *req, TALLOC_CTX *memctx, - struct sysdb_handle **handle); - -void sysdb_operation_done(struct sysdb_handle *handle); - -#endif /* __INT_SYS_DB_H__ */ diff --git a/server/db/sysdb_search.c b/server/db/sysdb_search.c deleted file mode 100644 index 4b9470ba..00000000 --- a/server/db/sysdb_search.c +++ /dev/null @@ -1,691 +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 "confdb/confdb.h" -#include <time.h> - -struct sysdb_search_ctx; - -typedef void (*gen_callback)(struct sysdb_search_ctx *); - -struct sysdb_search_ctx { - struct tevent_context *ev; - struct sysdb_ctx *ctx; - struct sysdb_handle *handle; - - struct sss_domain_info *domain; - - const char *expression; - - sysdb_callback_t callback; - void *ptr; - - gen_callback gen_aux_fn; - bool gen_conv_mpg_users; - - struct ldb_result *res; - - const char **attrs; - - int error; -}; - -static struct sysdb_search_ctx *init_src_ctx(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct sysdb_ctx *ctx, - sysdb_callback_t fn, - void *ptr) -{ - struct sysdb_search_ctx *sctx; - - sctx = talloc_zero(mem_ctx, struct sysdb_search_ctx); - if (!sctx) { - return NULL; - } - sctx->ctx = ctx; - sctx->ev = ctx->ev; - sctx->callback = fn; - sctx->ptr = ptr; - sctx->res = talloc_zero(sctx, struct ldb_result); - if (!sctx->res) { - talloc_free(sctx); - return NULL; - } - sctx->domain = domain; - - return sctx; -} - -static void request_ldberror(struct sysdb_search_ctx *sctx, int error) -{ - sysdb_operation_done(sctx->handle); - sctx->callback(sctx->ptr, sysdb_error_to_errno(error), NULL); -} - -static void request_error(struct sysdb_search_ctx *sctx, int error) -{ - sysdb_operation_done(sctx->handle); - sctx->callback(sctx->ptr, error, NULL); -} - -static void request_done(struct sysdb_search_ctx *sctx) -{ - sysdb_operation_done(sctx->handle); - sctx->callback(sctx->ptr, EOK, sctx->res); -} - -static int mpg_convert(struct ldb_message *msg); - -static int get_gen_callback(struct ldb_request *req, - struct ldb_reply *rep) -{ - struct sysdb_search_ctx *sctx; - struct ldb_result *res; - int n, ret; - - sctx = talloc_get_type(req->context, struct sysdb_search_ctx); - res = sctx->res; - - if (!rep) { - request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - return LDB_ERR_OPERATIONS_ERROR; - } - if (rep->error != LDB_SUCCESS) { - request_ldberror(sctx, rep->error); - return rep->error; - } - - switch (rep->type) { - case LDB_REPLY_ENTRY: - - if (sctx->gen_conv_mpg_users) { - ret = mpg_convert(rep->message); - if (ret != EOK) { - request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - return LDB_ERR_OPERATIONS_ERROR; - } - } - - res->msgs = talloc_realloc(res, res->msgs, - struct ldb_message *, - res->count + 2); - if (!res->msgs) { - request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - return LDB_ERR_OPERATIONS_ERROR; - } - - res->msgs[res->count + 1] = NULL; - - res->msgs[res->count] = talloc_steal(res->msgs, rep->message); - res->count++; - break; - - case LDB_REPLY_REFERRAL: - if (res->refs) { - for (n = 0; res->refs[n]; n++) /*noop*/ ; - } else { - n = 0; - } - - res->refs = talloc_realloc(res, res->refs, char *, n + 2); - if (! res->refs) { - request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - return LDB_ERR_OPERATIONS_ERROR; - } - - res->refs[n] = talloc_steal(res->refs, rep->referral); - res->refs[n + 1] = NULL; - break; - - case LDB_REPLY_DONE: - res->controls = talloc_steal(res, rep->controls); - - /* check if we need to call any aux function */ - if (sctx->gen_aux_fn) { - sctx->gen_aux_fn(sctx); - } else { - /* no aux functions, this means the request is done */ - request_done(sctx); - } - return LDB_SUCCESS; - } - - talloc_free(rep); - return LDB_SUCCESS; -} - -/* users */ - -static void user_search(struct tevent_req *treq) -{ - struct sysdb_search_ctx *sctx; - struct ldb_request *req; - struct ldb_dn *base_dn; - int ret; - - sctx = tevent_req_callback_data(treq, struct sysdb_search_ctx); - - ret = sysdb_operation_recv(treq, sctx, &sctx->handle); - if (ret) { - return request_error(sctx, ret); - } - - base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb, - SYSDB_TMPL_USER_BASE, sctx->domain->name); - if (!base_dn) { - return request_error(sctx, ENOMEM); - } - - ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx, - base_dn, LDB_SCOPE_SUBTREE, - sctx->expression, sctx->attrs, NULL, - sctx, get_gen_callback, - NULL); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } - - ret = ldb_request(sctx->ctx->ldb, req); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } -} - -int sysdb_getpwnam(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - sysdb_callback_t fn, void *ptr) -{ - static const char *attrs[] = SYSDB_PW_ATTRS; - struct sysdb_search_ctx *sctx; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - sctx->expression = talloc_asprintf(sctx, SYSDB_PWNAM_FILTER, name); - if (!sctx->expression) { - talloc_free(sctx); - return ENOMEM; - } - - sctx->attrs = attrs; - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, user_search, sctx); - - return EOK; -} - -int sysdb_getpwuid(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - uid_t uid, - sysdb_callback_t fn, void *ptr) -{ - static const char *attrs[] = SYSDB_PW_ATTRS; - struct sysdb_search_ctx *sctx; - unsigned long int filter_uid = uid; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - sctx->expression = talloc_asprintf(sctx, SYSDB_PWUID_FILTER, filter_uid); - if (!sctx->expression) { - talloc_free(sctx); - return ENOMEM; - } - - sctx->attrs = attrs; - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, user_search, sctx); - - return EOK; -} - -int sysdb_enumpwent(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *expression, - sysdb_callback_t fn, void *ptr) -{ - static const char *attrs[] = SYSDB_PW_ATTRS; - struct sysdb_search_ctx *sctx; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - if (expression) - sctx->expression = expression; - else - sctx->expression = SYSDB_PWENT_FILTER; - - sctx->attrs = attrs; - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, user_search, sctx); - - return EOK; -} - -/* groups */ - -static int mpg_convert(struct ldb_message *msg) -{ - struct ldb_message_element *el; - struct ldb_val *val; - int i; - - el = ldb_msg_find_element(msg, "objectClass"); - if (!el) return EINVAL; - - /* see if this is a user to convert to a group */ - for (i = 0; i < el->num_values; i++) { - val = &(el->values[i]); - if (strncasecmp(SYSDB_USER_CLASS, - (char *)val->data, val->length) == 0) { - break; - } - } - /* no, leave as is */ - if (i == el->num_values) return EOK; - - /* yes, convert */ - val->data = (uint8_t *)talloc_strdup(msg, SYSDB_GROUP_CLASS); - if (val->data == NULL) return ENOMEM; - val->length = strlen(SYSDB_GROUP_CLASS); - - return EOK; -} - -static void grp_search(struct tevent_req *treq) -{ - struct sysdb_search_ctx *sctx; - static const char *attrs[] = SYSDB_GRSRC_ATTRS; - struct ldb_request *req; - struct ldb_dn *base_dn; - int ret; - - sctx = tevent_req_callback_data(treq, struct sysdb_search_ctx); - - ret = sysdb_operation_recv(treq, sctx, &sctx->handle); - if (ret) { - return request_error(sctx, ret); - } - - if (sctx->gen_conv_mpg_users) { - base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb, - SYSDB_DOM_BASE, sctx->domain->name); - } else { - base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb, - SYSDB_TMPL_GROUP_BASE, sctx->domain->name); - } - if (!base_dn) { - return request_error(sctx, ENOMEM); - } - - ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx, - base_dn, LDB_SCOPE_SUBTREE, - sctx->expression, attrs, NULL, - sctx, get_gen_callback, - NULL); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } - - ret = ldb_request(sctx->ctx->ldb, req); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } -} - -int sysdb_getgrnam(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - sysdb_callback_t fn, void *ptr) -{ - struct sysdb_search_ctx *sctx; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - if (ctx->mpg) { - sctx->gen_conv_mpg_users = true; - sctx->expression = talloc_asprintf(sctx, SYSDB_GRNAM_MPG_FILTER, name); - } else { - sctx->expression = talloc_asprintf(sctx, SYSDB_GRNAM_FILTER, name); - } - if (!sctx->expression) { - talloc_free(sctx); - return ENOMEM; - } - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, grp_search, sctx); - - return EOK; -} - -int sysdb_getgrgid(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - gid_t gid, - sysdb_callback_t fn, void *ptr) -{ - struct sysdb_search_ctx *sctx; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - if (ctx->mpg) { - sctx->gen_conv_mpg_users = true; - sctx->expression = talloc_asprintf(sctx, - SYSDB_GRGID_MPG_FILTER, - (unsigned long int)gid); - } else { - sctx->expression = talloc_asprintf(sctx, - SYSDB_GRGID_FILTER, - (unsigned long int)gid); - } - if (!sctx->expression) { - talloc_free(sctx); - return ENOMEM; - } - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, grp_search, sctx); - - return EOK; -} - -int sysdb_enumgrent(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - sysdb_callback_t fn, void *ptr) -{ - struct sysdb_search_ctx *sctx; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - if (ctx->mpg) { - sctx->gen_conv_mpg_users = true; - sctx->expression = SYSDB_GRENT_MPG_FILTER; - } else { - sctx->expression = SYSDB_GRENT_FILTER; - } - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, grp_search, sctx); - - return EOK; -} - -static void initgr_mem_search(struct sysdb_search_ctx *sctx) -{ - struct sysdb_ctx *ctx = sctx->ctx; - struct ldb_result *res = sctx->res; - struct ldb_request *req; - struct ldb_control **ctrl; - struct ldb_asq_control *control; - static const char *attrs[] = SYSDB_INITGR_ATTRS; - int ret; - - if (res->count == 0) { - return request_done(sctx); - } - if (res->count > 1) { - return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - } - - /* make sure we don't loop with get_gen_callback() */ - sctx->gen_aux_fn = NULL; - - sctx->expression = talloc_asprintf(sctx, SYSDB_INITGR_FILTER); - if (!sctx->expression) { - return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - } - - ctrl = talloc_array(sctx, struct ldb_control *, 2); - if (!ctrl) { - return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - } - ctrl[1] = NULL; - ctrl[0] = talloc(ctrl, struct ldb_control); - if (!ctrl[0]) { - return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - } - ctrl[0]->oid = LDB_CONTROL_ASQ_OID; - ctrl[0]->critical = 1; - control = talloc(ctrl[0], struct ldb_asq_control); - if (!control) { - return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - } - control->request = 1; - control->source_attribute = talloc_strdup(control, SYSDB_INITGR_ATTR); - if (!control->source_attribute) { - return request_ldberror(sctx, LDB_ERR_OPERATIONS_ERROR); - } - control->src_attr_len = strlen(control->source_attribute); - ctrl[0]->data = control; - - ret = ldb_build_search_req(&req, ctx->ldb, sctx, - res->msgs[0]->dn, - LDB_SCOPE_BASE, - sctx->expression, attrs, ctrl, - sctx, get_gen_callback, - NULL); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } - - ret = ldb_request(ctx->ldb, req); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } -} - -static void initgr_search(struct tevent_req *treq) -{ - struct sysdb_search_ctx *sctx; - static const char *attrs[] = SYSDB_PW_ATTRS; - struct ldb_request *req; - struct ldb_dn *base_dn; - int ret; - - sctx = tevent_req_callback_data(treq, struct sysdb_search_ctx); - - ret = sysdb_operation_recv(treq, sctx, &sctx->handle); - if (ret) { - return request_error(sctx, ret); - } - - sctx->gen_aux_fn = initgr_mem_search; - - base_dn = ldb_dn_new_fmt(sctx, sctx->ctx->ldb, - SYSDB_TMPL_USER_BASE, sctx->domain->name); - if (!base_dn) { - return request_error(sctx, ENOMEM); - } - - ret = ldb_build_search_req(&req, sctx->ctx->ldb, sctx, - base_dn, LDB_SCOPE_SUBTREE, - sctx->expression, attrs, NULL, - sctx, get_gen_callback, - NULL); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } - - ret = ldb_request(sctx->ctx->ldb, req); - if (ret != LDB_SUCCESS) { - return request_ldberror(sctx, ret); - } -} - -int sysdb_initgroups(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - sysdb_callback_t fn, void *ptr) -{ - struct sysdb_search_ctx *sctx; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - sctx->expression = talloc_asprintf(sctx, SYSDB_PWNAM_FILTER, name); - if (!sctx->expression) { - talloc_free(sctx); - return ENOMEM; - } - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, initgr_search, sctx); - - return EOK; -} - -int sysdb_get_user_attr(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *ctx, - struct sss_domain_info *domain, - const char *name, - const char **attributes, - sysdb_callback_t fn, void *ptr) -{ - struct sysdb_search_ctx *sctx; - struct tevent_req *req; - - if (!domain) { - return EINVAL; - } - - sctx = init_src_ctx(mem_ctx, domain, ctx, fn, ptr); - if (!sctx) { - return ENOMEM; - } - - sctx->expression = talloc_asprintf(sctx, SYSDB_PWNAM_FILTER, name); - if (!sctx->expression) { - talloc_free(sctx); - return ENOMEM; - } - - sctx->attrs = attributes; - - req = sysdb_operation_send(mem_ctx, ctx->ev, ctx); - if (!req) { - talloc_free(sctx); - return ENOMEM; - } - - tevent_req_set_callback(req, user_search, sctx); - - return EOK; -} |