Blame SOURCES/0024-ad-refactor-tokengroups-initgroups.patch

2fc102
From 8b581624e18d6f232d3174ed112d032bb6deffba Mon Sep 17 00:00:00 2001
2fc102
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
2fc102
Date: Tue, 12 Nov 2013 13:52:40 +0100
2fc102
Subject: [PATCH 24/31] ad: refactor tokengroups initgroups
2fc102
2fc102
sdap_get_ad_tokengroups_initgroups is split into more parts so
2fc102
it can be reused later.
2fc102
---
2fc102
 src/providers/ldap/sdap_async.h               |  20 +-
2fc102
 src/providers/ldap/sdap_async_initgroups.c    |  16 +-
2fc102
 src/providers/ldap/sdap_async_initgroups_ad.c | 552 ++++++++++++++++----------
2fc102
 3 files changed, 357 insertions(+), 231 deletions(-)
2fc102
2fc102
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
2fc102
index dbf572cdc82b100ba9c26b4853f05db1ba5fa4ed..67623454e675f648259c089acca59258f386ecdb 100644
2fc102
--- a/src/providers/ldap/sdap_async.h
2fc102
+++ b/src/providers/ldap/sdap_async.h
2fc102
@@ -294,17 +294,17 @@ sdap_get_ad_match_rule_initgroups_recv(struct tevent_req *req);
2fc102
 
2fc102
 
2fc102
 struct tevent_req *
2fc102
-sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
2fc102
-                                        struct tevent_context *ev,
2fc102
-                                        struct sdap_options *opts,
2fc102
-                                        struct sysdb_ctx *sysdb,
2fc102
-                                        struct sss_domain_info *domain,
2fc102
-                                        struct sdap_handle *sh,
2fc102
-                                        const char *name,
2fc102
-                                        const char *orig_dn,
2fc102
-                                        int timeout);
2fc102
+sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
2fc102
+                                    struct tevent_context *ev,
2fc102
+                                    struct sdap_options *opts,
2fc102
+                                    struct sysdb_ctx *sysdb,
2fc102
+                                    struct sss_domain_info *domain,
2fc102
+                                    struct sdap_handle *sh,
2fc102
+                                    const char *name,
2fc102
+                                    const char *orig_dn,
2fc102
+                                    int timeout);
2fc102
 
2fc102
 errno_t
2fc102
-sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req);
2fc102
+sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req);
2fc102
 
2fc102
 #endif /* _SDAP_ASYNC_H_ */
2fc102
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
2fc102
index c16d484950e06c8474cc38db45b978b624473056..7d5cd2e7cbd86e2eb9774dfee1b8e31edec57b88 100644
2fc102
--- a/src/providers/ldap/sdap_async_initgroups.c
2fc102
+++ b/src/providers/ldap/sdap_async_initgroups.c
2fc102
@@ -2857,13 +2857,13 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
2fc102
             /* Take advantage of AD's tokenGroups mechanism to look up all
2fc102
              * parent groups in a single request.
2fc102
              */
