[SSSD] [PATCH] Add an option to disable GC lookups

Jakub Hrozek jhrozek at redhat.com
Thu Dec 19 10:10:08 UTC 2013


On Sat, Dec 14, 2013 at 10:15:14PM +0100, Jakub Hrozek wrote:
> Hi,
> 
> we're debating what is the right approach to GC lookups by default, but
> for the 1.11.3 release, we should offer an option to fall back from GC
> to LDAP. The attached patches do that.
> 
> [PATCH 1/3] AD: Add a utility function to create list of connections
> ad_id.c and ad_access.c used the same block of code. With the upcoming
> option to disable GC lookups, we should unify the code in a function to
> avoid breaking one of the code paths.
> 
> Defaulting to GC for access provider is safe, as you can see in
> ad_access.c we retry on any denial against the GC to make sure we don't
> miss an attribute from LDAP.
> 
> [PATCH 2/3] AD: Add a new option to turn off GC lookups
> Adds the option.
> 
> [PATCH 3/3] AD: Enable fallback to LDAP of trusted domain
> Since we have the LDAP port of a trusted AD GC always available now, we
> can always perform a fallback.
> 
> I'm fine with leaving the patch out of 1.11.3 if the other developers
> think we should stricly limit ourselves to what we've agreed on.

Hi,

the previous patches applied cleanly on origin/master but I think in
upstream, they should come after Sumit's local domain patches, so I
rebased them on top of those.

New patches are attached.
-------------- next part --------------
>From 1296f71cfe12ed29a10f3205806c272a9a0b3a4b Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Tue, 3 Dec 2013 20:45:44 +0100
Subject: [PATCH 1/3] AD: Add a utility function to create list of connections

ad_id.c and ad_access.c used the same block of code. With the upcoming
option to disable GC lookups, we should unify the code in a function to
avoid breaking one of the code paths.

The same applies for the LDAP connection to the trusted AD DC.

Includes a unit test.
---
 Makefile.am                       |  28 +++++
 src/providers/ad/ad_access.c      |  16 +--
 src/providers/ad/ad_access.h      |   4 +-
 src/providers/ad/ad_common.c      |  52 +++++++++
 src/providers/ad/ad_common.h      |   7 ++
 src/providers/ad/ad_id.c          |  29 ++---
 src/providers/ad/ad_init.c        |   3 +-
 src/tests/cmocka/test_ad_common.c | 221 ++++++++++++++++++++++++++++++++++++++
 8 files changed, 319 insertions(+), 41 deletions(-)
 create mode 100644 src/tests/cmocka/test_ad_common.c

diff --git a/Makefile.am b/Makefile.am
index 913e7e6a9dc61d0f3f3adf298ed0cb451c8dd914..f99588ba89d7f29b6f7f3528e60dfd906dc9f870 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -155,6 +155,7 @@ if HAVE_CMOCKA
         test_sss_idmap \
         test_utils \
         ad_access_filter_tests \
+        ad_common_tests \
         test_search_bases
 endif
 
@@ -1420,6 +1421,7 @@ ad_access_filter_tests_SOURCES = \
     src/util/sss_krb5.c \
     src/util/find_uid.c \
     src/util/user_info_msg.c \
+    src/providers/ad/ad_common.c \
     src/tests/cmocka/test_ad_access_filter.c
 ad_access_filter_tests_CFLAGS = \
     $(AM_CFLAGS) \
@@ -1438,6 +1440,32 @@ ad_access_filter_tests_LDADD = \
     libsss_krb5_common.la \
     libsss_test_common.la
 
+ad_common_tests_SOURCES = \
+    $(sssd_be_SOURCES) \
+    src/util/sss_ldap.c \
+    src/util/sss_krb5.c \
+    src/util/find_uid.c \
+    src/util/user_info_msg.c \
+    src/tests/cmocka/test_ad_common.c
+ad_common_tests_CFLAGS = \
+    $(AM_CFLAGS) \
+    $(SYSTEMD_LOGIN_CFLAGS) \
+    -DUNIT_TESTING
+ad_common_tests_LDFLAGS = \
+    -Wl,-wrap,sdap_set_sasl_options
+ad_common_tests_LDADD = \
+    $(PAM_LIBS) \
+    $(CMOCKA_LIBS) \
+    $(SSSD_LIBS) \
+    $(CARES_LIBS) \
+    $(KRB5_LIBS) \
+    $(SSSD_INTERNAL_LTLIBS) \
+    $(SYSTEMD_LOGIN_LIBS) \
+    libsss_ldap_common.la \
+    libsss_idmap.la \
+    libsss_krb5_common.la \
+    libsss_test_common.la
+
 endif
 
 noinst_PROGRAMS = pam_test_client
diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c
index 6995172db304810899e538b37572e4ba953db3e7..68a292abc88daa2f10f6797db50cc75335e80483 100644
--- a/src/providers/ad/ad_access.c
+++ b/src/providers/ad/ad_access.c
@@ -274,26 +274,12 @@ ad_access_send(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    state->clist = talloc_zero_array(state, struct sdap_id_conn_ctx *, 3);
+    state->clist = ad_gc_conn_list(state, ctx->ad_id_ctx, domain);
     if (state->clist == NULL) {
         ret = ENOMEM;
         goto done;
     }
 
-    /* Always try GC first */
-    ctx->gc_ctx->ignore_mark_offline = false;
-    state->clist[0] = ctx->gc_ctx;
-    if (IS_SUBDOMAIN(domain) == false) {
-        /* fall back to ldap if gc is not available */
-        state->clist[0]->ignore_mark_offline = true;
-
-        /* With root domain users we have the option to
-         * fall back to LDAP in case ie POSIX attributes
-         * are used but not replicated to GC
-         */
-        state->clist[1] = ctx->ldap_ctx;
-    }
-
     ret = ad_access_step(req, state->clist[state->cindex]);
     if (ret != EOK) {
         goto done;
diff --git a/src/providers/ad/ad_access.h b/src/providers/ad/ad_access.h
index ca5e69729c574be53b7da04df0ff89446da04c58..3bd19ccc508b43f7103c7041dcc8573a00235097 100644
--- a/src/providers/ad/ad_access.h
+++ b/src/providers/ad/ad_access.h
@@ -26,9 +26,7 @@
 struct ad_access_ctx {
     struct dp_option *ad_options;
     struct sdap_access_ctx *sdap_access_ctx;
-
-    struct sdap_id_conn_ctx *ldap_ctx;
-    struct sdap_id_conn_ctx *gc_ctx;
+    struct ad_id_ctx *ad_id_ctx;
 };
 
 void
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index f679c11ad18078b454b778ef30e40cca716412cb..af0ec839964233c7642205f4489e5b6462509848 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -1096,3 +1096,55 @@ ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx)
 
     return ad_ctx;
 }
+
+struct sdap_id_conn_ctx *
+ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom)
+{
+    struct sdap_id_conn_ctx *conn;
+    struct sdap_domain *sdom;
+    struct ad_id_ctx *subdom_id_ctx;
+
+    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);
+        conn = subdom_id_ctx->ldap_ctx;
+    } else {
+        conn = ad_ctx->ldap_ctx;
+    }
+
+    return conn;
+}
+
+struct sdap_id_conn_ctx **
+ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
+                struct sss_domain_info *dom)
+{
+    struct sdap_id_conn_ctx **clist;
+
+    clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3);
+    if (clist == NULL) return NULL;
+
+    /* Always try GC first */
+    clist[0] = ad_ctx->gc_ctx;
+    if (IS_SUBDOMAIN(dom) == true) {
+        clist[0]->ignore_mark_offline = false;
+        /* Subdomain users are only present in GC. */
+        return clist;
+    }
+
+    /* fall back to ldap if gc is not available */
+    clist[0]->ignore_mark_offline = true;
+
+    /* With root domain users we have the option to
+     * fall back to LDAP in case ie POSIX attributes
+     * are used but not replicated to GC
+     */
+    clist[1] = ad_ctx->ldap_ctx;
+
+    return clist;
+}
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index b8b73c042b8a5433f720c89c04447c07cd3eac43..ed5b8584dc5327a24e60985486c6155604271fd2 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -115,6 +115,13 @@ ad_get_dyndns_options(struct be_ctx *be_ctx,
 struct ad_id_ctx *
 ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx);
 
