2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina Pavel Březina <pbrezina@redhat.com>
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina Jakub Hrozek <jhrozek@redhat.com>
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina Copyright (C) 2011 Red Hat
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina This program is free software; you can redistribute it and/or modify
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina it under the terms of the GNU General Public License as published by
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina the Free Software Foundation; either version 3 of the License, or
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina (at your option) any later version.
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina This program is distributed in the hope that it will be useful,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina GNU General Public License for more details.
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina You should have received a copy of the GNU General Public License
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
4169fb26ea2ff93c19ecdad6e09382732ea5deebPavel Březina#include "responder/common/cache_req/cache_req.h"
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinasudo_order_cmp(const void *a, const void *b, bool lower_wins)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Wrong data?\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina ret = sysdb_attrs_get_uint32_t(r1, SYSDB_SUDO_CACHE_AT_ORDER, &o1);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina /* man sudoers-ldap: If the sudoOrder attribute is not present,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina * a value of 0 is assumed */
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_OP_FAILURE, "Cannot get sudoOrder value\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina ret = sysdb_attrs_get_uint32_t(r2, SYSDB_SUDO_CACHE_AT_ORDER, &o2);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina /* man sudoers-ldap: If the sudoOrder attribute is not present,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina * a value of 0 is assumed */
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_OP_FAILURE, "Cannot get sudoOrder value\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina /* The lowest value takes priority. Original wrong SSSD behaviour. */
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina /* The higher value takes priority. Standard LDAP behaviour. */
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinasudo_order_low_cmp_fn(const void *a, const void *b)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina return sudo_order_cmp(a, b, true);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinasudo_order_high_cmp_fn(const void *a, const void *b)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina return sudo_order_cmp(a, b, false);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinasort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool lower_wins)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Sorting rules with lower-wins logic\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina qsort(rules, count, sizeof(struct sysdb_attrs *),
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Sorting rules with higher-wins logic\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina qsort(rules, count, sizeof(struct sysdb_attrs *),
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic errno_t sudosrv_query_cache(TALLOC_CTX *mem_ctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina const char **attrs,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_FUNC_DATA, "Searching sysdb with [%s]\n", filter);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina /* rules are stored inside parent domain tree */
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina ret = sysdb_search_custom(tmp_ctx, domain, filter, SUDORULE_SUBDIR,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up SUDO rules\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &rules);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "Could not convert ldb message to sysdb_attrs\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic errno_t sudosrv_expired_rules(TALLOC_CTX *mem_ctx,
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina filter = sysdb_sudo_filter_expired(NULL, username, groups, uid);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina ret = sudosrv_query_cache(mem_ctx, domain, attrs, filter,
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březinastatic errno_t sudosrv_cached_rules_by_user(TALLOC_CTX *mem_ctx,
dee665060ba71ff61ad223e755ae61441118fbbaJakub Hrozek filter = sysdb_sudo_filter_user(tmp_ctx, username, groupnames, orig_uid);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina ret = sudosrv_query_cache(tmp_ctx, domain, attrs, filter,
dee665060ba71ff61ad223e755ae61441118fbbaJakub Hrozek val = talloc_asprintf(tmp_ctx, "#%"SPRIuid, cli_uid);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina /* Add sudoUser: #uid to prevent conflicts with fqnames. */
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Replacing sudoUser attribute with "
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina for (i = 0; i < num_rules; i++) {
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina ret = sysdb_attrs_add_string(rules[i], SYSDB_SUDO_CACHE_AT_USER, val);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to alter sudoUser attribute "
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březinastatic errno_t sudosrv_cached_rules_by_ng(TALLOC_CTX *mem_ctx,
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina filter = sysdb_sudo_filter_netgroups(NULL, username, groupnames, uid);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina ret = sudosrv_query_cache(mem_ctx, domain, attrs, filter,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic errno_t sudosrv_cached_rules(TALLOC_CTX *mem_ctx,
dee665060ba71ff61ad223e755ae61441118fbbaJakub Hrozek ret = sudosrv_cached_rules_by_user(tmp_ctx, domain,
dee665060ba71ff61ad223e755ae61441118fbbaJakub Hrozek ret = sudosrv_cached_rules_by_ng(tmp_ctx, domain,
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina rules = talloc_array(tmp_ctx, struct sysdb_attrs *, num_rules);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina for (i = 0; i < num_user_rules; rule_iter++, i++) {
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina rules[rule_iter] = talloc_steal(rules, user_rules[i]);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina for (i = 0; i < num_ng_rules; rule_iter++, i++) {
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina rules[rule_iter] = talloc_steal(rules, ng_rules[i]);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina ret = sort_sudo_rules(rules, num_rules, inverse_order);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina DEBUG(SSSDBG_OP_FAILURE, "Could not sort rules by sudoOrder\n");
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březinastatic errno_t sudosrv_cached_defaults(TALLOC_CTX *mem_ctx,
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina ret = sudosrv_query_cache(mem_ctx, domain, attrs, filter,
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březinastatic errno_t sudosrv_fetch_rules(TALLOC_CTX *mem_ctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Retrieving rules for [%s@%s]\n",
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Retrieving default options for [%s@%s]\n",
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina ret = sudosrv_cached_defaults(mem_ctx, domain, &rules, &num_rules);
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve %s [%d]: %s\n",
61913b8f0d1ba54d82640500d7486fac5f72b030Pavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Returning %u %s for [%s@%s]\n",
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina num_rules, debug_name, username, domain->name);
895ba2c346beb7e55d43be3d0c7f54fd287faa74Pavel Březinasudosrv_dp_oob_req_done(struct tevent_req *req)
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Out of band refresh finished\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic void sudosrv_refresh_rules_done(struct tevent_req *subreq);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic struct tevent_req *
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinasudosrv_refresh_rules_send(TALLOC_CTX *mem_ctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina ret = sudosrv_expired_rules(state, domain, uid, username, groups,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "Unable to retrieve expired sudo rules [%d]: %s\n",
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "No expired rules were found for [%s@%s].\n",
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_TRACE_INTERNAL, "Refreshing %d expired rules of [%s@%s]\n",
a5f300adf19ec9c3087c62bd93a5175db799687aPavel Březina "Rules threshold [%d] is reached, performing full refresh "
a5f300adf19ec9c3087c62bd93a5175db799687aPavel Březina subreq = sss_dp_get_sudoers_send(state, rctx, domain, false,
a5f300adf19ec9c3087c62bd93a5175db799687aPavel Březina subreq = sss_dp_get_sudoers_send(state, rctx, domain, false,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina tevent_req_set_callback(subreq, sudosrv_refresh_rules_done, req);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic void sudosrv_refresh_rules_done(struct tevent_req *subreq)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina state = tevent_req_data(req, struct sudosrv_refresh_rules_state);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina ret = sss_dp_get_sudoers_recv(state, subreq, &err_maj, &err_min, &err_msg);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "Unable to get information from Data Provider, "
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "Error: %u, %u, %s\n",
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina (unsigned int)err_maj, (unsigned int)err_min, err_msg);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "Some expired rules were removed from the server, scheduling "
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "full refresh out of band\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina subreq = sss_dp_get_sudoers_send(state->rctx, state->rctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_MINOR_FAILURE, "Cannot issue DP request.\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina tevent_req_set_callback(subreq, sudosrv_dp_oob_req_done, NULL);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic errno_t sudosrv_refresh_rules_recv(struct tevent_req *req)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic void sudosrv_get_rules_initgr_done(struct tevent_req *subreq);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic void sudosrv_get_rules_done(struct tevent_req *subreq);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastruct tevent_req *sudosrv_get_rules_send(TALLOC_CTX *mem_ctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina req = tevent_req_create(mem_ctx, &state, struct sudosrv_get_rules_state);
c02b8482375837b57cb618ed56d4bede0e006d9dPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina state->inverse_order = sudo_ctx->inverse_order;
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_TRACE_FUNC, "Running initgroups for [%s]\n", username);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina subreq = cache_req_initgr_by_name_send(state, ev, sudo_ctx->rctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina tevent_req_set_callback(subreq, sudosrv_get_rules_initgr_done, req);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic void sudosrv_get_rules_initgr_done(struct tevent_req *subreq)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina state = tevent_req_data(req, struct sudosrv_get_rules_state);
b206e1abb7f6ea373d12537b3338552aed6b656dPavel Březina ret = cache_req_initgr_by_name_recv(state, subreq, &result);
b206e1abb7f6ea373d12537b3338552aed6b656dPavel Březina state->username = talloc_steal(state, result->lookup_name);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina ret = sysdb_get_sudo_user_info(state, state->domain, state->username,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain user groups [%d]: %s\n",
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina subreq = sudosrv_refresh_rules_send(state, state->ev, state->rctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina tevent_req_set_callback(subreq, sudosrv_get_rules_done, req);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinastatic void sudosrv_get_rules_done(struct tevent_req *subreq)
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina req = tevent_req_callback_data(subreq, struct tevent_req);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina state = tevent_req_data(req, struct sudosrv_get_rules_state);
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "Unable to refresh expired rules, we will return what is "
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina "in cache.\n");
dee665060ba71ff61ad223e755ae61441118fbbaJakub Hrozek ret = sudosrv_fetch_rules(state, state->type, state->domain,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březinaerrno_t sudosrv_get_rules_recv(TALLOC_CTX *mem_ctx,
b3ca35780617b2e5a7637f9888b089e8e26a4e8cPavel Březina state = tevent_req_data(req, struct sudosrv_get_rules_state);