2fc102
-            subreq = sdap_get_ad_tokengroups_initgroups_send(state, state->ev,
2fc102
-                                                             state->opts,
2fc102
-                                                             state->sysdb,
2fc102
-                                                             state->dom,
2fc102
-                                                             state->sh,
2fc102
-                                                             cname, orig_dn,
2fc102
-                                                             state->timeout);
2fc102
+            subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev,
2fc102
+                                                         state->opts,
2fc102
+                                                         state->sysdb,
2fc102
+                                                         state->dom,
2fc102
+                                                         state->sh,
2fc102
+                                                         cname, orig_dn,
2fc102
+                                                         state->timeout);
2fc102
         } else if (state->opts->support_matching_rule
2fc102
                     && dp_opt_get_bool(state->opts->basic,
2fc102
                                        SDAP_AD_MATCHING_RULE_INITGROUPS)) {
2fc102
@@ -2952,7 +2952,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
2fc102
     case SDAP_SCHEMA_AD:
2fc102
         if (state->use_id_mapping
2fc102
                 && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
2fc102
-            ret = sdap_get_ad_tokengroups_initgroups_recv(subreq);
2fc102
+            ret = sdap_ad_tokengroups_initgroups_recv(subreq);
2fc102
         }
2fc102
         else if (state->opts->support_matching_rule
2fc102
                 && dp_opt_get_bool(state->opts->basic,
2fc102
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
2fc102
index e58d93fb2da36febd6074381882192ba9e204e86..7ba155338a358681c1bd201bee1c75f67afb4650 100644
2fc102
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
2fc102
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
2fc102
@@ -298,96 +298,87 @@ sdap_get_ad_match_rule_initgroups_recv(struct tevent_req *req)
2fc102
     return EOK;
2fc102
 }
2fc102
 
2fc102
-struct sdap_ad_tokengroups_initgr_state {
2fc102
+struct sdap_get_ad_tokengroups_state {
2fc102
     struct tevent_context *ev;
2fc102
-    struct sdap_options *opts;
2fc102
-    struct sysdb_ctx *sysdb;
2fc102
-    struct sss_domain_info *domain;
2fc102
-    struct sdap_handle *sh;
2fc102
+    struct sss_idmap_ctx *idmap_ctx;
2fc102
     const char *username;
2fc102
+
2fc102
+    char **sids;
2fc102
+    size_t num_sids;
2fc102
 };
2fc102
 
2fc102
-static void
2fc102
-sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *req);
2fc102
+static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq);
2fc102
 
2fc102
-struct tevent_req *
2fc102
-sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
2fc102
-                                        struct tevent_context *ev,
2fc102
-                                        struct sdap_options *opts,
2fc102
-                                        struct sysdb_ctx *sysdb,
2fc102
-                                        struct sss_domain_info *domain,
2fc102
-                                        struct sdap_handle *sh,
2fc102
-                                        const char *name,
2fc102
-                                        const char *orig_dn,
2fc102
-                                        int timeout)
2fc102
+static struct tevent_req *
2fc102
+sdap_get_ad_tokengroups_send(TALLOC_CTX *mem_ctx,
2fc102
+                             struct tevent_context *ev,
2fc102
+                             struct sdap_options *opts,
2fc102
+                             struct sdap_handle *sh,
2fc102
+                             const char *name,
2fc102
+                             const char *orig_dn,
2fc102
+                             int timeout)
2fc102
 {
2fc102
-    struct tevent_req *req;
2fc102
-    struct tevent_req *subreq;
2fc102
-    struct sdap_ad_tokengroups_initgr_state *state;
2fc102
+    struct sdap_get_ad_tokengroups_state *state = NULL;
2fc102
+    struct tevent_req *req = NULL;
2fc102
+    struct tevent_req *subreq = NULL;
2fc102
     const char *attrs[] = {AD_TOKENGROUPS_ATTR, NULL};
2fc102
+    errno_t ret;
2fc102
 
2fc102
     req = tevent_req_create(mem_ctx, &state,
2fc102
-                            struct sdap_ad_tokengroups_initgr_state);
2fc102
-    if (!req) return NULL;
2fc102
+                            struct sdap_get_ad_tokengroups_state);
2fc102
+    if (req == NULL) {
2fc102
+        DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n"));
2fc102
+        return NULL;
2fc102
+    }
2fc102
 
2fc102
+    state->idmap_ctx = opts->idmap_ctx->map;
2fc102
     state->ev = ev;
2fc102
-    state->opts = opts;
2fc102
-    state->sysdb = sysdb;
2fc102
-    state->domain = domain;
2fc102
-    state->sh = sh;
2fc102
-    state->username = name;
2fc102
+    state->username = talloc_strdup(state, name);
2fc102
+    if (state->username == NULL) {
2fc102
+        ret = ENOMEM;
2fc102
+        goto immediately;
2fc102
+    }
2fc102
+
2fc102
+    subreq = sdap_get_generic_send(state, state->ev, opts, sh, orig_dn,
2fc102
+                                   LDAP_SCOPE_BASE, NULL, attrs,
2fc102
+                                   NULL, 0, timeout, false);
2fc102
+    if (subreq == NULL) {
2fc102
+        ret = ENOMEM;
2fc102
+        goto immediately;
2fc102
+    }
2fc102
+
2fc102
+    tevent_req_set_callback(subreq, sdap_get_ad_tokengroups_done, req);
2fc102
+
2fc102
+    return req;
2fc102
 
