Blame SOURCES/0017-AD-use-LDAP-for-group-lookups.patch

2fc102
From 0324d31d0479e5de0d3aac05bf5fb922d84f84c4 Mon Sep 17 00:00:00 2001
2fc102
From: Sumit Bose <sbose@redhat.com>
2fc102
Date: Mon, 9 Dec 2013 11:45:28 +0100
2fc102
Subject: [PATCH 17/17] AD: use LDAP for group lookups
2fc102
2fc102
The group memberships cannot be reliable retrieved from the Global
2fc102
Catalog. By default the memberOf attribute is not replicated to the GC
2fc102
at all and the member attribute is copied from the local LDAP instance
2fc102
to the GC running on the same host, but is only replicated to other GC
2fc102
instances for groups with universal scope. Additionally the tokenGroups
2fc102
attribute contains invalid SIDs when used with the GC for users from a
2fc102
different domains than the GC belongs to.
2fc102
2fc102
As a result the requests which tries to resolve group-memberships of a
2fc102
AD user have to go to a LDAP server from the domain of the user.
2fc102
2fc102
Fixes https://fedorahosted.org/sssd/ticket/2161 and
2fc102
https://fedorahosted.org/sssd/ticket/2148 as a side-effect.
2fc102
---
2fc102
 src/providers/ad/ad_id.c         |  20 +++++-
2fc102
 src/providers/ad/ad_subdomains.c | 133 ++++++++++++++++++++++++++++++++++++++-
2fc102
 src/providers/ldap/sdap.h        |   2 +
2fc102
 3 files changed, 152 insertions(+), 3 deletions(-)
2fc102
2fc102
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
2fc102
index 87b69c66892ebfa48a1067c63006f3e3bd2e7444..dadb50da92cac87d3162bddb44395dad7d2abbc4 100644
2fc102
--- a/src/providers/ad/ad_id.c
2fc102
+++ b/src/providers/ad/ad_id.c
2fc102
@@ -188,6 +188,8 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
2fc102
               struct sss_domain_info *dom, struct be_acct_req *ar)
2fc102
 {
2fc102
     struct sdap_id_conn_ctx **clist;
2fc102
+    struct sdap_domain *sdom;
2fc102
+    struct ad_id_ctx *subdom_id_ctx;
2fc102
 
2fc102
     /* LDAP, GC, sentinel */
2fc102
     clist = talloc_zero_array(breq, struct sdap_id_conn_ctx *, 3);
2fc102
@@ -197,8 +199,6 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
2fc102
     case BE_REQ_USER: /* user */
2fc102
     case BE_REQ_BY_SECID:   /* by SID */
2fc102
     case BE_REQ_USER_AND_GROUP: /* get SID */
2fc102
-    case BE_REQ_GROUP: /* group */
2fc102
-    case BE_REQ_INITGROUPS: /* init groups for user */
2fc102
         /* Always try GC first */
2fc102
         clist[0] = ad_ctx->gc_ctx;
2fc102
         if (IS_SUBDOMAIN(dom) == true) {
2fc102
@@ -216,6 +216,22 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
2fc102
         clist[1] = ad_ctx->ldap_ctx;
2fc102
         break;
2fc102
 
2fc102
+    case BE_REQ_GROUP: /* group */
2fc102
+    case BE_REQ_INITGROUPS: /* init groups for user */
2fc102
+        if (IS_SUBDOMAIN(dom)) {
2fc102
+            sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom);
2fc102
+            if (sdom == NULL || sdom->pvt == NULL) {
2fc102
+                DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n",
2fc102
+                                            dom->name));
2fc102
+                return NULL;
2fc102
+            }
2fc102
+            subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
2fc102
+            clist[0] = subdom_id_ctx->ldap_ctx;
2fc102
+        } else {
2fc102
+            clist[0] = ad_ctx->ldap_ctx;
2fc102
+        }
2fc102
+        break;
2fc102
+
2fc102
     default:
2fc102
         clist[0] = ad_ctx->ldap_ctx;
2fc102
         break;
