URL: https://github.com/SSSD/sssd/pull/610
Author: jhrozek
 Title: #610: AD: consult the Partial Attribute Set instead of searching the GC 
for POSIX attributes
Action: opened

PR body:
"""
These patches implement fixes that should improve the performance of
detecting the presence of the POSIX attributes in the Global Catalog.

Instead of running the full search `(|(uidNumber=*)(gidNumber=*))` with
sizelimit=1 which causes the server to first find a full page of results
and then return only one, consult the AD schema which marks the attributes
replicated to the Global Catalog.

More details are described in the desing page PR at
https://pagure.io/SSSD/docs/pull-request/69
"""

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/610/head:pr610
git checkout pr610
From 46d2945df8ac7c9aa2362860ea528666c7386b1c Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Fri, 29 Jun 2018 12:30:20 +0200
Subject: [PATCH 1/6] AD: Refactor ad_account_info_handler_send() to allow
 adding a request there later

Just splits the send function into a new function
ad_account_info_handler_lookup(). Later in the patchset, we will
introduce a function that looksup POSIX attributes in the Global Catalog
and we'll want to put the new request between
ad_account_info_handler_send() and ad_account_info_handler_lookup().

Related:
https://pagure.io/SSSD/sssd/issue/3755
---
 src/providers/ad/ad_id.c | 86 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 55 insertions(+), 31 deletions(-)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 782d9bc40..499879948 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -385,10 +385,16 @@ get_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
 }
 
 struct ad_account_info_handler_state {
-    struct sss_domain_info *domain;
+    struct ad_id_ctx *id_ctx;
+    struct dp_id_data *data;
+    struct sdap_id_ctx *sdap_id_ctx;
+    struct be_ctx *be_ctx;
+
+    struct sdap_domain *sdom;
     struct dp_reply_std reply;
 };
 
+static errno_t ad_account_info_handler_lookup(struct tevent_req *req);
 static void ad_account_info_handler_done(struct tevent_req *subreq);
 
 struct tevent_req *