2fc102
-    subreq = sdap_get_generic_send(
2fc102
-            state, state->ev, state->opts, state->sh,
2fc102
-            orig_dn, LDAP_SCOPE_BASE, NULL, attrs,
2fc102
-            NULL, 0, timeout, false);
2fc102
-    if (!subreq) {
2fc102
-        tevent_req_error(req, ENOMEM);
2fc102
-        tevent_req_post(req, ev);
2fc102
-        return req;
2fc102
+immediately:
2fc102
+    if (ret == EOK) {
2fc102
+        tevent_req_done(req);
2fc102
+    } else {
2fc102
+        tevent_req_error(req, ret);
2fc102
     }
2fc102
+    tevent_req_post(req, ev);
2fc102
 
2fc102
-    tevent_req_set_callback(subreq,
2fc102
-                            sdap_get_ad_tokengroups_initgroups_lookup_done,
2fc102
-                            req);
2fc102
     return req;
2fc102
 }
2fc102
 
2fc102
-static void
2fc102
-sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq)
2fc102
+static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq)
2fc102
 {
2fc102
-    errno_t ret, sret;
2fc102
+    TALLOC_CTX *tmp_ctx = NULL;
2fc102
+    struct sdap_get_ad_tokengroups_state *state = NULL;
2fc102
+    struct tevent_req *req = NULL;
2fc102
+    struct sysdb_attrs **users = NULL;
2fc102
+    struct ldb_message_element *el = NULL;
2fc102
     enum idmap_error_code err;
2fc102
-    size_t user_count, group_count, i;
2fc102
-    TALLOC_CTX *tmp_ctx;
2fc102
-    bool in_transaction = false;
2fc102
     char *sid_str = NULL;
2fc102
-    gid_t gid;
2fc102
-    time_t now;
2fc102
-    struct sss_domain_info *group_domain;
2fc102
-    struct sysdb_attrs **users;
2fc102
-    struct ldb_message_element *el;
2fc102
-    struct ldb_message *msg;
2fc102
-    struct ldb_dn *group_ldb_dn;
2fc102
-    const char *group_str_dn;
2fc102
-    char **ldap_grouplist;
2fc102
-    char **sysdb_grouplist;
2fc102
-    char **add_groups;
2fc102
-    char **del_groups;
2fc102
-    const char *attrs[] = { SYSDB_NAME, NULL };
2fc102
-    const char *group_name;
2fc102
-    struct tevent_req *req =
2fc102
-            tevent_req_callback_data(subreq, struct tevent_req);
2fc102
-    struct sdap_ad_tokengroups_initgr_state *state =
2fc102
-            tevent_req_data(req, struct sdap_ad_tokengroups_initgr_state);
2fc102
+    size_t num_users;
2fc102
+    size_t i;
2fc102
+    errno_t ret;
2fc102
 
2fc102
-    tmp_ctx = talloc_new(NULL);
2fc102
-    if (!tmp_ctx) {
2fc102
-        ret = ENOMEM;
2fc102
-        goto done;
2fc102
-    }
2fc102
+    req = tevent_req_callback_data(subreq, struct tevent_req);
2fc102
+    state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state);
2fc102
 
2fc102
-    ret = sdap_get_generic_recv(subreq, tmp_ctx, &user_count, &users);
2fc102
+    ret = sdap_get_generic_recv(subreq, tmp_ctx, &num_users, &users);
2fc102
     talloc_zfree(subreq);
2fc102
     if (ret != EOK) {
2fc102
         DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
@@ -395,226 +386,361 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq)
2fc102
         goto done;
2fc102
     }
2fc102
 
2fc102
-    if (user_count != 1) {
2fc102
+    if (num_users != 1) {
2fc102
         DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
               ("More than one result on a base search!\n"));
2fc102
         ret = EINVAL;
2fc102
         goto done;
2fc102
     }
2fc102
 
