LCOV - code coverage report
Current view: top level - providers/ipa - ipa_netgroups.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 494 0.0 %
Date: 2016-06-29 Functions: 0 13 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Async IPA Helper routines for netgroups
       5             : 
       6             :     Authors:
       7             :         Jan Zeleny <jzeleny@redhat.com>
       8             : 
       9             :     Copyright (C) 2011 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "util/util.h"
      26             : #include "db/sysdb.h"
      27             : #include "providers/ldap/sdap_async_private.h"
      28             : #include "providers/ipa/ipa_id.h"
      29             : #include "db/sysdb.h"
      30             : #include <ctype.h>
      31             : 
      32             : #define ENTITY_NG 1
      33             : #define ENTITY_USER 2
      34             : #define ENTITY_HOST 4
      35             : 
      36             : struct ipa_get_netgroups_state {
      37             :     struct tevent_context *ev;
      38             :     struct sdap_options *opts;
      39             :     struct ipa_options *ipa_opts;
      40             :     struct sdap_handle *sh;
      41             :     struct sysdb_ctx *sysdb;
      42             :     struct sss_domain_info *dom;
      43             :     const char **attrs;
      44             :     int timeout;
      45             : 
      46             :     char *filter;
      47             :     const char *base_filter;
      48             : 
      49             :     size_t netgr_base_iter;
      50             :     size_t host_base_iter;
      51             :     size_t user_base_iter;
      52             : 
      53             :     /* Entities which have been already asked for
      54             :      * and are scheduled for inspection */
      55             :     hash_table_t *new_netgroups;
      56             :     hash_table_t *new_users;
      57             :     hash_table_t *new_hosts;
      58             : 
      59             :     int current_entity;
      60             :     int entities_found;
      61             : 
      62             :     struct sysdb_attrs **netgroups;
      63             :     int netgroups_count;
      64             : };
      65             : 
      66           0 : static errno_t ipa_save_netgroup(TALLOC_CTX *mem_ctx,
      67             :                                  struct sss_domain_info *dom,
      68             :                                  struct sdap_options *opts,
      69             :                                  struct sysdb_attrs *attrs)
      70             : {
      71             :     struct ldb_message_element *el;
      72             :     struct sysdb_attrs *netgroup_attrs;
      73           0 :     const char *name = NULL;
      74             :     int ret;
      75             :     size_t c;
      76             : 
      77           0 :     ret = sysdb_attrs_get_el(attrs,
      78           0 :                              opts->netgroup_map[IPA_AT_NETGROUP_NAME].sys_name,
      79             :                              &el);
      80           0 :     if (ret) goto fail;
      81           0 :     if (el->num_values == 0) {
      82           0 :         ret = EINVAL;
      83           0 :         goto fail;
      84             :     }
      85           0 :     name = (const char *)el->values[0].data;
      86           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Storing netgroup %s\n", name);
      87             : 
      88           0 :     netgroup_attrs = sysdb_new_attrs(mem_ctx);
      89           0 :     if (!netgroup_attrs) {
      90           0 :         ret = ENOMEM;
      91           0 :         goto fail;
      92             :     }
      93             : 
      94           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &el);
      95           0 :     if (ret) {
      96           0 :         goto fail;
      97             :     }
      98           0 :     if (el->num_values == 0) {
      99           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     100             :               "Original DN is not available for [%s].\n", name);
     101             :     } else {
     102           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     103             :               "Adding original DN [%s] to attributes of [%s].\n",
     104             :                   el->values[0].data, name);
     105           0 :         ret = sysdb_attrs_add_string(netgroup_attrs, SYSDB_ORIG_DN,
     106           0 :                                      (const char *)el->values[0].data);
     107           0 :         if (ret) {
     108           0 :             goto fail;
     109             :         }
     110             :     }
     111             : 
     112           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_NETGROUP_TRIPLE, &el);
     113           0 :     if (ret) {
     114           0 :         goto fail;
     115             :     }
     116           0 :     if (el->num_values == 0) {
     117           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "No netgroup triples for netgroup [%s].\n", name);
     118           0 :         ret = sysdb_attrs_get_el(netgroup_attrs, SYSDB_NETGROUP_TRIPLE, &el);
     119           0 :         if (ret != EOK) {
     120           0 :             goto fail;
     121             :         }
     122             :     } else {
     123           0 :         for(c = 0; c < el->num_values; c++) {
     124           0 :             ret = sysdb_attrs_add_string_safe(netgroup_attrs,
     125             :                                               SYSDB_NETGROUP_TRIPLE,
     126           0 :                                               (const char*)el->values[c].data);
     127           0 :             if (ret) {
     128           0 :                 goto fail;
     129             :             }
     130             :         }
     131             :     }
     132             : 
     133           0 :     ret = sysdb_attrs_get_el(attrs,
     134           0 :                        opts->netgroup_map[IPA_AT_NETGROUP_MEMBER].sys_name,
     135             :                        &el);
     136           0 :     if (ret != EOK) {
     137           0 :         goto fail;
     138             :     }
     139           0 :     if (el->num_values == 0) {
     140           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     141             :               "No original members for netgroup [%s]\n", name);
     142             : 
     143             :     } else {
     144           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     145             :               "Adding original members to netgroup [%s]\n", name);
     146           0 :         for(c = 0; c < el->num_values; c++) {
     147           0 :             ret = sysdb_attrs_add_string(netgroup_attrs,
     148           0 :                        opts->netgroup_map[IPA_AT_NETGROUP_MEMBER].sys_name,
     149           0 :                        (const char*)el->values[c].data);
     150           0 :             if (ret) {
     151           0 :                 goto fail;
     152             :             }
     153             :         }
     154             :     }
     155             : 
     156             : 
     157           0 :     ret = sysdb_attrs_get_el(attrs, SYSDB_NETGROUP_MEMBER, &el);
     158           0 :     if (ret != EOK) {
     159           0 :         goto fail;
     160             :     }
     161           0 :     if (el->num_values == 0) {
     162           0 :         DEBUG(SSSDBG_TRACE_LIBS, "No members for netgroup [%s]\n", name);
     163             : 
     164             :     } else {
     165           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Adding members to netgroup [%s]\n", name);
     166           0 :         for(c = 0; c < el->num_values; c++) {
     167           0 :             ret = sysdb_attrs_add_string(netgroup_attrs, SYSDB_NETGROUP_MEMBER,
     168           0 :                                          (const char*)el->values[c].data);
     169           0 :             if (ret) {
     170           0 :                 goto fail;
     171             :             }
     172             :         }
     173             :     }
     174             : 
     175           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Storing info for netgroup %s\n", name);
     176             : 
     177           0 :     ret = sysdb_add_netgroup(dom, name, NULL, netgroup_attrs, NULL,
     178           0 :                              dom->netgroup_timeout, 0);
     179           0 :     if (ret) goto fail;
     180             : 
     181           0 :     return EOK;
     182             : 
     183             : fail:
     184           0 :     DEBUG(SSSDBG_OP_FAILURE, "Failed to save netgroup %s\n", name);
     185           0 :     return ret;
     186             : }
     187             : 
     188             : static errno_t ipa_netgr_next_base(struct tevent_req *req);
     189             : static void ipa_get_netgroups_process(struct tevent_req *subreq);
     190             : static int ipa_netgr_process_all(struct ipa_get_netgroups_state *state);
     191             : 
     192           0 : struct tevent_req *ipa_get_netgroups_send(TALLOC_CTX *memctx,
     193             :                                           struct tevent_context *ev,
     194             :                                           struct sysdb_ctx *sysdb,
     195             :                                           struct sss_domain_info *dom,
     196             :                                           struct sdap_options *opts,
     197             :                                           struct ipa_options *ipa_options,
     198             :                                           struct sdap_handle *sh,
     199             :                                           const char **attrs,
     200             :                                           const char *filter,
     201             :                                           int timeout)
     202             : {
     203             :     struct tevent_req *req;
     204             :     struct ipa_get_netgroups_state *state;
     205             :     int ret;
     206             : 
     207           0 :     req = tevent_req_create(memctx, &state, struct ipa_get_netgroups_state);
     208           0 :     if (!req) return NULL;
     209             : 
     210           0 :     state->ev = ev;
     211           0 :     state->opts = opts;
     212           0 :     state->ipa_opts = ipa_options;
     213           0 :     state->sh = sh;
     214           0 :     state->sysdb = sysdb;
     215           0 :     state->attrs = attrs;
     216           0 :     state->timeout = timeout;
     217           0 :     state->base_filter = filter;
     218           0 :     state->netgr_base_iter = 0;
     219           0 :     state->dom = dom;
     220             : 
     221           0 :     if (!ipa_options->id->sdom->netgroup_search_bases) {
     222           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     223             :               "Netgroup lookup request without a search base\n");
     224           0 :         ret = EINVAL;
     225           0 :         goto done;
     226             :     }
     227             : 
     228           0 :     ret = sss_hash_create(state, 32, &state->new_netgroups);
     229           0 :     if (ret != EOK) goto done;
     230           0 :     ret = sss_hash_create(state, 32, &state->new_users);
     231           0 :     if (ret != EOK) goto done;
     232           0 :     ret = sss_hash_create(state, 32, &state->new_hosts);
     233           0 :     if (ret != EOK) goto done;
     234             : 
     235             : 
     236           0 :     ret = ipa_netgr_next_base(req);
     237             : 
     238             : done:
     239           0 :     if (ret != EOK) {
     240           0 :         tevent_req_error(req, ret);
     241           0 :         tevent_req_post(req, ev);
     242             :     }
     243             : 
     244           0 :     return req;
     245             : }
     246             : 
     247           0 : static errno_t ipa_netgr_next_base(struct tevent_req *req)
     248             : {
     249             :     struct tevent_req *subreq;
     250             :     struct ipa_get_netgroups_state *state;
     251             :     struct sdap_search_base **netgr_bases;
     252             : 
     253           0 :     state = tevent_req_data(req, struct ipa_get_netgroups_state);
     254           0 :     netgr_bases = state->ipa_opts->id->sdom->netgroup_search_bases;
     255             : 
     256           0 :     talloc_zfree(state->filter);
     257           0 :     state->filter = sdap_combine_filters(
     258             :             state,
     259             :             state->base_filter,
     260           0 :             netgr_bases[state->netgr_base_iter]->filter);
     261           0 :     if (!state->filter) {
     262           0 :         return ENOMEM;
     263             :     }
     264             : 
     265           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     266             :             "Searching for netgroups with base [%s]\n",
     267             :              netgr_bases[state->netgr_base_iter]->basedn);
     268             : 
     269           0 :     subreq = sdap_get_generic_send(
     270             :             state, state->ev, state->opts, state->sh,
     271           0 :             netgr_bases[state->netgr_base_iter]->basedn,
     272           0 :             netgr_bases[state->netgr_base_iter]->scope,
     273           0 :             state->filter, state->attrs,
     274           0 :             state->opts->netgroup_map, IPA_OPTS_NETGROUP,
     275             :             state->timeout,
     276             :             true);
     277           0 :     if (!subreq) {
     278           0 :         return ENOMEM;
     279             :     }
     280           0 :     tevent_req_set_callback(subreq, ipa_get_netgroups_process, req);
     281             : 
     282           0 :     return EOK;
     283             : }
     284             : 
     285             : static int ipa_netgr_fetch_netgroups(struct ipa_get_netgroups_state *state,
     286             :                                      struct tevent_req *req);
     287             : static int ipa_netgr_fetch_users(struct ipa_get_netgroups_state *state,
     288             :                                  struct tevent_req *req);
     289             : static int ipa_netgr_fetch_hosts(struct ipa_get_netgroups_state *state,
     290             :                                  struct tevent_req *req);
     291             : static void ipa_netgr_members_process(struct tevent_req *subreq);
     292             : 
     293           0 : static void ipa_get_netgroups_process(struct tevent_req *subreq)
     294             : {
     295           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     296             :                                                       struct tevent_req);
     297           0 :     struct ipa_get_netgroups_state *state = tevent_req_data(req,
     298             :                                                struct ipa_get_netgroups_state);
     299             :     int i, ret;
     300             :     struct ldb_message_element *el;
     301             :     struct sdap_search_base **netgr_bases;
     302             :     struct sysdb_attrs **netgroups;
     303             :     size_t netgroups_count;
     304             :     const char *orig_dn;
     305             :     char *dn;
     306             :     char *filter;
     307           0 :     bool fetch_members = false;
     308             :     hash_key_t key;
     309             :     hash_value_t value;
     310             : 
     311           0 :     netgr_bases = state->ipa_opts->id->sdom->netgroup_search_bases;
     312             : 
     313           0 :     ret = sdap_get_generic_recv(subreq, state, &netgroups_count, &netgroups);
     314           0 :     talloc_zfree(subreq);
     315           0 :     if (ret) {
     316           0 :         goto done;
     317             :     }
     318             : 
     319           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Search for netgroups, returned %zu results.\n",
     320             :                               netgroups_count);
     321             : 
     322           0 :     if (netgroups_count == 0) {
     323             :         /* No netgroups found in this search */
     324           0 :         state->netgr_base_iter++;
     325           0 :         if (netgr_bases[state->netgr_base_iter]) {
     326             :             /* There are more search bases to try */
     327           0 :             ret = ipa_netgr_next_base(req);
     328           0 :             if (ret != EOK) {
     329           0 :                 tevent_req_error(req, ENOENT);
     330             :             }
     331           0 :             return;
     332             :         }
     333             : 
     334           0 :         ret = ENOENT;
     335           0 :         goto done;
     336             :     }
     337             : 
     338           0 :     filter = talloc_strdup(state, "(|");
     339           0 :     if (filter == NULL) {
     340           0 :         ret = ENOMEM;
     341           0 :         goto done;
     342             :     }
     343             : 
     344           0 :     for (i = 0; i < netgroups_count; i++) {
     345           0 :         ret = sysdb_attrs_get_el(netgroups[i], SYSDB_ORIG_NETGROUP_MEMBER,
     346             :                                  &el);
     347           0 :         if (ret != EOK) goto done;
     348           0 :         if (el->num_values) state->entities_found |= ENTITY_NG;
     349             : 
     350           0 :         ret = sysdb_attrs_get_el(netgroups[i], SYSDB_ORIG_MEMBER_USER,
     351             :                                  &el);
     352           0 :         if (ret != EOK) goto done;
     353           0 :         if (el->num_values) state->entities_found |= ENTITY_USER;
     354             : 
     355           0 :         ret = sysdb_attrs_get_el(netgroups[i], SYSDB_ORIG_MEMBER_HOST,
     356             :                                  &el);
     357           0 :         if (ret != EOK) goto done;
     358           0 :         if (el->num_values) state->entities_found |= ENTITY_HOST;
     359             : 
     360           0 :         ret = sysdb_attrs_get_string(netgroups[i], SYSDB_ORIG_DN, &orig_dn);
     361           0 :         if (ret != EOK) {
     362           0 :             goto done;
     363             :         }
     364             : 
     365           0 :         key.type = HASH_KEY_STRING;
     366           0 :         value.type = HASH_VALUE_PTR;
     367           0 :         key.str = discard_const(orig_dn);
     368           0 :         value.ptr = netgroups[i];
     369           0 :         ret = hash_enter(state->new_netgroups, &key, &value);
     370           0 :         if (ret != HASH_SUCCESS) {
     371           0 :             ret = ENOMEM;
     372           0 :             goto done;
     373             :         }
     374             : 
     375           0 :         if (state->entities_found == 0) {
     376           0 :             continue;
     377             :         }
     378             : 
     379           0 :         ret = sss_filter_sanitize(state, orig_dn, &dn);
     380           0 :         if (ret != EOK) {
     381           0 :             goto done;
     382             :         }
     383             :         /* Add this to the filter */
     384           0 :         filter = talloc_asprintf_append(filter, "(%s=%s)",
     385           0 :                             state->opts->netgroup_map[IPA_AT_NETGROUP_MEMBER_OF].name,
     386             :                             dn);
     387           0 :         if (filter == NULL) {
     388           0 :             ret = ENOMEM;
     389           0 :             goto done;
     390             :         }
     391           0 :         fetch_members = true;
     392             :     }
     393             : 
     394           0 :     if (!fetch_members) {
     395           0 :         ret = ipa_netgr_process_all(state);
     396           0 :         if (ret != EOK) {
     397           0 :             tevent_req_error(req, ret);
     398             :         } else {
     399           0 :             tevent_req_done(req);
     400             :         }
     401           0 :         return;
     402             :     }
     403             : 
     404           0 :     state->filter = talloc_asprintf_append(filter, ")");
     405           0 :     if (state->filter == NULL) {
     406           0 :         ret = ENOMEM;
     407           0 :         goto done;
     408             :     }
     409             : 
     410           0 :     if (state->entities_found & ENTITY_NG) {
     411           0 :         state->netgr_base_iter = 0;
     412           0 :         ret = ipa_netgr_fetch_netgroups(state, req);
     413           0 :         if (ret != EOK) goto done;
     414           0 :     } else if (state->entities_found & ENTITY_USER) {
     415           0 :         ret = ipa_netgr_fetch_users(state, req);
     416           0 :         if (ret != EOK) goto done;
     417           0 :     } else if (state->entities_found & ENTITY_HOST) {
     418           0 :         ret = ipa_netgr_fetch_hosts(state, req);
     419           0 :         if (ret != EOK) goto done;
     420             :     }
     421             : 
     422           0 :     return;
     423             : done:
     424           0 :     tevent_req_error(req, ret);
     425           0 :     return;
     426             : }
     427             : 
     428           0 : static int ipa_netgr_fetch_netgroups(struct ipa_get_netgroups_state *state,
     429             :                                      struct tevent_req *req)
     430             : {
     431             :     char *filter;
     432             :     const char *base_filter;
     433             :     struct tevent_req *subreq;
     434             :     struct sdap_search_base **bases;
     435             : 
     436           0 :     bases = state->ipa_opts->id->sdom->netgroup_search_bases;
     437           0 :     if (bases[state->netgr_base_iter] == NULL) {
     438             :         /* No more bases to try */
     439           0 :         return ENOENT;
     440             :     }
     441           0 :     base_filter = bases[state->netgr_base_iter]->filter;
     442             : 
     443           0 :     filter = talloc_asprintf(state, "(&%s%s(objectclass=%s))",
     444             :                              state->filter,
     445             :                              base_filter?base_filter:"",
     446           0 :                              state->opts->netgroup_map[SDAP_OC_NETGROUP].name);
     447           0 :     if (filter == NULL)
     448           0 :         return ENOMEM;
     449             : 
     450           0 :     subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
     451           0 :                                    bases[state->netgr_base_iter]->basedn,
     452           0 :                                    bases[state->netgr_base_iter]->scope,
     453           0 :                                    filter, state->attrs, state->opts->netgroup_map,
     454             :                                    IPA_OPTS_NETGROUP, state->timeout, true);
     455             : 
     456           0 :     state->current_entity = ENTITY_NG;
     457           0 :     if (subreq == NULL) {
     458           0 :         return ENOMEM;
     459             :     }
     460             : 
     461           0 :     tevent_req_set_callback(subreq, ipa_netgr_members_process, req);
     462             : 
     463           0 :     return EOK;
     464             : }
     465             : 
     466           0 : static int ipa_netgr_fetch_users(struct ipa_get_netgroups_state *state,
     467             :                                  struct tevent_req *req)
     468             : {
     469           0 :     const char *attrs[] = { state->opts->user_map[SDAP_AT_USER_NAME].name,
     470           0 :                             state->opts->user_map[SDAP_AT_USER_MEMBEROF].name,
     471             :                             "objectclass", NULL };
     472             :     char *filter;
     473             :     const char *base_filter;
     474             :     struct tevent_req *subreq;
     475             :     struct sdap_search_base **bases;
     476             : 
     477           0 :     bases = state->ipa_opts->id->sdom->user_search_bases;
     478           0 :     if (bases[state->user_base_iter] == NULL) {
     479           0 :         return ENOENT;
     480             :     }
     481           0 :     base_filter = bases[state->user_base_iter]->filter;
     482             : 
     483           0 :     filter = talloc_asprintf(state, "(&%s%s(objectclass=%s))",
     484             :                              state->filter,
     485             :                              base_filter?base_filter:"",
     486           0 :                              state->opts->user_map[SDAP_OC_USER].name);
     487           0 :     if (filter == NULL)
     488           0 :         return ENOMEM;
     489             : 
     490           0 :     subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
     491           0 :                                    dp_opt_get_string(state->opts->basic,
     492             :                                                      SDAP_USER_SEARCH_BASE),
     493             :                                    LDAP_SCOPE_SUBTREE,
     494           0 :                                    filter, attrs, state->opts->user_map,
     495           0 :                                    state->opts->user_map_cnt,
     496             :                                    state->timeout, true);
     497             : 
     498           0 :     state->current_entity = ENTITY_USER;
     499           0 :     if (subreq == NULL) {
     500           0 :         talloc_free(attrs);
     501           0 :         return ENOMEM;
     502             :     }
     503             : 
     504           0 :     tevent_req_set_callback(subreq, ipa_netgr_members_process, req);
     505             : 
     506           0 :     return EOK;
     507             : }
     508             : 
     509           0 : static int ipa_netgr_fetch_hosts(struct ipa_get_netgroups_state *state,
     510             :                                  struct tevent_req *req)
     511             : {
     512             :     const char **attrs;
     513             :     char *filter;
     514             :     const char *base_filter;
     515             :     struct tevent_req *subreq;
     516             :     int ret;
     517             :     struct sdap_search_base **bases;
     518             : 
     519           0 :     bases = state->ipa_opts->host_search_bases;
     520           0 :     if (bases[state->host_base_iter] == NULL) {
     521           0 :         return ENOENT;
     522             :     }
     523           0 :     base_filter = bases[state->host_base_iter]->filter;
     524             : 
     525           0 :     filter = talloc_asprintf(state, "(&%s%s(objectclass=%s))",
     526             :                              state->filter,
     527             :                              base_filter?base_filter:"",
     528           0 :                              state->ipa_opts->host_map[IPA_OC_HOST].name);
     529           0 :     if (filter == NULL)
     530           0 :         return ENOMEM;
     531             : 
     532           0 :     ret = build_attrs_from_map(state, state->ipa_opts->host_map,
     533             :                                IPA_OPTS_HOST, NULL, &attrs, NULL);
     534           0 :     if (ret != EOK) {
     535           0 :         talloc_free(filter);
     536           0 :         return ret;
     537             :     }
     538             : 
     539           0 :     subreq = sdap_get_generic_send(state, state->ev, state->opts, state->sh,
     540           0 :                                    bases[state->host_base_iter]->basedn,
     541           0 :                                    bases[state->host_base_iter]->scope,
     542           0 :                                    filter, attrs, state->ipa_opts->host_map,
     543             :                                    IPA_OPTS_HOST, state->timeout, true);
     544             : 
     545           0 :     state->current_entity = ENTITY_HOST;
     546           0 :     if (subreq == NULL) {
     547           0 :         talloc_free(filter);
     548           0 :         return ENOMEM;
     549             :     }
     550             : 
     551           0 :     tevent_req_set_callback(subreq, ipa_netgr_members_process, req);
     552             : 
     553           0 :     return EOK;
     554             : }
     555             : 
     556           0 : static void ipa_netgr_members_process(struct tevent_req *subreq)
     557             : {
     558           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     559             :                                                       struct tevent_req);
     560           0 :     struct ipa_get_netgroups_state *state = tevent_req_data(req,
     561             :                                                struct ipa_get_netgroups_state);
     562             :     struct sysdb_attrs **entities;
     563             :     size_t count;
     564             :     int ret, i;
     565             :     const char *orig_dn;
     566             :     char *orig_dn_lower;
     567             :     hash_table_t *table;
     568             :     hash_key_t key;
     569             :     hash_value_t value;
     570             :     int (* next_call)(struct ipa_get_netgroups_state *,
     571             :                       struct tevent_req *);
     572           0 :     bool next_batch_scheduled = false;
     573             : 
     574           0 :     ret = sdap_get_generic_recv(subreq, state, &count, &entities);
     575           0 :     talloc_zfree(subreq);
     576           0 :     if (ret) {
     577           0 :         goto fail;
     578             :     }
     579             : 
     580           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Found %zu members in current search base\n",
     581             :                                   count);
     582             : 
     583           0 :     next_call = NULL;
     584             :     /* While processing a batch of entities from one search base,
     585             :      * schedule query for another search base if there is one
     586             :      *
     587             :      * If there is no other search base, another class of entities
     588             :      * will be scheduled for lookup after processing of current
     589             :      * batch. The order of lookup is: netgroups -> users -> hosts
     590             :      */
     591           0 :     if (state->current_entity == ENTITY_NG) {
     592             :         /* We just received a batch of netgroups */
     593           0 :         state->netgr_base_iter++;
     594           0 :         ret = ipa_netgr_fetch_netgroups(state, req);
     595           0 :         table = state->new_netgroups;
     596             :         /* If there is a member netgroup, we always have to
     597             :          * ask for both member users and hosts
     598             :          * -> now schedule users
     599             :          */
     600           0 :         next_call = ipa_netgr_fetch_users;
     601           0 :     } else if (state->current_entity == ENTITY_USER) {
     602             :         /* We just received a batch of users */
     603           0 :         state->user_base_iter++;
     604           0 :         ret = ipa_netgr_fetch_users(state, req);
     605           0 :         table = state->new_users;
     606           0 :         if (state->entities_found & ENTITY_HOST ||
     607           0 :             state->entities_found & ENTITY_NG) {
     608           0 :             next_call = ipa_netgr_fetch_hosts;
     609             :         }
     610           0 :     } else if (state->current_entity == ENTITY_HOST) {
     611             :         /* We just received a batch of hosts */
     612           0 :         state->host_base_iter++;
     613           0 :         ret = ipa_netgr_fetch_hosts(state, req);
     614           0 :         table = state->new_hosts;
     615             :     } else {
     616           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     617             :               "Invalid entity type given for processing: %d\n",
     618             :                state->current_entity);
     619           0 :         ret = EINVAL;
     620           0 :         goto fail;
     621             :     }
     622             : 
     623           0 :     if (ret == EOK) {
     624             :         /* Next search base has been scheduled for inspection,
     625             :          * don't try to look for other type of entities
     626             :          */
     627           0 :         next_batch_scheduled = true;
     628           0 :     } else if (ret != ENOENT) {
     629           0 :         goto fail;
     630             :     }
     631             : 
     632             :     /* Process all member entites and store them in the designated hash table */
     633           0 :     key.type = HASH_KEY_STRING;
     634           0 :     value.type = HASH_VALUE_PTR;
     635           0 :     for (i = 0; i < count; i++) {
     636           0 :         ret = sysdb_attrs_get_string(entities[i], SYSDB_ORIG_DN, &orig_dn);
     637           0 :         if (ret != EOK) {
     638           0 :             goto fail;
     639             :         }
     640             : 
     641           0 :         orig_dn_lower = talloc_strdup(table, orig_dn);
     642           0 :         if (orig_dn_lower == NULL) {
     643           0 :             ret = ENOMEM;
     644           0 :             goto fail;
     645             :         }
     646             :         /* Transform the DN to lower case.
     647             :          * this is important, as the member/memberof attributes
     648             :          * have the value also in lower-case
     649             :          */
     650           0 :         key.str = orig_dn_lower;
     651           0 :         while (*orig_dn_lower != '\0') {
     652           0 :             *orig_dn_lower = tolower(*orig_dn_lower);
     653           0 :             orig_dn_lower++;
     654             :         }
     655           0 :         value.ptr = entities[i];
     656           0 :         ret = hash_enter(table, &key, &value);
     657           0 :         if (ret !=  HASH_SUCCESS) {
     658           0 :             goto fail;
     659             :         }
     660             :     }
     661             : 
     662           0 :     if (next_batch_scheduled) {
     663             :         /* The next search base is already scheduled to be searched */
     664           0 :         return;
     665             :     }
     666             : 
     667           0 :     if (next_call) {
     668             :         /* There is another class of members that has to be retrieved
     669             :          * - schedule the lookup
     670             :          */
     671           0 :         ret = next_call(state, req);
     672           0 :         if (ret != EOK) goto fail;
     673             :     } else {
     674             :         /* All members, that could have been fetched, were fetched */
     675           0 :         ret = ipa_netgr_process_all(state);
     676           0 :         if (ret != EOK) goto fail;
     677             : 
     678           0 :         tevent_req_done(req);
     679             :     }
     680             : 
     681           0 :     return;
     682             : 
     683             : fail:
     684           0 :     tevent_req_error(req, ret);
     685           0 :     return;
     686             : }
     687             : 
     688           0 : static bool extract_netgroups(hash_entry_t *entry, void *pvt)
     689             : {
     690             :     struct ipa_get_netgroups_state *state;
     691           0 :     state = talloc_get_type(pvt, struct ipa_get_netgroups_state);
     692             : 
     693           0 :     state->netgroups[state->netgroups_count] = talloc_get_type(entry->value.ptr,
     694             :                                                                struct sysdb_attrs);
     695           0 :     state->netgroups_count++;
     696             : 
     697           0 :     return true;
     698             : }
     699             : 
     700             : struct extract_state {
     701             :     const char *group;
     702             :     const char *appropriateMemberOf;
     703             : 
     704             :     const char **entries;
     705             :     int entries_count;
     706             : };
     707             : 
     708           0 : static bool extract_entities(hash_entry_t *entry, void *pvt)
     709             : {
     710             :     int ret;
     711             :     struct extract_state *state;
     712             :     struct sysdb_attrs *member;
     713             :     struct ldb_message_element *el;
     714             :     struct ldb_message_element *name_el;
     715             : 
     716           0 :     state = talloc_get_type(pvt, struct extract_state);
     717           0 :     member = talloc_get_type(entry->value.ptr, struct sysdb_attrs);
     718             : 
     719           0 :     ret = sysdb_attrs_get_el(member, state->appropriateMemberOf, &el);
     720           0 :     if (ret != EOK) {
     721           0 :         return false;
     722             :     }
     723             : 
     724           0 :     ret = sysdb_attrs_get_el(member, SYSDB_NAME, &name_el);
     725           0 :     if (ret != EOK || name_el == NULL || name_el->num_values == 0) {
     726           0 :         return false;
     727             :     }
     728             : 
     729           0 :     for (int j = 0; j < el->num_values; j++) {
     730           0 :         if (strcmp((char *)el->values[j].data, state->group) == 0) {
     731           0 :             state->entries = talloc_realloc(state, state->entries,
     732             :                                             const char *,
     733             :                                             state->entries_count + 1);
     734           0 :             if (state->entries == NULL) {
     735           0 :                 return false;
     736             :             }
     737             : 
     738           0 :             state->entries[state->entries_count] = (char *)name_el->values[0].data;
     739           0 :             state->entries_count++;
     740           0 :             break;
     741             :         }
     742             :     }
     743             : 
     744           0 :     return true;
     745             : }
     746             : 
     747           0 : static int extract_members(TALLOC_CTX *mem_ctx,
     748             :                            struct sysdb_attrs *netgroup,
     749             :                            const char *member_type,
     750             :                            const char *appropriateMemberOf,
     751             :                            hash_table_t *lookup_table,
     752             :                            const char ***_ret_array,
     753             :                            int *_ret_count)
     754             : {
     755             :     struct extract_state *state;
     756             :     struct ldb_message_element *el;
     757             :     struct sysdb_attrs *member;
     758             :     hash_key_t key;
     759             :     hash_value_t value;
     760           0 :     const char **process = NULL;
     761           0 :     const char **ret_array = NULL;
     762           0 :     int process_count = 0;
     763           0 :     int ret_count = 0;
     764             :     int ret, i, pi;
     765             : 
     766           0 :     key.type = HASH_KEY_STRING;
     767           0 :     value.type = HASH_VALUE_PTR;
     768             : 
     769           0 :     state = talloc_zero(mem_ctx, struct extract_state);
     770           0 :     if (state == NULL) {
     771           0 :         ret = ENOMEM;
     772           0 :         goto done;
     773             :     }
     774             : 
     775           0 :     state->appropriateMemberOf = appropriateMemberOf;
     776             : 
     777           0 :     ret = sysdb_attrs_get_el(netgroup, member_type, &el);
     778           0 :     if (ret != EOK && ret != ENOENT) {
     779           0 :         goto done;
     780             :     }
     781             : 
     782           0 :     if (ret == EOK) {
     783           0 :         for (i = 0; i < el->num_values; i++) {
     784           0 :             key.str = (char *)el->values[i].data;
     785           0 :             ret = hash_lookup(lookup_table, &key, &value);
     786           0 :             if (ret != HASH_SUCCESS && ret != HASH_ERROR_KEY_NOT_FOUND) {
     787           0 :                 ret = ENOENT;
     788           0 :                 goto done;
     789             :             }
     790             : 
     791           0 :             if (ret == HASH_ERROR_KEY_NOT_FOUND) {
     792           0 :                 process = talloc_realloc(mem_ctx, process, const char *, process_count + 1);
     793           0 :                 if (process == NULL) {
     794           0 :                     ret = ENOMEM;
     795           0 :                     goto done;
     796             :                 }
     797             : 
     798           0 :                 process[process_count] = (char *)el->values[i].data;
     799           0 :                 process_count++;
     800             :             } else {
     801           0 :                 ret_array = talloc_realloc(mem_ctx, ret_array, const char *, ret_count + 1);
     802           0 :                 if (ret_array == NULL) {
     803           0 :                     ret = ENOMEM;
     804           0 :                     goto done;
     805             :                 }
     806           0 :                 member = talloc_get_type(value.ptr, struct sysdb_attrs);
     807           0 :                 ret = sysdb_attrs_get_string(member, SYSDB_NAME, &ret_array[ret_count]);
     808           0 :                 if (ret != EOK) {
     809           0 :                     goto done;
     810             :                 }
     811           0 :                 ret_count++;
     812             :             }
     813             : 
     814           0 :             for (pi = 0; pi < process_count; pi++) {
     815           0 :                 state->group = process[pi];
     816           0 :                 hash_iterate(lookup_table, extract_entities, state);
     817           0 :                 if (state->entries_count > 0) {
     818           0 :                     ret_array = talloc_realloc(mem_ctx, ret_array, const char *,
     819             :                             ret_count + state->entries_count);
     820           0 :                     if (ret_array == NULL) {
     821           0 :                         ret = ENOMEM;
     822           0 :                         goto done;
     823             :                     }
     824           0 :                     memcpy(&ret_array[ret_count], state->entries,
     825           0 :                             state->entries_count*sizeof(const char *));
     826           0 :                     ret_count += state->entries_count;
     827             :                 }
     828           0 :                 state->entries_count = 0;
     829           0 :                 talloc_zfree(state->entries);
     830             :             }
     831             :         }
     832             :     } else {
     833           0 :         ret_array = NULL;
     834             :     }
     835             : 
     836           0 :     *_ret_array = ret_array;
     837           0 :     *_ret_count = ret_count;
     838           0 :     ret = EOK;
     839             : 
     840             : done:
     841           0 :     return ret;
     842             : }
     843             : 
     844           0 : static int ipa_netgr_process_all(struct ipa_get_netgroups_state *state)
     845             : {
     846             :     int i, j, k, ret;
     847             :     const char **members;
     848             :     struct sysdb_attrs *member;
     849             :     const char *member_name;
     850             :     struct extract_state *extract_state;
     851             :     struct ldb_message_element *external_hosts;
     852           0 :     const char *dash[] = {"-"};
     853           0 :     const char **uids = NULL;
     854           0 :     const char **hosts = NULL;
     855           0 :     int uids_count = 0;
     856           0 :     int hosts_count = 0;
     857             :     hash_key_t key;
     858             :     hash_value_t value;
     859             :     const char *domain;
     860             :     char *triple;
     861             : 
     862           0 :     state->netgroups = talloc_zero_array(state, struct sysdb_attrs *,
     863             :                                          hash_count(state->new_netgroups));
     864           0 :     if (state->netgroups == NULL) {
     865           0 :         return ENOMEM;
     866             :     }
     867             : 
     868           0 :     extract_state = talloc_zero(state, struct extract_state);
     869           0 :     if (extract_state == NULL) {
     870           0 :         ret = ENOMEM;
     871           0 :         goto done;
     872             :     }
     873             : 
     874           0 :     key.type = HASH_KEY_STRING;
     875           0 :     value.type = HASH_VALUE_PTR;
     876             : 
     877           0 :     hash_iterate(state->new_netgroups, extract_netgroups, state);
     878           0 :     for (i = 0; i < state->netgroups_count; i++) {
     879             :         /* load all its member netgroups, translate */
     880           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Extracting netgroup members of netgroup %d\n", i);
     881           0 :         ret = sysdb_attrs_get_string_array(state->netgroups[i],
     882             :                                            SYSDB_ORIG_NETGROUP_MEMBER,
     883             :                                            state, &members);
     884           0 :         if (ret != EOK && ret != ENOENT) {
     885           0 :             goto done;
     886             :         }
     887             : 
     888           0 :         j = 0;
     889           0 :         if (ret == EOK) {
     890           0 :             for (j = 0; members[j]; j++) {
     891           0 :                 key.str = discard_const(members[j]);
     892           0 :                 ret = hash_lookup(state->new_netgroups, &key, &value);
     893           0 :                 if (ret != HASH_SUCCESS) {
     894           0 :                     ret = ENOENT;
     895           0 :                     goto done;
     896             :                 }
     897             : 
     898           0 :                 member = talloc_get_type(value.ptr, struct sysdb_attrs);
     899           0 :                 ret = sysdb_attrs_get_string(member, SYSDB_NAME, &member_name);
     900           0 :                 if (ret != EOK) {
     901           0 :                     goto done;
     902             :                 }
     903             : 
     904           0 :                 ret = sysdb_attrs_add_string(state->netgroups[i],
     905             :                                              SYSDB_NETGROUP_MEMBER,
     906             :                                              member_name);
     907           0 :                 if (ret != EOK) {
     908           0 :                     goto done;
     909             :                 }
     910             :             }
     911           0 :             talloc_zfree(members);
     912             :         }
     913           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Extracted %d netgroup members\n", j);
     914             : 
     915             :         /* Load all UIDs */
     916           0 :         DEBUG(SSSDBG_TRACE_ALL, "Extracting user members of netgroup %d\n", i);
     917           0 :         ret = extract_members(state, state->netgroups[i],
     918             :                               SYSDB_ORIG_MEMBER_USER,
     919           0 :                               state->ipa_opts->id->user_map[SDAP_AT_USER_MEMBEROF].sys_name,
     920             :                               state->new_users,
     921             :                               &uids, &uids_count);
     922           0 :         if (ret != EOK) {
     923           0 :             goto done;
     924             :         }
     925           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Extracted %d user members\n", uids_count);
     926             : 
     927           0 :         DEBUG(SSSDBG_TRACE_ALL, "Extracting host members of netgroup %d\n", i);
     928           0 :         ret = extract_members(state, state->netgroups[i],
     929             :                               SYSDB_ORIG_MEMBER_HOST,
     930           0 :                               state->ipa_opts->host_map[IPA_AT_HOST_MEMBER_OF].sys_name,
     931             :                               state->new_hosts,
     932             :                               &hosts, &hosts_count);
     933           0 :         if (ret != EOK) {
     934           0 :             goto done;
     935             :         }
     936           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Extracted %d host members\n", hosts_count);
     937             : 
     938           0 :         ret = sysdb_attrs_get_el(state->netgroups[i],
     939             :                                  SYSDB_ORIG_NETGROUP_EXTERNAL_HOST,
     940             :                                  &external_hosts);
     941           0 :         if (ret != EOK) {
     942           0 :             goto done;
     943             :         }
     944             : 
     945           0 :         if (external_hosts->num_values > 0) {
     946           0 :             hosts = talloc_realloc(state, hosts, const char *,
     947             :                                    hosts_count + external_hosts->num_values);
     948           0 :             if (hosts == NULL) {
     949           0 :                 ret = ENOMEM;
     950           0 :                 goto done;
     951             :             }
     952             : 
     953           0 :             for (j = 0; j < external_hosts->num_values; j++) {
     954           0 :                 hosts[hosts_count] = talloc_strdup(hosts, (char *)external_hosts->values[j].data);
     955           0 :                 if (hosts[hosts_count] == NULL) {
     956           0 :                     ret = ENOMEM;
     957           0 :                     goto done;
     958             :                 }
     959           0 :                 hosts_count++;
     960             :             }
     961             :         }
     962             : 
     963           0 :         ret = sysdb_attrs_get_string(state->netgroups[i], SYSDB_NETGROUP_DOMAIN,
     964             :                                      &domain);
     965           0 :         if (ret != EOK) {
     966           0 :             goto done;
     967             :         }
     968             : 
     969           0 :         if (uids_count > 0 || hosts_count > 0) {
     970           0 :             if (uids_count == 0) {
     971           0 :                 uids_count = 1;
     972           0 :                 uids = dash;
     973             :             }
     974             : 
     975           0 :             if (hosts_count == 0) {
     976           0 :                 hosts_count = 1;
     977           0 :                 hosts = dash;
     978             :             }
     979             : 
     980           0 :             DEBUG(SSSDBG_TRACE_INTERNAL, "Putting together triples of "
     981             :                                           "netgroup %d\n", i);
     982           0 :             for (j = 0; j < uids_count; j++) {
     983           0 :                 for (k = 0; k < hosts_count; k++) {
     984           0 :                     triple = talloc_asprintf(state, "(%s,%s,%s)",
     985           0 :                                              hosts[k], uids[j],
     986             :                                              domain);
     987           0 :                     if (triple == NULL) {
     988           0 :                         ret = ENOMEM;
     989           0 :                         goto done;
     990             :                     }
     991             : 
     992           0 :                     ret = sysdb_attrs_add_string(state->netgroups[i],
     993             :                                                  SYSDB_NETGROUP_TRIPLE,
     994             :                                                  triple);
     995           0 :                     if (ret != EOK) {
     996           0 :                         goto done;
     997             :                     }
     998             :                 }
     999             :             }
    1000             :         }
    1001             : 
    1002           0 :         ret = ipa_save_netgroup(state, state->dom,
    1003           0 :                                 state->opts, state->netgroups[i]);
    1004           0 :         if (ret != EOK) {
    1005           0 :             goto done;
    1006             :         }
    1007             :     }
    1008             : 
    1009           0 :     ret = EOK;
    1010             : done:
    1011           0 :     return ret;
    1012             : }
    1013             : 
    1014           0 : int ipa_get_netgroups_recv(struct tevent_req *req,
    1015             :                            TALLOC_CTX *mem_ctx,
    1016             :                            size_t *reply_count,
    1017             :                            struct sysdb_attrs ***reply)
    1018             : {
    1019           0 :     struct ipa_get_netgroups_state *state = tevent_req_data(req,
    1020             :                                                struct ipa_get_netgroups_state);
    1021             : 
    1022           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1023             : 
    1024           0 :     if (reply_count) {
    1025           0 :         *reply_count = state->netgroups_count;
    1026             :     }
    1027             : 
    1028           0 :     if (reply) {
    1029           0 :         *reply = talloc_steal(mem_ctx, state->netgroups);
    1030             :     }
    1031             : 
    1032           0 :     return EOK;
    1033             : }

Generated by: LCOV version 1.10