LCOV - code coverage report
Current view: top level - providers/ipa - ipa_hbac_hosts.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 190 0.0 %
Date: 2016-06-29 Functions: 0 4 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 "util/util.h"
      24             : #include "db/sysdb.h"
      25             : #include "providers/ipa/ipa_hbac_private.h"
      26             : #include "providers/ldap/sdap_async.h"
      27             : 
      28             : /*
      29             :  * Functions to convert sysdb_attrs to the hbac_rule format
      30             :  */
      31           0 : static errno_t hbac_host_attrs_to_rule(TALLOC_CTX *mem_ctx,
      32             :                                        struct sss_domain_info *domain,
      33             :                                        const char *rule_name,
      34             :                                        struct sysdb_attrs *rule_attrs,
      35             :                                        const char *category_attr,
      36             :                                        const char *member_attr,
      37             :                                        size_t *host_count,
      38             :                                        struct hbac_rule_element **hosts)
      39             : {
      40             :     errno_t ret;
      41             :     TALLOC_CTX *tmp_ctx;
      42             :     struct hbac_rule_element *new_hosts;
      43           0 :     const char *attrs[] = { SYSDB_FQDN, SYSDB_NAME, NULL };
      44             :     struct ldb_message_element *el;
      45           0 :     size_t num_hosts = 0;
      46           0 :     size_t num_hostgroups = 0;
      47             :     size_t i;
      48             :     char *member_dn;
      49             :     char *filter;
      50             :     size_t count;
      51             :     struct ldb_message **msgs;
      52             :     const char *name;
      53             : 
      54           0 :     tmp_ctx = talloc_new(mem_ctx);
      55           0 :     if (tmp_ctx == NULL) return ENOMEM;
      56             : 
      57           0 :     new_hosts = talloc_zero(tmp_ctx, struct hbac_rule_element);
      58           0 :     if (new_hosts == NULL) {
      59           0 :         ret = ENOMEM;
      60           0 :         goto done;
      61             :     }
      62             : 
      63             :     /* First check for host category */
      64           0 :     ret = hbac_get_category(rule_attrs, category_attr, &new_hosts->category);
      65           0 :     if (ret != EOK) {
      66           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not identify host categories\n");
      67           0 :         goto done;
      68             :     }
      69           0 :     if (new_hosts->category & HBAC_CATEGORY_ALL) {
      70             :         /* Short-cut to the exit */
      71           0 :         ret = EOK;
      72           0 :         goto done;
      73             :     }
      74             : 
      75             :     /* Get the list of DNs from the member_attr */
      76           0 :     ret = sysdb_attrs_get_el(rule_attrs, member_attr, &el);
      77           0 :     if (ret != EOK && ret != ENOENT) {
      78           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_get_el failed.\n");
      79           0 :         goto done;
      80             :     }
      81           0 :     if (ret == ENOENT || el->num_values == 0) {
      82           0 :         el->num_values = 0;
      83           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
      84             :               "No host specified, rule will never apply.\n");
      85             :     }
      86             : 
      87             :     /* Assume maximum size; We'll trim it later */
      88           0 :     new_hosts->names = talloc_array(new_hosts,
      89             :                                     const char *,
      90             :                                     el->num_values +1);
      91           0 :     if (new_hosts->names == NULL) {
      92           0 :         ret = ENOMEM;
      93           0 :         goto done;
      94             :     }
      95             : 
      96           0 :     new_hosts->groups = talloc_array(new_hosts,
      97             :                                      const char *,
      98             :                                      el->num_values + 1);
      99           0 :     if (new_hosts->groups == NULL) {
     100           0 :         ret = ENOMEM;
     101           0 :         goto done;
     102             :     }
     103             : 
     104           0 :     for (i = 0; i < el->num_values; i++) {
     105           0 :         ret = sss_filter_sanitize(tmp_ctx,
     106           0 :                                   (const char *)el->values[i].data,
     107             :                                   &member_dn);
     108           0 :         if (ret != EOK) goto done;
     109             : 
     110           0 :         filter = talloc_asprintf(member_dn, "(%s=%s)",
     111             :                                  SYSDB_ORIG_DN, member_dn);
     112           0 :         if (filter == NULL) {
     113           0 :             ret = ENOMEM;
     114           0 :             goto done;
     115             :         }
     116             : 
     117             :         /* First check if this is a specific host */
     118           0 :         ret = sysdb_search_custom(tmp_ctx, domain, filter,
     119             :                                   HBAC_HOSTS_SUBDIR, attrs,
     120             :                                   &count, &msgs);
     121           0 :         if (ret != EOK && ret != ENOENT) goto done;
     122           0 :         if (ret == EOK && count == 0) {
     123           0 :             ret = ENOENT;
     124             :         }
     125             : 
     126           0 :         if (ret == EOK) {
     127           0 :             if (count > 1) {
     128           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     129             :                       "Original DN matched multiple hosts. Skipping \n");
     130           0 :                 talloc_zfree(member_dn);
     131           0 :                 continue;
     132             :             }
     133             : 
     134             :             /* Original DN matched a single host. Get the hostname */
     135           0 :             name = ldb_msg_find_attr_as_string(msgs[0],
     136             :                                                SYSDB_FQDN,
     137             :                                                NULL);
     138           0 :             if (name == NULL) {
     139           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "FQDN is missing!\n");
     140           0 :                 ret = EFAULT;
     141           0 :                 goto done;
     142             :             }
     143             : 
     144           0 :             new_hosts->names[num_hosts] = talloc_strdup(new_hosts->names,
     145             :                                                         name);
     146           0 :             if (new_hosts->names[num_hosts] == NULL) {
     147           0 :                 ret = ENOMEM;
     148           0 :                 goto done;
     149             :             }
     150           0 :             DEBUG(SSSDBG_TRACE_INTERNAL, "Added host [%s] to rule [%s]\n",
     151             :                       name, rule_name);
     152           0 :             num_hosts++;
     153             :         } else { /* ret == ENOENT */
     154             :             /* Check if this is a hostgroup */
     155           0 :             ret = sysdb_search_custom(tmp_ctx, domain, filter,
     156             :                                       HBAC_HOSTGROUPS_SUBDIR, attrs,
     157             :                                       &count, &msgs);
     158           0 :             if (ret != EOK && ret != ENOENT) goto done;
     159           0 :             if (ret == EOK && count == 0) {
     160           0 :                 ret = ENOENT;
     161             :             }
     162             : 
     163           0 :             if (ret == EOK) {
     164           0 :                 if (count > 1) {
     165           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     166             :                           "Original DN matched multiple hostgroups. "
     167             :                               "Skipping\n");
     168           0 :                     talloc_zfree(member_dn);
     169           0 :                     continue;
     170             :                 }
     171             : 
     172             :                 /* Original DN matched a single group. Get the groupname */
     173           0 :                 name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
     174           0 :                 if (name == NULL) {
     175           0 :                     DEBUG(SSSDBG_CRIT_FAILURE, "Hostgroup name is missing!\n");
     176           0 :                     ret = EFAULT;
     177           0 :                     goto done;
     178             :                 }
     179             : 
     180           0 :                 new_hosts->groups[num_hostgroups] =
     181           0 :                         talloc_strdup(new_hosts->groups, name);
     182           0 :                 if (new_hosts->groups[num_hostgroups] == NULL) {
     183           0 :                     ret = ENOMEM;
     184           0 :                     goto done;
     185             :                 }
     186             : 
     187           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL,
     188             :                       "Added hostgroup [%s] to rule [%s]\n",
     189             :                           name, rule_name);
     190           0 :                 num_hostgroups++;
     191             :             } else { /* ret == ENOENT */
     192             :                 /* Neither a host nor a hostgroup? Skip it */
     193           0 :                 DEBUG(SSSDBG_TRACE_LIBS,
     194             :                       "[%s] does not map to either a host or hostgroup. "
     195             :                        "Skipping\n", member_dn);
     196             :             }
     197             :         }
     198           0 :         talloc_zfree(member_dn);
     199             :     }
     200           0 :     new_hosts->names[num_hosts] = NULL;
     201           0 :     new_hosts->groups[num_hostgroups] = NULL;
     202             : 
     203             :     /* Shrink the arrays down to their real sizes */
     204           0 :     new_hosts->names = talloc_realloc(new_hosts, new_hosts->names,
     205             :                                       const char *, num_hosts + 1);
     206           0 :     if (new_hosts->names == NULL) {
     207           0 :         ret = ENOMEM;
     208           0 :         goto done;
     209             :     }
     210             : 
     211           0 :     new_hosts->groups = talloc_realloc(new_hosts, new_hosts->groups,
     212             :                                        const char *, num_hostgroups + 1);
     213           0 :     if (new_hosts->groups == NULL) {
     214           0 :         ret = ENOMEM;
     215           0 :         goto done;
     216             :     }
     217             : 
     218           0 :     ret = EOK;
     219             : 
     220             : done:
     221           0 :     if (ret == EOK) {
     222           0 :         *hosts = talloc_steal(mem_ctx, new_hosts);
     223           0 :         if (host_count) *host_count = num_hosts;
     224             :     }
     225           0 :     talloc_free(tmp_ctx);
     226           0 :     return ret;
     227             : }
     228             : 
     229             : errno_t
     230           0 : hbac_thost_attrs_to_rule(TALLOC_CTX *mem_ctx,
     231             :                          struct sss_domain_info *domain,
     232             :                          const char *rule_name,
     233             :                          struct sysdb_attrs *rule_attrs,
     234             :                          struct hbac_rule_element **thosts)
     235             : {
     236           0 :     DEBUG(SSSDBG_TRACE_LIBS,
     237             :           "Processing target hosts for rule [%s]\n", rule_name);
     238             : 
     239           0 :     return hbac_host_attrs_to_rule(mem_ctx, domain,
     240             :                                    rule_name, rule_attrs,
     241             :                                    IPA_HOST_CATEGORY, IPA_MEMBER_HOST,
     242             :                                    NULL, thosts);
     243             : }
     244             : 
     245             : errno_t
     246           0 : hbac_shost_attrs_to_rule(TALLOC_CTX *mem_ctx,
     247             :                          struct sss_domain_info *domain,
     248             :                          const char *rule_name,
     249             :                          struct sysdb_attrs *rule_attrs,
     250             :                          bool support_srchost,
     251             :                          struct hbac_rule_element **source_hosts)
     252             : {
     253             :     errno_t ret;
     254             :     size_t host_count;
     255             :     TALLOC_CTX *tmp_ctx;
     256             :     size_t idx;
     257             :     struct ldb_message_element *el;
     258             :     struct hbac_rule_element *shosts;
     259             : 
     260           0 :     tmp_ctx = talloc_new(mem_ctx);
     261           0 :     if (tmp_ctx == NULL) return ENOMEM;
     262             : 
     263           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Processing source hosts for rule [%s]\n", rule_name);
     264             : 
     265           0 :     if (!support_srchost) {
     266           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Source hosts disabled, setting ALL\n");
     267           0 :         shosts = talloc_zero(tmp_ctx, struct hbac_rule_element);
     268           0 :         if (shosts == NULL) {
     269           0 :             ret = ENOMEM;
     270           0 :             goto done;
     271             :         }
     272             : 
     273           0 :         shosts->category = HBAC_CATEGORY_ALL;
     274           0 :         ret = EOK;
     275           0 :         goto done;
     276             :     } else {
     277           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "WARNING: Using deprecated option "
     278             :                     "ipa_hbac_support_srchost.\n");
     279           0 :         sss_log(SSS_LOG_NOTICE, "WARNING: Using deprecated option "
     280             :                     "ipa_hbac_support_srchost.\n");
     281             :     }
     282             : 
     283           0 :     ret = hbac_host_attrs_to_rule(tmp_ctx, domain,
     284             :                                   rule_name, rule_attrs,
     285             :                                   IPA_SOURCE_HOST_CATEGORY, IPA_SOURCE_HOST,
     286             :                                   &host_count, &shosts);
     287           0 :     if (ret != EOK) {
     288           0 :         goto done;
     289             :     }
     290             : 
     291           0 :     if (shosts->category & HBAC_CATEGORY_ALL) {
     292             :         /* All hosts (including external) are
     293             :          * allowed.
     294             :          */
     295           0 :         goto done;
     296             :     }
     297             : 
     298             :     /* Include external (non-IPA-managed) source hosts */
     299           0 :     ret = sysdb_attrs_get_el(rule_attrs, IPA_EXTERNAL_HOST, &el);
     300           0 :     if (ret != EOK && ret != ENOENT) goto done;
     301           0 :     if (ret == EOK && el->num_values == 0) ret = ENOENT;
     302             : 
     303           0 :     if (ret != ENOENT) {
     304           0 :         shosts->names = talloc_realloc(shosts, shosts->names, const char *,
     305             :                                        host_count + el->num_values + 1);
     306           0 :         if (shosts->names == NULL) {
     307           0 :             ret = ENOMEM;
     308           0 :             goto done;
     309             :         }
     310             : 
     311           0 :         for (idx = host_count; idx < host_count + el->num_values; idx++) {
     312           0 :             shosts->names[idx] =
     313           0 :                     talloc_strdup(shosts->names,
     314           0 :                                (const char *)el->values[idx - host_count].data);
     315           0 :             if (shosts->names[idx] == NULL) {
     316           0 :                 ret = ENOMEM;
     317           0 :                 goto done;
     318             :             }
     319           0 :             DEBUG(SSSDBG_TRACE_INTERNAL,
     320             :                   "Added external source host [%s] to rule [%s]\n",
     321             :                       shosts->names[idx], rule_name);
     322             :         }
     323           0 :         shosts->names[idx] = NULL;
     324             :     }
     325             : 
     326           0 :     ret = EOK;
     327             : 
     328             : done:
     329           0 :     if (ret == EOK) {
     330           0 :         *source_hosts = talloc_steal(mem_ctx, shosts);
     331             :     }
     332           0 :     talloc_free(tmp_ctx);
     333           0 :     return ret;
     334             : }
     335             : 
     336             : errno_t
     337           0 : get_ipa_hostgroupname(TALLOC_CTX *mem_ctx,
     338             :                       struct sysdb_ctx *sysdb,
     339             :                       const char *host_dn,
     340             :                       char **hostgroupname)
     341             : {
     342             :     errno_t ret;
     343             :     struct ldb_dn *dn;
     344             :     const char *rdn_name;
     345             :     const char *hostgroup_comp_name;
     346             :     const char *account_comp_name;
     347             :     const struct ldb_val *rdn_val;
     348             :     const struct ldb_val *hostgroup_comp_val;
     349             :     const struct ldb_val *account_comp_val;
     350             : 
     351             :     /* This is an IPA-specific hack. It may not
     352             :      * work for non-IPA servers and will need to
     353             :      * be changed if SSSD ever supports HBAC on
     354             :      * a non-IPA server.
     355             :      */
     356           0 :     *hostgroupname = NULL;
     357             : 
     358           0 :     dn = ldb_dn_new(mem_ctx, sysdb_ctx_get_ldb(sysdb), host_dn);
     359           0 :     if (dn == NULL) {
     360           0 :         ret = ENOMEM;
     361           0 :         goto done;
     362             :     }
     363             : 
     364           0 :     if (!ldb_dn_validate(dn)) {
     365           0 :         ret = ERR_MALFORMED_ENTRY;
     366           0 :         goto done;
     367             :     }
     368             : 
     369           0 :     if (ldb_dn_get_comp_num(dn) < 4) {
     370             :         /* RDN, hostgroups, accounts, and at least one DC= */
     371             :         /* If it's fewer, it's not a group DN */
     372           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     373           0 :         goto done;
     374             :     }
     375             : 
     376             :     /* If the RDN name is 'cn' */
     377           0 :     rdn_name = ldb_dn_get_rdn_name(dn);
     378           0 :     if (rdn_name == NULL) {
     379             :         /* Shouldn't happen if ldb_dn_validate()
     380             :          * passed, but we'll be careful.
     381             :          */
     382           0 :         ret = ERR_MALFORMED_ENTRY;
     383           0 :         goto done;
     384             :     }
     385             : 
     386           0 :     if (strcasecmp("cn", rdn_name) != 0) {
     387             :         /* RDN has the wrong attribute name.
     388             :          * It's not a host.
     389             :          */
     390           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     391           0 :         goto done;
     392             :     }
     393             : 
     394             :     /* and the second component is "cn=hostgroups" */
     395           0 :     hostgroup_comp_name = ldb_dn_get_component_name(dn, 1);
     396           0 :     if (strcasecmp("cn", hostgroup_comp_name) != 0) {
     397             :         /* The second component name is not "cn" */
     398           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     399           0 :         goto done;
     400             :     }
     401             : 
     402           0 :     hostgroup_comp_val = ldb_dn_get_component_val(dn, 1);
     403           0 :     if (strncasecmp("hostgroups",
     404           0 :                     (const char *) hostgroup_comp_val->data,
     405             :                     hostgroup_comp_val->length) != 0) {
     406             :         /* The second component value is not "hostgroups" */
     407           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     408           0 :         goto done;
     409             :     }
     410             : 
     411             :     /* and the third component is "accounts" */
     412           0 :     account_comp_name = ldb_dn_get_component_name(dn, 2);
     413           0 :     if (strcasecmp("cn", account_comp_name) != 0) {
     414             :         /* The third component name is not "cn" */
     415           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     416           0 :         goto done;
     417             :     }
     418             : 
     419           0 :     account_comp_val = ldb_dn_get_component_val(dn, 2);
     420           0 :     if (strncasecmp("accounts",
     421           0 :                     (const char *) account_comp_val->data,
     422             :                     account_comp_val->length) != 0) {
     423             :         /* The third component value is not "accounts" */
     424           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     425           0 :         goto done;
     426             :     }
     427             : 
     428             :     /* Then the value of the RDN is the group name */
     429           0 :     rdn_val = ldb_dn_get_rdn_val(dn);
     430           0 :     *hostgroupname = talloc_strndup(mem_ctx,
     431           0 :                                     (const char *)rdn_val->data,
     432             :                                     rdn_val->length);
     433           0 :     if (*hostgroupname == NULL) {
     434           0 :         ret = ENOMEM;
     435           0 :         goto done;
     436             :     }
     437             : 
     438           0 :     ret = EOK;
     439             : 
     440             : done:
     441           0 :     talloc_free(dn);
     442           0 :     return ret;
     443             : }

Generated by: LCOV version 1.10