+struct sdap_id_conn_ctx **
+ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
+               struct sss_domain_info *dom);
+
+struct sdap_id_conn_ctx *
+ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom);
+
 /* AD dynamic DNS updates */
 errno_t ad_dyndns_init(struct be_ctx *be_ctx,
                        struct ad_options *ctx);
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 7a86afdb72dd29a035a02cc0f947980823034cfc..0280d755cc4a3b73fd500f2dc4ca27988df92c2b 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -188,12 +188,6 @@ 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);
-    if (clist == NULL) return NULL;
 
     switch (ar->entry_type & BE_REQ_TYPE_MASK) {
     case BE_REQ_USER: /* user */
@@ -201,24 +195,17 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
     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) {
-            clist[0]->ignore_mark_offline = false;
-            /* Subdomain users are only present in GC. */
-            break;
-        }
-        /* fall back to ldap if gc is not available */
-        clist[0]->ignore_mark_offline = true;
-
-        /* With root domain users we have the option to
-         * fall back to LDAP in case ie POSIX attributes
-         * are used but not replicated to GC
-         */
-        clist[1] = ad_ctx->ldap_ctx;
+        clist = ad_gc_conn_list(breq, ad_ctx, dom);
+        if (clist == NULL) return NULL;
         break;
+
     default:
+        /* Requests for other object should only contact LDAP by default */
+        clist = talloc_zero_array(breq, struct sdap_id_conn_ctx *, 2);
+        if (clist == NULL) return NULL;
+
         clist[0] = ad_ctx->ldap_ctx;