2fc102
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
2fc102
index 18414523096ba0e53261415551eea57b4b2758b2..28c5eafb395b70e8f3630a43b67c61810683fe7c 100644
2fc102
--- a/src/providers/ad/ad_subdomains.c
2fc102
+++ b/src/providers/ad/ad_subdomains.c
2fc102
@@ -25,6 +25,7 @@
2fc102
 #include "providers/ldap/sdap_async.h"
2fc102
 #include "providers/ad/ad_subdomains.h"
2fc102
 #include "providers/ad/ad_domain_info.h"
2fc102
+#include "providers/ad/ad_srv.h"
2fc102
 #include "providers/ldap/sdap_idmap.h"
2fc102
 #include "util/util_sss_idmap.h"
2fc102
 #include <ctype.h>
2fc102
@@ -68,6 +69,7 @@ struct ad_subdomains_ctx {
2fc102
 
2fc102
     time_t last_refreshed;
2fc102
     struct tevent_timer *timer_event;
2fc102
+    struct ad_id_ctx *ad_id_ctx;
2fc102
 };
2fc102
 
2fc102
 struct ad_subdomains_req_ctx {
2fc102
@@ -86,10 +88,138 @@ struct ad_subdomains_req_ctx {
2fc102
 };
2fc102
 
2fc102
 static errno_t
2fc102
+ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
2fc102
+                     struct ad_id_ctx *id_ctx,
2fc102
+                     struct sss_domain_info *subdom,
2fc102
+                     struct ad_id_ctx **_subdom_id_ctx)
2fc102
+{
2fc102
+    struct ad_options *ad_options;
2fc102
+    struct ad_id_ctx *ad_id_ctx;
2fc102
+    const char *gc_service_name;
2fc102
+    struct ad_srv_plugin_ctx *srv_ctx;
2fc102
+    char *ad_domain;
2fc102
+    struct sdap_domain *sdom;
2fc102
+    errno_t ret;
2fc102
+    const char *realm;
2fc102
+    const char *hostname;
2fc102
+
2fc102
+    realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
2fc102
+    hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
2fc102
+    if (realm == NULL || hostname == NULL) {
2fc102
+        DEBUG(SSSDBG_CONF_SETTINGS, ("Missing realm or hostname.\n"));
2fc102
+        return EINVAL;
2fc102
+    }
2fc102
+
2fc102
+    ad_options = ad_create_default_options(id_ctx, realm, hostname);
2fc102
+    if (ad_options == NULL) {
2fc102
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD options\n"));
2fc102
+        talloc_free(ad_options);
2fc102
+        return ENOMEM;
2fc102
+    }
2fc102
+
2fc102
+    ad_domain = subdom->name;
2fc102
+
2fc102
+    ret = dp_opt_set_string(ad_options->basic, AD_DOMAIN, ad_domain);
2fc102
+    if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot set AD domain\n"));
2fc102
+        talloc_free(ad_options);
2fc102
+        return ret;
2fc102
+    }
2fc102
+
2fc102
+    gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
2fc102
+    if (gc_service_name == NULL) {
2fc102
+        talloc_free(ad_options);
2fc102
+        return ENOMEM;
2fc102
+    }
2fc102
+
2fc102
+    ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, realm,
2fc102
+                           subdom->name, gc_service_name,
2fc102
+                           subdom->name, &ad_options->service);
2fc102
+    if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD failover\n"));
2fc102
+        talloc_free(ad_options);
2fc102
+        return ret;
2fc102
+    }
2fc102
+
2fc102
+    ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
2fc102
+    if (ad_id_ctx == NULL) {
2fc102
+        talloc_free(ad_options);
2fc102
+        return ENOMEM;
2fc102
+    }
2fc102
+    ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
2fc102
+    ad_options->id_ctx = ad_id_ctx;
2fc102
+
2fc102
+    /* use AD plugin */
2fc102
+    srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
2fc102
+                                     default_host_dbs,
2fc102
+                                     ad_id_ctx->ad_options->id,
2fc102
+                                     hostname,
2fc102
+                                     ad_domain);
2fc102
+    if (srv_ctx == NULL) {
2fc102
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory?\n"));
2fc102
+        return ENOMEM;
2fc102
+    }
2fc102
+    be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
2fc102
+                                ad_srv_plugin_recv, srv_ctx, "AD");
2fc102
+
2fc102
+    ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
2fc102
+                                 ad_id_ctx->sdap_id_ctx->opts->sdom,
2fc102
+                                 subdom->parent);
2fc102
+    if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize sdap domain\n"));
2fc102
+        talloc_free(ad_options);
2fc102
+        return ret;
2fc102
+    }
2fc102
+
2fc102
+    sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
2fc102
+    if (sdom == NULL) {
2fc102
+        return EFAULT;
2fc102
+    }
2fc102
+
2fc102
+    ret = sdap_id_setup_tasks(ad_id_ctx->sdap_id_ctx,
2fc102
+                              ad_id_ctx->ldap_ctx, sdom,
2fc102
+                              ldap_enumeration_send,
2fc102
+                              ldap_enumeration_recv);
2fc102
+    if (ret != EOK) {
2fc102
+        talloc_free(ad_options);
2fc102
+        return ret;
2fc102
+    }
2fc102
+
2fc102
+    /* Set up the ID mapping object */
2fc102
+    ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
2fc102
+        id_ctx->sdap_id_ctx->opts->idmap_ctx;
2fc102
+
2fc102
+    *_subdom_id_ctx = ad_id_ctx;
2fc102
+    return EOK;
2fc102
+}
2fc102
+
2fc102
+static errno_t
2fc102
 ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx,