@@ -398,24 +404,20 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx,
                               struct dp_req_params *params)
 {
     struct ad_account_info_handler_state *state;
-    struct sdap_id_conn_ctx **clist;
-    struct sdap_id_ctx *sdap_id_ctx;
-    struct sss_domain_info *domain;
-    struct sdap_domain *sdom;
-    struct tevent_req *subreq;
     struct tevent_req *req;
-    struct be_ctx *be_ctx;
+    struct sss_domain_info *domain;
     errno_t ret;
 
-    sdap_id_ctx = id_ctx->sdap_id_ctx;
-    be_ctx = params->be_ctx;
-
     req = tevent_req_create(mem_ctx, &state,
                             struct ad_account_info_handler_state);
     if (req == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
         return NULL;
     }
+    state->id_ctx = id_ctx;
+    state->data = data;
+    state->sdap_id_ctx = id_ctx->sdap_id_ctx;
+    state->be_ctx = params->be_ctx;
 
     if (sdap_is_enum_request(data)) {
         DEBUG(SSSDBG_TRACE_LIBS, "Skipping enumeration on demand\n");
@@ -423,41 +425,32 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx,
         goto immediately;
     }
 
-    domain = be_ctx->domain;
-    if (strcasecmp(data->domain, be_ctx->domain->name) != 0) {
+    domain = state->be_ctx->domain;
+    if (strcasecmp(data->domain, state->be_ctx->domain->name) != 0) {
         /* Subdomain request, verify subdomain. */
-        domain = find_domain_by_name(be_ctx->domain, data->domain, true);
+        domain = find_domain_by_name(state->be_ctx->domain,
+                                     data->domain,
+                                     true);
     }
 
     if (domain == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find domain %s\n", data->domain);
         ret = EINVAL;
         goto immediately;
     }
 
-    /* Determine whether to connect to GC, LDAP or try both. */
-    clist = get_conn_list(state, id_ctx, domain, data);
-    if (clist == NULL) {
-        ret = EIO;
-        goto immediately;
-    }
-
-    sdom = sdap_domain_get(sdap_id_ctx->opts, domain);
-    if (sdom == NULL) {
-        ret = EIO;
+    state->sdom = sdap_domain_get(state->sdap_id_ctx->opts,
+                                  domain);
+    if (state->sdom == NULL) {
+        ret = EINVAL;
         goto immediately;
     }
 
-    state->domain = sdom->dom;
-
-    subreq = ad_handle_acct_info_send(state, data, sdap_id_ctx,
-                                      id_ctx->ad_options, sdom, clist);
-    if (subreq == NULL) {
-        ret = ENOMEM;
+    ret = ad_account_info_handler_lookup(req);
+    if (ret != EAGAIN) {
         goto immediately;
     }
 
-    tevent_req_set_callback(subreq, ad_account_info_handler_done, req);
-
     return req;
 
 immediately:
@@ -470,6 +463,37 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx,
     return req;
 }
 
+static errno_t ad_account_info_handler_lookup(struct tevent_req *req)
+{
+    struct ad_account_info_handler_state *state = NULL;
+    struct sdap_id_conn_ctx **clist = NULL;
+    struct tevent_req *subreq = NULL;
+
+    state = tevent_req_data(req, struct ad_account_info_handler_state);
+
+    /* Determine whether to connect to GC, LDAP or try both. */
+    clist = get_conn_list(state,
+                          state->id_ctx,
+                          state->sdom->dom,
+                          state->data);
+    if (clist == NULL) {
+        return EIO;
+    }
+
+    subreq = ad_handle_acct_info_send(state,
+                                      state->data,
+                                      state->sdap_id_ctx,
+                                      state->id_ctx->ad_options,
+                                      state->sdom,
+                                      clist);
+    if (subreq == NULL) {
+        return ENOMEM;
+    }
+
+    tevent_req_set_callback(subreq, ad_account_info_handler_done, req);
+    return EAGAIN;
+}
+
 static void ad_account_info_handler_done(struct tevent_req *subreq)
 {
     struct ad_account_info_handler_state *state;

From e7264b211111b65dba4bb59c5207615498ad3149 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Wed, 20 Jun 2018 09:25:13 +0200
Subject: [PATCH 2/6] AD: Check for POSIX attribute presence by looking at the
 schema

Addsa a new tevent request which checks for the presence of uidNumber
and gidNumber under cn=schema,cn=configuration,$BASEDN. For both
objects representing each of the attributes, the
isMemberOfPartialAttributeSet attribute is requested. If this attribute
is set to TRUE, then the attribute corresponding to this schema object
had been replicated to the Global Catalog.

Because the isMemberOfPartialAttributeSet is not replicated to the GC
itself, we use the LDAP connection for the search.

Adds a new flag called posix_gc_checked to the ad_id_ctx and makes sure
to explicitly initialize the flag instead of relying on talloc_zero().

Related:
https://pagure.io/SSSD/sssd/issue/3755
---
 src/providers/ad/ad_common.c |   4 +
 src/providers/ad/ad_common.h |   7 +
 src/providers/ad/ad_id.c     | 321 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 332 insertions(+)

diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index eaf0814f1..8b531d4f9 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -232,6 +232,8 @@ ad_create_options(TALLOC_CTX *mem_ctx,
     ad_options = talloc_zero(mem_ctx, struct ad_options);
     if (ad_options == NULL) return NULL;
 
+    ad_options->posix_gc_checked = false;
+
     if (cdb != NULL && conf_path != NULL) {
         ret = dp_get_options(ad_options,
                              cdb,
@@ -426,6 +428,8 @@ ad_get_common_options(TALLOC_CTX *mem_ctx,
     opts = talloc_zero(mem_ctx, struct ad_options);
     if (!opts) return ENOMEM;
 
+    opts->posix_gc_checked = false;
+
     ret = dp_get_options(opts, cdb, conf_path,
                          ad_basic_opts,
                          AD_OPTS_BASIC,
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index dd440da33..5a4fcdfc0 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -38,6 +38,10 @@
 
 #define MASTER_DOMAIN_SID_FILTER "objectclass=domain"
 
+#define AD_AT_SCHEMA_NAME       "cn"
+#define AD_AT_SCHEMA_IS_REPL    "isMemberOfPartialAttributeSet"
+#define AD_SCHEMA_BASE_FMT      "cn=schema,cn=configuration,%s"
+
 struct ad_options;
 
 enum ad_basic_opt {
@@ -97,6 +101,9 @@ struct ad_options {
     /* Dynamic DNS updates */
     struct be_resolv_ctx *be_res;
     struct be_nsupdate_ctx *dyndns_ctx;
+
+    /* Did we already check for POSIX attr presence in GC? */
+    bool posix_gc_checked;
 };
 
 errno_t
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 499879948..77b2493d1 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -124,6 +124,262 @@ static bool ad_account_can_shortcut(struct sdap_idmap_ctx *idmap_ctx,
     return shortcut;
 }
 
+static errno_t ad_check_posix_attrs_retry(struct tevent_req *req);
+static void ad_check_posix_attrs_connected(struct tevent_req *subreq);
+static void ad_check_posix_attrs_search_done(struct tevent_req *subreq);
+
+struct ad_check_posix_attrs_state {
+    struct tevent_context *ev;
+    struct sdap_options *opts;
+
+    struct sdap_id_op *op;
+
+    const char *attrs[3];
+
+    bool has_posix;
+};
+
+struct tevent_req *
+ad_check_posix_attrs_send(TALLOC_CTX *mem_ctx,
+                          struct tevent_context *ev,
+                          struct ad_id_ctx *id_ctx)
+{
+    struct ad_check_posix_attrs_state *state;
+    struct tevent_req *req;
+    errno_t ret;
+
+    req = tevent_req_create(mem_ctx, &state,
+                            struct ad_check_posix_attrs_state);
+    if (req == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+        return NULL;
+    }
+    state->ev = ev;
+    state->opts = id_ctx->sdap_id_ctx->opts;
+
+    state->attrs[0] = AD_AT_SCHEMA_NAME;
+    state->attrs[1] = AD_AT_SCHEMA_IS_REPL;
+    state->attrs[2] = NULL;
+
+    DEBUG(SSSDBG_TRACE_FUNC, "Checking for POSIX attributes in GC\n");
+
+    /* Since the schema is replicated forest-wide, it is safest
+     * to search the joined domain over the LDAP port, hence
+     * id_ctx->ldap_ctx->conn_cache
+     */
+    state->op = sdap_id_op_create(state, id_ctx->ldap_ctx->conn_cache);
+    if (state->op == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    ret = ad_check_posix_attrs_retry(req);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "Connection error [%d]: %s\n", ret, sss_strerror(ret));
+        goto immediately;
+    }
+
+    return req;
+
+immediately:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static errno_t ad_check_posix_attrs_retry(struct tevent_req *req)
+{
+    struct ad_check_posix_attrs_state *state = tevent_req_data(req,
+                                          struct ad_check_posix_attrs_state);
+    struct tevent_req *subreq;
+    errno_t ret;
+
+    subreq = sdap_id_op_connect_send(state->op, state, &ret);
+    if (subreq == NULL) {
+        return ENOMEM;
+    }
+
+    tevent_req_set_callback(subreq, ad_check_posix_attrs_connected, req);
+    return ret;
+}
+
+static void ad_check_posix_attrs_connected(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_check_posix_attrs_state *state = tevent_req_data(req,
+                                          struct ad_check_posix_attrs_state);
+    int dp_error = DP_ERR_FATAL;
+    errno_t ret;
+    const char *basedn;
+    const char *filter;
+
+    ret = sdap_id_op_connect_recv(subreq, &dp_error);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "Unable to connect to LDAP "
+              "[%d]: %s\n", ret, sss_strerror(ret));
+        if (dp_error == DP_ERR_OFFLINE) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
+                  "cannot get the subdomain list while offline\n");
+            ret = ERR_OFFLINE;
+        }
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    basedn = talloc_asprintf(state,
+                             AD_SCHEMA_BASE_FMT,
+                             dp_opt_get_string(state->opts->basic,
+                                               SDAP_SEARCH_BASE));
+    if (basedn == NULL) {
+        tevent_req_error(req, ENOMEM);
+        return;
+    }
+
+    filter = talloc_asprintf(state,
+                             "(|(cn=%s)(cn=%s))",
+                             state->opts->user_map[SDAP_AT_USER_UID].name,
+                             state->opts->group_map[SDAP_AT_GROUP_GID].name);
+    if (filter == NULL) {
+        tevent_req_error(req, ENOMEM);
+        return;
+    }
+
+    subreq = sdap_get_generic_send(state,
+                                   state->ev,
+                                   state->opts,
+                                   sdap_id_op_handle(state->op),
+                                   basedn,
+                                   LDAP_SCOPE_SUBTREE,
+                                   filter,
+                                   state->attrs,
+                                   NULL, 0,
+                                   dp_opt_get_int(state->opts->basic,
+                                                  SDAP_SEARCH_TIMEOUT),
+                                   false);
+    if (subreq == NULL) {
+        tevent_req_error(req, ENOMEM);
+        return;
+    }
+    tevent_req_set_callback(subreq, ad_check_posix_attrs_search_done, req);
+
+}
+
+static void ad_check_posix_attrs_search_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_check_posix_attrs_state *state = tevent_req_data(req,
+                                          struct ad_check_posix_attrs_state);
+    errno_t ret;
+    size_t reply_count;
+    struct sysdb_attrs **reply;
+    bool uid = false;
+    bool gid = false;
+    int dp_error;
+
+    ret = sdap_get_generic_recv(subreq, state, &reply_count, &reply);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "sdap_get_generic_recv failed [%d]: %s\n",
+              ret, strerror(ret));
+        /* We continue to finish sdap_id_op. */
+    }
+
+    ret = sdap_id_op_done(state->op, ret, &dp_error);
+    if (dp_error == DP_ERR_OK && ret != EOK) {
+        /* retry */
+        DEBUG(SSSDBG_MINOR_FAILURE, "Retrying..\n");
+        ret = ad_check_posix_attrs_retry(req);
+        if (ret != EOK) {
+            tevent_req_error(req, ret);
+            return;
+        }
+        return;
+    } else if (dp_error == DP_ERR_OFFLINE) {
+        DEBUG(SSSDBG_MINOR_FAILURE, "Returning ERR_OFFLINE\n");
+        tevent_req_error(req, ERR_OFFLINE);
+        return;
+    } else if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "sdap_id_op failed [%d]: %s\n", ret, sss_strerror(ret));
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    if (reply_count == 0) {
+        DEBUG(SSSDBG_TRACE_LIBS,
+              "Nothing found, so no POSIX attrs can exist\n");
+        state->has_posix = false;
+        tevent_req_done(req);
+        return;
+    }
+
+    for (size_t i = 0; i < reply_count; i++) {
+        const char *name = NULL;
+        const char *is_in_partial_set = NULL;
+        bool *val = NULL;
+
+        ret = sysdb_attrs_get_string(reply[i], AD_AT_SCHEMA_NAME, &name);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Cannot get "AD_AT_SCHEMA_NAME);
+            continue;
+        }
+
+        if (strcasecmp(name, state->opts->user_map[SDAP_AT_USER_UID].name) == 0) {
+            val = &uid;
+        } else if (strcasecmp(name, state->opts->user_map[SDAP_AT_USER_GID].name) == 0) {
+            val = &gid;
+        } else {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected attribute\n");
+            continue;
+        }
+
+        ret = sysdb_attrs_get_string(reply[i],
+                                     AD_AT_SCHEMA_IS_REPL,
+                                     &is_in_partial_set);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_MINOR_FAILURE, "Cannot get "AD_AT_SCHEMA_IS_REPL);
+            continue;
+        }
+
+        if (strcasecmp(is_in_partial_set, "true") == 0) {
+            *val = true;
+        }
+    }
+
+    if (uid == true && gid == true) {
+        state->has_posix = true;
+    }
+
+    if (state->has_posix == true) {
+        DEBUG(SSSDBG_FUNC_DATA, "Server has POSIX attributes. Global Catalog will "
+                                "be used for user and group lookups. Note that if "
+                                "only a subset of POSIX attributes is present "
+                                "in GC, the non-replicated attributes are "
+                                "currently not read from the LDAP port\n");
+    }
+
+    tevent_req_done(req);
+}
+
+errno_t ad_check_posix_attrs_recv(struct tevent_req *req,
+                                   bool *_has_posix)
+{
+    struct ad_check_posix_attrs_state *state = NULL;
+
+    state = tevent_req_data(req, struct ad_check_posix_attrs_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *_has_posix = state->has_posix;
+    return EOK;
+}
+
 struct ad_handle_acct_info_state {
     struct dp_id_data *ar;
     struct sdap_id_ctx *ctx;
@@ -394,6 +650,8 @@ struct ad_account_info_handler_state {
     struct dp_reply_std reply;
 };
 
+static void ad_account_info_handler_gc_check_done(struct tevent_req *subreq);
+static void ad_account_info_handler_done(struct tevent_req *subreq);
 static errno_t ad_account_info_handler_lookup(struct tevent_req *req);
 static void ad_account_info_handler_done(struct tevent_req *subreq);
 
@@ -407,6 +665,8 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx,
     struct tevent_req *req;
     struct sss_domain_info *domain;
     errno_t ret;
+    bool use_id_mapping;
+    struct tevent_req *subreq;
 
     req = tevent_req_create(mem_ctx, &state,
                             struct ad_account_info_handler_state);
@@ -446,6 +706,33 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx,
         goto immediately;
     }
 
+    if (dp_opt_get_bool(id_ctx->ad_options->basic, AD_ENABLE_GC) == true
+                && state->id_ctx->ad_options->posix_gc_checked == false) {
+        /* If this is the very first lookup against a domain that has POSIX attributes
+         * enabled, check for POSIX attributes presence in GC
+         */
+        state->id_ctx->ad_options->posix_gc_checked = true;
+
+        use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                            state->sdap_id_ctx->opts->idmap_ctx,
+                                            state->sdom->dom->name,
+                                            state->sdom->dom->domain_id);
+        if (use_id_mapping == true) {
+            DEBUG(SSSDBG_CONF_SETTINGS,
+                  "No point in checking POSIX attributes with GC if ID-mapping "
+                  "is enabled\n");
+            /* Don't even evaluate this condition from now on */
+        } else {
+            subreq = ad_check_posix_attrs_send(state, params->ev, id_ctx);
+            if (subreq == NULL) {
+                ret = ENOMEM;
+                goto immediately;
+            }
+            tevent_req_set_callback(subreq, ad_account_info_handler_gc_check_done, req);
+            return req;
+        }
+    }
+
     ret = ad_account_info_handler_lookup(req);
     if (ret != EAGAIN) {
         goto immediately;
@@ -463,6 +750,40 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx,
     return req;
 }
 
