LCOV - code coverage report
Current view: top level - providers/ldap - sdap_async_initgroups_ad.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 688 0.0 %
Date: 2015-10-19 Functions: 0 27 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Authors:
       5             :         Stephen Gallagher <sgallagh@redhat.com>
       6             : 
       7             :     Copyright (C) 2012 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/ldap/sdap_async.h"
      25             : #include "providers/ldap/ldap_common.h"
      26             : #include "providers/ldap/sdap_async_private.h"
      27             : #include "providers/ldap/sdap_idmap.h"
      28             : #include "providers/ad/ad_common.h"
      29             : #include "lib/idmap/sss_idmap.h"
      30             : 
      31             : struct sdap_ad_match_rule_initgr_state {
      32             :     struct tevent_context *ev;
      33             :     struct sdap_options *opts;
      34             :     struct sysdb_ctx *sysdb;
      35             :     struct sss_domain_info *domain;
      36             :     struct sdap_handle *sh;
      37             :     const char *name;
      38             :     const char *orig_dn;
      39             :     const char **attrs;
      40             :     int timeout;
      41             :     const char *base_filter;
      42             :     char *filter;
      43             : 
      44             :     size_t count;
      45             :     struct sysdb_attrs **groups;
      46             : 
      47             :     size_t base_iter;
      48             :     struct sdap_search_base **search_bases;
      49             : };
      50             : 
      51             : static errno_t
      52             : sdap_get_ad_match_rule_initgroups_next_base(struct tevent_req *req);
      53             : 
      54             : static void
      55             : sdap_get_ad_match_rule_initgroups_step(struct tevent_req *subreq);
      56             : 
      57             : struct tevent_req *
      58           0 : sdap_get_ad_match_rule_initgroups_send(TALLOC_CTX *mem_ctx,
      59             :                                        struct tevent_context *ev,
      60             :                                        struct sdap_options *opts,
      61             :                                        struct sysdb_ctx *sysdb,
      62             :                                        struct sss_domain_info *domain,
      63             :                                        struct sdap_handle *sh,
      64             :                                        const char *name,
      65             :                                        const char *orig_dn,
      66             :                                        int timeout)
      67             : {
      68             :     errno_t ret;
      69             :     struct tevent_req *req;
      70             :     struct sdap_ad_match_rule_initgr_state *state;
      71             :     const char **filter_members;
      72             :     char *sanitized_user_dn;
      73             :     char *oc_list;
      74             : 
      75           0 :     req = tevent_req_create(mem_ctx, &state,
      76             :                             struct sdap_ad_match_rule_initgr_state);
      77           0 :     if (!req) return NULL;
      78             : 
      79           0 :     state->ev = ev;
      80           0 :     state->opts = opts;
      81           0 :     state->sysdb = sysdb;
      82           0 :     state->domain = domain;
      83           0 :     state->sh = sh;
      84           0 :     state->name = name;
      85           0 :     state->orig_dn = orig_dn;
      86           0 :     state->base_iter = 0;
      87           0 :     state->search_bases = opts->sdom->group_search_bases;
      88             : 
      89             :     /* Request all of the group attributes that we know
      90             :      * about, except for 'member' because that wastes a
      91             :      * lot of bandwidth here and we only really
      92             :      * care about a single member (the one we already
      93             :      * have).
      94             :      */
      95           0 :     filter_members = talloc_array(state, const char *, 2);
      96           0 :     if (!filter_members) {
      97           0 :         ret = ENOMEM;
      98           0 :         goto immediate;
      99             :     }
     100           0 :     filter_members[0] = opts->group_map[SDAP_AT_GROUP_MEMBER].name;
     101           0 :     filter_members[1] = NULL;
     102             : 
     103           0 :     ret = build_attrs_from_map(state, opts->group_map,
     104             :                                SDAP_OPTS_GROUP,
     105             :                                filter_members,
     106           0 :                                &state->attrs, NULL);
     107           0 :     if (ret != EOK) {
     108           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     109             :               "Could not build attribute map: [%s]\n",
     110             :                strerror(ret));
     111           0 :         goto immediate;
     112             :     }
     113             : 
     114             :     /* Sanitize the user DN in case we have special characters in DN */
     115           0 :     ret = sss_filter_sanitize(state, state->orig_dn, &sanitized_user_dn);
     116           0 :     if (ret != EOK) {
     117           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     118             :               "Could not sanitize user DN: %s\n",
     119             :                strerror(ret));
     120           0 :         goto immediate;
     121             :     }
     122             : 
     123             :     /* Craft a special filter according to
     124             :      * http://msdn.microsoft.com/en-us/library/windows/desktop/aa746475%28v=vs.85%29.aspx
     125             :      */
     126           0 :     oc_list = sdap_make_oc_list(state, state->opts->group_map);
     127           0 :     if (oc_list == NULL) {
     128           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create objectClass list.\n");
     129           0 :         ret = ENOMEM;
     130           0 :         goto immediate;
     131             :     }
     132             : 
     133           0 :     state->base_filter =
     134           0 :             talloc_asprintf(state,
     135             :                             "(&(%s:%s:=%s)(%s))",
     136           0 :                             state->opts->group_map[SDAP_AT_GROUP_MEMBER].name,
     137             :                             SDAP_MATCHING_RULE_IN_CHAIN,
     138             :                             sanitized_user_dn, oc_list);
     139           0 :     talloc_zfree(sanitized_user_dn);
     140           0 :     if (!state->base_filter) {
     141           0 :         ret = ENOMEM;
     142           0 :         goto immediate;
     143             :     }
     144             : 
     145             :     /* Start the loop through the search bases to get all of the
     146             :      * groups to which this user belongs.
     147             :      */
     148           0 :     ret = sdap_get_ad_match_rule_initgroups_next_base(req);
     149           0 :     if (ret != EOK) {
     150           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     151             :               "sdap_get_ad_match_rule_members_next_base failed: [%s]\n",
     152             :                strerror(ret));
     153           0 :         goto immediate;
     154             :     }
     155             : 
     156           0 :     return req;
     157             : 
     158             : immediate:
     159           0 :     tevent_req_error(req, ret);
     160           0 :     tevent_req_post(req, ev);
     161           0 :     return req;
     162             : }
     163             : 
     164             : static errno_t
     165           0 : sdap_get_ad_match_rule_initgroups_next_base(struct tevent_req *req)
     166             : {
     167             :     struct tevent_req *subreq;
     168             :     struct sdap_ad_match_rule_initgr_state *state;
     169             : 
     170           0 :     state = tevent_req_data(req, struct sdap_ad_match_rule_initgr_state);
     171             : 
     172           0 :     talloc_zfree(state->filter);
     173           0 :     state->filter = sdap_get_id_specific_filter(state,
     174             :                         state->base_filter,
     175           0 :                         state->search_bases[state->base_iter]->filter);
     176           0 :     if (!state->filter) {
     177           0 :         return ENOMEM;
     178             :     }
     179             : 
     180           0 :     DEBUG(SSSDBG_TRACE_FUNC,
     181             :           "Searching for groups with base [%s]\n",
     182             :            state->search_bases[state->base_iter]->basedn);
     183             : 
     184           0 :     subreq = sdap_get_generic_send(
     185             :             state, state->ev, state->opts, state->sh,
     186           0 :             state->search_bases[state->base_iter]->basedn,
     187           0 :             state->search_bases[state->base_iter]->scope,
     188           0 :             state->filter, state->attrs,
     189           0 :             state->opts->group_map, SDAP_OPTS_GROUP,
     190             :             state->timeout, true);
     191           0 :     if (!subreq) {
     192           0 :         return ENOMEM;
     193             :     }
     194             : 
     195           0 :     tevent_req_set_callback(subreq,
     196             :                             sdap_get_ad_match_rule_initgroups_step,
     197             :                             req);
     198             : 
     199           0 :     return EOK;
     200             : }
     201             : 
     202             : static void
     203           0 : sdap_get_ad_match_rule_initgroups_step(struct tevent_req *subreq)
     204             : {
     205             :     errno_t ret;
     206           0 :     struct tevent_req *req =
     207           0 :             tevent_req_callback_data(subreq, struct tevent_req);
     208           0 :     struct sdap_ad_match_rule_initgr_state *state =
     209           0 :             tevent_req_data(req, struct sdap_ad_match_rule_initgr_state);
     210             :     size_t count, i;
     211             :     struct sysdb_attrs **groups;
     212             :     char **sysdb_grouplist;
     213             : 
     214           0 :     ret = sdap_get_generic_recv(subreq, state, &count, &groups);
     215           0 :     talloc_zfree(subreq);
     216           0 :     if (ret != EOK) {
     217           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     218             :               "LDAP search failed: [%s]\n", sss_strerror(ret));
     219           0 :         goto error;
     220             :     }
     221             : 
     222           0 :     DEBUG(SSSDBG_TRACE_LIBS,
     223             :           "Search for users returned %zu results\n", count);
     224             : 
     225             :     /* Add this batch of groups to the list */
     226           0 :     if (count > 0) {
     227           0 :         state->groups = talloc_realloc(state, state->groups,
     228             :                                       struct sysdb_attrs *,
     229             :                                       state->count + count + 1);
     230           0 :         if (!state->groups) {
     231           0 :             tevent_req_error(req, ENOMEM);
     232           0 :             return;
     233             :         }
     234             : 
     235             :         /* Copy the new groups into the list */
     236           0 :         for (i = 0; i < count; i++) {
     237           0 :             state->groups[state->count + i] =
     238           0 :                     talloc_steal(state->groups, groups[i]);
     239             :         }
     240             : 
     241           0 :         state->count += count;
     242           0 :         state->groups[state->count] = NULL;
     243             :     }
     244             : 
     245             :     /* Continue checking other search bases */
     246           0 :     state->base_iter++;
     247           0 :     if (state->search_bases[state->base_iter]) {
     248             :         /* There are more search bases to try */
     249           0 :         ret = sdap_get_ad_match_rule_initgroups_next_base(req);
     250           0 :         if (ret != EOK) {
     251           0 :             goto error;
     252             :         }
     253           0 :         return;
     254             :     }
     255             : 
     256             :     /* No more search bases. Save the groups. */
     257             : 
     258           0 :     if (state->count == 0) {
     259           0 :         DEBUG(SSSDBG_TRACE_LIBS,
     260             :               "User is not a member of any group in the search bases\n");
     261             :     }
     262             : 
     263             :     /* Get the current sysdb group list for this user
     264             :      * so we can update it.
     265             :      */
     266           0 :     ret = get_sysdb_grouplist(state, state->sysdb, state->domain,
     267             :                               state->name, &sysdb_grouplist);
     268           0 :     if (ret != EOK) {
     269           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     270             :               "Could not get the list of groups for [%s] in the sysdb: "
     271             :                "[%s]\n",
     272             :                state->name, strerror(ret));
     273           0 :         goto error;
     274             :     }
     275             : 
     276             :     /* The extensibleMatch search rule eliminates the need for
     277             :      * nested group searches, so we can just update the
     278             :      * memberships now.
     279             :      */
     280           0 :     ret = sdap_initgr_common_store(state->sysdb,
     281             :                                    state->domain,
     282             :                                    state->opts,
     283             :                                    state->name,
     284             :                                    SYSDB_MEMBER_USER,
     285             :                                    sysdb_grouplist,
     286             :                                    state->groups,
     287           0 :                                    state->count);
     288           0 :     if (ret != EOK) {
     289           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     290             :               "Could not store groups for user [%s]: [%s]\n",
     291             :                state->name, strerror(ret));
     292           0 :         goto error;
     293             :     }
     294             : 
     295           0 :     tevent_req_done(req);
     296           0 :     return;
     297             : 
     298             : error:
     299           0 :     tevent_req_error(req, ret);
     300             : }
     301             : 
     302             : errno_t
     303           0 : sdap_get_ad_match_rule_initgroups_recv(struct tevent_req *req)
     304             : {
     305           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     306           0 :     return EOK;
     307             : }
     308             : 
     309             : struct sdap_get_ad_tokengroups_state {
     310             :     struct tevent_context *ev;
     311             :     struct sss_idmap_ctx *idmap_ctx;
     312             :     const char *username;
     313             : 
     314             :     char **sids;
     315             :     size_t num_sids;
     316             : };
     317             : 
     318             : static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq);
     319             : 
     320             : static struct tevent_req *
     321           0 : sdap_get_ad_tokengroups_send(TALLOC_CTX *mem_ctx,
     322             :                              struct tevent_context *ev,
     323             :                              struct sdap_options *opts,
     324             :                              struct sdap_handle *sh,
     325             :                              const char *name,
     326             :                              const char *orig_dn,
     327             :                              int timeout)
     328             : {
     329           0 :     struct sdap_get_ad_tokengroups_state *state = NULL;
     330           0 :     struct tevent_req *req = NULL;
     331           0 :     struct tevent_req *subreq = NULL;
     332           0 :     const char *attrs[] = {AD_TOKENGROUPS_ATTR, NULL};
     333             :     errno_t ret;
     334             : 
     335           0 :     req = tevent_req_create(mem_ctx, &state,
     336             :                             struct sdap_get_ad_tokengroups_state);
     337           0 :     if (req == NULL) {
     338           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     339           0 :         return NULL;
     340             :     }
     341             : 
     342           0 :     state->idmap_ctx = opts->idmap_ctx->map;
     343           0 :     state->ev = ev;
     344           0 :     state->username = talloc_strdup(state, name);
     345           0 :     if (state->username == NULL) {
     346           0 :         ret = ENOMEM;
     347           0 :         goto immediately;
     348             :     }
     349             : 
     350           0 :     subreq = sdap_get_generic_send(state, state->ev, opts, sh, orig_dn,
     351             :                                    LDAP_SCOPE_BASE, NULL, attrs,
     352             :                                    NULL, 0, timeout, false);
     353           0 :     if (subreq == NULL) {
     354           0 :         ret = ENOMEM;
     355           0 :         goto immediately;
     356             :     }
     357             : 
     358           0 :     tevent_req_set_callback(subreq, sdap_get_ad_tokengroups_done, req);
     359             : 
     360           0 :     return req;
     361             : 
     362             : immediately:
     363           0 :     if (ret == EOK) {
     364           0 :         tevent_req_done(req);
     365             :     } else {
     366           0 :         tevent_req_error(req, ret);
     367             :     }
     368           0 :     tevent_req_post(req, ev);
     369             : 
     370           0 :     return req;
     371             : }
     372             : 
     373           0 : static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq)
     374             : {
     375           0 :     TALLOC_CTX *tmp_ctx = NULL;
     376           0 :     struct sdap_get_ad_tokengroups_state *state = NULL;
     377           0 :     struct tevent_req *req = NULL;
     378           0 :     struct sysdb_attrs **users = NULL;
     379           0 :     struct ldb_message_element *el = NULL;
     380             :     enum idmap_error_code err;
     381           0 :     char *sid_str = NULL;
     382             :     size_t num_users;
     383             :     size_t i;
     384             :     errno_t ret;
     385             : 
     386           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     387           0 :     state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state);
     388             : 
     389           0 :     ret = sdap_get_generic_recv(subreq, tmp_ctx, &num_users, &users);
     390           0 :     talloc_zfree(subreq);
     391           0 :     if (ret != EOK) {
     392           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     393             :               "LDAP search failed: [%s]\n", sss_strerror(ret));
     394           0 :         goto done;
     395             :     }
     396             : 
     397           0 :     if (num_users != 1) {
     398           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     399             :               "More than one result on a base search!\n");
     400           0 :         ret = EINVAL;
     401           0 :         goto done;
     402             :     }
     403             : 
     404             :     /* get the list of sids from tokengroups */
     405           0 :     ret = sysdb_attrs_get_el_ext(users[0], AD_TOKENGROUPS_ATTR, false, &el);
     406           0 :     if (ret == ENOENT) {
     407           0 :         DEBUG(SSSDBG_TRACE_LIBS, "No tokenGroups entries for [%s]\n",
     408             :                                   state->username);
     409             : 
     410           0 :         state->sids = NULL;
     411           0 :         state->num_sids = 0;
     412           0 :         ret = EOK;
     413           0 :         goto done;
     414           0 :     } else if (ret != EOK) {
     415           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Could not read tokenGroups attribute: "
     416             :                                      "[%s]\n", strerror(ret));
     417           0 :         goto done;
     418             :     }
     419             : 
     420           0 :     state->num_sids = 0;
     421           0 :     state->sids = talloc_zero_array(state, char*, el->num_values);
     422           0 :     if (state->sids == NULL) {
     423           0 :         ret = ENOMEM;
     424           0 :         goto done;
     425             :     }
     426             : 
     427             :     /* convert binary sid to string */
     428           0 :     for (i = 0; i < el->num_values; i++) {
     429           0 :         err = sss_idmap_bin_sid_to_sid(state->idmap_ctx, el->values[i].data,
     430           0 :                                        el->values[i].length, &sid_str);
     431           0 :         if (err != IDMAP_SUCCESS) {
     432           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     433             :                   "Could not convert binary SID to string: [%s]. Skipping\n",
     434             :                    idmap_error_string(err));
     435           0 :             continue;
     436             :         }
     437             : 
     438           0 :         state->sids[i] = talloc_move(state->sids, &sid_str);
     439           0 :         state->num_sids++;
     440             :     }
     441             : 
     442             :     /* shrink array to final number of elements */
     443           0 :     state->sids = talloc_realloc(state, state->sids, char*, state->num_sids);
     444           0 :     if (state->sids == NULL) {
     445           0 :         ret = ENOMEM;
     446           0 :         goto done;
     447             :     }
     448             : 
     449           0 :     ret = EOK;
     450             : 
     451             : done:
     452           0 :     talloc_free(tmp_ctx);
     453             : 
     454           0 :     if (ret != EOK) {
     455           0 :         tevent_req_error(req, ret);
     456           0 :         return;
     457             :     }
     458             : 
     459           0 :     tevent_req_done(req);
     460             : }
     461             : 
     462           0 : static errno_t sdap_get_ad_tokengroups_recv(TALLOC_CTX *mem_ctx,
     463             :                                             struct tevent_req *req,
     464             :                                             size_t *_num_sids,
     465             :                                             char ***_sids)
     466             : {
     467           0 :     struct sdap_get_ad_tokengroups_state *state = NULL;
     468           0 :     state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state);
     469             : 
     470           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     471             : 
     472           0 :     if (_num_sids != NULL) {
     473           0 :         *_num_sids = state->num_sids;
     474             :     }
     475             : 
     476           0 :     if (_sids != NULL) {
     477           0 :         *_sids = talloc_steal(mem_ctx, state->sids);
     478             :     }
     479             : 
     480           0 :     return EOK;
     481             : }
     482             : 
     483             : static errno_t
     484           0 : sdap_ad_tokengroups_update_members(const char *username,
     485             :                                    struct sysdb_ctx *sysdb,
     486             :                                    struct sss_domain_info *domain,
     487             :                                    char **ldap_groups)
     488             : {
     489           0 :     TALLOC_CTX *tmp_ctx = NULL;
     490           0 :     char **sysdb_groups = NULL;
     491           0 :     char **add_groups = NULL;
     492           0 :     char **del_groups = NULL;
     493             :     errno_t ret;
     494             : 
     495           0 :     tmp_ctx = talloc_new(NULL);
     496           0 :     if (tmp_ctx == NULL) {
     497           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     498           0 :         return ENOMEM;
     499             :     }
     500             : 
     501             :     /* Get the current sysdb group list for this user so we can update it. */
     502           0 :     ret = get_sysdb_grouplist_dn(tmp_ctx, sysdb, domain,
     503             :                                  username, &sysdb_groups);
     504           0 :     if (ret != EOK) {
     505           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Could not get the list of groups for "
     506             :               "[%s] in the sysdb: [%s]\n", username, strerror(ret));
     507           0 :         goto done;
     508             :     }
     509             : 
     510             :     /* Find the differences between the sysdb and LDAP lists.
     511             :      * Groups in the sysdb only must be removed. */
     512           0 :     ret = diff_string_lists(tmp_ctx, ldap_groups, sysdb_groups,
     513             :                             &add_groups, &del_groups, NULL);
     514           0 :     if (ret != EOK) {
     515           0 :         goto done;
     516             :     }
     517             : 
     518           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Updating memberships for [%s]\n", username);
     519             : 
     520           0 :     ret = sysdb_update_members_dn(domain, username, SYSDB_MEMBER_USER,
     521             :                                   (const char *const *) add_groups,
     522             :                                   (const char *const *) del_groups);
     523           0 :     if (ret != EOK) {
     524           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
     525             :                                      ret, strerror(ret));
     526           0 :         goto done;
     527             :     }
     528             : 
     529             : done:
     530           0 :     talloc_free(tmp_ctx);
     531           0 :     return ret;
     532             : }
     533             : 
     534             : struct sdap_ad_resolve_sids_state {
     535             :     struct tevent_context *ev;
     536             :     struct sdap_id_ctx *id_ctx;
     537             :     struct sdap_id_conn_ctx *conn;
     538             :     struct sdap_options *opts;
     539             :     struct sss_domain_info *domain;
     540             :     char **sids;
     541             : 
     542             :     const char *current_sid;
     543             :     int index;
     544             : };
     545             : 
     546             : static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req);
     547             : static void sdap_ad_resolve_sids_done(struct tevent_req *subreq);
     548             : 
     549             : static struct tevent_req *
     550           0 : sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx,
     551             :                           struct tevent_context *ev,
     552             :                           struct sdap_id_ctx *id_ctx,
     553             :                           struct sdap_id_conn_ctx *conn,
     554             :                           struct sdap_options *opts,
     555             :                           struct sss_domain_info *domain,
     556             :                           char **sids)
     557             : {
     558           0 :     struct sdap_ad_resolve_sids_state *state = NULL;
     559           0 :     struct tevent_req *req = NULL;
     560             :     errno_t ret;
     561             : 
     562           0 :     req = tevent_req_create(mem_ctx, &state,
     563             :                             struct sdap_ad_resolve_sids_state);
     564           0 :     if (req == NULL) {
     565           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     566           0 :         return NULL;
     567             :     }
     568             : 
     569           0 :     state->ev = ev;
     570           0 :     state->id_ctx = id_ctx;
     571           0 :     state->conn = conn;
     572           0 :     state->opts = opts;
     573           0 :     state->domain = get_domains_head(domain);
     574           0 :     state->sids = sids;
     575           0 :     state->index = 0;
     576             : 
     577           0 :     if (state->sids == NULL || state->sids[0] == NULL) {
     578           0 :         ret = EOK;
     579           0 :         goto immediately;
     580             :     }
     581             : 
     582           0 :     ret = sdap_ad_resolve_sids_step(req);
     583           0 :     if (ret != EAGAIN) {
     584           0 :         goto immediately;
     585             :     }
     586             : 
     587           0 :     return req;
     588             : 
     589             : immediately:
     590           0 :     if (ret == EOK) {
     591           0 :         tevent_req_done(req);
     592             :     } else {
     593           0 :         tevent_req_error(req, ret);
     594             :     }
     595           0 :     tevent_req_post(req, ev);
     596             : 
     597           0 :     return req;
     598             : }
     599             : 
     600           0 : static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req)
     601             : {
     602           0 :     struct sdap_ad_resolve_sids_state *state = NULL;
     603           0 :     struct tevent_req *subreq = NULL;
     604           0 :     struct sdap_domain *sdap_domain = NULL;
     605           0 :     struct sss_domain_info *domain = NULL;
     606             : 
     607           0 :     state = tevent_req_data(req, struct sdap_ad_resolve_sids_state);
     608             : 
     609             :     do {
     610           0 :         state->current_sid = state->sids[state->index];
     611           0 :         if (state->current_sid == NULL) {
     612           0 :             return EOK;
     613             :         }
     614           0 :         state->index++;
     615             : 
     616           0 :         domain = sss_get_domain_by_sid_ldap_fallback(state->domain,
     617             :                                                      state->current_sid);
     618             : 
     619           0 :         if (domain == NULL) {
     620           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "SID %s does not belong to any known "
     621             :                                          "domain\n", state->current_sid);
     622             :         }
     623           0 :     } while (domain == NULL);
     624             : 
     625           0 :     sdap_domain = sdap_domain_get(state->opts, domain);
     626           0 :     if (sdap_domain == NULL) {
     627           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "SDAP domain does not exist?\n");
     628           0 :         return ERR_INTERNAL;
     629             :     }
     630             : 
     631           0 :     subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain,
     632             :                              state->conn, state->current_sid,
     633             :                              BE_FILTER_SECID, BE_ATTR_CORE, false, true);
     634           0 :     if (subreq == NULL) {
     635           0 :         return ENOMEM;
     636             :     }
     637             : 
     638           0 :     tevent_req_set_callback(subreq, sdap_ad_resolve_sids_done, req);
     639             : 
     640           0 :     return EAGAIN;
     641             : }
     642             : 
     643           0 : static void sdap_ad_resolve_sids_done(struct tevent_req *subreq)
     644             : {
     645           0 :     struct sdap_ad_resolve_sids_state *state = NULL;
     646           0 :     struct tevent_req *req = NULL;
     647             :     int dp_error;
     648             :     int sdap_error;
     649             :     errno_t ret;
     650             : 
     651           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     652           0 :     state = tevent_req_data(req, struct sdap_ad_resolve_sids_state);
     653             : 
     654           0 :     ret = groups_get_recv(subreq, &dp_error, &sdap_error);
     655           0 :     talloc_zfree(subreq);
     656             : 
     657           0 :     if (ret == EOK && sdap_error == ENOENT && dp_error == DP_ERR_OK) {
     658             :         /* Group was not found, we will ignore the error and continue with
     659             :          * next group. This may happen for example if the group is built-in,
     660             :          * but a custom search base is provided. */
     661           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     662             :               "Unable to resolve SID %s - will try next sid.\n",
     663             :               state->current_sid);
     664           0 :     } else if (ret != EOK || sdap_error != EOK || dp_error != DP_ERR_OK) {
     665           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s [dp_error: %d, "
     666             :               "sdap_error: %d, ret: %d]: %s\n", state->current_sid, dp_error,
     667             :               sdap_error, ret, strerror(ret));
     668           0 :         goto done;
     669             :     }
     670             : 
     671           0 :     ret = sdap_ad_resolve_sids_step(req);
     672           0 :     if (ret == EAGAIN) {
     673             :         /* continue with next SID */
     674           0 :         return;
     675             :     }
     676             : 
     677             : done:
     678           0 :     if (ret != EOK) {
     679           0 :         tevent_req_error(req, ret);
     680           0 :         return;
     681             :     }
     682             : 
     683           0 :     tevent_req_done(req);
     684             : }
     685             : 
     686           0 : static errno_t sdap_ad_resolve_sids_recv(struct tevent_req *req)
     687             : {
     688           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     689             : 
     690           0 :     return EOK;
     691             : }
     692             : 
     693             : 
     694             : struct sdap_ad_tokengroups_initgr_mapping_state {
     695             :     struct tevent_context *ev;
     696             :     struct sdap_options *opts;
     697             :     struct sdap_handle *sh;
     698             :     struct sdap_idmap_ctx *idmap_ctx;
     699             :     struct sysdb_ctx *sysdb;
     700             :     struct sss_domain_info *domain;
     701             :     const char *orig_dn;
     702             :     int timeout;
     703             :     const char *username;
     704             : 
     705             :     struct sdap_id_op *op;
     706             : };
     707             : 
     708             : static void
     709             : sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq);
     710             : static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq);
     711             : static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx,
     712             :                                   struct tevent_context *ev,
     713             :                                   struct sdap_options *opts,
     714             :                                   const char *orig_dn,
     715             :                                   int timeout,
     716             :                                   const char *username,
     717             :                                   struct sdap_handle *sh,
     718             :                                   struct tevent_req *req,
     719             :                                   tevent_req_fn callback);
     720             : 
     721             : static struct tevent_req *
     722           0 : sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx,
     723             :                                         struct tevent_context *ev,
     724             :                                         struct sdap_options *opts,
     725             :                                         struct sysdb_ctx *sysdb,
     726             :                                         struct sss_domain_info *domain,
     727             :                                         struct sdap_handle *sh,
     728             :                                         const char *name,
     729             :                                         const char *orig_dn,
     730             :                                         int timeout)
     731             : {
     732           0 :     struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
     733           0 :     struct tevent_req *req = NULL;
     734           0 :     struct tevent_req *subreq = NULL;
     735             :     struct sdap_domain *sdom;
     736             :     struct ad_id_ctx *subdom_id_ctx;
     737             :     errno_t ret;
     738             : 
     739           0 :     req = tevent_req_create(mem_ctx, &state,
     740             :                             struct sdap_ad_tokengroups_initgr_mapping_state);
     741           0 :     if (req == NULL) {
     742           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     743           0 :         return NULL;
     744             :     }
     745             : 
     746           0 :     state->ev = ev;
     747           0 :     state->opts = opts;
     748           0 :     state->sh = sh;
     749           0 :     state->idmap_ctx = opts->idmap_ctx;
     750           0 :     state->sysdb = sysdb;
     751           0 :     state->domain = domain;
     752           0 :     state->timeout = timeout;
     753           0 :     state->orig_dn = orig_dn;
     754           0 :     state->username = talloc_strdup(state, name);
     755           0 :     if (state->username == NULL) {
     756           0 :         ret = ENOMEM;
     757           0 :         goto immediately;
     758             :     }
     759             : 
     760           0 :     sdom = sdap_domain_get(opts, domain);
     761           0 :     if (sdom == NULL || sdom->pvt == NULL) {
     762           0 :         ret = handle_missing_pvt(mem_ctx, ev, opts, orig_dn, timeout,
     763           0 :                                  state->username, sh, req,
     764             :                                  sdap_ad_tokengroups_initgr_mapping_done);
     765           0 :         if (ret == EOK) {
     766           0 :             return req;
     767             :         } else {
     768           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
     769             :                   domain->name);
     770           0 :             goto immediately;
     771             :         }
     772             :     }
     773             : 
     774           0 :     subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
     775           0 :     state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache);
     776           0 :     if (!state->op) {
     777           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
     778           0 :         ret = ENOMEM;
     779           0 :         goto immediately;
     780             :     }
     781             : 
     782           0 :     subreq = sdap_id_op_connect_send(state->op, state, &ret);
     783           0 :     if (subreq == NULL) {
     784           0 :         ret = ENOMEM;
     785           0 :         goto immediately;
     786             :     }
     787             : 
     788           0 :     tevent_req_set_callback(subreq,
     789             :                             sdap_ad_tokengroups_initgr_mapping_connect_done,
     790             :                             req);
     791             : 
     792           0 :     return req;
     793             : 
     794             : immediately:
     795           0 :     if (ret == EOK) {
     796           0 :         tevent_req_done(req);
     797             :     } else {
     798           0 :         tevent_req_error(req, ret);
     799             :     }
     800           0 :     tevent_req_post(req, ev);
     801             : 
     802           0 :     return req;
     803             : }
     804             : 
     805             : static void
     806           0 : sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq)
     807             : {
     808           0 :     struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
     809           0 :     struct tevent_req *req = NULL;
     810             :     int ret;
     811           0 :     int dp_error = DP_ERR_FATAL;
     812             : 
     813           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     814           0 :     state = tevent_req_data(req,
     815             :                             struct sdap_ad_tokengroups_initgr_mapping_state);
     816             : 
     817             : 
     818           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     819           0 :     talloc_zfree(subreq);
     820             : 
     821           0 :     if (ret != EOK) {
     822           0 :         tevent_req_error(req, ret);
     823           0 :         return;
     824             :     }
     825             : 
     826           0 :     subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts,
     827             :                                           sdap_id_op_handle(state->op),
     828             :                                           state->username,
     829             :                                           state->orig_dn, state->timeout);
     830           0 :     if (subreq == NULL) {
     831           0 :         tevent_req_error(req, ENOMEM);
     832           0 :         return;
     833             :     }
     834             : 
     835           0 :     tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_mapping_done,
     836             :                             req);
     837             : 
     838           0 :     return;
     839             : }
     840             : 
     841           0 : static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq)
     842             : {
     843           0 :     TALLOC_CTX *tmp_ctx = NULL;
     844           0 :     struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
     845           0 :     struct tevent_req *req = NULL;
     846           0 :     struct sss_domain_info *domain = NULL;
     847           0 :     struct ldb_message *msg = NULL;
     848           0 :     const char *attrs[] = {SYSDB_NAME, NULL};
     849           0 :     const char *name = NULL;
     850           0 :     const char *sid = NULL;
     851           0 :     char **sids = NULL;
     852           0 :     size_t num_sids = 0;
     853             :     size_t i;
     854             :     time_t now;
     855             :     gid_t gid;
     856           0 :     char **groups = NULL;
     857             :     size_t num_groups;
     858             :     errno_t ret, sret;
     859           0 :     bool in_transaction = false;
     860             : 
     861           0 :     tmp_ctx = talloc_new(NULL);
     862           0 :     if (tmp_ctx == NULL) {
     863           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     864           0 :         ret = ENOMEM;
     865           0 :         goto done;
     866             :     }
     867             : 
     868           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     869           0 :     state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_mapping_state);
     870             : 
     871           0 :     ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids);
     872           0 :     talloc_zfree(subreq);
     873           0 :     if (ret != EOK) {
     874           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire tokengroups [%d]: %s\n",
     875             :                                     ret, strerror(ret));
     876           0 :         goto done;
     877             :     }
     878             : 
     879           0 :     num_groups = 0;
     880           0 :     groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
     881           0 :     if (groups == NULL) {
     882           0 :         ret = ENOMEM;
     883           0 :         goto done;
     884             :     }
     885             : 
     886           0 :     now = time(NULL);
     887           0 :     ret = sysdb_transaction_start(state->sysdb);
     888           0 :     if (ret != EOK) {
     889           0 :         goto done;
     890             :     }
     891           0 :     in_transaction = true;
     892             : 
     893           0 :     for (i = 0; i < num_sids; i++) {
     894           0 :         sid = sids[i];
     895           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Processing membership SID [%s]\n", sid);
     896             : 
     897           0 :         ret = sdap_idmap_sid_to_unix(state->idmap_ctx, sid, &gid);
     898           0 :         if (ret == ENOTSUP) {
     899           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Skipping built-in object.\n");
     900           0 :             continue;
     901           0 :         } else if (ret != EOK) {
     902           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Could not convert SID to GID: [%s]. "
     903             :                                          "Skipping\n", strerror(ret));
     904           0 :             continue;
     905             :         }
     906             : 
     907           0 :         domain = sss_get_domain_by_sid_ldap_fallback(state->domain, sid);
     908           0 :         if (domain == NULL) {
     909           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Domain not found for SID %s\n", sid);
     910           0 :             continue;
     911             :         }
     912             : 
     913           0 :         DEBUG(SSSDBG_TRACE_LIBS, "SID [%s] maps to GID [%"SPRIgid"]\n",
     914             :                                   sid, gid);
     915             : 
     916             :         /* Check whether this GID already exists in the sysdb */
     917           0 :         ret = sysdb_search_group_by_gid(tmp_ctx, domain, gid, attrs, &msg);
     918           0 :         if (ret == EOK) {
     919           0 :             name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
     920           0 :             if (name == NULL) {
     921           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
     922             :                       "Could not retrieve group name from sysdb\n");
     923           0 :                 ret = EINVAL;
     924           0 :                 goto done;
     925             :             }
     926           0 :         } else if (ret == ENOENT) {
     927             :             /* This is a new group. For now, we will store it under the name
     928             :              * of its SID. When a direct lookup of the group or its GID occurs,
     929             :              * it will replace this temporary entry. */
     930           0 :             name = sid;
     931           0 :             ret = sysdb_add_incomplete_group(domain, name, gid,
     932             :                                              NULL, sid, NULL, false, now);
     933           0 :             if (ret != EOK) {
     934           0 :                 DEBUG(SSSDBG_MINOR_FAILURE, "Could not create incomplete "
     935             :                                              "group: [%s]\n", strerror(ret));
     936           0 :                 goto done;
     937             :             }
     938             :         } else {
     939             :             /* Unexpected error */
     940           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Could not look up group in sysdb: "
     941             :                                          "[%s]\n", strerror(ret));
     942           0 :             goto done;
     943             :         }
     944             : 
     945           0 :         groups[num_groups] = sysdb_group_strdn(tmp_ctx, domain->name, name);
     946           0 :         if (groups[num_groups] == NULL) {
     947           0 :             ret = ENOMEM;
     948           0 :             goto done;
     949             :         }
     950           0 :         num_groups++;
     951             :     }
     952             : 
     953           0 :     groups[num_groups] = NULL;
     954             : 
     955           0 :     ret = sdap_ad_tokengroups_update_members(state->username,
     956             :                                              state->sysdb, state->domain,
     957             :                                              groups);
     958           0 :     if (ret != EOK) {
     959           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
     960             :                                      ret, strerror(ret));
     961           0 :         goto done;
     962             :     }
     963             : 
     964           0 :     ret = sysdb_transaction_commit(state->sysdb);
     965           0 :     if (ret != EOK) {
     966           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not commit transaction! [%s]\n",
     967             :                                     strerror(ret));
     968           0 :         goto done;
     969             :     }
     970           0 :     in_transaction = false;
     971             : 
     972             : done:
     973           0 :     talloc_free(tmp_ctx);
     974             : 
     975           0 :     if (in_transaction) {
     976           0 :         sret = sysdb_transaction_cancel(state->sysdb);
     977           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Could not cancel transaction! [%s]\n",
     978             :                                      strerror(sret));
     979             :     }
     980             : 
     981           0 :     if (ret != EOK) {
     982           0 :         tevent_req_error(req, ret);
     983           0 :         return;
     984             :     }
     985             : 
     986           0 :     tevent_req_done(req);
     987             : }
     988             : 
     989           0 : static int sdap_ad_tokengroups_initgr_mapping_recv(struct tevent_req *req)
     990             : {
     991           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     992             : 
     993           0 :     return EOK;
     994             : }
     995             : 
     996             : struct sdap_ad_tokengroups_initgr_posix_state {
     997             :     struct tevent_context *ev;
     998             :     struct sdap_id_ctx *id_ctx;
     999             :     struct sdap_id_conn_ctx *conn;
    1000             :     struct sdap_options *opts;
    1001             :     struct sdap_handle *sh;
    1002             :     struct sysdb_ctx *sysdb;
    1003             :     struct sss_domain_info *domain;
    1004             :     const char *orig_dn;
    1005             :     int timeout;
    1006             :     const char *username;
    1007             : 
    1008             :     struct sdap_id_op *op;
    1009             :     char **missing_sids;
    1010             :     size_t num_missing_sids;
    1011             :     char **cached_groups;
    1012             :     size_t num_cached_groups;
    1013             : };
    1014             : 
    1015             : static void
    1016             : sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq);
    1017             : 
    1018             : static void
    1019             : sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq);
    1020             : static void
    1021             : sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq);
    1022             : 
    1023             : static struct tevent_req *
    1024           0 : sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx,
    1025             :                                       struct tevent_context *ev,
    1026             :                                       struct sdap_id_ctx *id_ctx,
    1027             :                                       struct sdap_id_conn_ctx *conn,
    1028             :                                       struct sdap_options *opts,
    1029             :                                       struct sysdb_ctx *sysdb,
    1030             :                                       struct sss_domain_info *domain,
    1031             :                                       struct sdap_handle *sh,
    1032             :                                       const char *name,
    1033             :                                       const char *orig_dn,
    1034             :                                       int timeout)
    1035             : {
    1036           0 :     struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
    1037           0 :     struct tevent_req *req = NULL;
    1038           0 :     struct tevent_req *subreq = NULL;
    1039             :     struct sdap_domain *sdom;
    1040             :     struct ad_id_ctx *subdom_id_ctx;
    1041             :     errno_t ret;
    1042             : 
    1043           0 :     req = tevent_req_create(mem_ctx, &state,
    1044             :                             struct sdap_ad_tokengroups_initgr_posix_state);
    1045           0 :     if (req == NULL) {
    1046           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
    1047           0 :         return NULL;
    1048             :     }
    1049             : 
    1050           0 :     state->ev = ev;
    1051           0 :     state->id_ctx = id_ctx;
    1052           0 :     state->conn = conn;
    1053           0 :     state->opts = opts;
    1054           0 :     state->sh = sh;
    1055           0 :     state->sysdb = sysdb;
    1056           0 :     state->domain = domain;
    1057           0 :     state->orig_dn = orig_dn;
    1058           0 :     state->timeout = timeout;
    1059           0 :     state->username = talloc_strdup(state, name);
    1060           0 :     if (state->username == NULL) {
    1061           0 :         ret = ENOMEM;
    1062           0 :         goto immediately;
    1063             :     }
    1064             : 
    1065           0 :     sdom = sdap_domain_get(opts, domain);
    1066           0 :     if (sdom == NULL || sdom->pvt == NULL) {
    1067           0 :         ret = handle_missing_pvt(mem_ctx, ev, opts, orig_dn, timeout,
    1068           0 :                                  state->username, sh, req,
    1069             :                                  sdap_ad_tokengroups_initgr_posix_tg_done);
    1070           0 :         if (ret == EOK) {
    1071           0 :             return req;
    1072             :         } else {
    1073           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n",
    1074             :                   domain->name);
    1075           0 :             goto immediately;
    1076             :         }
    1077             :     }
    1078           0 :     subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
    1079           0 :     state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache);
    1080           0 :     if (!state->op) {
    1081           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
    1082           0 :         ret = ENOMEM;
    1083           0 :         goto immediately;
    1084             :     }
    1085             : 
    1086           0 :     subreq = sdap_id_op_connect_send(state->op, state, &ret);
    1087           0 :     if (subreq == NULL) {
    1088           0 :         ret = ENOMEM;
    1089           0 :         goto immediately;
    1090             :     }
    1091             : 
    1092           0 :     tevent_req_set_callback(subreq,
    1093             :                             sdap_ad_tokengroups_initgr_posix_sids_connect_done,
    1094             :                             req);
    1095             : 
    1096           0 :     return req;
    1097             : 
    1098             : immediately:
    1099           0 :     if (ret == EOK) {
    1100           0 :         tevent_req_done(req);
    1101             :     } else {
    1102           0 :         tevent_req_error(req, ret);
    1103             :     }
    1104           0 :     tevent_req_post(req, ev);
    1105             : 
    1106           0 :     return req;
    1107             : }
    1108             : 
    1109             : static void
    1110           0 : sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq)
    1111             : {
    1112           0 :     struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
    1113           0 :     struct tevent_req *req = NULL;
    1114             :     int ret;
    1115           0 :     int dp_error = DP_ERR_FATAL;
    1116             : 
    1117           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1118           0 :     state = tevent_req_data(req,
    1119             :                             struct sdap_ad_tokengroups_initgr_posix_state);
    1120             : 
    1121             : 
    1122           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
    1123           0 :     talloc_zfree(subreq);
    1124             : 
    1125           0 :     if (ret != EOK) {
    1126           0 :         tevent_req_error(req, ret);
    1127           0 :         return;
    1128             :     }
    1129             : 
    1130           0 :     subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts,
    1131             :                                           sdap_id_op_handle(state->op),
    1132             :                                           state->username, state->orig_dn,
    1133             :                                           state->timeout);
    1134           0 :     if (subreq == NULL) {
    1135           0 :         tevent_req_error(req, ENOMEM);
    1136           0 :         return;
    1137             :     }
    1138             : 
    1139           0 :     tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_tg_done,
    1140             :                             req);
    1141             : 
    1142           0 :     return;
    1143             : }
    1144             : 
    1145             : static errno_t
    1146           0 : sdap_ad_tokengroups_get_posix_members(TALLOC_CTX *mem_ctx,
    1147             :                          struct sdap_ad_tokengroups_initgr_posix_state *state,
    1148             :                          size_t num_sids,
    1149             :                          char **sids,
    1150             :                          size_t *_num_missing,
    1151             :                          char ***_missing,
    1152             :                          size_t *_num_valid,
    1153             :                          char ***_valid_groups)
    1154             : {
    1155           0 :     TALLOC_CTX *tmp_ctx = NULL;
    1156           0 :     struct sss_domain_info *domain = NULL;
    1157           0 :     struct ldb_message *msg = NULL;
    1158           0 :     const char *attrs[] = {SYSDB_NAME, NULL};
    1159           0 :     const char *name = NULL;
    1160           0 :     char *sid = NULL;
    1161           0 :     char **valid_groups = NULL;
    1162             :     size_t num_valid_groups;
    1163           0 :     char **missing_sids = NULL;
    1164             :     size_t num_missing_sids;
    1165             :     size_t i;
    1166             :     errno_t ret;
    1167             : 
    1168           0 :     tmp_ctx = talloc_new(NULL);
    1169           0 :     if (tmp_ctx == NULL) {
    1170           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
    1171           0 :         ret = ENOMEM;
    1172           0 :         goto done;
    1173             :     }
    1174             : 
    1175           0 :     num_valid_groups = 0;
    1176           0 :     valid_groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
    1177           0 :     if (valid_groups == NULL) {
    1178           0 :         ret = ENOMEM;
    1179           0 :         goto done;
    1180             :     }
    1181             : 
    1182           0 :     num_missing_sids = 0;
    1183           0 :     missing_sids = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
    1184           0 :     if (missing_sids == NULL) {
    1185           0 :         ret = ENOMEM;
    1186           0 :         goto done;
    1187             :     }
    1188             : 
    1189             :     /* For each SID check if it is already present in the cache. If yes, we
    1190             :      * will get name of the group and update the membership. Otherwise we need
    1191             :      * to remember the SID and download missing groups one by one. */
    1192           0 :     for (i = 0; i < num_sids; i++) {
    1193           0 :         sid = sids[i];
    1194           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Processing membership SID [%s]\n", sid);
    1195             : 
    1196           0 :         domain = sss_get_domain_by_sid_ldap_fallback(state->domain, sid);
    1197           0 :         if (domain == NULL) {
    1198           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Domain not found for SID %s\n", sid);
    1199           0 :             continue;
    1200             :         }
    1201             : 
    1202           0 :         ret = sysdb_search_group_by_sid_str(tmp_ctx, domain, sid, attrs, &msg);
    1203           0 :         if (ret == EOK) {
    1204             :             /* we will update membership of this group */
    1205           0 :             name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
    1206           0 :             if (name == NULL) {
    1207           0 :                 DEBUG(SSSDBG_MINOR_FAILURE,
    1208             :                       "Could not retrieve group name from sysdb\n");
    1209           0 :                 ret = EINVAL;
    1210           0 :                 goto done;
    1211             :             }
    1212             : 
    1213           0 :             valid_groups[num_valid_groups] = sysdb_group_strdn(valid_groups,
    1214           0 :                                                                domain->name,
    1215             :                                                                name);
    1216           0 :             if (valid_groups[num_valid_groups] == NULL) {
    1217           0 :                 ret = ENOMEM;
    1218           0 :                 goto done;
    1219             :             }
    1220           0 :             num_valid_groups++;
    1221           0 :         } else if (ret == ENOENT) {
    1222           0 :             if (_missing != NULL) {
    1223             :                 /* we need to download this group */
    1224           0 :                 missing_sids[num_missing_sids] = talloc_steal(missing_sids,
    1225             :                                                               sid);
    1226           0 :                 num_missing_sids++;
    1227             : 
    1228           0 :                 DEBUG(SSSDBG_TRACE_FUNC, "Missing SID %s will be downloaded\n",
    1229             :                                           sid);
    1230             :             }
    1231             : 
    1232             :             /* else: We have downloaded missing groups but some of them may
    1233             :              * remained missing because they are outside of search base. We
    1234             :              * will just ignore them and continue with the next group. */
    1235             :         } else {
    1236           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "Could not look up SID %s in sysdb: "
    1237             :                                          "[%s]\n", sid, strerror(ret));
    1238           0 :             goto done;
    1239             :         }
    1240             :     }
    1241             : 
    1242           0 :     valid_groups[num_valid_groups] = NULL;
    1243           0 :     missing_sids[num_missing_sids] = NULL;
    1244             : 
    1245             :     /* return list of missing groups */
    1246           0 :     if (_missing != NULL) {
    1247           0 :         *_missing = talloc_steal(mem_ctx, missing_sids);
    1248           0 :         *_num_missing = num_missing_sids;
    1249             :     }
    1250             : 
    1251             :     /* return list of missing groups */
    1252           0 :     if (_valid_groups != NULL) {
    1253           0 :         *_valid_groups = talloc_steal(mem_ctx, valid_groups);
    1254           0 :         *_num_valid = num_valid_groups;
    1255             :     }
    1256             : 
    1257           0 :     ret = EOK;
    1258             : 
    1259             : done:
    1260           0 :     talloc_free(tmp_ctx);
    1261           0 :     return ret;
    1262             : }
    1263             : 
    1264             : static void
    1265           0 : sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq)
    1266             : {
    1267           0 :     struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
    1268           0 :     struct tevent_req *req = NULL;
    1269           0 :     char **sids = NULL;
    1270           0 :     size_t num_sids = 0;
    1271             :     errno_t ret;
    1272             : 
    1273           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1274           0 :     state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state);
    1275             : 
    1276           0 :     ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids);
    1277           0 :     talloc_zfree(subreq);
    1278           0 :     if (ret != EOK) {
    1279           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire tokengroups [%d]: %s\n",
    1280             :                                     ret, strerror(ret));
    1281           0 :         goto done;
    1282             :     }
    1283             : 
    1284           0 :     ret = sdap_ad_tokengroups_get_posix_members(state, state,
    1285             :                                                 num_sids, sids,
    1286             :                                                 &state->num_missing_sids,
    1287             :                                                 &state->missing_sids,
    1288             :                                                 &state->num_cached_groups,
    1289             :                                                 &state->cached_groups);
    1290           0 :     if (ret != EOK) {
    1291           0 :         goto done;
    1292             :     }
    1293             : 
    1294             :     /* download missing SIDs */
    1295           0 :     subreq = sdap_ad_resolve_sids_send(state, state->ev, state->id_ctx,
    1296             :                                        state->conn,
    1297             :                                        state->opts, state->domain,
    1298             :                                        state->missing_sids);
    1299           0 :     if (subreq == NULL) {
    1300           0 :         ret = ENOMEM;
    1301           0 :         goto done;
    1302             :     }
    1303             : 
    1304           0 :     tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_sids_done,
    1305             :                             req);
    1306             : 
    1307           0 :     return;
    1308             : 
    1309             : done:
    1310           0 :     if (ret != EOK) {
    1311           0 :         tevent_req_error(req, ret);
    1312           0 :         return;
    1313             :     }
    1314             : 
    1315           0 :     tevent_req_done(req);
    1316             : }
    1317             : 
    1318             : static char **concatenate_string_array(TALLOC_CTX *mem_ctx,
    1319             :                                        char **arr1, size_t len1,
    1320             :                                        char **arr2, size_t len2);
    1321             : 
    1322             : static void
    1323           0 : sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq)
    1324             : {
    1325           0 :     struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
    1326           0 :     struct tevent_req *req = NULL;
    1327             :     errno_t ret;
    1328             :     char **cached_groups;
    1329             :     size_t num_cached_groups;
    1330             : 
    1331           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1332           0 :     state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_posix_state);
    1333             : 
    1334           0 :     ret = sdap_ad_resolve_sids_recv(subreq);
    1335           0 :     talloc_zfree(subreq);
    1336           0 :     if (ret != EOK) {
    1337           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve missing SIDs "
    1338             :                                    "[%d]: %s\n", ret, strerror(ret));
    1339           0 :         goto done;
    1340             :     }
    1341             : 
    1342           0 :     ret = sdap_ad_tokengroups_get_posix_members(state, state,
    1343             :                                                 state->num_missing_sids,
    1344             :                                                 state->missing_sids,
    1345             :                                                 NULL, NULL,
    1346             :                                                 &num_cached_groups,
    1347             :                                                 &cached_groups);
    1348           0 :     if (ret != EOK){
    1349           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    1350             :               "sdap_ad_tokengroups_get_posix_members failed [%d]: %s\n",
    1351             :               ret, strerror(ret));
    1352           0 :         goto done;
    1353             :     }
    1354             : 
    1355           0 :     state->cached_groups = concatenate_string_array(state,
    1356             :                                                     state->cached_groups,
    1357             :                                                     state->num_cached_groups,
    1358             :                                                     cached_groups,
    1359             :                                                     num_cached_groups);
    1360           0 :     if (state->cached_groups == NULL) {
    1361           0 :         ret = ENOMEM;
    1362           0 :         goto done;
    1363             :     }
    1364             : 
    1365             :     /* update membership of existing groups */
    1366           0 :     ret = sdap_ad_tokengroups_update_members(state->username,
    1367             :                                              state->sysdb, state->domain,
    1368             :                                              state->cached_groups);
    1369           0 :     if (ret != EOK) {
    1370           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n",
    1371             :                                      ret, strerror(ret));
    1372           0 :         goto done;
    1373             :     }
    1374             : 
    1375             : done:
    1376           0 :     if (ret != EOK) {
    1377           0 :         tevent_req_error(req, ret);
    1378           0 :         return;
    1379             :     }
    1380             : 
    1381           0 :     tevent_req_done(req);
    1382             : }
    1383             : 
    1384           0 : static char **concatenate_string_array(TALLOC_CTX *mem_ctx,
    1385             :                                        char **arr1, size_t len1,
    1386             :                                        char **arr2, size_t len2)
    1387             : {
    1388             :     size_t i, j;
    1389           0 :     size_t new_size = len1 + len2;
    1390           0 :     char ** string_array = talloc_realloc(mem_ctx, arr1, char *, new_size + 1);
    1391           0 :     if (string_array == NULL) {
    1392           0 :         return NULL;
    1393             :     }
    1394             : 
    1395           0 :     for (i=len1, j=0; i < new_size; ++i,++j) {
    1396           0 :         string_array[i] = talloc_steal(string_array,
    1397             :                                        arr2[j]);
    1398             :     }
    1399             : 
    1400           0 :     string_array[i] = NULL;
    1401             : 
    1402           0 :     return string_array;
    1403             : }
    1404             : 
    1405           0 : static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req)
    1406             : {
    1407           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1408             : 
    1409           0 :     return EOK;
    1410             : }
    1411             : 
    1412             : struct sdap_ad_tokengroups_initgroups_state {
    1413             :     bool use_id_mapping;
    1414             :     struct sss_domain_info *domain;
    1415             : };
    1416             : 
    1417             : static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq);
    1418             : 
    1419             : struct tevent_req *
    1420           0 : sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
    1421             :                                     struct tevent_context *ev,
    1422             :                                     struct sdap_id_ctx *id_ctx,
    1423             :                                     struct sdap_id_conn_ctx *conn,
    1424             :                                     struct sdap_options *opts,
    1425             :                                     struct sysdb_ctx *sysdb,
    1426             :                                     struct sss_domain_info *domain,
    1427             :                                     struct sdap_handle *sh,
    1428             :                                     const char *name,
    1429             :                                     const char *orig_dn,
    1430             :                                     int timeout,
    1431             :                                     bool use_id_mapping)
    1432             : {
    1433           0 :     struct sdap_ad_tokengroups_initgroups_state *state = NULL;
    1434           0 :     struct tevent_req *req = NULL;
    1435           0 :     struct tevent_req *subreq = NULL;
    1436             :     errno_t ret;
    1437             : 
    1438           0 :     req = tevent_req_create(mem_ctx, &state,
    1439             :                             struct sdap_ad_tokengroups_initgroups_state);
    1440           0 :     if (req == NULL) {
    1441           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
    1442           0 :         return NULL;
    1443             :     }
    1444             : 
    1445           0 :     state->use_id_mapping = use_id_mapping;
    1446           0 :     state->domain = domain;
    1447             : 
    1448             :     /* We can compute the gidNumber attribute from SIDs obtained from
    1449             :      * the tokenGroups lookup in case ID mapping is used for a user from the
    1450             :      * parent domain. For trusted domains, we need to know the group type
    1451             :      * to be able to filter out domain-local groups. Additionally, as a
    1452             :      * temporary workaround until https://fedorahosted.org/sssd/ticket/2656
    1453             :      * is fixed, we also fetch the group object if group members are ignored
    1454             :      * to avoid having to transfer and retain members when the fake
    1455             :      * tokengroups object without name is replaced by the full group object
    1456             :      */
    1457           0 :     if (state->use_id_mapping
    1458           0 :             && !IS_SUBDOMAIN(state->domain)
    1459           0 :             && state->domain->ignore_group_members == false) {
    1460           0 :         subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts,
    1461             :                                                          sysdb, domain, sh,
    1462             :                                                          name, orig_dn,
    1463             :                                                          timeout);
    1464             :     } else {
    1465           0 :         subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, conn,
    1466             :                                                        opts, sysdb, domain, sh,
    1467             :                                                        name, orig_dn,
    1468             :                                                        timeout);
    1469             :     }
    1470           0 :     if (subreq == NULL) {
    1471           0 :         ret = ENOMEM;
    1472           0 :         goto immediately;
    1473             :     }
    1474             : 
    1475           0 :     tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgroups_done, req);
    1476             : 
    1477           0 :     return req;
    1478             : 
    1479             : immediately:
    1480           0 :     if (ret == EOK) {
    1481           0 :         tevent_req_done(req);
    1482             :     } else {
    1483           0 :         tevent_req_error(req, ret);
    1484             :     }
    1485           0 :     tevent_req_post(req, ev);
    1486             : 
    1487           0 :     return req;
    1488             : }
    1489             : 
    1490           0 : static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq)
    1491             : {
    1492           0 :     struct sdap_ad_tokengroups_initgroups_state *state = NULL;
    1493           0 :     struct tevent_req *req = NULL;
    1494             :     errno_t ret;
    1495             : 
    1496           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
    1497           0 :     state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state);
    1498             : 
    1499           0 :     if (state->use_id_mapping
    1500           0 :             && !IS_SUBDOMAIN(state->domain)
    1501           0 :             && state->domain->ignore_group_members == false) {
    1502           0 :         ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq);
    1503             :     } else {
    1504           0 :         ret = sdap_ad_tokengroups_initgr_posix_recv(subreq);
    1505             :     }
    1506           0 :     talloc_zfree(subreq);
    1507           0 :     if (ret != EOK) {
    1508           0 :         goto done;
    1509             :     }
    1510             : 
    1511             : done:
    1512           0 :     if (ret != EOK) {
    1513           0 :         tevent_req_error(req, ret);
    1514           0 :         return;
    1515             :     }
    1516             : 
    1517           0 :     tevent_req_done(req);
    1518             : }
    1519             : 
    1520           0 : errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req)
    1521             : {
    1522           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1523             : 
    1524           0 :     return EOK;
    1525             : }
    1526             : 
    1527           0 : static errno_t handle_missing_pvt(TALLOC_CTX *mem_ctx,
    1528             :                                   struct tevent_context *ev,
    1529             :                                   struct sdap_options *opts,
    1530             :                                   const char *orig_dn,
    1531             :                                   int timeout,
    1532             :                                   const char *username,
    1533             :                                   struct sdap_handle *sh,
    1534             :                                   struct tevent_req *req,
    1535             :                                   tevent_req_fn callback)
    1536             : {
    1537           0 :     struct tevent_req *subreq = NULL;
    1538             :     errno_t ret;
    1539             : 
    1540           0 :     if (sh != NULL) {
    1541             :         /*  plain LDAP provider already has a sdap_handle */
    1542           0 :         subreq = sdap_get_ad_tokengroups_send(mem_ctx, ev, opts, sh, username,
    1543             :                                               orig_dn, timeout);
    1544           0 :         if (subreq == NULL) {
    1545           0 :             ret = ENOMEM;
    1546           0 :             tevent_req_error(req, ret);
    1547           0 :             goto done;
    1548             :         }
    1549             : 
    1550           0 :         tevent_req_set_callback(subreq, callback, req);
    1551           0 :         ret = EOK;
    1552           0 :         goto done;
    1553             : 
    1554             :     } else {
    1555           0 :         ret = EINVAL;
    1556           0 :         goto done;
    1557             :     }
    1558             : 
    1559             : done:
    1560           0 :     return ret;
    1561             : }

Generated by: LCOV version 1.10