2fc102
                       struct sss_domain_info *parent)
2fc102
 {
2fc102
-    return sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
2fc102
+    int ret;
2fc102
+    struct sdap_domain *sditer;
2fc102
+    struct ad_id_ctx *subdom_id_ctx;
2fc102
+
2fc102
+    ret = sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
2fc102
+    if (ret != EOK) {
2fc102
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_domain_subdom_add failed.\n"));
2fc102
+        return ret;
2fc102
+    }
2fc102
+
2fc102
+    DLIST_FOR_EACH(sditer, ctx->sdom) {
2fc102
+        if (IS_SUBDOMAIN(sditer->dom) && sditer->pvt == NULL) {
2fc102
+            ret = ad_subdom_ad_ctx_new(ctx->be_ctx, ctx->ad_id_ctx,
2fc102
+                                       sditer->dom, &subdom_id_ctx);
2fc102
+            if (ret != EOK) {
2fc102
+                DEBUG(SSSDBG_OP_FAILURE, ("ad_subdom_ad_ctx_new failed.\n"));
2fc102
+            } else {
2fc102
+                sditer->pvt = subdom_id_ctx;
2fc102
+            }
2fc102
+        }
2fc102
+    }
2fc102
+
2fc102
+    return EOK;
2fc102
 }
2fc102
 
2fc102
 static errno_t
2fc102
@@ -630,6 +760,7 @@ int ad_subdom_init(struct be_ctx *be_ctx,
2fc102
         DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
2fc102
         return ENOMEM;
2fc102
     }
2fc102
+    ctx->ad_id_ctx = id_ctx;
2fc102
     *ops = &ad_subdomains_ops;
2fc102
     *pvt_data = ctx;
2fc102
 
2fc102
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
2fc102
index c53471b9bd6d9b18f37a8bf4089c8700d4a1163d..fa641730bb78b6a96c0b9640af7612b876f56533 100644
2fc102
--- a/src/providers/ldap/sdap.h
2fc102
+++ b/src/providers/ldap/sdap.h
2fc102
@@ -394,6 +394,8 @@ struct sdap_domain {
2fc102
     struct timeval last_enum;
2fc102
     /* cleanup loop timer */
2fc102
     struct timeval last_purge;
2fc102
+
2fc102
+    void *pvt;
2fc102
 };
2fc102
 
2fc102
 struct sdap_options {
2fc102
-- 
2fc102
1.8.4.2
2fc102