+        clist[1] = NULL;
         break;
     }
 
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 332bfda3801db3824ce1896d37e65e2c3a6b8b8b..ed69a7d9889bac1281b5ff7c7b0f290ab09173fb 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -377,8 +377,7 @@ sssm_ad_access_init(struct be_ctx *bectx,
     if (ret != EOK) {
         goto fail;
     }
-    access_ctx->ldap_ctx = ad_id_ctx->ldap_ctx;
-    access_ctx->gc_ctx = ad_id_ctx->gc_ctx;
+    access_ctx->ad_id_ctx = ad_id_ctx;
 
     ret = dp_copy_options(access_ctx, ad_options->basic, AD_OPTS_BASIC,
                           &access_ctx->ad_options);
diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe24d7cc8a02b798fd1e612a6eb5ede4bffa9e84
--- /dev/null
+++ b/src/tests/cmocka/test_ad_common.c
@@ -0,0 +1,221 @@
+/*
+    Authors:
+        Jakub Hrozek <jhrozek at redhat.com>
+
+    Copyright (C) 2013 Red Hat
+
+    SSSD tests: AD access control filter tests
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <talloc.h>
+#include <tevent.h>
+#include <errno.h>
+#include <popt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+
+/* In order to access opaque types */
+#include "providers/ad/ad_common.c"
+
+#include "tests/cmocka/common_mock.h"
+
+#define DOMNAME     "domname"
+#define SUBDOMNAME  "sub."DOMNAME
+#define REALMNAME   DOMNAME
+#define HOST_NAME   "ad."REALMNAME
+
+struct ad_common_test_ctx {
+    struct ad_id_ctx *ad_ctx;
+    struct ad_id_ctx *subdom_ad_ctx;
+
+    struct sss_domain_info *dom;
+    struct sss_domain_info *subdom;
+};
+
+static void
+ad_common_test_setup(void **state)
+{
+    struct ad_common_test_ctx *test_ctx;
+    errno_t ret;
+    struct sdap_domain *sdom;
+    struct ad_id_ctx *ad_ctx;
+    struct ad_id_ctx *subdom_ad_ctx;
+    struct sdap_id_conn_ctx *subdom_ldap_ctx;
+
+    assert_true(leak_check_setup());
+    check_leaks_push(global_talloc_context);
+
+    test_ctx = talloc_zero(global_talloc_context, struct ad_common_test_ctx);
+    assert_non_null(test_ctx);
+
+    test_ctx->dom = talloc_zero(test_ctx, struct sss_domain_info);
+    assert_non_null(test_ctx->dom);
+    test_ctx->dom->name = discard_const(DOMNAME);
+
+    test_ctx->subdom = talloc_zero(test_ctx, struct sss_domain_info);
+    assert_non_null(test_ctx->subdom);
+    test_ctx->subdom->name = discard_const(SUBDOMNAME);
+    test_ctx->subdom->parent = test_ctx->dom;
+
+    ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx);
+    assert_non_null(ad_ctx);
+
+    ad_ctx->ad_options = ad_create_default_options(ad_ctx,
+                                                   REALMNAME, HOST_NAME);
+    assert_non_null(ad_ctx->ad_options);
+
+    ad_ctx->gc_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx);
+    assert_non_null(ad_ctx->gc_ctx);
+
+    ad_ctx->ldap_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx);
+    assert_non_null(ad_ctx->ldap_ctx);
+
+    ad_ctx->sdap_id_ctx = talloc_zero(ad_ctx, struct sdap_id_ctx);
+    assert_non_null(ad_ctx->sdap_id_ctx);
+
+    ad_ctx->sdap_id_ctx->opts = talloc_zero(ad_ctx->sdap_id_ctx,
+                                            struct sdap_options);
+    assert_non_null(ad_ctx->sdap_id_ctx->opts);
+
+    ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->dom, &sdom);
+    assert_int_equal(ret, EOK);
+
+    subdom_ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx);
+    assert_non_null(subdom_ad_ctx);
+
+    subdom_ldap_ctx = talloc_zero(subdom_ad_ctx, struct sdap_id_conn_ctx);
+    assert_non_null(subdom_ldap_ctx);
+    subdom_ad_ctx->ldap_ctx = subdom_ldap_ctx;
+
+    ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->subdom, &sdom);
+    assert_int_equal(ret, EOK);
+    sdom->pvt = subdom_ad_ctx;
+
+    test_ctx->ad_ctx = ad_ctx;
+    test_ctx->subdom_ad_ctx = subdom_ad_ctx;
+
+    check_leaks_push(test_ctx);
+    *state = test_ctx;
+}
+
+static void
+ad_common_test_teardown(void **state)
+{
+    struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
+                                                  struct ad_common_test_ctx);
+    assert_non_null(test_ctx);
+
+    assert_true(check_leaks_pop(test_ctx) == true);
+    talloc_free(test_ctx);
+    assert_true(check_leaks_pop(global_talloc_context) == true);
+    assert_true(leak_check_teardown());
+}
+
+errno_t
+__wrap_sdap_set_sasl_options(struct sdap_options *id_opts,
+                             char *default_primary,
+                             char *default_realm,
+                             const char *keytab_path)
+{
+    /* Pretend SASL is fine */
+    return EOK;
+}
+
+void test_ldap_conn_list(void **state)
+{
+    struct sdap_id_conn_ctx *conn;
+
+    struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
+                                                     struct ad_common_test_ctx);
+    assert_non_null(test_ctx);
+
+    conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->dom);
+    assert_true(conn == test_ctx->ad_ctx->ldap_ctx);
+
+    conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->subdom);
+    assert_true(conn == test_ctx->subdom_ad_ctx->ldap_ctx);
+}
+
+void test_conn_list(void **state)
+{
+    struct sdap_id_conn_ctx **conn_list;
+
+    struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
+                                                     struct ad_common_test_ctx);
+    assert_non_null(test_ctx);
+
+    conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom);
+    assert_non_null(conn_list);
+
+    assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
+    /* If there is a fallback, we should ignore the offline mode */
+    assert_true(conn_list[0]->ignore_mark_offline);
+    assert_true(conn_list[1] == test_ctx->ad_ctx->ldap_ctx);
+    assert_false(conn_list[1]->ignore_mark_offline);
+    assert_true(conn_list[2] == NULL);
+    talloc_free(conn_list);
+
+    conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom);
+    assert_non_null(conn_list);
+
+    assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
+    assert_false(conn_list[0]->ignore_mark_offline);
+    assert_true(conn_list[1] == NULL);
+    talloc_free(conn_list);
+}
+
+int main(int argc, const char *argv[])
+{
+    poptContext pc;
+    int opt;
+    struct poptOption long_options[] = {
+        POPT_AUTOHELP
+        SSSD_DEBUG_OPTS
+        POPT_TABLEEND
+    };
+
+    const UnitTest tests[] = {
+        unit_test_setup_teardown(test_ldap_conn_list,
+                                 ad_common_test_setup,
+                                 ad_common_test_teardown),
+        unit_test_setup_teardown(test_conn_list,
+                                 ad_common_test_setup,
+                                 ad_common_test_teardown),
+    };
+
+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
+    debug_level = SSSDBG_INVALID;
+
+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+    while((opt = poptGetNextOpt(pc)) != -1) {
+        switch(opt) {
+        default:
+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
+                    poptBadOption(pc, 0), poptStrerror(opt));
+            poptPrintUsage(pc, stderr, 0);
+            return 1;
+        }
+    }
+    poptFreeContext(pc);
+
+    DEBUG_INIT(debug_level);
+
+    tests_set_cwd();
+
+    return run_tests(tests);
+}
-- 
1.8.4.2

