LCOV - code coverage report
Current view: top level - providers/ipa - ipa_selinux.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 708 0.0 %
Date: 2015-10-19 Functions: 0 27 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     IPA Backend Module -- selinux loading
       5             : 
       6             :     Authors:
       7             :         Jan Zeleny <jzeleny@redhat.com>
       8             : 
       9             :     Copyright (C) 2012 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             : #include <security/pam_modules.h>
      25             : 
      26             : #include "db/sysdb_selinux.h"
      27             : #include "util/child_common.h"
      28             : #include "util/sss_selinux.h"
      29             : #include "providers/ldap/sdap_async.h"
      30             : #include "providers/ipa/ipa_common.h"
      31             : #include "providers/ipa/ipa_config.h"
      32             : #include "providers/ipa/ipa_selinux.h"
      33             : #include "providers/ipa/ipa_hosts.h"
      34             : #include "providers/ipa/ipa_hbac_rules.h"
      35             : #include "providers/ipa/ipa_hbac_private.h"
      36             : #include "providers/ipa/ipa_access.h"
      37             : #include "providers/ipa/ipa_selinux_maps.h"
      38             : #include "providers/ipa/ipa_subdomains.h"
      39             : 
      40             : #if defined HAVE_SELINUX && defined HAVE_SELINUX_LOGIN_DIR
      41             : 
      42             : #ifndef SELINUX_CHILD_DIR
      43             : #ifndef SSSD_LIBEXEC_PATH
      44             : #error "SSSD_LIBEXEC_PATH not defined"
      45             : #endif  /* SSSD_LIBEXEC_PATH */
      46             : 
      47             : #define SELINUX_CHILD_DIR SSSD_LIBEXEC_PATH
      48             : #endif /* SELINUX_CHILD_DIR */
      49             : 
      50             : #define SELINUX_CHILD SELINUX_CHILD_DIR"/selinux_child"
      51             : #define SELINUX_CHILD_LOG_FILE "selinux_child"
      52             : 
      53             : #include <selinux/selinux.h>
      54             : 
      55             : /* fd used by the selinux_child process for logging */
      56             : int selinux_child_debug_fd = -1;
      57             : 
      58             : static struct tevent_req *
      59             : ipa_get_selinux_send(TALLOC_CTX *mem_ctx,
      60             :                      struct be_ctx *be_ctx,
      61             :                      struct sysdb_attrs *user,
      62             :                      struct sysdb_attrs *host,
      63             :                      struct ipa_selinux_ctx *selinux_ctx);
      64             : static errno_t ipa_get_selinux_recv(struct tevent_req *req,
      65             :                                     TALLOC_CTX *mem_ctx,
      66             :                                     size_t *count,
      67             :                                     struct sysdb_attrs ***maps,
      68             :                                     size_t *hbac_count,
      69             :                                     struct sysdb_attrs ***hbac_rules,
      70             :                                     char **default_user,
      71             :                                     char **map_order);
      72             : 
      73             : static struct ipa_selinux_op_ctx *
      74             : ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
      75             :                           struct sss_domain_info *ipa_domain,
      76             :                           struct sss_domain_info *user_domain,
      77             :                           struct be_req *be_req, const char *username,
      78             :                           const char *hostname,
      79             :                           struct ipa_selinux_ctx *selinux_ctx);
      80             : static void ipa_selinux_handler_done(struct tevent_req *subreq);
      81             : 
      82             : static void ipa_get_selinux_connect_done(struct tevent_req *subreq);
      83             : static void ipa_get_selinux_hosts_done(struct tevent_req *subreq);
      84             : static void ipa_get_config_step(struct tevent_req *req);
      85             : static void ipa_get_selinux_config_done(struct tevent_req *subreq);
      86             : static void ipa_get_selinux_maps_done(struct tevent_req *subreq);
      87             : static void ipa_get_selinux_hbac_done(struct tevent_req *subreq);
      88             : static errno_t ipa_selinux_process_maps(TALLOC_CTX *mem_ctx,
      89             :                                         struct sysdb_attrs *user,
      90             :                                         struct sysdb_attrs *host,
      91             :                                         struct sysdb_attrs **selinux_maps,
      92             :                                         size_t selinux_map_count,
      93             :                                         struct sysdb_attrs **hbac_rules,
      94             :                                         size_t hbac_rule_count,
      95             :                                         struct sysdb_attrs ***usermaps);
      96             : 
      97             : struct ipa_selinux_op_ctx {
      98             :     struct be_req *be_req;
      99             :     struct sss_domain_info *user_domain;
     100             :     struct sss_domain_info *ipa_domain;
     101             :     struct ipa_selinux_ctx *selinux_ctx;
     102             : 
     103             :     struct sysdb_attrs *user;
     104             :     struct sysdb_attrs *host;
     105             : };
     106             : 
     107           0 : void ipa_selinux_handler(struct be_req *be_req)
     108             : {
     109           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
     110             :     struct ipa_selinux_ctx *selinux_ctx;
     111             :     struct ipa_selinux_op_ctx *op_ctx;
     112             :     struct tevent_req *req;
     113             :     struct pam_data *pd;
     114             :     const char *hostname;
     115             :     struct sss_domain_info *user_domain;
     116             :     struct be_ctx *subdom_be_ctx;
     117             : 
     118           0 :     pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
     119             : 
     120           0 :     selinux_ctx = talloc_get_type(be_ctx->bet_info[BET_SELINUX].pvt_bet_data,
     121             :                                   struct ipa_selinux_ctx);
     122             : 
     123           0 :     hostname = dp_opt_get_string(selinux_ctx->id_ctx->ipa_options->basic,
     124             :                                  IPA_HOSTNAME);
     125           0 :     if (!hostname) {
     126           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot determine this machine's host name\n");
     127           0 :         goto fail;
     128             :     }
     129             : 
     130           0 :     if (strcasecmp(pd->domain, be_ctx->domain->name) != 0) {
     131           0 :         subdom_be_ctx = ipa_get_subdomains_be_ctx(be_ctx);
     132           0 :         if (subdom_be_ctx == NULL) {
     133           0 :             DEBUG(SSSDBG_OP_FAILURE, "Subdomains are not configured, " \
     134             :                                       "cannot lookup domain [%s].\n",
     135             :                                        pd->domain);
     136           0 :             goto fail;
     137             :         } else {
     138           0 :             user_domain = find_domain_by_name(subdom_be_ctx->domain,
     139           0 :                                               pd->domain, true);
     140           0 :             if (user_domain == NULL) {
     141           0 :                 DEBUG(SSSDBG_MINOR_FAILURE, "No domain entry found " \
     142             :                                              "for [%s].\n", pd->domain);
     143           0 :                 goto fail;
     144             :             }
     145             :         }
     146             :     } else {
     147           0 :         user_domain = be_ctx->domain;
     148             :     }
     149             : 
     150           0 :     op_ctx = ipa_selinux_create_op_ctx(be_req, user_domain->sysdb,
     151             :                                        be_ctx->domain,
     152             :                                        user_domain,
     153           0 :                                        be_req, pd->user, hostname,
     154             :                                        selinux_ctx);
     155           0 :     if (op_ctx == NULL) {
     156           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot create op context\n");
     157           0 :         goto fail;
     158             :     }
     159             : 
     160           0 :     req = ipa_get_selinux_send(be_req, be_ctx,
     161             :                                op_ctx->user, op_ctx->host, selinux_ctx);
     162           0 :     if (req == NULL) {
     163           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot initiate the search\n");
     164           0 :         goto fail;
     165             :     }
     166             : 
     167           0 :     tevent_req_set_callback(req, ipa_selinux_handler_done, op_ctx);
     168           0 :     return;
     169             : 
     170             : fail:
     171           0 :     be_req_terminate(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
     172             : }
     173             : 
     174             : static errno_t
     175           0 : ipa_save_user_maps(struct sysdb_ctx *sysdb,
     176             :                    struct sss_domain_info *domain,
     177             :                    size_t map_count,
     178             :                    struct sysdb_attrs **maps)
     179             : {
     180             :     errno_t ret;
     181             :     errno_t sret;
     182           0 :     bool in_transaction = false;
     183             :     int i;
     184             : 
     185           0 :     ret = sysdb_transaction_start(sysdb);
     186           0 :     if (ret) {
     187           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
     188           0 :         goto done;
     189             :     }
     190           0 :     in_transaction = true;
     191             : 
     192           0 :     for (i = 0; i < map_count; i++) {
     193           0 :         ret = sysdb_store_selinux_usermap(domain, maps[i]);
     194           0 :         if (ret != EOK) {
     195           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to store user map %d. "
     196             :                                       "Ignoring.\n", i);
     197             :         } else {
     198           0 :             DEBUG(SSSDBG_TRACE_FUNC, "User map %d processed.\n", i);
     199             :         }
     200             :     }
     201             : 
     202           0 :     ret = sysdb_transaction_commit(sysdb);
     203           0 :     if (ret) {
     204           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction!\n");
     205           0 :         goto done;
     206             :     }
     207           0 :     in_transaction = false;
     208           0 :     ret = EOK;
     209             : 
     210             : done:
     211           0 :     if (in_transaction) {
     212           0 :         sret = sysdb_transaction_cancel(sysdb);
     213           0 :         if (sret != EOK) {
     214           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
     215             :         }
     216             :     }
     217           0 :     return ret;
     218             : }
     219             : 
     220             : static struct ipa_selinux_op_ctx *
     221           0 : ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
     222             :                           struct sss_domain_info *ipa_domain,
     223             :                           struct sss_domain_info *user_domain,
     224             :                           struct be_req *be_req, const char *username,
     225             :                           const char *hostname,
     226             :                           struct ipa_selinux_ctx *selinux_ctx)
     227             : {
     228             :     struct ipa_selinux_op_ctx *op_ctx;
     229             :     struct ldb_dn *host_dn;
     230           0 :     const char *attrs[] = { SYSDB_ORIG_DN,
     231             :                             SYSDB_ORIG_MEMBEROF,
     232             :                             NULL };
     233             :     size_t count;
     234             :     struct ldb_message **msgs;
     235             :     struct sysdb_attrs **hosts;
     236             :     errno_t ret;
     237             : 
     238           0 :     op_ctx = talloc_zero(mem_ctx, struct ipa_selinux_op_ctx);
     239           0 :     if (op_ctx == NULL) {
     240           0 :         return NULL;
     241             :     }
     242           0 :     op_ctx->be_req = be_req;
     243           0 :     op_ctx->ipa_domain = ipa_domain;
     244           0 :     op_ctx->user_domain = user_domain;
     245           0 :     op_ctx->selinux_ctx = selinux_ctx;
     246             : 
     247           0 :     ret = sss_selinux_extract_user(op_ctx, user_domain, username, &op_ctx->user);
     248           0 :     if (ret != EOK) {
     249           0 :         goto fail;
     250             :     }
     251             : 
     252           0 :     host_dn = sysdb_custom_dn(op_ctx, ipa_domain, hostname, HBAC_HOSTS_SUBDIR);
     253           0 :     if (host_dn == NULL) {
     254           0 :         goto fail;
     255             :     }
     256             : 
     257             :     /* Look up the host to get its originalMemberOf entries */
     258           0 :     ret = sysdb_search_entry(op_ctx, sysdb, host_dn,
     259             :                              LDB_SCOPE_BASE, NULL,
     260             :                              attrs, &count, &msgs);
     261           0 :     if (ret == ENOENT || count == 0) {
     262           0 :         op_ctx->host = NULL;
     263           0 :         return op_ctx;
     264           0 :     } else if (ret != EOK) {
     265           0 :         goto fail;
     266           0 :     } else if (count > 1) {
     267           0 :         DEBUG(SSSDBG_OP_FAILURE, "More than one result for a BASE search!\n");
     268           0 :         goto fail;
     269             :     }
     270             : 
     271           0 :     ret = sysdb_msg2attrs(op_ctx, count, msgs, &hosts);
     272           0 :     talloc_free(msgs);
     273           0 :     if (ret != EOK) {
     274           0 :         goto fail;
     275             :     }
     276             : 
     277           0 :     op_ctx->host = hosts[0];
     278           0 :     return op_ctx;
     279             : 
     280             : fail:
     281           0 :     talloc_free(op_ctx);
     282           0 :     return NULL;
     283             : }
     284             : 
     285             : struct map_order_ctx {
     286             :     char *order;
     287             :     char **order_array;
     288             :     size_t order_count;
     289             : };
     290             : 
     291             : static errno_t init_map_order_ctx(TALLOC_CTX *mem_ctx, const char *map_order,
     292             :                                   struct map_order_ctx **_mo_ctx);
     293             : 
     294             : struct selinux_child_input {
     295             :     const char *seuser;
     296             :     const char *mls_range;
     297             :     const char *username;
     298             : };
     299             : 
     300             : static errno_t choose_best_seuser(TALLOC_CTX *mem_ctx,
     301             :                                   struct sysdb_attrs **usermaps,
     302             :                                   struct pam_data *pd,
     303             :                                   struct sss_domain_info *user_domain,
     304             :                                   struct map_order_ctx *mo_ctx,
     305             :                                   const char *default_user,
     306             :                                   struct selinux_child_input **_sci);
     307             : 
     308             : static struct tevent_req *selinux_child_send(TALLOC_CTX *mem_ctx,
     309             :                                              struct tevent_context *ev,
     310             :                                              struct selinux_child_input *sci);
     311             : static errno_t selinux_child_recv(struct tevent_req *req);
     312             : 
     313             : static void ipa_selinux_child_done(struct tevent_req *child_req);
     314             : 
     315           0 : static void ipa_selinux_handler_done(struct tevent_req *req)
     316             : {
     317           0 :     struct ipa_selinux_op_ctx *op_ctx = tevent_req_callback_data(req, struct ipa_selinux_op_ctx);
     318           0 :     struct be_req *breq = op_ctx->be_req;
     319           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
     320           0 :     struct sysdb_ctx *sysdb = op_ctx->ipa_domain->sysdb;
     321             :     errno_t ret, sret;
     322           0 :     size_t map_count = 0;
     323           0 :     struct sysdb_attrs **maps = NULL;
     324           0 :     bool in_transaction = false;
     325           0 :     char *default_user = NULL;
     326           0 :     struct pam_data *pd =
     327           0 :                     talloc_get_type(be_req_get_data(breq), struct pam_data);
     328           0 :     char *map_order = NULL;
     329           0 :     size_t hbac_count = 0;
     330           0 :     struct sysdb_attrs **hbac_rules = 0;
     331             :     struct sysdb_attrs **best_match_maps;
     332             :     struct map_order_ctx *map_order_ctx;
     333           0 :     struct selinux_child_input *sci = NULL;
     334             :     struct tevent_req *child_req;
     335             : 
     336           0 :     ret = ipa_get_selinux_recv(req, breq, &map_count, &maps,
     337             :                                &hbac_count, &hbac_rules,
     338             :                                &default_user, &map_order);
     339           0 :     if (ret != EOK) {
     340           0 :         goto fail;
     341             :     }
     342             : 
     343           0 :     ret = sysdb_transaction_start(sysdb);
     344           0 :     if (ret != EOK) {
     345           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
     346           0 :         goto fail;
     347             :     }
     348           0 :     in_transaction = true;
     349             : 
     350           0 :     ret = sysdb_delete_usermaps(op_ctx->ipa_domain);
     351           0 :     if (ret != EOK) {
     352           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     353             :               "Cannot delete existing maps from sysdb\n");
     354           0 :         goto fail;
     355             :     }
     356             : 
     357           0 :     ret = sysdb_store_selinux_config(op_ctx->ipa_domain,
     358             :                                      default_user, map_order);
     359           0 :     if (ret != EOK) {
     360           0 :         goto fail;
     361             :     }
     362             : 
     363           0 :     if (map_count > 0) {
     364           0 :         ret = ipa_save_user_maps(sysdb, op_ctx->ipa_domain, map_count, maps);
     365           0 :         if (ret != EOK) {
     366           0 :             goto fail;
     367             :         }
     368             :     }
     369             : 
     370           0 :     ret = sysdb_transaction_commit(sysdb);
     371           0 :     if (ret != EOK) {
     372           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not commit transaction\n");
     373           0 :         goto fail;
     374             :     }
     375           0 :     in_transaction = false;
     376             : 
     377             :     /* Process the maps and return list of best matches (maps with
     378             :      * highest priority). The input maps are also parent memory
     379             :      * context for the output list of best matches. The best match
     380             :      * maps should never be freed explicitly but always through
     381             :      * their parent (or any indirect parent) */
     382           0 :     ret = ipa_selinux_process_maps(maps, op_ctx->user, op_ctx->host,
     383             :                                    maps, map_count,
     384             :                                    hbac_rules, hbac_count, &best_match_maps);
     385           0 :     if (ret != EOK) {
     386           0 :         goto fail;
     387             :     }
     388             : 
     389           0 :     ret = init_map_order_ctx(op_ctx, map_order, &map_order_ctx);
     390           0 :     if (ret != EOK) {
     391           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     392             :               "Failed to create ordered SELinux users array.\n");
     393           0 :         goto fail;
     394             :     }
     395             : 
     396           0 :     ret = choose_best_seuser(breq,
     397             :                              best_match_maps, pd, op_ctx->user_domain,
     398             :                              map_order_ctx, default_user, &sci);
     399           0 :     if (ret != EOK) {
     400           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     401             :               "Failed to evaluate ordered SELinux users array.\n");
     402           0 :         goto fail;
     403             :     }
     404             : 
     405             :     /* Update the SELinux context in a privileged child as the back end is
     406             :      * running unprivileged
     407             :      */
     408           0 :     child_req = selinux_child_send(breq, be_ctx->ev, sci);
     409           0 :     if (child_req == NULL) {
     410           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "selinux_child_send() failed\n");
     411           0 :         ret = ENOMEM;
     412           0 :         goto fail;
     413             :     }
     414           0 :     tevent_req_set_callback(child_req, ipa_selinux_child_done, op_ctx);
     415           0 :     return;
     416             : 
     417             : fail:
     418           0 :     if (in_transaction) {
     419           0 :         sret = sysdb_transaction_cancel(sysdb);
     420           0 :         if (sret != EOK) {
     421           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
     422             :         }
     423             :     }
     424           0 :     if (ret == EAGAIN) {
     425           0 :         be_req_terminate(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
     426             :     } else {
     427           0 :         be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
     428             :     }
     429             : }
     430             : 
     431           0 : static void ipa_selinux_child_done(struct tevent_req *child_req)
     432             : {
     433             :     errno_t ret;
     434             :     struct ipa_selinux_op_ctx *op_ctx;
     435             :     struct be_req *breq;
     436             :     struct pam_data *pd;
     437             :     struct be_ctx *be_ctx;
     438             : 
     439           0 :     op_ctx = tevent_req_callback_data(child_req, struct ipa_selinux_op_ctx);
     440           0 :     breq = op_ctx->be_req;
     441           0 :     pd = talloc_get_type(be_req_get_data(breq), struct pam_data);
     442           0 :     be_ctx = be_req_get_be_ctx(breq);
     443             : 
     444           0 :     ret = selinux_child_recv(child_req);
     445           0 :     talloc_free(child_req);
     446           0 :     if (ret != EOK) {
     447           0 :         be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
     448           0 :         return;
     449             :     }
     450             : 
     451             :     /* If we got here in online mode, set last_update to current time */
     452           0 :     if (!be_is_offline(be_ctx)) {
     453           0 :         op_ctx->selinux_ctx->last_update = time(NULL);
     454             :     }
     455             : 
     456           0 :     pd->pam_status = PAM_SUCCESS;
     457           0 :     be_req_terminate(breq, DP_ERR_OK, EOK, "Success");
     458             : }
     459             : 
     460             : static errno_t
     461             : ipa_selinux_process_seealso_maps(struct sysdb_attrs *user,
     462             :                                  struct sysdb_attrs *host,
     463             :                                  struct sysdb_attrs **seealso_rules,
     464             :                                  size_t seealso_rules_count,
     465             :                                  struct sysdb_attrs **hbac_rules,
     466             :                                  size_t hbac_rule_count,
     467             :                                  uint32_t top_priority,
     468             :                                  struct sysdb_attrs **usermaps,
     469             :                                  size_t best_match_maps_cnt);
     470             : static errno_t
     471           0 : ipa_selinux_process_maps(TALLOC_CTX *mem_ctx,
     472             :                          struct sysdb_attrs *user,
     473             :                          struct sysdb_attrs *host,
     474             :                          struct sysdb_attrs **selinux_maps,
     475             :                          size_t selinux_map_count,
     476             :                          struct sysdb_attrs **hbac_rules,
     477             :                          size_t hbac_rule_count,
     478             :                          struct sysdb_attrs ***_usermaps)
     479             : {
     480             :     TALLOC_CTX *tmp_ctx;
     481             :     int i;
     482             :     errno_t ret;
     483           0 :     uint32_t priority = 0;
     484           0 :     uint32_t top_priority = 0;
     485             :     struct sysdb_attrs **seealso_rules;
     486           0 :     size_t num_seealso_rules = 0;
     487             :     const char *seealso_str;
     488             :     struct sysdb_attrs **usermaps;
     489           0 :     size_t best_match_maps_cnt = 0;
     490             : 
     491           0 :     tmp_ctx = talloc_new(NULL);
     492           0 :     if (!tmp_ctx) {
     493           0 :         return ENOMEM;
     494             :     }
     495             : 
     496           0 :     seealso_rules = talloc_zero_array(tmp_ctx, struct sysdb_attrs *,
     497             :                                       selinux_map_count + 1);
     498           0 :     if (seealso_rules == NULL) {
     499           0 :         ret = ENOMEM;
     500           0 :         goto done;
     501             :     }
     502             : 
     503           0 :     usermaps = talloc_zero_array(tmp_ctx, struct sysdb_attrs *, selinux_map_count + 1);
     504           0 :     if (usermaps == NULL) {
     505           0 :         ret = ENOMEM;
     506           0 :         goto done;
     507             :     }
     508             : 
     509           0 :     for (i = 0; i < selinux_map_count; i++) {
     510           0 :         if (sss_selinux_match(selinux_maps[i], user, host, &priority)) {
     511           0 :             if (priority < top_priority) {
     512             :                 /* This rule has lower priority than what we already have,
     513             :                  * skip it. */
     514           0 :                 continue;
     515           0 :             } else if (priority > top_priority) {
     516             :                 /* This rule has higher priority, drop what we already have */
     517           0 :                 while (best_match_maps_cnt > 0) {
     518           0 :                     best_match_maps_cnt--;
     519           0 :                     usermaps[best_match_maps_cnt] = NULL;
     520             :                 }
     521           0 :                 top_priority = priority;
     522             :             }
     523             : 
     524           0 :             usermaps[best_match_maps_cnt] = selinux_maps[i];
     525           0 :             best_match_maps_cnt++;
     526             : 
     527           0 :             continue;
     528             :         }
     529             : 
     530             :         /* SELinux map did not matched -> check sealso attribute for
     531             :          * possible HBAC match */
     532           0 :         ret = sysdb_attrs_get_string(selinux_maps[i],
     533             :                                      SYSDB_SELINUX_SEEALSO, &seealso_str);
     534           0 :         if (ret == ENOENT) {
     535           0 :             continue;
     536           0 :         } else if (ret != EOK) {
     537           0 :             goto done;
     538             :         }
     539             : 
     540           0 :         seealso_rules[num_seealso_rules] = selinux_maps[i];
     541           0 :         num_seealso_rules++;
     542             :     }
     543             : 
     544           0 :     ret = ipa_selinux_process_seealso_maps(user, host,
     545             :                                            seealso_rules, num_seealso_rules,
     546             :                                            hbac_rules, hbac_rule_count,
     547             :                                            top_priority, usermaps, best_match_maps_cnt);
     548           0 :     if (ret != EOK) {
     549           0 :         goto done;
     550             :     }
     551             : 
     552           0 :     *_usermaps = talloc_steal(mem_ctx, usermaps);
     553             : 
     554           0 :     ret = EOK;
     555             : done:
     556           0 :     talloc_free(tmp_ctx);
     557           0 :     return ret;
     558             : }
     559             : 
     560             : static errno_t
     561           0 : ipa_selinux_process_seealso_maps(struct sysdb_attrs *user,
     562             :                                  struct sysdb_attrs *host,
     563             :                                  struct sysdb_attrs **seealso_rules,
     564             :                                  size_t seealso_rules_count,
     565             :                                  struct sysdb_attrs **hbac_rules,
     566             :                                  size_t hbac_rule_count,
     567             :                                  uint32_t top_priority,
     568             :                                  struct sysdb_attrs **usermaps,
     569             :                                  size_t best_match_maps_cnt)
     570             : {
     571             :     int i, j;
     572             :     errno_t ret;
     573             :     struct ldb_message_element *el;
     574             :     struct sysdb_attrs *usermap;
     575             :     const char *seealso_dn;
     576             :     const char *hbac_dn;
     577             :     uint32_t priority;
     578             : 
     579           0 :     for (i = 0; i < hbac_rule_count; i++) {
     580           0 :         ret = sysdb_attrs_get_string(hbac_rules[i], SYSDB_ORIG_DN, &hbac_dn);
     581           0 :         if (ret != EOK) {
     582           0 :             return ret;
     583             :         }
     584             : 
     585             :         /* We need to do this translation for further processing. We have to
     586             :          * do it manually because no map was used to retrieve HBAC rules.
     587             :          */
     588           0 :         ret = sysdb_attrs_get_el(hbac_rules[i], IPA_MEMBER_HOST, &el);
     589           0 :         if (ret != EOK) return ret;
     590           0 :         el->name = SYSDB_ORIG_MEMBER_HOST;
     591             : 
     592           0 :         ret = sysdb_attrs_get_el(hbac_rules[i], IPA_MEMBER_USER, &el);
     593           0 :         if (ret != EOK) return ret;
     594           0 :         el->name = SYSDB_ORIG_MEMBER_USER;
     595             : 
     596           0 :         DEBUG(SSSDBG_TRACE_ALL,
     597             :               "Matching HBAC rule %s with SELinux mappings\n", hbac_dn);
     598             : 
     599           0 :         if (!sss_selinux_match(hbac_rules[i], user, host, &priority)) {
     600           0 :             DEBUG(SSSDBG_TRACE_ALL, "Rule did not match\n");
     601           0 :             continue;
     602             :         }
     603             : 
     604             :         /* HBAC rule matched, find if it is in the "possible" list */
     605           0 :         for (j = 0; j < seealso_rules_count; j++) {
     606           0 :             usermap = seealso_rules[j];
     607           0 :             if (usermap == NULL) {
     608           0 :                 continue;
     609             :             }
     610             : 
     611           0 :             ret = sysdb_attrs_get_string(usermap, SYSDB_SELINUX_SEEALSO, &seealso_dn);
     612           0 :             if (ret != EOK) {
     613           0 :                 return ret;
     614             :             }
     615             : 
     616           0 :             if (strcasecmp(hbac_dn, seealso_dn) == 0) {
     617           0 :                 DEBUG(SSSDBG_TRACE_FUNC, "HBAC rule [%s] matched, copying its"
     618             :                                           "attributes to SELinux user map [%s]\n",
     619             :                                           hbac_dn, seealso_dn);
     620             : 
     621             :                 /* Selinux maps priority evaluation removed --DELETE this comment before pushing*/
     622           0 :                 if (priority < top_priority) {
     623             :                     /* This rule has lower priority than what we already have,
     624             :                      * skip it. */
     625           0 :                     continue;
     626           0 :                 } else if (priority > top_priority) {
     627             :                     /* This rule has higher priority, drop what we already have */
     628           0 :                     while (best_match_maps_cnt > 0) {
     629           0 :                         best_match_maps_cnt--;
     630           0 :                         usermaps[best_match_maps_cnt] = NULL;
     631             :                     }
     632           0 :                     top_priority = priority;
     633             :                 }
     634             : 
     635           0 :                 usermaps[best_match_maps_cnt] = usermap;
     636           0 :                 best_match_maps_cnt++;
     637             : 
     638           0 :                 ret = sysdb_attrs_copy_values(hbac_rules[i], usermap, SYSDB_ORIG_MEMBER_USER);
     639           0 :                 if (ret != EOK) {
     640           0 :                     return ret;
     641             :                 }
     642             : 
     643           0 :                 ret = sysdb_attrs_copy_values(hbac_rules[i], usermap, SYSDB_USER_CATEGORY);
     644           0 :                 if (ret != EOK) {
     645           0 :                     return ret;
     646             :                 }
     647             : 
     648             :                 /* Speed up the next iteration */
     649           0 :                 seealso_rules[j] = NULL;
     650             :             }
     651             :         }
     652             :     }
     653             : 
     654           0 :     return EOK;
     655             : }
     656             : 
     657           0 : static errno_t init_map_order_ctx(TALLOC_CTX *mem_ctx, const char *map_order,
     658             :                                   struct map_order_ctx **_mo_ctx)
     659             : {
     660             :     TALLOC_CTX *tmp_ctx;
     661             :     errno_t ret;
     662             :     int i;
     663             :     int len;
     664             :     struct map_order_ctx *mo_ctx;
     665             : 
     666           0 :     tmp_ctx = talloc_new(NULL);
     667           0 :     if (tmp_ctx == NULL) {
     668           0 :         ret = ENOMEM;
     669           0 :         goto done;
     670             :     }
     671             : 
     672           0 :     mo_ctx = talloc(tmp_ctx, struct map_order_ctx);
     673           0 :     if (mo_ctx == NULL) {
     674           0 :         ret = ENOMEM;
     675           0 :         goto done;
     676             :     }
     677             : 
     678             :     /* The "order" string contains one or more SELinux user records
     679             :      * separated by $. Now we need to create an array of string from
     680             :      * this one string. First find out how many elements in the array
     681             :      * will be. This way only one alloc will be necessary for the array
     682             :      */
     683           0 :     mo_ctx->order_count = 1;
     684           0 :     len = strlen(map_order);
     685           0 :     for (i = 0; i < len; i++) {
     686           0 :         if (map_order[i] == '$') mo_ctx->order_count++;
     687             :     }
     688             : 
     689           0 :     mo_ctx->order_array = talloc_array(mo_ctx, char *, mo_ctx->order_count);
     690           0 :     if (mo_ctx->order_array == NULL) {
     691           0 :         ret = ENOMEM;
     692           0 :         goto done;
     693             :     }
     694             : 
     695           0 :     mo_ctx->order = talloc_strdup(mo_ctx, map_order);
     696           0 :     if (mo_ctx->order == NULL) {
     697           0 :         ret = ENOMEM;
     698           0 :         goto done;
     699             :     }
     700             : 
     701             :     /* Now fill the array with pointers to the original string. Also
     702             :      * use binary zeros to make multiple string out of the one.
     703             :      */
     704           0 :     mo_ctx->order_array[0] = mo_ctx->order;
     705           0 :     mo_ctx->order_count = 1;
     706           0 :     for (i = 0; i < len; i++) {
     707           0 :         if (mo_ctx->order[i] == '$') {
     708           0 :             mo_ctx->order[i] = '\0';
     709           0 :             mo_ctx->order_array[mo_ctx->order_count] = &mo_ctx->order[i+1];
     710           0 :             mo_ctx->order_count++;
     711             :         }
     712             :     }
     713             : 
     714           0 :     *_mo_ctx = talloc_steal(mem_ctx, mo_ctx);
     715           0 :     ret = EOK;
     716             : done:
     717           0 :     talloc_free(tmp_ctx);
     718           0 :     return ret;
     719             : }
     720             : 
     721             : static errno_t selinux_child_setup(TALLOC_CTX *mem_ctx,
     722             :                                    const char *orig_name,
     723             :                                    struct sss_domain_info *dom,
     724             :                                    const char *seuser_mls_string,
     725             :                                    struct selinux_child_input **_sci);
     726             : 
     727             : /* Choose best selinux user based on given order and write
     728             :  * the user to selinux login file. */
     729           0 : static errno_t choose_best_seuser(TALLOC_CTX *mem_ctx,
     730             :                                   struct sysdb_attrs **usermaps,
     731             :                                   struct pam_data *pd,
     732             :                                   struct sss_domain_info *user_domain,
     733             :                                   struct map_order_ctx *mo_ctx,
     734             :                                   const char *default_user,
     735             :                                   struct selinux_child_input **_sci)
     736             : {
     737             :     TALLOC_CTX *tmp_ctx;
     738           0 :     char *seuser_mls_str = NULL;
     739             :     const char *tmp_str;
     740             :     errno_t ret;
     741             :     int i, j;
     742             :     struct selinux_child_input *sci;
     743             : 
     744           0 :     tmp_ctx = talloc_new(NULL);
     745           0 :     if (tmp_ctx == NULL) {
     746           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     747           0 :         return ENOMEM;
     748             :     }
     749             : 
     750             :     /* If no maps match, we'll use the default SELinux user from the
     751             :      * config */
     752           0 :     seuser_mls_str = talloc_strdup(tmp_ctx, default_user ? default_user : "");
     753           0 :     if (seuser_mls_str == NULL) {
     754           0 :         ret = ENOMEM;
     755           0 :         goto done;
     756             :     }
     757             : 
     758             :     /* Iterate through the order array and try to find SELinux users
     759             :      * in fetched maps. The order array contains all SELinux users
     760             :      * allowed in the domain in the same order they should appear
     761             :      * in the SELinux config file. If any user from the order array
     762             :      * is not in fetched user maps, it means it should not be allowed
     763             :      * for the user who is just logging in.
     764             :      *
     765             :      * Right now we have empty content of the SELinux config file,
     766             :      * we shall add only those SELinux users that are present both in
     767             :      * the order array and user maps applicable to the user who is
     768             :      * logging in.
     769             :      */
     770           0 :     for (i = 0; i < mo_ctx->order_count; i++) {
     771           0 :         for (j = 0; usermaps[j] != NULL; j++) {
     772           0 :             tmp_str = sss_selinux_map_get_seuser(usermaps[j]);
     773             : 
     774           0 :             if (tmp_str && !strcasecmp(tmp_str, mo_ctx->order_array[i])) {
     775             :                 /* If seuser_mls_str contained something, overwrite it.
     776             :                  * This record has higher priority.
     777             :                  */
     778           0 :                 talloc_zfree(seuser_mls_str);
     779           0 :                 seuser_mls_str = talloc_strdup(tmp_ctx, tmp_str);
     780           0 :                 if (seuser_mls_str == NULL) {
     781           0 :                     ret = ENOMEM;
     782           0 :                     goto done;
     783             :                 }
     784           0 :                 break;
     785             :             }
     786             :         }
     787             :     }
     788             : 
     789           0 :     ret = selinux_child_setup(tmp_ctx, pd->user, user_domain, seuser_mls_str, &sci);
     790           0 :     if (ret != EOK) {
     791           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot set up child input buffer\n");
     792           0 :         goto done;
     793             :     }
     794             : 
     795           0 :     *_sci = talloc_steal(mem_ctx, sci);
     796           0 :     ret = EOK;
     797             : done:
     798           0 :     talloc_free(tmp_ctx);
     799           0 :     return ret;
     800             : }
     801             : 
     802             : static errno_t
     803           0 : selinux_child_setup(TALLOC_CTX *mem_ctx,
     804             :                     const char *orig_name,
     805             :                     struct sss_domain_info *dom,
     806             :                     const char *seuser_mls_string,
     807             :                     struct selinux_child_input **_sci)
     808             : {
     809             :     errno_t ret;
     810             :     char *seuser;
     811             :     const char *mls_range;
     812             :     char *ptr;
     813             :     char *username;
     814             :     char *username_final;
     815           0 :     char *domain_name = NULL;
     816             :     TALLOC_CTX *tmp_ctx;
     817             :     struct selinux_child_input *sci;
     818             : 
     819           0 :     tmp_ctx = talloc_new(NULL);
     820           0 :     if (tmp_ctx == NULL) {
     821           0 :         return ENOMEM;
     822             :     }
     823             : 
     824             :     /* Split seuser and mls_range */
     825           0 :     seuser = talloc_strdup(tmp_ctx, seuser_mls_string);
     826           0 :     if (seuser == NULL) {
     827           0 :         ret = ENOMEM;
     828           0 :         goto done;
     829             :     }
     830             : 
     831           0 :     ptr = seuser;
     832           0 :     while (*ptr != ':' && *ptr != '\0') {
     833           0 :         ptr++;
     834             :     }
     835           0 :     if (*ptr == '\0') {
     836             :         /* No mls_range specified */
     837           0 :         mls_range = "";
     838             :     } else {
     839           0 :         *ptr = '\0'; /* split */
     840           0 :         mls_range = ptr + 1;
     841             :     }
     842             : 
     843             :     /* pam_selinux needs the username in the same format getpwnam() would
     844             :      * return it
     845             :      */
     846           0 :     username = sss_get_cased_name(tmp_ctx, orig_name, dom->case_preserve);
     847           0 :     if (username == NULL) {
     848           0 :         ret = ENOMEM;
     849           0 :         goto done;
     850             :     }
     851             : 
     852           0 :     if (dom->fqnames) {
     853           0 :         ret = sss_parse_name(tmp_ctx, dom->names, username, &domain_name,
     854             :                              NULL);
     855           0 :         if (ret == EOK && domain_name != NULL) {
     856             :             /* username is already a fully qualified name */
     857           0 :             username_final = username;
     858           0 :         } else if ((ret == EOK && domain_name == NULL)
     859           0 :                    || ret == ERR_REGEX_NOMATCH) {
     860           0 :             username_final = talloc_asprintf(tmp_ctx, dom->names->fq_fmt,
     861             :                                              username, dom->name);
     862           0 :             if (username_final == NULL) {
     863           0 :                 ret = ENOMEM;
     864           0 :                 goto done;
     865             :             }
     866             :         } else {
     867           0 :             DEBUG(SSSDBG_OP_FAILURE,
     868             :                   "sss_parse_name failed: [%d] %s\n", ret, sss_strerror(ret));
     869           0 :             goto done;
     870             :         }
     871             :     } else {
     872           0 :         username_final = username;
     873             :     }
     874             : 
     875           0 :     sci = talloc(tmp_ctx, struct selinux_child_input);
     876           0 :     if (sci == NULL) {
     877           0 :         ret = ENOMEM;
     878           0 :         goto done;
     879             :     }
     880             : 
     881           0 :     sci->seuser = talloc_strdup(sci, seuser);
     882           0 :     sci->mls_range = talloc_strdup(sci, mls_range);
     883           0 :     sci->username = talloc_strdup(sci, username_final);
     884           0 :     if (sci->seuser == NULL || sci->mls_range == NULL
     885           0 :         || sci->username == NULL) {
     886           0 :         ret = ENOMEM;
     887           0 :         goto done;
     888             :     }
     889             : 
     890           0 :     *_sci = talloc_steal(mem_ctx, sci);
     891           0 :     ret = EOK;
     892             : done:
     893           0 :     talloc_free(tmp_ctx);
     894           0 :     return ret;
     895             : }
     896             : 
     897             : struct selinux_child_state {
     898             :     struct selinux_child_input *sci;
     899             :     struct tevent_context *ev;
     900             :     struct io_buffer *buf;
     901             :     struct child_io_fds *io;
     902             : };
     903             : 
     904             : static errno_t selinux_child_init(void);
     905             : static errno_t selinux_child_create_buffer(struct selinux_child_state *state);
     906             : static errno_t selinux_fork_child(struct selinux_child_state *state);
     907             : static void selinux_child_step(struct tevent_req *subreq);
     908             : static void selinux_child_done(struct tevent_req *subreq);
     909             : static errno_t selinux_child_parse_response(uint8_t *buf, ssize_t len,
     910             :                                             uint32_t *_child_result);
     911             : 
     912           0 : static struct tevent_req *selinux_child_send(TALLOC_CTX *mem_ctx,
     913             :                                              struct tevent_context *ev,
     914             :                                              struct selinux_child_input *sci)
     915             : {
     916             :     struct tevent_req *req;
     917             :     struct tevent_req *subreq;
     918             :     struct selinux_child_state *state;
     919             :     errno_t ret;
     920             : 
     921           0 :     req = tevent_req_create(mem_ctx, &state, struct selinux_child_state);
     922           0 :     if (req == NULL) {
     923           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     924           0 :         return NULL;
     925             :     }
     926             : 
     927           0 :     state->sci = sci;
     928           0 :     state->ev = ev;
     929           0 :     state->io = talloc(state, struct child_io_fds);
     930           0 :     state->buf = talloc(state, struct io_buffer);
     931           0 :     if (state->io == NULL || state->buf == NULL) {
     932           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
     933           0 :         ret = ENOMEM;
     934           0 :         goto immediately;
     935             :     }
     936             : 
     937           0 :     state->io->write_to_child_fd = -1;
     938           0 :     state->io->read_from_child_fd = -1;
     939           0 :     talloc_set_destructor((void *) state->io, child_io_destructor);
     940             : 
     941           0 :     ret = selinux_child_init();
     942           0 :     if (ret != EOK) {
     943           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to init the child\n");
     944           0 :         goto immediately;
     945             :     }
     946             : 
     947           0 :     ret = selinux_child_create_buffer(state);
     948           0 :     if (ret != EOK) {
     949           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to create the send buffer\n");
     950           0 :         ret = ENOMEM;
     951           0 :         goto immediately;
     952             :     }
     953             : 
     954           0 :     ret = selinux_fork_child(state);
     955           0 :     if (ret != EOK) {
     956           0 :         DEBUG(SSSDBG_OP_FAILURE, "Failed to fork the child\n");
     957           0 :         goto immediately;
     958             :     }
     959             : 
     960           0 :     subreq = write_pipe_send(state, ev, state->buf->data, state->buf->size,
     961           0 :                              state->io->write_to_child_fd);
     962           0 :     if (subreq == NULL) {
     963           0 :         ret = ENOMEM;
     964           0 :         goto immediately;
     965             :     }
     966           0 :     tevent_req_set_callback(subreq, selinux_child_step, req);
     967             : 
     968           0 :     ret = EOK;
     969             : immediately:
     970           0 :     if (ret != EOK) {
     971           0 :         tevent_req_error(req, ret);
     972           0 :         tevent_req_post(req, ev);
     973             :     }
     974           0 :     return req;
     975             : }
     976             : 
     977           0 : static errno_t selinux_child_init(void)
     978             : {
     979           0 :     return child_debug_init(SELINUX_CHILD_LOG_FILE, &selinux_child_debug_fd);
     980             : }
     981             : 
     982           0 : static errno_t selinux_child_create_buffer(struct selinux_child_state *state)
     983             : {
     984             :     size_t rp;
     985             :     size_t seuser_len;
     986             :     size_t mls_range_len;
     987             :     size_t username_len;
     988             : 
     989           0 :     seuser_len = strlen(state->sci->seuser);
     990           0 :     mls_range_len = strlen(state->sci->mls_range);
     991           0 :     username_len = strlen(state->sci->username);
     992             : 
     993           0 :     state->buf->size = 3 * sizeof(uint32_t);
     994           0 :     state->buf->size += seuser_len + mls_range_len + username_len;
     995             : 
     996           0 :     DEBUG(SSSDBG_TRACE_ALL, "buffer size: %zu\n", state->buf->size);
     997             : 
     998           0 :     state->buf->data = talloc_size(state->buf, state->buf->size);
     999           0 :     if (state->buf->data == NULL) {
    1000           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
    1001           0 :         return ENOMEM;
    1002             :     }
    1003             : 
    1004           0 :     rp = 0;
    1005             : 
    1006             :     /* seuser */
    1007           0 :     SAFEALIGN_SET_UINT32(&state->buf->data[rp], seuser_len, &rp);
    1008           0 :     safealign_memcpy(&state->buf->data[rp], state->sci->seuser,
    1009             :                      seuser_len, &rp);
    1010             : 
    1011             :     /* mls_range */
    1012           0 :     SAFEALIGN_SET_UINT32(&state->buf->data[rp], mls_range_len, &rp);
    1013           0 :     safealign_memcpy(&state->buf->data[rp], state->sci->mls_range,
    1014             :                      mls_range_len, &rp);
    1015             : 
    1016             :     /* username */
    1017           0 :     SAFEALIGN_SET_UINT32(&state->buf->data[rp], username_len, &rp);
    1018           0 :     safealign_memcpy(&state->buf->data[rp], state->sci->username,
    1019             :                      username_len, &rp);
    1020             : 
    1021           0 :     return EOK;
    1022             : }
    1023             : 
    1024           0 : static errno_t selinux_fork_child(struct selinux_child_state *state)
    1025             : {
    1026             :     int pipefd_to_child[2];
    1027             :     int pipefd_from_child[2];
    1028             :     pid_t pid;
    1029             :     errno_t ret;
    1030             : 
    1031           0 :     ret = pipe(pipefd_from_child);
    1032           0 :     if (ret == -1) {
    1033           0 :         ret = errno;
    1034           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1035             :               "pipe failed [%d][%s].\n", errno, sss_strerror(errno));
    1036           0 :         return ret;
    1037             :     }
    1038             : 
    1039           0 :     ret = pipe(pipefd_to_child);
    1040           0 :     if (ret == -1) {
    1041           0 :         ret = errno;
    1042           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1043             :               "pipe failed [%d][%s].\n", errno, sss_strerror(errno));
    1044           0 :         return ret;
    1045             :     }
    1046             : 
    1047           0 :     pid = fork();
    1048             : 
    1049           0 :     if (pid == 0) { /* child */
    1050           0 :         ret = exec_child(state,
    1051             :                          pipefd_to_child, pipefd_from_child,
    1052             :                          SELINUX_CHILD, selinux_child_debug_fd);
    1053           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec selinux_child: [%d][%s].\n",
    1054             :               ret, sss_strerror(ret));
    1055           0 :         return ret;
    1056           0 :     } else if (pid > 0) { /* parent */
    1057           0 :         state->io->read_from_child_fd = pipefd_from_child[0];
    1058           0 :         close(pipefd_from_child[1]);
    1059           0 :         state->io->write_to_child_fd = pipefd_to_child[1];
    1060           0 :         close(pipefd_to_child[0]);
    1061           0 :         sss_fd_nonblocking(state->io->read_from_child_fd);
    1062           0 :         sss_fd_nonblocking(state->io->write_to_child_fd);
    1063             : 
    1064           0 :         ret = child_handler_setup(state->ev, pid, NULL, NULL, NULL);
    1065           0 :         if (ret != EOK) {
    1066           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
    1067             :                   "Could not set up child signal handler\n");
    1068           0 :             return ret;
    1069             :         }
    1070             :     } else { /* error */
    1071           0 :         ret = errno;
    1072           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1073             :               "fork failed [%d][%s].\n", errno, sss_strerror(errno));
    1074           0 :         return ret;
    1075             :     }
    1076             : 
    1077           0 :     return EOK;
    1078             : }
    1079             : 
    1080           0 : static void selinux_child_step(struct tevent_req *subreq)
    1081             : {
    1082             :     struct tevent_req *req;
    1083             :     errno_t ret;
    1084             :     struct selinux_child_state *state;
    1085             : 
    1086             : 
    1087           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1088           0 :     state = tevent_req_data(req, struct selinux_child_state);
    1089             : 
    1090           0 :     ret = write_pipe_recv(subreq);
    1091           0 :     talloc_zfree(subreq);
    1092           0 :     if (ret != EOK) {
    1093           0 :         tevent_req_error(req, ret);
    1094           0 :         return;
    1095             :     }
    1096             : 
    1097           0 :     close(state->io->write_to_child_fd);
    1098           0 :     state->io->write_to_child_fd = -1;
    1099             : 
    1100           0 :     subreq = read_pipe_send(state, state->ev, state->io->read_from_child_fd);
    1101           0 :     if (subreq == NULL) {
    1102           0 :         tevent_req_error(req, ENOMEM);
    1103           0 :         return;
    1104             :     }
    1105           0 :     tevent_req_set_callback(subreq, selinux_child_done, req);
    1106             : }
    1107             : 
    1108           0 : static void selinux_child_done(struct tevent_req *subreq)
    1109             : {
    1110             :     struct tevent_req *req;
    1111             :     struct selinux_child_state *state;
    1112             :     uint32_t child_result;
    1113             :     errno_t ret;
    1114             :     ssize_t len;
    1115             :     uint8_t *buf;
    1116             : 
    1117           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1118           0 :     state = tevent_req_data(req, struct selinux_child_state);
    1119             : 
    1120           0 :     ret = read_pipe_recv(subreq, state, &buf, &len);
    1121           0 :     talloc_zfree(subreq);
    1122           0 :     if (ret != EOK) {
    1123           0 :         tevent_req_error(req, ret);
    1124           0 :         return;
    1125             :     }
    1126             : 
    1127           0 :     close(state->io->read_from_child_fd);
    1128           0 :     state->io->read_from_child_fd = -1;
    1129             : 
    1130           0 :     ret = selinux_child_parse_response(buf, len, &child_result);
    1131           0 :     if (ret != EOK) {
    1132           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1133             :               "selinux_child_parse_response failed: [%d][%s]\n",
    1134             :               ret, strerror(ret));
    1135           0 :         tevent_req_error(req, ret);
    1136           0 :         return;
    1137           0 :     } else if (child_result != 0){
    1138           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1139             :               "Error in selinux_child: [%d][%s]\n",
    1140             :               child_result, strerror(child_result));
    1141           0 :         tevent_req_error(req, ERR_SELINUX_CONTEXT);
    1142           0 :         return;
    1143             :     }
    1144             : 
    1145           0 :     tevent_req_done(req);
    1146           0 :     return;
    1147             : }
    1148             : 
    1149           0 : static errno_t selinux_child_parse_response(uint8_t *buf,
    1150             :                                             ssize_t len,
    1151             :                                             uint32_t *_child_result)
    1152             : {
    1153           0 :     size_t p = 0;
    1154             :     uint32_t child_result;
    1155             : 
    1156             :     /* semanage retval */
    1157           0 :     SAFEALIGN_COPY_UINT32_CHECK(&child_result, buf + p, len, &p);
    1158             : 
    1159           0 :     *_child_result = child_result;
    1160           0 :     return EOK;
    1161             : }
    1162             : 
    1163           0 : static errno_t selinux_child_recv(struct tevent_req *req)
    1164             : {
    1165           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1166           0 :     return EOK;
    1167             : }
    1168             : 
    1169             : /* A more generic request to gather all SELinux and HBAC rules. Updates
    1170             :  * cache if necessary
    1171             :  */
    1172             : struct ipa_get_selinux_state {
    1173             :     struct be_ctx *be_ctx;
    1174             :     struct ipa_selinux_ctx *selinux_ctx;
    1175             :     struct sdap_id_op *op;
    1176             : 
    1177             :     struct sysdb_attrs *host;
    1178             :     struct sysdb_attrs *user;
    1179             : 
    1180             :     struct sysdb_attrs *defaults;
    1181             :     struct sysdb_attrs **selinuxmaps;
    1182             :     size_t nmaps;
    1183             : 
    1184             :     struct sysdb_attrs **hbac_rules;
    1185             :     size_t hbac_rule_count;
    1186             : };
    1187             : 
    1188             : static errno_t
    1189             : ipa_get_selinux_maps_offline(struct tevent_req *req);
    1190             : 
    1191             : static struct tevent_req *
    1192           0 : ipa_get_selinux_send(TALLOC_CTX *mem_ctx,
    1193             :                      struct be_ctx *be_ctx,
    1194             :                      struct sysdb_attrs *user,
    1195             :                      struct sysdb_attrs *host,
    1196             :                      struct ipa_selinux_ctx *selinux_ctx)
    1197             : {
    1198             :     struct tevent_req *req;
    1199             :     struct tevent_req *subreq;
    1200             :     struct ipa_get_selinux_state *state;
    1201             :     bool offline;
    1202           0 :     int ret = EOK;
    1203             :     time_t now;
    1204             :     time_t refresh_interval;
    1205           0 :     struct ipa_options *ipa_options = selinux_ctx->id_ctx->ipa_options;
    1206             : 
    1207           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Retrieving SELinux user mapping\n");
    1208           0 :     req = tevent_req_create(mem_ctx, &state, struct ipa_get_selinux_state);
    1209           0 :     if (req == NULL) {
    1210           0 :         return NULL;
    1211             :     }
    1212             : 
    1213           0 :     state->be_ctx = be_ctx;
    1214           0 :     state->selinux_ctx = selinux_ctx;
    1215           0 :     state->user = user;
    1216           0 :     state->host = host;
    1217             : 
    1218           0 :     offline = be_is_offline(be_ctx);
    1219           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Connection status is [%s].\n",
    1220             :                                   offline ? "offline" : "online");
    1221             : 
    1222           0 :     if (!offline) {
    1223           0 :         refresh_interval = dp_opt_get_int(ipa_options->basic,
    1224             :                                           IPA_SELINUX_REFRESH);
    1225           0 :         now = time(NULL);
    1226           0 :         if (now < selinux_ctx->last_update + refresh_interval) {
    1227             :             /* SELinux maps were recently updated -> force offline */
    1228           0 :             DEBUG(SSSDBG_TRACE_INTERNAL,
    1229             :                   "Performing cached SELinux processing\n");
    1230           0 :             offline = true;
    1231             :         }
    1232             :     }
    1233             : 
    1234           0 :     if (!offline) {
    1235           0 :         state->op = sdap_id_op_create(state,
    1236           0 :                         selinux_ctx->id_ctx->sdap_id_ctx->conn->conn_cache);
    1237           0 :         if (!state->op) {
    1238           0 :             DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
    1239           0 :             ret = ENOMEM;
    1240           0 :             goto immediate;
    1241             :         }
    1242             : 
    1243           0 :         subreq = sdap_id_op_connect_send(state->op, state, &ret);
    1244           0 :         if (!subreq) {
    1245           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send failed: "
    1246             :                                         "%d(%s).\n", ret, strerror(ret));
    1247           0 :             talloc_zfree(state->op);
    1248           0 :             goto immediate;
    1249             :         }
    1250             : 
    1251           0 :         tevent_req_set_callback(subreq, ipa_get_selinux_connect_done, req);
    1252             :     } else {
    1253           0 :         ret = ipa_get_selinux_maps_offline(req);
    1254           0 :         goto immediate;
    1255             :     }
    1256             : 
    1257           0 :     return req;
    1258             : 
    1259             : immediate:
    1260           0 :     if (ret == EOK) {
    1261           0 :         tevent_req_done(req);
    1262             :     } else {
    1263           0 :         tevent_req_error(req, ret);
    1264             :     }
    1265           0 :     tevent_req_post(req, be_ctx->ev);
    1266           0 :     return req;
    1267             : }
    1268             : 
    1269           0 : static void ipa_get_selinux_connect_done(struct tevent_req *subreq)
    1270             : {
    1271           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1272             :                                                   struct tevent_req);
    1273           0 :     struct ipa_get_selinux_state *state = tevent_req_data(req,
    1274             :                                                   struct ipa_get_selinux_state);
    1275           0 :     int dp_error = DP_ERR_FATAL;
    1276             :     int ret;
    1277           0 :     struct ipa_id_ctx *id_ctx = state->selinux_ctx->id_ctx;
    1278             : 
    1279             :     const char *access_name;
    1280             :     const char *selinux_name;
    1281             :     const char *hostname;
    1282             : 
    1283           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
    1284           0 :     talloc_zfree(subreq);
    1285             : 
    1286           0 :     if (dp_error == DP_ERR_OFFLINE) {
    1287           0 :         talloc_zfree(state->op);
    1288           0 :         ret = ipa_get_selinux_maps_offline(req);
    1289           0 :         if (ret == EOK) {
    1290           0 :             tevent_req_done(req);
    1291           0 :             return;
    1292             :         }
    1293           0 :         goto fail;
    1294             :     }
    1295             : 
    1296           0 :     if (ret != EOK) {
    1297           0 :         goto fail;
    1298             :     }
    1299             : 
    1300           0 :     access_name = state->be_ctx->bet_info[BET_ACCESS].mod_name;
    1301           0 :     selinux_name = state->be_ctx->bet_info[BET_SELINUX].mod_name;
    1302           0 :     if (strcasecmp(access_name, selinux_name) == 0 && state->host != NULL) {
    1303             :         /* If the access control module is the same as the selinux module
    1304             :          * and the access control had already discovered the host
    1305             :          */
    1306           0 :         return ipa_get_config_step(req);
    1307             :     }
    1308             : 
    1309           0 :     hostname = dp_opt_get_string(state->selinux_ctx->id_ctx->ipa_options->basic,
    1310             :                                         IPA_HOSTNAME);
    1311           0 :     if (hostname == NULL) {
    1312           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot determine the host name\n");
    1313           0 :         goto fail;
    1314             :     }
    1315             : 
    1316           0 :     subreq = ipa_host_info_send(state, state->be_ctx->ev,
    1317             :                                 sdap_id_op_handle(state->op),
    1318           0 :                                 id_ctx->sdap_id_ctx->opts,
    1319             :                                 hostname,
    1320           0 :                                 id_ctx->ipa_options->host_map,
    1321             :                                 NULL,
    1322           0 :                                 state->selinux_ctx->host_search_bases);
    1323           0 :     if (subreq == NULL) {
    1324           0 :         ret = ENOMEM;
    1325           0 :         goto fail;
    1326             :     }
    1327             : 
    1328           0 :     tevent_req_set_callback(subreq, ipa_get_selinux_hosts_done, req);
    1329           0 :     return;
    1330             : 
    1331             : fail:
    1332           0 :     tevent_req_error(req, ret);
    1333             : }
    1334             : 
    1335             : static errno_t
    1336           0 : ipa_get_selinux_maps_offline(struct tevent_req *req)
    1337             : {
    1338             :     errno_t ret;
    1339             :     size_t nmaps;
    1340             :     struct ldb_message **maps;
    1341             :     struct ldb_message *defaults;
    1342           0 :     const char *attrs[] = { SYSDB_NAME,
    1343             :                             SYSDB_USER_CATEGORY,
    1344             :                             SYSDB_HOST_CATEGORY,
    1345             :                             SYSDB_ORIG_MEMBER_USER,
    1346             :                             SYSDB_ORIG_MEMBER_HOST,
    1347             :                             SYSDB_SELINUX_SEEALSO,
    1348             :                             SYSDB_SELINUX_USER,
    1349             :                             NULL };
    1350             :     const char *default_user;
    1351             :     const char *order;
    1352             : 
    1353           0 :     struct ipa_get_selinux_state *state = tevent_req_data(req,
    1354             :                                                   struct ipa_get_selinux_state);
    1355             : 
    1356             :     /* read the config entry */
    1357           0 :     ret = sysdb_search_selinux_config(state, state->be_ctx->domain,
    1358             :                                       NULL, &defaults);
    1359           0 :     if (ret != EOK) {
    1360           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_selinux_config failed [%d]: %s\n",
    1361             :                                   ret, strerror(ret));
    1362           0 :         return ret;
    1363             :     }
    1364             : 
    1365           0 :     default_user = ldb_msg_find_attr_as_string(defaults,
    1366             :                                                SYSDB_SELINUX_DEFAULT_USER,
    1367             :                                                NULL);
    1368           0 :     order = ldb_msg_find_attr_as_string(defaults, SYSDB_SELINUX_DEFAULT_ORDER,
    1369             :                                         NULL);
    1370             : 
    1371           0 :     state->defaults = sysdb_new_attrs(state);
    1372           0 :     if (state->defaults == NULL) {
    1373           0 :         return ENOMEM;
    1374             :     }
    1375             : 
    1376           0 :     if (default_user) {
    1377           0 :         ret = sysdb_attrs_add_string(state->defaults,
    1378             :                                     IPA_CONFIG_SELINUX_DEFAULT_USER_CTX,
    1379             :                                     default_user);
    1380           0 :         if (ret != EOK) {
    1381           0 :             return ret;
    1382             :         }
    1383             :     }
    1384             : 
    1385           0 :     ret = sysdb_attrs_add_string(state->defaults,
    1386             :                                  IPA_CONFIG_SELINUX_MAP_ORDER, order);
    1387           0 :     if (ret != EOK) {
    1388           0 :         return ret;
    1389             :     }
    1390             : 
    1391             :     /* read all the SELinux rules */
    1392           0 :     ret = sysdb_get_selinux_usermaps(state, state->be_ctx->domain,
    1393             :                                      attrs, &nmaps, &maps);
    1394           0 :     if (ret != EOK) {
    1395           0 :         DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_selinux_usermaps failed [%d]: %s\n",
    1396             :                                   ret, strerror(ret));
    1397           0 :         return ret;
    1398             :     }
    1399             : 
    1400           0 :     ret = sysdb_msg2attrs(state, nmaps, maps, &state->selinuxmaps);
    1401           0 :     if (ret != EOK) {
    1402           0 :         return ret;
    1403             :     }
    1404           0 :     state->nmaps = nmaps;
    1405             : 
    1406             :     /* read all the HBAC rules */
    1407           0 :     ret = hbac_get_cached_rules(state, state->be_ctx->domain,
    1408             :                                 &state->hbac_rule_count, &state->hbac_rules);
    1409           0 :     if (ret != EOK) {
    1410           0 :         DEBUG(SSSDBG_OP_FAILURE, "hbac_get_cached_rules failed [%d]: %s\n",
    1411             :                                   ret, strerror(ret));
    1412           0 :         return ret;
    1413             :     }
    1414             : 
    1415           0 :     return EOK;
    1416             : }
    1417             : 
    1418           0 : static void ipa_get_selinux_hosts_done(struct tevent_req *subreq)
    1419             : {
    1420             :     errno_t ret;
    1421           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1422             :                                                   struct tevent_req);
    1423           0 :     struct ipa_get_selinux_state *state = tevent_req_data(req,
    1424             :                                                   struct ipa_get_selinux_state);
    1425             :     size_t host_count, hostgroup_count;
    1426             :     struct sysdb_attrs **hostgroups;
    1427             :     struct sysdb_attrs **host;
    1428             : 
    1429           0 :     ret = ipa_host_info_recv(subreq, state, &host_count, &host,
    1430             :                              &hostgroup_count, &hostgroups);
    1431           0 :     talloc_free(subreq);
    1432           0 :     if (ret != EOK) {
    1433           0 :         goto done;
    1434             :     }
    1435           0 :     state->host = host[0];
    1436             : 
    1437           0 :     return ipa_get_config_step(req);
    1438             : 
    1439             : done:
    1440           0 :     if (ret != EOK) {
    1441           0 :         tevent_req_error(req, ret);
    1442             :     }
    1443             : }
    1444             : 
    1445           0 : static void ipa_get_config_step(struct tevent_req *req)
    1446             : {
    1447             :     const char *domain;
    1448             :     struct tevent_req *subreq;
    1449           0 :     struct ipa_get_selinux_state *state = tevent_req_data(req,
    1450             :                                                   struct ipa_get_selinux_state);
    1451           0 :     struct ipa_id_ctx *id_ctx = state->selinux_ctx->id_ctx;
    1452             : 
    1453           0 :     domain = dp_opt_get_string(state->selinux_ctx->id_ctx->ipa_options->basic,
    1454             :                                IPA_KRB5_REALM);
    1455           0 :     subreq = ipa_get_config_send(state, state->be_ctx->ev,
    1456             :                                  sdap_id_op_handle(state->op),
    1457           0 :                                  id_ctx->sdap_id_ctx->opts,
    1458             :                                  domain, NULL);
    1459           0 :     if (subreq == NULL) {
    1460           0 :         tevent_req_error(req, ENOMEM);
    1461             :     }
    1462           0 :     tevent_req_set_callback(subreq, ipa_get_selinux_config_done, req);
    1463           0 : }
    1464             : 
    1465           0 : static void ipa_get_selinux_config_done(struct tevent_req *subreq)
    1466             : {
    1467           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1468             :                                                   struct tevent_req);
    1469           0 :     struct ipa_get_selinux_state *state = tevent_req_data(req,
    1470             :                                                   struct ipa_get_selinux_state);
    1471           0 :     struct sdap_id_ctx *id_ctx = state->selinux_ctx->id_ctx->sdap_id_ctx;
    1472             :     errno_t ret;
    1473             : 
    1474           0 :     ret = ipa_get_config_recv(subreq, state, &state->defaults);
    1475           0 :     talloc_free(subreq);
    1476           0 :     if (ret != EOK) {
    1477           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not get IPA config\n");
    1478           0 :         goto done;
    1479             :     }
    1480             : 
    1481           0 :     subreq = ipa_selinux_get_maps_send(state, state->be_ctx->ev,
    1482           0 :                                        state->be_ctx->domain->sysdb,
    1483             :                                      sdap_id_op_handle(state->op),
    1484             :                                      id_ctx->opts,
    1485           0 :                                      state->selinux_ctx->id_ctx->ipa_options,
    1486           0 :                                      state->selinux_ctx->selinux_search_bases);
    1487           0 :     if (!subreq) {
    1488           0 :         ret = ENOMEM;
    1489           0 :         goto done;
    1490             :     }
    1491           0 :     tevent_req_set_callback(subreq, ipa_get_selinux_maps_done, req);
    1492           0 :     return;
    1493             : 
    1494             : done:
    1495           0 :     if (ret != EOK) {
    1496           0 :         tevent_req_error(req, ret);
    1497             :     } else {
    1498           0 :         tevent_req_done(req);
    1499             :     }
    1500             : }
    1501             : 
    1502           0 : static void ipa_get_selinux_maps_done(struct tevent_req *subreq)
    1503             : {
    1504             :     struct tevent_req *req;
    1505             :     struct ipa_get_selinux_state *state;
    1506             : 
    1507             :     struct ipa_id_ctx *id_ctx;
    1508             : 
    1509             :     char *selinux_name;
    1510             :     char *access_name;
    1511             : 
    1512             :     const char *tmp_str;
    1513             :     bool check_hbac;
    1514             :     errno_t ret;
    1515             :     int i;
    1516             : 
    1517           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1518           0 :     state = tevent_req_data(req, struct ipa_get_selinux_state);
    1519           0 :     id_ctx = state->selinux_ctx->id_ctx;
    1520             : 
    1521           0 :     ret = ipa_selinux_get_maps_recv(subreq, state,
    1522             :                                     &state->nmaps, &state->selinuxmaps);
    1523           0 :     talloc_free(subreq);
    1524           0 :     if (ret != EOK) {
    1525           0 :         if (ret == ENOENT) {
    1526             :             /* This is returned if no SELinux mapping
    1527             :              * rules were found. In that case no error
    1528             :              * occurred, but we don't want any more processing.*/
    1529           0 :             ret = EOK;
    1530             :         }
    1531           0 :         goto done;
    1532             :     }
    1533             : 
    1534           0 :     DEBUG(SSSDBG_TRACE_FUNC,
    1535             :          "Found %zu SELinux user maps\n", state->nmaps);
    1536             : 
    1537           0 :     check_hbac = false;
    1538           0 :     for (i = 0; i < state->nmaps; i++) {
    1539           0 :         ret = sysdb_attrs_get_string(state->selinuxmaps[i],
    1540             :                                      SYSDB_SELINUX_SEEALSO, &tmp_str);
    1541           0 :         if (ret == EOK) {
    1542           0 :             check_hbac = true;
    1543           0 :             break;
    1544             :         }
    1545             :     }
    1546             : 
    1547           0 :     if (check_hbac) {
    1548           0 :         access_name = state->be_ctx->bet_info[BET_ACCESS].mod_name;
    1549           0 :         selinux_name = state->be_ctx->bet_info[BET_SELINUX].mod_name;
    1550           0 :         if (strcasecmp(access_name, selinux_name) == 0) {
    1551           0 :             ret = hbac_get_cached_rules(state, state->be_ctx->domain,
    1552             :                                         &state->hbac_rule_count,
    1553             :                                         &state->hbac_rules);
    1554             :             /* Terminates the request */
    1555           0 :             goto done;
    1556             :         }
    1557             : 
    1558           0 :         DEBUG(SSSDBG_TRACE_FUNC, "SELinux maps referenced an HBAC rule. "
    1559             :               "Need to refresh HBAC rules\n");
    1560           0 :         subreq = ipa_hbac_rule_info_send(state, state->be_ctx->ev,
    1561             :                                          sdap_id_op_handle(state->op),
    1562           0 :                                          id_ctx->sdap_id_ctx->opts,
    1563           0 :                                          state->selinux_ctx->hbac_search_bases,
    1564             :                                          state->host);
    1565           0 :         if (subreq == NULL) {
    1566           0 :             ret = ENOMEM;
    1567           0 :             goto done;
    1568             :         }
    1569             : 
    1570           0 :         tevent_req_set_callback(subreq, ipa_get_selinux_hbac_done, req);
    1571           0 :         return;
    1572             :     }
    1573             : 
    1574           0 :     ret = EOK;
    1575             : done:
    1576           0 :     if (ret == EOK) {
    1577           0 :         tevent_req_done(req);
    1578             :     } else {
    1579           0 :         tevent_req_error(req, ret);
    1580             :     }
    1581             : }
    1582             : 
    1583           0 : static void ipa_get_selinux_hbac_done(struct tevent_req *subreq)
    1584             : {
    1585           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
    1586             :                                                       struct tevent_req);
    1587           0 :     struct ipa_get_selinux_state *state = tevent_req_data(req,
    1588             :                                                   struct ipa_get_selinux_state);
    1589             :     errno_t ret;
    1590             : 
    1591           0 :     ret = ipa_hbac_rule_info_recv(subreq, state, &state->hbac_rule_count,
    1592             :                                   &state->hbac_rules);
    1593           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
    1594             :           "Received %zu HBAC rules\n", state->hbac_rule_count);
    1595           0 :     talloc_free(subreq);
    1596             : 
    1597           0 :     if (ret != EOK) {
    1598           0 :         tevent_req_error(req, ret);
    1599             :     } else {
    1600           0 :         tevent_req_done(req);
    1601             :     }
    1602           0 : }
    1603             : 
    1604             : static errno_t
    1605           0 : ipa_get_selinux_recv(struct tevent_req *req,
    1606             :                      TALLOC_CTX *mem_ctx,
    1607             :                      size_t *count,
    1608             :                      struct sysdb_attrs ***maps,
    1609             :                      size_t *hbac_count,
    1610             :                      struct sysdb_attrs ***hbac_rules,
    1611             :                      char **default_user,
    1612             :                      char **map_order)
    1613             : {
    1614           0 :     struct ipa_get_selinux_state *state =
    1615           0 :             tevent_req_data(req, struct ipa_get_selinux_state);
    1616             :     const char *tmp_str;
    1617             :     errno_t ret;
    1618             : 
    1619           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1620             : 
    1621           0 :     ret = sysdb_attrs_get_string(state->defaults,
    1622             :                                  IPA_CONFIG_SELINUX_DEFAULT_USER_CTX,
    1623             :                                  &tmp_str);
    1624           0 :     if (ret != EOK && ret != ENOENT) {
    1625           0 :         return ret;
    1626             :     }
    1627             : 
    1628           0 :     if (ret == EOK) {
    1629           0 :         *default_user = talloc_strdup(mem_ctx, tmp_str);
    1630           0 :         if (*default_user == NULL) {
    1631           0 :             return ENOMEM;
    1632             :         }
    1633             :     }
    1634             : 
    1635           0 :     ret = sysdb_attrs_get_string(state->defaults, IPA_CONFIG_SELINUX_MAP_ORDER,
    1636             :                                  &tmp_str);
    1637           0 :     if (ret != EOK) {
    1638           0 :         return ret;
    1639             :     }
    1640             : 
    1641           0 :     *map_order = talloc_strdup(mem_ctx, tmp_str);
    1642           0 :     if (*map_order == NULL) {
    1643           0 :         talloc_zfree(*default_user);
    1644           0 :         return ENOMEM;
    1645             :     }
    1646             : 
    1647           0 :     *count = state->nmaps;
    1648           0 :     *maps = talloc_steal(mem_ctx, state->selinuxmaps);
    1649             : 
    1650           0 :     *hbac_count = state->hbac_rule_count;
    1651           0 :     *hbac_rules = talloc_steal(mem_ctx, state->hbac_rules);
    1652             : 
    1653           0 :     return EOK;
    1654             : }
    1655             : 
    1656             : /*end of #if defined HAVE_SELINUX && defined HAVE_SELINUX_LOGIN_DIR */
    1657             : #else
    1658             : /* Simply return success if HAVE_SELINUX_LOGIN_DIR is not defined. */
    1659             : void ipa_selinux_handler(struct be_req *be_req)
    1660             : {
    1661             :     struct pam_data *pd;
    1662             : 
    1663             :     pd = talloc_get_type(be_req_get_data(be_req), struct pam_data);
    1664             : 
    1665             :     pd->pam_status = PAM_SUCCESS;
    1666             :     be_req_terminate(be_req, DP_ERR_OK, EOK, "Success");
    1667             : }
    1668             : #endif

Generated by: LCOV version 1.10