New patches are attached.

[PATCH 1/3] LDAP: Make sdap_add_incomplete_groups public

The function is needed for latter patch, when groups are added from ad initgroups module.

[PATCH 2/3] AD: Enable TokenGroups initgroups lookup

Prepares the list of SIDs that are not in cache and updates members of groups which are found

[PATCH 3/3] AD: Add lookup for SIDs not found in cache during
 TokenGroups

Performs LDAPsearch with list of tokengroups SIDs that are missing from sysdb and stores them.


Ondra
--
Ondrej Kos
Associate Software Engineer
Identity Management - SSSD
Red Hat Czech
From ddb9f88dd70f8e500a065782ea6ce7686b797a9d Mon Sep 17 00:00:00 2001
From: Ondrej Kos <[email protected]>
Date: Wed, 11 Sep 2013 17:35:51 +0200
Subject: [PATCH 1/3] LDAP: Make sdap_add_incomplete_groups public

Needed for tokengroups sid lookup
---
 src/providers/ldap/sdap_async.h            | 6 ++++++
 src/providers/ldap/sdap_async_initgroups.c | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index c8031c9a9d527a6d808f1ddce096de23850ebfd6..af41c719e40c263feeadaaf0f8919a61decbf852 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -291,4 +291,10 @@ sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
 errno_t
 sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req);
 
+errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
+                                   struct sss_domain_info *domain,
+                                   struct sdap_options *opts,
+                                   char **groupnames,
+                                   struct sysdb_attrs **ldap_groups,
+                                   int ldap_groups_count);
 #endif /* _SDAP_ASYNC_H_ */
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index aa0ea4c1b28fa2a69390605d3fff3cfff1642aa1..c27d587d15c6bdffd8fe168d96753793753165f6 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -29,7 +29,7 @@
 #include "providers/ldap/sdap_users.h"
 
 /* ==Save-fake-group-list=====================================*/
-static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
+errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
                                           struct sss_domain_info *domain,
                                           struct sdap_options *opts,
                                           char **groupnames,
-- 
1.8.1.4

From f40bbaa3a21b4a9b8607f25eb831276cf16543b8 Mon Sep 17 00:00:00 2001
From: Ondrej Kos <[email protected]>
Date: Tue, 3 Sep 2013 12:27:17 +0200
Subject: [PATCH 2/3] AD: Enable TokenGroups initgroups lookup

Process the group SIDs that are in sysdb. Update members of those and
those, which arent in db, are passed back as list of SIDs.

Resolves:
https://fedorahosted.org/sssd/ticket/1568
---
 src/providers/ldap/sdap_async.h               |   7 +-
 src/providers/ldap/sdap_async_initgroups.c    |  46 +++++----
 src/providers/ldap/sdap_async_initgroups_ad.c | 136 +++++++++++++++++++-------
 3 files changed, 133 insertions(+), 56 deletions(-)

diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index af41c719e40c263feeadaaf0f8919a61decbf852..0c682992a4037c30a347a19f06529d1920d2c099 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -286,10 +286,13 @@ sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
                                         struct sdap_handle *sh,
                                         const char *name,
                                         const char *orig_dn,
-                                        int timeout);
+                                        int timeout,
+                                        bool use_id_mapping);
 
 errno_t
-sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req);
+sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req,
+                                        bool *_lookup_sids,
+                                        const char ***_group_sid_list);
 
 errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
                                    struct sss_domain_info *domain,
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index c27d587d15c6bdffd8fe168d96753793753165f6..31c33e785cd408bbc737c16433b97df9a84185ab 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2547,6 +2547,7 @@ struct sdap_get_initgr_state {
     struct sdap_id_ctx *id_ctx;
     struct sdap_id_conn_ctx *conn;
     const char *name;
+    const char *cname;
     const char **grp_attrs;
     const char **user_attrs;
     const char *user_base_filter;
@@ -2594,6 +2595,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
     state->name = name;
     state->grp_attrs = grp_attrs;
     state->orig_user = NULL;
+    state->cname = NULL;
     state->timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT);
     state->user_base_iter = 0;
     state->user_search_bases = sdom->user_search_bases;
