diff options
Diffstat (limited to 'server/providers/ldap/ldap_id_cleanup.c')
-rw-r--r-- | server/providers/ldap/ldap_id_cleanup.c | 555 |
1 files changed, 0 insertions, 555 deletions
diff --git a/server/providers/ldap/ldap_id_cleanup.c b/server/providers/ldap/ldap_id_cleanup.c deleted file mode 100644 index f3fb4443..00000000 --- a/server/providers/ldap/ldap_id_cleanup.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - SSSD - - LDAP Identity Cleanup Functions - - Authors: - Simo Sorce <ssorce@redhat.com> - - Copyright (C) 2009 Red Hat - - 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 <errno.h> -#include <time.h> -#include <sys/time.h> - -#include "util/util.h" -#include "db/sysdb.h" -#include "providers/ldap/ldap_common.h" -#include "providers/ldap/sdap_async.h" - -/* ==Cleanup-Task========================================================= */ - -struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); -static void ldap_id_cleanup_reschedule(struct tevent_req *req); - -static void ldap_id_cleanup_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt); - -static void ldap_id_cleanup_timer(struct tevent_context *ev, - struct tevent_timer *tt, - struct timeval tv, void *pvt) -{ - struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); - struct tevent_timer *timeout; - struct tevent_req *req; - int delay; - - if (be_is_offline(ctx->be)) { - DEBUG(4, ("Backend is marked offline, retry later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_cleanup_set_timer(ctx, tv); - return; - } - - req = ldap_id_cleanup_send(ctx, ev, ctx); - if (!req) { - DEBUG(1, ("Failed to schedule cleanup, retrying later!\n")); - /* schedule starting from now, not the last run */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_cleanup_set_timer(ctx, tv); - return; - } - tevent_req_set_callback(req, ldap_id_cleanup_reschedule, ctx); - - /* if cleanup takes so long, either we try to cleanup too - * frequently, or something went seriously wrong */ - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_current_ofs(delay, 0); - timeout = tevent_add_timer(ctx->be->ev, req, tv, - ldap_id_cleanup_timeout, req); - return; -} - -static void ldap_id_cleanup_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - int delay; - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - DEBUG(1, ("Cleanup timed out! Timeout too small? (%ds)!\n", delay)); - - tv = tevent_timeval_current_ofs(delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); - - talloc_zfree(req); -} - -static void ldap_id_cleanup_reschedule(struct tevent_req *req) -{ - struct sdap_id_ctx *ctx = tevent_req_callback_data(req, - struct sdap_id_ctx); - enum tevent_req_state tstate; - uint64_t err; - struct timeval tv; - int delay; - - if (tevent_req_is_error(req, &tstate, &err)) { - /* On error schedule starting from now, not the last run */ - tv = tevent_timeval_current(); - } else { - tv = ctx->last_purge; - } - talloc_zfree(req); - - delay = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); - tv = tevent_timeval_add(&tv, delay, 0); - ldap_id_enumerate_set_timer(ctx, tv); -} - - - -int ldap_id_cleanup_set_timer(struct sdap_id_ctx *ctx, struct timeval tv) -{ - struct tevent_timer *cleanup_task; - - DEBUG(6, ("Scheduling next cleanup at %ld.%ld\n", - (long)tv.tv_sec, (long)tv.tv_usec)); - - cleanup_task = tevent_add_timer(ctx->be->ev, ctx, - tv, ldap_id_cleanup_timer, ctx); - if (!cleanup_task) { - DEBUG(0, ("FATAL: failed to setup cleanup task!\n")); - return EFAULT; - } - - return EOK; -} - - - -struct global_cleanup_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; -}; - -static struct tevent_req *cleanup_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); -static void ldap_id_cleanup_users_done(struct tevent_req *subreq); -static struct tevent_req *cleanup_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx); -static void ldap_id_cleanup_groups_done(struct tevent_req *subreq); - -struct tevent_req *ldap_id_cleanup_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct global_cleanup_state *state; - struct tevent_req *req, *subreq; - - req = tevent_req_create(memctx, &state, struct global_cleanup_state); - if (!req) return NULL; - - state->ev = ev; - state->ctx = ctx; - - subreq = cleanup_users_send(state, ev, ctx); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, ldap_id_cleanup_users_done, req); - - ctx->last_purge = tevent_timeval_current(); - - return req; -} - -static void ldap_id_cleanup_users_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_cleanup_state *state = tevent_req_data(req, - struct global_cleanup_state); - enum tevent_req_state tstate; - uint64_t err = 0; - - if (tevent_req_is_error(subreq, &tstate, &err)) { - if (tstate != TEVENT_REQ_USER_ERROR) { - err = EIO; - } - if (err != ENOENT) { - goto fail; - } - } - talloc_zfree(subreq); - - subreq = cleanup_groups_send(state, state->ev, state->ctx); - if (!subreq) { - goto fail; - } - tevent_req_set_callback(subreq, ldap_id_cleanup_groups_done, req); - - return; - -fail: - if (err) { - DEBUG(9, ("User cleanup failed with: (%d)[%s]\n", - (int)err, strerror(err))); - - if (sdap_check_gssapi_reconnect(state->ctx)) { - talloc_zfree(state->ctx->gsh); - subreq = cleanup_users_send(state, state->ev, state->ctx); - if (subreq != NULL) { - tevent_req_set_callback(subreq, ldap_id_cleanup_users_done, req); - return; - } - } - sdap_mark_offline(state->ctx); - } - - DEBUG(1, ("Failed to cleanup users, retrying later!\n")); - tevent_req_done(req); -} - -static void ldap_id_cleanup_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct global_cleanup_state *state = tevent_req_data(req, - struct global_cleanup_state); - enum tevent_req_state tstate; - uint64_t err; - - if (tevent_req_is_error(subreq, &tstate, &err)) { - if (tstate != TEVENT_REQ_USER_ERROR) { - err = EIO; - } - if (err != ENOENT) { - goto fail; - } - } - talloc_zfree(subreq); - - tevent_req_done(req); - return; - -fail: - /* check if credentials are expired otherwise go offline on failures */ - if (sdap_check_gssapi_reconnect(state->ctx)) { - talloc_zfree(state->ctx->gsh); - subreq = cleanup_groups_send(state, state->ev, state->ctx); - if (subreq != NULL) { - tevent_req_set_callback(subreq, ldap_id_cleanup_groups_done, req); - return; - } - } - sdap_mark_offline(state->ctx); - DEBUG(1, ("Failed to cleanup groups (%d [%s]), retrying later!\n", - (int)err, strerror(err))); - tevent_req_done(req); -} - - -/* ==User-Cleanup-Process================================================= */ - -struct cleanup_users_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - - struct sysdb_handle *handle; - - struct ldb_message **msgs; - size_t count; - int cur; -}; - -static void cleanup_users_process(struct tevent_req *subreq); -static void cleanup_users_update(struct tevent_req *req); -static void cleanup_users_up_done(struct tevent_req *subreq); - -static struct tevent_req *cleanup_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct tevent_req *req, *subreq; - struct cleanup_users_state *state; - static const char *attrs[] = { SYSDB_NAME, NULL }; - time_t now = time(NULL); - char *subfilter; - - req = tevent_req_create(memctx, &state, struct cleanup_users_state); - if (!req) { - return NULL; - } - - state->ev = ev; - state->ctx = ctx; - state->sysdb = ctx->be->sysdb; - state->domain = ctx->be->domain; - state->msgs = NULL; - state->count = 0; - state->cur = 0; - - subfilter = talloc_asprintf(state, "(&(!(%s=0))(%s<=%ld))", - SYSDB_CACHE_EXPIRE, - SYSDB_CACHE_EXPIRE, (long)now); - if (!subfilter) { - DEBUG(2, ("Failed to build filter\n")); - talloc_zfree(req); - return NULL; - } - - subreq = sysdb_search_users_send(state, state->ev, - state->sysdb, NULL, - state->domain, subfilter, attrs); - if (!subreq) { - DEBUG(2, ("Failed to send entry search\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, cleanup_users_process, req); - - return req; -} - -static void cleanup_users_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_users_state *state = tevent_req_data(req, - struct cleanup_users_state); - int ret; - - ret = sysdb_search_users_recv(subreq, state, &state->count, &state->msgs); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOENT) { - tevent_req_done(req); - return; - } - tevent_req_error(req, ret); - return; - } - - DEBUG(4, ("Found %d expired user entries!\n", state->count)); - - if (state->count == 0) { - tevent_req_done(req); - } - - cleanup_users_update(req); -} - -static void cleanup_users_update(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct cleanup_users_state *state = tevent_req_data(req, - struct cleanup_users_state); - const char *str; - - str = ldb_msg_find_attr_as_string(state->msgs[state->cur], - SYSDB_NAME, NULL); - if (!str) { - DEBUG(2, ("Entry %s has no Name Attribute ?!?\n", - ldb_dn_get_linearized(state->msgs[state->cur]->dn))); - tevent_req_error(req, EFAULT); - return; - } - - subreq = users_get_send(state, state->ev, state->ctx, - str, BE_FILTER_NAME, BE_ATTR_CORE); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, cleanup_users_up_done, req); -} - -static void cleanup_users_up_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_users_state *state = tevent_req_data(req, - struct cleanup_users_state); - int ret; - - ret = users_get_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("User check returned: %d(%s)\n", - ret, strerror(ret))); - } - - /* if the entry doesn't need to be purged, remove it from the list */ - if (ret != ENOENT) { - talloc_zfree(state->msgs[state->cur]); - } - - state->cur++; - if (state->cur < state->count) { - cleanup_users_update(req); - return; - } - - tevent_req_done(req); -} - -/* ==Group-Cleanup-Process================================================ */ - -struct cleanup_groups_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - - struct sysdb_handle *handle; - - struct ldb_message **msgs; - size_t count; - int cur; -}; - -static void cleanup_groups_process(struct tevent_req *subreq); -static void cleanup_groups_update(struct tevent_req *req); -static void cleanup_groups_up_done(struct tevent_req *subreq); - -static struct tevent_req *cleanup_groups_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx) -{ - struct tevent_req *req, *subreq; - struct cleanup_groups_state *state; - static const char *attrs[] = { SYSDB_NAME, NULL }; - time_t now = time(NULL); - char *subfilter; - - req = tevent_req_create(memctx, &state, struct cleanup_groups_state); - if (!req) { - return NULL; - } - - state->ev = ev; - state->ctx = ctx; - state->sysdb = ctx->be->sysdb; - state->domain = ctx->be->domain; - state->msgs = NULL; - state->count = 0; - state->cur = 0; - - subfilter = talloc_asprintf(state, "(&(!(%s=0))(%s<=%ld))", - SYSDB_CACHE_EXPIRE, - SYSDB_CACHE_EXPIRE, (long)now); - if (!subfilter) { - DEBUG(2, ("Failed to build filter\n")); - talloc_zfree(req); - return NULL; - } - - subreq = sysdb_search_groups_send(state, state->ev, - state->sysdb, NULL, - state->domain, subfilter, attrs); - if (!subreq) { - DEBUG(2, ("Failed to send entry search\n")); - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, cleanup_groups_process, req); - - return req; -} - -static void cleanup_groups_process(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_groups_state *state = tevent_req_data(req, - struct cleanup_groups_state); - int ret; - - ret = sysdb_search_groups_recv(subreq, state, &state->count, &state->msgs); - talloc_zfree(subreq); - if (ret) { - if (ret == ENOENT) { - tevent_req_done(req); - return; - } - tevent_req_error(req, ret); - return; - } - - DEBUG(4, ("Found %d expired group entries!\n", state->count)); - - if (state->count == 0) { - tevent_req_done(req); - } - - cleanup_groups_update(req); -} - -static void cleanup_groups_update(struct tevent_req *req) -{ - struct tevent_req *subreq; - struct cleanup_groups_state *state = tevent_req_data(req, - struct cleanup_groups_state); - const char *str; - - str = ldb_msg_find_attr_as_string(state->msgs[state->cur], - SYSDB_NAME, NULL); - if (!str) { - DEBUG(2, ("Entry %s has no Name Attribute ?!?\n", - ldb_dn_get_linearized(state->msgs[state->cur]->dn))); - tevent_req_error(req, EFAULT); - return; - } - - subreq = groups_get_send(state, state->ev, state->ctx, - str, BE_FILTER_NAME, BE_ATTR_CORE); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, cleanup_groups_up_done, req); -} - -static void cleanup_groups_up_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cleanup_groups_state *state = tevent_req_data(req, - struct cleanup_groups_state); - int ret; - - ret = groups_get_recv(subreq); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("User check returned: %d(%s)\n", - ret, strerror(ret))); - } - - state->cur++; - if (state->cur < state->count) { - cleanup_groups_update(req); - return; - } - - tevent_req_done(req); -} - |