LCOV - code coverage report
Current view: top level - providers/ipa - ipa_hbac_users.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 154 0.0 %
Date: 2015-10-19 Functions: 0 2 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 "providers/ipa/ipa_hbac_private.h"
      25             : #include "providers/ldap/sdap_async.h"
      26             : 
      27             : /* Returns EOK and populates groupname if
      28             :  * the group_dn is actually a group.
      29             :  * Returns ENOENT if group_dn does not point
      30             :  * at a a group.
      31             :  * Returns EINVAL if there is a parsing error.
      32             :  * Returns ENOMEM as appropriate
      33             :  */
      34             : errno_t
      35           0 : get_ipa_groupname(TALLOC_CTX *mem_ctx,
      36             :                   struct sysdb_ctx *sysdb,
      37             :                   const char *group_dn,
      38             :                   const char **groupname)
      39             : {
      40             :     errno_t ret;
      41             :     struct ldb_dn *dn;
      42             :     const char *rdn_name;
      43             :     const char *group_comp_name;
      44             :     const char *account_comp_name;
      45             :     const struct ldb_val *rdn_val;
      46             :     const struct ldb_val *group_comp_val;
      47             :     const struct ldb_val *account_comp_val;
      48             : 
      49             :     /* This is an IPA-specific hack. It may not
      50             :      * work for non-IPA servers and will need to
      51             :      * be changed if SSSD ever supports HBAC on
      52             :      * a non-IPA server.
      53             :      */
      54           0 :     *groupname = NULL;
      55             : 
      56           0 :     dn = ldb_dn_new(mem_ctx, sysdb_ctx_get_ldb(sysdb), group_dn);
      57           0 :     if (dn == NULL) {
      58           0 :         ret = ENOMEM;
      59           0 :         goto done;
      60             :     }
      61             : 
      62           0 :     if (!ldb_dn_validate(dn)) {
      63           0 :         ret = ERR_MALFORMED_ENTRY;
      64           0 :         goto done;
      65             :     }
      66             : 
      67           0 :     if (ldb_dn_get_comp_num(dn) < 4) {
      68             :         /* RDN, groups, accounts, and at least one DC= */
      69             :         /* If it's fewer, it's not a group DN */
      70           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
      71           0 :         goto done;
      72             :     }
      73             : 
      74             :     /* If the RDN name is 'cn' */
      75           0 :     rdn_name = ldb_dn_get_rdn_name(dn);
      76           0 :     if (rdn_name == NULL) {
      77             :         /* Shouldn't happen if ldb_dn_validate()
      78             :          * passed, but we'll be careful.
      79             :          */
      80           0 :         ret = ERR_MALFORMED_ENTRY;
      81           0 :         goto done;
      82             :     }
      83             : 
      84           0 :     if (strcasecmp("cn", rdn_name) != 0) {
      85             :         /* RDN has the wrong attribute name.
      86             :          * It's not a group.
      87             :          */
      88           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
      89           0 :         goto done;
      90             :     }
      91             : 
      92             :     /* and the second component is "cn=groups" */
      93           0 :     group_comp_name = ldb_dn_get_component_name(dn, 1);
      94           0 :     if (strcasecmp("cn", group_comp_name) != 0) {
      95             :         /* The second component name is not "cn" */
      96           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
      97           0 :         goto done;
      98             :     }
      99             : 
     100           0 :     group_comp_val = ldb_dn_get_component_val(dn, 1);
     101           0 :     if (strncasecmp("groups",
     102           0 :                     (const char *) group_comp_val->data,
     103             :                     group_comp_val->length) != 0) {
     104             :         /* The second component value is not "groups" */
     105           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     106           0 :         goto done;
     107             :     }
     108             : 
     109             :     /* and the third component is "accounts" */
     110           0 :     account_comp_name = ldb_dn_get_component_name(dn, 2);
     111           0 :     if (strcasecmp("cn", account_comp_name) != 0) {
     112             :         /* The third component name is not "cn" */
     113           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     114           0 :         goto done;
     115             :     }
     116             : 
     117           0 :     account_comp_val = ldb_dn_get_component_val(dn, 2);
     118           0 :     if (strncasecmp("accounts",
     119           0 :                     (const char *) account_comp_val->data,
     120             :                     account_comp_val->length) != 0) {
     121             :         /* The third component value is not "accounts" */
     122           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     123           0 :         goto done;
     124             :     }
     125             : 
     126             :     /* Then the value of the RDN is the group name */
     127           0 :     rdn_val = ldb_dn_get_rdn_val(dn);
     128           0 :     *groupname = talloc_strndup(mem_ctx,
     129           0 :                                 (const char *)rdn_val->data,
     130             :                                 rdn_val->length);
     131           0 :     if (*groupname == NULL) {
     132           0 :         ret = ENOMEM;
     133           0 :         goto done;
     134             :     }
     135             : 
     136           0 :     ret = EOK;
     137             : 
     138             : done:
     139           0 :     talloc_free(dn);
     140           0 :     return ret;
     141             : }
     142             : 
     143             : errno_t
     144           0 : hbac_user_attrs_to_rule(TALLOC_CTX *mem_ctx,
     145             :                         struct sss_domain_info *domain,
     146             :                         const char *rule_name,
     147             :                         struct sysdb_attrs *rule_attrs,
     148             :                         struct hbac_rule_element **users)
     149             : {
     150             :     errno_t ret;
     151           0 :     TALLOC_CTX *tmp_ctx = NULL;
     152           0 :     struct hbac_rule_element *new_users = NULL;
     153           0 :     struct ldb_message_element *el = NULL;
     154           0 :     struct ldb_message **msgs = NULL;
     155             :     char *filter;
     156             :     char *member_dn;
     157             :     const char *member_user;
     158           0 :     const char *attrs[] = { SYSDB_NAME, NULL };
     159           0 :     size_t num_users = 0;
     160           0 :     size_t num_groups = 0;
     161             :     const char *name;
     162             : 
     163             :     size_t count;
     164             :     size_t i;
     165             : 
     166           0 :     tmp_ctx = talloc_new(mem_ctx);
     167           0 :     if (tmp_ctx == NULL) return ENOMEM;
     168             : 
     169           0 :     new_users = talloc_zero(tmp_ctx, struct hbac_rule_element);
     170           0 :     if (new_users == NULL) {
     171           0 :         ret = ENOMEM;
     172           0 :         goto done;
     173             :     }
     174             : 
     175           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Processing users for rule [%s]\n", rule_name);
     176             : 
     177           0 :     ret = hbac_get_category(rule_attrs, IPA_USER_CATEGORY,
     178             :                             &new_users->category);
     179           0 :     if (ret != EOK) {
     180           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not identify user categories\n");
     181           0 :         goto done;
     182             :     }
     183           0 :     if (new_users->category & HBAC_CATEGORY_ALL) {
     184             :         /* Short-cut to the exit */
     185           0 :         ret = EOK;
     186           0 :         goto done;
     187             :     }
     188             : 
     189           0 :     ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_USER, &el);
     190           0 :     if (ret != EOK && ret != ENOENT) {
     191           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_get_el failed.\n");
     192           0 :         goto done;
     193             :     }
     194           0 :     if (ret == ENOENT || el->num_values == 0) {
     195           0 :         el->num_values = 0;
     196           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     197             :               "No user specified, rule will never apply.\n");
     198             :     }
     199             : 
     200           0 :     new_users->names = talloc_array(new_users,
     201             :                                     const char *,
     202             :                                     el->num_values + 1);
     203           0 :     if (new_users->names == NULL) {
     204           0 :         ret = ENOMEM;
     205           0 :         goto done;
     206             :     }
     207             : 
     208           0 :     new_users->groups = talloc_array(new_users,
     209             :                                      const char *,
     210             :                                      el->num_values + 1);
     211           0 :     if (new_users->groups == NULL) {
     212           0 :         ret = ENOMEM;
     213           0 :         goto done;
     214             :     }
     215             : 
     216           0 :     for (i = 0; i < el->num_values; i++) {
     217           0 :         member_user = (const char *)el->values[i].data;
     218           0 :         ret = sss_filter_sanitize(tmp_ctx, member_user, &member_dn);
     219           0 :         if (ret != EOK) goto done;
     220             : 
     221           0 :         filter = talloc_asprintf(member_dn, "(%s=%s)",
     222             :                                  SYSDB_ORIG_DN, member_dn);
     223           0 :         if (filter == NULL) {
     224           0 :             ret = ENOMEM;
     225           0 :             goto done;
     226             :         }
     227             : 
     228             :         /* First check if this is a user */
     229           0 :         ret = sysdb_search_users(tmp_ctx, domain,
     230             :                                  filter, attrs, &count, &msgs);
     231           0 :         if (ret != EOK && ret != ENOENT) goto done;
     232           0 :         if (ret == EOK && count == 0) {
     233           0 :             ret = ENOENT;
     234             :         }
     235             : 
     236           0 :         if (ret == EOK) {
     237           0 :             if (count > 1) {
     238           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     239             :                       "Original DN matched multiple users. Skipping \n");
     240           0 :                 talloc_zfree(member_dn);
     241           0 :                 continue;
     242             :             }
     243             : 
     244             :             /* Original DN matched a single user. Get the username */
     245           0 :             name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
     246           0 :             if (name == NULL) {
     247           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
     248           0 :                 ret = EFAULT;
     249           0 :                 goto done;
     250             :             }
     251             : 
     252           0 :             new_users->names[num_users] = talloc_strdup(new_users->names,
     253             :                                                         name);
     254           0 :             if (new_users->names[num_users] == NULL) {
     255           0 :                 ret = ENOMEM;
     256           0 :                 goto done;
     257             :             }
     258           0 :             DEBUG(SSSDBG_TRACE_INTERNAL, "Added user [%s] to rule [%s]\n",
     259             :                       name, rule_name);
     260           0 :             num_users++;
     261             :         } else {
     262             :             /* Check if it is a group instead */
     263           0 :             ret = sysdb_search_groups(tmp_ctx, domain, filter, attrs,
     264             :                                       &count, &msgs);
     265           0 :             if (ret != EOK && ret != ENOENT) goto done;
     266           0 :             if (ret == EOK && count == 0) {
     267           0 :                 ret = ENOENT;
     268             :             }
     269             : 
     270           0 :             if (ret == EOK) {
     271           0 :                 if (count > 1) {
     272           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     273             :                           "Original DN matched multiple groups. "
     274             :                               "Skipping\n");
     275           0 :                     talloc_zfree(member_dn);
     276           0 :                     continue;
     277             :                 }
     278             : 
     279             :                 /* Original DN matched a single group. Get the groupname */
     280           0 :                 name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
     281           0 :                 if (name == NULL) {
     282           0 :                     DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
     283           0 :                     ret = EFAULT;
     284           0 :                     goto done;
     285             :                 }
     286             : 
     287           0 :                 new_users->groups[num_groups] =
     288           0 :                         talloc_strdup(new_users->groups, name);
     289           0 :                 if (new_users->groups[num_groups] == NULL) {
     290           0 :                     ret = ENOMEM;
     291           0 :                     goto done;
     292             :                 }
     293           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL,
     294             :                       "Added POSIX group [%s] to rule [%s]\n",
     295             :                           name, rule_name);
     296           0 :                 num_groups++;
     297             :             } else {
     298             :                 /* If the group still matches the group pattern,
     299             :                  * we can assume it is a non-POSIX group.
     300             :                  */
     301           0 :                 ret = get_ipa_groupname(new_users->groups, domain->sysdb,
     302             :                                         member_user,
     303           0 :                                         &new_users->groups[num_groups]);
     304           0 :                 if (ret == EOK) {
     305           0 :                     DEBUG(SSSDBG_TRACE_INTERNAL,
     306             :                           "Added non-POSIX group [%s] to rule [%s]\n",
     307             :                               new_users->groups[num_groups], rule_name);
     308           0 :                     num_groups++;
     309             :                 } else {
     310             :                     /* Not a group, so we don't care about it */
     311           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     312             :                           "[%s] does not map to either a user or group. "
     313             :                               "Skipping\n", member_dn);
     314             :                 }
     315             :             }
     316             :         }
     317           0 :         talloc_zfree(member_dn);
     318             :     }
     319           0 :     new_users->names[num_users] = NULL;
     320           0 :     new_users->groups[num_groups] = NULL;
     321             : 
     322             :     /* Shrink the arrays down to their real sizes */
     323           0 :     new_users->names = talloc_realloc(new_users, new_users->names,
     324             :                                       const char *, num_users + 1);
     325           0 :     if (new_users->names == NULL) {
     326           0 :         ret = ENOMEM;
     327           0 :         goto done;
     328             :     }
     329             : 
     330           0 :     new_users->groups = talloc_realloc(new_users, new_users->groups,
     331             :                                       const char *, num_groups + 1);
     332           0 :     if (new_users->groups == NULL) {
     333           0 :         ret = ENOMEM;
     334           0 :         goto done;
     335             :     }
     336             : 
     337           0 :     ret = EOK;
     338             : done:
     339           0 :     if (ret == EOK) {
     340           0 :         *users = talloc_steal(mem_ctx, new_users);
     341             :     }
     342           0 :     talloc_free(tmp_ctx);
     343             : 
     344           0 :     return ret;
     345             : }

Generated by: LCOV version 1.10