+static void ad_account_info_handler_gc_check_done(struct tevent_req *subreq)
+{
+    struct ad_account_info_handler_state *state;
+    struct tevent_req *req;
+    errno_t ret;
+    bool has_posix;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct ad_account_info_handler_state);
+
+    ret = ad_check_posix_attrs_recv(subreq, &has_posix);
+    if (ret != EOK) {
+        /* Would it be better to carry on with the GC and hope for the
+         * best? */
+        DEBUG(SSSDBG_IMPORTANT_INFO,
+              "Cannot check if the Global Catalog has POSIX data, "
+              "the Global Catalog will be disabled\n");
+        has_posix = false;
+    }
+
+    if (has_posix == false) {
+        disable_gc(state->id_ctx->ad_options);
+    }
+
+    ret = ad_account_info_handler_lookup(req);
+    if (ret != EAGAIN) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "ad_account_info_handler_lookup failed [%d]: %s\n",
+              ret, sss_strerror(ret));
+        tevent_req_error(req, ret);
+        return;
+    }
+}
+
 static errno_t ad_account_info_handler_lookup(struct tevent_req *req)
 {
     struct ad_account_info_handler_state *state = NULL;

From 6c7b3a19d51043b5584b13cdc2f8a485436426e2 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Fri, 29 Jun 2018 13:44:45 +0200
Subject: [PATCH 3/6] AD: Replace sdap_gc_posix_check with ad_check_posix_attrs
 in domain locator request

Instead of the old sdap_gc_posix_check_send() request use the new
ad_check_posix_attrs request.

The connection handling is a bit different in the domain locator request
after this patch, because previously both the domain locator and the
sdap posix check used the Global Catalog connection.

Now, the ad_check_posix_attrs request handles its LDAP connection
internally, the domain locator connects after the POSIX check (if
needed) and finishes the sdap operation immediately.

Related:
https://pagure.io/SSSD/sssd/issue/3755
---
 src/providers/ad/ad_id.c | 85 +++++++++++++++++++++++++-----------------------
 1 file changed, 45 insertions(+), 40 deletions(-)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 77b2493d1..37942c379 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -1463,6 +1463,7 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx,
 {
     struct ad_get_account_domain_state *state;
     struct tevent_req *req;
+    struct tevent_req *subreq;
     errno_t ret;
     bool use_id_mapping;
 
@@ -1549,6 +1550,23 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx,
         goto immediately;
     }
 
+    /* If POSIX attributes have been requested with an AD server and we
+     * have no idea about POSIX attributes support, run a one-time check
+     */
+    if (id_ctx->ad_options->posix_gc_checked == false) {
+        subreq = ad_check_posix_attrs_send(state,
+                                           state->ev,
+                                           state->id_ctx);
+        if (subreq == NULL) {
+            ret = ENOMEM;
+            goto immediately;
+        }
+        tevent_req_set_callback(subreq, ad_get_account_domain_posix_check_done, req);
+
+        state->id_ctx->ad_options->posix_gc_checked = true;
+        return req;
+    }
+
     ret = ad_get_account_domain_connect_retry(req);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE, "Connection error");
