be_refresh.c revision cc2d77d5218c188119fa954c856e858cbde76947
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder/*
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder Authors:
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder Pavel Březina <pbrezina@redhat.com>
75a6279dbae159d018ef812185416cf6df386c10Till Mossakowski
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder Copyright (C) 2013 Red Hat
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder This program is free software; you can redistribute it and/or modify
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder it under the terms of the GNU General Public License as published by
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder the Free Software Foundation; either version 3 of the License, or
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder (at your option) any later version.
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder This program is distributed in the hope that it will be useful,
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder but WITHOUT ANY WARRANTY; without even the implied warranty of
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder GNU General Public License for more details.
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder
fc7df539e6d41b050161ed8f9ae6e444b1b5ab14Christian Maeder You should have received a copy of the GNU General Public License
ee9eddfa6953868fd6fbaff0d9ff68675a13675aChristian Maeder along with this program. If not, see <http://www.gnu.org/licenses/>.
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder*/
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder#include <tevent.h>
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder#include <talloc.h>
ee9eddfa6953868fd6fbaff0d9ff68675a13675aChristian Maeder#include <time.h>
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder#include <ldb.h>
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder
33a5d53a412ba0a4e5847f7538d6da2e22bd116cChristian Maeder#include "providers/backend.h"
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder#include "providers/be_ptask.h"
e774ab5733a1d673b123b0e63b14dd533e6fd4fcChristian Maeder#include "providers/be_refresh.h"
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder#include "util/util_errors.h"
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder#include "db/sysdb.h"
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maederstatic errno_t be_refresh_get_values_ex(TALLOC_CTX *mem_ctx,
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder struct sss_domain_info *domain,
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder time_t period,
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder const char *objectclass,
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder struct ldb_dn *base_dn,
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder const char *attr,
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder char ***_values)
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder{
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder TALLOC_CTX *tmp_ctx = NULL;
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder const char *attrs[] = {attr, NULL};
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder const char *filter = NULL;
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder char **values = NULL;
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder struct ldb_message **msgs = NULL;
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder struct sysdb_attrs **records = NULL;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder size_t count;
38775225cf810f5895cc03b4acbcfe8f84f2513aChristian Maeder time_t now = time(NULL);
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder errno_t ret;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder tmp_ctx = talloc_new(NULL);
fc8c6570c7b4ee13f375eb607bed2290438573bfChristian Maeder if (tmp_ctx == NULL) {
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder return ENOMEM;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder }
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder filter = talloc_asprintf(tmp_ctx, "(&(%s<=%lld))",
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder SYSDB_CACHE_EXPIRE, (long long) now + period);
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder if (filter == NULL) {
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder ret = ENOMEM;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder goto done;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder }
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder ret = sysdb_search_entry(tmp_ctx, domain->sysdb, base_dn,
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder LDB_SCOPE_SUBTREE, filter, attrs,
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder &count, &msgs);
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder if (ret == ENOENT) {
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder count = 0;
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder } else if (ret != EOK) {
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder goto done;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder }
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &records);
fc8c6570c7b4ee13f375eb607bed2290438573bfChristian Maeder if (ret != EOK) {
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE,
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder "Could not convert ldb message to sysdb_attrs\n");
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder goto done;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder }
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder ret = sysdb_attrs_to_list(tmp_ctx, records, count, attr, &values);
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder if (ret != EOK) {
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder goto done;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder }
715ffaf874309df081d1e1cd8e05073fc1227729Christian Maeder
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder *_values = talloc_steal(mem_ctx, values);
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder ret = EOK;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maederdone:
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder talloc_free(tmp_ctx);
836e72a3c413366ba9801726f3b249c7791cb9caChristian Maeder
836e72a3c413366ba9801726f3b249c7791cb9caChristian Maeder return ret;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder}
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maederstatic errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx,
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder enum be_refresh_type type,
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder struct sss_domain_info *domain,
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder time_t period,
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder char ***_values)
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder{
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder struct ldb_dn *base_dn = NULL;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder const char *class = NULL;
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder errno_t ret;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder switch (type) {
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder case BE_REFRESH_TYPE_USERS:
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder base_dn = sysdb_user_base_dn(mem_ctx, domain);
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder class = SYSDB_USER_CLASS;
797f811e57952d59e73b8cd03b667eef276db972Christian Maeder break;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder case BE_REFRESH_TYPE_GROUPS:
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder base_dn = sysdb_group_base_dn(mem_ctx, domain);
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder class = SYSDB_GROUP_CLASS;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder break;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder case BE_REFRESH_TYPE_NETGROUPS:
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder base_dn = sysdb_netgroup_base_dn(mem_ctx, domain);
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder class = SYSDB_NETGROUP_CLASS;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder break;
bbae6e6ca0de7f2ffbb44d2c8da179f2b717237fChristian Maeder case BE_REFRESH_TYPE_SENTINEL:
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder return ERR_INTERNAL;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder break;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder }
e1839fb37a3a2ccd457464cb0dcc5efd466dbe22Christian Maeder
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder if (base_dn == NULL) {
e774ab5733a1d673b123b0e63b14dd533e6fd4fcChristian Maeder return ENOMEM;
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder }
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder ret = be_refresh_get_values_ex(mem_ctx, domain, period, class,
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder base_dn, SYSDB_NAME, _values);
1738d16957389457347bee85075d3d33d002158fChristian Maeder
1738d16957389457347bee85075d3d33d002158fChristian Maeder talloc_free(base_dn);
1738d16957389457347bee85075d3d33d002158fChristian Maeder return ret;
33a5d53a412ba0a4e5847f7538d6da2e22bd116cChristian Maeder}
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maederstruct be_refresh_cb {
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder const char *name;
0f67ca7b0c738a28f6688ba6e96d44d7c14af611Christian Maeder bool enabled;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder be_refresh_send_t send_fn;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder be_refresh_recv_t recv_fn;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder void *pvt;
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder};
struct be_refresh_ctx {
struct be_refresh_cb callbacks[BE_REFRESH_TYPE_SENTINEL];
};
struct be_refresh_ctx *be_refresh_ctx_init(TALLOC_CTX *mem_ctx)
{
struct be_refresh_ctx *ctx = NULL;
ctx = talloc_zero(mem_ctx, struct be_refresh_ctx);
if (ctx == NULL) {
return NULL;
}
ctx->callbacks[BE_REFRESH_TYPE_USERS].name = "users";
ctx->callbacks[BE_REFRESH_TYPE_GROUPS].name = "groups";
ctx->callbacks[BE_REFRESH_TYPE_NETGROUPS].name = "netgroups";
return ctx;
}
errno_t be_refresh_add_cb(struct be_refresh_ctx *ctx,
enum be_refresh_type type,
be_refresh_send_t send_fn,
be_refresh_recv_t recv_fn,
void *pvt)
{
if (ctx == NULL || send_fn == NULL || recv_fn == NULL
|| type >= BE_REFRESH_TYPE_SENTINEL) {
return EINVAL;
}
if (ctx->callbacks[type].enabled) {
return EEXIST;
}
ctx->callbacks[type].enabled = true;
ctx->callbacks[type].send_fn = send_fn;
ctx->callbacks[type].recv_fn = recv_fn;
ctx->callbacks[type].pvt = pvt;
return EOK;
}
struct be_refresh_state {
struct tevent_context *ev;
struct be_ctx *be_ctx;
struct be_refresh_ctx *ctx;
struct be_refresh_cb *cb;
struct sss_domain_info *domain;
enum be_refresh_type index;
time_t period;
};
static errno_t be_refresh_step(struct tevent_req *req);
static void be_refresh_done(struct tevent_req *subreq);
struct tevent_req *be_refresh_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct be_ctx *be_ctx,
struct be_ptask *be_ptask,
void *pvt)
{
struct be_refresh_state *state = NULL;
struct tevent_req *req = NULL;
errno_t ret;
req = tevent_req_create(mem_ctx, &state,
struct be_refresh_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
return NULL;
}
state->ev = ev;
state->be_ctx = be_ctx;
state->domain = be_ctx->domain;
state->period = be_ptask_get_period(be_ptask);
state->ctx = talloc_get_type(pvt, struct be_refresh_ctx);
if (state->ctx == NULL) {
ret = EINVAL;
goto immediately;
}
ret = be_refresh_step(req);
if (ret == EOK) {
goto immediately;
} else if (ret != EAGAIN) {
DEBUG(SSSDBG_CRIT_FAILURE, "be_refresh_step() failed [%d]: %s\n",
ret, sss_strerror(ret));
goto immediately;
}
return req;
immediately:
if (ret == EOK) {
tevent_req_done(req);
} else {
tevent_req_error(req, ret);
}
tevent_req_post(req, ev);
return req;
}
static errno_t be_refresh_step(struct tevent_req *req)
{
struct be_refresh_state *state = NULL;
struct tevent_req *subreq = NULL;
char **values = NULL;
errno_t ret;
state = tevent_req_data(req, struct be_refresh_state);
while (state->domain != NULL) {
/* find first enabled callback */
state->cb = &state->ctx->callbacks[state->index];
while (state->index != BE_REFRESH_TYPE_SENTINEL && !state->cb->enabled) {
state->index++;
state->cb = &state->ctx->callbacks[state->index];
}
/* if not found than continue with next domain */
if (state->index == BE_REFRESH_TYPE_SENTINEL) {
state->domain = get_next_domain(state->domain, 0);
continue;
}
if (state->cb->send_fn == NULL || state->cb->recv_fn == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid parameters!\n");
ret = ERR_INTERNAL;
goto done;
}
ret = be_refresh_get_values(state, state->index, state->domain,
state->period, &values);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain DN list [%d]: %s\n",
ret, sss_strerror(ret));
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Refreshing %s in domain %s\n",
state->cb->name, state->domain->name);
subreq = state->cb->send_fn(state, state->ev, state->be_ctx,
state->domain, values, state->cb->pvt);
if (subreq == NULL) {
ret = ENOMEM;
goto done;
}
/* make the list disappear with subreq */
talloc_steal(subreq, values);
tevent_req_set_callback(subreq, be_refresh_done, req);
state->index++;
ret = EAGAIN;
goto done;
}
ret = EOK;
done:
if (ret != EOK && ret != EAGAIN) {
talloc_free(values);
}
return ret;
}
static void be_refresh_done(struct tevent_req *subreq)
{
struct be_refresh_state *state = NULL;
struct tevent_req *req = NULL;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct be_refresh_state);
ret = state->cb->recv_fn(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
goto done;
}
ret = be_refresh_step(req);
if (ret == EAGAIN) {
return;
}
done:
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
tevent_req_done(req);
}
errno_t be_refresh_recv(struct tevent_req *req)
{
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}