ipa_access.c revision 1390b5db218b0ecf0a806ab206bbda4d485658fb
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen/*
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen SSSD
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen IPA Backend Module -- Access control
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen Authors:
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen Sumit Bose <sbose@redhat.com>
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen Copyright (C) 2009 Red Hat
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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
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
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 Gundersen*/
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include <sys/param.h>
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include <security/pam_modules.h>
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "util/util.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ldap/sdap_async.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ldap/sdap_access.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ipa/ipa_common.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ipa/ipa_access.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ipa/ipa_hbac.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ipa/ipa_hosts.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ipa/ipa_hbac_private.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen#include "providers/ipa/ipa_hbac_rules.h"
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void ipa_access_reply(struct hbac_ctx *hbac_ctx, int pam_status)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct be_req *be_req = hbac_ctx->be_req;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct pam_data *pd;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd = talloc_get_type(be_req->req_data, struct pam_data);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd->pam_status = pam_status;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* destroy HBAC context now to release all used resources and LDAP connection */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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 } else {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen}
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenenum hbac_result {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen HBAC_ALLOW = 1,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen HBAC_DENY,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen HBAC_NOT_APPLICABLE
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen};
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenenum check_result {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen RULE_APPLICABLE = 0,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen RULE_NOT_APPLICABLE,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen RULE_ERROR
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen};
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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 Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenvoid ipa_access_handler(struct be_req *be_req)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct pam_data *pd;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct ipa_access_ctx *ipa_access_ctx;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct tevent_req *req;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd = talloc_get_type(be_req->req_data, struct pam_data);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_access_ctx = talloc_get_type(
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct ipa_access_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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 if (be_req->domain == 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 return;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->sysdb = be_req->domain->sysdb;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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 */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen req = sdap_access_send(be_req,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->be_ctx->ev,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_access_ctx->sdap_access_ctx,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (!req) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen tevent_req_set_callback(req, ipa_hbac_check, be_req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen}
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void ipa_hbac_check(struct tevent_req *req)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct be_req *be_req;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct pam_data *pd;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct hbac_ctx *hbac_ctx = NULL;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen const char *deny_method;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen int pam_status = PAM_SYSTEM_ERR;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct ipa_access_ctx *ipa_access_ctx;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen int ret;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = sdap_access_recv(req, &pam_status);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(req);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (ret != EOK) goto fail;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen switch(pam_status) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen case PAM_SUCCESS:
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Account wasn't locked. Continue below
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * to HBAC processing.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen break;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen case PAM_PERM_DENIED:
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Account was locked. Return permission denied
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * here.
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd->pam_status = PAM_PERM_DENIED;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_OK, PAM_PERM_DENIED, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen default:
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* We got an unexpected error. Return it as-is */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen pd->pam_status = PAM_SYSTEM_ERR;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx = talloc_zero(be_req, struct hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (hbac_ctx == NULL) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(1, ("talloc failed.\n"));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen goto fail;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->be_req = be_req;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->pd = pd;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_access_ctx = talloc_get_type(
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct ipa_access_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->access_ctx = ipa_access_ctx;
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->tr_ctx = ipa_access_ctx->tr_ctx;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->search_bases = ipa_access_ctx->hbac_search_bases;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (hbac_ctx->search_bases == NULL) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(1, ("No HBAC search base found.\n"));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen goto fail;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen deny_method = dp_opt_get_string(hbac_ctx->ipa_options,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen IPA_HBAC_DENY_METHOD);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (strcasecmp(deny_method, "IGNORE") == 0) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->get_deny_rules = false;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen } else {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->get_deny_rules = true;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = hbac_retry(hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (ret != EOK) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen goto fail;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenfail:
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (hbac_ctx) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Return an proper error */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_access_reply(hbac_ctx, pam_status);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen } else {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen be_req->fn(be_req, DP_ERR_FATAL, pam_status, NULL);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen}
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic int hbac_retry(struct hbac_ctx *hbac_ctx)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct tevent_req *subreq;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen int ret;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen bool offline;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen time_t now, refresh_interval;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct ipa_access_ctx *access_ctx = hbac_ctx->access_ctx;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen refresh_interval = dp_opt_get_int(hbac_ctx->ipa_options,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen IPA_HBAC_REFRESH);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen now = time(NULL);
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 offline = true;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (!offline) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (hbac_ctx->sdap_op == NULL) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->sdap_op = sdap_id_op_create(hbac_ctx,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx_sdap_id_ctx(hbac_ctx)->conn_cache);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (hbac_ctx->sdap_op == NULL) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(1, ("sdap_id_op_create failed.\n"));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return EIO;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen subreq = sdap_id_op_connect_send(hbac_ctx_sdap_id_op(hbac_ctx), hbac_ctx, &ret);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (!subreq) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen DEBUG(1, ("sdap_id_op_connect_send failed: %d(%s).\n", ret, strerror(ret)));
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->sdap_op);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return ret;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen tevent_req_set_callback(subreq, hbac_connect_done, hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen } else {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Evaluate the rules based on what we have in the
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen * sysdb
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_hbac_evaluate_rules(hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return EOK;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return EOK;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen}
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_connect_done(struct tevent_req *subreq)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct hbac_ctx *hbac_ctx = tevent_req_callback_data(subreq, struct hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen int ret, dp_error;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = sdap_id_op_connect_recv(subreq, &dp_error);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(subreq);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (dp_error == DP_ERR_OFFLINE) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* switching to offline mode */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->sdap_op);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_hbac_evaluate_rules(hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen } else if (ret != EOK) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen goto fail;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = hbac_get_host_info_step(hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (ret != EOK) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen goto fail;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenfail:
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen}
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic void hbac_clear_rule_data(struct hbac_ctx *hbac_ctx)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->host_count = 0;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->hosts);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->hostgroup_count = 0;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->hostgroups);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->service_count = 0;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->services);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->servicegroup_count = 0;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->servicegroups);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx->rule_count = 0;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->rules);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen}
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen int dp_error;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (ret == EOK) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return true;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (hbac_ctx_is_offline(hbac_ctx)) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* already offline => the error is fatal */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return false;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = sdap_id_op_done(hbac_ctx_sdap_id_op(hbac_ctx), ret, &dp_error);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (ret != EOK) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (dp_error == DP_ERR_OFFLINE) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* switching to offline mode */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen talloc_zfree(hbac_ctx->sdap_op);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* Free any of the results we've gotten */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_clear_rule_data(hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen dp_error = DP_ERR_OK;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (dp_error == DP_ERR_OK) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen /* retry */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ret = hbac_retry(hbac_ctx);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen if (ret == EOK) {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return false;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen return false;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen}
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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 Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersenstatic int hbac_get_host_info_step(struct hbac_ctx *hbac_ctx)
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen{
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen const char *hostname;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen struct tevent_req *req;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
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 */
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hostname = NULL;
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen } else {
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hostname = dp_opt_get_string(hbac_ctx->ipa_options, IPA_HOSTNAME);
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen }
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen req = ipa_host_info_send(hbac_ctx,
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx_ev(hbac_ctx),
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx_sysdb(hbac_ctx),
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen sdap_id_op_handle(hbac_ctx->sdap_op),
eac684ef1c29684b1bcd27a89c38c202e568e469Tom Gundersen hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
hostname,
hbac_ctx->access_ctx->host_map,
hbac_ctx->access_ctx->hostgroup_map,
hbac_ctx->access_ctx->host_search_bases);
if (req == NULL) {
DEBUG(1, ("Could not get host info\n"));
return ENOMEM;
}
tevent_req_set_callback(req, hbac_get_service_info_step, hbac_ctx);
return EOK;
}
static void hbac_get_service_info_step(struct tevent_req *req)
{
errno_t ret;
struct hbac_ctx *hbac_ctx =
tevent_req_callback_data(req, struct hbac_ctx);
ret = ipa_host_info_recv(req, hbac_ctx,
&hbac_ctx->host_count,
&hbac_ctx->hosts,
&hbac_ctx->hostgroup_count,
&hbac_ctx->hostgroups);
talloc_zfree(req);
if (!hbac_check_step_result(hbac_ctx, ret)) {
return;
}
/* Get services and service groups */
req = ipa_hbac_service_info_send(hbac_ctx,
hbac_ctx_ev(hbac_ctx),
hbac_ctx_sysdb(hbac_ctx),
sdap_id_op_handle(hbac_ctx->sdap_op),
hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
hbac_ctx->search_bases);
if (req == NULL) {
DEBUG(1,("Could not get service info\n"));
goto fail;
}
tevent_req_set_callback(req, hbac_get_rule_info_step, hbac_ctx);
return;
fail:
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
static void hbac_get_rule_info_step(struct tevent_req *req)
{
errno_t ret;
size_t i;
const char *ipa_hostname;
const char *hostname;
struct hbac_ctx *hbac_ctx =
tevent_req_callback_data(req, struct hbac_ctx);
ret = ipa_hbac_service_info_recv(req, hbac_ctx,
&hbac_ctx->service_count,
&hbac_ctx->services,
&hbac_ctx->servicegroup_count,
&hbac_ctx->servicegroups);
talloc_zfree(req);
if (!hbac_check_step_result(hbac_ctx, ret)) {
return;
}
/* Get the ipa_host attrs */
hbac_ctx->ipa_host = NULL;
ipa_hostname = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
if (ipa_hostname == NULL) {
DEBUG(1, ("Missing ipa_hostname, this should never happen.\n"));
goto fail;
}
for (i = 0; i < hbac_ctx->host_count; i++) {
ret = sysdb_attrs_get_string(hbac_ctx->hosts[i],
SYSDB_FQDN,
&hostname);
if (ret != EOK) {
DEBUG(1, ("Could not locate IPA host\n"));
goto fail;
}
if (strcasecmp(hostname, ipa_hostname) == 0) {
hbac_ctx->ipa_host = hbac_ctx->hosts[i];
break;
}
}
if (hbac_ctx->ipa_host == NULL) {
DEBUG(1, ("Could not locate IPA host\n"));
goto fail;
}
/* Get the list of applicable rules */
req = ipa_hbac_rule_info_send(hbac_ctx,
hbac_ctx->get_deny_rules,
hbac_ctx_ev(hbac_ctx),
sdap_id_op_handle(hbac_ctx->sdap_op),
hbac_ctx_sdap_id_ctx(hbac_ctx)->opts,
hbac_ctx->search_bases,
hbac_ctx->ipa_host);
if (req == NULL) {
DEBUG(1, ("Could not get rules\n"));
goto fail;
}
tevent_req_set_callback(req, hbac_sysdb_save, hbac_ctx);
return;
fail:
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
static void hbac_sysdb_save(struct tevent_req *req)
{
errno_t ret;
bool in_transaction = false;
struct hbac_ctx *hbac_ctx =
tevent_req_callback_data(req, struct hbac_ctx);
struct sss_domain_info *domain = hbac_ctx_be(hbac_ctx)->domain;
struct sysdb_ctx *sysdb = hbac_ctx_sysdb(hbac_ctx);
struct ldb_dn *base_dn;
struct be_ctx *be_ctx = hbac_ctx_be(hbac_ctx);
struct ipa_access_ctx *access_ctx =
talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data,
struct ipa_access_ctx);
TALLOC_CTX *tmp_ctx;
ret = ipa_hbac_rule_info_recv(req, hbac_ctx,
&hbac_ctx->rule_count,
&hbac_ctx->rules);
talloc_zfree(req);
if (ret == ENOENT) {
/* No rules were found that apply to this
* host.
*/
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
return;
}
/* Delete any rules in the sysdb so offline logins
* are also denied.
*/
base_dn = sysdb_custom_subtree_dn(sysdb, tmp_ctx,
domain->name,
HBAC_RULES_SUBDIR);
if (base_dn == NULL) {
talloc_free(tmp_ctx);
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
return;
}
ret = sysdb_delete_recursive(sysdb, base_dn, true);
talloc_free(tmp_ctx);
if (ret != EOK) {
DEBUG(1, ("sysdb_delete_recursive failed.\n"));
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
return;
}
/* If no rules are found, we default to DENY */
ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
return;
}
if (!hbac_check_step_result(hbac_ctx, ret)) {
return;
}
ret = sysdb_transaction_start(sysdb);
if (ret != EOK) {
DEBUG(0, ("Could not start transaction\n"));
goto fail;
}
in_transaction = true;
/* Save the hosts */
ret = ipa_hbac_sysdb_save(sysdb, domain,
HBAC_HOSTS_SUBDIR, SYSDB_FQDN,
hbac_ctx->host_count, hbac_ctx->hosts,
HBAC_HOSTGROUPS_SUBDIR, SYSDB_NAME,
hbac_ctx->hostgroup_count,
hbac_ctx->hostgroups);
if (ret != EOK) {
DEBUG(1, ("Error saving hosts: [%d][%s]\n",
ret, strerror(ret)));
goto fail;
}
/* Save the services */
ret = ipa_hbac_sysdb_save(sysdb, domain,
HBAC_SERVICES_SUBDIR, IPA_CN,
hbac_ctx->service_count, hbac_ctx->services,
HBAC_SERVICEGROUPS_SUBDIR, IPA_CN,
hbac_ctx->servicegroup_count,
hbac_ctx->servicegroups);
if (ret != EOK) {
DEBUG(1, ("Error saving services: [%d][%s]\n",
ret, strerror(ret)));
goto fail;
}
/* Save the rules */
ret = ipa_hbac_sysdb_save(sysdb, domain,
HBAC_RULES_SUBDIR, IPA_UNIQUE_ID,
hbac_ctx->rule_count,
hbac_ctx->rules,
NULL, NULL, 0, NULL);
if (ret != EOK) {
DEBUG(1, ("Error saving rules: [%d][%s]\n",
ret, strerror(ret)));
goto fail;
}
ret = sysdb_transaction_commit(sysdb);
if (ret != EOK) {
DEBUG(0, ("Failed to commit transaction\n"));
goto fail;
}
/* We don't need the rule data any longer,
* the rest of the processing relies on
* sysdb lookups.
*/
hbac_clear_rule_data(hbac_ctx);
access_ctx->last_update = time(NULL);
/* Now evaluate the request against the rules */
ipa_hbac_evaluate_rules(hbac_ctx);
return;
fail:
if (in_transaction) {
ret = sysdb_transaction_cancel(sysdb);
if (ret != EOK) {
DEBUG(0, ("Could not cancel transaction\n"));
}
}
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
void ipa_hbac_evaluate_rules(struct hbac_ctx *hbac_ctx)
{
errno_t ret;
struct hbac_rule **hbac_rules;
struct hbac_eval_req *eval_req;
enum hbac_eval_result result;
struct hbac_info *info;
/* Get HBAC rules from the sysdb */
ret = hbac_get_cached_rules(hbac_ctx, hbac_ctx_sysdb(hbac_ctx),
&hbac_ctx->rule_count, &hbac_ctx->rules);
if (ret != EOK) {
DEBUG(1, ("Could not retrieve rules from the cache\n"));
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
}
ret = hbac_ctx_to_rules(hbac_ctx, hbac_ctx,
&hbac_rules, &eval_req);
if (ret == EPERM) {
DEBUG(1, ("DENY rules detected. Denying access to all users\n"));
ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
return;
} else if (ret != EOK) {
DEBUG(1, ("Could not construct HBAC rules\n"));
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
return;
}
result = hbac_evaluate(hbac_rules, eval_req, &info);
if (result == HBAC_EVAL_ALLOW) {
DEBUG(3, ("Access granted by HBAC rule [%s]\n",
info->rule_name));
hbac_free_info(info);
ipa_access_reply(hbac_ctx, PAM_SUCCESS);
return;
} else if (result == HBAC_EVAL_ERROR) {
DEBUG(1, ("Error [%s] occurred in rule [%s]\n",
hbac_error_string(info->code),
info->rule_name));
hbac_free_info(info);
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
return;
} else if (result == HBAC_EVAL_OOM) {
DEBUG(1, ("Insufficient memory\n"));
ipa_access_reply(hbac_ctx, PAM_SYSTEM_ERR);
return;
}
DEBUG(3, ("Access denied by HBAC rules\n"));
hbac_free_info(info);
ipa_access_reply(hbac_ctx, PAM_PERM_DENIED);
}
errno_t hbac_get_cached_rules(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
size_t *_rule_count,
struct sysdb_attrs ***_rules)
{
errno_t ret;
struct ldb_message **msgs;
struct sysdb_attrs **rules;
size_t rule_count;
TALLOC_CTX *tmp_ctx;
char *filter;
const char *attrs[] = { OBJECTCLASS,
IPA_CN,
SYSDB_ORIG_DN,
IPA_UNIQUE_ID,
IPA_ENABLED_FLAG,
IPA_ACCESS_RULE_TYPE,
IPA_MEMBER_USER,
IPA_USER_CATEGORY,
IPA_MEMBER_SERVICE,
IPA_SERVICE_CATEGORY,
IPA_SOURCE_HOST,
IPA_SOURCE_HOST_CATEGORY,
IPA_EXTERNAL_HOST,
IPA_MEMBER_HOST,
IPA_HOST_CATEGORY,
NULL };
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) return ENOMEM;
filter = talloc_asprintf(tmp_ctx, "(objectClass=%s)", IPA_HBAC_RULE);
if (filter == NULL) {
ret = ENOMEM;
goto done;
}
ret = sysdb_search_custom(tmp_ctx, sysdb, filter,
HBAC_RULES_SUBDIR, attrs,
&rule_count, &msgs);
if (ret != EOK && ret != ENOENT) {
DEBUG(1, ("Error looking up HBAC rules"));
goto done;
} if (ret == ENOENT) {
rule_count = 0;
}
ret = sysdb_msg2attrs(tmp_ctx, rule_count, msgs, &rules);
if (ret != EOK) {
DEBUG(1, ("Could not convert ldb message to sysdb_attrs\n"));
goto done;
}
if (_rules) *_rules = talloc_steal(mem_ctx, rules);
if (_rule_count) *_rule_count = rule_count;
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}