@@ -1648,26 +1666,6 @@ static void ad_get_account_domain_connect_done(struct tevent_req *subreq)
         return;
     }
 
-    /* If POSIX attributes have been requested with an AD server and we
-     * have no idea about POSIX attributes support, run a one-time check
-     */
-    if (state->sdap_id_ctx->srv_opts &&
-        state->sdap_id_ctx->srv_opts->posix_checked == false) {
-        subreq = sdap_gc_posix_check_send(state,
-                                          state->ev,
-                                          state->sdap_id_ctx->opts,
-                                          sdap_id_op_handle(state->op),
-                                          dp_opt_get_int(
-                                              state->sdap_id_ctx->opts->basic,
-                                              SDAP_SEARCH_TIMEOUT));
-        if (subreq == NULL) {
-            tevent_req_error(req, ENOMEM);
-            return;
-        }
-        tevent_req_set_callback(subreq, ad_get_account_domain_posix_check_done, req);
-        return;
-    }
-
     ad_get_account_domain_search(req);
 }
 
@@ -1677,33 +1675,16 @@ static void ad_get_account_domain_posix_check_done(struct tevent_req *subreq)
                                                       struct tevent_req);
     struct ad_get_account_domain_state *state = tevent_req_data(req,
                                           struct ad_get_account_domain_state);
-    int dp_error = DP_ERR_FATAL;
     bool has_posix;
     errno_t ret;
-    errno_t ret2;
 
-    ret = sdap_gc_posix_check_recv(subreq, &has_posix);
+    ret = ad_check_posix_attrs_recv(subreq, &has_posix);
     talloc_zfree(subreq);
     if (ret != EOK) {
-        /* We can only finish the id_op on error as the connection
-         * is re-used by the real search
-         */
-        ret2 = sdap_id_op_done(state->op, ret, &dp_error);
-        if (dp_error == DP_ERR_OK && ret2 != EOK) {
-            /* retry */
-            ret = ad_get_account_domain_connect_retry(req);
-            if (ret != EOK) {
-                tevent_req_error(req, ret);
-            }
-            return;
-        }
-
-        tevent_req_error(req, ret);
+        has_posix = false;
         return;
     }
 
-    state->sdap_id_ctx->srv_opts->posix_checked = true;
-
     /*
      * If the GC has no POSIX attributes, there is nothing we can do.
      * Return an error and let the responders disable the functionality
@@ -1721,7 +1702,11 @@ static void ad_get_account_domain_posix_check_done(struct tevent_req *subreq)
         return;
     }
 
-    ad_get_account_domain_search(req);
+    ret = ad_get_account_domain_connect_retry(req);
+    if (ret != EAGAIN) {
+        tevent_req_error(req, ret);
+        return;
+    }
 }
 
 static void ad_get_account_domain_search(struct tevent_req *req)
@@ -1766,11 +1751,31 @@ static void ad_get_account_domain_search_done(struct tevent_req *subreq)
     size_t count;
     struct sysdb_attrs **objects;
     errno_t ret;
+    int dp_error;
 
     ret = sdap_get_generic_recv(subreq, state,
                                 &count, &objects);
     talloc_zfree(subreq);
     if (ret) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "sdap_get_generic_recv failed [%d]: %s\n",
+              ret, strerror(ret));
+        /* We continue to finish sdap_id_op. */
+    }
+
+    ret = sdap_id_op_done(state->op, ret, &dp_error);
+    if (dp_error == DP_ERR_OK && ret != EOK) {
+        /* retry */
+        ret = ad_get_account_domain_connect_retry(req);
+        if (ret != EOK) {
+            tevent_req_error(req, ret);
+            return;
+        }
+        return;
+    } else if (dp_error == DP_ERR_OFFLINE) {
+        tevent_req_error(req, ERR_OFFLINE);
+        return;
+    } else if (ret != EOK) {
         tevent_req_error(req, ret);
         return;
     }

From 511af0e2c4db410ffcbd924817a0c68f3f98b2b7 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Sat, 30 Jun 2018 13:11:35 +0200
Subject: [PATCH 4/6] AD: Use the new POSIX check in AD enumeration code

