From 261bc18d8d1d2db0531395beb583da15088bd297 Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Fri, 19 Jul 2013 12:26:15 +0200 Subject: providers: refresh expired netgroups https://fedorahosted.org/sssd/ticket/1713 --- Makefile.am | 1 + src/providers/ad/ad_init.c | 10 +++ src/providers/dp_refresh.c | 12 ++- src/providers/ipa/ipa_init.c | 10 +++ src/providers/ldap/ldap_common.h | 8 ++ src/providers/ldap/ldap_init.c | 11 +++ src/providers/ldap/sdap_refresh.c | 160 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 src/providers/ldap/sdap_refresh.c diff --git a/Makefile.am b/Makefile.am index 539eae667..288de2319 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1291,6 +1291,7 @@ libsss_ldap_common_la_SOURCES = \ src/providers/ldap/sdap_idmap.h \ src/providers/ldap/sdap_range.c \ src/providers/ldap/sdap_reinit.c \ + src/providers/ldap/sdap_refresh.c \ src/providers/ldap/sdap.c if BUILD_SUDO diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c index 2add74a20..1e7d9be0e 100644 --- a/src/providers/ad/ad_init.c +++ b/src/providers/ad/ad_init.c @@ -175,6 +175,16 @@ sssm_ad_id_init(struct be_ctx *bectx, goto done; } + /* setup periodical refresh of expired records */ + ret = be_refresh_add_cb(bectx->refresh_ctx, BE_REFRESH_TYPE_NETGROUPS, + sdap_refresh_netgroups_send, + sdap_refresh_netgroups_recv, + sdap_ctx); + if (ret != EOK && ret != EEXIST) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Periodical refresh of netgroups " + "will not work [%d]: %s\n", ret, strerror(ret))); + } + *ops = &ad_id_ops; *pvt_data = ad_ctx; diff --git a/src/providers/dp_refresh.c b/src/providers/dp_refresh.c index e6a9269ae..6a7a9b52b 100644 --- a/src/providers/dp_refresh.c +++ b/src/providers/dp_refresh.c @@ -30,6 +30,7 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, + time_t period, const char *objectclass, struct ldb_dn *base_dn, const char *attr, @@ -51,7 +52,7 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx, } filter = talloc_asprintf(tmp_ctx, "(&(%s<=%lld))", - SYSDB_CACHE_EXPIRE, (long long) now); + SYSDB_CACHE_EXPIRE, (long long) now + period); if (filter == NULL) { ret = ENOMEM; goto done; @@ -89,6 +90,7 @@ done: static errno_t be_refresh_get_netgroups(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, + time_t period, char ***_values) { struct ldb_dn *base_dn = NULL; @@ -99,7 +101,7 @@ static errno_t be_refresh_get_netgroups(TALLOC_CTX *mem_ctx, return ENOMEM; } - ret = be_refresh_get_values(mem_ctx, domain, SYSDB_NETGROUP_CLASS, + ret = be_refresh_get_values(mem_ctx, domain, period, SYSDB_NETGROUP_CLASS, base_dn, SYSDB_NAME, _values); talloc_free(base_dn); @@ -109,6 +111,7 @@ static errno_t be_refresh_get_netgroups(TALLOC_CTX *mem_ctx, typedef errno_t (*be_refresh_get_values_t)(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, + time_t period, char ***_values); @@ -168,6 +171,7 @@ struct be_refresh_state { struct be_refresh_ctx *ctx; struct be_refresh_cb *cb; enum be_refresh_type index; + time_t period; }; static errno_t be_refresh_step(struct tevent_req *req); @@ -192,6 +196,7 @@ struct tevent_req *be_refresh_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->be_ctx = be_ctx; + state->period = be_ptask_get_period(be_ptask); state->ctx = talloc_get_type(pvt, struct be_refresh_ctx); if (state->ctx == NULL) { ret = EINVAL; @@ -246,7 +251,8 @@ static errno_t be_refresh_step(struct tevent_req *req) goto done; } - ret = state->cb->get_values(state, state->be_ctx->domain, &values); + ret = state->cb->get_values(state, state->be_ctx->domain, state->period, + &values); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to obtain DN list [%d]: %s\n", ret, strerror(ret))); diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index 4be6be64e..8bdc50c04 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -207,6 +207,16 @@ int sssm_ipa_id_init(struct be_ctx *bectx, goto done; } + /* setup periodical refresh of expired records */ + ret = be_refresh_add_cb(bectx->refresh_ctx, BE_REFRESH_TYPE_NETGROUPS, + sdap_refresh_netgroups_send, + sdap_refresh_netgroups_recv, + sdap_ctx); + if (ret != EOK && ret != EEXIST) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Periodical refresh of netgroups " + "will not work [%d]: %s\n", ret, strerror(ret))); + } + *ops = &ipa_id_ops; *pvt_data = ipa_ctx; ret = EOK; diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 86079fa6a..05dd6c84a 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -235,4 +235,12 @@ sdap_set_sasl_options(struct sdap_options *id_opts, char *default_realm, const char *keytab_path); +struct tevent_req *sdap_refresh_netgroups_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + char **names, + void *pvt); + +errno_t sdap_refresh_netgroups_recv(struct tevent_req *req); + #endif /* _LDAP_COMMON_H_ */ diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index b8e5ee3aa..976448194 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -29,6 +29,7 @@ #include "providers/ldap/sdap_sudo.h" #include "providers/ldap/sdap_autofs.h" #include "providers/ldap/sdap_idmap.h" +#include "providers/dp_refresh.h" static void sdap_shutdown(struct be_req *req); @@ -172,6 +173,16 @@ int sssm_ldap_id_init(struct be_ctx *bectx, goto done; } + /* setup periodical refresh of expired records */ + ret = be_refresh_add_cb(bectx->refresh_ctx, BE_REFRESH_TYPE_NETGROUPS, + sdap_refresh_netgroups_send, + sdap_refresh_netgroups_recv, + ctx); + if (ret != EOK && ret != EEXIST) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Periodical refresh of netgroups " + "will not work [%d]: %s\n", ret, strerror(ret))); + } + *ops = &sdap_id_ops; *pvt_data = ctx; ret = EOK; diff --git a/src/providers/ldap/sdap_refresh.c b/src/providers/ldap/sdap_refresh.c new file mode 100644 index 000000000..e183f7027 --- /dev/null +++ b/src/providers/ldap/sdap_refresh.c @@ -0,0 +1,160 @@ +/* + Authors: + Pavel B??ezina + + Copyright (C) 2013 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 . +*/ + +#include +#include + +#include "providers/ldap/sdap.h" +#include "providers/ldap/ldap_common.h" + +struct sdap_refresh_netgroups_state { + struct tevent_context *ev; + struct sdap_id_ctx *id_ctx; + char **names; + size_t index; +}; + +static errno_t sdap_refresh_netgroups_step(struct tevent_req *req); +static void sdap_refresh_netgroups_done(struct tevent_req *subreq); + +struct tevent_req *sdap_refresh_netgroups_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + char **names, + void *pvt) +{ + struct sdap_refresh_netgroups_state *state = NULL; + struct tevent_req *req = NULL; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sdap_refresh_netgroups_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); + return NULL; + } + + state->ev = ev; + state->id_ctx = talloc_get_type(pvt, struct sdap_id_ctx); + state->names = names; + state->index = 0; + + if (names == NULL) { + ret = EOK; + goto immediately; + } + + ret = sdap_refresh_netgroups_step(req); + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, ("Nothing to refresh\n")); + goto immediately; + } else if (ret != EAGAIN) { + DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_refresh_netgroups_step() failed " + "[%d]: %s\n", ret, 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 sdap_refresh_netgroups_step(struct tevent_req *req) +{ + struct sdap_refresh_netgroups_state *state = NULL; + struct tevent_req *subreq = NULL; + const char *name = NULL; + errno_t ret; + + state = tevent_req_data(req, struct sdap_refresh_netgroups_state); + + if (state->names == NULL) { + ret = EOK; + goto done; + } + + name = state->names[state->index]; + if (name == NULL) { + ret = EOK; + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, ("Issuing refresh of netgroup %s\n", name)); + + subreq = ldap_netgroup_get_send(state, state->ev, state->id_ctx, name); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, sdap_refresh_netgroups_done, req); + + state->index++; + ret = EAGAIN; + +done: + return ret; +} + +static void sdap_refresh_netgroups_done(struct tevent_req *subreq) +{ + struct tevent_req *req = NULL; + errno_t dp_error; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + + ret = ldap_netgroup_get_recv(subreq, &dp_error); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to refresh netgroup [dp_error: %d, " + "sdap_ret: %d, errno: %d]: %s\n", + dp_error, ret, strerror(ret))); + goto done; + } + + ret = sdap_refresh_netgroups_step(req); + if (ret == EAGAIN) { + return; + } + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t sdap_refresh_netgroups_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} -- cgit