-------------- next part --------------
>From e227234cc6d334bb2b9f93f1fd667be0c4515b0a Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Fri, 29 Nov 2013 11:39:09 +0100
Subject: [PATCH 2/3] AD: Add a new option to turn off GC lookups

SSSD now defaults to using GC by default. For some environments, for
instance those that don't or can't replicate the POSIX attributes to
Global Catalog, this might not be desirable.

This patch introduces a new option ad_enable_gc, that is enabled by
default. Setting this option to false makes the SSSD contact only the
LDAP port of AD DCs.
---
 src/config/etc/sssd.api.d/sssd-ad.conf |  1 +
 src/man/sssd-ad.5.xml                  | 17 +++++++++++++++++
 src/providers/ad/ad_common.c           | 31 ++++++++++++++++++-------------
 src/providers/ad/ad_common.h           |  1 +
 src/providers/ad/ad_opts.h             |  1 +
 src/tests/cmocka/test_ad_common.c      | 20 ++++++++++++++++++++
 6 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index cea28a18cea44546e99a9e51d1a3bb3b860138c7..6b136f2ec88614092cf1ceb4e2cea79db064d468 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -5,6 +5,7 @@ ad_backup_server = str, None, false
 ad_hostname = str, None, false
 ad_enable_dns_sites = bool, None, false
 ad_access_filter = str, None, false
+ad_enable_gc = bool, None, false
 ldap_uri = str, None, false
 ldap_backup_uri = str, None, false
 ldap_search_base = str, None, false
diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
index 0484af3e3b3e9927b280fd638dbb1c14a9060ac2..b763e42ed40954b64bc26c76f8ce601402f5cdfa 100644
--- a/src/man/sssd-ad.5.xml
+++ b/src/man/sssd-ad.5.xml
@@ -228,6 +228,23 @@ FOREST:EXAMPLE.COM:(memberOf=cn=admins,ou=groups,dc=example,dc=com)
                 </varlistentry>
 
                 <varlistentry>
+                    <term>ad_enable_gc (boolean)</term>
+                    <listitem>
+                        <para>
+                            By default, the SSSD connects to the Global
+                            Catalog first to retrieve users and uses the
+                            LDAP port to retrieve group memberships or
+                            as a fallback. Disabling this option makes
+                            the SSSD only connect to the LDAP port of the
+                            current AD server.
+                        </para>
+                        <para>
+                            Default: true
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
                     <term>dyndns_update (boolean)</term>
                     <listitem>
                         <para>
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index af0ec839964233c7642205f4489e5b6462509848..a5ea4f587f30575a5903d8ae1a459f53512c011f 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -1125,26 +1125,31 @@ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
                 struct sss_domain_info *dom)
 {
     struct sdap_id_conn_ctx **clist;
+    int cindex = 0;
 
     clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3);
     if (clist == NULL) return NULL;
 
     /* Always try GC first */
-    clist[0] = ad_ctx->gc_ctx;
-    if (IS_SUBDOMAIN(dom) == true) {
-        clist[0]->ignore_mark_offline = false;
-        /* Subdomain users are only present in GC. */
-        return clist;
+    if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) {
+        clist[cindex] = ad_ctx->gc_ctx;
+        if (IS_SUBDOMAIN(dom) == true) {
+            clist[cindex]->ignore_mark_offline = false;
+            /* Subdomain users are only present in GC. */
+            return clist;
+        }
+        /* fall back to ldap if gc is not available */
+        clist[cindex]->ignore_mark_offline = true;
+        cindex++;
     }
 
