LCOV - code coverage report
Current view: top level - providers/ipa - ipa_access.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 372 0.0 %
Date: 2016-06-29 Functions: 0 17 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     IPA Backend Module -- Access control
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2009 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <sys/param.h>
      26             : #include <security/pam_modules.h>
      27             : 
      28             : #include "util/util.h"
      29             : #include "providers/ldap/sdap_async.h"
      30             : #include "providers/ldap/sdap_access.h"
      31             : #include "providers/ipa/ipa_common.h"
      32             : #include "providers/ipa/ipa_access.h"
      33             : #include "providers/ipa/ipa_hosts.h"
      34             : #include "providers/ipa/ipa_hbac_private.h"
      35             : #include "providers/ipa/ipa_hbac_rules.h"
      36             : 
      37             : /* External logging function for HBAC. */
      38           0 : void hbac_debug_messages(const char *file, int line,
      39             :                          const char *function,
      40             :                          enum hbac_debug_level level,
      41             :                          const char *fmt, ...)
      42             : {
      43             :     int loglevel;
      44             : 
      45           0 :     switch(level) {
      46             :     case HBAC_DBG_FATAL:
      47           0 :         loglevel = SSSDBG_FATAL_FAILURE;
      48           0 :         break;
      49             :     case HBAC_DBG_ERROR:
      50           0 :         loglevel = SSSDBG_OP_FAILURE;
      51           0 :         break;
      52             :     case HBAC_DBG_WARNING:
      53           0 :         loglevel = SSSDBG_MINOR_FAILURE;
      54           0 :         break;
      55             :     case HBAC_DBG_INFO:
      56           0 :         loglevel = SSSDBG_CONF_SETTINGS;
      57           0 :         break;
      58             :     case HBAC_DBG_TRACE:
      59           0 :         loglevel = SSSDBG_TRACE_INTERNAL;
      60           0 :         break;
      61             :     default:
      62           0 :         loglevel = SSSDBG_UNRESOLVED;
      63           0 :         break;
      64             :     }
      65             : 
      66           0 :     if (DEBUG_IS_SET(loglevel)) {
      67             :         va_list ap;
      68             : 
      69           0 :         va_start(ap, fmt);
      70           0 :         sss_vdebug_fn(file, line, function, loglevel, 0, fmt, ap);
      71           0 :         va_end(ap);
      72             :     }
      73           0 : }
      74             : 
      75             : enum hbac_result {
      76             :     HBAC_ALLOW = 1,
      77             :     HBAC_DENY,
      78             :     HBAC_NOT_APPLICABLE
      79             : };
      80             : 
      81             : enum check_result {
      82             :     RULE_APPLICABLE = 0,
      83             :     RULE_NOT_APPLICABLE,
      84             :     RULE_ERROR
      85             : };
      86             : 
      87             : struct ipa_fetch_hbac_state {
      88             :     struct tevent_context *ev;
      89             :     struct be_ctx *be_ctx;
      90             :     struct sdap_id_ctx *sdap_ctx;
      91             :     struct ipa_access_ctx *access_ctx;
      92             :     struct sdap_id_op *sdap_op;
      93             :     struct dp_option *ipa_options;
      94             :     struct time_rules_ctx *tr_ctx;
      95             : 
      96             :     struct sdap_search_base **search_bases;
      97             : 
      98             :     /* Hosts */
      99             :     size_t host_count;
     100             :     struct sysdb_attrs **hosts;
     101             :     size_t hostgroup_count;
     102             :     struct sysdb_attrs **hostgroups;
     103             :     struct sysdb_attrs *ipa_host;
     104             : 
     105             :     /* Rules */
     106             :     size_t rule_count;
     107             :     struct sysdb_attrs **rules;
     108             : 
     109             :     /* Services */
     110             :     size_t service_count;
     111             :     struct sysdb_attrs **services;
     112             :     size_t servicegroup_count;
     113             :     struct sysdb_attrs **servicegroups;
     114             : };
     115             : 
     116             : static errno_t ipa_fetch_hbac_retry(struct tevent_req *req);
     117             : static void ipa_fetch_hbac_connect_done(struct tevent_req *subreq);
     118             : static errno_t ipa_fetch_hbac_hostinfo(struct tevent_req *req);
     119             : static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq);
     120             : static void ipa_fetch_hbac_services_done(struct tevent_req *subreq);
     121             : static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq);
     122             : static errno_t ipa_purge_hbac(struct sss_domain_info *domain);
     123             : static errno_t ipa_save_hbac(struct sss_domain_info *domain,
     124             :                              struct ipa_fetch_hbac_state *state);
     125             : 
     126             : static struct tevent_req *
     127           0 : ipa_fetch_hbac_send(TALLOC_CTX *mem_ctx,
     128             :                     struct tevent_context *ev,
     129             :                     struct be_ctx *be_ctx,
     130             :                     struct ipa_access_ctx *access_ctx)
     131             : {
     132             :     struct ipa_fetch_hbac_state *state;
     133             :     struct tevent_req *req;
     134             :     time_t now, refresh_interval;
     135             :     bool offline;
     136             :     errno_t ret;
     137             : 
     138           0 :     req = tevent_req_create(mem_ctx, &state,
     139             :                             struct ipa_fetch_hbac_state);
     140           0 :     if (req == NULL) {
     141           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     142           0 :         return NULL;
     143             :     }
     144             : 
     145           0 :     state->ev = ev;
     146           0 :     state->be_ctx = be_ctx;
     147           0 :     state->access_ctx = access_ctx;
     148           0 :     state->sdap_ctx = access_ctx->sdap_ctx;
     149           0 :     state->ipa_options = access_ctx->ipa_options;
     150           0 :     state->tr_ctx = access_ctx->tr_ctx;
     151           0 :     state->search_bases = access_ctx->hbac_search_bases;
     152             : 
     153           0 :     if (state->search_bases == NULL) {
     154           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "No HBAC search base found.\n");
     155           0 :         ret = EINVAL;
     156           0 :         goto immediately;
     157             :     }
     158             : 
     159           0 :     state->sdap_op = sdap_id_op_create(state, state->sdap_ctx->conn->conn_cache);
     160           0 :     if (state->sdap_op == NULL) {
     161           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
     162           0 :         ret = ENOMEM;
     163           0 :         goto immediately;
     164             :     }
     165             : 
     166           0 :     offline = be_is_offline(be_ctx);
     167           0 :     DEBUG(SSSDBG_TRACE_ALL, "Connection status is [%s].\n",
     168             :           offline ? "offline" : "online");
     169             : 
     170           0 :     refresh_interval = dp_opt_get_int(state->ipa_options, IPA_HBAC_REFRESH);
     171           0 :     now = time(NULL);
     172             : 
     173           0 :     if (offline || now < access_ctx->last_update + refresh_interval) {
     174           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Performing cached HBAC evaluation\n");
     175           0 :         ret = EOK;
     176           0 :         goto immediately;
     177             :     }
     178             : 
     179           0 :     ret = ipa_fetch_hbac_retry(req);
     180           0 :     if (ret != EAGAIN) {
     181           0 :         goto immediately;
     182             :     }
     183             : 
     184           0 :     return req;
     185             : 
     186             : immediately:
     187           0 :     if (ret == EOK) {
     188           0 :         tevent_req_done(req);
     189             :     } else {
     190           0 :         tevent_req_error(req, ret);
     191             :     }
     192           0 :     tevent_req_post(req, ev);
     193             : 
     194           0 :     return req;
     195             : }
     196             : 
     197           0 : static errno_t ipa_fetch_hbac_retry(struct tevent_req *req)
     198             : {
     199             :     struct ipa_fetch_hbac_state *state;
     200             :     struct tevent_req *subreq;
     201             :     int ret;
     202             : 
     203           0 :     state = tevent_req_data(req, struct ipa_fetch_hbac_state);
     204             : 
     205           0 :     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
     206           0 :     if (subreq == NULL) {
     207           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: "
     208             :                                    "%d(%s)\n", ret, strerror(ret));
     209           0 :         return ret;
     210             :     }
     211             : 
     212           0 :     tevent_req_set_callback(subreq, ipa_fetch_hbac_connect_done, req);
     213             : 
     214           0 :     return EAGAIN;
     215             : }
     216             : 
     217           0 : static void ipa_fetch_hbac_connect_done(struct tevent_req *subreq)
     218             : {
     219           0 :     struct tevent_req *req = NULL;
     220             :     int dp_error;
     221             :     errno_t ret;
     222             : 
     223           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     224             : 
     225           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     226           0 :     talloc_zfree(subreq);
     227           0 :     if (ret != EOK) {
     228           0 :         goto done;
     229             :     }
     230             : 
     231           0 :     if (dp_error == DP_ERR_OFFLINE) {
     232           0 :         ret = EOK;
     233           0 :         goto done;
     234             :     }
     235             : 
     236           0 :     ret = ipa_fetch_hbac_hostinfo(req);
     237           0 :     if (ret == EAGAIN) {
     238           0 :         return;
     239             :     }
     240             : 
     241             : done:
     242           0 :     if (ret != EOK) {
     243           0 :         tevent_req_error(req, ret);
     244           0 :         return;
     245             :     }
     246             : 
     247           0 :     tevent_req_done(req);
     248             : }
     249             : 
     250           0 : static errno_t ipa_fetch_hbac_hostinfo(struct tevent_req *req)
     251             : {
     252             :     struct ipa_fetch_hbac_state *state;
     253             :     struct tevent_req *subreq;
     254             :     const char *hostname;
     255             :     bool srchost;
     256             : 
     257           0 :     state = tevent_req_data(req, struct ipa_fetch_hbac_state);
     258             : 
     259           0 :     srchost = dp_opt_get_bool(state->ipa_options, IPA_HBAC_SUPPORT_SRCHOST);
     260           0 :     if (srchost) {
     261             :         /* Support srchost
     262             :          * -> we don't want any particular host,
     263             :          *    we want all hosts
     264             :          */
     265           0 :         hostname = NULL;
     266             : 
     267             :         /* THIS FEATURE IS DEPRECATED */
     268           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "WARNING: Using deprecated option "
     269             :                     "ipa_hbac_support_srchost.\n");
     270           0 :         sss_log(SSS_LOG_NOTICE, "WARNING: Using deprecated option "
     271             :                     "ipa_hbac_support_srchost.\n");
     272             :     } else {
     273           0 :         hostname = dp_opt_get_string(state->ipa_options, IPA_HOSTNAME);
     274             :     }
     275             : 
     276           0 :     subreq = ipa_host_info_send(state, state->ev,
     277             :                                 sdap_id_op_handle(state->sdap_op),
     278           0 :                                 state->sdap_ctx->opts, hostname,
     279           0 :                                 state->access_ctx->host_map,
     280           0 :                                 state->access_ctx->hostgroup_map,
     281           0 :                                 state->access_ctx->host_search_bases);
     282           0 :     if (subreq == NULL) {
     283           0 :         return ENOMEM;
     284             :     }
     285             : 
     286           0 :     tevent_req_set_callback(subreq, ipa_fetch_hbac_hostinfo_done, req);
     287             : 
     288           0 :     return EAGAIN;
     289             : }
     290             : 
     291           0 : static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq)
     292             : {
     293           0 :     struct ipa_fetch_hbac_state *state = NULL;
     294           0 :     struct tevent_req *req = NULL;
     295             :     errno_t ret;
     296             : 
     297           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     298           0 :     state = tevent_req_data(req, struct ipa_fetch_hbac_state);
     299             : 
     300           0 :     ret = ipa_host_info_recv(subreq, state,
     301             :                              &state->host_count, &state->hosts,
     302             :                              &state->hostgroup_count, &state->hostgroups);
     303           0 :     talloc_zfree(subreq);
     304           0 :     if (ret != EOK) {
     305           0 :         goto done;
     306             :     }
     307             : 
     308           0 :     subreq = ipa_hbac_service_info_send(state, state->ev,
     309             :                                         sdap_id_op_handle(state->sdap_op),
     310           0 :                                         state->sdap_ctx->opts,
     311             :                                         state->search_bases);
     312           0 :     if (subreq == NULL) {
     313           0 :         ret = ENOMEM;
     314           0 :         goto done;
     315             :     }
     316             : 
     317           0 :     tevent_req_set_callback(subreq, ipa_fetch_hbac_services_done, req);
     318             : 
     319           0 :     return;
     320             : 
     321             : done:
     322           0 :     if (ret != EOK) {
     323           0 :         tevent_req_error(req, ret);
     324           0 :         return;
     325             :     }
     326             : 
     327           0 :     tevent_req_done(req);
     328             : }
     329             : 
     330           0 : static void ipa_fetch_hbac_services_done(struct tevent_req *subreq)
     331             : {
     332             :     struct ipa_fetch_hbac_state *state;
     333             :     struct tevent_req *req;
     334             :     const char *ipa_hostname;
     335             :     const char *hostname;
     336             :     errno_t ret;
     337             :     size_t i;
     338             : 
     339           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     340           0 :     state = tevent_req_data(req, struct ipa_fetch_hbac_state);
     341             : 
     342           0 :     ret = ipa_hbac_service_info_recv(subreq, state,
     343             :                              &state->service_count, &state->services,
     344             :                              &state->servicegroup_count, &state->servicegroups);
     345           0 :     talloc_zfree(subreq);
     346           0 :     if (ret != EOK) {
     347           0 :         goto done;
     348             :     }
     349             : 
     350             :     /* Get the ipa_host attrs */
     351           0 :     state->ipa_host = NULL;
     352           0 :     ipa_hostname = dp_opt_get_cstring(state->ipa_options, IPA_HOSTNAME);
     353           0 :     if (ipa_hostname == NULL) {
     354           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     355             :               "Missing ipa_hostname, this should never happen.\n");
     356           0 :         ret = EINVAL;
     357           0 :         goto done;
     358             :     }
     359             : 
     360           0 :     for (i = 0; i < state->host_count; i++) {
     361           0 :         ret = sysdb_attrs_get_string(state->hosts[i], SYSDB_FQDN, &hostname);
     362           0 :         if (ret != EOK) {
     363           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not locate IPA host\n");
     364           0 :             goto done;
     365             :         }
     366             : 
     367           0 :         if (strcasecmp(hostname, ipa_hostname) == 0) {
     368           0 :             state->ipa_host = state->hosts[i];
     369           0 :             break;
     370             :         }
     371             :     }
     372             : 
     373           0 :     if (state->ipa_host == NULL) {
     374           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not locate IPA host\n");
     375           0 :         ret = EINVAL;
     376           0 :         goto done;
     377             :     }
     378             : 
     379           0 :     subreq = ipa_hbac_rule_info_send(state, state->ev,
     380             :                                      sdap_id_op_handle(state->sdap_op),
     381           0 :                                      state->sdap_ctx->opts,
     382             :                                      state->search_bases,
     383             :                                      state->ipa_host);
     384           0 :     if (subreq == NULL) {
     385           0 :         ret = ENOMEM;
     386           0 :         goto done;
     387             :     }
     388             : 
     389           0 :     tevent_req_set_callback(subreq, ipa_fetch_hbac_rules_done, req);
     390             : 
     391           0 :     return;
     392             : 
     393             : done:
     394           0 :     if (ret != EOK) {
     395           0 :         tevent_req_error(req, ret);
     396           0 :         return;
     397             :     }
     398             : 
     399           0 :     tevent_req_done(req);
     400             : }
     401             : 
     402           0 : static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq)
     403             : {
     404           0 :     struct ipa_fetch_hbac_state *state = NULL;
     405           0 :     struct tevent_req *req = NULL;
     406             :     int dp_error;
     407             :     errno_t ret;
     408             :     bool found;
     409             : 
     410           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     411           0 :     state = tevent_req_data(req, struct ipa_fetch_hbac_state);
     412             : 
     413           0 :     ret = ipa_hbac_rule_info_recv(subreq, state,
     414             :                                   &state->rule_count, &state->rules);
     415           0 :     talloc_zfree(subreq);
     416           0 :     if (ret == ENOENT) {
     417             :         /* Set ret to EOK so we can safely call sdap_id_op_done. */
     418           0 :         found = false;
     419           0 :         ret = EOK;
     420           0 :     } else if (ret == EOK) {
     421           0 :         found = true;
     422             :     } else {
     423           0 :         goto done;
     424             :     }
     425             : 
     426           0 :     ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
     427           0 :     if (dp_error == DP_ERR_OK && ret != EOK) {
     428             :         /* retry */
     429           0 :         ret = ipa_fetch_hbac_retry(req);
     430           0 :         if (ret != EAGAIN) {
     431           0 :             tevent_req_error(req, ret);
     432             :         }
     433           0 :         return;
     434           0 :     } else if (ret != EOK) {
     435           0 :         tevent_req_error(req, ret);
     436           0 :         return;
     437             :     }
     438             : 
     439           0 :     if (found == false) {
     440             :         /* No rules were found that apply to this host. */
     441           0 :         ret = ipa_purge_hbac(state->be_ctx->domain);
     442           0 :         if (ret != EOK) {
     443           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to remove HBAC rules\n");
     444           0 :             goto done;
     445             :         }
     446             : 
     447           0 :         ret = ENOENT;
     448           0 :         goto done;
     449             :     }
     450             : 
     451           0 :     ret = ipa_save_hbac(state->be_ctx->domain, state);
     452           0 :     if (ret != EOK) {
     453           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to save HBAC rules\n");
     454           0 :         goto done;
     455             :     }
     456             : 
     457           0 :     ret = EOK;
     458             : 
     459             : done:
     460           0 :     if (ret != EOK) {
     461           0 :         tevent_req_error(req, ret);
     462           0 :         return;
     463             :     }
     464             : 
     465           0 :     tevent_req_done(req);
     466             : }
     467             : 
     468           0 : static errno_t ipa_fetch_hbac_recv(struct tevent_req *req)
     469             : {
     470           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     471             : 
     472           0 :     return EOK;
     473             : }
     474             : 
     475           0 : static errno_t ipa_purge_hbac(struct sss_domain_info *domain)
     476             : {
     477             :     TALLOC_CTX *tmp_ctx;
     478             :     struct ldb_dn *base_dn;
     479             :     errno_t ret;
     480             : 
     481           0 :     tmp_ctx = talloc_new(NULL);
     482           0 :     if (tmp_ctx == NULL) {
     483           0 :         return ENOMEM;
     484             :     }
     485             : 
     486             :     /* Delete any rules in the sysdb so offline logins are also denied. */
     487           0 :     base_dn = sysdb_custom_subtree_dn(tmp_ctx, domain, HBAC_RULES_SUBDIR);
     488           0 :     if (base_dn == NULL) {
     489           0 :         ret = ENOMEM;
     490           0 :         goto done;
     491             :     }
     492             : 
     493           0 :     ret = sysdb_delete_recursive(domain->sysdb, base_dn, true);
     494           0 :     if (ret != EOK) {
     495           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_delete_recursive failed.\n");
     496           0 :         goto done;
     497             :     }
     498             : 
     499           0 :     ret = EOK;
     500             : 
     501             : done:
     502           0 :     talloc_free(tmp_ctx);
     503           0 :     return ret;
     504             : }
     505             : 
     506           0 : static errno_t ipa_save_hbac(struct sss_domain_info *domain,
     507             :                              struct ipa_fetch_hbac_state *state)
     508             : {
     509           0 :     bool in_transaction = false;
     510             :     errno_t ret;
     511             :     errno_t sret;
     512             : 
     513           0 :     ret = sysdb_transaction_start(domain->sysdb);
     514           0 :     if (ret != EOK) {
     515           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Could not start transaction\n");
     516           0 :         goto done;
     517             :     }
     518           0 :     in_transaction = true;
     519             : 
     520             :     /* Save the hosts */
     521           0 :     ret = ipa_hbac_sysdb_save(domain, HBAC_HOSTS_SUBDIR, SYSDB_FQDN,
     522             :                               state->host_count, state->hosts,
     523             :                               HBAC_HOSTGROUPS_SUBDIR, SYSDB_NAME,
     524             :                               state->hostgroup_count, state->hostgroups);
     525           0 :     if (ret != EOK) {
     526           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error saving hosts [%d]: %s\n",
     527             :               ret, sss_strerror(ret));
     528           0 :         goto done;
     529             :     }
     530             : 
     531             :     /* Save the services */
     532           0 :     ret = ipa_hbac_sysdb_save(domain, HBAC_SERVICES_SUBDIR, IPA_CN,
     533             :                               state->service_count, state->services,
     534             :                               HBAC_SERVICEGROUPS_SUBDIR, IPA_CN,
     535             :                               state->servicegroup_count,
     536             :                               state->servicegroups);
     537           0 :     if (ret != EOK) {
     538           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error saving services [%d]: %s\n",
     539             :               ret, sss_strerror(ret));
     540           0 :         goto done;
     541             :     }
     542             :     /* Save the rules */
     543           0 :     ret = ipa_hbac_sysdb_save(domain, HBAC_RULES_SUBDIR, IPA_UNIQUE_ID,
     544             :                               state->rule_count, state->rules,
     545             :                               NULL, NULL, 0, NULL);
     546           0 :     if (ret != EOK) {
     547           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error saving rules [%d]: %s\n",
     548             :               ret, sss_strerror(ret));
     549           0 :         goto done;
     550             :     }
     551             : 
     552           0 :     ret = sysdb_transaction_commit(domain->sysdb);
     553           0 :     if (ret != EOK) {
     554           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
     555           0 :         goto done;
     556             :     }
     557           0 :     in_transaction = false;
     558             : 
     559           0 :     state->access_ctx->last_update = time(NULL);
     560             : 
     561           0 :     ret = EOK;
     562             : 
     563             : done:
     564           0 :     if (in_transaction) {
     565           0 :         sret = sysdb_transaction_cancel(domain->sysdb);
     566           0 :         if (sret != EOK) {
     567           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
     568             :         }
     569             :     }
     570             : 
     571           0 :     return ret;
     572             : }
     573             : 
     574           0 : errno_t ipa_hbac_evaluate_rules(struct be_ctx *be_ctx,
     575             :                                 struct dp_option *ipa_options,
     576             :                                 struct pam_data *pd)
     577             : {
     578             :     TALLOC_CTX *tmp_ctx;
     579             :     struct hbac_ctx hbac_ctx;
     580             :     struct hbac_rule **hbac_rules;
     581             :     struct hbac_eval_req *eval_req;
     582             :     enum hbac_eval_result result;
     583           0 :     struct hbac_info *info = NULL;
     584             :     errno_t ret;
     585             : 
     586           0 :     tmp_ctx = talloc_new(NULL);
     587           0 :     if (tmp_ctx == NULL) {
     588           0 :         return ENOMEM;
     589             :     }
     590             : 
     591           0 :     hbac_ctx.be_ctx = be_ctx;
     592           0 :     hbac_ctx.ipa_options = ipa_options;
     593           0 :     hbac_ctx.pd = pd;
     594             : 
     595             :     /* Get HBAC rules from the sysdb */
     596           0 :     ret = hbac_get_cached_rules(tmp_ctx, be_ctx->domain,
     597             :                                 &hbac_ctx.rule_count, &hbac_ctx.rules);
     598           0 :     if (ret != EOK) {
     599           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not retrieve rules from the cache\n");
     600           0 :         goto done;
     601             :     }
     602             : 
     603           0 :     ret = hbac_ctx_to_rules(tmp_ctx, &hbac_ctx, &hbac_rules, &eval_req);
     604           0 :     if (ret == EPERM) {
     605           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     606             :               "DENY rules detected. Denying access to all users\n");
     607           0 :         ret = ERR_ACCESS_DENIED;
     608           0 :         goto done;
     609           0 :     } else if (ret != EOK) {
     610           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not construct HBAC rules\n");
     611           0 :         goto done;
     612             :     }
     613             : 
     614           0 :     hbac_enable_debug(hbac_debug_messages);
     615             : 
     616           0 :     result = hbac_evaluate(hbac_rules, eval_req, &info);
     617           0 :     if (result == HBAC_EVAL_ALLOW) {
     618           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Access granted by HBAC rule [%s]\n",
     619             :               info->rule_name);
     620           0 :         ret = EOK;
     621           0 :         goto done;
     622           0 :     } else if (result == HBAC_EVAL_ERROR) {
     623           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error [%s] occurred in rule [%s]\n",
     624             :               hbac_error_string(info->code), info->rule_name);
     625           0 :         ret = EIO;
     626           0 :         goto done;
     627           0 :     } else if (result == HBAC_EVAL_OOM) {
     628           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Insufficient memory\n");
     629           0 :         ret = ENOMEM;
     630           0 :         goto done;
     631             :     }
     632             : 
     633           0 :     DEBUG(SSSDBG_MINOR_FAILURE, "Access denied by HBAC rules\n");
     634           0 :     ret = ERR_ACCESS_DENIED;
     635             : 
     636             : done:
     637           0 :     hbac_free_info(info);
     638           0 :     talloc_free(tmp_ctx);
     639           0 :     return ret;
     640             : }
     641             : 
     642           0 : errno_t hbac_get_cached_rules(TALLOC_CTX *mem_ctx,
     643             :                               struct sss_domain_info *domain,
     644             :                               size_t *_rule_count,
     645             :                               struct sysdb_attrs ***_rules)
     646             : {
     647             :     errno_t ret;
     648             :     struct ldb_message **msgs;
     649             :     struct sysdb_attrs **rules;
     650             :     size_t rule_count;
     651             :     TALLOC_CTX *tmp_ctx;
     652             :     char *filter;
     653           0 :     const char *attrs[] = { OBJECTCLASS,
     654             :                             IPA_CN,
     655             :                             SYSDB_ORIG_DN,
     656             :                             IPA_UNIQUE_ID,
     657             :                             IPA_ENABLED_FLAG,
     658             :                             IPA_ACCESS_RULE_TYPE,
     659             :                             IPA_MEMBER_USER,
     660             :                             IPA_USER_CATEGORY,
     661             :                             IPA_MEMBER_SERVICE,
     662             :                             IPA_SERVICE_CATEGORY,
     663             :                             IPA_SOURCE_HOST,
     664             :                             IPA_SOURCE_HOST_CATEGORY,
     665             :                             IPA_EXTERNAL_HOST,
     666             :                             IPA_MEMBER_HOST,
     667             :                             IPA_HOST_CATEGORY,
     668             :                             NULL };
     669             : 
     670           0 :     tmp_ctx = talloc_new(NULL);
     671           0 :     if (tmp_ctx == NULL) return ENOMEM;
     672             : 
     673           0 :     filter = talloc_asprintf(tmp_ctx, "(objectClass=%s)", IPA_HBAC_RULE);
     674           0 :     if (filter == NULL) {
     675           0 :         ret = ENOMEM;
     676           0 :         goto done;
     677             :     }
     678             : 
     679           0 :     ret = sysdb_search_custom(tmp_ctx, domain, filter,
     680             :                               HBAC_RULES_SUBDIR, attrs,
     681             :                               &rule_count, &msgs);
     682           0 :     if (ret != EOK && ret != ENOENT) {
     683           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up HBAC rules\n");
     684           0 :         goto done;
     685           0 :     } if (ret == ENOENT) {
     686           0 :        rule_count = 0;
     687             :     }
     688             : 
     689           0 :     ret = sysdb_msg2attrs(tmp_ctx, rule_count, msgs, &rules);
     690           0 :     if (ret != EOK) {
     691           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     692             :               "Could not convert ldb message to sysdb_attrs\n");
     693           0 :         goto done;
     694             :     }
     695             : 
     696           0 :     if (_rules) *_rules = talloc_steal(mem_ctx, rules);
     697           0 :     if (_rule_count) *_rule_count = rule_count;
     698             : 
     699           0 :     ret = EOK;
     700             : done:
     701           0 :     talloc_free(tmp_ctx);
     702           0 :     return ret;
     703             : }
     704             : 
     705             : struct ipa_pam_access_handler_state {
     706             :     struct tevent_context *ev;
     707             :     struct be_ctx *be_ctx;
     708             :     struct ipa_access_ctx *access_ctx;
     709             :     struct pam_data *pd;
     710             : };
     711             : 
     712             : static void ipa_pam_access_handler_sdap_done(struct tevent_req *subreq);
     713             : static void ipa_pam_access_handler_done(struct tevent_req *subreq);
     714             : 
     715             : struct tevent_req *
     716           0 : ipa_pam_access_handler_send(TALLOC_CTX *mem_ctx,
     717             :                            struct ipa_access_ctx *access_ctx,
     718             :                            struct pam_data *pd,
     719             :                            struct dp_req_params *params)
     720             : {
     721             :     struct ipa_pam_access_handler_state *state;
     722             :     struct tevent_req *subreq;
     723             :     struct tevent_req *req;
     724             : 
     725           0 :     req = tevent_req_create(mem_ctx, &state,
     726             :                             struct ipa_pam_access_handler_state);
     727           0 :     if (req == NULL) {
     728           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     729           0 :         return NULL;
     730             :     }
     731             : 
     732           0 :     state->pd = pd;
     733           0 :     state->ev = params->ev;
     734           0 :     state->be_ctx = params->be_ctx;
     735           0 :     state->access_ctx = access_ctx;
     736             : 
     737           0 :     subreq = sdap_access_send(state, params->ev, params->be_ctx,
     738             :                               params->domain, access_ctx->sdap_access_ctx,
     739           0 :                               access_ctx->sdap_ctx->conn, pd);
     740           0 :     if (subreq == NULL) {
     741           0 :         state->pd->pam_status = PAM_SYSTEM_ERR;
     742           0 :         goto immediately;
     743             :     }
     744             : 
     745           0 :     tevent_req_set_callback(subreq, ipa_pam_access_handler_sdap_done, req);
     746             : 
     747           0 :     return req;
     748             : 
     749             : immediately:
     750             :     /* TODO For backward compatibility we always return EOK to DP now. */
     751           0 :     tevent_req_done(req);
     752           0 :     tevent_req_post(req, params->ev);
     753             : 
     754           0 :     return req;
     755             : }
     756             : 
     757           0 : static void ipa_pam_access_handler_sdap_done(struct tevent_req *subreq)
     758             : {
     759             :     struct ipa_pam_access_handler_state *state;
     760             :     struct tevent_req *req;
     761             :     errno_t ret;
     762             : 
     763           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     764           0 :     state = tevent_req_data(req, struct ipa_pam_access_handler_state);
     765             : 
     766           0 :     ret = sdap_access_recv(subreq);
     767           0 :     talloc_free(subreq);
     768           0 :     switch (ret) {
     769             :     case EOK:
     770             :         /* Account wasn't locked. Continue below to HBAC processing. */
     771           0 :         break;
     772             :     case ERR_ACCESS_DENIED:
     773             :         /* Account was locked. Return permission denied here. */
     774           0 :         state->pd->pam_status = PAM_PERM_DENIED;
     775           0 :         goto done;
     776             :     case ERR_ACCOUNT_EXPIRED:
     777           0 :         state->pd->pam_status = PAM_ACCT_EXPIRED;
     778           0 :         goto done;
     779             :     default:
     780           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error retrieving access check result "
     781             :               "[%d]: %s.\n", ret, sss_strerror(ret));
     782           0 :         state->pd->pam_status = PAM_SYSTEM_ERR;
     783           0 :         break;
     784             :     }
     785             : 
     786           0 :     subreq = ipa_fetch_hbac_send(state, state->ev, state->be_ctx,
     787             :                                  state->access_ctx);
     788           0 :     if (subreq == NULL) {
     789           0 :         state->pd->pam_status = PAM_SYSTEM_ERR;
     790           0 :         goto done;
     791             :     }
     792             : 
     793           0 :     tevent_req_set_callback(subreq, ipa_pam_access_handler_done, req);
     794             : 
     795           0 :     return;
     796             : 
     797             : done:
     798             :     /* TODO For backward compatibility we always return EOK to DP now. */
     799           0 :     tevent_req_done(req);
     800             : }
     801             : 
     802           0 : static void ipa_pam_access_handler_done(struct tevent_req *subreq)
     803             : {
     804             :     struct ipa_pam_access_handler_state *state;
     805             :     struct tevent_req *req;
     806             :     errno_t ret;
     807             : 
     808           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     809           0 :     state = tevent_req_data(req, struct ipa_pam_access_handler_state);
     810             : 
     811           0 :     ret = ipa_fetch_hbac_recv(subreq);
     812           0 :     talloc_free(subreq);
     813             : 
     814           0 :     if (ret == ENOENT) {
     815           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "No HBAC rules find, denying access\n");
     816           0 :         state->pd->pam_status = PAM_PERM_DENIED;
     817           0 :         goto done;
     818           0 :     } else if (ret != EOK) {
     819           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to fetch HBAC rules [%d]: %s\n",
     820             :               ret, sss_strerror(ret));
     821           0 :         state->pd->pam_status = PAM_SYSTEM_ERR;
     822           0 :         goto done;
     823             :     }
     824             : 
     825           0 :     ret = ipa_hbac_evaluate_rules(state->be_ctx,
     826           0 :                                   state->access_ctx->ipa_options, state->pd);
     827           0 :     if (ret == EOK) {
     828           0 :         state->pd->pam_status = PAM_SUCCESS;
     829           0 :     } else if (ret == ERR_ACCESS_DENIED) {
     830           0 :         state->pd->pam_status = PAM_PERM_DENIED;
     831             :     } else {
     832           0 :         state->pd->pam_status = PAM_SYSTEM_ERR;
     833             :     }
     834             : 
     835             : done:
     836             :     /* TODO For backward compatibility we always return EOK to DP now. */
     837           0 :     tevent_req_done(req);
     838           0 : }
     839             : 
     840             : errno_t
     841           0 : ipa_pam_access_handler_recv(TALLOC_CTX *mem_ctx,
     842             :                              struct tevent_req *req,
     843             :                              struct pam_data **_data)
     844             : {
     845           0 :     struct ipa_pam_access_handler_state *state = NULL;
     846             : 
     847           0 :     state = tevent_req_data(req, struct ipa_pam_access_handler_state);
     848             : 
     849           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     850             : 
     851           0 :     *_data = talloc_steal(mem_ctx, state->pd);
     852             : 
     853           0 :     return EOK;
     854             : }

Generated by: LCOV version 1.10