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

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2015 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <ldb.h>
      22             : #include <talloc.h>
      23             : #include <dhash.h>
      24             : 
      25             : #include "providers/ldap/sdap.h"
      26             : #include "providers/ipa/ipa_common.h"
      27             : #include "providers/ipa/ipa_dn.h"
      28             : #include "db/sysdb_sudo.h"
      29             : #include "db/sysdb.h"
      30             : #include "util/util.h"
      31             : 
      32             : #define SUDO_DN_CMDGROUPS "sudocmdgroups"
      33             : #define SUDO_DN_CMDS      "sudocmds"
      34             : #define SUDO_DN_CONTAINER "sudo"
      35             : #define SUDO_DN_CN        "cn"
      36             : 
      37             : #define MATCHDN(cat)      SUDO_DN_CN, (cat), SUDO_DN_CN, SUDO_DN_CONTAINER
      38             : #define MATCHDN_CMDGROUPS MATCHDN(SUDO_DN_CMDGROUPS)
      39             : #define MATCHDN_CMDS      MATCHDN(SUDO_DN_CMDS)
      40             : 
      41             : #define MATCHRDN_CMDGROUPS(map)  (map)[IPA_AT_SUDOCMDGROUP_NAME].name, MATCHDN_CMDGROUPS
      42             : #define MATCHRDN_CMDS(attr, map) (map)[attr].name, MATCHDN_CMDS
      43             : 
      44             : #define MATCHRDN_USER(map)      (map)[SDAP_AT_USER_NAME].name, "cn", "users", "cn", "accounts"
      45             : #define MATCHRDN_GROUP(map)     (map)[SDAP_AT_GROUP_NAME].name, "cn", "groups", "cn", "accounts"
      46             : #define MATCHRDN_HOST(map)      (map)[IPA_AT_HOST_FQDN].name, "cn", "computers", "cn", "accounts"
      47             : #define MATCHRDN_HOSTGROUP(map) (map)[IPA_AT_HOSTGROUP_NAME].name, "cn", "hostgroups", "cn", "accounts"
      48             : 
      49             : struct ipa_sudo_conv {
      50             :     struct sysdb_ctx *sysdb;
      51             : 
      52             :     struct sdap_attr_map *map_rule;
      53             :     struct sdap_attr_map *map_cmdgroup;
      54             :     struct sdap_attr_map *map_cmd;
      55             :     struct sdap_attr_map *map_user;
      56             :     struct sdap_attr_map *map_group;
      57             :     struct sdap_attr_map *map_host;
      58             :     struct sdap_attr_map *map_hostgroup;
      59             : 
      60             :     hash_table_t *rules;
      61             :     hash_table_t *cmdgroups;
      62             :     hash_table_t *cmds;
      63             : };
      64             : 
      65             : struct ipa_sudo_dn_list {
      66             :     struct ipa_sudo_dn_list *prev, *next;
      67             :     const char *dn;
      68             : };
      69             : 
      70             : struct ipa_sudo_rulemember {
      71             :     struct ipa_sudo_dn_list *cmdgroups;
      72             :     struct ipa_sudo_dn_list *cmds;
      73             : };
      74             : 
      75             : struct ipa_sudo_rule {
      76             :     struct sysdb_attrs *attrs;
      77             :     struct ipa_sudo_rulemember allow;
      78             :     struct ipa_sudo_rulemember deny;
      79             : };
      80             : 
      81             : struct ipa_sudo_cmdgroup {
      82             :     struct ipa_sudo_dn_list *cmds;
      83             :     const char **expanded;
      84             : };
      85             : 
      86             : static size_t
      87           0 : ipa_sudo_dn_list_count(struct ipa_sudo_dn_list *list)
      88             : {
      89             :     struct ipa_sudo_dn_list *item;
      90             :     size_t i;
      91             : 
      92           0 :     for (i = 0, item = list; item != NULL; item = item->next, i++) {
      93             :         /* no op */
      94             :     }
      95             : 
      96           0 :     return i;
      97             : }
      98             : 
      99             : static errno_t
     100           0 : ipa_sudo_conv_store(hash_table_t *table,
     101             :                     const char *key,
     102             :                     void *value)
     103             : {
     104             :     hash_key_t hkey;
     105             :     hash_value_t hvalue;
     106             :     int hret;
     107             : 
     108           0 :     if (table == NULL || key == NULL) {
     109           0 :         return EINVAL;
     110             :     }
     111             : 
     112           0 :     hkey.type = HASH_KEY_STRING;
     113           0 :     hkey.str = discard_const(key);
     114             : 
     115             :     /* If value is NULL we don't want to override existing entry. */
     116           0 :     if (value == NULL && hash_has_key(table, &hkey)) {
     117           0 :         return EEXIST;
     118             :     }
     119             : 
     120           0 :     hvalue.type = HASH_VALUE_PTR;
     121           0 :     hvalue.ptr = value;
     122             : 
     123           0 :     hret = hash_enter(table, &hkey, &hvalue);
     124           0 :     if (hret != HASH_SUCCESS) {
     125           0 :         return EIO;
     126             :     }
     127             : 
     128           0 :     if (value != NULL) {
     129           0 :         talloc_steal(table, value);
     130             :     }
     131             : 
     132           0 :     return EOK;
     133             : }
     134             : 
     135             : static void *
     136           0 : ipa_sudo_conv_lookup(hash_table_t *table,
     137             :                      const char *key)
     138             : {
     139             :     hash_key_t hkey;
     140             :     hash_value_t hvalue;
     141             :     int hret;
     142             : 
     143           0 :     hkey.type = HASH_KEY_STRING;
     144           0 :     hkey.str = discard_const(key);
     145             : 
     146           0 :     hret = hash_lookup(table, &hkey, &hvalue);
     147           0 :     if (hret == HASH_ERROR_KEY_NOT_FOUND) {
     148           0 :         DEBUG(SSSDBG_OP_FAILURE, "Key not found %s\n", key);
     149           0 :         return NULL;
     150           0 :     } else if (hret != HASH_SUCCESS) {
     151           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup value [%d]\n", hret);
     152           0 :         return NULL;
     153             :     }
     154             : 
     155           0 :     return hvalue.ptr;
     156             : }
     157             : 
     158             : static errno_t
     159           0 : store_rulemember(TALLOC_CTX *mem_ctx,
     160             :                  struct ipa_sudo_dn_list **list,
     161             :                  hash_table_t *table,
     162             :                  const char *dn)
     163             : {
     164             :     struct ipa_sudo_dn_list *item;
     165             :     errno_t ret;
     166             : 
     167           0 :     item = talloc_zero(mem_ctx, struct ipa_sudo_dn_list);
     168           0 :     if (item == NULL) {
     169           0 :         return ENOMEM;
     170             :     }
     171             : 
     172           0 :     ret = ipa_sudo_conv_store(table, dn, NULL);
     173           0 :     if (ret != EOK && ret != EEXIST) {
     174           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to store DN %s [%d]: %s\n",
     175             :               dn, ret, sss_strerror(ret));
     176           0 :         goto done;
     177             :     }
     178             : 
     179           0 :     item->dn = talloc_steal(item, dn);
     180           0 :     DLIST_ADD(*list, item);
     181             : 
     182             : done:
     183           0 :     if (ret != EOK && ret != EEXIST) {
     184           0 :         talloc_free(item);
     185             :     }
     186             : 
     187           0 :     return ret;
     188             : }
     189             : 
     190           0 : static bool is_ipacmdgroup(struct ipa_sudo_conv *conv, const char *dn)
     191             : {
     192           0 :     if (ipa_check_rdn_bool(conv->sysdb, dn,
     193             :             MATCHRDN_CMDGROUPS(conv->map_cmdgroup))) {
     194           0 :         return true;
     195             :     }
     196             : 
     197           0 :     return false;
     198             : }
     199             : 
     200           0 : static bool is_ipacmd(struct ipa_sudo_conv *conv, const char *dn)
     201             : {
     202           0 :     if (ipa_check_rdn_bool(conv->sysdb, dn,
     203             :             MATCHRDN_CMDS(IPA_AT_SUDOCMD_UUID, conv->map_cmd))) {
     204           0 :         return true;
     205             :     }
     206             : 
     207             :     /* For older versions of FreeIPA than 3.1. */
     208           0 :     if (ipa_check_rdn_bool(conv->sysdb, dn,
     209             :             MATCHRDN_CMDS(IPA_AT_SUDOCMD_CMD, conv->map_cmd))) {
     210           0 :         return true;
     211             :     }
     212             : 
     213           0 :     return false;
     214             : }
     215             : 
     216             : static errno_t
     217           0 : process_rulemember(TALLOC_CTX *mem_ctx,
     218             :                    struct ipa_sudo_conv *conv,
     219             :                    struct ipa_sudo_rulemember *rulemember,
     220             :                    struct sysdb_attrs *rule,
     221             :                    const char *attr)
     222             : {
     223             :     TALLOC_CTX *tmp_ctx;
     224             :     const char **members;
     225             :     errno_t ret;
     226             :     int i;
     227             : 
     228           0 :     tmp_ctx = talloc_new(NULL);
     229           0 :     if (tmp_ctx == NULL) {
     230           0 :         return ENOMEM;
     231             :     }
     232             : 
     233           0 :     ret = sysdb_attrs_get_string_array(rule, attr, tmp_ctx, &members);
     234           0 :     if (ret == ENOENT) {
     235           0 :         ret = EOK;
     236           0 :         goto done;
     237           0 :     } else if (ret != EOK) {
     238           0 :         goto done;
     239             :     }
     240             : 
     241           0 :     for (i = 0; members[i] != NULL; i++) {
     242           0 :         if (is_ipacmdgroup(conv, members[i])) {
     243           0 :             ret = store_rulemember(mem_ctx, &rulemember->cmdgroups,
     244           0 :                                    conv->cmdgroups, members[i]);
     245           0 :             if (ret == EOK) {
     246           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL, "Found sudo command group %s\n",
     247             :                       members[i]);
     248           0 :             } else if (ret != EEXIST) {
     249           0 :                 goto done;
     250             :             }
     251           0 :         } else if (is_ipacmd(conv, members[i])) {
     252           0 :             ret = store_rulemember(mem_ctx, &rulemember->cmds,
     253           0 :                                    conv->cmds, members[i]);
     254           0 :             if (ret == EOK) {
     255           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL, "Found sudo command %s\n",
     256             :                       members[i]);
     257           0 :             } else if (ret != EEXIST) {
     258           0 :                 goto done;
     259             :             }
     260             :         } else {
     261           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Invalid member DN %s, skipping...\n",
     262             :                   members[i]);
     263           0 :             continue;
     264             :         }
     265             :     }
     266             : 
     267           0 :     ret = EOK;
     268             : 
     269             : done:
     270           0 :     talloc_free(tmp_ctx);
     271           0 :     return ret;
     272             : }
     273             : 
     274             : static errno_t
     275           0 : process_allowcmd(struct ipa_sudo_conv *conv,
     276             :                  struct ipa_sudo_rule *rule)
     277             : {
     278           0 :     return process_rulemember(rule, conv, &rule->allow, rule->attrs,
     279             :                               SYSDB_IPA_SUDORULE_ALLOWCMD);
     280             : }
     281             : 
     282             : static errno_t
     283           0 : process_denycmd(struct ipa_sudo_conv *conv,
     284             :                 struct ipa_sudo_rule *rule)
     285             : {
     286           0 :     return process_rulemember(rule, conv, &rule->deny, rule->attrs,
     287             :                               SYSDB_IPA_SUDORULE_DENYCMD);
     288             : }
     289             : 
     290             : static errno_t
     291           0 : process_cmdgroupmember(struct ipa_sudo_conv *conv,
     292             :                        struct ipa_sudo_cmdgroup *cmdgroup,
     293             :                        struct sysdb_attrs *attrs)
     294             : {
     295             :     TALLOC_CTX *tmp_ctx;
     296             :     struct ipa_sudo_dn_list *item;
     297             :     const char **members;
     298             :     errno_t ret;
     299             :     int i;
     300             : 
     301           0 :     tmp_ctx = talloc_new(NULL);
     302           0 :     if (tmp_ctx == NULL) {
     303           0 :         return ENOMEM;
     304             :     }
     305             : 
     306           0 :     ret = sysdb_attrs_get_string_array(attrs, SYSDB_MEMBER, tmp_ctx, &members);
     307           0 :     if (ret == ENOENT) {
     308           0 :         ret = EOK;
     309           0 :         goto done;
     310           0 :     } else if (ret != EOK) {
     311           0 :         goto done;
     312             :     }
     313             : 
     314           0 :     for (i = 0; members[i] != NULL; i++) {
     315           0 :         ret = ipa_sudo_conv_store(conv->cmds, members[i], NULL);
     316           0 :         if (ret == EOK) {
     317           0 :             DEBUG(SSSDBG_TRACE_INTERNAL, "Found sudo command %s\n",
     318             :                   members[i]);
     319           0 :         } else if (ret != EEXIST) {
     320           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to store DN [%d]: %s\n",
     321             :                   ret, sss_strerror(ret));
     322           0 :             goto done;
     323             :         }
     324             : 
     325           0 :         item = talloc_zero(tmp_ctx, struct ipa_sudo_dn_list);
     326           0 :         if (item == NULL) {
     327           0 :             ret = ENOMEM;
     328           0 :             goto done;
     329             :         }
     330             : 
     331           0 :         item->dn = talloc_steal(item, members[i]);
     332           0 :         DLIST_ADD(cmdgroup->cmds, item);
     333           0 :         talloc_steal(cmdgroup, item);
     334             :     }
     335             : 
     336           0 :     ret = EOK;
     337             : 
     338             : done:
     339           0 :     talloc_free(tmp_ctx);
     340           0 :     return ret;
     341             : }
     342             : 
     343             : struct ipa_sudo_conv *
     344           0 : ipa_sudo_conv_init(TALLOC_CTX *mem_ctx,
     345             :                    struct sysdb_ctx *sysdb,
     346             :                    struct sdap_attr_map *map_rule,
     347             :                    struct sdap_attr_map *map_cmdgroup,
     348             :                    struct sdap_attr_map *map_cmd,
     349             :                    struct sdap_attr_map *map_user,
     350             :                    struct sdap_attr_map *map_group,
     351             :                    struct sdap_attr_map *map_host,
     352             :                    struct sdap_attr_map *map_hostgroup)
     353             : {
     354             :     struct ipa_sudo_conv *conv;
     355             :     errno_t ret;
     356             : 
     357           0 :     conv = talloc_zero(mem_ctx, struct ipa_sudo_conv);
     358           0 :     if (conv == NULL) {
     359           0 :         return NULL;
     360             :     }
     361             : 
     362           0 :     conv->sysdb = sysdb;
     363           0 :     conv->map_rule = map_rule;
     364           0 :     conv->map_cmdgroup = map_cmdgroup;
     365           0 :     conv->map_cmd = map_cmd;
     366           0 :     conv->map_user = map_user;
     367           0 :     conv->map_group = map_group;
     368           0 :     conv->map_host = map_host;
     369           0 :     conv->map_hostgroup = map_hostgroup;
     370             : 
     371           0 :     ret = sss_hash_create(conv, 20, &conv->rules);
     372           0 :     if (ret != EOK) {
     373           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create hash table [%d]: %s\n",
     374             :               ret, sss_strerror(ret));
     375           0 :         goto done;
     376             :     }
     377             : 
     378           0 :     ret = sss_hash_create(conv, 20, &conv->cmdgroups);
     379           0 :     if (ret != EOK) {
     380           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create hash table [%d]: %s\n",
     381             :               ret, sss_strerror(ret));
     382           0 :         goto done;
     383             :     }
     384             : 
     385           0 :     ret = sss_hash_create(conv, 20, &conv->cmds);
     386           0 :     if (ret != EOK) {
     387           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create hash table [%d]: %s\n",
     388             :               ret, sss_strerror(ret));
     389           0 :         goto done;
     390             :     }
     391             : 
     392             : done:
     393           0 :     if (ret != EOK) {
     394           0 :         talloc_free(conv);
     395           0 :         return NULL;
     396             :     }
     397             : 
     398           0 :     return conv;
     399             : }
     400             : 
     401             : errno_t
     402           0 : ipa_sudo_conv_rules(struct ipa_sudo_conv *conv,
     403             :                     struct sysdb_attrs **rules,
     404             :                     size_t num_rules)
     405             : {
     406           0 :     struct ipa_sudo_rule *rule = NULL;
     407             :     const char *key;
     408             :     errno_t ret;
     409             :     size_t i;
     410             : 
     411           0 :     if (num_rules == 0) {
     412             :         /* We're done here. */
     413           0 :         return EOK;
     414             :     }
     415             : 
     416           0 :     for (i = 0; i < num_rules; i++) {
     417           0 :         ret = sysdb_attrs_get_string(rules[i], SYSDB_NAME, &key);
     418           0 :         if (ret != EOK) {
     419           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to get rule name, skipping "
     420             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     421           0 :             continue;
     422             :         }
     423             : 
     424           0 :         rule = talloc_zero(conv->rules, struct ipa_sudo_rule);
     425           0 :         if (rule == NULL) {
     426           0 :             ret = ENOMEM;
     427           0 :             goto done;
     428             :         }
     429             : 
     430           0 :         rule->attrs = rules[i];
     431             : 
     432           0 :         ret = process_allowcmd(conv, rule);
     433           0 :         if (ret != EOK && ret != EEXIST) {
     434           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to process memberAllowCmd "
     435             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     436           0 :             return ret;
     437             :         }
     438             : 
     439           0 :         ret = process_denycmd(conv, rule);
     440           0 :         if (ret != EOK && ret != EEXIST) {
     441           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to process memberDenyCmd "
     442             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     443           0 :             return ret;
     444             :         }
     445             : 
     446           0 :         ret = ipa_sudo_conv_store(conv->rules, key, rule);
     447           0 :         if (ret != EOK) {
     448           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to store rule into table "
     449             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     450           0 :             goto done;
     451             :         }
     452             : 
     453           0 :         talloc_steal(rule, rule->attrs);
     454           0 :         rule = NULL;
     455             :     }
     456             : 
     457           0 :     ret = EOK;
     458             : 
     459             : done:
     460           0 :     if (ret != EOK) {
     461           0 :         talloc_free(rule);
     462             :     }
     463             : 
     464           0 :     return ret;
     465             : }
     466             : 
     467             : errno_t
     468           0 : ipa_sudo_conv_cmdgroups(struct ipa_sudo_conv *conv,
     469             :                         struct sysdb_attrs **cmdgroups,
     470             :                         size_t num_cmdgroups)
     471             : {
     472           0 :     struct ipa_sudo_cmdgroup *cmdgroup = NULL;
     473             :     const char *key;
     474             :     errno_t ret;
     475             :     size_t i;
     476             : 
     477           0 :     if (num_cmdgroups == 0) {
     478             :         /* We're done here. */
     479           0 :         return EOK;
     480             :     }
     481             : 
     482           0 :     for (i = 0; i < num_cmdgroups; i++) {
     483           0 :         ret = sysdb_attrs_get_string(cmdgroups[i], SYSDB_ORIG_DN, &key);
     484           0 :         if (ret != EOK) {
     485           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to get command group DN, "
     486             :                   "skipping [%d]: %s\n", ret, sss_strerror(ret));
     487           0 :             continue;
     488             :         }
     489             : 
     490           0 :         cmdgroup = talloc_zero(conv->cmdgroups, struct ipa_sudo_cmdgroup);
     491           0 :         if (cmdgroup == NULL) {
     492           0 :             ret = ENOMEM;
     493           0 :             goto done;
     494             :         }
     495             : 
     496           0 :         ret = process_cmdgroupmember(conv, cmdgroup, cmdgroups[i]);
     497           0 :         if (ret != EOK) {
     498           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to process member "
     499             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     500           0 :             return ret;
     501             :         }
     502             : 
     503           0 :         ret = ipa_sudo_conv_store(conv->cmdgroups, key, cmdgroup);
     504           0 :         if (ret != EOK) {
     505           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to store command group into "
     506             :                   "table [%d]: %s\n", ret, sss_strerror(ret));
     507           0 :             goto done;
     508             :         }
     509             : 
     510           0 :         cmdgroup = NULL;
     511             :     }
     512             : 
     513           0 :     ret = EOK;
     514             : 
     515             : done:
     516           0 :     if (ret != EOK) {
     517           0 :         talloc_free(cmdgroup);
     518             :     }
     519             : 
     520           0 :     return ret;
     521             : }
     522             : 
     523             : errno_t
     524           0 : ipa_sudo_conv_cmds(struct ipa_sudo_conv *conv,
     525             :                    struct sysdb_attrs **cmds,
     526             :                    size_t num_cmds)
     527             : {
     528             :     const char *key;
     529             :     const char *cmd;
     530             :     errno_t ret;
     531             :     size_t i;
     532             : 
     533           0 :     if (num_cmds == 0) {
     534             :         /* We're done here. */
     535           0 :         return EOK;
     536             :     }
     537             : 
     538           0 :     for (i = 0; i < num_cmds; i++) {
     539           0 :         ret = sysdb_attrs_get_string(cmds[i], SYSDB_ORIG_DN, &key);
     540           0 :         if (ret != EOK) {
     541           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to get command DN, skipping "
     542             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     543           0 :             continue;
     544             :         }
     545             : 
     546           0 :         ret = sysdb_attrs_get_string(cmds[i], SYSDB_IPA_SUDOCMD_SUDOCMD, &cmd);
     547           0 :         if (ret != EOK) {
     548           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to get command, skipping "
     549             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     550           0 :             continue;
     551             :         }
     552             : 
     553           0 :         ret = ipa_sudo_conv_store(conv->cmds, key, discard_const(cmd));
     554           0 :         if (ret != EOK) {
     555           0 :             DEBUG(SSSDBG_OP_FAILURE, "Failed to store command into table "
     556             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     557           0 :             goto done;
     558             :         }
     559             :     }
     560             : 
     561           0 :     ret = EOK;
     562             : 
     563             : done:
     564           0 :     return ret;
     565             : }
     566             : 
     567             : bool
     568           0 : ipa_sudo_conv_has_cmdgroups(struct ipa_sudo_conv *conv)
     569             : {
     570           0 :     return hash_count(conv->cmdgroups) == 0;
     571             : }
     572             : 
     573             : bool
     574           0 : ipa_sudo_conv_has_cmds(struct ipa_sudo_conv *conv)
     575             : {
     576           0 :     return hash_count(conv->cmds) == 0;
     577             : }
     578             : 
     579             : typedef errno_t (*ipa_sudo_conv_rdn_fn)(TALLOC_CTX *mem_ctx,
     580             :                                       struct sdap_attr_map *map,
     581             :                                       struct sysdb_ctx *sysdb,
     582             :                                       const char *dn,
     583             :                                       char **_rdn_val,
     584             :                                       const char **_rdn_attr);
     585             : 
     586           0 : static errno_t get_sudo_cmdgroup_rdn(TALLOC_CTX *mem_ctx,
     587             :                                      struct sdap_attr_map *map,
     588             :                                      struct sysdb_ctx *sysdb,
     589             :                                      const char *dn,
     590             :                                      char **_rdn_val,
     591             :                                      const char **_rdn_attr)
     592             : {
     593             :     char *rdn_val;
     594             :     errno_t ret;
     595             : 
     596           0 :     ret = ipa_get_rdn(mem_ctx, sysdb, dn, &rdn_val,
     597             :                       MATCHRDN_CMDGROUPS(map));
     598           0 :     if (ret != EOK) {
     599           0 :         return ret;
     600             :     }
     601             : 
     602           0 :     *_rdn_val = rdn_val;
     603           0 :     *_rdn_attr = map[IPA_AT_SUDOCMDGROUP_NAME].name;
     604             : 
     605           0 :     return EOK;
     606             : }
     607             : 
     608           0 : static errno_t get_sudo_cmd_rdn(TALLOC_CTX *mem_ctx,
     609             :                                 struct sdap_attr_map *map,
     610             :                                 struct sysdb_ctx *sysdb,
     611             :                                 const char *dn,
     612             :                                 char **_rdn_val,
     613             :                                 const char **_rdn_attr)
     614             : {
     615             :     char *rdn_val;
     616             :     errno_t ret;
     617             : 
     618           0 :     ret = ipa_get_rdn(mem_ctx, sysdb, dn, &rdn_val,
     619             :                       MATCHRDN_CMDS(IPA_AT_SUDOCMD_UUID, map));
     620           0 :     if (ret == EOK) {
     621           0 :         *_rdn_val = rdn_val;
     622           0 :         *_rdn_attr = map[IPA_AT_SUDOCMD_UUID].name;
     623             : 
     624           0 :         return EOK;
     625           0 :     } else if (ret != ENOENT) {
     626           0 :         return ret;
     627             :     }
     628             : 
     629             :     /* For older versions of FreeIPA than 3.1. */
     630           0 :     ret = ipa_get_rdn(mem_ctx, sysdb, dn, &rdn_val,
     631             :                       MATCHRDN_CMDS(IPA_AT_SUDOCMD_CMD, map));
     632           0 :     if (ret != EOK) {
     633           0 :         return ret;
     634             :     }
     635             : 
     636           0 :     *_rdn_val = rdn_val;
     637           0 :     *_rdn_attr = map[IPA_AT_SUDOCMD_CMD].name;;
     638             : 
     639           0 :     return EOK;
     640             : }
     641             : 
     642             : static char *
     643           0 : build_filter(TALLOC_CTX *mem_ctx,
     644             :              struct sysdb_ctx *sysdb,
     645             :              hash_table_t *table,
     646             :              struct sdap_attr_map *map,
     647             :              ipa_sudo_conv_rdn_fn rdn_fn)
     648             : {
     649             :     TALLOC_CTX *tmp_ctx;
     650             :     hash_key_t *keys;
     651             :     unsigned long int count;
     652             :     unsigned long int i;
     653             :     char *filter;
     654             :     char *rdn_val;
     655             :     const char *rdn_attr;
     656             :     char *safe_rdn;
     657             :     errno_t ret;
     658             :     int hret;
     659             : 
     660           0 :     tmp_ctx = talloc_new(NULL);
     661           0 :     if (tmp_ctx == NULL) {
     662           0 :         return NULL;
     663             :     }
     664             : 
     665           0 :     hret = hash_keys(table, &count, &keys);
     666           0 :     if (hret != HASH_SUCCESS) {
     667           0 :         ret = ENOMEM;
     668           0 :         goto done;
     669             :     }
     670             : 
     671           0 :     talloc_steal(tmp_ctx, keys);
     672             : 
     673           0 :     filter = talloc_strdup(tmp_ctx, "");
     674           0 :     if (filter == NULL) {
     675           0 :         ret = ENOMEM;
     676           0 :         goto done;
     677             :     }
     678             : 
     679           0 :     for (i = 0; i < count; i++) {
     680           0 :         ret = rdn_fn(tmp_ctx, map, sysdb, keys[i].str, &rdn_val, &rdn_attr);
     681           0 :         if (ret != EOK) {
     682           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get member %s [%d]: %s\n",
     683             :                   keys[i].str, ret, sss_strerror(ret));
     684           0 :             goto done;
     685             :         }
     686             : 
     687           0 :         ret = sss_filter_sanitize(tmp_ctx, rdn_val, &safe_rdn);
     688           0 :         if (ret != EOK) {
     689           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to sanitize DN "
     690             :                   "[%d]: %s\n", ret, sss_strerror(ret));
     691           0 :             goto done;
     692             :         }
     693             : 
     694           0 :         filter = talloc_asprintf_append(filter, "(%s=%s)", rdn_attr, safe_rdn);
     695           0 :         if (filter == NULL) {
     696           0 :             ret = ENOMEM;
     697           0 :             goto done;
     698             :         }
     699             :     }
     700             : 
     701             :     /* objectClass is always first */
     702           0 :     filter = talloc_asprintf(filter, "(&(objectClass=%s)(|%s))",
     703             :                              map[0].name, filter);
     704           0 :     if (filter == NULL) {
     705           0 :         ret = ENOMEM;
     706           0 :         goto done;
     707             :     }
     708             : 
     709           0 :     talloc_steal(mem_ctx, filter);
     710             : 
     711           0 :     ret = EOK;
     712             : 
     713             : done:
     714           0 :     talloc_free(tmp_ctx);
     715             : 
     716           0 :     if (ret != EOK) {
     717           0 :         return NULL;
     718             :     }
     719             : 
     720           0 :     return filter;
     721             : }
     722             : 
     723             : char *
     724           0 : ipa_sudo_conv_cmdgroup_filter(TALLOC_CTX *mem_ctx,
     725             :                               struct ipa_sudo_conv *conv)
     726             : {
     727           0 :     return build_filter(mem_ctx, conv->sysdb, conv->cmdgroups,
     728             :                         conv->map_cmdgroup, get_sudo_cmdgroup_rdn);
     729             : }
     730             : 
     731             : char *
     732           0 : ipa_sudo_conv_cmd_filter(TALLOC_CTX *mem_ctx,
     733             :                          struct ipa_sudo_conv *conv)
     734             : {
     735           0 :     return build_filter(mem_ctx, conv->sysdb, conv->cmds,
     736             :                             conv->map_cmd, get_sudo_cmd_rdn);
     737             : }
     738             : 
     739             : struct ipa_sudo_conv_result_ctx {
     740             :     struct ipa_sudo_conv *conv;
     741             :     struct sysdb_attrs **rules;
     742             :     size_t num_rules;
     743             :     errno_t ret;
     744             : };
     745             : 
     746             : static const char *
     747           0 : convert_host(TALLOC_CTX *mem_ctx,
     748             :              struct ipa_sudo_conv *conv,
     749             :              const char *value)
     750             : {
     751             :     char *rdn;
     752             :     const char *group;
     753             :     errno_t ret;
     754             : 
     755           0 :     ret = ipa_get_rdn(mem_ctx, conv->sysdb, value, &rdn,
     756             :                       MATCHRDN_HOST(conv->map_host));
     757           0 :     if (ret == EOK) {
     758           0 :         return rdn;
     759           0 :     } else if (ret != ENOENT) {
     760           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n",
     761             :               value, ret, sss_strerror(ret));
     762           0 :         return NULL;
     763             :     }
     764             : 
     765           0 :     ret = ipa_get_rdn(mem_ctx, conv->sysdb, value, &rdn,
     766             :                       MATCHRDN_HOSTGROUP(conv->map_hostgroup));
     767           0 :     if (ret == ENOENT) {
     768           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected DN %s\n", value);
     769           0 :         return NULL;
     770           0 :     } else if (ret != EOK) {
     771           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n",
     772             :               value, ret, sss_strerror(ret));
     773           0 :         return NULL;
     774             :     }
     775             : 
     776           0 :     group = talloc_asprintf(mem_ctx, "+%s", rdn);
     777           0 :     talloc_free(rdn);
     778             : 
     779           0 :     return group;
     780             : }
     781             : 
     782             : static const char *
     783           0 : convert_user(TALLOC_CTX *mem_ctx,
     784             :              struct ipa_sudo_conv *conv,
     785             :              const char *value)
     786             : {
     787             :     char *rdn;
     788             :     const char *group;
     789             :     errno_t ret;
     790             : 
     791           0 :     ret = ipa_get_rdn(mem_ctx, conv->sysdb, value, &rdn,
     792             :                       MATCHRDN_USER(conv->map_user));
     793           0 :     if (ret == EOK) {
     794           0 :         return rdn;
     795           0 :     } else if (ret != ENOENT) {
     796           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n",
     797             :               value, ret, sss_strerror(ret));
     798           0 :         return NULL;
     799             :     }
     800             : 
     801           0 :     ret = ipa_get_rdn(mem_ctx, conv->sysdb, value, &rdn,
     802             :                       MATCHRDN_GROUP(conv->map_group));
     803           0 :     if (ret == ENOENT) {
     804           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected DN %s\n", value);
     805           0 :         return NULL;
     806           0 :     } else if (ret != EOK) {
     807           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n",
     808             :               value, ret, sss_strerror(ret));
     809           0 :         return NULL;
     810             :     }
     811             : 
     812           0 :     group = talloc_asprintf(mem_ctx, "%%%s", rdn);
     813           0 :     talloc_free(rdn);
     814             : 
     815           0 :     return group;
     816             : }
     817             : 
     818             : static const char *
     819           0 : convert_group(TALLOC_CTX *mem_ctx,
     820             :               struct ipa_sudo_conv *conv,
     821             :               const char *value)
     822             : {
     823             :     char *rdn;
     824             :     errno_t ret;
     825             : 
     826           0 :     ret = ipa_get_rdn(mem_ctx, conv->sysdb, value, &rdn,
     827             :                       MATCHRDN_GROUP(conv->map_group));
     828           0 :     if (ret == ENOENT) {
     829           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected DN %s\n", value);
     830           0 :         return NULL;
     831           0 :     } else if (ret != EOK) {
     832           0 :         DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n",
     833             :               value, ret, sss_strerror(ret));
     834           0 :         return NULL;
     835             :     }
     836             : 
     837           0 :     return rdn;
     838             : }
     839             : 
     840             : static const char *
     841           0 : convert_runasextusergroup(TALLOC_CTX *mem_ctx,
     842             :                           struct ipa_sudo_conv *conv,
     843             :                           const char *value)
     844             : {
     845           0 :     return talloc_asprintf(mem_ctx, "%%%s", value);
     846             : }
     847             : 
     848             : static const char *
     849           0 : convert_cat(TALLOC_CTX *mem_ctx,
     850             :             struct ipa_sudo_conv *conv,
     851             :             const char *value)
     852             : {
     853           0 :     if (strcmp(value, "all") == 0) {
     854           0 :         return talloc_strdup(mem_ctx, "ALL");
     855             :     }
     856             : 
     857           0 :     return value;
     858             : }
     859             : 
     860             : static errno_t
     861           0 : convert_attributes(struct ipa_sudo_conv *conv,
     862             :                    struct ipa_sudo_rule *rule,
     863             :                    struct sysdb_attrs *attrs)
     864             : {
     865             :     TALLOC_CTX *tmp_ctx;
     866             :     const char **values;
     867             :     const char *value;
     868             :     errno_t ret;
     869             :     int i, j;
     870             :     static struct {
     871             :         const char *ipa;
     872             :         const char *sudo;
     873             :         const char *(*conv_fn)(TALLOC_CTX *mem_ctx,
     874             :                                struct ipa_sudo_conv *conv,
     875             :                                const char *value);
     876             :     } table[] = {{SYSDB_NAME,                            SYSDB_SUDO_CACHE_AT_CN         , NULL},
     877             :                  {SYSDB_IPA_SUDORULE_HOST,               SYSDB_SUDO_CACHE_AT_HOST       , convert_host},
     878             :                  {SYSDB_IPA_SUDORULE_USER,               SYSDB_SUDO_CACHE_AT_USER       , convert_user},
     879             :                  {SYSDB_IPA_SUDORULE_RUNASUSER,          SYSDB_SUDO_CACHE_AT_RUNASUSER  , convert_user},
     880             :                  {SYSDB_IPA_SUDORULE_RUNASGROUP,         SYSDB_SUDO_CACHE_AT_RUNASGROUP , convert_group},
     881             :                  {SYSDB_IPA_SUDORULE_OPTION,             SYSDB_SUDO_CACHE_AT_OPTION     , NULL},
     882             :                  {SYSDB_IPA_SUDORULE_NOTAFTER,           SYSDB_SUDO_CACHE_AT_NOTAFTER   , NULL},
     883             :                  {SYSDB_IPA_SUDORULE_NOTBEFORE,          SYSDB_SUDO_CACHE_AT_NOTBEFORE  , NULL},
     884             :                  {SYSDB_IPA_SUDORULE_SUDOORDER,          SYSDB_SUDO_CACHE_AT_ORDER      , NULL},
     885             :                  {SYSDB_IPA_SUDORULE_CMDCATEGORY,        SYSDB_SUDO_CACHE_AT_COMMAND    , convert_cat},
     886             :                  {SYSDB_IPA_SUDORULE_HOSTCATEGORY,       SYSDB_SUDO_CACHE_AT_HOST       , convert_cat},
     887             :                  {SYSDB_IPA_SUDORULE_USERCATEGORY,       SYSDB_SUDO_CACHE_AT_USER       , convert_cat},
     888             :                  {SYSDB_IPA_SUDORULE_RUNASUSERCATEGORY,  SYSDB_SUDO_CACHE_AT_RUNASUSER  , convert_cat},
     889             :                  {SYSDB_IPA_SUDORULE_RUNASGROUPCATEGORY, SYSDB_SUDO_CACHE_AT_RUNASGROUP , convert_cat},
     890             :                  {SYSDB_IPA_SUDORULE_RUNASEXTUSER,       SYSDB_SUDO_CACHE_AT_RUNASUSER  , NULL},
     891             :                  {SYSDB_IPA_SUDORULE_RUNASEXTGROUP,      SYSDB_SUDO_CACHE_AT_RUNASGROUP , NULL},
     892             :                  {SYSDB_IPA_SUDORULE_RUNASEXTUSERGROUP,  SYSDB_SUDO_CACHE_AT_RUNASUSER  , convert_runasextusergroup},
     893             :                  {SYSDB_IPA_SUDORULE_EXTUSER,            SYSDB_SUDO_CACHE_AT_USER       , NULL},
     894             :                  {SYSDB_IPA_SUDORULE_ALLOWCMD,           SYSDB_IPA_SUDORULE_ORIGCMD     , NULL},
     895             :                  {SYSDB_IPA_SUDORULE_DENYCMD,            SYSDB_IPA_SUDORULE_ORIGCMD     , NULL},
     896             :                  {NULL, NULL, NULL}};
     897             : 
     898           0 :     tmp_ctx = talloc_new(NULL);
     899           0 :     if (tmp_ctx == NULL) {
     900           0 :         return ENOMEM;
     901             :     }
     902             : 
     903           0 :     for (i = 0; table[i].ipa != NULL; i++) {
     904           0 :         ret = sysdb_attrs_get_string_array(rule->attrs, table[i].ipa,
     905             :                                            tmp_ctx, &values);
     906           0 :         if (ret == ENOENT) {
     907           0 :             continue;
     908           0 :         } else if (ret != EOK) {
     909           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read attribute "
     910             :                   "%s [%d]: %s\n", table[i].ipa, ret, sss_strerror(ret));
     911           0 :             goto done;
     912             :         }
     913             : 
     914           0 :         for (j = 0; values[j] != NULL; j++) {
     915           0 :             if (table[i].conv_fn != NULL) {
     916           0 :                 value = table[i].conv_fn(tmp_ctx, conv, values[j]);
     917           0 :                 if (value == NULL) {
     918           0 :                     ret = ENOMEM;
     919           0 :                     goto done;
     920             :                 }
     921             :             } else {
     922           0 :                 value = values[j];
     923             :             }
     924             : 
     925           0 :             ret = sysdb_attrs_add_string_safe(attrs, table[i].sudo, value);
     926           0 :             if (ret != EOK) {
     927           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute "
     928             :                       "%s [%d]: %s\n", table[i].sudo, ret, sss_strerror(ret));
     929           0 :                 goto done;
     930             :             }
     931             :         }
     932             :     }
     933             : 
     934           0 :     ret = EOK;
     935             : 
     936             : done:
     937           0 :     talloc_free(tmp_ctx);
     938           0 :     return ret;
     939             : }
     940             : 
     941             : static const char **
     942           0 : combine_cmdgroups(TALLOC_CTX *mem_ctx,
     943             :                   struct ipa_sudo_conv *conv,
     944             :                   struct ipa_sudo_dn_list *list)
     945             : {
     946             :     TALLOC_CTX *tmp_ctx;
     947             :     struct ipa_sudo_cmdgroup *cmdgroup;
     948             :     struct ipa_sudo_dn_list *listitem;
     949           0 :     const char **values = NULL;
     950             :     errno_t ret;
     951             : 
     952           0 :     tmp_ctx = talloc_new(NULL);
     953           0 :     if (tmp_ctx == NULL) {
     954           0 :         return NULL;
     955             :     }
     956             : 
     957           0 :     values = talloc_zero_array(tmp_ctx, const char *, 1);
     958           0 :     if (values == NULL) {
     959           0 :         talloc_free(tmp_ctx);
     960           0 :         return NULL;
     961             :     }
     962             : 
     963           0 :     DLIST_FOR_EACH(listitem, list) {
     964           0 :         cmdgroup = ipa_sudo_conv_lookup(conv->cmdgroups, listitem->dn);
     965           0 :         if (cmdgroup == NULL) {
     966           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     967             :                   "ipa_sudo_conv_lookup failed for DN:%s\n", listitem->dn);
     968           0 :             continue;
     969             :         }
     970             : 
     971           0 :         ret = add_strings_lists(mem_ctx, values, cmdgroup->expanded,
     972             :                                 false, discard_const(&values));
     973           0 :         if (ret != EOK) {
     974           0 :             talloc_free(tmp_ctx);
     975           0 :             return NULL;
     976             :         }
     977             :     }
     978             : 
     979           0 :     talloc_steal(mem_ctx, values);
     980           0 :     talloc_free(tmp_ctx);
     981             : 
     982           0 :     return values;
     983             : }
     984             : 
     985             : static const char **
     986           0 : combine_cmds(TALLOC_CTX *mem_ctx,
     987             :              struct ipa_sudo_conv *conv,
     988             :              struct ipa_sudo_dn_list *list)
     989             : {
     990             :     struct ipa_sudo_dn_list *listitem;
     991             :     const char **values;
     992             :     const char *command;
     993             :     size_t count;
     994             :     size_t i;
     995             : 
     996           0 :     count = ipa_sudo_dn_list_count(list);
     997             : 
     998           0 :     values = talloc_zero_array(mem_ctx, const char *, count + 1);
     999           0 :     if (values == NULL) {
    1000           0 :         return NULL;
    1001             :     }
    1002             : 
    1003           0 :     i = 0;
    1004           0 :     DLIST_FOR_EACH(listitem, list) {
    1005           0 :         command = ipa_sudo_conv_lookup(conv->cmds, listitem->dn);
    1006           0 :         if (command == NULL) {
    1007           0 :             continue;
    1008             :         }
    1009             : 
    1010           0 :         values[i] = command;
    1011           0 :         i++;
    1012             :     }
    1013             : 
    1014           0 :     return values;
    1015             : }
    1016             : 
    1017             : static errno_t
    1018           0 : build_sudocommand(struct ipa_sudo_conv *conv,
    1019             :                   struct ipa_sudo_rulemember *mlist,
    1020             :                   struct sysdb_attrs *attrs,
    1021             :                   char prefix)
    1022             : {
    1023             :     TALLOC_CTX *tmp_ctx;
    1024             :     const char **cmds[2];
    1025             :     const char *command;
    1026             :     errno_t ret;
    1027             :     int i, j;
    1028             : 
    1029           0 :     tmp_ctx = talloc_new(NULL);
    1030           0 :     if (tmp_ctx == NULL) {
    1031           0 :         return ENOMEM;
    1032             :     }
    1033             : 
    1034           0 :     cmds[0] = combine_cmdgroups(tmp_ctx, conv, mlist->cmdgroups);
    1035           0 :     if (cmds[0] == NULL) {
    1036           0 :         ret = ENOMEM;
    1037           0 :         goto done;
    1038             :     }
    1039             : 
    1040           0 :     cmds[1] = combine_cmds(tmp_ctx, conv, mlist->cmds);
    1041           0 :     if (cmds[1] == NULL) {
    1042           0 :         ret = ENOMEM;
    1043           0 :         goto done;
    1044             :     }
    1045             : 
    1046           0 :     for (i = 0; i < 2; i++) {
    1047           0 :         for (j = 0; cmds[i][j] != NULL; j++) {
    1048           0 :             if (prefix == '\0') {
    1049           0 :                 command = cmds[i][j];
    1050             :             } else {
    1051           0 :                 command = talloc_asprintf(tmp_ctx, "%c%s", prefix, cmds[i][j]);
    1052           0 :                 if (command == NULL) {
    1053           0 :                     ret = ENOMEM;
    1054           0 :                     goto done;
    1055             :                 }
    1056             :             }
    1057             : 
    1058           0 :             ret = sysdb_attrs_add_string_safe(attrs,
    1059             :                         SYSDB_SUDO_CACHE_AT_COMMAND, command);
    1060           0 :             if (ret != EOK) {
    1061           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute "
    1062             :                       "%s [%d]: %s\n", SYSDB_SUDO_CACHE_AT_COMMAND,
    1063             :                       ret, sss_strerror(ret));
    1064           0 :                 goto done;
    1065             :             }
    1066             :         }
    1067             :     }
    1068             : 
    1069           0 :     ret = EOK;
    1070             : 
    1071             : done:
    1072           0 :     talloc_free(tmp_ctx);
    1073           0 :     return ret;
    1074             : }
    1075             : 
    1076             : static errno_t
    1077           0 : convert_sudocommand(struct ipa_sudo_conv *conv,
    1078             :                     struct ipa_sudo_rule *rule,
    1079             :                     struct sysdb_attrs *attrs)
    1080             : {
    1081             :     TALLOC_CTX *tmp_ctx;
    1082             :     errno_t ret;
    1083             : 
    1084           0 :     tmp_ctx = talloc_new(NULL);
    1085           0 :     if (tmp_ctx == NULL) {
    1086           0 :         return ENOMEM;
    1087             :     }
    1088             : 
    1089           0 :     ret = build_sudocommand(conv, &rule->allow, attrs, '\0');
    1090           0 :     if (ret != EOK) {
    1091           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build allow commands "
    1092             :               "[%d]: %s\n", ret, sss_strerror(ret));
    1093           0 :         goto done;
    1094             :     }
    1095             : 
    1096           0 :     ret = build_sudocommand(conv, &rule->deny, attrs, '!');
    1097           0 :     if (ret != EOK) {
    1098           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build deny commands "
    1099             :               "[%d]: %s\n", ret, sss_strerror(ret));
    1100           0 :         goto done;
    1101             :     }
    1102             : 
    1103           0 :     ret = EOK;
    1104             : 
    1105             : done:
    1106           0 :     talloc_free(tmp_ctx);
    1107           0 :     return ret;
    1108             : }
    1109             : 
    1110             : static bool
    1111           0 : rules_iterator(hash_entry_t *item,
    1112             :                void *user_data)
    1113             : {
    1114           0 :     struct ipa_sudo_conv_result_ctx *ctx = user_data;
    1115           0 :     struct ipa_sudo_rule *rule = item->value.ptr;
    1116             :     struct sysdb_attrs *attrs;
    1117             : 
    1118           0 :     if (ctx == NULL) {
    1119           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Bug: ctx is NULL\n");
    1120           0 :         return false;
    1121             :     }
    1122             : 
    1123           0 :     if (rule == NULL) {
    1124           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Bug: rule is NULL\n");
    1125           0 :         ctx->ret = ERR_INTERNAL;
    1126           0 :         return false;
    1127             :     }
    1128             : 
    1129           0 :     attrs = sysdb_new_attrs(ctx->rules);
    1130           0 :     if (attrs == NULL) {
    1131           0 :         ctx->ret = ENOMEM;
    1132           0 :         return false;
    1133             :     }
    1134             : 
    1135           0 :     ctx->ret = convert_attributes(ctx->conv, rule, attrs);
    1136           0 :     if (ctx->ret != EOK) {
    1137           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to convert attributes [%d]: %s\n",
    1138             :               ctx->ret, sss_strerror(ctx->ret));
    1139           0 :         talloc_free(attrs);
    1140           0 :         return false;
    1141             :     }
    1142             : 
    1143           0 :     ctx->ret = convert_sudocommand(ctx->conv, rule, attrs);
    1144           0 :     if (ctx->ret != EOK) {
    1145           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to build sudoCommand [%d]: %s\n",
    1146             :               ctx->ret, sss_strerror(ctx->ret));
    1147           0 :         talloc_free(attrs);
    1148           0 :         return false;
    1149             :     }
    1150             : 
    1151           0 :     ctx->rules[ctx->num_rules] = attrs;
    1152           0 :     ctx->num_rules++;
    1153             : 
    1154           0 :     return true;
    1155             : }
    1156             : 
    1157             : static bool
    1158           0 : cmdgroups_iterator(hash_entry_t *item,
    1159             :                    void *user_data)
    1160             : {
    1161           0 :     struct ipa_sudo_conv_result_ctx *ctx = user_data;
    1162           0 :     struct ipa_sudo_cmdgroup *cmdgroup = item->value.ptr;
    1163             :     const char **values;
    1164             : 
    1165           0 :     if (ctx == NULL) {
    1166           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Bug: ctx is NULL\n");
    1167           0 :         return false;
    1168             :     }
    1169             : 
    1170           0 :     if (cmdgroup == NULL) {
    1171           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Bug: rule is NULL\n");
    1172           0 :         ctx->ret = ERR_INTERNAL;
    1173           0 :         return false;
    1174             :     }
    1175             : 
    1176           0 :     values = combine_cmds(cmdgroup, ctx->conv, cmdgroup->cmds);
    1177           0 :     if (values == NULL) {
    1178           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to expand commands\n");
    1179           0 :         ctx->ret = ENOMEM;
    1180           0 :         return false;
    1181             :     }
    1182             : 
    1183           0 :     cmdgroup->expanded = values;
    1184           0 :     ctx->ret = EOK;
    1185             : 
    1186           0 :     return true;
    1187             : }
    1188             : 
    1189             : errno_t
    1190           0 : ipa_sudo_conv_result(TALLOC_CTX *mem_ctx,
    1191             :                      struct ipa_sudo_conv *conv,
    1192             :                      struct sysdb_attrs ***_rules,
    1193             :                      size_t *_num_rules)
    1194             : {
    1195             :     struct ipa_sudo_conv_result_ctx ctx;
    1196             :     struct sysdb_attrs **rules;
    1197             :     unsigned long num_rules;
    1198             :     int hret;
    1199             : 
    1200           0 :     num_rules = hash_count(conv->rules);
    1201           0 :     if (num_rules == 0) {
    1202           0 :         *_rules = NULL;
    1203           0 :         *_num_rules = 0;
    1204           0 :         return EOK;
    1205             :     }
    1206             : 
    1207           0 :     ctx.conv = conv;
    1208           0 :     ctx.rules = NULL;
    1209           0 :     ctx.num_rules = 0;
    1210             : 
    1211             :     /* If there are no cmdgroups the iterator is not called and ctx.ret is
    1212             :      * uninitialized. Since it is ok that there are no cmdgroups initializing
    1213             :      * ctx.ret to EOK. */
    1214           0 :     ctx.ret = EOK;
    1215             : 
    1216             :     /* Expand commands in command groups. */
    1217           0 :     hret = hash_iterate(conv->cmdgroups, cmdgroups_iterator, &ctx);
    1218           0 :     if (hret != HASH_SUCCESS) {
    1219           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to iterate over command groups "
    1220             :               "[%d]\n", hret);
    1221           0 :         return EIO;
    1222             :     }
    1223             : 
    1224           0 :     if (ctx.ret != EOK) {
    1225           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to expand command groups "
    1226             :               "[%d]: %s\n", ctx.ret, sss_strerror(ctx.ret));
    1227           0 :         return ctx.ret;
    1228             :     }
    1229             : 
    1230             :     /* Convert rules. */
    1231           0 :     rules = talloc_zero_array(mem_ctx, struct sysdb_attrs *, num_rules);
    1232           0 :     if (rules == NULL) {
    1233           0 :         return ENOMEM;
    1234             :     }
    1235             : 
    1236           0 :     ctx.rules = rules;
    1237           0 :     ctx.num_rules = 0;
    1238             : 
    1239           0 :     hret = hash_iterate(conv->rules, rules_iterator, &ctx);
    1240           0 :     if (hret != HASH_SUCCESS) {
    1241           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to iterate over rules [%d]\n", hret);
    1242           0 :         return EIO;
    1243             :     }
    1244             : 
    1245           0 :     if (ctx.ret != EOK) {
    1246           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to convert rules [%d]: %s\n",
    1247             :               ctx.ret, sss_strerror(ctx.ret));
    1248           0 :         talloc_free(rules);
    1249           0 :         return ctx.ret;
    1250             :     }
    1251             : 
    1252           0 :     *_rules = ctx.rules;
    1253           0 :     *_num_rules = ctx.num_rules;
    1254             : 
    1255           0 :     return EOK;
    1256             : }

Generated by: LCOV version 1.10