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

Generated by: LCOV version 1.10