sudosrv_get_sudorules.c revision 41ef946f3f74a46b9e26118116e4811e259b30ef
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/>.
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinaerrno_t sudosrv_get_sudorules(struct sudo_dom_ctx *dctx)
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Looking up the user info from Data Provider\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Error looking up user information [%d]: %s\n", ret, strerror(ret)));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* OK, got the user from cache. Try to get the rules. */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Looking up the sudo rules from Data Provider\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Error looking up sudo rules [%d]: %s\n", ret, strerror(ret)));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic void sudosrv_dp_send_acct_req_done(struct tevent_req *req);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic void sudosrv_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx;
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* if it is a domainless search, skip domains that require fully
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek * qualified names instead */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek while (dom && cmd_ctx->check_next && dom->fqnames) {
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek if (!dom) break;
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* make sure to update the dctx if we changed domain */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_FUNC_DATA, ("Requesting info about [%s@%s]\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_get_ctx_from_list(cli_ctx->rctx->db_list,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("sysdb context not found for this domain!\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_getpwnam(dctx, sysdb, cmd_ctx->username, &dctx->user);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Failed to make request to our cache!\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("getpwnam call returned more than one result !?!\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek if (dctx->user->count == 0 && !dctx->check_provider) {
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* if a multidomain search, try with next */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek if (dom) continue;
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE, ("No results for getpwnam call\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* One result found, check cache expiry */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek cache_expire = ldb_msg_find_attr_as_uint64(dctx->user->msgs[0],
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* If cache miss and we haven't checked DP yet OR the entry is
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek * outdated, go to DP */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek if ((dctx->user->count == 0 && dctx->check_provider) ||
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Out of memory sending data provider request\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek cb_ctx = talloc_zero(cli_ctx, struct dp_callback_ctx);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek cb_ctx->callback = sudosrv_check_user_dp_callback;
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek tevent_req_set_callback(dpreq, sudosrv_dp_send_acct_req_done, cb_ctx);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* tell caller we are in an async call */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, ("Returning info for user [%s@%s]\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic void sudosrv_dp_send_acct_req_done(struct tevent_req *req)
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek tevent_req_callback_data(req, struct dp_callback_ctx);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sss_dp_get_account_recv(cb_ctx->mem_ctx, req,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Fatal error, killing connection!\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic void sudosrv_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek struct sudo_dom_ctx *dctx = talloc_get_type(ptr, struct sudo_dom_ctx);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Unable to get information from Data Provider\n"
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek "Error: %u, %u, %s\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek (unsigned int)err_maj, (unsigned int)err_min, err_msg));
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek ("Data Provider returned, check the cache again\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Could not look up the user [%d]: %s\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, ("Looking up sudo rules..\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Error getting sudo rules [%d]: %s\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx);
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozeksudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
c47e9d522f0d87259e5074ea643daaa3dfcb8d92Pavel Březinaerrno_t sudosrv_get_rules(struct sudo_dom_ctx *dctx)
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina DEBUG(SSSDBG_TRACE_FUNC, ("getting rules for %s\n",
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina cmd_ctx->username ? cmd_ctx->username : "default options"));
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek dpreq = sss_dp_get_sudoers_send(cmd_ctx->cli_ctx,
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek ("Cannot issue DP request.\n"));
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek cb_ctx = talloc_zero(dctx, struct dp_callback_ctx);
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek cb_ctx->callback = sudosrv_get_sudorules_dp_callback;
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek tevent_req_set_callback(dpreq, sudosrv_dp_req_done, cb_ctx);
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek tevent_req_callback_data(req, struct dp_callback_ctx);
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek talloc_get_type(cb_ctx->ptr, struct sudo_dom_ctx);
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek ret = sss_dp_get_sudoers_recv(cb_ctx->mem_ctx, req,
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, ("Fatal error, killing connection!\n"));
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek cb_ctx->callback(err_maj, err_min, err_msg, cb_ctx->ptr);
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozeksudosrv_get_sudorules_dp_callback(uint16_t err_maj, uint32_t err_min,
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek ("Unable to get information from Data Provider\n"
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek "Error: %u, %u, %s\n"
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek "Will try to return what we have in cache\n",
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek (unsigned int)err_maj, (unsigned int)err_min, err_msg));
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek /* Loop to the next domain if possible */
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek if (dctx->domain->next && dctx->cmd_ctx->check_next) {
3b121852048a7931f8a608527b760963e2ed2bb4Jakub Hrozek dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, ("About to get sudo rules from cache\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Failed to make a request to our cache [%d]: %s\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic errno_t sudosrv_get_sudorules_from_cache(struct sudo_dom_ctx *dctx)
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx;
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina struct sudo_ctx *sudo_ctx = dctx->cmd_ctx->sudo_ctx;
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina const char *safe_name = dctx->cmd_ctx->username ?
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_get_ctx_from_list(cli_ctx->rctx->db_list,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("sysdb context not found for this domain!\n"));
c47e9d522f0d87259e5074ea643daaa3dfcb8d92Pavel Březina if (dctx->cmd_ctx->type == SSS_DP_SUDO_USER) {
c47e9d522f0d87259e5074ea643daaa3dfcb8d92Pavel Březina ret = sysdb_get_sudo_user_info(tmp_ctx, dctx->cmd_ctx->username,
c47e9d522f0d87259e5074ea643daaa3dfcb8d92Pavel Březina ("Unable to retrieve user info [%d]: %s\n", strerror(ret)));
c47e9d522f0d87259e5074ea643daaa3dfcb8d92Pavel Březina ret = sudosrv_get_sudorules_query_cache(dctx, sysdb, dctx->cmd_ctx->type,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Unable to retrieve sudo rules [%d]: %s\n", strerror(ret)));
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina /* Store result in in-memory cache */
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina ret = sudosrv_cache_set_entry(sudo_ctx->rctx->ev, sudo_ctx,
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina DEBUG(SSSDBG_MINOR_FAILURE, ("Unable to store rules in cache for "
41ef946f3f74a46b9e26118116e4811e259b30efPavel Březina DEBUG(SSSDBG_FUNC_DATA, ("Rules for [%s@%s] stored in in-memory cache\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, ("Returning rules for [%s@%s]\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozeksort_sudo_rules(struct sysdb_attrs **rules, size_t count);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozekstatic errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
c47e9d522f0d87259e5074ea643daaa3dfcb8d92Pavel Březina flags = SYSDB_SUDO_FILTER_USERINFO | SYSDB_SUDO_FILTER_INCLUDE_ALL;
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_get_sudo_filter(tmp_ctx, username, uid, groupnames,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Could not construct the search filter [%d]: %s\n",
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_FUNC_DATA, ("Searching sysdb with [%s]\n", filter));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_search_custom(tmp_ctx, sysdb, filter,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, ("Error looking up SUDO rules"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &rules);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Could not convert ldb message to sysdb_attrs\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ("Could not sort rules by sudoOrder\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozeksudo_order_cmp_fn(const void *a, const void *b)
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, ("BUG: Wrong data?\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_attrs_get_uint32_t(r1, SYSDB_SUDO_CACHE_AT_ORDER, &o1);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* man sudoers-ldap: If the sudoOrder attribute is not present,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek * a value of 0 is assumed */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("Cannot get sudoOrder value\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek ret = sysdb_attrs_get_uint32_t(r2, SYSDB_SUDO_CACHE_AT_ORDER, &o2);
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek /* man sudoers-ldap: If the sudoOrder attribute is not present,
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek * a value of 0 is assumed */
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("Cannot get sudoOrder value\n"));
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozeksort_sudo_rules(struct sysdb_attrs **rules, size_t count)
20e310e32a47e861ce0c11bcd1dcf89dc78d8abaJakub Hrozek qsort(rules, count, sizeof(struct sysdb_attrs *),
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinachar * sudosrv_get_sudorules_parse_query(TALLOC_CTX *mem_ctx,
f643754db81eeade60485bbe3d80324d889cc4f3Pavel Březina /* empty string or not NULL terminated */
f643754db81eeade60485bbe3d80324d889cc4f3Pavel Březina if (query_len < 2 || strnlen(query_body, query_len) == query_len) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query.\n"));
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina * Response format:
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina * <error_code(uint32_t)><num_entries(uint32_t)><rule1><rule2>...
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina * <ruleN> = <num_attrs(uint32_t)><attr1><attr2>...
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina * <attrN> = <name(char*)>\0<num_values(uint32_t)><value1(char*)>\0<value2(char*)>\0...
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina * if <error_code> is not SSS_SUDO_ERROR_OK, the rest of the data is skipped.
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinaint sudosrv_get_sudorules_build_response(TALLOC_CTX *mem_ctx,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* error code */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ret = sudosrv_response_append_uint32(tmp_ctx, error,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* rules count */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ret = sudosrv_response_append_uint32(tmp_ctx, (uint32_t)rules_num,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina for (i = 0; i < rules_num; i++) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ret = sudosrv_response_append_rule(tmp_ctx, rules[i]->num, rules[i]->a,