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

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Authors:
       5             :         Stephen Gallagher <sgallagh@redhat.com>
       6             : 
       7             :     Copyright (C) 2011 Red Hat
       8             : 
       9             :     This program is free software; you can redistribute it and/or modify
      10             :     it under the terms of the GNU General Public License as published by
      11             :     the Free Software Foundation; either version 3 of the License, or
      12             :     (at your option) any later version.
      13             : 
      14             :     This program is distributed in the hope that it will be useful,
      15             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :     GNU General Public License for more details.
      18             : 
      19             :     You should have received a copy of the GNU General Public License
      20             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "providers/ipa/ipa_hbac_private.h"
      24             : #include "providers/ipa/ipa_hbac.h"
      25             : #include "providers/ipa/ipa_common.h"
      26             : 
      27             : static errno_t
      28           0 : ipa_hbac_save_list(struct sss_domain_info *domain,
      29             :                    bool delete_subdir, const char *subdir,
      30             :                    const char *naming_attribute, size_t count,
      31             :                    struct sysdb_attrs **list)
      32             : {
      33             :     int ret;
      34             :     size_t c;
      35             :     struct ldb_dn *base_dn;
      36             :     const char *object_name;
      37             :     struct ldb_message_element *el;
      38             :     TALLOC_CTX *tmp_ctx;
      39             : 
      40           0 :     tmp_ctx = talloc_new(NULL);
      41           0 :     if (tmp_ctx == NULL) {
      42           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
      43           0 :         return ENOMEM;
      44             :     }
      45             : 
      46           0 :     if (delete_subdir) {
      47           0 :         base_dn = sysdb_custom_subtree_dn(tmp_ctx, domain, subdir);
      48           0 :         if (base_dn == NULL) {
      49           0 :             ret = ENOMEM;
      50           0 :             goto done;
      51             :         }
      52             : 
      53           0 :         ret = sysdb_delete_recursive(domain->sysdb, base_dn, true);
      54           0 :         if (ret != EOK) {
      55           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_delete_recursive failed.\n");
      56           0 :             goto done;
      57             :         }
      58             :     }
      59             : 
      60           0 :     for (c = 0; c < count; c++) {
      61           0 :         ret = sysdb_attrs_get_el(list[c], naming_attribute, &el);
      62           0 :         if (ret != EOK) {
      63           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_get_el failed.\n");
      64           0 :             goto done;
      65             :         }
      66           0 :         if (el->num_values == 0) {
      67           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "[%s] not found.\n", naming_attribute);
      68           0 :             ret = EINVAL;
      69           0 :             goto done;
      70             :         }
      71           0 :         object_name = talloc_strndup(tmp_ctx, (const char *)el->values[0].data,
      72           0 :                                      el->values[0].length);
      73           0 :         if (object_name == NULL) {
      74           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strndup failed.\n");
      75           0 :             ret = ENOMEM;
      76           0 :             goto done;
      77             :         }
      78           0 :         DEBUG(SSSDBG_TRACE_ALL, "Object name: [%s].\n", object_name);
      79             : 
      80           0 :         ret = sysdb_store_custom(domain, object_name, subdir, list[c]);
      81           0 :         if (ret != EOK) {
      82           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_store_custom failed.\n");
      83           0 :             goto done;
      84             :         }
      85             :     }
      86             : 
      87           0 :     ret = EOK;
      88             : 
      89             : done:
      90           0 :     talloc_free(tmp_ctx);
      91           0 :     return ret;
      92             : }
      93             : 
      94             : errno_t
      95           0 : ipa_hbac_sysdb_save(struct sss_domain_info *domain,
      96             :                     const char *primary_subdir, const char *attr_name,
      97             :                     size_t primary_count, struct sysdb_attrs **primary,
      98             :                     const char *group_subdir, const char *groupattr_name,
      99             :                     size_t group_count, struct sysdb_attrs **groups)
     100             : {
     101             :     errno_t ret, sret;
     102           0 :     bool in_transaction = false;
     103             : 
     104           0 :     if ((primary_count == 0 || primary == NULL)
     105           0 :         || (group_count > 0 && groups == NULL)) {
     106             :         /* There always has to be at least one
     107             :          * primary entry.
     108             :          */
     109           0 :         return EINVAL;
     110             :     }
     111             : 
     112             :     /* Save the entries and groups to the cache */
     113           0 :     ret = sysdb_transaction_start(domain->sysdb);
     114           0 :     if (ret != EOK) {
     115           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
     116           0 :         goto done;
     117             :     };
     118           0 :     in_transaction = true;
     119             : 
     120             :     /* First, save the specific entries */
     121           0 :     ret = ipa_hbac_save_list(domain, true, primary_subdir,
     122             :                              attr_name, primary_count, primary);
     123           0 :     if (ret != EOK) {
     124           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not save %s. [%d][%s]\n",
     125             :                   primary_subdir, ret, strerror(ret));
     126           0 :         goto done;
     127             :     }
     128             : 
     129             :     /* Second, save the groups */
     130           0 :     if (group_count > 0) {
     131           0 :         ret = ipa_hbac_save_list(domain, true, group_subdir,
     132             :                                  groupattr_name, group_count, groups);
     133           0 :         if (ret != EOK) {
     134           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not save %s. [%d][%s]\n",
     135             :                       group_subdir, ret, strerror(ret));
     136           0 :             goto done;
     137             :         }
     138             :     }
     139             : 
     140           0 :     ret = sysdb_transaction_commit(domain->sysdb);
     141           0 :     if (ret != EOK) {
     142           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
     143           0 :         goto done;
     144             :     }
     145           0 :     in_transaction = false;
     146             : 
     147             : done:
     148           0 :     if (in_transaction) {
     149           0 :         sret = sysdb_transaction_cancel(domain->sysdb);
     150           0 :         if (sret != EOK) {
     151           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "Could not cancel sysdb transaction\n");
     152             :         }
     153             :     }
     154             : 
     155           0 :     if (ret != EOK) {
     156           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Error [%d][%s]\n", ret, strerror(ret));
     157             :     }
     158           0 :     return ret;
     159             : }
     160             : 
     161             : errno_t
     162           0 : replace_attribute_name(const char *old_name,
     163             :                        const char *new_name, const size_t count,
     164             :                        struct sysdb_attrs **list)
     165             : {
     166             :     int ret;
     167             :     int i;
     168             : 
     169           0 :     for (i = 0; i < count; i++) {
     170           0 :         ret = sysdb_attrs_replace_name(list[i], old_name, new_name);
     171           0 :         if (ret != EOK) {
     172           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_replace_name failed.\n");
     173           0 :             return ret;
     174             :         }
     175             :     }
     176             : 
     177           0 :     return EOK;
     178             : }
     179             : 
     180             : static errno_t
     181           0 : create_empty_grouplist(struct hbac_request_element *el)
     182             : {
     183           0 :     el->groups = talloc_array(el, const char *, 1);
     184           0 :     if (!el->groups) return ENOMEM;
     185             : 
     186           0 :     el->groups[0] = NULL;
     187           0 :     return EOK;
     188             : }
     189             : 
     190             : /********************************************
     191             :  * Functions for handling conversion to the *
     192             :  * HBAC evaluator format                    *
     193             :  ********************************************/
     194             : 
     195             : static errno_t
     196             : hbac_attrs_to_rule(TALLOC_CTX *mem_ctx,
     197             :                    struct hbac_ctx *hbac_ctx,
     198             :                    size_t index,
     199             :                    struct hbac_rule **rule);
     200             : 
     201             : static errno_t
     202             : hbac_ctx_to_eval_request(TALLOC_CTX *mem_ctx,
     203             :                          struct hbac_ctx *hbac_ctx,
     204             :                          struct hbac_eval_req **request);
     205             : 
     206             : errno_t
     207           0 : hbac_ctx_to_rules(TALLOC_CTX *mem_ctx,
     208             :                   struct hbac_ctx *hbac_ctx,
     209             :                   struct hbac_rule ***rules,
     210             :                   struct hbac_eval_req **request)
     211             : {
     212             :     errno_t ret;
     213             :     struct hbac_rule **new_rules;
     214           0 :     struct hbac_eval_req *new_request = NULL;
     215             :     size_t i;
     216           0 :     TALLOC_CTX *tmp_ctx = NULL;
     217             : 
     218           0 :     if (!rules || !request) return EINVAL;
     219             : 
     220           0 :     tmp_ctx = talloc_new(mem_ctx);
     221           0 :     if (tmp_ctx == NULL) return ENOMEM;
     222             : 
     223             :     /* First create an array of rules */
     224           0 :     new_rules = talloc_array(tmp_ctx, struct hbac_rule *,
     225             :                              hbac_ctx->rule_count + 1);
     226           0 :     if (new_rules == NULL) {
     227           0 :         ret = ENOMEM;
     228           0 :         goto done;
     229             :     }
     230             : 
     231             :     /* Create each rule one at a time */
     232           0 :     for (i = 0; i < hbac_ctx->rule_count ; i++) {
     233           0 :         ret = hbac_attrs_to_rule(new_rules, hbac_ctx, i, &(new_rules[i]));
     234           0 :         if (ret == EPERM) {
     235           0 :             goto done;
     236           0 :         } else if (ret != EOK) {
     237           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not construct rules\n");
     238           0 :             goto done;
     239             :         }
     240             :     }
     241           0 :     new_rules[i] = NULL;
     242             : 
     243             :     /* Create the eval request */
     244           0 :     ret = hbac_ctx_to_eval_request(tmp_ctx, hbac_ctx, &new_request);
     245           0 :     if (ret != EOK) {
     246           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not construct eval request\n");
     247           0 :         goto done;
     248             :     }
     249             : 
     250           0 :     *rules = talloc_steal(mem_ctx, new_rules);
     251           0 :     *request = talloc_steal(mem_ctx, new_request);
     252           0 :     ret = EOK;
     253             : 
     254             : done:
     255           0 :     talloc_free(tmp_ctx);
     256           0 :     return ret;
     257             : }
     258             : 
     259             : static errno_t
     260           0 : hbac_attrs_to_rule(TALLOC_CTX *mem_ctx,
     261             :                    struct hbac_ctx *hbac_ctx,
     262             :                    size_t idx,
     263             :                    struct hbac_rule **rule)
     264             : {
     265           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);
     266             :     errno_t ret;
     267             :     struct hbac_rule *new_rule;
     268             :     struct ldb_message_element *el;
     269             :     const char *rule_type;
     270             : 
     271           0 :     new_rule = talloc_zero(mem_ctx, struct hbac_rule);
     272           0 :     if (new_rule == NULL) return ENOMEM;
     273             : 
     274           0 :     ret = sysdb_attrs_get_el(hbac_ctx->rules[idx],
     275             :                              IPA_CN, &el);
     276           0 :     if (ret != EOK || el->num_values == 0) {
     277           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "rule has no name, assuming '(none)'.\n");
     278           0 :         new_rule->name = talloc_strdup(new_rule, "(none)");
     279             :     } else {
     280           0 :         new_rule->name = talloc_strndup(new_rule,
     281           0 :                                         (const char*) el->values[0].data,
     282           0 :                                         el->values[0].length);
     283             :     }
     284             : 
     285           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Processing rule [%s]\n", new_rule->name);
     286             : 
     287           0 :     ret = sysdb_attrs_get_bool(hbac_ctx->rules[idx], IPA_ENABLED_FLAG,
     288             :                                &new_rule->enabled);
     289           0 :     if (ret != EOK) goto done;
     290             : 
     291           0 :     if (!new_rule->enabled) {
     292           0 :         ret = EOK;
     293           0 :         goto done;
     294             :     }
     295             : 
     296           0 :     ret = sysdb_attrs_get_string(hbac_ctx->rules[idx],
     297             :                                  IPA_ACCESS_RULE_TYPE,
     298             :                                  &rule_type);
     299           0 :     if (ret != EOK) goto done;
     300             : 
     301           0 :     if (strcasecmp(rule_type, IPA_HBAC_ALLOW) != 0) {
     302           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     303             :               "Rule [%s] is not an ALLOW rule\n", new_rule->name);
     304           0 :         ret = EPERM;
     305           0 :         goto done;
     306             :     }
     307             : 
     308             :     /* Get the users */
     309           0 :     ret = hbac_user_attrs_to_rule(new_rule, be_ctx->domain,
     310             :                                   new_rule->name,
     311           0 :                                   hbac_ctx->rules[idx],
     312             :                                   &new_rule->users);
     313           0 :     if (ret != EOK) {
     314           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not parse users for rule [%s]\n",
     315             :                   new_rule->name);
     316           0 :         goto done;
     317             :     }
     318             : 
     319             :     /* Get the services */
     320           0 :     ret = hbac_service_attrs_to_rule(new_rule, be_ctx->domain,
     321             :                                      new_rule->name,
     322           0 :                                      hbac_ctx->rules[idx],
     323             :                                      &new_rule->services);
     324           0 :     if (ret != EOK) {
     325           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not parse services for rule [%s]\n",
     326             :                   new_rule->name);
     327           0 :         goto done;
     328             :     }
     329             : 
     330             :     /* Get the target hosts */
     331           0 :     ret = hbac_thost_attrs_to_rule(new_rule, be_ctx->domain,
     332             :                                    new_rule->name,
     333           0 :                                    hbac_ctx->rules[idx],
     334             :                                    &new_rule->targethosts);
     335           0 :     if (ret != EOK) {
     336           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     337             :               "Could not parse target hosts for rule [%s]\n",
     338             :                   new_rule->name);
     339           0 :         goto done;
     340             :     }
     341             : 
     342             :     /* Get the source hosts */
     343             : 
     344           0 :     ret = hbac_shost_attrs_to_rule(new_rule, be_ctx->domain,
     345             :                                    new_rule->name,
     346           0 :                                    hbac_ctx->rules[idx],
     347           0 :                                    dp_opt_get_bool(hbac_ctx->ipa_options,
     348             :                                                    IPA_HBAC_SUPPORT_SRCHOST),
     349             :                                    &new_rule->srchosts);
     350           0 :     if (ret != EOK) {
     351           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     352             :               "Could not parse source hosts for rule [%s]\n",
     353             :                   new_rule->name);
     354           0 :         goto done;
     355             :     }
     356             : 
     357           0 :     *rule = new_rule;
     358           0 :     ret = EOK;
     359             : 
     360             : done:
     361           0 :     if (ret != EOK) talloc_free(new_rule);
     362           0 :     return ret;
     363             : }
     364             : 
     365             : errno_t
     366           0 : hbac_get_category(struct sysdb_attrs *attrs,
     367             :                   const char *category_attr,
     368             :                   uint32_t *_categories)
     369             : {
     370             :     errno_t ret;
     371             :     size_t i;
     372           0 :     uint32_t cats = HBAC_CATEGORY_NULL;
     373             :     const char **categories;
     374             : 
     375           0 :     TALLOC_CTX *tmp_ctx = talloc_new(NULL);
     376           0 :     if (tmp_ctx == NULL) return ENOMEM;
     377             : 
     378           0 :     ret = sysdb_attrs_get_string_array(attrs, category_attr,
     379             :                                        tmp_ctx, &categories);
     380           0 :     if (ret != EOK && ret != ENOENT) goto done;
     381             : 
     382           0 :     if (ret != ENOENT) {
     383           0 :         for (i = 0; categories[i]; i++) {
     384           0 :             if (strcasecmp("all", categories[i]) == 0) {
     385           0 :                 DEBUG(SSSDBG_FUNC_DATA, "Category is set to 'all'.\n");
     386           0 :                 cats |= HBAC_CATEGORY_ALL;
     387           0 :                 continue;
     388             :             }
     389           0 :             DEBUG(SSSDBG_TRACE_ALL, "Unsupported user category [%s].\n",
     390             :                       categories[i]);
     391             :         }
     392             :     }
     393             : 
     394           0 :     *_categories = cats;
     395           0 :     ret = EOK;
     396             : 
     397             : done:
     398           0 :     talloc_free(tmp_ctx);
     399           0 :     return ret;
     400             : }
     401             : 
     402             : static errno_t
     403             : hbac_eval_user_element(TALLOC_CTX *mem_ctx,
     404             :                        struct sss_domain_info *domain,
     405             :                        const char *username,
     406             :                        struct hbac_request_element **user_element);
     407             : 
     408             : static errno_t
     409             : hbac_eval_service_element(TALLOC_CTX *mem_ctx,
     410             :                           struct sss_domain_info *domain,
     411             :                           const char *servicename,
     412             :                           struct hbac_request_element **svc_element);
     413             : 
     414             : static errno_t
     415             : hbac_eval_host_element(TALLOC_CTX *mem_ctx,
     416             :                        struct sss_domain_info *domain,
     417             :                        const char *hostname,
     418             :                        struct hbac_request_element **host_element);
     419             : 
     420             : static errno_t
     421           0 : hbac_ctx_to_eval_request(TALLOC_CTX *mem_ctx,
     422             :                          struct hbac_ctx *hbac_ctx,
     423             :                          struct hbac_eval_req **request)
     424             : {
     425             :     errno_t ret;
     426           0 :     struct pam_data *pd = hbac_ctx->pd;
     427             :     TALLOC_CTX *tmp_ctx;
     428             :     struct hbac_eval_req *eval_req;
     429           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(hbac_ctx->be_req);
     430           0 :     struct sss_domain_info *domain = be_ctx->domain;
     431             :     const char *rhost;
     432             :     const char *thost;
     433             :     struct sss_domain_info *user_dom;
     434             : 
     435           0 :     tmp_ctx = talloc_new(mem_ctx);
     436           0 :     if (tmp_ctx == NULL) return ENOMEM;
     437             : 
     438           0 :     eval_req = talloc_zero(tmp_ctx, struct hbac_eval_req);
     439           0 :     if (eval_req == NULL) {
     440           0 :         ret = ENOMEM;
     441           0 :         goto done;
     442             :     }
     443             : 
     444           0 :     eval_req->request_time = time(NULL);
     445             : 
     446             :     /* Get user the user name and groups,
     447             :      * take care of subdomain users as well */
     448           0 :     if (strcasecmp(pd->domain, domain->name) != 0) {
     449           0 :         user_dom = find_domain_by_name(domain, pd->domain, true);
     450           0 :         if (user_dom == NULL) {
     451           0 :             DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
     452           0 :             ret = ENOMEM;
     453           0 :             goto done;
     454             :         }
     455           0 :         ret = hbac_eval_user_element(eval_req, user_dom, pd->user,
     456             :                                      &eval_req->user);
     457             :     } else {
     458           0 :         ret = hbac_eval_user_element(eval_req, domain, pd->user,
     459             :                                      &eval_req->user);
     460             :     }
     461           0 :     if (ret != EOK) goto done;
     462             : 
     463             :     /* Get the PAM service and service groups */
     464           0 :     ret = hbac_eval_service_element(eval_req, domain, pd->service,
     465             :                                     &eval_req->service);
     466           0 :     if (ret != EOK) goto done;
     467             : 
     468             :     /* Get the source host */
     469           0 :     if (pd->rhost == NULL || pd->rhost[0] == '\0') {
     470             :             /* If we haven't been passed an rhost,
     471             :              * the rhost is unknown. This will fail
     472             :              * to match any rule requiring the
     473             :              * source host.
     474             :              */
     475           0 :         rhost = NULL;
     476             :     } else {
     477           0 :         rhost = pd->rhost;
     478             :     }
     479             : 
     480           0 :     ret = hbac_eval_host_element(eval_req, domain, rhost,
     481             :                                  &eval_req->srchost);
     482           0 :     if (ret != EOK) goto done;
     483             : 
     484             :     /* The target host is always the current machine */
     485           0 :     thost = dp_opt_get_cstring(hbac_ctx->ipa_options, IPA_HOSTNAME);
     486           0 :     if (thost == NULL) {
     487           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     488             :               "Missing ipa_hostname, this should never happen.\n");
     489           0 :         ret = EINVAL;
     490           0 :         goto done;
     491             :     }
     492             : 
     493           0 :     ret = hbac_eval_host_element(eval_req, domain, thost,
     494             :                                  &eval_req->targethost);
     495           0 :     if (ret != EOK) goto done;
     496             : 
     497           0 :     *request = talloc_steal(mem_ctx, eval_req);
     498             : 
     499           0 :     ret = EOK;
     500             : 
     501             : done:
     502           0 :     talloc_free(tmp_ctx);
     503           0 :     return ret;
     504             : }
     505             : 
     506             : static errno_t
     507           0 : hbac_eval_user_element(TALLOC_CTX *mem_ctx,
     508             :                        struct sss_domain_info *domain,
     509             :                        const char *username,
     510             :                        struct hbac_request_element **user_element)
     511             : {
     512             :     errno_t ret;
     513             :     unsigned int i;
     514           0 :     unsigned int num_groups = 0;
     515             :     TALLOC_CTX *tmp_ctx;
     516             :     const char *member_dn;
     517             :     struct hbac_request_element *users;
     518             :     struct ldb_message *msg;
     519             :     struct ldb_message_element *el;
     520           0 :     const char *attrs[] = { SYSDB_ORIG_MEMBEROF, NULL };
     521             : 
     522           0 :     tmp_ctx = talloc_new(mem_ctx);
     523           0 :     if (tmp_ctx == NULL) return ENOMEM;
     524             : 
     525           0 :     users = talloc_zero(tmp_ctx, struct hbac_request_element);
     526           0 :     if (users == NULL) {
     527           0 :         ret = ENOMEM;
     528           0 :         goto done;
     529             :     }
     530             : 
     531           0 :     users->name = username;
     532             : 
     533             :     /* Read the originalMemberOf attribute
     534             :      * This will give us the list of both POSIX and
     535             :      * non-POSIX groups that this user belongs to.
     536             :      */
     537           0 :     ret = sysdb_search_user_by_name(tmp_ctx, domain, users->name,
     538             :                                     attrs, &msg);
     539           0 :     if (ret != EOK) {
     540           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     541             :               "Could not determine user memberships for [%s]\n",
     542             :                   users->name);
     543           0 :         goto done;
     544             :     }
     545             : 
     546           0 :     el = ldb_msg_find_element(msg, SYSDB_ORIG_MEMBEROF);
     547           0 :     if (el == NULL || el->num_values == 0) {
     548           0 :         DEBUG(SSSDBG_TRACE_LIBS, "No groups for [%s]\n", users->name);
     549           0 :         ret = create_empty_grouplist(users);
     550           0 :         goto done;
     551             :     }
     552           0 :     DEBUG(SSSDBG_TRACE_LIBS,
     553             :           "[%d] groups for [%s]\n", el->num_values, users->name);
     554             : 
     555           0 :     users->groups = talloc_array(users, const char *, el->num_values + 1);
     556           0 :     if (users->groups == NULL) {
     557           0 :         ret = ENOMEM;
     558           0 :         goto done;
     559             :     }
     560             : 
     561           0 :     for (i = 0; i < el->num_values; i++) {
     562           0 :         member_dn = (const char *)el->values[i].data;
     563             : 
     564           0 :         ret = get_ipa_groupname(users->groups, domain->sysdb, member_dn,
     565           0 :                                 &users->groups[num_groups]);
     566           0 :         if (ret != EOK && ret != ERR_UNEXPECTED_ENTRY_TYPE) {
     567           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     568             :                     "Skipping malformed entry [%s]\n", member_dn);
     569           0 :             continue;
     570           0 :         } else if (ret == EOK) {
     571           0 :             DEBUG(SSSDBG_TRACE_LIBS, "Added group [%s] for user [%s]\n",
     572             :                       users->groups[num_groups], users->name);
     573           0 :             num_groups++;
     574           0 :             continue;
     575             :         }
     576             :         /* Skip entries that are not groups */
     577           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
     578             :               "Skipping non-group memberOf [%s]\n", member_dn);
     579             :     }
     580           0 :     users->groups[num_groups] = NULL;
     581             : 
     582           0 :     if (num_groups < el->num_values) {
     583             :         /* Shrink the array memory */
     584           0 :         users->groups = talloc_realloc(users, users->groups, const char *,
     585             :                                        num_groups+1);
     586           0 :         if (users->groups == NULL) {
     587           0 :             ret = ENOMEM;
     588           0 :             goto done;
     589             :         }
     590             :     }
     591             : 
     592           0 :     ret = EOK;
     593             : done:
     594           0 :     if (ret == EOK) {
     595           0 :         *user_element = talloc_steal(mem_ctx, users);
     596             :     }
     597           0 :     talloc_free(tmp_ctx);
     598           0 :     return ret;
     599             : }
     600             : 
     601             : static errno_t
     602           0 : hbac_eval_service_element(TALLOC_CTX *mem_ctx,
     603             :                           struct sss_domain_info *domain,
     604             :                           const char *servicename,
     605             :                           struct hbac_request_element **svc_element)
     606             : {
     607             :     errno_t ret;
     608             :     size_t i, j, count;
     609             :     TALLOC_CTX *tmp_ctx;
     610             :     struct hbac_request_element *svc;
     611             :     struct ldb_message **msgs;
     612             :     struct ldb_message_element *el;
     613             :     struct ldb_dn *svc_dn;
     614           0 :     const char *memberof_attrs[] = { SYSDB_ORIG_MEMBEROF, NULL };
     615             :     char *name;
     616             : 
     617           0 :     tmp_ctx = talloc_new(mem_ctx);
     618           0 :     if (tmp_ctx == NULL) return ENOMEM;
     619             : 
     620           0 :     svc = talloc_zero(tmp_ctx, struct hbac_request_element);
     621           0 :     if (svc == NULL) {
     622           0 :         ret = ENOMEM;
     623           0 :         goto done;
     624             :     }
     625             : 
     626           0 :     svc->name = servicename;
     627             : 
     628           0 :     svc_dn = sysdb_custom_dn(tmp_ctx, domain, svc->name, HBAC_SERVICES_SUBDIR);
     629           0 :     if (svc_dn == NULL) {
     630           0 :         ret = ENOMEM;
     631           0 :         goto done;
     632             :     }
     633             : 
     634             :     /* Look up the service to get its originalMemberOf entries */
     635           0 :     ret = sysdb_search_entry(tmp_ctx, domain->sysdb, svc_dn,
     636             :                              LDB_SCOPE_BASE, NULL,
     637             :                              memberof_attrs,
     638             :                              &count, &msgs);
     639           0 :     if (ret == ENOENT || count == 0) {
     640             :         /* We won't be able to identify any groups
     641             :          * This rule will only match the name or
     642             :          * a service category of ALL
     643             :          */
     644           0 :         ret = create_empty_grouplist(svc);
     645           0 :         goto done;
     646           0 :     } else if (ret != EOK) {
     647           0 :         goto done;
     648           0 :     } else if (count > 1) {
     649           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "More than one result for a BASE search!\n");
     650           0 :         ret = EIO;
     651           0 :         goto done;
     652             :     }
     653             : 
     654           0 :     el = ldb_msg_find_element(msgs[0], SYSDB_ORIG_MEMBEROF);
     655           0 :     if (!el) {
     656             :         /* Service is not a member of any groups
     657             :          * This rule will only match the name or
     658             :          * a service category of ALL
     659             :          */
     660           0 :         ret = create_empty_grouplist(svc);
     661           0 :         goto done;
     662             :     }
     663             : 
     664             : 
     665           0 :     svc->groups = talloc_array(svc, const char *, el->num_values + 1);
     666           0 :     if (svc->groups == NULL) {
     667           0 :         ret = ENOMEM;
     668           0 :         goto done;
     669             :     }
     670             : 
     671           0 :     for (i = j = 0; i < el->num_values; i++) {
     672           0 :         ret = get_ipa_servicegroupname(tmp_ctx, domain->sysdb,
     673           0 :                                        (const char *)el->values[i].data,
     674             :                                        &name);
     675           0 :         if (ret != EOK && ret != ERR_UNEXPECTED_ENTRY_TYPE) {
     676           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Skipping malformed entry [%s]\n",
     677             :                                         (const char *)el->values[i].data);
     678           0 :             continue;
     679             :         }
     680             : 
     681             :         /* ERR_UNEXPECTED_ENTRY_TYPE means we had a memberOf entry that wasn't a
     682             :          * service group. We'll just ignore those (could be
     683             :          * HBAC rules)
     684             :          */
     685             : 
     686           0 :         if (ret == EOK) {
     687           0 :             svc->groups[j] = talloc_steal(svc->groups, name);
     688           0 :             j++;
     689             :         }
     690             :     }
     691           0 :     svc->groups[j] = NULL;
     692             : 
     693           0 :     ret = EOK;
     694             : 
     695             : done:
     696           0 :     if (ret == EOK) {
     697           0 :         *svc_element = talloc_steal(mem_ctx, svc);
     698             :     }
     699           0 :     talloc_free(tmp_ctx);
     700           0 :     return ret;
     701             : }
     702             : 
     703             : static errno_t
     704           0 : hbac_eval_host_element(TALLOC_CTX *mem_ctx,
     705             :                        struct sss_domain_info *domain,
     706             :                        const char *hostname,
     707             :                        struct hbac_request_element **host_element)
     708             : {
     709             :     errno_t ret;
     710             :     size_t i, j, count;
     711             :     TALLOC_CTX *tmp_ctx;
     712             :     struct hbac_request_element *host;
     713             :     struct ldb_message **msgs;
     714             :     struct ldb_message_element *el;
     715             :     struct ldb_dn *host_dn;
     716           0 :     const char *memberof_attrs[] = { SYSDB_ORIG_MEMBEROF, NULL };
     717             :     char *name;
     718             : 
     719           0 :     tmp_ctx = talloc_new(mem_ctx);
     720           0 :     if (tmp_ctx == NULL) return ENOMEM;
     721             : 
     722           0 :     host = talloc_zero(tmp_ctx, struct hbac_request_element);
     723           0 :     if (host == NULL) {
     724           0 :         ret = ENOMEM;
     725           0 :         goto done;
     726             :     }
     727             : 
     728           0 :     host->name = hostname;
     729             : 
     730           0 :     if (host->name == NULL) {
     731             :         /* We don't know the host (probably an rhost)
     732             :          * So we can't determine it's groups either.
     733             :          */
     734           0 :         ret = create_empty_grouplist(host);
     735           0 :         goto done;
     736             :     }
     737             : 
     738           0 :     host_dn = sysdb_custom_dn(tmp_ctx, domain, host->name, HBAC_HOSTS_SUBDIR);
     739           0 :     if (host_dn == NULL) {
     740           0 :         ret = ENOMEM;
     741           0 :         goto done;
     742             :     }
     743             : 
     744             :     /* Look up the host to get its originalMemberOf entries */
     745           0 :     ret = sysdb_search_entry(tmp_ctx, domain->sysdb, host_dn,
     746             :                              LDB_SCOPE_BASE, NULL,
     747             :                              memberof_attrs,
     748             :                              &count, &msgs);
     749           0 :     if (ret == ENOENT || count == 0) {
     750             :         /* We won't be able to identify any groups
     751             :          * This rule will only match the name or
     752             :          * a host category of ALL
     753             :          */
     754           0 :         ret = create_empty_grouplist(host);
     755           0 :         goto done;
     756           0 :     } else if (ret != EOK) {
     757           0 :         goto done;
     758           0 :     } else if (count > 1) {
     759           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "More than one result for a BASE search!\n");
     760           0 :         ret = EIO;
     761           0 :         goto done;
     762             :     }
     763             : 
     764           0 :     el = ldb_msg_find_element(msgs[0], SYSDB_ORIG_MEMBEROF);
     765           0 :     if (!el) {
     766             :         /* Host is not a member of any groups
     767             :          * This rule will only match the name or
     768             :          * a host category of ALL
     769             :          */
     770           0 :         ret = create_empty_grouplist(host);
     771           0 :         goto done;
     772             :     }
     773             : 
     774             : 
     775           0 :     host->groups = talloc_array(host, const char *, el->num_values + 1);
     776           0 :     if (host->groups == NULL) {
     777           0 :         ret = ENOMEM;
     778           0 :         goto done;
     779             :     }
     780             : 
     781           0 :     for (i = j = 0; i < el->num_values; i++) {
     782           0 :         ret = get_ipa_hostgroupname(tmp_ctx, domain->sysdb,
     783           0 :                                     (const char *)el->values[i].data,
     784             :                                     &name);
     785           0 :         if (ret != EOK && ret != ERR_UNEXPECTED_ENTRY_TYPE) {
     786           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Skipping malformed entry [%s]\n",
     787             :                                         (const char *)el->values[i].data);
     788           0 :             continue;
     789             :         }
     790             : 
     791             :         /* ERR_UNEXPECTED_ENTRY_TYPE means we had a memberOf entry that wasn't a
     792             :          * host group. We'll just ignore those (could be
     793             :          * HBAC rules)
     794             :          */
     795             : 
     796           0 :         if (ret == EOK) {
     797           0 :             host->groups[j] = talloc_steal(host->groups, name);
     798           0 :             j++;
     799             :         }
     800             :     }
     801           0 :     host->groups[j] = NULL;
     802             : 
     803           0 :     ret = EOK;
     804             : 
     805             : done:
     806           0 :     if (ret == EOK) {
     807           0 :         *host_element = talloc_steal(mem_ctx, host);
     808             :     }
     809           0 :     talloc_free(tmp_ctx);
     810           0 :     return ret;
     811             : }

Generated by: LCOV version 1.10