-    /* fall back to ldap if gc is not available */
-    clist[0]->ignore_mark_offline = true;
-
-    /* With root domain users we have the option to
-     * fall back to LDAP in case ie POSIX attributes
-     * are used but not replicated to GC
-     */
-    clist[1] = ad_ctx->ldap_ctx;
+    if (IS_SUBDOMAIN(dom) == false) {
+        /* With root domain users we have the option to
+         * fall back to LDAP in case ie POSIX attributes
+         * are used but not replicated to GC
+         */
+        clist[cindex] = ad_ctx->ldap_ctx;
+    }
 
     return clist;
 }
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index ed5b8584dc5327a24e60985486c6155604271fd2..d370cef69124c127f41d7c4cbaa25713363e7752 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -42,6 +42,7 @@ enum ad_basic_opt {
     AD_KRB5_REALM,
     AD_ENABLE_DNS_SITES,
     AD_ACCESS_FILTER,
+    AD_ENABLE_GC,
 
     AD_OPTS_BASIC /* opts counter */
 };
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
index 75c2613146d736cb20e59434b8b0ee455f2d2118..6b4e874edc8f9cac3c141cb22d4d78ee8320b75d 100644
--- a/src/providers/ad/ad_opts.h
+++ b/src/providers/ad/ad_opts.h
@@ -36,6 +36,7 @@ struct dp_option ad_basic_opts[] = {
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING},
     { "ad_enable_dns_sites", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     { "ad_access_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING},
+    { "ad_enable_gc", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     DP_OPTION_TERMINATOR
 };
 
diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
index fe24d7cc8a02b798fd1e612a6eb5ede4bffa9e84..c7de8e9ca8e4662a5d05ec782916293c6660a645 100644
--- a/src/tests/cmocka/test_ad_common.c
+++ b/src/tests/cmocka/test_ad_common.c
@@ -159,6 +159,8 @@ void test_conn_list(void **state)
                                                      struct ad_common_test_ctx);
     assert_non_null(test_ctx);
 
+    assert_true(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic,
+                                AD_ENABLE_GC));
     conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom);
     assert_non_null(conn_list);
 
@@ -177,6 +179,24 @@ void test_conn_list(void **state)
     assert_false(conn_list[0]->ignore_mark_offline);
     assert_true(conn_list[1] == NULL);
     talloc_free(conn_list);
+
+    dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false);
+    assert_false(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic,
+                                 AD_ENABLE_GC));
+
+    conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom);
+    assert_non_null(conn_list);
+
+    assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx);
+    assert_false(conn_list[0]->ignore_mark_offline);
+    assert_true(conn_list[1] == NULL);
+    talloc_free(conn_list);
+
+    conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom);
+    assert_non_null(conn_list);
+
+    assert_true(conn_list[0] == NULL);
+    talloc_free(conn_list);
 }
 
 int main(int argc, const char *argv[])
-- 
1.8.4.2

-------------- next part --------------
>From 0fede9d56ce693057d05e7f608cd5aff30377215 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Fri, 13 Dec 2013 20:11:11 +0100
Subject: [PATCH 3/3] AD: Enable fallback to LDAP of trusted domain

Since we have the LDAP port of a trusted AD GC always available now, we
can always perform a fallback.
---
 src/providers/ad/ad_common.c      | 14 +-------------
 src/tests/cmocka/test_ad_common.c |  7 ++++---
 2 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index a5ea4f587f30575a5903d8ae1a459f53512c011f..99fa4c07af2a79bb3ca195214ddb0dbd60c61620 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -1133,23 +1133,11 @@ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
     /* Always try GC first */
     if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) {
         clist[cindex] = ad_ctx->gc_ctx;
-        if (IS_SUBDOMAIN(dom) == true) {
-            clist[cindex]->ignore_mark_offline = false;
-            /* Subdomain users are only present in GC. */
-            return clist;
-        }
-        /* fall back to ldap if gc is not available */
         clist[cindex]->ignore_mark_offline = true;
         cindex++;
     }
 
-    if (IS_SUBDOMAIN(dom) == false) {
-        /* With root domain users we have the option to
-         * fall back to LDAP in case ie POSIX attributes
-         * are used but not replicated to GC
-         */
-        clist[cindex] = ad_ctx->ldap_ctx;
-    }
+    clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom);
 
     return clist;
 }
diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
index c7de8e9ca8e4662a5d05ec782916293c6660a645..b4522f8d4636fb1a4af0df3ecbd22d3cee9228be 100644
--- a/src/tests/cmocka/test_ad_common.c
+++ b/src/tests/cmocka/test_ad_common.c
@@ -176,8 +176,9 @@ void test_conn_list(void **state)
     assert_non_null(conn_list);
 
     assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
-    assert_false(conn_list[0]->ignore_mark_offline);
-    assert_true(conn_list[1] == NULL);
+    assert_true(conn_list[0]->ignore_mark_offline);
+    assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx);
+    assert_false(conn_list[1]->ignore_mark_offline);
     talloc_free(conn_list);
 
     dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false);
@@ -195,7 +196,7 @@ void test_conn_list(void **state)
     conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom);
     assert_non_null(conn_list);
 
-    assert_true(conn_list[0] == NULL);
+    assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx);
     talloc_free(conn_list);
 }
 
-- 
1.8.4.2



More information about the sssd-devel mailing list