2fc102
-    /* Get the list of group SIDs */
2fc102
-    ret = sysdb_attrs_get_el_ext(users[0], AD_TOKENGROUPS_ATTR,
2fc102
-                                 false, &el);
2fc102
-    if (ret != EOK) {
2fc102
-        if (ret == ENOENT) {
2fc102
-            DEBUG(SSSDBG_TRACE_LIBS,
2fc102
-                  ("No tokenGroups entries for [%s]\n",
2fc102
-                   state->username));
2fc102
-            /* No groups in LDAP. We need to ensure that the
2fc102
-             * sysdb matches.
2fc102
-             */
2fc102
-            el = talloc_zero(tmp_ctx, struct ldb_message_element);
2fc102
-            if (!el) {
2fc102
-                ret = ENOMEM;
2fc102
-                goto done;
2fc102
-            }
2fc102
-            el->num_values = 0;
2fc102
+    /* get the list of sids from tokengroups */
2fc102
+    ret = sysdb_attrs_get_el_ext(users[0], AD_TOKENGROUPS_ATTR, false, &el);
2fc102
+    if (ret == ENOENT) {
2fc102
+        DEBUG(SSSDBG_TRACE_LIBS, ("No tokenGroups entries for [%s]\n",
2fc102
+                                  state->username));
2fc102
 
2fc102
-            /* This will skip the group-processing loop below
2fc102
-             * and proceed to removing any sysdb groups.
2fc102
-             */
2fc102
-        } else {
2fc102
-            DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
-                  ("Could not read tokenGroups attribute: [%s]\n",
2fc102
-                   strerror(ret)));
2fc102
-            goto done;
2fc102
-        }
2fc102
+        state->sids = NULL;
2fc102
+        state->num_sids = 0;
2fc102
+        ret = EOK;
2fc102
+        goto done;
2fc102
+    } else if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Could not read tokenGroups attribute: "
2fc102
+                                     "[%s]\n", strerror(ret)));
2fc102
+        goto done;
2fc102
     }
2fc102
 
