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

Generated by: LCOV version 1.10