Instead of the old sdap posix check, use the new AD specific one.

Related:
https://pagure.io/SSSD/sssd/issue/3755
---
 src/providers/ad/ad_id.c | 79 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 63 insertions(+), 16 deletions(-)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 37942c379..70dbce6aa 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -862,6 +862,7 @@ struct ad_enumeration_state {
 
 static void ad_enumeration_conn_done(struct tevent_req *subreq);
 static void ad_enumeration_master_done(struct tevent_req *subreq);
+static void ad_enumeration_posix_check_done(struct tevent_req *subreq);
 static errno_t ad_enum_sdom(struct tevent_req *req, struct sdap_domain *sd,
                             struct ad_id_ctx *id_ctx);
 static void ad_enumeration_done(struct tevent_req *subreq);
@@ -975,6 +976,7 @@ ad_enumeration_master_done(struct tevent_req *subreq)
     char *flat_name;
     char *master_sid;
     char *forest;
+    bool use_id_mapping;
 
     ret = ad_master_domain_recv(subreq, state,
                                 &flat_name, &master_sid, NULL, &forest);
@@ -993,6 +995,33 @@ ad_enumeration_master_done(struct tevent_req *subreq)
         return;
     }
 
+    if (dp_opt_get_bool(state->id_ctx->ad_options->basic, AD_ENABLE_GC) == true
+                && state->id_ctx->ad_options->posix_gc_checked == false) {
+        /* If this is the very first lookup against a domain that has POSIX attributes
+         * enabled, check for POSIX attributes presence in GC
+         */
+        use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
+                                state->id_ctx->sdap_id_ctx->opts->idmap_ctx,
+                                state->sdom->dom->name,
+                                state->sdom->dom->domain_id);
+        if (use_id_mapping == true) {
+            DEBUG(SSSDBG_CONF_SETTINGS,
+                  "No point in checking POSIX attributes with GC if ID-mapping "
+                  "is enabled\n");
+            /* Don't even evaluate this condition from now on */
+            state->id_ctx->ad_options->posix_gc_checked = true;
+        } else {
+            subreq = ad_check_posix_attrs_send(state, state->ev, state->id_ctx);
+            if (subreq == NULL) {
+                tevent_req_error(req, ENOMEM);
+                return;
+            }
+            tevent_req_set_callback(subreq, ad_enumeration_posix_check_done, req);
+            return;
+        }
+    }
+
+
     ret = ad_enum_sdom(req, state->sdom, state->id_ctx);
     if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE,
@@ -1004,6 +1033,39 @@ ad_enumeration_master_done(struct tevent_req *subreq)
     /* Execution will resume in ad_enumeration_done */
 }
 