2fc102
-    /* Process the groups */
2fc102
-    now = time(NULL);
2fc102
-
2fc102
-    ret = sysdb_transaction_start(state->sysdb);
2fc102
-    if (ret != EOK) goto done;
2fc102
-    in_transaction = true;
2fc102
-
2fc102
-    ldap_grouplist = talloc_array(tmp_ctx, char *, el->num_values + 1);
2fc102
-    if (!ldap_grouplist) {
2fc102
+    state->num_sids = 0;
2fc102
+    state->sids = talloc_zero_array(state, char*, el->num_values);
2fc102
+    if (state->sids == NULL) {
2fc102
         ret = ENOMEM;
2fc102
         goto done;
2fc102
     }
2fc102
-    group_count = 0;
2fc102
 
2fc102
+    /* convert binary sid to string */
2fc102
     for (i = 0; i < el->num_values; i++) {
2fc102
-        /* Get the SID and convert it to a GID */
2fc102
-
2fc102
-        err = sss_idmap_bin_sid_to_sid(state->opts->idmap_ctx->map,
2fc102
-                                        el->values[i].data,
2fc102
-                                        el->values[i].length,
2fc102
-                                        &sid_str);
2fc102
+        err = sss_idmap_bin_sid_to_sid(state->idmap_ctx, el->values[i].data,
2fc102
+                                       el->values[i].length, &sid_str);
2fc102
         if (err != IDMAP_SUCCESS) {
2fc102
             DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
                   ("Could not convert binary SID to string: [%s]. Skipping\n",
2fc102
                    idmap_error_string(err)));
2fc102
             continue;
2fc102
         }
2fc102
-        DEBUG(SSSDBG_TRACE_LIBS,
2fc102
-              ("Processing membership SID [%s]\n",
2fc102
-               sid_str));
2fc102
-        ret = sdap_idmap_sid_to_unix(state->opts->idmap_ctx, sid_str,
2fc102
-                                     &gid;;
2fc102
+
2fc102
+        state->sids[i] = talloc_move(state->sids, &sid_str);
2fc102
+        state->num_sids++;
2fc102
+    }
2fc102
+
2fc102
+    /* shrink array to final number of elements */
2fc102
+    state->sids = talloc_realloc(state, state->sids, char*, state->num_sids);
2fc102
+    if (state->sids == NULL) {
2fc102
+        ret = ENOMEM;
2fc102
+        goto done;
2fc102
+    }
2fc102
+
2fc102
+    ret = EOK;
2fc102
+
2fc102
+done:
2fc102
+    talloc_free(tmp_ctx);
2fc102
+
2fc102
+    if (ret != EOK) {
2fc102
+        tevent_req_error(req, ret);
2fc102
+        return;
2fc102
+    }
2fc102
+
2fc102
+    tevent_req_done(req);
2fc102
+}
2fc102
+
2fc102
+static errno_t sdap_get_ad_tokengroups_recv(TALLOC_CTX *mem_ctx,
2fc102
+                                            struct tevent_req *req,
2fc102
+                                            size_t *_num_sids,
2fc102
+                                            char ***_sids)
2fc102
+{
2fc102
+    struct sdap_get_ad_tokengroups_state *state = NULL;
2fc102
+    state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state);
2fc102
+
2fc102
+    TEVENT_REQ_RETURN_ON_ERROR(req);
2fc102
+
2fc102
+    if (_num_sids != NULL) {
2fc102
+        *_num_sids = state->num_sids;
2fc102
+    }
2fc102
+
2fc102
+    if (_sids != NULL) {
2fc102
+        *_sids = talloc_steal(mem_ctx, state->sids);
2fc102
+    }
2fc102
+
2fc102
+    return EOK;
2fc102
+}
2fc102
+
2fc102
+static errno_t
2fc102
+sdap_ad_tokengroups_update_members(TALLOC_CTX *mem_ctx,
2fc102
+                                   const char *username,
2fc102
+                                   struct sysdb_ctx *sysdb,
2fc102
+                                   struct sss_domain_info *domain,
2fc102
+                                   char **ldap_groups)
2fc102
+{
2fc102
+    TALLOC_CTX *tmp_ctx = NULL;
2fc102
+    char **sysdb_groups = NULL;
2fc102
+    char **add_groups = NULL;
2fc102
+    char **del_groups = NULL;
2fc102
+    errno_t ret;
2fc102
+
2fc102
+    tmp_ctx = talloc_new(NULL);
2fc102
+    if (tmp_ctx == NULL) {
2fc102
+        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
2fc102
+        return ENOMEM;
2fc102
+    }
2fc102
+
2fc102
+    /* Get the current sysdb group list for this user so we can update it. */
2fc102
+    ret = get_sysdb_grouplist_dn(tmp_ctx, sysdb, domain,
2fc102
+                                 username, &sysdb_groups);
2fc102
+    if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Could not get the list of groups for "
2fc102
+              "[%s] in the sysdb: [%s]\n", username, strerror(ret)));
2fc102
+        goto done;
2fc102
+    }
2fc102
+
2fc102
+    /* Find the differences between the sysdb and LDAP lists.
2fc102
+     * Groups in the sysdb only must be removed. */
2fc102
+    ret = diff_string_lists(tmp_ctx, ldap_groups, sysdb_groups,
2fc102
+                            &add_groups, &del_groups, NULL);
2fc102
+    if (ret != EOK) {
2fc102
+        goto done;
2fc102
+    }
2fc102
+
2fc102
+    DEBUG(SSSDBG_TRACE_LIBS, ("Updating memberships for [%s]\n", username));
2fc102
+
2fc102
+    ret = sysdb_update_members_dn(domain->sysdb, domain, username,
2fc102
+                                  SYSDB_MEMBER_USER,
2fc102
+                                  (const char *const *) add_groups,
2fc102
+                                  (const char *const *) del_groups);
2fc102
+    if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Membership update failed [%d]: %s\n",
2fc102
+                                     ret, strerror(ret)));
2fc102
+        goto done;
2fc102
+    }
2fc102
+
2fc102
+done:
2fc102
+    talloc_free(tmp_ctx);
2fc102
+    return ret;
2fc102
+}
2fc102
+
2fc102
+struct sdap_ad_tokengroups_initgroups_state {
2fc102
+    struct sdap_idmap_ctx *idmap_ctx;
2fc102
+    struct sysdb_ctx *sysdb;
2fc102
+    struct sss_domain_info *domain;
2fc102
+    const char *username;
2fc102
+};
2fc102
+
2fc102
+static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq);
2fc102
+
2fc102
+struct tevent_req *
2fc102
+sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
2fc102
+                                    struct tevent_context *ev,
2fc102
+                                    struct sdap_options *opts,
2fc102
+                                    struct sysdb_ctx *sysdb,
2fc102
+                                    struct sss_domain_info *domain,
2fc102
+                                    struct sdap_handle *sh,
2fc102
+                                    const char *name,
2fc102
+                                    const char *orig_dn,
2fc102
+                                    int timeout)
2fc102
+{
2fc102
+    struct sdap_ad_tokengroups_initgroups_state *state = NULL;
2fc102
+    struct tevent_req *req = NULL;
2fc102
+    struct tevent_req *subreq = NULL;
2fc102
+    errno_t ret;
2fc102
+
2fc102
+    req = tevent_req_create(mem_ctx, &state,
2fc102
+                            struct sdap_ad_tokengroups_initgroups_state);
2fc102
+    if (req == NULL) {
2fc102
+        DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n"));
2fc102
+        return NULL;
2fc102
+    }
2fc102
+
2fc102
+    state->idmap_ctx = opts->idmap_ctx;
2fc102
+    state->sysdb = sysdb;
2fc102
+    state->domain = domain;
2fc102
+    state->username = talloc_strdup(state, name);
2fc102
+    if (state->username == NULL) {
2fc102
+        ret = ENOMEM;
2fc102
+        goto immediately;
2fc102
+    }
2fc102
+
2fc102
+    subreq = sdap_get_ad_tokengroups_send(state, ev, opts, sh, name, orig_dn,
2fc102
+                                          timeout);
2fc102
+    if (subreq == NULL) {
2fc102
+        ret = ENOMEM;
2fc102
+        goto immediately;
2fc102
+    }
2fc102
+
2fc102
+    tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgroups_done, req);
2fc102
+
2fc102
+    return req;
2fc102
+
2fc102
+immediately:
2fc102
+    if (ret == EOK) {
2fc102
+        tevent_req_done(req);
2fc102
+    } else {
2fc102
+        tevent_req_error(req, ret);
2fc102
+    }
2fc102
+    tevent_req_post(req, ev);
2fc102
+
2fc102
+    return req;
2fc102
+}
2fc102
+
2fc102
+static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq)
2fc102
+{
2fc102
+    TALLOC_CTX *tmp_ctx = NULL;
2fc102
+    struct sdap_ad_tokengroups_initgroups_state *state = NULL;
2fc102
+    struct tevent_req *req = NULL;
2fc102
+    struct sss_domain_info *domain = NULL;
2fc102
+    struct ldb_message *msg = NULL;
2fc102
+    const char *attrs[] = {SYSDB_NAME, NULL};
2fc102
+    const char *name = NULL;
2fc102
+    const char *sid = NULL;
2fc102
+    char **sids = NULL;
2fc102
+    size_t num_sids;
2fc102
+    size_t i;
2fc102
+    time_t now;
2fc102
+    gid_t gid;
2fc102
+    char **groups = NULL;
2fc102
+    size_t num_groups;
2fc102
+    errno_t ret, sret;
2fc102
+    bool in_transaction;
2fc102
+
2fc102
+    tmp_ctx = talloc_new(NULL);
2fc102
+    if (tmp_ctx == NULL) {
2fc102
+        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
2fc102
+        ret = ENOMEM;
2fc102
+        goto done;
2fc102
+    }
2fc102
+
2fc102
+    req = tevent_req_callback_data(subreq, struct tevent_req);
2fc102
+    state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state);
2fc102
+
2fc102
+    ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids);
2fc102
+    talloc_zfree(subreq);
2fc102
+    if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to acquire tokengroups [%d]: %s\n",
2fc102
+                                    ret, strerror(ret)));
2fc102
+        goto done;
2fc102
+    }
2fc102
+
2fc102
+    num_groups = 0;
2fc102
+    groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1);
2fc102
+    if (groups == NULL) {
2fc102
+        ret = ENOMEM;
2fc102
+        goto done;
2fc102
+    }
2fc102
+
2fc102
+    now = time(NULL);
2fc102
+    ret = sysdb_transaction_start(state->sysdb);
2fc102
+    if (ret != EOK) {
2fc102
+        goto done;
2fc102
+    }
2fc102
+    in_transaction = true;
2fc102
+
2fc102
+    for (i = 0; i < num_sids; i++) {
2fc102
+        sid = sids[i];
2fc102
+        DEBUG(SSSDBG_TRACE_LIBS, ("Processing membership SID [%s]\n", sid));
2fc102
+
2fc102
+        ret = sdap_idmap_sid_to_unix(state->idmap_ctx, sid, &gid;;
2fc102
         if (ret == ENOTSUP) {
2fc102
             DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n"));
2fc102
             ret = EOK;
2fc102
             continue;
2fc102
         } else if (ret != EOK) {
2fc102
-            DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
-                  ("Could not convert SID to GID: [%s]. Skipping\n",
2fc102
-                   strerror(ret)));
2fc102
+            DEBUG(SSSDBG_MINOR_FAILURE, ("Could not convert SID to GID: [%s]. "
2fc102
+                                         "Skipping\n", strerror(ret)));
2fc102
             continue;
2fc102
         }
2fc102
 
2fc102
-        group_domain = find_subdomain_by_sid(get_domains_head(state->domain),
2fc102
-                                                              sid_str);
2fc102
-        if (group_domain == NULL) {
2fc102
-            DEBUG(SSSDBG_MINOR_FAILURE, ("Domain not found for SID %s\n",
2fc102
-                                         sid_str));
2fc102
+        domain = find_subdomain_by_sid(get_domains_head(state->domain), sid);
2fc102
+        if (domain == NULL) {
2fc102
+            DEBUG(SSSDBG_MINOR_FAILURE, ("Domain not found for SID %s\n", sid));
2fc102
             continue;
2fc102
         }
2fc102
 
2fc102
-        DEBUG(SSSDBG_TRACE_LIBS,
2fc102
-              ("Processing membership GID [%"SPRIgid"]\n", gid));
2fc102
+        DEBUG(SSSDBG_TRACE_LIBS, ("SID [%s] maps to GID [%"SPRIgid"]\n",
2fc102
+                                  sid, gid));
2fc102
 
2fc102
         /* Check whether this GID already exists in the sysdb */
2fc102
-        ret = sysdb_search_group_by_gid(tmp_ctx, group_domain->sysdb,
2fc102
-                                        group_domain, gid, attrs, &msg;;
2fc102
+        ret = sysdb_search_group_by_gid(tmp_ctx, domain->sysdb, domain,
2fc102
+                                        gid, attrs, &msg;;
2fc102
         if (ret == EOK) {
2fc102
-            group_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
2fc102
-            if (!group_name) {
2fc102
+            name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
2fc102
+            if (name == NULL) {
2fc102
                 DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
                       ("Could not retrieve group name from sysdb\n"));
2fc102
                 ret = EINVAL;
2fc102
                 goto done;
2fc102
             }
2fc102
         } else if (ret == ENOENT) {
2fc102
-            /* This is a new group. For now, we will store it
2fc102
-             * under the name of its SID. When a direct lookup of
2fc102
-             * the group or its GID occurs, it will replace this
2fc102
-             * temporary entry.
2fc102
-             */
2fc102
-
2fc102
-            group_name = sid_str;
2fc102
-            ret = sysdb_add_incomplete_group(group_domain->sysdb,
2fc102
-                                             group_domain,
2fc102
-                                             group_name, gid,
2fc102
-                                             NULL, sid_str, false, now);
2fc102
+            /* This is a new group. For now, we will store it under the name
2fc102
+             * of its SID. When a direct lookup of the group or its GID occurs,
2fc102
+             * it will replace this temporary entry. */
2fc102
+            name = sid;
2fc102
+            ret = sysdb_add_incomplete_group(domain->sysdb, domain, name, gid,
2fc102
+                                             NULL, sid, false, now);
2fc102
             if (ret != EOK) {
2fc102
-                DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
-                      ("Could not create incomplete group: [%s]\n",
2fc102
-                       strerror(ret)));
2fc102
+                DEBUG(SSSDBG_MINOR_FAILURE, ("Could not create incomplete "
2fc102
+                                             "group: [%s]\n", strerror(ret)));
2fc102
                 goto done;
2fc102
             }
2fc102
         } else {
2fc102
             /* Unexpected error */
2fc102
-            DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
-                  ("Could not look up group in sysdb: [%s]\n",
2fc102
-                   strerror(ret)));
2fc102
+            DEBUG(SSSDBG_MINOR_FAILURE, ("Could not look up group in sysdb: "
2fc102
+                                         "[%s]\n", strerror(ret)));
2fc102
             goto done;
2fc102
         }
2fc102
 
2fc102
-        group_ldb_dn = sysdb_group_dn(group_domain->sysdb, tmp_ctx,
2fc102
-                                      group_domain, group_name);
2fc102
-        if (group_ldb_dn == NULL) {
2fc102
-            DEBUG(SSSDBG_CRIT_FAILURE, ("sysdb_group_dn() failed\n"));
2fc102
+        groups[num_groups] = sysdb_group_strdn(tmp_ctx, domain->name, name);
2fc102
+        if (groups[num_groups] == NULL) {
2fc102
             ret = ENOMEM;
2fc102
             goto done;
2fc102
         }
2fc102
-
2fc102
-        group_str_dn = ldb_dn_get_linearized(group_ldb_dn);
2fc102
-        if (group_str_dn == NULL) {
2fc102
-            DEBUG(SSSDBG_CRIT_FAILURE, ("ldb_dn_get_linearized() failed\n"));
2fc102
-            ret = EINVAL;
2fc102
-            goto done;
2fc102
-        }
2fc102
-
2fc102
-        ldap_grouplist[group_count] =
2fc102
-                talloc_strdup(ldap_grouplist, group_str_dn);
2fc102
-        if (!ldap_grouplist[group_count]) {
2fc102
-            ret = ENOMEM;
2fc102
-            goto done;
2fc102
-        }
2fc102
-
2fc102
-        talloc_zfree(group_ldb_dn); /* also frees group_str_dn */
2fc102
-        group_str_dn = NULL;
2fc102
-
2fc102
-        group_count++;
2fc102
-    }
2fc102
-    ldap_grouplist[group_count] = NULL;
2fc102
-
2fc102
-    /* Get the current sysdb group list for this user
2fc102
-     * so we can update it.
2fc102
-     */
2fc102
-    ret = get_sysdb_grouplist_dn(state, state->sysdb, state->domain,
2fc102
-                                 state->username, &sysdb_grouplist);
2fc102
-    if (ret != EOK) {
2fc102
-        DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
-              ("Could not get the list of groups for [%s] in the sysdb: "
2fc102
-               "[%s]\n",
2fc102
-               state->username, strerror(ret)));
2fc102
-        goto done;
2fc102
+        num_groups++;
2fc102
     }
2fc102
 
2fc102
-    /* Find the differences between the sysdb and LDAP lists
2fc102
-     * Groups in the sysdb only must be removed.
2fc102
-     */
2fc102
-    ret = diff_string_lists(tmp_ctx, ldap_grouplist, sysdb_grouplist,
2fc102
-                            &add_groups, &del_groups, NULL);
2fc102
-    if (ret != EOK) goto done;
2fc102
+    groups[num_groups] = NULL;
2fc102
 
2fc102
-    DEBUG(SSSDBG_TRACE_LIBS,
2fc102
-          ("Updating memberships for [%s]\n", state->username));
2fc102
-    ret = sysdb_update_members_dn(state->sysdb, state->domain,
2fc102
-                                  state->username, SYSDB_MEMBER_USER,
2fc102
-                                  (const char *const *) add_groups,
2fc102
-                                  (const char *const *) del_groups);
2fc102
+    ret = sdap_ad_tokengroups_update_members(state, state->username,
2fc102
+                                             state->sysdb, state->domain,
2fc102
+                                             groups);
2fc102
     if (ret != EOK) {
2fc102
-        DEBUG(SSSDBG_MINOR_FAILURE,
2fc102
-              ("Membership update failed [%d]: %s\n",
2fc102
-               ret, strerror(ret)));
2fc102
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Membership update failed [%d]: %s\n",
2fc102
+                                     ret, strerror(ret)));
2fc102
         goto done;
