[SSSD] [PATCH] AD: use LDAP for group lookups

Sumit Bose sbose at redhat.com
Wed Dec 11 14:12:13 UTC 2013


Hi,

this patch should fix the issues related to group-memberships in the AD
provider. The aim was to fix https://fedorahosted.org/sssd/ticket/2161
but since now the group lookups are done against LDAP
https://fedorahosted.org/sssd/ticket/2148 should be fixed as well.

bye,
Sumit
-------------- next part --------------
From 09f69a209548102d00f484f0665ffcb810d5722c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 9 Dec 2013 11:45:28 +0100
Subject: [PATCH] AD: use LDAP for group lookups

The group memberships cannot be reliable retrieved from the Global
Catalog. By default the memberOf attribute is not replicated to the GC
at all and the member attribute is copied from the local LDAP instance
to the GC running on the same host, but is only replicated to other GC
instances for groups with universal scope. Additionally the tokenGroups
attribute contains invalid SIDs when used with the GC for users from a
different domains than the GC belongs to.

As a result the requests which tries to resolve group-memberships of a
AD user have to go to a LDAP server from the domain of the user.

Fixes https://fedorahosted.org/sssd/ticket/2161 and
https://fedorahosted.org/sssd/ticket/2148 as a side-effect.
---
 src/providers/ad/ad_id.c         |  20 +++++-
 src/providers/ad/ad_subdomains.c | 133 ++++++++++++++++++++++++++++++++++++++-
 src/providers/ldap/sdap.h        |   2 +
 3 files changed, 152 insertions(+), 3 deletions(-)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 242e962..2de3ba7 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -188,6 +188,8 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
               struct sss_domain_info *dom, struct be_acct_req *ar)
 {
     struct sdap_id_conn_ctx **clist;
+    struct sdap_domain *sdom;
+    struct ad_id_ctx *subdom_id_ctx;
 
     /* LDAP, GC, sentinel */
     clist = talloc_zero_array(breq, struct sdap_id_conn_ctx *, 3);
@@ -197,8 +199,6 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
     case BE_REQ_USER: /* user */
     case BE_REQ_BY_SECID:   /* by SID */
     case BE_REQ_USER_AND_GROUP: /* get SID */
-    case BE_REQ_GROUP: /* group */
-    case BE_REQ_INITGROUPS: /* init groups for user */
         /* Always try GC first */
         clist[0] = ad_ctx->gc_ctx;
         if (IS_SUBDOMAIN(dom) == true) {
@@ -216,6 +216,22 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
         clist[1] = ad_ctx->ldap_ctx;
         break;
 
+    case BE_REQ_GROUP: /* group */
+    case BE_REQ_INITGROUPS: /* init groups for user */
+        if (IS_SUBDOMAIN(dom)) {
+            sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom);
+            if (sdom == NULL || sdom->pvt == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n",
+                                            dom->name));
+                return NULL;
+            }
+            subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
+            clist[0] = subdom_id_ctx->ldap_ctx;
+        } else {
+            clist[0] = ad_ctx->ldap_ctx;
+        }
+        break;
+
     default:
         clist[0] = ad_ctx->ldap_ctx;
         break;
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 4cf083c..100fb13 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -25,6 +25,7 @@
 #include "providers/ldap/sdap_async.h"
 #include "providers/ad/ad_subdomains.h"
 #include "providers/ad/ad_domain_info.h"
+#include "providers/ad/ad_srv.h"
 #include "providers/ldap/sdap_idmap.h"
 #include "util/util_sss_idmap.h"
 #include <ctype.h>
