diff options
author | Pavel Březina <pbrezina@redhat.com> | 2012-05-13 21:45:49 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-06-29 11:37:18 -0400 |
commit | fc99ea70d735fa4094c450dd52c3503cb23e5f59 (patch) | |
tree | 4b6740f78c954e61a79e76474dc533be4e20c9b1 | |
parent | 4684d427e7e10642ceff62128c3d22db87872c4c (diff) | |
download | sssd-fc99ea70d735fa4094c450dd52c3503cb23e5f59.tar.gz sssd-fc99ea70d735fa4094c450dd52c3503cb23e5f59.tar.bz2 sssd-fc99ea70d735fa4094c450dd52c3503cb23e5f59.zip |
sudo ldap provider: notify responder when an expired rule has been deleted
When an expired rule is not present on the server server during specific rule
refresh, the provider will notify the sudo responder that it has been deleted.
Because there is a high probability that some other rules were deleted from
the server as well, we want to remove them from sysdb as soon as possible.
Once the responder is notified, it will schedule an out of band full refresh.
This is issued by responder, because we already have a mechanism that
prohibits creation of similar request (i.e. once the OOB full refresh is
scheduled, there won't be another).
The notification is done by returning:
DP error = DP_ERR_OK, error = ENOENT
-rw-r--r-- | src/providers/ldap/sdap_sudo.c | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c index 9d735a4a..15fb5156 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -46,6 +46,12 @@ static int sdap_sudo_full_refresh_recv(struct tevent_req *req, int *dp_error, int *error); +struct sdap_sudo_rules_refresh_state { + size_t num_rules; + int dp_error; + int error; +}; + static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sdap_options *opts, @@ -56,6 +62,8 @@ static int sdap_sudo_rules_refresh_recv(struct tevent_req *req, int *dp_error, int *error); +static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq); + struct sdap_sudo_smart_refresh_state { struct tevent_req *subreq; struct sdap_id_ctx *id_ctx; @@ -435,6 +443,8 @@ static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, char **rules) { struct tevent_req *req = NULL; + struct tevent_req *subreq = NULL; + struct sdap_sudo_rules_refresh_state *state = NULL; TALLOC_CTX *tmp_ctx = NULL; char *ldap_filter = NULL; char *sysdb_filter = NULL; @@ -452,6 +462,12 @@ static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, return NULL; } + req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_rules_refresh_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); + return NULL; + } + ldap_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */ sysdb_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */ @@ -460,46 +476,62 @@ static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, for (i = 0; rules[i] != NULL; i++) { ret = sss_filter_sanitize(tmp_ctx, rules[i], &safe_rule); if (ret != EOK) { - goto done; + ret = ENOMEM; + goto immediately; } ldap_filter = talloc_asprintf_append_buffer(ldap_filter, "(%s=%s)", opts->sudorule_map[SDAP_AT_SUDO_NAME].name, safe_rule); if (ldap_filter == NULL) { - goto done; + ret = ENOMEM; + goto immediately; } sysdb_filter = talloc_asprintf_append_buffer(sysdb_filter, "(%s=%s)", SYSDB_SUDO_CACHE_AT_CN, safe_rule); if (sysdb_filter == NULL) { - goto done; + ret = ENOMEM; + goto immediately; } } + state->num_rules = i; + ldap_filter = talloc_asprintf(tmp_ctx, "(&"SDAP_SUDO_FILTER_CLASS"(|%s))", opts->sudorule_map[SDAP_OC_SUDORULE].name, ldap_filter); if (ldap_filter == NULL) { - goto done; + ret = ENOMEM; + goto immediately; } sysdb_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|%s))", SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_AT_OC, sysdb_filter); if (sysdb_filter == NULL) { - goto done; + ret = ENOMEM; + goto immediately; } - req = sdap_sudo_refresh_send(mem_ctx, be_ctx, opts, conn_cache, - ldap_filter, sysdb_filter); - if (req == NULL) { - goto done; + subreq = sdap_sudo_refresh_send(req, be_ctx, opts, conn_cache, + ldap_filter, sysdb_filter); + if (subreq == NULL) { + ret = ENOMEM; + goto immediately; } -done: + tevent_req_set_callback(subreq, sdap_sudo_rules_refresh_done, req); + +immediately: talloc_free(tmp_ctx); + + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, be_ctx->ev); + } + return req; } @@ -507,7 +539,40 @@ static int sdap_sudo_rules_refresh_recv(struct tevent_req *req, int *dp_error, int *error) { - return sdap_sudo_refresh_recv(req, req, dp_error, error, NULL, NULL); + struct sdap_sudo_rules_refresh_state *state = NULL; + state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *dp_error = state->dp_error; + *error = state->error; + + return EOK; +} + +static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq) +{ + struct tevent_req *req = NULL; + struct sdap_sudo_rules_refresh_state *state = NULL; + size_t downloaded_rules_num; + int ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state); + + ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error, + NULL, &downloaded_rules_num); + talloc_zfree(subreq); + if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) { + tevent_req_error(req, ret); + return; + } + + if (downloaded_rules_num != state->num_rules) { + state->error = ENOENT; + } + + tevent_req_done(req); } /* issue smart refresh of sudo rules */ |