diff --git a/.gitignore b/.gitignore
index 2091f63..d94250a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/sssd-1.16.2.tar.gz
+SOURCES/sssd-1.16.4.tar.gz
diff --git a/.sssd.metadata b/.sssd.metadata
index 7f29762..ab6b049 100644
--- a/.sssd.metadata
+++ b/.sssd.metadata
@@ -1 +1 @@
-46c59f189e5ae3286ef7878faf4801068d7bf2a7 SOURCES/sssd-1.16.2.tar.gz
+9deedae904567f197ddcdc6ef69c72956d14d39e SOURCES/sssd-1.16.4.tar.gz
diff --git a/SOURCES/0001-Providers-Delay-online-check-on-startup.patch b/SOURCES/0001-Providers-Delay-online-check-on-startup.patch
new file mode 100644
index 0000000..6ab2a19
--- /dev/null
+++ b/SOURCES/0001-Providers-Delay-online-check-on-startup.patch
@@ -0,0 +1,229 @@
+From dab55626ce859dd519fe108b89fa723a38fb21d1 Mon Sep 17 00:00:00 2001
+From: Tomas Halman <thalman@redhat.com>
+Date: Wed, 20 Mar 2019 15:44:02 +0100
+Subject: [PATCH] Providers: Delay online check on startup
+
+Typical usecase is system startup or network restart. In such
+cases SSSD receives several messages from the system about
+network change and immediately starts connecting.
+With multiple addresses on interface or multiple interfaces
+SSSD receives even more messages.
+
+This patch introduces 1s delay for online check after first
+message.
+
+Online callback tries 3 times to go online. There is increasing
+delay between online checks up to 4s.
+
+Resolves: https://pagure.io/SSSD/sssd/issue/3467
+
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit fe4288088e6cccf7650e5c5def3bd67be90756be)
+---
+ src/providers/backend.h          |  1 +
+ src/providers/data_provider_be.c | 94 ++++++++++++++++++++++++--------
+ 2 files changed, 72 insertions(+), 23 deletions(-)
+
+diff --git a/src/providers/backend.h b/src/providers/backend.h
+index 1fe1c2313..5ab47b29a 100644
+--- a/src/providers/backend.h
++++ b/src/providers/backend.h
+@@ -112,6 +112,7 @@ struct be_ctx {
+     struct be_refresh_ctx *refresh_ctx;
+ 
+     size_t check_online_ref_count;
++    int check_online_retry_delay;
+ 
+     struct data_provider *provider;
+ 
+diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
+index fad6f2801..17513111c 100644
+--- a/src/providers/data_provider_be.c
++++ b/src/providers/data_provider_be.c
+@@ -50,6 +50,9 @@
+ #include "resolv/async_resolv.h"
+ #include "monitor/monitor_interfaces.h"
+ 
++#define ONLINE_CB_RETRY 3
++#define ONLINE_CB_RETRY_MAX_DELAY 4
++
+ static int data_provider_res_init(struct sbus_request *dbus_req, void *data);
+ static int data_provider_go_offline(struct sbus_request *dbus_req, void *data);
+ static int data_provider_reset_offline(struct sbus_request *dbus_req, void *data);
+@@ -71,7 +74,7 @@ bool be_is_offline(struct be_ctx *ctx)
+     return ctx->offstat.offline;
+ }
+ 
+-static void check_if_online(struct be_ctx *be_ctx);
++static void check_if_online(struct be_ctx *be_ctx, int delay);
+ 
+ static errno_t
+ try_to_go_online(TALLOC_CTX *mem_ctx,
+@@ -82,7 +85,7 @@ try_to_go_online(TALLOC_CTX *mem_ctx,
+ {
+     struct be_ctx *ctx = (struct be_ctx*) be_ctx_void;
+ 
+-    check_if_online(ctx);
++    check_if_online(ctx, 0);
+     return EOK;
+ }
+ 
+@@ -247,10 +250,39 @@ static errno_t be_check_online_request(struct be_ctx *be_ctx)
+     return EOK;
+ }
+ 
++static void check_if_online_delayed(struct tevent_context *ev,
++                                    struct tevent_timer *tim,
++                                    struct timeval current_time,
++                                    void *private_data)
++{
++    errno_t ret;
++    struct be_ctx *be_ctx = talloc_get_type(private_data, struct be_ctx);
++
++    be_run_unconditional_online_cb(be_ctx);
++
++    if (!be_is_offline(be_ctx)) {
++        DEBUG(SSSDBG_TRACE_INTERNAL,
++              "Backend is already online, nothing to do.\n");
++        be_ctx->check_online_ref_count = 0;
++        return;
++    }
++
++    DEBUG(SSSDBG_TRACE_INTERNAL, "Trying to go back online!\n");
++
++    ret = be_check_online_request(be_ctx);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create check online req.\n");
++    } else {
++        DEBUG(SSSDBG_TRACE_INTERNAL, "Check online req created.\n");
++    }
++}
++
+ static void be_check_online_done(struct tevent_req *req)
+ {
+     struct be_ctx *be_ctx;
+     struct dp_reply_std *reply;
++    struct tevent_timer *time_event;
++    struct timeval schedule;
+     errno_t ret;
+ 
+     be_ctx = tevent_req_callback_data(req, struct be_ctx);
+@@ -285,11 +317,24 @@ static void be_check_online_done(struct tevent_req *req)
+     be_ctx->check_online_ref_count--;
+ 
+     if (reply->dp_error != DP_ERR_OK && be_ctx->check_online_ref_count > 0) {
+-        ret = be_check_online_request(be_ctx);
+-        if (ret != EOK) {
+-            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create check online req.\n");
++        be_ctx->check_online_retry_delay *= 2;
++        if (be_ctx->check_online_retry_delay > ONLINE_CB_RETRY_MAX_DELAY) {
++            be_ctx->check_online_retry_delay = ONLINE_CB_RETRY_MAX_DELAY;
++        }
++
++        schedule = tevent_timeval_current_ofs(be_ctx->check_online_retry_delay,
++                                              0);
++        time_event = tevent_add_timer(be_ctx->ev, be_ctx, schedule,
++                                      check_if_online_delayed, be_ctx);
++
++        if (time_event == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "Failed to schedule online check\n");
+             goto done;
+         }
++
++        DEBUG(SSSDBG_TRACE_INTERNAL,
++              "Schedule check_if_online_delayed in %ds.\n",
++              be_ctx->check_online_retry_delay);
+         return;
+     }
+ 
+@@ -303,28 +348,23 @@ done:
+     }
+ }
+ 
+-static void check_if_online(struct be_ctx *be_ctx)
++static void check_if_online(struct be_ctx *be_ctx, int delay)
+ {
+-    errno_t ret;
+-
+-    be_run_unconditional_online_cb(be_ctx);
+-
+-    if (!be_is_offline(be_ctx)) {
+-        DEBUG(SSSDBG_TRACE_INTERNAL,
+-              "Backend is already online, nothing to do.\n");
+-        return;
+-    }
++    struct tevent_timer *time_event;
++    struct timeval schedule;
+ 
+     /* Make sure nobody tries to go online while we are checking */
+     be_ctx->offstat.went_offline = time(NULL);
+ 
+-    DEBUG(SSSDBG_TRACE_INTERNAL, "Trying to go back online!\n");
+-
+     be_ctx->check_online_ref_count++;
+ 
+     if (be_ctx->check_online_ref_count != 1) {
+         DEBUG(SSSDBG_TRACE_INTERNAL,
+               "There is an online check already running.\n");
++        /* Do not have more than ONLINE_CB_RETRY retries in the queue */
++        if (be_ctx->check_online_ref_count > ONLINE_CB_RETRY) {
++            be_ctx->check_online_ref_count--;
++        }
+         return;
+     }
+ 
+@@ -334,12 +374,20 @@ static void check_if_online(struct be_ctx *be_ctx)
+         goto failed;
+     }
+ 
+-    ret = be_check_online_request(be_ctx);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create check online req.\n");
++    schedule = tevent_timeval_current_ofs(delay, 0);
++    time_event = tevent_add_timer(be_ctx->ev, be_ctx, schedule,
++                                  check_if_online_delayed, be_ctx);
++
++    if (time_event == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Scheduling check_if_online_delayed failed.\n");
+         goto failed;
+     }
+ 
++    be_ctx->check_online_ref_count = ONLINE_CB_RETRY;
++    be_ctx->check_online_retry_delay = 1;
++    DEBUG(SSSDBG_TRACE_INTERNAL,
++          "Schedule check_if_online_delayed in %ds.\n", delay);
+     return;
+ 
+ failed:
+@@ -373,7 +421,7 @@ static void signal_be_reset_offline(struct tevent_context *ev,
+                                     void *private_data)
+ {
+     struct be_ctx *ctx = talloc_get_type(private_data, struct be_ctx);
+-    check_if_online(ctx);
++    check_if_online(ctx, 0);
+ }
+ 
+ errno_t be_process_init(TALLOC_CTX *mem_ctx,
+@@ -649,7 +697,7 @@ static int data_provider_res_init(struct sbus_request *dbus_req, void *data)
+     be_ctx = talloc_get_type(data, struct be_ctx);
+ 
+     resolv_reread_configuration(be_ctx->be_res->resolv);
+-    check_if_online(be_ctx);
++    check_if_online(be_ctx, 1);
+ 
+     return monitor_common_res_init(dbus_req, data);
+ }
+@@ -666,7 +714,7 @@ static int data_provider_reset_offline(struct sbus_request *dbus_req, void *data
+ {
+     struct be_ctx *be_ctx;
+     be_ctx = talloc_get_type(data, struct be_ctx);
+-    check_if_online(be_ctx);
++    check_if_online(be_ctx, 1);
+     return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
+ }
+ 
+-- 
+2.19.1
+
diff --git a/SOURCES/0001-krb5-locator-add-support-for-multiple-addresses.patch b/SOURCES/0001-krb5-locator-add-support-for-multiple-addresses.patch
deleted file mode 100644
index 747c2f2..0000000
--- a/SOURCES/0001-krb5-locator-add-support-for-multiple-addresses.patch
+++ /dev/null
@@ -1,468 +0,0 @@
-From 4b1137562c3446e85a6383010702850f9532a4f2 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 24 Feb 2017 13:55:47 +0100
-Subject: [PATCH] krb5 locator: add support for multiple addresses
-
-Read multiple addresses from the kdcinfo files add call the provided
-callback with each of them.
-
-Related to https://pagure.io/SSSD/sssd/issue/941
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-(cherry picked from commit efae9509cb05648357e9b4c10a93c0d38558bed4)
-
-DOWNSTREAM:
-Resolves: rhbz#1494690 - kdcinfo files are not created for subdomains of a directly joined AD client
----
- src/krb5_plugin/sssd_krb5_locator_plugin.c | 344 +++++++++++++++------
- 1 file changed, 246 insertions(+), 98 deletions(-)
-
-diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-index 7c17fcb33373293fbbbe2be967dca57b31ef13de..82fb5c7b2ffa319ed250e54cdf9a0b6798d4ff51 100644
---- a/src/krb5_plugin/sssd_krb5_locator_plugin.c
-+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-@@ -42,7 +42,7 @@
- #define DEFAULT_KADMIN_PORT 749
- #define DEFAULT_KPASSWD_PORT 464
- 
--#define BUFSIZE 512
-+#define BUFSIZE 4096
- #define PORT_STR_SIZE 7
- #define SSSD_KRB5_LOCATOR_DEBUG "SSSD_KRB5_LOCATOR_DEBUG"
- #define SSSD_KRB5_LOCATOR_DISABLE "SSSD_KRB5_LOCATOR_DISABLE"
-@@ -53,12 +53,15 @@
-     } \
- } while(0)
- 
-+struct addr_port {
-+    char *addr;
-+    uint16_t port;
-+};
-+
- struct sssd_ctx {
-     char *sssd_realm;
--    char *kdc_addr;
--    uint16_t kdc_port;
--    char *kpasswd_addr;
--    uint16_t kpasswd_port;
-+    struct addr_port *kdc_addr;
-+    struct addr_port *kpasswd_addr;
-     bool debug;
-     bool disabled;
- };
-@@ -82,6 +85,186 @@ void plugin_debug_fn(const char *format, ...)
-     free(s);
- }
- 
-+
-+static void free_addr_port_list(struct addr_port **list)
-+{
-+    size_t c;
-+
-+    if (list == NULL || *list == NULL) {
-+        return;
-+    }
-+
-+    for (c = 0; (*list)[c].addr != NULL; c++) {
-+        free((*list)[c].addr);
-+    }
-+    free(*list);
-+    *list = NULL;
-+}
-+
-+static int copy_addr_port_list(struct addr_port *src, bool clear_port,
-+                               struct addr_port **dst)
-+{
-+    size_t c;
-+    struct addr_port *d = NULL;
-+    int ret;
-+
-+    /* only copy if dst is initialized to NULL */
-+    if (dst == NULL || *dst != NULL) {
-+        return EINVAL;
-+    }
-+
-+    if (src == NULL) {
-+        return 0;
-+    }
-+
-+    for (c = 0; src[c].addr != NULL; c++);
-+
-+    d = calloc((c + 1), sizeof(struct addr_port));
-+    if (d == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    for (c = 0; src[c].addr != NULL; c++) {
-+        d[c].addr = strdup(src[c].addr);
-+        if (d[c].addr == NULL) {
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+        if (clear_port) {
-+            d[c].port = 0;
-+        } else {
-+            d[c].port = src[c].port;
-+        }
-+    }
-+
-+    ret = EOK;
-+
-+done:
-+    if (ret != EOK) {
-+        free_addr_port_list(&d);
-+    } else {
-+        *dst = d;
-+    }
-+
-+    return ret;
-+}
-+
-+static int buf_to_addr_port_list(struct sssd_ctx *ctx,
-+                                 uint8_t *buf, size_t buf_size,
-+                                 struct addr_port **list)
-+{
-+    struct addr_port *l = NULL;
-+    int ret;
-+    uint8_t *p;
-+    uint8_t *pn;
-+    size_t c;
-+    size_t len;
-+    char *tmp = NULL;
-+    char *port_str;
-+    long port;
-+    char *endptr;
-+
-+    /* only create if list is initialized to NULL */
-+    if (buf == NULL || buf_size == 0 || list == NULL || *list != NULL) {
-+        return EINVAL;
-+    }
-+
-+    c = 1; /* to account for a missing \n at the very end */
-+    p = buf;
-+    while ((p - buf) < buf_size
-+                && (p = memchr(p, '\n', buf_size - (p - buf))) != NULL) {
-+        p++;
-+        c++;
-+    }
-+
-+    l = calloc((c + 1), sizeof(struct addr_port));
-+    if (l == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    c = 0;
-+    p = buf;
-+    do {
-+        pn = memchr(p, '\n', buf_size - (p - buf));
-+        if (pn != NULL) {
-+            len = pn - p;
-+        } else {
-+            len = buf_size - (p - buf);
-+        }
-+        if (len == 0) {
-+            /* empty line no more processing */
-+            break;
-+        }
-+
-+        free(tmp);
-+        tmp = strndup((char *) p, len);
-+        if (tmp == NULL) {
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+
-+        port_str = strrchr(tmp, ':');
-+        if (port_str == NULL) {
-+            port = 0;
-+        } else {
-+            *port_str = '\0';
-+            ++port_str;
-+
-+            if (isdigit(*port_str)) {
-+                errno = 0;
-+                port = strtol(port_str, &endptr, 10);
-+                if (errno != 0) {
-+                    ret = errno;
-+                    PLUGIN_DEBUG(("strtol failed on [%s]: [%d][%s], "
-+                                "assuming default.\n", port_str, ret,
-+                                                       strerror(ret)));
-+                    port = 0;
-+                }
-+                if (*endptr != '\0') {
-+                    PLUGIN_DEBUG(("Found additional characters [%s] in port "
-+                                "number [%s], assuming default.\n", endptr,
-+                                                                    port_str));
-+                    port = 0;
-+                }
-+
-+                if (port < 0 || port > 65535) {
-+                    PLUGIN_DEBUG(("Illegal port number [%ld], assuming "
-+                                  "default.\n", port));
-+                    port = 0;
-+                }
-+            } else {
-+                PLUGIN_DEBUG(("Illegal port number [%s], assuming default.\n",
-+                            port_str));
-+                port = 0;
-+            }
-+        }
-+
-+        PLUGIN_DEBUG(("Found [%s][%d].\n", tmp, port));
-+
-+        l[c].addr = strdup(tmp);
-+        if (l[c].addr == NULL) {
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+        l[c].port = port;
-+
-+        c++;
-+        p = pn == NULL ? NULL : (pn + 1);
-+    } while (p != NULL);
-+
-+    ret = EOK;
-+
-+done:
-+    free(tmp);
-+    if (ret != EOK) {
-+        free_addr_port_list(&l);
-+    } else {
-+        *list = l;
-+    }
-+
-+    return ret;
-+}
-+
- static int get_krb5info(const char *realm, struct sssd_ctx *ctx,
-                         enum locate_service_type svc)
- {
-@@ -91,9 +274,6 @@ static int get_krb5info(const char *realm, struct sssd_ctx *ctx,
-     uint8_t buf[BUFSIZE + 1];
-     int fd = -1;
-     const char *name_tmpl = NULL;
--    char *port_str;
--    long port;
--    char *endptr;
- 
-     switch (svc) {
-         case locate_service_kdc:
-@@ -148,62 +328,21 @@ static int get_krb5info(const char *realm, struct sssd_ctx *ctx,
-         PLUGIN_DEBUG(("Content of krb5info file [%s] is [%d] or larger.\n",
-                       krb5info_name, BUFSIZE));
-     }
--    PLUGIN_DEBUG(("Found [%s] in [%s].\n", buf, krb5info_name));
--
--    port_str = strrchr((char *) buf, ':');
--    if (port_str == NULL) {
--        port = 0;
--    } else {
--        *port_str = '\0';
--        ++port_str;
--
--        if (isdigit(*port_str)) {
--            errno = 0;
--            port = strtol(port_str, &endptr, 10);
--            if (errno != 0) {
--                ret = errno;
--                PLUGIN_DEBUG(("strtol failed on [%s]: [%d][%s], "
--                            "assuming default.\n", port_str, ret, strerror(ret)));
--                port = 0;
--            }
--            if (*endptr != '\0') {
--                PLUGIN_DEBUG(("Found additional characters [%s] in port number "
--                            "[%s], assuming default.\n", endptr, port_str));
--                port = 0;
--            }
--
--            if (port < 0 || port > 65535) {
--                PLUGIN_DEBUG(("Illegal port number [%ld], assuming default.\n",
--                            port));
--                port = 0;
--            }
--        } else {
--            PLUGIN_DEBUG(("Illegal port number [%s], assuming default.\n",
--                        port_str));
--            port = 0;
--        }
--    }
- 
-     switch (svc) {
-         case locate_service_kdc:
--            free(ctx->kdc_addr);
--            ctx->kdc_addr = strdup((char *) buf);
--            if (ctx->kdc_addr == NULL) {
--                PLUGIN_DEBUG(("strdup failed.\n"));
--                ret = ENOMEM;
-+            free_addr_port_list(&(ctx->kdc_addr));
-+            ret = buf_to_addr_port_list(ctx, buf, len, &(ctx->kdc_addr));
-+            if (ret != EOK) {
-                 goto done;
-             }
--            ctx->kdc_port = (uint16_t) port;
-             break;
-         case locate_service_kpasswd:
--            free(ctx->kpasswd_addr);
--            ctx->kpasswd_addr = strdup((char *) buf);
--            if (ctx->kpasswd_addr == NULL) {
--                PLUGIN_DEBUG(("strdup failed.\n"));
--                ret = ENOMEM;
-+            free_addr_port_list(&(ctx->kpasswd_addr));
-+            ret = buf_to_addr_port_list(ctx, buf, len, &(ctx->kpasswd_addr));
-+            if (ret != EOK) {
-                 goto done;
-             }
--            ctx->kpasswd_port = (uint16_t) port;
-             break;
-         default:
-             PLUGIN_DEBUG(("Unsupported service [%d].\n", svc));
-@@ -256,8 +395,8 @@ void sssd_krb5_locator_close(void *private_data)
-     ctx = (struct sssd_ctx *) private_data;
-     PLUGIN_DEBUG(("sssd_krb5_locator_close called\n"));
- 
--    free(ctx->kdc_addr);
--    free(ctx->kpasswd_addr);
-+    free_addr_port_list(&(ctx->kdc_addr));
-+    free_addr_port_list(&(ctx->kpasswd_addr));
-     free(ctx->sssd_realm);
-     free(ctx);
- 
-@@ -277,8 +416,10 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-     struct sssd_ctx *ctx;
-     struct addrinfo ai_hints;
-     uint16_t port = 0;
--    const char *addr = NULL;
-+    uint16_t default_port = 0;
-+    struct addr_port *addr = NULL;
-     char port_str[PORT_STR_SIZE];
-+    size_t c;
- 
-     if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE;
-     ctx = (struct sssd_ctx *) private_data;
-@@ -308,9 +449,13 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-             if (ret != EOK) {
-                 PLUGIN_DEBUG(("reading kpasswd address failed, "
-                               "using kdc address.\n"));
--                free(ctx->kpasswd_addr);
--                ctx->kpasswd_addr = strdup(ctx->kdc_addr);
--                ctx->kpasswd_port = 0;
-+                free_addr_port_list(&(ctx->kpasswd_addr));
-+                ret = copy_addr_port_list(ctx->kdc_addr, true,
-+                                          &(ctx->kpasswd_addr));
-+                if (ret != EOK) {
-+                    PLUGIN_DEBUG(("copying address list failed.\n"));
-+                    return KRB5_PLUGIN_NO_HANDLE;
-+                }
-             }
-         }
-     }
-@@ -322,19 +467,19 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-     switch (svc) {
-         case locate_service_kdc:
-             addr = ctx->kdc_addr;
--            port = ctx->kdc_port ? ctx->kdc_port : DEFAULT_KERBEROS_PORT;
-+            default_port = DEFAULT_KERBEROS_PORT;
-             break;
-         case locate_service_master_kdc:
-             addr = ctx->kpasswd_addr;
--            port = DEFAULT_KERBEROS_PORT;
-+            default_port = DEFAULT_KERBEROS_PORT;
-             break;
-         case locate_service_kadmin:
-             addr = ctx->kpasswd_addr;
--            port = DEFAULT_KADMIN_PORT;
-+            default_port = DEFAULT_KADMIN_PORT;
-             break;
-         case locate_service_kpasswd:
-             addr = ctx->kpasswd_addr;
--            port = ctx->kpasswd_port ? ctx->kpasswd_port : DEFAULT_KPASSWD_PORT;
-+            default_port = DEFAULT_KPASSWD_PORT;
-             break;
-         case locate_service_krb524:
-             return KRB5_PLUGIN_NO_HANDLE;
-@@ -362,46 +507,49 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-     if (strcmp(realm, ctx->sssd_realm) != 0)
-         return KRB5_PLUGIN_NO_HANDLE;
- 
--    memset(port_str, 0, PORT_STR_SIZE);
--    ret = snprintf(port_str, PORT_STR_SIZE-1, "%u", port);
--    if (ret < 0 || ret >= (PORT_STR_SIZE-1)) {
--        PLUGIN_DEBUG(("snprintf failed.\n"));
--        return KRB5_PLUGIN_NO_HANDLE;
--    }
--
--    memset(&ai_hints, 0, sizeof(struct addrinfo));
--    ai_hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
--    ai_hints.ai_socktype = socktype;
--
--    ret = getaddrinfo(addr, port_str, &ai_hints, &ai);
--    if (ret != 0) {
--        PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n", ret,
--                                                        gai_strerror(ret)));
--        if (ret == EAI_SYSTEM) {
--            PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n", errno,
--                                                            strerror(errno)));
-+    for (c = 0; addr[c].addr != NULL; c++) {
-+        port = (addr[c].port == 0 ? default_port : addr[c].port);
-+        memset(port_str, 0, PORT_STR_SIZE);
-+        ret = snprintf(port_str, PORT_STR_SIZE-1, "%u", port);
-+        if (ret < 0 || ret >= (PORT_STR_SIZE-1)) {
-+            PLUGIN_DEBUG(("snprintf failed.\n"));
-+            return KRB5_PLUGIN_NO_HANDLE;
-         }
--        return KRB5_PLUGIN_NO_HANDLE;
--    }
- 
--    PLUGIN_DEBUG(("addr[%s:%s] family[%d] socktype[%d]\n", addr, port_str,
--                 ai->ai_family, ai->ai_socktype));
-+        memset(&ai_hints, 0, sizeof(struct addrinfo));
-+        ai_hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
-+        ai_hints.ai_socktype = socktype;
- 
--    if ((family == AF_UNSPEC || ai->ai_family == family) &&
--        ai->ai_socktype == socktype) {
--
--        ret = cbfunc(cbdata, socktype, ai->ai_addr);
-+        ret = getaddrinfo(addr[c].addr, port_str, &ai_hints, &ai);
-         if (ret != 0) {
--            PLUGIN_DEBUG(("cbfunc failed\n"));
--            freeaddrinfo(ai);
--            return ret;
-+            PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n", ret,
-+                                                            gai_strerror(ret)));
-+            if (ret == EAI_SYSTEM) {
-+                PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n",
-+                              errno, strerror(errno)));
-+            }
-+            return KRB5_PLUGIN_NO_HANDLE;
-+        }
-+
-+        PLUGIN_DEBUG(("addr[%s:%s] family[%d] socktype[%d]\n", addr[c].addr,
-+                     port_str, ai->ai_family, ai->ai_socktype));
-+
-+        if ((family == AF_UNSPEC || ai->ai_family == family) &&
-+            ai->ai_socktype == socktype) {
-+
-+            ret = cbfunc(cbdata, socktype, ai->ai_addr);
-+            if (ret != 0) {
-+                PLUGIN_DEBUG(("cbfunc failed\n"));
-+                freeaddrinfo(ai);
-+                return ret;
-+            } else {
-+                PLUGIN_DEBUG(("[%s] used\n", addr[c].addr));
-+            }
-         } else {
--            PLUGIN_DEBUG(("[%s] used\n", addr));
-+            PLUGIN_DEBUG(("[%s] NOT used\n", addr[c].addr));
-         }
--    } else {
--        PLUGIN_DEBUG(("[%s] NOT used\n", addr));
-+        freeaddrinfo(ai);
-     }
--    freeaddrinfo(ai);
- 
-     return 0;
- }
--- 
-2.17.1
-
diff --git a/SOURCES/0002-KCM-Fall-back-to-using-the-first-ccache-if-the-defau.patch b/SOURCES/0002-KCM-Fall-back-to-using-the-first-ccache-if-the-defau.patch
new file mode 100644
index 0000000..0b2ee89
--- /dev/null
+++ b/SOURCES/0002-KCM-Fall-back-to-using-the-first-ccache-if-the-defau.patch
@@ -0,0 +1,49 @@
+From 6c568c9126e950d56cee734934e455eb2f5a3659 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Fri, 28 Sep 2018 17:29:10 +0200
+Subject: [PATCH] KCM: Fall back to using the first ccache if the default does
+ not exist
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3838
+
+KCM stores the default ccache in a separate DB entry. If the DB entry
+contains a UUID that cannot be found in the DB for whatever reason, we
+should just use the first ccache as the default. (This is what we
+already do if there is no default)
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 6bf5bcad6b9c5fb5fd867cbb094fef2a02ebf22d)
+---
+ src/responder/kcm/kcmsrv_ops.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/src/responder/kcm/kcmsrv_ops.c b/src/responder/kcm/kcmsrv_ops.c
+index 1e229adc4..5c4ece79e 100644
+--- a/src/responder/kcm/kcmsrv_ops.c
++++ b/src/responder/kcm/kcmsrv_ops.c
+@@ -1509,7 +1509,17 @@ static void kcm_op_get_default_ccache_byuuid_done(struct tevent_req *subreq)
+         DEBUG(SSSDBG_OP_FAILURE,
+               "Cannot get ccahe by UUID [%d]: %s\n",
+               ret, sss_strerror(ret));
+-        tevent_req_error(req, ret);
++        /* Instead of failing the whole operation, return the first
++         * ccache as a fallback
++         */
++        subreq = kcm_ccdb_list_send(state, state->ev,
++                                    state->op_ctx->kcm_data->db,
++                                    state->op_ctx->client);
++        if (subreq == NULL) {
++            tevent_req_error(req, ENOMEM);
++            return;
++        }
++        tevent_req_set_callback(subreq, kcm_op_get_default_ccache_list_done, req);
+         return;
+     }
+ 
+-- 
+2.19.1
+
diff --git a/SOURCES/0002-krb5-locator-fix-IPv6-support.patch b/SOURCES/0002-krb5-locator-fix-IPv6-support.patch
deleted file mode 100644
index f602116..0000000
--- a/SOURCES/0002-krb5-locator-fix-IPv6-support.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 45a48b9a73f39e9ef9e622dbcf87cc05a2a54e40 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 22 May 2018 17:59:52 +0200
-Subject: [PATCH] krb5 locator: fix IPv6 support
-
-IPv6 addresses are added with surrounding '[' and ']' to the kdcinfo
-file to be able to specify a port number properly. The Kerberos location
-plugin didn't handle those entries properly.
-
-Related to https://pagure.io/SSSD/sssd/issue/941
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-(cherry picked from commit 9f683246228848173c57ad02bde241bd761481ea)
----
- src/krb5_plugin/sssd_krb5_locator_plugin.c | 19 +++++++++++++++++--
- 1 file changed, 17 insertions(+), 2 deletions(-)
-
-diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-index 82fb5c7b2ffa319ed250e54cdf9a0b6798d4ff51..58cac7f4b244903347e6f1811cd8de2d61281c4f 100644
---- a/src/krb5_plugin/sssd_krb5_locator_plugin.c
-+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-@@ -159,6 +159,8 @@ static int buf_to_addr_port_list(struct sssd_ctx *ctx,
-     uint8_t *pn;
-     size_t c;
-     size_t len;
-+    size_t addr_len;
-+    char *addr_str = NULL;
-     char *tmp = NULL;
-     char *port_str;
-     long port;
-@@ -206,6 +208,9 @@ static int buf_to_addr_port_list(struct sssd_ctx *ctx,
-         port_str = strrchr(tmp, ':');
-         if (port_str == NULL) {
-             port = 0;
-+        } else if (tmp[0] == '[' && *(port_str - 1) != ']') {
-+            /* IPv6 address without port number */
-+            port = 0;
-         } else {
-             *port_str = '\0';
-             ++port_str;
-@@ -239,9 +244,19 @@ static int buf_to_addr_port_list(struct sssd_ctx *ctx,
-             }
-         }
- 
--        PLUGIN_DEBUG(("Found [%s][%d].\n", tmp, port));
-+        /* make sure tmp is not modified so that it can be freed later */
-+        addr_str = tmp;
-+        /* strip leading '[' and trailing ']' from IPv6 addresses */
-+        if (addr_str[0] == '['
-+                && (addr_len = strlen(addr_str))
-+                && addr_str[addr_len - 1] == ']') {
-+            addr_str[addr_len -1] = '\0';
-+            addr_str++;
-+        }
- 
--        l[c].addr = strdup(tmp);
-+        PLUGIN_DEBUG(("Found [%s][%d].\n", addr_str, port));
-+
-+        l[c].addr = strdup(addr_str);
-         if (l[c].addr == NULL) {
-             ret = ENOMEM;
-             goto done;
--- 
-2.17.1
-
diff --git a/SOURCES/0003-GPO-Add-option-ad_gpo_ignore_unreadable.patch b/SOURCES/0003-GPO-Add-option-ad_gpo_ignore_unreadable.patch
new file mode 100644
index 0000000..088ce18
--- /dev/null
+++ b/SOURCES/0003-GPO-Add-option-ad_gpo_ignore_unreadable.patch
@@ -0,0 +1,219 @@
+From ad058011b6b75b15c674be46a3ae9b3cc5228175 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
+Date: Wed, 17 Oct 2018 16:57:20 +0200
+Subject: [PATCH] GPO: Add option ad_gpo_ignore_unreadable
+
+Add option to ignore group policy containers in AD
+with unreadable or missing attributes. This is
+for the case when server contains GPOs that
+have very strict permissions on their attributes
+in AD but are unrelated to access control.
+
+Rather then using this option it is better to
+change the permissions on the AD objects but
+that may not be always possible (company policy,
+not access to server etc.).
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3867
+CVE-2018-16838
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 2f27dd9f05c2d3ed1c190ba387bc97738988efb0)
+---
+ src/config/cfg_rules.ini     |  1 +
+ src/man/sssd-ad.5.xml        | 19 ++++++++++
+ src/providers/ad/ad_common.h |  1 +
+ src/providers/ad/ad_gpo.c    | 67 +++++++++++++++++++++++++++++++++---
+ src/providers/ad/ad_opts.c   |  1 +
+ 5 files changed, 85 insertions(+), 4 deletions(-)
+
+diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
+index 887428437..603211711 100644
+--- a/src/config/cfg_rules.ini
++++ b/src/config/cfg_rules.ini
+@@ -439,6 +439,7 @@ option = ad_enabled_domains
+ option = ad_enable_gc
+ option = ad_gpo_access_control
+ option = ad_gpo_implicit_deny
++option = ad_gpo_ignore_unreadable
+ option = ad_gpo_cache_timeout
+ option = ad_gpo_default_right
+ option = ad_gpo_map_batch
+diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
+index f9b7f7667..b14f07f7f 100644
+--- a/src/man/sssd-ad.5.xml
++++ b/src/man/sssd-ad.5.xml
+@@ -437,6 +437,25 @@ DOM:dom1:(memberOf:1.2.840.113556.1.4.1941:=cn=nestedgroup,ou=groups,dc=example,
+                     </listitem>
+                 </varlistentry>
+ 
++                <varlistentry>
++                    <term>ad_gpo_ignore_unreadable (boolean)</term>
++                    <listitem>
++                        <para>
++                            Normally when some group policy containers (AD
++                            object) of applicable group policy objects are
++                            not readable by SSSD then users are denied access.
++                            This option allows to ignore group policy
++                            containers and with them associated policies
++                            if their attributes in group policy containers
++                            are not readable for SSSD.
++                        </para>
++                        <para>
++                            Default: False
++                        </para>
++                    </listitem>
++                </varlistentry>
++
++
+ 
+                 <varlistentry>
+                     <term>ad_gpo_cache_timeout (integer)</term>
+diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
+index 2c52c997a..529753a8a 100644
+--- a/src/providers/ad/ad_common.h
++++ b/src/providers/ad/ad_common.h
+@@ -53,6 +53,7 @@ enum ad_basic_opt {
+     AD_ENABLE_GC,
+     AD_GPO_ACCESS_CONTROL,
+     AD_GPO_IMPLICIT_DENY,
++    AD_GPO_IGNORE_UNREADABLE,
+     AD_GPO_CACHE_TIMEOUT,
+     AD_GPO_MAP_INTERACTIVE,
+     AD_GPO_MAP_REMOTE_INTERACTIVE,
+diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
+index 3b472e0e9..5f85910a9 100644
+--- a/src/providers/ad/ad_gpo.c
++++ b/src/providers/ad/ad_gpo.c
+@@ -3603,6 +3603,7 @@ struct ad_gpo_process_gpo_state {
+     struct ad_access_ctx *access_ctx;
+     struct tevent_context *ev;
+     struct sdap_id_op *sdap_op;
++    struct dp_option *ad_options;
+     struct sdap_options *opts;
+     char *server_hostname;
+     struct sss_domain_info *host_domain;
+@@ -3647,6 +3648,7 @@ ad_gpo_process_gpo_send(TALLOC_CTX *mem_ctx,
+ 
+     state->ev = ev;
+     state->sdap_op = sdap_op;
++    state->ad_options = access_ctx->ad_options;
+     state->opts = opts;
+     state->server_hostname = server_hostname;
+     state->host_domain = host_domain;
+@@ -3871,6 +3873,54 @@ static bool machine_ext_names_is_blank(char *attr_value)
+     return true;
+ }
+ 
++static errno_t
++ad_gpo_missing_or_unreadable_attr(struct ad_gpo_process_gpo_state *state,
++                                  struct tevent_req *req)
++{
++    bool ignore_unreadable = dp_opt_get_bool(state->ad_options,
++                                             AD_GPO_IGNORE_UNREADABLE);
++
++    if (ignore_unreadable) {
++        /* If admins decided to skip GPOs with unreadable
++         * attributes just log the SID of skipped GPO */
++        DEBUG(SSSDBG_TRACE_FUNC,
++              "Group Policy Container with DN [%s] has unreadable or missing "
++              "attributes -> skipping this GPO "
++              "(ad_gpo_ignore_unreadable = True)\n",
++              state->candidate_gpos[state->gpo_index]->gpo_dn);
++        state->gpo_index++;
++        return ad_gpo_get_gpo_attrs_step(req);
++    } else {
++        /* Inform in logs and syslog that this GPO can
++         * not be processed due to unreadable or missing
++         * attributes and point to possible server side
++         * and client side solutions. */
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Group Policy Container with DN [%s] is unreadable or has "
++              "unreadable or missing attributes. In order to fix this "
++              "make sure that this AD object has following attributes "
++              "readable: nTSecurityDescriptor, cn, gPCFileSysPath, "
++              "gPCMachineExtensionNames, gPCFunctionalityVersion, flags. "
++              "Alternatively if you do not have access to the server or can "
++              "not change permissions on this object, you can use option "
++              "ad_gpo_ignore_unreadable = True which will skip this GPO."
++              "See 'man ad_gpo_ignore_unreadable for details.'\n",
++              state->candidate_gpos[state->gpo_index]->gpo_dn);
++        sss_log(SSSDBG_CRIT_FAILURE,
++                "Group Policy Container with DN [%s] is unreadable or has "
++                "unreadable or missing attributes. In order to fix this "
++                "make sure that this AD object has following attributes "
++                "readable: nTSecurityDescriptor, cn, gPCFileSysPath, "
++                "gPCMachineExtensionNames, gPCFunctionalityVersion, flags. "
++                "Alternatively if you do not have access to the server or can "
++                "not change permissions on this object, you can use option "
++                "ad_gpo_ignore_unreadable = True which will skip this GPO."
++                "See 'man ad_gpo_ignore_unreadable for details.'\n",
++                state->candidate_gpos[state->gpo_index]->gpo_dn);
++        return EFAULT;
++    }
++}
++
+ static errno_t
+ ad_gpo_sd_process_attrs(struct tevent_req *req,
+                         char *smb_host,
+@@ -3890,7 +3940,10 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
+ 
+     /* retrieve AD_AT_CN */
+     ret = sysdb_attrs_get_string(result, AD_AT_CN, &gpo_guid);
+-    if (ret != EOK) {
++    if (ret == ENOENT) {
++        ret = ad_gpo_missing_or_unreadable_attr(state, req);
++        goto done;
++    } else if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE,
+               "sysdb_attrs_get_string failed: [%d](%s)\n",
+               ret, sss_strerror(ret));
+@@ -3911,7 +3964,10 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
+                                  AD_AT_FILE_SYS_PATH,
+                                  &raw_file_sys_path);
+ 
+-    if (ret != EOK) {
++    if (ret == ENOENT) {
++        ret = ad_gpo_missing_or_unreadable_attr(state, req);
++        goto done;
++    } else if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE,
+               "sysdb_attrs_get_string failed: [%d](%s)\n",
+               ret, sss_strerror(ret));
+@@ -3959,7 +4015,10 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
+     /* retrieve AD_AT_FLAGS */
+     ret = sysdb_attrs_get_int32_t(result, AD_AT_FLAGS,
+                                   &gp_gpo->gpo_flags);
+-    if (ret != EOK) {
++    if (ret == ENOENT) {
++        ret = ad_gpo_missing_or_unreadable_attr(state, req);
++        goto done;
++    } else if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE,
+               "sysdb_attrs_get_int32_t failed: [%d](%s)\n",
+               ret, sss_strerror(ret));
+@@ -3977,7 +4036,7 @@ ad_gpo_sd_process_attrs(struct tevent_req *req,
+     if ((ret == ENOENT) || (el->num_values == 0)) {
+         DEBUG(SSSDBG_OP_FAILURE,
+               "nt_sec_desc attribute not found or has no value\n");
+-        ret = ENOENT;
++        ret = ad_gpo_missing_or_unreadable_attr(state, req);
+         goto done;
+     }
+ 
+diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
+index b274ba9b3..c408295f3 100644
+--- a/src/providers/ad/ad_opts.c
++++ b/src/providers/ad/ad_opts.c
+@@ -39,6 +39,7 @@ struct dp_option ad_basic_opts[] = {
+     { "ad_enable_gc", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "ad_gpo_access_control", DP_OPT_STRING, { AD_GPO_ACCESS_MODE_DEFAULT }, NULL_STRING },
+     { "ad_gpo_implicit_deny", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
++    { "ad_gpo_ignore_unreadable", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "ad_gpo_cache_timeout", DP_OPT_NUMBER, { .number = 5 }, NULL_NUMBER },
+     { "ad_gpo_map_interactive", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "ad_gpo_map_remote_interactive", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+-- 
+2.19.1
+
diff --git a/SOURCES/0003-krb5-locator-make-plugin-more-robust.patch b/SOURCES/0003-krb5-locator-make-plugin-more-robust.patch
deleted file mode 100644
index fb596fb..0000000
--- a/SOURCES/0003-krb5-locator-make-plugin-more-robust.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 4e851d1391f56c632c271fd21dd96f29565cadfe Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 22 May 2018 18:03:05 +0200
-Subject: [PATCH] krb5 locator: make plugin more robust
-
-Although currently libkrb5 sets all parameters of the locator plugin
-calls to suitable values we should make sure that provided pointers are
-not NULL before trying to dereference them.
-
-Related to https://pagure.io/SSSD/sssd/issue/941
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-(cherry picked from commit c1fbc6b64ecaf51efc4379c4c8a4960de095abf0)
----
- src/krb5_plugin/sssd_krb5_locator_plugin.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-index 58cac7f4b244903347e6f1811cd8de2d61281c4f..9874fd2d1ce63b69099f057dd05f6e353a12ce75 100644
---- a/src/krb5_plugin/sssd_krb5_locator_plugin.c
-+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-@@ -439,6 +439,10 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-     if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE;
-     ctx = (struct sssd_ctx *) private_data;
- 
-+    if (realm == NULL || cbfunc == NULL || cbdata == NULL) {
-+        return KRB5_PLUGIN_NO_HANDLE;
-+    }
-+
-     if (ctx->disabled) {
-         PLUGIN_DEBUG(("Plugin disabled, nothing to do.\n"));
-         return KRB5_PLUGIN_NO_HANDLE;
--- 
-2.17.1
-
diff --git a/SOURCES/0004-AD-Allow-configuring-auto_private_groups-per-subdoma.patch b/SOURCES/0004-AD-Allow-configuring-auto_private_groups-per-subdoma.patch
new file mode 100644
index 0000000..86c2403
--- /dev/null
+++ b/SOURCES/0004-AD-Allow-configuring-auto_private_groups-per-subdoma.patch
@@ -0,0 +1,297 @@
+From 6f6b3b1f4fcec79a1640a97fb3cd875f2cd8b83a Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 19 Mar 2019 11:01:10 +0100
+Subject: [PATCH] AD: Allow configuring auto_private_groups per subdomain or
+ with subdomain_inherit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3965
+
+Previously, subdomains that used ID mapping always only used MPGs and
+POSIX subdomains always inherited the parent domain settings. This patch
+is a small RFE which allows to either set the auto_private_groups option
+directly per subdomain or set it for all subdomains using the
+subdomain_inherit option
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 41c497b8b9e6efb9f2aa8e4cc869d465c3b954b3)
+---
+ src/man/sssd.conf.5.xml               |  38 +++++----
+ src/providers/ad/ad_subdomains.c      | 107 ++++++++++++++++++++++----
+ src/providers/ldap/sdap_async_users.c |   2 +-
+ src/util/domain_info_utils.c          |  14 +++-
+ src/util/util.h                       |   3 +
+ 5 files changed, 130 insertions(+), 34 deletions(-)
+
+diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
+index 41ba7b924..3d017f638 100644
+--- a/src/man/sssd.conf.5.xml
++++ b/src/man/sssd.conf.5.xml
+@@ -2995,6 +2995,13 @@ subdomain_inherit = ldap_purge_cache_timeout
+                                             Create user's private group unconditionally from user's UID number.
+                                             The GID number is ignored in this case.
+                                         </para>
++                                        <para>
++                                            NOTE: Because the GID number and the user private group
++                                            are inferred from the UID number, it is not supported
++                                            to have multiple entries with the same UID or GID number
++                                            with this option. In other words, enabling this option
++                                            enforces uniqueness across the ID space.
++                                        </para>
+                                     </listitem>
+                                 </varlistentry>
+                                 <varlistentry>
+@@ -3041,24 +3048,25 @@ subdomain_inherit = ldap_purge_cache_timeout
+                                 </varlistentry>
+                             </variablelist>
+                         </para>
+-			<para>
+-			    For POSIX subdomains, setting the option in the main
+-			    domain is inherited in the subdomain.
+-			</para>
+-			<para>
+-			    For ID-mapping subdomains, auto_private_groups is
+-			    already enabled for the subdomains and setting it to
+-			    false will not have any effect for the subdomain.
+-			</para>
+                         <para>
+-                            NOTE: Because the GID number and the user private group
+-                            are inferred from the UID number, it is not supported
+-                            to have multiple entries with the same UID or GID number
+-                            with this option. In other words, enabling this option
+-                            enforces uniqueness across the ID space.
++                            For subdomains, the default value is False for
++                            subdomains that use assigned POSIX IDs and True
++                            for subdomains that use automatic ID-mapping.
+                         </para>
+                         <para>
+-                            Default: False
++                            The value of auto_private_groups can either be set per subdomains
++                            in a subsection, for example:
++<programlisting>
++[domain/forest.domain/sub.domain]
++auto_private_groups = false
++</programlisting>
++                            or globally for all subdomains in the main domain section
++                            using the subdomain_inherit option:
++<programlisting>
++[domain/forest.domain]
++subdomain_inherit = auto_private_groups
++auto_private_groups = false
++</programlisting>
+                         </para>
+                     </listitem>
+                 </varlistentry>
+diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
+index 5b046773c..4fc4be094 100644
+--- a/src/providers/ad/ad_subdomains.c
++++ b/src/providers/ad/ad_subdomains.c
+@@ -436,8 +436,87 @@ static errno_t ad_subdom_enumerates(struct sss_domain_info *parent,
+     return EOK;
+ }
+ 
++static enum sss_domain_mpg_mode
++get_default_subdom_mpg_mode(struct sdap_idmap_ctx *idmap_ctx,
++                            struct sss_domain_info *parent,
++                            const char *subdom_name,
++                            char *subdom_sid_str)
++{
++    bool use_id_mapping;
++    bool inherit_option;
++    enum sss_domain_mpg_mode default_mpg_mode;
++
++    inherit_option = string_in_list(CONFDB_DOMAIN_AUTO_UPG,
++                                    parent->sd_inherit, false);
++    if (inherit_option) {
++        return get_domain_mpg_mode(parent);
++    }
++
++    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx,
++                                                               subdom_name,
++                                                               subdom_sid_str);
++    if (use_id_mapping == true) {
++        default_mpg_mode = MPG_ENABLED;
++    } else {
++        /* Domains that use the POSIX attributes set by the admin must
++         * inherit the MPG setting from the parent domain so that the
++         * auto_private_groups options works for trusted domains as well
++         */
++        default_mpg_mode = get_domain_mpg_mode(parent);
++    }
++
++    return default_mpg_mode;
++}
++
++static enum sss_domain_mpg_mode
++ad_subdom_mpg_mode(TALLOC_CTX *mem_ctx,
++                   struct confdb_ctx *cdb,
++                   struct sss_domain_info *parent,
++                   enum sss_domain_mpg_mode default_mpg_mode,
++                   const char *subdom_name)
++{
++    char *subdom_conf_path;
++    char *mpg_str_opt;
++    errno_t ret;
++    enum sss_domain_mpg_mode ret_mode;
++
++    subdom_conf_path = subdomain_create_conf_path_from_str(mem_ctx,
++                                                           parent->name,
++                                                           subdom_name);
++    if (subdom_conf_path == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "subdom_conf_path failed, will use %s mode as fallback\n",
++              str_domain_mpg_mode(default_mpg_mode));
++        return default_mpg_mode;
++    }
++
++    ret = confdb_get_string(cdb, mem_ctx, subdom_conf_path,
++                            CONFDB_DOMAIN_AUTO_UPG,
++                            NULL,
++                            &mpg_str_opt);
++    talloc_free(subdom_conf_path);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "condb_get_string failed, will use %s mode as fallback\n",
++              str_domain_mpg_mode(default_mpg_mode));
++        return default_mpg_mode;
++    }
++
++    if (mpg_str_opt == NULL) {
++        DEBUG(SSSDBG_CONF_SETTINGS,
++              "Subdomain MPG mode not set, using %s\n",
++              str_domain_mpg_mode(default_mpg_mode));
++        return default_mpg_mode;
++    }
++
++    ret_mode = str_to_domain_mpg_mode(mpg_str_opt);
++    talloc_free(mpg_str_opt);
++    return ret_mode;
++}
++
+ static errno_t
+-ad_subdom_store(struct sdap_idmap_ctx *idmap_ctx,
++ad_subdom_store(struct confdb_ctx *cdb,
++                struct sdap_idmap_ctx *idmap_ctx,
+                 struct sss_domain_info *domain,
+                 struct sysdb_attrs *subdom_attrs,
+                 bool enumerate)
+@@ -451,8 +530,8 @@ ad_subdom_store(struct sdap_idmap_ctx *idmap_ctx,
+     struct ldb_message_element *el;
+     char *sid_str = NULL;
+     uint32_t trust_type;
+-    bool use_id_mapping;
+     enum sss_domain_mpg_mode mpg_mode;
++    enum sss_domain_mpg_mode default_mpg_mode;
+ 
+     tmp_ctx = talloc_new(NULL);
+     if (tmp_ctx == NULL) {
+@@ -501,17 +580,13 @@ ad_subdom_store(struct sdap_idmap_ctx *idmap_ctx,
+         goto done;
+     }
+ 
+-    use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx,
+-                                                               name, sid_str);
+-    if (use_id_mapping == true) {
+-        mpg_mode = MPG_ENABLED;
+-    } else {
+-        /* Domains that use the POSIX attributes set by the admin must
+-         * inherit the MPG setting from the parent domain so that the
+-         * auto_private_groups options works for trusted domains as well
+-         */
+-        mpg_mode = get_domain_mpg_mode(domain);
+-    }
++    default_mpg_mode = get_default_subdom_mpg_mode(idmap_ctx, domain,
++                                                   name, sid_str);
++
++    mpg_mode = ad_subdom_mpg_mode(tmp_ctx, cdb, domain,
++                                  default_mpg_mode, name);
++    DEBUG(SSSDBG_CONF_SETTINGS, "MPG mode of %s is %s\n",
++                                name, str_domain_mpg_mode(mpg_mode));
+ 
+     ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str,
+                                 mpg_mode, enumerate, domain->forest, 0, NULL);
+@@ -625,7 +700,8 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
+                 goto done;
+             }
+ 
+-            ret = ad_subdom_store(idmap_ctx, domain, subdomains[c], enumerate);
++            ret = ad_subdom_store(be_ctx->cdb, idmap_ctx, domain,
++                                  subdomains[c], enumerate);
+             if (ret) {
+                 /* Nothing we can do about the error. Let's at least try
+                  * to reuse the existing domains
+@@ -660,7 +736,8 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx,
+             goto done;
+         }
+ 
+-        ret = ad_subdom_store(idmap_ctx, domain, subdomains[c], enumerate);
++        ret = ad_subdom_store(be_ctx->cdb, idmap_ctx, domain,
++                              subdomains[c], enumerate);
+         if (ret) {
+             DEBUG(SSSDBG_MINOR_FAILURE, "Failed to parse subdom data, "
+                   "will try to use cached subdomain\n");
+diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
+index 92eeda1d3..af4dc1a17 100644
+--- a/src/providers/ldap/sdap_async_users.c
++++ b/src/providers/ldap/sdap_async_users.c
+@@ -389,7 +389,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
+             goto done;
+         }
+ 
+-        if (IS_SUBDOMAIN(dom) || sss_domain_is_mpg(dom) == true) {
++        if (sss_domain_is_mpg(dom) == true) {
+             /* For subdomain users, only create the private group as
+              * the subdomain is an MPG domain.
+              * But we have to save the GID of the original primary group
+diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
+index 4896ef051..4b1c9df39 100644
+--- a/src/util/domain_info_utils.c
++++ b/src/util/domain_info_utils.c
+@@ -889,6 +889,14 @@ bool sss_domain_is_forest_root(struct sss_domain_info *dom)
+     return (dom->forest_root == dom);
+ }
+ 
++char *subdomain_create_conf_path_from_str(TALLOC_CTX *mem_ctx,
++                                          const char *parent_name,
++                                          const char *subdom_name)
++{
++    return talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL "/%s",
++                           parent_name, subdom_name);
++}
++
+ char *subdomain_create_conf_path(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *subdomain)
+ {
+@@ -899,9 +907,9 @@ char *subdomain_create_conf_path(TALLOC_CTX *mem_ctx,
+         return NULL;
+     }
+ 
+-    return talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL "/%s",
+-                           subdomain->parent->name,
+-                           subdomain->name);
++    return subdomain_create_conf_path_from_str(mem_ctx,
++                                               subdomain->parent->name,
++                                               subdomain->name);
+ }
+ 
+ const char *sss_domain_type_str(struct sss_domain_info *dom)
+diff --git a/src/util/util.h b/src/util/util.h
+index 1e36bf02a..3003583b7 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -557,6 +557,9 @@ find_domain_by_object_name_ex(struct sss_domain_info *domain,
+ bool subdomain_enumerates(struct sss_domain_info *parent,
+                           const char *sd_name);
+ 
++char *subdomain_create_conf_path_from_str(TALLOC_CTX *mem_ctx,
++                                          const char *parent_name,
++                                          const char *subdom_name);
+ char *subdomain_create_conf_path(TALLOC_CTX *mem_ctx,
+                                  struct sss_domain_info *subdomain);
+ 
+-- 
+2.19.1
+
diff --git a/SOURCES/0004-krb5-locator-add-unit-tests.patch b/SOURCES/0004-krb5-locator-add-unit-tests.patch
deleted file mode 100644
index 28fe091..0000000
--- a/SOURCES/0004-krb5-locator-add-unit-tests.patch
+++ /dev/null
@@ -1,724 +0,0 @@
-From 3d6b8b306cdbd4ec15b36a1e7936d219204e08dc Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 24 May 2018 17:14:42 +0200
-Subject: [PATCH] krb5 locator: add unit tests
-
-Unit test for existing and new functionality of the Kerberos locator
-plugin.
-
-Related to https://pagure.io/SSSD/sssd/issue/941
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-(cherry picked from commit 2124275fe494a0241a552538c70f40c2291f3795)
----
- Makefile.am                                   |  20 +
- src/krb5_plugin/sssd_krb5_locator_plugin.c    |  16 +
- .../cmocka/test_sssd_krb5_locator_plugin.c    | 631 ++++++++++++++++++
- 3 files changed, 667 insertions(+)
- create mode 100644 src/tests/cmocka/test_sssd_krb5_locator_plugin.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 9539b3cff8544cf406e3e19ab23e76e9cc8234ee..9055130ed74057987795285c243ff47584cf8316 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -288,6 +288,7 @@ if HAVE_CMOCKA
-         krb5_common_test \
-         test_iobuf \
-         sss_certmap_test \
-+        test_sssd_krb5_locator_plugin \
-         $(NULL)
- 
- 
-@@ -3518,6 +3519,25 @@ sss_certmap_test_LDADD = \
-     libsss_certmap.la \
-     $(NULL)
- 
-+test_sssd_krb5_locator_plugin_SOURCES = \
-+    src/tests/cmocka/test_sssd_krb5_locator_plugin.c \
-+    src/krb5_plugin/sssd_krb5_locator_plugin.c \
-+    $(NULL)
-+test_sssd_krb5_locator_plugin_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(POPT_CFLAGS) \
-+    $(TALLOC_CFLAGS) \
-+    $(KRB5_CFLAGS) \
-+    -DTEST_PUBCONF_PATH=\"$(abs_builddir)/src/tests/cmocka/pubconf\" \
-+    $(NULL)
-+test_sssd_krb5_locator_plugin_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(POPT_LIBS) \
-+    $(TALLOC_LIBS) \
-+    $(KRB5_LIBS) \
-+    libsss_test_common.la \
-+    $(NULL)
-+
- if BUILD_KCM
- test_kcm_json_SOURCES = \
-     src/tests/cmocka/test_kcm_json_marshalling.c \
-diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-index 9874fd2d1ce63b69099f057dd05f6e353a12ce75..952d487c276ed51e0c3a018b0d0af59ca214525f 100644
---- a/src/krb5_plugin/sssd_krb5_locator_plugin.c
-+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-@@ -38,6 +38,22 @@
- 
- #include "providers/krb5/krb5_common.h"
- 
-+/* The following override of KDCINFO_TMPL and KPASSWDINFO_TMPL is not very
-+ * elegant but since they are defined in krb5_common.h with the help of
-+ * PUBCONF_PATH from config.h and PUBCONF_PATH can by set by a configure
-+ * options I didn't found another way to change the path for a unit test. */
-+#ifdef TEST_PUBCONF_PATH
-+#ifdef KDCINFO_TMPL
-+#undef KDCINFO_TMPL
-+#endif
-+#define KDCINFO_TMPL TEST_PUBCONF_PATH"/kdcinfo.%s"
-+
-+#ifdef KPASSWDINFO_TMPL
-+#undef KPASSWDINFO_TMPL
-+#endif
-+#define KPASSWDINFO_TMPL TEST_PUBCONF_PATH"/kpasswdinfo.%s"
-+#endif /* TEST_PUBCONF_PATH */
-+
- #define DEFAULT_KERBEROS_PORT 88
- #define DEFAULT_KADMIN_PORT 749
- #define DEFAULT_KPASSWD_PORT 464
-diff --git a/src/tests/cmocka/test_sssd_krb5_locator_plugin.c b/src/tests/cmocka/test_sssd_krb5_locator_plugin.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..3e7d00632ddb59da5474c0544eee6fc67edc5570
---- /dev/null
-+++ b/src/tests/cmocka/test_sssd_krb5_locator_plugin.c
-@@ -0,0 +1,631 @@
-+/*
-+    SSSD
-+
-+    Unit test for SSSD's MIT Kerberos locator plugin
-+
-+    Authors:
-+        Sumit Bose <sbose@redhat.com>
-+
-+    Copyright (C) 2018 Red Hat
-+
-+    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 "config.h"
-+
-+#include <popt.h>
-+#include <sys/types.h>
-+#include <sys/socket.h>
-+#include <sys/stat.h>
-+#include <string.h>
-+#include <fcntl.h>
-+#include <netdb.h>
-+#include <krb5/krb5.h>
-+#include <krb5/locate_plugin.h>
-+
-+#include "tests/cmocka/common_mock.h"
-+
-+#define TEST_REALM "TEST.REALM"
-+#define TEST_IP_1 "123.231.132.213"
-+#define TEST_IPV6_1_PURE "7025:4d2d:2b06:e321:d971:16c0:6eeb:cc41"
-+#define TEST_IPV6_1 "["TEST_IPV6_1_PURE"]"
-+#define TEST_SERVICE_1 "22334"
-+#define TEST_SERVICE_2 "54321"
-+#define TEST_IP_1_WITH_SERVICE TEST_IP_1":"TEST_SERVICE_1
-+#define TEST_IPV6_1_WITH_SERVICE TEST_IPV6_1":"TEST_SERVICE_2
-+
-+struct test_state {
-+    void *dummy;
-+};
-+
-+static int setup(void **state)
-+{
-+    struct test_state *ts = NULL;
-+
-+    assert_true(leak_check_setup());
-+
-+    ts = talloc(global_talloc_context, struct test_state);
-+    assert_non_null(ts);
-+
-+    check_leaks_push(ts);
-+    *state = (void *)ts;
-+
-+    unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-+    rmdir(TEST_PUBCONF_PATH);
-+
-+    return 0;
-+}
-+
-+static int teardown(void **state)
-+{
-+    struct test_state *ts = talloc_get_type_abort(*state, struct test_state);
-+
-+    assert_non_null(ts);
-+
-+    assert_true(check_leaks_pop(ts));
-+    talloc_free(ts);
-+    assert_true(leak_check_teardown());
-+    return 0;
-+}
-+
-+/* Taken from MIT Kerberos src/lib/krb5/os/locate_kdc.c and
-+ * lib/krb5/os/os-proto.h */
-+
-+typedef enum {
-+    TCP_OR_UDP = 0,
-+    TCP,
-+    UDP,
-+    HTTPS,
-+} k5_transport;
-+
-+/* A single server hostname or address. */
-+struct server_entry {
-+    char *hostname;             /* NULL -> use addrlen/addr instead */
-+    int port;                   /* Used only if hostname set */
-+    k5_transport transport;     /* May be 0 for UDP/TCP if hostname set */
-+    char *uri_path;             /* Used only if transport is HTTPS */
-+    int family;                 /* May be 0 (aka AF_UNSPEC) if hostname set */
-+    int master;                 /* True, false, or -1 for unknown. */
-+    size_t addrlen;
-+    struct sockaddr_storage addr;
-+};
-+
-+/* A list of server hostnames/addresses. */
-+struct serverlist {
-+    struct server_entry *servers;
-+    size_t nservers;
-+};
-+#define SERVERLIST_INIT { NULL, 0 }
-+
-+/* Free up everything pointed to by the serverlist structure, but don't
-+ *  * free the structure itself. */
-+void
-+k5_free_serverlist (struct serverlist *list)
-+{
-+    size_t i;
-+
-+    for (i = 0; i < list->nservers; i++) {
-+        free(list->servers[i].hostname);
-+        free(list->servers[i].uri_path);
-+    }
-+    free(list->servers);
-+    list->servers = NULL;
-+    list->nservers = 0;
-+}
-+
-+/* Make room for a new server entry in list and return a pointer to the new
-+ * entry.  (Do not increment list->nservers.) */
-+static struct server_entry *
-+new_server_entry(struct serverlist *list)
-+{
-+    struct server_entry *newservers, *entry;
-+    size_t newspace = (list->nservers + 1) * sizeof(struct server_entry);
-+
-+    newservers = realloc(list->servers, newspace);
-+    if (newservers == NULL)
-+        return NULL;
-+    list->servers = newservers;
-+    entry = &newservers[list->nservers];
-+    memset(entry, 0, sizeof(*entry));
-+    entry->master = -1;
-+    return entry;
-+}
-+
-+/* Add an address entry to list. */
-+static int
-+add_addr_to_list(struct serverlist *list, k5_transport transport, int family,
-+                 size_t addrlen, struct sockaddr *addr)
-+{
-+    struct server_entry *entry;
-+
-+    entry = new_server_entry(list);
-+    if (entry == NULL)
-+        return ENOMEM;
-+    entry->transport = transport;
-+    entry->family = family;
-+    entry->hostname = NULL;
-+    entry->uri_path = NULL;
-+    entry->addrlen = addrlen;
-+    memcpy(&entry->addr, addr, addrlen);
-+    list->nservers++;
-+    return 0;
-+}
-+
-+struct module_callback_data {
-+    int out_of_mem;
-+    struct serverlist *list;
-+};
-+
-+static int
-+module_callback(void *cbdata, int socktype, struct sockaddr *sa)
-+{
-+    struct module_callback_data *d = cbdata;
-+    size_t addrlen;
-+    k5_transport transport;
-+
-+    if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
-+        return 0;
-+    if (sa->sa_family == AF_INET)
-+        addrlen = sizeof(struct sockaddr_in);
-+    else if (sa->sa_family == AF_INET6)
-+        addrlen = sizeof(struct sockaddr_in6);
-+    else
-+        return 0;
-+    transport = (socktype == SOCK_STREAM) ? TCP : UDP;
-+    if (add_addr_to_list(d->list, transport, sa->sa_family, addrlen,
-+                         sa) != 0) {
-+        /* Assumes only error is ENOMEM.  */
-+        d->out_of_mem = 1;
-+        return 1;
-+    }
-+    return 0;
-+}
-+
-+krb5_error_code sssd_krb5_locator_init(krb5_context context,
-+                                       void **private_data);
-+void sssd_krb5_locator_close(void *private_data);
-+
-+krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-+                    enum locate_service_type svc,
-+                    const char *realm,
-+                    int socktype,
-+                    int family,
-+                    int (*cbfunc)(void *, int, struct sockaddr *),
-+                    void *cbdata);
-+
-+void test_init(void **state)
-+{
-+    krb5_context ctx;
-+    krb5_error_code kerr;
-+    void *priv;
-+
-+    kerr = krb5_init_context (&ctx);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_init(ctx, &priv);
-+    assert_int_equal(kerr, 0);
-+
-+    sssd_krb5_locator_close(priv);
-+
-+    krb5_free_context(ctx);
-+}
-+
-+void test_failed_lookup(void **state)
-+{
-+    krb5_context ctx;
-+    krb5_error_code kerr;
-+    void *priv;
-+    struct module_callback_data cbdata = { 0 };
-+
-+
-+    kerr = krb5_init_context (&ctx);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_init(ctx, &priv);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_lookup(NULL, -1, NULL, -1, -1, NULL, NULL);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, -1, NULL, -1, -1, NULL, NULL);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , NULL, -1, -1,
-+                                    NULL, NULL);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM, -1,
-+                                    -1, NULL, NULL);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, -1, NULL, NULL);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, NULL, NULL);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    NULL);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+
-+    sssd_krb5_locator_close(priv);
-+
-+    krb5_free_context(ctx);
-+}
-+
-+void test_empty(void **state)
-+{
-+    krb5_context ctx;
-+    krb5_error_code kerr;
-+    void *priv;
-+    int fd;
-+    struct module_callback_data cbdata = { 0 };
-+
-+    kerr = krb5_init_context (&ctx);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_init(ctx, &priv);
-+    assert_int_equal(kerr, 0);
-+
-+    mkdir(TEST_PUBCONF_PATH, 0777);
-+    fd = open(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM, O_CREAT, 0777);
-+    assert_int_not_equal(fd, -1);
-+    close(fd);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, KRB5_PLUGIN_NO_HANDLE);
-+    unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-+    rmdir(TEST_PUBCONF_PATH);
-+
-+    sssd_krb5_locator_close(priv);
-+
-+    krb5_free_context(ctx);
-+}
-+
-+void test_single(void **state)
-+{
-+    krb5_context ctx;
-+    krb5_error_code kerr;
-+    void *priv;
-+    int fd;
-+    struct serverlist list = SERVERLIST_INIT;
-+    struct module_callback_data cbdata = { 0 };
-+    ssize_t s;
-+    int ret;
-+    char host[NI_MAXHOST];
-+    char service[NI_MAXSERV];
-+
-+    cbdata.list = &list;
-+
-+    kerr = krb5_init_context (&ctx);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_init(ctx, &priv);
-+    assert_int_equal(kerr, 0);
-+
-+    mkdir(TEST_PUBCONF_PATH, 0777);
-+    fd = open(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM, O_CREAT|O_RDWR, 0777);
-+    assert_int_not_equal(fd, -1);
-+    s = write(fd, TEST_IP_1, sizeof(TEST_IP_1));
-+    assert_int_equal(s, sizeof(TEST_IP_1));
-+    close(fd);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+
-+    /* We asked for AF_INET6, but TEST_IP_1 is IPv4 */
-+    assert_int_equal(list.nservers, 0);
-+    assert_null(list.servers);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    assert_int_equal(list.servers[0].addrlen, 16);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IP_1, host);
-+    assert_string_equal("88", service);
-+
-+    k5_free_serverlist(&list);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_UNSPEC, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    assert_int_equal(list.servers[0].addrlen, 16);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IP_1, host);
-+    assert_string_equal("88", service);
-+
-+    k5_free_serverlist(&list);
-+
-+    unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-+    rmdir(TEST_PUBCONF_PATH);
-+    sssd_krb5_locator_close(priv);
-+
-+    krb5_free_context(ctx);
-+}
-+
-+struct test_data {
-+    const char *ip;
-+    bool found;
-+};
-+
-+void test_multi_check_results(struct test_data *test_data,
-+                              struct serverlist *list,
-+                              const char *exp_service)
-+{
-+    int ret;
-+    char host[NI_MAXHOST];
-+    char service[NI_MAXSERV];
-+    size_t c;
-+    size_t d;
-+
-+    /* To make sure each result from list has a matching entry in test_data we
-+     * use a flag to mark found entries, this way we can properly detect is
-+     * the same address is used multiple times. */
-+    for (d = 0; test_data[d].ip != NULL; d++) {
-+        test_data[d].found = false;
-+    }
-+
-+    for (c = 0; c < list->nservers; c++) {
-+        ret = getnameinfo((struct sockaddr *) &list->servers[c].addr,
-+                          list->servers[c].addrlen,
-+                          host, sizeof(host), service, sizeof(service),
-+                          NI_NUMERICHOST|NI_NUMERICSERV);
-+        assert_int_equal(ret, 0);
-+        assert_string_equal(exp_service, service);
-+        for (d = 0; test_data[d].ip != NULL; d++) {
-+            /* Compare result with test_data, be aware that the test_data has
-+             * '[]' around IPv& addresses */
-+            if (strncmp(host,
-+                        test_data[d].ip + (test_data[d].ip[0] == '[' ? 1 : 0),
-+                        strlen(host)) == 0 && !test_data[d].found) {
-+                test_data[d].found = true;
-+                break;
-+            }
-+        }
-+        /* Make sure we found the result in the list */
-+        assert_non_null(test_data[d].ip);
-+    }
-+}
-+
-+void test_multi(void **state)
-+{
-+    krb5_context ctx;
-+    krb5_error_code kerr;
-+    void *priv;
-+    int fd;
-+    struct serverlist list = SERVERLIST_INIT;
-+    struct module_callback_data cbdata = { 0 };
-+    ssize_t s;
-+    size_t c;
-+    struct test_data test_data[] = {
-+                           {TEST_IP_1, false},
-+                           {TEST_IPV6_1, false},
-+                           {"[c89a:565b:4510:5b9f:41fe:ea81:87a0:f21b]", false},
-+                           {"155.42.66.53", false},
-+                           {"[f812:5941:ba69:2bae:e806:3b68:770d:d75e]", false},
-+                           {"[3ad3:9dda:50e4:3c82:548f:eaa1:e120:6dd]", false},
-+                           {"55.116.79.183", false},
-+                           {"[ce8a:ee99:98cd:d8cd:218d:393e:d5a9:dc52]", false},
-+                           /* the following address is added twice to check if
-+                            * an address can be added more than once. */
-+                           {"37.230.88.162", false},
-+                           {"37.230.88.162", false},
-+                           {NULL, false} };
-+
-+    cbdata.list = &list;
-+
-+    kerr = krb5_init_context (&ctx);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_init(ctx, &priv);
-+    assert_int_equal(kerr, 0);
-+
-+    mkdir(TEST_PUBCONF_PATH, 0777);
-+    fd = open(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM, O_CREAT|O_RDWR, 0777);
-+    assert_int_not_equal(fd, -1);
-+    for (c = 0; test_data[c].ip != NULL; c++) {
-+        s = write(fd, test_data[c].ip, strlen(test_data[c].ip));
-+        assert_int_equal(s, strlen(test_data[c].ip));
-+        s = write(fd, "\n", 1);
-+        assert_int_equal(s, 1);
-+    }
-+    close(fd);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+
-+    assert_int_equal(list.nservers, 5);
-+    assert_non_null(list.servers);
-+    test_multi_check_results(test_data, &list, "88");
-+
-+    k5_free_serverlist(&list);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+
-+    assert_int_equal(list.nservers, 5);
-+    assert_non_null(list.servers);
-+    test_multi_check_results(test_data, &list, "88");
-+
-+
-+    k5_free_serverlist(&list);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_UNSPEC, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+
-+    assert_int_equal(list.nservers, 10);
-+    assert_non_null(list.servers);
-+    test_multi_check_results(test_data, &list, "88");
-+
-+    k5_free_serverlist(&list);
-+
-+    unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-+    rmdir(TEST_PUBCONF_PATH);
-+    sssd_krb5_locator_close(priv);
-+
-+    krb5_free_context(ctx);
-+}
-+
-+void test_service(void **state)
-+{
-+    krb5_context ctx;
-+    krb5_error_code kerr;
-+    void *priv;
-+    int fd;
-+    struct serverlist list = SERVERLIST_INIT;
-+    struct module_callback_data cbdata = { 0 };
-+    ssize_t s;
-+    int ret;
-+    char host[NI_MAXHOST];
-+    char service[NI_MAXSERV];
-+
-+    cbdata.list = &list;
-+
-+    kerr = krb5_init_context (&ctx);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_init(ctx, &priv);
-+    assert_int_equal(kerr, 0);
-+
-+    mkdir(TEST_PUBCONF_PATH, 0777);
-+    fd = open(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM, O_CREAT|O_RDWR, 0777);
-+    assert_int_not_equal(fd, -1);
-+    s = write(fd, TEST_IP_1_WITH_SERVICE, sizeof(TEST_IP_1_WITH_SERVICE));
-+    assert_int_equal(s, sizeof(TEST_IP_1_WITH_SERVICE));
-+    s = write(fd, "\n", 1);
-+    assert_int_equal(s, 1);
-+    s = write(fd, TEST_IPV6_1_WITH_SERVICE, sizeof(TEST_IPV6_1_WITH_SERVICE));
-+    assert_int_equal(s, sizeof(TEST_IPV6_1_WITH_SERVICE));
-+    close(fd);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IPV6_1_PURE, host);
-+    assert_string_equal(TEST_SERVICE_2, service);
-+
-+    k5_free_serverlist(&list);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kdc , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IP_1, host);
-+    assert_string_equal(TEST_SERVICE_1, service);
-+
-+    k5_free_serverlist(&list);
-+
-+
-+    unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-+    rmdir(TEST_PUBCONF_PATH);
-+    sssd_krb5_locator_close(priv);
-+
-+    krb5_free_context(ctx);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    poptContext pc;
-+    int opt;
-+    int ret;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const struct CMUnitTest tests[] = {
-+        cmocka_unit_test_setup_teardown(test_init,
-+                                        setup, teardown),
-+        cmocka_unit_test_setup_teardown(test_failed_lookup,
-+                                        setup, teardown),
-+        cmocka_unit_test_setup_teardown(test_empty,
-+                                        setup, teardown),
-+        cmocka_unit_test_setup_teardown(test_single,
-+                                        setup, teardown),
-+        cmocka_unit_test_setup_teardown(test_multi,
-+                                        setup, teardown),
-+        cmocka_unit_test_setup_teardown(test_service,
-+                                        setup, teardown),
-+    };
-+
-+    /* Set debug level to invalid value so we can decide 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_CLI_INIT(debug_level);
-+
-+    ret = cmocka_run_group_tests(tests, NULL, NULL);
-+
-+    return ret;
-+}
--- 
-2.17.1
-
diff --git a/SOURCES/0005-AD-IPA-Create-kdcinfo-file-for-sub-domains.patch b/SOURCES/0005-AD-IPA-Create-kdcinfo-file-for-sub-domains.patch
deleted file mode 100644
index f6d7cd8..0000000
--- a/SOURCES/0005-AD-IPA-Create-kdcinfo-file-for-sub-domains.patch
+++ /dev/null
@@ -1,148 +0,0 @@
-From 660ef95e36ad73b4715656a4207aeb499ac96d16 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 24 May 2018 17:15:38 +0200
-Subject: [PATCH] AD/IPA: Create kdcinfo file for sub-domains
-
-With this patch kdcinfo files are created for sub-domains by the AD
-provider and by the IPA provider on the IPA servers
-(ipa_server_mode=True).
-
-Related to https://pagure.io/SSSD/sssd/issue/3652
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-(cherry picked from commit cc7922755dac53c69558ba060b309ac48ae82783)
----
- src/providers/ad/ad_common.c              |  9 +++++++++
- src/providers/ad/ad_common.h              |  1 +
- src/providers/ad/ad_init.c                |  1 +
- src/providers/ad/ad_subdomains.c          | 17 ++++++++++++++---
- src/providers/ipa/ipa_subdomains_server.c | 16 ++++++++++++++--
- 5 files changed, 39 insertions(+), 5 deletions(-)
-
-diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
-index be7791e6cc2527d45d3e2ff50294f9b98106ffae..0aea985e00faa996643fd7e7630d4264fb6cf233 100644
---- a/src/providers/ad/ad_common.c
-+++ b/src/providers/ad/ad_common.c
-@@ -727,6 +727,7 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
-                  const char *ad_service,
-                  const char *ad_gc_service,
-                  const char *ad_domain,
-+                 bool use_kdcinfo,
-                  struct ad_service **_service)
- {
-     errno_t ret;
-@@ -762,6 +763,14 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
-         goto done;
-     }
- 
-+    /* Set flag that controls whether we want to write the
-+     * kdcinfo files at all
-+     */
-+    service->krb5_service->write_kdcinfo = use_kdcinfo;
-+    DEBUG(SSSDBG_CONF_SETTINGS, "write_kdcinfo for realm %s set to %s\n",
-+                       krb5_realm,
-+                       service->krb5_service->write_kdcinfo ? "true" : "false");
-+
-     ret = be_fo_add_service(bectx, ad_service, ad_user_data_cmp);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n");
-diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
-index 6eb2ba7e9a7350d1924c45d33d8c332073767a34..dd440da33d48a5820c665f43908d1e1fb18171a6 100644
---- a/src/providers/ad/ad_common.h
-+++ b/src/providers/ad/ad_common.h
-@@ -144,6 +144,7 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
-                  const char *ad_service,
-                  const char *ad_gc_service,
-                  const char *ad_domain,
-+                 bool use_kdcinfo,
-                  struct ad_service **_service);
- 
- errno_t
-diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
-index b19624782000c5c7c65e766e3e01ff6ac3ab7adb..637efb761c1cf87b0a2c2b1c19b00ea0bbbe161f 100644
---- a/src/providers/ad/ad_init.c
-+++ b/src/providers/ad/ad_init.c
-@@ -159,6 +159,7 @@ static errno_t ad_init_options(TALLOC_CTX *mem_ctx,
-     ret = ad_failover_init(ad_options, be_ctx, ad_servers, ad_backup_servers,
-                            ad_realm, AD_SERVICE_NAME, AD_GC_SERVICE_NAME,
-                            dp_opt_get_string(ad_options->basic, AD_DOMAIN),
-+                           false, /* will be set in ad_get_auth_options() */
-                            &ad_options->service);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init AD failover service: "
-diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
-index 74b9f075174b1eaa6c5b5dcbaf609600ef197b52..84886e920b37f8803d85ce0903b74e6c809a8904 100644
---- a/src/providers/ad/ad_subdomains.c
-+++ b/src/providers/ad/ad_subdomains.c
-@@ -249,6 +249,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
-     const char *hostname;
-     const char *keytab;
-     char *subdom_conf_path;
-+    bool use_kdcinfo = false;
- 
-     realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
-     hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
-@@ -296,9 +297,19 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
-     servers = dp_opt_get_string(ad_options->basic, AD_SERVER);
-     backup_servers = dp_opt_get_string(ad_options->basic, AD_BACKUP_SERVER);
- 
--    ret = ad_failover_init(ad_options, be_ctx, servers, backup_servers, realm,
--                           service_name, gc_service_name,
--                           subdom->name, &ad_options->service);
-+    if (id_ctx->ad_options->auth_ctx != NULL
-+            && id_ctx->ad_options->auth_ctx->opts != NULL) {
-+        use_kdcinfo = dp_opt_get_bool(id_ctx->ad_options->auth_ctx->opts,
-+                                      KRB5_USE_KDCINFO);
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_ALL,
-+          "Init failover for [%s][%s] with use_kdcinfo [%s].\n",
-+          subdom->name, subdom->realm, use_kdcinfo ? "true" : "false");
-+
-+    ret = ad_failover_init(ad_options, be_ctx, servers, backup_servers,
-+                           subdom->realm, service_name, gc_service_name,
-+                           subdom->name, use_kdcinfo, &ad_options->service);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
-         talloc_free(ad_options);
-diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
-index 1e53e7a951189120fcf3f438362e902a5a8f6d97..02577c92159d099a04cbd5cee80064309466db93 100644
---- a/src/providers/ipa/ipa_subdomains_server.c
-+++ b/src/providers/ipa/ipa_subdomains_server.c
-@@ -228,6 +228,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
-     struct sdap_domain *sdom;
-     errno_t ret;
-     const char *extra_attrs;
-+    bool use_kdcinfo = false;
- 
-     ad_domain = subdom->name;
-     DEBUG(SSSDBG_TRACE_LIBS, "Setting up AD subdomain %s\n", subdom->name);
-@@ -284,12 +285,23 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
-     ad_servers = dp_opt_get_string(ad_options->basic, AD_SERVER);
-     ad_backup_servers = dp_opt_get_string(ad_options->basic, AD_BACKUP_SERVER);
- 
-+    if (id_ctx->ipa_options != NULL && id_ctx->ipa_options->auth != NULL) {
-+        use_kdcinfo = dp_opt_get_bool(id_ctx->ipa_options->auth,
-+                                      KRB5_USE_KDCINFO);
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_ALL,
-+          "Init failover for [%s][%s] with use_kdcinfo [%s].\n",
-+          subdom->name, subdom->realm, use_kdcinfo ? "true" : "false");
-+
-     /* Set KRB5 realm to same as the one of IPA when IPA
-      * is able to attach PAC. For testing, use hardcoded. */
-+    /* Why? */
-     ret = ad_failover_init(ad_options, be_ctx, ad_servers, ad_backup_servers,
--                           id_ctx->server_mode->realm,
-+                           subdom->realm,
-                            service_name, gc_service_name,
--                           subdom->name, &ad_options->service);
-+                           subdom->name, use_kdcinfo,
-+                           &ad_options->service);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
-         talloc_free(ad_options);
--- 
-2.17.1
-
diff --git a/SOURCES/0005-ipa-store-sudo-runas-attribute-with-internal-fqname.patch b/SOURCES/0005-ipa-store-sudo-runas-attribute-with-internal-fqname.patch
new file mode 100644
index 0000000..cd5415f
--- /dev/null
+++ b/SOURCES/0005-ipa-store-sudo-runas-attribute-with-internal-fqname.patch
@@ -0,0 +1,62 @@
+From 5ad7f5e817b2bd8ca0f49b1001f4fb987de32c08 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 27 Feb 2019 14:04:54 +0100
+Subject: [PATCH 5/6] ipa: store sudo runas attribute with internal fqname
+
+We need to be able to differentiate between external users and IPA user.
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3957
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit d411febc98da36eb961b9251c1674af802151786)
+---
+ src/providers/ipa/ipa_sudo_conversion.c | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+diff --git a/src/providers/ipa/ipa_sudo_conversion.c b/src/providers/ipa/ipa_sudo_conversion.c
+index bfa66b2c6..9586e6a2a 100644
+--- a/src/providers/ipa/ipa_sudo_conversion.c
++++ b/src/providers/ipa/ipa_sudo_conversion.c
+@@ -908,6 +908,27 @@ convert_group(TALLOC_CTX *mem_ctx,
+     return rdn;
+ }
+ 
++static const char *
++convert_group_fqdn(TALLOC_CTX *mem_ctx,
++                   struct ipa_sudo_conv *conv,
++                   const char *value,
++                   bool *skip_entry)
++{
++    const char *shortname = NULL;
++    char *fqdn = NULL;
++
++    *skip_entry = false;
++
++    shortname = convert_group(mem_ctx, conv, value, skip_entry);
++    if (shortname == NULL) {
++        return NULL;
++    }
++
++    fqdn = sss_create_internal_fqname(mem_ctx, shortname, conv->dom->name);
++    talloc_free(discard_const(shortname));
++    return fqdn;
++}
++
+ static const char *
+ convert_runasextusergroup(TALLOC_CTX *mem_ctx,
+                           struct ipa_sudo_conv *conv,
+@@ -954,8 +975,8 @@ convert_attributes(struct ipa_sudo_conv *conv,
+     } table[] = {{SYSDB_NAME,                            SYSDB_SUDO_CACHE_AT_CN         , NULL},
+                  {SYSDB_IPA_SUDORULE_HOST,               SYSDB_SUDO_CACHE_AT_HOST       , convert_host},
+                  {SYSDB_IPA_SUDORULE_USER,               SYSDB_SUDO_CACHE_AT_USER       , convert_user_fqdn},
+-                 {SYSDB_IPA_SUDORULE_RUNASUSER,          SYSDB_SUDO_CACHE_AT_RUNASUSER  , convert_user},
+-                 {SYSDB_IPA_SUDORULE_RUNASGROUP,         SYSDB_SUDO_CACHE_AT_RUNASGROUP , convert_group},
++                 {SYSDB_IPA_SUDORULE_RUNASUSER,          SYSDB_SUDO_CACHE_AT_RUNASUSER  , convert_user_fqdn},
++                 {SYSDB_IPA_SUDORULE_RUNASGROUP,         SYSDB_SUDO_CACHE_AT_RUNASGROUP , convert_group_fqdn},
+                  {SYSDB_IPA_SUDORULE_OPTION,             SYSDB_SUDO_CACHE_AT_OPTION     , NULL},
+                  {SYSDB_IPA_SUDORULE_NOTAFTER,           SYSDB_SUDO_CACHE_AT_NOTAFTER   , NULL},
+                  {SYSDB_IPA_SUDORULE_NOTBEFORE,          SYSDB_SUDO_CACHE_AT_NOTBEFORE  , NULL},
+-- 
+2.19.1
+
diff --git a/SOURCES/0006-krb5-refactor-removal-of-krb5info-files.patch b/SOURCES/0006-krb5-refactor-removal-of-krb5info-files.patch
deleted file mode 100644
index 9787c85..0000000
--- a/SOURCES/0006-krb5-refactor-removal-of-krb5info-files.patch
+++ /dev/null
@@ -1,493 +0,0 @@
-From 713bc782502163251ef22eb81b09eed61a8407f7 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 5 Jun 2018 17:44:59 +0200
-Subject: [PATCH] krb5: refactor removal of krb5info files
-
-Currently a persistent offline callback removes the krb5info files for
-the configured main domain and those files were removed by a SIGTERM
-signal handlers as well.
-
-This does not scale if krb5info files are created for sub-domains as
-well. To remove the files automatically the removal is moved into a
-talloc destructor of an offline callback which is added if the file is
-created and frees itself when the system goes offline. Due to the
-talloc memory hierarchy we get removal on shutdown for free.
-
-Related to https://pagure.io/SSSD/sssd/issue/3652
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-(cherry picked from commit d91661e295c8e878f1bbf34e6f65f61e8301bf0e)
----
- src/providers/ad/ad_common.c          |   7 +-
- src/providers/ipa/ipa_common.c        |   5 +-
- src/providers/krb5/krb5_common.c      | 176 +++++++++++++-------------
- src/providers/krb5/krb5_common.h      |   7 +-
- src/providers/krb5/krb5_init_shared.c |   6 -
- src/providers/ldap/ldap_common.c      |  87 -------------
- 6 files changed, 102 insertions(+), 186 deletions(-)
-
-diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
-index 0aea985e00faa996643fd7e7630d4264fb6cf233..8caaba6c0d06cfe83d9741536192d662fc936273 100644
---- a/src/providers/ad/ad_common.c
-+++ b/src/providers/ad/ad_common.c
-@@ -804,6 +804,8 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
-         goto done;
-     }
- 
-+    service->krb5_service->be_ctx = bectx;
-+
-     if (!primary_servers) {
-         DEBUG(SSSDBG_CONF_SETTINGS,
-               "No primary servers defined, using service discovery\n");
-@@ -984,8 +986,9 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
-             goto done;
-         }
- 
--        ret = write_krb5info_file(service->krb5_service->realm, safe_address,
--                                SSS_KRB5KDC_FO_SRV);
-+        ret = write_krb5info_file(service->krb5_service,
-+                                  safe_address,
-+                                  SSS_KRB5KDC_FO_SRV);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_MINOR_FAILURE,
-                 "write_krb5info_file failed, authentication might fail.\n");
-diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
-index 87ed967673358bf833dae13c29b1f6a17b0fc19c..dcbb54a744358718e444972b9827ee64887e5e33 100644
---- a/src/providers/ipa/ipa_common.c
-+++ b/src/providers/ipa/ipa_common.c
-@@ -838,7 +838,8 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server)
-             return;
-         }
- 
--        ret = write_krb5info_file(service->krb5_service->realm, safe_address,
-+        ret = write_krb5info_file(service->krb5_service,
-+                                  safe_address,
-                                   SSS_KRB5KDC_FO_SRV);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE,
-@@ -1012,6 +1013,8 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-         goto done;
-     }
- 
-+    service->krb5_service->be_ctx = ctx;
-+
-     if (!primary_servers) {
-         DEBUG(SSSDBG_CONF_SETTINGS,
-               "No primary servers defined, using service discovery\n");
-diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
-index 520e7591ce1b37b4a8dea357b6dd0ec7afd76f58..c6896a6cd663da896075e72aa0a0602c198b45e8 100644
---- a/src/providers/krb5/krb5_common.c
-+++ b/src/providers/krb5/krb5_common.c
-@@ -389,7 +389,76 @@ done:
-     return ret;
- }
- 
--errno_t write_krb5info_file(const char *realm, const char *server,
-+static int remove_info_files_destructor(void *p)
-+{
-+    int ret;
-+    struct remove_info_files_ctx *ctx = talloc_get_type(p,
-+                                                  struct remove_info_files_ctx);
-+
-+    ret = remove_krb5_info_files(ctx, ctx->realm);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
-+    }
-+
-+    return 0;
-+}
-+
-+static errno_t
-+krb5_add_krb5info_offline_callback(struct krb5_service *krb5_service)
-+{
-+    int ret;
-+    struct remove_info_files_ctx *ctx;
-+
-+    if (krb5_service == NULL || krb5_service->name == NULL
-+                             || krb5_service->realm == NULL
-+                             || krb5_service->be_ctx == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Missing KDC service name or realm!\n");
-+        return EINVAL;
-+    }
-+
-+    ctx = talloc_zero(krb5_service->be_ctx, struct remove_info_files_ctx);
-+    if (ctx == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zfree failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    ctx->realm = talloc_strdup(ctx, krb5_service->realm);
-+    if (ctx->realm == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    ctx->be_ctx = krb5_service->be_ctx;
-+    ctx->kdc_service_name = talloc_strdup(ctx, krb5_service->name);
-+    if (ctx->kdc_service_name == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    ret = be_add_offline_cb(ctx, krb5_service->be_ctx,
-+                            remove_krb5_info_files_callback, ctx, NULL);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n");
-+        goto done;
-+    }
-+
-+    talloc_set_destructor((TALLOC_CTX *) ctx, remove_info_files_destructor);
-+
-+    ret = EOK;
-+
-+done:
-+    if (ret != EOK) {
-+        talloc_zfree(ctx);
-+    }
-+
-+    return ret;
-+}
-+
-+
-+errno_t write_krb5info_file(struct krb5_service *krb5_service,
-+                            const char *server,
-                             const char *service)
- {
-     int ret;
-@@ -401,17 +470,19 @@ errno_t write_krb5info_file(const char *realm, const char *server,
-     size_t server_len;
-     ssize_t written;
- 
--    if (realm == NULL || *realm == '\0' || server == NULL || *server == '\0' ||
--        service == NULL || *service == '\0') {
-+    if (krb5_service == NULL || krb5_service->realm == NULL
-+                             || *krb5_service->realm == '\0'
-+                             || server == NULL || *server == '\0'
-+                             || service == NULL || *service == '\0') {
-         DEBUG(SSSDBG_CRIT_FAILURE,
-               "Missing or empty realm, server or service.\n");
-         return EINVAL;
-     }
- 
--    if (sss_krb5_realm_has_proxy(realm)) {
-+    if (sss_krb5_realm_has_proxy(krb5_service->realm)) {
-         DEBUG(SSSDBG_CONF_SETTINGS,
-               "KDC Proxy available for realm [%s], no kdcinfo file created.\n",
--              realm);
-+              krb5_service->realm);
-         return EOK;
-     }
- 
-@@ -439,7 +510,7 @@ errno_t write_krb5info_file(const char *realm, const char *server,
-         goto done;
-     }
- 
--    krb5info_name = talloc_asprintf(tmp_ctx, name_tmpl, realm);
-+    krb5info_name = talloc_asprintf(tmp_ctx, name_tmpl, krb5_service->realm);
-     if (krb5info_name == NULL) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
-         ret = ENOMEM;
-@@ -495,6 +566,12 @@ errno_t write_krb5info_file(const char *realm, const char *server,
-         goto done;
-     }
- 
-+    ret = krb5_add_krb5info_offline_callback(krb5_service);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Failed to add offline callback, krb5info "
-+                                 "file might not be removed properly.\n");
-+    }
-+
-     ret = EOK;
- done:
-     if (fd != -1) {
-@@ -561,7 +638,8 @@ static void krb5_resolve_callback(void *private_data, struct fo_server *server)
-             return;
-         }
- 
--        ret = write_krb5info_file(krb5_service->realm, safe_address,
-+        ret = write_krb5info_file(krb5_service,
-+                                  safe_address,
-                                   krb5_service->name);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE,
-@@ -761,6 +839,7 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-     }
- 
-     service->write_kdcinfo = use_kdcinfo;
-+    service->be_ctx = ctx;
- 
-     if (!primary_servers) {
-         DEBUG(SSSDBG_CONF_SETTINGS,
-@@ -839,7 +918,6 @@ errno_t remove_krb5_info_files(TALLOC_CTX *mem_ctx, const char *realm)
- void remove_krb5_info_files_callback(void *pvt)
- {
-     int ret;
--    TALLOC_CTX *tmp_ctx = NULL;
-     struct remove_info_files_ctx *ctx = talloc_get_type(pvt,
-                                                   struct remove_info_files_ctx);
- 
-@@ -864,19 +942,10 @@ void remove_krb5_info_files_callback(void *pvt)
-         }
-     }
- 
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "talloc_new failed, cannot remove krb5 info files.\n");
--        return;
--    }
--
--    ret = remove_krb5_info_files(tmp_ctx, ctx->realm);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
--    }
--
--    talloc_zfree(tmp_ctx);
-+    /* Freeing the remove_info_files_ctx will remove the related krb5info
-+     * file. Additionally the callback from the list of callbacks is removed,
-+     * it will be added again when a new krb5info file is created. */
-+    talloc_free(ctx);
- }
- 
- void krb5_finalize(struct tevent_context *ev,
-@@ -886,74 +955,9 @@ void krb5_finalize(struct tevent_context *ev,
-                    void *siginfo,
-                    void *private_data)
- {
--    char *realm = (char *)private_data;
--    int ret;
--
--    ret = remove_krb5_info_files(se, realm);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
--    }
--
-     orderly_shutdown(0);
- }
- 
--errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
--                                      struct krb5_ctx *krb5_ctx)
--{
--    int ret;
--    struct remove_info_files_ctx *ctx;
--    const char *krb5_realm;
--
--    if (krb5_ctx->service == NULL || krb5_ctx->service->name == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Missing KDC service name!\n");
--        return EINVAL;
--    }
--
--    ctx = talloc_zero(krb5_ctx, struct remove_info_files_ctx);
--    if (ctx == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zfree failed.\n");
--        return ENOMEM;
--    }
--
--    krb5_realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM);
--    if (krb5_realm == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Missing krb5_realm option!\n");
--        ret = EINVAL;
--        goto done;
--    }
--
--    ctx->realm = talloc_strdup(ctx, krb5_realm);
--    if (ctx->realm == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
--        ret = ENOMEM;
--        goto done;
--    }
--
--    ctx->be_ctx = be_ctx;
--    ctx->kdc_service_name = krb5_ctx->service->name;
--    if (krb5_ctx->kpasswd_service == NULL) {
--        ctx->kpasswd_service_name =NULL;
--    } else {
--        ctx->kpasswd_service_name = krb5_ctx->kpasswd_service->name;
--    }
--
--    ret = be_add_offline_cb(ctx, be_ctx, remove_krb5_info_files_callback, ctx,
--                            NULL);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n");
--        goto done;
--    }
--
--    ret = EOK;
--
--done:
--    if (ret != EOK) {
--        talloc_zfree(ctx);
--    }
--
--    return ret;
--}
--
- errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
-                                      struct krb5_ctx *krb5_ctx)
- {
-diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
-index 48368a528e75947102c74cb75bf7a74ec0dd258f..a2e47b0605debdffa28305dab4f7674707f713ac 100644
---- a/src/providers/krb5/krb5_common.h
-+++ b/src/providers/krb5/krb5_common.h
-@@ -67,6 +67,7 @@ enum krb5_opts {
- typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
- 
- struct krb5_service {
-+    struct be_ctx *be_ctx;
-     char *name;
-     char *realm;
-     bool write_kdcinfo;
-@@ -157,7 +158,8 @@ errno_t krb5_try_kdcip(struct confdb_ctx *cdb, const char *conf_path,
- errno_t sss_krb5_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb,
-                              const char *conf_path, struct dp_option **_opts);
- 
--errno_t write_krb5info_file(const char *realm, const char *kdc,
-+errno_t write_krb5info_file(struct krb5_service *krb5_service,
-+                            const char *server,
-                             const char *service);
- 
- int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-@@ -177,9 +179,6 @@ void krb5_finalize(struct tevent_context *ev,
-                    void *siginfo,
-                    void *private_data);
- 
--errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
--                                      struct krb5_ctx *krb_ctx);
--
- errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
-                                      struct krb5_ctx *krb5_ctx);
- 
-diff --git a/src/providers/krb5/krb5_init_shared.c b/src/providers/krb5/krb5_init_shared.c
-index 3901b7272119c32930c2b6b47279a2c685bf3cfb..368d6f7b0f2bc038e4cc4aa8f0970cd0e81d7b6b 100644
---- a/src/providers/krb5/krb5_init_shared.c
-+++ b/src/providers/krb5/krb5_init_shared.c
-@@ -71,12 +71,6 @@ errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx,
-         goto done;
-     }
- 
--    ret = krb5_install_offline_callback(bectx, krb5_auth_ctx);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_install_offline_callback failed.\n");
--        goto done;
--    }
--
-     ret = krb5_install_sigterm_handler(bectx->ev, krb5_auth_ctx);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_install_sigterm_handler failed.\n");
-diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
-index 91e229243b9a1b43e7a57704824f5db0341f4ee9..15377ee1f062c0167aabee30ef0757ebe7271682 100644
---- a/src/providers/ldap/ldap_common.c
-+++ b/src/providers/ldap/ldap_common.c
-@@ -158,14 +158,6 @@ static void sdap_finalize(struct tevent_context *ev,
-                           void *siginfo,
-                           void *private_data)
- {
--    char *realm = (char *) private_data;
--    int ret;
--
--    ret = remove_krb5_info_files(se, realm);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
--    }
--
-     orderly_shutdown(0);
- }
- 
-@@ -196,78 +188,6 @@ errno_t sdap_install_sigterm_handler(TALLOC_CTX *mem_ctx,
-     return EOK;
- }
- 
--void sdap_remove_kdcinfo_files_callback(void *pvt)
--{
--    int ret;
--    TALLOC_CTX *tmp_ctx = NULL;
--    struct remove_info_files_ctx *ctx = talloc_get_type(pvt,
--                                                  struct remove_info_files_ctx);
--
--    ret = be_fo_run_callbacks_at_next_request(ctx->be_ctx,
--                                              ctx->kdc_service_name);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "be_fo_run_callbacks_at_next_request failed, "
--                  "krb5 info files will not be removed, because "
--                  "it is unclear if they will be recreated properly.\n");
--        return;
--    }
--
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "talloc_new failed, cannot remove krb5 info files.\n");
--        return;
--    }
--
--    ret = remove_krb5_info_files(tmp_ctx, ctx->realm);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
--    }
--
--    talloc_zfree(tmp_ctx);
--}
--
--
--errno_t sdap_install_offline_callback(TALLOC_CTX *mem_ctx,
--                                      struct be_ctx *be_ctx,
--                                      const char *realm,
--                                      const char *service_name)
--{
--    int ret;
--    struct remove_info_files_ctx *ctx;
--
--    ctx = talloc_zero(mem_ctx, struct remove_info_files_ctx);
--    if (ctx == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zfree failed.\n");
--        return ENOMEM;
--    }
--
--    ctx->be_ctx = be_ctx;
--    ctx->realm = talloc_strdup(ctx, realm);
--    ctx->kdc_service_name = talloc_strdup(ctx, service_name);
--    if (ctx->realm == NULL || ctx->kdc_service_name == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
--        ret = ENOMEM;
--        goto done;
--    }
--
--    ret = be_add_offline_cb(ctx, be_ctx,
--                            sdap_remove_kdcinfo_files_callback,
--                            ctx, NULL);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n");
--        goto done;
--    }
--
--    ret = EOK;
--done:
--    if (ret != EOK) {
--        talloc_zfree(ctx);
--    }
--    return ret;
--}
--
- errno_t
- sdap_set_sasl_options(struct sdap_options *id_opts,
-                       char *default_primary,
-@@ -458,13 +378,6 @@ int sdap_gssapi_init(TALLOC_CTX *mem_ctx,
-         goto done;
-     }
- 
--    ret = sdap_install_offline_callback(mem_ctx, bectx,
--                                        krb5_realm, SSS_KRB5KDC_FO_SRV);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to install sigterm handler\n");
--        goto done;
--    }
--
-     sdap_service->kinit_service_name = talloc_strdup(sdap_service,
-                                                      service->name);
-     if (sdap_service->kinit_service_name == NULL) {
--- 
-2.17.1
-
diff --git a/SOURCES/0006-sudo-format-runas-attributes-to-correct-output-name.patch b/SOURCES/0006-sudo-format-runas-attributes-to-correct-output-name.patch
new file mode 100644
index 0000000..237febc
--- /dev/null
+++ b/SOURCES/0006-sudo-format-runas-attributes-to-correct-output-name.patch
@@ -0,0 +1,176 @@
+From 3a18e33f983cd17860b6ff41f9d538ee8fcc6d98 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 27 Feb 2019 14:06:06 +0100
+Subject: [PATCH 6/6] sudo: format runas attributes to correct output name
+
+sudo internally calls getpwnam and getgrnam on user and groups
+that should be used for the invoked command. Output of these calls
+is compared to values in runAsUser/Group attributes.
+
+When different output format is used then what is present in LDAP,
+this comparison will fail, denying user to use sudo. Now, we convert
+these attributes into correct output name, respecting domain resolution
+order, fully qualified domains and fqname format.
+
+E.g. sudo call:
+sudo -u tuser@ipa.vm -g tgroup@ipa.vm id
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3957
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 0aa657165f189035c160beda4840e3271fc56c88)
+---
+ src/responder/sudo/sudosrv_get_sudorules.c | 101 ++++++++++++++++++++-
+ 1 file changed, 99 insertions(+), 2 deletions(-)
+
+diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
+index a420c76fb..d928a5ead 100644
+--- a/src/responder/sudo/sudosrv_get_sudorules.c
++++ b/src/responder/sudo/sudosrv_get_sudorules.c
+@@ -113,6 +113,95 @@ sort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool lower_wins)
+     return EOK;
+ }
+ 
++static errno_t sudosrv_format_runas(struct resp_ctx *rctx,
++                                    struct sysdb_attrs *rule,
++                                    const char *attr)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct ldb_message_element *el;
++    struct sss_domain_info *dom;
++    const char *value;
++    char *fqname;
++    unsigned int i;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n");
++        return ENOMEM;
++    }
++
++    ret = sysdb_attrs_get_el_ext(rule, attr, false, &el);
++    if (ret == ENOENT) {
++        ret = EOK;
++        goto done;
++    } else if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get %s attribute "
++              "[%d]: %s\n", attr, ret, sss_strerror(ret));
++        goto done;
++    }
++
++    for (i = 0; i < el->num_values; i++) {
++        value = (const char *)el->values[i].data;
++        if (value == NULL) {
++            continue;
++        }
++
++        dom = find_domain_by_object_name_ex(rctx->domains, value, true);
++        if (dom == NULL) {
++            continue;
++        }
++
++        ret = sss_output_fqname(tmp_ctx, dom, value,
++                                rctx->override_space, &fqname);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to convert %s to output fqname "
++                  "[%d]: %s\n", value, ret, sss_strerror(ret));
++            goto done;
++        }
++
++        talloc_free(el->values[i].data);
++        el->values[i].data = (uint8_t*)talloc_steal(el->values, fqname);
++        el->values[i].length = strlen(fqname);
++    }
++
++done:
++    talloc_free(tmp_ctx);
++
++    return ret;
++}
++
++static errno_t sudosrv_format_rules(struct resp_ctx *rctx,
++                                    struct sysdb_attrs **rules,
++                                    uint32_t num_rules)
++{
++    uint32_t i;
++    errno_t ret;
++
++
++    for (i = 0; i < num_rules; i++) {
++        ret = sudosrv_format_runas(rctx, rules[i],
++                                   SYSDB_SUDO_CACHE_AT_RUNAS);
++        if (ret != EOK) {
++            return ret;
++        }
++
++        ret = sudosrv_format_runas(rctx, rules[i],
++                                   SYSDB_SUDO_CACHE_AT_RUNASUSER);
++        if (ret != EOK) {
++            return ret;
++        }
++
++        ret = sudosrv_format_runas(rctx, rules[i],
++                                   SYSDB_SUDO_CACHE_AT_RUNASGROUP);
++        if (ret != EOK) {
++            return ret;
++        }
++    }
++
++    return ret;
++}
++
+ static errno_t sudosrv_query_cache(TALLOC_CTX *mem_ctx,
+                                    struct sss_domain_info *domain,
+                                    const char **attrs,
+@@ -301,6 +390,7 @@ static errno_t sudosrv_cached_rules_by_ng(TALLOC_CTX *mem_ctx,
+ }
+ 
+ static errno_t sudosrv_cached_rules(TALLOC_CTX *mem_ctx,
++                                    struct resp_ctx *rctx,
+                                     struct sss_domain_info *domain,
+                                     uid_t cli_uid,
+                                     uid_t orig_uid,
+@@ -368,6 +458,12 @@ static errno_t sudosrv_cached_rules(TALLOC_CTX *mem_ctx,
+         goto done;
+     }
+ 
++    ret = sudosrv_format_rules(rctx, rules, num_rules);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "Could not format sudo rules\n");
++        goto done;
++    }
++
+     *_rules = talloc_steal(mem_ctx, rules);
+     *_num_rules = num_rules;
+ 
+@@ -412,6 +508,7 @@ static errno_t sudosrv_cached_defaults(TALLOC_CTX *mem_ctx,
+ }
+ 
+ static errno_t sudosrv_fetch_rules(TALLOC_CTX *mem_ctx,
++                                   struct resp_ctx *rctx,
+                                    enum sss_sudo_type type,
+                                    struct sss_domain_info *domain,
+                                    uid_t cli_uid,
+@@ -433,7 +530,7 @@ static errno_t sudosrv_fetch_rules(TALLOC_CTX *mem_ctx,
+               username, domain->name);
+         debug_name = "rules";
+ 
+-        ret = sudosrv_cached_rules(mem_ctx, domain,
++        ret = sudosrv_cached_rules(mem_ctx, rctx, domain,
+                                    cli_uid, orig_uid, username, groups,
+                                    inverse_order, &rules, &num_rules);
+ 
+@@ -760,7 +857,7 @@ static void sudosrv_get_rules_done(struct tevent_req *subreq)
+               "in cache.\n");
+     }
+ 
+-    ret = sudosrv_fetch_rules(state, state->type, state->domain,
++    ret = sudosrv_fetch_rules(state, state->rctx, state->type, state->domain,
+                               state->cli_uid,
+                               state->orig_uid,
+                               state->orig_username,
+-- 
+2.19.1
+
diff --git a/SOURCES/0007-SYSDB-Inherit-cached_auth_timeout-from-the-main-doma.patch b/SOURCES/0007-SYSDB-Inherit-cached_auth_timeout-from-the-main-doma.patch
new file mode 100644
index 0000000..b6b74bb
--- /dev/null
+++ b/SOURCES/0007-SYSDB-Inherit-cached_auth_timeout-from-the-main-doma.patch
@@ -0,0 +1,59 @@
+From fedfc4fa5978dc0ef2c3b6efcd1e9462a8575b3a Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 7 Mar 2019 22:13:32 +0100
+Subject: [PATCH] SYSDB: Inherit cached_auth_timeout from the main domain
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+cached_auth_timeout is a domain option used by the responder. And
+because at the moment the options read from a subdomain section (e.g.
+[domain/main/trusted] are only those represented by the back end specific
+dp_option structure instance, the option cached_auth_timeout, which
+is directly read from the confdb was not set for the main domain.
+
+This is a minimal patch that just inherits the option from the main
+domain until SSSD has a more systematic way of inheriting config
+attributes regardless of how they are read and set.
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3960
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 4dd268333ca9ca13555f5dfbd2928154b885a3e7)
+---
+ src/db/sysdb_subdomains.c | 1 +
+ src/man/sssd.conf.5.xml   | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
+index e380e6c8b..34d052fdd 100644
+--- a/src/db/sysdb_subdomains.c
++++ b/src/db/sysdb_subdomains.c
+@@ -154,6 +154,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
+     dom->cache_credentials = parent->cache_credentials;
+     dom->cache_credentials_min_ff_length =
+                                         parent->cache_credentials_min_ff_length;
++    dom->cached_auth_timeout = parent->cached_auth_timeout;
+     dom->case_sensitive = false;
+     dom->user_timeout = parent->user_timeout;
+     dom->group_timeout = parent->group_timeout;
+diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
+index ef5a4b952..41ba7b924 100644
+--- a/src/man/sssd.conf.5.xml
++++ b/src/man/sssd.conf.5.xml
+@@ -2962,6 +2962,11 @@ subdomain_inherit = ldap_purge_cache_timeout
+                             authenticated using cached credentials while
+                             SSSD is in the online mode.
+                         </para>
++                        <para>
++                            This option's value is inherited by all trusted
++                            domains. At the moment it is not possible to set
++                            a different value per trusted domain.
++                        </para>
+                         <para>
+                             Special value 0 implies that this feature is
+                             disabled.
+-- 
+2.19.1
+
diff --git a/SOURCES/0007-krb5_common-add-callback-only-once.patch b/SOURCES/0007-krb5_common-add-callback-only-once.patch
deleted file mode 100644
index 2b36703..0000000
--- a/SOURCES/0007-krb5_common-add-callback-only-once.patch
+++ /dev/null
@@ -1,86 +0,0 @@
-From 54ea4576ba8cb8dfbefdd3ced29fc35f836afc61 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 8 Jun 2018 08:29:04 +0200
-Subject: [PATCH] krb5_common: add callback only once
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 4759a482781bcecdb0ad1119e74dcefa1fe94337)
----
- src/providers/krb5/krb5_common.c | 12 +++++++++++-
- src/providers/krb5/krb5_common.h |  2 ++
- 2 files changed, 13 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
-index c6896a6cd663da896075e72aa0a0602c198b45e8..d064a09ac3726c4185c2fa1eeac76ef6c261d33b 100644
---- a/src/providers/krb5/krb5_common.c
-+++ b/src/providers/krb5/krb5_common.c
-@@ -399,6 +399,7 @@ static int remove_info_files_destructor(void *p)
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "remove_krb5_info_files failed.\n");
-     }
-+    ctx->krb5_service->removal_callback_available = false;
- 
-     return 0;
- }
-@@ -407,7 +408,7 @@ static errno_t
- krb5_add_krb5info_offline_callback(struct krb5_service *krb5_service)
- {
-     int ret;
--    struct remove_info_files_ctx *ctx;
-+    struct remove_info_files_ctx *ctx = NULL;
- 
-     if (krb5_service == NULL || krb5_service->name == NULL
-                              || krb5_service->realm == NULL
-@@ -416,6 +417,13 @@ krb5_add_krb5info_offline_callback(struct krb5_service *krb5_service)
-         return EINVAL;
-     }
- 
-+    if (krb5_service->removal_callback_available) {
-+        DEBUG(SSSDBG_TRACE_ALL,
-+              "Removal callback already available for service [%s].\n",
-+              krb5_service->name);
-+        return EOK;
-+    }
-+
-     ctx = talloc_zero(krb5_service->be_ctx, struct remove_info_files_ctx);
-     if (ctx == NULL) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zfree failed.\n");
-@@ -430,6 +438,7 @@ krb5_add_krb5info_offline_callback(struct krb5_service *krb5_service)
-     }
- 
-     ctx->be_ctx = krb5_service->be_ctx;
-+    ctx->krb5_service = krb5_service;
-     ctx->kdc_service_name = talloc_strdup(ctx, krb5_service->name);
-     if (ctx->kdc_service_name == NULL) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed!\n");
-@@ -445,6 +454,7 @@ krb5_add_krb5info_offline_callback(struct krb5_service *krb5_service)
-     }
- 
-     talloc_set_destructor((TALLOC_CTX *) ctx, remove_info_files_destructor);
-+    krb5_service->removal_callback_available = true;
- 
-     ret = EOK;
- 
-diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
-index a2e47b0605debdffa28305dab4f7674707f713ac..3529d740b89fee91281f936fdafd1bdb99e95bd7 100644
---- a/src/providers/krb5/krb5_common.h
-+++ b/src/providers/krb5/krb5_common.h
-@@ -71,6 +71,7 @@ struct krb5_service {
-     char *name;
-     char *realm;
-     bool write_kdcinfo;
-+    bool removal_callback_available;
- };
- 
- struct fo_service;
-@@ -146,6 +147,7 @@ struct remove_info_files_ctx {
-     struct be_ctx *be_ctx;
-     const char *kdc_service_name;
-     const char *kpasswd_service_name;
-+    struct krb5_service *krb5_service;
- };
- 
- errno_t sss_krb5_check_options(struct dp_option *opts,
--- 
-2.17.1
-
diff --git a/SOURCES/0008-data-provider-run-offline-callbacks-only-once.patch b/SOURCES/0008-data-provider-run-offline-callbacks-only-once.patch
deleted file mode 100644
index fd7a973..0000000
--- a/SOURCES/0008-data-provider-run-offline-callbacks-only-once.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 2d350235bc960a91233d29b97c3a205bd2e04c08 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 8 Jun 2018 18:42:28 +0200
-Subject: [PATCH] data provider: run offline callbacks only once
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit f28d995719db632130e9e063cb1ab7cb4e0fc8d8)
----
- src/providers/backend.h                 |  1 +
- src/providers/data_provider_be.c        |  1 +
- src/providers/data_provider_callbacks.c | 36 +++++++++++++++++++------
- 3 files changed, 30 insertions(+), 8 deletions(-)
-
-diff --git a/src/providers/backend.h b/src/providers/backend.h
-index 1914274037ce7f7ff4b6d8486b041789a865fd59..6a34b91a911fc12163fa9448ea82ff93f5bf3849 100644
---- a/src/providers/backend.h
-+++ b/src/providers/backend.h
-@@ -95,6 +95,7 @@ struct be_ctx {
-     struct be_cb *online_cb_list;
-     bool run_online_cb;
-     struct be_cb *offline_cb_list;
-+    bool run_offline_cb;
-     struct be_cb *reconnect_cb_list;
-     /* In contrast to online_cb_list which are only run if the backend is
-      * offline the unconditional_online_cb_list should be run whenever the
-diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
-index e8cddd976bb164dc6d4655bf2ebe9a03c3d9d26a..fad6f280195b615d1de45afaf0c459bdf78c8c0a 100644
---- a/src/providers/data_provider_be.c
-+++ b/src/providers/data_provider_be.c
-@@ -219,6 +219,7 @@ static void be_reset_offline(struct be_ctx *ctx)
- {
-     ctx->offstat.went_offline = 0;
-     ctx->offstat.offline = false;
-+    ctx->run_offline_cb = true;
- 
-     reactivate_subdoms(ctx->domain);
- 
-diff --git a/src/providers/data_provider_callbacks.c b/src/providers/data_provider_callbacks.c
-index 436357e228c0e1a689aa18b8ef41a82f63774d3a..24e125ea5be70208d7cf2cb06a80c39207e29db4 100644
---- a/src/providers/data_provider_callbacks.c
-+++ b/src/providers/data_provider_callbacks.c
-@@ -265,22 +265,42 @@ void be_run_unconditional_online_cb(struct be_ctx *be)
- int be_add_offline_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
-                       void *pvt, struct be_cb **offline_cb)
- {
--    return be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->offline_cb_list, offline_cb);
-+    int ret;
-+
-+    ret = be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->offline_cb_list, offline_cb);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "be_add_cb failed.\n");
-+        return ret;
-+    }
-+
-+    /* Make sure we run the callback when SSSD goes offline */
-+    ctx->run_offline_cb = true;
-+
-+    return EOK;
- }
- 
- void be_run_offline_cb(struct be_ctx *be) {
-     int ret;
- 
--    if (be->offline_cb_list) {
--        DEBUG(SSSDBG_MINOR_FAILURE, "Going offline. Running callbacks.\n");
-+    if (be->run_offline_cb) {
-+        /* Reset the flag, we only want to run these callbacks once when going
-+         * offline */
-+        be->run_offline_cb = false;
- 
--        ret = be_run_cb(be, be->offline_cb_list);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "be_run_cb failed.\n");
-+        if (be->offline_cb_list) {
-+            DEBUG(SSSDBG_MINOR_FAILURE, "Going offline. Running callbacks.\n");
-+
-+            ret = be_run_cb(be, be->offline_cb_list);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_CRIT_FAILURE, "be_run_cb failed.\n");
-+            }
-+
-+        } else {
-+            DEBUG(SSSDBG_TRACE_ALL,
-+                  "Offline call back list is empty, nothing to do.\n");
-         }
--
-     } else {
-         DEBUG(SSSDBG_TRACE_ALL,
--              "Offline call back list is empty, nothing to do.\n");
-+              "Flag indicates that offline callback were already called.\n");
-     }
- }
--- 
-2.17.1
-
diff --git a/SOURCES/0008-krb5-Do-not-use-unindexed-objectCategory-in-a-search.patch b/SOURCES/0008-krb5-Do-not-use-unindexed-objectCategory-in-a-search.patch
new file mode 100644
index 0000000..d5cdf41
--- /dev/null
+++ b/SOURCES/0008-krb5-Do-not-use-unindexed-objectCategory-in-a-search.patch
@@ -0,0 +1,48 @@
+From e4dd2843a4a302ababd3ccedfbf23832244a1655 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Sat, 23 Mar 2019 21:53:05 +0100
+Subject: [PATCH] krb5: Do not use unindexed objectCategory in a search filter
+
+Related:
+https://pagure.io/SSSD/sssd/issue/3968
+
+Since we switched to using objectcategory instead of objectclass for
+users and groups, the objectCategory attribute is also not indexed. This
+means that searches using this attribute must traverse the whole
+database which can be very slow.
+
+This patch uses the cn=users container instead of the full sysdb
+container as the search base which is more or less equivalent to using
+objectCategory=user anyway.
+
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+(cherry picked from commit e474c2dd305db654b42f2a123a6f60d12d7978c5)
+---
+ src/providers/krb5/krb5_renew_tgt.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c
+index 549c08c6f..c7e2bd91f 100644
+--- a/src/providers/krb5/krb5_renew_tgt.c
++++ b/src/providers/krb5/krb5_renew_tgt.c
+@@ -385,7 +385,7 @@ static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx)
+ {
+     TALLOC_CTX *tmp_ctx;
+     int ret;
+-    const char *ccache_filter = "(&("SYSDB_CCACHE_FILE"=*)("SYSDB_UC"))";
++    const char *ccache_filter = SYSDB_CCACHE_FILE"=*";
+     const char *ccache_attrs[] = { SYSDB_CCACHE_FILE, SYSDB_UPN, SYSDB_NAME,
+                                    SYSDB_CANONICAL_UPN, NULL };
+     size_t msgs_count = 0;
+@@ -403,7 +403,7 @@ static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx)
+         return ENOMEM;
+     }
+ 
+-    base_dn = sysdb_base_dn(renew_tgt_ctx->be_ctx->domain->sysdb, tmp_ctx);
++    base_dn = sysdb_user_base_dn(tmp_ctx, renew_tgt_ctx->be_ctx->domain);
+     if (base_dn == NULL) {
+         DEBUG(SSSDBG_OP_FAILURE, "sysdb_base_dn failed.\n");
+         ret = ENOMEM;
+-- 
+2.19.1
+
diff --git a/SOURCES/0009-SYSDB-Index-the-ccacheFile-attribute.patch b/SOURCES/0009-SYSDB-Index-the-ccacheFile-attribute.patch
new file mode 100644
index 0000000..1117004
--- /dev/null
+++ b/SOURCES/0009-SYSDB-Index-the-ccacheFile-attribute.patch
@@ -0,0 +1,141 @@
+From 7d8b28ad691335ebb679c6230b5e4818a7434bc5 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Sat, 23 Mar 2019 22:18:18 +0100
+Subject: [PATCH] SYSDB: Index the ccacheFile attribute
+
+Related:
+https://pagure.io/SSSD/sssd/issue/3968
+
+The Kerberos ticket renewal code searches for user entries which have
+the ccacheFile attribute set. Since the search can potentially traverse
+all the users, it might be a good idea to index the attribute.
+
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+(cherry picked from commit 96013bbb7d937d1a9e4e5c678df3034520d98f32)
+---
+ src/db/sysdb_init.c    |  7 ++++++
+ src/db/sysdb_private.h |  5 +++-
+ src/db/sysdb_upgrade.c | 52 ++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 63 insertions(+), 1 deletion(-)
+
+diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c
+index 89f8c6a5b..48e21baab 100644
+--- a/src/db/sysdb_init.c
++++ b/src/db/sysdb_init.c
+@@ -558,6 +558,13 @@ static errno_t sysdb_domain_cache_upgrade(TALLOC_CTX *mem_ctx,
+         }
+     }
+ 
++    if (strcmp(version, SYSDB_VERSION_0_20) == 0) {
++        ret = sysdb_upgrade_20(sysdb, &version);
++        if (ret != EOK) {
++            goto done;
++        }
++    }
++
+ 
+     ret = EOK;
+ done:
+diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
+index c297715cd..58544d826 100644
+--- a/src/db/sysdb_private.h
++++ b/src/db/sysdb_private.h
+@@ -23,6 +23,7 @@
+ #ifndef __INT_SYS_DB_H__
+ #define __INT_SYS_DB_H__
+ 
++#define SYSDB_VERSION_0_21 "0.21"
+ #define SYSDB_VERSION_0_20 "0.20"
+ #define SYSDB_VERSION_0_19 "0.19"
+ #define SYSDB_VERSION_0_18 "0.18"
+@@ -44,7 +45,7 @@
+ #define SYSDB_VERSION_0_2 "0.2"
+ #define SYSDB_VERSION_0_1 "0.1"
+ 
+-#define SYSDB_VERSION SYSDB_VERSION_0_20
++#define SYSDB_VERSION SYSDB_VERSION_0_21
+ 
+ #define SYSDB_BASE_LDIF \
+      "dn: @ATTRIBUTES\n" \
+@@ -79,6 +80,7 @@
+      "@IDXATTR: uniqueID\n" \
+      "@IDXATTR: mail\n" \
+      "@IDXATTR: userMappedCertificate\n" \
++     "@IDXATTR: ccacheFile\n" \
+      "\n" \
+      "dn: @MODULES\n" \
+      "@LIST: asq,memberof\n" \
+@@ -171,6 +173,7 @@ int sysdb_upgrade_17(struct sysdb_ctx *sysdb,
+                      const char **ver);
+ int sysdb_upgrade_18(struct sysdb_ctx *sysdb, const char **ver);
+ int sysdb_upgrade_19(struct sysdb_ctx *sysdb, const char **ver);
++int sysdb_upgrade_20(struct sysdb_ctx *sysdb, const char **ver);
+ 
+ int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver);
+ 
+diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
+index 46df971e9..f6a481147 100644
+--- a/src/db/sysdb_upgrade.c
++++ b/src/db/sysdb_upgrade.c
+@@ -2501,6 +2501,58 @@ done:
+     return ret;
+ }
+ 
++int sysdb_upgrade_20(struct sysdb_ctx *sysdb, const char **ver)
++{
++    struct upgrade_ctx *ctx;
++    errno_t ret;
++    struct ldb_message *msg = NULL;
++
++    ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_21, &ctx);
++    if (ret) {
++        return ret;
++    }
++
++    /* Add missing indices */
++    msg = ldb_msg_new(ctx);
++    if (msg == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST");
++    if (msg->dn == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL);
++    if (ret != LDB_SUCCESS) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = ldb_msg_add_string(msg, "@IDXATTR", SYSDB_CCACHE_FILE);
++    if (ret != LDB_SUCCESS) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = ldb_modify(sysdb->ldb, msg);
++    if (ret != LDB_SUCCESS) {
++        ret = sysdb_error_to_errno(ret);
++        goto done;
++    }
++
++    talloc_free(msg);
++
++    /* conversion done, update version number */
++    ret = update_version(ctx);
++
++done:
++    ret = finish_upgrade(ret, &ctx, ver);
++    return ret;
++}
++
+ int sysdb_ts_upgrade_01(struct sysdb_ctx *sysdb, const char **ver)
+ {
+     struct upgrade_ctx *ctx;
+-- 
+2.19.1
+
diff --git a/SOURCES/0009-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch b/SOURCES/0009-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch
deleted file mode 100644
index 3cb7eda..0000000
--- a/SOURCES/0009-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 2b210b10ce54f6f2595f6ab181a51bce367d43a9 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 17 Jun 2018 21:48:36 +0200
-Subject: [PATCH] TESTS: Extend the schema with sshPublicKey attribute
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This will allow to store the users with a sshPublicKey attribute
-provided that they have the right objectclass as well.
-
-Related to:
-https://pagure.io/SSSD/sssd/issue/3747
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 1575ec97e080656f69b3f93e641c76e74ffb8182)
-
-DOWNSTREAM:
-Resolves: rhbz#1583343 - Login with sshkeys stored in ipa not working after update to RHEL-7.5
----
- src/tests/intg/data/ssh_schema.ldif | 11 +++++++++++
- src/tests/intg/ds_openldap.py       |  6 ++++++
- 2 files changed, 17 insertions(+)
- create mode 100644 src/tests/intg/data/ssh_schema.ldif
-
-diff --git a/src/tests/intg/data/ssh_schema.ldif b/src/tests/intg/data/ssh_schema.ldif
-new file mode 100644
-index 0000000000000000000000000000000000000000..efe05706b9ded5614a7f3f5e0bab28a7eb869daa
---- /dev/null
-+++ b/src/tests/intg/data/ssh_schema.ldif
-@@ -0,0 +1,11 @@
-+dn: cn=openssh-lpk,cn=schema,cn=config
-+objectClass: olcSchemaConfig
-+cn: openssh-lpk
-+olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
-+  DESC 'MANDATORY: OpenSSH Public key'
-+  EQUALITY octetStringMatch
-+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
-+olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
-+  DESC 'MANDATORY: OpenSSH LPK objectclass'
-+  MAY ( sshPublicKey $ uid )
-+  )
-diff --git a/src/tests/intg/ds_openldap.py b/src/tests/intg/ds_openldap.py
-index 842ff910803658834841c8f9181f3c4af29b955a..c9a4b6de8c53c6644b3de9047d657ee35ce06512 100644
---- a/src/tests/intg/ds_openldap.py
-+++ b/src/tests/intg/ds_openldap.py
-@@ -186,6 +186,12 @@ class DSOpenLDAP(DS):
-         db_config_file.write(db_config)
-         db_config_file.close()
- 
-+        # Import ad schema
-+        subprocess.check_call(
-+            ["slapadd", "-F", self.conf_slapd_d_dir, "-b", "cn=config",
-+             "-l", "data/ssh_schema.ldif"],
-+        )
-+
-     def _start_daemon(self):
-         """Start the instance."""
-         if subprocess.call(["slapd", "-F", self.conf_slapd_d_dir,
--- 
-2.17.1
-
diff --git a/SOURCES/0010-TESTS-Allow-adding-sshPublicKey-for-users.patch b/SOURCES/0010-TESTS-Allow-adding-sshPublicKey-for-users.patch
deleted file mode 100644
index ed461cd..0000000
--- a/SOURCES/0010-TESTS-Allow-adding-sshPublicKey-for-users.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From 4bff9d92a51bff2fabb6168f8ae69c8a8d17ba2a Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 17 Jun 2018 22:06:22 +0200
-Subject: [PATCH] TESTS: Allow adding sshPublicKey for users
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Adds the objectclass and allows storing a list of sshPublicKey
-attributes for users. Since there is no harm in adding the extra
-objectclass, we can do it unconditionally.
-
-Related to:
-https://pagure.io/SSSD/sssd/issue/3747
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 56cda832e9f61c52e9cfde1f0864507de718ffbb)
----
- src/tests/intg/ldap_ent.py | 15 +++++++++++----
- 1 file changed, 11 insertions(+), 4 deletions(-)
-
-diff --git a/src/tests/intg/ldap_ent.py b/src/tests/intg/ldap_ent.py
-index 6b6d8f903cbcc277d892c3212ca382f4aaadc671..a4c987969d3dcefba2af69e095b220180e0fa54c 100644
---- a/src/tests/intg/ldap_ent.py
-+++ b/src/tests/intg/ldap_ent.py
-@@ -24,7 +24,8 @@ def user(base_dn, uid, uidNumber, gidNumber,
-          homeDirectory=None,
-          loginShell=None,
-          cn=None,
--         sn=None):
-+         sn=None,
-+         sshPubKey=()):
-     """
-     Generate an RFC2307(bis) user add-modlist for passing to ldap.add*
-     """
-@@ -33,7 +34,8 @@ def user(base_dn, uid, uidNumber, gidNumber,
-     user = (
-         "uid=" + uid + ",ou=Users," + base_dn,
-         [
--            ('objectClass', [b'top', b'inetOrgPerson', b'posixAccount']),
-+            ('objectClass', [b'top', b'inetOrgPerson',
-+                             b'posixAccount', b'ldapPublicKey']),
-             ('cn', [uidNumber if cn is None else cn.encode('utf-8')]),
-             ('sn', [b'User' if sn is None else sn.encode('utf-8')]),
-             ('uidNumber', [uidNumber]),
-@@ -51,6 +53,9 @@ def user(base_dn, uid, uidNumber, gidNumber,
-     )
-     if gecos is not None:
-         user[1].append(('gecos', [gecos.encode('utf-8')]))
-+    if len(sshPubKey) > 0:
-+        pubkeys = [key.encode('utf-8') for key in sshPubKey]
-+        user[1].append(('sshPublicKey', pubkeys))
-     return user
- 
- 
-@@ -118,7 +123,8 @@ class List(list):
-                  homeDirectory=None,
-                  loginShell=None,
-                  cn=None,
--                 sn=None):
-+                 sn=None,
-+                 sshPubKey=()):
-         """Add an RFC2307(bis) user add-modlist."""
-         self.append(user(base_dn or self.base_dn,
-                          uid, uidNumber, gidNumber,
-@@ -127,7 +133,8 @@ class List(list):
-                          homeDirectory=homeDirectory,
-                          loginShell=loginShell,
-                          cn=cn,
--                         sn=sn))
-+                         sn=sn,
-+                         sshPubKey=sshPubKey))
- 
-     def add_group(self, cn, gidNumber, member_uids=[],
-                   base_dn=None):
--- 
-2.17.1
-
diff --git a/SOURCES/0010-krb5-Silence-an-error-message-if-no-cache-entries-ha.patch b/SOURCES/0010-krb5-Silence-an-error-message-if-no-cache-entries-ha.patch
new file mode 100644
index 0000000..99a2c27
--- /dev/null
+++ b/SOURCES/0010-krb5-Silence-an-error-message-if-no-cache-entries-ha.patch
@@ -0,0 +1,33 @@
+From 23fb7ea2f98c08a7df21b68bf96ddfe982fa284e Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 25 Mar 2019 10:17:39 +0100
+Subject: [PATCH] krb5: Silence an error message if no cache entries have
+ ccache stored but renewal is enabled
+
+If no user entries had the ccacheFile attribute, the code would treat
+ENOENT as an error and print a CRIT-level debug message.
+
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+(cherry picked from commit 22fc051df8bd1a9ec9e22aac85659d1da3bdbaec)
+---
+ src/providers/krb5/krb5_renew_tgt.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c
+index c7e2bd91f..8b2159e92 100644
+--- a/src/providers/krb5/krb5_renew_tgt.c
++++ b/src/providers/krb5/krb5_renew_tgt.c
+@@ -413,7 +413,9 @@ static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx)
+     ret = sysdb_search_entry(tmp_ctx, renew_tgt_ctx->be_ctx->domain->sysdb, base_dn,
+                              LDB_SCOPE_SUBTREE, ccache_filter, ccache_attrs,
+                              &msgs_count, &msgs);
+-    if (ret != EOK) {
++    if (ret == ENOENT) {
++        msgs_count = 0; /* Fall through */
++    } else if (ret != EOK) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry failed.\n");
+         goto done;
+     }
+-- 
+2.19.1
+
diff --git a/SOURCES/0011-TESTS-Add-a-basic-SSH-responder-test.patch b/SOURCES/0011-TESTS-Add-a-basic-SSH-responder-test.patch
deleted file mode 100644
index 0760c43..0000000
--- a/SOURCES/0011-TESTS-Add-a-basic-SSH-responder-test.patch
+++ /dev/null
@@ -1,276 +0,0 @@
-From 079464a0fd417f09cfafa2bda9ff1a4e1afdbe8a Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 18 Jun 2018 09:12:13 +0200
-Subject: [PATCH] TESTS: Add a basic SSH responder test
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Adds a basic test that makes sure that a list of SSH public keys can be
-retrieved. This is to make sure we don't break the SSH integration later
-on.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3747
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 804c5b538ad89a1a3897b93f39d716fa50530842)
----
- src/tests/intg/Makefile.am        |   1 +
- src/tests/intg/test_ssh_pubkey.py | 232 ++++++++++++++++++++++++++++++
- 2 files changed, 233 insertions(+)
- create mode 100644 src/tests/intg/test_ssh_pubkey.py
-
-diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am
-index 9c5338261353f473d9051c0512c15a54ec38e1ec..a15022eb578394313155538898fe7cd7407eb9c0 100644
---- a/src/tests/intg/Makefile.am
-+++ b/src/tests/intg/Makefile.am
-@@ -36,6 +36,7 @@ dist_noinst_DATA = \
-     data/ad_schema.ldif \
-     test_pysss_nss_idmap.py \
-     test_infopipe.py \
-+    test_ssh_pubkey.py \
-     $(NULL)
- 
- EXTRA_DIST = data/cwrap-dbus-system.conf.in
-diff --git a/src/tests/intg/test_ssh_pubkey.py b/src/tests/intg/test_ssh_pubkey.py
-new file mode 100644
-index 0000000000000000000000000000000000000000..fbf55566e341373873057ec4e3af1d7f83202aa7
---- /dev/null
-+++ b/src/tests/intg/test_ssh_pubkey.py
-@@ -0,0 +1,232 @@
-+#
-+# ssh public key integration test
-+#
-+# Copyright (c) 2018 Red Hat, Inc.
-+#
-+# This 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; version 2 only
-+#
-+# 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/>.
-+#
-+
-+import os
-+import stat
-+import signal
-+import subprocess
-+import time
-+import ldap
-+import ldap.modlist
-+import pytest
-+
-+import config
-+import ds_openldap
-+import ent
-+import ldap_ent
-+from util import unindent, get_call_output
-+
-+LDAP_BASE_DN = "dc=example,dc=com"
-+
-+USER1_PUBKEY1 = "ssh-dss AAAAB3NzaC1kc3MAAACBAPMkvcU53RVhBtjwiC3IqeRIWR9Qwdv8\
-+DmZzEsDD3Csd6jYxMsPZoXcPrHqwYcEj1s5MVqhdSFS0Cjz13e7gO6OMLInO3xMBSSFHjfp9RE1H\
-+pgc4WisazzyJaW9EMkQo/DqvkFkKh31oqAmxcSbLAFJRg4TTIqm18qu8IRKS6m/RAAAAFQC97TA5\
-+JSsMsaX1bRszC7y4PhMBvQAAAIEAt9Yo9v/h9W4nDbzUdkGwNRszlPEK+T12bJv0O9Fk6subD3Do\
-+6A4Qru/Nr6voXoq8b018Wb7iFWvKOoz5uT/plWBKLXL2NN7ovTR+dUJIzvwurQZroukmU1EghNey\
-+lkSHmDlxSoMK6Nh21uGu6l+b6x5pXNaZHMpsywG4kY8SoC0AAACAAWLHneEGvqkYA8La4Eob+Hjj\
-+mAKilx8byxm3Kfb1XO+ZrR6XxadofZOaUYRMpPKgFjKAKPxJftPLiDjWM7lSe6h8df0dUMLVXt6m\
-+eA83kE0uK5JOOGJfJDqmRed2YnfxUDNNFQGT4xFWGrNtYNbGyw9BWKbkooAsLqaO04zP3Rs= \
-+user1@LDAP"
-+
-+USER1_PUBKEY2 = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwHUUF3HPH+DkU6j8k7Q1wHG\
-+RJY9NeLqSav3h95mTSCQYPSC7I9RTJ4OORgqCbEzrP/DYrrn4TtQ9dhRJar3ZY+F36SH5yFIXORb\
-+lAIbFU+/anahBuFS9vHi1MqFPckGmwJ4QCpjQhdYxo1ro0e1RuGSaQNp/w9N6S/fDz4Cj4I99xDz\
-+SeQeGHxYv0e60plQ8dUajmnaGmYRJHF9a6Ban7IWySActCja7eQP2zIRXEZMpuhl1E0U4y+gHTFI\
-+gD3zQai3QrXm8RUrQURIJ0u6BlGS910OPbHqLpLTFWG08L8sNUcYzC+DY6yoCSO0n/Df3pVRS4C9\
-+5Krf3FqppMTjdfQ== user1@LDAP"
-+
-+
-+@pytest.fixture(scope="module")
-+def ds_inst(request):
-+    """LDAP server instance fixture"""
-+    ds_inst = ds_openldap.DSOpenLDAP(
-+        config.PREFIX, 10389, LDAP_BASE_DN,
-+        "cn=admin", "Secret123"
-+    )
-+
-+    try:
-+        ds_inst.setup()
-+    except:
-+        ds_inst.teardown()
-+        raise
-+    request.addfinalizer(ds_inst.teardown)
-+    return ds_inst
-+
-+
-+@pytest.fixture(scope="module")
-+def ldap_conn(request, ds_inst):
-+    """LDAP server connection fixture"""
-+    ldap_conn = ds_inst.bind()
-+    ldap_conn.ds_inst = ds_inst
-+    request.addfinalizer(ldap_conn.unbind_s)
-+    return ldap_conn
-+
-+
-+def create_ldap_entries(ldap_conn, ent_list=None):
-+    """Add LDAP entries from ent_list"""
-+    if ent_list is not None:
-+        for entry in ent_list:
-+            ldap_conn.add_s(entry[0], entry[1])
-+
-+
-+def cleanup_ldap_entries(ldap_conn, ent_list=None):
-+    """Remove LDAP entries added by create_ldap_entries"""
-+    if ent_list is None:
-+        for ou in ("Users", "Groups", "Netgroups", "Services", "Policies"):
-+            for entry in ldap_conn.search_s("ou=" + ou + "," +
-+                                            ldap_conn.ds_inst.base_dn,
-+                                            ldap.SCOPE_ONELEVEL,
-+                                            attrlist=[]):
-+                ldap_conn.delete_s(entry[0])
-+    else:
-+        for entry in ent_list:
-+            ldap_conn.delete_s(entry[0])
-+
-+
-+def create_ldap_cleanup(request, ldap_conn, ent_list=None):
-+    """Add teardown for removing all user/group LDAP entries"""
-+    request.addfinalizer(lambda: cleanup_ldap_entries(ldap_conn, ent_list))
-+
-+
-+def create_ldap_fixture(request, ldap_conn, ent_list=None):
-+    """Add LDAP entries and add teardown for removing them"""
-+    create_ldap_entries(ldap_conn, ent_list)
-+    create_ldap_cleanup(request, ldap_conn, ent_list)
-+
-+
-+SCHEMA_RFC2307_BIS = "rfc2307bis"
-+
-+
-+def format_basic_conf(ldap_conn, schema):
-+    """Format a basic SSSD configuration"""
-+    schema_conf = "ldap_schema         = " + schema + "\n"
-+    schema_conf += "ldap_group_object_class = groupOfNames\n"
-+    return unindent("""\
-+        [sssd]
-+        domains             = LDAP
-+        services            = nss, ssh
-+
-+        [nss]
-+
-+        [ssh]
-+        debug_level=10
-+
-+        [domain/LDAP]
-+        {schema_conf}
-+        id_provider         = ldap
-+        auth_provider       = ldap
-+        ldap_uri            = {ldap_conn.ds_inst.ldap_url}
-+        ldap_search_base    = {ldap_conn.ds_inst.base_dn}
-+        ldap_sudo_use_host_filter = false
-+        debug_level=10
-+    """).format(**locals())
-+
-+
-+def create_conf_file(contents):
-+    """Create sssd.conf with specified contents"""
-+    conf = open(config.CONF_PATH, "w")
-+    conf.write(contents)
-+    conf.close()
-+    os.chmod(config.CONF_PATH, stat.S_IRUSR | stat.S_IWUSR)
-+
-+
-+def cleanup_conf_file():
-+    """Remove sssd.conf, if it exists"""
-+    if os.path.lexists(config.CONF_PATH):
-+        os.unlink(config.CONF_PATH)
-+
-+
-+def create_conf_cleanup(request):
-+    """Add teardown for removing sssd.conf"""
-+    request.addfinalizer(cleanup_conf_file)
-+
-+
-+def create_conf_fixture(request, contents):
-+    """
-+    Create sssd.conf with specified contents and add teardown for removing it
-+    """
-+    create_conf_file(contents)
-+    create_conf_cleanup(request)
-+
-+
-+def create_sssd_process():
-+    """Start the SSSD process"""
-+    if subprocess.call(["sssd", "-D", "-f"]) != 0:
-+        raise Exception("sssd start failed")
-+
-+
-+def get_sssd_pid():
-+    pid_file = open(config.PIDFILE_PATH, "r")
-+    pid = int(pid_file.read())
-+    return pid
-+
-+
-+def cleanup_sssd_process():
-+    """Stop the SSSD process and remove its state"""
-+    try:
-+        pid = get_sssd_pid()
-+        os.kill(pid, signal.SIGTERM)
-+        while True:
-+            try:
-+                os.kill(pid, signal.SIGCONT)
-+            except:
-+                break
-+            time.sleep(1)
-+    except:
-+        pass
-+    for path in os.listdir(config.DB_PATH):
-+        os.unlink(config.DB_PATH + "/" + path)
-+    for path in os.listdir(config.MCACHE_PATH):
-+        os.unlink(config.MCACHE_PATH + "/" + path)
-+
-+
-+def create_sssd_fixture(request):
-+    """Start SSSD and add teardown for stopping it and removing its state"""
-+    create_sssd_process()
-+    create_sssd_cleanup(request)
-+
-+
-+def create_sssd_cleanup(request):
-+    """Add teardown for stopping SSSD and removing its state"""
-+    request.addfinalizer(cleanup_sssd_process)
-+
-+
-+@pytest.fixture
-+def add_user_with_ssh_key(request, ldap_conn):
-+    ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
-+    ent_list.add_user("user1", 1001, 2001,
-+                      sshPubKey=(USER1_PUBKEY1, USER1_PUBKEY2))
-+    ent_list.add_user("user2", 1002, 2001)
-+    create_ldap_fixture(request, ldap_conn, ent_list)
-+
-+    conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS)
-+    create_conf_fixture(request, conf)
-+    create_sssd_fixture(request)
-+    return None
-+
-+
-+def test_ssh_pubkey_retrieve(add_user_with_ssh_key):
-+    """
-+    Test that we can retrieve an SSH public key for a user who has one
-+    and can't retrieve a key for a user who does not have one.
-+    """
-+    sshpubkey = get_call_output(["sss_ssh_authorizedkeys", "user1"])
-+    assert sshpubkey == USER1_PUBKEY1 + '\n' + USER1_PUBKEY2 + '\n'
-+
-+    sshpubkey = get_call_output(["sss_ssh_authorizedkeys", "user2"])
-+    assert len(sshpubkey) == 0
--- 
-2.17.1
-
diff --git a/SOURCES/0011-Util-added-facility-to-load-nss-lib-syms.patch b/SOURCES/0011-Util-added-facility-to-load-nss-lib-syms.patch
new file mode 100644
index 0000000..e16eb66
--- /dev/null
+++ b/SOURCES/0011-Util-added-facility-to-load-nss-lib-syms.patch
@@ -0,0 +1,555 @@
+From ac1c193a3d8d2e0be39fc647e9a4b616b7513a45 Mon Sep 17 00:00:00 2001
+From: Alexey Tikhonov <atikhono@redhat.com>
+Date: Fri, 22 Mar 2019 15:33:22 +0100
+Subject: [PATCH 11/15] Util: added facility to load nss lib syms
+
+Factored out (from proxy provider code) utility to load NSS symbols
+from shared library.
+
+Related: https://pagure.io/SSSD/sssd/issue/3964
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 6a6aad282e56a5f0bf52f20b98c1764d43abbbaf)
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                      |   2 +
+ src/providers/proxy/proxy.h      |  54 +---------
+ src/providers/proxy/proxy_init.c | 163 ++++++++++++-------------------
+ src/util/nss_dl_load.c           | 106 ++++++++++++++++++++
+ src/util/nss_dl_load.h           |  81 +++++++++++++++
+ 5 files changed, 255 insertions(+), 151 deletions(-)
+ create mode 100644 src/util/nss_dl_load.c
+ create mode 100644 src/util/nss_dl_load.h
+
+diff --git a/Makefile.am b/Makefile.am
+index 4475b3d12..05f5f4e26 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -677,6 +677,7 @@ dist_noinst_HEADERS = \
+     src/util/inotify.h \
+     src/util/sss_iobuf.h \
+     src/util/tev_curl.h \
++    src/util/nss_dl_load.h \
+     src/monitor/monitor.h \
+     src/monitor/monitor_interfaces.h \
+     src/monitor/monitor_iface_generated.h \
+@@ -3996,6 +3997,7 @@ libsss_proxy_la_SOURCES = \
+     src/providers/proxy/proxy_services.c \
+     src/providers/proxy/proxy_auth.c \
+     src/providers/proxy/proxy_iface_generated.c \
++    src//util/nss_dl_load.c \
+     $(NULL)
+ libsss_proxy_la_CFLAGS = \
+     $(AM_CFLAGS)
+diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h
+index 3b0475d08..6debd4953 100644
+--- a/src/providers/proxy/proxy.h
++++ b/src/providers/proxy/proxy.h
+@@ -25,11 +25,7 @@
+ #ifndef __PROXY_H__
+ #define __PROXY_H__
+ 
+-#include <nss.h>
+ #include <errno.h>
+-#include <pwd.h>
+-#include <grp.h>
+-#include <dlfcn.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ 
+@@ -37,58 +33,13 @@
+ #include <security/pam_modules.h>
+ 
+ #include "util/util.h"
++#include "util/nss_dl_load.h"
+ #include "providers/backend.h"
+ #include "db/sysdb.h"
+-#include "sss_client/nss_compat.h"
+ #include <dhash.h>
+ 
+ #define PROXY_CHILD_PATH "/org/freedesktop/sssd/proxychild"
+ 
+-struct proxy_nss_ops {
+-    enum nss_status (*getpwnam_r)(const char *name, struct passwd *result,
+-                                  char *buffer, size_t buflen, int *errnop);
+-    enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result,
+-                                  char *buffer, size_t buflen, int *errnop);
+-    enum nss_status (*setpwent)(void);
+-    enum nss_status (*getpwent_r)(struct passwd *result,
+-                                  char *buffer, size_t buflen, int *errnop);
+-    enum nss_status (*endpwent)(void);
+-
+-    enum nss_status (*getgrnam_r)(const char *name, struct group *result,
+-                                  char *buffer, size_t buflen, int *errnop);
+-    enum nss_status (*getgrgid_r)(gid_t gid, struct group *result,
+-                                  char *buffer, size_t buflen, int *errnop);
+-    enum nss_status (*setgrent)(void);
+-    enum nss_status (*getgrent_r)(struct group *result,
+-                                  char *buffer, size_t buflen, int *errnop);
+-    enum nss_status (*endgrent)(void);
+-    enum nss_status (*initgroups_dyn)(const char *user, gid_t group,
+-                                      long int *start, long int *size,
+-                                      gid_t **groups, long int limit,
+-                                      int *errnop);
+-    enum nss_status (*setnetgrent)(const char *netgroup,
+-                                   struct __netgrent *result);
+-    enum nss_status (*getnetgrent_r)(struct __netgrent *result, char *buffer,
+-                                     size_t buflen, int *errnop);
+-    enum nss_status (*endnetgrent)(struct __netgrent *result);
+-
+-    /* Services */
+-    enum nss_status (*getservbyname_r)(const char *name,
+-                                        const char *protocol,
+-                                        struct servent *result,
+-                                        char *buffer, size_t buflen,
+-                                        int *errnop);
+-    enum nss_status (*getservbyport_r)(int port, const char *protocol,
+-                                        struct servent *result,
+-                                        char *buffer, size_t buflen,
+-                                        int *errnop);
+-    enum nss_status (*setservent)(void);
+-    enum nss_status (*getservent_r)(struct servent *result,
+-                                    char *buffer, size_t buflen,
+-                                    int *errnop);
+-    enum nss_status (*endservent)(void);
+-};
+-
+ struct authtok_conv {
+     struct sss_auth_token *authtok;
+     struct sss_auth_token *newauthtok;
+@@ -99,8 +50,7 @@ struct authtok_conv {
+ struct proxy_id_ctx {
+     struct be_ctx *be;
+     bool fast_alias;
+-    struct proxy_nss_ops ops;
+-    void *handle;
++    struct sss_nss_ops ops;
+ };
+ 
+ struct proxy_auth_ctx {
+diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c
+index 7d997cb16..e3273d9a7 100644
+--- a/src/providers/proxy/proxy_init.c
++++ b/src/providers/proxy/proxy_init.c
+@@ -27,44 +27,15 @@
+ #include "util/sss_format.h"
+ #include "providers/proxy/proxy.h"
+ 
+-#define NSS_FN_NAME "_nss_%s_%s"
+-
+ #define OPT_MAX_CHILDREN_DEFAULT 10
+ 
+-#define ERROR_INITGR "The '%s' library does not provides the " \
+-                         "_nss_XXX_initgroups_dyn function!\n" \
+-                         "initgroups will be slow as it will require " \
+-                         "full groups enumeration!\n"
+-#define ERROR_NETGR "The '%s' library does not support netgroups.\n"
+-#define ERROR_SERV "The '%s' library does not support services.\n"
+-
+-static void *proxy_dlsym(void *handle,
+-                         const char *name,
+-                         const char *libname)
+-{
+-    char *funcname;
+-    void *funcptr;
+-
+-    funcname = talloc_asprintf(NULL, NSS_FN_NAME, libname, name);
+-    if (funcname == NULL) {
+-        return NULL;
+-    }
+-
+-    funcptr = dlsym(handle, funcname);
+-    talloc_free(funcname);
+-
+-    return funcptr;
+-}
+-
+ static errno_t proxy_id_conf(TALLOC_CTX *mem_ctx,
+                              struct be_ctx *be_ctx,
+                              char **_libname,
+-                             char **_libpath,
+                              bool *_fast_alias)
+ {
+     TALLOC_CTX *tmp_ctx;
+     char *libname;
+-    char *libpath;
+     bool fast_alias;
+     errno_t ret;
+ 
+@@ -94,15 +65,7 @@ static errno_t proxy_id_conf(TALLOC_CTX *mem_ctx,
+         goto done;
+     }
+ 
+-    libpath = talloc_asprintf(tmp_ctx, "libnss_%s.so.2", libname);
+-    if (libpath == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
+-        ret = ENOMEM;
+-        goto done;
+-    }
+-
+     *_libname = talloc_steal(mem_ctx, libname);
+-    *_libpath = talloc_steal(mem_ctx, libpath);
+     *_fast_alias = fast_alias;
+ 
+     ret = EOK;
+@@ -113,57 +76,6 @@ done:
+     return ret;
+ }
+ 
+-static errno_t proxy_id_load_symbols(struct proxy_nss_ops *ops,
+-                                     const char *libname,
+-                                     void *handle)
+-{
+-    int i;
+-    struct {void **dest;
+-            const char *name;
+-            const char *custom_error;
+-            bool is_fatal;
+-    } symbols[] = {
+-        {(void**)&ops->getpwnam_r, "getpwnam_r", NULL, true},
+-        {(void**)&ops->getpwuid_r, "getpwuid_r", NULL, true},
+-        {(void**)&ops->setpwent, "setpwent", NULL, true},
+-        {(void**)&ops->getpwent_r, "getpwent_r", NULL, true},
+-        {(void**)&ops->endpwent, "endpwent", NULL, true},
+-        {(void**)&ops->getgrnam_r, "getgrnam_r", NULL, true},
+-        {(void**)&ops->getgrgid_r, "getgrgid_r", NULL, true},
+-        {(void**)&ops->setgrent, "setgrent", NULL, true},
+-        {(void**)&ops->getgrent_r, "getgrent_r", NULL, true},
+-        {(void**)&ops->endgrent, "endgrent", NULL, true},
+-        {(void**)&ops->initgroups_dyn, "initgroups_dyn", ERROR_INITGR, false},
+-        {(void**)&ops->setnetgrent, "setnetgrent", ERROR_NETGR, false},
+-        {(void**)&ops->getnetgrent_r, "getnetgrent_r", ERROR_NETGR, false},
+-        {(void**)&ops->endnetgrent, "endnetgrent", ERROR_NETGR, false},
+-        {(void**)&ops->getservbyname_r, "getservbyname_r", ERROR_SERV, false},
+-        {(void**)&ops->getservbyport_r, "getservbyport_r", ERROR_SERV, false},
+-        {(void**)&ops->setservent, "setservent", ERROR_SERV, false},
+-        {(void**)&ops->getservent_r, "getservent_r", ERROR_SERV, false},
+-        {(void**)&ops->endservent, "endservent", ERROR_SERV, false},
+-        {NULL, NULL, NULL, false}
+-    };
+-
+-    for (i = 0; symbols[i].dest != NULL; i++) {
+-        *symbols[i].dest = proxy_dlsym(handle, symbols[i].name, libname);
+-        if (*symbols[i].dest == NULL) {
+-            DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load _nss_%s_%s, "
+-                  "error: %s.\n", libname, symbols[i].name, dlerror());
+-
+-            if (symbols[i].custom_error != NULL) {
+-                DEBUG(SSSDBG_CRIT_FAILURE, symbols[i].custom_error, libname);
+-            }
+-
+-            if (symbols[i].is_fatal) {
+-                return ELIBBAD;
+-            }
+-        }
+-    }
+-
+-    return EOK;
+-}
+-
+ static errno_t proxy_setup_sbus(TALLOC_CTX *mem_ctx,
+                                 struct proxy_auth_ctx *ctx,
+                                 struct be_ctx *be_ctx)
+@@ -310,6 +222,68 @@ errno_t sssm_proxy_init(TALLOC_CTX *mem_ctx,
+     return EOK;
+ }
+ 
++
++#define ERROR_INITGR "The '%s' library does not provides the " \
++                         "_nss_XXX_initgroups_dyn function!\n" \
++                         "initgroups will be slow as it will require " \
++                         "full groups enumeration!\n"
++#define ERROR_NETGR "The '%s' library does not support netgroups.\n"
++#define ERROR_SERV "The '%s' library does not support services.\n"
++
++static errno_t proxy_load_nss_symbols(struct sss_nss_ops *ops,
++                                      const char *libname)
++{
++    errno_t ret;
++    size_t i;
++
++    ret = sss_load_nss_symbols(ops, libname);
++    if (ret != EOK) {
++        return ret;
++    }
++
++    struct {
++        void *fptr;
++        const char* custom_error;
++    } optional_syms[] = {
++        {(void*)ops->initgroups_dyn,  ERROR_INITGR},
++        {(void*)ops->setnetgrent,     ERROR_NETGR},
++        {(void*)ops->getnetgrent_r,   ERROR_NETGR},
++        {(void*)ops->endnetgrent,     ERROR_NETGR},
++        {(void*)ops->getservbyname_r, ERROR_SERV},
++        {(void*)ops->getservbyport_r, ERROR_SERV},
++        {(void*)ops->setservent,      ERROR_SERV},
++        {(void*)ops->getservent_r,    ERROR_SERV},
++        {(void*)ops->endservent,      ERROR_SERV},
++    };
++    for (i = 0; i < sizeof(optional_syms) / sizeof(optional_syms[0]); ++i) {
++        if (!optional_syms[i].fptr) {
++            DEBUG(SSSDBG_CRIT_FAILURE, optional_syms[i].custom_error, libname);
++        }
++    }
++
++    void *mandatory_syms[] = {
++        (void*)ops->getpwnam_r,
++        (void*)ops->getpwuid_r,
++        (void*)ops->setpwent,
++        (void*)ops->getpwent_r,
++        (void*)ops->endpwent,
++        (void*)ops->getgrnam_r,
++        (void*)ops->getgrgid_r,
++        (void*)ops->setgrent,
++        (void*)ops->getgrent_r,
++        (void*)ops->endgrent,
++    };
++    for (i = 0; i < sizeof(mandatory_syms)/sizeof(mandatory_syms[0]); ++i) {
++        if (!mandatory_syms[i]) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "The '%s' library does not provide mandatory function", libname);
++            return ELIBBAD;
++        }
++    }
++
++    return EOK;
++}
++
++
+ errno_t sssm_proxy_id_init(TALLOC_CTX *mem_ctx,
+                            struct be_ctx *be_ctx,
+                            void *module_data,
+@@ -317,7 +291,6 @@ errno_t sssm_proxy_id_init(TALLOC_CTX *mem_ctx,
+ {
+     struct proxy_id_ctx *ctx;
+     char *libname;
+-    char *libpath;
+     errno_t ret;
+ 
+     ctx = talloc_zero(mem_ctx, struct proxy_id_ctx);
+@@ -327,20 +300,12 @@ errno_t sssm_proxy_id_init(TALLOC_CTX *mem_ctx,
+ 
+     ctx->be = be_ctx;
+ 
+-    ret = proxy_id_conf(ctx, be_ctx, &libname, &libpath, &ctx->fast_alias);
++    ret = proxy_id_conf(ctx, be_ctx, &libname, &ctx->fast_alias);
+     if (ret != EOK) {
+         goto done;
+     }
+ 
+-    ctx->handle = dlopen(libpath, RTLD_NOW);
+-    if (ctx->handle == NULL) {
+-        DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load %s module, "
+-              "error: %s\n", libpath, dlerror());
+-        ret = ELIBACC;
+-        goto done;
+-    }
+-
+-    ret = proxy_id_load_symbols(&ctx->ops, libname, ctx->handle);
++    ret = proxy_load_nss_symbols(&ctx->ops, libname);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load NSS symbols [%d]: %s\n",
+               ret, sss_strerror(ret));
+diff --git a/src/util/nss_dl_load.c b/src/util/nss_dl_load.c
+new file mode 100644
+index 000000000..60df33376
+--- /dev/null
++++ b/src/util/nss_dl_load.c
+@@ -0,0 +1,106 @@
++/*
++    Copyright (C) 2019 Red Hat
++
++    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 <dlfcn.h>
++#include <talloc.h>
++#include <stdbool.h>
++#include <errno.h>
++
++#include "util/util_errors.h"
++#include "util/debug.h"
++#include "nss_dl_load.h"
++
++
++#define NSS_FN_NAME "_nss_%s_%s"
++
++
++static void *proxy_dlsym(void *handle,
++                         const char *name,
++                         const char *libname)
++{
++    char *funcname;
++    void *funcptr;
++
++    funcname = talloc_asprintf(NULL, NSS_FN_NAME, libname, name);
++    if (funcname == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
++        return NULL;
++    }
++
++    funcptr = dlsym(handle, funcname);
++    talloc_free(funcname);
++
++    return funcptr;
++}
++
++
++errno_t sss_load_nss_symbols(struct sss_nss_ops *ops, const char *libname)
++{
++    char *libpath;
++    size_t i;
++    struct {
++        void **dest;
++        const char *name;
++    } symbols[] = {
++        {(void**)&ops->getpwnam_r,      "getpwnam_r"},
++        {(void**)&ops->getpwuid_r,      "getpwuid_r"},
++        {(void**)&ops->setpwent,        "setpwent"},
++        {(void**)&ops->getpwent_r,      "getpwent_r"},
++        {(void**)&ops->endpwent,        "endpwent"},
++        {(void**)&ops->getgrnam_r,      "getgrnam_r"},
++        {(void**)&ops->getgrgid_r,      "getgrgid_r"},
++        {(void**)&ops->setgrent,        "setgrent"},
++        {(void**)&ops->getgrent_r,      "getgrent_r"},
++        {(void**)&ops->endgrent,        "endgrent"},
++        {(void**)&ops->initgroups_dyn,  "initgroups_dyn"},
++        {(void**)&ops->setnetgrent,     "setnetgrent"},
++        {(void**)&ops->getnetgrent_r,   "getnetgrent_r"},
++        {(void**)&ops->endnetgrent,     "endnetgrent"},
++        {(void**)&ops->getservbyname_r, "getservbyname_r"},
++        {(void**)&ops->getservbyport_r, "getservbyport_r"},
++        {(void**)&ops->setservent,      "setservent"},
++        {(void**)&ops->getservent_r,    "getservent_r"},
++        {(void**)&ops->endservent,      "endservent"}
++    };
++
++    libpath = talloc_asprintf(NULL, "libnss_%s.so.2", libname);
++    if (libpath == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
++        return ENOMEM;
++    }
++
++    ops->dl_handle = dlopen(libpath, RTLD_NOW);
++    if (ops->dl_handle == NULL) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load %s module, "
++              "error: %s\n", libpath, dlerror());
++        talloc_free(libpath);
++        return ELIBACC;
++    }
++    talloc_free(libpath);
++
++    for (i = 0; i < sizeof(symbols)/sizeof(symbols[0]); ++i) {
++        *symbols[i].dest = proxy_dlsym(ops->dl_handle, symbols[i].name,
++                                       libname);
++        if (*symbols[i].dest == NULL) {
++            DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load "NSS_FN_NAME", "
++                  "error: %s.\n", libname, symbols[i].name, dlerror());
++        }
++    }
++
++    return EOK;
++}
+diff --git a/src/util/nss_dl_load.h b/src/util/nss_dl_load.h
+new file mode 100644
+index 000000000..5097acacd
+--- /dev/null
++++ b/src/util/nss_dl_load.h
+@@ -0,0 +1,81 @@
++/*
++    Copyright (C) 2019 Red Hat
++
++    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/>.
++*/
++
++#ifndef __SSSD_NSS_DL_LOAD_H__
++#define __SSSD_NSS_DL_LOAD_H__
++
++
++#include <nss.h>
++#include <pwd.h>
++#include <grp.h>
++#include <netdb.h>
++#include "util/util_errors.h"
++#include "sss_client/nss_compat.h"
++
++
++struct sss_nss_ops {
++    enum nss_status (*getpwnam_r)(const char *name, struct passwd *result,
++                                  char *buffer, size_t buflen, int *errnop);
++    enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result,
++                                  char *buffer, size_t buflen, int *errnop);
++    enum nss_status (*setpwent)(void);
++    enum nss_status (*getpwent_r)(struct passwd *result,
++                                  char *buffer, size_t buflen, int *errnop);
++    enum nss_status (*endpwent)(void);
++
++    enum nss_status (*getgrnam_r)(const char *name, struct group *result,
++                                  char *buffer, size_t buflen, int *errnop);
++    enum nss_status (*getgrgid_r)(gid_t gid, struct group *result,
++                                  char *buffer, size_t buflen, int *errnop);
++    enum nss_status (*setgrent)(void);
++    enum nss_status (*getgrent_r)(struct group *result,
++                                  char *buffer, size_t buflen, int *errnop);
++    enum nss_status (*endgrent)(void);
++    enum nss_status (*initgroups_dyn)(const char *user, gid_t group,
++                                      long int *start, long int *size,
++                                      gid_t **groups, long int limit,
++                                      int *errnop);
++    enum nss_status (*setnetgrent)(const char *netgroup,
++                                   struct __netgrent *result);
++    enum nss_status (*getnetgrent_r)(struct __netgrent *result, char *buffer,
++                                     size_t buflen, int *errnop);
++    enum nss_status (*endnetgrent)(struct __netgrent *result);
++
++    /* Services */
++    enum nss_status (*getservbyname_r)(const char *name,
++                                        const char *protocol,
++                                        struct servent *result,
++                                        char *buffer, size_t buflen,
++                                        int *errnop);
++    enum nss_status (*getservbyport_r)(int port, const char *protocol,
++                                        struct servent *result,
++                                        char *buffer, size_t buflen,
++                                        int *errnop);
++    enum nss_status (*setservent)(void);
++    enum nss_status (*getservent_r)(struct servent *result,
++                                    char *buffer, size_t buflen,
++                                    int *errnop);
++    enum nss_status (*endservent)(void);
++
++    void *dl_handle;
++};
++
++
++errno_t sss_load_nss_symbols(struct sss_nss_ops *ops, const char *libname);
++
++
++#endif /* __SSSD_NSS_DL_LOAD_H__ */
+-- 
+2.19.1
+
diff --git a/SOURCES/0012-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch b/SOURCES/0012-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch
deleted file mode 100644
index b212cbc..0000000
--- a/SOURCES/0012-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-From 60f868ac16c4678d60f17d62fa3b47534d4d07cb Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 28 May 2018 21:41:49 +0200
-Subject: [PATCH] SSH: Do not exit abruptly if SSHD closes its end of the pipe
- before reading all the SSH keys
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3747
-
-Before writing the keys to sshd, ignore SIGPIPE so that if the pipe
-towards the authorizedkeys helper is closed, the sss_ssh_authorizedkeys
-helper is not terminated with SIGPIPE, but instead proceeds and then the
-write(2) calls would non-terminally fail with EPIPE.
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit cb138d7d060611e891d341db08477e41f9a3d17d)
----
- src/sss_client/ssh/sss_ssh_authorizedkeys.c | 35 ++++++++++++++++++++-
- 1 file changed, 34 insertions(+), 1 deletion(-)
-
-diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
-index 782a9f44379bff5346c896b3e03570720632c0be..b0280fbf8b0ed0501d792973241b826fc4a7a04d 100644
---- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c
-+++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
-@@ -21,6 +21,7 @@
- #include <stdio.h>
- #include <talloc.h>
- #include <popt.h>
-+#include <signal.h>
- 
- #include "util/util.h"
- #include "util/crypto/sss_crypto.h"
-@@ -99,8 +100,16 @@ int main(int argc, const char **argv)
-         goto fini;
-     }
- 
-+    /* if sshd closes its end of the pipe, we don't want sss_ssh_authorizedkeys
-+     * to exit abruptly, but to finish gracefully instead because the valid
-+     * key can be present in the data already written
-+     */
-+    signal(SIGPIPE, SIG_IGN);
-+
-     /* print results */
-     for (i = 0; i < ent->num_pubkeys; i++) {
-+        char *repr_break = NULL;
-+
-         ret = sss_ssh_format_pubkey(mem_ctx, &ent->pubkeys[i], &repr);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE,
-@@ -109,7 +118,31 @@ int main(int argc, const char **argv)
-             continue;
-         }
- 
--        printf("%s\n", repr);
-+        /* OpenSSH expects a linebreak after each key */
-+        repr_break = talloc_asprintf(mem_ctx, "%s\n", repr);
-+        talloc_zfree(repr);
-+        if (repr_break == NULL) {
-+            ret = ENOMEM;
-+            goto fini;
-+        }
-+
-+        ret = sss_atomic_write_s(STDOUT_FILENO, repr_break, strlen(repr_break));
-+        /* Avoid spiking memory with too many large keys */
-+        talloc_zfree(repr_break);
-+        if (ret < 0) {
-+            ret = errno;
-+            if (ret == EPIPE) {
-+                DEBUG(SSSDBG_MINOR_FAILURE,
-+                      "SSHD closed the pipe before all keys could be written\n");
-+                /* Return 0 so that openssh doesn't abort pubkey auth */
-+                ret = 0;
-+                goto fini;
-+            }
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "sss_atomic_write_s() failed (%d): %s\n",
-+                  ret, strerror(ret));
-+            goto fini;
-+        }
-     }
- 
-     ret = EXIT_SUCCESS;
--- 
-2.17.1
-
diff --git a/SOURCES/0012-responder-negcache-avoid-calling-nsswitch-NSS-API.patch b/SOURCES/0012-responder-negcache-avoid-calling-nsswitch-NSS-API.patch
new file mode 100644
index 0000000..554a973
--- /dev/null
+++ b/SOURCES/0012-responder-negcache-avoid-calling-nsswitch-NSS-API.patch
@@ -0,0 +1,1107 @@
+From b08906169216fdec43008c38891145386017d12f Mon Sep 17 00:00:00 2001
+From: Alexey Tikhonov <atikhono@redhat.com>
+Date: Fri, 22 Mar 2019 16:06:49 +0100
+Subject: [PATCH 12/15] responder/negcache: avoid calling nsswitch NSS API
+
+Changed "negcache_files.c::is_*_local_by_*()" to use functions from
+"libnss_files" directly to check users (instead of calling glibc
+NSS API).
+Changed affected tests to avoid using NSS-wrapper and to use real
+local user&group (otherwise tests were broken).
+
+Resolves: https://pagure.io/SSSD/sssd/issue/3964
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 2b564f849a20289a857cf19bbfaa5c6eb8670bad)
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                           |  20 +++
+ src/responder/common/negcache.c       |  52 +++++-
+ src/responder/common/negcache_files.c |  74 ++++-----
+ src/responder/common/negcache_files.h |  12 +-
+ src/tests/cwrap/Makefile.am           |   4 +
+ src/tests/cwrap/test_negcache.c       | 227 +++++++++++++++++++-------
+ src/tests/intg/test_ldap.py           | 114 ++++++-------
+ 7 files changed, 333 insertions(+), 170 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 05f5f4e26..6a67dc7b1 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -569,6 +569,7 @@ SSSD_RESPONDER_IFACE_OBJ = \
+ SSSD_RESPONDER_OBJ = \
+     src/responder/common/negcache_files.c \
+     src/responder/common/negcache.c \
++    src/util/nss_dl_load.c \
+     src/responder/common/responder_cmd.c \
+     src/responder/common/responder_common.c \
+     src/responder/common/responder_dp.c \
+@@ -1380,6 +1381,7 @@ sssd_nss_SOURCES = \
+     src/responder/nss/nsssrv_mmap_cache.c \
+     $(SSSD_RESPONDER_OBJ)
+ sssd_nss_LDADD = \
++    $(LIBADD_DL) \
+     $(TDB_LIBS) \
+     $(SSSD_LIBS) \
+     libsss_idmap.la \
+@@ -1396,6 +1398,7 @@ sssd_pam_SOURCES = \
+     src/responder/pam/pam_helpers.c \
+     $(SSSD_RESPONDER_OBJ)
+ sssd_pam_LDADD = \
++    $(LIBADD_DL) \
+     $(TDB_LIBS) \
+     $(SSSD_LIBS) \
+     $(SELINUX_LIBS) \
+@@ -1414,6 +1417,7 @@ sssd_sudo_SOURCES = \
+     src/responder/sudo/sudosrv_dp.c \
+     $(SSSD_RESPONDER_OBJ)
+ sssd_sudo_LDADD = \
++    $(LIBADD_DL) \
+     $(SSSD_LIBS) \
+     $(SYSTEMD_DAEMON_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS)
+@@ -1426,6 +1430,7 @@ sssd_autofs_SOURCES = \
+     src/responder/autofs/autofssrv_dp.c \
+     $(SSSD_RESPONDER_OBJ)
+ sssd_autofs_LDADD = \
++    $(LIBADD_DL) \
+     $(SSSD_LIBS) \
+     $(SYSTEMD_DAEMON_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS)
+@@ -1441,6 +1446,7 @@ sssd_ssh_SOURCES = \
+     $(SSSD_RESPONDER_OBJ) \
+     $(NULL)
+ sssd_ssh_LDADD = \
++    $(LIBADD_DL) \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+     $(SYSTEMD_DAEMON_LIBS) \
+@@ -1457,6 +1463,7 @@ sssd_pac_CFLAGS = \
+     $(AM_CFLAGS) \
+     $(NDR_KRB5PAC_CFLAGS)
+ sssd_pac_LDADD = \
++    $(LIBADD_DL) \
+     $(NDR_KRB5PAC_LIBS) \
+     $(TDB_LIBS) \
+     $(SSSD_LIBS) \
+@@ -1481,6 +1488,7 @@ sssd_ifp_SOURCES = \
+ sssd_ifp_CFLAGS = \
+     $(AM_CFLAGS)
+ sssd_ifp_LDADD = \
++    $(LIBADD_DL) \
+     $(SSSD_LIBS) \
+     $(SYSTEMD_DAEMON_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+@@ -1525,6 +1533,7 @@ sssd_secrets_SOURCES = \
+     $(SSSD_RESPONDER_OBJ) \
+     $(NULL)
+ sssd_secrets_LDADD = \
++    $(LIBADD_DL) \
+     $(HTTP_PARSER_LIBS) \
+     $(JANSSON_LIBS) \
+     $(TDB_LIBS) \
+@@ -1559,6 +1568,7 @@ sssd_kcm_CFLAGS = \
+     $(JANSSON_CFLAGS) \
+     $(NULL)
+ sssd_kcm_LDADD = \
++    $(LIBADD_DL) \
+     $(KRB5_LIBS) \
+     $(CURL_LIBS) \
+     $(JANSSON_LIBS) \
+@@ -2254,6 +2264,7 @@ responder_socket_access_tests_SOURCES = \
+     src/tests/responder_socket_access-tests.c \
+     src/responder/common/negcache_files.c \
+     src/responder/common/negcache.c \
++    src/util/nss_dl_load.c \
+     src/responder/common/responder_common.c \
+     src/responder/common/responder_packet.c \
+     src/responder/common/responder_cmd.c \
+@@ -2267,6 +2278,7 @@ responder_socket_access_tests_CFLAGS = \
+     $(AM_CFLAGS) \
+     $(CHECK_CFLAGS)
+ responder_socket_access_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CHECK_LIBS) \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+@@ -2358,6 +2370,7 @@ TEST_MOCK_RESP_OBJ = \
+      src/responder/common/responder_cmd.c \
+      src/responder/common/negcache_files.c \
+      src/responder/common/negcache.c \
++     src/util/nss_dl_load.c \
+      src/responder/common/responder_common.c \
+      src/responder/common/data_provider/rdp_message.c \
+      src/responder/common/data_provider/rdp_client.c \
+@@ -2409,6 +2422,7 @@ nss_srv_tests_LDFLAGS = \
+     -Wl,-wrap,sss_cmd_send_empty \
+     -Wl,-wrap,sss_cmd_done
+ nss_srv_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+@@ -2444,6 +2458,7 @@ pam_srv_tests_LDFLAGS = \
+     -Wl,-wrap,pam_dp_send_req \
+     $(NULL)
+ pam_srv_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(PAM_LIBS) \
+     $(SSSD_LIBS) \
+@@ -2480,6 +2495,7 @@ ssh_srv_tests_LDFLAGS = \
+     -Wl,-wrap,ssh_dp_send_req \
+     $(NULL)
+ ssh_srv_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+@@ -2499,6 +2515,7 @@ responder_get_domains_tests_LDFLAGS = \
+     -Wl,-wrap,sss_parse_name_for_domains \
+     -Wl,-wrap,sss_ncache_reset_repopulate_permanent
+ responder_get_domains_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+@@ -2578,6 +2595,7 @@ test_negcache_CFLAGS = \
+     $(TALLOC_CFLAGS) \
+     $(DHASH_CFLAGS)
+ test_negcache_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SYSTEMD_DAEMON_LIBS) \
+@@ -2922,6 +2940,7 @@ ifp_tests_SOURCES = \
+ ifp_tests_CFLAGS = \
+     $(AM_CFLAGS)
+ ifp_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+@@ -3178,6 +3197,7 @@ responder_cache_req_tests_LDFLAGS = \
+     -Wl,-wrap,sss_dp_get_account_send \
+     $(NULL)
+ responder_cache_req_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS) \
+diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
+index f9034d164..d6f72d816 100644
+--- a/src/responder/common/negcache.c
++++ b/src/responder/common/negcache.c
+@@ -19,14 +19,16 @@
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+ 
++#include <fcntl.h>
++#include <time.h>
++#include "tdb.h"
+ #include "util/util.h"
++#include "util/nss_dl_load.h"
+ #include "confdb/confdb.h"
+ #include "responder/common/negcache_files.h"
+ #include "responder/common/responder.h"
+ #include "responder/common/negcache.h"
+-#include <fcntl.h>
+-#include <time.h>
+-#include "tdb.h"
++
+ 
+ #define NC_ENTRY_PREFIX "NCE/"
+ #define NC_USER_PREFIX NC_ENTRY_PREFIX"USER"
+@@ -44,6 +46,7 @@ struct sss_nc_ctx {
+     struct tdb_context *tdb;
+     uint32_t timeout;
+     uint32_t local_timeout;
++    struct sss_nss_ops ops;
+ };
+ 
+ typedef int (*ncache_set_byname_fn_t)(struct sss_nc_ctx *, bool,
+@@ -63,14 +66,49 @@ static int string_to_tdb_data(char *str, TDB_DATA *ret)
+     return EOK;
+ }
+ 
++static errno_t ncache_load_nss_symbols(struct sss_nss_ops *ops)
++{
++    errno_t ret;
++    size_t i;
++
++    ret = sss_load_nss_symbols(ops, "files");
++    if (ret != EOK) {
++        return ret;
++    }
++
++    void *mandatory_syms[] = {
++        (void*)ops->getpwnam_r,
++        (void*)ops->getpwuid_r,
++        (void*)ops->getgrnam_r,
++        (void*)ops->getgrgid_r
++    };
++    for (i = 0; i < sizeof(mandatory_syms)/sizeof(mandatory_syms[0]); ++i) {
++        if (!mandatory_syms[i]) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "The 'files' library does not provide mandatory function");
++            return ELIBBAD;
++        }
++    }
++
++    return EOK;
++}
++
+ int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout,
+                     uint32_t local_timeout, struct sss_nc_ctx **_ctx)
+ {
++    errno_t ret;
+     struct sss_nc_ctx *ctx;
+ 
+     ctx = talloc_zero(memctx, struct sss_nc_ctx);
+     if (!ctx) return ENOMEM;
+ 
++    ret = ncache_load_nss_symbols(&ctx->ops);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load NSS symbols [%d]: %s\n",
++              ret, sss_strerror(ret));
++        talloc_free(ctx);
++        return ret;
++    }
++
+     errno = 0;
+     /* open a memory only tdb with default hash size */
+     ctx->tdb = tdb_open("memcache", 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0);
+@@ -488,7 +526,7 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
+     if (!str) return ENOMEM;
+ 
+     if ((!permanent) && (ctx->local_timeout > 0)) {
+-        use_local_negative = is_user_local_by_name(name);
++        use_local_negative = is_user_local_by_name(&ctx->ops, name);
+     }
+     ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative);
+ 
+@@ -509,7 +547,7 @@ static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent,
+     if (!str) return ENOMEM;
+ 
+     if ((!permanent) && (ctx->local_timeout > 0)) {
+-        use_local_negative = is_group_local_by_name(name);
++        use_local_negative = is_group_local_by_name(&ctx->ops, name);
+     }
+     ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative);
+ 
+@@ -606,7 +644,7 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
+     if (!str) return ENOMEM;
+ 
+     if ((!permanent) && (ctx->local_timeout > 0)) {
+-        use_local_negative = is_user_local_by_uid(uid);
++        use_local_negative = is_user_local_by_uid(&ctx->ops, uid);
+     }
+     ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative);
+ 
+@@ -630,7 +668,7 @@ int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
+     if (!str) return ENOMEM;
+ 
+     if ((!permanent) && (ctx->local_timeout > 0)) {
+-        use_local_negative = is_group_local_by_gid(gid);
++        use_local_negative = is_group_local_by_gid(&ctx->ops, gid);
+     }
+     ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative);
+ 
+diff --git a/src/responder/common/negcache_files.c b/src/responder/common/negcache_files.c
+index 4256186d9..85a7065a4 100644
+--- a/src/responder/common/negcache_files.c
++++ b/src/responder/common/negcache_files.c
+@@ -19,94 +19,90 @@
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+ 
+-#include <sys/types.h>
+-#include <pwd.h>
+-#include <grp.h>
+ #include "util/util.h"
++#include "util/nss_dl_load.h"
+ #include "responder/common/negcache_files.h"
+ 
+ #define BUFFER_SIZE 16384
+ 
+-bool is_user_local_by_name(const char *name)
++bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name)
+ {
+     struct passwd pwd = { 0 };
+-    struct passwd *pwd_result;
++    int errnop;
+     char buffer[BUFFER_SIZE];
+-    bool is_local = false;
+-    int ret;
++    enum nss_status ret;
+     char *shortname = NULL;
++    int parse_ret;
+ 
+-    ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL);
+-    if (ret != EOK) {
++    parse_ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL);
++    if (parse_ret != EOK) {
+         return false;
+     }
+ 
+-    ret = getpwnam_r(shortname, &pwd, buffer, BUFFER_SIZE, &pwd_result);
++    ret = ops->getpwnam_r(shortname, &pwd, buffer, BUFFER_SIZE, &errnop);
+     talloc_free(shortname);
+-    if (ret == EOK && pwd_result != NULL) {
++    if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC, "User %s is a local user\n", name);
+-        is_local = true;
++        return true;
+     }
+ 
+-    return is_local;
++    return false;
+ }
+ 
+-bool is_user_local_by_uid(uid_t uid)
++bool is_user_local_by_uid(const struct sss_nss_ops *ops, uid_t uid)
+ {
+     struct passwd pwd = { 0 };
+-    struct passwd *pwd_result;
++    int errnop;
+     char buffer[BUFFER_SIZE];
+-    bool is_local = false;
+-    int ret;
++    enum nss_status ret;
+ 
+-    ret = getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &pwd_result);
+-    if (ret == EOK && pwd_result != NULL) {
++    ret = ops->getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &errnop);
++    if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC,
+               "User with UID %"SPRIuid" is a local user\n", uid);
+-        is_local = true;
++        return true;
+     }
+ 
+-    return is_local;
++    return false;
+ }
+ 
+-bool is_group_local_by_name(const char *name)
++bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name)
+ {
+     struct group grp = { 0 };
+-    struct group *grp_result;
++    int errnop;
+     char buffer[BUFFER_SIZE];
+-    bool is_local = false;
+-    int ret;
++    enum nss_status ret;
+     char *shortname = NULL;
++    int parse_ret;
+ 
+-    ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL);
+-    if (ret != EOK) {
++    parse_ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL);
++    if (parse_ret != EOK) {
+         return false;
+     }
+ 
+-    ret = getgrnam_r(shortname, &grp, buffer, BUFFER_SIZE, &grp_result);
++    ret = ops->getgrnam_r(shortname, &grp, buffer, BUFFER_SIZE, &errnop);
+     talloc_free(shortname);
+-    if (ret == EOK && grp_result != NULL) {
++    if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC, "Group %s is a local group\n", name);
+-        is_local = true;
++        return true;
+     }
+ 
+-    return is_local;
++    return false;
+ }
+ 
+-bool is_group_local_by_gid(uid_t gid)
++bool is_group_local_by_gid(const struct sss_nss_ops *ops, uid_t gid)
+ {
+     struct group grp = { 0 };
+-    struct group *grp_result;
++    int errnop;
+     char buffer[BUFFER_SIZE];
+-    bool is_local = false;
+-    int ret;
++    enum nss_status ret;
+ 
+-    ret = getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &grp_result);
+-    if (ret == EOK && grp_result != NULL) {
++    ret = ops->getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &errnop);
++    if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC,
+               "Group with GID %"SPRIgid" is a local group\n", gid);
+-        is_local = true;
++        return true;
+     }
+ 
+-    return is_local;
++    return false;
+ }
+diff --git a/src/responder/common/negcache_files.h b/src/responder/common/negcache_files.h
+index 01d9f0828..a3e18deb0 100644
+--- a/src/responder/common/negcache_files.h
++++ b/src/responder/common/negcache_files.h
+@@ -22,10 +22,14 @@
+ #ifndef _NEGCACHE_FILES_H_
+ #define _NEGCACHE_FILES_H_
+ 
+-bool is_user_local_by_name(const char *name);
+-bool is_user_local_by_uid(uid_t uid);
++#include <stdbool.h>
+ 
+-bool is_group_local_by_name(const char *name);
+-bool is_group_local_by_gid(uid_t gid);
++struct sss_nss_ops;
++
++bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name);
++bool is_user_local_by_uid(const struct sss_nss_ops *ops, uid_t uid);
++
++bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name);
++bool is_group_local_by_gid(const struct sss_nss_ops *ops, uid_t gid);
+ 
+ #endif /* _NEGCACHE_FILES_H_ */
+diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
+index a559abe9e..bfc493395 100644
+--- a/src/tests/cwrap/Makefile.am
++++ b/src/tests/cwrap/Makefile.am
+@@ -75,6 +75,7 @@ SSSD_RESPONDER_IFACE_OBJ = \
+ 
+ SSSD_RESPONDER_OBJ = \
+     ../../../src/responder/common/negcache_files.c \
++    ../../../src/util/nss_dl_load.c \
+     ../../../src/responder/common/negcache.c \
+     ../../../src/responder/common/responder_cmd.c \
+     ../../../src/responder/common/responder_common.c \
+@@ -175,6 +176,7 @@ responder_common_tests_SOURCES =\
+     ../../../src/responder/common/iface/responder_ncache.c \
+     ../../../src/responder/common/iface/responder_iface_generated.c \
+     ../../../src/responder/common/negcache_files.c \
++    ../../../src/util/nss_dl_load.c \
+     ../../../src/responder/common/negcache.c \
+     ../../../src/responder/common/data_provider/rdp_message.c \
+     ../../../src/responder/common/data_provider/rdp_client.c \
+@@ -189,6 +191,7 @@ responder_common_tests_CFLAGS = \
+     $(AM_CFLAGS) \
+     $(NULL)
+ responder_common_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SELINUX_LIBS) \
+@@ -207,6 +210,7 @@ negcache_tests_CFLAGS = \
+     -DBASE_FILE_STEM=\"$(*F)\" \
+     $(NULL)
+ negcache_tests_LDADD = \
++    $(LIBADD_DL) \
+     $(CMOCKA_LIBS) \
+     $(SSSD_LIBS) \
+     $(SELINUX_LIBS) \
+diff --git a/src/tests/cwrap/test_negcache.c b/src/tests/cwrap/test_negcache.c
+index c4f601b34..690e797e2 100644
+--- a/src/tests/cwrap/test_negcache.c
++++ b/src/tests/cwrap/test_negcache.c
+@@ -18,6 +18,10 @@
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+ 
++#include <stdio.h>
++#include <sys/types.h>
++#include <pwd.h>
++
+ #include <stdarg.h>
+ #include <stddef.h>
+ #include <setjmp.h>
+@@ -35,38 +39,40 @@
+ #define TEST_CONF_DB "test_negcache_confdb.ldb"
+ #define TEST_DOM_NAME "test_domain.test"
+ 
+-#define TEST_LOCAL_USER_NAME_1 "foobar"
+-#define TEST_LOCAL_USER_NAME_2 "sssd"
+-
+-#define TEST_LOCAL_USER_UID_1 10001
+-#define TEST_LOCAL_USER_UID_2 123
+-
+-#define TEST_LOCAL_GROUP_NAME_1 "foogroup"
+-#define TEST_LOCAL_GROUP_NAME_2 "sssd"
+-
+-#define TEST_LOCAL_GID_1 10001
+-#define TEST_LOCAL_GID_2 123
+-
+-struct test_user {
++struct user_descriptor_t {
+     const char *name;
+     uid_t uid;
++};
++
++struct group_descriptor_t {
++    const char *name;
+     gid_t gid;
+-} users[] = { { "test_user1", 1001, 50001 },
+-              { "test_user2", 1002, 50002 } };
++};
+ 
+-static void create_users(TALLOC_CTX *mem_ctx,
+-                         struct sss_domain_info *domain)
++struct ncache_test_ctx {
++    struct sss_test_ctx *tctx;
++    struct sss_nc_ctx *ncache;
++    struct user_descriptor_t local_users[2];
++    struct user_descriptor_t non_local_users[2];
++    struct group_descriptor_t local_groups[2];
++    struct group_descriptor_t non_local_groups[2];
++};
++
++static void create_users(struct ncache_test_ctx *test_ctx)
+ {
+     errno_t ret;
+     char *fqname;
++    struct sss_domain_info *domain = test_ctx->tctx->dom;
++    const struct user_descriptor_t *users = test_ctx->non_local_users;
++    const struct group_descriptor_t *groups = test_ctx->non_local_groups;
+ 
+     for (int i = 0; i < 2; i++) {
+-        fqname = sss_create_internal_fqname(mem_ctx,
++        fqname = sss_create_internal_fqname(test_ctx,
+                                             users[i].name,
+                                             domain->name);
+         assert_non_null(fqname);
+ 
+-        ret = sysdb_add_user(domain, users[i].name, users[i].uid, users[i].gid,
++        ret = sysdb_add_user(domain, users[i].name, users[i].uid, groups[i].gid,
+                              fqname, NULL, "/bin/bash", domain->name,
+                              NULL, 30, time(NULL));
+         talloc_free(fqname);
+@@ -74,25 +80,15 @@ static void create_users(TALLOC_CTX *mem_ctx,
+     }
+ }
+ 
+-struct test_group {
+-    const char *name;
+-    gid_t gid;
+-} groups[] = { { "test_group1", 50001 },
+-               { "test_group2", 50002 } };
+-
+-struct ncache_test_ctx {
+-    struct sss_test_ctx *tctx;
+-    struct sss_nc_ctx *ncache;
+-};
+-
+-static void create_groups(TALLOC_CTX *mem_ctx,
+-                          struct sss_domain_info *domain)
++static void create_groups(struct ncache_test_ctx *test_ctx)
+ {
+     errno_t ret;
+     char *fqname;
++    struct sss_domain_info *domain = test_ctx->tctx->dom;
++    const struct group_descriptor_t *groups = test_ctx->non_local_groups;
+ 
+     for (int i = 0; i < 2; i++) {
+-        fqname = sss_create_internal_fqname(mem_ctx,
++        fqname = sss_create_internal_fqname(test_ctx,
+                                             groups[i].name,
+                                             domain->name);
+         assert_non_null(fqname);
+@@ -116,6 +112,114 @@ struct cli_protocol_version *register_cli_protocol_version(void)
+     return responder_test_cli_protocol_version;
+ }
+ 
++static void find_local_users(struct ncache_test_ctx *test_ctx)
++{
++    int i;
++    FILE *passwd_file;
++    const struct passwd *pwd;
++
++    passwd_file = fopen("/etc/passwd", "r");
++    assert_non_null(passwd_file);
++
++    for (i = 0; i < 2; /*no-op*/) {
++        pwd = fgetpwent(passwd_file);
++        assert_non_null(pwd);
++        if (pwd->pw_uid == 0) {
++            /* skip root */
++            continue;
++        }
++        test_ctx->local_users[i].uid = pwd->pw_uid;
++        test_ctx->local_users[i].name = talloc_strdup(test_ctx, pwd->pw_name);
++        assert_non_null(test_ctx->local_users[i].name);
++        ++i;
++    }
++
++    fclose(passwd_file);
++}
++
++static void find_local_groups(struct ncache_test_ctx *test_ctx)
++{
++    int i;
++    FILE *group_file;
++    const struct group *grp;
++
++    group_file = fopen("/etc/group", "r");
++    assert_non_null(group_file);
++
++    for (i = 0; i < 2; /* no-op */) {
++        grp = fgetgrent(group_file);
++        assert_non_null(grp);
++        if (grp->gr_gid == 0) {
++            /* skip root */
++            continue;
++        }
++        test_ctx->local_groups[i].gid = grp->gr_gid;
++        test_ctx->local_groups[i].name = talloc_strdup(test_ctx, grp->gr_name);
++        assert_non_null(test_ctx->local_groups[i].name);
++        ++i;
++    }
++
++    fclose(group_file);
++}
++
++static void find_non_local_users(struct ncache_test_ctx *test_ctx)
++{
++    int i;
++    int k;
++    uid_t uid;
++    char *name;
++
++    for (i = 0, k = 1; (k < 100) && (i < 2); ++k) {
++        uid = 65534-k;
++        if (getpwuid(uid)) {
++            continue;
++        }
++        test_ctx->non_local_users[i].uid = uid;
++        ++i;
++    }
++    assert_int_equal(i, 2);
++
++    for (i = 0, k = 0; (k < 100) && (i < 2); ++k) {
++        name = talloc_asprintf(test_ctx, "nctestuser%d", k);
++        if (getpwnam(name)) {
++            talloc_free(name);
++            continue;
++        }
++        test_ctx->non_local_users[i].name = name;
++        ++i;
++    }
++    assert_int_equal(i, 2);
++}
++
++static void find_non_local_groups(struct ncache_test_ctx *test_ctx)
++{
++    int i = 0;
++    int k;
++    gid_t gid;
++    char *name;
++
++    for (i = 0, k = 1; (k < 100) && (i < 2); ++k) {
++        gid = 65534-k;
++        if (getgrgid(gid)) {
++            continue;
++        }
++        test_ctx->non_local_groups[i].gid = gid;
++        ++i;
++    }
++    assert_int_equal(i, 2);
++
++    for (i = 0, k = 0; (k < 100) && (i < 2); ++k) {
++        name = talloc_asprintf(test_ctx, "nctestgroup%d", k);
++        if (getgrnam(name)) {
++            talloc_free(name);
++            continue;
++        }
++        test_ctx->non_local_groups[i].name = name;
++        ++i;
++    }
++    assert_int_equal(i, 2);
++}
++
+ static int test_ncache_setup(void **state)
+ {
+     struct ncache_test_ctx *test_ctx;
+@@ -125,14 +229,19 @@ static int test_ncache_setup(void **state)
+     test_ctx = talloc_zero(global_talloc_context, struct ncache_test_ctx);
+     assert_non_null(test_ctx);
+ 
++    find_local_users(test_ctx);
++    find_local_groups(test_ctx);
++    find_non_local_users(test_ctx);
++    find_non_local_groups(test_ctx);
++
+     test_dom_suite_setup(TESTS_PATH);
+ 
+     test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, TEST_CONF_DB,
+                                          TEST_DOM_NAME, "ipa", NULL);
+     assert_non_null(test_ctx->tctx);
+ 
+-    create_groups(test_ctx, test_ctx->tctx->dom);
+-    create_users(test_ctx, test_ctx->tctx->dom);
++    create_groups(test_ctx);
++    create_users(test_ctx);
+ 
+     check_leaks_push(test_ctx);
+ 
+@@ -213,11 +322,11 @@ static void set_users(struct ncache_test_ctx *test_ctx)
+     int ret;
+ 
+     ret = set_user_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                              users[0].name);
++                             test_ctx->non_local_users[0].name);
+     assert_int_equal(ret, EOK);
+ 
+     ret = set_user_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                             TEST_LOCAL_USER_NAME_1);
++                             test_ctx->local_users[0].name);
+     assert_int_equal(ret, EOK);
+ }
+ 
+@@ -227,19 +336,19 @@ static void check_users(struct ncache_test_ctx *test_ctx,
+     int ret;
+ 
+     ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                users[0].name);
++                                test_ctx->non_local_users[0].name);
+     assert_int_equal(ret, case_a);
+ 
+     ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                users[1].name);
++                                test_ctx->non_local_users[1].name);
+     assert_int_equal(ret, case_b);
+ 
+     ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                TEST_LOCAL_USER_NAME_1);
++                                test_ctx->local_users[0].name);
+     assert_int_equal(ret, case_c);
+ 
+     ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                TEST_LOCAL_USER_NAME_2);
++                                test_ctx->local_users[1].name);
+     assert_int_equal(ret, case_d);
+ }
+ 
+@@ -324,11 +433,11 @@ static void set_uids(struct ncache_test_ctx *test_ctx)
+     int ret;
+ 
+     ret = sss_ncache_set_uid(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                             users[0].uid);
++                             test_ctx->non_local_users[0].uid);
+     assert_int_equal(ret, EOK);
+ 
+     ret = sss_ncache_set_uid(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                             TEST_LOCAL_USER_UID_1);
++                             test_ctx->local_users[0].uid);
+     assert_int_equal(ret, EOK);
+ }
+ 
+@@ -338,19 +447,19 @@ static void check_uids(struct ncache_test_ctx *test_ctx,
+     int ret;
+ 
+     ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               users[0].uid);
++                               test_ctx->non_local_users[0].uid);
+     assert_int_equal(ret, case_a);
+ 
+     ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               users[1].uid);
++                               test_ctx->non_local_users[1].uid);
+     assert_int_equal(ret, case_b);
+ 
+     ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               TEST_LOCAL_USER_UID_1);
++                               test_ctx->local_users[0].uid);
+     assert_int_equal(ret, case_c);
+ 
+     ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               TEST_LOCAL_USER_UID_2);
++                               test_ctx->local_users[1].uid);
+     assert_int_equal(ret, case_d);
+ }
+ 
+@@ -435,11 +544,11 @@ static void set_groups(struct ncache_test_ctx *test_ctx)
+     int ret;
+ 
+     ret = set_group_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                              groups[0].name);
++                              test_ctx->non_local_groups[0].name);
+     assert_int_equal(ret, EOK);
+ 
+     ret = set_group_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                              TEST_LOCAL_GROUP_NAME_1);
++                              test_ctx->local_groups[0].name);
+     assert_int_equal(ret, EOK);
+ }
+ 
+@@ -449,19 +558,19 @@ static void check_groups(struct ncache_test_ctx *test_ctx,
+     int ret;
+ 
+     ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                groups[0].name);
++                                test_ctx->non_local_groups[0].name);
+     assert_int_equal(ret, case_a);
+ 
+     ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                groups[1].name);
++                                test_ctx->non_local_groups[1].name);
+     assert_int_equal(ret, case_b);
+ 
+     ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                TEST_LOCAL_GROUP_NAME_1);
++                                test_ctx->local_groups[0].name);
+     assert_int_equal(ret, case_c);
+ 
+     ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
+-                                TEST_LOCAL_GROUP_NAME_2);
++                                test_ctx->local_groups[1].name);
+     assert_int_equal(ret, case_d);
+ }
+ 
+@@ -546,11 +655,11 @@ static void set_gids(struct ncache_test_ctx *test_ctx)
+     int ret;
+ 
+     ret = sss_ncache_set_gid(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                             users[0].gid);
++                             test_ctx->non_local_groups[0].gid);
+     assert_int_equal(ret, EOK);
+ 
+     ret = sss_ncache_set_gid(test_ctx->ncache, false, test_ctx->tctx->dom,
+-                             TEST_LOCAL_GID_1);
++                             test_ctx->local_groups[0].gid);
+     assert_int_equal(ret, EOK);
+ }
+ 
+@@ -560,19 +669,19 @@ static void check_gids(struct ncache_test_ctx *test_ctx,
+     int ret;
+ 
+     ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               users[0].gid);
++                               test_ctx->non_local_groups[0].gid);
+     assert_int_equal(ret, case_a);
+ 
+     ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               users[1].gid);
++                               test_ctx->non_local_groups[1].gid);
+     assert_int_equal(ret, case_b);
+ 
+     ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               TEST_LOCAL_GID_1);
++                               test_ctx->local_groups[0].gid);
+     assert_int_equal(ret, case_c);
+ 
+     ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
+-                               TEST_LOCAL_GID_2);
++                               test_ctx->local_groups[1].gid);
+     assert_int_equal(ret, case_d);
+ }
+ 
+diff --git a/src/tests/intg/test_ldap.py b/src/tests/intg/test_ldap.py
+index 63f6ea4ed..787255f92 100644
+--- a/src/tests/intg/test_ldap.py
++++ b/src/tests/intg/test_ldap.py
+@@ -43,15 +43,6 @@ from files_ops import passwd_ops_setup, group_ops_setup
+ LDAP_BASE_DN = "dc=example,dc=com"
+ INTERACTIVE_TIMEOUT = 4
+ 
+-PASSWD_USER = dict(name='passwduser', passwd='x', uid=100000, gid=2000,
+-                   gecos='User for tests',
+-                   dir='/home/passwduser',
+-                   shell='/bin/bash')
+-
+-PASSWD_GROUP = dict(name='passwdgroup',
+-                    gid=200000,
+-                    mem=['passwduser'])
+-
+ 
+ @pytest.fixture(scope="module")
+ def ds_inst(request):
+@@ -1860,14 +1851,32 @@ def test_rename_incomplete_group_rdn_changed(ldap_conn, rename_setup_cleanup):
+ 
+ 
+ @pytest.fixture
+-def user_and_group_rfc2307_lcl(passwd_ops_setup, group_ops_setup,
+-                               user_and_group_rfc2307):
+-    pwd_ops = passwd_ops_setup
+-    pwd_ops.useradd(**PASSWD_USER)
+-    grp_ops = group_ops_setup
+-    grp_ops.groupadd(**PASSWD_GROUP)
++def find_local_user_and_group():
++    f = open("/etc/passwd")
++    for line in f:
++        passwd_user = line.split(':')
++        passwd_user[2] = int(passwd_user[2])
++        if passwd_user[2] != 0:
++            break
++    f.close()
++    assert passwd_user[2] != 0
++
++    f = open("/etc/group")
++    for line in f:
++        passwd_group = line.split(':')
++        passwd_group[2] = int(passwd_group[2])
++        if passwd_group[2] != 0:
++            break
++    f.close()
++    assert passwd_group[2] != 0
++
++    return (passwd_user, passwd_group)
+ 
+-    return user_and_group_rfc2307
++
++@pytest.fixture
++def user_and_group_rfc2307_lcl(find_local_user_and_group,
++                               user_and_group_rfc2307):
++    return find_local_user_and_group
+ 
+ 
+ def test_local_negative_timeout_enabled_by_default(ldap_conn,
+@@ -1879,64 +1888,53 @@ def test_local_negative_timeout_enabled_by_default(ldap_conn,
+     # sanity check - try resolving an LDAP user
+     ent.assert_passwd_by_name("user", dict(name="user", uid=1001, gid=2000))
+ 
++    passwd_user, passwd_group = user_and_group_rfc2307_lcl
++
+     # resolve a user who is not in LDAP, but exists locally
+-    res, _ = call_sssd_getpwnam("passwduser")
++    res, _ = call_sssd_getpwnam(passwd_user[0])
+     assert res == NssReturnCode.NOTFOUND
+-    res = pwd.getpwnam("passwduser")
+-    assert res is not None
+     # Do the same by UID
+-    res, _ = call_sssd_getpwuid(100000)
++    res, _ = call_sssd_getpwuid(passwd_user[2])
+     assert res == NssReturnCode.NOTFOUND
+-    res = pwd.getpwuid(100000)
+-    assert res is not None
+ 
+     # Do the same for a group both by name and by ID
+-    res, _ = call_sssd_getgrnam("passwdgroup")
++    res, _ = call_sssd_getgrnam(passwd_group[0])
+     assert res == NssReturnCode.NOTFOUND
+-    res = grp.getgrnam("passwdgroup")
+-    assert res is not None
+-    res, _ = call_sssd_getgrgid(200000)
++    res, _ = call_sssd_getgrgid(passwd_group[2])
+     assert res == NssReturnCode.NOTFOUND
+-    res = grp.getgrgid(200000)
+-    assert res is not None
+ 
+     # add the user and the group to LDAP
+     ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
+-    ent_list.add_user("passwduser", 100000, 2000)
+-    ent_list.add_group("passwdgroup", 200000)
++    ent_list.add_user(passwd_user[0], passwd_user[2], 2000)
++    ent_list.add_group(passwd_group[0], passwd_group[2])
+     create_ldap_entries(ldap_conn, ent_list)
+ 
+-    # Make sure the negative cache expired
++    # Make sure the negative cache would expire if global timeout was used
+     time.sleep(2)
+ 
+     # The user is now negatively cached and can't be resolved by either
+     # name or UID
+-    res, _ = call_sssd_getpwnam("passwduser")
++    res, _ = call_sssd_getpwnam(passwd_group[0])
+     assert res == NssReturnCode.NOTFOUND
+-    res, _ = call_sssd_getpwuid(100000)
++    res, _ = call_sssd_getpwuid(passwd_group[2])
+     assert res == NssReturnCode.NOTFOUND
+ 
+-    res, _ = call_sssd_getgrnam("passwdgroup")
++    res, _ = call_sssd_getgrnam(passwd_group[0])
+     assert res == NssReturnCode.NOTFOUND
+-    res, _ = call_sssd_getgrgid(200000)
++    res, _ = call_sssd_getgrgid(passwd_group[2])
+     assert res == NssReturnCode.NOTFOUND
+ 
+     cleanup_ldap_entries(ldap_conn, ent_list)
+ 
+ 
+ @pytest.fixture
+-def usr_and_grp_rfc2307_no_local_ncache(request, passwd_ops_setup,
+-                                        group_ops_setup, ldap_conn):
++def usr_and_grp_rfc2307_no_local_ncache(request, find_local_user_and_group,
++                                        ldap_conn):
+     """
+     Create an RFC2307 directory fixture with interactive SSSD conf,
+     one user and one group but with the local negative timeout
+     disabled
+     """
+-    pwd_ops = passwd_ops_setup
+-    pwd_ops.useradd(**PASSWD_USER)
+-    grp_ops = group_ops_setup
+-    grp_ops.groupadd(**PASSWD_GROUP)
+-
+     ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
+     ent_list.add_user("user", 1001, 2000)
+     ent_list.add_group("group", 2001)
+@@ -1948,7 +1946,7 @@ def usr_and_grp_rfc2307_no_local_ncache(request, passwd_ops_setup,
+         """)
+     create_conf_fixture(request, conf)
+     create_sssd_fixture(request)
+-    return None
++    return find_local_user_and_group
+ 
+ 
+ def test_local_negative_timeout_disabled(ldap_conn,
+@@ -1960,46 +1958,40 @@ def test_local_negative_timeout_disabled(ldap_conn,
+     # sanity check - try resolving an LDAP user
+     ent.assert_passwd_by_name("user", dict(name="user", uid=1001, gid=2000))
+ 
++    passwd_user, passwd_group = usr_and_grp_rfc2307_no_local_ncache
++
+     # resolve a user who is not in LDAP, but exists locally
+-    res, _ = call_sssd_getpwnam("passwduser")
++    res, _ = call_sssd_getpwnam(passwd_user[0])
+     assert res == NssReturnCode.NOTFOUND
+-    res = pwd.getpwnam("passwduser")
+-    assert res is not None
+     # Do the same by UID
+-    res, _ = call_sssd_getpwuid(100000)
++    res, _ = call_sssd_getpwuid(passwd_user[2])
+     assert res == NssReturnCode.NOTFOUND
+-    res = pwd.getpwuid(100000)
+-    assert res is not None
+ 
+     # Do the same for a group both by name and by ID
+-    res, _ = call_sssd_getgrnam("passwdgroup")
++    res, _ = call_sssd_getgrnam(passwd_group[0])
+     assert res == NssReturnCode.NOTFOUND
+-    res = grp.getgrnam("passwdgroup")
+-    assert res is not None
+-    res, _ = call_sssd_getgrgid(200000)
++    res, _ = call_sssd_getgrgid(passwd_group[2])
+     assert res == NssReturnCode.NOTFOUND
+-    res = grp.getgrgid(200000)
+-    assert res is not None
+ 
+     # add the user and the group to LDAP
+     ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
+-    ent_list.add_user("passwduser", 100000, 2000)
+-    ent_list.add_group("passwdgroup", 200000)
++    ent_list.add_user(passwd_user[0], passwd_user[2], 2000)
++    ent_list.add_group(passwd_group[0], passwd_group[2])
+     create_ldap_entries(ldap_conn, ent_list)
+ 
+     # Make sure the negative cache expired
+     time.sleep(2)
+ 
+     # The user can now be resolved
+-    res, _ = call_sssd_getpwnam("passwduser")
++    res, _ = call_sssd_getpwnam(passwd_user[0])
+     assert res == NssReturnCode.SUCCESS
+     # Do the same by UID
+-    res, _ = call_sssd_getpwuid(100000)
++    res, _ = call_sssd_getpwuid(passwd_user[2])
+     assert res == NssReturnCode.SUCCESS
+ 
+-    res, _ = call_sssd_getgrnam("passwdgroup")
++    res, _ = call_sssd_getgrnam(passwd_group[0])
+     assert res == NssReturnCode.SUCCESS
+-    res, _ = call_sssd_getgrgid(200000)
++    res, _ = call_sssd_getgrgid(passwd_group[2])
+     assert res == NssReturnCode.SUCCESS
+ 
+     cleanup_ldap_entries(ldap_conn, ent_list)
+-- 
+2.19.1
+
diff --git a/SOURCES/0013-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch b/SOURCES/0013-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch
deleted file mode 100644
index a9da871..0000000
--- a/SOURCES/0013-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch
+++ /dev/null
@@ -1,213 +0,0 @@
-From ef28a3bdc50d0da6fab86b0d27e4c548ac61a749 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 28 May 2018 21:49:41 +0200
-Subject: [PATCH] TESTS: Add a helper binary that can trigger the SIGPIPE to
- authorizedkeys
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Adds a test tool that simulates the behaviour of OpenSSH in the sense
-that it starts to read the output from the sss_ssh_authorizedkeys tool,
-but then closes the pipe before reading the whole output.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3747
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 909c16edb26a3c48b10a49e7919a35d13d31c52e)
----
- Makefile.am                 |  15 +++-
- src/tests/test_ssh_client.c | 133 ++++++++++++++++++++++++++++++++++++
- 2 files changed, 147 insertions(+), 1 deletion(-)
- create mode 100644 src/tests/test_ssh_client.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 9055130ed74057987795285c243ff47584cf8316..99974cf0e94e1ec6086a53585042653ec5966c2c 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -331,6 +331,7 @@ endif   # HAVE_CMOCKA
- check_PROGRAMS = \
-     stress-tests \
-     krb5-child-test \
-+    test_ssh_client \
-     $(non_interactive_cmocka_based_tests) \
-     $(non_interactive_check_based_tests)
- 
-@@ -2291,6 +2292,18 @@ krb5_child_test_LDADD = \
-     $(SSSD_INTERNAL_LTLIBS) \
-     libsss_test_common.la
- 
-+test_ssh_client_SOURCES = \
-+    src/tests/test_ssh_client.c \
-+    $(NULL)
-+test_ssh_client_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    -DSSH_CLIENT_DIR=\"$(abs_top_builddir)\" \
-+    $(NULL)
-+test_ssh_client_LDADD = \
-+    $(SSSD_INTERNAL_LTLIBS) \
-+    $(SSSD_LIBS) \
-+    $(NULL)
-+
- if BUILD_DBUS_TESTS
- 
- sbus_tests_SOURCES = \
-@@ -3446,7 +3459,6 @@ test_iobuf_LDADD = \
-     $(SSSD_LIBS) \
-     $(NULL)
- 
--
- EXTRA_simple_access_tests_DEPENDENCIES = \
-     $(ldblib_LTLIBRARIES)
- simple_access_tests_SOURCES = \
-@@ -3655,6 +3667,7 @@ intgcheck-prepare:
- 	    $(INTGCHECK_CONFIGURE_FLAGS) \
- 	    CFLAGS="-O2 -g $$CFLAGS -DKCM_PEER_UID=$$(id -u)"; \
- 	$(MAKE) $(AM_MAKEFLAGS) ; \
-+	$(MAKE) $(AM_MAKEFLAGS) test_ssh_client; \
- 	: Force single-thread install to workaround concurrency issues; \
- 	$(MAKE) $(AM_MAKEFLAGS) -j1 install; \
- 	: Remove .la files from LDB module directory to avoid loader warnings; \
-diff --git a/src/tests/test_ssh_client.c b/src/tests/test_ssh_client.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..8f963941f3249561178436d6f6dfc376780a4cda
---- /dev/null
-+++ b/src/tests/test_ssh_client.c
-@@ -0,0 +1,133 @@
-+/*
-+    Copyright (C) 2018 Red Hat
-+
-+    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 <popt.h>
-+#include <sys/wait.h>
-+#include "util/util.h"
-+
-+#ifdef SSH_CLIENT_DIR
-+#define SSH_AK_CLIENT_PATH SSH_CLIENT_DIR"/sss_ssh_authorizedkeys"
-+#else
-+#error "The path to the ssh authorizedkeys helper is not defined"
-+#endif /* SSH_CLIENT_DIR */
-+
-+int main(int argc, const char *argv[])
-+{
-+    poptContext pc;
-+    int opt;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+    struct stat sb;
-+    int ret;
-+    int status;
-+    int p[2];
-+    pid_t pid;
-+    const char *pc_user = NULL;
-+    char *av[3];
-+    char buf[5]; /* Ridiculously small buffer by design */
-+
-+    /* Set debug level to invalid value so we can decide if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    poptSetOtherOptionHelp(pc, "USER");
-+    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 3;
-+        }
-+    }
-+
-+    pc_user = poptGetArg(pc);
-+    if (pc_user == NULL) {
-+        fprintf(stderr, "No user specified\n");
-+        return 3;
-+    }
-+
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    ret = stat(SSH_AK_CLIENT_PATH, &sb);
-+    if (ret != 0) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Could not stat %s [%d]: %s\n",
-+              SSH_AK_CLIENT_PATH, ret, strerror(ret));
-+        return 3;
-+    }
-+
-+    ret = pipe(p);
-+    if (ret != 0) {
-+        perror("pipe");
-+        return 3;
-+    }
-+
-+    switch (pid = fork()) {
-+    case -1:
-+        ret = errno;
-+        close(p[0]);
-+        close(p[1]);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "fork failed: %d\n", ret);
-+        return 3;
-+    case 0:
-+        /* child */
-+        av[0] = discard_const(SSH_AK_CLIENT_PATH);
-+        av[1] = discard_const(pc_user);
-+        av[2] = NULL;
-+
-+        close(p[0]);
-+        ret = dup2(p[1], STDOUT_FILENO);
-+        if (ret == -1) {
-+            perror("dup2");
-+            return 3;
-+        }
-+
-+        execv(av[0], av);
-+        return 3;
-+    default:
-+        /* parent */
-+        break;
-+    }
-+
-+    close(p[1]);
-+    read(p[0], buf, sizeof(buf));
-+    close(p[0]);
-+
-+    pid = waitpid(pid, &status, 0);
-+    if (pid == -1) {
-+        perror("waitpid");
-+        return 3;
-+    }
-+
-+    if (WIFEXITED(status)) {
-+        printf("sss_ssh_authorizedkeys exited with return code %d\n", WEXITSTATUS(status));
-+        return 0;
-+    } else if (WIFSIGNALED(status)) {
-+        printf("sss_ssh_authorizedkeys exited with signal %d\n", WTERMSIG(status));
-+        return 1;
-+    }
-+
-+    printf("sss_ssh_authorizedkeys exited for another reason\n");
-+    return 2;
-+}
--- 
-2.17.1
-
diff --git a/SOURCES/0013-negcache_files-got-rid-of-large-array-on-stack.patch b/SOURCES/0013-negcache_files-got-rid-of-large-array-on-stack.patch
new file mode 100644
index 0000000..a405d8f
--- /dev/null
+++ b/SOURCES/0013-negcache_files-got-rid-of-large-array-on-stack.patch
@@ -0,0 +1,89 @@
+From 921a949f6aa8170f851483e4d5763b3e8fb5d5c9 Mon Sep 17 00:00:00 2001
+From: Alexey Tikhonov <atikhono@redhat.com>
+Date: Fri, 22 Mar 2019 14:21:00 +0100
+Subject: [PATCH 13/15] negcache_files: got rid of large array on stack
+
+Removed large buffer from function stack.
+It is safe to use single (static) global buffer since:
+1) Responders are single threaded
+2) Code doesn't use content of this buffer anyway
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 8e6656c974ac05bb52607014bb4c30b87f4abd8b)
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/responder/common/negcache_files.c | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/src/responder/common/negcache_files.c b/src/responder/common/negcache_files.c
+index 85a7065a4..f22796a0c 100644
+--- a/src/responder/common/negcache_files.c
++++ b/src/responder/common/negcache_files.c
+@@ -24,12 +24,12 @@
+ #include "responder/common/negcache_files.h"
+ 
+ #define BUFFER_SIZE 16384
++static char s_nss_buffer[BUFFER_SIZE];
+ 
+ bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name)
+ {
+     struct passwd pwd = { 0 };
+     int errnop;
+-    char buffer[BUFFER_SIZE];
+     enum nss_status ret;
+     char *shortname = NULL;
+     int parse_ret;
+@@ -39,7 +39,7 @@ bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name)
+         return false;
+     }
+ 
+-    ret = ops->getpwnam_r(shortname, &pwd, buffer, BUFFER_SIZE, &errnop);
++    ret = ops->getpwnam_r(shortname, &pwd, s_nss_buffer, BUFFER_SIZE, &errnop);
+     talloc_free(shortname);
+     if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC, "User %s is a local user\n", name);
+@@ -53,10 +53,9 @@ bool is_user_local_by_uid(const struct sss_nss_ops *ops, uid_t uid)
+ {
+     struct passwd pwd = { 0 };
+     int errnop;
+-    char buffer[BUFFER_SIZE];
+     enum nss_status ret;
+ 
+-    ret = ops->getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &errnop);
++    ret = ops->getpwuid_r(uid, &pwd, s_nss_buffer, BUFFER_SIZE, &errnop);
+     if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC,
+               "User with UID %"SPRIuid" is a local user\n", uid);
+@@ -70,7 +69,6 @@ bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name)
+ {
+     struct group grp = { 0 };
+     int errnop;
+-    char buffer[BUFFER_SIZE];
+     enum nss_status ret;
+     char *shortname = NULL;
+     int parse_ret;
+@@ -80,7 +78,7 @@ bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name)
+         return false;
+     }
+ 
+-    ret = ops->getgrnam_r(shortname, &grp, buffer, BUFFER_SIZE, &errnop);
++    ret = ops->getgrnam_r(shortname, &grp, s_nss_buffer, BUFFER_SIZE, &errnop);
+     talloc_free(shortname);
+     if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC, "Group %s is a local group\n", name);
+@@ -94,10 +92,9 @@ bool is_group_local_by_gid(const struct sss_nss_ops *ops, uid_t gid)
+ {
+     struct group grp = { 0 };
+     int errnop;
+-    char buffer[BUFFER_SIZE];
+     enum nss_status ret;
+ 
+-    ret = ops->getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &errnop);
++    ret = ops->getgrgid_r(gid, &grp, s_nss_buffer, BUFFER_SIZE, &errnop);
+     if (ret == NSS_STATUS_SUCCESS) {
+         DEBUG(SSSDBG_TRACE_FUNC,
+               "Group with GID %"SPRIgid" is a local group\n", gid);
+-- 
+2.19.1
+
diff --git a/SOURCES/0014-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch b/SOURCES/0014-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch
deleted file mode 100644
index ccb7133..0000000
--- a/SOURCES/0014-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From 0adf4f50e9773afda2dc422b04163f19d946c150 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 19 Jun 2018 11:39:02 +0200
-Subject: [PATCH] TESTS: Add a regression test for SIGHUP handling in
- sss_ssh_authorizedkeys
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-A regression test for:
-https://pagure.io/SSSD/sssd/issue/3747
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 4cc3c1a1b1070c12bcc4351880d8207e47b37496)
----
- src/tests/intg/test_ssh_pubkey.py | 58 +++++++++++++++++++++++++++++++
- 1 file changed, 58 insertions(+)
-
-diff --git a/src/tests/intg/test_ssh_pubkey.py b/src/tests/intg/test_ssh_pubkey.py
-index fbf55566e341373873057ec4e3af1d7f83202aa7..8fb41c62d87ec210c9aad8582023fe1cb00f2b4e 100644
---- a/src/tests/intg/test_ssh_pubkey.py
-+++ b/src/tests/intg/test_ssh_pubkey.py
-@@ -24,6 +24,8 @@ import time
- import ldap
- import ldap.modlist
- import pytest
-+import string
-+import random
- 
- import config
- import ds_openldap
-@@ -230,3 +232,59 @@ def test_ssh_pubkey_retrieve(add_user_with_ssh_key):
- 
-     sshpubkey = get_call_output(["sss_ssh_authorizedkeys", "user2"])
-     assert len(sshpubkey) == 0
-+
-+
-+@pytest.fixture()
-+def sighup_client(request):
-+    test_ssh_cli_path = os.path.join(config.ABS_BUILDDIR,
-+                                     "..", "..", "..", "test_ssh_client")
-+    assert os.access(test_ssh_cli_path, os.X_OK)
-+    return test_ssh_cli_path
-+
-+
-+@pytest.fixture
-+def add_user_with_many_keys(request, ldap_conn):
-+    # Generate a large list of unique ssh pubkeys
-+    pubkey_list = []
-+    while len(pubkey_list) < 50:
-+        new_pubkey = list(USER1_PUBKEY1)
-+        new_pubkey[10] = random.choice(string.ascii_uppercase)
-+        new_pubkey[11] = random.choice(string.ascii_uppercase)
-+        new_pubkey[12] = random.choice(string.ascii_uppercase)
-+        str_new_pubkey = ''.join(c for c in new_pubkey)
-+        if str_new_pubkey in pubkey_list:
-+            continue
-+        pubkey_list.append(str_new_pubkey)
-+
-+    ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
-+    ent_list.add_user("user1", 1001, 2001, sshPubKey=pubkey_list)
-+    create_ldap_fixture(request, ldap_conn, ent_list)
-+
-+    conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS)
-+    create_conf_fixture(request, conf)
-+    create_sssd_fixture(request)
-+    return None
-+
-+
-+def test_ssh_sighup(add_user_with_many_keys, sighup_client):
-+    """
-+    A regression test for https://pagure.io/SSSD/sssd/issue/3747
-+
-+    OpenSSH can close its end of the pipe towards sss_ssh_authorizedkeys
-+    before all of the output is read. In that case, older versions
-+    of sss_ssh_authorizedkeys were receiving a SIGPIPE
-+    """
-+    cli_path = sighup_client
-+
-+    # python actually does the sensible, but unexpected (for a C programmer)
-+    # thing and handles SIGPIPE. In order to reproduce the bug, we need
-+    # to unset the SIGPIPE handler
-+    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-+
-+    process = subprocess.Popen([cli_path, "user1"],
-+                               stdout=subprocess.PIPE,
-+                               stderr=subprocess.PIPE)
-+    _, _ = process.communicate()
-+    # If the test tool detects that sss_ssh_authorizedkeys was killed with a
-+    # signal, it would have returned 1
-+    assert process.returncode == 0
--- 
-2.17.1
-
diff --git a/SOURCES/0014-TESTS-moved-cwrap-test_negcache-to-cmocka-tests.patch b/SOURCES/0014-TESTS-moved-cwrap-test_negcache-to-cmocka-tests.patch
new file mode 100644
index 0000000..92aefef
--- /dev/null
+++ b/SOURCES/0014-TESTS-moved-cwrap-test_negcache-to-cmocka-tests.patch
@@ -0,0 +1,126 @@
+From 861a45d9a866e5a9d87eaad8b8b9734eb6bc59aa Mon Sep 17 00:00:00 2001
+From: Alexey Tikhonov <atikhono@redhat.com>
+Date: Fri, 22 Mar 2019 16:33:14 +0100
+Subject: [PATCH 14/15] TESTS: moved cwrap/test_negcache to cmocka tests
+
+Moved cwrap/test_negcache.c to cmocka tests since it doesn't use
+cwrap tools anymore.
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 137b684d0a01afa02618b07ba46a44dad017b5b9)
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                                   | 19 +++++++++
+ .../test_negcache_2.c}                        |  0
+ src/tests/cwrap/Makefile.am                   | 40 -------------------
+ 3 files changed, 19 insertions(+), 40 deletions(-)
+ rename src/tests/{cwrap/test_negcache.c => cmocka/test_negcache_2.c} (100%)
+
+diff --git a/Makefile.am b/Makefile.am
+index 6a67dc7b1..d09f50aa2 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -239,6 +239,7 @@ if HAVE_CMOCKA
+         test-find-uid \
+         test-io \
+         test-negcache \
++        negcache_2-tests \
+         test-authtok \
+         sss_nss_idmap-tests \
+         deskprofile_utils-tests \
+@@ -2603,6 +2604,24 @@ test_negcache_LDADD = \
+     libsss_test_common.la \
+     libsss_idmap.la
+ 
++negcache_2_tests_SOURCES =\
++    $(SSSD_RESPONDER_OBJ) \
++    src/tests/cmocka/test_negcache_2.c \
++    $(NULL)
++negcache_2_tests_CFLAGS = \
++    $(AM_CFLAGS) \
++    -DBASE_FILE_STEM=\"$(*F)\" \
++    $(NULL)
++negcache_2_tests_LDADD = \
++    $(LIBADD_DL) \
++    $(CMOCKA_LIBS) \
++    $(SSSD_LIBS) \
++    $(SYSTEMD_DAEMON_LIBS) \
++    libsss_util.la \
++    libsss_test_common.la \
++    libsss_debug.la \
++    $(NULL)
++
+ test_authtok_SOURCES = \
+     src/tests/cmocka/test_authtok.c \
+     src/util/authtok.c \
+diff --git a/src/tests/cwrap/test_negcache.c b/src/tests/cmocka/test_negcache_2.c
+similarity index 100%
+rename from src/tests/cwrap/test_negcache.c
+rename to src/tests/cmocka/test_negcache_2.c
+diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
+index bfc493395..1edefc678 100644
+--- a/src/tests/cwrap/Makefile.am
++++ b/src/tests/cwrap/Makefile.am
+@@ -73,26 +73,6 @@ SSSD_RESPONDER_IFACE_OBJ = \
+     ../../../src/responder/common/iface/responder_iface_generated.c \
+     $(NULL)
+ 
+-SSSD_RESPONDER_OBJ = \
+-    ../../../src/responder/common/negcache_files.c \
+-    ../../../src/util/nss_dl_load.c \
+-    ../../../src/responder/common/negcache.c \
+-    ../../../src/responder/common/responder_cmd.c \
+-    ../../../src/responder/common/responder_common.c \
+-    ../../../src/responder/common/responder_dp.c \
+-    ../../../src/responder/common/responder_dp_ssh.c \
+-    ../../../src/responder/common/responder_packet.c \
+-    ../../../src/responder/common/responder_get_domains.c \
+-    ../../../src/responder/common/responder_utils.c \
+-    ../../../src/responder/common/data_provider/rdp_message.c \
+-    ../../../src/responder/common/data_provider/rdp_client.c \
+-    ../../../src/monitor/monitor_iface_generated.c \
+-    ../../../src/providers/data_provider_req.c \
+-    ../../../src/util/session_recording.c \
+-    $(SSSD_RESPONDER_IFACE_OBJ) \
+-    $(SSSD_CACHE_REQ_OBJ) \
+-    $(NULL)
+-
+ dist_noinst_DATA = \
+     group \
+     passwd \
+@@ -107,7 +87,6 @@ check_PROGRAMS += \
+     server-tests \
+     usertools-tests \
+     responder_common-tests \
+-    negcache-tests \
+     $(NULL)
+ endif # HAVE_UID_WRAPPER
+ endif # HAVE_NSS_WRAPPER
+@@ -201,23 +180,4 @@ responder_common_tests_LDADD = \
+     $(abs_top_builddir)/libsss_test_common.la \
+     $(NULL)
+ 
+-negcache_tests_SOURCES =\
+-    $(SSSD_RESPONDER_OBJ) \
+-    test_negcache.c \
+-    $(NULL)
+-negcache_tests_CFLAGS = \
+-    $(AM_CFLAGS) \
+-    -DBASE_FILE_STEM=\"$(*F)\" \
+-    $(NULL)
+-negcache_tests_LDADD = \
+-    $(LIBADD_DL) \
+-    $(CMOCKA_LIBS) \
+-    $(SSSD_LIBS) \
+-    $(SELINUX_LIBS) \
+-    $(SYSTEMD_DAEMON_LIBS) \
+-    $(abs_top_builddir)/libsss_util.la \
+-    $(abs_top_builddir)/libsss_debug.la \
+-    $(abs_top_builddir)/libsss_test_common.la \
+-    $(NULL)
+-
+ tests: $(check_PROGRAMS)
+-- 
+2.19.1
+
diff --git a/SOURCES/0015-Revert-LDAP-IPA-add-local-email-address-to-aliases.patch b/SOURCES/0015-Revert-LDAP-IPA-add-local-email-address-to-aliases.patch
deleted file mode 100644
index fb6b1da..0000000
--- a/SOURCES/0015-Revert-LDAP-IPA-add-local-email-address-to-aliases.patch
+++ /dev/null
@@ -1,141 +0,0 @@
-From 9efaade255e59b4a2f5cff2ab78c1db61132a40a Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 21 Jun 2018 12:27:32 +0200
-Subject: [PATCH] Revert "LDAP/IPA: add local email address to aliases"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This reverts commit 9a310913d696d190db14c625080678db853a33fd.
-
-Storing the e-mail address as a nameAlias was a performance optimization
-to avoid having to fall back to the UPN lookup, but had the disadvantage
-of returning multiple results for cases where an e-mail address is the
-same as a user's fully qualified name.
-
-Since the e-mail lookups would still work without this optimization,
-just after one more lookup, let's revert the patch.
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3607
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit b0ec3875da281a9c29eda2cb19c1026510866d5b)
-
-DOWNSTREAM:
-Resolves: rhbz#1527662 - Handle conflicting e-mail addresses more gracefully
----
- src/providers/ipa/ipa_s2n_exop.c | 49 --------------------------------
- src/providers/ldap/sdap_utils.c  | 22 --------------
- 2 files changed, 71 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 9cb735526293ff5a209d732366b86fdb95dc8679..6f3974637a08b9d70e32fb6d79724be4f6e8dbde 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -2118,49 +2118,6 @@ done:
-     return ret;
- }
- 
--static errno_t add_emails_to_aliases(struct sysdb_attrs *attrs,
--                                     struct sss_domain_info *dom)
--{
--    int ret;
--    const char **emails;
--    size_t c;
--    TALLOC_CTX *tmp_ctx;
--
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
--        return ENOMEM;
--    }
--
--    ret = sysdb_attrs_get_string_array(attrs, SYSDB_USER_EMAIL, tmp_ctx,
--                                       &emails);
--    if (ret == EOK) {
--        for (c = 0; emails[c] != NULL; c++) {
--            if (is_email_from_domain(emails[c], dom)) {
--                ret = sysdb_attrs_add_lc_name_alias_safe(attrs, emails[c]);
--                if (ret != EOK) {
--                    DEBUG(SSSDBG_OP_FAILURE,
--                          "Failed to add lower-cased version of email [%s] "
--                          "into the alias list\n", emails[c]);
--                    goto done;
--                }
--            }
--        }
--    } else if (ret == ENOENT) {
--        DEBUG(SSSDBG_TRACE_ALL, "No email addresses available.\n");
--    } else {
--        DEBUG(SSSDBG_OP_FAILURE,
--              "sysdb_attrs_get_string_array failed, skipping ...\n");
--    }
--
--    ret = EOK;
--
--done:
--    talloc_free(tmp_ctx);
--
--    return ret;
--}
--
- static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                                     struct req_input *req_input,
-                                     struct resp_attrs *attrs,
-@@ -2314,12 +2271,6 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                 goto done;
-             }
- 
--            ret = add_emails_to_aliases(attrs->sysdb_attrs, dom);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE,
--                      "add_emails_to_aliases failed, skipping ...\n");
--            }
--
-             if (upn == NULL) {
-                 /* We also have to store a fake UPN here, because otherwise the
-                  * krb5 child later won't be able to properly construct one as
-diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c
-index 0ac3ab2e416d887d00480b5123859c611f514274..6d543101f06ce3cd3925a675af6cabdacb8ebcaa 100644
---- a/src/providers/ldap/sdap_utils.c
-+++ b/src/providers/ldap/sdap_utils.c
-@@ -87,7 +87,6 @@ sdap_save_all_names(const char *name,
-     int i;
-     bool lowercase = !dom->case_sensitive;
-     bool store_as_fqdn;
--    const char **emails;
- 
-     switch (entry_type) {
-     case SYSDB_MEMBER_USER:
-@@ -144,27 +143,6 @@ sdap_save_all_names(const char *name,
- 
-     }
- 
--    ret = sysdb_attrs_get_string_array(ldap_attrs, SYSDB_USER_EMAIL, tmp_ctx,
--                                       &emails);
--    if (ret == EOK) {
--        for (i = 0; emails[i] != NULL; i++) {
--            if (is_email_from_domain(emails[i], dom)) {
--                ret = sysdb_attrs_add_lc_name_alias_safe(attrs, emails[i]);
--                if (ret) {
--                    DEBUG(SSSDBG_OP_FAILURE,
--                          "Failed to add lower-cased version of email [%s] "
--                          "into the alias list\n", emails[i]);
--                    goto done;
--                }
--            }
--        }
--    } else if (ret == ENOENT) {
--        DEBUG(SSSDBG_TRACE_ALL, "No email addresses available.\n");
--    } else {
--        DEBUG(SSSDBG_OP_FAILURE,
--              "sysdb_attrs_get_string_array failed, skipping ...\n");
--    }
--
-     ret = EOK;
- done:
-     talloc_free(tmp_ctx);
--- 
-2.17.1
-
diff --git a/SOURCES/0015-ci-sssd.supp-getpwuid-leak-suppression.patch b/SOURCES/0015-ci-sssd.supp-getpwuid-leak-suppression.patch
new file mode 100644
index 0000000..d8ac895
--- /dev/null
+++ b/SOURCES/0015-ci-sssd.supp-getpwuid-leak-suppression.patch
@@ -0,0 +1,50 @@
+From 2dbfa995e592329470f57f456a054f845a9a3da3 Mon Sep 17 00:00:00 2001
+From: Alexey Tikhonov <atikhono@redhat.com>
+Date: Mon, 1 Apr 2019 16:44:26 +0200
+Subject: [PATCH 15/15] ci/sssd.supp: getpwuid() leak suppression
+
+Supresses following error:
+ 4,096 bytes in 1 blocks are definitely lost in loss record 67 of 83
+    at 0x4C2CDCB: malloc (vg_replace_malloc.c:299)
+    by 0xB8F8627: ???
+    by 0xB91EF3F: ???
+    by 0xB90E112: ???
+    by 0x9992974: getpwuid_r@@GLIBC_2.2.5 (in /usr/lib64/libc-2.26.so)
+    by 0x99920D7: getpwuid (in /usr/lib64/libc-2.26.so)
+
+This https://sourceware.org/bugzilla/show_bug.cgi?id=2314#c8 might
+be related.
+
+This problem seems to be afecting Fedora < F28
+
+(cherry picked from commit 9eb8b784d4365b846f1a620f11632099d10de2c8)
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ contrib/ci/sssd.supp | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/contrib/ci/sssd.supp b/contrib/ci/sssd.supp
+index 4303eed22..0bef4fa90 100644
+--- a/contrib/ci/sssd.supp
++++ b/contrib/ci/sssd.supp
+@@ -221,3 +221,16 @@
+    fun:set_default_locale
+    fun:main
+ }
++
++# glibc nsswitch (getpwuid) leak
++# Seems to be affecting Fedora < F28
++{
++   glibc-nss-getpwuid
++   Memcheck:Leak
++   fun:malloc
++   ...
++   fun:getpwuid_r@@GLIBC_2.2.5
++   fun:getpwuid
++   ...
++   fun:main
++}
+-- 
+2.19.1
+
diff --git a/SOURCES/0016-pam-introduce-prompt_config-struct.patch b/SOURCES/0016-pam-introduce-prompt_config-struct.patch
new file mode 100644
index 0000000..5623b8b
--- /dev/null
+++ b/SOURCES/0016-pam-introduce-prompt_config-struct.patch
@@ -0,0 +1,881 @@
+From a5e15f1e5af7d7c41717c18566ea0f2a01c086ec Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 27 Mar 2019 09:02:27 +0100
+Subject: [PATCH 16/21] pam: introduce prompt_config struct
+
+prompt_config is the internal struct to control the prompting of
+pam_sss. To make it easy to change internal details when more options
+are added it should be opaque and only accessed by getters and setter.
+
+Related to https://pagure.io/SSSD/sssd/issue/3264
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit fa8ef7c6db19a160d807f05b08bbc66c0c25ebfe)
+---
+ Makefile.am                            |  17 +
+ src/sss_client/pam_sss_prompt_config.c | 547 +++++++++++++++++++++++++
+ src/sss_client/sss_cli.h               |  29 ++
+ src/tests/cmocka/test_prompt_config.c  | 215 ++++++++++
+ 4 files changed, 808 insertions(+)
+ create mode 100644 src/sss_client/pam_sss_prompt_config.c
+ create mode 100644 src/tests/cmocka/test_prompt_config.c
+
+diff --git a/Makefile.am b/Makefile.am
+index d09f50aa2..f7f55e96a 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -241,6 +241,7 @@ if HAVE_CMOCKA
+         test-negcache \
+         negcache_2-tests \
+         test-authtok \
++        test_prompt_config \
+         sss_nss_idmap-tests \
+         deskprofile_utils-tests \
+         dyndns-tests \
+@@ -2644,6 +2645,21 @@ test_authtok_LDADD = \
+     libsss_debug.la \
+     $(NULL)
+ 
++test_prompt_config_SOURCES = \
++    src/tests/cmocka/test_prompt_config.c \
++    src/sss_client/pam_sss_prompt_config.c \
++    $(NULL)
++test_prompt_config_CFLAGS = \
++    $(AM_CFLAGS) \
++    $(POPT_CFLAGS) \
++    $(NULL)
++test_prompt_config_LDADD = \
++    $(CMOCKA_LIBS) \
++    $(POPT_LIBS) \
++    libsss_debug.la \
++    $(TALLOC_LIBS) \
++    $(NULL)
++
+ sss_nss_idmap_tests_SOURCES = \
+     src/tests/cmocka/sss_nss_idmap-tests.c
+ sss_nss_idmap_tests_CFLAGS = \
+@@ -3820,6 +3836,7 @@ endif
+ pamlib_LTLIBRARIES = pam_sss.la
+ pam_sss_la_SOURCES = \
+     src/sss_client/pam_sss.c \
++    src/sss_client/pam_sss_prompt_config.c \
+     src/sss_client/pam_message.c \
+     src/sss_client/common.c \
+     src/sss_client/sss_cli.h \
+diff --git a/src/sss_client/pam_sss_prompt_config.c b/src/sss_client/pam_sss_prompt_config.c
+new file mode 100644
+index 000000000..35094b406
+--- /dev/null
++++ b/src/sss_client/pam_sss_prompt_config.c
+@@ -0,0 +1,547 @@
++/*
++    Authors:
++        Sumit Bose <sbose@redhat.com>
++
++    Copyright (C) 2019 Red Hat
++
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
++
++    You should have received a copy of the GNU Lesser General Public License
++    along with this program.  If not, see <http://www.gnu.org/licenses/>.
++*/
++
++#include "config.h"
++#include <stdlib.h>
++#include <errno.h>
++
++#include "sss_cli.h"
++
++#include <libintl.h>
++#define _(STRING) dgettext (PACKAGE, STRING)
++
++struct prompt_config_password {
++    char *prompt;
++};
++
++struct prompt_config_2fa {
++    char *prompt_1st;
++    char *prompt_2nd;
++};
++
++struct prompt_config_2fa_single {
++    char *prompt;
++};
++
++struct prompt_config_sc_pin {
++    char *prompt; /* Currently not used */
++};
++
++struct prompt_config {
++    enum prompt_config_type type;
++    union {
++        struct prompt_config_password password;
++        struct prompt_config_2fa two_fa;
++        struct prompt_config_2fa_single two_fa_single;
++        struct prompt_config_sc_pin sc_pin;
++    } data;
++};
++
++enum prompt_config_type pc_get_type(struct prompt_config *pc)
++{
++    if (pc != NULL && pc->type > PC_TYPE_INVALID && pc->type < PC_TYPE_LAST) {
++        return pc->type;
++    }
++    return PC_TYPE_INVALID;
++}
++
++const char *pc_get_password_prompt(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_PASSWORD) {
++        return pc->data.password.prompt;
++    }
++    return NULL;
++}
++
++const char *pc_get_2fa_1st_prompt(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_2FA) {
++        return pc->data.two_fa.prompt_1st;
++    }
++    return NULL;
++}
++
++const char *pc_get_2fa_2nd_prompt(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_2FA) {
++        return pc->data.two_fa.prompt_2nd;
++    }
++    return NULL;
++}
++
++const char *pc_get_2fa_single_prompt(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_2FA_SINGLE) {
++        return pc->data.two_fa_single.prompt;
++    }
++    return NULL;
++}
++
++static void pc_free_password(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_PASSWORD) {
++        free(pc->data.password.prompt);
++    }
++    return;
++}
++
++static void pc_free_2fa(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_2FA) {
++        free(pc->data.two_fa.prompt_1st);
++        free(pc->data.two_fa.prompt_2nd);
++    }
++    return;
++}
++
++static void pc_free_2fa_single(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_2FA_SINGLE) {
++        free(pc->data.two_fa_single.prompt);
++    }
++    return;
++}
++
++static void pc_free_sc_pin(struct prompt_config *pc)
++{
++    if (pc != NULL && pc_get_type(pc) == PC_TYPE_SC_PIN) {
++        free(pc->data.sc_pin.prompt);
++    }
++    return;
++}
++
++void pc_list_free(struct prompt_config **pc_list)
++{
++    size_t c;
++
++    if (pc_list == NULL) {
++        return;
++    }
++
++    for (c = 0; pc_list[c] != NULL; c++) {
++        switch (pc_list[c]->type) {
++        case PC_TYPE_PASSWORD:
++            pc_free_password(pc_list[c]);
++            break;
++        case PC_TYPE_2FA:
++            pc_free_2fa(pc_list[c]);
++            break;
++        case PC_TYPE_2FA_SINGLE:
++            pc_free_2fa_single(pc_list[c]);
++            break;
++        case PC_TYPE_SC_PIN:
++            pc_free_sc_pin(pc_list[c]);
++            break;
++        default:
++            return;
++        }
++        free(pc_list[c]);
++    }
++    free(pc_list);
++}
++
++static errno_t pc_list_add_pc(struct prompt_config ***pc_list,
++                              struct prompt_config *pc)
++{
++    size_t c = 0;
++    struct prompt_config **pcl;
++
++    for (c = 0; *pc_list != NULL && (*pc_list)[c] != NULL; c++); /* just counting */
++
++    pcl = realloc(*pc_list, (c + 2) * sizeof(struct prompt_config *));
++    if (pcl == NULL) {
++        return ENOMEM;
++    }
++    pcl[c] = pc;
++    pcl[c + 1] = NULL;
++
++    *pc_list = pcl;
++
++    return EOK;
++}
++
++#define DEFAULT_PASSWORD_PROMPT _("Password: ")
++#define DEFAULT_2FA_SINGLE_PROMPT _("Password + Token value: ")
++#define DEFAULT_2FA_PROMPT_1ST _("First Factor: ")
++#define DEFAULT_2FA_PROMPT_2ND _("Second Factor: ")
++
++errno_t pc_list_add_password(struct prompt_config ***pc_list,
++                             const char *prompt)
++{
++    struct prompt_config *pc;
++    int ret;
++
++    if (pc_list == NULL) {
++        return EINVAL;
++    }
++
++    pc = calloc(1, sizeof(struct prompt_config));
++    if (pc == NULL) {
++        return ENOMEM;
++    }
++
++    pc->type = PC_TYPE_PASSWORD;
++    pc->data.password.prompt = strdup(prompt != NULL ? prompt
++                                                     : DEFAULT_PASSWORD_PROMPT);
++    if (pc->data.password.prompt == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = pc_list_add_pc(pc_list, pc);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        free(pc->data.password.prompt);
++        free(pc);
++    }
++
++    return ret;
++}
++
++errno_t pc_list_add_2fa(struct prompt_config ***pc_list,
++                        const char *prompt_1st, const char *prompt_2nd)
++{
++    struct prompt_config *pc;
++    int ret;
++
++    if (pc_list == NULL) {
++        return EINVAL;
++    }
++
++    pc = calloc(1, sizeof(struct prompt_config));
++    if (pc == NULL) {
++        return ENOMEM;
++    }
++
++    pc->type = PC_TYPE_2FA;
++    pc->data.two_fa.prompt_1st = strdup(prompt_1st != NULL ? prompt_1st
++                                                   : DEFAULT_2FA_PROMPT_1ST);
++    if (pc->data.two_fa.prompt_1st == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++    pc->data.two_fa.prompt_2nd = strdup(prompt_2nd != NULL ? prompt_2nd
++                                                   : DEFAULT_2FA_PROMPT_2ND);
++    if (pc->data.two_fa.prompt_2nd == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = pc_list_add_pc(pc_list, pc);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        free(pc->data.two_fa.prompt_1st);
++        free(pc->data.two_fa.prompt_2nd);
++        free(pc);
++    }
++
++    return ret;
++}
++
++errno_t pc_list_add_2fa_single(struct prompt_config ***pc_list,
++                               const char *prompt)
++{
++    struct prompt_config *pc;
++    int ret;
++
++    if (pc_list == NULL) {
++        return EINVAL;
++    }
++
++    pc = calloc(1, sizeof(struct prompt_config));
++    if (pc == NULL) {
++        return ENOMEM;
++    }
++
++    pc->type = PC_TYPE_2FA_SINGLE;
++    pc->data.two_fa_single.prompt = strdup(prompt != NULL ? prompt
++                                                   : DEFAULT_2FA_SINGLE_PROMPT);
++    if (pc->data.two_fa_single.prompt == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = pc_list_add_pc(pc_list, pc);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        free(pc->data.two_fa_single.prompt);
++        free(pc);
++    }
++
++    return ret;
++}
++
++errno_t pam_get_response_prompt_config(struct prompt_config **pc_list, int *len,
++                                       uint8_t **data)
++{
++    size_t c;
++    size_t l = 0;
++    uint8_t *d = NULL;
++    uint32_t uint32_val;
++    size_t rp;
++
++    if (pc_list == NULL || *pc_list == NULL) {
++        return ENOENT;
++    }
++
++    l += sizeof(uint32_t);
++    for (c = 0; pc_list[c] != NULL; c++) {
++        l += sizeof(uint32_t);
++        switch (pc_list[c]->type) {
++        case PC_TYPE_PASSWORD:
++            l += sizeof(uint32_t);
++            l += strlen(pc_list[c]->data.password.prompt);
++            break;
++        case PC_TYPE_2FA:
++            l += sizeof(uint32_t);
++            l += strlen(pc_list[c]->data.two_fa.prompt_1st);
++            l += sizeof(uint32_t);
++            l += strlen(pc_list[c]->data.two_fa.prompt_2nd);
++            break;
++        case PC_TYPE_2FA_SINGLE:
++            l += sizeof(uint32_t);
++            l += strlen(pc_list[c]->data.two_fa_single.prompt);
++            break;
++        case PC_TYPE_SC_PIN:
++            break;
++        default:
++            return EINVAL;
++        }
++    }
++
++    d = malloc(l * sizeof(uint8_t));
++    if (d == NULL) {
++        return ENOMEM;
++    }
++
++    rp = 0;
++    uint32_val = c;
++    SAFEALIGN_COPY_UINT32(&d[rp], &uint32_val, &rp);
++
++    for (c = 0; pc_list[c] != NULL; c++) {
++        uint32_val = pc_list[c]->type;
++        SAFEALIGN_COPY_UINT32(&d[rp], &uint32_val, &rp);
++
++        switch (pc_list[c]->type) {
++        case PC_TYPE_PASSWORD:
++            SAFEALIGN_SET_UINT32(&d[rp],
++                                 strlen(pc_list[c]->data.password.prompt), &rp);
++            safealign_memcpy(&d[rp], pc_list[c]->data.password.prompt,
++                             strlen(pc_list[c]->data.password.prompt), &rp);
++            break;
++        case PC_TYPE_2FA:
++            SAFEALIGN_SET_UINT32(&d[rp],
++                                 strlen(pc_list[c]->data.two_fa.prompt_1st),
++                                 &rp);
++            safealign_memcpy(&d[rp], pc_list[c]->data.two_fa.prompt_1st,
++                             strlen(pc_list[c]->data.two_fa.prompt_1st), &rp);
++            SAFEALIGN_SET_UINT32(&d[rp],
++                                 strlen(pc_list[c]->data.two_fa.prompt_2nd),
++                                 &rp);
++            safealign_memcpy(&d[rp], pc_list[c]->data.two_fa.prompt_2nd,
++                             strlen(pc_list[c]->data.two_fa.prompt_2nd), &rp);
++            break;
++        case PC_TYPE_2FA_SINGLE:
++            SAFEALIGN_SET_UINT32(&d[rp],
++                                 strlen(pc_list[c]->data.two_fa_single.prompt),
++                                 &rp);
++            safealign_memcpy(&d[rp], pc_list[c]->data.two_fa_single.prompt,
++                             strlen(pc_list[c]->data.two_fa_single.prompt),
++                             &rp);
++            break;
++        case PC_TYPE_SC_PIN:
++            break;
++        default:
++            free(d);
++            return EINVAL;
++        }
++    }
++
++    if (rp != l) {
++        free(d);
++        return EFAULT;
++    }
++
++    *data = d;
++    *len = l;
++
++    return EOK;
++}
++
++errno_t pc_list_from_response(int size, uint8_t *buf,
++                              struct prompt_config ***pc_list)
++{
++    int ret;
++    uint32_t count;
++    uint32_t type;
++    uint32_t l;
++    size_t rp;
++    size_t c;
++    struct prompt_config **pl = NULL;
++    char *str;
++    char *str2;
++
++    if (buf == NULL || size < 3 * sizeof(uint32_t)) {
++        return EINVAL;
++    }
++
++    rp = 0;
++    SAFEALIGN_COPY_UINT32_CHECK(&count, buf + rp, size, &rp);
++
++    for (c = 0; c < count; c++) {
++        /* Since we already know size < 3 * sizeof(uint32_t) this check should
++         * be safe and without over- or underflow. */
++        if (rp > size - sizeof(uint32_t)) {
++            ret = EINVAL;
++            goto done;
++        }
++        SAFEALIGN_COPY_UINT32(&type, buf + rp, &rp);
++
++        switch (type) {
++        case PC_TYPE_PASSWORD:
++            if (rp > size - sizeof(uint32_t)) {
++                ret = EINVAL;
++                goto done;
++            }
++            SAFEALIGN_COPY_UINT32(&l, buf + rp, &rp);
++
++            if (l > size || rp > size - l) {
++                ret = EINVAL;
++                goto done;
++            }
++            str = strndup((char *) buf + rp, l);
++            if (str == NULL) {
++                ret = ENOMEM;
++                goto done;
++            }
++            rp += l;
++
++            ret = pc_list_add_password(&pl, str);
++            free(str);
++            if (ret != EOK) {
++                goto done;
++            }
++            break;
++        case PC_TYPE_2FA:
++            if (rp > size - sizeof(uint32_t)) {
++                ret = EINVAL;
++                goto done;
++            }
++            SAFEALIGN_COPY_UINT32(&l, buf + rp, &rp);
++
++            if (l > size || rp > size - l) {
++                ret = EINVAL;
++                goto done;
++            }
++            str = strndup((char *) buf + rp, l);
++            if (str == NULL) {
++                ret = ENOMEM;
++                goto done;
++            }
++            rp += l;
++
++            if (rp > size - sizeof(uint32_t)) {
++                free(str);
++                ret = EINVAL;
++                goto done;
++            }
++            SAFEALIGN_COPY_UINT32(&l, buf + rp, &rp);
++
++            if (l > size || rp > size - l) {
++                free(str);
++                ret = EINVAL;
++                goto done;
++            }
++            str2 = strndup((char *) buf + rp, l);
++            if (str2 == NULL) {
++                free(str);
++                ret = ENOMEM;
++                goto done;
++            }
++            rp += l;
++
++            ret = pc_list_add_2fa(&pl, str, str2);
++            free(str);
++            free(str2);
++            if (ret != EOK) {
++                goto done;
++            }
++            break;
++        case PC_TYPE_2FA_SINGLE:
++            if (rp > size - sizeof(uint32_t)) {
++                ret = EINVAL;
++                goto done;
++            }
++            SAFEALIGN_COPY_UINT32(&l, buf + rp, &rp);
++
++            if (l > size || rp > size - l) {
++                ret = EINVAL;
++                goto done;
++            }
++            str = strndup((char *) buf + rp, l);
++            if (str == NULL) {
++                ret = ENOMEM;
++                goto done;
++            }
++            rp += l;
++
++            ret = pc_list_add_2fa_single(&pl, str);
++            free(str);
++            if (ret != EOK) {
++                goto done;
++            }
++            break;
++        case PC_TYPE_SC_PIN:
++            break;
++        default:
++            ret = EINVAL;
++            goto done;
++        }
++    }
++
++    *pc_list = pl;
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        pc_list_free(pl);
++    }
++
++    return ret;
++}
+diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
+index 24d28ed4b..7e748c281 100644
+--- a/src/sss_client/sss_cli.h
++++ b/src/sss_client/sss_cli.h
+@@ -561,6 +561,35 @@ enum user_info_type {
+  * @}
+  */ /* end of group sss_pam_cli */
+ 
++
++enum prompt_config_type {
++    PC_TYPE_INVALID = 0,
++    PC_TYPE_PASSWORD,
++    PC_TYPE_2FA,
++    PC_TYPE_2FA_SINGLE,
++    PC_TYPE_SC_PIN,
++    PC_TYPE_LAST
++};
++
++struct prompt_config;
++
++enum prompt_config_type pc_get_type(struct prompt_config *pc);
++const char *pc_get_password_prompt(struct prompt_config *pc);
++const char *pc_get_2fa_1st_prompt(struct prompt_config *pc);
++const char *pc_get_2fa_2nd_prompt(struct prompt_config *pc);
++const char *pc_get_2fa_single_prompt(struct prompt_config *pc);
++void pc_list_free(struct prompt_config **pc_list);
++errno_t pc_list_add_password(struct prompt_config ***pc_list,
++                             const char *prompt);
++errno_t pc_list_add_2fa(struct prompt_config ***pc_list,
++                        const char *prompt_1st, const char *prompt_2nd);
++errno_t pc_list_add_2fa_single(struct prompt_config ***pc_list,
++                               const char *prompt);
++errno_t pam_get_response_prompt_config(struct prompt_config **pc_list, int *len,
++                                       uint8_t **data);
++errno_t pc_list_from_response(int size, uint8_t *buf,
++                              struct prompt_config ***pc_list);
++
+ enum sss_netgr_rep_type {
+     SSS_NETGR_REP_TRIPLE = 1,
+     SSS_NETGR_REP_GROUP
+diff --git a/src/tests/cmocka/test_prompt_config.c b/src/tests/cmocka/test_prompt_config.c
+new file mode 100644
+index 000000000..0b761ae4c
+--- /dev/null
++++ b/src/tests/cmocka/test_prompt_config.c
+@@ -0,0 +1,215 @@
++/*
++    SSSD
++
++    prompt config - Utilities tests
++
++    Authors:
++        Sumit bose <sbose@redhat.com>
++
++    Copyright (C) 2019 Red Hat
++
++    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 <string.h>
++#include <popt.h>
++
++#include "tests/cmocka/common_mock.h"
++
++#include "sss_client/sss_cli.h"
++
++void test_pc_list_add_password(void **state)
++{
++    int ret;
++    struct prompt_config **pc_list = NULL;
++
++    ret = pc_list_add_password(&pc_list, "Hello");
++    assert_int_equal(ret, EOK);
++    assert_non_null(pc_list);
++    assert_non_null(pc_list[0]);
++    assert_int_equal(PC_TYPE_PASSWORD, pc_get_type(pc_list[0]));
++    assert_string_equal("Hello", pc_get_password_prompt(pc_list[0]));
++    assert_null(pc_list[1]);
++
++    ret = pc_list_add_password(&pc_list, "Hello2");
++    assert_int_equal(ret, EOK);
++    assert_non_null(pc_list);
++    assert_non_null(pc_list[0]);
++    assert_int_equal(PC_TYPE_PASSWORD, pc_get_type(pc_list[0]));
++    assert_string_equal("Hello", pc_get_password_prompt(pc_list[0]));
++    assert_non_null(pc_list[1]);
++    assert_int_equal(PC_TYPE_PASSWORD, pc_get_type(pc_list[1]));
++    assert_string_equal("Hello2", pc_get_password_prompt(pc_list[1]));
++    assert_null(pc_list[2]);
++
++    pc_list_free(pc_list);
++}
++
++void test_pc_list_add_2fa_single(void **state)
++{
++    int ret;
++    struct prompt_config **pc_list = NULL;
++
++    ret = pc_list_add_2fa_single(&pc_list, "Hello");
++    assert_int_equal(ret, EOK);
++    assert_non_null(pc_list);
++    assert_non_null(pc_list[0]);
++    assert_int_equal(PC_TYPE_2FA_SINGLE, pc_get_type(pc_list[0]));
++    assert_string_equal("Hello", pc_get_2fa_single_prompt(pc_list[0]));
++    assert_null(pc_list[1]);
++
++    ret = pc_list_add_2fa_single(&pc_list, "Hello2");
++    assert_int_equal(ret, EOK);
++    assert_non_null(pc_list);
++    assert_non_null(pc_list[0]);
++    assert_int_equal(PC_TYPE_2FA_SINGLE, pc_get_type(pc_list[0]));
++    assert_string_equal("Hello", pc_get_2fa_single_prompt(pc_list[0]));
++    assert_non_null(pc_list[1]);
++    assert_int_equal(PC_TYPE_2FA_SINGLE, pc_get_type(pc_list[1]));
++    assert_string_equal("Hello2", pc_get_2fa_single_prompt(pc_list[1]));
++    assert_null(pc_list[2]);
++
++    pc_list_free(pc_list);
++}
++
++void test_pc_list_add_2fa(void **state)
++{
++    int ret;
++    struct prompt_config **pc_list = NULL;
++
++    ret = pc_list_add_2fa(&pc_list, "Hello", "Good Bye");
++    assert_int_equal(ret, EOK);
++    assert_non_null(pc_list);
++    assert_non_null(pc_list[0]);
++    assert_int_equal(PC_TYPE_2FA, pc_get_type(pc_list[0]));
++    assert_string_equal("Hello", pc_get_2fa_1st_prompt(pc_list[0]));
++    assert_string_equal("Good Bye", pc_get_2fa_2nd_prompt(pc_list[0]));
++    assert_null(pc_list[1]);
++
++    pc_list_free(pc_list);
++}
++
++void test_pam_get_response_prompt_config(void **state)
++{
++    int ret;
++    struct prompt_config **pc_list = NULL;
++    int len;
++    uint8_t *data;
++
++    ret = pc_list_add_password(&pc_list, "password");
++    assert_int_equal(ret, EOK);
++
++    ret = pc_list_add_2fa(&pc_list, "first", "second");
++    assert_int_equal(ret, EOK);
++
++    ret = pc_list_add_2fa_single(&pc_list, "single");
++    assert_int_equal(ret, EOK);
++
++    ret = pam_get_response_prompt_config(pc_list, &len, &data);
++    pc_list_free(pc_list);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(len, 57);
++
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++    assert_memory_equal(data, "\3\0\0\0\1\0\0\0\10\0\0\0" "password\2\0\0\0\5\0\0\0" "first\6\0\0\0" "second\3\0\0\0\6\0\0\0" "single", len);
++#else
++    assert_memory_equal(data, "\0\0\0\3\0\0\0\1\0\0\0\10" "password\0\0\0\2\0\0\0\5" "first\0\0\0\6" "second\0\0\0\3\0\0\0\6" "single", len);
++#endif
++
++    free(data);
++}
++
++void test_pc_list_from_response(void **state)
++{
++    int ret;
++    struct prompt_config **pc_list = NULL;
++    int len;
++    uint8_t *data;
++
++    ret = pc_list_add_password(&pc_list, "password");
++    assert_int_equal(ret, EOK);
++
++    ret = pc_list_add_2fa(&pc_list, "first", "second");
++    assert_int_equal(ret, EOK);
++
++    ret = pc_list_add_2fa_single(&pc_list, "single");
++    assert_int_equal(ret, EOK);
++
++    ret = pam_get_response_prompt_config(pc_list, &len, &data);
++    pc_list_free(pc_list);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(len, 57);
++
++    pc_list = NULL;
++
++    ret = pc_list_from_response(len, data, &pc_list);
++    free(data);
++    assert_int_equal(ret, EOK);
++    assert_non_null(pc_list);
++
++    assert_non_null(pc_list[0]);
++    assert_int_equal(PC_TYPE_PASSWORD, pc_get_type(pc_list[0]));
++    assert_string_equal("password", pc_get_password_prompt(pc_list[0]));
++
++    assert_non_null(pc_list[1]);
++    assert_int_equal(PC_TYPE_2FA, pc_get_type(pc_list[1]));
++    assert_string_equal("first", pc_get_2fa_1st_prompt(pc_list[1]));
++    assert_string_equal("second", pc_get_2fa_2nd_prompt(pc_list[1]));
++
++    assert_non_null(pc_list[2]);
++    assert_int_equal(PC_TYPE_2FA_SINGLE, pc_get_type(pc_list[2]));
++    assert_string_equal("single", pc_get_2fa_single_prompt(pc_list[2]));
++
++    assert_null(pc_list[3]);
++
++    pc_list_free(pc_list);
++}
++
++int main(int argc, const char *argv[])
++{
++    poptContext pc;
++    int opt;
++    struct poptOption long_options[] = {
++        POPT_AUTOHELP
++        SSSD_DEBUG_OPTS
++        POPT_TABLEEND
++    };
++
++    const struct CMUnitTest tests[] = {
++        cmocka_unit_test(test_pc_list_add_password),
++        cmocka_unit_test(test_pc_list_add_2fa_single),
++        cmocka_unit_test(test_pc_list_add_2fa),
++        cmocka_unit_test(test_pam_get_response_prompt_config),
++        cmocka_unit_test(test_pc_list_from_response),
++    };
++
++    /* Set debug level to invalid value so we can decide 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_CLI_INIT(debug_level);
++
++    return cmocka_run_group_tests(tests, NULL, NULL);
++}
+-- 
+2.19.1
+
diff --git a/SOURCES/0016-util-Remove-the-unused-function-is_email_from_domain.patch b/SOURCES/0016-util-Remove-the-unused-function-is_email_from_domain.patch
deleted file mode 100644
index ba26190..0000000
--- a/SOURCES/0016-util-Remove-the-unused-function-is_email_from_domain.patch
+++ /dev/null
@@ -1,117 +0,0 @@
-From 5651a893f7dddb13fa9edc94e96d7bc95ec13f8b Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 21 Jun 2018 12:40:44 +0200
-Subject: [PATCH] util: Remove the unused function is_email_from_domain
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This commit pretty much reverts commit
-04d4c4d45f3942a813b7f772737f801f877f4e64, it's just coded manually,
-because "git revert 04d4c4d45f3942a813b7f772737f801f877f4e64"
-resulted in conflicts. It's easier to just remove the single
-function.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3607
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 58f60a0949f5d84b1fe5d15e52adfceb84053569)
----
- src/tests/cmocka/test_utils.c | 21 ---------------------
- src/util/domain_info_utils.c  | 27 ---------------------------
- src/util/util.h               |  1 -
- 3 files changed, 49 deletions(-)
-
-diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
-index cf314abe2db4056fe92c167454a4ddc31be98a51..1a8699a2a87d57ab43c70ceebf9bc71da4def4d4 100644
---- a/src/tests/cmocka/test_utils.c
-+++ b/src/tests/cmocka/test_utils.c
-@@ -1849,25 +1849,6 @@ static void test_sss_get_domain_mappings_content(void **state)
-      * capaths might not be as expected. */
- }
- 
--static void test_is_email_from_domain(void **state)
--{
--    struct dom_list_test_ctx *test_ctx = talloc_get_type(*state,
--                                                      struct dom_list_test_ctx);
--    struct sss_domain_info *d;
--
--    d = find_domain_by_name(test_ctx->dom_list, "name_0.dom", false);
--    assert_non_null(d);
--
--    assert_false(is_email_from_domain(NULL, NULL));
--    assert_false(is_email_from_domain("hello", NULL));
--    assert_false(is_email_from_domain(NULL, d));
--    assert_false(is_email_from_domain("hello", d));
--    assert_false(is_email_from_domain("hello@hello", d));
--
--    assert_true(is_email_from_domain("hello@name_0.dom", d));
--    assert_true(is_email_from_domain("hello@NaMe_0.DoM", d));
--}
--
- int main(int argc, const char *argv[])
- {
-     poptContext pc;
-@@ -1896,8 +1877,6 @@ int main(int argc, const char *argv[])
-                                         setup_dom_list, teardown_dom_list),
-         cmocka_unit_test_setup_teardown(test_find_domain_by_name_disabled,
-                                         setup_dom_list, teardown_dom_list),
--        cmocka_unit_test_setup_teardown(test_is_email_from_domain,
--                                        setup_dom_list, teardown_dom_list),
- 
-         cmocka_unit_test_setup_teardown(test_sss_names_init,
-                                         confdb_test_setup,
-diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
-index 66077092a40111967a98b0937506d9e4472f50d5..9d608ef2079cadbf3c66187e3bb8c81d2d7b4604 100644
---- a/src/util/domain_info_utils.c
-+++ b/src/util/domain_info_utils.c
-@@ -889,33 +889,6 @@ bool sss_domain_is_forest_root(struct sss_domain_info *dom)
-     return (dom->forest_root == dom);
- }
- 
--bool is_email_from_domain(const char *email, struct sss_domain_info *dom)
--{
--    const char *p;
--
--    if (email == NULL || dom == NULL) {
--        return false;
--    }
--
--    p = strchr(email, '@');
--    if (p == NULL) {
--        DEBUG(SSSDBG_TRACE_ALL,
--              "Input [%s] does not look like an email address.\n", email);
--        return false;
--    }
--
--    if (strcasecmp(p+1, dom->name) == 0) {
--        DEBUG(SSSDBG_TRACE_ALL, "Email [%s] is from domain [%s].\n", email,
--                                                                     dom->name);
--        return true;
--    }
--
--    DEBUG(SSSDBG_TRACE_ALL, "Email [%s] is not from domain [%s].\n", email,
--                                                                     dom->name);
--
--    return false;
--}
--
- char *subdomain_create_conf_path(TALLOC_CTX *mem_ctx,
-                                  struct sss_domain_info *subdomain)
- {
-diff --git a/src/util/util.h b/src/util/util.h
-index 4657ab0c691e3e0442f340b94ae149e9d6602bb5..2785ac2e285cfb4dd6a309fe5d73dd755e07b8ad 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -539,7 +539,6 @@ struct sss_domain_info *find_domain_by_sid(struct sss_domain_info *domain,
- enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom);
- void sss_domain_set_state(struct sss_domain_info *dom,
-                           enum sss_domain_state state);
--bool is_email_from_domain(const char *email, struct sss_domain_info *dom);
- bool sss_domain_is_forest_root(struct sss_domain_info *dom);
- const char *sss_domain_type_str(struct sss_domain_info *dom);
- 
--- 
-2.17.1
-
diff --git a/SOURCES/0017-TESTS-Allow-storing-e-mail-address-for-users.patch b/SOURCES/0017-TESTS-Allow-storing-e-mail-address-for-users.patch
deleted file mode 100644
index 85bee19..0000000
--- a/SOURCES/0017-TESTS-Allow-storing-e-mail-address-for-users.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 75710952e74ea6070a53baaf5ea4e80507cdc26c Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 21 Jun 2018 12:37:42 +0200
-Subject: [PATCH] TESTS: Allow storing e-mail address for users
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This would allow adding tests for by-e-mail lookups later
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3607
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit d057eb2e20a19ce975dc2202f7c0e9f204eb9510)
----
- src/tests/intg/ldap_ent.py | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/src/tests/intg/ldap_ent.py b/src/tests/intg/ldap_ent.py
-index a4c987969d3dcefba2af69e095b220180e0fa54c..1f23e3ab7a7ee62909babb8338379a5f2d4e37f2 100644
---- a/src/tests/intg/ldap_ent.py
-+++ b/src/tests/intg/ldap_ent.py
-@@ -25,7 +25,8 @@ def user(base_dn, uid, uidNumber, gidNumber,
-          loginShell=None,
-          cn=None,
-          sn=None,
--         sshPubKey=()):
-+         sshPubKey=(),
-+         mail=None):
-     """
-     Generate an RFC2307(bis) user add-modlist for passing to ldap.add*
-     """
-@@ -56,6 +57,8 @@ def user(base_dn, uid, uidNumber, gidNumber,
-     if len(sshPubKey) > 0:
-         pubkeys = [key.encode('utf-8') for key in sshPubKey]
-         user[1].append(('sshPublicKey', pubkeys))
-+    if mail is not None:
-+        user[1].append(('mail', [mail.encode('utf-8')]))
-     return user
- 
- 
-@@ -124,7 +127,8 @@ class List(list):
-                  loginShell=None,
-                  cn=None,
-                  sn=None,
--                 sshPubKey=()):
-+                 sshPubKey=(),
-+                 mail=None):
-         """Add an RFC2307(bis) user add-modlist."""
-         self.append(user(base_dn or self.base_dn,
-                          uid, uidNumber, gidNumber,
-@@ -134,7 +138,8 @@ class List(list):
-                          loginShell=loginShell,
-                          cn=cn,
-                          sn=sn,
--                         sshPubKey=sshPubKey))
-+                         sshPubKey=sshPubKey,
-+                         mail=mail))
- 
-     def add_group(self, cn, gidNumber, member_uids=[],
-                   base_dn=None):
--- 
-2.17.1
-
diff --git a/SOURCES/0017-authtok-add-dedicated-type-for-2fa-with-single-strin.patch b/SOURCES/0017-authtok-add-dedicated-type-for-2fa-with-single-strin.patch
new file mode 100644
index 0000000..7b685a4
--- /dev/null
+++ b/SOURCES/0017-authtok-add-dedicated-type-for-2fa-with-single-strin.patch
@@ -0,0 +1,324 @@
+From fc57f57b805a5b91348a8355e74ceb4444881729 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 27 Mar 2019 09:04:53 +0100
+Subject: [PATCH 17/21] authtok: add dedicated type for 2fa with single string
+
+Currently the password type is used to send two-factor authentication
+credentials entered in a single string to the backend, This is
+unreliable and only works properly if password authentication is not
+available for the user as well.
+
+To support 2FA credentials in a single string better a new authtok type
+is added.
+
+Related to https://pagure.io/SSSD/sssd/issue/3264
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit ac4b33f765ac322949ac7c2f24985d3b9c178168)
+---
+ src/providers/krb5/krb5_auth.c          |  1 +
+ src/providers/krb5/krb5_child.c         | 13 +++++++
+ src/providers/krb5/krb5_child_handler.c |  4 +++
+ src/responder/pam/pamsrv_cmd.c          |  1 +
+ src/sss_client/sss_cli.h                |  3 ++
+ src/tests/cmocka/test_authtok.c         | 45 +++++++++++++++++++++++++
+ src/util/authtok.c                      | 42 +++++++++++++++++++++++
+ src/util/authtok.h                      | 35 +++++++++++++++++++
+ 8 files changed, 144 insertions(+)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index d40d2afed..9a9250434 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -495,6 +495,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
+         case SSS_PAM_CHAUTHTOK:
+             if (authtok_type != SSS_AUTHTOK_TYPE_PASSWORD
+                     && authtok_type != SSS_AUTHTOK_TYPE_2FA
++                    && authtok_type != SSS_AUTHTOK_TYPE_2FA_SINGLE
+                     && authtok_type != SSS_AUTHTOK_TYPE_SC_PIN
+                     && authtok_type != SSS_AUTHTOK_TYPE_SC_KEYPAD) {
+                 /* handle empty password gracefully */
+diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
+index a578930a9..a86d9a7ae 100644
+--- a/src/providers/krb5/krb5_child.c
++++ b/src/providers/krb5/krb5_child.c
+@@ -503,6 +503,15 @@ static krb5_error_code tokeninfo_matches(TALLOC_CTX *mem_ctx,
+             return ret;
+         }
+ 
++        return tokeninfo_matches_pwd(mem_ctx, ti, pwd, len, out_token, out_pin);
++        break;
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
++        ret = sss_authtok_get_2fa_single(auth_tok, &pwd, &len);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_password failed.\n");
++            return ret;
++        }
++
+         return tokeninfo_matches_pwd(mem_ctx, ti, pwd, len, out_token, out_pin);
+         break;
+     case SSS_AUTHTOK_TYPE_2FA:
+@@ -2091,6 +2100,7 @@ static errno_t tgt_req_child(struct krb5_req *kr)
+     /* No password is needed for pre-auth or if we have 2FA or SC */
+     if (kr->pd->cmd != SSS_PAM_PREAUTH
+             && sss_authtok_get_type(kr->pd->authtok) != SSS_AUTHTOK_TYPE_2FA
++            && sss_authtok_get_type(kr->pd->authtok) != SSS_AUTHTOK_TYPE_2FA_SINGLE
+             && sss_authtok_get_type(kr->pd->authtok) != SSS_AUTHTOK_TYPE_SC_PIN
+             && sss_authtok_get_type(kr->pd->authtok)
+                                                 != SSS_AUTHTOK_TYPE_SC_KEYPAD) {
+@@ -2349,6 +2359,9 @@ static errno_t unpack_authtok(struct sss_auth_token *tok,
+     case SSS_AUTHTOK_TYPE_CCFILE:
+         ret = sss_authtok_set_ccfile(tok, (char *)(buf + *p), 0);
+         break;
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
++        ret = sss_authtok_set_2fa_single(tok, (char *)(buf + *p), 0);
++        break;
+     case SSS_AUTHTOK_TYPE_2FA:
+     case SSS_AUTHTOK_TYPE_SC_PIN:
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
+index 352ff980d..b7fb54499 100644
+--- a/src/providers/krb5/krb5_child_handler.c
++++ b/src/providers/krb5/krb5_child_handler.c
+@@ -79,6 +79,10 @@ static errno_t pack_authtok(struct io_buffer *buf, size_t *rp,
+         ret = sss_authtok_get_ccfile(tok, &data, &len);
+         auth_token_length = len + 1;
+         break;
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
++        ret = sss_authtok_get_2fa_single(tok, &data, &len);
++        auth_token_length = len + 1;
++        break;
+     case SSS_AUTHTOK_TYPE_2FA:
+     case SSS_AUTHTOK_TYPE_SC_PIN:
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
+index 94867a0fe..6f3a7e56b 100644
+--- a/src/responder/pam/pamsrv_cmd.c
++++ b/src/responder/pam/pamsrv_cmd.c
+@@ -160,6 +160,7 @@ static int extract_authtok_v2(struct sss_auth_token *tok,
+         }
+         break;
+     case SSS_AUTHTOK_TYPE_2FA:
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
+     case SSS_AUTHTOK_TYPE_SC_PIN:
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+         ret = sss_authtok_set(tok, auth_token_type,
+diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
+index 7e748c281..23ef21608 100644
+--- a/src/sss_client/sss_cli.h
++++ b/src/sss_client/sss_cli.h
+@@ -340,6 +340,9 @@ enum sss_authtok_type {
+                                           * Smart Card authentication is used
+                                           * and that the PIN will be entered
+                                           * at the card reader. */
++    SSS_AUTHTOK_TYPE_2FA_SINGLE = 0x0006, /**< Authentication token has two
++                                           * factors in a single string, it may
++                                           * or may no contain a trailing \\0 */
+ };
+ 
+ /**
+diff --git a/src/tests/cmocka/test_authtok.c b/src/tests/cmocka/test_authtok.c
+index 9422f96bc..84e209783 100644
+--- a/src/tests/cmocka/test_authtok.c
++++ b/src/tests/cmocka/test_authtok.c
+@@ -652,6 +652,49 @@ void test_sss_authtok_sc_pin(void **state)
+     assert_int_equal(ret, EFAULT);
+ }
+ 
++/* Test when type has value SSS_AUTHTOK_TYPE_2FA_SINGLE */
++static void test_sss_authtok_2fa_single(void **state)
++{
++    size_t len;
++    errno_t ret;
++    char *data;
++    size_t ret_len;
++    const char *pwd;
++    struct test_state *ts;
++    enum sss_authtok_type type;
++
++    ts = talloc_get_type_abort(*state, struct test_state);
++    data = talloc_strdup(ts, "1stfacto2ndfactor");
++    assert_non_null(data);
++
++    len = strlen(data) + 1;
++    type = SSS_AUTHTOK_TYPE_2FA_SINGLE;
++    ret = sss_authtok_set(ts->authtoken, type, (const uint8_t *)data, len);
++
++    assert_int_equal(ret, EOK);
++    assert_int_equal(type, sss_authtok_get_type(ts->authtoken));
++    assert_int_equal(len, sss_authtok_get_size(ts->authtoken));
++    assert_string_equal(data, sss_authtok_get_data(ts->authtoken));
++
++    ret = sss_authtok_get_2fa_single(ts->authtoken, &pwd, &ret_len);
++
++    assert_int_equal(ret, EOK);
++    assert_string_equal(data, pwd);
++    assert_int_equal(len - 1, ret_len);
++
++    ret = sss_authtok_set_2fa_single(ts->authtoken, data, len);
++    assert_int_equal(ret, EOK);
++
++    ret = sss_authtok_get_2fa_single(ts->authtoken, &pwd, &ret_len);
++    assert_int_equal(ret, EOK);
++    assert_string_equal(data, pwd);
++    assert_int_equal(len - 1, ret_len);
++
++    talloc_free(data);
++    sss_authtok_set_empty(ts->authtoken);
++}
++
++
+ int main(int argc, const char *argv[])
+ {
+     poptContext pc;
+@@ -687,6 +730,8 @@ int main(int argc, const char *argv[])
+                                         setup, teardown),
+         cmocka_unit_test_setup_teardown(test_sss_authtok_sc_blobs,
+                                         setup, teardown),
++        cmocka_unit_test_setup_teardown(test_sss_authtok_2fa_single,
++                                        setup, teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can decide if -d 0 was used. */
+diff --git a/src/util/authtok.c b/src/util/authtok.c
+index c2f78be32..0cac24598 100644
+--- a/src/util/authtok.c
++++ b/src/util/authtok.c
+@@ -41,6 +41,7 @@ size_t sss_authtok_get_size(struct sss_auth_token *tok)
+     case SSS_AUTHTOK_TYPE_2FA:
+     case SSS_AUTHTOK_TYPE_SC_PIN:
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
+         return tok->length;
+     case SSS_AUTHTOK_TYPE_EMPTY:
+         return 0;
+@@ -76,6 +77,7 @@ errno_t sss_authtok_get_password(struct sss_auth_token *tok,
+     case SSS_AUTHTOK_TYPE_2FA:
+     case SSS_AUTHTOK_TYPE_SC_PIN:
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
+         return EACCES;
+     }
+ 
+@@ -101,6 +103,33 @@ errno_t sss_authtok_get_ccfile(struct sss_auth_token *tok,
+     case SSS_AUTHTOK_TYPE_2FA:
+     case SSS_AUTHTOK_TYPE_SC_PIN:
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
++        return EACCES;
++    }
++
++    return EINVAL;
++}
++
++errno_t sss_authtok_get_2fa_single(struct sss_auth_token *tok,
++                                   const char **str, size_t *len)
++{
++    if (!tok) {
++        return EINVAL;
++    }
++    switch (tok->type) {
++    case SSS_AUTHTOK_TYPE_EMPTY:
++        return ENOENT;
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
++        *str = (const char *)tok->data;
++        if (len) {
++            *len = tok->length - 1;
++        }
++        return EOK;
++    case SSS_AUTHTOK_TYPE_PASSWORD:
++    case SSS_AUTHTOK_TYPE_2FA:
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++    case SSS_AUTHTOK_TYPE_CCFILE:
+         return EACCES;
+     }
+ 
+@@ -151,6 +180,7 @@ void sss_authtok_set_empty(struct sss_auth_token *tok)
+     case SSS_AUTHTOK_TYPE_PASSWORD:
+     case SSS_AUTHTOK_TYPE_2FA:
+     case SSS_AUTHTOK_TYPE_SC_PIN:
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
+         safezero(tok->data, tok->length);
+         break;
+     case SSS_AUTHTOK_TYPE_CCFILE:
+@@ -181,6 +211,15 @@ errno_t sss_authtok_set_ccfile(struct sss_auth_token *tok,
+                                   "ccfile", ccfile, len);
+ }
+ 
++errno_t sss_authtok_set_2fa_single(struct sss_auth_token *tok,
++                                   const char *str, size_t len)
++{
++    sss_authtok_set_empty(tok);
++
++    return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_2FA_SINGLE,
++                                  "2fa_single", str, len);
++}
++
+ static errno_t sss_authtok_set_2fa_from_blob(struct sss_auth_token *tok,
+                                              const uint8_t *data, size_t len);
+ 
+@@ -199,6 +238,8 @@ errno_t sss_authtok_set(struct sss_auth_token *tok,
+         return sss_authtok_set_sc_from_blob(tok, data, len);
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+         return sss_authtok_set_sc_from_blob(tok, data, len);
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
++        return sss_authtok_set_2fa_single(tok, (const char *) data, len);
+     case SSS_AUTHTOK_TYPE_EMPTY:
+         sss_authtok_set_empty(tok);
+         return EOK;
+@@ -566,6 +607,7 @@ errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **_pin,
+     case SSS_AUTHTOK_TYPE_CCFILE:
+     case SSS_AUTHTOK_TYPE_2FA:
+     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++    case SSS_AUTHTOK_TYPE_2FA_SINGLE:
+         return EACCES;
+     }
+ 
+diff --git a/src/util/authtok.h b/src/util/authtok.h
+index a55e89fd2..dae3ff6b1 100644
+--- a/src/util/authtok.h
++++ b/src/util/authtok.h
+@@ -348,4 +348,39 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok,
+                            const char **_token_name, size_t *_token_name_len,
+                            const char **_module_name, size_t *_module_name_len,
+                            const char **_key_id, size_t *_key_id_len);
++
++
++/**
++ * @brief Returns a const string if the auth token is of type
++          SSS_AUTHTOK_TYPE_2FA_SINGLE, otherwise it returns an error
++ *
++ * @param tok    A pointer to an sss_auth_token
++ * @param pwd    A pointer to a const char *, that will point to a null
++ *               terminated string
++ * @param len    The length of the credential string
++ *
++ * @return       EOK on success
++ *               ENOENT if the token is empty
++ *               EACCESS if the token is not a password token
++ */
++errno_t sss_authtok_get_2fa_single(struct sss_auth_token *tok,
++                                   const char **str, size_t *len);
++
++/**
++ * @brief Set a 2FA credentials in a single strings  into an auth token,
++ *        replacing any previous data
++ *
++ * @param tok        A pointer to an sss_auth_token structure to change, also
++ *                   used as a memory context to allocate the internal data.
++ * @param password   A string where the two authentication factors are
++ *                   concatenated together
++ * @param len        The length of the string or, if 0 is passed,
++ *                   then strlen(password) will be used internally.
++ *
++ * @return       EOK on success
++ *               ENOMEM on error
++ */
++errno_t sss_authtok_set_2fa_single(struct sss_auth_token *tok,
++                                   const char *str, size_t len);
++
+ #endif /*  __AUTHTOK_H__ */
+-- 
+2.19.1
+
diff --git a/SOURCES/0018-TESTS-Add-regression-test-for-looking-up-users-with-.patch b/SOURCES/0018-TESTS-Add-regression-test-for-looking-up-users-with-.patch
deleted file mode 100644
index 109d6c0..0000000
--- a/SOURCES/0018-TESTS-Add-regression-test-for-looking-up-users-with-.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From 0cbf6070bccb6c1f904cea596f00af0cc6328bae Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 21 Jun 2018 12:37:57 +0200
-Subject: [PATCH] TESTS: Add regression test for looking up users with
- conflicting e-mail addresses
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3607
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 76ce965fc3abfdcf3a4a9518e57545ea060033d6)
----
- src/tests/intg/test_ldap.py | 64 +++++++++++++++++++++++++++++++++++++
- 1 file changed, 64 insertions(+)
-
-diff --git a/src/tests/intg/test_ldap.py b/src/tests/intg/test_ldap.py
-index f71915a8086d395e9971a7c82e2744bdd7b931b6..d70ae39841f111fdf2d6c00c9acca8073725c5c5 100644
---- a/src/tests/intg/test_ldap.py
-+++ b/src/tests/intg/test_ldap.py
-@@ -1736,3 +1736,67 @@ def test_local_negative_timeout_disabled(ldap_conn,
-     assert res == NssReturnCode.SUCCESS
- 
-     cleanup_ldap_entries(ldap_conn, ent_list)
-+
-+
-+@pytest.fixture
-+def users_with_email_setup(request, ldap_conn):
-+    ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn)
-+    ent_list.add_user("user1", 1001, 2001, mail="user1.email@LDAP")
-+
-+    ent_list.add_user("emailuser", 1002, 2002)
-+    ent_list.add_user("emailuser2", 1003, 2003, mail="emailuser@LDAP")
-+
-+    ent_list.add_user("userx", 1004, 2004, mail="userxy@LDAP")
-+    ent_list.add_user("usery", 1005, 2005, mail="userxy@LDAP")
-+
-+    create_ldap_fixture(request, ldap_conn, ent_list)
-+
-+    conf = format_basic_conf(ldap_conn, SCHEMA_RFC2307_BIS)
-+    create_conf_fixture(request, conf)
-+    create_sssd_fixture(request)
-+    return None
-+
-+
-+def test_lookup_by_email(ldap_conn, users_with_email_setup):
-+    """
-+    Test the simple case of looking up a user by e-mail
-+    """
-+    ent.assert_passwd_by_name("user1.email@LDAP",
-+                              dict(name="user1", uid=1001, gid=2001))
-+
-+
-+def test_conflicting_mail_addresses_and_fqdn(ldap_conn,
-+                                             users_with_email_setup):
-+    """
-+    Test that we handle the case where one user's mail address is the
-+    same as another user's FQDN
-+
-+    This is a regression test for https://pagure.io/SSSD/sssd/issue/3607
-+    """
-+    # With #3607 unfixed, these two lookups would prime the cache with
-+    # nameAlias: emailuser@LDAP for both entries..
-+    ent.assert_passwd_by_name("emailuser@LDAP",
-+                              dict(name="emailuser", uid=1002, gid=2002))
-+    ent.assert_passwd_by_name("emailuser2@LDAP",
-+                              dict(name="emailuser2", uid=1003, gid=2003))
-+
-+    # ..and subsequently, emailuser would not be returned because the cache
-+    # lookup would have had returned two entries which is an error
-+    ent.assert_passwd_by_name("emailuser@LDAP",
-+                              dict(name="emailuser", uid=1002, gid=2002))
-+    ent.assert_passwd_by_name("emailuser2@LDAP",
-+                              dict(name="emailuser2", uid=1003, gid=2003))
-+
-+
-+def test_conflicting_mail_addresses(ldap_conn,
-+                                    users_with_email_setup):
-+    """
-+    Negative test: looking up a user by e-mail which belongs to more than
-+    one account fails in the back end.
-+    """
-+    with pytest.raises(KeyError):
-+        pwd.getpwnam("userxy@LDAP")
-+
-+    # However resolving the users on their own must work
-+    ent.assert_passwd_by_name("userx", dict(name="userx", uid=1004, gid=2004))
-+    ent.assert_passwd_by_name("usery", dict(name="usery", uid=1005, gid=2005))
--- 
-2.17.1
-
diff --git a/SOURCES/0018-pam_sss-use-configured-prompting.patch b/SOURCES/0018-pam_sss-use-configured-prompting.patch
new file mode 100644
index 0000000..b2237e9
--- /dev/null
+++ b/SOURCES/0018-pam_sss-use-configured-prompting.patch
@@ -0,0 +1,232 @@
+From 6b7ce87976ebba7b3c1aea24dbf91486ec5de2ed Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 27 Mar 2019 09:48:42 +0100
+Subject: [PATCH 18/21] pam_sss: use configured prompting
+
+If the responds of SSSD's PAM responder contains a prompt_config
+structure use the content to prompt the user for credentials.
+
+Related to https://pagure.io/SSSD/sssd/issue/3264
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked with fixes from commit fc26b4a82d4a92b29cf321fba8dbec52c3bff8d6)
+---
+ src/sss_client/pam_message.h |   2 +
+ src/sss_client/pam_sss.c     | 136 +++++++++++++++++++++++++++++------
+ src/sss_client/sss_cli.h     |   3 +
+ 3 files changed, 119 insertions(+), 22 deletions(-)
+
+diff --git a/src/sss_client/pam_message.h b/src/sss_client/pam_message.h
+index 11526a80a..c87162479 100644
+--- a/src/sss_client/pam_message.h
++++ b/src/sss_client/pam_message.h
+@@ -64,6 +64,8 @@ struct pam_items {
+     bool user_name_hint;
+     struct cert_auth_info *cert_list;
+     struct cert_auth_info *selected_cert;
++
++    struct prompt_config **pc;
+ };
+ 
+ int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer);
+diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
+index 59081cc67..ab9b7478e 100644
+--- a/src/sss_client/pam_sss.c
++++ b/src/sss_client/pam_sss.c
+@@ -205,6 +205,9 @@ static void overwrite_and_free_pam_items(struct pam_items *pi)
+     free_cert_list(pi->cert_list);
+     pi->cert_list = NULL;
+     pi->selected_cert = NULL;
++
++    pc_list_free(pi->pc);
++    pi->pc = NULL;
+ }
+ 
+ static int null_strcmp(const char *s1, const char *s2) {
+@@ -1163,6 +1166,16 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
+                 D(("Password prompting available."));
+                 pi->password_prompting = true;
+                 break;
++            case SSS_PAM_PROMPT_CONFIG:
++                if (pi->pc == NULL) {
++                    ret = pc_list_from_response(len, &buf[p], &pi->pc);
++                    if (ret != EOK) {
++                        D(("Failed to parse prompting data, using defaults"));
++                        pc_list_free(pi->pc);
++                        pi->pc = NULL;
++                    }
++                }
++                break;
+             default:
+                 D(("Unknown response type [%d]", type));
+         }
+@@ -1256,6 +1269,8 @@ static int get_pam_items(pam_handle_t *pamh, uint32_t flags,
+     pi->cert_list = NULL;
+     pi->selected_cert = NULL;
+ 
++    pi->pc = NULL;
++
+     return PAM_SUCCESS;
+ }
+ 
+@@ -1558,6 +1573,37 @@ done:
+     return ret;
+ }
+ 
++static int prompt_2fa_single(pam_handle_t *pamh, struct pam_items *pi,
++                             const char *prompt)
++{
++    int ret;
++    char *answer = NULL;
++
++    ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer);
++    if (ret != PAM_SUCCESS) {
++        D(("do_pam_conversation failed."));
++        return ret;
++    }
++
++    if (answer == NULL) {
++        pi->pam_authtok = NULL;
++        pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY;
++        pi->pam_authtok_size=0;
++    } else {
++        pi->pam_authtok = strdup(answer);
++        _pam_overwrite((void *)answer);
++        free(answer);
++        answer=NULL;
++        if (pi->pam_authtok == NULL) {
++            return PAM_BUF_ERR;
++        }
++        pi->pam_authtok_type = SSS_AUTHTOK_TYPE_2FA_SINGLE;
++        pi->pam_authtok_size=strlen(pi->pam_authtok);
++    }
++
++    return PAM_SUCCESS;
++}
++
+ #define SC_PROMPT_FMT "PIN for %s"
+ 
+ #ifndef discard_const
+@@ -2014,6 +2060,48 @@ static void eval_argv(pam_handle_t *pamh, int argc, const char **argv,
+     return;
+ }
+ 
++static int prompt_by_config(pam_handle_t *pamh, struct pam_items *pi)
++{
++    size_t c;
++    int ret;
++
++    if (pi->pc == NULL || *pi->pc == NULL) {
++        return EINVAL;
++    }
++
++    for (c = 0; pi->pc[c] != NULL; c++) {
++        switch (pc_get_type(pi->pc[c])) {
++        case PC_TYPE_PASSWORD:
++            ret = prompt_password(pamh, pi, pc_get_password_prompt(pi->pc[c]));
++            break;
++        case PC_TYPE_2FA:
++            ret = prompt_2fa(pamh, pi, pc_get_2fa_1st_prompt(pi->pc[c]),
++                             pc_get_2fa_2nd_prompt(pi->pc[c]));
++            break;
++        case PC_TYPE_2FA_SINGLE:
++            ret = prompt_2fa_single(pamh, pi,
++                                    pc_get_2fa_single_prompt(pi->pc[c]));
++            break;
++        case PC_TYPE_SC_PIN:
++            ret = prompt_sc_pin(pamh, pi);
++            /* Todo: add extra string option */
++            break;
++        default:
++            ret = EINVAL;
++        }
++
++        /* If not credential where given try the next type otherwise we are
++         * done. */
++        if (ret == PAM_SUCCESS && pi->pam_authtok_size == 0) {
++            continue;
++        }
++
++        break;
++    }
++
++    return ret;
++}
++
+ static int get_authtok_for_authentication(pam_handle_t *pamh,
+                                           struct pam_items *pi,
+                                           uint32_t flags)
+@@ -2032,30 +2120,34 @@ static int get_authtok_for_authentication(pam_handle_t *pamh,
+         }
+         pi->pam_authtok_size = strlen(pi->pam_authtok);
+     } else {
+-        if (flags & FLAGS_USE_2FA
+-                || (pi->otp_vendor != NULL && pi->otp_token_id != NULL
+-                        && pi->otp_challenge != NULL)) {
+-            if (pi->password_prompting) {
+-                ret = prompt_2fa(pamh, pi, _("First Factor: "),
+-                                 _("Second Factor (optional): "));
+-            } else {
+-                ret = prompt_2fa(pamh, pi, _("First Factor: "),
+-                                 _("Second Factor: "));
+-            }
+-        } else if (pi->cert_list != NULL) {
+-            if (pi->cert_list->next == NULL) {
+-                /* Only one certificate */
+-                pi->selected_cert = pi->cert_list;
+-            } else {
+-                ret = prompt_multi_cert(pamh, pi);
+-                if (ret != 0) {
+-                    D(("Failed to select certificate"));
+-                    return PAM_AUTHTOK_ERR;
++        if (pi->pc != NULL) {
++            ret = prompt_by_config(pamh, pi);
++        } else {
++            if (flags & FLAGS_USE_2FA
++                    || (pi->otp_vendor != NULL && pi->otp_token_id != NULL
++                            && pi->otp_challenge != NULL)) {
++                if (pi->password_prompting) {
++                    ret = prompt_2fa(pamh, pi, _("First Factor: "),
++                                     _("Second Factor (optional): "));
++                } else {
++                    ret = prompt_2fa(pamh, pi, _("First Factor: "),
++                                     _("Second Factor: "));
+                 }
++            } else if (pi->cert_list != NULL) {
++                if (pi->cert_list->next == NULL) {
++                    /* Only one certificate */
++                    pi->selected_cert = pi->cert_list;
++                } else {
++                    ret = prompt_multi_cert(pamh, pi);
++                    if (ret != 0) {
++                        D(("Failed to select certificate"));
++                        return PAM_AUTHTOK_ERR;
++                    }
++                }
++                ret = prompt_sc_pin(pamh, pi);
++            } else {
++                ret = prompt_password(pamh, pi, _("Password: "));
+             }
+-            ret = prompt_sc_pin(pamh, pi);
+-        } else {
+-            ret = prompt_password(pamh, pi, _("Password: "));
+         }
+         if (ret != PAM_SUCCESS) {
+             D(("failed to get password from user"));
+diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
+index 23ef21608..24b24a91b 100644
+--- a/src/sss_client/sss_cli.h
++++ b/src/sss_client/sss_cli.h
+@@ -469,6 +469,9 @@ enum response_type {
+     SSS_PAM_CERT_INFO_WITH_HINT, /**< Same as SSS_PAM_CERT_INFO but user name
+                                   * might be missing and should be prompted
+                                   * for. */
++    SSS_PAM_PROMPT_CONFIG, /**< Contains data which controls which credentials
++                            * are expected and how the user is prompted for
++                            * them. */
+ };
+ 
+ /**
+-- 
+2.19.1
+
diff --git a/SOURCES/0019-MAN-Remove-outdated-notes-from-the-re_expression-des.patch b/SOURCES/0019-MAN-Remove-outdated-notes-from-the-re_expression-des.patch
deleted file mode 100644
index 4ce9fed..0000000
--- a/SOURCES/0019-MAN-Remove-outdated-notes-from-the-re_expression-des.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 8d5241404e8eb2388a9fc45115f5210e3ada1f1b Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 22 Jun 2018 10:40:29 +0200
-Subject: [PATCH] MAN: Remove outdated notes from the re_expression description
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-These notes are only valid for very old pcre releases which hopefully
-nobody is using anymore.
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 4c79db69cbad88ed56e87e8fe61f697f72d7408d)
-
-DOWNSTREAM:
-Resolves: rhbz#1509691 - Document how to change the regular expression for SSSD so that group names with an @-sign can be parsed
----
- src/man/sssd.conf.5.xml | 12 ------------
- 1 file changed, 12 deletions(-)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index beed677072c9bbfb9e7749f25c2a90d743f9328d..558c97e834d7aaf46adb31b1573eb59705569782 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -2630,18 +2630,6 @@ pam_account_locked_message = Account locked, please contact help desk.
-                             the <quote>@</quote> sign, the domain everything
-                             after that"
-                         </para>
--                        <para>
--                            PLEASE NOTE: the support for non-unique named
--                            subpatterns is not available on all platforms
--                            (e.g. RHEL5 and SLES10). Only platforms with
--                            libpcre version 7 or higher can support non-unique
--                            named subpatterns.
--                        </para>
--                        <para>
--                            PLEASE NOTE ALSO: older version of libpcre only
--                            support the Python syntax (?P&lt;name&gt;) to label
--                            subpatterns.
--                        </para>
-                     </listitem>
-                 </varlistentry>
-                 <varlistentry>
--- 
-2.17.1
-
diff --git a/SOURCES/0019-PAM-add-initial-prompting-configuration.patch b/SOURCES/0019-PAM-add-initial-prompting-configuration.patch
new file mode 100644
index 0000000..7c65b56
--- /dev/null
+++ b/SOURCES/0019-PAM-add-initial-prompting-configuration.patch
@@ -0,0 +1,511 @@
+From 45580b2c90d7c19f1d8df57ce7b3e9f3e0acc244 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 27 Mar 2019 21:05:06 +0100
+Subject: [PATCH 19/21] PAM: add initial prompting configuration
+
+Add new section for sssd.conf to allow more flexible prompting during
+authentication.
+
+Related to https://pagure.io/SSSD/sssd/issue/3264
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked with fixes from commit a4d178593bec65a4c7534b841cedfbb74c56f49f)
+---
+ Makefile.am                              |   7 +
+ src/confdb/confdb.h                      |  10 +
+ src/man/sssd.conf.5.xml                  |  66 ++++++
+ src/responder/pam/pam_prompting_config.c | 275 +++++++++++++++++++++++
+ src/responder/pam/pamsrv.c               |  16 +-
+ src/responder/pam/pamsrv.h               |   6 +
+ src/responder/pam/pamsrv_cmd.c           |   8 +
+ 7 files changed, 387 insertions(+), 1 deletion(-)
+ create mode 100644 src/responder/pam/pam_prompting_config.c
+
+diff --git a/Makefile.am b/Makefile.am
+index f7f55e96a..e22423071 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1397,8 +1397,13 @@ sssd_pam_SOURCES = \
+     src/responder/pam/pamsrv_cmd.c \
+     src/responder/pam/pamsrv_p11.c \
+     src/responder/pam/pamsrv_dp.c \
++    src/responder/pam/pam_prompting_config.c \
++    src/sss_client/pam_sss_prompt_config.c \
+     src/responder/pam/pam_helpers.c \
+     $(SSSD_RESPONDER_OBJ)
++sssd_pam_CFLAGS = \
++    $(AM_CFLAGS) \
++    $(NULL)
+ sssd_pam_LDADD = \
+     $(LIBADD_DL) \
+     $(TDB_LIBS) \
+@@ -2446,6 +2451,8 @@ pam_srv_tests_SOURCES = \
+     src/responder/pam/pam_helpers.c \
+     src/responder/pam/pamsrv_dp.c \
+     src/responder/pam/pam_LOCAL_domain.c \
++    src/responder/pam/pam_prompting_config.c \
++    src/sss_client/pam_sss_prompt_config.c \
+     $(NULL)
+ pam_srv_tests_CFLAGS = \
+     -U SSSD_LIBEXEC_PATH -DSSSD_LIBEXEC_PATH=\"$(abs_builddir)\" \
+diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
+index e8091fcd9..0251ab606 100644
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -266,6 +266,16 @@
+ #define CONFDB_KCM_SOCKET "socket_path"
+ #define CONFDB_KCM_DB "ccache_storage" /* Undocumented on purpose */
+ 
++/* Prompting */
++#define CONFDB_PC_CONF_ENTRY "config/prompting"
++#define CONFDB_PC_TYPE_PASSWORD "password"
++#define CONFDB_PC_PASSWORD_PROMPT "password_prompt"
++#define CONFDB_PC_TYPE_2FA "2fa"
++#define CONFDB_PC_2FA_SINGLE_PROMPT "single_prompt"
++#define CONFDB_PC_2FA_1ST_PROMPT "first_prompt"
++#define CONFDB_PC_2FA_2ND_PROMPT "second_prompt"
++#define CONFDB_PC_TYPE_CERT_AUTH "cert_auth"
++
+ struct confdb_ctx;
+ struct config_file_ctx;
+ 
+diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
+index 3d017f638..274809e24 100644
+--- a/src/man/sssd.conf.5.xml
++++ b/src/man/sssd.conf.5.xml
+@@ -3364,6 +3364,72 @@ ldap_user_extra_attrs = phone:telephoneNumber
+         </para>
+     </refsect1>
+ 
++    <refsect1 id='prompting_configuration'>
++        <title>PROMPTING CONFIGURATION SECTION</title>
++        <para>
++            If a special file
++            (<filename>/var/lib/sss/pubconf/pam_preauth_available</filename>)
++            exists SSSD's PAM module pam_sss will ask SSSD to figure out which
++            authentication methods are available for the user trying to log in.
++            Based on the results pam_sss will prompt the user for appropriate
++            credentials.
++        </para>
++        <para>
++            With the growing number of authentication methods and the
++            possibility that there are multiple ones for a single user the
++            heuristic used by pam_sss to select the prompting might not be
++            suitable for all use cases. To following options should provide a
++            better flexibility here.
++        </para>
++        <para>
++            Each supported authentication method has it's own configuration
++            sub-section under <quote>[prompting/...]</quote>. Currently there
++            are:
++        <variablelist>
++            <varlistentry>
++                <term>[prompting/password]</term>
++                <listitem>
++                    <para>to configure password prompting, allowed options are:
++                    <variablelist><varlistentry><term>password_prompt</term>
++                        <listitem><para>to change the string of the password
++                        prompt</para></listitem></varlistentry></variablelist>
++                    </para>
++                </listitem>
++            </varlistentry>
++        </variablelist>
++        <variablelist>
++            <varlistentry>
++                <term>[prompting/2fa]</term>
++                <listitem>
++                    <para>to configure two-factor authentication prompting,
++                    allowed options are:
++                    <variablelist><varlistentry><term>first_prompt</term>
++                        <listitem><para>to change the string of the prompt for
++                        the first factor </para></listitem>
++                        </varlistentry>
++                        <varlistentry><term>second_prompt</term>
++                        <listitem><para>to change the string of the prompt for
++                        the second factor </para></listitem>
++                        </varlistentry>
++                        <varlistentry><term>single_prompt</term>
++                        <listitem><para>boolean value, if True there will be
++                        only a single prompt using the value of first_prompt
++                        where it is expected that both factor are entered as a
++                        single string</para></listitem>
++                        </varlistentry>
++                    </variablelist>
++                    </para>
++                </listitem>
++            </varlistentry>
++        </variablelist>
++        </para>
++        <para>
++            It is possible to add a sub-section for specific PAM services like
++            e.g. <quote>[prompting/password/sshd]</quote> to individual change
++            the prompting for this service.
++        </para>
++    </refsect1>
++
+     <refsect1 id='example'>
+         <title>EXAMPLES</title>
+         <para>
+diff --git a/src/responder/pam/pam_prompting_config.c b/src/responder/pam/pam_prompting_config.c
+new file mode 100644
+index 000000000..c3ee41d4b
+--- /dev/null
++++ b/src/responder/pam/pam_prompting_config.c
+@@ -0,0 +1,275 @@
++/*
++   SSSD
++
++   PAM Responder - helpers for PAM prompting configuration
++
++   Copyright (C) Sumit Bose <sbose@redhat.com> 2019
++
++   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 "util/util.h"
++#include "providers/data_provider.h"
++#include "confdb/confdb.h"
++#include "sss_client/sss_cli.h"
++#include "responder/pam/pamsrv.h"
++
++typedef errno_t (pam_set_prompting_fn_t)(TALLOC_CTX *, struct confdb_ctx *,
++                                         const char *,
++                                         struct prompt_config ***);
++
++
++static errno_t pam_set_password_prompting_options(TALLOC_CTX *tmp_ctx,
++                                                struct confdb_ctx *cdb,
++                                                const char *section,
++                                                struct prompt_config ***pc_list)
++{
++    int ret;
++    char *value = NULL;
++
++    ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_PASSWORD_PROMPT,
++                            NULL, &value);
++    if (ret == EOK && value != NULL) {
++        ret = pc_list_add_password(pc_list, value);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_password failed.\n");
++        }
++        return ret;
++    }
++
++    return ENOENT;
++}
++
++static errno_t pam_set_2fa_prompting_options(TALLOC_CTX *tmp_ctx,
++                                             struct confdb_ctx *cdb,
++                                             const char *section,
++                                             struct prompt_config ***pc_list)
++{
++    bool single_2fa_prompt = false;
++    char *first_prompt = NULL;
++    char *second_prompt = NULL;
++    int ret;
++
++
++    ret = confdb_get_bool(cdb, section, CONFDB_PC_2FA_SINGLE_PROMPT, false,
++                          &single_2fa_prompt);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "confdb_get_bool failed, using defaults");
++    }
++    ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_2FA_1ST_PROMPT,
++                            NULL, &first_prompt);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed, using defaults");
++    }
++
++    if (single_2fa_prompt) {
++        ret = pc_list_add_2fa_single(pc_list, first_prompt);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_2fa_single failed.\n");
++        }
++        return ret;
++    } else {
++        ret = confdb_get_string(cdb, tmp_ctx, section, CONFDB_PC_2FA_2ND_PROMPT,
++                                NULL, &second_prompt);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "confdb_get_string failed, using defaults");
++        }
++
++        ret = pc_list_add_2fa(pc_list, first_prompt, second_prompt);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "pc_list_add_2fa failed.\n");
++        }
++        return ret;
++    }
++
++    return ENOENT;
++}
++
++static errno_t pam_set_prompting_options(struct confdb_ctx *cdb,
++                                         const char *service_name,
++                                         char **sections,
++                                         int num_sections,
++                                         const char *section_path,
++                                         pam_set_prompting_fn_t *setter,
++                                         struct prompt_config ***pc_list)
++{
++    char *dummy;
++    size_t c;
++    bool global = false;
++    bool specific = false;
++    char *section = NULL;
++    int ret;
++    char *last;
++    TALLOC_CTX *tmp_ctx = NULL;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++
++    dummy = talloc_asprintf(tmp_ctx, "%s/%s", section_path,
++                                              service_name);
++    for (c = 0; c < num_sections; c++) {
++        if (strcmp(sections[c], CONFDB_PC_TYPE_PASSWORD) == 0) {
++            global = true;
++        }
++        if (dummy != NULL && strcmp(sections[c], dummy) == 0) {
++            specific = true;
++        }
++    }
++
++    section = talloc_asprintf(tmp_ctx, "%s/%s", CONFDB_PC_CONF_ENTRY, dummy);
++    if (section == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = ENOENT;
++    if (specific) {
++        ret = setter(tmp_ctx, cdb, section, pc_list);
++    }
++    if (global && ret == ENOENT) {
++        last = strrchr(section, '/');
++        if (last != NULL) {
++            *last = '\0';
++            ret = setter(tmp_ctx, cdb, section, pc_list);
++        }
++    }
++    if (ret != EOK && ret != ENOENT) {
++        DEBUG(SSSDBG_OP_FAILURE, "setter failed.\n");
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    talloc_free(tmp_ctx);
++    return ret;
++}
++
++errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd)
++{
++    int ret;
++    struct response_data *resp;
++    bool password_auth = false;
++    bool otp_auth = false;
++    bool cert_auth = false;
++    struct prompt_config **pc_list = NULL;
++    int resp_len;
++    uint8_t *resp_data = NULL;
++
++    if (pctx->num_prompting_config_sections == 0) {
++        DEBUG(SSSDBG_TRACE_ALL, "No prompting configuration found.\n");
++        return EOK;
++    }
++
++    resp = pd->resp_list;
++    while (resp != NULL) {
++        switch (resp->type) {
++        case SSS_PAM_OTP_INFO:
++            otp_auth = true;
++            break;
++        case SSS_PAM_CERT_INFO:
++            cert_auth = true;
++            break;
++        case SSS_PASSWORD_PROMPTING:
++            password_auth = true;
++            break;
++        case SSS_CERT_AUTH_PROMPTING:
++            /* currently not used */
++            break;
++        default:
++            break;
++        }
++        resp = resp->next;
++    }
++
++    if (!password_auth && !otp_auth && !cert_auth) {
++        /* If the backend cannot determine which authentication types are
++         * available the default would be to prompt for a password. */
++        password_auth = true;
++    }
++
++    DEBUG(SSSDBG_TRACE_ALL, "Authentication types for user [%s] and service "
++                            "[%s]:%s%s%s\n", pd->user, pd->service,
++                            password_auth ? " password": "",
++                            otp_auth ? " two-factor" : "",
++                            cert_auth ? " smartcard" : "");
++
++    if (cert_auth) {
++        /* If certificate based authentication is possilbe, i.e. a Smartcard
++         * or similar with the mapped certificate is available we currently
++         * prefer this authentication type unconditionally. If other types
++         * should be used the Smartcard can be removed during authentication.
++         * Since there currently are no specific options for cert_auth we are
++         * done. */
++        ret = EOK;
++        goto done;
++    }
++
++    /* If OTP and password auth are possible we currently prefer OTP. */
++    if (otp_auth) {
++        ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service,
++                                        pctx->prompting_config_sections,
++                                        pctx->num_prompting_config_sections,
++                                        CONFDB_PC_TYPE_2FA,
++                                        pam_set_2fa_prompting_options,
++                                        &pc_list);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "pam_set_prompting_options failed.\n");
++            goto done;
++        }
++    }
++
++    if (password_auth) {
++        ret = pam_set_prompting_options(pctx->rctx->cdb, pd->service,
++                                        pctx->prompting_config_sections,
++                                        pctx->num_prompting_config_sections,
++                                        CONFDB_PC_TYPE_PASSWORD,
++                                        pam_set_password_prompting_options,
++                                        &pc_list);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "pam_set_prompting_options failed.\n");
++            goto done;
++        }
++    }
++
++    if (pc_list != NULL) {
++        ret = pam_get_response_prompt_config(pc_list, &resp_len, &resp_data);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "pam_get_response_prompt_config failed.\n");
++            goto done;
++        }
++
++        ret = pam_add_response(pd, SSS_PAM_PROMPT_CONFIG, resp_len, resp_data);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "pam_add_response failed.\n");
++            goto done;
++        }
++    }
++
++    ret = EOK;
++done:
++    free(resp_data);
++    pc_list_free(pc_list);
++
++    return ret;
++}
+diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
+index 4ddd1d0b3..fb799d28b 100644
+--- a/src/responder/pam/pamsrv.c
++++ b/src/responder/pam/pamsrv.c
+@@ -315,6 +315,16 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
+         goto done;
+     }
+ 
++    /* Check if there is a prompting configuration */
++    pctx->prompting_config_sections = NULL;
++    pctx->num_prompting_config_sections = 0;
++    ret = confdb_get_sub_sections(pctx, pctx->rctx->cdb, CONFDB_PC_CONF_ENTRY,
++                                  &pctx->prompting_config_sections,
++                                  &pctx->num_prompting_config_sections);
++    if (ret != EOK && ret != ENOENT) {
++        DEBUG(SSSDBG_OP_FAILURE, "confdb_get_sub_sections failed, not fatal.\n");
++    }
++
+     /* Check if certificate based authentication is enabled */
+     ret = confdb_get_bool(pctx->rctx->cdb,
+                           CONFDB_PAM_CONF_ENTRY,
+@@ -346,11 +356,15 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
+             goto done;
+         }
+ 
++    }
++
++    if (pctx->cert_auth || pctx->num_prompting_config_sections != 0) {
+         ret = create_preauth_indicator();
+         if (ret != EOK) {
+             DEBUG(SSSDBG_OP_FAILURE,
+                   "Failed to create pre-authentication indicator file, "
+-                  "Smartcard authentication might not work as expected.\n");
++                  "Smartcard authentication or configured prompting might "
++                  "not work as expected.\n");
+         }
+     }
+ 
+diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
+index 3325d9b9f..319362a95 100644
+--- a/src/responder/pam/pamsrv.h
++++ b/src/responder/pam/pamsrv.h
+@@ -52,6 +52,9 @@ struct pam_ctx {
+     char *nss_db;
+     struct sss_certmap_ctx *sss_certmap_ctx;
+     char **smartcard_services;
++
++    char **prompting_config_sections;
++    int num_prompting_config_sections;
+ };
+ 
+ struct pam_auth_dp_req {
+@@ -130,4 +133,7 @@ pam_set_last_online_auth_with_curr_token(struct sss_domain_info *domain,
+ errno_t filter_responses(struct confdb_ctx *cdb,
+                          struct response_data *resp_list,
+                          struct pam_data *pd);
++
++errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd);
++
+ #endif /* __PAMSRV_H__ */
+diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
+index 6f3a7e56b..6b2dc5bdc 100644
+--- a/src/responder/pam/pamsrv_cmd.c
++++ b/src/responder/pam/pamsrv_cmd.c
+@@ -1003,6 +1003,14 @@ static void pam_reply(struct pam_auth_req *preq)
+         }
+     }
+ 
++    if (pd->cmd == SSS_PAM_PREAUTH) {
++        ret = pam_eval_prompting_config(pctx, pd);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "Failed to add prompting information, "
++                                     "using defaults.\n");
++        }
++    }
++
+     /*
+      * Export non-overridden shell to tlog-rec-session when opening the session
+      */
+-- 
+2.19.1
+
diff --git a/SOURCES/0020-SUDO-Create-the-socket-with-stricter-permissions.patch b/SOURCES/0020-SUDO-Create-the-socket-with-stricter-permissions.patch
deleted file mode 100644
index 0b81675..0000000
--- a/SOURCES/0020-SUDO-Create-the-socket-with-stricter-permissions.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From e13d53326bc154c684ea1bef9efc5922b5228945 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 15 Jun 2018 22:29:34 +0200
-Subject: [PATCH] SUDO: Create the socket with stricter permissions
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This patch switches the sudo responder from being created as a public
-responder where the permissions are open and not checked by the sssd
-deaamon to a private socket. In this case, sssd creates the pipes with
-strict permissions (see the umask in the call to create_pipe_fd() in
-set_unix_socket()) and additionaly checks the permissions with every read
-via the tevent integrations (see accept_fd_handler()).
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3766 (CVE-2018-10852)
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-(cherry picked from commit ed90a20a0f0e936eb00d268080716c0384ffb01d)
-
-DOWNSTREAM:
-Resolves: rhbz#1590603 - EMBARGOED CVE-2018-10852 sssd: information leak from the sssd-sudo responder [rhel-7]
----
- src/responder/sudo/sudosrv.c         | 3 ++-
- src/sysv/systemd/sssd-sudo.socket.in | 1 +
- 2 files changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
-index ac4258710d3a9b48285522abd23bdd59ba42ad4e..e87a24499c2d82fafaa8e1f9b386e44332394266 100644
---- a/src/responder/sudo/sudosrv.c
-+++ b/src/responder/sudo/sudosrv.c
-@@ -79,7 +79,8 @@ int sudo_process_init(TALLOC_CTX *mem_ctx,
-     sudo_cmds = get_sudo_cmds();
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            sudo_cmds,
--                           SSS_SUDO_SOCKET_NAME, -1, NULL, -1,
-+                           NULL, -1,                   /* No public socket */
-+                           SSS_SUDO_SOCKET_NAME, -1,   /* Private socket only */
-                            CONFDB_SUDO_CONF_ENTRY,
-                            SSS_SUDO_SBUS_SERVICE_NAME,
-                            SSS_SUDO_SBUS_SERVICE_VERSION,
-diff --git a/src/sysv/systemd/sssd-sudo.socket.in b/src/sysv/systemd/sssd-sudo.socket.in
-index c9abb875f0accbaf58d78846020fef74c7473528..96a8b0327ddb4d331c9b2e97ece3453f8f76872d 100644
---- a/src/sysv/systemd/sssd-sudo.socket.in
-+++ b/src/sysv/systemd/sssd-sudo.socket.in
-@@ -11,6 +11,7 @@ ExecStartPre=@libexecdir@/sssd/sssd_check_socket_activated_responders -r sudo
- ListenStream=@pipepath@/sudo
- SocketUser=@SSSD_USER@
- SocketGroup=@SSSD_USER@
-+SocketMode=0600
- 
- [Install]
- WantedBy=sssd.service
--- 
-2.17.1
-
diff --git a/SOURCES/0020-getsockopt_wrapper-add-support-for-PAM-clients.patch b/SOURCES/0020-getsockopt_wrapper-add-support-for-PAM-clients.patch
new file mode 100644
index 0000000..6e1fd70
--- /dev/null
+++ b/SOURCES/0020-getsockopt_wrapper-add-support-for-PAM-clients.patch
@@ -0,0 +1,80 @@
+From c8d517bacd47f3d5c706a53561924ac20d0b3321 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 7 Sep 2018 22:19:26 +0200
+Subject: [PATCH 20/21] getsockopt_wrapper: add support for PAM clients
+
+PAM clients expect that the private socket of the PAM responder is
+handled by root. With this patch getsockopt_wrapper can return the
+expected UID and GID to PAM clients.
+
+Related to https://pagure.io/SSSD/sssd/issue/3500
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked with fixes from commit d332c8a0e7a4c7f0b3ee1b2110145a23cbd61c2a)
+---
+ src/tests/intg/getsockopt_wrapper.c | 35 +++++++++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+
+diff --git a/src/tests/intg/getsockopt_wrapper.c b/src/tests/intg/getsockopt_wrapper.c
+index 77c832329..eb8fa56dd 100644
+--- a/src/tests/intg/getsockopt_wrapper.c
++++ b/src/tests/intg/getsockopt_wrapper.c
+@@ -9,6 +9,7 @@
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <dlfcn.h>
++#include <stdlib.h>
+ 
+ static bool is_dbus_socket(int fd)
+ {
+@@ -27,6 +28,38 @@ static bool is_dbus_socket(int fd)
+     return NULL != strstr(unix_socket->sun_path, "system_bus_socket");
+ }
+ 
++static bool peer_is_private_pam(int fd)
++{
++    int ret;
++    struct sockaddr_storage addr = { 0 };
++    socklen_t addrlen = sizeof(addr);
++    struct sockaddr_un *unix_socket;
++
++    ret = getpeername(fd, (struct sockaddr *)&addr, &addrlen);
++    if (ret != 0) return false;
++
++    if (addr.ss_family != AF_UNIX) return false;
++
++    unix_socket = (struct sockaddr_un *)&addr;
++
++    return NULL != strstr(unix_socket->sun_path, "private/pam");
++}
++
++static void fake_peer_uid_gid(uid_t *uid, gid_t *gid)
++{
++    char *val;
++
++    val = getenv("SSSD_INTG_PEER_UID");
++    if (val != NULL) {
++        *uid = atoi(val);
++    }
++
++    val = getenv("SSSD_INTG_PEER_GID");
++    if (val != NULL) {
++        *gid = atoi(val);
++    }
++}
++
+ typedef typeof(getsockopt) getsockopt_fn_t;
+ 
+ static getsockopt_fn_t *orig_getsockopt = NULL;
+@@ -52,6 +85,8 @@ int getsockopt(int sockfd, int level, int optname,
+         cr = optval;
+         if (cr->uid != 0 && is_dbus_socket(sockfd)) {
+             cr->uid = 0;
++        } else if (peer_is_private_pam(sockfd)) {
++            fake_peer_uid_gid(&cr->uid, &cr->gid);
+         }
+     }
+ 
+-- 
+2.19.1
+
diff --git a/SOURCES/0021-MAN-Give-information-regarding-priority-of-ldap-look.patch b/SOURCES/0021-MAN-Give-information-regarding-priority-of-ldap-look.patch
deleted file mode 100644
index 56e7687..0000000
--- a/SOURCES/0021-MAN-Give-information-regarding-priority-of-ldap-look.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 7689f3c8b4661c16a019c4410b1557f6ae4229aa Mon Sep 17 00:00:00 2001
-From: amitkumar50 <amitkuma@redhat.com>
-Date: Fri, 15 Jun 2018 10:45:38 +0530
-Subject: [PATCH] MAN: Give information regarding priority of ldap lookup
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This PR provides information about priority of lookup
-similar to as provided by function select_principal_from_keytab().
-
-Resolves: https://pagure.io/SSSD/sssd/issue/3475
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-(cherry picked from commit c5ef56b4f9ffb361742edae36b261a4ffd0e75ae)
-
-DOWNSTREAM:
-Resolves: rhbz#1450778 - Full information regarding priority of lookup of principal in keytab not in man page
----
- src/man/sssd-ldap.5.xml | 13 ++++++++++++-
- 1 file changed, 12 insertions(+), 1 deletion(-)
-
-diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
-index f7617670c8b0fe1a5922c1a811b94e25bacecbfe..3145f0730341bf40159277ef2ae23be601154a89 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -1778,7 +1778,18 @@
-                             principal used for authentication to the directory.
-                             This option can either contain the full principal (for
-                             example host/myhost@EXAMPLE.COM) or just the principal name
--                            (for example host/myhost).
-+                            (for example host/myhost). By default, the value is not set
-+                            and the following principals are used:
-+                            <programlisting>
-+hostname@REALM
-+netbiosname$@REALM
-+host/hostname@REALM
-+*$@REALM
-+host/*@REALM
-+host/*
-+                            </programlisting>
-+                            If none of them are found, the first principal in keytab is
-+                            returned.
-                         </para>
-                         <para>
-                             Default: host/hostname@REALM
--- 
-2.17.1
-
diff --git a/SOURCES/0021-intg-add-test-for-password-prompt-configuration.patch b/SOURCES/0021-intg-add-test-for-password-prompt-configuration.patch
new file mode 100644
index 0000000..d98cc65
--- /dev/null
+++ b/SOURCES/0021-intg-add-test-for-password-prompt-configuration.patch
@@ -0,0 +1,261 @@
+From abfba08af067f70b736108310c3e55534ef7085e Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 29 Mar 2019 10:38:50 +0100
+Subject: [PATCH 21/21] intg: add test for password prompt configuration
+
+Related to Related to https://pagure.io/SSSD/sssd/issue/3264
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked with fixes from commit 45efba71befd96c8e9fe0a51fc300cafa93bd703)
+---
+ src/tests/intg/Makefile.am           |  32 +++++-
+ src/tests/intg/test_pam_responder.py | 154 ++++++++++++++++++++++++++-
+ 2 files changed, 184 insertions(+), 2 deletions(-)
+
+diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am
+index 91dc86a4f..884c903b6 100644
+--- a/src/tests/intg/Makefile.am
++++ b/src/tests/intg/Makefile.am
+@@ -105,13 +105,36 @@ passwd: root
+ group:
+ 	echo "root:x:0:" > $@
+ 
++PAM_SERVICE_DIR=pam_service_dir
++pam_sss_service:
++	$(MKDIR_P) $(PAM_SERVICE_DIR)
++	echo "auth     required       $(DESTDIR)$(pammoddir)/pam_sss.so"  > $(PAM_SERVICE_DIR)/$@
++	echo "account  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
++	echo "password required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
++	echo "session  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
++
++pam_sss_alt_service:
++	$(MKDIR_P) $(PAM_SERVICE_DIR)
++	echo "auth     required       $(DESTDIR)$(pammoddir)/pam_sss.so"  > $(PAM_SERVICE_DIR)/$@
++	echo "account  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
++	echo "password required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
++	echo "session  required       $(DESTDIR)$(pammoddir)/pam_sss.so" >> $(PAM_SERVICE_DIR)/$@
++
+ CLEANFILES=config.py config.pyc passwd group
+ 
+ clean-local:
+ 	rm -Rf root
+ 	rm -f $(builddir)/cwrap-dbus-system.conf
+ 
+-intgcheck-installed: config.py passwd group
++if HAVE_NSS
++PAM_CERT_DB_PATH="sql:$(DESTDIR)$(sysconfdir)/pki/nssdb"
++SOFTHSM2_CONF=""
++else
++PAM_CERT_DB_PATH="$(abs_builddir)/../test_CA/SSSD_test_CA.pem"
++SOFTHSM2_CONF="$(abs_builddir)/../test_CA/softhsm2_one.conf"
++endif
++
++intgcheck-installed: config.py passwd group pam_sss_service pam_sss_alt_service
+ 	pipepath="$(DESTDIR)$(pipepath)"; \
+ 	if test $${#pipepath} -gt 80; then \
+ 	    echo "error: Pipe directory path too long," \
+@@ -126,16 +149,23 @@ intgcheck-installed: config.py passwd group
+ 	PATH="$$(dirname -- $(SLAPD)):$$PATH" \
+ 	PATH="$(DESTDIR)$(sbindir):$(DESTDIR)$(bindir):$$PATH" \
+ 	PATH="$$PATH:$(abs_builddir):$(abs_srcdir)" \
++	LANG=C \
+ 	PYTHONPATH="$(abs_builddir):$(abs_srcdir)" \
+ 	LDB_MODULES_PATH="$(DESTDIR)$(ldblibdir)" \
+ 	NON_WRAPPED_UID=$$(id -u) \
+ 	LD_PRELOAD="$(libdir)/getsockopt_wrapper.so:$$nss_wrapper:$$uid_wrapper" \
++	LD_LIBRARY_PATH="$$LD_LIBRARY_PATH:$(DESTDIR)$(nsslibdir)" \
+ 	NSS_WRAPPER_PASSWD="$(abs_builddir)/passwd" \
+ 	NSS_WRAPPER_GROUP="$(abs_builddir)/group" \
+ 	NSS_WRAPPER_MODULE_SO_PATH="$(DESTDIR)$(nsslibdir)/libnss_sss.so.2" \
+ 	NSS_WRAPPER_MODULE_FN_PREFIX="sss" \
+ 	UID_WRAPPER=1 \
+ 	UID_WRAPPER_ROOT=1 \
++	PAM_WRAPPER=0 \
++	PAM_WRAPPER_SERVICE_DIR="$(abs_builddir)/$(PAM_SERVICE_DIR)" \
++	PAM_WRAPPER_PATH=$$(pkg-config --libs pam_wrapper) \
++	PAM_CERT_DB_PATH=$(PAM_CERT_DB_PATH) \
++	SOFTHSM2_CONF=$(SOFTHSM2_CONF) \
+ 	DBUS_SOCK_DIR="$(DESTDIR)$(runstatedir)/dbus/" \
+ 	DBUS_SESSION_BUS_ADDRESS="unix:path=$$DBUS_SOCK_DIR/fake_socket" \
+ 	DBUS_SYSTEM_BUS_ADDRESS="unix:path=$$DBUS_SOCK_DIR/system_bus_socket" \
+diff --git a/src/tests/intg/test_pam_responder.py b/src/tests/intg/test_pam_responder.py
+index cf6fff2db..7e5828dde 100644
+--- a/src/tests/intg/test_pam_responder.py
++++ b/src/tests/intg/test_pam_responder.py
+@@ -30,9 +30,84 @@ import time
+ import pytest
+ 
+ import config
+-
++import shutil
+ from util import unindent
+ 
++import intg.ds_openldap
++
++import pytest
++
++from intg.util import unindent
++from intg.files_ops import passwd_ops_setup
++
++LDAP_BASE_DN = "dc=example,dc=com"
++
++
++@pytest.fixture(scope="module")
++def ad_inst(request):
++    """Fake AD server instance fixture"""
++    instance = intg.ds_openldap.FakeAD(
++        config.PREFIX, 10389, LDAP_BASE_DN,
++        "cn=admin", "Secret123"
++    )
++
++    try:
++        instance.setup()
++    except:
++        instance.teardown()
++        raise
++    request.addfinalizer(instance.teardown)
++    return instance
++
++
++@pytest.fixture(scope="module")
++def ldap_conn(request, ad_inst):
++    """LDAP server connection fixture"""
++    ldap_conn = ad_inst.bind()
++    ldap_conn.ad_inst = ad_inst
++    request.addfinalizer(ldap_conn.unbind_s)
++    return ldap_conn
++
++
++def format_basic_conf(ldap_conn):
++    """Format a basic SSSD configuration"""
++    return unindent("""\
++        [sssd]
++        domains = FakeAD
++        services = pam, nss
++
++        [nss]
++
++        [pam]
++        debug_level = 10
++
++        [domain/FakeAD]
++        debug_level = 10
++        ldap_search_base = {ldap_conn.ad_inst.base_dn}
++        ldap_referrals = false
++
++        id_provider = ldap
++        auth_provider = ldap
++        chpass_provider = ldap
++        access_provider = ldap
++
++        ldap_uri = {ldap_conn.ad_inst.ldap_url}
++        ldap_default_bind_dn = {ldap_conn.ad_inst.admin_dn}
++        ldap_default_authtok_type = password
++        ldap_default_authtok = {ldap_conn.ad_inst.admin_pw}
++
++        ldap_schema = ad
++        ldap_id_mapping = true
++        ldap_idmap_default_domain_sid = S-1-5-21-1305200397-2901131868-73388776
++        case_sensitive = False
++
++        [prompting/password]
++        password_prompt = My global prompt
++
++        [prompting/password/pam_sss_alt_service]
++        password_prompt = My alt service prompt
++    """).format(**locals())
++
+ 
+ def format_pam_cert_auth_conf():
+     """Format a basic SSSD configuration"""
+@@ -79,6 +154,8 @@ def create_conf_fixture(request, contents):
+ 
+ def create_sssd_process():
+     """Start the SSSD process"""
++    os.environ["SSS_FILES_PASSWD"] = os.environ["NSS_WRAPPER_PASSWD"]
++    os.environ["SSS_FILES_GROUP"] = os.environ["NSS_WRAPPER_GROUP"]
+     if subprocess.call(["sssd", "-D", "-f"]) != 0:
+         raise Exception("sssd start failed")
+ 
+@@ -129,3 +206,78 @@ def test_preauth_indicator(simple_pam_cert_auth):
+     """Check if preauth indicator file is created"""
+     statinfo = os.stat(config.PUBCONF_PATH + "/pam_preauth_available")
+     assert stat.S_ISREG(statinfo.st_mode)
++
++
++@pytest.fixture
++def pam_prompting_config(request, ldap_conn):
++    """Setup SSSD with PAM prompting config"""
++    conf = format_basic_conf(ldap_conn)
++    create_conf_fixture(request, conf)
++    create_sssd_fixture(request)
++    return None
++
++
++def test_password_prompting_config_global(ldap_conn, pam_prompting_config,
++                                          env_for_sssctl):
++    """Check global change of the password prompt"""
++
++    sssctl = subprocess.Popen(["sssctl", "user-checks", "user1_dom1-19661",
++                               "--action=auth", "--service=pam_sss_service"],
++                              universal_newlines=True,
++                              env=env_for_sssctl, stdin=subprocess.PIPE,
++                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
++
++    try:
++        out, err = sssctl.communicate(input="111")
++    except:
++        sssctl.kill()
++        out, err = sssctl.communicate()
++
++    sssctl.stdin.close()
++    sssctl.stdout.close()
++
++    if sssctl.wait() != 0:
++        raise Exception("sssctl failed")
++
++    assert err.find("My global prompt") != -1
++
++
++def test_password_prompting_config_srv(ldap_conn, pam_prompting_config,
++                                       env_for_sssctl):
++    """Check change of the password prompt for dedicated service"""
++
++    sssctl = subprocess.Popen(["sssctl", "user-checks", "user1_dom1-19661",
++                               "--action=auth",
++                               "--service=pam_sss_alt_service"],
++                              universal_newlines=True,
++                              env=env_for_sssctl, stdin=subprocess.PIPE,
++                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
++
++    try:
++        out, err = sssctl.communicate(input="111")
++    except:
++        sssctl.kill()
++        out, err = sssctl.communicate()
++
++    sssctl.stdin.close()
++    sssctl.stdout.close()
++
++    if sssctl.wait() != 0:
++        raise Exception("sssctl failed")
++
++    assert err.find("My alt service prompt") != -1
++
++
++@pytest.fixture
++def env_for_sssctl(request):
++    pwrap_runtimedir = os.getenv("PAM_WRAPPER_SERVICE_DIR")
++    if pwrap_runtimedir is None:
++        raise ValueError("The PAM_WRAPPER_SERVICE_DIR variable is unset\n")
++
++    env_for_sssctl = os.environ.copy()
++    env_for_sssctl['PAM_WRAPPER'] = "1"
++    env_for_sssctl['SSSD_INTG_PEER_UID'] = "0"
++    env_for_sssctl['SSSD_INTG_PEER_GID'] = "0"
++    env_for_sssctl['LD_PRELOAD'] += ':' + os.environ['PAM_WRAPPER_PATH']
++
++    return env_for_sssctl
+-- 
+2.19.1
+
diff --git a/SOURCES/0022-AD-LDAP-Do-not-misuse-the-ignore_mark_offline-to-che.patch b/SOURCES/0022-AD-LDAP-Do-not-misuse-the-ignore_mark_offline-to-che.patch
deleted file mode 100644
index 2806c55..0000000
--- a/SOURCES/0022-AD-LDAP-Do-not-misuse-the-ignore_mark_offline-to-che.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From 7b8ed13c2bac164fdc49227d1b51364bdf907a98 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 19 Jun 2018 16:09:30 +0200
-Subject: [PATCH] AD/LDAP: Do not misuse the ignore_mark_offline to check if a
- connection needs to be checked for POSIX attribute presence
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The logic behind deciding whether to check if a server contains any
-POSIX attributes used the ignore_mark_offline flag. This was OK for some
-time, because this flag was only set for to true for Global Catalog
-connections, which are those that we need to check.
-
-However, in recent releases, the flag was also set for any connection
-towards a trusted domain. This had the unintended effect that any
-lookup, LDAP or GC against a trusted domain ran the wide POSIX presence
-check.
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3754
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 5e1641b104f159f9fa47c3008d84119dfd5ab226)
-
-DOWNSTREAM:
-Resolves: rhbz#1583725 - SSSD AD uses LDAP filter to detect POSIX attributes stored in AD GC also for regular AD DC queries
----
- src/providers/ad/ad_common.c     | 2 ++
- src/providers/ldap/ldap_common.c | 2 +-
- src/providers/ldap/ldap_common.h | 2 ++
- 3 files changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
-index 8caaba6c0d06cfe83d9741536192d662fc936273..feeb5d09643a02b99be1a387b41842a034a323b8 100644
---- a/src/providers/ad/ad_common.c
-+++ b/src/providers/ad/ad_common.c
-@@ -1408,6 +1408,7 @@ 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++;
-     }
- 
-@@ -1454,6 +1455,7 @@ 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 15377ee1f062c0167aabee30ef0757ebe7271682..a0a9b8523310b2551ee992f8d0c2e369dafaa56d 100644
---- a/src/providers/ldap/ldap_common.c
-+++ b/src/providers/ldap/ldap_common.c
-@@ -893,7 +893,7 @@ bool should_run_posix_check(struct sdap_id_ctx *ctx,
-     if (use_id_mapping == false &&
-             posix_request == true &&
-             ctx->opts->schema_type == SDAP_SCHEMA_AD &&
--            conn->ignore_mark_offline == true &&
-+            conn->check_posix_attrs == true &&
-             ctx->srv_opts &&
-             ctx->srv_opts->posix_checked == false) {
-         return true;
-diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
-index 3cefdd0bfb0e96b5a7f904fe753dfc457b2a45c2..3de3568cb28c258c00f9b522c0b9120adca81d81 100644
---- a/src/providers/ldap/ldap_common.h
-+++ b/src/providers/ldap/ldap_common.h
-@@ -59,6 +59,8 @@ 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 {
--- 
-2.17.1
-
diff --git a/SOURCES/0022-krb5-Write-multiple-dnsnames-into-kdc-info-file.patch b/SOURCES/0022-krb5-Write-multiple-dnsnames-into-kdc-info-file.patch
new file mode 100644
index 0000000..3a2fcf6
--- /dev/null
+++ b/SOURCES/0022-krb5-Write-multiple-dnsnames-into-kdc-info-file.patch
@@ -0,0 +1,432 @@
+From f61c92c399531a5530dbb57a36b4e0db46c72b5b Mon Sep 17 00:00:00 2001
+From: Tomas Halman <thalman@redhat.com>
+Date: Wed, 13 Mar 2019 08:37:36 +0100
+Subject: [PATCH 22/23] krb5: Write multiple dnsnames into kdc info file
+
+Multiple servers should be written to kdc info file. In
+this PR we iterate trough server list and we write
+list of primary servers followed by backup servers.
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3974
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 208a79a83c76b6693bdf927c3d7d6267e3218b0b)
+---
+ src/providers/ad/ad_common.c       |  39 +++++----
+ src/providers/fail_over.c          |  27 ++++++
+ src/providers/fail_over.h          |   9 ++
+ src/providers/ipa/ipa_common.c     |  25 +-----
+ src/providers/ipa/ipa_subdomains.c |   4 +-
+ src/providers/krb5/krb5_common.c   | 131 ++++++++++++++++++++---------
+ src/providers/krb5/krb5_common.h   |   7 +-
+ 7 files changed, 158 insertions(+), 84 deletions(-)
+
+diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
+index 0d154ca57..b7f34daa9 100644
+--- a/src/providers/ad/ad_common.c
++++ b/src/providers/ad/ad_common.c
+@@ -24,6 +24,7 @@
+ #include "providers/ad/ad_common.h"
+ #include "providers/ad/ad_opts.h"
+ #include "providers/be_dyndns.h"
++#include "providers/fail_over.h"
+ 
+ struct ad_server_data {
+     bool gc;
+@@ -839,6 +840,20 @@ done:
+     return ret;
+ }
+ 
++static bool
++ad_krb5info_file_filter(struct fo_server *server)
++{
++    struct ad_server_data *sdata = NULL;
++    if (server == NULL) return true;
++
++    sdata = fo_get_server_user_data(server);
++    if (sdata && sdata->gc) {
++        /* Only write kdcinfo files for local servers */
++        return true;
++    }
++    return false;
++}
++
+ static void
+ ad_resolve_callback(void *private_data, struct fo_server *server)
+ {
+@@ -848,7 +863,6 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
+     struct resolv_hostent *srvaddr;
+     struct sockaddr_storage *sockaddr;
+     char *address;
+-    char *safe_addr_list[2] = { NULL, NULL };
+     char *new_uri;
+     int new_port;
+     const char *srv_name;
+@@ -953,25 +967,14 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
+         goto done;
+     }
+ 
+-    /* Only write kdcinfo files for local servers */
+-    if ((sdata == NULL || sdata->gc == false) &&
+-        service->krb5_service->write_kdcinfo) {
+-        /* Write krb5 info files */
+-        safe_addr_list[0] = sss_escape_ip_address(tmp_ctx,
+-                                                  srvaddr->family,
+-                                                  address);
+-        if (safe_addr_list[0] == NULL) {
+-            DEBUG(SSSDBG_CRIT_FAILURE, "sss_escape_ip_address failed.\n");
+-            ret = ENOMEM;
+-            goto done;
+-        }
+-
+-        ret = write_krb5info_file(service->krb5_service,
+-                                  safe_addr_list,
+-                                  SSS_KRB5KDC_FO_SRV);
++    if (service->krb5_service->write_kdcinfo) {
++        ret = write_krb5info_file_from_fo_server(service->krb5_service,
++                                                 server,
++                                                 SSS_KRB5KDC_FO_SRV,
++                                                 ad_krb5info_file_filter);
+         if (ret != EOK) {
+             DEBUG(SSSDBG_MINOR_FAILURE,
+-                "write_krb5info_file failed, authentication might fail.\n");
++                  "write_krb5info_file failed, authentication might fail.\n");
+         }
+     }
+ 
+diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
+index 168e59d6f..dc5c7c7d8 100644
+--- a/src/providers/fail_over.c
++++ b/src/providers/fail_over.c
+@@ -1637,6 +1637,33 @@ fo_get_server_hostname_last_change(struct fo_server *server)
+     return server->common->last_status_change.tv_sec;
+ }
+ 
++struct fo_server *fo_server_first(struct fo_server *server)
++{
++    if (!server) return NULL;
++
++    while (server->prev) { server = server->prev; }
++    return server;
++}
++
++struct fo_server *fo_server_next(struct fo_server *server)
++{
++    if (!server) return NULL;
++
++    return server->next;
++}
++
++size_t fo_server_count(struct fo_server *server)
++{
++    struct fo_server *item = fo_server_first(server);
++    size_t size = 0;
++
++    while (item) {
++        ++size;
++        item = item->next;
++    }
++    return size;
++}
++
+ time_t fo_get_service_retry_timeout(struct fo_service *svc)
+ {
+     if (svc == NULL || svc->ctx == NULL || svc->ctx->opts == NULL) {
+diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h
+index d70212fb7..bc8142710 100644
+--- a/src/providers/fail_over.h
++++ b/src/providers/fail_over.h
+@@ -216,6 +216,15 @@ const char **fo_svc_server_list(TALLOC_CTX *mem_ctx,
+                                 struct fo_service *service,
+                                 size_t *_count);
+ 
++/*
++ * Folowing functions allow to iterate trough list of servers.
++ */
++struct fo_server *fo_server_first(struct fo_server *server);
++
++struct fo_server *fo_server_next(struct fo_server *server);
++
++size_t fo_server_count(struct fo_server *server);
++
+ /*
+  * pvt will be talloc_stealed to ctx
+  */
+diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
+index 17d14e6b0..1ed2e2203 100644
+--- a/src/providers/ipa/ipa_common.c
++++ b/src/providers/ipa/ipa_common.c
+@@ -819,8 +819,6 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server)
+     struct ipa_service *service;
+     struct resolv_hostent *srvaddr;
+     struct sockaddr_storage *sockaddr;
+-    char *address;
+-    char *safe_addr_list[2] = { NULL, NULL };
+     char *new_uri;
+     const char *srv_name;
+     int ret;
+@@ -854,13 +852,6 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server)
+         return;
+     }
+ 
+-    address = resolv_get_string_address(tmp_ctx, srvaddr);
+-    if (address == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_string_address failed.\n");
+-        talloc_free(tmp_ctx);
+-        return;
+-    }
+-
+     srv_name = fo_get_server_name(server);
+     if (srv_name == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Could not get server host name\n");
+@@ -883,18 +874,10 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server)
+     service->sdap->sockaddr = talloc_steal(service, sockaddr);
+ 
+     if (service->krb5_service->write_kdcinfo) {
+-        safe_addr_list[0] = sss_escape_ip_address(tmp_ctx,
+-                                             srvaddr->family,
+-                                             address);
+-        if (safe_addr_list[0] == NULL) {
+-            DEBUG(SSSDBG_CRIT_FAILURE, "sss_escape_ip_address failed.\n");
+-            talloc_free(tmp_ctx);
+-            return;
+-        }
+-
+-        ret = write_krb5info_file(service->krb5_service,
+-                                  safe_addr_list,
+-                                  SSS_KRB5KDC_FO_SRV);
++        ret = write_krb5info_file_from_fo_server(service->krb5_service,
++                                                 server,
++                                                 SSS_KRB5KDC_FO_SRV,
++                                                 NULL);
+         if (ret != EOK) {
+             DEBUG(SSSDBG_OP_FAILURE,
+                   "write_krb5info_file failed, authentication might fail.\n");
+diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
+index d86ca4cc5..da1279e3e 100644
+--- a/src/providers/ipa/ipa_subdomains.c
++++ b/src/providers/ipa/ipa_subdomains.c
+@@ -2545,7 +2545,7 @@ static errno_t ipa_subdomains_write_kdcinfo_write_step(struct sss_domain_info *d
+     errno_t ret;
+     char *address = NULL;
+     char *safe_address = NULL;
+-    char **safe_addr_list;
++    const char **safe_addr_list;
+     int addr_index = 0;
+     TALLOC_CTX *tmp_ctx = NULL;
+ 
+@@ -2554,7 +2554,7 @@ static errno_t ipa_subdomains_write_kdcinfo_write_step(struct sss_domain_info *d
+         return ENOMEM;
+     }
+ 
+-    safe_addr_list = talloc_zero_array(tmp_ctx, char *, rhp_len+1);
++    safe_addr_list = talloc_zero_array(tmp_ctx, const char *, rhp_len+1);
+     if (safe_addr_list == NULL) {
+         ret = ENOMEM;
+         goto done;
+diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
+index 2b003e164..1e33fc0f5 100644
+--- a/src/providers/krb5/krb5_common.c
++++ b/src/providers/krb5/krb5_common.c
+@@ -33,6 +33,7 @@
+ #include "providers/krb5/krb5_common.h"
+ #include "providers/krb5/krb5_opts.h"
+ #include "providers/krb5/krb5_utils.h"
++#include "providers/fail_over.h"
+ 
+ #ifdef HAVE_KRB5_CC_COLLECTION
+ /* krb5 profile functions */
+@@ -592,7 +593,7 @@ done:
+ }
+ 
+ errno_t write_krb5info_file(struct krb5_service *krb5_service,
+-                            char **server_list,
++                            const char **server_list,
+                             const char *service)
+ {
+     int i;
+@@ -635,73 +636,119 @@ done:
+     return ret;
+ }
+ 
+-static void krb5_resolve_callback(void *private_data, struct fo_server *server)
++static const char* fo_server_address_or_name(TALLOC_CTX *tmp_ctx, struct fo_server *server)
+ {
+-    struct krb5_service *krb5_service;
+     struct resolv_hostent *srvaddr;
+     char *address;
+-    char *safe_addr_list[2] = { NULL, NULL };
+-    int ret;
++
++    if (!server) return NULL;
++
++    srvaddr = fo_get_server_hostent(server);
++    if (srvaddr) {
++        address = resolv_get_string_address(tmp_ctx, srvaddr);
++        if (address) {
++            return sss_escape_ip_address(tmp_ctx,
++                                         srvaddr->family,
++                                         address);
++        }
++    }
++
++    return fo_get_server_name(server);
++}
++
++errno_t write_krb5info_file_from_fo_server(struct krb5_service *krb5_service,
++                                           struct fo_server *server,
++                                           const char *service,
++                                           bool (*filter)(struct fo_server *))
++{
+     TALLOC_CTX *tmp_ctx = NULL;
++    const char **server_list;
++    size_t server_idx;
++    struct fo_server *item;
++    int primary;
++    const char *address;
++    errno_t ret;
+ 
+     tmp_ctx = talloc_new(NULL);
+     if (tmp_ctx == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed\n");
+-        return;
++        return ENOMEM;
+     }
+ 
+-    krb5_service = talloc_get_type(private_data, struct krb5_service);
+-    if (!krb5_service) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "FATAL: Bad private_data\n");
++    server_idx = 0;
++    server_list = talloc_zero_array(tmp_ctx,
++                                    const char *,
++                                    fo_server_count(server) + 1);
++    if (server_list == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array failed\n");
+         talloc_free(tmp_ctx);
+-        return;
++        return ENOMEM;
+     }
+ 
+-    srvaddr = fo_get_server_hostent(server);
+-    if (!srvaddr) {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
+-              "FATAL: No hostent available for server (%s)\n",
+-                  fo_get_server_str_name(server));
+-        talloc_free(tmp_ctx);
+-        return;
++    if (filter == NULL || filter(server) == false) {
++        address = fo_server_address_or_name(tmp_ctx, server);
++        if (address) {
++            server_list[server_idx++] = address;
++        } else {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Server without name and address found in list.\n");
++        }
+     }
+ 
+-    address = resolv_get_string_address(tmp_ctx, srvaddr);
+-    if (address == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_string_address failed.\n");
+-        talloc_free(tmp_ctx);
+-        return;
++    for (primary = 1; primary >= 0; --primary) {
++        for (item = fo_server_next(server) ? fo_server_next(server) : fo_server_first(server);
++             item != server;
++             item = fo_server_next(item) ? fo_server_next(item) : fo_server_first(item)) {
++
++            if (primary && !fo_is_server_primary(item)) continue;
++            if (!primary && fo_is_server_primary(item)) continue;
++            if (filter != NULL && filter(item)) continue;
++
++            address = fo_server_address_or_name(tmp_ctx, item);
++            if (address == NULL) {
++                DEBUG(SSSDBG_CRIT_FAILURE,
++                      "Server without name and address found in list.\n");
++                continue;
++            }
++
++            server_list[server_idx++] = address;
++        }
+     }
++    if (server_list[0] == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "There is no server that can be written into kdc info file.\n");
++        ret = EINVAL;
++    } else {
++        ret = write_krb5info_file(krb5_service,
++                                  server_list,
++                                  service);
++    }
++    talloc_free(tmp_ctx);
++    return ret;
++}
+ 
+-    safe_addr_list[0] = sss_escape_ip_address(tmp_ctx,
+-                                              srvaddr->family,
+-                                              address);
+-    if (safe_addr_list[0] == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "sss_escape_ip_address failed.\n");
+-        talloc_free(tmp_ctx);
++
++static void krb5_resolve_callback(void *private_data, struct fo_server *server)
++{
++    struct krb5_service *krb5_service;
++    int ret;
++
++    krb5_service = talloc_get_type(private_data, struct krb5_service);
++    if (!krb5_service) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "FATAL: Bad private_data\n");
+         return;
+     }
+ 
+     if (krb5_service->write_kdcinfo) {
+-        safe_addr_list[0] = talloc_asprintf_append(safe_addr_list[0], ":%d",
+-                                                   fo_get_server_port(server));
+-        if (safe_addr_list[0] == NULL) {
+-            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf_append failed.\n");
+-            talloc_free(tmp_ctx);
+-            return;
+-        }
+-
+-        ret = write_krb5info_file(krb5_service,
+-                                  safe_addr_list,
+-                                  krb5_service->name);
++        ret = write_krb5info_file_from_fo_server(krb5_service,
++                                                 server,
++                                                 krb5_service->name,
++                                                 NULL);
+         if (ret != EOK) {
+             DEBUG(SSSDBG_OP_FAILURE,
+                   "write_krb5info_file failed, authentication might fail.\n");
+         }
+     }
+-
+-    talloc_free(tmp_ctx);
+-    return;
+ }
+ 
+ static errno_t _krb5_servers_init(struct be_ctx *ctx,
+diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
+index bf36a551a..be541626b 100644
+--- a/src/providers/krb5/krb5_common.h
++++ b/src/providers/krb5/krb5_common.h
+@@ -161,9 +161,14 @@ errno_t sss_krb5_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb,
+                              const char *conf_path, struct dp_option **_opts);
+ 
+ errno_t write_krb5info_file(struct krb5_service *krb5_service,
+-                            char **server_list,
++                            const char **server_list,
+                             const char *service);
+ 
++errno_t write_krb5info_file_from_fo_server(struct krb5_service *krb5_service,
++                                           struct fo_server *server,
++                                           const char *service,
++                                           bool (*filter)(struct fo_server *));
++
+ struct krb5_service *krb5_service_new(TALLOC_CTX *mem_ctx,
+                                       struct be_ctx *be_ctx,
+                                       const char *service_name,
+-- 
+2.19.1
+
diff --git a/SOURCES/0023-AD-expose-the-helper-function-to-format-the-site-DNS.patch b/SOURCES/0023-AD-expose-the-helper-function-to-format-the-site-DNS.patch
deleted file mode 100644
index 4208977..0000000
--- a/SOURCES/0023-AD-expose-the-helper-function-to-format-the-site-DNS.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From 09fd8246f25dbfb80db638a0dd8f2fe4c1fba957 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 25 Jun 2018 13:03:38 +0200
-Subject: [PATCH] AD: expose the helper function to format the site DNS query
-
-This function will be used later in the patchset. Instead of exposing
-the format constant, expose the function that builds the DNS query for
-site discovery.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3291
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 29bbc8e017f2d9b98667890a9b7056128a93e572)
-
-DOWNSTREAM:
-Resolves: rhbz#1416528 - sssd in cross realm trust configuration should be able to use AD KDCs from a client site defined in sssd.conf or a snippet
----
- src/providers/ad/ad_srv.c | 21 +++++++++++++++------
- src/providers/ad/ad_srv.h |  4 ++++
- 2 files changed, 19 insertions(+), 6 deletions(-)
-
-diff --git a/src/providers/ad/ad_srv.c b/src/providers/ad/ad_srv.c
-index 4fa1668605e131b2e31802b1401f49fc6e00a23b..5fd25f60e8bf38c3952823601593515b6c703284 100644
---- a/src/providers/ad/ad_srv.c
-+++ b/src/providers/ad/ad_srv.c
-@@ -38,6 +38,13 @@
- 
- #define AD_SITE_DOMAIN_FMT "%s._sites.%s"
- 
-+char *ad_site_dns_discovery_domain(TALLOC_CTX *mem_ctx,
-+                                   const char *site,
-+                                   const char *domain)
-+{
-+    return talloc_asprintf(mem_ctx, AD_SITE_DOMAIN_FMT, site, domain);
-+}
-+
- static errno_t ad_sort_servers_by_dns(TALLOC_CTX *mem_ctx,
-                                       const char *domain,
-                                       struct fo_server_info **_srv,
-@@ -154,8 +161,8 @@ static struct tevent_req *ad_get_dc_servers_send(TALLOC_CTX *mem_ctx,
-         DEBUG(SSSDBG_TRACE_FUNC, "Looking up domain controllers in domain "
-               "%s and site %s\n", discovery_domain, site);
- 
--        domains[0] = talloc_asprintf(state, AD_SITE_DOMAIN_FMT,
--                                     site, discovery_domain);
-+        domains[0] = ad_site_dns_discovery_domain(domains,
-+                                                  site, discovery_domain);
-         if (domains[0] == NULL) {
-             ret = ENOMEM;
-             goto immediately;
-@@ -775,9 +782,10 @@ static void ad_srv_plugin_site_done(struct tevent_req *subreq)
-         if (strcmp(state->service, "gc") == 0) {
-             if (state->forest != NULL) {
-                 if (state->site != NULL) {
--                    primary_domain = talloc_asprintf(state, AD_SITE_DOMAIN_FMT,
--                                                     state->site,
--                                                     state->forest);
-+                    primary_domain = ad_site_dns_discovery_domain(
-+                                                            state,
-+                                                            state->site,
-+                                                            state->forest);
-                     if (primary_domain == NULL) {
-                         ret = ENOMEM;
-                         goto done;
-@@ -791,7 +799,8 @@ static void ad_srv_plugin_site_done(struct tevent_req *subreq)
-             }
-         } else {
-             if (state->site != NULL) {
--                primary_domain = talloc_asprintf(state, AD_SITE_DOMAIN_FMT,
-+                primary_domain = ad_site_dns_discovery_domain(
-+                                                 state,
-                                                  state->site,
-                                                  state->discovery_domain);
-                 if (primary_domain == NULL) {
-diff --git a/src/providers/ad/ad_srv.h b/src/providers/ad/ad_srv.h
-index fddef686762e57bb95d648247131d39a797aa516..e553d594d77ad99f806af9634c2817754a80d4f5 100644
---- a/src/providers/ad/ad_srv.h
-+++ b/src/providers/ad/ad_srv.h
-@@ -49,4 +49,8 @@ errno_t ad_srv_plugin_recv(TALLOC_CTX *mem_ctx,
-                             struct fo_server_info **_backup_servers,
-                             size_t *_num_backup_servers);
- 
-+char *ad_site_dns_discovery_domain(TALLOC_CTX *mem_ctx,
-+                                   const char *site,
-+                                   const char *domain);
-+
- #endif /* __AD_SRV_H__ */
--- 
-2.17.1
-
diff --git a/SOURCES/0023-krb5-Lookahead-resolving-of-host-names.patch b/SOURCES/0023-krb5-Lookahead-resolving-of-host-names.patch
new file mode 100644
index 0000000..42ba03b
--- /dev/null
+++ b/SOURCES/0023-krb5-Lookahead-resolving-of-host-names.patch
@@ -0,0 +1,650 @@
+From 385c8c7e0e6f184dd61953745bfe04a5a79a951a Mon Sep 17 00:00:00 2001
+From: Tomas Halman <thalman@redhat.com>
+Date: Fri, 15 Mar 2019 10:27:50 +0100
+Subject: [PATCH 23/23] krb5: Lookahead resolving of host names
+
+The caller that initializes
+the fail over service (maybe with be_fo_add_service) should provide
+a hint with the value of the lookahead option. Then, if a request for
+server resolution is triggered, the fail over code would resolve a server
+and afterwards check if enough fo_server entries with a valid hostname
+in the struct server_common structure. If not, the request would
+check if any of the fo_server structures represents a SRV query and
+try to resolve the query to receive more host names.
+
+Resolves:
+https://pagure.io/SSSD/sssd/issue/3975
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit e8d806d9bbb1ba288ed6a83158113f4d8f8a8929)
+---
+ Makefile.am                               |  1 +
+ src/man/sssd-krb5.5.xml                   | 34 +++++++++++
+ src/providers/ad/ad_common.c              | 10 +++-
+ src/providers/ad/ad_common.h              |  2 +
+ src/providers/ad/ad_init.c                |  2 +
+ src/providers/ad/ad_opts.c                |  2 +
+ src/providers/ad/ad_subdomains.c          | 12 +++-
+ src/providers/ipa/ipa_common.c            | 14 +++--
+ src/providers/ipa/ipa_opts.c              |  2 +
+ src/providers/ipa/ipa_subdomains.c        |  4 +-
+ src/providers/ipa/ipa_subdomains_server.c |  7 +++
+ src/providers/krb5/krb5_common.c          | 71 ++++++++++++++++++++++-
+ src/providers/krb5/krb5_common.h          | 13 ++++-
+ src/providers/krb5/krb5_init.c            | 19 +++++-
+ src/providers/krb5/krb5_opts.c            |  1 +
+ src/providers/ldap/ldap_common.c          |  9 +++
+ src/providers/ldap/ldap_opts.c            |  1 +
+ src/providers/ldap/sdap.h                 |  1 +
+ 18 files changed, 193 insertions(+), 12 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index e22423071..0c24ae664 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -3339,6 +3339,7 @@ test_ad_subdom_LDADD = \
+     libsss_idmap.la \
+     libsss_test_common.la \
+     libdlopen_test_providers.la \
++    libsss_krb5_common.la \
+     $(NULL)
+ 
+ test_ipa_subdom_util_SOURCES = \
+diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml
+index 60b7dfb50..5a0bb5e9c 100644
+--- a/src/man/sssd-krb5.5.xml
++++ b/src/man/sssd-krb5.5.xml
+@@ -501,6 +501,40 @@
+                     </listitem>
+                 </varlistentry>
+ 
++                <varlistentry>
++                    <term>krb5_kdcinfo_lookahead (string)</term>
++                    <listitem>
++                        <para>
++                            When krb5_use_kdcinfo is set to true, you can limit the amount
++                            of servers handed to
++                            <citerefentry>
++                                <refentrytitle>sssd_krb5_locator_plugin</refentrytitle>
++                                <manvolnum>8</manvolnum>
++                            </citerefentry>.
++                            This might be helpful when there are too many servers
++                            discovered using SRV record.
++                        </para>
++                        <para>
++                            The krb5_kdcinfo_lookahead option contains two
++                            numbers seperated by a colon. The first number represents
++                            number of primary servers used and the second number
++                            specifies the number of backup servers.
++                        </para>
++                        <para>
++                            For example <emphasis>10:0</emphasis> means that up to
++                            10 primary servers will be handed to
++                            <citerefentry>
++                                <refentrytitle>sssd_krb5_locator_plugin</refentrytitle>
++                                <manvolnum>8</manvolnum>
++                            </citerefentry>.
++                            but no backup servers.
++                        </para>
++                        <para>
++                            Default: 3:1
++                        </para>
++                    </listitem>
++                </varlistentry>
++
+                 <varlistentry>
+                     <term>krb5_use_enterprise_principal (boolean)</term>
+                     <listitem>
+diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
+index b7f34daa9..4d1800806 100644
+--- a/src/providers/ad/ad_common.c
++++ b/src/providers/ad/ad_common.c
+@@ -729,6 +729,8 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
+                  const char *ad_gc_service,
+                  const char *ad_domain,
+                  bool use_kdcinfo,
++                 size_t n_lookahead_primary,
++                 size_t n_lookahead_backup,
+                  struct ad_service **_service)
+ {
+     errno_t ret;
+@@ -760,7 +762,9 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
+ 
+     service->krb5_service = krb5_service_new(service, bectx,
+                                              ad_service, krb5_realm,
+-                                             use_kdcinfo);
++                                             use_kdcinfo,
++                                             n_lookahead_primary,
++                                             n_lookahead_backup);
+     if (!service->krb5_service) {
+         ret = ENOMEM;
+         goto done;
+@@ -1292,6 +1296,10 @@ ad_get_auth_options(TALLOC_CTX *mem_ctx,
+     DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
+           krb5_options[KRB5_USE_KDCINFO].opt_name,
+           ad_opts->service->krb5_service->write_kdcinfo ? "true" : "false");
++    sss_krb5_parse_lookahead(
++        dp_opt_get_string(krb5_options, KRB5_KDCINFO_LOOKAHEAD),
++        &ad_opts->service->krb5_service->lookahead_primary,
++        &ad_opts->service->krb5_service->lookahead_backup);
+ 
+     *_opts = talloc_steal(mem_ctx, krb5_options);
+ 
+diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
+index 529753a8a..638465958 100644
+--- a/src/providers/ad/ad_common.h
++++ b/src/providers/ad/ad_common.h
+@@ -147,6 +147,8 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
+                  const char *ad_gc_service,
+                  const char *ad_domain,
+                  bool use_kdcinfo,
++                 size_t n_lookahead_primary,
++                 size_t n_lookahead_backup,
+                  struct ad_service **_service);
+ 
+ errno_t
+diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
+index 637efb761..612d4587e 100644
+--- a/src/providers/ad/ad_init.c
++++ b/src/providers/ad/ad_init.c
+@@ -160,6 +160,8 @@ static errno_t ad_init_options(TALLOC_CTX *mem_ctx,
+                            ad_realm, AD_SERVICE_NAME, AD_GC_SERVICE_NAME,
+                            dp_opt_get_string(ad_options->basic, AD_DOMAIN),
+                            false, /* will be set in ad_get_auth_options() */
++                           (size_t) -1,
++                           (size_t) -1,
+                            &ad_options->service);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init AD failover service: "
+diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
+index c408295f3..652d8bb27 100644
+--- a/src/providers/ad/ad_opts.c
++++ b/src/providers/ad/ad_opts.c
+@@ -111,6 +111,7 @@ struct dp_option ad_def_ldap_opts[] = {
+     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
++    { "krb5_kdcinfo_lookahead", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "ldap_pwd_policy", DP_OPT_STRING, { "none" }, NULL_STRING },
+     { "ldap_referrals", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "account_cache_expiration", DP_OPT_NUMBER, { .number = 0 }, NULL_NUMBER },
+@@ -175,6 +176,7 @@ struct dp_option ad_def_krb5_opts[] = {
+     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
++    { "krb5_kdcinfo_lookahead", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     DP_OPTION_TERMINATOR
+ };
+diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
+index 4fc4be094..b4ad347e4 100644
+--- a/src/providers/ad/ad_subdomains.c
++++ b/src/providers/ad/ad_subdomains.c
+@@ -280,6 +280,8 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
+     const char *keytab;
+     char *subdom_conf_path;
+     bool use_kdcinfo = false;
++    size_t n_lookahead_primary = SSS_KRB5_LOOKAHEAD_PRIMARY_DEFAULT;
++    size_t n_lookahead_backup = SSS_KRB5_LOOKAHEAD_BACKUP_DEFAULT;
+ 
+     realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
+     hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
+@@ -331,6 +333,11 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
+             && id_ctx->ad_options->auth_ctx->opts != NULL) {
+         use_kdcinfo = dp_opt_get_bool(id_ctx->ad_options->auth_ctx->opts,
+                                       KRB5_USE_KDCINFO);
++        sss_krb5_parse_lookahead(
++            dp_opt_get_string(id_ctx->ad_options->auth_ctx->opts,
++                              KRB5_KDCINFO_LOOKAHEAD),
++            &n_lookahead_primary,
++            &n_lookahead_backup);
+     }
+ 
+     DEBUG(SSSDBG_TRACE_ALL,
+@@ -339,7 +346,10 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
+ 
+     ret = ad_failover_init(ad_options, be_ctx, servers, backup_servers,
+                            subdom->realm, service_name, gc_service_name,
+-                           subdom->name, use_kdcinfo, &ad_options->service);
++                           subdom->name, use_kdcinfo,
++                           n_lookahead_primary,
++                           n_lookahead_backup,
++                           &ad_options->service);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
+         talloc_free(ad_options);
+diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
+index 1ed2e2203..871fb9bbc 100644
+--- a/src/providers/ipa/ipa_common.c
++++ b/src/providers/ipa/ipa_common.c
+@@ -801,6 +801,12 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts,
+     DEBUG(SSSDBG_CONF_SETTINGS, "Option %s set to %s\n",
+           ipa_opts->auth[KRB5_USE_KDCINFO].opt_name,
+           ipa_opts->service->krb5_service->write_kdcinfo ? "true" : "false");
++    if (ipa_opts->service->krb5_service->write_kdcinfo) {
++        sss_krb5_parse_lookahead(
++            dp_opt_get_string(ipa_opts->auth, KRB5_KDCINFO_LOOKAHEAD),
++            &ipa_opts->service->krb5_service->lookahead_primary,
++            &ipa_opts->service->krb5_service->lookahead_backup);
++    }
+ 
+     *_opts = ipa_opts->auth;
+     ret = EOK;
+@@ -1022,10 +1028,10 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
+ 
+     service->krb5_service = krb5_service_new(service, ctx,
+                                              "IPA", realm,
+-                                             true); /* The configured value
+-                                                     * will be set later when
+-                                                     * the auth provider is set up
+-                                                     */
++                                             true,   /* The configured value */
++                                             0,      /* will be set later when */
++                                             0);     /* the auth provider is set up */
++
+     if (!service->krb5_service) {
+         ret = ENOMEM;
+         goto done;
+diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
+index 373dc0e53..600b9ec4b 100644
+--- a/src/providers/ipa/ipa_opts.c
++++ b/src/providers/ipa/ipa_opts.c
+@@ -121,6 +121,7 @@ struct dp_option ipa_def_ldap_opts[] = {
+     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
++    { "krb5_kdcinfo_lookahead", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "ldap_pwd_policy", DP_OPT_STRING, { "none" } , NULL_STRING },
+     { "ldap_referrals", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "account_cache_expiration", DP_OPT_NUMBER, { .number = 0 }, NULL_NUMBER },
+@@ -320,6 +321,7 @@ struct dp_option ipa_def_krb5_opts[] = {
+     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
++    { "krb5_kdcinfo_lookahead", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     DP_OPTION_TERMINATOR
+ };
+diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
+index da1279e3e..94365aaca 100644
+--- a/src/providers/ipa/ipa_subdomains.c
++++ b/src/providers/ipa/ipa_subdomains.c
+@@ -692,7 +692,9 @@ ipa_subdom_get_k5_svc(struct ipa_subdomains_ctx *ctx,
+                                         ctx->be_ctx,
+                                         "IPA",
+                                         dom->realm,
+-                                        use_kdcinfo);
++                                        use_kdcinfo,
++                                        (size_t) -1,
++                                        (size_t) -1);
+     if (k5svc_ent->k5svc == NULL) {
+         talloc_free(k5svc_ent);
+         return NULL;
+diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
+index 43a3053cb..dd0933642 100644
+--- a/src/providers/ipa/ipa_subdomains_server.c
++++ b/src/providers/ipa/ipa_subdomains_server.c
+@@ -225,6 +225,8 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
+     errno_t ret;
+     const char *extra_attrs;
+     bool use_kdcinfo = false;
++    size_t n_lookahead_primary = (size_t)-1;
++    size_t n_lookahead_backup = (size_t)-1;
+ 
+     ad_domain = subdom->name;
+     DEBUG(SSSDBG_TRACE_LIBS, "Setting up AD subdomain %s\n", subdom->name);
+@@ -284,6 +286,10 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
+     if (id_ctx->ipa_options != NULL && id_ctx->ipa_options->auth != NULL) {
+         use_kdcinfo = dp_opt_get_bool(id_ctx->ipa_options->auth,
+                                       KRB5_USE_KDCINFO);
++        sss_krb5_parse_lookahead(
++            dp_opt_get_string(id_ctx->ipa_options->auth, KRB5_KDCINFO_LOOKAHEAD),
++            &n_lookahead_primary,
++            &n_lookahead_backup);
+     }
+ 
+     DEBUG(SSSDBG_TRACE_ALL,
+@@ -297,6 +303,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
+                            subdom->realm,
+                            service_name, gc_service_name,
+                            subdom->name, use_kdcinfo,
++                           n_lookahead_primary, n_lookahead_backup,
+                            &ad_options->service);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n");
+diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
+index 1e33fc0f5..e56820b8d 100644
+--- a/src/providers/krb5/krb5_common.c
++++ b/src/providers/krb5/krb5_common.c
+@@ -390,6 +390,39 @@ done:
+     return ret;
+ }
+ 
++void sss_krb5_parse_lookahead(const char *param, size_t *primary, size_t *backup)
++{
++    int ret;
++
++    if (primary == NULL || backup == NULL) {
++        return;
++    }
++
++    *primary = SSS_KRB5_LOOKAHEAD_PRIMARY_DEFAULT;
++    *backup = SSS_KRB5_LOOKAHEAD_BACKUP_DEFAULT;
++
++    if (param == NULL) {
++        return;
++    }
++
++    if (strchr(param, ':')) {
++        ret = sscanf(param, "%zu:%zu", primary, backup);
++        if (ret != 2) {
++            DEBUG(SSSDBG_MINOR_FAILURE, "Could not parse krb5_kdcinfo_lookahead!\n");
++        }
++    } else {
++        ret = sscanf(param, "%zu", primary);
++        if (ret != 1) {
++            DEBUG(SSSDBG_MINOR_FAILURE, "Could not parse krb5_kdcinfo_lookahead!\n");
++        }
++    }
++
++    DEBUG(SSSDBG_CONF_SETTINGS,
++          "Option krb5_kdcinfo_lookahead set to %zu:%zu",
++          *primary, *backup);
++}
++
++
+ static int remove_info_files_destructor(void *p)
+ {
+     int ret;
+@@ -668,6 +701,13 @@ errno_t write_krb5info_file_from_fo_server(struct krb5_service *krb5_service,
+     int primary;
+     const char *address;
+     errno_t ret;
++    size_t n_lookahead_primary;
++    size_t n_lookahead_backup;
++
++    if (krb5_service == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "The krb5_service must not be NULL!\n");
++        return EINVAL;
++    }
+ 
+     tmp_ctx = talloc_new(NULL);
+     if (tmp_ctx == NULL) {
+@@ -675,6 +715,9 @@ errno_t write_krb5info_file_from_fo_server(struct krb5_service *krb5_service,
+         return ENOMEM;
+     }
+ 
++    n_lookahead_primary = krb5_service->lookahead_primary;
++    n_lookahead_backup = krb5_service->lookahead_backup;
++
+     server_idx = 0;
+     server_list = talloc_zero_array(tmp_ctx,
+                                     const char *,
+@@ -689,6 +732,15 @@ errno_t write_krb5info_file_from_fo_server(struct krb5_service *krb5_service,
+         address = fo_server_address_or_name(tmp_ctx, server);
+         if (address) {
+             server_list[server_idx++] = address;
++            if (fo_is_server_primary(server)) {
++                if (n_lookahead_primary > 0) {
++                    n_lookahead_primary--;
++                }
++            } else {
++                if (n_lookahead_backup > 0) {
++                    n_lookahead_backup--;
++                }
++            }
+         } else {
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "Server without name and address found in list.\n");
+@@ -700,6 +752,8 @@ errno_t write_krb5info_file_from_fo_server(struct krb5_service *krb5_service,
+              item != server;
+              item = fo_server_next(item) ? fo_server_next(item) : fo_server_first(item)) {
+ 
++            if (primary && n_lookahead_primary == 0) break;
++            if (!primary && n_lookahead_backup == 0) break;
+             if (primary && !fo_is_server_primary(item)) continue;
+             if (!primary && fo_is_server_primary(item)) continue;
+             if (filter != NULL && filter(item)) continue;
+@@ -712,6 +766,11 @@ errno_t write_krb5info_file_from_fo_server(struct krb5_service *krb5_service,
+             }
+ 
+             server_list[server_idx++] = address;
++            if (primary) {
++                n_lookahead_primary--;
++            } else {
++                n_lookahead_backup--;
++            }
+         }
+     }
+     if (server_list[0] == NULL) {
+@@ -901,7 +960,9 @@ struct krb5_service *krb5_service_new(TALLOC_CTX *mem_ctx,
+                                       struct be_ctx *be_ctx,
+                                       const char *service_name,
+                                       const char *realm,
+-                                      bool use_kdcinfo)
++                                      bool use_kdcinfo,
++                                      size_t n_lookahead_primary,
++                                      size_t n_lookahead_backup)
+ {
+     struct krb5_service *service;
+ 
+@@ -927,6 +988,9 @@ struct krb5_service *krb5_service_new(TALLOC_CTX *mem_ctx,
+           realm,
+           use_kdcinfo ? "true" : "false");
+     service->write_kdcinfo = use_kdcinfo;
++    service->lookahead_primary = n_lookahead_primary;
++    service->lookahead_backup = n_lookahead_backup;
++
+     service->be_ctx = be_ctx;
+     return service;
+ }
+@@ -937,6 +1001,8 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
+                       const char *backup_servers,
+                       const char *realm,
+                       bool use_kdcinfo,
++                      size_t n_lookahead_primary,
++                      size_t n_lookahead_backup,
+                       struct krb5_service **_service)
+ {
+     TALLOC_CTX *tmp_ctx;
+@@ -948,7 +1014,8 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
+         return ENOMEM;
+     }
+ 
+-    service = krb5_service_new(tmp_ctx, ctx, service_name, realm, use_kdcinfo);
++    service = krb5_service_new(tmp_ctx, ctx, service_name, realm, use_kdcinfo,
++                               n_lookahead_primary, n_lookahead_backup);
+     if (!service) {
+         ret = ENOMEM;
+         goto done;
+diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
+index be541626b..441c52b34 100644
+--- a/src/providers/krb5/krb5_common.h
++++ b/src/providers/krb5/krb5_common.h
+@@ -38,6 +38,8 @@
+ 
+ #define SSS_KRB5KDC_FO_SRV "KERBEROS"
+ #define SSS_KRB5KPASSWD_FO_SRV "KPASSWD"
++#define SSS_KRB5_LOOKAHEAD_PRIMARY_DEFAULT 3
++#define SSS_KRB5_LOOKAHEAD_BACKUP_DEFAULT 1
+ 
+ enum krb5_opts {
+     KRB5_KDC = 0,
+@@ -59,6 +61,7 @@ enum krb5_opts {
+     KRB5_CANONICALIZE,
+     KRB5_USE_ENTERPRISE_PRINCIPAL,
+     KRB5_USE_KDCINFO,
++    KRB5_KDCINFO_LOOKAHEAD,
+     KRB5_MAP_USER,
+ 
+     KRB5_OPTS
+@@ -71,6 +74,8 @@ struct krb5_service {
+     char *name;
+     char *realm;
+     bool write_kdcinfo;
++    size_t lookahead_primary;
++    size_t lookahead_backup;
+     bool removal_callback_available;
+ };
+ 
+@@ -160,6 +165,8 @@ errno_t krb5_try_kdcip(struct confdb_ctx *cdb, const char *conf_path,
+ errno_t sss_krb5_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb,
+                              const char *conf_path, struct dp_option **_opts);
+ 
++void sss_krb5_parse_lookahead(const char *param, size_t *primary, size_t *backup);
++
+ errno_t write_krb5info_file(struct krb5_service *krb5_service,
+                             const char **server_list,
+                             const char *service);
+@@ -173,7 +180,9 @@ struct krb5_service *krb5_service_new(TALLOC_CTX *mem_ctx,
+                                       struct be_ctx *be_ctx,
+                                       const char *service_name,
+                                       const char *realm,
+-                                      bool use_kdcinfo);
++                                      bool use_kdcinfo,
++                                      size_t n_lookahead_primary,
++                                      size_t n_lookahead_backup);
+ 
+ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
+                       const char *service_name,
+@@ -181,6 +190,8 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
+                       const char *backup_servers,
+                       const char *realm,
+                       bool use_kdcinfo,
++                      size_t n_lookahead_primary,
++                      size_t n_lookahead_backup,
+                       struct krb5_service **_service);
+ 
+ void remove_krb5_info_files_callback(void *pvt);
+diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
+index 66ae68fb4..3f4c1b361 100644
+--- a/src/providers/krb5/krb5_init.c
++++ b/src/providers/krb5/krb5_init.c
+@@ -40,6 +40,8 @@ static errno_t krb5_init_kpasswd(struct krb5_ctx *ctx,
+     const char *backup_servers;
+     const char *kdc_servers;
+     bool use_kdcinfo;
++    size_t n_lookahead_primary;
++    size_t n_lookahead_backup;
+     errno_t ret;
+ 
+     realm = dp_opt_get_string(ctx->opts, KRB5_REALM);
+@@ -52,6 +54,9 @@ static errno_t krb5_init_kpasswd(struct krb5_ctx *ctx,
+     primary_servers = dp_opt_get_string(ctx->opts, KRB5_KPASSWD);
+     backup_servers = dp_opt_get_string(ctx->opts, KRB5_BACKUP_KPASSWD);
+     use_kdcinfo = dp_opt_get_bool(ctx->opts, KRB5_USE_KDCINFO);
++    sss_krb5_parse_lookahead(dp_opt_get_string(ctx->opts, KRB5_KDCINFO_LOOKAHEAD),
++                             &n_lookahead_primary, &n_lookahead_backup);
++
+ 
+     if (primary_servers == NULL && backup_servers != NULL) {
+         DEBUG(SSSDBG_CONF_SETTINGS, "kpasswd server wasn't specified but "
+@@ -67,7 +72,10 @@ static errno_t krb5_init_kpasswd(struct krb5_ctx *ctx,
+     } else {
+         ret = krb5_service_init(ctx, be_ctx, SSS_KRB5KPASSWD_FO_SRV,
+                                 primary_servers, backup_servers, realm,
+-                                use_kdcinfo, &ctx->kpasswd_service);
++                                use_kdcinfo,
++                                n_lookahead_primary,
++                                n_lookahead_backup,
++                                &ctx->kpasswd_service);
+         if (ret != EOK) {
+             DEBUG(SSSDBG_FATAL_FAILURE,
+                   "Failed to init KRB5KPASSWD failover service!\n");
+@@ -84,6 +92,8 @@ static errno_t krb5_init_kdc(struct krb5_ctx *ctx, struct be_ctx *be_ctx)
+     const char *backup_servers;
+     const char *realm;
+     bool use_kdcinfo;
++    size_t n_lookahead_primary;
++    size_t n_lookahead_backup;
+     errno_t ret;
+ 
+     realm = dp_opt_get_string(ctx->opts, KRB5_REALM);
+@@ -96,10 +106,15 @@ static errno_t krb5_init_kdc(struct krb5_ctx *ctx, struct be_ctx *be_ctx)
+     backup_servers = dp_opt_get_string(ctx->opts, KRB5_BACKUP_KDC);
+ 
+     use_kdcinfo = dp_opt_get_bool(ctx->opts, KRB5_USE_KDCINFO);
++    sss_krb5_parse_lookahead(dp_opt_get_string(ctx->opts, KRB5_KDCINFO_LOOKAHEAD),
++                             &n_lookahead_primary, &n_lookahead_backup);
+ 
+     ret = krb5_service_init(ctx, be_ctx, SSS_KRB5KDC_FO_SRV,
+                             primary_servers, backup_servers, realm,
+-                            use_kdcinfo, &ctx->service);
++                            use_kdcinfo,
++                            n_lookahead_primary,
++                            n_lookahead_backup,
++                            &ctx->service);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init KRB5 failover service!\n");
+         return ret;
+diff --git a/src/providers/krb5/krb5_opts.c b/src/providers/krb5/krb5_opts.c
+index 6bec52767..05395e0f4 100644
+--- a/src/providers/krb5/krb5_opts.c
++++ b/src/providers/krb5/krb5_opts.c
+@@ -42,6 +42,7 @@ struct dp_option default_krb5_opts[] = {
+     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
++    { "krb5_kdcinfo_lookahead", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "krb5_map_user", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     DP_OPTION_TERMINATOR
+ };
+diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
+index 9cd8ec09c..4c49f08c5 100644
+--- a/src/providers/ldap/ldap_common.c
++++ b/src/providers/ldap/ldap_common.c
+@@ -335,6 +335,8 @@ int sdap_gssapi_init(TALLOC_CTX *mem_ctx,
+     const char *krb5_opt_realm;
+     struct krb5_service *service = NULL;
+     TALLOC_CTX *tmp_ctx;
++    size_t n_lookahead_primary;
++    size_t n_lookahead_backup;
+ 
+     tmp_ctx = talloc_new(NULL);
+     if (tmp_ctx == NULL) return ENOMEM;
+@@ -361,11 +363,18 @@ int sdap_gssapi_init(TALLOC_CTX *mem_ctx,
+         }
+     }
+ 
++    sss_krb5_parse_lookahead(
++        dp_opt_get_string(opts, SDAP_KRB5_KDCINFO_LOOKAHEAD),
++        &n_lookahead_primary,
++        &n_lookahead_backup);
++
+     ret = krb5_service_init(mem_ctx, bectx,
+                             SSS_KRB5KDC_FO_SRV, krb5_servers,
+                             krb5_backup_servers, krb5_realm,
+                             dp_opt_get_bool(opts,
+                                             SDAP_KRB5_USE_KDCINFO),
++                            n_lookahead_primary,
++                            n_lookahead_backup,
+                             &service);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init KRB5 failover service!\n");
+diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c
+index f7574fac2..613fe7463 100644
+--- a/src/providers/ldap/ldap_opts.c
++++ b/src/providers/ldap/ldap_opts.c
+@@ -82,6 +82,7 @@ struct dp_option default_basic_opts[] = {
+     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "krb5_use_kdcinfo", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
++    { "krb5_kdcinfo_lookahead", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     { "ldap_pwd_policy", DP_OPT_STRING, { "none" }, NULL_STRING },
+     { "ldap_referrals", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "account_cache_expiration", DP_OPT_NUMBER, { .number = 0 }, NULL_NUMBER },
+diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
+index 0f79ae9de..48061d389 100644
+--- a/src/providers/ldap/sdap.h
++++ b/src/providers/ldap/sdap.h
+@@ -199,6 +199,7 @@ enum sdap_basic_opt {
+     SDAP_KRB5_REALM,
+     SDAP_KRB5_CANONICALIZE,
+     SDAP_KRB5_USE_KDCINFO,
++    SDAP_KRB5_KDCINFO_LOOKAHEAD,
+     SDAP_PWD_POLICY,
+     SDAP_REFERRALS,
+     SDAP_ACCOUNT_CACHE_EXPIRATION,
+-- 
+2.19.1
+
diff --git a/SOURCES/0024-RESOLV-Add-a-resolv_hostport_list-request.patch b/SOURCES/0024-RESOLV-Add-a-resolv_hostport_list-request.patch
deleted file mode 100644
index e19eb54..0000000
--- a/SOURCES/0024-RESOLV-Add-a-resolv_hostport_list-request.patch
+++ /dev/null
@@ -1,265 +0,0 @@
-From e73e35f2a1ef037d89f73b4ce5609e2567dc8714 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 25 Jun 2018 12:46:51 +0200
-Subject: [PATCH] RESOLV: Add a resolv_hostport_list request
-
-Adds a request that resolves a list of (host,port) tuples and returns a
-list of structures that contain the resolv_hostent structure as other
-resolver requests do, but also a pointer to the original request tuple.
-
-This is done because the request skips any unresolvable inputs, so it
-might be handy to know which input an output maps to.
-
-It is expected that the request will be used in the future also for cases
-where we want to e.g. try the connectivity to a serve using a mechanism
-such as an LDAP ping.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3291
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 6f80bccc6f8203381c387080bd0563ba10994487)
----
- src/resolv/async_resolv.c | 187 ++++++++++++++++++++++++++++++++++++++
- src/resolv/async_resolv.h |  30 ++++++
- 2 files changed, 217 insertions(+)
-
-diff --git a/src/resolv/async_resolv.c b/src/resolv/async_resolv.c
-index ba6fabf285533153ea440394ce1cc224aa42cbd3..bb27011548b73c0cc62f6638401847ab9e0b175c 100644
---- a/src/resolv/async_resolv.c
-+++ b/src/resolv/async_resolv.c
-@@ -2322,3 +2322,190 @@ resolv_sort_srv_reply(struct ares_srv_reply **reply)
- 
-     return EOK;
- }
-+
-+struct resolv_hostport_list_state {
-+    struct tevent_context *ev;
-+    struct resolv_ctx *ctx;
-+    struct resolv_hostport *hostport_list;
-+    size_t list_size;
-+    size_t limit;
-+    enum restrict_family family_order;
-+    enum host_database *db;
-+
-+    size_t hpindex;
-+
-+    struct resolv_hostport_addr **rhp_addrs;
-+    size_t addrindex;
-+};
-+
-+static errno_t resolv_hostport_list_step(struct tevent_req *req);
-+static void resolv_hostport_list_resolv_hostname_done(struct tevent_req *subreq);
-+
-+struct tevent_req *resolv_hostport_list_send(TALLOC_CTX *mem_ctx,
-+                                             struct tevent_context *ev,
-+                                             struct resolv_ctx *ctx,
-+                                             struct resolv_hostport *hostport_list,
-+                                             size_t list_size,
-+                                             size_t limit,
-+                                             enum restrict_family family_order,
-+                                             enum host_database *db)
-+{
-+    struct resolv_hostport_list_state *state;
-+    struct tevent_req *req;
-+    errno_t ret;
-+
-+    req = tevent_req_create(mem_ctx, &state,
-+                            struct resolv_hostport_list_state);
-+    if (req == NULL) {
-+        return NULL;
-+    }
-+    state->ev = ev;
-+    state->ctx = ctx;
-+    state->hostport_list = hostport_list;
-+    state->family_order = family_order;
-+    state->db = db;
-+    state->list_size = list_size;
-+    state->limit = limit;
-+
-+    state->rhp_addrs = talloc_array(state,
-+                                    struct resolv_hostport_addr *,
-+                                    state->list_size);
-+    if (state->rhp_addrs == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+
-+    ret = resolv_hostport_list_step(req);
-+    if (ret != EAGAIN) {
-+        goto immediately;
-+    }
-+
-+    return req;
-+
-+immediately:
-+    if (ret != EOK) {
-+        tevent_req_error(req, ret);
-+    } else {
-+        tevent_req_done(req);
-+    }
-+    tevent_req_post(req, ev);
-+    return req;
-+}
-+
-+static errno_t resolv_hostport_list_step(struct tevent_req *req)
-+{
-+    struct tevent_req *subreq = NULL;
-+    struct resolv_hostport_list_state *state = tevent_req_data(req,
-+                                        struct resolv_hostport_list_state);
-+
-+    if (state->hpindex >= state->list_size) {
-+        DEBUG(SSSDBG_TRACE_INTERNAL, "Done\n");
-+        return EOK;
-+    }
-+
-+    subreq = resolv_gethostbyname_send(state,
-+                                       state->ev,
-+                                       state->ctx,
-+                                       state->hostport_list[state->hpindex].host,
-+                                       state->family_order,
-+                                       state->db);
-+    if (subreq == NULL) {
-+        return ENOMEM;
-+    }
-+    tevent_req_set_callback(subreq,
-+                            resolv_hostport_list_resolv_hostname_done, req);
-+    return EAGAIN;
-+}
-+
-+static struct resolv_hostport_addr*
-+resolv_hostport_addr_new(TALLOC_CTX *mem_ctx,
-+                         const char *host,
-+                         int port,
-+                         struct resolv_hostent *reply)
-+{
-+    struct resolv_hostport_addr *rhp_addr;
-+
-+    rhp_addr = talloc_zero(mem_ctx, struct resolv_hostport_addr);
-+    if (rhp_addr == NULL) {
-+        return NULL;
-+    }
-+
-+    rhp_addr->origin.host = talloc_strdup(rhp_addr, host);
-+    if (rhp_addr->origin.host == NULL) {
-+        return NULL;
-+    }
-+
-+    rhp_addr->origin.port = port;
-+    rhp_addr->reply = talloc_steal(rhp_addr, reply);
-+    return rhp_addr;
-+}
-+
-+static void resolv_hostport_list_resolv_hostname_done(struct tevent_req *subreq)
-+{
-+    errno_t ret;
-+    struct tevent_req *req =
-+            tevent_req_callback_data(subreq, struct tevent_req);
-+    struct resolv_hostport_list_state *state = tevent_req_data(req,
-+                                        struct resolv_hostport_list_state);
-+    struct resolv_hostent *rhostent;
-+    int resolv_status;
-+
-+    ret = resolv_gethostbyname_recv(subreq, state, &resolv_status, NULL,
-+                                    &rhostent);
-+    talloc_zfree(subreq);
-+
-+    if (ret != EOK) {
-+        /* Don't abort the request, just go to the next one */
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "Could not resolve address for this machine, error [%d]: %s, "
-+              "resolver returned: [%d]: %s\n", ret, sss_strerror(ret),
-+              resolv_status, resolv_strerror(resolv_status));
-+    } else {
-+        state->rhp_addrs[state->addrindex] = \
-+            resolv_hostport_addr_new(state->rhp_addrs,
-+                                     state->hostport_list[state->hpindex].host,
-+                                     state->hostport_list[state->hpindex].port,
-+                                     rhostent);
-+        state->addrindex++;
-+
-+        if (state->limit > 0 && state->addrindex >= state->limit) {
-+            DEBUG(SSSDBG_TRACE_INTERNAL,
-+                "Reached the limit or addresses to resolve\n");
-+            tevent_req_done(req);
-+            return;
-+        }
-+    }
-+
-+    state->hpindex++;
-+
-+    ret = resolv_hostport_list_step(req);
-+    if (ret == EOK) {
-+        tevent_req_done(req);
-+        return;
-+    } else if (ret != EAGAIN) {
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+    /* Next iteration .. */
-+}
-+
-+int resolv_hostport_list_recv(struct tevent_req *req,
-+                              TALLOC_CTX *mem_ctx,
-+                              size_t *_rhp_len,
-+                              struct resolv_hostport_addr ***_rhp_addrs)
-+{
-+    struct resolv_hostport_list_state *state = tevent_req_data(req,
-+                                        struct resolv_hostport_list_state);
-+
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+
-+    if (_rhp_len) {
-+        *_rhp_len = state->addrindex;
-+    }
-+
-+    if (_rhp_addrs) {
-+        *_rhp_addrs = talloc_steal(mem_ctx, state->rhp_addrs);
-+    }
-+
-+    return EOK;
-+}
-diff --git a/src/resolv/async_resolv.h b/src/resolv/async_resolv.h
-index b602a425c21b5f3bfd0098ce3208f6750d4ed1ad..90ed037075c7becb0f8bcd580b218092f2d8579e 100644
---- a/src/resolv/async_resolv.h
-+++ b/src/resolv/async_resolv.h
-@@ -112,6 +112,36 @@ int resolv_gethostbyname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-                               int *status, int *timeouts,
-                               struct resolv_hostent **rhostent);
- 
-+struct resolv_hostport {
-+    const char *host;
-+    int port;
-+};
-+
-+struct resolv_hostport_addr {
-+    struct resolv_hostport origin;
-+    struct resolv_hostent *reply;
-+};
-+
-+/* Resolves a list of resolv_hostport tuples into a list of
-+ * resolv_hostport_addr. Any unresolvable addresses are skipped.
-+ *
-+ * Optionally takes a limit argument and stops after the request
-+ * had resolved addresses up to the limit.
-+ */
-+struct tevent_req *resolv_hostport_list_send(TALLOC_CTX *mem_ctx,
-+                                             struct tevent_context *ev,
-+                                             struct resolv_ctx *ctx,
-+                                             struct resolv_hostport *hostport_list,
-+                                             size_t list_size,
-+                                             size_t limit,
-+                                             enum restrict_family family_order,
-+                                             enum host_database *db);
-+
-+int resolv_hostport_list_recv(struct tevent_req *req,
-+                              TALLOC_CTX *mem_ctx,
-+                              size_t *_rhp_len,
-+                              struct resolv_hostport_addr ***_rhp_addrs);
-+
- char *
- resolv_get_string_address_index(TALLOC_CTX *mem_ctx,
-                                 struct resolv_hostent *hostent,
--- 
-2.17.1
-
diff --git a/SOURCES/0024-SDAP-Add-sdap_has_deref_support_ex.patch b/SOURCES/0024-SDAP-Add-sdap_has_deref_support_ex.patch
new file mode 100644
index 0000000..d6f73a2
--- /dev/null
+++ b/SOURCES/0024-SDAP-Add-sdap_has_deref_support_ex.patch
@@ -0,0 +1,114 @@
+From eaceb6a212c989613c228fcbf939cf00427fb543 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 12 Mar 2019 12:48:29 +0100
+Subject: [PATCH 24/25] SDAP: Add sdap_has_deref_support_ex()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+https://pagure.io/SSSD/sssd/issue/3979
+
+In some cases, it makes sense for performance reasons to disable
+dereference when processing user groups. But since processing of HBAC host
+groups is not much of a performance sensitive operation, we can get away
+with ignoring the client side setting and always using the dereference
+branch if the server supports the dereference call.
+
+This patch extends the sdap_has_deref_support call with a flag that
+allows the caller to bypass the client side check.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 1eb3ae1c46314ccc9151dc271966584b3d0f39f5)
+---
+ src/providers/ldap/sdap_async.c     | 19 ++++++++++++++-----
+ src/providers/ldap/sdap_async.h     |  6 +++++-
+ src/tests/cmocka/common_mock_sdap.c | 10 +++++++++-
+ 3 files changed, 28 insertions(+), 7 deletions(-)
+
+diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
+index c9c633b44..822baf06a 100644
+--- a/src/providers/ldap/sdap_async.c
++++ b/src/providers/ldap/sdap_async.c
+@@ -2959,7 +2959,9 @@ int sdap_deref_search_recv(struct tevent_req *req,
+     return EOK;
+ }
+ 
+-bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts)
++bool sdap_has_deref_support_ex(struct sdap_handle *sh,
++                               struct sdap_options *opts,
++                               bool ignore_client)
+ {
+     const char *deref_oids[][2] = { { LDAP_SERVER_ASQ_OID, "ASQ" },
+                                     { LDAP_CONTROL_X_DEREF, "OpenLDAP" },
+@@ -2972,18 +2974,25 @@ bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts)
+         return false;
+     }
+ 
+-    deref_threshold = dp_opt_get_int(opts->basic, SDAP_DEREF_THRESHOLD);
+-    if (deref_threshold == 0) {
+-        return false;
++    if (ignore_client == false) {
++        deref_threshold = dp_opt_get_int(opts->basic, SDAP_DEREF_THRESHOLD);
++        if (deref_threshold == 0) {
++            return false;
++        }
+     }
+ 
+     for (i=0; deref_oids[i][0]; i++) {
+         if (sdap_is_control_supported(sh, deref_oids[i][0])) {
+             DEBUG(SSSDBG_TRACE_FUNC, "The server supports deref method %s\n",
+-                      deref_oids[i][1]);
++                  deref_oids[i][1]);
+             return true;
+         }
+     }
+ 
+     return false;
+ }
++
++bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts)
++{
++    return sdap_has_deref_support_ex(sh, opts, false);
++}
+diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
+index cdf4e9e46..34940ad75 100644
+--- a/src/providers/ldap/sdap_async.h
++++ b/src/providers/ldap/sdap_async.h
+@@ -252,7 +252,11 @@ int sdap_get_generic_recv(struct tevent_req *req,
+                          TALLOC_CTX *mem_ctx, size_t *reply_count,
+                          struct sysdb_attrs ***reply_list);
+ 
+-bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts);
++bool sdap_has_deref_support_ex(struct sdap_handle *sh,
++                               struct sdap_options *opts,
++                               bool ignore_client);
++bool sdap_has_deref_support(struct sdap_handle *sh,
++                            struct sdap_options *opts);
+ 
+ enum sdap_deref_flags {
+     SDAP_DEREF_FLG_SILENT = 1 << 0,     /* Do not warn if dereference fails */
+diff --git a/src/tests/cmocka/common_mock_sdap.c b/src/tests/cmocka/common_mock_sdap.c
+index fa4787c4b..9bbaaf4fb 100644
+--- a/src/tests/cmocka/common_mock_sdap.c
++++ b/src/tests/cmocka/common_mock_sdap.c
+@@ -76,7 +76,15 @@ struct sdap_handle *mock_sdap_handle(TALLOC_CTX *mem_ctx)
+  * their mock equivalent shall be used.
+  */
+ 
+-bool sdap_has_deref_support(struct sdap_handle *sh, struct sdap_options *opts)
++bool sdap_has_deref_support_ex(struct sdap_handle *sh,
++                               struct sdap_options *opts,
++                               bool ignore_client)
++{
++    return sss_mock_type(bool);
++}
++
++bool sdap_has_deref_support(struct sdap_handle *sh,
++                            struct sdap_options *opts)
+ {
+     return sss_mock_type(bool);
+ }
+-- 
+2.19.1
+
diff --git a/SOURCES/0025-IPA-Use-dereference-for-host-groups-even-if-the-conf.patch b/SOURCES/0025-IPA-Use-dereference-for-host-groups-even-if-the-conf.patch
new file mode 100644
index 0000000..45a69ba
--- /dev/null
+++ b/SOURCES/0025-IPA-Use-dereference-for-host-groups-even-if-the-conf.patch
@@ -0,0 +1,63 @@
+From 2c97edb4bd965499fe4cc39710de1a565c1b40d3 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 12 Mar 2019 12:48:48 +0100
+Subject: [PATCH 25/25] IPA: Use dereference for host groups even if the
+ configuration disables dereference
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+https://pagure.io/SSSD/sssd/issue/3979
+
+In some cases, it makes sense for performance reasons to disable
+dereference when processing user groups. But since processing of HBAC host
+groups is not much of a performance sensitive operation, we can get away
+with ignoring the client side setting and always using the dereference
+branch if the server supports the dereference call.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 9d63616000c0c886a6da87708a460218a9e24474)
+---
+ src/man/sssd-ldap.5.xml       | 11 +++++++++--
+ src/providers/ipa/ipa_hosts.c |  2 +-
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
+index 5b858be62..25acc19e6 100644
+--- a/src/man/sssd-ldap.5.xml
++++ b/src/man/sssd-ldap.5.xml
+@@ -1601,8 +1601,15 @@
+                             they are looked up individually.
+                         </para>
+                         <para>
+-                            You can turn off dereference lookups completely by
+-                            setting the value to 0.
++                            You can turn off dereference lookups completely
++                            by setting the value to 0. Please note that
++                            there are some codepaths in SSSD, like the IPA
++                            HBAC provider, that are only implemented using
++                            the dereference call, so even with dereference
++                            explicitly disabled, those parts will still
++                            use dereference if the server supports it
++                            and advertises the dereference control in the
++                            rootDSE object.
+                         </para>
+                         <para>
+                             A dereference lookup is a means of fetching all
+diff --git a/src/providers/ipa/ipa_hosts.c b/src/providers/ipa/ipa_hosts.c
+index 288bfb865..e209bca67 100644
+--- a/src/providers/ipa/ipa_hosts.c
++++ b/src/providers/ipa/ipa_hosts.c
+@@ -157,7 +157,7 @@ ipa_host_info_done(struct tevent_req *subreq)
+                 return;
+             }
+ 
+-            if (!sdap_has_deref_support(state->sh, state->opts)) {
++            if (!sdap_has_deref_support_ex(state->sh, state->opts, true)) {
+                 DEBUG(SSSDBG_CRIT_FAILURE, "Server does not support deref\n");
+                 tevent_req_error(req, EIO);
+                 return;
+-- 
+2.19.1
+
diff --git a/SOURCES/0025-KRB5-IPA-AD-Add-a-utility-function-to-create-a-krb5_.patch b/SOURCES/0025-KRB5-IPA-AD-Add-a-utility-function-to-create-a-krb5_.patch
deleted file mode 100644
index 53d87db..0000000
--- a/SOURCES/0025-KRB5-IPA-AD-Add-a-utility-function-to-create-a-krb5_.patch
+++ /dev/null
@@ -1,246 +0,0 @@
-From 95cb7de6221dad54b37f7dd05dbfc3b717168488 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 25 Jun 2018 13:08:25 +0200
-Subject: [PATCH] KRB5/IPA/AD: Add a utility function to create a krb5_service
- instance
-
-Each Kerberized provider used hand-crafted copy-paste code to set up its
-copy of the krb5_service structure. Instead of adding yet another copy in
-this patchset in the IPA subdomains code, create a utility function instead.
-
-Due to IPA provider first creating the krb5_service in the common setup
-function, but only later reading the auth options in the auth provider
-constructor, the code first uses the default true value for the use_kdcinfo
-flag and then overrides it with the configured value in the auth constructor
--- it would be preferable to create the structure with the right value at
-creation time, but this would require bigger refactoring. Also, the code
-before this change was even less correct as the flag was initially set the
-"false" due to the structure being allocated with talloc_zero(). At least
-now it uses the default value.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3291
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit a9a9f39342ebd26425cb1b3baedfea2429d88b04)
----
- src/providers/ad/ad_common.c     | 26 ++--------------
- src/providers/ipa/ipa_common.c   | 35 +++++++++-------------
- src/providers/krb5/krb5_common.c | 51 ++++++++++++++++++++++----------
- src/providers/krb5/krb5_common.h |  6 ++++
- 4 files changed, 58 insertions(+), 60 deletions(-)
-
-diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
-index feeb5d09643a02b99be1a387b41842a034a323b8..b103410e5915a380d0404e18da869517e4d4e355 100644
---- a/src/providers/ad/ad_common.c
-+++ b/src/providers/ad/ad_common.c
-@@ -757,20 +757,14 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
-         goto done;
-     }
- 
--    service->krb5_service = talloc_zero(service, struct krb5_service);
-+    service->krb5_service = krb5_service_new(service, bectx,
-+                                             ad_service, krb5_realm,
-+                                             use_kdcinfo);
-     if (!service->krb5_service) {
-         ret = ENOMEM;
-         goto done;
-     }
- 
--    /* Set flag that controls whether we want to write the
--     * kdcinfo files at all
--     */
--    service->krb5_service->write_kdcinfo = use_kdcinfo;
--    DEBUG(SSSDBG_CONF_SETTINGS, "write_kdcinfo for realm %s set to %s\n",
--                       krb5_realm,
--                       service->krb5_service->write_kdcinfo ? "true" : "false");
--
-     ret = be_fo_add_service(bectx, ad_service, ad_user_data_cmp);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n");
-@@ -783,12 +777,6 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
-         goto done;
-     }
- 
--    service->krb5_service->name = talloc_strdup(service->krb5_service,
--                                                ad_service);
--    if (!service->krb5_service->name) {
--        ret = ENOMEM;
--        goto done;
--    }
-     service->sdap->kinit_service_name = service->krb5_service->name;
-     service->gc->kinit_service_name = service->krb5_service->name;
- 
-@@ -797,14 +785,6 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
-         ret = EINVAL;
-         goto done;
-     }
--    service->krb5_service->realm =
--        talloc_strdup(service->krb5_service, krb5_realm);
--    if (!service->krb5_service->realm) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    service->krb5_service->be_ctx = bectx;
- 
-     if (!primary_servers) {
-         DEBUG(SSSDBG_CONF_SETTINGS,
-diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
-index dcbb54a744358718e444972b9827ee64887e5e33..5808513bfd570c43bc1712114aabba5749ba0fec 100644
---- a/src/providers/ipa/ipa_common.c
-+++ b/src/providers/ipa/ipa_common.c
-@@ -965,6 +965,13 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-         return ENOMEM;
-     }
- 
-+    realm = dp_opt_get_string(options->basic, IPA_KRB5_REALM);
-+    if (!realm) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm set\n");
-+        ret = EINVAL;
-+        goto done;
-+    }
-+
-     service = talloc_zero(tmp_ctx, struct ipa_service);
-     if (!service) {
-         ret = ENOMEM;
-@@ -975,7 +982,13 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-         ret = ENOMEM;
-         goto done;
-     }
--    service->krb5_service = talloc_zero(service, struct krb5_service);
-+
-+    service->krb5_service = krb5_service_new(service, ctx,
-+                                             "IPA", realm,
-+                                             true); /* The configured value
-+                                                     * will be set later when
-+                                                     * the auth provider is set up
-+                                                     */
-     if (!service->krb5_service) {
-         ret = ENOMEM;
-         goto done;
-@@ -993,28 +1006,8 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-         goto done;
-     }
- 
--    service->krb5_service->name = talloc_strdup(service, "IPA");
--    if (!service->krb5_service->name) {
--        ret = ENOMEM;
--        goto done;
--    }
-     service->sdap->kinit_service_name = service->krb5_service->name;
- 
--    realm = dp_opt_get_string(options->basic, IPA_KRB5_REALM);
--    if (!realm) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm set\n");
--        ret = EINVAL;
--        goto done;
--    }
--    service->krb5_service->realm =
--        talloc_strdup(service->krb5_service, realm);
--    if (!service->krb5_service->realm) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    service->krb5_service->be_ctx = ctx;
--
-     if (!primary_servers) {
-         DEBUG(SSSDBG_CONF_SETTINGS,
-               "No primary servers defined, using service discovery\n");
-diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
-index d064a09ac3726c4185c2fa1eeac76ef6c261d33b..2a50dfec55c29b8d7f8b8751c904977c22aa906a 100644
---- a/src/providers/krb5/krb5_common.c
-+++ b/src/providers/krb5/krb5_common.c
-@@ -807,6 +807,40 @@ static int krb5_user_data_cmp(void *ud1, void *ud2)
-     return strcasecmp((char*) ud1, (char*) ud2);
- }
- 
-+struct krb5_service *krb5_service_new(TALLOC_CTX *mem_ctx,
-+                                      struct be_ctx *be_ctx,
-+                                      const char *service_name,
-+                                      const char *realm,
-+                                      bool use_kdcinfo)
-+{
-+    struct krb5_service *service;
-+
-+    service = talloc_zero(mem_ctx, struct krb5_service);
-+    if (service == NULL) {
-+        return NULL;
-+    }
-+
-+    service->name = talloc_strdup(service, service_name);
-+    if (service->name == NULL) {
-+        talloc_free(service);
-+        return NULL;
-+    }
-+
-+    service->realm = talloc_strdup(service, realm);
-+    if (service->realm == NULL) {
-+        talloc_free(service);
-+        return NULL;
-+    }
-+
-+    DEBUG(SSSDBG_CONF_SETTINGS,
-+          "write_kdcinfo for realm %s set to %s\n",
-+          realm,
-+          use_kdcinfo ? "true" : "false");
-+    service->write_kdcinfo = use_kdcinfo;
-+    service->be_ctx = be_ctx;
-+    return service;
-+}
-+
- int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-                       const char *service_name,
-                       const char *primary_servers,
-@@ -824,7 +858,7 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-         return ENOMEM;
-     }
- 
--    service = talloc_zero(tmp_ctx, struct krb5_service);
-+    service = krb5_service_new(tmp_ctx, ctx, service_name, realm, use_kdcinfo);
-     if (!service) {
-         ret = ENOMEM;
-         goto done;
-@@ -836,21 +870,6 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-         goto done;
-     }
- 
--    service->name = talloc_strdup(service, service_name);
--    if (!service->name) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    service->realm = talloc_strdup(service, realm);
--    if (!service->realm) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    service->write_kdcinfo = use_kdcinfo;
--    service->be_ctx = ctx;
--
-     if (!primary_servers) {
-         DEBUG(SSSDBG_CONF_SETTINGS,
-               "No primary servers defined, using service discovery\n");
-diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
-index 3529d740b89fee91281f936fdafd1bdb99e95bd7..1c12d5652ccef7e1738177eedad1c9de543916b7 100644
---- a/src/providers/krb5/krb5_common.h
-+++ b/src/providers/krb5/krb5_common.h
-@@ -164,6 +164,12 @@ errno_t write_krb5info_file(struct krb5_service *krb5_service,
-                             const char *server,
-                             const char *service);
- 
-+struct krb5_service *krb5_service_new(TALLOC_CTX *mem_ctx,
-+                                      struct be_ctx *be_ctx,
-+                                      const char *service_name,
-+                                      const char *realm,
-+                                      bool use_kdcinfo);
-+
- int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
-                       const char *service_name,
-                       const char *primary_servers,
--- 
-2.17.1
-
diff --git a/SOURCES/0026-KRB5-Allow-writing-multiple-addresses-to-the-kdcinfo.patch b/SOURCES/0026-KRB5-Allow-writing-multiple-addresses-to-the-kdcinfo.patch
deleted file mode 100644
index 87a0435..0000000
--- a/SOURCES/0026-KRB5-Allow-writing-multiple-addresses-to-the-kdcinfo.patch
+++ /dev/null
@@ -1,246 +0,0 @@
-From 73f452058c8ac83117cb86c12d4d266c8caccc57 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 26 Jun 2018 10:35:15 +0200
-Subject: [PATCH] KRB5: Allow writing multiple addresses to the kdcinfo plugin
-
-Turns the previous write_krb5info_file() function into a static function
-that writes whatever input it recevies. Adds a wrapper around it that
-accepts a list of strings, turns that into a newline-separated string
-which is then passed to the original function.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3291
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 8971399c872c21769d5c62cf753c5f9df4caf8cb)
----
- src/providers/ad/ad_common.c     | 12 ++---
- src/providers/ipa/ipa_common.c   |  8 ++--
- src/providers/krb5/krb5_common.c | 75 +++++++++++++++++++++++++-------
- src/providers/krb5/krb5_common.h |  2 +-
- 4 files changed, 70 insertions(+), 27 deletions(-)
-
-diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
-index b103410e5915a380d0404e18da869517e4d4e355..eaf0814f1aaf51a5085e992efa633240f32c498e 100644
---- a/src/providers/ad/ad_common.c
-+++ b/src/providers/ad/ad_common.c
-@@ -848,7 +848,7 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
-     struct resolv_hostent *srvaddr;
-     struct sockaddr_storage *sockaddr;
-     char *address;
--    const char *safe_address;
-+    char *safe_addr_list[2] = { NULL, NULL };
-     char *new_uri;
-     int new_port;
-     const char *srv_name;
-@@ -957,17 +957,17 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
-     if ((sdata == NULL || sdata->gc == false) &&
-         service->krb5_service->write_kdcinfo) {
-         /* Write krb5 info files */
--        safe_address = sss_escape_ip_address(tmp_ctx,
--                                            srvaddr->family,
--                                            address);
--        if (safe_address == NULL) {
-+        safe_addr_list[0] = sss_escape_ip_address(tmp_ctx,
-+                                                  srvaddr->family,
-+                                                  address);
-+        if (safe_addr_list[0] == NULL) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "sss_escape_ip_address failed.\n");
-             ret = ENOMEM;
-             goto done;
-         }
- 
-         ret = write_krb5info_file(service->krb5_service,
--                                  safe_address,
-+                                  safe_addr_list,
-                                   SSS_KRB5KDC_FO_SRV);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_MINOR_FAILURE,
-diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
-index 5808513bfd570c43bc1712114aabba5749ba0fec..0614019764287e5114aa8b8b5c670b717732068b 100644
---- a/src/providers/ipa/ipa_common.c
-+++ b/src/providers/ipa/ipa_common.c
-@@ -766,7 +766,7 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server)
-     struct resolv_hostent *srvaddr;
-     struct sockaddr_storage *sockaddr;
-     char *address;
--    const char *safe_address;
-+    char *safe_addr_list[2] = { NULL, NULL };
-     char *new_uri;
-     const char *srv_name;
-     int ret;
-@@ -829,17 +829,17 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server)
-     service->sdap->sockaddr = talloc_steal(service, sockaddr);
- 
-     if (service->krb5_service->write_kdcinfo) {
--        safe_address = sss_escape_ip_address(tmp_ctx,
-+        safe_addr_list[0] = sss_escape_ip_address(tmp_ctx,
-                                              srvaddr->family,
-                                              address);
--        if (safe_address == NULL) {
-+        if (safe_addr_list[0] == NULL) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "sss_escape_ip_address failed.\n");
-             talloc_free(tmp_ctx);
-             return;
-         }
- 
-         ret = write_krb5info_file(service->krb5_service,
--                                  safe_address,
-+                                  safe_addr_list,
-                                   SSS_KRB5KDC_FO_SRV);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE,
-diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
-index 2a50dfec55c29b8d7f8b8751c904977c22aa906a..2b003e1642b449e8db20ba4259ba13273e21212f 100644
---- a/src/providers/krb5/krb5_common.c
-+++ b/src/providers/krb5/krb5_common.c
-@@ -466,10 +466,9 @@ done:
-     return ret;
- }
- 
--
--errno_t write_krb5info_file(struct krb5_service *krb5_service,
--                            const char *server,
--                            const char *service)
-+static errno_t write_krb5info_file_contents(struct krb5_service *krb5_service,
-+                                            const char *contents,
-+                                            const char *service)
- {
-     int ret;
-     int fd = -1;
-@@ -482,7 +481,7 @@ errno_t write_krb5info_file(struct krb5_service *krb5_service,
- 
-     if (krb5_service == NULL || krb5_service->realm == NULL
-                              || *krb5_service->realm == '\0'
--                             || server == NULL || *server == '\0'
-+                             || contents == NULL || *contents == '\0'
-                              || service == NULL || *service == '\0') {
-         DEBUG(SSSDBG_CRIT_FAILURE,
-               "Missing or empty realm, server or service.\n");
-@@ -505,7 +504,7 @@ errno_t write_krb5info_file(struct krb5_service *krb5_service,
-         return EINVAL;
-     }
- 
--    server_len = strlen(server);
-+    server_len = strlen(contents);
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -535,7 +534,7 @@ errno_t write_krb5info_file(struct krb5_service *krb5_service,
-     }
- 
-     errno = 0;
--    written = sss_atomic_write_s(fd, discard_const(server), server_len);
-+    written = sss_atomic_write_s(fd, discard_const(contents), server_len);
-     if (written == -1) {
-         ret = errno;
-         DEBUG(SSSDBG_CRIT_FAILURE,
-@@ -592,12 +591,56 @@ done:
-     return ret;
- }
- 
-+errno_t write_krb5info_file(struct krb5_service *krb5_service,
-+                            char **server_list,
-+                            const char *service)
-+{
-+    int i;
-+    errno_t ret;
-+    TALLOC_CTX *tmp_ctx = NULL;
-+    char *contents = NULL;
-+
-+    if (krb5_service == NULL || server_list == NULL || service == NULL) {
-+        return EINVAL;
-+    }
-+
-+    if (server_list[0] == NULL) {
-+        return EOK;
-+    }
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    contents = talloc_strdup(tmp_ctx, "");
-+    if (contents == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    i = 0;
-+    do {
-+        contents = talloc_asprintf_append(contents, "%s\n", server_list[i]);
-+        if (contents == NULL) {
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+        i++;
-+    } while (server_list[i] != NULL);
-+
-+    ret = write_krb5info_file_contents(krb5_service, contents, service);
-+done:
-+    talloc_free(tmp_ctx);
-+    return ret;
-+}
-+
- static void krb5_resolve_callback(void *private_data, struct fo_server *server)
- {
-     struct krb5_service *krb5_service;
-     struct resolv_hostent *srvaddr;
-     char *address;
--    char *safe_address;
-+    char *safe_addr_list[2] = { NULL, NULL };
-     int ret;
-     TALLOC_CTX *tmp_ctx = NULL;
- 
-@@ -630,26 +673,26 @@ static void krb5_resolve_callback(void *private_data, struct fo_server *server)
-         return;
-     }
- 
--    safe_address = sss_escape_ip_address(tmp_ctx,
--                                         srvaddr->family,
--                                         address);
--    if (safe_address == NULL) {
-+    safe_addr_list[0] = sss_escape_ip_address(tmp_ctx,
-+                                              srvaddr->family,
-+                                              address);
-+    if (safe_addr_list[0] == NULL) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "sss_escape_ip_address failed.\n");
-         talloc_free(tmp_ctx);
-         return;
-     }
- 
-     if (krb5_service->write_kdcinfo) {
--        safe_address = talloc_asprintf_append(safe_address, ":%d",
--                                            fo_get_server_port(server));
--        if (safe_address == NULL) {
-+        safe_addr_list[0] = talloc_asprintf_append(safe_addr_list[0], ":%d",
-+                                                   fo_get_server_port(server));
-+        if (safe_addr_list[0] == NULL) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf_append failed.\n");
-             talloc_free(tmp_ctx);
-             return;
-         }
- 
-         ret = write_krb5info_file(krb5_service,
--                                  safe_address,
-+                                  safe_addr_list,
-                                   krb5_service->name);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE,
-diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
-index 1c12d5652ccef7e1738177eedad1c9de543916b7..bf36a551a92877ec838d8d3a041903144f22bc8f 100644
---- a/src/providers/krb5/krb5_common.h
-+++ b/src/providers/krb5/krb5_common.h
-@@ -161,7 +161,7 @@ errno_t sss_krb5_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb,
-                              const char *conf_path, struct dp_option **_opts);
- 
- errno_t write_krb5info_file(struct krb5_service *krb5_service,
--                            const char *server,
-+                            char **server_list,
-                             const char *service);
- 
- struct krb5_service *krb5_service_new(TALLOC_CTX *mem_ctx,
--- 
-2.17.1
-
diff --git a/SOURCES/0026-PAM-Also-cache-SSS_PAM_PREAUTH.patch b/SOURCES/0026-PAM-Also-cache-SSS_PAM_PREAUTH.patch
new file mode 100644
index 0000000..5253c3d
--- /dev/null
+++ b/SOURCES/0026-PAM-Also-cache-SSS_PAM_PREAUTH.patch
@@ -0,0 +1,115 @@
+From 0a637fff4fe575916bdae0eb17b7c36e8427308a Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 17 Apr 2019 15:07:43 +0200
+Subject: [PATCH] PAM: Also cache SSS_PAM_PREAUTH
+
+Related: https://pagure.io/SSSD/sssd/issue/3960
+
+Even if cached_auth_timeout was set, the pam responder would still
+forward the preauthentication requests to the back end. This could
+trigger unwanted traffic towards the KDCs.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit c911562d1bea8ae44e45e564c9df5df43d87b035)
+---
+ src/man/sssd.conf.5.xml        |  4 +++-
+ src/responder/pam/pamsrv_cmd.c | 40 +++++++++++++++-------------------
+ 2 files changed, 21 insertions(+), 23 deletions(-)
+
+diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
+index 274809e24..1ab7af00b 100644
+--- a/src/man/sssd.conf.5.xml
++++ b/src/man/sssd.conf.5.xml
+@@ -2960,7 +2960,9 @@ subdomain_inherit = ldap_purge_cache_timeout
+                             Specifies time in seconds since last successful
+                             online authentication for which user will be
+                             authenticated using cached credentials while
+-                            SSSD is in the online mode.
++                            SSSD is in the online mode. If the credentials
++                            are incorrect, SSSD falls back to online
++                            authentication.
+                         </para>
+                         <para>
+                             This option's value is inherited by all trusted
+diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
+index 6b2dc5bdc..00302be75 100644
+--- a/src/responder/pam/pamsrv_cmd.c
++++ b/src/responder/pam/pamsrv_cmd.c
+@@ -803,8 +803,9 @@ static void pam_reply(struct pam_auth_req *preq)
+         pam_verbosity = DEFAULT_PAM_VERBOSITY;
+     }
+ 
+-    DEBUG(SSSDBG_FUNC_DATA,
+-          "pam_reply called with result [%d]: %s.\n",
++    DEBUG(SSSDBG_TRACE_ALL,
++          "pam_reply initially called with result [%d]: %s. "
++          "this result might be changed during processing\n",
+           pd->pam_status, pam_strerror(NULL, pd->pam_status));
+ 
+     if (pd->cmd == SSS_PAM_AUTHENTICATE
+@@ -886,6 +887,7 @@ static void pam_reply(struct pam_auth_req *preq)
+             break;
+ /* TODO: we need the pam session cookie here to make sure that cached
+  * authentication was successful */
++        case SSS_PAM_PREAUTH:
+         case SSS_PAM_SETCRED:
+         case SSS_PAM_ACCT_MGMT:
+         case SSS_PAM_OPEN_SESSION:
+@@ -1067,6 +1069,8 @@ static void pam_reply(struct pam_auth_req *preq)
+     }
+ 
+ done:
++    DEBUG(SSSDBG_FUNC_DATA, "Returning [%d]: %s to the client\n",
++          pd->pam_status, pam_strerror(NULL, pd->pam_status));
+     sss_cmd_done(cctx, preq);
+ }
+ 
+@@ -1949,21 +1953,6 @@ done:
+     return ret;
+ }
+ 
+-static bool pam_is_cmd_cachable(int cmd)
+-{
+-    bool is_cachable;
+-
+-    switch(cmd) {
+-    case SSS_PAM_AUTHENTICATE:
+-        is_cachable = true;
+-        break;
+-    default:
+-        is_cachable = false;
+-    }
+-
+-    return is_cachable;
+-}
+-
+ static bool pam_is_authtok_cachable(struct sss_auth_token *authtok)
+ {
+     enum sss_authtok_type type;
+@@ -1988,11 +1977,18 @@ static bool pam_can_user_cache_auth(struct sss_domain_info *domain,
+     errno_t ret;
+     bool result = false;
+ 
+-    if (!cached_auth_failed /* don't try cached auth again */
+-            && domain->cache_credentials
+-            && domain->cached_auth_timeout > 0
+-            && pam_is_authtok_cachable(authtok)
+-            && pam_is_cmd_cachable(pam_cmd)) {
++    if (cached_auth_failed) {
++        /* Do not retry indefinitely */
++        return false;
++    }
++
++    if (!domain->cache_credentials || domain->cached_auth_timeout <= 0) {
++        return false;
++    }
++
++    if (pam_cmd == SSS_PAM_PREAUTH
++        || (pam_cmd == SSS_PAM_AUTHENTICATE
++            && pam_is_authtok_cachable(authtok))) {
+ 
+         ret = pam_is_last_online_login_fresh(domain, user,
+                                              domain->cached_auth_timeout,
+-- 
+2.19.2
+
diff --git a/SOURCES/0027-IPA-Add-the-options-that-the-IPA-subdomains-code-wil.patch b/SOURCES/0027-IPA-Add-the-options-that-the-IPA-subdomains-code-wil.patch
deleted file mode 100644
index b000355..0000000
--- a/SOURCES/0027-IPA-Add-the-options-that-the-IPA-subdomains-code-wil.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 51354c3e23aa59d88e0340fb7cdbb9b7d4990743 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 25 Jun 2018 13:10:34 +0200
-Subject: [PATCH] IPA: Add the options that the IPA subdomains code will read
- for trusted domains on the client
-
-With this patchset, IPA clients will read and evaluate the ad_server and
-ad_site options. This patch just adds the required structures for later
-usage.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3291
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 1cce549e0f88f4873c320577d6213dcaeb08766f)
----
- src/providers/ipa/ipa_common.h | 7 +++++++
- src/providers/ipa/ipa_opts.c   | 6 ++++++
- src/providers/ipa/ipa_opts.h   | 2 ++
- 3 files changed, 15 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
-index 725e0e93728f7643bdf2220a4cb7ecfbbb8b958a..31e671eb50393f77225281226558d9848b3d3d78 100644
---- a/src/providers/ipa/ipa_common.h
-+++ b/src/providers/ipa/ipa_common.h
-@@ -175,6 +175,13 @@ enum ipa_sudocmd_attrs {
-     IPA_OPTS_SUDOCMD
- };
- 
-+enum ipa_cli_ad_subdom_attrs {
-+    IPA_CLI_AD_SERVER,
-+    IPA_CLI_AD_SITE,
-+
-+    IPA_OPTS_CLI_AD_SUBDOM
-+};
-+
- struct ipa_auth_ctx {
-     struct krb5_ctx *krb5_auth_ctx;
-     struct sdap_id_ctx *sdap_id_ctx;
-diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
-index 9419cdcc3913c58e2bcefe238b56fb75e8aa52ec..485ad4fe3ff9808343a94b1792f8c632a3d4b481 100644
---- a/src/providers/ipa/ipa_opts.c
-+++ b/src/providers/ipa/ipa_opts.c
-@@ -389,3 +389,9 @@ struct sdap_attr_map ipa_sudocmd_map[] = {
-     { "ipa_sudocmd_memberof", "memberOf", SYSDB_MEMBEROF, NULL },
-     SDAP_ATTR_MAP_TERMINATOR
- };
-+
-+struct dp_option ipa_cli_ad_subdom_opts [] = {
-+    { "ad_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-+    { "ad_site", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-+    DP_OPTION_TERMINATOR
-+};
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index 68326b8649a268232394a8fe970d932feb01d46e..378a9922c7b58fc4374262250efbd61b4b6a932f 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -64,4 +64,6 @@ extern struct sdap_attr_map ipa_sudocmdgroup_map[];
- 
- extern struct sdap_attr_map ipa_sudocmd_map[];
- 
-+extern struct dp_option ipa_cli_ad_subdom_opts[];
-+
- #endif /* IPA_OPTS_H_ */
--- 
-2.17.1
-
diff --git a/SOURCES/0027-winbind-idmap-plugin-update-struct-idmap_domain-to-l.patch b/SOURCES/0027-winbind-idmap-plugin-update-struct-idmap_domain-to-l.patch
new file mode 100644
index 0000000..d32bc45
--- /dev/null
+++ b/SOURCES/0027-winbind-idmap-plugin-update-struct-idmap_domain-to-l.patch
@@ -0,0 +1,94 @@
+From e6734785fd1970c4b63d0dd021074003e35d7137 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 5 Apr 2019 18:05:08 +0200
+Subject: [PATCH] winbind idmap plugin: update struct idmap_domain to latest
+ version
+
+While updating to interface version 6 we forgot to add the query_user
+member.
+
+Recent version of Samba added a new member dom_sid. Unfortunately the
+interface version was not update for this change so we have to enable
+the member based on the Samba version.
+
+Related to https://pagure.io/SSSD/sssd/issue/4005
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 30734e5f213f4bd2984e632d497d7cbfc16495db)
+---
+ src/external/samba.m4                         | 13 +++++++++++++
+ src/lib/winbind_idmap_sss/winbind_idmap_sss.c |  4 ++++
+ src/lib/winbind_idmap_sss/winbind_idmap_sss.h | 15 +++++++++++++++
+ 3 files changed, 32 insertions(+)
+
+diff --git a/src/external/samba.m4 b/src/external/samba.m4
+index 7a8c1eb7b..e68f064b3 100644
+--- a/src/external/samba.m4
++++ b/src/external/samba.m4
+@@ -121,6 +121,19 @@ int main(void)
+     AC_MSG_NOTICE([Samba's idmap interface version: $idmap_version])
+     AC_DEFINE_UNQUOTED(SMB_IDMAP_INTERFACE_VERSION, $idmap_version,
+                        [Detected version of Samba's idmap plugin interface])
++
++    samba_major_version=`echo -e '#include <samba/version.h>\nSAMBA_VERSION_MAJOR' | $CPP $SMBCLIENT_CFLAGS -P -`
++    samba_minor_version=`echo -e '#include <samba/version.h>\nSAMBA_VERSION_MINOR' | $CPP $SMBCLIENT_CFLAGS -P -`
++    samba_release_version=`echo -e '#include <samba/version.h>\nSAMBA_VERSION_RELEASE' | $CPP $SMBCLIENT_CFLAGS -P -`
++    AC_MSG_NOTICE([Samba version: $samba_major_version $samba_minor_version $samba_release_version])
++    if test $samba_major_version -ge 4 -a $samba_minor_version -ge 8 ; then
++        AC_DEFINE_UNQUOTED(SMB_IDMAP_DOMAIN_HAS_DOM_SID, 1,
++                           [Samba's struct idmap_domain has dom_sid member])
++        AC_MSG_NOTICE([Samba's struct idmap_domain has dom_sid member])
++    else
++        AC_MSG_NOTICE([Samba's struct idmap_domain does not have dom_sid member])
++    fi
++
+ fi
+ 
+ SAVE_CFLAGS=$CFLAGS
+diff --git a/src/lib/winbind_idmap_sss/winbind_idmap_sss.c b/src/lib/winbind_idmap_sss/winbind_idmap_sss.c
+index 0d9109455..58375322a 100644
+--- a/src/lib/winbind_idmap_sss/winbind_idmap_sss.c
++++ b/src/lib/winbind_idmap_sss/winbind_idmap_sss.c
+@@ -55,6 +55,10 @@ static NTSTATUS idmap_sss_initialize(struct idmap_domain *dom)
+         return NT_STATUS_NO_MEMORY;
+     }
+ 
++#if SMB_IDMAP_INTERFACE_VERSION == 6
++    dom->query_user = NULL;
++#endif
++
+     dom->private_data = ctx;
+ 
+     return NT_STATUS_OK;
+diff --git a/src/lib/winbind_idmap_sss/winbind_idmap_sss.h b/src/lib/winbind_idmap_sss/winbind_idmap_sss.h
+index 868049fff..78800838e 100644
+--- a/src/lib/winbind_idmap_sss/winbind_idmap_sss.h
++++ b/src/lib/winbind_idmap_sss/winbind_idmap_sss.h
+@@ -70,9 +70,24 @@ struct id_map {
+ #error Missing Samba idmap interface version
+ #endif
+ 
++#if SMB_IDMAP_INTERFACE_VERSION == 6
++struct wbint_userinfo;
++#endif
++
+ struct idmap_domain {
+     const char *name;
++#if SMB_IDMAP_INTERFACE_VERSION == 6 && defined(SMB_IDMAP_DOMAIN_HAS_DOM_SID)
++    /*
++     * dom_sid is currently only initialized in the unixids_to_sids request,
++     * so don't rely on this being filled out everywhere!
++     */
++    struct dom_sid dom_sid;
++#endif
+     struct idmap_methods *methods;
++#if SMB_IDMAP_INTERFACE_VERSION == 6
++    NTSTATUS (*query_user)(struct idmap_domain *domain,
++                           struct wbint_userinfo *info);
++#endif
+     uint32_t low_id;
+     uint32_t high_id;
+     bool read_only;
+-- 
+2.19.1
+
diff --git a/SOURCES/0028-DP-add-NULL-check-to-be_ptask_-enable-disable.patch b/SOURCES/0028-DP-add-NULL-check-to-be_ptask_-enable-disable.patch
new file mode 100644
index 0000000..6081663
--- /dev/null
+++ b/SOURCES/0028-DP-add-NULL-check-to-be_ptask_-enable-disable.patch
@@ -0,0 +1,77 @@
+From cb94d00f31d1d6b6fcaa69dbaa928031d2e7c092 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 24 May 2019 09:18:25 +0200
+Subject: [PATCH 28/29] DP: add NULL check to be_ptask_{enable|disable}
+
+Currently the files and the proxy provider do not provide a check online
+method (DPM_CHECK_ONLINE). The files provider because it can never go
+offline. The proxy provider because there is no generic way to check
+since the nature of the actual provider is unknown.
+
+Since the method is missing check_if_online() jumps into the error
+handling block were we try to reset the offline state
+unconditionally. If there is no check_if_online_ptask, which never
+exists for the files provider and will not be available in the proxy
+provider as long as the backend is online, be_ptask_{enable|disable}
+will be called with a NULL pointer.
+
+Related to https://pagure.io/SSSD/sssd/issue/4014
+
+Reviewed-by: Tomas Halman <thalman@redhat.com>
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+(cherry picked from commit 2720d97ce2559a3a382caf8f669820f64d6097fe)
+---
+ src/providers/be_ptask.c | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/src/providers/be_ptask.c b/src/providers/be_ptask.c
+index dc3c57db5..c43351755 100644
+--- a/src/providers/be_ptask.c
++++ b/src/providers/be_ptask.c
+@@ -352,26 +352,31 @@ done:
+ 
+ void be_ptask_enable(struct be_ptask *task)
+ {
+-    if (task->enabled) {
+-        DEBUG(SSSDBG_MINOR_FAILURE, "Task [%s]: already enabled\n",
+-                                     task->name);
+-        return;
+-    }
++    if (task != NULL) {
++        if (task->enabled) {
++            DEBUG(SSSDBG_MINOR_FAILURE, "Task [%s]: already enabled\n",
++                                         task->name);
++            return;
++        }
+ 
+-    DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: enabling task\n", task->name);
++        DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: enabling task\n", task->name);
+ 
+-    task->enabled = true;
+-    be_ptask_schedule(task, BE_PTASK_ENABLED_DELAY, BE_PTASK_SCHEDULE_FROM_NOW);
++        task->enabled = true;
++        be_ptask_schedule(task, BE_PTASK_ENABLED_DELAY,
++                          BE_PTASK_SCHEDULE_FROM_NOW);
++    }
+ }
+ 
+ /* Disable the task, but if a request already in progress, let it finish. */
+ void be_ptask_disable(struct be_ptask *task)
+ {
+-    DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: disabling task\n", task->name);
++    if (task != NULL) {
++        DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: disabling task\n", task->name);
+ 
+-    talloc_zfree(task->timer);
+-    task->enabled = false;
+-    task->period = task->orig_period;
++        talloc_zfree(task->timer);
++        task->enabled = false;
++        task->period = task->orig_period;
++    }
+ }
+ 
+ void be_ptask_destroy(struct be_ptask **task)
+-- 
+2.20.1
+
diff --git a/SOURCES/0028-IPA-Populate-kdcinfo-files-on-trust-clients-with-con.patch b/SOURCES/0028-IPA-Populate-kdcinfo-files-on-trust-clients-with-con.patch
deleted file mode 100644
index abbcae1..0000000
--- a/SOURCES/0028-IPA-Populate-kdcinfo-files-on-trust-clients-with-con.patch
+++ /dev/null
@@ -1,800 +0,0 @@
-From f1780cea77deb98789cc9c53cb6d7c83e2931e70 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 25 Jun 2018 13:10:39 +0200
-Subject: [PATCH] IPA: Populate kdcinfo files on trust clients with configured
- AD servers
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3291
-
-Adds a new request into the IPA subdomains provider. This request runs on
-IPA clients only.
-
-The request looks into the configuration for either the ad_site or ad_server
-options for each subdomain. If none are found, the subdomain is skipped.
-
-If either is found, the request resolves the server names, or first the
-site and then the server names from the site and writes their addresses
-to the kdcinfo files for each subdomain. This allows programs such as
-kinit but also SSSD's krb5_child to use the configured servers.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 18b7f0a30b4745b7d61b3e599e5fb8cd399c23f3)
----
- src/providers/ipa/ipa_subdomains.c | 718 ++++++++++++++++++++++++++++-
- 1 file changed, 716 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index a8a18ad8a3ec08c137994a84d51851e996aad6dc..1b443559eada3b8feeb9c91fbebd4e2dcca87a23 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -76,6 +76,18 @@
-                               "("IPA_ENABLED_FLAG"="IPA_TRUE_VALUE"))" \
-                           "("OBJECTCLASS"="IPA_OC_CERTMAP_CONFIG_OBJECT"))"
- 
-+/* It doesn't make sense to resolve more servers than this from the SRV
-+ * lookup because kinit would time out before we are able to cycle
-+ * through the whole list
-+ */
-+#define MAX_SERVERS_FROM_SRV    5
-+
-+struct ipa_sd_k5_svc_list {
-+    struct krb5_service *k5svc;
-+
-+    struct ipa_sd_k5_svc_list *next;
-+    struct ipa_sd_k5_svc_list *prev;
-+};
- 
- struct ipa_subdomains_ctx {
-     struct be_ctx *be_ctx;
-@@ -88,6 +100,11 @@ struct ipa_subdomains_ctx {
- 
-     time_t last_refreshed;
-     bool view_read_at_init;
-+    /* List of krb5_service structures for each subdomain
-+     * in order to write the kdcinfo files. For use on
-+     * the client only
-+     */
-+    struct ipa_sd_k5_svc_list *k5svc_list;
- };
- 
- static errno_t
-@@ -635,6 +652,69 @@ done:
-     return ret;
- }
- 
-+static struct krb5_service *
-+ipa_subdom_get_k5_svc(struct ipa_subdomains_ctx *ctx,
-+                      struct sss_domain_info *dom,
-+                      bool use_kdcinfo)
-+{
-+    struct ipa_sd_k5_svc_list *k5svc_ent;
-+
-+    /* get the service by realm */
-+    DLIST_FOR_EACH(k5svc_ent, ctx->k5svc_list) {
-+        if (strcasecmp(dom->realm, k5svc_ent->k5svc->realm) == 0) {
-+            break;
-+        }
-+    }
-+
-+    if (k5svc_ent != NULL) {
-+        /* Already exists */
-+        return k5svc_ent->k5svc;
-+    }
-+
-+    /* Create a new service */
-+    k5svc_ent = talloc_zero(ctx, struct ipa_sd_k5_svc_list);
-+    if (k5svc_ent == NULL) {
-+        return NULL;
-+    }
-+
-+    k5svc_ent->k5svc = krb5_service_new(k5svc_ent,
-+                                        ctx->be_ctx,
-+                                        "IPA",
-+                                        dom->realm,
-+                                        use_kdcinfo);
-+    if (k5svc_ent->k5svc == NULL) {
-+        talloc_free(k5svc_ent);
-+        return NULL;
-+    }
-+    DLIST_ADD(ctx->k5svc_list, k5svc_ent);
-+
-+    return k5svc_ent->k5svc;
-+}
-+
-+static void ipa_subdom_remove_k5_svc(struct ipa_subdomains_ctx *ctx)
-+{
-+    /* Domain going away is such a rare operation that it makes
-+     * more sense to just throw away the whole k5svc_list and let
-+     * the write_kdcinfo request recreate them all again instead
-+     * of coding up complex logic..
-+     */
-+    talloc_zfree(ctx->k5svc_list);
-+}
-+
-+static void ipa_subdom_remove_step(struct ipa_subdomains_ctx *ctx,
-+                                   struct sss_domain_info *dom)
-+{
-+    if (dp_opt_get_bool(ctx->ipa_id_ctx->ipa_options->basic,
-+                        IPA_SERVER_MODE) == false) {
-+        /* IPA clients keep track of krb5_service wrappers */
-+        return ipa_subdom_remove_k5_svc(ctx);
-+    } else {
-+        /* IPA servers keeps track of AD contexts */
-+        return ipa_ad_subdom_remove(ctx->be_ctx, ctx->ipa_id_ctx, dom);
-+    }
-+
-+}
-+
- static void ipa_subdom_store_step(struct sss_domain_info *parent,
-                                   struct ipa_id_ctx *id_ctx,
-                                   struct sdap_idmap_ctx *sdap_idmap_ctx,
-@@ -697,8 +777,7 @@ static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
-                 goto done;
-             }
- 
--            /* Remove the AD ID ctx from the list of LDAP domains */
--            ipa_ad_subdom_remove(ctx->be_ctx, ctx->ipa_id_ctx, dom);
-+            ipa_subdom_remove_step(ctx, dom);
-         } else {
-             /* ok let's try to update it */
-             ipa_subdom_store_step(parent, ctx->ipa_id_ctx,
-@@ -1917,6 +1996,611 @@ static errno_t ipa_domain_resolution_order_recv(struct tevent_req *req)
-     return EOK;
- }
- 
-+struct kdcinfo_from_server_list_state {
-+    struct resolv_hostport *hostport_list;
-+    enum host_database db[2];
-+
-+    struct resolv_hostport_addr **rhp_addrs;
-+    size_t rhp_len;
-+};
-+
-+static void kdcinfo_from_server_list_done(struct tevent_req *subreq);
-+
-+static struct tevent_req *
-+kdcinfo_from_server_list_send(TALLOC_CTX *mem_ctx,
-+                              struct tevent_context *ev,
-+                              struct be_resolv_ctx *be_res,
-+                              const char *servers)
-+{
-+    struct kdcinfo_from_server_list_state *state;
-+    struct tevent_req *req;
-+    struct tevent_req *subreq;
-+    errno_t ret;
-+    int server_list_len;
-+    char **server_list;
-+
-+    req = tevent_req_create(mem_ctx, &state,
-+                            struct kdcinfo_from_server_list_state);
-+    if (req == NULL) {
-+        return NULL;
-+    }
-+    state->db[0] = DB_DNS;
-+    state->db[1] = DB_SENTINEL;
-+
-+    if (servers == NULL) {
-+        ret = EOK;
-+        goto immediately;
-+    }
-+
-+    ret = split_on_separator(state, servers, ',', true, true,
-+                             &server_list,
-+                             &server_list_len);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Failed to parse server list!\n");
-+        goto immediately;
-+    }
-+
-+    state->hostport_list = talloc_array(state,
-+                                        struct resolv_hostport,
-+                                        server_list_len);
-+    if (state->hostport_list == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+
-+    for (int i = 0; i < server_list_len; i++) {
-+        state->hostport_list[i].host = server_list[i];
-+        state->hostport_list[i].port = 0;
-+    }
-+
-+    subreq = resolv_hostport_list_send(state,
-+                                       ev,
-+                                       be_res->resolv,
-+                                       state->hostport_list,
-+                                       server_list_len,
-+                                       0,
-+                                       be_res->family_order,
-+                                       state->db);
-+    if (subreq == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+    tevent_req_set_callback(subreq, kdcinfo_from_server_list_done, req);
-+    return req;
-+
-+immediately:
-+    if (ret != EOK) {
-+        tevent_req_error(req, ret);
-+    } else {
-+        tevent_req_done(req);
-+    }
-+    tevent_req_post(req, ev);
-+    return req;
-+}
-+
-+static void kdcinfo_from_server_list_done(struct tevent_req *subreq)
-+{
-+    errno_t ret;
-+    struct tevent_req *req =
-+            tevent_req_callback_data(subreq, struct tevent_req);
-+    struct kdcinfo_from_server_list_state *state = tevent_req_data(req,
-+                                        struct kdcinfo_from_server_list_state);
-+
-+    ret = resolv_hostport_list_recv(subreq,
-+                                    state,
-+                                    &state->rhp_len,
-+                                    &state->rhp_addrs);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "Failed to resolve address list [%d]: %s\n", ret, sss_strerror(ret));
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    tevent_req_done(req);
-+}
-+
-+static errno_t kdcinfo_from_server_list_recv(TALLOC_CTX *mem_ctx,
-+                                             struct tevent_req *req,
-+                                             struct resolv_hostport_addr ***_rhp_addrs,
-+                                             size_t *_rhp_len)
-+{
-+    struct kdcinfo_from_server_list_state *state = tevent_req_data(req,
-+                                        struct kdcinfo_from_server_list_state);
-+
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+
-+    if (_rhp_addrs != NULL) {
-+        *_rhp_addrs = talloc_steal(mem_ctx, state->rhp_addrs);
-+    }
-+
-+    if (_rhp_len != NULL) {
-+        *_rhp_len = state->rhp_len;
-+    }
-+
-+    return EOK;
-+}
-+
-+struct kdcinfo_from_site_state {
-+    struct tevent_context *ev;
-+    struct be_resolv_ctx *be_res;
-+
-+    const char *discovery_domains[2];
-+    struct resolv_hostport *hostport_list;
-+    enum host_database db[2];
-+
-+    struct resolv_hostport_addr **rhp_addrs;
-+    size_t rhp_len;
-+};
-+
-+static void kdcinfo_from_site_srv_done(struct tevent_req *subreq);
-+static void kdcinfo_from_site_server_list_done(struct tevent_req *subreq);
-+
-+static struct tevent_req *
-+kdcinfo_from_site_send(TALLOC_CTX *mem_ctx,
-+                       struct tevent_context *ev,
-+                       struct be_resolv_ctx *be_res,
-+                       const char *site,
-+                       const char *domain)
-+{
-+    struct kdcinfo_from_site_state *state;
-+    struct tevent_req *req;
-+    struct tevent_req *subreq;
-+    errno_t ret;
-+
-+    req = tevent_req_create(mem_ctx, &state,
-+                            struct kdcinfo_from_site_state);
-+    if (req == NULL) {
-+        return NULL;
-+    }
-+    state->ev = ev;
-+    state->be_res = be_res;
-+    state->db[0] = DB_DNS;
-+    state->db[1] = DB_SENTINEL;
-+
-+    state->discovery_domains[0] = ad_site_dns_discovery_domain(state,
-+                                                               site,
-+                                                               domain);
-+    if (state->discovery_domains[0] == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+    state->discovery_domains[1] = NULL;
-+
-+    subreq = fo_discover_srv_send(state,
-+                                  state->ev,
-+                                  state->be_res->resolv,
-+                                  "kerberos", "tcp",
-+                                  state->discovery_domains);
-+    if (subreq == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+    tevent_req_set_callback(subreq, kdcinfo_from_site_srv_done, req);
-+    return req;
-+
-+immediately:
-+    if (ret != EOK) {
-+        tevent_req_error(req, ret);
-+    } else {
-+        tevent_req_done(req);
-+    }
-+    tevent_req_post(req, ev);
-+    return req;
-+}
-+
-+static void kdcinfo_from_site_srv_done(struct tevent_req *subreq)
-+{
-+    errno_t ret;
-+    struct tevent_req *req =
-+            tevent_req_callback_data(subreq, struct tevent_req);
-+    struct kdcinfo_from_site_state *state = tevent_req_data(req,
-+                                        struct kdcinfo_from_site_state);
-+    struct fo_server_info *servers;
-+    size_t num_servers;
-+
-+    ret = fo_discover_srv_recv(state, subreq,
-+                               NULL, NULL, /* not interested in TTL etc */
-+                               &servers, &num_servers);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "Could not resolve the site [%d]: %s\n", ret, sss_strerror(ret));
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    state->hostport_list = talloc_array(state,
-+                                        struct resolv_hostport,
-+                                        num_servers);
-+    if (state->hostport_list == NULL) {
-+        tevent_req_error(req, ENOMEM);
-+        return;
-+    }
-+
-+    for (size_t i = 0; i < num_servers; i++) {
-+        state->hostport_list[i].host = servers[i].host;
-+        state->hostport_list[i].port = servers[i].port;
-+    }
-+
-+    subreq = resolv_hostport_list_send(state,
-+                                       state->ev,
-+                                       state->be_res->resolv,
-+                                       state->hostport_list,
-+                                       num_servers,
-+                                       MAX_SERVERS_FROM_SRV,
-+                                       state->be_res->family_order,
-+                                       state->db);
-+    if (subreq == NULL) {
-+        tevent_req_error(req, ENOMEM);
-+        return;
-+    }
-+    tevent_req_set_callback(subreq, kdcinfo_from_site_server_list_done, req);
-+}
-+
-+static void kdcinfo_from_site_server_list_done(struct tevent_req *subreq)
-+{
-+    errno_t ret;
-+    struct tevent_req *req =
-+            tevent_req_callback_data(subreq, struct tevent_req);
-+    struct kdcinfo_from_site_state *state = tevent_req_data(req,
-+                                        struct kdcinfo_from_site_state);
-+
-+    ret = resolv_hostport_list_recv(subreq,
-+                                    state,
-+                                    &state->rhp_len,
-+                                    &state->rhp_addrs);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "Failed to resolve address list [%d]: %s\n",
-+              ret, sss_strerror(ret));
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    tevent_req_done(req);
-+}
-+
-+
-+static errno_t kdcinfo_from_site_recv(TALLOC_CTX *mem_ctx,
-+                                      struct tevent_req *req,
-+                                      struct resolv_hostport_addr ***_rhp_addrs,
-+                                      size_t *_rhp_len)
-+{
-+    struct kdcinfo_from_site_state *state = tevent_req_data(req,
-+                                        struct kdcinfo_from_site_state);
-+
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+
-+    if (_rhp_addrs != NULL) {
-+        *_rhp_addrs = talloc_steal(mem_ctx, state->rhp_addrs);
-+    }
-+
-+    if (_rhp_len != NULL) {
-+        *_rhp_len = state->rhp_len;
-+    }
-+
-+    return EOK;
-+}
-+
-+/* Anything per-domain in this request goes here so that we
-+ * can just free the whole struct without mixing data from
-+ * different domains or the overhead of another request
-+ */
-+struct ipa_sd_per_dom_kdcinfo_ctx {
-+    struct sss_domain_info *dom;
-+
-+    const char *servers;
-+    const char *site;
-+
-+    const char *discovery_domains[2];
-+    struct krb5_service *krb5_service;
-+};
-+
-+struct ipa_subdomains_write_kdcinfo_state {
-+    struct tevent_context *ev;
-+    struct ipa_subdomains_ctx *ipa_sd_ctx;
-+    struct be_ctx *be_ctx;
-+
-+    bool use_kdcinfo;
-+    struct ipa_sd_per_dom_kdcinfo_ctx *pdctx;
-+};
-+
-+static errno_t ipa_subdomains_write_kdcinfo_domain_step(struct sss_domain_info *start_dom,
-+                                                        struct tevent_req *req);
-+static void ipa_subdomains_write_kdcinfo_domain_done(struct tevent_req *subreq);
-+static errno_t ipa_subdomains_write_kdcinfo_write_step(struct sss_domain_info *dom,
-+                                                       struct krb5_service *krb5_service,
-+                                                       struct resolv_hostport_addr **rhp_addrs,
-+                                                       size_t rhp_len);
-+
-+static struct tevent_req *
-+ipa_subdomains_write_kdcinfo_send(TALLOC_CTX *mem_ctx,
-+                                  struct tevent_context *ev,
-+                                  struct ipa_subdomains_ctx *ipa_sd_ctx,
-+                                  struct be_ctx *be_ctx)
-+{
-+    struct ipa_subdomains_write_kdcinfo_state *state;
-+    struct tevent_req *req;
-+    errno_t ret;
-+
-+    req = tevent_req_create(mem_ctx, &state,
-+                            struct ipa_subdomains_write_kdcinfo_state);
-+    if (req == NULL) {
-+        return NULL;
-+    }
-+    state->ev = ev;
-+    state->ipa_sd_ctx = ipa_sd_ctx;
-+    state->be_ctx = be_ctx;
-+
-+    if (ipa_sd_ctx->ipa_id_ctx->server_mode != NULL) {
-+        /* This request is valid for clients only */
-+        ret = EOK;
-+        goto immediately;
-+    }
-+
-+    state->use_kdcinfo = dp_opt_get_bool(ipa_sd_ctx->ipa_id_ctx->ipa_options->auth,
-+                                         KRB5_USE_KDCINFO);
-+    if (state->use_kdcinfo == false) {
-+        DEBUG(SSSDBG_CONF_SETTINGS, "kdcinfo creation disabled\n");
-+        ret = EOK;
-+        goto immediately;
-+    }
-+
-+    if (be_ctx->domain->subdomains == NULL) {
-+        DEBUG(SSSDBG_CONF_SETTINGS, "No subdomains, done\n");
-+        ret = EOK;
-+        goto immediately;
-+    }
-+
-+    ret = ipa_subdomains_write_kdcinfo_domain_step(be_ctx->domain->subdomains,
-+                                                   req);
-+    if (ret != EAGAIN) {
-+        goto immediately;
-+    }
-+    return req;
-+
-+immediately:
-+    if (ret == EOK) {
-+        tevent_req_done(req);
-+    } else {
-+        tevent_req_error(req, ret);
-+    }
-+    tevent_req_post(req, ev);
-+    return req;
-+}
-+
-+static errno_t ipa_subdomains_write_kdcinfo_domain_step(struct sss_domain_info *start_dom,
-+                                                        struct tevent_req *req)
-+{
-+    struct ipa_subdomains_write_kdcinfo_state *state = \
-+                tevent_req_data(req,
-+                                struct ipa_subdomains_write_kdcinfo_state);
-+    struct dp_option *ipa_ad_subdom_opts;
-+    struct tevent_req *subreq = NULL;
-+    char *subdom_conf_path;
-+    errno_t ret;
-+    const char *servers;
-+    const char *site;
-+
-+    for (struct sss_domain_info *dom = start_dom;
-+            dom != NULL;
-+            dom = get_next_domain(dom, 0)) {
-+
-+        talloc_zfree(state->pdctx);
-+
-+        subdom_conf_path = subdomain_create_conf_path(state, dom);
-+        if (subdom_conf_path == NULL) {
-+            DEBUG(SSSDBG_MINOR_FAILURE,
-+                  "subdom_conf_path failed for %s\n", dom->name);
-+            /* Not fatal */
-+            continue;
-+        }
-+
-+        ret = dp_get_options(state, state->be_ctx->cdb,
-+                             subdom_conf_path,
-+                             ipa_cli_ad_subdom_opts,
-+                             IPA_OPTS_CLI_AD_SUBDOM,
-+                             &ipa_ad_subdom_opts);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_MINOR_FAILURE,
-+                  "Cannot get options for %s: [%d]: %s\n",
-+                  dom->name, ret, sss_strerror(ret));
-+            /* Not fatal */
-+            continue;
-+        }
-+
-+        servers = dp_opt_get_string(ipa_ad_subdom_opts, IPA_CLI_AD_SERVER);
-+        site = dp_opt_get_string(ipa_ad_subdom_opts, IPA_CLI_AD_SITE);
-+
-+        if (servers == NULL && site == NULL) {
-+            /* If neither is set, just go to the next domain */
-+            DEBUG(SSSDBG_TRACE_INTERNAL,
-+                  "No site or server defined for %s, skipping\n",
-+                  dom->name);
-+            continue;
-+        }
-+
-+        /* We will resolve this domain, create a per-domain context */
-+        state->pdctx = talloc_zero(state, struct ipa_sd_per_dom_kdcinfo_ctx);
-+        if (state->pdctx == NULL) {
-+            return ENOMEM;
-+        }
-+        state->pdctx->dom = dom;
-+        state->pdctx->servers = servers;
-+        state->pdctx->site = site;
-+        state->pdctx->krb5_service = ipa_subdom_get_k5_svc(state->ipa_sd_ctx,
-+                                                           dom,
-+                                                           state->use_kdcinfo);
-+        if (state->pdctx->krb5_service == NULL) {
-+            continue;
-+        }
-+
-+        if (state->pdctx->servers != NULL) {
-+            DEBUG(SSSDBG_CONF_SETTINGS,
-+                  "Resolving servers [%s] for domain %s\n",
-+                  state->pdctx->servers, dom->name);
-+
-+            subreq = kdcinfo_from_server_list_send(state,
-+                                                   state->ev,
-+                                                   state->be_ctx->be_res,
-+                                                   state->pdctx->servers);
-+        } else if (state->pdctx->site != NULL) {
-+            DEBUG(SSSDBG_CONF_SETTINGS,
-+                  "Resolving site %s for domain %s\n",
-+                  state->pdctx->site, dom->name);
-+
-+            subreq = kdcinfo_from_site_send(state,
-+                                            state->ev,
-+                                            state->be_ctx->be_res,
-+                                            state->pdctx->site,
-+                                            state->pdctx->dom->name);
-+        } else {
-+            /* We should never get here */
-+            return EINVAL;
-+        }
-+
-+        if (subreq == NULL) {
-+            return ENOMEM;
-+        }
-+        tevent_req_set_callback(subreq, ipa_subdomains_write_kdcinfo_domain_done, req);
-+        return EAGAIN;
-+    }
-+
-+    return EOK;
-+}
-+
-+static void ipa_subdomains_write_kdcinfo_domain_done(struct tevent_req *subreq)
-+{
-+    errno_t ret;
-+    struct tevent_req *req =
-+            tevent_req_callback_data(subreq, struct tevent_req);
-+    struct ipa_subdomains_write_kdcinfo_state *state = \
-+                tevent_req_data(req,
-+                                struct ipa_subdomains_write_kdcinfo_state);
-+    struct sss_domain_info *next_domain;
-+    struct resolv_hostport_addr **rhp_addrs;
-+    size_t rhp_len;
-+
-+    if (state->pdctx->servers != NULL) {
-+        ret = kdcinfo_from_server_list_recv(state->pdctx, subreq,
-+                                            &rhp_addrs, &rhp_len);
-+    } else if (state->pdctx->site != NULL) {
-+        ret = kdcinfo_from_site_recv(state->pdctx, subreq,
-+                                     &rhp_addrs, &rhp_len);
-+    } else {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Neither site nor servers set\n");
-+        ret = EINVAL;
-+    }
-+
-+    if (ret == EOK) {
-+        ret = ipa_subdomains_write_kdcinfo_write_step(state->pdctx->dom,
-+                                                      state->pdctx->krb5_service,
-+                                                      rhp_addrs, rhp_len);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_MINOR_FAILURE,
-+                  "Could not write kdcinfo file for %s\n", state->pdctx->dom->name);
-+            /* Not fatal, loop to the next domain below */
-+        }
-+    } else {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Could not get address list for %s\n", state->pdctx->dom->name);
-+        /* Not fatal, loop to the next domain below */
-+    }
-+
-+    next_domain = get_next_domain(state->pdctx->dom, 0);
-+    ret = ipa_subdomains_write_kdcinfo_domain_step(next_domain, req);
-+    if (ret == EOK) {
-+        tevent_req_done(req);
-+        return;
-+    } else if (ret != EAGAIN) {
-+        /* the loop in ipa_subdomains_write_kdcinfo_domain_step already
-+         * tries to be quite permissive, so any error is fatal
-+         */
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    /* Continue to the next domain */
-+}
-+
-+static errno_t ipa_subdomains_write_kdcinfo_write_step(struct sss_domain_info *dom,
-+                                                       struct krb5_service *krb5_service,
-+                                                       struct resolv_hostport_addr **rhp_addrs,
-+                                                       size_t rhp_len)
-+{
-+    errno_t ret;
-+    char *address = NULL;
-+    char *safe_address = NULL;
-+    char **safe_addr_list;
-+    int addr_index = 0;
-+    TALLOC_CTX *tmp_ctx = NULL;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    safe_addr_list = talloc_zero_array(tmp_ctx, char *, rhp_len+1);
-+    if (safe_addr_list == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    for (size_t i = 0; i < rhp_len; i++) {
-+        address = resolv_get_string_address(tmp_ctx, rhp_addrs[i]->reply);
-+        if (address == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_string_address failed.\n");
-+            continue;
-+        }
-+
-+        if (rhp_addrs[i]->origin.port != 0) {
-+            address = talloc_asprintf_append(address,
-+                                             ":%d",
-+                                             rhp_addrs[i]->origin.port);
-+        }
-+
-+        safe_address = sss_escape_ip_address(tmp_ctx,
-+                                             rhp_addrs[i]->reply->family,
-+                                             address);
-+        talloc_zfree(address);
-+        if (safe_address == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "sss_escape_ip_address failed.\n");
-+            continue;
-+        }
-+
-+        DEBUG(SSSDBG_CONF_SETTINGS,
-+              "Will write [%s] for %s\n",
-+              safe_address, dom->name);
-+
-+        safe_addr_list[addr_index] = talloc_steal(safe_addr_list,
-+                                                  safe_address);
-+        addr_index++;
-+    }
-+
-+    ret = write_krb5info_file(krb5_service,
-+                              safe_addr_list,
-+                              SSS_KRB5KDC_FO_SRV);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+                "write_krb5info_file failed, authentication might fail.\n");
-+        goto done;
-+    }
-+
-+    ret = EOK;
-+done:
-+    talloc_free(tmp_ctx);
-+    return ret;
-+}
-+
-+static errno_t ipa_subdomains_write_kdcinfo_recv(struct tevent_req *req)
-+{
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+    return EOK;
-+}
-+
- struct ipa_subdomains_refresh_state {
-     struct tevent_context *ev;
-     struct ipa_subdomains_ctx *sd_ctx;
-@@ -1933,6 +2617,7 @@ static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq);
- static void ipa_subdomains_refresh_view_domain_resolution_order_done(
-                                                     struct tevent_req *subreq);
- static void ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq);
-+static void ipa_domain_refresh_kdcinfo_done(struct tevent_req *subreq);
- 
- static struct tevent_req *
- ipa_subdomains_refresh_send(TALLOC_CTX *mem_ctx,
-@@ -2253,6 +2938,35 @@ ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq)
-         return;
-     }
- 
-+    subreq = ipa_subdomains_write_kdcinfo_send(state,
-+                                               state->ev,
-+                                               state->sd_ctx,
-+                                               state->sd_ctx->be_ctx);
-+    if (subreq == NULL) {
-+        tevent_req_error(req, ENOMEM);
-+        return;
-+    }
-+    tevent_req_set_callback(subreq, ipa_domain_refresh_kdcinfo_done, req);
-+}
-+
-+static void
-+ipa_domain_refresh_kdcinfo_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req;
-+    errno_t ret;
-+
-+    req = tevent_req_callback_data(subreq, struct tevent_req);
-+
-+    ret = ipa_subdomains_write_kdcinfo_recv(subreq);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Unable to write the kdc info files, authentication might "
-+              "fail or time out [%d]: %s\n",
-+              ret, sss_strerror(ret));
-+        /* Not fatal, let's hope DNS is set correctly */
-+    }
-+
-     tevent_req_done(req);
- }
- 
--- 
-2.17.1
-
diff --git a/SOURCES/0029-LDAP-Return-the-error-message-from-the-extended-oper.patch b/SOURCES/0029-LDAP-Return-the-error-message-from-the-extended-oper.patch
new file mode 100644
index 0000000..8661da8
--- /dev/null
+++ b/SOURCES/0029-LDAP-Return-the-error-message-from-the-extended-oper.patch
@@ -0,0 +1,57 @@
+From 4ab1b754a2659d8e75ae734987ed93f3e1ed047f Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 15 May 2019 21:20:26 +0200
+Subject: [PATCH 29/29] LDAP: Return the error message from the extended
+ operation password change also on failure
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves: https://pagure.io/SSSD/sssd/issue/4015
+
+If password change fails, the tevent request would call
+TEVENT_REQ_RETURN_ON_ERROR before returning the error message that comes
+from the server, so the server message would not be propagated to the caller.
+
+This regressed in cf1d7ff
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 9a4d5f0601b432b87c3bf93f7126d07e65993e0d)
+---
+ src/providers/ldap/ldap_auth.c  | 5 +++--
+ src/providers/ldap/sdap_async.c | 1 +
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
+index 86724e388..4f416c1aa 100644
+--- a/src/providers/ldap/ldap_auth.c
++++ b/src/providers/ldap/ldap_auth.c
+@@ -1212,10 +1212,11 @@ sdap_pam_change_password_recv(TALLOC_CTX *mem_ctx,
+     struct sdap_pam_change_password_state *state;
+     state = tevent_req_data(req, struct sdap_pam_change_password_state);
+ 
+-    TEVENT_REQ_RETURN_ON_ERROR(req);
+-
++    /* We want to return the error message even on failure */
+     *_user_error_message = talloc_steal(mem_ctx, state->user_error_message);
+ 
++    TEVENT_REQ_RETURN_ON_ERROR(req);
++
+     return EOK;
+ }
+ 
+diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
+index 822baf06a..7e78e6b6e 100644
+--- a/src/providers/ldap/sdap_async.c
++++ b/src/providers/ldap/sdap_async.c
+@@ -696,6 +696,7 @@ errno_t sdap_exop_modify_passwd_recv(struct tevent_req *req,
+     struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
+                                          struct sdap_exop_modify_passwd_state);
+ 
++    /* We want to return the error message even on failure */
+     *user_error_message = talloc_steal(mem_ctx, state->user_error_message);
+ 
+     TEVENT_REQ_RETURN_ON_ERROR(req);
+-- 
+2.20.1
+
diff --git a/SOURCES/0029-MAN-Document-the-options-available-for-AD-trusted-do.patch b/SOURCES/0029-MAN-Document-the-options-available-for-AD-trusted-do.patch
deleted file mode 100644
index ef6ab6e..0000000
--- a/SOURCES/0029-MAN-Document-the-options-available-for-AD-trusted-do.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From 731f098767ce352722dc4d4525c6a520cc5b5dab Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 27 Jun 2018 09:59:42 +0200
-Subject: [PATCH] MAN: Document the options available for AD trusted domains
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3291
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 014e7d8ab6aa4cf3051764052326258230c0bc86)
----
- src/man/sssd-ipa.5.xml | 92 ++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 92 insertions(+)
-
-diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
-index e4e58afaf6616f759ef82c77e339bdc738939dbe..e46957d5f742bafc11774992afe08d32443d061f 100644
---- a/src/man/sssd-ipa.5.xml
-+++ b/src/man/sssd-ipa.5.xml
-@@ -728,6 +728,98 @@
-         </para>
-     </refsect1>
- 
-+    <refsect1 id='trusted_domains'>
-+        <title>TRUSTED DOMAINS CONFIGURATION</title>
-+        <para>
-+            Some configuration options can be also set for a trusted domain.
-+            A trusted domain configuration can either be done using
-+            a subsection, for example:
-+<programlisting>
-+[domain/ipa.domain.com/ad.domain.com]
-+ad_server = dc.ad.domain.com
-+</programlisting>
-+        </para>
-+        <para>
-+            In addition, some options can be set in the parent domain
-+            and inherited by the trusted domain using the
-+            <quote>subdomain_inherit</quote> option. For more details,
-+            see the
-+            <citerefentry>
-+                <refentrytitle>sssd.conf</refentrytitle>
-+                <manvolnum>5</manvolnum>
-+            </citerefentry> manual page.
-+        </para>
-+        <para>
-+            Different configuration options are tunable for a trusted
-+            domain depending on whether you are configuring SSSD on an
-+            IPA server or an IPA client.
-+        </para>
-+        <refsect2 id='server_configuration'>
-+            <title>OPTIONS TUNABLE ON IPA MASTERS</title>
-+            <para>
-+                The following options can be set in a subdomain
-+                section on an IPA master:
-+                <itemizedlist>
-+                    <listitem>
-+                        <para>ad_server</para>
-+                    </listitem>
-+                    <listitem>
-+                        <para>ad_backup_server</para>
-+                    </listitem>
-+                    <listitem>
-+                        <para>ad_site</para>
-+                    </listitem>
-+                    <listitem>
-+                        <para>ldap_search_base</para>
-+                    </listitem>
-+                    <listitem>
-+                        <para>ldap_user_search_base</para>
-+                    </listitem>
-+                    <listitem>
-+                        <para>ldap_group_search_base</para>
-+                    </listitem>
-+                    <listitem>
-+                        <para>use_fully_qualified_names</para>
-+                    </listitem>
-+                </itemizedlist>
-+            </para>
-+        </refsect2>
-+        <refsect2 id='client_configuration'>
-+            <title>OPTIONS TUNABLE ON IPA CLIENTS</title>
-+            <para>
-+                The following options can be set in a subdomain
-+                section on an IPA client:
-+                <itemizedlist>
-+                    <listitem>
-+                        <para>ad_server</para>
-+                    </listitem>
-+                    <listitem>
-+                        <para>ad_site</para>
-+                    </listitem>
-+                </itemizedlist>
-+            </para>
-+            <para>
-+                Note that if both options are set, only
-+                <quote>ad_server</quote> is evaluated.
-+            </para>
-+            <para>
-+                Since any request for a user or a group identity from a
-+                trusted domain triggered from an IPA client is resolved
-+                by the IPA server, the <quote>ad_server</quote> and
-+                <quote>ad_site</quote> options only affect which AD DC will
-+                the authentication be performed against. In particular,
-+                the addresses resolved from these lists will be written to
-+                <quote>kdcinfo</quote> files read by the Kerberos locator
-+                plugin. Please refer to the
-+                <citerefentry>
-+                    <refentrytitle>sssd_krb5_locator_plugin</refentrytitle>
-+                    <manvolnum>8</manvolnum>
-+                </citerefentry> manual page for more details on the Kerberos
-+                locator plugin.
-+            </para>
-+        </refsect2>
-+    </refsect1>
-+
-     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/failover.xml" />
- 
-     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/service_discovery.xml" />
--- 
-2.17.1
-
diff --git a/SOURCES/0030-AD-consider-resource_groups-in-PAC-as-well.patch b/SOURCES/0030-AD-consider-resource_groups-in-PAC-as-well.patch
deleted file mode 100644
index 212bab0..0000000
--- a/SOURCES/0030-AD-consider-resource_groups-in-PAC-as-well.patch
+++ /dev/null
@@ -1,334 +0,0 @@
-From a7b308a01914458234bc05539e773e4c0762ad4b Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 28 Jun 2018 12:41:41 +0200
-Subject: [PATCH] AD: consider resource_groups in PAC as well
-
-With recent versions of Active Directory the SIDs of Domain Local groups
-might be only available in the resource_groups section of the PAC, this
-feature is also called SID compression. To get a complete list of groups
-the user is a member of the SIDs from this section must be extracted as
-well.
-
-Resolves https://pagure.io/SSSD/sssd/issue/3767
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 13c8450788a429fa49ba532b40ebfd7f3a4132e4)
-
-DOWNSTREAM:
-Resolves: rhbz#1592964 - Groups go missing with PAC enabled in sssd
----
- src/external/samba.m4             |   8 ++
- src/providers/ad/ad_pac.c         | 130 ++++++++++++++++++++++++------
- src/tests/cmocka/test_ad_common.c |  95 ++++++++++++++++++++++
- 3 files changed, 210 insertions(+), 23 deletions(-)
-
-diff --git a/src/external/samba.m4 b/src/external/samba.m4
-index 794cac2461d7fbd5e690ea105cd346cbe6fcce9a..7a8c1eb7b9069f18def4e915b0fb9ab054a68e01 100644
---- a/src/external/samba.m4
-+++ b/src/external/samba.m4
-@@ -122,3 +122,11 @@ int main(void)
-     AC_DEFINE_UNQUOTED(SMB_IDMAP_INTERFACE_VERSION, $idmap_version,
-                        [Detected version of Samba's idmap plugin interface])
- fi
-+
-+SAVE_CFLAGS=$CFLAGS
-+CFLAGS="$CFLAGS $SMBCLIENT_CFLAGS $NDR_NBT_CFLAGS $NDR_KRB5PAC_CFLAGS -I/usr/include/samba-4.0"
-+AC_CHECK_MEMBERS([struct PAC_LOGON_INFO.resource_groups], , ,
-+                 [[ #include <ndr.h>
-+                    #include <gen_ndr/krb5pac.h>
-+                    #include <gen_ndr/krb5pac.h>]])
-+CFLAGS=$SAVE_CFLAGS
-diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c
-index 1a344725fbf57d4d95c46163f2e31d44e69b3e65..80424b44e334958402cb8cfebedc1898f1e2f9c8 100644
---- a/src/providers/ad/ad_pac.c
-+++ b/src/providers/ad/ad_pac.c
-@@ -146,6 +146,87 @@ errno_t check_if_pac_is_available(TALLOC_CTX *mem_ctx,
-     return EOK;
- }
- 
-+static errno_t
-+add_sids_from_rid_array_to_hash_table(struct dom_sid *dom_sid,
-+                                      struct samr_RidWithAttributeArray *groups,
-+                                      struct sss_idmap_ctx *idmap_ctx,
-+                                      hash_table_t *sid_table)
-+{
-+    enum idmap_error_code err;
-+    char *dom_sid_str = NULL;
-+    size_t dom_sid_str_len;
-+    char *sid_str = NULL;
-+    char *rid_start;
-+    hash_key_t key;
-+    hash_value_t value;
-+    int ret;
-+    size_t c;
-+    TALLOC_CTX *tmp_ctx = NULL;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    key.type = HASH_KEY_STRING;
-+    value.type = HASH_VALUE_ULONG;
-+
-+    err = sss_idmap_smb_sid_to_sid(idmap_ctx, dom_sid, &dom_sid_str);
-+    if (err != IDMAP_SUCCESS) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sss_idmap_smb_sid_to_sid failed.\n");
-+        ret = EFAULT;
-+        goto done;
-+    }
-+
-+    dom_sid_str_len = strlen(dom_sid_str);
-+    sid_str = talloc_zero_size(tmp_ctx, dom_sid_str_len + 12);
-+    if (sid_str == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+    rid_start = sid_str + dom_sid_str_len;
-+
-+    memcpy(sid_str, dom_sid_str, dom_sid_str_len);
-+
-+    for (c = 0; c < groups->count; c++) {
-+        memset(rid_start, '\0', 12);
-+        ret = snprintf(rid_start, 12, "-%lu",
-+                       (unsigned long) groups->rids[c].rid);
-+        if (ret < 0 || ret > 12) {
-+            DEBUG(SSSDBG_OP_FAILURE, "snprintf failed.\n");
-+            ret = EIO;
-+            goto done;
-+        }
-+
-+        key.str = sid_str;
-+        value.ul = 0;
-+
-+        ret = hash_enter(sid_table, &key, &value);
-+        if (ret != HASH_SUCCESS) {
-+            DEBUG(SSSDBG_OP_FAILURE, "hash_enter failed [%d][%s].\n",
-+                                      ret, hash_error_string(ret));
-+            ret = EIO;
-+            goto done;
-+        }
-+
-+    }
-+
-+    ret = EOK;
-+
-+done:
-+    sss_idmap_free_sid(idmap_ctx, dom_sid_str);
-+    talloc_free(tmp_ctx);
-+
-+    return ret;
-+}
-+
-+struct resource_groups {
-+    struct dom_sid2 *domain_sid;
-+    struct samr_RidWithAttributeArray groups;
-+};
-+
- errno_t ad_get_sids_from_pac(TALLOC_CTX *mem_ctx,
-                              struct sss_idmap_ctx *idmap_ctx,
-                              struct PAC_LOGON_INFO *logon_info,
-@@ -157,6 +238,7 @@ errno_t ad_get_sids_from_pac(TALLOC_CTX *mem_ctx,
-     int ret;
-     size_t s;
-     struct netr_SamInfo3 *info3;
-+    struct resource_groups resource_groups = { 0 };
-     char *sid_str = NULL;
-     char *msid_str = NULL;
-     char *user_dom_sid_str = NULL;
-@@ -188,9 +270,15 @@ errno_t ad_get_sids_from_pac(TALLOC_CTX *mem_ctx,
-     }
- 
-     info3 = &logon_info->info3;
-+#ifdef HAVE_STRUCT_PAC_LOGON_INFO_RESOURCE_GROUPS
-+    resource_groups.domain_sid = logon_info->resource_groups.domain_sid;
-+    resource_groups.groups.count = logon_info->resource_groups.groups.count;
-+    resource_groups.groups.rids = logon_info->resource_groups.groups.rids;
-+#endif
- 
-     ret = sss_hash_create(tmp_ctx,
--                          info3->sidcount + info3->base.groups.count + 2,
-+                          info3->sidcount + info3->base.groups.count + 2
-+                                          + resource_groups.groups.count,
-                           &sid_table);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n");
-@@ -265,28 +353,13 @@ errno_t ad_get_sids_from_pac(TALLOC_CTX *mem_ctx,
-         goto done;
-     }
- 
--
--    for (s = 0; s < info3->base.groups.count; s++) {
--        memset(rid_start, '\0', 12);
--        ret = snprintf(rid_start, 12, "-%lu",
--                                (unsigned long) info3->base.groups.rids[s].rid);
--        if (ret < 0 || ret > 12) {
--            DEBUG(SSSDBG_OP_FAILURE, "snprintf failed.\n");
--            ret = EIO;
--            goto done;
--        }
--
--        key.str = sid_str;
--        value.ul = 0;
--
--        ret = hash_enter(sid_table, &key, &value);
--        if (ret != HASH_SUCCESS) {
--            DEBUG(SSSDBG_OP_FAILURE, "hash_enter failed [%d][%s].\n",
--                                      ret, hash_error_string(ret));
--            ret = EIO;
--            goto done;
--        }
--
-+    ret = add_sids_from_rid_array_to_hash_table(info3->base.domain_sid,
-+                                                &info3->base.groups,
-+                                                idmap_ctx, sid_table);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "add_sids_from_rid_array_to_hash_table failed.\n");
-+        goto done;
-     }
- 
-     for(s = 0; s < info3->sidcount; s++) {
-@@ -311,6 +384,17 @@ errno_t ad_get_sids_from_pac(TALLOC_CTX *mem_ctx,
-         }
-     }
- 
-+    if (resource_groups.domain_sid != NULL) {
-+        ret = add_sids_from_rid_array_to_hash_table(resource_groups.domain_sid,
-+                                                    &resource_groups.groups,
-+                                                    idmap_ctx, sid_table);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "add_sids_from_rid_array_to_hash_table failed.\n");
-+            goto done;
-+        }
-+    }
-+
-     num_sids = hash_count(sid_table);
-     sid_list = talloc_array(tmp_ctx, char *, num_sids);
-     if (sid_list == NULL) {
-diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
-index 39ebbc63324ca40d071f30582d2f15d732f6c466..ac3b0d0ab3c7b0a0ee4d21d96e1b4783ff1b4139 100644
---- a/src/tests/cmocka/test_ad_common.c
-+++ b/src/tests/cmocka/test_ad_common.c
-@@ -207,6 +207,29 @@ static void test_check_if_pac_is_available(void **state)
-     "BEAEUAVgBFAEwAdv///4yBQZ5ZQnp3qwj2lKGcd0UAAAAAdv//" \
-     "/39fn4UneD5l6YxP8w/U0coAAAAA"
- 
-+#define TEST_PAC_RESOURCE_GROUPS_BASE64 \
-+    "BQAAAAAAAAABAAAA8AEAAFgAAAAAAAAACgAAABQAAABIAgAA" \
-+    "AAAAAAwAAABYAAAAYAIAAAAAAAAGAAAAEAAAALgCAAAAAAAA" \
-+    "BwAAABQAAADIAgAAAAAAAAEQCADMzMzM4AEAAAAAAAAAAAIA" \
-+    "Rr0gPUQO1AH/////////f/////////9/TRPNRwtu0wFN0zZy" \
-+    "1G7TAf////////9/CgAKAAQAAgAKAAoACAACAAAAAAAMAAIA" \
-+    "AAAAABAAAgAAAAAAFAACAAAAAAAYAAIACwAAAFEEAAABAgAA" \
-+    "AwAAABwAAgAgAgAAAAAAAAAAAAAAAAAAAAAAAAQABgAgAAIA" \
-+    "BgAIACQAAgAoAAIAAAAAAAAAAAAQAgAAAAAAAAAAAAAAAAAA" \
-+    "AAAAAAAAAAAAAAAAAAAAAAEAAAAsAAIANAACAAEAAAA4AAIA" \
-+    "BQAAAAAAAAAFAAAAdAB1AHMAZQByAAAABQAAAAAAAAAFAAAA" \
-+    "dAB1AHMAZQByAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \
-+    "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAECAAAHAAAA" \
-+    "YgQAAAcAAABjBAAABwAAAAMAAAAAAAAAAgAAAEQAQwAEAAAA" \
-+    "AAAAAAMAAABXAEkATgAAAAQAAAABBAAAAAAABRUAAAAkYm0r" \
-+    "SyFumd73jX0BAAAAMAACAAcAAAABAAAAAQEAAAAAABIBAAAA" \
-+    "BAAAAAEEAAAAAAAFFQAAACRibStLIW6Z3veNfQEAAABoBAAA" \
-+    "BwAAIAAAAACAEuVfRA7UAQoAdAB1AHMAZQByAAAAAAAoABAA" \
-+    "HAA4AAAAAAAAAAAAdAB1AHMAZQByAEAAdwBpAG4ALgB0AHIA" \
-+    "dQBzAHQALgB0AGUAcwB0AFcASQBOAC4AVABSAFUAUwBUAC4A" \
-+    "VABFAFMAVAAAAAAAEAAAAOGTj7I9Qn7XebOqdHb///+fHhrZ" \
-+    "kBt0So4jOFBk84sDAAAAAA=="
-+
- static void test_ad_get_data_from_pac(void **state)
- {
-     int ret;
-@@ -303,6 +326,73 @@ static void test_ad_get_sids_from_pac(void **state)
-     sss_idmap_free(idmap_ctx);
- }
- 
-+#ifdef HAVE_STRUCT_PAC_LOGON_INFO_RESOURCE_GROUPS
-+static void test_ad_get_sids_from_pac_with_resource_groups(void **state)
-+{
-+    int ret;
-+    struct PAC_LOGON_INFO *logon_info;
-+    uint8_t *test_pac_blob;
-+    size_t test_pac_blob_size;
-+    char *user_sid;
-+    char *primary_group_sid;
-+    size_t num_sids;
-+    char **sid_list;
-+    struct sss_idmap_ctx *idmap_ctx;
-+    enum idmap_error_code err;
-+    size_t c;
-+    size_t s;
-+
-+    const char *sid_check_list[] = { "S-1-5-21-728588836-2574131531-2106456030-513",
-+                                     "S-1-5-21-728588836-2574131531-2106456030-1122",
-+                                     "S-1-5-21-728588836-2574131531-2106456030-1123",
-+                                     "S-1-5-21-728588836-2574131531-2106456030-1128",
-+                                     "S-1-18-1",
-+                                     NULL };
-+
-+    struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
-+                                                  struct ad_common_test_ctx);
-+
-+    err = sss_idmap_init(sss_idmap_talloc, test_ctx, sss_idmap_talloc_free,
-+                         &idmap_ctx);
-+    assert_int_equal(err, IDMAP_SUCCESS);
-+
-+    test_pac_blob = sss_base64_decode(test_ctx, TEST_PAC_RESOURCE_GROUPS_BASE64,
-+                                      &test_pac_blob_size);
-+    assert_non_null(test_pac_blob_size);
-+
-+    ret = ad_get_data_from_pac(test_ctx, test_pac_blob, test_pac_blob_size,
-+                               &logon_info);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = ad_get_sids_from_pac(test_ctx, idmap_ctx, logon_info, &user_sid,
-+                               &primary_group_sid, &num_sids, &sid_list);
-+    assert_int_equal(ret, EOK);
-+    assert_string_equal(user_sid,
-+                        "S-1-5-21-728588836-2574131531-2106456030-1105");
-+    assert_string_equal(primary_group_sid,
-+                        "S-1-5-21-728588836-2574131531-2106456030-513");
-+    assert_int_equal(num_sids, 5);
-+
-+    for (c = 0; sid_check_list[c] != NULL; c++) {
-+        for (s = 0; s < num_sids; s++) {
-+            if (strcmp(sid_check_list[c], sid_list[s]) == 0) {
-+                break;
-+            }
-+        }
-+        if (s == num_sids) {
-+            fail_msg("SID [%s] not found in SID list.", sid_check_list[c]);
-+        }
-+    }
-+
-+    talloc_free(test_pac_blob);
-+    talloc_free(logon_info);
-+    talloc_free(user_sid);
-+    talloc_free(primary_group_sid);
-+    talloc_free(sid_list);
-+    sss_idmap_free(idmap_ctx);
-+}
-+#endif
-+
- static void test_ad_get_pac_data_from_user_entry(void **state)
- {
-     int ret;
-@@ -912,6 +1002,11 @@ int main(int argc, const char *argv[])
-         cmocka_unit_test_setup_teardown(test_ad_get_sids_from_pac,
-                                         test_ad_common_setup,
-                                         test_ad_common_teardown),
-+#ifdef HAVE_STRUCT_PAC_LOGON_INFO_RESOURCE_GROUPS
-+        cmocka_unit_test_setup_teardown(test_ad_get_sids_from_pac_with_resource_groups,
-+                                        test_ad_common_setup,
-+                                        test_ad_common_teardown),
-+#endif
-         cmocka_unit_test_setup_teardown(test_ad_get_pac_data_from_user_entry,
-                                         test_ad_common_setup,
-                                         test_ad_common_teardown),
--- 
-2.17.1
-
diff --git a/SOURCES/0030-SDAP-allow-GSS-SPNEGO-for-LDAP-SASL-bind-as-well.patch b/SOURCES/0030-SDAP-allow-GSS-SPNEGO-for-LDAP-SASL-bind-as-well.patch
new file mode 100644
index 0000000..6a809bf
--- /dev/null
+++ b/SOURCES/0030-SDAP-allow-GSS-SPNEGO-for-LDAP-SASL-bind-as-well.patch
@@ -0,0 +1,272 @@
+From f5d031ba41b1c297f95df61f013f1c7ef8bca275 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Sun, 12 May 2019 16:38:43 +0200
+Subject: [PATCH 30/31] SDAP: allow GSS-SPNEGO for LDAP SASL bind as well
+
+From the LDAP client perspective GSS-SPNEGO and GSSAPI are quite
+similar. To support GSS-SPNEGO SSSD must make sure that a Kerberos
+ticket is available before the LDAP SASL bind is started.
+
+Related to https://pagure.io/SSSD/sssd/issue/4006
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 3b89934e831fa4e575e398fee6e4c3d4d24854eb)
+---
+ src/man/sssd-ldap.5.xml                    | 29 ++++++++++++----------
+ src/providers/ad/ad_common.c               |  6 ++---
+ src/providers/ad/ad_init.c                 |  2 +-
+ src/providers/ldap/ldap_auth.c             | 10 ++++----
+ src/providers/ldap/ldap_common.h           |  2 +-
+ src/providers/ldap/ldap_init.c             |  2 +-
+ src/providers/ldap/sdap.c                  |  9 +++++++
+ src/providers/ldap/sdap.h                  |  2 ++
+ src/providers/ldap/sdap_async_connection.c |  8 +++---
+ 9 files changed, 42 insertions(+), 28 deletions(-)
+
+diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
+index 25acc19e6..17c5523c0 100644
+--- a/src/man/sssd-ldap.5.xml
++++ b/src/man/sssd-ldap.5.xml
+@@ -1805,8 +1805,8 @@
+                     <term>ldap_sasl_mech (string)</term>
+                     <listitem>
+                         <para>
+-                            Specify the SASL mechanism to use.
+-                            Currently only GSSAPI is tested and supported.
++                            Specify the SASL mechanism to use.  Currently only
++                            GSSAPI and GSS-SPNEGO are tested and supported.
+                         </para>
+                         <para>
+                             Default: not set
+@@ -1818,13 +1818,14 @@
+                     <term>ldap_sasl_authid (string)</term>
+                     <listitem>
+                         <para>
+-                            Specify the SASL authorization id to use.
+-                            When GSSAPI is used, this represents the Kerberos
+-                            principal used for authentication to the directory.
+-                            This option can either contain the full principal (for
+-                            example host/myhost@EXAMPLE.COM) or just the principal name
+-                            (for example host/myhost). By default, the value is not set
+-                            and the following principals are used:
++                            Specify the SASL authorization id to use.  When
++                            GSSAPI/GSS-SPNEGO are used, this represents the
++                            Kerberos principal used for authentication to the
++                            directory.  This option can either contain the full
++                            principal (for example host/myhost@EXAMPLE.COM) or
++                            just the principal name (for example host/myhost).
++                            By default, the value is not set and the following
++                            principals are used:
+                             <programlisting>
+ hostname@REALM
+ netbiosname$@REALM
+@@ -1875,7 +1876,8 @@ host/*
+                     <term>ldap_krb5_keytab (string)</term>
+                     <listitem>
+                         <para>
+-                            Specify the keytab to use when using SASL/GSSAPI.
++                            Specify the keytab to use when using
++                            SASL/GSSAPI/GSS-SPNEGO.
+                         </para>
+                         <para>
+                             Default: System keytab, normally <filename>/etc/krb5.keytab</filename>
+@@ -1890,7 +1892,7 @@ host/*
+                             Specifies that the id_provider should init
+                             Kerberos credentials (TGT).
+                             This action is performed only if SASL is used and
+-                            the mechanism selected is GSSAPI.
++                            the mechanism selected is GSSAPI or GSS-SPNEGO.
+                         </para>
+                         <para>
+                             Default: true
+@@ -1903,7 +1905,7 @@ host/*
+                     <listitem>
+                         <para>
+                             Specifies the lifetime in seconds of the TGT if
+-                            GSSAPI is used.
++                            GSSAPI or GSS-SPNEGO is used.
+                         </para>
+                         <para>
+                             Default: 86400 (24 hours)
+@@ -1944,7 +1946,8 @@ host/*
+                     <term>krb5_realm (string)</term>
+                     <listitem>
+                         <para>
+-                            Specify the Kerberos REALM (for SASL/GSSAPI auth).
++                            Specify the Kerberos REALM (for
++                            SASL/GSSAPI/GSS-SPNEGO auth).
+                         </para>
+                         <para>
+                             Default: System defaults, see <filename>/etc/krb5.conf</filename>
+diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
+index 4d1800806..19d4b3d5a 100644
+--- a/src/providers/ad/ad_common.c
++++ b/src/providers/ad/ad_common.c
+@@ -577,7 +577,7 @@ _ad_servers_init(struct ad_service *service,
+         if (resolv_is_address(list[j])) {
+             DEBUG(SSSDBG_IMPORTANT_INFO,
+                   "ad_server [%s] is detected as IP address, "
+-                  "this can cause GSSAPI problems\n", list[j]);
++                  "this can cause GSSAPI/GSS-SPNEGO problems\n", list[j]);
+         }
+     }
+ 
+@@ -1012,7 +1012,7 @@ ad_set_sdap_options(struct ad_options *ad_opts,
+         goto done;
+     }
+ 
+-    /* Set the Kerberos Realm for GSSAPI */
++    /* Set the Kerberos Realm for GSSAPI or GSS-SPNEGO */
+     krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
+     if (!krb5_realm) {
+         /* Should be impossible, this is set in ad_get_common_options() */
+@@ -1269,7 +1269,7 @@ ad_get_auth_options(TALLOC_CTX *mem_ctx,
+            ad_servers);
+ 
+     /* Set krb5 realm */
+-    /* Set the Kerberos Realm for GSSAPI */
++    /* Set the Kerberos Realm for GSSAPI/GSS-SPNEGO */
+     krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
+     if (!krb5_realm) {
+         /* Should be impossible, this is set in ad_get_common_options() */
+diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
+index 612d4587e..302bcae7d 100644
+--- a/src/providers/ad/ad_init.c
++++ b/src/providers/ad/ad_init.c
+@@ -56,7 +56,7 @@ static int ad_sasl_getopt(void *context, const char *plugin_name,
+     if (!plugin_name || !result) {
+         return SASL_FAIL;
+     }
+-    if (strcmp(plugin_name, "GSSAPI") != 0) {
++    if (!sdap_sasl_mech_needs_kinit(plugin_name)) {
+         return SASL_FAIL;
+     }
+     if (strcmp(option, "ad_compat") != 0) {
+diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
+index de22689ae..86724e388 100644
+--- a/src/providers/ldap/ldap_auth.c
++++ b/src/providers/ldap/ldap_auth.c
+@@ -715,9 +715,9 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
+          * 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.
++         * and the server is AD, because otherwise the connection would both
++         * do a startTLS and later bind using GSSAPI or GSS-SPNEGO which
++         * doesn't work well with AD.
+          */
+         skip_conn_auth = true;
+     }
+@@ -725,8 +725,8 @@ static struct tevent_req *auth_connect_send(struct tevent_req *req)
+     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 */
++        if (sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) {
++            /* Don't force TLS on if we're told to use GSSAPI or GSS-SPNEGO */
+             use_tls = false;
+         }
+     }
+diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
+index 6647241b4..04548a388 100644
+--- a/src/providers/ldap/ldap_common.h
++++ b/src/providers/ldap/ldap_common.h
+@@ -65,7 +65,7 @@ struct sdap_id_ctx {
+     struct be_ctx *be;
+     struct sdap_options *opts;
+ 
+-    /* If using GSSAPI */
++    /* If using GSSAPI or GSS-SPNEGO */
+     struct krb5_service *krb5_service;
+     /* connection to a server */
+     struct sdap_id_conn_ctx *conn;
+diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
+index 44b3e9ab3..352f0b656 100644
+--- a/src/providers/ldap/ldap_init.c
++++ b/src/providers/ldap/ldap_init.c
+@@ -365,7 +365,7 @@ static bool should_call_gssapi_init(struct sdap_options *opts)
+         return false;
+     }
+ 
+-    if (strcasecmp(sasl_mech, "GSSAPI") != 0) {
++    if (!sdap_sasl_mech_needs_kinit(sasl_mech)) {
+         return false;
+     }
+ 
+diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
+index 5c9d0a45d..5591a6718 100644
+--- a/src/providers/ldap/sdap.c
++++ b/src/providers/ldap/sdap.c
+@@ -904,6 +904,15 @@ errno_t setup_tls_config(struct dp_option *basic_opts)
+     return EOK;
+ }
+ 
++bool sdap_sasl_mech_needs_kinit(const char *sasl_mech)
++{
++    if (strcasecmp(sasl_mech, "GSSAPI") == 0
++            || strcasecmp(sasl_mech, "GSS-SPNEGO") == 0) {
++        return true;
++    }
++
++    return false;
++}
+ 
+ bool sdap_check_sup_list(struct sup_list *l, const char *val)
+ {
+diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
+index 48061d389..dddcf5faf 100644
+--- a/src/providers/ldap/sdap.h
++++ b/src/providers/ldap/sdap.h
+@@ -619,6 +619,8 @@ bool sdap_check_sup_list(struct sup_list *l, const char *val);
+ #define sdap_is_extension_supported(sh, ext_oid) \
+     sdap_check_sup_list(&((sh)->supported_extensions), ext_oid)
+ 
++bool sdap_sasl_mech_needs_kinit(const char *mech);
++
+ int build_attrs_from_map(TALLOC_CTX *memctx,
+                          struct sdap_attr_map *map,
+                          size_t size,
+diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
+index 8aacd6705..6bc271a91 100644
+--- a/src/providers/ldap/sdap_async_connection.c
++++ b/src/providers/ldap/sdap_async_connection.c
+@@ -1605,14 +1605,14 @@ static void sdap_cli_connect_done(struct tevent_req *subreq)
+     sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
+ 
+     if (state->do_auth && sasl_mech && state->use_rootdse) {
+-        /* check if server claims to support GSSAPI */
++        /* check if server claims to support the configured SASL MECH */
+         if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) {
+             tevent_req_error(req, ENOTSUP);
+             return;
+         }
+     }
+ 
+-    if (state->do_auth && sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) {
++    if (state->do_auth && sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) {
+         if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) {
+             sdap_cli_kinit_step(req);
+             return;
+@@ -1690,14 +1690,14 @@ static void sdap_cli_rootdse_done(struct tevent_req *subreq)
+     sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);
+ 
+     if (state->do_auth && sasl_mech && state->rootdse) {
+-        /* check if server claims to support GSSAPI */
++        /* check if server claims to support the configured SASL MECH */
+         if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) {
+             tevent_req_error(req, ENOTSUP);
+             return;
+         }
+     }
+ 
+-    if (state->do_auth && sasl_mech && (strcasecmp(sasl_mech, "GSSAPI") == 0)) {
++    if (state->do_auth && sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) {
+         if (dp_opt_get_bool(state->opts->basic, SDAP_KRB5_KINIT)) {
+             sdap_cli_kinit_step(req);
+             return;
+-- 
+2.20.1
+
diff --git a/SOURCES/0031-LDAP-Remove-the-legacy-POSIX-check-itself.patch b/SOURCES/0031-LDAP-Remove-the-legacy-POSIX-check-itself.patch
deleted file mode 100644
index 86f9235..0000000
--- a/SOURCES/0031-LDAP-Remove-the-legacy-POSIX-check-itself.patch
+++ /dev/null
@@ -1,321 +0,0 @@
-From 5fcce16c212037b5193556dc2f6bcb7e4d7f0f85 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sat, 30 Jun 2018 13:21:18 +0200
-Subject: [PATCH] LDAP: Remove the legacy POSIX check itself
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This code is no longer needed now.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3755
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-(cherry picked from commit 5b2b6493dfb3c1f2cb945356e34c70d8c5d64185)
-
-DOWNSTREAM:
-Resolves: rhbz#1582975 - The search filter for detecting POSIX attributes in global catalog is too broad and can cause a high load on the servers
----
- 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 eaf0814f1aaf51a5085e992efa633240f32c498e..6d395cfb1d4148e803a656a8f7205fe13570085b 100644
---- a/src/providers/ad/ad_common.c
-+++ b/src/providers/ad/ad_common.c
-@@ -1388,7 +1388,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++;
-     }
- 
-@@ -1435,7 +1434,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 a0a9b8523310b2551ee992f8d0c2e369dafaa56d..9cd8ec09c7fdc6bd1c8d64da150178f483f2a5a3 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 3de3568cb28c258c00f9b522c0b9120adca81d81..6c08d789b339424649c938b845e7118f5ea88f73 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 e892c407103b18a296ae6baaf3dcfff11ca4bf31..0790544818633e26ee5a8fbdca556b8230b1df3f 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 1e77b1c3c612d28a7d1f7e686cbc0b094b07c89d..8fc832ae5720acac07b0e2a24255f6c5e3d6994b 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 6ca3ed8d82ea7e4cb049b1c65c639b2773b8c296..6d09aca7a3465df4503991f0dc82e2af3871ccd5 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,
--- 
-2.17.1
-
diff --git a/SOURCES/0031-sdap-inherit-SDAP_SASL_MECH-if-not-set-explicitly.patch b/SOURCES/0031-sdap-inherit-SDAP_SASL_MECH-if-not-set-explicitly.patch
new file mode 100644
index 0000000..25394a1
--- /dev/null
+++ b/SOURCES/0031-sdap-inherit-SDAP_SASL_MECH-if-not-set-explicitly.patch
@@ -0,0 +1,209 @@
+From 373b1136ccb3bf54f32d47473e8120d0258f8405 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Tue, 21 May 2019 10:22:04 +0200
+Subject: [PATCH 31/31] sdap: inherit SDAP_SASL_MECH if not set explicitly
+
+If ldap_sasl_mech is set for the configured domain in sssd.conf the
+value is inherited automatically to all sub-domains. The can be
+overwritten by setting ldap_sasl_mech for a given sub-domain explicitly
+in sssd.conf.
+
+Related to https://pagure.io/SSSD/sssd/issue/4006
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 070f22f896b909c140ed7598aed2393d61a834ae)
+---
+ src/config/cfg_rules.ini                  |  1 +
+ src/man/sssd-ldap.5.xml                   | 10 ++++++
+ src/man/sssd.conf.5.xml                   |  1 +
+ src/providers/ad/ad_common.c              | 38 +++++++++++++++++++++++
+ src/providers/ad/ad_common.h              |  5 +++
+ src/providers/ad/ad_subdomains.c          | 18 ++++++++++-
+ src/providers/ipa/ipa_subdomains_server.c | 19 +++++++++++-
+ 7 files changed, 90 insertions(+), 2 deletions(-)
+
+diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
+index 603211711..3976ec4e1 100644
+--- a/src/config/cfg_rules.ini
++++ b/src/config/cfg_rules.ini
+@@ -753,6 +753,7 @@ option = ldap_user_search_base
+ option = ldap_group_search_base
+ option = ldap_netgroup_search_base
+ option = ldap_service_search_base
++option = ldap_sasl_mech
+ option = ad_server
+ option = ad_backup_server
+ option = ad_site
+diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
+index 17c5523c0..fadd05cb7 100644
+--- a/src/man/sssd-ldap.5.xml
++++ b/src/man/sssd-ldap.5.xml
+@@ -1808,6 +1808,16 @@
+                             Specify the SASL mechanism to use.  Currently only
+                             GSSAPI and GSS-SPNEGO are tested and supported.
+                         </para>
++                        <para>
++                            If the backend supports sub-domains the value of
++                            ldap_sasl_mech is automatically inherited to the
++                            sub-domains. If a different value is needed for a
++                            sub-domain it can be overwritten by setting
++                            ldap_sasl_mech for this sub-domain explicitly.
++                            Please see TRUSTED DOMAIN SECTION in
++                            <citerefentry><refentrytitle>sssd.conf</refentrytitle>
++                            <manvolnum>5</manvolnum></citerefentry> for details.
++                        </para>
+                         <para>
+                             Default: not set
+                         </para>
+diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
+index 1ab7af00b..3f05b3942 100644
+--- a/src/man/sssd.conf.5.xml
++++ b/src/man/sssd.conf.5.xml
+@@ -3356,6 +3356,7 @@ ldap_user_extra_attrs = phone:telephoneNumber
+             <para>ldap_group_search_base,</para>
+             <para>ldap_netgroup_search_base,</para>
+             <para>ldap_service_search_base,</para>
++            <para>ldap_sasl_mech,</para>
+             <para>ad_server,</para>
+             <para>ad_backup_server,</para>
+             <para>ad_site,</para>
+diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
+index 19d4b3d5a..1b8b1df19 100644
+--- a/src/providers/ad/ad_common.c
++++ b/src/providers/ad/ad_common.c
+@@ -1455,3 +1455,41 @@ ad_user_conn_list(TALLOC_CTX *mem_ctx,
+ 
+     return clist;
+ }
++
++errno_t ad_inherit_opts_if_needed(struct dp_option *parent_opts,
++                                  struct dp_option *suddom_opts,
++                                  struct confdb_ctx *cdb,
++                                  const char *subdom_conf_path,
++                                  int opt_id)
++{
++    int ret;
++    const char *parent_val = NULL;
++    char *dummy = NULL;
++    char *option_list[2] = { NULL, NULL };
++
++    parent_val = dp_opt_get_cstring(parent_opts, opt_id);
++    if (parent_val != NULL) {
++        ret = confdb_get_string(cdb, NULL, subdom_conf_path,
++                                parent_opts[opt_id].opt_name, NULL, &dummy);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "confdb_get_string failed.\n");
++            goto done;
++        }
++
++        if (dummy == NULL) {
++            DEBUG(SSSDBG_CONF_SETTINGS,
++                  "Option [%s] is set in parent domain but not set for "
++                  "sub-domain trying to set it to [%s].\n",
++                  parent_opts[opt_id].opt_name, parent_val);
++            option_list[0] = discard_const(parent_opts[opt_id].opt_name);
++            dp_option_inherit(option_list, opt_id, parent_opts, suddom_opts);
++        }
++    }
++
++    ret = EOK;
++
++done:
++    talloc_free(dummy);
++
++    return ret;
++}
+diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
+index 638465958..2f624df3d 100644
+--- a/src/providers/ad/ad_common.h
++++ b/src/providers/ad/ad_common.h
+@@ -216,4 +216,9 @@ errno_t netlogon_get_domain_info(TALLOC_CTX *mem_ctx,
+                                  char **_site,
+                                  char **_forest);
+ 
++errno_t ad_inherit_opts_if_needed(struct dp_option *parent_opts,
++                                  struct dp_option *suddom_opts,
++                                  struct confdb_ctx *cdb,
++                                  const char *subdom_conf_path,
++                                  int opt_id);
+ #endif /* AD_COMMON_H_ */
+diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
+index b4ad347e4..b4e09fb7e 100644
+--- a/src/providers/ad/ad_subdomains.c
++++ b/src/providers/ad/ad_subdomains.c
+@@ -305,13 +305,29 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
+                                               realm,
+                                               subdom,
+                                               hostname, keytab);
+-    talloc_free(subdom_conf_path);
+     if (ad_options == NULL) {
+         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
+         talloc_free(ad_options);
++        talloc_free(subdom_conf_path);
+         return ENOMEM;
+     }
+ 
++    ret = ad_inherit_opts_if_needed(id_ctx->sdap_id_ctx->opts->basic,
++                                    ad_options->id->basic,
++                                    be_ctx->cdb, subdom_conf_path,
++                                    SDAP_SASL_MECH);
++    talloc_free(subdom_conf_path);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Failed to inherit option [%s] to sub-domain [%s]. "
++              "This error is ignored but might cause issues or unexpected "
++              "behavior later on.\n",
++              id_ctx->ad_options->id->basic[SDAP_SASL_MECH].opt_name,
++              subdom->name);
++
++        return ret;
++    }
++
+     ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
+ 
+     gc_service_name = talloc_asprintf(ad_options, "sd_gc_%s", subdom->name);
+diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
+index 1d480e52b..d0e89a4f9 100644
+--- a/src/providers/ipa/ipa_subdomains_server.c
++++ b/src/providers/ipa/ipa_subdomains_server.c
+@@ -172,6 +172,7 @@ static struct ad_options *ipa_ad_options_new(struct be_ctx *be_ctx,
+     const char *forest;
+     const char *forest_realm;
+     char *subdom_conf_path;
++    int ret;
+ 
+     /* Trusts are only established with forest roots */
+     direction = subdom->forest_root->trust_direction;
+@@ -196,12 +197,28 @@ static struct ad_options *ipa_ad_options_new(struct be_ctx *be_ctx,
+         DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported trust direction!\n");
+         ad_options = NULL;
+     }
+-    talloc_free(subdom_conf_path);
+ 
+     if (ad_options == NULL) {
+         DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD options\n");
++        talloc_free(subdom_conf_path);
+         return NULL;
+     }
++
++    ret = ad_inherit_opts_if_needed(id_ctx->ipa_options->id->basic,
++                                    ad_options->id->basic, be_ctx->cdb,
++                                    subdom_conf_path, SDAP_SASL_MECH);
++    talloc_free(subdom_conf_path);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Failed to inherit option [%s] to sub-domain [%s]. "
++              "This error is ignored but might cause issues or unexpected "
++              "behavior later on.\n",
++              id_ctx->ipa_options->id->basic[SDAP_SASL_MECH].opt_name,
++              subdom->name);
++
++        return NULL;
++    }
++
+     return ad_options;
+ }
+ 
+-- 
+2.20.1
+
diff --git a/SOURCES/0032-LDAP-AD-Remove-the-legacy-POSIX-check-from-user-grou.patch b/SOURCES/0032-LDAP-AD-Remove-the-legacy-POSIX-check-from-user-grou.patch
deleted file mode 100644
index 430f309..0000000
--- a/SOURCES/0032-LDAP-AD-Remove-the-legacy-POSIX-check-from-user-grou.patch
+++ /dev/null
@@ -1,385 +0,0 @@
-From ba23021935fcc984b1000bc007fcd3e52fa752cd Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sat, 30 Jun 2018 12:31:13 +0200
-Subject: [PATCH] LDAP/AD: Remove the legacy POSIX check from user, group and
- enumeration searches
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This code is superseded by the POSIX check in the subdomains provider.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3755
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-(cherry picked from commit 8d78119811e2572bb1a05da5abb7c5a2d43d1f97)
----
- src/providers/ad/ad_id.c             |  43 +---------
- src/providers/ldap/ldap_id.c         | 121 ---------------------------
- src/providers/ldap/sdap_async_enum.c | 105 +----------------------
- 3 files changed, 4 insertions(+), 265 deletions(-)
-
-diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
-index 782d9bc402e71d6b20976367f6afbae82bd25750..96c5677c681e40419172c2e5aa3c32b8403147b1 100644
---- a/src/providers/ad/ad_id.c
-+++ b/src/providers/ad/ad_id.c
-@@ -29,28 +29,6 @@
- #include "providers/ldap/sdap_idmap.h"
- #include "providers/ldap/sdap_async.h"
- 
--static void
--disable_gc(struct ad_options *ad_options)
--{
--    errno_t ret;
--
--    if (dp_opt_get_bool(ad_options->basic, AD_ENABLE_GC) == false) {
--        return;
--    }
--
--    DEBUG(SSSDBG_IMPORTANT_INFO, "POSIX attributes were requested "
--          "but are not present on the server side. Global Catalog "
--          "lookups will be disabled\n");
--
--    ret = dp_opt_set_bool(ad_options->basic,
--                          AD_ENABLE_GC, false);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_MINOR_FAILURE,
--                "Could not turn off GC support\n");
--        /* Not fatal */
--    }
--}
--
- static bool ad_account_can_shortcut(struct sdap_idmap_ctx *idmap_ctx,
-                                     struct sss_domain_info *domain,
-                                     int filter_type,
-@@ -296,14 +274,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) {
-@@ -710,22 +686,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);
-diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
-index ebf5d9cb2e2d1cc4b356d431965a00588a876444..9e8289904e60512e088aae77666bcd765bfe3392 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 ea9d51adc7f94145cd7e689893bf7fd81028c5bb..899d59d3831bf473a98b44a7bf4d2007fac84c5e 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)
--- 
-2.17.1
-
diff --git a/SOURCES/0032-Translation-Update-japanese-translation.patch b/SOURCES/0032-Translation-Update-japanese-translation.patch
new file mode 100644
index 0000000..fd67828
--- /dev/null
+++ b/SOURCES/0032-Translation-Update-japanese-translation.patch
@@ -0,0 +1,2750 @@
+From 74f29a0e83d3995de770500b270a3b0d02fa079c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
+Date: Thu, 6 Jun 2019 03:27:05 +0200
+Subject: [PATCH 32/33] Translation: Update japanese translation
+
+---
+ po/ja.po | 1350 ++++++++++++++++++++++++++----------------------------
+ 1 file changed, 647 insertions(+), 703 deletions(-)
+
+diff --git a/po/ja.po b/po/ja.po
+index d8ca6e838..396b693c2 100644
+--- a/po/ja.po
++++ b/po/ja.po
+@@ -1,23 +1,24 @@
+ # SOME DESCRIPTIVE TITLE.
+ # Copyright (C) YEAR Red Hat, Inc.
+ # This file is distributed under the same license as the PACKAGE package.
+-#
++# 
+ # Translators:
+ # Tomoyuki KATO <tomo@dream.daynight.jp>, 2012-2013
+ # Noriko Mizumoto <noriko.mizumoto@gmail.com>, 2016. #zanata
++# Keiko Moriguchi <kemorigu@redhat.com>, 2019. #zanata
+ msgid ""
+ msgstr ""
+ "Project-Id-Version: PACKAGE VERSION\n"
+ "Report-Msgid-Bugs-To: sssd-devel@lists.fedorahosted.org\n"
+-"POT-Creation-Date: 2019-03-20 22:07+0100\n"
+-"PO-Revision-Date: 2016-08-18 08:06+0000\n"
+-"Last-Translator: Noriko Mizumoto <noriko.mizumoto@gmail.com>\n"
+-"Language-Team: Japanese (http://www.transifex.com/projects/p/sssd/language/"
+-"ja/)\n"
+-"Language: ja\n"
++"POT-Creation-Date: 2019-02-27 19:55+0100\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=UTF-8\n"
+ "Content-Transfer-Encoding: 8bit\n"
++"PO-Revision-Date: 2019-05-28 11:45+0000\n"
++"Last-Translator: Keiko Moriguchi <kemorigu@redhat.com>\n"
++"Language-Team: Japanese (http://www.transifex.com/projects/p/sssd/language/"
++"ja/)\n"
++"Language: ja\n"
+ "Plural-Forms: nplurals=1; plural=0;\n"
+ "X-Generator: Zanata 4.6.2\n"
+ 
+@@ -40,7 +41,7 @@ msgstr "デバッグメッセージをログファイルに書き込む"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:48
+ msgid "Watchdog timeout before restarting service"
+-msgstr ""
++msgstr "サービス再起動前の Watchdog タイムアウト"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:49
+ msgid "Command to start service"
+@@ -60,11 +61,11 @@ msgstr "クライアントの自動切断までのアイドル時間"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:53
+ msgid "Idle time before automatic shutdown of the responder"
+-msgstr ""
++msgstr "レスポンダーの自動シャットダウンまでのアイドル時間"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:54
+ msgid "Always query all the caches before querying the Data Providers"
+-msgstr ""
++msgstr "データプロバイダーをクエリーする前に、常にすべてのキャッシュをクエリーします"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:57
+ msgid "SSSD Services to start"
+@@ -79,12 +80,12 @@ msgid "Timeout for messages sent over the SBUS"
+ msgstr "SBUS 経由のメッセージ送信のタイムアウト"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:60
+-#: src/config/SSSDConfig/__init__.py.in:198
++#: src/config/SSSDConfig/__init__.py.in:199
+ msgid "Regex to parse username and domain"
+ msgstr "ユーザー名とドメインを構文解析する正規表現"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:61
+-#: src/config/SSSDConfig/__init__.py.in:197
++#: src/config/SSSDConfig/__init__.py.in:198
+ msgid "Printf-compatible format for displaying fully-qualified names"
+ msgstr "完全修飾名を表示するための printf 互換の形式"
+ 
+@@ -92,9 +93,7 @@ msgstr "完全修飾名を表示するための printf 互換の形式"
+ msgid ""
+ "Directory on the filesystem where SSSD should store Kerberos replay cache "
+ "files."
+-msgstr ""
+-"SSSD が Kerberos リプレイキャッシュファイルを保存するファイルシステムのディレ"
+-"クトリです。"
++msgstr "SSSD が Kerberos リプレイキャッシュファイルを保存するファイルシステムのディレクトリです。"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:63
+ msgid "Domain to add to names without a domain component."
+@@ -102,27 +101,27 @@ msgstr "domain 要素なしで追加するドメインの名前。"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:64
+ msgid "The user to drop privileges to"
+-msgstr ""
++msgstr "ユーザーが特権を停止します"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:65
+ msgid "Tune certificate verification"
+-msgstr ""
++msgstr "証明書検証の調整"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:66
+ msgid "All spaces in group or user names will be replaced with this character"
+-msgstr ""
++msgstr "グループ名またはユーザー名のすべてのスペースは、この文字に置き換えられます"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:67
+ msgid "Tune sssd to honor or ignore netlink state changes"
+-msgstr ""
++msgstr "SSSD を調整し、netlink の状態変更を尊重するか、または無視します"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:68
+ msgid "Enable or disable the implicit files domain"
+-msgstr ""
++msgstr "暗黙のファイルドメインを有効化または無効化する"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:69
+ msgid "A specific order of the domains to be looked up"
+-msgstr ""
++msgstr "検索するドメインの特定の順番"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:72
+ msgid "Enumeration cache timeout length (seconds)"
+@@ -133,13 +132,13 @@ msgid "Entry cache background update timeout length (seconds)"
+ msgstr "エントリーキャッシュのバックグラウンド更新のタイムアウト時間(秒)"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:74
+-#: src/config/SSSDConfig/__init__.py.in:114
++#: src/config/SSSDConfig/__init__.py.in:116
+ msgid "Negative cache timeout length (seconds)"
+ msgstr "ネガティブキャッシュのタイムアウト(秒)"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:75
+ msgid "Files negative cache timeout length (seconds)"
+-msgstr ""
++msgstr "ファイルネガティブキャッシュのタイムアウト時間(秒)"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:76
+ msgid "Users that SSSD should explicitly ignore"
+@@ -164,9 +163,7 @@ msgstr "識別プロバイダーからのホームディレクトリーの値を
+ #: src/config/SSSDConfig/__init__.py.in:81
+ msgid ""
+ "Substitute empty homedir value from the identity provider with this value"
+-msgstr ""
+-"アイデンティティプロバイダーからの空のホームディレクトリーをこの値で置き換え"
+-"ます"
++msgstr "アイデンティティプロバイダーからの空のホームディレクトリーをこの値で置き換えます"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:82
+ msgid "Override shell value from the identity provider with this value"
+@@ -185,9 +182,7 @@ msgstr "拒否されてフォールバックシェルで置き換えられるシ
+ msgid ""
+ "If a shell stored in central directory is allowed but not available, use "
+ "this fallback"
+-msgstr ""
+-"中央ディレクトリーに保存されたシェルが許可されるが、利用できない場合、この"
+-"フォールバックを使用する"
++msgstr "中央ディレクトリーに保存されたシェルが許可されるが、利用できない場合、このフォールバックを使用する"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:86
+ msgid "Shell to use if the provider does not list one"
+@@ -199,7 +194,7 @@ msgstr "メモリー内のキャッシュレコードが有効な期間"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:88
+ msgid "List of user attributes the NSS responder is allowed to publish"
+-msgstr ""
++msgstr "NSS レスポンダーがパブリッシュを許可されたユーザー属性の一覧"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:91
+ msgid "How long to allow cached logins between online logins (days)"
+@@ -221,7 +216,7 @@ msgstr "認証中にユーザーに表示されるメッセージの種類"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:95
+ msgid "Filter PAM responses sent to the pam_sss"
+-msgstr ""
++msgstr "pam_sss へ送信された PAM のレスポンスをフィルタリングします"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:96
+ msgid "How many seconds to keep identity information cached for PAM requests"
+@@ -233,625 +228,630 @@ msgstr "警告が表示されるパスワード失効前の日数"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:98
+ msgid "List of trusted uids or user's name"
+-msgstr ""
++msgstr "信頼できる UID またはユーザー名の一覧"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:99
+ msgid "List of domains accessible even for untrusted users."
+-msgstr ""
++msgstr "信頼できないユーザーでさえアクセス可能なドメインの一覧。"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:100
+ msgid "Message printed when user account is expired."
+-msgstr ""
++msgstr "ユーザーアカウントの有効期限が切れると、メッセージが印刷されます。"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:101
+ msgid "Message printed when user account is locked."
+-msgstr ""
++msgstr "ユーザーアカウントがロックされると、メッセージが印刷されます。"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:102
+ msgid "Allow certificate based/Smartcard authentication."
+-msgstr ""
++msgstr "証明書ベースまたはスマートカードによる認証を許可します。"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:103
+ msgid "Path to certificate database with PKCS#11 modules."
+-msgstr ""
++msgstr "PKCS#11 モジュールでの証明書データベースへのパス。"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:104
+ msgid "How many seconds will pam_sss wait for p11_child to finish"
+-msgstr ""
++msgstr "p11_child が完了するまでに pam_sss が待つ秒数"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:105
+ msgid "Which PAM services are permitted to contact application domains"
+-msgstr ""
++msgstr "アプリケーションドメインへの接続を許可される PAM サービスはどれか"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:106
+ msgid "Allowed services for using smartcards"
+-msgstr ""
++msgstr "スマートカードの使用が許可されたサービス"
++
++#: src/config/SSSDConfig/__init__.py.in:107
++msgid "Additional timeout to wait for a card if requested"
++msgstr "要求された場合に、カードが待つ追加のタイムアウト"
++
++#: src/config/SSSDConfig/__init__.py.in:108
++msgid ""
++"PKCS#11 URI to restrict the selection of devices for Smartcard "
++"authentication"
++msgstr "スマートカード認証向けのデバイスの選択を PKCS#11 URI が制限"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:109
++#: src/config/SSSDConfig/__init__.py.in:111
+ msgid "Whether to evaluate the time-based attributes in sudo rules"
+ msgstr "sudo ルールにおいて時間による属性を評価するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:110
++#: src/config/SSSDConfig/__init__.py.in:112
+ msgid "If true, SSSD will switch back to lower-wins ordering logic"
+-msgstr ""
++msgstr "正しい場合、SSSD は小さい番号が優先される順位付けのロジックへ戻ります"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:111
++#: src/config/SSSDConfig/__init__.py.in:113
+ msgid ""
+ "Maximum number of rules that can be refreshed at once. If this is exceeded, "
+ "full refresh is performed."
+-msgstr ""
++msgstr "一度にリフレッシュ可能なルールの最大数。最大数を超えると、フルリフレッシュが実行されます。"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:117
++#: src/config/SSSDConfig/__init__.py.in:119
+ msgid "Whether to hash host names and addresses in the known_hosts file"
+ msgstr "known_hosts ファイルにおいてホスト名とアドレスをハッシュ化するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:118
++#: src/config/SSSDConfig/__init__.py.in:120
+ msgid ""
+ "How many seconds to keep a host in the known_hosts file after its host keys "
+ "were requested"
+ msgstr "ホスト鍵が要求された後 known_hosts ファイルにホストを保持する秒数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:119
++#: src/config/SSSDConfig/__init__.py.in:121
+ msgid "Path to storage of trusted CA certificates"
+-msgstr ""
++msgstr "信頼された CA 証明書のストレージへのパス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:122
++#: src/config/SSSDConfig/__init__.py.in:124
+ msgid "List of UIDs or user names allowed to access the PAC responder"
+ msgstr "PAC レスポンダーへのアクセスが許可された UID またはユーザー名の一覧"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:123
++#: src/config/SSSDConfig/__init__.py.in:125
+ msgid "How long the PAC data is considered valid"
+-msgstr ""
++msgstr "PAC データが有効とされる期間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:126
++#: src/config/SSSDConfig/__init__.py.in:128
+ msgid "List of UIDs or user names allowed to access the InfoPipe responder"
+-msgstr ""
++msgstr "InfoPipe レスポンダーへのアクセスが許可された UID またはユーザー名の一覧"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:127
++#: src/config/SSSDConfig/__init__.py.in:129
+ msgid "List of user attributes the InfoPipe is allowed to publish"
+-msgstr ""
++msgstr "InfoPipe がパブリッシュを許可されたユーザー属性の一覧"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:130
++#: src/config/SSSDConfig/__init__.py.in:132
+ msgid "The provider where the secrets will be stored in"
+-msgstr ""
++msgstr "シークレットが保存されるプロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:131
++#: src/config/SSSDConfig/__init__.py.in:133
+ msgid "The maximum allowed number of nested containers"
+-msgstr ""
++msgstr "ネストされたコンテナーの最大許可数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:132
++#: src/config/SSSDConfig/__init__.py.in:134
+ msgid "The maximum number of secrets that can be stored"
+-msgstr ""
++msgstr "保存可能なシークレットの最大数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:133
++#: src/config/SSSDConfig/__init__.py.in:135
+ msgid "The maximum number of secrets that can be stored per UID"
+-msgstr ""
++msgstr "UID ごとに保存可能なシークレットの最大数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:134
++#: src/config/SSSDConfig/__init__.py.in:136
+ msgid "The maximum payload size of a secret in kilobytes"
+-msgstr ""
++msgstr "キロバイトでのシークレットの最大ペイロードサイズ"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:136
++#: src/config/SSSDConfig/__init__.py.in:138
+ msgid "The URL Custodia server is listening on"
+-msgstr ""
++msgstr "URL Custodia サーバーはリッスンしています"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:137
++#: src/config/SSSDConfig/__init__.py.in:139
+ msgid "The method to use when authenticating to a Custodia server"
+-msgstr ""
++msgstr "Custodia サーバーへの認証時に使用する方法"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:138
++#: src/config/SSSDConfig/__init__.py.in:140
+ msgid ""
+ "The name of the headers that will be added into a HTTP request with the "
+ "value defined in auth_header_value"
+-msgstr ""
++msgstr "auth_header_value で値が定義され、HTTP リクエストに追加されるヘッダーの名前"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:139
++#: src/config/SSSDConfig/__init__.py.in:141
+ msgid "The value sssd-secrets would use for auth_header_name"
+-msgstr ""
++msgstr "sssd-secrets の値は、auth_header_name で使用します"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:140
++#: src/config/SSSDConfig/__init__.py.in:142
+ msgid ""
+ "The list of the headers to forward to the Custodia server together with the "
+ "request"
+-msgstr ""
++msgstr "要求と共に Custodia サーバーへ転送するヘッダーの一覧"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:141
++#: src/config/SSSDConfig/__init__.py.in:143
+ msgid ""
+-"The username to use when authenticating to a Custodia server using basic_auth"
+-msgstr ""
++"The username to use when authenticating to a Custodia server using "
++"basic_auth"
++msgstr "basic_auth を使った Custodia サーバーへの認証時に使用するユーザー名"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:142
++#: src/config/SSSDConfig/__init__.py.in:144
+ msgid ""
+-"The password to use when authenticating to a Custodia server using basic_auth"
+-msgstr ""
++"The password to use when authenticating to a Custodia server using "
++"basic_auth"
++msgstr "basic_auth を使った Custodia サーバーへの認証時に使用するパスワード"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:143
+-msgid "If true peer's certificate is verified if proxy_url uses https protocol"
+-msgstr ""
++#: src/config/SSSDConfig/__init__.py.in:145
++msgid ""
++"If true peer's certificate is verified if proxy_url uses https protocol"
++msgstr "proxy_url が https protocol を使用する場合に、正しいピアの証明書が検証されるかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:144
++#: src/config/SSSDConfig/__init__.py.in:146
+ msgid ""
+ "If false peer's certificate may contain different hostname than proxy_url "
+ "when https protocol is used"
+-msgstr ""
++msgstr "https プロトコルが使用される場合に、間違ったピアの証明書が proxy_url 以外の異なるホスト名を含むかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:145
++#: src/config/SSSDConfig/__init__.py.in:147
+ msgid "Path to directory where certificate authority certificates are stored"
+-msgstr ""
++msgstr "CA 証明書が保存されているディレクトリーへのパス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:146
++#: src/config/SSSDConfig/__init__.py.in:148
+ msgid "Path to file containing server's CA certificate"
+-msgstr ""
++msgstr "サーバーの CA 証明書を含むファイルへのパス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:147
++#: src/config/SSSDConfig/__init__.py.in:149
+ msgid "Path to file containing client's certificate"
+-msgstr ""
++msgstr "クライアントの証明書を含むファイルへのパス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:148
++#: src/config/SSSDConfig/__init__.py.in:150
+ msgid "Path to file containing client's private key"
+-msgstr ""
++msgstr "クライアントのプライベートキーを含むファイルへのパス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:151
++#: src/config/SSSDConfig/__init__.py.in:153
+ msgid "Identity provider"
+ msgstr "アイデンティティプロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:152
++#: src/config/SSSDConfig/__init__.py.in:154
+ msgid "Authentication provider"
+ msgstr "認証プロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:153
++#: src/config/SSSDConfig/__init__.py.in:155
+ msgid "Access control provider"
+ msgstr "アクセス制御プロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:154
++#: src/config/SSSDConfig/__init__.py.in:156
+ msgid "Password change provider"
+ msgstr "パスワード変更プロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:155
++#: src/config/SSSDConfig/__init__.py.in:157
+ msgid "SUDO provider"
+ msgstr "SUDO プロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:156
++#: src/config/SSSDConfig/__init__.py.in:158
+ msgid "Autofs provider"
+ msgstr "Autofs プロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:157
++#: src/config/SSSDConfig/__init__.py.in:159
+ msgid "Host identity provider"
+ msgstr "ホスト識別プロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:158
++#: src/config/SSSDConfig/__init__.py.in:160
+ msgid "SELinux provider"
+-msgstr ""
++msgstr "SELinux プロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:159
++#: src/config/SSSDConfig/__init__.py.in:161
+ msgid "Session management provider"
+-msgstr ""
++msgstr "セッションマネージャーのプロバイダー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:162
++#: src/config/SSSDConfig/__init__.py.in:164
+ msgid "Whether the domain is usable by the OS or by applications"
+-msgstr ""
++msgstr "OS またはアプリケーションがドメインを使用できるかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:163
++#: src/config/SSSDConfig/__init__.py.in:165
+ msgid "Minimum user ID"
+ msgstr "最小ユーザー ID"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:164
++#: src/config/SSSDConfig/__init__.py.in:166
+ msgid "Maximum user ID"
+ msgstr "最大ユーザー ID"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:165
++#: src/config/SSSDConfig/__init__.py.in:167
+ msgid "Enable enumerating all users/groups"
+ msgstr "すべてのユーザー・グループの列挙を有効にする"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:166
++#: src/config/SSSDConfig/__init__.py.in:168
+ msgid "Cache credentials for offline login"
+ msgstr "オフラインログインのためにクレディンシャルをキャッシュする"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:167
+-msgid "Store password hashes"
+-msgstr ""
+-
+-#: src/config/SSSDConfig/__init__.py.in:168
++#: src/config/SSSDConfig/__init__.py.in:169
+ msgid "Display users/groups in fully-qualified form"
+ msgstr "ユーザー・グループを完全修飾形式で表示する"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:169
++#: src/config/SSSDConfig/__init__.py.in:170
+ msgid "Don't include group members in group lookups"
+ msgstr "グループ検索にグループメンバーを含めない"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:170
+-#: src/config/SSSDConfig/__init__.py.in:177
++#: src/config/SSSDConfig/__init__.py.in:171
+ #: src/config/SSSDConfig/__init__.py.in:178
+ #: src/config/SSSDConfig/__init__.py.in:179
+ #: src/config/SSSDConfig/__init__.py.in:180
+ #: src/config/SSSDConfig/__init__.py.in:181
+ #: src/config/SSSDConfig/__init__.py.in:182
++#: src/config/SSSDConfig/__init__.py.in:183
+ msgid "Entry cache timeout length (seconds)"
+ msgstr "エントリーキャッシュのタイムアウト長(秒)"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:171
++#: src/config/SSSDConfig/__init__.py.in:172
+ msgid ""
+ "Restrict or prefer a specific address family when performing DNS lookups"
+ msgstr "DNS 検索を実行するときに特定のアドレスファミリーを制限または優先します"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:172
++#: src/config/SSSDConfig/__init__.py.in:173
+ msgid "How long to keep cached entries after last successful login (days)"
+ msgstr "最終ログイン成功時からキャッシュエントリーを保持する日数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:173
++#: src/config/SSSDConfig/__init__.py.in:174
+ msgid "How long to wait for replies from DNS when resolving servers (seconds)"
+ msgstr "サーバーを名前解決するときに DNS から応答を待つ時間(秒)"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:174
++#: src/config/SSSDConfig/__init__.py.in:175
+ msgid "The domain part of service discovery DNS query"
+ msgstr "サービス検索 DNS クエリーのドメイン部分"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:175
++#: src/config/SSSDConfig/__init__.py.in:176
+ msgid "Override GID value from the identity provider with this value"
+ msgstr "識別プロバイダーからの GID 値をこの値で上書きする"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:176
++#: src/config/SSSDConfig/__init__.py.in:177
+ msgid "Treat usernames as case sensitive"
+ msgstr "ユーザー名が大文字小文字を区別するよう取り扱う"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:183
++#: src/config/SSSDConfig/__init__.py.in:184
+ msgid "How often should expired entries be refreshed in background"
+ msgstr "期限切れのエントリーがバックグラウンドで更新される頻度"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:184
++#: src/config/SSSDConfig/__init__.py.in:185
+ msgid "Whether to automatically update the client's DNS entry"
+ msgstr "自動的にクライアントの DNS エントリーを更新するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:185
+-#: src/config/SSSDConfig/__init__.py.in:207
++#: src/config/SSSDConfig/__init__.py.in:186
++#: src/config/SSSDConfig/__init__.py.in:208
+ msgid "The TTL to apply to the client's DNS entry after updating it"
+ msgstr "クライアントの DNS 項目を更新後、適用する TTL"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:186
+-#: src/config/SSSDConfig/__init__.py.in:208
++#: src/config/SSSDConfig/__init__.py.in:187
++#: src/config/SSSDConfig/__init__.py.in:209
+ msgid "The interface whose IP should be used for dynamic DNS updates"
+ msgstr "動的 DNS 更新のために使用される IP のインターフェース"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:187
++#: src/config/SSSDConfig/__init__.py.in:188
+ msgid "How often to periodically update the client's DNS entry"
+ msgstr "どのくらい定期的にクライアントの DNS エントリーを更新するか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:188
++#: src/config/SSSDConfig/__init__.py.in:189
+ msgid "Whether the provider should explicitly update the PTR record as well"
+-msgstr ""
+-"プロバイダーが同じように PTR レコードを明示的に更新する必要があるかどうか"
++msgstr "プロバイダーが同じように PTR レコードを明示的に更新する必要があるかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:189
++#: src/config/SSSDConfig/__init__.py.in:190
+ msgid "Whether the nsupdate utility should default to using TCP"
+ msgstr "nsupdate ユーティリティが標準で TCP を使用するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:190
++#: src/config/SSSDConfig/__init__.py.in:191
+ msgid "What kind of authentication should be used to perform the DNS update"
+ msgstr "DNS 更新を実行するために使用すべき認証の種類"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:191
++#: src/config/SSSDConfig/__init__.py.in:192
+ msgid "Override the DNS server used to perform the DNS update"
+-msgstr ""
++msgstr "DNS の更新を実行する際に使用する DNS サーバーを上書き"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:192
++#: src/config/SSSDConfig/__init__.py.in:193
+ msgid "Control enumeration of trusted domains"
+-msgstr ""
++msgstr "信頼されたドメインの列挙を制御"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:193
++#: src/config/SSSDConfig/__init__.py.in:194
+ msgid "How often should subdomains list be refreshed"
+-msgstr ""
++msgstr "サブドメインの一覧のリフレッシュ回数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:194
++#: src/config/SSSDConfig/__init__.py.in:195
+ msgid "List of options that should be inherited into a subdomain"
+-msgstr ""
++msgstr "サブドメインに継承すべきオプションの一覧"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:195
++#: src/config/SSSDConfig/__init__.py.in:196
+ msgid "Default subdomain homedir value"
+-msgstr ""
++msgstr "デフォルトのサブドメインホームディレクトリーの値"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:196
++#: src/config/SSSDConfig/__init__.py.in:197
+ msgid "How long can cached credentials be used for cached authentication"
+-msgstr ""
++msgstr "証明書キャッシュを認証キャッシュに使用できる期間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:199
++#: src/config/SSSDConfig/__init__.py.in:200
+ msgid "Whether to automatically create private groups for users"
+-msgstr ""
++msgstr "ユーザーにプライベートグループを自動的に作成するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:202
++#: src/config/SSSDConfig/__init__.py.in:203
+ msgid "IPA domain"
+ msgstr "IPA ドメイン"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:203
++#: src/config/SSSDConfig/__init__.py.in:204
+ msgid "IPA server address"
+ msgstr "IPA サーバーのアドレス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:204
++#: src/config/SSSDConfig/__init__.py.in:205
+ msgid "Address of backup IPA server"
+ msgstr "バックアップ IPA サーバーのアドレス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:205
++#: src/config/SSSDConfig/__init__.py.in:206
+ msgid "IPA client hostname"
+ msgstr "IPA クライアントのホスト名"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:206
++#: src/config/SSSDConfig/__init__.py.in:207
+ msgid "Whether to automatically update the client's DNS entry in FreeIPA"
+ msgstr "FreeIPA にあるクライアントの DNS エントリーを自動的に更新するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:209
++#: src/config/SSSDConfig/__init__.py.in:210
+ msgid "Search base for HBAC related objects"
+ msgstr "HBAC 関連オブジェクトの検索ベース"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:210
++#: src/config/SSSDConfig/__init__.py.in:211
+ msgid ""
+ "The amount of time between lookups of the HBAC rules against the IPA server"
+ msgstr "IPA サーバーに対する HBAC ルールを検索している間の合計時間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:211
++#: src/config/SSSDConfig/__init__.py.in:212
+ msgid ""
+ "The amount of time in seconds between lookups of the SELinux maps against "
+ "the IPA server"
+ msgstr "IPA サーバーに対する SELinux マップの検索の間の秒単位の合計時間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:212
++#: src/config/SSSDConfig/__init__.py.in:213
+ msgid "If set to false, host argument given by PAM will be ignored"
+ msgstr "もし偽に設定されていると、 PAM により渡されたホスト引数は無視されます"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:213
++#: src/config/SSSDConfig/__init__.py.in:214
+ msgid "The automounter location this IPA client is using"
+ msgstr "この IPA クライアントが使用している automounter の場所"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:214
++#: src/config/SSSDConfig/__init__.py.in:215
+ msgid "Search base for object containing info about IPA domain"
+ msgstr "IPA ドメインに関する情報を含むオブジェクトに対する検索ベース"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:215
++#: src/config/SSSDConfig/__init__.py.in:216
+ msgid "Search base for objects containing info about ID ranges"
+ msgstr "ID 範囲に関する情報を含むオブジェクトに対する検索ベース"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:216
+-#: src/config/SSSDConfig/__init__.py.in:234
++#: src/config/SSSDConfig/__init__.py.in:217
++#: src/config/SSSDConfig/__init__.py.in:235
+ msgid "Enable DNS sites - location based service discovery"
+ msgstr "DNS サイトの有効化 - 位置にサービス探索"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:217
++#: src/config/SSSDConfig/__init__.py.in:218
+ msgid "Search base for view containers"
+-msgstr ""
++msgstr "ビューコンテナーの検索ベース"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:218
++#: src/config/SSSDConfig/__init__.py.in:219
+ msgid "Objectclass for view containers"
+-msgstr ""
++msgstr "ビューコンテナーのオブジェクトクラス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:219
++#: src/config/SSSDConfig/__init__.py.in:220
+ msgid "Attribute with the name of the view"
+-msgstr ""
++msgstr "ビューの名前の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:220
++#: src/config/SSSDConfig/__init__.py.in:221
+ msgid "Objectclass for override objects"
+-msgstr ""
++msgstr "上書きされたオブジェクトのオブジェクトクラス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:221
++#: src/config/SSSDConfig/__init__.py.in:222
+ msgid "Attribute with the reference to the original object"
+-msgstr ""
++msgstr "オリジナルオブジェクトを参照する属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:222
++#: src/config/SSSDConfig/__init__.py.in:223
+ msgid "Objectclass for user override objects"
+-msgstr ""
++msgstr "ユーザーが上書きするオブジェクトのオブジェクトクラス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:223
++#: src/config/SSSDConfig/__init__.py.in:224
+ msgid "Objectclass for group override objects"
+-msgstr ""
++msgstr "グループが上書きするオブジェクトのオブジェクトクラス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:224
++#: src/config/SSSDConfig/__init__.py.in:225
+ msgid "Search base for Desktop Profile related objects"
+-msgstr ""
++msgstr "デスクトッププロファイルに関連するオブジェクトの検索ベース"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:225
++#: src/config/SSSDConfig/__init__.py.in:226
+ msgid ""
+ "The amount of time in seconds between lookups of the Desktop Profile rules "
+ "against the IPA server"
+-msgstr ""
++msgstr "IPA サーバーに対するデスクトッププロファイルルールを検索している間の秒単位の合計時間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:226
++#: src/config/SSSDConfig/__init__.py.in:227
+ msgid ""
+ "The amount of time in minutes between lookups of Desktop Profiles rules "
+ "against the IPA server when the last request did not find any rule"
+-msgstr ""
++msgstr "最後の要求がルールを何も見つけなかった場合の IPA サーバーに対するデスクトッププロファイルル ールを検索している間の分単位の合計時間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:229
++#: src/config/SSSDConfig/__init__.py.in:230
+ msgid "Active Directory domain"
+ msgstr "Active Directory ドメイン"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:230
++#: src/config/SSSDConfig/__init__.py.in:231
+ msgid "Enabled Active Directory domains"
+-msgstr ""
++msgstr "有効化された Active Directory ドメイン"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:231
++#: src/config/SSSDConfig/__init__.py.in:232
+ msgid "Active Directory server address"
+ msgstr "Active Directory サーバーアドレス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:232
++#: src/config/SSSDConfig/__init__.py.in:233
+ msgid "Active Directory backup server address"
+ msgstr "Active Directory バックアップサーバーのアドレス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:233
++#: src/config/SSSDConfig/__init__.py.in:234
+ msgid "Active Directory client hostname"
+ msgstr "Active Directory クライアントホスト名"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:235
+-#: src/config/SSSDConfig/__init__.py.in:422
++#: src/config/SSSDConfig/__init__.py.in:236
++#: src/config/SSSDConfig/__init__.py.in:420
+ msgid "LDAP filter to determine access privileges"
+ msgstr "アクセス権限を決めるための LDAP フィルター"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:236
++#: src/config/SSSDConfig/__init__.py.in:237
+ msgid "Whether to use the Global Catalog for lookups"
+-msgstr ""
++msgstr "検索にグローバルカタログを使用するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:237
++#: src/config/SSSDConfig/__init__.py.in:238
+ msgid "Operation mode for GPO-based access control"
+-msgstr ""
++msgstr "グローバルカタログベースのアクセス制御に対するオペレーションモード"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:238
++#: src/config/SSSDConfig/__init__.py.in:239
+ msgid ""
+ "The amount of time between lookups of the GPO policy files against the AD "
+ "server"
+-msgstr ""
++msgstr "AD サーバーに対する GPO ポリシーファイルを検索している間の合計時間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:239
++#: src/config/SSSDConfig/__init__.py.in:240
+ msgid ""
+ "PAM service names that map to the GPO (Deny)InteractiveLogonRight policy "
+ "settings"
+-msgstr ""
++msgstr "GPO (Deny)InteractiveLogonRight のポリシー設定にマッピングした PAM サービス名"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:240
++#: src/config/SSSDConfig/__init__.py.in:241
+ msgid ""
+ "PAM service names that map to the GPO (Deny)RemoteInteractiveLogonRight "
+ "policy settings"
+-msgstr ""
+-
+-#: src/config/SSSDConfig/__init__.py.in:241
+-msgid ""
+-"PAM service names that map to the GPO (Deny)NetworkLogonRight policy settings"
+-msgstr ""
++msgstr "GPO (Deny)RemoteInteractiveLogonRight のポリシー設定にマッピングした PAM サービス名"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:242
+ msgid ""
+-"PAM service names that map to the GPO (Deny)BatchLogonRight policy settings"
+-msgstr ""
++"PAM service names that map to the GPO (Deny)NetworkLogonRight policy "
++"settings"
++msgstr "GPO (Deny)NetworkLogonRight のポリシー設定にマッピングした PAM サービス名"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:243
+ msgid ""
+-"PAM service names that map to the GPO (Deny)ServiceLogonRight policy settings"
+-msgstr ""
++"PAM service names that map to the GPO (Deny)BatchLogonRight policy settings"
++msgstr "GPO (Deny)BatchLogonRight のポリシー設定にマッピングした PAM サービス名"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:244
+-msgid "PAM service names for which GPO-based access is always granted"
+-msgstr ""
++msgid ""
++"PAM service names that map to the GPO (Deny)ServiceLogonRight policy "
++"settings"
++msgstr "(Deny)ServiceLogonRight のポリシー設定にマッピングした PAM サービス名"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:245
+-msgid "PAM service names for which GPO-based access is always denied"
+-msgstr ""
++msgid "PAM service names for which GPO-based access is always granted"
++msgstr "GPO ベースのアクセスが常に許可される PAM サービス名"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:246
++msgid "PAM service names for which GPO-based access is always denied"
++msgstr "GPO ベースのアクセスが常に拒否される PAM サービス名"
++
++#: src/config/SSSDConfig/__init__.py.in:247
+ msgid ""
+ "Default logon right (or permit/deny) to use for unmapped PAM service names"
+-msgstr ""
++msgstr "マッピングされていない PAM サービス名に使用するデフォルトのログオン権利 (または許可/拒否)"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:247
++#: src/config/SSSDConfig/__init__.py.in:248
+ msgid "a particular site to be used by the client"
+-msgstr ""
++msgstr "クライアントが使用する特定のサイト"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:248
++#: src/config/SSSDConfig/__init__.py.in:249
+ msgid ""
+ "Maximum age in days before the machine account password should be renewed"
+-msgstr ""
++msgstr "マシンアカウントのパスワードの更新が必要となるまでの最大日数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:249
++#: src/config/SSSDConfig/__init__.py.in:250
+ msgid "Option for tuning the machine account renewal task"
+-msgstr ""
++msgstr "マシンアカウントの更新タスクをチューニングするオプション"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:252
+ #: src/config/SSSDConfig/__init__.py.in:253
++#: src/config/SSSDConfig/__init__.py.in:254
+ msgid "Kerberos server address"
+ msgstr "Kerberos サーバーのアドレス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:254
++#: src/config/SSSDConfig/__init__.py.in:255
+ msgid "Kerberos backup server address"
+ msgstr "Kerberos バックアップサーバーのアドレス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:255
++#: src/config/SSSDConfig/__init__.py.in:256
+ msgid "Kerberos realm"
+ msgstr "Kerberos レルム"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:256
++#: src/config/SSSDConfig/__init__.py.in:257
+ msgid "Authentication timeout"
+ msgstr "認証のタイムアウト"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:257
++#: src/config/SSSDConfig/__init__.py.in:258
+ msgid "Whether to create kdcinfo files"
+ msgstr "kdcinfo ファイルを作成するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:258
++#: src/config/SSSDConfig/__init__.py.in:259
+ msgid "Where to drop krb5 config snippets"
+-msgstr ""
++msgstr "krb5 設定スニペットを削除する場所"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:261
++#: src/config/SSSDConfig/__init__.py.in:262
+ msgid "Directory to store credential caches"
+ msgstr "クレディンシャルのキャッシュを保存するディレクトリー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:262
++#: src/config/SSSDConfig/__init__.py.in:263
+ msgid "Location of the user's credential cache"
+ msgstr "ユーザーのクレディンシャルキャッシュの位置"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:263
++#: src/config/SSSDConfig/__init__.py.in:264
+ msgid "Location of the keytab to validate credentials"
+ msgstr "クレディンシャルを検証するキーテーブルの場所"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:264
++#: src/config/SSSDConfig/__init__.py.in:265
+ msgid "Enable credential validation"
+ msgstr "クレディンシャルの検証を有効にする"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:265
++#: src/config/SSSDConfig/__init__.py.in:266
+ msgid "Store password if offline for later online authentication"
+ msgstr "後からオンライン認証するためにオフラインの場合にパスワードを保存します"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:266
++#: src/config/SSSDConfig/__init__.py.in:267
+ msgid "Renewable lifetime of the TGT"
+ msgstr "更新可能な TGT の有効期間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:267
++#: src/config/SSSDConfig/__init__.py.in:268
+ msgid "Lifetime of the TGT"
+ msgstr "TGT の有効期間"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:268
++#: src/config/SSSDConfig/__init__.py.in:269
+ msgid "Time between two checks for renewal"
+ msgstr "更新を確認する間隔"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:269
++#: src/config/SSSDConfig/__init__.py.in:270
+ msgid "Enables FAST"
+ msgstr "FAST を有効にする"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:270
++#: src/config/SSSDConfig/__init__.py.in:271
+ msgid "Selects the principal to use for FAST"
+ msgstr "FAST に使用するプリンシパルを選択する"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:271
++#: src/config/SSSDConfig/__init__.py.in:272
+ msgid "Enables principal canonicalization"
+ msgstr "プリンシパル正規化を有効にする"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:272
++#: src/config/SSSDConfig/__init__.py.in:273
+ msgid "Enables enterprise principals"
+ msgstr "エンタープライズ・プリンシパルの有効化"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:273
++#: src/config/SSSDConfig/__init__.py.in:274
+ msgid "A mapping from user names to Kerberos principal names"
+-msgstr ""
++msgstr "ユーザー名から Kerberos プリンシパル名までのマッピング"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:276
+ #: src/config/SSSDConfig/__init__.py.in:277
++#: src/config/SSSDConfig/__init__.py.in:278
+ msgid "Server where the change password service is running if not on the KDC"
+ msgstr "KDC になければ、パスワード変更サービスが実行されているサーバー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:280
++#: src/config/SSSDConfig/__init__.py.in:281
+ msgid "ldap_uri, The URI of the LDAP server"
+ msgstr "ldap_uri, LDAP サーバーの URI"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:281
++#: src/config/SSSDConfig/__init__.py.in:282
+ msgid "ldap_backup_uri, The URI of the LDAP server"
+ msgstr "ldap_backup_uri, LDAP サーバーの URI"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:282
++#: src/config/SSSDConfig/__init__.py.in:283
+ msgid "The default base DN"
+ msgstr "デフォルトのベース DN"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:283
++#: src/config/SSSDConfig/__init__.py.in:284
+ msgid "The Schema Type in use on the LDAP server, rfc2307"
+ msgstr "LDAP サーバーにおいて使用中のスキーマ形式, rfc2307"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:284
+-#, fuzzy
+-msgid "Mode used to change user password"
+-msgstr "パスワードの期限が切れました。いますぐパスワードを変更してください。"
+-
+ #: src/config/SSSDConfig/__init__.py.in:285
+ msgid "The default bind DN"
+ msgstr "デフォルトのバインド DN"
+@@ -956,9 +956,7 @@ msgstr "完全な参照解決を引き起こすために欠けている必要が
+ msgid ""
+ "Whether the LDAP library should perform a reverse lookup to canonicalize the "
+ "host name during a SASL bind"
+-msgstr ""
+-"LDAP ライブラリーが SASL バインド中にホスト名を正規化するために逆引きを実行す"
+-"るかどうか"
++msgstr "LDAP ライブラリーが SASL バインド中にホスト名を正規化するために逆引きを実行するかどうか"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:312
+ msgid "entryUSN attribute"
+@@ -969,7 +967,8 @@ msgid "lastUSN attribute"
+ msgstr "lastUSN 属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:315
+-msgid "How long to retain a connection to the LDAP server before disconnecting"
++msgid ""
++"How long to retain a connection to the LDAP server before disconnecting"
+ msgstr "LDAP サーバーを切断する前に接続を保持する時間"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:317
+@@ -1046,7 +1045,7 @@ msgstr "シェルの属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:338
+ msgid "UUID attribute"
+-msgstr ""
++msgstr "UUID 属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:339
+ #: src/config/SSSDConfig/__init__.py.in:381
+@@ -1111,7 +1110,7 @@ msgstr "認可されたサーバーホストを一覧化する属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:355
+ msgid "Attribute listing authorized server rhosts"
+-msgstr ""
++msgstr "認可されたサーバー rhosts を一覧化する属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:356
+ msgid "krbLastPwdChange attribute"
+@@ -1155,19 +1154,19 @@ msgstr "SSH 公開鍵の属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:366
+ msgid "attribute listing allowed authentication types for a user"
+-msgstr ""
++msgstr "ユーザー用に許可された認証タイプを一覧化する属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:367
+ msgid "attribute containing the X509 certificate of the user"
+-msgstr ""
++msgstr "ユーザーの X509 証明書を含む属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:368
+ msgid "attribute containing the email address of the user"
+-msgstr ""
++msgstr "ユーザーの電子メールアドレスを含む属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:370
+ msgid "A list of extra attributes to download along with the user entry"
+-msgstr ""
++msgstr "ユーザーエントリーと共にダウンロードする追加的な属性の一覧"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:372
+ msgid "Base DN for group lookups"
+@@ -1195,7 +1194,7 @@ msgstr "グループメンバー属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:380
+ msgid "Group UUID attribute"
+-msgstr ""
++msgstr "グループ UUID 属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:382
+ msgid "Modification time attribute for groups"
+@@ -1203,15 +1202,15 @@ msgstr "グループの変更日時の属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:383
+ msgid "Type of the group and other flags"
+-msgstr ""
++msgstr "グループおよび他のフラグのタイプ"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:384
+ msgid "The LDAP group external member attribute"
+-msgstr ""
++msgstr "LDAP グループの外部メンバーの属性"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:386
+ msgid "Maximum nesting level SSSD will follow"
+-msgstr ""
++msgstr "SSSD が従う最大ネストレベル"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:388
+ msgid "Base DN for netgroup lookups"
+@@ -1283,419 +1282,407 @@ msgstr "ID マッピングに対するデフォルトドメインの SID"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:408
+ msgid "Number of secondary slices"
+-msgstr ""
++msgstr "セカンダリースライスの数"
+ 
+ #: src/config/SSSDConfig/__init__.py.in:410
+-#, fuzzy
+-msgid "Use LDAP_MATCHING_RULE_IN_CHAIN for group lookups"
+-msgstr "グループ検索のベース DN"
+-
+-#: src/config/SSSDConfig/__init__.py.in:411
+-#, fuzzy
+-msgid "Use LDAP_MATCHING_RULE_IN_CHAIN for initgroup lookups"
+-msgstr "ネットグループ検索のベース DN"
+-
+-#: src/config/SSSDConfig/__init__.py.in:412
+ msgid "Whether to use Token-Groups"
+-msgstr ""
++msgstr "Token-Group を使うかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:413
++#: src/config/SSSDConfig/__init__.py.in:411
+ msgid "Set lower boundary for allowed IDs from the LDAP server"
+ msgstr "LDAP サーバーから許可される ID の下限の設定"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:414
++#: src/config/SSSDConfig/__init__.py.in:412
+ msgid "Set upper boundary for allowed IDs from the LDAP server"
+ msgstr "LDAP サーバーから許可される ID の上限の設定"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:415
++#: src/config/SSSDConfig/__init__.py.in:413
+ msgid "DN for ppolicy queries"
+-msgstr ""
++msgstr "ppolicy クエリーの DN"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:416
++#: src/config/SSSDConfig/__init__.py.in:414
+ msgid "How many maximum entries to fetch during a wildcard request"
+-msgstr ""
++msgstr "ワイルドカードの要求の間に取得する最大エントリーの数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:419
++#: src/config/SSSDConfig/__init__.py.in:417
+ msgid "Policy to evaluate the password expiration"
+ msgstr "パスワード失効の評価のポリシー"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:423
++#: src/config/SSSDConfig/__init__.py.in:421
+ msgid "Which attributes shall be used to evaluate if an account is expired"
+ msgstr "どの属性がアカウントが失効しているかを評価するために使用されるか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:424
++#: src/config/SSSDConfig/__init__.py.in:422
+ msgid "Which rules should be used to evaluate access control"
+ msgstr "どのルールがアクセス制御を評価するために使用されるか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:427
++#: src/config/SSSDConfig/__init__.py.in:425
+ msgid "URI of an LDAP server where password changes are allowed"
+ msgstr "パスワードの変更が許可される LDAP サーバーの URI"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:428
++#: src/config/SSSDConfig/__init__.py.in:426
+ msgid "URI of a backup LDAP server where password changes are allowed"
+ msgstr "パスワードの変更が許可されるバックアップ LDAP サーバーの URI"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:429
++#: src/config/SSSDConfig/__init__.py.in:427
+ msgid "DNS service name for LDAP password change server"
+ msgstr "LDAP パスワードの変更サーバーの DNS サービス名"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:430
++#: src/config/SSSDConfig/__init__.py.in:428
+ msgid ""
+ "Whether to update the ldap_user_shadow_last_change attribute after a "
+ "password change"
+ msgstr "パスワード変更後 ldap_user_shadow_last_change 属性を更新するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:433
++#: src/config/SSSDConfig/__init__.py.in:431
+ msgid "Base DN for sudo rules lookups"
+ msgstr "sudo ルール検索のベース DN"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:434
++#: src/config/SSSDConfig/__init__.py.in:432
+ msgid "Automatic full refresh period"
+ msgstr "自動的な完全更新間隔"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:435
++#: src/config/SSSDConfig/__init__.py.in:433
+ msgid "Automatic smart refresh period"
+ msgstr "自動的なスマート更新間隔"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:436
++#: src/config/SSSDConfig/__init__.py.in:434
+ msgid "Whether to filter rules by hostname, IP addresses and network"
+-msgstr ""
+-"ホスト名、IP アドレスおよびネットワークによるフィルタールールを使用するかどう"
+-"か"
++msgstr "ホスト名、IP アドレスおよびネットワークによるフィルタールールを使用するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:437
++#: src/config/SSSDConfig/__init__.py.in:435
+ msgid ""
+ "Hostnames and/or fully qualified domain names of this machine to filter sudo "
+ "rules"
+-msgstr ""
+-"sudo ルールをフィルターするこのマシンのホスト名および/または完全修飾ドメイン"
+-"名"
++msgstr "sudo ルールをフィルターするこのマシンのホスト名および/または完全修飾ドメイン名"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:438
++#: src/config/SSSDConfig/__init__.py.in:436
+ msgid "IPv4 or IPv6 addresses or network of this machine to filter sudo rules"
+-msgstr ""
+-"sudo ルールをフィルターするこのマシンの IPv4 または IPv6 アドレスまたはネット"
+-"ワーク"
++msgstr "sudo ルールをフィルターするこのマシンの IPv4 または IPv6 アドレスまたはネットワーク"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:439
++#: src/config/SSSDConfig/__init__.py.in:437
+ msgid "Whether to include rules that contains netgroup in host attribute"
+ msgstr "ホスト属性にネットワークグループを含むルールを含めるかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:440
++#: src/config/SSSDConfig/__init__.py.in:438
+ msgid ""
+ "Whether to include rules that contains regular expression in host attribute"
+ msgstr "ホスト属性に正規表現を含むルールを含めるかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:441
++#: src/config/SSSDConfig/__init__.py.in:439
+ msgid "Object class for sudo rules"
+ msgstr "sudo ルールのオブジェクトクラス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:442
++#: src/config/SSSDConfig/__init__.py.in:440
+ msgid "Sudo rule name"
+ msgstr "sudo ルール名"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:443
++#: src/config/SSSDConfig/__init__.py.in:441
+ msgid "Sudo rule command attribute"
+ msgstr "sudo ルールのコマンドの属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:444
++#: src/config/SSSDConfig/__init__.py.in:442
+ msgid "Sudo rule host attribute"
+ msgstr "sudo ルールのホストの属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:445
++#: src/config/SSSDConfig/__init__.py.in:443
+ msgid "Sudo rule user attribute"
+ msgstr "sudo ルールのユーザーの属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:446
++#: src/config/SSSDConfig/__init__.py.in:444
+ msgid "Sudo rule option attribute"
+ msgstr "sudo ルールのオプションの属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:447
++#: src/config/SSSDConfig/__init__.py.in:445
+ msgid "Sudo rule runas attribute"
+-msgstr ""
++msgstr "sudo ルールの runas の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:448
++#: src/config/SSSDConfig/__init__.py.in:446
+ msgid "Sudo rule runasuser attribute"
+ msgstr "sudo ルールの runasuser の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:449
++#: src/config/SSSDConfig/__init__.py.in:447
+ msgid "Sudo rule runasgroup attribute"
+ msgstr "sudo ルールの runasgroup の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:450
++#: src/config/SSSDConfig/__init__.py.in:448
+ msgid "Sudo rule notbefore attribute"
+ msgstr "sudo ルールの notbefore の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:451
++#: src/config/SSSDConfig/__init__.py.in:449
+ msgid "Sudo rule notafter attribute"
+ msgstr "sudo ルールの notafter の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:452
++#: src/config/SSSDConfig/__init__.py.in:450
+ msgid "Sudo rule order attribute"
+ msgstr "sudo ルールの order の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:455
++#: src/config/SSSDConfig/__init__.py.in:453
+ msgid "Object class for automounter maps"
+ msgstr "automounter マップのオブジェクトクラス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:456
++#: src/config/SSSDConfig/__init__.py.in:454
+ msgid "Automounter map name attribute"
+ msgstr "オートマウントのマップ名の属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:457
++#: src/config/SSSDConfig/__init__.py.in:455
+ msgid "Object class for automounter map entries"
+ msgstr "automounter マップエントリーのオブジェクトクラス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:458
++#: src/config/SSSDConfig/__init__.py.in:456
+ msgid "Automounter map entry key attribute"
+ msgstr "automounter マップエントリーのキー属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:459
++#: src/config/SSSDConfig/__init__.py.in:457
+ msgid "Automounter map entry value attribute"
+ msgstr "automounter マップエントリーの値属性"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:460
++#: src/config/SSSDConfig/__init__.py.in:458
+ msgid "Base DN for automounter map lookups"
+ msgstr "automonter のマップ検索のベース DN"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:463
++#: src/config/SSSDConfig/__init__.py.in:461
+ msgid "Comma separated list of allowed users"
+ msgstr "許可ユーザーのカンマ区切り一覧"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:464
++#: src/config/SSSDConfig/__init__.py.in:462
+ msgid "Comma separated list of prohibited users"
+ msgstr "禁止ユーザーのカンマ区切り一覧"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:467
++#: src/config/SSSDConfig/__init__.py.in:465
+ msgid "Default shell, /bin/bash"
+ msgstr "デフォルトのシェル, /bin/bash"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:468
++#: src/config/SSSDConfig/__init__.py.in:466
+ msgid "Base for home directories"
+ msgstr "ホームディレクトリーのベース"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:471
++#: src/config/SSSDConfig/__init__.py.in:469
+ msgid "The number of preforked proxy children."
+-msgstr ""
++msgstr "事前にフォークされた子プロキシの数"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:474
++#: src/config/SSSDConfig/__init__.py.in:472
+ msgid "The name of the NSS library to use"
+ msgstr "使用する NSS ライブラリーの名前"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:475
++#: src/config/SSSDConfig/__init__.py.in:473
+ msgid "Whether to look up canonical group name from cache if possible"
+ msgstr "可能ならばキャッシュから正規化されたグループ名を検索するかどうか"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:478
++#: src/config/SSSDConfig/__init__.py.in:476
+ msgid "PAM stack to use"
+ msgstr "使用する PAM スタック"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:481
++#: src/config/SSSDConfig/__init__.py.in:479
+ msgid "Path of passwd file sources."
+-msgstr ""
++msgstr "passwd ファイルソースへのパス"
+ 
+-#: src/config/SSSDConfig/__init__.py.in:482
++#: src/config/SSSDConfig/__init__.py.in:480
+ msgid "Path of group file sources."
+-msgstr ""
++msgstr "グループファイルソースへのパス"
+ 
+-#: src/monitor/monitor.c:2452
++#: src/monitor/monitor.c:2347
+ msgid "Become a daemon (default)"
+ msgstr "デーモンとして実行(デフォルト)"
+ 
+-#: src/monitor/monitor.c:2454
++#: src/monitor/monitor.c:2349
+ msgid "Run interactive (not a daemon)"
+ msgstr "対話的に実行(デーモンではない)"
+ 
+-#: src/monitor/monitor.c:2457
++#: src/monitor/monitor.c:2352
+ msgid "Disable netlink interface"
+-msgstr ""
++msgstr "netlink インターフェースを無効にする"
+ 
+-#: src/monitor/monitor.c:2459 src/tools/sssctl/sssctl_logs.c:311
++#: src/monitor/monitor.c:2354 src/tools/sssctl/sssctl_logs.c:311
+ msgid "Specify a non-default config file"
+ msgstr "非標準の設定ファイルの指定"
+ 
+-#: src/monitor/monitor.c:2461
++#: src/monitor/monitor.c:2356
+ msgid "Refresh the configuration database, then exit"
+-msgstr ""
++msgstr "設定データベースをリフレッシュし、その後終了します"
+ 
+-#: src/monitor/monitor.c:2464
++#: src/monitor/monitor.c:2359
++msgid "Similar to --genconf, but only refreshes the given section"
++msgstr "--genconf と似ていますが、任意のセクションのみをリフレッシュします"
++
++#: src/monitor/monitor.c:2362
+ msgid "Print version number and exit"
+ msgstr "バージョン番号を表示して終了する"
+ 
+-#: src/monitor/monitor.c:2630
++#: src/monitor/monitor.c:2538
+ msgid "SSSD is already running\n"
+-msgstr ""
++msgstr "SSSD はすでに実行中です\n"
+ 
+-#: src/providers/krb5/krb5_child.c:3216 src/providers/ldap/ldap_child.c:605
++#: src/providers/krb5/krb5_child.c:3219 src/providers/ldap/ldap_child.c:605
+ msgid "Debug level"
+ msgstr "デバッグレベル"
+ 
+-#: src/providers/krb5/krb5_child.c:3218 src/providers/ldap/ldap_child.c:607
++#: src/providers/krb5/krb5_child.c:3221 src/providers/ldap/ldap_child.c:607
+ msgid "Add debug timestamps"
+ msgstr "デバッグのタイムスタンプを追加する"
+ 
+-#: src/providers/krb5/krb5_child.c:3220 src/providers/ldap/ldap_child.c:609
++#: src/providers/krb5/krb5_child.c:3223 src/providers/ldap/ldap_child.c:609
+ msgid "Show timestamps with microseconds"
+ msgstr "タイムスタンプをミリ秒単位で表示する"
+ 
+-#: src/providers/krb5/krb5_child.c:3222 src/providers/ldap/ldap_child.c:611
++#: src/providers/krb5/krb5_child.c:3225 src/providers/ldap/ldap_child.c:611
+ msgid "An open file descriptor for the debug logs"
+ msgstr "デバッグログのオープンファイルディスクリプター"
+ 
+-#: src/providers/krb5/krb5_child.c:3225 src/providers/ldap/ldap_child.c:613
++#: src/providers/krb5/krb5_child.c:3228 src/providers/ldap/ldap_child.c:613
+ msgid "Send the debug output to stderr directly."
+-msgstr ""
++msgstr "デバッグ出力を stderr に直接送信します。"
+ 
+-#: src/providers/krb5/krb5_child.c:3228
++#: src/providers/krb5/krb5_child.c:3231
+ msgid "The user to create FAST ccache as"
+-msgstr ""
++msgstr "次のように FAST ccache を作成するユーザー"
+ 
+-#: src/providers/krb5/krb5_child.c:3230
++#: src/providers/krb5/krb5_child.c:3233
+ msgid "The group to create FAST ccache as"
+-msgstr ""
++msgstr "次のように FAST ccache を作成するグループ"
+ 
+-#: src/providers/krb5/krb5_child.c:3232
++#: src/providers/krb5/krb5_child.c:3235
+ msgid "Kerberos realm to use"
+-msgstr ""
++msgstr "使用する Kerberos レルム"
+ 
+-#: src/providers/krb5/krb5_child.c:3234
++#: src/providers/krb5/krb5_child.c:3237
+ msgid "Requested lifetime of the ticket"
+-msgstr ""
++msgstr "チケットの要求された有効期間"
+ 
+-#: src/providers/krb5/krb5_child.c:3236
++#: src/providers/krb5/krb5_child.c:3239
+ msgid "Requested renewable lifetime of the ticket"
+-msgstr ""
++msgstr "チケットの要求された更新可能な有効期間"
+ 
+-#: src/providers/krb5/krb5_child.c:3238
++#: src/providers/krb5/krb5_child.c:3241
+ msgid "FAST options ('never', 'try', 'demand')"
+-msgstr ""
++msgstr "FAST のオプション ('never'、'try'、'demand')"
+ 
+-#: src/providers/krb5/krb5_child.c:3241
++#: src/providers/krb5/krb5_child.c:3244
+ msgid "Specifies the server principal to use for FAST"
+-msgstr ""
++msgstr "FAST で使用するサーバープリンシパルを指定します"
+ 
+-#: src/providers/krb5/krb5_child.c:3243
++#: src/providers/krb5/krb5_child.c:3246
+ msgid "Requests canonicalization of the principal name"
+-msgstr ""
++msgstr "プリンシパル名の正規化を要求します"
+ 
+-#: src/providers/krb5/krb5_child.c:3245
++#: src/providers/krb5/krb5_child.c:3248
+ msgid "Use custom version of krb5_get_init_creds_password"
+-msgstr ""
++msgstr "krb5_get_init_creds_password のカスタムバージョンを使用します"
+ 
+-#: src/providers/data_provider_be.c:556
++#: src/providers/data_provider_be.c:630
+ msgid "Domain of the information provider (mandatory)"
+ msgstr "情報プロバイダーのドメイン (必須)"
+ 
+-#: src/sss_client/common.c:1066
++#: src/sss_client/common.c:1067
+ msgid "Privileged socket has wrong ownership or permissions."
+ msgstr "特権ソケットの所有者またはパーミッションが誤っています。"
+ 
+-#: src/sss_client/common.c:1069
++#: src/sss_client/common.c:1070
+ msgid "Public socket has wrong ownership or permissions."
+ msgstr "公開ソケットの所有者またはパーミッションが誤っています。"
+ 
+-#: src/sss_client/common.c:1072
++#: src/sss_client/common.c:1073
+ msgid "Unexpected format of the server credential message."
+ msgstr "サーバーのクレディンシャルメッセージの予期しない形式です。"
+ 
+-#: src/sss_client/common.c:1075
++#: src/sss_client/common.c:1076
+ msgid "SSSD is not run by root."
+ msgstr "SSSD は root により実行されません。"
+ 
+-#: src/sss_client/common.c:1080
++#: src/sss_client/common.c:1081
+ msgid "An error occurred, but no description can be found."
+ msgstr "エラーが発生しましたが、説明がありませんでした。"
+ 
+-#: src/sss_client/common.c:1086
++#: src/sss_client/common.c:1087
+ msgid "Unexpected error while looking for an error description"
+ msgstr "エラーの説明を検索中に予期しないエラーが発生しました"
+ 
+-#: src/sss_client/pam_sss.c:76
++#: src/sss_client/pam_sss.c:67
+ msgid "Permission denied. "
+-msgstr ""
++msgstr "パーミッションが拒否されました。"
+ 
+-#: src/sss_client/pam_sss.c:77 src/sss_client/pam_sss.c:782
+-#: src/sss_client/pam_sss.c:793
++#: src/sss_client/pam_sss.c:68 src/sss_client/pam_sss.c:774
++#: src/sss_client/pam_sss.c:785
+ msgid "Server message: "
+ msgstr "サーバーのメッセージ: "
+ 
+-#: src/sss_client/pam_sss.c:300
++#: src/sss_client/pam_sss.c:292
+ msgid "Passwords do not match"
+ msgstr "パスワードが一致しません"
+ 
+-#: src/sss_client/pam_sss.c:488
++#: src/sss_client/pam_sss.c:480
+ msgid "Password reset by root is not supported."
+ msgstr "root によるパスワードのリセットはサポートされません。"
+ 
+-#: src/sss_client/pam_sss.c:529
++#: src/sss_client/pam_sss.c:521
+ msgid "Authenticated with cached credentials"
+ msgstr "キャッシュされているクレディンシャルを用いて認証されました"
+ 
+-#: src/sss_client/pam_sss.c:530
++#: src/sss_client/pam_sss.c:522
+ msgid ", your cached password will expire at: "
+ msgstr "、キャッシュされたパスワードが失効します: "
+ 
+-#: src/sss_client/pam_sss.c:560
++#: src/sss_client/pam_sss.c:552
+ #, c-format
+ msgid "Your password has expired. You have %1$d grace login(s) remaining."
+ msgstr "パスワードの期限が切れています。あと %1$d 回ログインできます。"
+ 
+-#: src/sss_client/pam_sss.c:606
++#: src/sss_client/pam_sss.c:598
+ #, c-format
+ msgid "Your password will expire in %1$d %2$s."
+ msgstr "あなたのパスワードは %1$d %2$s に期限切れになります。"
+ 
+-#: src/sss_client/pam_sss.c:655
++#: src/sss_client/pam_sss.c:647
+ msgid "Authentication is denied until: "
+ msgstr "次まで認証が拒否されます: "
+ 
+-#: src/sss_client/pam_sss.c:676
++#: src/sss_client/pam_sss.c:668
+ msgid "System is offline, password change not possible"
+ msgstr "システムがオフラインです、パスワード変更ができません"
+ 
+-#: src/sss_client/pam_sss.c:691
++#: src/sss_client/pam_sss.c:683
+ msgid ""
+ "After changing the OTP password, you need to log out and back in order to "
+ "acquire a ticket"
+-msgstr ""
++msgstr "OTP パスワードの変更後、チケットを取得するためにログアウト後に再びログインする必要があります"
+ 
+-#: src/sss_client/pam_sss.c:779 src/sss_client/pam_sss.c:792
++#: src/sss_client/pam_sss.c:771 src/sss_client/pam_sss.c:784
+ msgid "Password change failed. "
+ msgstr "パスワードの変更に失敗しました。 "
+ 
+-#: src/sss_client/pam_sss.c:1926
++#: src/sss_client/pam_sss.c:1921
+ msgid "New Password: "
+ msgstr "新しいパスワード: "
+ 
+-#: src/sss_client/pam_sss.c:1927
++#: src/sss_client/pam_sss.c:1922
+ msgid "Reenter new Password: "
+ msgstr "新しいパスワードの再入力: "
+ 
+-#: src/sss_client/pam_sss.c:2039 src/sss_client/pam_sss.c:2042
++#: src/sss_client/pam_sss.c:2038 src/sss_client/pam_sss.c:2041
+ msgid "First Factor: "
+-msgstr ""
++msgstr "1 番目の要素: "
+ 
+-#: src/sss_client/pam_sss.c:2040 src/sss_client/pam_sss.c:2202
++#: src/sss_client/pam_sss.c:2039 src/sss_client/pam_sss.c:2201
+ msgid "Second Factor (optional): "
+-msgstr ""
++msgstr "2 番目の要素 (オプション): "
+ 
+-#: src/sss_client/pam_sss.c:2043 src/sss_client/pam_sss.c:2205
++#: src/sss_client/pam_sss.c:2042 src/sss_client/pam_sss.c:2204
+ msgid "Second Factor: "
+-msgstr ""
++msgstr "2 番目の要素:  "
+ 
+-#: src/sss_client/pam_sss.c:2058
++#: src/sss_client/pam_sss.c:2057
+ msgid "Password: "
+ msgstr "パスワード: "
+ 
+-#: src/sss_client/pam_sss.c:2201 src/sss_client/pam_sss.c:2204
++#: src/sss_client/pam_sss.c:2200 src/sss_client/pam_sss.c:2203
+ msgid "First Factor (Current Password): "
+-msgstr ""
++msgstr "1 番目の要素 (現在のパスワード): "
+ 
+-#: src/sss_client/pam_sss.c:2208
++#: src/sss_client/pam_sss.c:2207
+ msgid "Current Password: "
+ msgstr "現在のパスワード: "
+ 
+-#: src/sss_client/pam_sss.c:2536
++#: src/sss_client/pam_sss.c:2562
+ msgid "Password expired. Change your password now."
+ msgstr "パスワードの期限が切れました。いますぐパスワードを変更してください。"
+ 
+@@ -1739,7 +1726,7 @@ msgstr "ホストへの接続に使用するポート"
+ 
+ #: src/sss_client/ssh/sss_ssh_knownhostsproxy.c:210
+ msgid "Print the host ssh public keys"
+-msgstr ""
++msgstr "ホスト SSH 公開鍵を印刷"
+ 
+ #: src/sss_client/ssh/sss_ssh_knownhostsproxy.c:252
+ msgid "Invalid port\n"
+@@ -1751,7 +1738,7 @@ msgstr "ホストが指定されていません\n"
+ 
+ #: src/sss_client/ssh/sss_ssh_knownhostsproxy.c:263
+ msgid "The path to the proxy command must be absolute\n"
+-msgstr "プロキシーコマンドへのパスは絶対パスにする必要があります\n"
++msgstr "プロキシコマンドへのパスは絶対パスにする必要があります\n"
+ 
+ #: src/tools/sss_useradd.c:49 src/tools/sss_usermod.c:48
+ msgid "The UID of the user"
+@@ -1803,8 +1790,7 @@ msgstr "追加するユーザーを指定してください\n"
+ #: src/tools/sss_groupshow.c:714 src/tools/sss_userdel.c:198
+ #: src/tools/sss_usermod.c:162
+ msgid "Error initializing the tools - no local domain\n"
+-msgstr ""
+-"ツールを初期化中にエラーが発生しました - ローカルドメインがありません\n"
++msgstr "ツールを初期化中にエラーが発生しました - ローカルドメインがありません\n"
+ 
+ #: src/tools/sss_useradd.c:123 src/tools/sss_groupadd.c:88
+ #: src/tools/sss_groupdel.c:82 src/tools/sss_groupmod.c:115
+@@ -1854,9 +1840,7 @@ msgstr "ユーザーに関する情報を取得できません\n"
+ 
+ #: src/tools/sss_useradd.c:236
+ msgid "User's home directory already exists, not copying data from skeldir\n"
+-msgstr ""
+-"ユーザーのホームディレクトリーがすでに存在します、スケルトンディレクトリーか"
+-"らデータをコピーしません\n"
++msgstr "ユーザーのホームディレクトリーがすでに存在します、スケルトンディレクトリーからデータをコピーしません\n"
+ 
+ #: src/tools/sss_useradd.c:239
+ #, c-format
+@@ -1919,16 +1903,13 @@ msgstr "グループ %1$s はドメインに対して定義された ID の範
+ #: src/tools/sss_usermod.c:289 src/tools/sss_usermod.c:296
+ #, c-format
+ msgid "NSS request failed (%1$d). Entry might remain in memory cache.\n"
+-msgstr ""
+-"NSS リクエストに失敗しました (%1$d)。項目はメモリーキャッシュに残されます。\n"
++msgstr "NSS リクエストに失敗しました (%1$d)。項目はメモリーキャッシュに残されます。\n"
+ 
+ #: src/tools/sss_groupdel.c:132
+ msgid ""
+-"No such group in local domain. Removing groups only allowed in local "
+-"domain.\n"
+-msgstr ""
+-"そのようなグループはローカルドメインにありません。グループの削除はローカルド"
+-"メインにおいてのみ許可されます。\n"
++"No such group in local domain. Removing groups only allowed in local domain."
++"\n"
++msgstr "そのようなグループはローカルドメインにありません。グループの削除はローカルドメインにおいてのみ許可されます。\n"
+ 
+ #: src/tools/sss_groupdel.c:137
+ msgid "Internal error. Could not remove group.\n"
+@@ -1954,9 +1935,7 @@ msgstr "変更するグループを指定してください\n"
+ msgid ""
+ "Cannot find group in local domain, modifying groups is allowed only in local "
+ "domain\n"
+-msgstr ""
+-"ローカルドメインにグループが見つかりませんでした。グループの変更はローカルド"
+-"メインにおいてのみ許可されます\n"
++msgstr "ローカルドメインにグループが見つかりませんでした。グループの変更はローカルドメインにおいてのみ許可されます\n"
+ 
+ #: src/tools/sss_groupmod.c:153 src/tools/sss_groupmod.c:182
+ msgid "Member groups must be in the same domain as parent group\n"
+@@ -1968,20 +1947,15 @@ msgstr "メンバーグループが親グループと同じドメインにある
+ msgid ""
+ "Cannot find group %1$s in local domain, only groups in local domain are "
+ "allowed\n"
+-msgstr ""
+-"ローカルドメインにグループ %1$s が見つかりません。ローカルドメインにあるグ"
+-"ループのみが許可されます\n"
++msgstr "ローカルドメインにグループ %1$s が見つかりません。ローカルドメインにあるグループのみが許可されます\n"
+ 
+ #: src/tools/sss_groupmod.c:257
+ msgid "Could not modify group - check if member group names are correct\n"
+-msgstr ""
+-"グループを変更できませんでした - メンバーグループ名が正しいかを確認してくださ"
+-"い\n"
++msgstr "グループを変更できませんでした - メンバーグループ名が正しいかを確認してください\n"
+ 
+ #: src/tools/sss_groupmod.c:261
+ msgid "Could not modify group - check if groupname is correct\n"
+-msgstr ""
+-"グループを変更できませんでした - グループ名が正しいかを確認してください\n"
++msgstr "グループを変更できませんでした - グループ名が正しいかを確認してください\n"
+ 
+ #: src/tools/sss_groupmod.c:265
+ msgid "Transaction error. Could not modify group.\n"
+@@ -2008,20 +1982,16 @@ msgstr "%1$s メンバーユーザー: "
+ 
+ #: src/tools/sss_groupshow.c:627
+ #, c-format
+-msgid ""
+-"\n"
++msgid "\n"
+ "%1$sIs a member of: "
+-msgstr ""
+-"\n"
++msgstr "\n"
+ "%1$s は次のメンバー: "
+ 
+ #: src/tools/sss_groupshow.c:634
+ #, c-format
+-msgid ""
+-"\n"
++msgid "\n"
+ "%1$sMember groups: "
+-msgstr ""
+-"\n"
++msgstr "\n"
+ "%1$s メンバーグループ: "
+ 
+ #: src/tools/sss_groupshow.c:670
+@@ -2034,11 +2004,9 @@ msgstr "表示するグループを指定してください\n"
+ 
+ #: src/tools/sss_groupshow.c:744
+ msgid ""
+-"No such group in local domain. Printing groups only allowed in local "
+-"domain.\n"
+-msgstr ""
+-"そのようなグループはローカルドメインにありません。グループの表示はローカルド"
+-"メインにおいてのみ許可されます。\n"
++"No such group in local domain. Printing groups only allowed in local domain."
++"\n"
++msgstr "そのようなグループはローカルドメインにありません。グループの表示はローカルドメインにおいてのみ許可されます。\n"
+ 
+ #: src/tools/sss_groupshow.c:749
+ msgid "Internal error. Could not print group.\n"
+@@ -2076,13 +2044,11 @@ msgstr "SELinux ログインコンテキストをリセットできません\n"
+ #: src/tools/sss_userdel.c:271
+ #, c-format
+ msgid "WARNING: The user (uid %1$lu) was still logged in when deleted.\n"
+-msgstr ""
+-"警告: ユーザー (uid %1$lu) が削除されたときにまだログインしていました。\n"
++msgstr "警告: ユーザー (uid %1$lu) が削除されたときにまだログインしていました。\n"
+ 
+ #: src/tools/sss_userdel.c:276
+ msgid "Cannot determine if the user was logged in on this platform"
+-msgstr ""
+-"ユーザーがこのプラットフォームにログインしていたかを確認できませんでした"
++msgstr "ユーザーがこのプラットフォームにログインしていたかを確認できませんでした"
+ 
+ #: src/tools/sss_userdel.c:281
+ msgid "Error while checking if the user was logged in\n"
+@@ -2095,8 +2061,7 @@ msgstr "削除後コマンドの実行に失敗しました: %1$s\n"
+ 
+ #: src/tools/sss_userdel.c:308
+ msgid "Not removing home dir - not owned by user\n"
+-msgstr ""
+-"ホームディレクトリーを削除していません - ユーザーにより所有されていません\n"
++msgstr "ホームディレクトリーを削除していません - ユーザーにより所有されていません\n"
+ 
+ #: src/tools/sss_userdel.c:310
+ #, c-format
+@@ -2106,9 +2071,7 @@ msgstr "ホームディレクトリーを削除できません: %1$s\n"
+ #: src/tools/sss_userdel.c:324
+ msgid ""
+ "No such user in local domain. Removing users only allowed in local domain.\n"
+-msgstr ""
+-"そのようなユーザーはローカルドメインにいません。ユーザーの削除はローカルドメ"
+-"インにおいてのみ許可されます。\n"
++msgstr "そのようなユーザーはローカルドメインにいません。ユーザーの削除はローカルドメインにおいてのみ許可されます。\n"
+ 
+ #: src/tools/sss_userdel.c:329
+ msgid "Internal error. Could not remove user.\n"
+@@ -2136,22 +2099,23 @@ msgstr "アカウントをロック解除する"
+ 
+ #: src/tools/sss_usermod.c:57
+ msgid "Add an attribute/value pair. The format is attrname=value."
+-msgstr ""
++msgstr "属性/値のペアを追加します。フォーマットは attrname=value です。"
+ 
+ #: src/tools/sss_usermod.c:58
+ msgid "Delete an attribute/value pair. The format is attrname=value."
+-msgstr ""
++msgstr "属性/値のペアを削除します。フォーマットは attrname=value です。"
+ 
+ #: src/tools/sss_usermod.c:59
+ msgid ""
+ "Set an attribute to a name/value pair. The format is attrname=value. For "
+ "multi-valued attributes, the command replaces the values already present"
+ msgstr ""
++"名前/値のペアに属性を指定します。形式は attrname=value です。複数の値を持つ属性の場合、コマンドがすでに存在する値に置き換えられます。"
+ 
+ #: src/tools/sss_usermod.c:117 src/tools/sss_usermod.c:126
+ #: src/tools/sss_usermod.c:135
+ msgid "Specify the attribute name/value pair(s)\n"
+-msgstr ""
++msgstr "属性の名前/値のペアを指定します"
+ 
+ #: src/tools/sss_usermod.c:152
+ msgid "Specify user to modify\n"
+@@ -2161,19 +2125,15 @@ msgstr "変更するユーザーを指定してください\n"
+ msgid ""
+ "Cannot find user in local domain, modifying users is allowed only in local "
+ "domain\n"
+-msgstr ""
+-"ローカルドメインにユーザーを見つけられません。ユーザーの変更はローカルドメイ"
+-"ンにおいてのみ許可されます。\n"
++msgstr "ローカルドメインにユーザーを見つけられません。ユーザーの変更はローカルドメインにおいてのみ許可されます。\n"
+ 
+ #: src/tools/sss_usermod.c:322
+ msgid "Could not modify user - check if group names are correct\n"
+-msgstr ""
+-"ユーザーを変更できませんでした - グループ名が正しいかを確認してください\n"
++msgstr "ユーザーを変更できませんでした - グループ名が正しいかを確認してください\n"
+ 
+ #: src/tools/sss_usermod.c:326
+ msgid "Could not modify user - user already member of groups?\n"
+-msgstr ""
+-"ユーザーを変更できませんでした - ユーザーはすでにグループのメンバーですか?\n"
++msgstr "ユーザーを変更できませんでした - ユーザーはすでにグループのメンバーですか?\n"
+ 
+ #: src/tools/sss_usermod.c:330
+ msgid "Transaction error. Could not modify user.\n"
+@@ -2186,16 +2146,16 @@ msgstr "指定された検索に一致するキャッシュオブジェクトが
+ #: src/tools/sss_cache.c:519
+ #, c-format
+ msgid "Couldn't invalidate %1$s\n"
+-msgstr ""
++msgstr "%1$s を無効化できませんでした"
+ 
+ #: src/tools/sss_cache.c:526
+ #, c-format
+ msgid "Couldn't invalidate %1$s %2$s\n"
+-msgstr ""
++msgstr "%1$s %2$s を無効化できませんでした"
+ 
+ #: src/tools/sss_cache.c:689
+ msgid "Invalidate all cached entries"
+-msgstr ""
++msgstr "すべてのキャッシュエントリーを無効化します"
+ 
+ #: src/tools/sss_cache.c:691
+ msgid "Invalidate particular user"
+@@ -2239,19 +2199,19 @@ msgstr "すべての autofs マップの無効化"
+ 
+ #: src/tools/sss_cache.c:714
+ msgid "Invalidate particular SSH host"
+-msgstr ""
++msgstr "特定の SSH ホストを無効化します"
+ 
+ #: src/tools/sss_cache.c:716
+ msgid "Invalidate all SSH hosts"
+-msgstr ""
++msgstr "すべての SSH ホストを無効化します"
+ 
+ #: src/tools/sss_cache.c:720
+ msgid "Invalidate particular sudo rule"
+-msgstr ""
++msgstr "特定の sudo ルールを無効化します"
+ 
+ #: src/tools/sss_cache.c:722
+ msgid "Invalidate all cached sudo rules"
+-msgstr ""
++msgstr "すべてのキャッシュ sudo ルールを無効化します"
+ 
+ #: src/tools/sss_cache.c:725
+ msgid "Only invalidate entries from a particular domain"
+@@ -2261,7 +2221,7 @@ msgstr "特定のドメインのみからエントリーを無効にする"
+ msgid ""
+ "Unexpected argument(s) provided, options that invalidate a single object "
+ "only accept a single provided argument.\n"
+-msgstr ""
++msgstr "予期しない引数が提供される場合、1 つのオブジェクトを無効化するオプションは、提供された引数を 1 つだけ受け取ります。\n"
+ 
+ #: src/tools/sss_cache.c:789
+ msgid "Please select at least one object to invalidate\n"
+@@ -2273,8 +2233,8 @@ msgid ""
+ "Could not open domain %1$s. If the domain is a subdomain (trusted domain), "
+ "use fully qualified name instead of --domain/-d parameter.\n"
+ msgstr ""
+-"ドメイン %1$s を開けませんでした。ドメインがサブドメイン (信頼済みドメイン) "
+-"であれば、--domain/-d パラメーターの代わりに完全修飾名を使用してください。\n"
++"ドメイン %1$s を開けませんでした。ドメインがサブドメイン (信頼済みドメイン) であれば、--domain/-d "
++"パラメーターの代わりに完全修飾名を使用してください。\n"
+ 
+ #: src/tools/sss_cache.c:877
+ msgid "Could not open available domains\n"
+@@ -2283,8 +2243,7 @@ msgstr "利用可能なドメインを開けませんでした\n"
+ #: src/tools/tools_util.c:202
+ #, c-format
+ msgid "Name '%1$s' does not seem to be FQDN ('%2$s = TRUE' is set)\n"
+-msgstr ""
+-"名前 '%1$s' が FQDN であるように見えません ('%2$s = TRUE' が設定されます)\n"
++msgstr "名前 '%1$s' が FQDN であるように見えません ('%2$s = TRUE' が設定されます)\n"
+ 
+ #: src/tools/tools_util.c:309
+ msgid "Out of memory\n"
+@@ -2297,279 +2256,285 @@ msgstr "%1$s は root として実行する必要があります\n"
+ 
+ #: src/tools/sssctl/sssctl.c:35
+ msgid "yes"
+-msgstr ""
++msgstr "はい"
+ 
+ #: src/tools/sssctl/sssctl.c:37
+ msgid "no"
+-msgstr ""
++msgstr "いいえ"
+ 
+ #: src/tools/sssctl/sssctl.c:39
+ msgid "error"
+-msgstr ""
++msgstr "エラー"
+ 
+ #: src/tools/sssctl/sssctl.c:42
+ msgid "Invalid result."
+-msgstr ""
++msgstr "無効な結果。"
+ 
+ #: src/tools/sssctl/sssctl.c:78
+ #, c-format
+ msgid "Unable to read user input\n"
+-msgstr ""
++msgstr "ユーザーインプットの読み込みができませんでした\n"
+ 
+ #: src/tools/sssctl/sssctl.c:91
+ #, c-format
+ msgid "Invalid input, please provide either '%s' or '%s'.\n"
+-msgstr ""
++msgstr "無効なインプットです。'%s' または '%s' のいずれかを提供してください。\n"
+ 
+ #: src/tools/sssctl/sssctl.c:109 src/tools/sssctl/sssctl.c:114
+ #, c-format
+ msgid "Error while executing external command\n"
+-msgstr ""
++msgstr "外部のコマンドを実行中にエラーが発生しました\n"
+ 
+ #: src/tools/sssctl/sssctl.c:156
+ msgid "SSSD needs to be running. Start SSSD now?"
+-msgstr ""
++msgstr "SSSD を実行する必要があります。SSSD をすぐに実行しますか?"
+ 
+ #: src/tools/sssctl/sssctl.c:195
+ msgid "SSSD must not be running. Stop SSSD now?"
+-msgstr ""
++msgstr "SSSD を実行してはいけません。SSSD を今、停止しますか?"
+ 
+ #: src/tools/sssctl/sssctl.c:231
+ msgid "SSSD needs to be restarted. Restart SSSD now?"
+-msgstr ""
++msgstr "SSSD は再起動が必要です。SSSD を今、再起動しますか?"
+ 
+ #: src/tools/sssctl/sssctl_cache.c:31
+ #, c-format
+ msgid " %s is not present in cache.\n"
+-msgstr ""
++msgstr " %s はキャッシュにありません\n"
+ 
+ #: src/tools/sssctl/sssctl_cache.c:33
+ msgid "Name"
+-msgstr ""
++msgstr "名前"
+ 
+ #: src/tools/sssctl/sssctl_cache.c:34
+ msgid "Cache entry creation date"
+-msgstr ""
++msgstr "キャッシュエントリーの作成日"
+ 
+ #: src/tools/sssctl/sssctl_cache.c:35
+ msgid "Cache entry last update time"
+-msgstr ""
++msgstr "キャッシュエントリーが最後に更新された時間"
+ 
+ #: src/tools/sssctl/sssctl_cache.c:36
+ msgid "Cache entry expiration time"
+-msgstr ""
++msgstr "キャッシュエントリーの期限切れ時間"
+ 
+ #: src/tools/sssctl/sssctl_cache.c:37
+ msgid "Cached in InfoPipe"
+-msgstr ""
++msgstr "InfoPipe にキャッシュ"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:512
++#: src/tools/sssctl/sssctl_cache.c:522
+ #, c-format
+ msgid "Error: Unable to get object [%d]: %s\n"
+-msgstr ""
++msgstr "エラー: オブジェクト [%d] を取得できません: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:528
++#: src/tools/sssctl/sssctl_cache.c:538
+ #, c-format
+ msgid "%s: Unable to read value [%d]: %s\n"
+-msgstr ""
++msgstr "%s: 値 [%d] の読み込みができません: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:556
++#: src/tools/sssctl/sssctl_cache.c:566
+ msgid "Specify name."
+-msgstr ""
++msgstr "名前を指定します。"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:566
++#: src/tools/sssctl/sssctl_cache.c:576
+ #, c-format
+ msgid "Unable to parse name %s.\n"
+-msgstr ""
++msgstr "名前 %s を構文解析できません。\n"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:592 src/tools/sssctl/sssctl_cache.c:639
++#: src/tools/sssctl/sssctl_cache.c:602 src/tools/sssctl/sssctl_cache.c:649
+ msgid "Search by SID"
+-msgstr ""
++msgstr "SID で検索"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:593
++#: src/tools/sssctl/sssctl_cache.c:603
+ msgid "Search by user ID"
+-msgstr ""
++msgstr "ユーザーID で検索"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:602
++#: src/tools/sssctl/sssctl_cache.c:612
+ msgid "Initgroups expiration time"
+-msgstr ""
++msgstr "Initgroups の期限切れ時間"
+ 
+-#: src/tools/sssctl/sssctl_cache.c:640
++#: src/tools/sssctl/sssctl_cache.c:650
+ msgid "Search by group ID"
+-msgstr ""
++msgstr "グループ ID で検索"
+ 
+ #: src/tools/sssctl/sssctl_config.c:67
+ #, c-format
+ msgid ""
+ "File %1$s does not exist. SSSD will use default configuration with files "
+ "provider.\n"
+-msgstr ""
++msgstr "ファイル %1$s は存在しません。SSSD は、ファイルプロバイダーでデフォルトの設定を使用します。\n"
+ 
+ #: src/tools/sssctl/sssctl_config.c:81
+ #, c-format
+ msgid ""
+ "File ownership and permissions check failed. Expected root:root and 0600.\n"
+-msgstr ""
++msgstr "ファイルの所有権とパーミッションの確認に失敗しました。予期される root:root および 0600。\n"
+ 
+ #: src/tools/sssctl/sssctl_config.c:104
+ #, c-format
+ msgid "Issues identified by validators: %zu\n"
+-msgstr ""
++msgstr "バリデーターで特定された問題: %zu\n"
+ 
+ #: src/tools/sssctl/sssctl_config.c:114
+ #, c-format
+ msgid "Messages generated during configuration merging: %zu\n"
+-msgstr ""
++msgstr "設定のマージ中に生成されたメッセージ: %zu\n"
+ 
+ #: src/tools/sssctl/sssctl_config.c:127
+ #, c-format
+ msgid "Used configuration snippet files: %u\n"
+-msgstr ""
++msgstr "設定スニペットファイルを使用: %u\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:89
+ #, c-format
+ msgid "Unable to create backup directory [%d]: %s"
+-msgstr ""
++msgstr "バックアップディレクトリー [%d] の作成に失敗: %s"
+ 
+ #: src/tools/sssctl/sssctl_data.c:95
+ msgid "SSSD backup of local data already exists, override?"
+-msgstr ""
++msgstr "ローカルデータの SSSD バックアップはすでに存在しますが、上書きしますか?"
+ 
+ #: src/tools/sssctl/sssctl_data.c:111
+ #, c-format
+ msgid "Unable to export user overrides\n"
+-msgstr ""
++msgstr "ユーザーの上書きをエクスポートできません\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:118
+ #, c-format
+ msgid "Unable to export group overrides\n"
+-msgstr ""
++msgstr "グループの上書きをエクスポートできません\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:134 src/tools/sssctl/sssctl_data.c:217
+ msgid "Override existing backup"
+-msgstr ""
++msgstr "既存のバックアップを上書き"
+ 
+ #: src/tools/sssctl/sssctl_data.c:164
+ #, c-format
+ msgid "Unable to import user overrides\n"
+-msgstr ""
++msgstr "ユーザーの上書きをインポートできません\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:173
+ #, c-format
+ msgid "Unable to import group overrides\n"
+-msgstr ""
++msgstr "グループの上書きをインポートできません\n"
+ 
+-#: src/tools/sssctl/sssctl_data.c:194 src/tools/sssctl/sssctl_domains.c:74
+-#: src/tools/sssctl/sssctl_domains.c:339
++#: src/tools/sssctl/sssctl_data.c:194 src/tools/sssctl/sssctl_domains.c:82
++#: src/tools/sssctl/sssctl_domains.c:315
+ msgid "Start SSSD if it is not running"
+-msgstr ""
++msgstr "実行中でない場合、SSSD を開始します"
+ 
+ #: src/tools/sssctl/sssctl_data.c:195
+ msgid "Restart SSSD after data import"
+-msgstr ""
++msgstr "データのインポートの後、SSSD を再起動します"
+ 
+ #: src/tools/sssctl/sssctl_data.c:218
+ msgid "Create clean cache files and import local data"
+-msgstr ""
++msgstr "クリーンなキャッシュファイルを作成し、ローカルデータをインポートします"
+ 
+ #: src/tools/sssctl/sssctl_data.c:219
+ msgid "Stop SSSD before removing the cache"
+-msgstr ""
++msgstr "キャッシュを削除する前に SSSD を停止します"
+ 
+ #: src/tools/sssctl/sssctl_data.c:220
+ msgid "Start SSSD when the cache is removed"
+-msgstr ""
++msgstr "キャッシュの削除後に SSSD を開始します"
+ 
+ #: src/tools/sssctl/sssctl_data.c:235
+ #, c-format
+ msgid "Creating backup of local data...\n"
+-msgstr ""
++msgstr "ローカルデータのバックアップを作成中...\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:238
+ #, c-format
+ msgid "Unable to create backup of local data, can not remove the cache.\n"
+-msgstr ""
++msgstr "ローカルデータのバックアップの作成ができません。キャッシュを削除できません。\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:243
+ #, c-format
+ msgid "Removing cache files...\n"
+-msgstr ""
++msgstr "キャッシュファイルの削除中...\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:246
+ #, c-format
+ msgid "Unable to remove cache files\n"
+-msgstr ""
++msgstr "キャッシュファイルを削除できません\n"
+ 
+ #: src/tools/sssctl/sssctl_data.c:251
+ #, c-format
+ msgid "Restoring local data...\n"
+-msgstr ""
++msgstr "ローカルデータの復元中...\n"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:75
++#: src/tools/sssctl/sssctl_domains.c:83
+ msgid "Show domain list including primary or trusted domain type"
+-msgstr ""
++msgstr "プライマリーまたは信頼されたドメインタイプを含むドメインリストを表示します"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:156
++#: src/tools/sssctl/sssctl_domains.c:105 src/tools/sssctl/sssctl_domains.c:354
++#: src/tools/sssctl/sssctl_user_checks.c:95
++#, c-format
++msgid "Unable to connect to system bus!\n"
++msgstr "システムバスに接続できません!\n"
++
++#: src/tools/sssctl/sssctl_domains.c:167
+ #, c-format
+ msgid "Online status: %s\n"
+-msgstr ""
++msgstr "オンライン状態: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:156
++#: src/tools/sssctl/sssctl_domains.c:167
+ msgid "Online"
+-msgstr ""
++msgstr "オンライン"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:156
++#: src/tools/sssctl/sssctl_domains.c:167
+ msgid "Offline"
+-msgstr ""
++msgstr "オフライン"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:214
++#: src/tools/sssctl/sssctl_domains.c:212
+ #, c-format
+ msgid "Active servers:\n"
+-msgstr ""
++msgstr "アクティブサーバー:\n"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:231
++#: src/tools/sssctl/sssctl_domains.c:223
+ msgid "not connected"
+-msgstr ""
++msgstr "接続していません"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:278
++#: src/tools/sssctl/sssctl_domains.c:260
+ #, c-format
+ msgid "Discovered %s servers:\n"
+-msgstr ""
++msgstr "%s サーバーを発見:\n"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:296
++#: src/tools/sssctl/sssctl_domains.c:272
+ msgid "None so far.\n"
+-msgstr ""
++msgstr "今のところありません。\n"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:336
++#: src/tools/sssctl/sssctl_domains.c:312
+ msgid "Show online status"
+-msgstr ""
++msgstr "オンライン状態を表示"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:337
++#: src/tools/sssctl/sssctl_domains.c:313
+ msgid "Show information about active server"
+-msgstr ""
++msgstr "アクティブサーバーに関する情報の表示"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:338
++#: src/tools/sssctl/sssctl_domains.c:314
+ msgid "Show list of discovered servers"
+-msgstr ""
++msgstr "発見されたサーバーに関する一覧を表示"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:344
++#: src/tools/sssctl/sssctl_domains.c:320
+ msgid "Specify domain name."
+-msgstr ""
++msgstr "ドメイン名を指定します。"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:360
++#: src/tools/sssctl/sssctl_domains.c:342
+ #, c-format
+ msgid "Out of memory!\n"
+-msgstr ""
++msgstr "メモリの空き容量がありません。\n"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:377 src/tools/sssctl/sssctl_domains.c:387
++#: src/tools/sssctl/sssctl_domains.c:362 src/tools/sssctl/sssctl_domains.c:372
+ #, c-format
+ msgid "Unable to get online status\n"
+-msgstr ""
++msgstr "オンライン状態を取得できません\n"
+ 
+-#: src/tools/sssctl/sssctl_domains.c:397
++#: src/tools/sssctl/sssctl_domains.c:382
+ #, c-format
+ msgid "Unable to get server list\n"
+-msgstr ""
++msgstr "サーバー一覧を取得できません\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:47
+ msgid "\n"
+@@ -2577,282 +2542,261 @@ msgstr "\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:237
+ msgid "Delete log files instead of truncating"
+-msgstr ""
++msgstr "切り捨てる代わりにログファイルを削除します"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:248
+ #, c-format
+ msgid "Deleting log files...\n"
+-msgstr ""
++msgstr "ログファイルを削除中...\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:251
+ #, c-format
+ msgid "Unable to remove log files\n"
+-msgstr ""
++msgstr "ログファイルを削除できません\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:257
+ #, c-format
+ msgid "Truncating log files...\n"
+-msgstr ""
++msgstr "ログファイルを切り捨てます...\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:260
+ #, c-format
+ msgid "Unable to truncate log files\n"
+-msgstr ""
++msgstr "ログファイルの切り捨てができません\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:286
+ #, c-format
+ msgid "Out of memory!"
+-msgstr ""
++msgstr "メモリの空き容量がありません。"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:289
+ #, c-format
+ msgid "Archiving log files into %s...\n"
+-msgstr ""
++msgstr "ログファイルを %s へアーカイブ...\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:292
+ #, c-format
+ msgid "Unable to archive log files\n"
+-msgstr ""
++msgstr "ログファイルのアーカイブができません\n"
+ 
+ #: src/tools/sssctl/sssctl_logs.c:317
+ msgid "Specify debug level you want to set"
+-msgstr ""
+-
+-#: src/tools/sssctl/sssctl_sifp.c:28
+-msgid ""
+-"Check that SSSD is running and the InfoPipe responder is enabled. Make sure "
+-"'ifp' is listed in the 'services' option in sssd.conf.\n"
+-msgstr ""
+-
+-#: src/tools/sssctl/sssctl_user_checks.c:91
+-#, c-format
+-msgid "Unable to connect to the InfoPipe"
+-msgstr ""
+-
+-#: src/tools/sssctl/sssctl_user_checks.c:97
+-#, c-format
+-msgid "Unable to get user object"
+-msgstr ""
++msgstr "設定したいデバッグレベルを指定します"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:101
++#: src/tools/sssctl/sssctl_user_checks.c:117
+ #, c-format
+ msgid "SSSD InfoPipe user lookup result:\n"
+-msgstr ""
+-
+-#: src/tools/sssctl/sssctl_user_checks.c:113
+-#, c-format
+-msgid "Unable to get user name attr"
+-msgstr ""
++msgstr "SSSD InfoPipe ユーザー検索の結果:\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:146
++#: src/tools/sssctl/sssctl_user_checks.c:167
+ #, c-format
+ msgid "dlopen failed with [%s].\n"
+-msgstr ""
++msgstr "dlopen は [%s] で失敗しました。\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:153
++#: src/tools/sssctl/sssctl_user_checks.c:174
+ #, c-format
+ msgid "dlsym failed with [%s].\n"
+-msgstr ""
++msgstr "dlsym は [%s] で失敗しました。\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:161
++#: src/tools/sssctl/sssctl_user_checks.c:182
+ #, c-format
+ msgid "malloc failed.\n"
+-msgstr ""
++msgstr "malloc は失敗しました。\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:168
++#: src/tools/sssctl/sssctl_user_checks.c:189
+ #, c-format
+ msgid "sss_getpwnam_r failed with [%d].\n"
+-msgstr ""
++msgstr "sss_getpwnam_r が [%d] で失敗しました。\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:173
++#: src/tools/sssctl/sssctl_user_checks.c:194
+ #, c-format
+ msgid "SSSD nss user lookup result:\n"
+-msgstr ""
++msgstr "SSSD nss ユーザー検索の結果:\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:174
++#: src/tools/sssctl/sssctl_user_checks.c:195
+ #, c-format
+ msgid " - user name: %s\n"
+-msgstr ""
++msgstr " - user name: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:175
++#: src/tools/sssctl/sssctl_user_checks.c:196
+ #, c-format
+ msgid " - user id: %d\n"
+-msgstr ""
++msgstr " - user id: %d\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:176
++#: src/tools/sssctl/sssctl_user_checks.c:197
+ #, c-format
+ msgid " - group id: %d\n"
+-msgstr ""
++msgstr " - group id: %d\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:177
++#: src/tools/sssctl/sssctl_user_checks.c:198
+ #, c-format
+ msgid " - gecos: %s\n"
+-msgstr ""
++msgstr " - gecos: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:178
++#: src/tools/sssctl/sssctl_user_checks.c:199
+ #, c-format
+ msgid " - home directory: %s\n"
+-msgstr ""
++msgstr " - home directory: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:179
++#: src/tools/sssctl/sssctl_user_checks.c:200
+ #, c-format
+-msgid ""
+-" - shell: %s\n"
++msgid " - shell: %s\n"
++"\n"
++msgstr " - shell: %s\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:211
++#: src/tools/sssctl/sssctl_user_checks.c:232
+ msgid "PAM action [auth|acct|setc|chau|open|clos], default: "
+-msgstr ""
++msgstr "PAM アクション [auth|acct|setc|chau|open|clos]、デフォルト: "
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:214
++#: src/tools/sssctl/sssctl_user_checks.c:235
+ msgid "PAM service, default: "
+-msgstr ""
++msgstr "PAM サービス、デフォルト: "
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:219
++#: src/tools/sssctl/sssctl_user_checks.c:240
+ msgid "Specify user name."
+-msgstr ""
++msgstr "ユーザー名を指定します。"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:226
++#: src/tools/sssctl/sssctl_user_checks.c:247
+ #, c-format
+-msgid ""
+-"user: %s\n"
++msgid "user: %s\n"
+ "action: %s\n"
+ "service: %s\n"
+ "\n"
+-msgstr ""
++msgstr "ユーザー: %s\n"
++"アクション: %s\n"
++"サービス: %s\n"
++"\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:232
++#: src/tools/sssctl/sssctl_user_checks.c:253
+ #, c-format
+ msgid "User name lookup with [%s] failed.\n"
+-msgstr ""
++msgstr "[%s] でのユーザー名の検索に失敗しました。\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:237
++#: src/tools/sssctl/sssctl_user_checks.c:258
+ #, c-format
+ msgid "InfoPipe User lookup with [%s] failed.\n"
+-msgstr ""
++msgstr "[%s] での InfoPipe ユーザーの検索に失敗しました。\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:244
++#: src/tools/sssctl/sssctl_user_checks.c:265
+ #, c-format
+ msgid "pam_start failed: %s\n"
+-msgstr ""
++msgstr "pam_start に失敗しました: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:249
++#: src/tools/sssctl/sssctl_user_checks.c:270
+ #, c-format
+-msgid ""
+-"testing pam_authenticate\n"
++msgid "testing pam_authenticate\n"
++"\n"
++msgstr "pam_authenticate のテスト中\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:253
++#: src/tools/sssctl/sssctl_user_checks.c:274
+ #, c-format
+ msgid "pam_get_item failed: %s\n"
+-msgstr ""
++msgstr "pam_get_item に失敗しました: %s\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:257
++#: src/tools/sssctl/sssctl_user_checks.c:278
+ #, c-format
+-msgid ""
+-"pam_authenticate for user [%s]: %s\n"
++msgid "pam_authenticate for user [%s]: %s\n"
++"\n"
++msgstr "ユーザー [%s] 向けの pam_authenticate: %s\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:260
++#: src/tools/sssctl/sssctl_user_checks.c:281
+ #, c-format
+-msgid ""
+-"testing pam_chauthtok\n"
++msgid "testing pam_chauthtok\n"
++"\n"
++msgstr "pam_chauthtok のテスト中\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:262
++#: src/tools/sssctl/sssctl_user_checks.c:283
+ #, c-format
+-msgid ""
+-"pam_chauthtok: %s\n"
++msgid "pam_chauthtok: %s\n"
++"\n"
++msgstr "pam_chauthtok: %s\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:264
++#: src/tools/sssctl/sssctl_user_checks.c:285
+ #, c-format
+-msgid ""
+-"testing pam_acct_mgmt\n"
++msgid "testing pam_acct_mgmt\n"
+ "\n"
+-msgstr ""
++msgstr "pam_acct_mgmt のテスト中\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:266
++#: src/tools/sssctl/sssctl_user_checks.c:287
+ #, c-format
+-msgid ""
+-"pam_acct_mgmt: %s\n"
++msgid "pam_acct_mgmt: %s\n"
++"\n"
++msgstr "pam_acct_mgmt: %s\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:268
++#: src/tools/sssctl/sssctl_user_checks.c:289
+ #, c-format
+-msgid ""
+-"testing pam_setcred\n"
++msgid "testing pam_setcred\n"
++"\n"
++msgstr "pam_setcred のテスト中\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:270
++#: src/tools/sssctl/sssctl_user_checks.c:291
+ #, c-format
+-msgid ""
+-"pam_setcred: [%s]\n"
++msgid "pam_setcred: [%s]\n"
++"\n"
++msgstr "pam_setcred: [%s]\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:272
++#: src/tools/sssctl/sssctl_user_checks.c:293
+ #, c-format
+-msgid ""
+-"testing pam_open_session\n"
++msgid "testing pam_open_session\n"
+ "\n"
+-msgstr ""
++msgstr "pam_open_session のテスト中\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:274
++#: src/tools/sssctl/sssctl_user_checks.c:295
+ #, c-format
+-msgid ""
+-"pam_open_session: %s\n"
++msgid "pam_open_session: %s\n"
++"\n"
++msgstr "pam_open_session: %s\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:276
++#: src/tools/sssctl/sssctl_user_checks.c:297
+ #, c-format
+-msgid ""
+-"testing pam_close_session\n"
++msgid "testing pam_close_session\n"
+ "\n"
+-msgstr ""
++msgstr "pam_close_session のテスト中\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:278
++#: src/tools/sssctl/sssctl_user_checks.c:299
+ #, c-format
+-msgid ""
+-"pam_close_session: %s\n"
++msgid "pam_close_session: %s\n"
++"\n"
++msgstr "pam_close_session: %s\n"
+ "\n"
+-msgstr ""
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:281
++#: src/tools/sssctl/sssctl_user_checks.c:302
+ #, c-format
+ msgid "unknown action\n"
+-msgstr ""
++msgstr "不明なアクション\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:284
++#: src/tools/sssctl/sssctl_user_checks.c:305
+ #, c-format
+ msgid "PAM Environment:\n"
+-msgstr ""
++msgstr "PAM 環境:\n"
+ 
+-#: src/tools/sssctl/sssctl_user_checks.c:292
++#: src/tools/sssctl/sssctl_user_checks.c:313
+ #, c-format
+ msgid " - no env -\n"
+-msgstr ""
++msgstr " - no env -\n"
+ 
+-#: src/util/util.h:75
++#: src/util/util.h:73
+ msgid "The user ID to run the server as"
+-msgstr ""
++msgstr "次のようにサーバーを実行するユーザー ID"
+ 
+-#: src/util/util.h:77
++#: src/util/util.h:75
+ msgid "The group ID to run the server as"
+-msgstr ""
++msgstr "次のようにサーバーを実行するグループ ID"
+ 
+-#: src/util/util.h:85
++#: src/util/util.h:83
+ msgid "Informs that the responder has been socket-activated"
+-msgstr ""
++msgstr "レスポンダーがソケットでアクティベートされたと知らせます"
+ 
+-#: src/util/util.h:87
++#: src/util/util.h:85
+ msgid "Informs that the responder has been dbus-activated"
+-msgstr ""
++msgstr "レスポンダーが dbus でアクティベートされたと知らせます"
++
+-- 
+2.19.1
+
diff --git a/SOURCES/0033-AD-Remove-the-legacy-check-from-ad_get_account_domai.patch b/SOURCES/0033-AD-Remove-the-legacy-check-from-ad_get_account_domai.patch
deleted file mode 100644
index 2862524..0000000
--- a/SOURCES/0033-AD-Remove-the-legacy-check-from-ad_get_account_domai.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-From dcf8f47b85c0c93dd0c70d5a2093fff82f333e91 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 4 Jul 2018 20:10:30 +0200
-Subject: [PATCH] AD: Remove the legacy check from
- ad_get_account_domain_posix_check request
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Previously, the POSIX attribute presence check was run as part of the ID
-request, so it was necessary to also run the check as part of the
-get-domain-for-ID request.
-
-Since moving the POSIX check to being a part of the subdomain provider,
-this is no longer needed as the subdomain provider disables the GC
-support on its own if required. Therefore we can just remove the POSIX
-check from the get-domain-for-ID request.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3755
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-(cherry picked from commit 4273ac0490eeef72d2daa0c7f6cee80d65b6b34d)
----
- src/providers/ad/ad_id.c | 74 ----------------------------------------
- 1 file changed, 74 deletions(-)
-
-diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
-index 96c5677c681e40419172c2e5aa3c32b8403147b1..1da48433eeb01b069ea6e2829122d93a696fb8a3 100644
---- a/src/providers/ad/ad_id.c
-+++ b/src/providers/ad/ad_id.c
-@@ -1041,7 +1041,6 @@ ad_enumeration_recv(struct tevent_req *req)
- static errno_t ad_get_account_domain_prepare_search(struct tevent_req *req);
- static errno_t ad_get_account_domain_connect_retry(struct tevent_req *req);
- static void ad_get_account_domain_connect_done(struct tevent_req *subreq);
--static void ad_get_account_domain_posix_check_done(struct tevent_req *subreq);
- static void ad_get_account_domain_search(struct tevent_req *req);
- static void ad_get_account_domain_search_done(struct tevent_req *subreq);
- static void ad_get_account_domain_evaluate(struct tevent_req *req);
-@@ -1264,79 +1263,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);
--}
--
--static void ad_get_account_domain_posix_check_done(struct tevent_req *subreq)
--{
--    struct tevent_req *req = tevent_req_callback_data(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);
--    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);
--        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
--     * from now on.
--     */
--    if (has_posix == false) {
--        DEBUG(SSSDBG_CONF_SETTINGS,
--              "The Global Catalog has no POSIX attributes\n");
--
--        disable_gc(state->id_ctx->ad_options);
--        dp_reply_std_set(&state->reply,
--                         DP_ERR_DECIDE, ERR_GET_ACCT_DOM_NOT_SUPPORTED,
--                         NULL);
--        tevent_req_done(req);
--        return;
--    }
--
-     ad_get_account_domain_search(req);
- }
- 
--- 
-2.17.1
-
diff --git a/SOURCES/0033-Translation-Add-missing-newlines-in-the-ja-po-file.patch b/SOURCES/0033-Translation-Add-missing-newlines-in-the-ja-po-file.patch
new file mode 100644
index 0000000..970ab6a
--- /dev/null
+++ b/SOURCES/0033-Translation-Add-missing-newlines-in-the-ja-po-file.patch
@@ -0,0 +1,40 @@
+From 32d171f48920eaa98b84c73f69636e6388c28133 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
+Date: Thu, 6 Jun 2019 03:47:17 +0200
+Subject: [PATCH 33/33] Translation: Add missing newlines in the ja po file
+
+---
+ po/ja.po | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/po/ja.po b/po/ja.po
+index 396b693c2..f6ed9834b 100644
+--- a/po/ja.po
++++ b/po/ja.po
+@@ -2115,7 +2115,7 @@ msgstr ""
+ #: src/tools/sss_usermod.c:117 src/tools/sss_usermod.c:126
+ #: src/tools/sss_usermod.c:135
+ msgid "Specify the attribute name/value pair(s)\n"
+-msgstr "属性の名前/値のペアを指定します"
++msgstr "属性の名前/値のペアを指定します\n"
+ 
+ #: src/tools/sss_usermod.c:152
+ msgid "Specify user to modify\n"
+@@ -2146,12 +2146,12 @@ msgstr "指定された検索に一致するキャッシュオブジェクトが
+ #: src/tools/sss_cache.c:519
+ #, c-format
+ msgid "Couldn't invalidate %1$s\n"
+-msgstr "%1$s を無効化できませんでした"
++msgstr "%1$s を無効化できませんでした\n"
+ 
+ #: src/tools/sss_cache.c:526
+ #, c-format
+ msgid "Couldn't invalidate %1$s %2$s\n"
+-msgstr "%1$s %2$s を無効化できませんでした"
++msgstr "%1$s %2$s を無効化できませんでした\n"
+ 
+ #: src/tools/sss_cache.c:689
+ msgid "Invalidate all cached entries"
+-- 
+2.19.1
+
diff --git a/SOURCES/0034-AD-Add-Global-Catalog-usability-check-in-subdomain-c.patch b/SOURCES/0034-AD-Add-Global-Catalog-usability-check-in-subdomain-c.patch
deleted file mode 100644
index 0c323ec..0000000
--- a/SOURCES/0034-AD-Add-Global-Catalog-usability-check-in-subdomain-c.patch
+++ /dev/null
@@ -1,423 +0,0 @@
-From 7f9567ba8d62536c4aeb68897316781e82116c21 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 4 Jul 2018 13:14:40 +0200
-Subject: [PATCH] AD: Add Global Catalog usability check in subdomain code by
- looking at the schema
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Addsa a new tevent request which checks for the presence of uidNumber
-and gidNumber under the schema naming context, which is typically
-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.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3755
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-(cherry picked from commit ba96e7b839b875946f03787a3a57f259230a0fef)
----
- src/providers/ad/ad_subdomains.c | 308 +++++++++++++++++++++++++++++--
- 1 file changed, 288 insertions(+), 20 deletions(-)
-
-diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
-index 84886e920b37f8803d85ce0903b74e6c809a8904..549c2c1f76d4bbccdf03c6ab619fba5f9186358f 100644
---- a/src/providers/ad/ad_subdomains.c
-+++ b/src/providers/ad/ad_subdomains.c
-@@ -54,9 +54,39 @@
- #define SLAVE_DOMAIN_FILTER      "(&"SLAVE_DOMAIN_FILTER_BASE")"
- #define FOREST_ROOT_FILTER_FMT   "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))"
- 
-+/* Attributes of schema objects. See e.g.
-+ * https://docs.microsoft.com/en-us/windows/desktop/AD/characteristics-of-attributes
-+ * for more details
-+ */
-+#define AD_SCHEMA_AT_OC         "attributeSchema"
-+#define AD_AT_SCHEMA_NAME       "cn"
-+#define AD_AT_SCHEMA_IS_REPL    "isMemberOfPartialAttributeSet"
-+
- /* do not refresh more often than every 5 seconds for now */
- #define AD_SUBDOMAIN_REFRESH_LIMIT 5
- 
-+static void
-+ad_disable_gc(struct ad_options *ad_options)
-+{
-+    errno_t ret;
-+
-+    if (dp_opt_get_bool(ad_options->basic, AD_ENABLE_GC) == false) {
-+        return;
-+    }
-+
-+    DEBUG(SSSDBG_IMPORTANT_INFO, "POSIX attributes were requested "
-+          "but are not present on the server side. Global Catalog "
-+          "lookups will be disabled\n");
-+
-+    ret = dp_opt_set_bool(ad_options->basic,
-+                          AD_ENABLE_GC, false);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+                "Could not turn off GC support\n");
-+        /* Not fatal */
-+    }
-+}
-+
- static struct sss_domain_info *
- ads_get_root_domain(struct be_ctx *be_ctx, struct sysdb_attrs *attrs)
- {
-@@ -1261,6 +1291,212 @@ static errno_t ad_get_root_domain_recv(TALLOC_CTX *mem_ctx,
-     return EOK;
- }
- 
-+static void ad_check_gc_usability_search_done(struct tevent_req *subreq);
-+
-+struct ad_check_gc_usability_state {
-+    struct sdap_options *sdap_opts;
-+
-+    const char *attrs[3];
-+
-+    bool is_gc_usable;
-+};
-+
-+static struct tevent_req *
-+ad_check_gc_usability_send(TALLOC_CTX *mem_ctx,
-+                           struct tevent_context *ev,
-+                           struct ad_options *ad_options,
-+                           struct sdap_options *sdap_opts,
-+                           struct sdap_id_op *op,
-+                           const char *domain_name,
-+                           const char *domain_sid)
-+{
-+    struct ad_check_gc_usability_state *state = NULL;
-+    struct tevent_req *req = NULL;
-+    struct tevent_req *subreq = NULL;
-+    const char *filter = NULL;
-+    errno_t ret;
-+    bool uses_id_mapping;
-+
-+    req = tevent_req_create(mem_ctx, &state,
-+                            struct ad_check_gc_usability_state);
-+    if (req == NULL) {
-+        return NULL;
-+    }
-+    state->sdap_opts = sdap_opts;
-+    state->is_gc_usable = false;
-+
-+    if (dp_opt_get_bool(ad_options->basic, AD_ENABLE_GC) == false) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "GC explicitly disabled\n");
-+        state->is_gc_usable = false;
-+        ret = EOK;
-+        goto immediately;
-+    }
-+
-+    uses_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
-+                                                        sdap_opts->idmap_ctx,
-+                                                        domain_name,
-+                                                        domain_sid);
-+    if (uses_id_mapping == true) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "GC always usable while ID mapping\n");
-+        state->is_gc_usable = true;
-+        ret = EOK;
-+        goto immediately;
-+    }
-+
-+    /* The schema partition is replicated across all DCs in the forest, so
-+     * it's safe to use the baseDN even if e.g. joined to a child domain
-+     * even though the base DN "looks" like a part of the forest root
-+     * tree. On the other hand, it doesn't make sense to guess the value
-+     * if we can't detect it from the rootDSE.
-+     */
-+    if (state->sdap_opts->schema_basedn == NULL) {
-+        DEBUG(SSSDBG_TRACE_FUNC,
-+              "No idea where to look for the schema, disabling GC\n");
-+        state->is_gc_usable = false;
-+        ret = EOK;
-+        goto immediately;
-+    }
-+
-+    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");
-+
-+    filter = talloc_asprintf(
-+                        state,
-+                        "(&(objectclass=%s)(|(%s=%s)(%s=%s)))",
-+                        AD_SCHEMA_AT_OC,
-+                        AD_AT_SCHEMA_NAME,
-+                        state->sdap_opts->user_map[SDAP_AT_USER_UID].name,
-+                        AD_AT_SCHEMA_NAME,
-+                        state->sdap_opts->group_map[SDAP_AT_GROUP_GID].name);
-+    if (filter == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+
-+    subreq = sdap_get_generic_send(state,
-+                                   ev,
-+                                   state->sdap_opts,
-+                                   sdap_id_op_handle(op),
-+                                   state->sdap_opts->schema_basedn,
-+                                   LDAP_SCOPE_SUBTREE,
-+                                   filter,
-+                                   state->attrs,
-+                                   NULL, 0,
-+                                   dp_opt_get_int(state->sdap_opts->basic,
-+                                                  SDAP_SEARCH_TIMEOUT),
-+                                   false);
-+    if (subreq == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+    tevent_req_set_callback(subreq, ad_check_gc_usability_search_done, req);
-+
-+    return req;
-+
-+immediately:
-+    if (ret == EOK) {
-+        tevent_req_done(req);
-+    } else {
-+        tevent_req_error(req, ret);
-+    }
-+    tevent_req_post(req, ev);
-+
-+    return req;
-+}
-+
-+static void ad_check_gc_usability_search_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                      struct tevent_req);
-+    struct ad_check_gc_usability_state *state = tevent_req_data(req,
-+                                          struct ad_check_gc_usability_state);
-+    errno_t ret;
-+    size_t reply_count;
-+    struct sysdb_attrs **reply = NULL;
-+    bool uid = false;
-+    bool gid = false;
-+
-+    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. */
-+    }
-+
-+    if (reply_count == 0) {
-+        DEBUG(SSSDBG_TRACE_LIBS,
-+              "Nothing found, so no POSIX attrs can exist\n");
-+        state->is_gc_usable = 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->sdap_opts->user_map[SDAP_AT_USER_UID].name) == 0) {
-+            val = &uid;
-+        } else if (strcasecmp(name, state->sdap_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->is_gc_usable = true;
-+    }
-+
-+    if (state->is_gc_usable == 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);
-+}
-+
-+static errno_t ad_check_gc_usability_recv(struct tevent_req *req,
-+                                          bool *_is_gc_usable)
-+{
-+    struct ad_check_gc_usability_state *state = NULL;
-+
-+    state = tevent_req_data(req, struct ad_check_gc_usability_state);
-+
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+
-+    *_is_gc_usable = state->is_gc_usable;
-+    return EOK;
-+}
-+
- struct ad_subdomains_refresh_state {
-     struct tevent_context *ev;
-     struct be_ctx *be_ctx;
-@@ -1268,11 +1504,14 @@ struct ad_subdomains_refresh_state {
-     struct sdap_id_op *sdap_op;
-     struct sdap_id_ctx *id_ctx;
-     struct ad_options *ad_options;
-+
-+    char *forest;
- };
- 
- static errno_t ad_subdomains_refresh_retry(struct tevent_req *req);
- static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq);
- static void ad_subdomains_refresh_master_done(struct tevent_req *subreq);
-+static void ad_subdomains_refresh_gc_check_done(struct tevent_req *subreq);
- static void ad_subdomains_refresh_root_done(struct tevent_req *subreq);
- static void ad_subdomains_refresh_done(struct tevent_req *subreq);
- 
-@@ -1385,37 +1624,73 @@ static void ad_subdomains_refresh_master_done(struct tevent_req *subreq)
-     struct ad_subdomains_refresh_state *state;
-     struct tevent_req *req;
-     const char *realm;
--    const char *ad_domain;
-     char *master_sid;
-     char *flat_name;
--    char *forest;
-     errno_t ret;
- 
-     req = tevent_req_callback_data(subreq, struct tevent_req);
-     state = tevent_req_data(req, struct ad_subdomains_refresh_state);
- 
-     ret = ad_master_domain_recv(subreq, state, &flat_name, &master_sid,
--                                NULL, &forest);
-+                                NULL, &state->forest);
-     talloc_zfree(subreq);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get master domain information "
-               "[%d]: %s\n", ret, sss_strerror(ret));
--        goto done;
-+        tevent_req_error(req, ret);
-+        return;
-     }
- 
-     realm = dp_opt_get_cstring(state->ad_options->basic, AD_KRB5_REALM);
-     if (realm == NULL) {
-         DEBUG(SSSDBG_CONF_SETTINGS, "Missing realm.\n");
--        ret = EINVAL;
--        goto done;
-+        tevent_req_error(req, EINVAL);
-+        return;
-     }
- 
-     ret = sysdb_master_domain_add_info(state->be_ctx->domain, realm,
--                                       flat_name, master_sid, forest, NULL);
-+                                       flat_name, master_sid, state->forest, NULL);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info [%d]: %s\n",
-               ret, sss_strerror(ret));
--        goto done;
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    subreq = ad_check_gc_usability_send(state,
-+                                        state->ev,
-+                                        state->ad_options,
-+                                        state->id_ctx->opts,
-+                                        state->sdap_op,
-+                                        state->be_ctx->domain->name,
-+                                        master_sid);
-+    if (subreq == NULL) {
-+        tevent_req_error(req, ENOMEM);
-+        return;
-+    }
-+    tevent_req_set_callback(subreq, ad_subdomains_refresh_gc_check_done, req);
-+}
-+
-+static void ad_subdomains_refresh_gc_check_done(struct tevent_req *subreq)
-+{
-+    struct ad_subdomains_refresh_state *state;
-+    struct tevent_req *req;
-+    const char *ad_domain;
-+    bool is_gc_usable;
-+    errno_t ret;
-+
-+    req = tevent_req_callback_data(subreq, struct tevent_req);
-+    state = tevent_req_data(req, struct ad_subdomains_refresh_state);
-+
-+    ret = ad_check_gc_usability_recv(subreq, &is_gc_usable);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "Unable to get GC usability status\n");
-+        is_gc_usable = false;
-+    }
-+
-+    if (is_gc_usable == false) {
-+        ad_disable_gc(state->ad_options);
-     }
- 
-     /*
-@@ -1428,7 +1703,8 @@ static void ad_subdomains_refresh_master_done(struct tevent_req *subreq)
-                            state->be_ctx->domain->name) == 0) {
-                 DEBUG(SSSDBG_TRACE_FUNC,
-                       "No other enabled domain than master.\n");
--                goto done;
-+                tevent_req_done(req);
-+                return;
-             }
-         }
-     }
-@@ -1440,24 +1716,16 @@ static void ad_subdomains_refresh_master_done(struct tevent_req *subreq)
-         ad_domain = state->sd_ctx->be_ctx->domain->name;
-     }
- 
--    subreq = ad_get_root_domain_send(state, state->ev, ad_domain, forest,
-+    subreq = ad_get_root_domain_send(state, state->ev, ad_domain, state->forest,
-                                      sdap_id_op_handle(state->sdap_op),
-                                      state->sd_ctx);
-     if (subreq == NULL) {
--        ret = ENOMEM;
--        goto done;
-+        tevent_req_error(req, ENOMEM);
-+        return;
-     }
- 
-     tevent_req_set_callback(subreq, ad_subdomains_refresh_root_done, req);
-     return;
--
--done:
--    if (ret != EOK) {
--        tevent_req_error(req, ret);
--        return;
--    }
--
--    tevent_req_done(req);
- }
- 
- static void ad_subdomains_refresh_root_done(struct tevent_req *subreq)
--- 
-2.17.1
-
diff --git a/SOURCES/0035-SDAP-Detect-schemaNamingContext-from-the-rootDSE.patch b/SOURCES/0035-SDAP-Detect-schemaNamingContext-from-the-rootDSE.patch
deleted file mode 100644
index 6397fc5..0000000
--- a/SOURCES/0035-SDAP-Detect-schemaNamingContext-from-the-rootDSE.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From bf4580b2f893cfb29d804a9fe6bb2d6247bb5cf2 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 8 Jul 2018 22:17:41 +0200
-Subject: [PATCH] SDAP: Detect schemaNamingContext from the rootDSE
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Whether an attribute is replicated to the Global Catalog or not can be
-detected by checking the value of the isMemberOfPartialAttributeSet
-attribute:
-https://docs.microsoft.com/en-us/windows/desktop/ADSchema/a-ismemberofpartialattributeset
-
-This attribute is present in all objects with the objectClass
-attributeSchema in AD:
-https://docs.microsoft.com/en-us/windows/desktop/AD/characteristics-of-attributes
-
-And finally, the attributeSchema objects in AD are present in a schema
-naming context. The schema naming context is replicated to all DCs in the
-forest even though their own naming context might be different:
-https://docs.microsoft.com/en-us/windows/desktop/ad/naming-contexts-and-partitions
-
-Where the schema naming context is located is given by the
-schemaNamingContext attribute of the rootDSE.
-
-This patch is trivial on its own and just reads schemaNamingContext from
-the rootDSE and stores it in the sdap_options structure for later use.
-
-Related:
-https://pagure.io/SSSD/sssd/issue/3755
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-(cherry picked from commit c8d1c1b734a1763b3e1233f060cc5c8d6db078e9)
----
- src/providers/ldap/sdap.c | 10 ++++++++++
- src/providers/ldap/sdap.h |  3 +++
- 2 files changed, 13 insertions(+)
-
-diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
-index 0241a99e49e94345753399d5d62639c99b95ee77..5c9d0a45dfb96e8901467aa6a3391b8df84f6d42 100644
---- a/src/providers/ldap/sdap.c
-+++ b/src/providers/ldap/sdap.c
-@@ -1284,6 +1284,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
-     const char *last_usn_name;
-     const char *last_usn_value;
-     const char *entry_usn_name;
-+    const char *schema_nc = NULL;
-     char *endptr = NULL;
-     int ret;
-     int i;
-@@ -1400,6 +1401,15 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
-                    "(%s). Continuing without AD performance enhancements\n",
-                    strerror(ret));
-         }
-+
-+        ret = sysdb_attrs_get_string(rootdse,
-+                                     SDAP_ROOTDSE_ATTR_AD_SCHEMA_NC,
-+                                     &schema_nc);
-+        if (ret == EOK) {
-+            DEBUG(SSSDBG_CONF_SETTINGS,
-+                  "Will look for schema at [%s]\n", schema_nc);
-+            opts->schema_basedn = talloc_strdup(opts, schema_nc);
-+        }
-     }
- 
-     if (!last_usn_name) {
-diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
-index 0790544818633e26ee5a8fbdca556b8230b1df3f..31c25c32f059b4290a7511600cee638ee7a269e8 100644
---- a/src/providers/ldap/sdap.h
-+++ b/src/providers/ldap/sdap.h
-@@ -130,6 +130,7 @@ struct sdap_ppolicy_data {
- #define SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS "namingContexts"
- #define SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT "defaultNamingContext"
- #define SDAP_ROOTDSE_ATTR_AD_VERSION "domainControllerFunctionality"
-+#define SDAP_ROOTDSE_ATTR_AD_SCHEMA_NC "schemaNamingContext"
- 
- #define SDAP_IPA_USN "entryUSN"
- #define SDAP_IPA_LAST_USN "lastUSN"
-@@ -496,8 +497,10 @@ struct sdap_options {
-     /* The search bases for the domain or its subdomain */
-     struct sdap_domain *sdom;
- 
-+    /* The options below are normally only used with AD */
-     bool support_matching_rule;
-     enum dc_functional_level dc_functional_level;
-+    const char *schema_basedn;
- 
-     /* Certificate mapping support */
-     struct sdap_certmap_ctx *sdap_certmap_ctx;
--- 
-2.17.1
-
diff --git a/SOURCES/0036-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch b/SOURCES/0036-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch
deleted file mode 100644
index 820722b..0000000
--- a/SOURCES/0036-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From ef96cf36996d9e5802e529e5e812515ec3bda65c Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
-Date: Thu, 12 Jul 2018 23:55:03 +0200
-Subject: [PATCH] deskprofile: don't bail if we fail to save one profile
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Due to different reasons (a bug on fleet-commander, for instance?) we
-may face the situation where one profile ends up stored in freeipa on a
-half-broken state (with no data, for instance).
-
-In case it happens, we should try our best to save the not broken
-profiles and just skip the broken ones instead of bailing the whole
-operation.
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3773
-
-Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit efd6702e5f70bb3df0f840dd3ce9f8f9264661ba)
-
-DOWNSTREAM:
-Resolves: rhbz#1600822 - SSSD bails out saving desktop profiles in case an invalid profile is found
----
- src/providers/ipa/ipa_session.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c
-index 25ad5ce519e6923d7a4d8aa81e72b109ae36dbe1..33c64e5b7af9bd3353770f422be42a0b6ac23e09 100644
---- a/src/providers/ipa/ipa_session.c
-+++ b/src/providers/ipa/ipa_session.c
-@@ -768,7 +768,7 @@ ipa_pam_session_handler_save_deskprofile_rules(
-             DEBUG(SSSDBG_OP_FAILURE,
-                   "Failed to save a Desktop Profile Rule to disk [%d]: %s\n",
-                   ret, sss_strerror(ret));
--            goto done;
-+            continue;
-         }
-     }
- 
--- 
-2.17.1
-
diff --git a/SOURCES/0037-SUDO-Fix-running-in-unprivileged-responder.patch b/SOURCES/0037-SUDO-Fix-running-in-unprivileged-responder.patch
deleted file mode 100644
index 5ac4676..0000000
--- a/SOURCES/0037-SUDO-Fix-running-in-unprivileged-responder.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 261ff6442294b11261c11262d2a6acf379803e36 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 24 Jul 2018 18:52:08 +0000
-Subject: [PATCH] SUDO: Fix running in unprivileged responder
-
-There are strict checks for private sockets which does not work with
-unprivileged responder
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3778
-
-Merges: https://pagure.io/SSSD/sssd/pull-request/3784
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 4900b8e59bdbb89fbc1c9718969aabe26f3db34a)
-
-DOWNSTREAM:
-Resolves: rhbz#1607313 - When sssd is running as non-root user, the sudo pipe is created as sssd:sssd but then the private pipe ownership fails
----
- src/responder/sudo/sudosrv.c | 31 +++++++++++++++++++++++++++----
- 1 file changed, 27 insertions(+), 4 deletions(-)
-
-diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
-index e87a24499c2d82fafaa8e1f9b386e44332394266..82315e0a8f7879595e02458a9aa79e7332b04734 100644
---- a/src/responder/sudo/sudosrv.c
-+++ b/src/responder/sudo/sudosrv.c
-@@ -67,7 +67,8 @@ static void sudo_dp_reconnect_init(struct sbus_connection *conn,
- 
- int sudo_process_init(TALLOC_CTX *mem_ctx,
-                       struct tevent_context *ev,
--                      struct confdb_ctx *cdb)
-+                      struct confdb_ctx *cdb,
-+                      int pipe_fd)
- {
-     struct resp_ctx *rctx;
-     struct sss_cmd_table *sudo_cmds;
-@@ -79,8 +80,8 @@ int sudo_process_init(TALLOC_CTX *mem_ctx,
-     sudo_cmds = get_sudo_cmds();
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            sudo_cmds,
--                           NULL, -1,                   /* No public socket */
--                           SSS_SUDO_SOCKET_NAME, -1,   /* Private socket only */
-+                           SSS_SUDO_SOCKET_NAME, pipe_fd,   /* custom permissions on socket */
-+                           NULL, -1,                   /* No private socket */
-                            CONFDB_SUDO_CONF_ENTRY,
-                            SSS_SUDO_SBUS_SERVICE_NAME,
-                            SSS_SUDO_SBUS_SERVICE_VERSION,
-@@ -182,6 +183,7 @@ int main(int argc, const char *argv[])
-     char *opt_logger = NULL;
-     struct main_context *main_ctx;
-     int ret;
-+    int pipe_fd = -1;
-     uid_t uid;
-     gid_t gid;
- 
-@@ -219,6 +221,27 @@ int main(int argc, const char *argv[])
- 
-     sss_set_logger(opt_logger);
- 
-+    if (!is_socket_activated()) {
-+        /* Create pipe file descriptors here with right ownerschip */
-+        ret = create_pipe_fd(SSS_SUDO_SOCKET_NAME, &pipe_fd, SSS_DFL_UMASK);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_FATAL_FAILURE,
-+                  "create_pipe_fd failed [%d]: %s.\n",
-+                  ret, sss_strerror(ret));
-+            return 4;
-+        }
-+
-+        ret = chown(SSS_SUDO_SOCKET_NAME, uid, 0);
-+        if (ret != 0) {
-+            ret = errno;
-+            close(pipe_fd);
-+            DEBUG(SSSDBG_FATAL_FAILURE,
-+                  "create_pipe_fd failed [%d]: %s.\n",
-+                  ret, sss_strerror(ret));
-+            return 5;
-+        }
-+    }
-+
-     ret = server_setup("sssd[sudo]", 0, uid, gid, CONFDB_SUDO_CONF_ENTRY,
-                        &main_ctx);
-     if (ret != EOK) {
-@@ -234,7 +257,7 @@ int main(int argc, const char *argv[])
- 
-     ret = sudo_process_init(main_ctx,
-                             main_ctx->event_ctx,
--                            main_ctx->confdb_ctx);
-+                            main_ctx->confdb_ctx, pipe_fd);
-     if (ret != EOK) {
-         return 3;
-     }
--- 
-2.14.4
-
diff --git a/SOURCES/0038-SUDO-Root-should-be-able-to-read-write-sssd-sudo-soc.patch b/SOURCES/0038-SUDO-Root-should-be-able-to-read-write-sssd-sudo-soc.patch
deleted file mode 100644
index 607eabb..0000000
--- a/SOURCES/0038-SUDO-Root-should-be-able-to-read-write-sssd-sudo-soc.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 2708fb488277209a60a5daf5217502c029c196c1 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 24 Jul 2018 18:52:08 +0000
-Subject: [PATCH] SUDO: Root should be able to read/write sssd-sudo socket
-
-There is not any reason to require additional capabilities from root
-when sssd is running as unprivileged user.
-
-Sudo UNIX socket is not a real private socket. It just cannot
-be used by others. Just owner(sssd) and root should be able to use it.
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3778
-
-Merges: https://pagure.io/SSSD/sssd/pull-request/3784
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 21ea8204a0bd8ea4451f420713e909d3cfee34ef)
----
- src/sysv/systemd/sssd-sudo.socket.in | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/src/sysv/systemd/sssd-sudo.socket.in b/src/sysv/systemd/sssd-sudo.socket.in
-index 96a8b0327ddb4d331c9b2e97ece3453f8f76872d..e94a2f6151e3d69edc304776b72a81db22762503 100644
---- a/src/sysv/systemd/sssd-sudo.socket.in
-+++ b/src/sysv/systemd/sssd-sudo.socket.in
-@@ -10,8 +10,7 @@ Conflicts=shutdown.target
- ExecStartPre=@libexecdir@/sssd/sssd_check_socket_activated_responders -r sudo
- ListenStream=@pipepath@/sudo
- SocketUser=@SSSD_USER@
--SocketGroup=@SSSD_USER@
--SocketMode=0600
-+SocketMode=0660
- 
- [Install]
- WantedBy=sssd.service
--- 
-2.14.4
-
diff --git a/SOURCES/0039-sdap-respect-passwordGracelimit.patch b/SOURCES/0039-sdap-respect-passwordGracelimit.patch
deleted file mode 100644
index 4150d92..0000000
--- a/SOURCES/0039-sdap-respect-passwordGracelimit.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From bfafa12ae83bcdec53bb306f68eff9e6acfbb4a6 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
-Date: Fri, 20 Jul 2018 12:15:18 +0200
-Subject: [PATCH] sdap: respect passwordGracelimit
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Since recent changes in 389-ds two response controls are end when
-passwordGracelimit is set and about to expire:
-- [1.3.6.1.4.1.42.2.27.8.5.1] for the GraceLimit itself
-- [2.16.840.1.113730.3.4.4] for the PasswordExpired
-
-Whenever the former is returned and the GraceLimit is still valid, we
-shouldn't report the latter to the users.
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3597
-
-Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 954bf82b60b7cfd93b865a6618f155d042b15729)
-
-DOWNSTREAM:
-Resolves: rhbz#1522928 - sssd doesn't allow user with expired password
-to login when PasswordgraceLimit set
----
- src/providers/ldap/sdap_async_connection.c | 21 ++++++++++++++++++++-
- 1 file changed, 20 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
-index a8d4262b52c4b2d2810450d68794f00558ea5c2d..8aacd6705a1f82be8c14f97996786ac9b47396d5 100644
---- a/src/providers/ldap/sdap_async_connection.c
-+++ b/src/providers/ldap/sdap_async_connection.c
-@@ -734,6 +734,7 @@ static void simple_bind_done(struct sdap_op *op,
-     ber_int_t pp_expire;
-     LDAPPasswordPolicyError pp_error;
-     int result = LDAP_OTHER;
-+    bool on_grace_login_limit = false;
- 
-     if (error) {
-         tevent_req_error(req, error);
-@@ -772,6 +773,7 @@ static void simple_bind_done(struct sdap_op *op,
-             DEBUG(SSSDBG_TRACE_INTERNAL,
-                   "Server returned control [%s].\n",
-                    response_controls[c]->ldctl_oid);
-+
-             if (strcmp(response_controls[c]->ldctl_oid,
-                        LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
-                 lret = ldap_parse_passwordpolicy_control(state->sh->ldap,
-@@ -799,13 +801,26 @@ static void simple_bind_done(struct sdap_op *op,
-                 state->ppolicy->grace = pp_grace;
-                 state->ppolicy->expire = pp_expire;
-                 if (result == LDAP_SUCCESS) {
--
-+                    /* We have to set the on_grace_login_limit as when going
-+                     * through the response controls 389-ds may return both
-+                     * an warning and an error (and the order is not ensured)
-+                     * for the GraceLimit:
-+                     * - [1.3.6.1.4.1.42.2.27.8.5.1] for the GraceLimit itself
-+                     * - [2.16.840.1.113730.3.4.4] for the PasswordExpired
-+                     *
-+                     * So, in order to avoid bulldozing the GraceLimit, let's
-+                     * set it to true when pp_grace >= 0 and, in the end of
-+                     * this function, just return EOK when LDAP returns the
-+                     * PasswordExpired error but the GraceLimit is still valid.
-+                     */
-+                    on_grace_login_limit = false;
-                     if (pp_error == PP_changeAfterReset) {
-                         DEBUG(SSSDBG_TRACE_LIBS,
-                               "Password was reset. "
-                                "User must set a new password.\n");
-                         ret = ERR_PASSWORD_EXPIRED;
-                     } else if (pp_grace >= 0) {
-+                        on_grace_login_limit = true;
-                         DEBUG(SSSDBG_TRACE_LIBS,
-                               "Password expired. "
-                                "[%d] grace logins remaining.\n",
-@@ -875,6 +890,10 @@ static void simple_bind_done(struct sdap_op *op,
-         ret = ERR_AUTH_FAILED;
-     }
- 
-+    if (ret == ERR_PASSWORD_EXPIRED && on_grace_login_limit) {
-+        ret = EOK;
-+    }
-+
- done:
-     ldap_controls_free(response_controls);
-     ldap_memfree(errmsg);
--- 
-2.14.4
-
diff --git a/SOURCES/0040-MC-Remove-check-if-record-is-in-the-mapped-address-s.patch b/SOURCES/0040-MC-Remove-check-if-record-is-in-the-mapped-address-s.patch
deleted file mode 100644
index 5e9d331..0000000
--- a/SOURCES/0040-MC-Remove-check-if-record-is-in-the-mapped-address-s.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From 64085ac9dbc95bc7b227f24a9a8ec78952c68227 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 11 Jul 2018 22:18:41 +0200
-Subject: [PATCH] MC: Remove check if record is in the mapped address space
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-There is a check in the memory cache code that checks if a record pointer
-points to the mmapped region . But since some time ago, we return not
-a pointer to the mmapped region itself, but a copy to avoid issues with
-invalidating an entry while the same entry is being returned.
-
-In most cases, the check is correct, simply because of how memory is laid
-out on Linux, but in some cases the check was failing and causing a high
-load of SSSD.
-
-Signed-off-by: Jakub Hrozek <jhrozek@redhat.com>
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3776
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
-(cherry picked from commit f1c2d4139b6107ee3e9bec0cbe5bf8c2ea8428b2)
-
-DOWNSTREAM:
-Resolves: rhbz#1586127 - Spurious check in the sssd nss memcache can cause the memory cache to be skipped
----
- src/sss_client/nss_mc_group.c  | 4 +---
- src/sss_client/nss_mc_initgr.c | 5 +----
- src/sss_client/nss_mc_passwd.c | 4 +---
- 3 files changed, 3 insertions(+), 10 deletions(-)
-
-diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c
-index 6a2336b6116f198adea94f9eda9d9632f9fc8268..3371e0ffc274cd55dad4e7cdb74456f9f4b92d8b 100644
---- a/src/sss_client/nss_mc_group.c
-+++ b/src/sss_client/nss_mc_group.c
-@@ -152,12 +152,10 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
-         /* Integrity check
-          * - data->name cannot point outside strings
-          * - all strings must be within copy of record
--         * - record must not end outside data table
-          * - rec_name is a zero-terminated string */
-         if (data->name < strs_offset
-             || data->name >= strs_offset + data->strs_len
--            || data->strs_len > rec->len
--            || (uint8_t *) rec + rec->len > gr_mc_ctx.data_table + data_size) {
-+            || data->strs_len > rec->len) {
-             ret = ENOENT;
-             goto done;
-         }
-diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c
-index 5a8c661c7e15a085e9662297f62a6a84e70b669e..331930cef357d17c74892f67d5743ebc6a818631 100644
---- a/src/sss_client/nss_mc_initgr.c
-+++ b/src/sss_client/nss_mc_initgr.c
-@@ -133,15 +133,12 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
-         /* Integrity check
-          * - data->name cannot point outside all strings or data
-          * - all data must be within copy of record
--         * - size of record must be lower that data table size
-          * - data->strs cannot point outside strings
-          * - rec_name is a zero-terminated string */
-         if (data->name < data_offset
-             || data->name >= data_offset + data->data_len
-             || data->strs_len > data->data_len
--            || data->data_len > rec->len
--            || (uint8_t *) rec + rec->len
--                                      > initgr_mc_ctx.data_table + data_size) {
-+            || data->data_len > rec->len) {
-             ret = ENOENT;
-             goto done;
-         }
-diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c
-index 3c62481778788173227f8a241953e421316e248d..ac44b711d8614ac0daa841a7a9dd5894f1a1eb08 100644
---- a/src/sss_client/nss_mc_passwd.c
-+++ b/src/sss_client/nss_mc_passwd.c
-@@ -145,12 +145,10 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
-         /* Integrity check
-          * - data->name cannot point outside strings
-          * - all strings must be within copy of record
--         * - record must not end outside data table
-          * - rec_name is a zero-terminated string */
-         if (data->name < strs_offset
-             || data->name >= strs_offset + data->strs_len
--            || data->strs_len > rec->len
--            || (uint8_t *) rec + rec->len > pw_mc_ctx.data_table + data_size) {
-+            || data->strs_len > rec->len) {
-             ret = ENOENT;
-             goto done;
-         }
--- 
-2.14.4
-
diff --git a/SOURCES/0041-Revert-CRYPTO-Suppress-warning-Wstringop-truncation.patch b/SOURCES/0041-Revert-CRYPTO-Suppress-warning-Wstringop-truncation.patch
deleted file mode 100644
index 83f3206..0000000
--- a/SOURCES/0041-Revert-CRYPTO-Suppress-warning-Wstringop-truncation.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 61227cf82d01ee42300ad7054bfd683536e15acb Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
-Date: Fri, 27 Jul 2018 11:37:20 +0200
-Subject: [PATCH] Revert "CRYPTO: Suppress warning Wstringop-truncation"
-
-This reverts commit 2951a9a84bd85f384213a3e071ffc167907df2d7.
-
-The original use stpncpy was correct. Changing it to memcpy
-changed the resulting hash. This resulted in users from
-local domain to not be able to authenticate (offline
-authentication was also probably broken) if their hash was
-created before this change.
-
-https://pagure.io/SSSD/sssd/issue/3791
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-DOWNSTREAM:
-Resolves: rhbz#1602781 - Local users failed to login with same password
-after upgrading to RHEL7.6
----
- src/util/crypto/libcrypto/crypto_sha512crypt.c | 2 +-
- src/util/crypto/nss/nss_sha512crypt.c          | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/util/crypto/libcrypto/crypto_sha512crypt.c b/src/util/crypto/libcrypto/crypto_sha512crypt.c
-index 5861f34b9325f7552491a07e8b85fe35ca5ae607..b074eee555fafac6e486bfdf9efb9ddf4964a990 100644
---- a/src/util/crypto/libcrypto/crypto_sha512crypt.c
-+++ b/src/util/crypto/libcrypto/crypto_sha512crypt.c
-@@ -277,7 +277,7 @@ static int sha512_crypt_r(const char *key,
-         goto done;
-     }
- 
--    cp = memcpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-+    cp = stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-     buflen -= SALT_PREF_SIZE;
- 
-     if (rounds_custom) {
-diff --git a/src/util/crypto/nss/nss_sha512crypt.c b/src/util/crypto/nss/nss_sha512crypt.c
-index 709cf51961bb7069ddebf3d636aa29b020756f0a..2f1624e6396c40f539a4e2034ab545cad8f05434 100644
---- a/src/util/crypto/nss/nss_sha512crypt.c
-+++ b/src/util/crypto/nss/nss_sha512crypt.c
-@@ -267,7 +267,7 @@ static int sha512_crypt_r(const char *key,
-         goto done;
-     }
- 
--    cp = memcpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-+    cp = stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-     buflen -= SALT_PREF_SIZE;
- 
-     if (rounds_custom) {
--- 
-2.14.4
-
diff --git a/SOURCES/0042-Revert-Revert-CRYPTO-Suppress-warning-Wstringop-trun.patch b/SOURCES/0042-Revert-Revert-CRYPTO-Suppress-warning-Wstringop-trun.patch
deleted file mode 100644
index c9e72ef..0000000
--- a/SOURCES/0042-Revert-Revert-CRYPTO-Suppress-warning-Wstringop-trun.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From 503172f46360b33170063b3bf75047990c644ed5 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 31 Jul 2018 20:43:37 +0000
-Subject: [PATCH] Revert "Revert "CRYPTO: Suppress warning
- Wstringop-truncation""
-
-This reverts commit bb20d5160faed5e0076887ac4a83e550be15a8b2.
-
-The patch introduced compile time warning
-src/util/crypto/libcrypto/crypto_sha512crypt.c:280:10: error: 'stpncpy'
-    output truncated before terminating nul copying 3 bytes from a string
-    of the same length [-Werror=stringop-truncation]
-     cp = stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Merges: https://pagure.io/SSSD/sssd/pull-request/3792
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/util/crypto/libcrypto/crypto_sha512crypt.c | 2 +-
- src/util/crypto/nss/nss_sha512crypt.c          | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/util/crypto/libcrypto/crypto_sha512crypt.c b/src/util/crypto/libcrypto/crypto_sha512crypt.c
-index b074eee555fafac6e486bfdf9efb9ddf4964a990..5861f34b9325f7552491a07e8b85fe35ca5ae607 100644
---- a/src/util/crypto/libcrypto/crypto_sha512crypt.c
-+++ b/src/util/crypto/libcrypto/crypto_sha512crypt.c
-@@ -277,7 +277,7 @@ static int sha512_crypt_r(const char *key,
-         goto done;
-     }
- 
--    cp = stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-+    cp = memcpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-     buflen -= SALT_PREF_SIZE;
- 
-     if (rounds_custom) {
-diff --git a/src/util/crypto/nss/nss_sha512crypt.c b/src/util/crypto/nss/nss_sha512crypt.c
-index 2f1624e6396c40f539a4e2034ab545cad8f05434..709cf51961bb7069ddebf3d636aa29b020756f0a 100644
---- a/src/util/crypto/nss/nss_sha512crypt.c
-+++ b/src/util/crypto/nss/nss_sha512crypt.c
-@@ -267,7 +267,7 @@ static int sha512_crypt_r(const char *key,
-         goto done;
-     }
- 
--    cp = stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-+    cp = memcpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-     buflen -= SALT_PREF_SIZE;
- 
-     if (rounds_custom) {
--- 
-2.14.4
-
diff --git a/SOURCES/0043-CRYPTO-Save-prefix-in-s3crypt_sha512.patch b/SOURCES/0043-CRYPTO-Save-prefix-in-s3crypt_sha512.patch
deleted file mode 100644
index fea39ee..0000000
--- a/SOURCES/0043-CRYPTO-Save-prefix-in-s3crypt_sha512.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 62cfc6d28b770f56fcb103eeed32e961d3531f3d Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 31 Jul 2018 20:44:06 +0000
-Subject: [PATCH] CRYPTO: Save prefix in s3crypt_sha512
-
-Since commit 2951a9a84bd85f384213a3e071ffc167907df2d7 where we switched from
-stpncpy to memcpy the salt prefix "$6$" is not stored at all.
-This broke offline authentication if someone upgraded from old version
-that stored the prefix to one that doesn't store it.
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3791
-
-Merges: https://pagure.io/SSSD/sssd/pull-request/3792
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/util/crypto/libcrypto/crypto_sha512crypt.c | 1 +
- src/util/crypto/nss/nss_sha512crypt.c          | 1 +
- 2 files changed, 2 insertions(+)
-
-diff --git a/src/util/crypto/libcrypto/crypto_sha512crypt.c b/src/util/crypto/libcrypto/crypto_sha512crypt.c
-index 5861f34b9325f7552491a07e8b85fe35ca5ae607..2275ccd96212b28984e47c128ba2acb233b865d0 100644
---- a/src/util/crypto/libcrypto/crypto_sha512crypt.c
-+++ b/src/util/crypto/libcrypto/crypto_sha512crypt.c
-@@ -278,6 +278,7 @@ static int sha512_crypt_r(const char *key,
-     }
- 
-     cp = memcpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-+    cp += SALT_PREF_SIZE;
-     buflen -= SALT_PREF_SIZE;
- 
-     if (rounds_custom) {
-diff --git a/src/util/crypto/nss/nss_sha512crypt.c b/src/util/crypto/nss/nss_sha512crypt.c
-index 709cf51961bb7069ddebf3d636aa29b020756f0a..4d0594d9f21f0fe4228037901c6792625bd4f7c6 100644
---- a/src/util/crypto/nss/nss_sha512crypt.c
-+++ b/src/util/crypto/nss/nss_sha512crypt.c
-@@ -268,6 +268,7 @@ static int sha512_crypt_r(const char *key,
-     }
- 
-     cp = memcpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
-+    cp += SALT_PREF_SIZE;
-     buflen -= SALT_PREF_SIZE;
- 
-     if (rounds_custom) {
--- 
-2.14.4
-
diff --git a/SOURCES/0044-crypto-tests-Add-unit-test-for-s3crypt_sha512.patch b/SOURCES/0044-crypto-tests-Add-unit-test-for-s3crypt_sha512.patch
deleted file mode 100644
index b88bc1a..0000000
--- a/SOURCES/0044-crypto-tests-Add-unit-test-for-s3crypt_sha512.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From f0d437220d5c76f6b09dee5c5744397549fc3813 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 31 Jul 2018 20:44:16 +0000
-Subject: [PATCH] crypto-tests: Add unit test for s3crypt_sha512
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3791
-
-Merges: https://pagure.io/SSSD/sssd/pull-request/3792
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/tests/crypto-tests.c | 32 ++++++++++++++++++++++++++++++++
- 1 file changed, 32 insertions(+)
-
-diff --git a/src/tests/crypto-tests.c b/src/tests/crypto-tests.c
-index 2e826a41b3c1302b87c7136cc37b7c4df02a0584..6f5e22a878ad9e40b73b23915d08395b3f6f2e3d 100644
---- a/src/tests/crypto-tests.c
-+++ b/src/tests/crypto-tests.c
-@@ -201,6 +201,37 @@ START_TEST(test_sss_encrypt_decrypt)
- }
- END_TEST
- 
-+START_TEST(test_s3crypt_sha512)
-+{
-+    int ret;
-+    char *salt;
-+    char *userhash;
-+    char *comphash;
-+    const char *password = "password123";
-+    const char *expected_hash = "$6$tU67Q/9h3tm5WJ.U$aL9gjCfiSZQewHTI6A4/MHCVWrMCiJZ.gNXEIw6HO39XGbg.s2nTyGlYXeoQyQtDll3XSbIZN41fJEC3v7ELy0";
-+
-+    test_ctx = talloc_new(NULL);
-+    fail_if(test_ctx == NULL);
-+
-+    ret = s3crypt_gen_salt(test_ctx, &salt);
-+    fail_if(ret != 0);
-+
-+    ret = s3crypt_sha512(test_ctx, password, salt, &userhash);
-+    fail_if(ret != 0);
-+
-+    ret = s3crypt_sha512(test_ctx, password, userhash, &comphash);
-+    fail_if(ret != 0);
-+    ck_assert_str_eq(userhash, comphash);
-+    talloc_free(comphash);
-+
-+    ret = s3crypt_sha512(test_ctx, password, expected_hash, &comphash);
-+    fail_if(ret != 0);
-+    ck_assert_str_eq(expected_hash, comphash);
-+
-+    talloc_free(test_ctx);
-+}
-+END_TEST
-+
- Suite *crypto_suite(void)
- {
-     Suite *s = suite_create("sss_crypto");
-@@ -216,6 +247,7 @@ Suite *crypto_suite(void)
-     tcase_add_test(tc, test_base64_encode);
-     tcase_add_test(tc, test_base64_decode);
-     tcase_add_test(tc, test_sss_encrypt_decrypt);
-+    tcase_add_test(tc, test_s3crypt_sha512);
-     /* Add all test cases to the test suite */
-     suite_add_tcase(s, tc);
- 
--- 
-2.14.4
-
diff --git a/SOURCES/0045-SSS_CERT-Close-file-descriptors-after-executing-p11_.patch b/SOURCES/0045-SSS_CERT-Close-file-descriptors-after-executing-p11_.patch
deleted file mode 100644
index 8eb4a97..0000000
--- a/SOURCES/0045-SSS_CERT-Close-file-descriptors-after-executing-p11_.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From a195869e527df27451bee8b68108abd005976b2d Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 31 Jul 2018 21:03:38 +0000
-Subject: [PATCH] SSS_CERT: Close file descriptors after executing p11_child
-
-We can call cert_to_ssh_key_step from cert_to_ssh_key_done and thus
-p11_child can be executed more time. We created pipes for each call
-but destructor for state->io can close just last one.
-
-It's better to manually close pipes with macro PIPE_FD_CLOSE.
-that macro set file descriptor to -1 and destructor will not try
-to close them 2nd time. Destructor will cover just edge cases.
-
-Merges: https://pagure.io/SSSD/sssd/pull-request/3793
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3794
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit a76f96ac143128c11bdb975293d667aca861cd91)
-
-DOWNSTREAM:
-Resolves: rhbz#1610667 - sssd_ssh leaks file descriptors when more than one certificate is converted into an SSH key
----
- src/util/cert/cert_common_p11_child.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/util/cert/cert_common_p11_child.c b/src/util/cert/cert_common_p11_child.c
-index 17e97eeeeb1956ca6d2bbf048445117029b10dde..aacdb5c475274234fd18d5eca23ee5f9c9288c3e 100644
---- a/src/util/cert/cert_common_p11_child.c
-+++ b/src/util/cert/cert_common_p11_child.c
-@@ -255,6 +255,9 @@ static void cert_to_ssh_key_done(int child_status,
-     int ret;
-     bool valid = false;
- 
-+    PIPE_FD_CLOSE(state->io->read_from_child_fd);
-+    PIPE_FD_CLOSE(state->io->write_to_child_fd);
-+
-     if (WIFEXITED(child_status)) {
-         if (WEXITSTATUS(child_status) != 0) {
-             DEBUG(SSSDBG_OP_FAILURE,
--- 
-2.17.1
-
diff --git a/SOURCES/0046-SELINUX-Also-call-is_selinux_enabled-as-a-check-for-.patch b/SOURCES/0046-SELINUX-Also-call-is_selinux_enabled-as-a-check-for-.patch
deleted file mode 100644
index 7665629..0000000
--- a/SOURCES/0046-SELINUX-Also-call-is_selinux_enabled-as-a-check-for-.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 663fdd3897c5da1a54fcb51613bd71660ef9b19a Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 20 Jun 2018 22:02:57 +0200
-Subject: [PATCH] SELINUX: Also call is_selinux_enabled as a check for selinux
- child
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3796
-
-The SSSD selinux management routines were only checking if SELinux is
-managed on the system. If it is managed, the code tries to proceed and
-set the login context, otherwise an error is returned which SSSD handles
-gracefully.
-
-But this is not enough, in some cases SELinux might be disabled, but
-managed and in these cases SSSD was returning strange errors, which
-might have prevented login with selinux provider in effect.
-
-We got this hint form the RH SELinux maintainer:
-"""
-libsemanage is for managing SELinux infrastructure. generally if there's
-/etc/selinux/config where libsemanage can read SELINUXTYPE and SELinux
-module store - /etc/selinux/<SELINUXTYPE>/active (or
-/var/lib/selinux/<SELINUXTYPE>/active) - is available, libsemanage can
-manage it even when SELinux is disabled.
-
-I'm not sure if selinux_child doesn any is_selinux_enabled() checks but
-it could help to avoid such situations.
-"""
-
-Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
-(cherry picked from commit 1e81d040c75b2b15cab48fb7df1041138747e6c3)
-
-DOWNSTREAM:
-Resolves: rhbz#1583360 - The IPA selinux provider can return an error if SELinux is completely disabled
----
- src/util/sss_semanage.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c
-index 7b0eef22330db8df6ab8f46da5fb76c68f6adabc..bcce57b603bd1c4d5c6465dbb5cc7a3fbe72412d 100644
---- a/src/util/sss_semanage.c
-+++ b/src/util/sss_semanage.c
-@@ -82,6 +82,10 @@ static int sss_is_selinux_managed(semanage_handle_t *handle)
-         return EINVAL;
-     }
- 
-+    if (!is_selinux_enabled()) {
-+        return ERR_SELINUX_NOT_MANAGED;
-+    }
-+
-     ret = semanage_is_managed(handle);
-     if (ret == 0) {
-         DEBUG(SSSDBG_TRACE_FUNC, "SELinux policy not managed via libsemanage\n");
--- 
-2.17.1
-
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
deleted file mode 100644
index 66dbbbe..0000000
--- a/SOURCES/0047-SELINUX-Always-add-SELinux-user-to-the-semanage-data.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-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
deleted file mode 100644
index dcbe819..0000000
--- a/SOURCES/0048-sudo-respect-case-sensitivity-in-sudo-responder.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-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
deleted file mode 100644
index eb552b5..0000000
--- a/SOURCES/0049-nss-use-enumeration-context-as-talloc-parent-for-cac.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-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
deleted file mode 100644
index 4483916..0000000
--- a/SOURCES/0050-Revert-IPA-use-forest-name-when-looking-up-the-Globa.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-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
deleted file mode 100644
index 1ad7603..0000000
--- a/SOURCES/0051-ipa-use-only-the-global-catalog-service-of-the-fores.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-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
deleted file mode 100644
index c06a179..0000000
--- a/SOURCES/0052-LDAP-minor-refactoring-in-auth_send-to-conform-to-ou.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-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
deleted file mode 100644
index 7c781e7..0000000
--- a/SOURCES/0053-LDAP-Only-authenticate-the-auth-connection-if-we-nee.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-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
deleted file mode 100644
index 5a1c2bf..0000000
--- a/SOURCES/0054-LDAP-Log-the-encryption-used-during-LDAP-authenticat.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-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/SOURCES/0055-krb5_locator-always-use-port-88-for-master-KDC.patch b/SOURCES/0055-krb5_locator-always-use-port-88-for-master-KDC.patch
deleted file mode 100644
index 1bd571e..0000000
--- a/SOURCES/0055-krb5_locator-always-use-port-88-for-master-KDC.patch
+++ /dev/null
@@ -1,402 +0,0 @@
-From 941a381d7a7be2af73e41bd584aca4d22675d765 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 15 Feb 2019 16:54:19 +0100
-Subject: [PATCH] krb5_locator: always use port 88 for master KDC
-
-If the kpasswdinfo file exists and the found IP address includes a port
-number as well the master KDC lookup will use this port number which is
-most probably wrong. Better use the default port 88 always for master
-KDC lookups.
-
-This patch also updates the man page for the locator plugin which was
-quite outdated.
-
-Related to https://pagure.io/SSSD/sssd/issue/3958
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 05350abdf2ab98770ca296b9485578218644a2a7)
----
- src/krb5_plugin/sssd_krb5_locator_plugin.c    |  43 +++--
- src/man/sssd_krb5_locator_plugin.8.xml        |  76 +++++----
- .../cmocka/test_sssd_krb5_locator_plugin.c    | 156 ++++++++++++++++++
- 3 files changed, 233 insertions(+), 42 deletions(-)
-
-diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-index 952d487c2..fc5a4235d 100644
---- a/src/krb5_plugin/sssd_krb5_locator_plugin.c
-+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c
-@@ -80,6 +80,7 @@ struct sssd_ctx {
-     struct addr_port *kpasswd_addr;
-     bool debug;
-     bool disabled;
-+    bool kpasswdinfo_used;
- };
- 
- void plugin_debug_fn(const char *format, ...)
-@@ -411,6 +412,7 @@ krb5_error_code sssd_krb5_locator_init(krb5_context context,
-         ctx->disabled = true;
-         PLUGIN_DEBUG(("SSSD KRB5 locator plugin is disabled.\n"));
-     }
-+    ctx->kpasswdinfo_used = false;
- 
-     *private_data = ctx;
- 
-@@ -451,6 +453,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-     struct addr_port *addr = NULL;
-     char port_str[PORT_STR_SIZE];
-     size_t c;
-+    bool force_port = false;
- 
-     if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE;
-     ctx = (struct sssd_ctx *) private_data;
-@@ -478,20 +481,24 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-             return KRB5_PLUGIN_NO_HANDLE;
-         }
- 
--        if (svc == locate_service_kadmin || svc == locate_service_kpasswd ||
--            svc == locate_service_master_kdc) {
--            ret = get_krb5info(realm, ctx, locate_service_kpasswd);
-+    }
-+
-+    if (ctx->kpasswd_addr == NULL
-+            && (svc == locate_service_kadmin || svc == locate_service_kpasswd ||
-+                svc == locate_service_master_kdc)) {
-+        ret = get_krb5info(realm, ctx, locate_service_kpasswd);
-+        if (ret != EOK) {
-+            PLUGIN_DEBUG(("reading kpasswd address failed, "
-+                          "using kdc address.\n"));
-+            free_addr_port_list(&(ctx->kpasswd_addr));
-+            ret = copy_addr_port_list(ctx->kdc_addr, true,
-+                                      &(ctx->kpasswd_addr));
-             if (ret != EOK) {
--                PLUGIN_DEBUG(("reading kpasswd address failed, "
--                              "using kdc address.\n"));
--                free_addr_port_list(&(ctx->kpasswd_addr));
--                ret = copy_addr_port_list(ctx->kdc_addr, true,
--                                          &(ctx->kpasswd_addr));
--                if (ret != EOK) {
--                    PLUGIN_DEBUG(("copying address list failed.\n"));
--                    return KRB5_PLUGIN_NO_HANDLE;
--                }
-+                PLUGIN_DEBUG(("copying address list failed.\n"));
-+                return KRB5_PLUGIN_NO_HANDLE;
-             }
-+        } else {
-+            ctx->kpasswdinfo_used = true;
-         }
-     }
- 
-@@ -507,6 +514,12 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-         case locate_service_master_kdc:
-             addr = ctx->kpasswd_addr;
-             default_port = DEFAULT_KERBEROS_PORT;
-+            if (ctx->kpasswdinfo_used) {
-+                /* Use default port if the addresses from the kpasswdinfo
-+                 * files are used because the port numbers from the file will
-+                 * most probably not be suitable. */
-+                force_port = true;
-+            }
-             break;
-         case locate_service_kadmin:
-             addr = ctx->kpasswd_addr;
-@@ -539,11 +552,13 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
-             return KRB5_PLUGIN_NO_HANDLE;
-     }
- 
--    if (strcmp(realm, ctx->sssd_realm) != 0)
-+    if (strcmp(realm, ctx->sssd_realm) != 0 || addr == NULL) {
-         return KRB5_PLUGIN_NO_HANDLE;
-+    }
- 
-     for (c = 0; addr[c].addr != NULL; c++) {
--        port = (addr[c].port == 0 ? default_port : addr[c].port);
-+        port = ((addr[c].port == 0 || force_port) ? default_port
-+                                                  : addr[c].port);
-         memset(port_str, 0, PORT_STR_SIZE);
-         ret = snprintf(port_str, PORT_STR_SIZE-1, "%u", port);
-         if (ret < 0 || ret >= (PORT_STR_SIZE-1)) {
-diff --git a/src/man/sssd_krb5_locator_plugin.8.xml b/src/man/sssd_krb5_locator_plugin.8.xml
-index d28546012..d77f59d6a 100644
---- a/src/man/sssd_krb5_locator_plugin.8.xml
-+++ b/src/man/sssd_krb5_locator_plugin.8.xml
-@@ -20,40 +20,60 @@
-         <title>DESCRIPTION</title>
-         <para>
-             The Kerberos locator plugin
--            <command>sssd_krb5_locator_plugin</command> is used by the Kerberos
--            provider of
--            <citerefentry>
--                <refentrytitle>sssd</refentrytitle>
--                <manvolnum>8</manvolnum>
--            </citerefentry>
--            to tell the Kerberos libraries what Realm and which KDC to use.
--            Typically this is done in
-+            <command>sssd_krb5_locator_plugin</command> is used by libkrb5 to
-+            find KDCs for a given Kerberos realm. SSSD provides such a plugin to
-+            guide all Kerberos clients on a system to a single KDC. In general
-+            it should not matter to which KDC a client process is talking to.
-+            But there are cases, e.g. after a password change, where not all
-+            KDCs are in the same state because the new data has to be replicated
-+            first. To avoid unexpected authentication failures and maybe even
-+            account lockings it would be good to talk to a single KDC as long as
-+            possible.
-+        </para>
-+        <para>
-+            libkrb5 will search the locator plugin in the libkrb5 sub-directory
-+            of the Kerberos plugin directory, see plugin_base_dir in
-             <citerefentry>
-                 <refentrytitle>krb5.conf</refentrytitle>
-                 <manvolnum>5</manvolnum>
-             </citerefentry>
--            which is always read by the Kerberos libraries. To simplify the
--            configuration the Realm and the KDC can be defined in
--            <citerefentry>
--                <refentrytitle>sssd.conf</refentrytitle>
--                <manvolnum>5</manvolnum>
--            </citerefentry>
--            as described in
--            <citerefentry>
--                <refentrytitle>sssd-krb5</refentrytitle>
--                <manvolnum>5</manvolnum>
--            </citerefentry>
-+            for details. The plugin can only be disabled by removing the plugin
-+            file. There is no option in the Kerberos configuration to disable
-+            it. But the SSSD_KRB5_LOCATOR_DISABLE environment variable can be
-+            used to disable the plugin for individual commands. Alternatively
-+            the SSSD option krb5_use_kdcinfo=False can be used to not generate
-+            the data needed by the plugin. With this the plugin is still
-+            called but will provide no data to the caller so that libkrb5 can
-+            fall back to other methods defined in krb5.conf.
-         </para>
-         <para>
--            <citerefentry>
--                <refentrytitle>sssd</refentrytitle>
--                <manvolnum>8</manvolnum>
--            </citerefentry>
--            puts the Realm and the name or IP address of the KDC into the
--            environment variables SSSD_KRB5_REALM and SSSD_KRB5_KDC respectively.
--            When <command>sssd_krb5_locator_plugin</command> is called by the
--            kerberos libraries it reads and evaluates these variables and returns
--            them to the libraries.
-+            The plugin reads the information about the KDCs of a given realm
-+            from a file called <filename>kdcinfo.REALM</filename>. The file
-+            should contain one or more IP addresses either in dotted-decimal
-+            IPv4 notation or the hexadecimal IPv6 notation. An optional port
-+            number can be added to the end separated with a colon, the IPv6
-+            address has to be enclosed in squared brackets in this case as
-+            usual. Valid entries are:
-+            <itemizedlist>
-+                <listitem><para>1.2.3.4</para></listitem>
-+                <listitem><para>5.6.7.8:99</para></listitem>
-+                <listitem><para>2001:db8:85a3::8a2e:370:7334</para></listitem>
-+                <listitem><para>[2001:db8:85a3::8a2e:370:7334]:321</para></listitem>
-+            </itemizedlist>
-+            SSSD's krb5 auth-provider which is used by the IPA and AD providers
-+            as well adds the address of the current KDC or domain controller
-+            SSSD is using to this file.
-+        </para>
-+        <para>
-+            In environments with read-only and read-write KDCs where clients are
-+            expected to use the read-only instances for the general operations
-+            and only the read-write KDC for config changes like password changes
-+            a <filename>kpasswdinfo.REALM</filename> is used as well to identify
-+            read-write KDCs. If this file exists for the given realm the content
-+            will be used by the plugin to reply to requests for a kpasswd or
-+            kadmin server or for the MIT Kerberos specific master KDC. If the
-+            address contains a port number the default KDC port 88 will be used
-+            for the latter.
-         </para>
-     </refsect1>
- 
-diff --git a/src/tests/cmocka/test_sssd_krb5_locator_plugin.c b/src/tests/cmocka/test_sssd_krb5_locator_plugin.c
-index 3e7d00632..1b6838345 100644
---- a/src/tests/cmocka/test_sssd_krb5_locator_plugin.c
-+++ b/src/tests/cmocka/test_sssd_krb5_locator_plugin.c
-@@ -44,6 +44,9 @@
- #define TEST_IP_1_WITH_SERVICE TEST_IP_1":"TEST_SERVICE_1
- #define TEST_IPV6_1_WITH_SERVICE TEST_IPV6_1":"TEST_SERVICE_2
- 
-+#define TEST_IP_1_WITH_SERVICE_2 TEST_IP_1":"TEST_SERVICE_2
-+#define TEST_IPV6_1_WITH_SERVICE_1 TEST_IPV6_1":"TEST_SERVICE_1
-+
- struct test_state {
-     void *dummy;
- };
-@@ -61,6 +64,7 @@ static int setup(void **state)
-     *state = (void *)ts;
- 
-     unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-+    unlink(TEST_PUBCONF_PATH"/kpasswdinfo."TEST_REALM);
-     rmdir(TEST_PUBCONF_PATH);
- 
-     return 0;
-@@ -574,7 +578,157 @@ void test_service(void **state)
- 
-     k5_free_serverlist(&list);
- 
-+    /* locate_service_master_kdc should get the default port 88 if kpasswdinfo
-+     * does not exists. */
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IP_1, host);
-+    assert_string_equal("88", service);
-+
-+    k5_free_serverlist(&list);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IPV6_1_PURE, host);
-+    assert_string_equal("88", service);
-+
-+    k5_free_serverlist(&list);
-+
-+    unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-+    rmdir(TEST_PUBCONF_PATH);
-+    sssd_krb5_locator_close(priv);
-+
-+    krb5_free_context(ctx);
-+}
-+
-+void test_kpasswd_and_master_kdc(void **state)
-+{
-+    krb5_context ctx;
-+    krb5_error_code kerr;
-+    void *priv;
-+    int fd;
-+    struct serverlist list = SERVERLIST_INIT;
-+    struct module_callback_data cbdata = { 0 };
-+    ssize_t s;
-+    int ret;
-+    char host[NI_MAXHOST];
-+    char service[NI_MAXSERV];
-+
-+    cbdata.list = &list;
-+
-+    kerr = krb5_init_context (&ctx);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = sssd_krb5_locator_init(ctx, &priv);
-+    assert_int_equal(kerr, 0);
-+
-+    mkdir(TEST_PUBCONF_PATH, 0777);
-+    fd = open(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM, O_CREAT|O_RDWR, 0777);
-+    assert_int_not_equal(fd, -1);
-+    s = write(fd, TEST_IP_1_WITH_SERVICE, sizeof(TEST_IP_1_WITH_SERVICE));
-+    assert_int_equal(s, sizeof(TEST_IP_1_WITH_SERVICE));
-+    s = write(fd, "\n", 1);
-+    assert_int_equal(s, 1);
-+    s = write(fd, TEST_IPV6_1_WITH_SERVICE, sizeof(TEST_IPV6_1_WITH_SERVICE));
-+    assert_int_equal(s, sizeof(TEST_IPV6_1_WITH_SERVICE));
-+    close(fd);
-+    fd = open(TEST_PUBCONF_PATH"/kpasswdinfo."TEST_REALM, O_CREAT|O_RDWR, 0777);
-+    assert_int_not_equal(fd, -1);
-+    s = write(fd, TEST_IP_1_WITH_SERVICE_2, sizeof(TEST_IP_1_WITH_SERVICE_2));
-+    assert_int_equal(s, sizeof(TEST_IP_1_WITH_SERVICE_2));
-+    s = write(fd, "\n", 1);
-+    assert_int_equal(s, 1);
-+    s = write(fd, TEST_IPV6_1_WITH_SERVICE_1,
-+              sizeof(TEST_IPV6_1_WITH_SERVICE_1));
-+    assert_int_equal(s, sizeof(TEST_IPV6_1_WITH_SERVICE_1));
-+    close(fd);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kpasswd, TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IP_1, host);
-+    assert_string_equal(TEST_SERVICE_2, service);
-+
-+    k5_free_serverlist(&list);
-+
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_kpasswd , TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IPV6_1_PURE, host);
-+    assert_string_equal(TEST_SERVICE_1, service);
-+
-+    k5_free_serverlist(&list);
-+
-+    /* locate_service_master_kdc should use the default KDC port 88 and not
-+     * the one set in the kpasswdinfo file. */
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IP_1, host);
-+    assert_string_equal("88", service);
-+
-+    k5_free_serverlist(&list);
- 
-+    kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM,
-+                                    SOCK_DGRAM, AF_INET6, module_callback,
-+                                    &cbdata);
-+    assert_int_equal(kerr, 0);
-+    assert_int_equal(list.nservers, 1);
-+    assert_non_null(list.servers);
-+    ret = getnameinfo((struct sockaddr *) &list.servers[0].addr,
-+                      list.servers[0].addrlen,
-+                      host, sizeof(host), service, sizeof(service),
-+                      NI_NUMERICHOST|NI_NUMERICSERV);
-+    assert_int_equal(ret, 0);
-+    assert_string_equal(TEST_IPV6_1_PURE, host);
-+    assert_string_equal("88", service);
-+
-+    k5_free_serverlist(&list);
-+
-+    unlink(TEST_PUBCONF_PATH"/kpasswdinfo."TEST_REALM);
-     unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM);
-     rmdir(TEST_PUBCONF_PATH);
-     sssd_krb5_locator_close(priv);
-@@ -606,6 +760,8 @@ int main(int argc, const char *argv[])
-                                         setup, teardown),
-         cmocka_unit_test_setup_teardown(test_service,
-                                         setup, teardown),
-+        cmocka_unit_test_setup_teardown(test_kpasswd_and_master_kdc,
-+                                        setup, teardown),
-     };
- 
-     /* Set debug level to invalid value so we can decide if -d 0 was used. */
--- 
-2.19.1
-
diff --git a/SOURCES/0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch b/SOURCES/0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch
deleted file mode 100644
index ca07f08..0000000
--- a/SOURCES/0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch
+++ /dev/null
@@ -1,358 +0,0 @@
-From 118c44f90c9c901ffbf1b676be57b7a83a190399 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 30 Nov 2018 13:06:13 +0100
-Subject: [PATCH] NSS: Avoid changing the memory cache ownership away from the
- sssd user
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves:
-https://pagure.io/SSSD/sssd/issue/3890
-
-In case SSSD is compiled --with-sssd-user but run as root (which is the
-default on RHEL and derivatives), then the memory cache will be owned by
-the user that sssd_nss runs as, so root.
-
-This conflicts with the packaging which specifies sssd.sssd as the owner. And
-in turn, this means that users can't reliably assess the package integrity
-using rpm -V.
-
-This patch makes sure that the memory cache files are chowned to sssd.sssd
-even if the nss responder runs as root.
-
-Also, this patch changes the sssd_nss responder so that is becomes a member
-of the supplementary sssd group. Even though in traditional UNIX sense,
-a process running as root could write to a file owned by sssd:sssd, with
-SELinux enforcing mode this becomes problematic as SELinux emits an error
-such as:
-
-type=AVC msg=audit(1543524888.125:1495): avc:  denied  { fsetid } for
-pid=7706 comm="sssd_nss" capability=4  scontext=system_u:system_r:sssd_t:s0
-tcontext=system_u:system_r:sssd_t:s0 tclass=capability
-
-To make it possible for the sssd_nss process to write to the files, the
-files are also made group-writable. The 'others' permission is still set
-to read only.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
-(cherry picked from commit 61e4ba58934b20a950255e05797aca25aadc1242)
----
- src/responder/nss/nss_private.h       |   2 +
- src/responder/nss/nsssrv.c            | 106 ++++++++++++++++++++++++--
- src/responder/nss/nsssrv_mmap_cache.c |  51 ++++++++++++-
- src/responder/nss/nsssrv_mmap_cache.h |   5 +-
- 5 files changed, 154 insertions(+), 10 deletions(-)
-
-diff --git a/src/responder/nss/nss_private.h b/src/responder/nss/nss_private.h
-index cd0d35517..bae5fe074 100644
---- a/src/responder/nss/nss_private.h
-+++ b/src/responder/nss/nss_private.h
-@@ -87,6 +87,8 @@ struct nss_ctx {
-     struct sss_mc_ctx *pwd_mc_ctx;
-     struct sss_mc_ctx *grp_mc_ctx;
-     struct sss_mc_ctx *initgr_mc_ctx;
-+    uid_t mc_uid;
-+    gid_t mc_gid;
- };
- 
- struct sss_cmd_table *get_nss_cmds(void);
-diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
-index d6c5a08a9..87a3f1d50 100644
---- a/src/responder/nss/nsssrv.c
-+++ b/src/responder/nss/nsssrv.c
-@@ -101,7 +101,8 @@ static int nss_clear_memcache(struct sbus_request *dbus_req, void *data)
- 
-     /* TODO: read cache sizes from configuration */
-     DEBUG(SSSDBG_TRACE_FUNC, "Clearing memory caches.\n");
--    ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS,
-+    ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid,
-+                                SSS_MC_CACHE_ELEMENTS,
-                                 (time_t) memcache_timeout,
-                                 &nctx->pwd_mc_ctx);
-     if (ret != EOK) {
-@@ -110,7 +111,8 @@ static int nss_clear_memcache(struct sbus_request *dbus_req, void *data)
-         return ret;
-     }
- 
--    ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS,
-+    ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid,
-+                                SSS_MC_CACHE_ELEMENTS,
-                                 (time_t) memcache_timeout,
-                                 &nctx->grp_mc_ctx);
-     if (ret != EOK) {
-@@ -119,7 +121,8 @@ static int nss_clear_memcache(struct sbus_request *dbus_req, void *data)
-         return ret;
-     }
- 
--    ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS,
-+    ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid,
-+                                SSS_MC_CACHE_ELEMENTS,
-                                 (time_t)memcache_timeout,
-                                 &nctx->initgr_mc_ctx);
-     if (ret != EOK) {
-@@ -284,21 +287,27 @@ static int setup_memcaches(struct nss_ctx *nctx)
-     }
- 
-     /* TODO: read cache sizes from configuration */
--    ret = sss_mmap_cache_init(nctx, "passwd", SSS_MC_PASSWD,
-+    ret = sss_mmap_cache_init(nctx, "passwd",
-+                              nctx->mc_uid, nctx->mc_gid,
-+                              SSS_MC_PASSWD,
-                               SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout,
-                               &nctx->pwd_mc_ctx);
-     if (ret) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "passwd mmap cache is DISABLED\n");
-     }
- 
--    ret = sss_mmap_cache_init(nctx, "group", SSS_MC_GROUP,
-+    ret = sss_mmap_cache_init(nctx, "group",
-+                              nctx->mc_uid, nctx->mc_gid,
-+                              SSS_MC_GROUP,
-                               SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout,
-                               &nctx->grp_mc_ctx);
-     if (ret) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "group mmap cache is DISABLED\n");
-     }
- 
--    ret = sss_mmap_cache_init(nctx, "initgroups", SSS_MC_INITGROUPS,
-+    ret = sss_mmap_cache_init(nctx, "initgroups",
-+                              nctx->mc_uid, nctx->mc_gid,
-+                              SSS_MC_INITGROUPS,
-                               SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout,
-                               &nctx->initgr_mc_ctx);
-     if (ret) {
-@@ -308,6 +317,79 @@ static int setup_memcaches(struct nss_ctx *nctx)
-     return EOK;
- }
- 
-+static int sssd_supplementary_group(struct nss_ctx *nss_ctx)
-+{
-+    errno_t ret;
-+    int size;
-+    gid_t *supp_gids = NULL;
-+
-+    /*
-+     * We explicitly read the IDs of the SSSD user even though the server
-+     * receives --uid and --gid by parameters to account for the case where
-+     * the SSSD is compiled --with-sssd-user=sssd but the default of the
-+     * user option is root (this is what RHEL does)
-+     */
-+    ret = sss_user_by_name_or_uid(SSSD_USER,
-+                                  &nss_ctx->mc_uid,
-+                                  &nss_ctx->mc_gid);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "Cannot get info on "SSSD_USER);
-+        return ret;
-+    }
-+
-+    if (getgid() == nss_ctx->mc_gid) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "Already running as the sssd group\n");
-+        return EOK;
-+    }
-+
-+    size = getgroups(0, NULL);
-+    if (size == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Getgroups failed! (%d, %s)\n",
-+                                    ret, sss_strerror(ret));
-+        return ret;
-+    }
-+
-+    if (size > 0) {
-+        supp_gids = talloc_zero_array(NULL, gid_t, size);
-+        if (supp_gids == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Allocation failed!\n");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+    }
-+
-+    size = getgroups(size, supp_gids);
-+    if (size == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Getgroups failed! (%d, %s)\n",
-+                                    ret, sss_strerror(ret));
-+        goto done;
-+    }
-+
-+    for (int i = 0; i < size; i++) {
-+        if (supp_gids[i] == nss_ctx->mc_gid) {
-+            DEBUG(SSSDBG_TRACE_FUNC,
-+                  "Already assigned to the SSSD supplementary group\n");
-+            ret = EOK;
-+            goto done;
-+        }
-+    }
-+
-+    ret = setgroups(1, &nss_ctx->mc_gid);
-+    if (ret != EOK) {
-+        ret = errno;
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "Cannot setgroups [%d]: %s\n", ret, sss_strerror(ret));
-+        goto done;
-+    }
-+
-+    ret = EOK;
-+done:
-+    talloc_free(supp_gids);
-+    return ret;
-+}
-+
- int nss_process_init(TALLOC_CTX *mem_ctx,
-                      struct tevent_context *ev,
-                      struct confdb_ctx *cdb)
-@@ -405,6 +487,18 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
-         ret = EFAULT;
-         goto fail;
-     }
-+    /*
-+     * Adding the NSS process to the SSSD supplementary group avoids
-+     * dac_override AVC messages from SELinux in case sssd_nss runs
-+     * as root and tries to write to memcache owned by sssd:sssd
-+     */
-+    ret = sssd_supplementary_group(nctx);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Cannot add process to the sssd supplementary group [%d]: %s\n",
-+              ret, sss_strerror(ret));
-+        goto fail;
-+    }
- 
-     ret = setup_memcaches(nctx);
-     if (ret != EOK) {
-diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
-index de9e67513..d5181d771 100644
---- a/src/responder/nss/nsssrv_mmap_cache.c
-+++ b/src/responder/nss/nsssrv_mmap_cache.c
-@@ -57,6 +57,9 @@ struct sss_mc_ctx {
-     char *file;             /* mmap cache file name */
-     int fd;                 /* file descriptor */
- 
-+    uid_t uid;              /* User ID of owner */
-+    gid_t gid;              /* Group ID of owner */
-+
-     uint32_t seed;          /* pseudo-random seed to avoid collision attacks */
-     time_t valid_time_slot; /* maximum time the entry is valid in seconds */
- 
-@@ -623,7 +626,9 @@ static errno_t sss_mc_get_record(struct sss_mc_ctx **_mcc,
-         if (ret == EFAULT) {
-             DEBUG(SSSDBG_CRIT_FAILURE,
-                   "Fatal internal mmap cache error, invalidating cache!\n");
--            (void)sss_mmap_cache_reinit(talloc_parent(mcc), -1, -1, _mcc);
-+            (void)sss_mmap_cache_reinit(talloc_parent(mcc),
-+                                        -1, -1, -1, -1,
-+                                        _mcc);
-         }
-         return ret;
-     }
-@@ -1144,6 +1149,26 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx)
-         return ret;
-     }
- 
-+    /* Make sure that the memory cache files are chowned to sssd.sssd even
-+     * if the nss responder runs as root. This is because the specfile
-+     * has the ownership recorded as sssd.sssd
-+     */
-+    ret = fchown(mc_ctx->fd, mc_ctx->uid, mc_ctx->gid);
-+    if (ret != 0) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to chown mmap file %s: %d(%s)\n",
-+                                   mc_ctx->file, ret, strerror(ret));
-+        return ret;
-+    }
-+
-+    ret = fchmod(mc_ctx->fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to chmod mmap file %s: %d(%s)\n",
-+                                   mc_ctx->file, ret, strerror(ret));
-+        return ret;
-+    }
-+
-     ret = sss_br_lock_file(mc_ctx->fd, 0, 1, retries, t);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE,
-@@ -1224,6 +1249,7 @@ static int mc_ctx_destructor(struct sss_mc_ctx *mc_ctx)
- }
- 
- errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
-+                            uid_t uid, gid_t gid,
-                             enum sss_mc_type type, size_t n_elem,
-                             time_t timeout, struct sss_mc_ctx **mcc)
- {
-@@ -1259,6 +1285,9 @@ errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
-         goto done;
-     }
- 
-+    mc_ctx->uid = uid;
-+    mc_ctx->gid = gid;
-+
-     mc_ctx->type = type;
- 
-     mc_ctx->valid_time_slot = timeout;
-@@ -1352,7 +1381,9 @@ done:
-     return ret;
- }
- 
--errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
-+errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx,
-+                              uid_t uid, gid_t gid,
-+                              size_t n_elem,
-                               time_t timeout, struct sss_mc_ctx **mc_ctx)
- {
-     errno_t ret;
-@@ -1389,12 +1420,26 @@ errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
-         timeout = (*mc_ctx)->valid_time_slot;
-     }
- 
-+    if (uid == (uid_t)-1) {
-+        uid = (*mc_ctx)->uid;
-+    }
-+
-+    if (gid == (gid_t)-1) {
-+        gid = (*mc_ctx)->gid;
-+    }
-+
-     talloc_free(*mc_ctx);
- 
-     /* make sure we do not leave a potentially freed pointer around */
-     *mc_ctx = NULL;
- 
--    ret = sss_mmap_cache_init(mem_ctx, name, type, n_elem, timeout, mc_ctx);
-+    ret = sss_mmap_cache_init(mem_ctx,
-+                              name,
-+                              uid, gid,
-+                              type,
-+                              n_elem,
-+                              timeout,
-+                              mc_ctx);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to re-initialize mmap cache.\n");
-         goto done;
-diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h
-index b84fbc8ed..e06257949 100644
---- a/src/responder/nss/nsssrv_mmap_cache.h
-+++ b/src/responder/nss/nsssrv_mmap_cache.h
-@@ -34,6 +34,7 @@ enum sss_mc_type {
- };
- 
- errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
-+                            uid_t uid, gid_t gid,
-                             enum sss_mc_type type, size_t n_elem,
-                             time_t valid_time, struct sss_mc_ctx **mcc);
- 
-@@ -70,7 +71,9 @@ errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid);
- errno_t sss_mmap_cache_initgr_invalidate(struct sss_mc_ctx *mcc,
-                                          struct sized_string *name);
- 
--errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
-+errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx,
-+                              uid_t uid, gid_t gid,
-+                              size_t n_elem,
-                               time_t timeout, struct sss_mc_ctx **mc_ctx);
- 
- void sss_mmap_cache_reset(struct sss_mc_ctx *mc_ctx);
--- 
-2.19.1
-
diff --git a/SOURCES/1000-DOWNSTREAM-Use-OpenSSL-for-the-obfuscation-code.patch b/SOURCES/1000-DOWNSTREAM-Use-OpenSSL-for-the-obfuscation-code.patch
new file mode 100644
index 0000000..8580651
--- /dev/null
+++ b/SOURCES/1000-DOWNSTREAM-Use-OpenSSL-for-the-obfuscation-code.patch
@@ -0,0 +1,69 @@
+From 8232c1005e56393422b0b1e6018e308ebc4fb4c1 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 11 Apr 2019 22:39:03 +0200
+Subject: [PATCH] DOWNSTREAM: Use OpenSSL for the obfuscation code
+
+---
+ Makefile.am                         | 6 ++++++
+ configure.ac                        | 7 +++++++
+ src/util/crypto/nss/nss_obfuscate.c | 5 +++++
+ 3 files changed, 18 insertions(+)
+
+diff --git a/Makefile.am b/Makefile.am
+index 0c24ae664..8b1f4f144 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -954,6 +954,12 @@ else
+         $(NULL)
+ endif
+ 
++if OBF_WITH_LIBCRYPTO
++SSS_CRYPT_SOURCES += src/util/crypto/libcrypto/crypto_obfuscate.c
++SSS_CRYPT_CFLAGS += $(CRYPTO_CFLAGS)
++SSS_CRYPT_LIBS += $(CRYPTO_LIBS)
++endif
++
+ libsss_crypt_la_SOURCES = \
+     $(SSS_CRYPT_SOURCES)
+ libsss_crypt_la_CFLAGS = \
+diff --git a/configure.ac b/configure.ac
+index 9df463d9c..c3b349af4 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -391,6 +391,13 @@ if test x$cryptolib = xnss; then
+     AM_CHECK_NSS
+ fi
+ 
++dnl RHEL-specific: We always check for libcrypto because the obfuscation
++dnl feature is only implemented with OpenSSL as the NSS version doesn't
++dnl run in FIPS mode
++AM_CHECK_LIBCRYPTO
++AM_CONDITIONAL([OBF_WITH_LIBCRYPTO], [test x == x])
++AC_DEFINE_UNQUOTED(OBF_WITH_LIBCRYPTO, 1, [Build the obfuscation feature with libcrypt crypto back end])
++
+ if test x$cryptolib = xlibcrypto; then
+     AM_CHECK_LIBCRYPTO
+     m4_include([src/external/p11-kit.m4])
+diff --git a/src/util/crypto/nss/nss_obfuscate.c b/src/util/crypto/nss/nss_obfuscate.c
+index df9c41b3a..bf2a5f418 100644
+--- a/src/util/crypto/nss/nss_obfuscate.c
++++ b/src/util/crypto/nss/nss_obfuscate.c
+@@ -31,6 +31,9 @@
+  */
+ 
+ #include "config.h"
++
++#ifndef OBF_WITH_LIBCRYPTO
++
+ #include <prerror.h>
+ #include <pk11func.h>
+ 
+@@ -326,3 +329,5 @@ done:
+     talloc_free(tmp_ctx);
+     return ret;
+ }
++
++#endif /* OBF_WITH_LIBCRYPTO */
+-- 
+2.19.2
+
diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec
index ca52f84..1db58d0 100644
--- a/SPECS/sssd.spec
+++ b/SPECS/sssd.spec
@@ -47,8 +47,8 @@
 %endif
 
 Name: sssd
-Version: 1.16.2
-Release: 13%{?dist}.8
+Version: 1.16.4
+Release: 21%{?dist}
 Group: Applications/System
 Summary: System Security Services Daemon
 License: GPLv3+
@@ -57,65 +57,43 @@ Source0: https://releases.pagure.org/SSSD/sssd/sssd-%{version}.tar.gz
 BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
 ### Patches ###
-Patch0001: 0001-krb5-locator-add-support-for-multiple-addresses.patch
-Patch0002: 0002-krb5-locator-fix-IPv6-support.patch
-Patch0003: 0003-krb5-locator-make-plugin-more-robust.patch
-Patch0004: 0004-krb5-locator-add-unit-tests.patch
-Patch0005: 0005-AD-IPA-Create-kdcinfo-file-for-sub-domains.patch
-Patch0006: 0006-krb5-refactor-removal-of-krb5info-files.patch
-Patch0007: 0007-krb5_common-add-callback-only-once.patch
-Patch0008: 0008-data-provider-run-offline-callbacks-only-once.patch
-Patch0009: 0009-TESTS-Extend-the-schema-with-sshPublicKey-attribute.patch
-Patch0010: 0010-TESTS-Allow-adding-sshPublicKey-for-users.patch
-Patch0011: 0011-TESTS-Add-a-basic-SSH-responder-test.patch
-Patch0012: 0012-SSH-Do-not-exit-abruptly-if-SSHD-closes-its-end-of-t.patch
-Patch0013: 0013-TESTS-Add-a-helper-binary-that-can-trigger-the-SIGPI.patch
-Patch0014: 0014-TESTS-Add-a-regression-test-for-SIGHUP-handling-in-s.patch
-Patch0015: 0015-Revert-LDAP-IPA-add-local-email-address-to-aliases.patch
-Patch0016: 0016-util-Remove-the-unused-function-is_email_from_domain.patch
-Patch0017: 0017-TESTS-Allow-storing-e-mail-address-for-users.patch
-Patch0018: 0018-TESTS-Add-regression-test-for-looking-up-users-with-.patch
-Patch0019: 0019-MAN-Remove-outdated-notes-from-the-re_expression-des.patch
-Patch0020: 0020-SUDO-Create-the-socket-with-stricter-permissions.patch
-Patch0021: 0021-MAN-Give-information-regarding-priority-of-ldap-look.patch
-Patch0022: 0022-AD-LDAP-Do-not-misuse-the-ignore_mark_offline-to-che.patch
-Patch0023: 0023-AD-expose-the-helper-function-to-format-the-site-DNS.patch
-Patch0024: 0024-RESOLV-Add-a-resolv_hostport_list-request.patch
-Patch0025: 0025-KRB5-IPA-AD-Add-a-utility-function-to-create-a-krb5_.patch
-Patch0026: 0026-KRB5-Allow-writing-multiple-addresses-to-the-kdcinfo.patch
-Patch0027: 0027-IPA-Add-the-options-that-the-IPA-subdomains-code-wil.patch
-Patch0028: 0028-IPA-Populate-kdcinfo-files-on-trust-clients-with-con.patch
-Patch0029: 0029-MAN-Document-the-options-available-for-AD-trusted-do.patch
-Patch0030: 0030-AD-consider-resource_groups-in-PAC-as-well.patch
-Patch0031: 0031-LDAP-Remove-the-legacy-POSIX-check-itself.patch
-Patch0032: 0032-LDAP-AD-Remove-the-legacy-POSIX-check-from-user-grou.patch
-Patch0033: 0033-AD-Remove-the-legacy-check-from-ad_get_account_domai.patch
-Patch0034: 0034-AD-Add-Global-Catalog-usability-check-in-subdomain-c.patch
-Patch0035: 0035-SDAP-Detect-schemaNamingContext-from-the-rootDSE.patch
-Patch0036: 0036-deskprofile-don-t-bail-if-we-fail-to-save-one-profil.patch
-Patch0037: 0037-SUDO-Fix-running-in-unprivileged-responder.patch
-Patch0038: 0038-SUDO-Root-should-be-able-to-read-write-sssd-sudo-soc.patch
-Patch0039: 0039-sdap-respect-passwordGracelimit.patch
-Patch0040: 0040-MC-Remove-check-if-record-is-in-the-mapped-address-s.patch
-Patch0041: 0041-Revert-CRYPTO-Suppress-warning-Wstringop-truncation.patch
-Patch0042: 0042-Revert-Revert-CRYPTO-Suppress-warning-Wstringop-trun.patch
-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
-Patch0055: 0055-krb5_locator-always-use-port-88-for-master-KDC.patch
-Patch0056: 0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch
+Patch0001: 0001-Providers-Delay-online-check-on-startup.patch
+Patch0002: 0002-KCM-Fall-back-to-using-the-first-ccache-if-the-defau.patch
+Patch0003: 0003-GPO-Add-option-ad_gpo_ignore_unreadable.patch
+Patch0004: 0004-AD-Allow-configuring-auto_private_groups-per-subdoma.patch
+Patch0005: 0005-ipa-store-sudo-runas-attribute-with-internal-fqname.patch
+Patch0006: 0006-sudo-format-runas-attributes-to-correct-output-name.patch
+Patch0007: 0007-SYSDB-Inherit-cached_auth_timeout-from-the-main-doma.patch
+Patch0008: 0008-krb5-Do-not-use-unindexed-objectCategory-in-a-search.patch
+Patch0009: 0009-SYSDB-Index-the-ccacheFile-attribute.patch
+Patch0010: 0010-krb5-Silence-an-error-message-if-no-cache-entries-ha.patch
+Patch0011: 0011-Util-added-facility-to-load-nss-lib-syms.patch
+Patch0012: 0012-responder-negcache-avoid-calling-nsswitch-NSS-API.patch
+Patch0013: 0013-negcache_files-got-rid-of-large-array-on-stack.patch
+Patch0014: 0014-TESTS-moved-cwrap-test_negcache-to-cmocka-tests.patch
+Patch0015: 0015-ci-sssd.supp-getpwuid-leak-suppression.patch
+Patch0016: 0016-pam-introduce-prompt_config-struct.patch
+Patch0017: 0017-authtok-add-dedicated-type-for-2fa-with-single-strin.patch
+Patch0018: 0018-pam_sss-use-configured-prompting.patch
+Patch0019: 0019-PAM-add-initial-prompting-configuration.patch
+Patch0020: 0020-getsockopt_wrapper-add-support-for-PAM-clients.patch
+Patch0021: 0021-intg-add-test-for-password-prompt-configuration.patch
+Patch0022: 0022-krb5-Write-multiple-dnsnames-into-kdc-info-file.patch
+Patch0023: 0023-krb5-Lookahead-resolving-of-host-names.patch
+Patch0024: 0024-SDAP-Add-sdap_has_deref_support_ex.patch
+Patch0025: 0025-IPA-Use-dereference-for-host-groups-even-if-the-conf.patch
+Patch0026: 0026-PAM-Also-cache-SSS_PAM_PREAUTH.patch
+Patch0027: 0027-winbind-idmap-plugin-update-struct-idmap_domain-to-l.patch
+Patch0028: 0028-DP-add-NULL-check-to-be_ptask_-enable-disable.patch
+Patch0029: 0029-LDAP-Return-the-error-message-from-the-extended-oper.patch
+Patch0030: 0030-SDAP-allow-GSS-SPNEGO-for-LDAP-SASL-bind-as-well.patch
+Patch0031: 0031-sdap-inherit-SDAP_SASL_MECH-if-not-set-explicitly.patch
+Patch0032: 0032-Translation-Update-japanese-translation.patch
+Patch0033: 0033-Translation-Add-missing-newlines-in-the-ja-po-file.patch
 
 #This patch should not be removed in RHEL-7
 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec
+Patch1000: 1000-DOWNSTREAM-Use-OpenSSL-for-the-obfuscation-code.patch
 
 ### Dependencies ###
 
@@ -150,6 +128,9 @@ BuildRequires: libtalloc-devel
 BuildRequires: libtevent-devel
 BuildRequires: libtdb-devel
 
+# Needed since this downstream only fix: rhbz#1524566
+BuildRequires: openssl-devel
+
 # LDB needs a strict version match to build
 BuildRequires: libldb-devel >= %{ldb_version}
 BuildRequires: libdhash-devel >= 0.4.2
@@ -648,6 +629,7 @@ autoreconf -ivf
     %{?with_idmap_version}
 
 make %{?_smp_mflags} all docs
+make -C po ja.gmo # TODO: Rebuild all gmo files all remove this in next rebase
 
 %check
 export CK_TIMEOUT_MULTIPLIER=10
@@ -1265,35 +1247,106 @@ systemctl try-restart sssd >/dev/null 2>&1 || :
 }
 
 %changelog
-* Tue Mar 26 2019 Michal Židek <mzidek@redhat.com> - 1.16.2-13.8
-- Resolves: rhbz#1690759 - RHEL STIG pointing sssd Packaging issue [rhel-7.6.z]
-                         - Part 2.
-
-* Tue Mar 26 2019 Michal Židek <mzidek@redhat.com> - 1.16.2-13.7
-- Resolves: rhbz#1690759 - RHEL STIG pointing sssd Packaging issue [rhel-7.6.z]
-
-* Tue Dec 18 2018 Michal Židek <mzidek@redhat.com> - 1.16.2-13.6
-- Resolves: rhbz#1683578 - sssd_krb5_locator_plugin introduces delay in
-                           cifs.upcall krb5 calls [rhel-7.6.z]
-
-* Tue Dec 18 2018 Michal Židek <mzidek@redhat.com> - 1.16.2-13.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.2-13.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.2-13.3
-- Resolves: rhbz#1656833 - sssd_nss memory leak [rhel-7.6.z]
-
-* Wed Nov 28 2018 Michal Židek <mzidek@redhat.com> - 1.16.2-13.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.2-13.1
-- Resolves: rhbz#1645047 - sssd only sets the SELinux login context if it
-                           differs from the default [rhel-7.6.z]
+* Fri Jun 07 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-21
+- Resolves: rhbz#1714952 - [sssd] RHEL 7.7 Tier 0 Localization
+- Rebuild japanese gmo file explicitly
+
+* Fri Jun 07 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-20
+- Resolves: rhbz#1714952 - [sssd] RHEL 7.7 Tier 0 Localization
+
+* Tue May 28 2019 Jakub Hrozek <jhrozek@redhat.com> - 1.16.4-19
+- Resolves: rhbz#1707959 - sssd does not properly check GSS-SPNEGO
+
+* Tue May 28 2019 Jakub Hrozek <jhrozek@redhat.com> - 1.16.4-18
+- Resolves: rhbz#1710286 - The server error message is not returned if
+                           password change fails
+
+* Tue May 28 2019 Jakub Hrozek <jhrozek@redhat.com> - 1.16.4-17
+- Resolves: rhbz#1711832 - The files provider does not handle resetOffline
+                           properly
+
+* Mon May 20 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-16
+- Resolves: rhbz#1707759 - Error accessing files on samba share randomly
+
+* Mon May 20 2019 Jakub Hrozek <jhrozek@redhat.com> - 1.16.4-15
+- Resolves: rhbz#1685581 - Extend cached_auth_timeout to cover subdomains
+                           /trusts
+
+* Mon Apr 15 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-14
+- Resolves: rhbz#1684979 - The HBAC code requires dereference to be enabled
+                           and fails otherwise
+
+* Mon Apr 15 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-12
+- Resolves: rhbz#1576524 - RHEL STIG pointing sssd Packaging issue
+                         - This was partially fixed by the rebase, but one
+                           spec file change was missing.
+
+* Mon Apr 15 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-12
+- Resolves: rhbz#1524566 - FIPS mode breaks using pysss.so (sss_obfuscate)
+
+* Thu Apr 04 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-11
+- Resolves: rhbz#1350012 - kinit / sssd kerberos fail over
+- Resolves: rhbz#720688 - [RFE] return multiple server addresses to the
+                          Kerberos locator plugin
+
+* Thu Apr 04 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-10
+- Resolves: rhbz#1402056 - [RFE] Make 2FA prompting configurable
+
+* Thu Apr 04 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-9
+- Resolves: rhbz#1666819 - SSSD can trigger a NSS lookup when parsing the
+                           filter_users/groups lists on startup, this can
+                           block the startup
+
+* Fri Mar 29 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-8
+- Resolves: rhbz#1645461 - Slow ldb search causes blocking during startup
+                           which might cause the registration to time out
+
+* Fri Mar 29 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-7
+- Resolves: rhbz#1685581 - Extend cached_auth_timeout to cover
+                           subdomains / trusts
+
+* Fri Mar 29 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-6
+- Resolves: rhbz#1671138 - User is unable to perform sudo as a user on IPA
+                           Server, even though `sudo -l` shows permissions
+                           to do so
+
+* Fri Mar 29 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-5
+- Resolves: rhbz#1657806 - [RFE]: Optionally disable generating auto private
+                           groups for subdomains of an AD provider
+
+* Fri Mar 29 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-4
+- Resolves: rhbz#1641131 - [RFE] Need an option in SSSD so that it will skip
+                           GPOs that have groupPolicyContainers, unreadable
+                           by SSSD.
+- Resolves: rhbz#1660874 - CVE-2018-16838 sssd: improper implementation of
+                           GPOs due to too restrictive permissions [rhel-7]
+
+* Fri Mar 29 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-3
+- Resolves: rhbz#1631656 - KCM: kinit: Matching credential not found while
+                           getting default ccache
+
+* Fri Mar 29 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-2
+- Resolves: rhbz#1406678 - sssd service is starting before network service
+- Resolves: rhbz#1616853 - SSSD always boots in Offline mode
+
+* Thu Mar 21 2019 Michal Židek <mzidek@redhat.com> - 1.16.4-1
+- Resolves: rhbz#1658994 - Rebase SSSD to 1.16.x
+
+* Wed Mar 20 2019 Jakub Hrozek <jhrozek@redhat.com> - 1.16.2-17
+- Resolves: rhbz#1603311 - Enable generating user private groups only for
+                           users with uid == gid where gid does not
+                           correspond to a real LDAP group
+
+* Wed Nov 28 2018 Michal Židek <mzidek@redhat.com> - 1.16.2-16
+- Resolves: rhbz#1602172 - SSSD's LDAP authentication provider does not work
+                           if ID provider is authenticated with GSSAPI 
+
+* Thu Nov 15 2018 Michal Židek <mzidek@redhat.com> - 1.16.2-15
+- Resolves: rhbz#1622109 -  SSSD not fetching all sudo rules from AD
+
+* Wed Nov 14 2018 Michal Židek <mzidek@redhat.com> - 1.16.2-14
+- Resolves: rhbz#1619706 - sssd only sets the SELinux login context if it
+                           differs from the default
 
 * Wed Sep  5 2018 Jakub Hrozek <jhrozek@redhat.com> - 1.16.2-13
 - Resolves: rhbz#1593756 - sssd needs to require a newer version of