@@ -68,6 +69,7 @@ struct ad_subdomains_ctx {
 
     time_t last_refreshed;
     struct tevent_timer *timer_event;
+    struct ad_id_ctx *ad_id_ctx;
 };
 
 struct ad_subdomains_req_ctx {
@@ -86,10 +88,138 @@ struct ad_subdomains_req_ctx {
 };
 
 static errno_t
+ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
+                     struct ad_id_ctx *id_ctx,
+                     struct sss_domain_info *subdom,
+                     struct ad_id_ctx **_subdom_id_ctx)
+{
+    struct ad_options *ad_options;
+    struct ad_id_ctx *ad_id_ctx;
+    const char *gc_service_name;
+    struct ad_srv_plugin_ctx *srv_ctx;
+    char *ad_domain;
+    struct sdap_domain *sdom;
+    errno_t ret;
+    const char *realm;
+    const char *hostname;
+
+    realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
+    hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
+    if (realm == NULL || hostname == NULL) {
+        DEBUG(SSSDBG_CONF_SETTINGS, ("Missing realm or hostname.\n"));
+        return EINVAL;
+    }
+
+    ad_options = ad_create_default_options(id_ctx, realm, hostname);
+    if (ad_options == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD options\n"));
+        talloc_free(ad_options);
+        return ENOMEM;
+    }
+
+    ad_domain = subdom->name;
+
+    ret = dp_opt_set_string(ad_options->basic, AD_DOMAIN, ad_domain);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot set AD domain\n"));
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
+    if (gc_service_name == NULL) {
+        talloc_free(ad_options);
+        return ENOMEM;
+    }
+
+    ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, realm,
+                           subdom->name, gc_service_name,
+                           subdom->name, &ad_options->service);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD failover\n"));
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx);
+    if (ad_id_ctx == NULL) {
+        talloc_free(ad_options);
+        return ENOMEM;
+    }
+    ad_id_ctx->sdap_id_ctx->opts = ad_options->id;
+    ad_options->id_ctx = ad_id_ctx;
+
+    /* use AD plugin */
+    srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res,
+                                     default_host_dbs,
+                                     ad_id_ctx->ad_options->id,
+                                     hostname,
+                                     ad_domain);
+    if (srv_ctx == NULL) {
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory?\n"));
+        return ENOMEM;
+    }
+    be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send,
+                                ad_srv_plugin_recv, srv_ctx, "AD");
+
+    ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx,
+                                 ad_id_ctx->sdap_id_ctx->opts->sdom,
+                                 subdom->parent);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize sdap domain\n"));
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom);
+    if (sdom == NULL) {
+        return EFAULT;
+    }
+
+    ret = sdap_id_setup_tasks(ad_id_ctx->sdap_id_ctx,
+                              ad_id_ctx->ldap_ctx, sdom,
+                              ldap_enumeration_send,
+                              ldap_enumeration_recv);
+    if (ret != EOK) {
+        talloc_free(ad_options);
+        return ret;
+    }
+
+    /* Set up the ID mapping object */
+    ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
+        id_ctx->sdap_id_ctx->opts->idmap_ctx;
+
+    *_subdom_id_ctx = ad_id_ctx;
+    return EOK;
+}
+
+static errno_t
 ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx,
                       struct sss_domain_info *parent)
 {
-    return sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
+    int ret;
+    struct sdap_domain *sditer;
+    struct ad_id_ctx *subdom_id_ctx;
+
+    ret = sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("sdap_domain_subdom_add failed.\n"));
+        return ret;
+    }
+
+    DLIST_FOR_EACH(sditer, ctx->sdom) {
+        if (IS_SUBDOMAIN(sditer->dom) && sditer->pvt == NULL) {
+            ret = ad_subdom_ad_ctx_new(ctx->be_ctx, ctx->ad_id_ctx,
+                                       sditer->dom, &subdom_id_ctx);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, ("ad_subdom_ad_ctx_new failed.\n"));
+            } else {
+                sditer->pvt = subdom_id_ctx;
+            }
+        }
+    }
+
+    return EOK;
 }
 
 static errno_t
@@ -632,6 +762,7 @@ int ad_subdom_init(struct be_ctx *be_ctx,
         DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
         return ENOMEM;
     }
+    ctx->ad_id_ctx = id_ctx;
     *ops = &ad_subdomains_ops;
     *pvt_data = ctx;
 
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 92ff667..b8b5125 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -395,6 +395,8 @@ struct sdap_domain {
     struct timeval last_enum;
     /* cleanup loop timer */
     struct timeval last_purge;
+
+    void *pvt;
 };
 
 struct sdap_options {
-- 
1.8.3.1



More information about the sssd-devel mailing list