+static void
+ad_enumeration_posix_check_done(struct tevent_req *subreq)
+{
+    errno_t ret;
+    struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                      struct tevent_req);
+    struct ad_enumeration_state *state = tevent_req_data(req,
+                                                struct ad_enumeration_state);
+    bool has_posix;
+
+    ret = ad_check_posix_attrs_recv(subreq, &has_posix);
+    if (ret != EOK) {
+        /* Would it be better to carry on with the GC and hope for the
+         * best? */
+        DEBUG(SSSDBG_IMPORTANT_INFO,
+              "Cannot check if the Global Catalog has POSIX data, "
+              "the Global Catalog will be disabled\n");
+        has_posix = false;
+    }
+
+    if (has_posix == false) {
+        disable_gc(state->id_ctx->ad_options);
+    }
+
+    ret = ad_enum_sdom(req, state->sdom, state->id_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+                "Could not enumerate domain %s\n", state->sdom->dom->name);
+        tevent_req_error(req, ret);
+        return;
+    }
+}
+
 static errno_t
 ad_enum_sdom(struct tevent_req *req,
              struct sdap_domain *sd,
@@ -1055,22 +1117,7 @@ ad_enumeration_done(struct tevent_req *subreq)
 
     ret = sdap_dom_enum_ex_recv(subreq);
     talloc_zfree(subreq);
-    if (ret == ERR_NO_POSIX) {
-        /* Retry enumerating the same domain again, this time w/o
-         * connecting to GC
-         */
-        disable_gc(state->id_ctx->ad_options);
-        ret = ad_enum_sdom(req, state->sditer, state->id_ctx);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE,
-                "Could not retry domain %s\n", state->sditer->dom->name);
-            tevent_req_error(req, ret);
-            return;
-        }
-
-        /* Execution will resume in ad_enumeration_done */
-        return;
-    } else if (ret != EOK) {
+    if (ret != EOK) {
         DEBUG(SSSDBG_OP_FAILURE,
               "Could not enumerate domain %s\n", state->sditer->dom->name);
         tevent_req_error(req, ret);

From 09cfcfcdd08b29023b0821b8f4eddd9a1d5f2c7f Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Sat, 30 Jun 2018 12:31:13 +0200
Subject: [PATCH 5/6] LDAP: Remove the legacy POSIX check from user, group and
 enumeration searches

These are superseded by the checks in the AD handlers themselves.

Related:
https://pagure.io/SSSD/sssd/issue/3755
---
 src/providers/ad/ad_id.c             |   4 +-
 src/providers/ldap/ldap_id.c         | 121 -----------------------------------
 src/providers/ldap/sdap_async_enum.c | 105 +-----------------------------
 3 files changed, 3 insertions(+), 227 deletions(-)

diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 70dbce6aa..05c62a251 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -552,14 +552,12 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
     if (sdap_err == EOK) {
         tevent_req_done(req);
         return;
-    } else if (sdap_err == ERR_NO_POSIX) {
-        disable_gc(state->ad_options);
     } else if (sdap_err != ENOENT) {
         ret = EIO;
         goto fail;
     }
 
-    /* Ret is only ENOENT or ERR_NO_POSIX now. Try the next connection */
+    /* Ret is only ENOENT now. Try the next connection */
     state->cindex++;
     ret = ad_handle_acct_info_step(req);
     if (ret != EAGAIN) {
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index ebf5d9cb2..9e8289904 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -66,7 +66,6 @@ struct users_get_state {
 
 static int users_get_retry(struct tevent_req *req);
 static void users_get_connect_done(struct tevent_req *subreq);
-static void users_get_posix_check_done(struct tevent_req *subreq);
 static void users_get_search(struct tevent_req *req);
 static void users_get_done(struct tevent_req *subreq);
 
@@ -408,66 +407,6 @@ static void users_get_connect_done(struct tevent_req *subreq)
         return;
     }
 
-    /* If POSIX attributes have been requested with an AD server and we
-     * have no idea about POSIX attributes support, run a one-time check
-     */
-    if (should_run_posix_check(state->ctx,
-                               state->conn,
-                               state->use_id_mapping,
-                               !state->non_posix)) {
-        subreq = sdap_gc_posix_check_send(state, state->ev, state->ctx->opts,
-                                          sdap_id_op_handle(state->op),
-                                          dp_opt_get_int(state->ctx->opts->basic,
-                                                         SDAP_SEARCH_TIMEOUT));
-        if (subreq == NULL) {
-            tevent_req_error(req, ENOMEM);
-            return;
-        }
-        tevent_req_set_callback(subreq, users_get_posix_check_done, req);
-        return;
-    }
-
-    users_get_search(req);
-}
-
-static void users_get_posix_check_done(struct tevent_req *subreq)
-{
-    errno_t ret;
-    errno_t ret2;
-    bool has_posix;
-    int dp_error;
-    struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                      struct tevent_req);
-    struct users_get_state *state = tevent_req_data(req,
-                                                    struct users_get_state);
-
-    ret = sdap_gc_posix_check_recv(subreq, &has_posix);
-    talloc_zfree(subreq);
-    if (ret != EOK) {
-        /* We can only finish the id_op on error as the connection
-         * is re-used by the user search
-         */
-        ret2 = sdap_id_op_done(state->op, ret, &dp_error);
-        if (dp_error == DP_ERR_OK && ret2 != EOK) {
-            /* retry */
-            ret = users_get_retry(req);
-            if (ret != EOK) {
-                tevent_req_error(req, ret);
-            }
-            return;
-        }
-    }
-
-    state->ctx->srv_opts->posix_checked = true;
-
-    /* If the check ran to completion, we know for certain about the attributes
-     */
-    if (ret == EOK && has_posix == false) {
-        state->sdap_ret = ERR_NO_POSIX;
-        tevent_req_done(req);
-        return;
-    }
-
     users_get_search(req);
 }
 
@@ -691,7 +630,6 @@ struct groups_get_state {
 
 static int groups_get_retry(struct tevent_req *req);
 static void groups_get_connect_done(struct tevent_req *subreq);
-static void groups_get_posix_check_done(struct tevent_req *subreq);
 static void groups_get_mpg_done(struct tevent_req *subreq);
 static errno_t groups_get_handle_no_group(struct tevent_req *req);
 static void groups_get_search(struct tevent_req *req);
@@ -953,65 +891,6 @@ static void groups_get_connect_done(struct tevent_req *subreq)
         return;
     }
 
-    /* If POSIX attributes have been requested with an AD server and we
-     * have no idea about POSIX attributes support, run a one-time check
-     */
-    if (should_run_posix_check(state->ctx,
-                               state->conn,
-                               state->use_id_mapping,
-                               !state->non_posix)) {
-        subreq = sdap_gc_posix_check_send(state, state->ev, state->ctx->opts,
-                                          sdap_id_op_handle(state->op),
-                                          dp_opt_get_int(state->ctx->opts->basic,
-                                                         SDAP_SEARCH_TIMEOUT));
-        if (subreq == NULL) {
-            tevent_req_error(req, ENOMEM);
-            return;
-        }
-        tevent_req_set_callback(subreq, groups_get_posix_check_done, req);
-        return;
-    }
-
-    groups_get_search(req);
-}
-
-static void groups_get_posix_check_done(struct tevent_req *subreq)
-{
-    errno_t ret;
-    bool has_posix;
-    int dp_error;
-    struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                      struct tevent_req);
-    struct groups_get_state *state = tevent_req_data(req,
-                                                     struct groups_get_state);
-
-    ret = sdap_gc_posix_check_recv(subreq, &has_posix);
-    talloc_zfree(subreq);
-    if (ret != EOK) {
-        /* We can only finish the id_op on error as the connection
-         * is re-used by the group search
-         */
-        ret = sdap_id_op_done(state->op, ret, &dp_error);
-        if (dp_error == DP_ERR_OK && ret != EOK) {
-            /* retry */
-            ret = groups_get_retry(req);
-            if (ret != EOK) {
-                tevent_req_error(req, ret);
-            }
-            return;
-        }
-    }
-
-    state->ctx->srv_opts->posix_checked = true;
-
-    /* If the check ran to completion, we know for certain about the attributes
-     */
-    if (has_posix == false) {
-        state->sdap_ret = ERR_NO_POSIX;
-        tevent_req_done(req);
-        return;
-    }
-
     groups_get_search(req);
 }
 
diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c
index ea9d51adc..899d59d38 100644
--- a/src/providers/ldap/sdap_async_enum.c
+++ b/src/providers/ldap/sdap_async_enum.c
@@ -69,8 +69,6 @@ static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req,
                                       tevent_req_fn tcb);
 static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq);
 static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq);
-static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq);
-static errno_t sdap_dom_enum_search_users(struct tevent_req *req);
 static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq);
 static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq);
 static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq);
@@ -181,118 +179,19 @@ static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq)
                                                       struct tevent_req);
     struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
                                                 struct sdap_dom_enum_ex_state);
-    bool use_id_mapping;
-    errno_t ret;
 
     if (sdap_dom_enum_ex_connected(subreq) == false) {
         return;
     }
 