@@ -2688,7 +2690,6 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
     int ret;
     errno_t sret;
     const char *orig_dn;
-    const char *cname;
     bool in_transaction = false;
 
     DEBUG(9, ("Receiving info for the user\n"));
@@ -2761,7 +2762,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
     in_transaction = false;
 
     ret = sysdb_get_real_name(state, state->sysdb,
-                              state->dom, state->name, &cname);
+                              state->dom, state->name, &state->cname);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, ("Cannot canonicalize username\n"));
         tevent_req_error(req, ret);
@@ -2774,7 +2775,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
     case SDAP_SCHEMA_RFC2307:
         subreq = sdap_initgr_rfc2307_send(state, state->ev, state->opts,
                                           state->sysdb, state->dom, state->sh,
-                                          cname);
+                                          state->cname);
         if (!subreq) {
             tevent_req_error(req, ENOMEM);
             return;
@@ -2792,8 +2793,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
             return;
         }
 
-        if (state->use_id_mapping
-                && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
+        if (state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
             /* Take advantage of AD's tokenGroups mechanism to look up all
              * parent groups in a single request.
              */
@@ -2802,8 +2802,10 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
                                                              state->sysdb,
                                                              state->dom,
                                                              state->sh,
-                                                             cname, orig_dn,
-                                                             state->timeout);
+                                                             state->cname,
+                                                             orig_dn,
+                                                             state->timeout,
+                                                             state->use_id_mapping);
         } else if (state->opts->support_matching_rule
                     && dp_opt_get_bool(state->opts->basic,
                                        SDAP_AD_MATCHING_RULE_INITGROUPS)) {
@@ -2815,13 +2817,17 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
                                                             state->sysdb,
                                                             state->dom,
                                                             state->sh,
-                                                            cname, orig_dn,
+                                                            state->cname,
+                                                            orig_dn,
                                                             state->timeout);
         } else {
-            subreq = sdap_initgr_rfc2307bis_send(
-                    state, state->ev, state->opts, state->sysdb,
-                    state->dom, state->sh,
-                    cname, orig_dn);
+            subreq = sdap_initgr_rfc2307bis_send(state, state->ev,
+                                                 state->opts,
+                                                 state->sysdb,
+                                                 state->dom,
+                                                 state->sh,
+                                                 state->cname,
+                                                 orig_dn);
         }
         if (!subreq) {
             tevent_req_error(req, ENOMEM);
@@ -2874,8 +2880,8 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
     char *dom_sid_str;
     char *group_sid_str;
     struct sdap_options *opts = state->opts;
-
-    DEBUG(9, ("Initgroups done\n"));
+    const char **group_sid_list;
+    bool lookup_sids = false;
 
     tmp_ctx = talloc_new(NULL);
     if (!tmp_ctx) {
@@ -2890,9 +2896,8 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
 
     case SDAP_SCHEMA_RFC2307BIS:
     case SDAP_SCHEMA_AD:
-        if (state->use_id_mapping
-                && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
-            ret = sdap_get_ad_tokengroups_initgroups_recv(subreq);
+        if (state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
+            ret = sdap_get_ad_tokengroups_initgroups_recv(subreq, &lookup_sids, &group_sid_list);
         }
         else if (state->opts->support_matching_rule
                 && dp_opt_get_bool(state->opts->basic,
@@ -2913,6 +2918,13 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
         break;
     }
 
+    if (lookup_sids) {
+        DEBUG(SSSDBG_TRACE_FUNC, ("Some of users TokenGroups not found in "
+                                  "cache, will perform LDAP lookup.\n"));
+    }
+
+    DEBUG(9, ("Initgroups done\n"));
+
     talloc_zfree(subreq);
     if (ret) {
         DEBUG(9, ("Error in initgroups: [%d][%s]\n",
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
index e5649a2b9793253a55c48fba69cd3a902c0dc967..723b009c223118160e310e6a5efd5c4d12a85883 100644
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
@@ -305,6 +305,9 @@ struct sdap_ad_tokengroups_initgr_state {
     struct sss_domain_info *domain;
     struct sdap_handle *sh;
     const char *username;
+    bool use_id_mapping;
+    bool lookup_sids;
+    const char **group_sid_list;
 };
 
 static void
@@ -319,7 +322,8 @@ sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
                                         struct sdap_handle *sh,
                                         const char *name,
                                         const char *orig_dn,
-                                        int timeout)
+                                        int timeout,
+                                        bool use_id_mapping)
 {
     struct tevent_req *req;
     struct tevent_req *subreq;
@@ -336,6 +340,9 @@ sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
     state->domain = domain;
     state->sh = sh;
     state->username = name;
+    state->use_id_mapping = use_id_mapping;
+    state->lookup_sids = false;
+    state->group_sid_list = NULL;
 
     subreq = sdap_get_generic_send(
             state, state->ev, state->opts, state->sh,
@@ -359,6 +366,7 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq)
     errno_t ret, sret;
     enum idmap_error_code err;
     size_t user_count, group_count, i;
+    size_t sid_count = 0;
     TALLOC_CTX *tmp_ctx;
     bool in_transaction = false;
     char *sid_str;
@@ -442,6 +450,14 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq)
     }
     group_count = 0;
 
+    if (!state->use_id_mapping) {
+        state->group_sid_list = talloc_array(state, const char*, el->num_values + 1);
+        if (!state->group_sid_list) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
     for (i = 0; i < el->num_values; i++) {
         /* Get the SID and convert it to a GID */
 
@@ -464,20 +480,29 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq)
             DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n"));
             ret = EOK;
             continue;
-        } else if (ret != EOK) {
-            DEBUG(SSSDBG_MINOR_FAILURE,
-                  ("Could not convert SID to GID: [%s]. Skipping\n",
-                   strerror(ret)));
-            continue;
         }
 
-        DEBUG(SSSDBG_TRACE_LIBS,
-              ("Processing membership GID [%lu]\n",
-               gid));
+        if (state->use_id_mapping) {
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      ("Could not convert SID to GID: [%s]. Skipping\n",
+                       strerror(ret)));
+                continue;
+            }
+
+            DEBUG(SSSDBG_TRACE_LIBS,
+                  ("Processing membership GID [%lu]\n",
+                   gid));
+
+            /* Check whether this GID already exists in the sysdb */
+            ret = sysdb_search_group_by_gid(tmp_ctx, state->sysdb, state->domain,
+                                            gid, attrs, &msg);
+        } else {
+            ret = sysdb_search_group_by_sid_str(tmp_ctx, state->sysdb,
+                                                state->domain, sid_str, attrs,
+                                                &msg);
+        }
 
-        /* Check whether this GID already exists in the sysdb */
-        ret = sysdb_search_group_by_gid(tmp_ctx, state->sysdb, state->domain,
-                                        gid, attrs, &msg);
         if (ret == EOK) {
             group_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
             if (!group_name) {
@@ -486,22 +511,58 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq)
                 ret = EINVAL;
                 goto done;
             }
+
+            ldap_grouplist[group_count] =
+                    talloc_strdup(ldap_grouplist, group_name);
+            if (!ldap_grouplist[group_count]) {
+                ret = ENOMEM;
+                goto done;
+            }
+
+            group_count++;
+
         } else if (ret == ENOENT) {
-            /* This is a new group. For now, we will store it
-             * under the name of its SID. When a direct lookup of
-             * the group or its GID occurs, it will replace this
-             * temporary entry.
-             */
-            group_name = sid_str;
-            ret = sysdb_add_incomplete_group(state->sysdb,
-                                             state->domain,
-                                             group_name, gid,
-                                             NULL, sid_str, false, now);
-            if (ret != EOK) {
-                DEBUG(SSSDBG_MINOR_FAILURE,
-                      ("Could not create incomplete group: [%s]\n",
-                       strerror(ret)));
-                goto done;
+            if (state->use_id_mapping) {
+                /* This is a new group. For now, we will store it
+                 * under the name of its SID. When a direct lookup of
+                 * the group or its GID occurs, it will replace this
+                 * temporary entry.
+                 */
+                group_name = sid_str;
+                ret = sysdb_add_incomplete_group(state->sysdb,
+                                                 state->domain,
+                                                 group_name, gid,
+                                                 NULL, sid_str, false, now);
+                if (ret != EOK) {
+                    DEBUG(SSSDBG_MINOR_FAILURE,
+                          ("Could not create incomplete group: [%s]\n",
+                           strerror(ret)));
+                    goto done;
+                }
+
+                ldap_grouplist[group_count] =
+                        talloc_strdup(ldap_grouplist, group_name);
+                if (!ldap_grouplist[group_count]) {
+                    ret = ENOMEM;
+                    goto done;
+                }
+
+                group_count++;
+
+            } else {
+                DEBUG(SSSDBG_MINOR_FAILURE, ("SID [%s] not found in cache, "
+                                             "will be looked up\n", sid_str));
+
+                state->lookup_sids = true;
+
+                state->group_sid_list[sid_count] =
+                        talloc_strdup(state, sid_str);
+                if (!state->group_sid_list[sid_count]) {
+                    ret = ENOMEM;
+                    goto done;
+                }
+
+                sid_count++;
             }
         } else {
             /* Unexpected error */
@@ -510,17 +571,9 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq)
                    strerror(ret)));
             goto done;
         }
