diff --git a/SOURCES/0047-SELINUX-Always-add-SELinux-user-to-the-semanage-data.patch b/SOURCES/0047-SELINUX-Always-add-SELinux-user-to-the-semanage-data.patch
new file mode 100644
index 0000000..66dbbbe
--- /dev/null
+++ b/SOURCES/0047-SELINUX-Always-add-SELinux-user-to-the-semanage-data.patch
@@ -0,0 +1,146 @@
+From e7e942ceb1f8402d00f5f14a9e065d3fc434b711 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 23 Aug 2018 13:55:51 +0200
+Subject: [PATCH] SELINUX: Always add SELinux user to the semanage database if
+ it doesn't exist
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Previously, we tried to optimize too much and only set the SELinux user
+to Linux user mapping in case the SELinux user was different from the
+system default. But this doesn't work for the case where the Linux user
+has a non-standard home directory, because then SELinux would not have
+any idea that this user's home directory should be labeled as a home
+directory.
+
+This patch relaxes the optimization in the sense that on the first
+login, the SELinux context is saved regardless of whether it is the same
+as the default or different.
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3819
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit 945865ae16120ffade267227ca48cefd58822fd2)
+---
+ src/providers/ipa/selinux_child.c | 10 ++++++++--
+ src/util/sss_semanage.c           | 30 ++++++++++++++++++++++++++++++
+ src/util/util.h                   |  1 +
+ src/util/util_errors.c            |  1 +
+ src/util/util_errors.h            |  1 +
+ 5 files changed, 41 insertions(+), 2 deletions(-)
+
+diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
+index d061417..925591e 100644
+--- a/src/providers/ipa/selinux_child.c
++++ b/src/providers/ipa/selinux_child.c
+@@ -176,13 +176,16 @@ static bool seuser_needs_update(const char *username,
+ 
+     ret = sss_get_seuser(username, &db_seuser, &db_mls_range);
+     DEBUG(SSSDBG_TRACE_INTERNAL,
+-          "getseuserbyname: ret: %d seuser: %s mls: %s\n",
++          "sss_get_seuser: ret: %d seuser: %s mls: %s\n",
+           ret, db_seuser ? db_seuser : "unknown",
+           db_mls_range ? db_mls_range : "unknown");
+     if (ret == EOK && db_seuser && db_mls_range &&
+             strcmp(db_seuser, seuser) == 0 &&
+             strcmp(db_mls_range, mls_range) == 0) {
+-        needs_update = false;
++        ret = sss_seuser_exists(username);
++        if (ret == EOK) {
++            needs_update = false;
++        }
+     }
+     /* OR */
+     if (ret == ERR_SELINUX_NOT_MANAGED) {
+@@ -191,6 +194,9 @@ static bool seuser_needs_update(const char *username,
+ 
+     free(db_seuser);
+     free(db_mls_range);
++    DEBUG(SSSDBG_TRACE_FUNC,
++          "The SELinux user does %sneed an update\n",
++          needs_update ? "" : "not ");
+     return needs_update;
+ }
+ 
+diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c
+index bcce57b..aea0385 100644
+--- a/src/util/sss_semanage.c
++++ b/src/util/sss_semanage.c
+@@ -248,6 +248,36 @@ done:
+     return ret;
+ }
+ 
++int sss_seuser_exists(const char *linuxuser)
++{
++    int ret;
++    int exists;
++    semanage_seuser_key_t *sm_key = NULL;
++    semanage_handle_t *sm_handle = NULL;
++
++    ret = sss_semanage_init(&sm_handle);
++    if (ret != EOK) {
++        return ret;
++    }
++
++    ret = semanage_seuser_key_create(sm_handle, linuxuser, &sm_key);
++    if (ret < 0) {
++        sss_semanage_close(sm_handle);
++        return EIO;
++    }
++
++    ret = semanage_seuser_exists(sm_handle, sm_key, &exists);
++    semanage_seuser_key_free(sm_key);
++    sss_semanage_close(sm_handle);
++    if (ret < 0) {
++        return EIO;
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "seuser exists: %s\n", exists ? "yes" : "no");
++
++    return exists ? EOK : ERR_SELINUX_USER_NOT_FOUND;
++}
++
+ int sss_get_seuser(const char *linuxuser,
+                    char **selinuxuser,
+                    char **level)
+diff --git a/src/util/util.h b/src/util/util.h
+index bc89ecb..c78615b 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -660,6 +660,7 @@ int sss_del_seuser(const char *login_name);
+ int sss_get_seuser(const char *linuxuser,
+                    char **selinuxuser,
+                    char **level);
++int sss_seuser_exists(const char *linuxuser);
+ 
+ /* convert time from generalized form to unix time */
+ errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *unix_time);
+diff --git a/src/util/util_errors.c b/src/util/util_errors.c
+index e2bb2a0..e5c5bd1 100644
+--- a/src/util/util_errors.c
++++ b/src/util/util_errors.c
+@@ -75,6 +75,7 @@ struct err_string error_to_str[] = {
+     { "LDAP search returned a referral" }, /* ERR_REFERRAL */
+     { "Error setting SELinux user context" }, /* ERR_SELINUX_CONTEXT */
+     { "SELinux is not managed by libsemanage" }, /* ERR_SELINUX_NOT_MANAGED */
++    { "SELinux user does not exist" }, /* ERR_SELINUX_USER_NOT_FOUND */
+     { "Username format not allowed by re_expression" }, /* ERR_REGEX_NOMATCH */
+     { "Time specification not supported" }, /* ERR_TIMESPEC_NOT_SUPPORTED */
+     { "Invalid SSSD configuration detected" }, /* ERR_INVALID_CONFIG */
+diff --git a/src/util/util_errors.h b/src/util/util_errors.h
+index 4950172..a4760a1 100644
+--- a/src/util/util_errors.h
++++ b/src/util/util_errors.h
+@@ -97,6 +97,7 @@ enum sssd_errors {
+     ERR_REFERRAL,
+     ERR_SELINUX_CONTEXT,
+     ERR_SELINUX_NOT_MANAGED,
++    ERR_SELINUX_USER_NOT_FOUND,
+     ERR_REGEX_NOMATCH,
+     ERR_TIMESPEC_NOT_SUPPORTED,
+     ERR_INVALID_CONFIG,
+-- 
+2.9.5
+
diff --git a/SOURCES/0048-sudo-respect-case-sensitivity-in-sudo-responder.patch b/SOURCES/0048-sudo-respect-case-sensitivity-in-sudo-responder.patch
new file mode 100644
index 0000000..dcbe819
--- /dev/null
+++ b/SOURCES/0048-sudo-respect-case-sensitivity-in-sudo-responder.patch
@@ -0,0 +1,69 @@
+From 2d9286102f23ea9d13213f1176ba669b9315a75f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Thu, 6 Sep 2018 13:38:56 +0200
+Subject: [PATCH] sudo: respect case sensitivity in sudo responder
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If the domain is not case sensitive and the case of the original user
+or group name differs from the name in the rule we failed to find the
+rule.
+
+Now we filter the rule only with lower cased values in such domain.
+
+Steps to reproduce:
+1. Add user/group with upper case, e.g. USER-1
+2. Add sudo rule with lower cased name, e.g. sudoUser: user-1
+3. Login to system with lower case, e.g. user-1
+4. Run sudo -l
+
+Without the patch, rule is not found.
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3820
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit d7f0b58e2896ed2ef9ed5a390815c1e4df6caaee)
+---
+ src/db/sysdb_sudo.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c
+index 3ad462d8f..19ed97b86 100644
+--- a/src/db/sysdb_sudo.c
++++ b/src/db/sysdb_sudo.c
+@@ -418,7 +418,17 @@ sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx,
+         ret = EINVAL;
+         goto done;
+     }
+-    DEBUG(SSSDBG_TRACE_FUNC, "original name: %s\n", orig_name);
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Original name: %s\n", orig_name);
++
++    orig_name = sss_get_cased_name(tmp_ctx, orig_name, domain->case_sensitive);
++    if (orig_name == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Cased name: %s\n", orig_name);
+ 
+     if (_uid != NULL) {
+         uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0);
+@@ -450,8 +460,9 @@ sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx,
+                     continue;
+                 }
+ 
+-                sysdb_groupnames[num_groups] = talloc_strdup(sysdb_groupnames,
+-                                                             groupname);
++                sysdb_groupnames[num_groups] = \
++                    sss_get_cased_name(sysdb_groupnames, groupname,
++                                       domain->case_sensitive);
+                 if (sysdb_groupnames[num_groups] == NULL) {
+                     DEBUG(SSSDBG_MINOR_FAILURE, "Cannot strdup %s\n", groupname);
+                     continue;
+-- 
+2.19.1
+
diff --git a/SOURCES/0049-nss-use-enumeration-context-as-talloc-parent-for-cac.patch b/SOURCES/0049-nss-use-enumeration-context-as-talloc-parent-for-cac.patch
new file mode 100644
index 0000000..eb552b5
--- /dev/null
+++ b/SOURCES/0049-nss-use-enumeration-context-as-talloc-parent-for-cac.patch
@@ -0,0 +1,146 @@
+From 720a423a0119f23606c6029c3f48be98841ca910 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Tue, 30 Oct 2018 13:21:28 +0100
+Subject: [PATCH] nss: use enumeration context as talloc parent for cache req
+ result
+
+Otherwise we end up with memory leak since the result is never freed.
+
+We need to convert nctx->*ent structures into talloc pointer so
+we can use enum_ctx as parent.
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3870
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 406b731ddfbeb62623640cc37a7adc76af0a4b22)
+---
+ src/responder/nss/nss_cmd.c     | 12 ++++++------
+ src/responder/nss/nss_enum.c    |  2 +-
+ src/responder/nss/nss_private.h |  6 +++---
+ src/responder/nss/nsssrv.c      | 21 +++++++++++++++++++++
+ 4 files changed, 31 insertions(+), 10 deletions(-)
+
+diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c
+index 9ee6ca805..25e663ed5 100644
+--- a/src/responder/nss/nss_cmd.c
++++ b/src/responder/nss/nss_cmd.c
+@@ -942,7 +942,7 @@ static errno_t nss_cmd_setpwent(struct cli_ctx *cli_ctx)
+ 
+     nss_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct nss_ctx);
+ 
+-    return nss_setent(cli_ctx, CACHE_REQ_ENUM_USERS, &nss_ctx->pwent);
++    return nss_setent(cli_ctx, CACHE_REQ_ENUM_USERS, nss_ctx->pwent);
+ }
+ 
+ static errno_t nss_cmd_getpwent(struct cli_ctx *cli_ctx)
+@@ -955,7 +955,7 @@ static errno_t nss_cmd_getpwent(struct cli_ctx *cli_ctx)
+ 
+     return nss_getent(cli_ctx, CACHE_REQ_ENUM_USERS,
+                       &state_ctx->pwent, nss_protocol_fill_pwent,
+-                      &nss_ctx->pwent);
++                      nss_ctx->pwent);
+ }
+ 
+ static errno_t nss_cmd_endpwent(struct cli_ctx *cli_ctx)
+@@ -998,7 +998,7 @@ static errno_t nss_cmd_setgrent(struct cli_ctx *cli_ctx)
+ 
+     nss_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct nss_ctx);
+ 
+-    return nss_setent(cli_ctx, CACHE_REQ_ENUM_GROUPS, &nss_ctx->grent);
++    return nss_setent(cli_ctx, CACHE_REQ_ENUM_GROUPS, nss_ctx->grent);
+ }
+ 
+ static errno_t nss_cmd_getgrent(struct cli_ctx *cli_ctx)
+@@ -1011,7 +1011,7 @@ static errno_t nss_cmd_getgrent(struct cli_ctx *cli_ctx)
+ 
+     return nss_getent(cli_ctx, CACHE_REQ_ENUM_GROUPS,
+                       &state_ctx->grent, nss_protocol_fill_grent,
+-                      &nss_ctx->grent);
++                      nss_ctx->grent);
+ }
+ 
+ static errno_t nss_cmd_endgrent(struct cli_ctx *cli_ctx)
+@@ -1093,7 +1093,7 @@ static errno_t nss_cmd_setservent(struct cli_ctx *cli_ctx)
+ 
+     nss_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct nss_ctx);
+ 
+-    return nss_setent(cli_ctx, CACHE_REQ_ENUM_SVC, &nss_ctx->svcent);
++    return nss_setent(cli_ctx, CACHE_REQ_ENUM_SVC, nss_ctx->svcent);
+ }
+ 
+ static errno_t nss_cmd_getservent(struct cli_ctx *cli_ctx)
+@@ -1106,7 +1106,7 @@ static errno_t nss_cmd_getservent(struct cli_ctx *cli_ctx)
+ 
+     return nss_getent(cli_ctx, CACHE_REQ_ENUM_SVC,
+                       &state_ctx->svcent, nss_protocol_fill_svcent,
+-                      &nss_ctx->svcent);
++                      nss_ctx->svcent);
+ }
+ 
+ static errno_t nss_cmd_endservent(struct cli_ctx *cli_ctx)
+diff --git a/src/responder/nss/nss_enum.c b/src/responder/nss/nss_enum.c
+index a45b65233..9588943c9 100644
+--- a/src/responder/nss/nss_enum.c
++++ b/src/responder/nss/nss_enum.c
+@@ -138,7 +138,7 @@ static void nss_setent_internal_done(struct tevent_req *subreq)
+     switch (ret) {
+     case EOK:
+         talloc_zfree(state->enum_ctx->result);
+-        state->enum_ctx->result = talloc_steal(state->nss_ctx, result);
++        state->enum_ctx->result = talloc_steal(state->enum_ctx, result);
+ 
+         if (state->type == CACHE_REQ_NETGROUP_BY_NAME) {
+             /* We need to expand the netgroup into triples and members. */
+diff --git a/src/responder/nss/nss_private.h b/src/responder/nss/nss_private.h
+index aa8d8e9cd..cd0d35517 100644
+--- a/src/responder/nss/nss_private.h
++++ b/src/responder/nss/nss_private.h
+@@ -78,9 +78,9 @@ struct nss_ctx {
+     const char **extra_attributes;
+ 
+     /* Enumeration. */
+-    struct nss_enum_ctx pwent;
+-    struct nss_enum_ctx grent;
+-    struct nss_enum_ctx svcent;
++    struct nss_enum_ctx *pwent;
++    struct nss_enum_ctx *grent;
++    struct nss_enum_ctx *svcent;
+     hash_table_t *netgrent;
+ 
+     /* Memory cache. */
+diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
+index 004e6c1a1..d6c5a08a9 100644
+--- a/src/responder/nss/nsssrv.c
++++ b/src/responder/nss/nsssrv.c
+@@ -378,6 +378,27 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
+         goto fail;
+     }
+ 
++    nctx->pwent = talloc_zero(nctx, struct nss_enum_ctx);
++    if (nctx->pwent == NULL) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Unable to initialize pwent context!\n");
++        ret = ENOMEM;
++        goto fail;
++    }
++
++    nctx->grent = talloc_zero(nctx, struct nss_enum_ctx);
++    if (nctx->grent == NULL) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Unable to initialize grent context!\n");
++        ret = ENOMEM;
++        goto fail;
++    }
++
++    nctx->svcent = talloc_zero(nctx, struct nss_enum_ctx);
++    if (nctx->svcent == NULL) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Unable to initialize svcent context!\n");
++        ret = ENOMEM;
++        goto fail;
++    }
++
+     nctx->netgrent = sss_ptr_hash_create(nctx, NULL, NULL);
+     if (nctx->netgrent == NULL) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to initialize netgroups table!\n");
+-- 
+2.19.1
+
diff --git a/SOURCES/0050-Revert-IPA-use-forest-name-when-looking-up-the-Globa.patch b/SOURCES/0050-Revert-IPA-use-forest-name-when-looking-up-the-Globa.patch
new file mode 100644
index 0000000..4483916
--- /dev/null
+++ b/SOURCES/0050-Revert-IPA-use-forest-name-when-looking-up-the-Globa.patch
@@ -0,0 +1,30 @@
+From d33ec64423087261fcc14acb5922793fadb83342 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Tue, 4 Dec 2018 13:08:11 +0100
+Subject: [PATCH 50/51] Revert "IPA: use forest name when looking up the Global
+ Catalog"
+
+This reverts commit 149174acae677d1e72a0da431bf0850d55f2ccb4.
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 9096fc01cca8fcaeb19c36a27f3a9fa09d60772a)
+---
+ src/providers/ipa/ipa_subdomains_server.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
+index e5ea4bd02..43a3053cb 100644
+--- a/src/providers/ipa/ipa_subdomains_server.c
++++ b/src/providers/ipa/ipa_subdomains_server.c
+@@ -266,7 +266,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
+         DEBUG(SSSDBG_TRACE_ALL, "No extra attrs set.\n");
+     }
+ 
+-    gc_service_name = talloc_asprintf(ad_options, "sd_gc_%s", subdom->forest);
++    gc_service_name = talloc_asprintf(ad_options, "sd_gc_%s", subdom->name);
+     if (gc_service_name == NULL) {
+         talloc_free(ad_options);
+         return ENOMEM;
+-- 
+2.19.1
+
diff --git a/SOURCES/0051-ipa-use-only-the-global-catalog-service-of-the-fores.patch b/SOURCES/0051-ipa-use-only-the-global-catalog-service-of-the-fores.patch
new file mode 100644
index 0000000..1ad7603
--- /dev/null
+++ b/SOURCES/0051-ipa-use-only-the-global-catalog-service-of-the-fores.patch
@@ -0,0 +1,104 @@
+From 74568bdde833f752187cb1a38b39715556c91279 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Tue, 4 Dec 2018 13:06:23 +0100
+Subject: [PATCH 51/51] ipa: use only the global catalog service of the forest
+ root
+
+While creating the domains and sub-domains each domain gets a global
+catalog services assigned but only one should be used because the global
+catalog is by definition responsible for the whole forest so it does not
+make sense to use a global catalog service for each domain and in the
+worst case connect to the same GC multiple times.
+
+In the AD provider this is simple because the GC service of the
+configured domain AD_GC_SERVICE_NAME ("AD_GC") can be used. In the IPA
+case all domains from the trusted forest are on the level of sub-domains
+so we have to pick one. Since the forest root is linked from all domain
+of the same forest it will be the most straight forward choice.
+
+Related to https://pagure.io/SSSD/sssd/issue/3902
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 62d671b874a66101c0f4bff39fc6d7f49cb8fca6)
+---
+ src/providers/ipa/ipa_subdomains_id.c | 50 +++++++++++++++++++++++++--
+ 1 file changed, 47 insertions(+), 3 deletions(-)
+
+diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
+index a16eed284..48cf74460 100644
+--- a/src/providers/ipa/ipa_subdomains_id.c
++++ b/src/providers/ipa/ipa_subdomains_id.c
+@@ -713,6 +713,52 @@ int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out)
+     return EOK;
+ }
+ 
++static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx,
++                                           struct sss_domain_info *dom);
++
++static struct sdap_id_conn_ctx **
++ipa_ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ipa_id_ctx *ipa_ctx,
++                    struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom)
++{
++    struct ad_id_ctx *forest_root_ad_id_ctx;
++    struct sdap_id_conn_ctx **clist;
++    int cindex = 0;
++
++    /* While creating the domains and sub-domains each domain gets a global
++     * catalog services assigned but only one should be used because the
++     * global catalog is by definition responsible for the whole forest so it
++     * does not make sense to use a global catalog service for each domain and
++     * in the worst case connect to the same GC multiple times.
++     *
++     * In the AD provider this is simple because the GC service of the
++     * configured domain AD_GC_SERVICE_NAME ("AD_GC") can be used. In the IPA
++     * case all domains from the trusted forest are on the level of
++     * sub-domains so we have to pick one. Since the forest root is linked
++     * from all domain of the same forest it will be the most straight forward
++     * choice. */
++    forest_root_ad_id_ctx = ipa_get_ad_id_ctx(ipa_ctx, dom->forest_root);
++    if (forest_root_ad_id_ctx == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "Missing ad_id_ctx for forest root.\n");
++        return NULL;
++    }
++
++    clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3);
++    if (clist == NULL) return NULL;
++
++    /* Always try GC first */
++    if (dp_opt_get_bool(forest_root_ad_id_ctx->ad_options->basic,
++                        AD_ENABLE_GC)) {
++        clist[cindex] = forest_root_ad_id_ctx->gc_ctx;
++        clist[cindex]->ignore_mark_offline = true;
++        clist[cindex]->no_mpg_user_fallback = true;
++        cindex++;
++    }
++
++    clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom);
++
++    return clist;
++}
++
+ /* IPA lookup for server mode. Directly to AD. */
+ struct ipa_get_ad_acct_state {
+     int dp_error;
+@@ -731,8 +777,6 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req);
+ static errno_t ipa_get_ad_ipa_membership_step(struct tevent_req *req);
+ static void ipa_id_get_groups_overrides_done(struct tevent_req *subreq);
+ static void ipa_get_ad_acct_done(struct tevent_req *subreq);
+-static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx,
+-                                           struct sss_domain_info *dom);
+ 
+ static struct tevent_req *
+ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+@@ -785,7 +829,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+     case BE_REQ_INITGROUPS:
+     case BE_REQ_BY_SECID:
+     case BE_REQ_GROUP:
+-        clist = ad_gc_conn_list(req, ad_id_ctx, state->obj_dom);
++        clist = ipa_ad_gc_conn_list(req, ipa_ctx, ad_id_ctx, state->obj_dom);
+         break;
+     default:
+         clist = ad_ldap_conn_list(req, ad_id_ctx, state->obj_dom);
+-- 
+2.19.1
+
diff --git a/SOURCES/0052-LDAP-minor-refactoring-in-auth_send-to-conform-to-ou.patch b/SOURCES/0052-LDAP-minor-refactoring-in-auth_send-to-conform-to-ou.patch
new file mode 100644
index 0000000..c06a179
--- /dev/null
+++ b/SOURCES/0052-LDAP-minor-refactoring-in-auth_send-to-conform-to-ou.patch
@@ -0,0 +1,72 @@
+From 876f1cb87d1649d0681bf6475ab589287f15babb Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 22 Nov 2018 12:51:14 +0100
+Subject: [PATCH 52/54] LDAP: minor refactoring in auth_send() to conform to
+ our coding style
+
+Related:
+https://pagure.io/SSSD/sssd/issue/3451
+
+A tevent _send() function should only return NULL on ENOMEM, otherwise
+it should mark the request as failed but return the req pointer. This
+was not much of an issue, before, but the next patch will add another
+function call to the auth_send call which would make error handling
+awkward.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 09091b4b60456a989ecc8c3b6f76661a14c108ba)
+---
+ src/providers/ldap/ldap_auth.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
+index d40bc9414..c409353d9 100644
+--- a/src/providers/ldap/ldap_auth.c
++++ b/src/providers/ldap/ldap_auth.c
+@@ -636,6 +636,7 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
+ {
+     struct tevent_req *req;
+     struct auth_state *state;
++    errno_t ret;
+ 
+     req = tevent_req_create(memctx, &state, struct auth_state);
+     if (!req) return NULL;
+@@ -645,11 +646,11 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
+         if (sss_authtok_get_type(authtok) == SSS_AUTHTOK_TYPE_SC_PIN
+             || sss_authtok_get_type(authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD) {
+             /* Tell frontend that we do not support Smartcard authentication */
+-            tevent_req_error(req, ERR_SC_AUTH_NOT_SUPPORTED);
++            ret = ERR_SC_AUTH_NOT_SUPPORTED;
+         } else {
+-            tevent_req_error(req, ERR_AUTH_FAILED);
++            ret = ERR_AUTH_FAILED;
+         }
+-        return tevent_req_post(req, ev);
++        goto fail;
+     }
+ 
+     state->ev = ev;
+@@ -663,13 +664,17 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
+         state->sdap_service = ctx->service;
+     }
+ 
+-    if (!auth_connect_send(req)) goto fail;
++    if (auth_connect_send(req) == NULL) {
++        ret = ENOMEM;
++        goto fail;
++    }
+ 
+     return req;
+ 
+ fail:
+-    talloc_zfree(req);
+-    return NULL;
++    tevent_req_error(req, ret);
++    tevent_req_post(req, ev);
++    return req;
+ }
+ 
+ static struct tevent_req *auth_connect_send(struct tevent_req *req)
+-- 
+2.19.1
+
diff --git a/SOURCES/0053-LDAP-Only-authenticate-the-auth-connection-if-we-nee.patch b/SOURCES/0053-LDAP-Only-authenticate-the-auth-connection-if-we-nee.patch
new file mode 100644
index 0000000..7c781e7
--- /dev/null
+++ b/SOURCES/0053-LDAP-Only-authenticate-the-auth-connection-if-we-nee.patch
@@ -0,0 +1,131 @@
+From 7eb18ab68762d1b1ddbcbdc32dbcbd0df183d4f1 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 22 Nov 2018 12:17:51 +0100
+Subject: [PATCH 53/54] LDAP: Only authenticate the auth connection if we need
+ to look up user information
+
+Related:
+https://pagure.io/SSSD/sssd/issue/3451
+
+Commit add72860c7a7a2c418f4d8b6790b5caeaf7dfb7b initially addressed #3451 by
+using the full sdap_cli_connect() request during LDAP authentication. This
+was a good idea as it addressed the case where the authentication connection
+must also look up some user information (typically with id_provider=proxy
+where you don't know the DN to bind as during authentication), but this
+approach also broke the use-case of id_provider=ldap and auth_provider=ldap
+with ldap_sasl_auth=gssapi.
+
+This is because (for reason I don't know) AD doesn't like if you use
+both GSSAPI and startTLS on the same connection. But the code would
+force TLS during the authentication as a general measure to not transmit
+passwords in the clear, but then, the connection would also see that
+ldap_sasl_auth=gssapi is set and also bind with GSSAPI.
+
+This patch checks if the user DN is already known and if yes, then
+doesn't authenticate the connection as the connection will then only be
+used for the user simple bind.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 57fc60c9dc77698cf824813c36eb0f90d767b315)
+---
+ src/providers/ldap/ldap_auth.c | 53 +++++++++++++++++++++++++++-------
+ 1 file changed, 42 insertions(+), 11 deletions(-)
+
+diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
+index c409353d9..b4d045a65 100644
+--- a/src/providers/ldap/ldap_auth.c
++++ b/src/providers/ldap/ldap_auth.c
+@@ -664,6 +664,18 @@ static struct tevent_req *auth_send(TALLOC_CTX *memctx,
+         state->sdap_service = ctx->service;
+     }
+ 
++    ret = get_user_dn(state, state->ctx->be->domain,
++                      state->ctx->opts, state->username, &state->dn,
++                      &state->pw_expire_type, &state->pw_expire_data);
++    if (ret == EAGAIN) {
++        DEBUG(SSSDBG_TRACE_FUNC,
++              "Need to look up the DN of %s later\n", state->username);
++    } else if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Cannot get user DN [%d]: %s\n", ret, sss_strerror(ret));
++        goto fail;
++    }
++
+     if (auth_connect_send(req) == NULL) {
+         ret = ENOMEM;
+         goto fail;
+@@ -683,6 +695,8 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
+     struct auth_state *state = tevent_req_data(req,
+                                                struct auth_state);
+     bool use_tls;
++    bool skip_conn_auth = false;
++    const char *sasl_mech;
+ 
+     /* Check for undocumented debugging feature to disable TLS
+      * for authentication. This should never be used in production
+@@ -695,10 +709,33 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
+                                "for debugging purposes only.");
+     }
+ 
++    if (state->dn != NULL) {
++        /* In case the user's DN is known, the connection will only be used
++         * to bind as the user to perform the authentication. In that case,
++         * we don't need to authenticate the connection, because we're not
++         * looking up any information using the connection. This might be
++         * needed e.g. in case both ID and AUTH providers are set to LDAP
++         * and the server is AD, because otherwise the connection would
++         * both do a startTLS and later bind using GSSAPI which doesn't work
++         * well with AD.
++         */
++        skip_conn_auth = true;
++    }
++
++    if (skip_conn_auth == false) {
++        sasl_mech = dp_opt_get_string(state->ctx->opts->basic,
++                                      SDAP_SASL_MECH);
++        if (sasl_mech && strcasecmp(sasl_mech, "GSSAPI") == 0) {
++            /* Don't force TLS on if we're told to use GSSAPI */
++            use_tls = false;
++        }
++    }
++
+     subreq = sdap_cli_connect_send(state, state->ev, state->ctx->opts,
+                                    state->ctx->be,
+                                    state->sdap_service, false,
+-                                   use_tls ? CON_TLS_ON : CON_TLS_OFF, false);
++                                   use_tls ? CON_TLS_ON : CON_TLS_OFF,
++                                   skip_conn_auth);
+ 
+     if (subreq == NULL) {
+         tevent_req_error(req, ENOMEM);
+@@ -739,15 +776,7 @@ static void auth_connect_done(struct tevent_req *subreq)
+         return;
+     }
+ 
+-    ret = get_user_dn(state, state->ctx->be->domain,
+-                      state->ctx->opts, state->username, &state->dn,
+-                      &state->pw_expire_type, &state->pw_expire_data);
+-    if (ret == EOK) {
+-        /* All required user data was pre-cached during an identity lookup.
+-         * We can proceed with the bind */
+-        auth_do_bind(req);
+-        return;
+-    } else if (ret == EAGAIN) {
++    if (state->dn == NULL) {
+         /* The cached user entry was missing the bind DN. Need to look
+          * it up based on user name in order to perform the bind */
+         subreq = get_user_dn_send(req, state->ev, state->ctx->be->domain,
+@@ -760,7 +789,9 @@ static void auth_connect_done(struct tevent_req *subreq)
+         return;
+     }
+ 
+-    tevent_req_error(req, ret);
++    /* All required user data was pre-cached during an identity lookup.
++     * We can proceed with the bind */
++    auth_do_bind(req);
+     return;
+ }
+ 
+-- 
+2.19.1
+
diff --git a/SOURCES/0054-LDAP-Log-the-encryption-used-during-LDAP-authenticat.patch b/SOURCES/0054-LDAP-Log-the-encryption-used-during-LDAP-authenticat.patch
new file mode 100644
index 0000000..5a1c2bf
--- /dev/null
+++ b/SOURCES/0054-LDAP-Log-the-encryption-used-during-LDAP-authenticat.patch
@@ -0,0 +1,60 @@
+From 1a7c6ab6efce3720d27def426aad49ee99eb339d Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Mon, 26 Nov 2018 12:38:40 +0100
+Subject: [PATCH 54/54] LDAP: Log the encryption used during LDAP
+ authentication
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 6f113c7ddeaa5c82558e10118b499d22bf7a2b14)
+---
+ src/providers/ldap/ldap_auth.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
+index b4d045a65..4666dbfbb 100644
+--- a/src/providers/ldap/ldap_auth.c
++++ b/src/providers/ldap/ldap_auth.c
+@@ -747,6 +747,31 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
+     return subreq;
+ }
+ 
++static void check_encryption(LDAP *ldap)
++{
++    ber_len_t sasl_ssf = 0;
++    int tls_inplace = 0;
++    int ret;
++
++    ret = ldap_get_option(ldap, LDAP_OPT_X_SASL_SSF, &sasl_ssf);
++    if (ret != LDAP_SUCCESS) {
++        DEBUG(SSSDBG_TRACE_LIBS, "ldap_get_option failed to get sasl ssf, "
++                                 "assuming SASL is not used.\n");
++    }
++
++    tls_inplace = ldap_tls_inplace(ldap);
++
++    DEBUG(SSSDBG_TRACE_ALL,
++          "Encryption used: SASL SSF [%lu] tls_inplace [%s].\n", sasl_ssf,
++          tls_inplace == 1 ? "TLS inplace" : "TLS NOT inplace");
++
++    if (sasl_ssf <= 1 && tls_inplace != 1) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++                "No encryption detected on LDAP connection.\n");
++        sss_log(SSS_LOG_CRIT, "No encryption detected on LDAP connection.\n");
++    }
++}
++
+ static void auth_connect_done(struct tevent_req *subreq)
+ {
+     struct tevent_req *req = tevent_req_callback_data(subreq,
+@@ -776,6 +801,8 @@ static void auth_connect_done(struct tevent_req *subreq)
+         return;
+     }
+ 
++    check_encryption(state->sh->ldap);
++
+     if (state->dn == NULL) {
+         /* The cached user entry was missing the bind DN. Need to look
+          * it up based on user name in order to perform the bind */
+-- 
+2.19.1
+
diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec
index 2b87898..75d23a1 100644
--- a/SPECS/sssd.spec
+++ b/SPECS/sssd.spec
@@ -48,7 +48,7 @@
 
 Name: sssd
 Version: 1.16.2
-Release: 13%{?dist}
+Release: 13%{?dist}.5
 Group: Applications/System
 Summary: System Security Services Daemon
 License: GPLv3+
@@ -103,6 +103,14 @@ Patch0043: 0043-CRYPTO-Save-prefix-in-s3crypt_sha512.patch
 Patch0044: 0044-crypto-tests-Add-unit-test-for-s3crypt_sha512.patch
 Patch0045: 0045-SSS_CERT-Close-file-descriptors-after-executing-p11_.patch
 Patch0046: 0046-SELINUX-Also-call-is_selinux_enabled-as-a-check-for-.patch
+Patch0047: 0047-SELINUX-Always-add-SELinux-user-to-the-semanage-data.patch
+Patch0048: 0048-sudo-respect-case-sensitivity-in-sudo-responder.patch
+Patch0049: 0049-nss-use-enumeration-context-as-talloc-parent-for-cac.patch
+Patch0050: 0050-Revert-IPA-use-forest-name-when-looking-up-the-Globa.patch
+Patch0051: 0051-ipa-use-only-the-global-catalog-service-of-the-fores.patch
+Patch0052: 0052-LDAP-minor-refactoring-in-auth_send-to-conform-to-ou.patch
+Patch0053: 0053-LDAP-Only-authenticate-the-auth-connection-if-we-nee.patch
+Patch0054: 0054-LDAP-Log-the-encryption-used-during-LDAP-authenticat.patch
 
 #This patch should not be removed in RHEL-7
 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec
@@ -1255,6 +1263,25 @@ systemctl try-restart sssd >/dev/null 2>&1 || :
 }
 
 %changelog
+* Tue Dec 18 2018 Michal Židek <mzidek@redhat.com> - 1.16.3-5
+- Resolves: rhbz#1659507 - SSSD's LDAP authentication provider does not work
+                           if ID provider is authenticated with GSSAPI [rhel-7.6.z] 
+
+* Tue Dec 18 2018 Michal Židek <mzidek@redhat.com> - 1.16.3-4
+- Resolves: rhbz#1659083 - SSSD must be cleared/restarted periodically in
+            order to retrieve AD users through IPA Trust [rhel-7.6.z]
+
+* Tue Dec 18 2018 Michal Židek <mzidek@redhat.com> - 1.16.3-3
+- Resolves: rhbz#1656833 - sssd_nss memory leak [rhel-7.6.z]
+
+* Wed Nov 28 2018 Michal Židek <mzidek@redhat.com> - 1.16.3-2
+- Resolves: Bug 1649784 - SSSD not fetching all sudo rules from
+                          AD [rhel-7.6.z] 
+
+* Wed Nov 14 2018 Michal Židek <mzidek@redhat.com> - 1.16.3-1
+- Resolves: rhbz#1645047 - sssd only sets the SELinux login context if it
+                           differs from the default [rhel-7.6.z]
+
 * Wed Sep  5 2018 Jakub Hrozek <jhrozek@redhat.com> - 1.16.2-13
 - Resolves: rhbz#1593756 - sssd needs to require a newer version of
                            libtalloc and libtevent to avoid an issue