-    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
-                                            state->ctx->opts->idmap_ctx,
-                                            state->sdom->dom->name,
-                                            state->sdom->dom->domain_id);
-
-    /* If POSIX attributes have been requested with an AD server and we
-     * have no idea about POSIX attributes support, run a one-time check
-     */
-    if (should_run_posix_check(state->ctx,
-                               state->user_conn,
-                               use_id_mapping,
-                               true)) {
-        subreq = sdap_gc_posix_check_send(state, state->ev, state->ctx->opts,
-                                          sdap_id_op_handle(state->user_op),
-                                          dp_opt_get_int(state->ctx->opts->basic,
-                                                         SDAP_SEARCH_TIMEOUT));
-        if (subreq == NULL) {
-            tevent_req_error(req, ENOMEM);
-            return;
-        }
-        tevent_req_set_callback(subreq,
-                                sdap_dom_enum_ex_posix_check_done, req);
-        return;
-    }
-
-
-    ret = sdap_dom_enum_search_users(req);
-    if (ret != EOK) {
-        tevent_req_error(req, ret);
-        return;
-    }
-    /* Execution resumes in sdap_dom_enum_ex_users_done */
-}
-
-static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq)
-{
-    errno_t ret;
-    bool has_posix;
-    int dp_error;
-
-    struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                      struct tevent_req);
-    struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
-                                                struct sdap_dom_enum_ex_state);
-
-    ret = sdap_gc_posix_check_recv(subreq, &has_posix);
-    talloc_zfree(subreq);
-    if (ret != EOK && ret != ERR_NO_POSIX) {
-        /* We can only finish the id_op on error as the connection
-         * is re-used by the user search
-         */
-        ret = sdap_id_op_done(state->user_op, ret, &dp_error);
-        if (dp_error == DP_ERR_OK && ret != EOK) {
-            /* retry */
-            ret = sdap_dom_enum_ex_retry(req, state->user_op,
-                                         sdap_dom_enum_ex_get_users);
-            if (ret != EOK) {
-                tevent_req_error(req, ret);
-            }
-            return;
-        } else if (dp_error == DP_ERR_OFFLINE) {
-            DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
-            tevent_req_done(req);
-            return;
-        } else {
-            /* Non-recoverable error */
-            DEBUG(SSSDBG_OP_FAILURE,
-                "POSIX check failed: %d: %s\n", ret, sss_strerror(ret));
-            tevent_req_error(req, ret);
-            return;
-        }
-    }
-
-    state->ctx->srv_opts->posix_checked = true;
-
-    /* If the check ran to completion, we know for certain about the attributes
-     */
-    if (has_posix == false) {
-        tevent_req_error(req, ERR_NO_POSIX);
-        return;
-    }
-
-
-    ret = sdap_dom_enum_search_users(req);
-    if (ret != EOK) {
-        tevent_req_error(req, ret);
-        return;
-    }
-    /* Execution resumes in sdap_dom_enum_ex_users_done */
-}
-
-static errno_t sdap_dom_enum_search_users(struct tevent_req *req)
-{
-    struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
-                                                struct sdap_dom_enum_ex_state);
-    struct tevent_req *subreq;
-
     subreq = enum_users_send(state, state->ev,
                              state->ctx, state->sdom,
                              state->user_op, state->purge);
     if (subreq == NULL) {
-        return ENOMEM;
+        tevent_req_error(req, ENOMEM);
+        return;
     }
     tevent_req_set_callback(subreq, sdap_dom_enum_ex_users_done, req);
-    return EOK;
 }
 
 static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq)

From 08c8ac322bcab03d5954f51daa33da47b87c5bcc Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Sat, 30 Jun 2018 13:21:18 +0200
Subject: [PATCH 6/6] LDAP: Remove the legacy POSIX check itself

This code is no longer needed now.

Related:
https://pagure.io/SSSD/sssd/issue/3755
---
 src/providers/ad/ad_common.c     |   2 -
 src/providers/ldap/ldap_common.c |  17 ----
 src/providers/ldap/ldap_common.h |   7 --
 src/providers/ldap/sdap.h        |   1 -
 src/providers/ldap/sdap_async.c  | 174 ---------------------------------------
 src/providers/ldap/sdap_async.h  |  13 ---
 6 files changed, 214 deletions(-)

diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 8b531d4f9..d228e32ac 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -1392,7 +1392,6 @@ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
         clist[cindex] = ad_ctx->gc_ctx;
         clist[cindex]->ignore_mark_offline = true;
         clist[cindex]->no_mpg_user_fallback = true;
-        clist[cindex]->check_posix_attrs = true;
         cindex++;
     }
 
@@ -1439,7 +1438,6 @@ ad_user_conn_list(TALLOC_CTX *mem_ctx,
             && IS_SUBDOMAIN(dom)) {
         clist[cindex] = ad_ctx->gc_ctx;
         clist[cindex]->ignore_mark_offline = true;
-        clist[cindex]->check_posix_attrs = true;
         cindex++;
     }
 
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index a0a9b8523..9cd8ec09c 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -884,20 +884,3 @@ sdap_id_ctx_new(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
 
     return sdap_ctx;
 }