-
-        ldap_grouplist[group_count] =
-                talloc_strdup(ldap_grouplist, group_name);
-        if (!ldap_grouplist[group_count]) {
-            ret = ENOMEM;
-            goto done;
-        }
-
-        group_count++;
     }
     ldap_grouplist[group_count] = NULL;
+    state->group_sid_list[sid_count] = NULL;
 
     /* Get the current sysdb group list for this user
      * so we can update it.
@@ -582,8 +635,17 @@ done:
 }
 
 errno_t
-sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req)
+sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req,
+                                        bool *_lookup_sids,
+                                        const char ***_group_sid_list)
 {
+    struct sdap_ad_tokengroups_initgr_state *state =
+            tevent_req_data(req, struct sdap_ad_tokengroups_initgr_state);
+
     TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *_lookup_sids = state->lookup_sids;
+    *_group_sid_list = state->group_sid_list;
+
     return EOK;
 }
-- 
1.8.1.4

From 8b0b15f8255169cba59efdf81130aa1c0b25fed2 Mon Sep 17 00:00:00 2001
From: Ondrej Kos <[email protected]>
Date: Wed, 11 Sep 2013 19:17:29 +0200
Subject: [PATCH 3/3] AD: Add lookup for SIDs not found in cache during
 TokenGroups

SIDs, that are not found in sysdb during tokengroups initgroups call
will be queried to LDAP and saved to sysdb.

Resolves:
https://fedorahosted.org/sssd/ticket/1568

Conflicts:
	src/providers/ldap/sdap_async_private.h
---
 src/providers/ldap/sdap_async.h               |  14 ++
 src/providers/ldap/sdap_async_initgroups.c    |  38 +++-
 src/providers/ldap/sdap_async_initgroups_ad.c | 290 ++++++++++++++++++++++++++
 3 files changed, 340 insertions(+), 2 deletions(-)

diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 0c682992a4037c30a347a19f06529d1920d2c099..2e461ac9f957fc6d4653a2b5aae3d2e367cfeed6 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -294,6 +294,20 @@ sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req,
                                         bool *_lookup_sids,
                                         const char ***_group_sid_list);
 
+struct tevent_req *
+sdap_get_ad_token_initgr_sidlookup_send(TALLOC_CTX *mem_ctx,
+                                        struct tevent_context *ev,
+                                        struct sdap_options *opts,
+                                        struct sysdb_ctx *sysdb,
+                                        struct sss_domain_info *domain,
+                                        struct sdap_handle *sh,
+                                        const char *name,
+                                        const char *orig_dn,
+                                        const char **group_sid_list);
+
+errno_t
+sdap_get_ad_token_initgr_sidlookup_recv(struct tevent_req *req);
+
 errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
                                    struct sss_domain_info *domain,
                                    struct sdap_options *opts,
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index 31c33e785cd408bbc737c16433b97df9a84185ab..257a7b542b8e3bdc4d2a6329a209d9be9976d7cd 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2560,6 +2560,7 @@ struct sdap_get_initgr_state {
     struct sdap_search_base **user_search_bases;
 
     bool use_id_mapping;
+    bool sids_looked_up;
 };
 
 static errno_t sdap_get_initgr_next_base(struct tevent_req *req);
@@ -2598,6 +2599,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
     state->cname = NULL;
     state->timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT);
     state->user_base_iter = 0;
+    state->sids_looked_up = false;
     state->user_search_bases = sdom->user_search_bases;
     if (!state->user_search_bases) {
         DEBUG(SSSDBG_CRIT_FAILURE,
@@ -2880,6 +2882,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
     char *dom_sid_str;
     char *group_sid_str;
     struct sdap_options *opts = state->opts;
+    const char *orig_dn;
     const char **group_sid_list;
     bool lookup_sids = false;
 
@@ -2896,8 +2899,12 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
 
     case SDAP_SCHEMA_RFC2307BIS:
     case SDAP_SCHEMA_AD:
-        if (state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
-            ret = sdap_get_ad_tokengroups_initgroups_recv(subreq, &lookup_sids, &group_sid_list);
+        if (state->sids_looked_up) {
+            ret = sdap_get_ad_token_initgr_sidlookup_recv(subreq);
+        } else if (state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) {
+            ret = sdap_get_ad_tokengroups_initgroups_recv(subreq,
+                                                          &lookup_sids,
+                                                          &group_sid_list);
         }
         else if (state->opts->support_matching_rule
                 && dp_opt_get_bool(state->opts->basic,
@@ -2921,6 +2928,33 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
     if (lookup_sids) {
         DEBUG(SSSDBG_TRACE_FUNC, ("Some of users TokenGroups not found in "
                                   "cache, will perform LDAP lookup.\n"));
+
+        ret = sysdb_attrs_get_string(state->orig_user,
+                                     SYSDB_ORIG_DN,
+                                     &orig_dn);
+        if (ret != EOK) {
+            tevent_req_error(req, ret);
+            return;
+        }
+
+        subreq = sdap_get_ad_token_initgr_sidlookup_send(state, state->ev,
+                                                         state->opts,
+                                                         state->sysdb,
+                                                         state->dom,
+                                                         state->sh,
+                                                         state->cname,
+                                                         orig_dn,
+                                                         group_sid_list);
+
+        if (!subreq) {
+            tevent_req_error(req, ENOMEM);
+            return;
+        }
+
+        state->sids_looked_up = true;
+
+        tevent_req_set_callback(subreq, sdap_get_initgr_done, req);
+        return;
     }
 
     DEBUG(9, ("Initgroups done\n"));
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
index 723b009c223118160e310e6a5efd5c4d12a85883..3ab35fada97f3af1b9d29202ea571fc8774b45e9 100644
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
@@ -3,6 +3,7 @@
 
     Authors:
         Stephen Gallagher <[email protected]>
+        Ondrej Kos <[email protected]>
 
     Copyright (C) 2012 Red Hat
 
@@ -649,3 +650,292 @@ sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req,
 
     return EOK;
 }
+
+/* Lookup SIDs fetched by TokenGroups call and not found in db */
+
+struct sdap_ad_token_initgr_sidlookup_state {
+    struct tevent_context *ev;
+    struct sdap_options *opts;
+    struct sysdb_ctx *sysdb;
+    struct sss_domain_info *domain;
+    struct sdap_handle *sh;
+    struct sdap_search_base **search_bases;
+    struct sysdb_attrs **ldap_groups;
+    const char **attrs;
+    const char *username;
+    const char *base_filter;
+    size_t ldap_groups_count;
+    size_t base_iter;
+    char *filter;
+    int timeout;
+};
+
+static void
+sdap_get_ad_token_initgr_sidlookup_process(struct tevent_req *subreq);
+
+static errno_t
+sdap_get_ad_token_initgr_sidlookup_next_base(struct tevent_req *req);
+
+struct tevent_req *
+sdap_get_ad_token_initgr_sidlookup_send(TALLOC_CTX *mem_ctx,
+                                        struct tevent_context *ev,
+                                        struct sdap_options *opts,
+                                        struct sysdb_ctx *sysdb,
+                                        struct sss_domain_info *domain,
+                                        struct sdap_handle *sh,
+                                        const char *name,
+                                        const char *orig_dn,
+                                        const char **group_sid_list)
+{
+    errno_t ret;
+    int i;
+    struct tevent_req *req;
+    struct sdap_ad_token_initgr_sidlookup_state *state;
+    const char **filter_members;
+    char *clean_orig_dn;
+    char *sid_filter = NULL;
+
+    req = tevent_req_create(mem_ctx, &state,
+                            struct sdap_ad_token_initgr_sidlookup_state);
+    if (!req) return NULL;
+
+    state->ev = ev;
+    state->opts = opts;
+    state->sysdb = sysdb;
+    state->domain = domain;
+    state->sh = sh;
+    state->search_bases = opts->sdom->group_search_bases;
+    state->ldap_groups = NULL;
+    state->username = name;
+    state->ldap_groups_count = 0;
+    state->base_iter = 0;
+    state->timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT);
+
+    filter_members = talloc_array(state, const char *, 2);
+    if (!filter_members) {
+        ret = ENOMEM;
+        goto done;
+    }
+    filter_members[0] = opts->group_map[SDAP_AT_GROUP_MEMBER].name;
+    filter_members[1] = NULL;
+
+    ret = build_attrs_from_map(state, opts->group_map, SDAP_OPTS_GROUP,
+                               filter_members, &state->attrs, NULL);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_MINOR_FAILURE, ("Could not build attribute map: [%s]\n",
+                                     strerror(ret)));
+        goto done;
+    }
+
+    ret = sss_filter_sanitize(state, orig_dn, &clean_orig_dn);
+    if (ret != EOK) goto done;
+
+    i = 0;
+    while (group_sid_list[i]) {
+        sid_filter = talloc_asprintf(state, "%s(%s=%s)",
+                                     sid_filter ? sid_filter : "",
+                                     opts->group_map[SDAP_AT_GROUP_OBJECTSID].name,
+                                     group_sid_list[i]);
+        i++;
+    }
+
+    state->base_filter =
+            talloc_asprintf(state, "(&(objectclass=%s)(|%s)(!(%s=0)))",
+                            opts->group_map[SDAP_OC_GROUP].name,
+                            sid_filter,
+                            opts->group_map[SDAP_AT_GROUP_GID].name);
+    if (!state->base_filter) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    talloc_zfree(clean_orig_dn);
+
+    ret = sdap_get_ad_token_initgr_sidlookup_next_base(req);
+
+done:
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+        tevent_req_post(req, ev);
+    }
+
+    return req;
+}
+
+static errno_t
+sdap_get_ad_token_initgr_sidlookup_next_base(struct tevent_req *req)
+{
+    struct tevent_req *subreq;
+    struct sdap_ad_token_initgr_sidlookup_state *state;
+
+    state = tevent_req_data(req, struct sdap_ad_token_initgr_sidlookup_state);
+
+    talloc_zfree(state->filter);
+
+    state->filter = sdap_get_id_specific_filter(
+                               state,
+                               state->base_filter,
+                               state->search_bases[state->base_iter]->filter);
+    if (!state->filter) {
+        return ENOMEM;
+    }
+
+    subreq = sdap_get_generic_send(
+            state, state->ev, state->opts, state->sh,
+            state->search_bases[state->base_iter]->basedn,
+            state->search_bases[state->base_iter]->scope,
+            state->filter, state->attrs,
+            state->opts->group_map, SDAP_OPTS_GROUP,
+            state->timeout,
+            true);
+    if (!subreq) {
+        talloc_zfree(req);
+        return ENOMEM;
+    }
+
+    tevent_req_set_callback(subreq,
+                            sdap_get_ad_token_initgr_sidlookup_process,
+                            req);
+
+    return EOK;
+}
+
+static void
+sdap_get_ad_token_initgr_sidlookup_process(struct tevent_req *subreq)
+{
+    errno_t ret;
+    errno_t tret;
+    size_t i;
+    size_t count;
+    char **groupnames = NULL;
+    bool in_transaction = false;
+    struct sysdb_attrs **ldap_groups;
+    struct tevent_req *req =
+            tevent_req_callback_data(subreq, struct tevent_req);
+    struct sdap_ad_token_initgr_sidlookup_state *state =
+            tevent_req_data(req, struct sdap_ad_token_initgr_sidlookup_state);
+
+    ret = sdap_get_generic_recv(subreq, state, &count, &ldap_groups);
+
+    talloc_zfree(subreq);
+    if (ret) {
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    DEBUG(SSSDBG_TRACE_LIBS, ("Found %d parent groups for user [%s]\n",
+                              count, state->username));
+
+    /* Add this batch of groups to the list */
+    if (count > 0) {
+        state->ldap_groups =
+                talloc_realloc(state,
+                               state->ldap_groups,
+                               struct sysdb_attrs *,
+                               state->ldap_groups_count + count + 1);
+        if (!state->ldap_groups) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        /* Copy the new groups into the list.
+         */
+        for (i = 0; i < count; i++) {
+            state->ldap_groups[state->ldap_groups_count + i] =
+                talloc_steal(state->ldap_groups, ldap_groups[i]);
+        }
+
+        state->ldap_groups_count += count;
+
+        state->ldap_groups[state->ldap_groups_count] = NULL;
+    }
+
+    state->base_iter++;
+
+    /* Check for additional search bases, and iterate
+     * through again.
+     */
+    if (state->search_bases[state->base_iter] != NULL) {
+        ret = sdap_get_ad_token_initgr_sidlookup_next_base(req);
+        if (ret != EOK) {
+            goto done;
+        }
+    }
+
+    if (state->ldap_groups_count > 0) {
+        ret = sysdb_attrs_primary_name_list(
+                        state->sysdb,
+                        state,
+                        state->ldap_groups,
+                        state->ldap_groups_count,
+                        state->opts->group_map[SDAP_AT_GROUP_NAME].name,
+                        &groupnames);
+        if (ret != EOK) {
+            goto done;
+        }
+    }
+
+    ret = sysdb_transaction_start(state->sysdb);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
+        goto done;
+    }
+    in_transaction = true;
+
+    ret = sdap_add_incomplete_groups(state->sysdb,
+                                     state->domain,
+                                     state->opts,
+                                     groupnames,
+                                     state->ldap_groups,
+                                     state->ldap_groups_count);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_TRACE_FUNC, ("Could not add incomplete groups [%d]:%s\n",
+                   ret, strerror(ret)));
+        goto done;
+    }
+
+    i = 0;
+    while (groupnames[i]) {
+        ret = sysdb_add_group_member(state->sysdb,
+                                     state->domain,
+                                     groupnames[i],
+                                     state->username,
+                                     SYSDB_MEMBER_USER);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Could not add member [%s] to group "
+                                        "[%s]. Skipping.\n",
+                                        state->username,
+                                        groupnames[i]));
+        }
+        i++;
+    }
+
+    ret = sysdb_transaction_commit(state->sysdb);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
+        goto done;
+    }
+    in_transaction = false;
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Saving user groups done.\n"));
+
+done:
+    if (in_transaction) {
+        tret = sysdb_transaction_cancel(state->sysdb);
+        if (tret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to cancel transaction\n"));
+        }
+    }
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+    }
+    tevent_req_done(req);
+}
+
+errno_t
+sdap_get_ad_token_initgr_sidlookup_recv(struct tevent_req *req)
+{
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    return EOK;
+}
-- 
1.8.1.4

_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to