ipa_access.c revision 1390b5db218b0ecf0a806ab206bbda4d485658fb
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen IPA Backend Module -- Access control
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen Sumit Bose <sbose@redhat.com>
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen Copyright (C) 2009 Red Hat
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen This program is free software; you can redistribute it and/or modify
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen it under the terms of the GNU General Public License as published by
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen the Free Software Foundation; either version 3 of the License, or
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen (at your option) any later version.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen This program is distributed in the hope that it will be useful,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen but WITHOUT ANY WARRANTY; without even the implied warranty of
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen GNU General Public License for more details.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen You should have received a copy of the GNU General Public License
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen along with this program. If not, see <http://www.gnu.org/licenses/>.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void ipa_access_reply(struct hbac_ctx *hbac_ctx, int pam_status)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd = talloc_get_type(be_req->req_data, struct pam_data);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* destroy HBAC context now to release all used resources and LDAP connection */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (pam_status == PAM_SUCCESS || pam_status == PAM_PERM_DENIED) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_OK, pam_status, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void ipa_hbac_check(struct tevent_req *req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic int hbac_retry(struct hbac_ctx *hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_connect_done(struct tevent_req *subreq);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic bool hbac_check_step_result(struct hbac_ctx *hbac_ctx, int ret);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd = talloc_get_type(be_req->req_data, struct pam_data);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (strcasecmp(pd->domain, be_req->be_ctx->domain->name) != 0) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->domain = new_subdomain(be_req, be_req->be_ctx->domain, pd->domain, NULL, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(SSSDBG_OP_FAILURE, ("new_subdomain failed.\n"));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* First, verify that this account isn't locked.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * We need to do this in case the auth phase was
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * skipped (such as during GSSAPI single-sign-on
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * or SSH public key exchange.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen tevent_req_set_callback(req, ipa_hbac_check, be_req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void ipa_hbac_check(struct tevent_req *req)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req = tevent_req_callback_data(req, struct be_req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd = talloc_get_type(be_req->req_data, struct pam_data);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Account wasn't locked. Continue below
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * to HBAC processing.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Account was locked. Return permission denied
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_OK, PAM_PERM_DENIED, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* We got an unexpected error. Return it as-is */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx = talloc_zero(be_req, struct hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->sdap_ctx = ipa_access_ctx->sdap_ctx;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->ipa_options = ipa_access_ctx->ipa_options;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->search_bases = ipa_access_ctx->hbac_search_bases;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen deny_method = dp_opt_get_string(hbac_ctx->ipa_options,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Return an proper error */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic int hbac_retry(struct hbac_ctx *hbac_ctx)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct ipa_access_ctx *access_ctx = hbac_ctx->access_ctx;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen offline = be_is_offline(hbac_ctx->be_req->be_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(9, ("Connection status is [%s].\n", offline ? "offline" : "online"));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen refresh_interval = dp_opt_get_int(hbac_ctx->ipa_options,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (now < access_ctx->last_update + refresh_interval) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Simulate offline mode and just go to the cache */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(6, ("Performing cached HBAC evaluation\n"));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->sdap_op = sdap_id_op_create(hbac_ctx,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen subreq = sdap_id_op_connect_send(hbac_ctx_sdap_id_op(hbac_ctx), hbac_ctx, &ret);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(1, ("sdap_id_op_connect_send failed: %d(%s).\n", ret, strerror(ret)));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen tevent_req_set_callback(subreq, hbac_connect_done, hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Evaluate the rules based on what we have in the
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_connect_done(struct tevent_req *subreq)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct hbac_ctx *hbac_ctx = tevent_req_callback_data(subreq, struct hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = sdap_id_op_connect_recv(subreq, &dp_error);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* switching to offline mode */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_clear_rule_data(struct hbac_ctx *hbac_ctx)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen/* Check the step result code and continue, retry, get offline result or abort accordingly */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic bool hbac_check_step_result(struct hbac_ctx *hbac_ctx, int ret)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* already offline => the error is fatal */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return false;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = sdap_id_op_done(hbac_ctx_sdap_id_op(hbac_ctx), ret, &dp_error);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* switching to offline mode */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Free any of the results we've gotten */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return false;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return false;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_get_service_info_step(struct tevent_req *req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_get_rule_info_step(struct tevent_req *req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_sysdb_save (struct tevent_req *req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (dp_opt_get_bool(hbac_ctx->ipa_options, IPA_HBAC_SUPPORT_SRCHOST)) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Support srchost
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * -> we don't want any particular host,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * we want all hosts
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hostname = dp_opt_get_string(hbac_ctx->ipa_options, IPA_HOSTNAME);
return ENOMEM;
return EOK;
goto fail;
fail:
size_t i;
const char *ipa_hostname;
const char *hostname;
goto fail;
&hostname);
goto fail;
goto fail;
goto fail;
fail:
bool in_transaction = false;
struct ipa_access_ctx);
goto fail;
in_transaction = true;
goto fail;
goto fail;
goto fail;
goto fail;
fail:
if (in_transaction) {
char *filter;
NULL };
goto done;
goto done;
rule_count = 0;
goto done;
done:
return ret;