LCOV - code coverage report
Current view: top level - providers/ipa - ipa_hbac_services.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 307 0.0 %
Date: 2015-10-19 Functions: 0 8 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             : struct ipa_hbac_service_state {
      28             :     struct tevent_context *ev;
      29             :     struct sdap_handle *sh;
      30             :     struct sdap_options *opts;
      31             :     const char **attrs;
      32             : 
      33             :     char *service_filter;
      34             :     char *cur_filter;
      35             : 
      36             :     struct sdap_search_base **search_bases;
      37             :     int search_base_iter;
      38             : 
      39             :     /* Return values */
      40             :     size_t service_count;
      41             :     struct sysdb_attrs **services;
      42             : 
      43             :     size_t servicegroup_count;
      44             :     struct sysdb_attrs **servicegroups;
      45             : };
      46             : 
      47             : static errno_t
      48             : ipa_hbac_service_info_next(struct tevent_req *req,
      49             :                            struct ipa_hbac_service_state *state);
      50             : static void
      51             : ipa_hbac_service_info_done(struct tevent_req *subreq);
      52             : static errno_t
      53             : ipa_hbac_servicegroup_info_next(struct tevent_req *req,
      54             :                                 struct ipa_hbac_service_state *state);
      55             : static void
      56             : ipa_hbac_servicegroup_info_done(struct tevent_req *subreq);
      57             : 
      58             : struct tevent_req *
      59           0 : ipa_hbac_service_info_send(TALLOC_CTX *mem_ctx,
      60             :                            struct tevent_context *ev,
      61             :                            struct sdap_handle *sh,
      62             :                            struct sdap_options *opts,
      63             :                            struct sdap_search_base **search_bases)
      64             : {
      65             :     errno_t ret;
      66             :     struct ipa_hbac_service_state *state;
      67             :     struct tevent_req *req;
      68             :     char *service_filter;
      69             : 
      70           0 :     req = tevent_req_create(mem_ctx, &state, struct ipa_hbac_service_state);
      71           0 :     if (req == NULL) {
      72           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
      73           0 :         return NULL;
      74             :     }
      75             : 
      76           0 :     state->ev = ev;
      77           0 :     state->sh = sh;
      78           0 :     state->opts = opts;
      79             : 
      80           0 :     state->search_bases = search_bases;
      81           0 :     state->search_base_iter = 0;
      82             : 
      83           0 :     service_filter = talloc_asprintf(state, "(objectClass=%s)",
      84             :                                      IPA_HBAC_SERVICE);
      85           0 :     if (service_filter == NULL) {
      86           0 :         ret = ENOMEM;
      87           0 :         goto immediate;
      88             :     }
      89             : 
      90           0 :     state->service_filter = service_filter;
      91           0 :     state->cur_filter = NULL;
      92             : 
      93           0 :     state->attrs = talloc_array(state, const char *, 6);
      94           0 :     if (state->attrs == NULL) {
      95           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
      96             :               "Failed to allocate service attribute list.\n");
      97           0 :         ret = ENOMEM;
      98           0 :         goto immediate;
      99             :     }
     100           0 :     state->attrs[0] = OBJECTCLASS;
     101           0 :     state->attrs[1] = IPA_CN;
     102           0 :     state->attrs[2] = IPA_UNIQUE_ID;
     103           0 :     state->attrs[3] = IPA_MEMBER;
     104           0 :     state->attrs[4] = IPA_MEMBEROF;
     105           0 :     state->attrs[5] = NULL;
     106             : 
     107           0 :     ret = ipa_hbac_service_info_next(req, state);
     108           0 :     if (ret == EOK) {
     109           0 :         ret = EINVAL;
     110             :     }
     111             : 
     112           0 :     if (ret != EAGAIN) {
     113           0 :         goto immediate;
     114             :     }
     115             : 
     116           0 :     return req;
     117             : 
     118             : immediate:
     119           0 :     if (ret == EOK) {
     120           0 :         tevent_req_done(req);
     121             :     } else {
     122           0 :         tevent_req_error(req, ret);
     123             :     }
     124           0 :     tevent_req_post(req, ev);
     125           0 :     return req;
     126             : }
     127             : 
     128           0 : static errno_t ipa_hbac_service_info_next(struct tevent_req *req,
     129             :                                           struct ipa_hbac_service_state *state)
     130             : {
     131             :     struct tevent_req *subreq;
     132             :     struct sdap_search_base *base;
     133             : 
     134           0 :     base = state->search_bases[state->search_base_iter];
     135           0 :     if (base  == NULL) {
     136           0 :         return EOK;
     137             :     }
     138             : 
     139           0 :     talloc_zfree(state->cur_filter);
     140           0 :     state->cur_filter = sdap_get_id_specific_filter(state,
     141           0 :                                                     state->service_filter,
     142             :                                                     base->filter);
     143           0 :     if (state->cur_filter == NULL) {
     144           0 :         return ENOMEM;
     145             :     }
     146             : 
     147           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Sending request for next search base: "
     148             :                               "[%s][%d][%s]\n", base->basedn, base->scope,
     149             :                               state->cur_filter);
     150           0 :     subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
     151             :                                    base->basedn, base->scope,
     152           0 :                                    state->cur_filter,
     153             :                                    state->attrs, NULL, 0,
     154           0 :                                    dp_opt_get_int(state->opts->basic,
     155             :                                                   SDAP_ENUM_SEARCH_TIMEOUT),
     156             :                                    true);
     157           0 :     if (subreq == NULL) {
     158           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting service info\n");
     159           0 :         return EIO;
     160             :     }
     161           0 :     tevent_req_set_callback(subreq, ipa_hbac_service_info_done, req);
     162             : 
     163           0 :     return EAGAIN;
     164             : }
     165             : 
     166             : static void
     167           0 : ipa_hbac_service_info_done(struct tevent_req *subreq)
     168             : {
     169             :     errno_t ret;
     170           0 :     struct tevent_req *req =
     171           0 :             tevent_req_callback_data(subreq, struct tevent_req);
     172           0 :     struct ipa_hbac_service_state *state =
     173           0 :             tevent_req_data(req, struct ipa_hbac_service_state);
     174             :     char *servicegroup_filter;
     175             : 
     176           0 :     ret = sdap_get_generic_recv(subreq, state,
     177             :                                 &state->service_count,
     178             :                                 &state->services);
     179           0 :     talloc_zfree(subreq);
     180           0 :     if (ret != EOK && ret != ENOENT) {
     181           0 :         goto done;
     182             :     }
     183             : 
     184           0 :     if (ret == ENOENT || state->service_count == 0) {
     185             :         /* If there are no services, we'll shortcut out
     186             :          * This is still valid, as rules can apply to
     187             :          * all services
     188             :          *
     189             :          * There's no reason to try to process groups
     190             :          */
     191             : 
     192           0 :         state->search_base_iter++;
     193           0 :         ret = ipa_hbac_service_info_next(req, state);
     194           0 :         if (ret == EAGAIN) {
     195           0 :             return;
     196             :         }
     197             : 
     198           0 :         state->service_count = 0;
     199           0 :         state->services = NULL;
     200           0 :         goto done;
     201             :     }
     202             : 
     203           0 :     ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
     204             :                                  state->service_count,
     205             :                                  state->services);
     206           0 :     if (ret != EOK) {
     207           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
     208           0 :         goto done;
     209             :     }
     210             : 
     211           0 :     servicegroup_filter = talloc_asprintf(state, "(objectClass=%s)",
     212             :                                           IPA_HBAC_SERVICE_GROUP);
     213           0 :     if (servicegroup_filter == NULL) {
     214           0 :         ret = ENOMEM;
     215           0 :         goto done;
     216             :     }
     217             : 
     218           0 :     talloc_zfree(state->service_filter);
     219           0 :     state->service_filter = servicegroup_filter;
     220             : 
     221           0 :     state->search_base_iter = 0;
     222           0 :     ret = ipa_hbac_servicegroup_info_next(req, state);
     223           0 :     if (ret == EOK) {
     224           0 :         ret = EINVAL;
     225             :     }
     226             : 
     227           0 :     if (ret != EAGAIN) {
     228           0 :         goto done;
     229             :     }
     230             : 
     231           0 :     return;
     232             : 
     233             : done:
     234           0 :     if (ret == EOK) {
     235           0 :         tevent_req_done(req);
     236             :     } else {
     237           0 :         tevent_req_error(req, ret);
     238             :     }
     239             : }
     240             : 
     241             : static errno_t
     242           0 : ipa_hbac_servicegroup_info_next(struct tevent_req *req,
     243             :                                 struct ipa_hbac_service_state *state)
     244             : {
     245             :     struct tevent_req *subreq;
     246             :     struct sdap_search_base *base;
     247             : 
     248           0 :     base = state->search_bases[state->search_base_iter];
     249           0 :     if (base  == NULL) {
     250           0 :         return EOK;
     251             :     }
     252             : 
     253           0 :     talloc_zfree(state->cur_filter);
     254           0 :     state->cur_filter = sdap_get_id_specific_filter(state,
     255           0 :                                                     state->service_filter,
     256             :                                                     base->filter);
     257           0 :     if (state->cur_filter == NULL) {
     258           0 :         return ENOMEM;
     259             :     }
     260             : 
     261             :     /* Look up service groups */
     262           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Sending request for next search base: "
     263             :                               "[%s][%d][%s]\n", base->basedn, base->scope,
     264             :                               state->cur_filter);
     265           0 :     subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
     266             :                                    base->basedn, base->scope,
     267           0 :                                    state->cur_filter, state->attrs, NULL, 0,
     268           0 :                                    dp_opt_get_int(state->opts->basic,
     269             :                                                   SDAP_ENUM_SEARCH_TIMEOUT),
     270             :                                    true);
     271           0 :     if (subreq == NULL) {
     272           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Error requesting servicegroup info\n");
     273           0 :         return EIO;
     274             :     }
     275           0 :     tevent_req_set_callback(subreq, ipa_hbac_servicegroup_info_done, req);
     276             : 
     277           0 :     return EAGAIN;
     278             : }
     279             : 
     280             : static void
     281           0 : ipa_hbac_servicegroup_info_done(struct tevent_req *subreq)
     282             : {
     283             :     errno_t ret;
     284           0 :     struct tevent_req *req =
     285           0 :             tevent_req_callback_data(subreq, struct tevent_req);
     286           0 :     struct ipa_hbac_service_state *state =
     287           0 :             tevent_req_data(req, struct ipa_hbac_service_state);
     288             :     size_t total_count;
     289             :     size_t group_count;
     290             :     struct sysdb_attrs **groups;
     291             :     struct sysdb_attrs **target;
     292             :     int i;
     293             : 
     294           0 :     ret = sdap_get_generic_recv(subreq, state,
     295             :                                 &group_count,
     296             :                                 &groups);
     297           0 :     talloc_zfree(subreq);
     298           0 :     if (ret != EOK) {
     299           0 :         goto done;
     300             :     }
     301             : 
     302           0 :     if (group_count > 0) {
     303           0 :         ret = replace_attribute_name(IPA_MEMBER, SYSDB_ORIG_MEMBER,
     304             :                                      group_count,
     305             :                                      groups);
     306           0 :         if (ret != EOK) {
     307           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
     308           0 :             goto done;
     309             :         }
     310             : 
     311           0 :         ret = replace_attribute_name(IPA_MEMBEROF, SYSDB_ORIG_MEMBEROF,
     312             :                                      state->servicegroup_count,
     313             :                                      state->servicegroups);
     314           0 :         if (ret != EOK) {
     315           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Could not replace attribute names\n");
     316           0 :             goto done;
     317             :         }
     318             : 
     319           0 :         total_count = state->servicegroup_count + group_count;
     320           0 :         state->servicegroups = talloc_realloc(state, state->servicegroups,
     321             :                                               struct sysdb_attrs *,
     322             :                                               total_count);
     323           0 :         if (state->servicegroups == NULL) {
     324           0 :             ret = ENOMEM;
     325           0 :             goto done;
     326             :         }
     327             : 
     328           0 :         i = 0;
     329           0 :         while (state->servicegroup_count < total_count) {
     330           0 :             target = &state->servicegroups[state->servicegroup_count];
     331           0 :             *target = talloc_steal(state->servicegroups, groups[i]);
     332             : 
     333           0 :             state->servicegroup_count++;
     334           0 :             i++;
     335             :         }
     336             :     }
     337             : 
     338           0 :     state->search_base_iter++;
     339           0 :     ret = ipa_hbac_servicegroup_info_next(req, state);
     340           0 :     if (ret == EAGAIN) {
     341           0 :         return;
     342           0 :     } else if (ret != EOK) {
     343           0 :         goto done;
     344             :     }
     345             : 
     346             : done:
     347           0 :     if (ret == EOK) {
     348           0 :         tevent_req_done(req);
     349             :     } else {
     350           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Error [%d][%s]\n", ret, strerror(ret));
     351           0 :         tevent_req_error(req, ret);
     352             :     }
     353             : }
     354             : 
     355             : errno_t
     356           0 : ipa_hbac_service_info_recv(struct tevent_req *req,
     357             :                            TALLOC_CTX *mem_ctx,
     358             :                            size_t *service_count,
     359             :                            struct sysdb_attrs ***services,
     360             :                            size_t *servicegroup_count,
     361             :                            struct sysdb_attrs ***servicegroups)
     362             : {
     363             :     size_t c;
     364           0 :     struct ipa_hbac_service_state *state =
     365           0 :             tevent_req_data(req, struct ipa_hbac_service_state);
     366             : 
     367           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     368             : 
     369           0 :     *service_count = state->service_count;
     370           0 :     *services = talloc_steal(mem_ctx, state->services);
     371           0 :     for (c = 0; c < state->service_count; c++) {
     372             :         /* Guarantee the memory heirarchy of the list */
     373           0 :         talloc_steal(state->services, state->services[c]);
     374             :     }
     375             : 
     376           0 :     *servicegroup_count = state->servicegroup_count;
     377           0 :     *servicegroups = talloc_steal(mem_ctx, state->servicegroups);
     378             : 
     379           0 :     return EOK;
     380             : }
     381             : 
     382             : errno_t
     383           0 : hbac_service_attrs_to_rule(TALLOC_CTX *mem_ctx,
     384             :                            struct sss_domain_info *domain,
     385             :                            const char *rule_name,
     386             :                            struct sysdb_attrs *rule_attrs,
     387             :                            struct hbac_rule_element **services)
     388             : {
     389             :     errno_t ret;
     390             :     TALLOC_CTX *tmp_ctx;
     391             :     struct hbac_rule_element *new_services;
     392           0 :     const char *attrs[] = { IPA_CN, NULL };
     393             :     struct ldb_message_element *el;
     394           0 :     size_t num_services = 0;
     395           0 :     size_t num_servicegroups = 0;
     396             :     size_t i;
     397             :     char *member_dn;
     398             :     char *filter;
     399             :     size_t count;
     400             :     struct ldb_message **msgs;
     401             :     const char *name;
     402             : 
     403           0 :     DEBUG(SSSDBG_TRACE_LIBS,
     404             :           "Processing PAM services for rule [%s]\n", rule_name);
     405             : 
     406           0 :     tmp_ctx = talloc_new(mem_ctx);
     407           0 :     if (tmp_ctx == NULL) return ENOMEM;
     408             : 
     409           0 :     new_services = talloc_zero(tmp_ctx, struct hbac_rule_element);
     410           0 :     if (new_services == NULL) {
     411           0 :         ret = ENOMEM;
     412           0 :         goto done;
     413             :     }
     414             : 
     415             :     /* First check for service category */
     416           0 :     ret = hbac_get_category(rule_attrs, IPA_SERVICE_CATEGORY,
     417             :                             &new_services->category);
     418           0 :     if (ret != EOK) {
     419           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not identify service categories\n");
     420           0 :         goto done;
     421             :     }
     422           0 :     if (new_services->category & HBAC_CATEGORY_ALL) {
     423             :         /* Short-cut to the exit */
     424           0 :         ret = EOK;
     425           0 :         goto done;
     426             :     }
     427             : 
     428             :     /* Get the list of DNs from the member attr */
     429           0 :     ret = sysdb_attrs_get_el(rule_attrs, IPA_MEMBER_SERVICE, &el);
     430           0 :     if (ret != EOK && ret != ENOENT) {
     431           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_attrs_get_el failed.\n");
     432           0 :         goto done;
     433             :     }
     434           0 :     if (ret == ENOENT || el->num_values == 0) {
     435           0 :         el->num_values = 0;
     436           0 :         DEBUG(SSSDBG_CONF_SETTINGS,
     437             :               "No services specified, rule will never apply.\n");
     438             :     }
     439             : 
     440             :     /* Assume maximum size; We'll trim it later */
     441           0 :     new_services->names = talloc_array(new_services,
     442             :                                        const char *,
     443             :                                        el->num_values +1);
     444           0 :     if (new_services->names == NULL) {
     445           0 :         ret = ENOMEM;
     446           0 :         goto done;
     447             :     }
     448             : 
     449           0 :     new_services->groups = talloc_array(new_services,
     450             :                                         const char *,
     451             :                                         el->num_values + 1);
     452           0 :     if (new_services->groups == NULL) {
     453           0 :         ret = ENOMEM;
     454           0 :         goto done;
     455             :     }
     456             : 
     457           0 :     for (i = 0; i < el->num_values; i++) {
     458           0 :         ret = sss_filter_sanitize(tmp_ctx,
     459           0 :                                   (const char *)el->values[i].data,
     460             :                                   &member_dn);
     461           0 :         if (ret != EOK) goto done;
     462             : 
     463           0 :         filter = talloc_asprintf(member_dn, "(%s=%s)",
     464             :                                  SYSDB_ORIG_DN, member_dn);
     465           0 :         if (filter == NULL) {
     466           0 :             ret = ENOMEM;
     467           0 :             goto done;
     468             :         }
     469             : 
     470             :         /* First check if this is a specific service */
     471           0 :         ret = sysdb_search_custom(tmp_ctx, domain, filter,
     472             :                                   HBAC_SERVICES_SUBDIR, attrs,
     473             :                                   &count, &msgs);
     474           0 :         if (ret != EOK && ret != ENOENT) goto done;
     475           0 :         if (ret == EOK && count == 0) {
     476           0 :             ret = ENOENT;
     477             :         }
     478             : 
     479           0 :         if (ret == EOK) {
     480           0 :             if (count > 1) {
     481           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     482             :                       "Original DN matched multiple services. "
     483             :                           "Skipping \n");
     484           0 :                 talloc_zfree(member_dn);
     485           0 :                 continue;
     486             :             }
     487             : 
     488             :             /* Original DN matched a single service. Get the service name */
     489           0 :             name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
     490           0 :             if (name == NULL) {
     491           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
     492           0 :                 ret = EFAULT;
     493           0 :                 goto done;
     494             :             }
     495             : 
     496           0 :             new_services->names[num_services] =
     497           0 :                     talloc_strdup(new_services->names, name);
     498           0 :             if (new_services->names[num_services] == NULL) {
     499           0 :                 ret = ENOMEM;
     500           0 :                 goto done;
     501             :             }
     502           0 :             DEBUG(SSSDBG_TRACE_INTERNAL, "Added service [%s] to rule [%s]\n",
     503             :                       name, rule_name);
     504           0 :             num_services++;
     505             :         } else { /* ret == ENOENT */
     506             :             /* Check if this is a service group */
     507           0 :             ret = sysdb_search_custom(tmp_ctx, domain, filter,
     508             :                                       HBAC_SERVICEGROUPS_SUBDIR, attrs,
     509             :                                       &count, &msgs);
     510           0 :             if (ret != EOK && ret != ENOENT) goto done;
     511           0 :             if (ret == EOK && count == 0) {
     512           0 :                 ret = ENOENT;
     513             :             }
     514             : 
     515           0 :             if (ret == EOK) {
     516           0 :                 if (count > 1) {
     517           0 :                     DEBUG(SSSDBG_CRIT_FAILURE,
     518             :                           "Original DN matched multiple service groups. "
     519             :                               "Skipping\n");
     520           0 :                     talloc_zfree(member_dn);
     521           0 :                     continue;
     522             :                 }
     523             : 
     524             :                 /* Original DN matched a single group. Get the groupname */
     525           0 :                 name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL);
     526           0 :                 if (name == NULL) {
     527           0 :                     DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n");
     528           0 :                     ret = EFAULT;
     529           0 :                     goto done;
     530             :                 }
     531             : 
     532           0 :                 new_services->groups[num_servicegroups] =
     533           0 :                         talloc_strdup(new_services->groups, name);
     534           0 :                 if (new_services->groups[num_servicegroups] == NULL) {
     535           0 :                     ret = ENOMEM;
     536           0 :                     goto done;
     537             :                 }
     538             : 
     539           0 :                 DEBUG(SSSDBG_TRACE_INTERNAL,
     540             :                       "Added service group [%s] to rule [%s]\n",
     541             :                           name, rule_name);
     542           0 :                 num_servicegroups++;
     543             :             } else { /* ret == ENOENT */
     544             :                 /* Neither a service nor a service group? Skip it */
     545           0 :                 DEBUG(SSSDBG_CRIT_FAILURE,
     546             :                       "[%s] does not map to either a service or "
     547             :                           "service group. Skipping\n", member_dn);
     548             :             }
     549             :         }
     550           0 :         talloc_zfree(member_dn);
     551             :     }
     552           0 :     new_services->names[num_services] = NULL;
     553           0 :     new_services->groups[num_servicegroups] = NULL;
     554             : 
     555             :     /* Shrink the arrays down to their real sizes */
     556           0 :     new_services->names = talloc_realloc(new_services, new_services->names,
     557             :                                          const char *, num_services + 1);
     558           0 :     if (new_services->names == NULL) {
     559           0 :         ret = ENOMEM;
     560           0 :         goto done;
     561             :     }
     562             : 
     563           0 :     new_services->groups = talloc_realloc(new_services, new_services->groups,
     564             :                                           const char *, num_servicegroups + 1);
     565           0 :     if (new_services->groups == NULL) {
     566           0 :         ret = ENOMEM;
     567           0 :         goto done;
     568             :     }
     569             : 
     570           0 :     ret = EOK;
     571             : 
     572             : done:
     573           0 :     if (ret == EOK) {
     574           0 :         *services = talloc_steal(mem_ctx, new_services);
     575             :     }
     576           0 :     talloc_free(tmp_ctx);
     577           0 :     return ret;
     578             : }
     579             : 
     580             : errno_t
     581           0 : get_ipa_servicegroupname(TALLOC_CTX *mem_ctx,
     582             :                          struct sysdb_ctx *sysdb,
     583             :                          const char *service_dn,
     584             :                          char **servicegroupname)
     585             : {
     586             :     errno_t ret;
     587             :     struct ldb_dn *dn;
     588             :     const char *rdn_name;
     589             :     const char *svc_comp_name;
     590             :     const char *hbac_comp_name;
     591             :     const struct ldb_val *rdn_val;
     592             :     const struct ldb_val *svc_comp_val;
     593             :     const struct ldb_val *hbac_comp_val;
     594             : 
     595             :     /* This is an IPA-specific hack. It may not
     596             :      * work for non-IPA servers and will need to
     597             :      * be changed if SSSD ever supports HBAC on
     598             :      * a non-IPA server.
     599             :      */
     600           0 :     *servicegroupname = NULL;
     601             : 
     602           0 :     dn = ldb_dn_new(mem_ctx, sysdb_ctx_get_ldb(sysdb), service_dn);
     603           0 :     if (dn == NULL) {
     604           0 :         ret = ENOMEM;
     605           0 :         goto done;
     606             :     }
     607             : 
     608           0 :     if (!ldb_dn_validate(dn)) {
     609           0 :         ret = ERR_MALFORMED_ENTRY;
     610           0 :         goto done;
     611             :     }
     612             : 
     613           0 :     if (ldb_dn_get_comp_num(dn) < 4) {
     614             :         /* RDN, services, hbac, and at least one DC= */
     615             :         /* If it's fewer, it's not a group DN */
     616           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     617           0 :         goto done;
     618             :     }
     619             : 
     620             :     /* If the RDN name is 'cn' */
     621           0 :     rdn_name = ldb_dn_get_rdn_name(dn);
     622           0 :     if (rdn_name == NULL) {
     623             :         /* Shouldn't happen if ldb_dn_validate()
     624             :          * passed, but we'll be careful.
     625             :          */
     626           0 :         ret = ERR_MALFORMED_ENTRY;
     627           0 :         goto done;
     628             :     }
     629             : 
     630           0 :     if (strcasecmp("cn", rdn_name) != 0) {
     631             :         /* RDN has the wrong attribute name.
     632             :          * It's not a service.
     633             :          */
     634           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     635           0 :         goto done;
     636             :     }
     637             : 
     638             :     /* and the second component is "cn=hbacservicegroups" */
     639           0 :     svc_comp_name = ldb_dn_get_component_name(dn, 1);
     640           0 :     if (strcasecmp("cn", svc_comp_name) != 0) {
     641             :         /* The second component name is not "cn" */
     642           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     643           0 :         goto done;
     644             :     }
     645             : 
     646           0 :     svc_comp_val = ldb_dn_get_component_val(dn, 1);
     647           0 :     if (strncasecmp("hbacservicegroups",
     648           0 :                     (const char *) svc_comp_val->data,
     649             :                     svc_comp_val->length) != 0) {
     650             :         /* The second component value is not "hbacservicegroups" */
     651           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     652           0 :         goto done;
     653             :     }
     654             : 
     655             :     /* and the third component is "hbac" */
     656           0 :     hbac_comp_name = ldb_dn_get_component_name(dn, 2);
     657           0 :     if (strcasecmp("cn", hbac_comp_name) != 0) {
     658             :         /* The third component name is not "cn" */
     659           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     660           0 :         goto done;
     661             :     }
     662             : 
     663           0 :     hbac_comp_val = ldb_dn_get_component_val(dn, 2);
     664           0 :     if (strncasecmp("hbac",
     665           0 :                     (const char *) hbac_comp_val->data,
     666             :                     hbac_comp_val->length) != 0) {
     667             :         /* The third component value is not "hbac" */
     668           0 :         ret = ERR_UNEXPECTED_ENTRY_TYPE;
     669           0 :         goto done;
     670             :     }
     671             : 
     672             :     /* Then the value of the RDN is the group name */
     673           0 :     rdn_val = ldb_dn_get_rdn_val(dn);
     674           0 :     *servicegroupname = talloc_strndup(mem_ctx,
     675           0 :                                        (const char *)rdn_val->data,
     676             :                                        rdn_val->length);
     677           0 :     if (*servicegroupname == NULL) {
     678           0 :         ret = ENOMEM;
     679           0 :         goto done;
     680             :     }
     681             : 
     682           0 :     ret = EOK;
     683             : 
     684             : done:
     685           0 :     talloc_free(dn);
     686           0 :     return ret;
     687             : }

Generated by: LCOV version 1.10