2fc102
     }
2fc102
 
2fc102
     ret = sysdb_transaction_commit(state->sysdb);
2fc102
     if (ret != EOK) {
2fc102
-        DEBUG(SSSDBG_CRIT_FAILURE,
2fc102
-              ("Could not commit transaction! [%s]\n",
2fc102
-               strerror(ret)));
2fc102
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Could not commit transaction! [%s]\n",
2fc102
+                                    strerror(ret)));
2fc102
         goto done;
2fc102
     }
2fc102
     in_transaction = false;
2fc102
 
2fc102
 done:
2fc102
-    sss_idmap_free_sid(state->opts->idmap_ctx->map, sid_str);
2fc102
+    talloc_free(tmp_ctx);
2fc102
 
2fc102
     if (in_transaction) {
2fc102
         sret = sysdb_transaction_cancel(state->sysdb);
2fc102
-        DEBUG(SSSDBG_FATAL_FAILURE,
2fc102
-              ("Could not cancel transaction! [%s]\n",
2fc102
-               strerror(sret)));
2fc102
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Could not cancel transaction! [%s]\n",
2fc102
+                                     strerror(sret)));
2fc102
     }
2fc102
 
2fc102
-    if (ret == EOK) {
2fc102
-        tevent_req_done(req);
2fc102
-    } else {
2fc102
+    if (ret != EOK) {
2fc102
         tevent_req_error(req, ret);
2fc102
+        return;
2fc102
     }
2fc102
-    talloc_free(tmp_ctx);
2fc102
-    return;
2fc102
+
2fc102
+    tevent_req_done(req);
2fc102
 }
2fc102
 
2fc102
-errno_t
2fc102
-sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req)
2fc102
+errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req)
2fc102
 {
2fc102
     TEVENT_REQ_RETURN_ON_ERROR(req);
2fc102
+
2fc102
     return EOK;
2fc102
 }
2fc102
-- 
2fc102
1.8.4.2
2fc102