-
-bool should_run_posix_check(struct sdap_id_ctx *ctx,
-                            struct sdap_id_conn_ctx *conn,
-                            bool use_id_mapping,
-                            bool posix_request)
-{
-    if (use_id_mapping == false &&
-            posix_request == true &&
-            ctx->opts->schema_type == SDAP_SCHEMA_AD &&
-            conn->check_posix_attrs == true &&
-            ctx->srv_opts &&
-            ctx->srv_opts->posix_checked == false) {
-        return true;
-    }
-
-    return false;
-}
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 3de3568cb..6c08d789b 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -59,8 +59,6 @@ struct sdap_id_conn_ctx {
     bool ignore_mark_offline;
     /* do not fall back to user lookups for mpg domains on this connection */
     bool no_mpg_user_fallback;
-    /* check if this connection contains POSIX attributes */
-    bool check_posix_attrs;
 };
 
 struct sdap_id_ctx {
@@ -309,11 +307,6 @@ char *get_enterprise_principal_string_filter(TALLOC_CTX *mem_ctx,
                                              const char *princ,
                                              struct dp_option *sdap_basic_opts);
 
-bool should_run_posix_check(struct sdap_id_ctx *ctx,
-                            struct sdap_id_conn_ctx *conn,
-                            bool id_mapping,
-                            bool posix_request);
-
 char *sdap_get_access_filter(TALLOC_CTX *mem_ctx,
                              const char *base_filter);
 
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index e892c4071..079054481 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -511,7 +511,6 @@ struct sdap_server_opts {
     char *max_group_value;
     char *max_service_value;
     char *max_sudo_value;
-    bool posix_checked;
 };
 
 struct sdap_id_ctx;
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index 1e77b1c3c..8fc832ae5 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -2572,180 +2572,6 @@ int sdap_asq_search_recv(struct tevent_req *req,
     return EOK;
 }
 
-/* ==POSIX attribute presence test================================= */
-static void sdap_gc_posix_check_done(struct tevent_req *subreq);
-static errno_t sdap_gc_posix_check_parse(struct sdap_handle *sh,
-                                         struct sdap_msg *msg,
-                                         void *pvt);
-
-struct sdap_gc_posix_check_state {
-    struct tevent_context *ev;
-    struct sdap_options *opts;
-    struct sdap_handle *sh;
-    int timeout;
-
-    const char **attrs;
-    const char *filter;
-
-    bool has_posix;
-};
-
-struct tevent_req *
-sdap_gc_posix_check_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-                         struct sdap_options *opts, struct sdap_handle *sh,
-                         int timeout)
-{
-    struct tevent_req *req = NULL;
-    struct tevent_req *subreq = NULL;
-    struct sdap_gc_posix_check_state *state;
-    errno_t ret;
-
-    req = tevent_req_create(memctx, &state, struct sdap_gc_posix_check_state);
-    if (req == NULL) {
-        return NULL;
-    }
-    state->ev = ev;
-    state->sh = sh;
-    state->opts = opts;
-    state->timeout = timeout;
-
-    state->attrs = talloc_array(state, const char *, 4);
-    if (state->attrs == NULL) {
-        ret = ENOMEM;
-        goto fail;
-    }
-    state->attrs[0] = "objectclass";
-    state->attrs[1] = opts->user_map[SDAP_AT_USER_UID].name;
-    state->attrs[2] = opts->group_map[SDAP_AT_GROUP_GID].name;
-    state->attrs[3] = NULL;
-
-    state->filter = talloc_asprintf(state,
-        "(|(&(%s=*)(objectclass=%s))(&(%s=*)(objectclass=%s)))",
-                                    opts->user_map[SDAP_AT_USER_UID].name,
-                                    opts->user_map[SDAP_OC_USER].name,
-                                    opts->group_map[SDAP_AT_GROUP_GID].name,
-                                    opts->group_map[SDAP_OC_GROUP].name);
-    if (state->filter == NULL) {
-        ret = ENOMEM;
-        goto fail;
-    }
-
-    subreq = sdap_get_generic_ext_send(state, state->ev, state->opts,
-                                 state->sh,
-                                 "",
-                                 LDAP_SCOPE_SUBTREE, state->filter,
-                                 state->attrs,
-                                 NULL, NULL, 1, state->timeout,
-                                 sdap_gc_posix_check_parse, state,
-                                 SDAP_SRCH_FLG_SIZELIMIT_SILENT);
-    if (subreq == NULL) {
-        ret = ENOMEM;
-        goto fail;
-    }
-    tevent_req_set_callback(subreq, sdap_gc_posix_check_done, req);
-
-    return req;
-
-fail:
-    tevent_req_error(req, ret);
-    tevent_req_post(req, ev);
-    return req;
-}
-
-static errno_t sdap_gc_posix_check_parse(struct sdap_handle *sh,
-                                         struct sdap_msg *msg,
-                                         void *pvt)
-{
-    struct berval **vals = NULL;
-    struct sdap_gc_posix_check_state *state =
-        talloc_get_type(pvt, struct sdap_gc_posix_check_state);
-    char *dn;
-    char *endptr;
-
-    dn = ldap_get_dn(sh->ldap, msg->msg);
-    if (dn == NULL) {
-        DEBUG(SSSDBG_TRACE_LIBS,
-              "Search did not find any entry with POSIX attributes\n");
-        goto done;
-    }
-    DEBUG(SSSDBG_TRACE_LIBS, "Found [%s] with POSIX attributes\n", dn);
-    ldap_memfree(dn);
-
-    vals = ldap_get_values_len(sh->ldap, msg->msg,
-                               state->opts->user_map[SDAP_AT_USER_UID].name);
-    if (vals == NULL) {
-        vals = ldap_get_values_len(sh->ldap, msg->msg,
-                               state->opts->group_map[SDAP_AT_GROUP_GID].name);
-        if (vals == NULL) {
-            DEBUG(SSSDBG_TRACE_LIBS, "Entry does not have POSIX attrs?\n");
-            goto done;
-        }
-    }
-
-    if (vals[0] == NULL) {
-        DEBUG(SSSDBG_TRACE_LIBS, "No value for POSIX attr\n");
-        goto done;
-    }
-
-    errno = 0;
-    strtouint32(vals[0]->bv_val, &endptr, 10);
-    if (errno || *endptr || (vals[0]->bv_val == endptr)) {
-        DEBUG(SSSDBG_MINOR_FAILURE,
-              "POSIX attribute is not a number: %s\n", vals[0]->bv_val);
-    }
-
-    state->has_posix = true;
-done:
-    ldap_value_free_len(vals);
-    return EOK;
-}
-
-static void sdap_gc_posix_check_done(struct tevent_req *subreq)
-{
-    struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                      struct tevent_req);
-    struct sdap_gc_posix_check_state *state =
-        tevent_req_data(req, struct sdap_gc_posix_check_state);
-    errno_t ret;
-
-    ret = sdap_get_generic_ext_recv(subreq, NULL, NULL, NULL);
-    talloc_zfree(subreq);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE,
-              "sdap_get_generic_ext_recv failed [%d]: %s\n",
-              ret, strerror(ret));
-        tevent_req_error(req, ret);
-        return;
-    }
-
-    /* Positive hit is definitive, no need to search other bases */
-    if (state->has_posix == true) {
-        DEBUG(SSSDBG_FUNC_DATA, "Server has POSIX attributes. Global Catalog will "
-                                "be used for user and group lookups. Note that if "
-                                "only a subset of POSIX attributes is present "
-                                "in GC, the non-replicated attributes are "
-                                "currently not read from the LDAP port\n");
-        tevent_req_done(req);
-        return;
-    }
-
-    /* All bases done! */
-    DEBUG(SSSDBG_TRACE_LIBS, "Cycled through all bases\n");
-    tevent_req_done(req);
-}
-
-int sdap_gc_posix_check_recv(struct tevent_req *req,
-                             bool *_has_posix)
-{
-    struct sdap_gc_posix_check_state *state = tevent_req_data(req,
-                                            struct sdap_gc_posix_check_state);
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
-    *_has_posix = state->has_posix;
-    return EOK;
-}
-
 /* ==Generic Deref Search============================================ */
 enum sdap_deref_type {
     SDAP_DEREF_OPENLDAP,
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 6ca3ed8d8..6d09aca7a 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -281,19 +281,6 @@ int sdap_deref_search_recv(struct tevent_req *req,
                            size_t *reply_count,
                            struct sdap_deref_attrs ***reply);
 
-/*
- * This request should only be ran against a Global Catalog connection
- * because it uses a NULL search base to search all domains in the forest,
- * which would return an error with an LDAP port:
- *  https://technet.microsoft.com/en-us/library/cc755809(v=ws.10).aspx
- */
-struct tevent_req *
-sdap_gc_posix_check_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-                         struct sdap_options *opts, struct sdap_handle *sh,
-                         int timeout);
-
-int sdap_gc_posix_check_recv(struct tevent_req *req,
-                             bool *_has_posix);
 
 struct tevent_req *
 sdap_sd_search_send(TALLOC_CTX *memctx,
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedoraproject.org/archives/list/sssd-devel@lists.fedorahosted.org/message/GFGKISDCE4Y444IHKLRSGGAL7SKRHDPB/

Reply via email to