diff --git a/.gitignore b/.gitignore
index 5032c1d..27ea61f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-SOURCES/sssd-1.12.2.tar.gz
+SOURCES/cert9.db
+SOURCES/key4.db
+SOURCES/sssd-1.13.0.tar.gz
diff --git a/.sssd.metadata b/.sssd.metadata
index 1ccf4e7..7e1423b 100644
--- a/.sssd.metadata
+++ b/.sssd.metadata
@@ -1 +1,3 @@
-c7969eeb880fdd79cead88504c313fa042ca524a SOURCES/sssd-1.12.2.tar.gz
+7f7d2513294f425b8a393a7e3f37b36634dd55de SOURCES/cert9.db
+6048e03ea386ac40bd801d41d77ece9545592ad3 SOURCES/key4.db
+f9c57cfb91d8e0e35d565a1d5b165e8f669989d2 SOURCES/sssd-1.13.0.tar.gz
diff --git a/SOURCES/0001-test-common-sss_dp_get_account_recv-fix-assignment.patch b/SOURCES/0001-test-common-sss_dp_get_account_recv-fix-assignment.patch
new file mode 100644
index 0000000..4733a5c
--- /dev/null
+++ b/SOURCES/0001-test-common-sss_dp_get_account_recv-fix-assignment.patch
@@ -0,0 +1,26 @@
+From 1b20d057dd7d4284d4c88319a12eee5845b14d8f Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 10 Jul 2015 12:37:43 +0200
+Subject: [PATCH 01/13] test common: sss_dp_get_account_recv() fix assignment
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/tests/cmocka/common_mock_resp_dp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/tests/cmocka/common_mock_resp_dp.c b/src/tests/cmocka/common_mock_resp_dp.c
+index 08d74179d8e2dc0561ea3e2d1e9b5580762ee633..a67ceee4a43184d9894c19a5c11161aca4e1caff 100644
+--- a/src/tests/cmocka/common_mock_resp_dp.c
++++ b/src/tests/cmocka/common_mock_resp_dp.c
+@@ -51,7 +51,7 @@ sss_dp_get_account_recv(TALLOC_CTX *mem_ctx,
+ 
+     *dp_err = sss_mock_type(dbus_uint16_t);
+     *dp_ret = sss_mock_type(dbus_uint32_t);
+-    *dp_ret = sss_mock_type(dbus_uint32_t);
++    *err_msg = sss_mock_ptr_type(char *);
+ 
+     cb = sss_mock_ptr_type(acct_cb_t);
+     if (cb) {
+-- 
+2.4.3
+
diff --git a/SOURCES/0001-util-Move-semanage-related-functions-to-src-util.patch b/SOURCES/0001-util-Move-semanage-related-functions-to-src-util.patch
deleted file mode 100644
index f87ee45..0000000
--- a/SOURCES/0001-util-Move-semanage-related-functions-to-src-util.patch
+++ /dev/null
@@ -1,590 +0,0 @@
-From 40dac78bce81ebf65ccbcd4f346de9e91d3da58b Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Wed, 24 Sep 2014 15:50:04 +0200
-Subject: [PATCH 01/22] util: Move semanage related functions to src/util
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-These functions will be reused by IPA provider.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am                                  |  37 ++-
- src/tests/dlopen-tests.c                     |   1 +
- src/tools/selinux.c                          | 334 ---------------------------
- src/tools/tools_util.h                       |   2 -
- src/{tools/selinux.c => util/sss_semanage.c} |  61 +----
- src/util/util.h                              |   4 +
- 6 files changed, 35 insertions(+), 404 deletions(-)
- copy src/{tools/selinux.c => util/sss_semanage.c} (87%)
-
-diff --git a/Makefile.am b/Makefile.am
-index 6a8124b5ad30f9e54a0325dc574a96c91ec4e805..49acdb107cb45410493dfabe30a2ea4553a23669 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -476,10 +476,6 @@ if BUILD_SELINUX
-     PYTHON_BINDINGS_LIBS += $(SELINUX_LIBS)
-     TOOLS_LIBS += $(SELINUX_LIBS)
- endif
--if BUILD_SEMANAGE
--    PYTHON_BINDINGS_LIBS += $(SEMANAGE_LIBS)
--    TOOLS_LIBS += $(SEMANAGE_LIBS)
--endif
- 
- dist_noinst_HEADERS = \
-     src/monitor/monitor.h \
-@@ -728,11 +724,26 @@ libsss_util_la_SOURCES += \
- endif
- libsss_util_la_LDFLAGS = -avoid-version
- 
-+pkglib_LTLIBRARIES += libsss_semanage.la
-+libsss_semanage_la_SOURCES = \
-+    src/util/sss_semanage.c \
-+    $(NULL)
-+libsss_semanage_la_LIBADD = \
-+    libsss_debug.la \
-+    $(NULL)
-+if BUILD_SEMANAGE
-+libsss_semanage_la_LIBADD += $(SEMANAGE_LIBS)
-+endif
-+
-+libsss_semanage_la_LDFLAGS = \
-+    -avoid-version
-+
- SSSD_INTERNAL_LTLIBS = \
-     libsss_util.la \
-     libsss_crypt.la \
-     libsss_debug.la \
--    libsss_child.la
-+    libsss_child.la \
-+    $(NULL)
- 
- if BUILD_IFP
- if BUILD_CONFIG_LIB
-@@ -1065,7 +1076,9 @@ sss_useradd_SOURCES = \
-     $(SSSD_TOOLS_OBJ)
- sss_useradd_LDADD = \
-     $(TOOLS_LIBS) \
--    $(SSSD_INTERNAL_LTLIBS)
-+    $(SSSD_INTERNAL_LTLIBS) \
-+    libsss_semanage.la \
-+    $(NULL)
- 
- sss_userdel_SOURCES = \
-     src/tools/sss_userdel.c \
-@@ -1073,7 +1086,9 @@ sss_userdel_SOURCES = \
- sss_userdel_LDADD = \
-     $(TOOLS_LIBS) \
-     $(SSSD_INTERNAL_LTLIBS) \
--    $(CLIENT_LIBS)
-+    $(CLIENT_LIBS) \
-+    libsss_semanage.la \
-+    $(NULL)
- sss_userdel_CFLAGS = \
-     $(AM_CFLAGS)
- 
-@@ -1099,7 +1114,9 @@ sss_usermod_SOURCES = \
- sss_usermod_LDADD = \
-     $(TOOLS_LIBS) \
-     $(SSSD_INTERNAL_LTLIBS) \
--    $(CLIENT_LIBS)
-+    $(CLIENT_LIBS) \
-+    libsss_semanage.la \
-+    $(NULL)
- sss_usermod_CFLAGS = $(AM_CFLAGS)
- 
- sss_groupmod_SOURCES = \
-@@ -2372,7 +2389,9 @@ libsss_ipa_la_LIBADD = \
-     libsss_ldap_common.la \
-     libsss_krb5_common.la \
-     libipa_hbac.la \
--    libsss_idmap.la
-+    libsss_idmap.la \
-+    libsss_semanage.la \
-+    $(NULL)
- libsss_ipa_la_LDFLAGS = \
-     -avoid-version \
-     -module
-diff --git a/src/tests/dlopen-tests.c b/src/tests/dlopen-tests.c
-index 1dd80c49cf3e91e214ac6ffb2df1f98268571831..7e56d652461155045023fddeb988f4f4ba017277 100644
---- a/src/tests/dlopen-tests.c
-+++ b/src/tests/dlopen-tests.c
-@@ -38,6 +38,7 @@ struct so {
-     const char *libs[6];
- } so[] = {
-     { "libsss_debug.so", { LIBPFX"libsss_debug.so", NULL } },
-+    { "libsss_semanage.so", { LIBPFX"libsss_semanage.so", NULL } },
-     { "libipa_hbac.so", { LIBPFX"libipa_hbac.so", NULL } },
-     { "libsss_idmap.so", { LIBPFX"libsss_idmap.so", NULL } },
-     { "libsss_nss_idmap.so", { LIBPFX"libsss_nss_idmap.so", NULL } },
-diff --git a/src/tools/selinux.c b/src/tools/selinux.c
-index 1f87d40f99440b15ed71be9c225003b2860c5003..5e9c458f93340fcb4264eced7964a6cfecadc9e6 100644
---- a/src/tools/selinux.c
-+++ b/src/tools/selinux.c
-@@ -27,16 +27,8 @@
- #include <selinux/selinux.h>
- #endif
- 
--#ifdef HAVE_SEMANAGE
--#include <semanage/semanage.h>
--#endif
--
- #include "tools/tools_util.h"
- 
--#ifndef DEFAULT_SERANGE
--#define DEFAULT_SERANGE "s0"
--#endif
--
- #ifdef HAVE_SELINUX
- /*
-  * selinux_file_context - Set the security context before any file or
-@@ -89,329 +81,3 @@ int reset_selinux_file_context(void)
-     return EOK;
- }
- #endif  /* HAVE_SELINUX */
--
--#ifdef HAVE_SEMANAGE
--/* turn libselinux messages into SSSD DEBUG() calls */
--static void sss_semanage_error_callback(void *varg,
--                                        semanage_handle_t *handle,
--                                        const char *fmt, ...)
--{
--    int level = SSSDBG_INVALID;
--    int ret;
--    char * message = NULL;
--    va_list ap;
--
--    switch (semanage_msg_get_level(handle)) {
--        case SEMANAGE_MSG_ERR:
--            level = SSSDBG_CRIT_FAILURE;
--            break;
--        case SEMANAGE_MSG_WARN:
--            level = SSSDBG_MINOR_FAILURE;
--            break;
--        case SEMANAGE_MSG_INFO:
--            level = SSSDBG_TRACE_FUNC;
--            break;
--    }
--
--    va_start(ap, fmt);
--    ret = vasprintf(&message, fmt, ap);
--    va_end(ap);
--    if (ret < 0) {
--        /* ENOMEM */
--        return;
--    }
--
--    if (DEBUG_IS_SET(level))
--        debug_fn(__FILE__, __LINE__, "libsemanage", level, "%s\n", message);
--    free(message);
--}
--
--static semanage_handle_t *sss_semanage_init(void)
--{
--    int ret;
--    semanage_handle_t *handle = NULL;
--
--    handle = semanage_handle_create();
--    if (!handle) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux management handle\n");
--        return NULL;
--    }
--
--    semanage_msg_set_callback(handle,
--                              sss_semanage_error_callback,
--                              NULL);
--
--    ret = semanage_is_managed(handle);
--    if (ret != 1) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "SELinux policy not managed\n");
--        goto fail;
--    }
--
--    ret = semanage_access_check(handle);
--    if (ret < SEMANAGE_CAN_READ) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot read SELinux policy store\n");
--        goto fail;
--    }
--
--    ret = semanage_connect(handle);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Cannot estabilish SELinux management connection\n");
--        goto fail;
--    }
--
--    ret = semanage_begin_transaction(handle);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot begin SELinux transaction\n");
--        goto fail;
--    }
--
--    return handle;
--fail:
--    semanage_handle_destroy(handle);
--    return NULL;
--}
--
--static int sss_semanage_user_add(semanage_handle_t *handle,
--                                 semanage_seuser_key_t *key,
--                                 const char *login_name,
--                                 const char *seuser_name)
--{
--    int ret;
--    semanage_seuser_t *seuser = NULL;
--
--    ret = semanage_seuser_create(handle, &seuser);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Cannot create SELinux login mapping for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_set_name(handle, seuser, login_name);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Could not set name for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_set_mlsrange(handle, seuser, DEFAULT_SERANGE);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not set serange for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_set_sename(handle, seuser, seuser_name);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not set SELinux user for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_modify_local(handle, key, seuser);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not add login mapping for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = EOK;
--done:
--    semanage_seuser_free(seuser);
--    return ret;
--}
--
--static int sss_semanage_user_mod(semanage_handle_t *handle,
--                                 semanage_seuser_key_t *key,
--                                 const char *login_name,
--                                 const char *seuser_name)
--{
--    int ret;
--    semanage_seuser_t *seuser = NULL;
--
--    semanage_seuser_query(handle, key, &seuser);
--    if (seuser == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not query seuser for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_set_mlsrange(handle, seuser, DEFAULT_SERANGE);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not set serange for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_set_sename(handle, seuser, seuser_name);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Could not set sename for %s\n", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_modify_local(handle, key, seuser);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              ("Could not modify login mapping for %s\n"), login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = EOK;
--done:
--    semanage_seuser_free(seuser);
--    return ret;
--}
--
--int set_seuser(const char *login_name, const char *seuser_name)
--{
--    semanage_handle_t *handle = NULL;
--    semanage_seuser_key_t *key = NULL;
--    int ret;
--    int seuser_exists = 0;
--
--    if (seuser_name == NULL) {
--        /* don't care, just let system pick the defaults */
--        return EOK;
--    }
--
--    handle = sss_semanage_init();
--    if (!handle) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init SELinux management\n");
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_key_create(handle, login_name, &key);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux user key\n");
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_exists(handle, key, &seuser_exists);
--    if (ret < 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot verify the SELinux user\n");
--        ret = EIO;
--        goto done;
--    }
--
--    if (seuser_exists) {
--        ret = sss_semanage_user_mod(handle, key, login_name, seuser_name);
--        if (ret != 0) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot modify SELinux user mapping\n");
--            ret = EIO;
--            goto done;
--        }
--    } else {
--        ret = sss_semanage_user_add(handle, key, login_name, seuser_name);
--        if (ret != 0) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add SELinux user mapping\n");
--            ret = EIO;
--            goto done;
--        }
--    }
--
--    ret = semanage_commit(handle);
--    if (ret < 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot commit SELinux transaction\n");
--        ret = EIO;
--        goto done;
--    }
--
--    ret = EOK;
--done:
--    semanage_seuser_key_free(key);
--    semanage_handle_destroy(handle);
--    return ret;
--}
--
--int del_seuser(const char *login_name)
--{
--    semanage_handle_t *handle = NULL;
--    semanage_seuser_key_t *key = NULL;
--    int ret;
--    int exists = 0;
--
--    handle = sss_semanage_init();
--    if (!handle) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init SELinux management\n");
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_key_create(handle, login_name, &key);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux user key\n");
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_seuser_exists(handle, key, &exists);
--    if (ret < 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot verify the SELinux user\n");
--        ret = EIO;
--        goto done;
--    }
--
--    if (!exists) {
--        DEBUG(SSSDBG_FUNC_DATA,
--              "Login mapping for %s is not defined, OK if default mapping "
--                  "was used\n", login_name);
--        ret = EOK;  /* probably default mapping */
--        goto done;
--    }
--
--    ret = semanage_seuser_exists_local(handle, key, &exists);
--    if (ret < 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot verify the SELinux user\n");
--        ret = EIO;
--        goto done;
--    }
--
--    if (!exists) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Login mapping for %s is defined in policy, "
--                  "cannot be deleted", login_name);
--        ret = ENOENT;
--        goto done;
--    }
--
--    ret = semanage_seuser_del_local(handle, key);
--    if (ret != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not delete login mapping for %s", login_name);
--        ret = EIO;
--        goto done;
--    }
--
--    ret = semanage_commit(handle);
--    if (ret < 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot commit SELinux transaction\n");
--        ret = EIO;
--        goto done;
--    }
--
--    ret = EOK;
--done:
--    semanage_handle_destroy(handle);
--    return ret;
--}
--
--#else /* HAVE_SEMANAGE */
--int set_seuser(const char *login_name, const char *seuser_name)
--{
--    return EOK;
--}
--
--int del_seuser(const char *login_name)
--{
--    return EOK;
--}
--#endif  /* HAVE_SEMANAGE */
-diff --git a/src/tools/tools_util.h b/src/tools/tools_util.h
-index 87fe752eac49ef85d77043fe0a8c459bc4f5a74c..c5990b012892a25b315d744a056861e7b2130410 100644
---- a/src/tools/tools_util.h
-+++ b/src/tools/tools_util.h
-@@ -123,7 +123,5 @@ int copy_tree(const char *src_root, const char *dst_root,
- /* from selinux.c */
- int selinux_file_context(const char *dst_name);
- int reset_selinux_file_context(void);
--int set_seuser(const char *login_name, const char *seuser_name);
--int del_seuser(const char *login_name);
- 
- #endif  /* __TOOLS_UTIL_H__ */
-diff --git a/src/tools/selinux.c b/src/util/sss_semanage.c
-similarity index 87%
-copy from src/tools/selinux.c
-copy to src/util/sss_semanage.c
-index 1f87d40f99440b15ed71be9c225003b2860c5003..dbef3b3437f9ac51021f30b510b9c15cd34e297a 100644
---- a/src/tools/selinux.c
-+++ b/src/util/sss_semanage.c
-@@ -1,7 +1,7 @@
- /*
-    SSSD
- 
--   selinux.c
-+   sss_semanage.c
- 
-    Copyright (C) Jakub Hrozek <jhrozek@redhat.com>        2010
- 
-@@ -23,73 +23,16 @@
- 
- #include <stdio.h>
- 
--#ifdef HAVE_SELINUX
--#include <selinux/selinux.h>
--#endif
--
- #ifdef HAVE_SEMANAGE
- #include <semanage/semanage.h>
- #endif
- 
--#include "tools/tools_util.h"
-+#include "util/util.h"
- 
- #ifndef DEFAULT_SERANGE
- #define DEFAULT_SERANGE "s0"
- #endif
- 
--#ifdef HAVE_SELINUX
--/*
-- * selinux_file_context - Set the security context before any file or
-- *                        directory creation.
-- *
-- *  selinux_file_context () should be called before any creation of file,
-- *  symlink, directory, ...
-- *
-- *  Callers may have to Reset SELinux to create files with default
-- *  contexts:
-- *      reset_selinux_file_context();
-- */
--int selinux_file_context(const char *dst_name)
--{
--    security_context_t scontext = NULL;
--
--    if (is_selinux_enabled() == 1) {
--        /* Get the default security context for this file */
--        if (matchpathcon(dst_name, 0, &scontext) < 0) {
--            if (security_getenforce () != 0) {
--                return 1;
--            }
--        }
--        /* Set the security context for the next created file */
--        if (setfscreatecon(scontext) < 0) {
--            if (security_getenforce() != 0) {
--                return 1;
--            }
--        }
--        freecon(scontext);
--    }
--
--    return 0;
--}
--
--int reset_selinux_file_context(void)
--{
--    setfscreatecon(NULL);
--    return EOK;
--}
--
--#else   /* HAVE_SELINUX */
--int selinux_file_context(const char *dst_name)
--{
--    return EOK;
--}
--
--int reset_selinux_file_context(void)
--{
--    return EOK;
--}
--#endif  /* HAVE_SELINUX */
--
- #ifdef HAVE_SEMANAGE
- /* turn libselinux messages into SSSD DEBUG() calls */
- static void sss_semanage_error_callback(void *varg,
-diff --git a/src/util/util.h b/src/util/util.h
-index 0ac9b0104ca941b52bb37720dd16d2bbc9fbb9f8..b43ce6f5092e9920609826bead483976fef2f9b1 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -591,4 +591,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
-                      struct sss_creds **saved_creds);
- errno_t restore_creds(struct sss_creds *saved_creds);
- 
-+/* from sss_semanage.c */
-+int set_seuser(const char *login_name, const char *seuser_name);
-+int del_seuser(const char *login_name);
-+
- #endif /* __SSSD_UTIL_H__ */
--- 
-1.9.3
-
diff --git a/SOURCES/0002-sss_semanage-Add-mlsrange-parameter-to-set_seuser.patch b/SOURCES/0002-sss_semanage-Add-mlsrange-parameter-to-set_seuser.patch
deleted file mode 100644
index c6f920d..0000000
--- a/SOURCES/0002-sss_semanage-Add-mlsrange-parameter-to-set_seuser.patch
+++ /dev/null
@@ -1,153 +0,0 @@
-From 214c04af59ea09589743b88943a7ba0adac64a7a Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Wed, 24 Sep 2014 16:03:04 +0200
-Subject: [PATCH 02/22] sss_semanage: Add mlsrange parameter to set_seuser
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-mlsrange parameter will be needed in IPA provider
-and probably at some point in the tools as well.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/tools/sss_useradd.c |  2 +-
- src/tools/sss_usermod.c |  2 +-
- src/util/sss_semanage.c | 25 ++++++++++++++++---------
- src/util/util.h         |  3 ++-
- 4 files changed, 20 insertions(+), 12 deletions(-)
-
-diff --git a/src/tools/sss_useradd.c b/src/tools/sss_useradd.c
-index 59439401e225d752ea9a82fdb33900bf44699e18..8521b83011b42c9e2acca4136f154acb3919440c 100644
---- a/src/tools/sss_useradd.c
-+++ b/src/tools/sss_useradd.c
-@@ -205,7 +205,7 @@ int main(int argc, const char **argv)
- 
-     /* Set SELinux login context - must be done after transaction is done
-      * b/c libselinux calls getpwnam */
--    ret = set_seuser(tctx->octx->name, pc_selinux_user);
-+    ret = set_seuser(tctx->octx->name, pc_selinux_user, NULL);
-     if (ret != EOK) {
-         ERROR("Cannot set SELinux login context\n");
-         ret = EXIT_FAILURE;
-diff --git a/src/tools/sss_usermod.c b/src/tools/sss_usermod.c
-index 9683c6e9e7c2bf389563515162a3772ee73987ed..55e94394766f5f46bb3c14c231186f2d79d6b6ab 100644
---- a/src/tools/sss_usermod.c
-+++ b/src/tools/sss_usermod.c
-@@ -300,7 +300,7 @@ int main(int argc, const char **argv)
- 
-     /* Set SELinux login context - must be done after transaction is done
-      * b/c libselinux calls getpwnam */
--    ret = set_seuser(tctx->octx->name, pc_selinux_user);
-+    ret = set_seuser(tctx->octx->name, pc_selinux_user, NULL);
-     if (ret != EOK) {
-         ERROR("Cannot set SELinux login context\n");
-         ret = EXIT_FAILURE;
-diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c
-index dbef3b3437f9ac51021f30b510b9c15cd34e297a..3c566553f2085a696f79c5ee35ec6015824d56a6 100644
---- a/src/util/sss_semanage.c
-+++ b/src/util/sss_semanage.c
-@@ -22,7 +22,6 @@
- #include "config.h"
- 
- #include <stdio.h>
--
- #ifdef HAVE_SEMANAGE
- #include <semanage/semanage.h>
- #endif
-@@ -118,7 +117,8 @@ fail:
- static int sss_semanage_user_add(semanage_handle_t *handle,
-                                  semanage_seuser_key_t *key,
-                                  const char *login_name,
--                                 const char *seuser_name)
-+                                 const char *seuser_name,
-+                                 const char *mls)
- {
-     int ret;
-     semanage_seuser_t *seuser = NULL;
-@@ -138,7 +138,8 @@ static int sss_semanage_user_add(semanage_handle_t *handle,
-         goto done;
-     }
- 
--    ret = semanage_seuser_set_mlsrange(handle, seuser, DEFAULT_SERANGE);
-+    ret = semanage_seuser_set_mlsrange(handle, seuser,
-+                                       mls ? mls : DEFAULT_SERANGE);
-     if (ret != 0) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
-               "Could not set serange for %s\n", login_name);
-@@ -171,7 +172,8 @@ done:
- static int sss_semanage_user_mod(semanage_handle_t *handle,
-                                  semanage_seuser_key_t *key,
-                                  const char *login_name,
--                                 const char *seuser_name)
-+                                 const char *seuser_name,
-+                                 const char *mls)
- {
-     int ret;
-     semanage_seuser_t *seuser = NULL;
-@@ -184,7 +186,8 @@ static int sss_semanage_user_mod(semanage_handle_t *handle,
-         goto done;
-     }
- 
--    ret = semanage_seuser_set_mlsrange(handle, seuser, DEFAULT_SERANGE);
-+    ret = semanage_seuser_set_mlsrange(handle, seuser,
-+                                       mls ? mls : DEFAULT_SERANGE);
-     if (ret != 0) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
-               "Could not set serange for %s\n", login_name);
-@@ -213,7 +216,8 @@ done:
-     return ret;
- }
- 
--int set_seuser(const char *login_name, const char *seuser_name)
-+int set_seuser(const char *login_name, const char *seuser_name,
-+               const char *mls)
- {
-     semanage_handle_t *handle = NULL;
-     semanage_seuser_key_t *key = NULL;
-@@ -247,14 +251,16 @@ int set_seuser(const char *login_name, const char *seuser_name)
-     }
- 
-     if (seuser_exists) {
--        ret = sss_semanage_user_mod(handle, key, login_name, seuser_name);
-+        ret = sss_semanage_user_mod(handle, key, login_name, seuser_name,
-+                                    mls);
-         if (ret != 0) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "Cannot modify SELinux user mapping\n");
-             ret = EIO;
-             goto done;
-         }
-     } else {
--        ret = sss_semanage_user_add(handle, key, login_name, seuser_name);
-+        ret = sss_semanage_user_add(handle, key, login_name, seuser_name,
-+                                    mls);
-         if (ret != 0) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add SELinux user mapping\n");
-             ret = EIO;
-@@ -348,7 +354,8 @@ done:
- }
- 
- #else /* HAVE_SEMANAGE */
--int set_seuser(const char *login_name, const char *seuser_name)
-+int set_seuser(const char *login_name, const char *seuser_name,
-+               const char *mls)
- {
-     return EOK;
- }
-diff --git a/src/util/util.h b/src/util/util.h
-index b43ce6f5092e9920609826bead483976fef2f9b1..0af4db3fec723ef372f7c1acde0e3f9f013f90e0 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -592,7 +592,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
- errno_t restore_creds(struct sss_creds *saved_creds);
- 
- /* from sss_semanage.c */
--int set_seuser(const char *login_name, const char *seuser_name);
-+int set_seuser(const char *login_name, const char *seuser_name,
-+               const char *mlsrange);
- int del_seuser(const char *login_name);
- 
- #endif /* __SSSD_UTIL_H__ */
--- 
-1.9.3
-
diff --git a/SOURCES/0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch b/SOURCES/0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch
new file mode 100644
index 0000000..bc0e246
--- /dev/null
+++ b/SOURCES/0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch
@@ -0,0 +1,76 @@
+From fd554736d9b0e909acfcdf1aa5358423beefbe91 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 25 Mar 2015 10:03:43 +0100
+Subject: [PATCH 02/13] tests: Move N_ELEMENTS definition to tests/common.h
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Avoids code duplication
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/tests/cmocka/test_nested_groups.c | 3 ---
+ src/tests/cmocka/test_nss_srv.c       | 3 ---
+ src/tests/common.h                    | 2 ++
+ src/tests/sbus_codegen_tests.c        | 3 ---
+ 4 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/src/tests/cmocka/test_nested_groups.c b/src/tests/cmocka/test_nested_groups.c
+index eef9df2dc25c231cb81243f48b759e2fced1a85d..8081ff26102e53b2e453838c3a18e4560ac5317e 100644
+--- a/src/tests/cmocka/test_nested_groups.c
++++ b/src/tests/cmocka/test_nested_groups.c
+@@ -48,9 +48,6 @@
+ #define GROUP_BASE_DN "cn=groups," OBJECT_BASE_DN
+ #define USER_BASE_DN "cn=users," OBJECT_BASE_DN
+ 
+-#define N_ELEMENTS(arr) \
+-    (sizeof(arr) / sizeof(arr[0]))
+-
+ struct nested_groups_test_ctx {
+     struct sss_test_ctx *tctx;
+ 
+diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
+index d1a4c16851427a36b123f04cecee5fe5ae2d333d..3ab8d39c44a8bb8cacae20f534dcbeb6ca7dec08 100644
+--- a/src/tests/cmocka/test_nss_srv.c
++++ b/src/tests/cmocka/test_nss_srv.c
+@@ -41,9 +41,6 @@
+ #define TEST_ID_PROVIDER "ldap"
+ #define TEST_DOM_SID "S-1-5-21-444379608-1639770488-2995963434"
+ 
+-#define N_ELEMENTS(arr) \
+-    (sizeof(arr) / sizeof(arr[0]))
+-
+ struct nss_test_ctx {
+     struct sss_test_ctx *tctx;
+     struct sss_domain_info *subdom;
+diff --git a/src/tests/common.h b/src/tests/common.h
+index 0b351f5d647a8f72bdbc399c6fe02579d4b4e1be..1c6de2c3d6eb924ba7306bd350f8546d61f30751 100644
+--- a/src/tests/common.h
++++ b/src/tests/common.h
+@@ -30,6 +30,8 @@
+ #include "providers/data_provider.h"
+ #include "providers/ldap/sdap.h"
+ 
++#define N_ELEMENTS(arr) (sizeof(arr) / sizeof(arr[0]))
++
+ extern TALLOC_CTX *global_talloc_context;
+ 
+ #define check_leaks(ctx, bytes) _check_leaks((ctx), (bytes), __location__)
+diff --git a/src/tests/sbus_codegen_tests.c b/src/tests/sbus_codegen_tests.c
+index 9e9be52e84672eb3ee3afa4e13d5f60047150e98..4637b92b84459041806bb5950e969e988716bec8 100644
+--- a/src/tests/sbus_codegen_tests.c
++++ b/src/tests/sbus_codegen_tests.c
+@@ -33,9 +33,6 @@
+ #include "tests/sbus_codegen_tests_generated.h"
+ #include "util/util_errors.h"
+ 
+-#define N_ELEMENTS(arr) \
+-    (sizeof(arr) / sizeof(arr[0]))
+-
+ /* The following 2 macros were taken from check's project source files (0.9.10)
+  * http://check.sourceforge.net/
+  */
+-- 
+2.4.3
+
diff --git a/SOURCES/0003-IPA-Use-set_seuser-instead-of-writing-selinux-login-.patch b/SOURCES/0003-IPA-Use-set_seuser-instead-of-writing-selinux-login-.patch
deleted file mode 100644
index 83341fe..0000000
--- a/SOURCES/0003-IPA-Use-set_seuser-instead-of-writing-selinux-login-.patch
+++ /dev/null
@@ -1,277 +0,0 @@
-From 7d5eda445b127f4fdb5ff2f680792d46aa82439b Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Wed, 24 Sep 2014 16:51:55 +0200
-Subject: [PATCH 03/22] IPA: Use set_seuser instead of writing selinux login
- file
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Remove the write/remove_selinux login file functions
-and use set_seuser instead.
-
-This patch will require change in selinux policy.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/ipa/ipa_selinux.c | 184 +++++++++++-----------------------------
- 1 file changed, 49 insertions(+), 135 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index 5b65a7b04cb0d55b10de47c4ea306b6d4470dfe9..7db1c6ed2981e4c4a85d892171bbfa60b006980e 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -652,10 +652,10 @@ done:
-     return ret;
- }
- 
--static errno_t write_selinux_login_file(const char *orig_name,
--                                        struct sss_domain_info *dom,
--                                        char *string);
--static errno_t remove_selinux_login_file(const char *username);
-+static errno_t
-+set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
-+                  const char *seuser_mls_string);
-+
- 
- /* Choose best selinux user based on given order and write
-  * the user to selinux login file. */
-@@ -666,9 +666,9 @@ static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
-                                   const char *default_user)
- {
-     TALLOC_CTX *tmp_ctx;
--    char *file_content = NULL;
-+    char *seuser_mls_str = NULL;
-     const char *tmp_str;
--    errno_t ret, err;
-+    errno_t ret;
-     int i, j;
- 
-     tmp_ctx = talloc_new(NULL);
-@@ -679,8 +679,8 @@ static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
- 
-     /* If no maps match, we'll use the default SELinux user from the
-      * config */
--    file_content = talloc_strdup(tmp_ctx, default_user);
--    if (file_content == NULL) {
-+    seuser_mls_str = talloc_strdup(tmp_ctx, default_user);
-+    if (seuser_mls_str == NULL) {
-         ret = ENOMEM;
-         goto done;
-     }
-@@ -702,12 +702,12 @@ static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
-             tmp_str = sss_selinux_map_get_seuser(usermaps[j]);
- 
-             if (tmp_str && !strcasecmp(tmp_str, mo_ctx->order_array[i])) {
--                /* If file_content contained something, overwrite it.
-+                /* If seuser_mls_str contained something, overwrite it.
-                  * This record has higher priority.
-                  */
--                talloc_zfree(file_content);
--                file_content = talloc_strdup(tmp_ctx, tmp_str);
--                if (file_content == NULL) {
-+                talloc_zfree(seuser_mls_str);
-+                seuser_mls_str = talloc_strdup(tmp_ctx, tmp_str);
-+                if (seuser_mls_str == NULL) {
-                     ret = ENOMEM;
-                     goto done;
-                 }
-@@ -716,44 +716,48 @@ static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
-         }
-     }
- 
--    ret = write_selinux_login_file(pd->user, user_domain, file_content);
-+    ret = set_seuser_helper(pd->user, user_domain, seuser_mls_str);
- done:
--    if (!file_content) {
--        err = remove_selinux_login_file(pd->user);
--        /* Don't overwrite original error condition if there was one */
--        if (ret == EOK) ret = err;
--    }
-     talloc_free(tmp_ctx);
-     return ret;
- }
- 
--static errno_t write_selinux_login_file(const char *orig_name,
--                                        struct sss_domain_info *dom,
--                                        char *string)
-+static errno_t
-+set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
-+                  const char *seuser_mls_string)
- {
--    char *path = NULL;
--    char *tmp_path = NULL;
--    ssize_t written;
--    size_t len;
--    int fd = -1;
--    mode_t oldmask;
-+    errno_t ret;
-+    char *seuser;
-+    char *mls_range;
-+    char *ptr;
-+    char *username;
-+    char *username_final;
-     TALLOC_CTX *tmp_ctx;
--    char *full_string = NULL;
--    int enforce;
--    errno_t ret = EOK;
--    const char *username;
--
--    len = strlen(string);
--    if (len == 0) {
--        return EINVAL;
--    }
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
-         return ENOMEM;
-     }
- 
-+    /* Split seuser and mls_range */
-+    seuser = talloc_strdup(tmp_ctx, seuser_mls_string);
-+    if (seuser == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    ptr = seuser;
-+    while (*ptr != ':' && *ptr != '\0') {
-+        ptr++;
-+    }
-+    if (*ptr == '\0') {
-+        /* No mls_range specified */
-+        mls_range = NULL;
-+    } else {
-+        *ptr = '\0'; /* split */
-+        mls_range = ptr + 1;
-+    }
-+
-     /* pam_selinux needs the username in the same format getpwnam() would
-      * return it
-      */
-@@ -763,113 +767,23 @@ static errno_t write_selinux_login_file(const char *orig_name,
-         goto done;
-     }
- 
--    path = selogin_path(tmp_ctx, username);
--    if (path == NULL) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    tmp_path = talloc_asprintf(tmp_ctx, "%sXXXXXX", path);
--    if (tmp_path == NULL) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    oldmask = umask(022);
--    fd = mkstemp(tmp_path);
--    ret = errno;
--    umask(oldmask);
--    if (fd < 0) {
--        if (ret == ENOENT) {
--            /* if selinux is disabled and selogin dir does not exist,
--             * just ignore the error */
--            if (selinux_getenforcemode(&enforce) == 0 && enforce == -1) {
--                ret = EOK;
--                goto done;
--            }
--
--            /* continue if we can't get enforce mode or selinux is enabled */
-+    if (dom->fqnames) {
-+        username_final = talloc_asprintf(tmp_ctx, dom->names->fq_fmt,
-+                                         username, dom->name);
-+        if (username_final == NULL) {
-+            ret = ENOMEM;
-+            goto done;
-         }
--
--        DEBUG(SSSDBG_OP_FAILURE, "unable to create temp file [%s] "
--              "for SELinux data [%d]: %s\n", tmp_path, ret, strerror(ret));
--        goto done;
--    }
--
--    full_string = talloc_asprintf(tmp_ctx, "%s:%s", ALL_SERVICES, string);
--    if (full_string == NULL) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    len = strlen(full_string);
--
--    errno = 0;
--    written = sss_atomic_write_s(fd, full_string, len);
--    if (written == -1) {
--        ret = errno;
--        DEBUG(SSSDBG_OP_FAILURE, "writing to SELinux data file %s"
--                                  "failed [%d]: %s", tmp_path, ret,
--                                  strerror(ret));
--        goto done;
--    }
--
--    if (written != len) {
--        DEBUG(SSSDBG_OP_FAILURE, "Expected to write %zd bytes, wrote %zu",
--                                  written, len);
--        ret = EIO;
--        goto done;
--    }
--
--    errno = 0;
--    if (rename(tmp_path, path) < 0) {
--        ret = errno;
-     } else {
--        ret = EOK;
-+        username_final = username;
-     }
--    close(fd);
--    fd = -1;
- 
-+    ret = set_seuser(username_final, seuser, mls_range);
- done:
--    if (fd != -1) {
--        close(fd);
--        if (unlink(tmp_path) < 0) {
--            DEBUG(SSSDBG_MINOR_FAILURE, "Could not remove file [%s]",
--                                         tmp_path);
--        }
--    }
--
-     talloc_free(tmp_ctx);
-     return ret;
- }
- 
--static errno_t remove_selinux_login_file(const char *username)
--{
--    char *path;
--    errno_t ret;
--
--    path = selogin_path(NULL, username);
--    if (!path) return ENOMEM;
--
--    errno = 0;
--    ret = unlink(path);
--    if (ret < 0) {
--        ret = errno;
--        if (ret == ENOENT) {
--            /* Just return success if the file was not there */
--            ret = EOK;
--        } else {
--            DEBUG(SSSDBG_OP_FAILURE,
--                  "Could not remove login file %s [%d]: %s\n",
--                   path, ret, strerror(ret));
--        }
--    }
--
--    talloc_free(path);
--    return ret;
--}
--
--
- /* A more generic request to gather all SELinux and HBAC rules. Updates
-  * cache if necessary
-  */
--- 
-1.9.3
-
diff --git a/SOURCES/0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch b/SOURCES/0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch
new file mode 100644
index 0000000..5b07384
--- /dev/null
+++ b/SOURCES/0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch
@@ -0,0 +1,925 @@
+From 1d245226d88537123827dcda3fd0bd093275019d Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 24 Mar 2015 23:24:22 +0100
+Subject: [PATCH 03/13] SYSDB: Add functions to look up multiple entries
+ including name and custom filter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Adds new sysdb function:
+    - sysdb_enumpwent_filter
+    - sysdb_enumpwent_filter_with_views
+    - sysdb_enumgrent_filter
+    - sysdb_enumgrent_filter_with_views
+
+These are similar to enumeration functions, but optionally allow to
+specify a filter to be applied on user/group names. Also an additional
+custom filter can be applied.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/db/sysdb.h                      |  24 ++
+ src/db/sysdb_search.c               | 252 ++++++++++++------
+ src/tests/cmocka/test_sysdb_views.c | 494 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 691 insertions(+), 79 deletions(-)
+
+diff --git a/src/db/sysdb.h b/src/db/sysdb.h
+index 48dd26dd294333b265b69b28cd3b5d37f1293b43..0f745ccb1a646d77ba4ad3d714d5f4dce0a51211 100644
+--- a/src/db/sysdb.h
++++ b/src/db/sysdb.h
+@@ -601,10 +601,22 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
+                     struct sss_domain_info *domain,
+                     struct ldb_result **res);
+ 
++int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx,
++                           struct sss_domain_info *domain,
++                           const char *name_filter,
++                           const char *addtl_filter,
++                           struct ldb_result **res);
++
+ int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
+                                struct sss_domain_info *domain,
+                                struct ldb_result **res);
+ 
++int sysdb_enumpwent_filter_with_views(TALLOC_CTX *mem_ctx,
++                                      struct sss_domain_info *domain,
++                                      const char *name_filter,
++                                      const char *addtl_filter,
++                                      struct ldb_result **res);
++
+ int sysdb_getgrnam(TALLOC_CTX *mem_ctx,
+                    struct sss_domain_info *domain,
+                    const char *name,
+@@ -619,10 +631,22 @@ int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
+                     struct sss_domain_info *domain,
+                     struct ldb_result **res);
+ 
++int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx,
++                           struct sss_domain_info *domain,
++                           const char *name_filter,
++                           const char *addtl_filter,
++                           struct ldb_result **res);
++
+ int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
+                                struct sss_domain_info *domain,
+                                struct ldb_result **res);
+ 
++int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx,
++                                      struct sss_domain_info *domain,
++                                      const char *name_filter,
++                                      const char *addtl_filter,
++                                      struct ldb_result **res);
++
+ struct sysdb_netgroup_ctx {
+     enum {SYSDB_NETGROUP_TRIPLE_VAL, SYSDB_NETGROUP_GROUP_VAL} type;
+     union {
+diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
+index a8dcc9f8d6617be8e8fb82a1c6360c6df9726a37..4f617b841bf3b3760d9cb05a06f4b46ea0c58ff5 100644
+--- a/src/db/sysdb_search.c
++++ b/src/db/sysdb_search.c
+@@ -255,44 +255,104 @@ done:
+     return ret;
+ }
+ 
++static char *enum_filter(TALLOC_CTX *mem_ctx,
++                         const char *base_filter,
++                         const char *name_filter,
++                         const char *addtl_filter)
++{
++    char *filter;
++    TALLOC_CTX *tmp_ctx = NULL;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        return NULL;
++    }
++
++    if (name_filter == NULL && addtl_filter == NULL) {
++        filter = talloc_strdup(tmp_ctx, base_filter);
++    } else {
++        filter = talloc_asprintf(tmp_ctx, "(&%s", base_filter);
++
++        if (filter != NULL && name_filter != NULL) {
++            filter = talloc_asprintf_append(filter, "(%s=%s)",
++                                            SYSDB_NAME, name_filter);
++        }
++
++        if (filter != NULL && addtl_filter != NULL) {
++            filter = talloc_asprintf_append(filter, "%s", addtl_filter);
++        }
++
++        if (filter != NULL) {
++            filter = talloc_asprintf_append(filter, ")");
++        }
++    }
++
++    if (filter) {
++        talloc_steal(mem_ctx, filter);
++    }
++
++    talloc_free(tmp_ctx);
++    return filter;
++}
++
++int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx,
++                           struct sss_domain_info *domain,
++                           const char *name_filter,
++                           const char *addtl_filter,
++                           struct ldb_result **_res)
++{
++    TALLOC_CTX *tmp_ctx;
++    static const char *attrs[] = SYSDB_PW_ATTRS;
++    char *filter = NULL;
++    struct ldb_dn *base_dn;
++    struct ldb_result *res;
++    int ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (!tmp_ctx) {
++        return ENOMEM;
++    }
++
++    base_dn = sysdb_user_base_dn(tmp_ctx, domain);
++    if (!base_dn) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    filter = enum_filter(tmp_ctx, SYSDB_PWENT_FILTER,
++                         name_filter, addtl_filter);
++    if (filter == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++    DEBUG(SSSDBG_TRACE_LIBS, "Searching cache with [%s]\n", filter);
++
++    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
++                     LDB_SCOPE_SUBTREE, attrs, "%s", filter);
++    if (ret) {
++        ret = sysdb_error_to_errno(ret);
++        goto done;
++    }
++
++    *_res = talloc_steal(mem_ctx, res);
++
++done:
++    talloc_zfree(tmp_ctx);
++    return ret;
++}
++
+ int sysdb_enumpwent(TALLOC_CTX *mem_ctx,
+                     struct sss_domain_info *domain,
+                     struct ldb_result **_res)
+ {
+-    TALLOC_CTX *tmp_ctx;
+-    static const char *attrs[] = SYSDB_PW_ATTRS;
+-    struct ldb_dn *base_dn;
+-    struct ldb_result *res;
+-    int ret;
+-
+-    tmp_ctx = talloc_new(NULL);
+-    if (!tmp_ctx) {
+-        return ENOMEM;
+-    }
+-
+-    base_dn = sysdb_user_base_dn(tmp_ctx, domain);
+-    if (!base_dn) {
+-        ret = ENOMEM;
+-        goto done;
+-    }
+-
+-    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+-                     LDB_SCOPE_SUBTREE, attrs, SYSDB_PWENT_FILTER);
+-    if (ret) {
+-        ret = sysdb_error_to_errno(ret);
+-        goto done;
+-    }
+-
+-    *_res = talloc_steal(mem_ctx, res);
+-
+-done:
+-    talloc_zfree(tmp_ctx);
+-    return ret;
++    return sysdb_enumpwent_filter(mem_ctx, domain, NULL, 0, _res);
+ }
+ 
+-int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
+-                               struct sss_domain_info *domain,
+-                               struct ldb_result **_res)
++int sysdb_enumpwent_filter_with_views(TALLOC_CTX *mem_ctx,
++                                      struct sss_domain_info *domain,
++                                      const char *name_filter,
++                                      const char *addtl_filter,
++                                      struct ldb_result **_res)
+ {
+     TALLOC_CTX *tmp_ctx;
+     struct ldb_result *res;
+@@ -305,7 +365,7 @@ int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
+         return ENOMEM;
+     }
+ 
+-    ret = sysdb_enumpwent(tmp_ctx, domain, &res);
++    ret = sysdb_enumpwent_filter(tmp_ctx, domain, name_filter, addtl_filter, &res);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumpwent failed.\n");
+         goto done;
+@@ -331,6 +391,13 @@ done:
+     return ret;
+ }
+ 
++int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
++                               struct sss_domain_info *domain,
++                               struct ldb_result **_res)
++{
++    return sysdb_enumpwent_filter_with_views(mem_ctx, domain, NULL, NULL, _res);
++}
++
+ /* groups */
+ 
+ static int mpg_convert(struct ldb_message *msg)
+@@ -662,57 +729,77 @@ done:
+     return ret;
+ }
+ 
++int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx,
++                           struct sss_domain_info *domain,
++                           const char *name_filter,
++                           const char *addtl_filter,
++                           struct ldb_result **_res)
++{
++    TALLOC_CTX *tmp_ctx;
++    static const char *attrs[] = SYSDB_GRSRC_ATTRS;
++    const char *filter = NULL;
++    const char *base_filter;
++    struct ldb_dn *base_dn;
++    struct ldb_result *res;
++    int ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (!tmp_ctx) {
++        return ENOMEM;
++    }
++
++    if (domain->mpg) {
++        base_filter = SYSDB_GRENT_MPG_FILTER;
++        base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
++                                 SYSDB_DOM_BASE, domain->name);
++    } else {
++        base_filter = SYSDB_GRENT_FILTER;
++        base_dn = sysdb_group_base_dn(tmp_ctx, domain);
++    }
++    if (!base_dn) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    filter = enum_filter(tmp_ctx, base_filter,
++                         name_filter, addtl_filter);
++    if (filter == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++    DEBUG(SSSDBG_TRACE_LIBS, "Searching cache with [%s]\n", filter);
++
++    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
++                     LDB_SCOPE_SUBTREE, attrs, "%s", filter);
++    if (ret) {
++        ret = sysdb_error_to_errno(ret);
++        goto done;
++    }
++
++    ret = mpg_res_convert(res);
++    if (ret) {
++        goto done;
++    }
++
++    *_res = talloc_steal(mem_ctx, res);
++
++done:
++    talloc_zfree(tmp_ctx);
++    return ret;
++}
++
+ int sysdb_enumgrent(TALLOC_CTX *mem_ctx,
+                     struct sss_domain_info *domain,
+                     struct ldb_result **_res)
+ {
+-    TALLOC_CTX *tmp_ctx;
+-    static const char *attrs[] = SYSDB_GRSRC_ATTRS;
+-    const char *fmt_filter;
+-    struct ldb_dn *base_dn;
+-    struct ldb_result *res;
+-    int ret;
+-
+-    tmp_ctx = talloc_new(NULL);
+-    if (!tmp_ctx) {
+-        return ENOMEM;
+-    }
+-
+-    if (domain->mpg) {
+-        fmt_filter = SYSDB_GRENT_MPG_FILTER;
+-        base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
+-                                 SYSDB_DOM_BASE, domain->name);
+-    } else {
+-        fmt_filter = SYSDB_GRENT_FILTER;
+-        base_dn = sysdb_group_base_dn(tmp_ctx, domain);
+-    }
+-    if (!base_dn) {
+-        ret = ENOMEM;
+-        goto done;
+-    }
+-
+-    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn,
+-                     LDB_SCOPE_SUBTREE, attrs, "%s", fmt_filter);
+-    if (ret) {
+-        ret = sysdb_error_to_errno(ret);
+-        goto done;
+-    }
+-
+-    ret = mpg_res_convert(res);
+-    if (ret) {
+-        goto done;
+-    }
+-
+-    *_res = talloc_steal(mem_ctx, res);
+-
+-done:
+-    talloc_zfree(tmp_ctx);
+-    return ret;
++    return sysdb_enumgrent_filter(mem_ctx, domain, NULL, 0, _res);
+ }
+ 
+-int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
+-                               struct sss_domain_info *domain,
+-                               struct ldb_result **_res)
++int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx,
++                                      struct sss_domain_info *domain,
++                                      const char *name_filter,
++                                      const char *addtl_filter,
++                                      struct ldb_result **_res)
+ {
+     TALLOC_CTX *tmp_ctx;
+     struct ldb_result *res;
+@@ -725,7 +812,7 @@ int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
+         return ENOMEM;
+     }
+ 
+-    ret = sysdb_enumgrent(tmp_ctx, domain,&res);
++    ret = sysdb_enumgrent_filter(tmp_ctx, domain, name_filter, addtl_filter, &res);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumgrent failed.\n");
+         goto done;
+@@ -759,6 +846,13 @@ done:
+     return ret;
+ }
+ 
++int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
++                               struct sss_domain_info *domain,
++                               struct ldb_result **_res)
++{
++    return sysdb_enumgrent_filter_with_views(mem_ctx, domain, NULL, NULL, _res);
++}
++
+ int sysdb_initgroups(TALLOC_CTX *mem_ctx,
+                      struct sss_domain_info *domain,
+                      const char *name,
+diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
+index 69118cd87a172696f8220e1446df7a856e368cb6..1fb598219e9ee581e465ddbb32ba9f2544600c26 100644
+--- a/src/tests/cmocka/test_sysdb_views.c
++++ b/src/tests/cmocka/test_sysdb_views.c
+@@ -45,6 +45,7 @@
+ #define TEST_USER_HOMEDIR "/home/home"
+ #define TEST_USER_SHELL "/bin/shell"
+ #define TEST_USER_SID "S-1-2-3-4"
++#define TEST_GID_OVERRIDE_BASE 100
+ 
+ struct sysdb_test_ctx {
+     struct sysdb_ctx *sysdb;
+@@ -108,6 +109,7 @@ static int _setup_sysdb_tests(struct sysdb_test_ctx **ctx, bool enumerate)
+                            TESTS_PATH, &test_ctx->domain);
+     assert_int_equal(ret, EOK);
+ 
++    test_ctx->domain->has_views = true;
+     test_ctx->sysdb = test_ctx->domain->sysdb;
+ 
+     *ctx = test_ctx;
+@@ -115,6 +117,7 @@ static int _setup_sysdb_tests(struct sysdb_test_ctx **ctx, bool enumerate)
+ }
+ 
+ #define setup_sysdb_tests(ctx) _setup_sysdb_tests((ctx), false)
++#define setup_sysdb_enum_tests(ctx) _setup_sysdb_tests((ctx), true)
+ 
+ static int test_sysdb_setup(void **state)
+ {
+@@ -426,6 +429,473 @@ void test_sysdb_invalidate_overrides(void **state)
+     assert_int_equal(ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0),
+                      1);
+     assert_null(ldb_msg_find_attr_as_string(msg, SYSDB_OVERRIDE_DN, NULL));
++
++    ret = sysdb_delete_user(test_ctx->domain, TEST_USER_NAME, 0);
++    assert_int_equal(ret, EOK);
++}
++
++static const char *users[] = { "alice", "bob", "barney", NULL };
++
++static void enum_test_user_override(struct sysdb_test_ctx *test_ctx,
++                                    const char *name)
++{
++    int ret;
++    struct sysdb_attrs *attrs;
++    struct ldb_dn *dn;
++    TALLOC_CTX *tmp_ctx;
++    const char *anchor;
++    const char *override_gecos;
++
++    tmp_ctx = talloc_new(test_ctx);
++    assert_non_null(tmp_ctx);
++
++    attrs = sysdb_new_attrs(tmp_ctx);
++    assert_non_null(attrs);
++
++    dn = sysdb_user_dn(tmp_ctx, test_ctx->domain, name);
++    assert_non_null(dn);
++
++    anchor = talloc_asprintf(tmp_ctx, "%s%s", TEST_ANCHOR_PREFIX, name);
++    ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, anchor);
++    assert_int_equal(ret, EOK);
++
++    override_gecos = talloc_asprintf(attrs, "%s_GECOS_OVERRIDE", name);
++    ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, override_gecos);
++    assert_int_equal(ret, EOK);
++
++    ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
++                               SYSDB_MEMBER_USER, attrs, dn);
++    assert_int_equal(ret, EOK);
++
++    talloc_free(tmp_ctx);
++}
++
++static void enum_test_add_users(struct sysdb_test_ctx *test_ctx,
++                                const char *usernames[])
++{
++    int i;
++    int ret;
++    struct sysdb_attrs *attrs;
++
++    for (i = 0; usernames[i] != NULL; i++) {
++        attrs = talloc(test_ctx, struct sysdb_attrs);
++        assert_non_null(attrs);
++
++        ret = sysdb_store_user(test_ctx->domain, usernames[i],
++                               NULL, 0, 0, usernames[i], "/", "/bin/sh",
++                               NULL, NULL, NULL, 1, 1234 + i);
++        assert_int_equal(ret, EOK);
++
++        enum_test_user_override(test_ctx, usernames[i]);
++
++        talloc_free(attrs);
++    }
++}
++
++static void enum_test_del_users(struct sss_domain_info *dom,
++                               const char *usernames[])
++{
++    int i;
++    int ret;
++
++    for (i = 0; usernames[i] != NULL; i++) {
++        ret = sysdb_delete_user(dom, usernames[i], 0);
++        if (ret != EOK && ret != ENOENT) {
++            fail();
++        }
++    }
++}
++
++static int test_enum_users_setup(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx;
++
++    assert_true(leak_check_setup());
++
++    ret = setup_sysdb_enum_tests(&test_ctx);
++    assert_int_equal(ret, EOK);
++
++    enum_test_add_users(test_ctx, users);
++
++    *state = (void *) test_ctx;
++    return 0;
++}
++
++static void assert_user_attrs(struct ldb_message *msg,
++                              const char *name,
++                              bool has_views)
++{
++    const char *str;
++
++    str = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
++    assert_string_equal(str, name);
++    str = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
++    assert_string_equal(str, name);
++
++    str = ldb_msg_find_attr_as_string(msg, OVERRIDE_PREFIX SYSDB_GECOS, NULL);
++    if (has_views) {
++        char *override;
++
++        assert_non_null(str);
++        override = talloc_asprintf(msg, "%s_GECOS_OVERRIDE", name);
++        assert_non_null(override);
++
++        assert_string_equal(str, override);
++        talloc_free(override);
++    } else {
++        assert_null(str);
++    }
++}
++
++static int test_enum_users_teardown(void **state)
++{
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++
++    enum_test_del_users(test_ctx->domain, users);
++    return test_sysdb_teardown(state);
++}
++
++static void check_enumpwent(int ret, struct ldb_result *res, bool views)
++{
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, N_ELEMENTS(users)-1);
++    assert_user_attrs(res->msgs[0], "barney", views);
++    assert_user_attrs(res->msgs[1], "alice", views);
++    assert_user_attrs(res->msgs[2], "bob", views);
++}
++
++static void test_sysdb_enumpwent(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++
++    ret = sysdb_enumpwent(test_ctx, test_ctx->domain, &res);
++    check_enumpwent(ret, res, false);
++}
++
++static void test_sysdb_enumpwent_views(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++
++    ret = sysdb_enumpwent_with_views(test_ctx, test_ctx->domain, &res);
++    check_enumpwent(ret, res, true);
++}
++
++static void test_sysdb_enumpwent_filter(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++    char *addtl_filter;
++
++    ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "a*", 0, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_user_attrs(res->msgs[0], "alice", false);
++
++    ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "b*", 0, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 2);
++    assert_user_attrs(res->msgs[0], "barney", false);
++    assert_user_attrs(res->msgs[1], "bob", false);
++
++    ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "c*", 0, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 0);
++
++    ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "*", 0, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, N_ELEMENTS(users)-1);
++
++    /* Test searching based on time as well */
++    addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)",
++                                   SYSDB_LAST_UPDATE, 1233);
++    ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "a*", addtl_filter, &res);
++    talloc_free(addtl_filter);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 0);
++
++    addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)",
++                                   SYSDB_LAST_UPDATE, 1234);
++    ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "a*", addtl_filter, &res);
++    talloc_free(addtl_filter);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_user_attrs(res->msgs[0], "alice", false);
++}
++
++static void test_sysdb_enumpwent_filter_views(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++    char *addtl_filter;
++
++    ret = sysdb_enumpwent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "a*", NULL, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_user_attrs(res->msgs[0], "alice", true);
++
++    ret = sysdb_enumpwent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "b*", NULL, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 2);
++    assert_user_attrs(res->msgs[0], "barney", true);
++    assert_user_attrs(res->msgs[1], "bob", true);
++
++    addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)",
++                                   SYSDB_LAST_UPDATE, 1235);
++    ret = sysdb_enumpwent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "b*", addtl_filter, &res);
++    talloc_free(addtl_filter);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_user_attrs(res->msgs[0], "bob", true);
++
++    ret = sysdb_enumpwent_filter_with_views(test_ctx,
++                                            test_ctx->domain, "c*", NULL, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 0);
++
++    ret = sysdb_enumpwent_filter_with_views(test_ctx,
++                                            test_ctx->domain, "*", NULL, &res);
++    check_enumpwent(ret, res, true);
++}
++
++static const char *groups[] = { "one", "two", "three", NULL };
++
++static void enum_test_group_override(struct sysdb_test_ctx *test_ctx,
++                                     const char *name,
++                                     unsigned override_gid)
++{
++    int ret;
++    struct sysdb_attrs *attrs;
++    struct ldb_dn *dn;
++    TALLOC_CTX *tmp_ctx;
++    const char *anchor;
++
++    tmp_ctx = talloc_new(test_ctx);
++    assert_non_null(tmp_ctx);
++
++    attrs = sysdb_new_attrs(tmp_ctx);
++    assert_non_null(attrs);
++
++    dn = sysdb_group_dn(tmp_ctx, test_ctx->domain, name);
++    assert_non_null(dn);
++
++    anchor = talloc_asprintf(tmp_ctx, "%s%s", TEST_ANCHOR_PREFIX, name);
++    ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, anchor);
++    assert_int_equal(ret, EOK);
++
++    ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, override_gid);
++    assert_int_equal(ret, EOK);
++
++    ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
++                               SYSDB_MEMBER_GROUP, attrs, dn);
++    assert_int_equal(ret, EOK);
++
++    talloc_free(tmp_ctx);
++}
++
++static void enum_test_add_groups(struct sysdb_test_ctx *test_ctx,
++                                 const char *groupnames[])
++{
++    int i;
++    int ret;
++    struct sysdb_attrs *attrs;
++
++    for (i = 0; groupnames[i] != NULL; i++) {
++        attrs = talloc(test_ctx, struct sysdb_attrs);
++        assert_non_null(attrs);
++
++        ret = sysdb_store_group(test_ctx->domain, groupnames[i],
++                                0, NULL, 1, 1234 + i);
++        assert_int_equal(ret, EOK);
++
++        enum_test_group_override(test_ctx, groupnames[i],
++                                 TEST_GID_OVERRIDE_BASE + i);
++        talloc_free(attrs);
++    }
++}
++
++static void enum_test_del_groups(struct sss_domain_info *dom,
++                                 const char *groupnames[])
++{
++    int i;
++    int ret;
++
++    for (i = 0; groupnames[i] != NULL; i++) {
++        ret = sysdb_delete_group(dom, groupnames[i], 0);
++        if (ret != EOK && ret != ENOENT) {
++            fail();
++        }
++    }
++}
++
++static int test_enum_groups_setup(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx;
++
++    assert_true(leak_check_setup());
++
++    ret = setup_sysdb_enum_tests(&test_ctx);
++    assert_int_equal(ret, EOK);
++
++    enum_test_add_groups(test_ctx, groups);
++
++    *state = (void *) test_ctx;
++    return 0;
++}
++
++static int test_enum_groups_teardown(void **state)
++{
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++
++    enum_test_del_groups(test_ctx->domain, groups);
++    return test_sysdb_teardown(state);
++}
++
++static void assert_group_attrs(struct ldb_message *msg,
++                               const char *name,
++                               unsigned expected_override_gid)
++{
++    const char *str;
++    unsigned gid;
++
++    str = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
++    assert_string_equal(str, name);
++
++    if (expected_override_gid) {
++        gid = ldb_msg_find_attr_as_uint64(msg,
++                                          OVERRIDE_PREFIX SYSDB_GIDNUM, 0);
++        assert_int_equal(gid, expected_override_gid);
++    }
++}
++
++static void check_enumgrent(int ret, struct ldb_result *res, bool views)
++{
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, N_ELEMENTS(groups)-1);
++    assert_group_attrs(res->msgs[0], "three", views ? TEST_GID_OVERRIDE_BASE + 2 : 0);
++    assert_group_attrs(res->msgs[1], "one", views ? TEST_GID_OVERRIDE_BASE : 0);
++    assert_group_attrs(res->msgs[2], "two", views ? TEST_GID_OVERRIDE_BASE + 1 : 0);
++}
++
++static void test_sysdb_enumgrent(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++
++    ret = sysdb_enumgrent(test_ctx, test_ctx->domain, &res);
++    check_enumgrent(ret, res, false);
++}
++
++static void test_sysdb_enumgrent_views(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++
++    ret = sysdb_enumgrent_with_views(test_ctx, test_ctx->domain, &res);
++    check_enumgrent(ret, res, true);
++}
++
++static void test_sysdb_enumgrent_filter(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++    char *addtl_filter;
++
++    ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "o*", 0, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_group_attrs(res->msgs[0], "one", 0);
++
++    ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "t*", 0, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 2);
++    assert_group_attrs(res->msgs[0], "three", 0);
++    assert_group_attrs(res->msgs[1], "two", 0);
++
++    ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "x*", 0, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 0);
++
++    ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "*", 0, &res);
++    check_enumgrent(ret, res, false);
++
++    addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)",
++                                   SYSDB_LAST_UPDATE, 1233);
++    ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "o*", addtl_filter, &res);
++    talloc_free(addtl_filter);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 0);
++
++    addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)",
++                                   SYSDB_LAST_UPDATE, 1234);
++    ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "o*", addtl_filter, &res);
++    talloc_free(addtl_filter);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_group_attrs(res->msgs[0], "one", 0);
++
++}
++
++static void test_sysdb_enumgrent_filter_views(void **state)
++{
++    int ret;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                        struct sysdb_test_ctx);
++    struct ldb_result *res;
++    char *addtl_filter;
++
++    ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "o*", NULL, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_group_attrs(res->msgs[0], "one", TEST_GID_OVERRIDE_BASE);
++
++    ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "t*", NULL, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 2);
++    assert_group_attrs(res->msgs[0], "three", TEST_GID_OVERRIDE_BASE + 2);
++    assert_group_attrs(res->msgs[1], "two", TEST_GID_OVERRIDE_BASE + 1);
++
++    addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)",
++                                   SYSDB_LAST_UPDATE, 1235);
++    ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "t*", addtl_filter, &res);
++    talloc_free(addtl_filter);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 1);
++    assert_group_attrs(res->msgs[0], "two", TEST_GID_OVERRIDE_BASE + 1);
++
++    ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "x*", NULL, &res);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(res->count, 0);
++
++    ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain,
++                                            "*", NULL, &res);
++    check_enumgrent(ret, res, true);
+ }
+ 
+ int main(int argc, const char *argv[])
+@@ -453,6 +923,30 @@ int main(int argc, const char *argv[])
+                                         test_sysdb_setup, test_sysdb_teardown),
+         cmocka_unit_test_setup_teardown(test_sysdb_invalidate_overrides,
+                                         test_sysdb_setup, test_sysdb_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumpwent,
++                                        test_enum_users_setup,
++                                        test_enum_users_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumpwent_views,
++                                        test_enum_users_setup,
++                                        test_enum_users_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumpwent_filter,
++                                        test_enum_users_setup,
++                                        test_enum_users_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumpwent_filter_views,
++                                        test_enum_users_setup,
++                                        test_enum_users_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumgrent,
++                                        test_enum_groups_setup,
++                                        test_enum_groups_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumgrent_views,
++                                        test_enum_groups_setup,
++                                        test_enum_groups_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumgrent_filter,
++                                        test_enum_groups_setup,
++                                        test_enum_groups_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_enumgrent_filter_views,
++                                        test_enum_groups_setup,
++                                        test_enum_groups_teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+-- 
+2.4.3
+
diff --git a/SOURCES/0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch b/SOURCES/0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch
new file mode 100644
index 0000000..1d308d5
--- /dev/null
+++ b/SOURCES/0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch
@@ -0,0 +1,114 @@
+From 15dcdcf23bce2423f05c03f7c0aa61f23383d488 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 4 May 2015 12:34:32 +0200
+Subject: [PATCH 04/13] DP: Add DP_WILDCARD and
+ SSS_DP_WILDCARD_USER/SSS_DP_WILDCARD_GROUP
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Extends the Data Provider interface and the responder<->Data provider
+interface with wildcard lookups.
+
+The patch uses a new "wildcard" prefix rather than reusing the existing
+user/group prefixes.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/providers/data_provider.h       |  4 ++++
+ src/providers/data_provider_be.c    |  5 +++++
+ src/responder/common/responder.h    |  4 +++-
+ src/responder/common/responder_dp.c | 11 +++++++++++
+ 4 files changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
+index 13a700308e9c9d1a80c0310dbb1c17de33607498..510c63ce41c99314ec8fcf11fffb2e66082e8951 100644
+--- a/src/providers/data_provider.h
++++ b/src/providers/data_provider.h
+@@ -129,6 +129,7 @@
+ #define BE_FILTER_SECID 4
+ #define BE_FILTER_UUID 5
+ #define BE_FILTER_CERT 6
++#define BE_FILTER_WILDCARD 7
+ 
+ #define BE_REQ_USER          0x0001
+ #define BE_REQ_GROUP         0x0002
+@@ -153,6 +154,9 @@
+ #define DP_SEC_ID_LEN (sizeof(DP_SEC_ID) - 1)
+ #define DP_CERT_LEN (sizeof(DP_CERT) - 1)
+ 
++#define DP_WILDCARD "wildcard"
++#define DP_WILDCARD_LEN (sizeof(DP_WILDCARD) - 1)
++
+ #define EXTRA_NAME_IS_UPN "U"
+ #define EXTRA_INPUT_MAYBE_WITH_VIEW "V"
+ 
+diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
+index f5bdfb676011975defa4c5a734d420c8694f3bdd..d147630248f0a24f5a632760b55b9284a6928e40 100644
+--- a/src/providers/data_provider_be.c
++++ b/src/providers/data_provider_be.c
+@@ -1204,6 +1204,11 @@ static int be_get_account_info(struct sbus_request *dbus_req, void *user_data)
+             ret = split_name_extended(req, &filter[DP_CERT_LEN + 1],
+                                       &req->filter_value,
+                                       &req->extra_value);
++        } else if (strncmp(filter, DP_WILDCARD"=", DP_WILDCARD_LEN + 1) == 0) {
++            req->filter_type = BE_FILTER_WILDCARD;
++            ret = split_name_extended(req, &filter[DP_WILDCARD_LEN + 1],
++                                      &req->filter_value,
++                                      &req->extra_value);
+         } else if (strcmp(filter, ENUM_INDICATOR) == 0) {
+             req->filter_type = BE_FILTER_ENUM;
+             req->filter_value = NULL;
+diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
+index bd0250d52aae1efdac3bc0847f692542c6cfb6d2..4d927cfe321bf3ad240b7c175568081ea73ab652 100644
+--- a/src/responder/common/responder.h
++++ b/src/responder/common/responder.h
+@@ -282,7 +282,9 @@ enum sss_dp_acct_type {
+     SSS_DP_SERVICES,
+     SSS_DP_SECID,
+     SSS_DP_USER_AND_GROUP,
+-    SSS_DP_CERT
++    SSS_DP_CERT,
++    SSS_DP_WILDCARD_USER,
++    SSS_DP_WILDCARD_GROUP,
+ };
+ 
+ struct tevent_req *
+diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c
+index f752c94c37fd0efa0d072ef8c567bd875a08e6f7..f7f8df04e80439d2d02df3e4d2aa4f3576997f36 100644
+--- a/src/responder/common/responder_dp.c
++++ b/src/responder/common/responder_dp.c
+@@ -528,9 +528,11 @@ sss_dp_get_account_msg(void *pvt)
+ 
+     switch (info->type) {
+         case SSS_DP_USER:
++        case SSS_DP_WILDCARD_USER:
+             be_type = BE_REQ_USER;
+             break;
+         case SSS_DP_GROUP:
++        case SSS_DP_WILDCARD_GROUP:
+             be_type = BE_REQ_GROUP;
+             break;
+         case SSS_DP_INITGROUPS:
+@@ -574,6 +576,15 @@ sss_dp_get_account_msg(void *pvt)
+                 filter = talloc_asprintf(info, "%s=%s", DP_CERT,
+                                                info->opt_name);
+             }
++        } else if (info->type == SSS_DP_WILDCARD_USER ||
++                   info->type == SSS_DP_WILDCARD_GROUP) {
++            if (info->extra) {
++                filter = talloc_asprintf(info, "%s=%s:%s", DP_WILDCARD,
++                                               info->opt_name, info->extra);
++            } else {
++                filter = talloc_asprintf(info, "%s=%s", DP_WILDCARD,
++                                               info->opt_name);
++            }
+         } else {
+             if (info->extra) {
+                 filter = talloc_asprintf(info, "name=%s:%s",
+-- 
+2.4.3
+
diff --git a/SOURCES/0004-SSSD-Add-the-options-to-specify-a-UID-and-GID-to-run.patch b/SOURCES/0004-SSSD-Add-the-options-to-specify-a-UID-and-GID-to-run.patch
deleted file mode 100644
index 31302d7..0000000
--- a/SOURCES/0004-SSSD-Add-the-options-to-specify-a-UID-and-GID-to-run.patch
+++ /dev/null
@@ -1,366 +0,0 @@
-From b967aefd1c7463ecad93f63d67c77446584cc829 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 6 Oct 2014 16:28:13 +0200
-Subject: [PATCH 04/22] SSSD: Add the options to specify a UID and GID to run
- as
-
-Adds new command line options --uid and --gid to all SSSD servers,
-making it possible to switch to another user ID if needed.
-
-So far all code still runs as root.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- Makefile.am                       | 7 +++++--
- src/monitor/monitor.c             | 3 ++-
- src/providers/data_provider_be.c  | 5 ++++-
- src/providers/proxy/proxy_child.c | 5 ++++-
- src/responder/autofs/autofssrv.c  | 6 +++++-
- src/responder/ifp/ifpsrv.c        | 6 +++++-
- src/responder/nss/nsssrv.c        | 5 ++++-
- src/responder/pac/pacsrv.c        | 5 ++++-
- src/responder/pam/pamsrv.c        | 5 ++++-
- src/responder/ssh/sshsrv.c        | 5 ++++-
- src/responder/sudo/sudosrv.c      | 6 +++++-
- src/util/server.c                 | 8 ++++++++
- src/util/util.h                   | 7 +++++++
- 13 files changed, 61 insertions(+), 12 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 49acdb107cb45410493dfabe30a2ea4553a23669..b949c9c24070026570de970b545918a7eb279c6d 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -706,14 +706,17 @@ libsss_util_la_SOURCES = \
-     src/util/util_sss_idmap.c \
-     src/util/well_known_sids.c \
-     src/util/string_utils.c \
-+    src/util/become_user.c \
-     $(NULL)
- libsss_util_la_CFLAGS = \
-     $(AM_CFLAGS) \
--    $(SYSTEMD_LOGIN_CFLAGS)
-+    $(SYSTEMD_LOGIN_CFLAGS) \
-+    $(NULL)
- libsss_util_la_LIBADD = \
-     $(SSSD_LIBS) \
-     $(SYSTEMD_LOGIN_LIBS) \
--    $(UNICODE_LIBS)
-+    $(UNICODE_LIBS) \
-+    $(NULL)
- if BUILD_SUDO
-     libsss_util_la_SOURCES += src/db/sysdb_sudo.c
- endif
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 624e45026b01842ab81d8c37d50751977185d20c..edd1c2dfc674d8a7ca9d069d6499c0dcc959f210 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -2855,7 +2855,8 @@ int main(int argc, const char *argv[])
-     ret = close(STDIN_FILENO);
-     if (ret != EOK) return 6;
- 
--    ret = server_setup(MONITOR_NAME, flags, monitor->conf_path, &main_ctx);
-+    ret = server_setup(MONITOR_NAME, flags, 0, 0,
-+                       monitor->conf_path, &main_ctx);
-     if (ret != EOK) return 2;
- 
-     monitor->is_daemon = !opt_interactive;
-diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
-index e7f345f922361b60775e149c1b28f45cf16ed00e..18b50214b0795709d583d5891bf4f6fd220bcb11 100644
---- a/src/providers/data_provider_be.c
-+++ b/src/providers/data_provider_be.c
-@@ -2804,10 +2804,13 @@ int main(int argc, const char *argv[])
-     struct main_context *main_ctx;
-     char *confdb_path;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         {"domain", 0, POPT_ARG_STRING, &be_domain, 0,
-          _("Domain of the information provider (mandatory)"), NULL },
-         POPT_TABLEEND
-@@ -2847,7 +2850,7 @@ int main(int argc, const char *argv[])
-     confdb_path = talloc_asprintf(NULL, CONFDB_DOMAIN_PATH_TMPL, be_domain);
-     if (!confdb_path) return 2;
- 
--    ret = server_setup(srv_name, 0, confdb_path, &main_ctx);
-+    ret = server_setup(srv_name, 0, 0, 0, confdb_path, &main_ctx);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set up mainloop [%d]\n", ret);
-         return 2;
-diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c
-index 6bee1c7f63c4bb5b33f11601c2be32df05206756..e261b2f588a89a27ed6fe78f7fc5cfa053b49833 100644
---- a/src/providers/proxy/proxy_child.c
-+++ b/src/providers/proxy/proxy_child.c
-@@ -504,10 +504,13 @@ int main(int argc, const char *argv[])
-     int ret;
-     long id;
-     char *pam_target = NULL;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         {"domain", 0, POPT_ARG_STRING, &domain, 0,
-          _("Domain of the information provider (mandatory)"), NULL },
-         {"id", 0, POPT_ARG_LONG, &id, 0,
-@@ -557,7 +560,7 @@ int main(int argc, const char *argv[])
-     conf_entry = talloc_asprintf(NULL, CONFDB_DOMAIN_PATH_TMPL, domain);
-     if (!conf_entry) return 2;
- 
--    ret = server_setup(srv_name, 0, conf_entry, &main_ctx);
-+    ret = server_setup(srv_name, 0, 0, 0, conf_entry, &main_ctx);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set up mainloop [%d]\n", ret);
-         return 2;
-diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
-index bd5aa135a3fb64a020e74a9dd39fa1b67dc76533..931cf018bfe15b37bf8e5f93a21c7ab61d238c18 100644
---- a/src/responder/autofs/autofssrv.c
-+++ b/src/responder/autofs/autofssrv.c
-@@ -207,10 +207,13 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     struct main_context *main_ctx;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         POPT_TABLEEND
-     };
- 
-@@ -235,7 +238,8 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_autofs";
- 
--    ret = server_setup("sssd[autofs]", 0, CONFDB_AUTOFS_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[autofs]", 0, 0, 0,
-+                       CONFDB_AUTOFS_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) {
-         return 2;
-     }
-diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
-index 4af836543d3945603d22099b7ab98a90588bce35..8d8fe885abb8ef53ee7f49e763ba78c4dda9a983 100644
---- a/src/responder/ifp/ifpsrv.c
-+++ b/src/responder/ifp/ifpsrv.c
-@@ -441,10 +441,13 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     struct main_context *main_ctx;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         POPT_TABLEEND
-     };
- 
-@@ -469,7 +472,8 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_ifp";
- 
--    ret = server_setup("sssd[ifp]", 0, CONFDB_IFP_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[ifp]", 0, 0, 0,
-+                       CONFDB_IFP_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) return 2;
- 
-     ret = die_if_parent_died();
-diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
-index 84a6b7fedd096a7d4159b7ac6670820c1d8fd941..420fd3d316959a67737f23e9a8b3d1c797583ea3 100644
---- a/src/responder/nss/nsssrv.c
-+++ b/src/responder/nss/nsssrv.c
-@@ -537,10 +537,13 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     struct main_context *main_ctx;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         POPT_TABLEEND
-     };
- 
-@@ -565,7 +568,7 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_nss";
- 
--    ret = server_setup("sssd[nss]", 0, CONFDB_NSS_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[nss]", 0, 0, 0, CONFDB_NSS_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) return 2;
- 
-     ret = die_if_parent_died();
-diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
-index 47a9d1a68fbf1615277af41cef297b4955e7f7c3..b76691de829b4f40937a07ea83825a606950aa1e 100644
---- a/src/responder/pac/pacsrv.c
-+++ b/src/responder/pac/pacsrv.c
-@@ -216,10 +216,13 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     struct main_context *main_ctx;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         POPT_TABLEEND
-     };
- 
-@@ -244,7 +247,7 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_pac";
- 
--    ret = server_setup("sssd[pac]", 0, CONFDB_PAC_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[pac]", 0, 0, 0, CONFDB_PAC_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) return 2;
- 
-     ret = die_if_parent_died();
-diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
-index 428b252acb56406291e3cac5d2a13e6f6b581c36..91b395080820b27f5d57341e59dd739e674be31a 100644
---- a/src/responder/pam/pamsrv.c
-+++ b/src/responder/pam/pamsrv.c
-@@ -316,10 +316,13 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     struct main_context *main_ctx;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         POPT_TABLEEND
-     };
- 
-@@ -344,7 +347,7 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_pam";
- 
--    ret = server_setup("sssd[pam]", 0, CONFDB_PAM_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[pam]", 0, 0, 0, CONFDB_PAM_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) return 2;
- 
-     ret = die_if_parent_died();
-diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
-index 8aa603d79dddb327606f02d9e7ddf2b18a98e700..1328d1746b9e2d6474d6c2f8ce2825be463ca3e7 100644
---- a/src/responder/ssh/sshsrv.c
-+++ b/src/responder/ssh/sshsrv.c
-@@ -184,10 +184,13 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     struct main_context *main_ctx;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         POPT_TABLEEND
-     };
- 
-@@ -212,7 +215,7 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_ssh";
- 
--    ret = server_setup("sssd[ssh]", 0, CONFDB_SSH_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[ssh]", 0, 0, 0, CONFDB_SSH_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) {
-         return 2;
-     }
-diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
-index 8a197159b23abde45953b65121ff2e3fc3f2f67a..30752c9dacdc390b24fe837c0630333b5e171448 100644
---- a/src/responder/sudo/sudosrv.c
-+++ b/src/responder/sudo/sudosrv.c
-@@ -164,10 +164,13 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     struct main_context *main_ctx;
-     int ret;
-+    uid_t uid;
-+    gid_t gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-         SSSD_MAIN_OPTS
-+        SSSD_SERVER_OPTS(uid, gid)
-         POPT_TABLEEND
-     };
- 
-@@ -192,7 +195,8 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_sudo";
- 
--    ret = server_setup("sssd[sudo]", 0, CONFDB_SUDO_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[sudo]", 0, 0, 0, CONFDB_SUDO_CONF_ENTRY,
-+                       &main_ctx);
-     if (ret != EOK) {
-         return 2;
-     }
-diff --git a/src/util/server.c b/src/util/server.c
-index 51934f8ba287d6f6e395231ed893753e10b4c9b0..3a84dee0cee06cb98c94a1d57209c2bcf7c4340a 100644
---- a/src/util/server.c
-+++ b/src/util/server.c
-@@ -412,6 +412,7 @@ errno_t server_common_rotate_logs(struct confdb_ctx *confdb,
- }
- 
- int server_setup(const char *name, int flags,
-+                 uid_t uid, gid_t gid,
-                  const char *conf_entry,
-                  struct main_context **main_ctx)
- {
-@@ -426,6 +427,13 @@ int server_setup(const char *name, int flags,
-     struct tevent_signal *tes;
-     struct logrotate_ctx *lctx;
- 
-+    ret = become_user(uid, gid);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_FUNC_DATA,
-+              "Cannot become user [%"SPRIuid"][%"SPRIgid"].\n", uid, gid);
-+        return ret;
-+    }
-+
-     debug_prg_name = strdup(name);
-     if (!debug_prg_name) {
-         return ENOMEM;
-diff --git a/src/util/util.h b/src/util/util.h
-index 0af4db3fec723ef372f7c1acde0e3f9f013f90e0..cc5588c183006a03525e0540524c28bd9eb4dc57 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -175,6 +175,12 @@ errno_t set_debug_file_from_fd(const int fd);
- 
- #define SSSD_MAIN_OPTS SSSD_DEBUG_OPTS
- 
-+#define SSSD_SERVER_OPTS(uid, gid) \
-+        {"uid", 0, POPT_ARG_INT, &uid, 0, \
-+          _("The user ID to run the server as"), NULL}, \
-+        {"gid", 0, POPT_ARG_INT, &gid, 0, \
-+          _("The group ID to run the server as"), NULL},
-+
- #define FLAGS_NONE 0x0000
- #define FLAGS_DAEMON 0x0001
- #define FLAGS_INTERACTIVE 0x0002
-@@ -242,6 +248,7 @@ errno_t server_common_rotate_logs(struct confdb_ctx *confdb,
- int die_if_parent_died(void);
- int pidfile(const char *path, const char *name);
- int server_setup(const char *name, int flags,
-+                 uid_t uid, gid_t gid,
-                  const char *conf_entry,
-                  struct main_context **main_ctx);
- void server_loop(struct main_context *main_ctx);
--- 
-1.9.3
-
diff --git a/SOURCES/0005-SSSD-Chown-the-log-files.patch b/SOURCES/0005-SSSD-Chown-the-log-files.patch
deleted file mode 100644
index f1f2b37..0000000
--- a/SOURCES/0005-SSSD-Chown-the-log-files.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From 9f4f7549998e4047063fc12561068893b2100d59 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 20 Oct 2014 13:59:49 +0200
-Subject: [PATCH 05/22] SSSD: Chown the log files
-
-We need to chown the log files before dropping root to make sure they
-are usable by the SSSD user. Unfortunately, we can't just rely on
-passing the fd opened by root, because we need to be also able to rotate
-the log files.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/util/debug.c  | 33 +++++++++++++++++++++++++++++++++
- src/util/server.c |  6 ++++++
- src/util/util.h   |  1 +
- 3 files changed, 40 insertions(+)
-
-diff --git a/src/util/debug.c b/src/util/debug.c
-index a99d5403a238f125010b9b309355b30f9f528c44..41375709170abe33b0c7fd90e3b1244299ed0241 100644
---- a/src/util/debug.c
-+++ b/src/util/debug.c
-@@ -297,6 +297,39 @@ void ldb_debug_messages(void *context, enum ldb_debug_level level,
-     free(message);
- }
- 
-+/* In cases SSSD used to run as the root user, but runs as the SSSD user now,
-+ * we need to chown the log files
-+ */
-+int chown_debug_file(const char *filename,
-+                     uid_t uid, gid_t gid)
-+{
-+    char *logpath;
-+    const char *log_file;
-+    errno_t ret;
-+
-+    if (filename == NULL) {
-+        log_file = debug_log_file;
-+    } else {
-+        log_file = filename;
-+    }
-+
-+    ret = asprintf(&logpath, "%s/%s.log", LOG_PATH, log_file);
-+    if (ret == -1) {
-+        return ENOMEM;
-+    }
-+
-+    ret = chown(logpath, uid, gid);
-+    free(logpath);
-+    if (ret != 0) {
-+        ret = errno;
-+        DEBUG(SSSDBG_FATAL_FAILURE, "chown failed for [%s]: [%d]\n",
-+              log_file, ret);
-+        return ret;
-+    }
-+
-+    return EOK;
-+}
-+
- int open_debug_file_ex(const char *filename, FILE **filep, bool want_cloexec)
- {
-     FILE *f = NULL;
-diff --git a/src/util/server.c b/src/util/server.c
-index 3a84dee0cee06cb98c94a1d57209c2bcf7c4340a..a908470cdcf2cb85a6742e44905ae12d136c83d5 100644
---- a/src/util/server.c
-+++ b/src/util/server.c
-@@ -427,6 +427,12 @@ int server_setup(const char *name, int flags,
-     struct tevent_signal *tes;
-     struct logrotate_ctx *lctx;
- 
-+    ret = chown_debug_file(NULL, uid, gid);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Cannot chown the debug files, debugging might not work!\n");
-+    }
-+
-     ret = become_user(uid, gid);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FUNC_DATA,
-diff --git a/src/util/util.h b/src/util/util.h
-index cc5588c183006a03525e0540524c28bd9eb4dc57..df83aac7d53ccadb806e8a1be90f0e45abb829ae 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -218,6 +218,7 @@ errno_t set_debug_file_from_fd(const int fd);
- /* From debug.c */
- void ldb_debug_messages(void *context, enum ldb_debug_level level,
-                         const char *fmt, va_list ap);
-+int chown_debug_file(const char *filename, uid_t uid, gid_t gid);
- int open_debug_file_ex(const char *filename, FILE **filep, bool want_cloexec);
- int open_debug_file(void);
- int rotate_debug_files(void);
--- 
-1.9.3
-
diff --git a/SOURCES/0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch b/SOURCES/0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch
new file mode 100644
index 0000000..40a41fb
--- /dev/null
+++ b/SOURCES/0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch
@@ -0,0 +1,800 @@
+From e069e53495d77bc737abd80fb2e7799fa6245e0f Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 24 Mar 2015 23:24:50 +0100
+Subject: [PATCH 05/13] cache_req: Extend cache_req with wildcard lookups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Adds two new functions to the cache_req API:
+    - cache_req_user_by_filter_send
+    - cache_req_group_by_filter_send
+
+These functions can be used to retrieve users or groups that match a
+specified filter.
+
+Also renames a variable to avoid constant confusion -- the variable is
+only used for debug output.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/responder/common/responder_cache_req.c  | 156 ++++++++++-
+ src/responder/common/responder_cache_req.h  |  24 +-
+ src/tests/cmocka/test_responder_cache_req.c | 414 +++++++++++++++++++++++++++-
+ 3 files changed, 579 insertions(+), 15 deletions(-)
+
+diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c
+index dd81abadf71c5e10e7bc2ea2490429a49bdc0270..e7099f171d7ef39af7b146a524dadc38a9165e22 100644
+--- a/src/responder/common/responder_cache_req.c
++++ b/src/responder/common/responder_cache_req.c
+@@ -28,6 +28,44 @@
+ #include "responder/common/responder_cache_req.h"
+ #include "providers/data_provider.h"
+ 
++static errno_t updated_users_by_filter(TALLOC_CTX *mem_ctx,
++                                       struct sss_domain_info *domain,
++                                       const char *name_filter,
++                                       time_t since,
++                                       struct ldb_result **_res)
++{
++    int ret;
++    char *recent_filter;
++
++    recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)",
++                                    SYSDB_LAST_UPDATE, since);
++    ret = sysdb_enumpwent_filter_with_views(mem_ctx, domain,
++                                            name_filter, recent_filter,
++                                            _res);
++    talloc_free(recent_filter);
++
++    return ret;
++}
++
++static errno_t updated_groups_by_filter(TALLOC_CTX *mem_ctx,
++                                        struct sss_domain_info *domain,
++                                        const char *name_filter,
++                                        time_t since,
++                                        struct ldb_result **_res)
++{
++    int ret;
++    char *recent_filter;
++
++    recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)",
++                                    SYSDB_LAST_UPDATE, since);
++    ret = sysdb_enumgrent_filter_with_views(mem_ctx, domain,
++                                            name_filter, recent_filter,
++                                            _res);
++    talloc_free(recent_filter);
++
++    return ret;
++}
++
+ struct cache_req_input {
+     enum cache_req_type type;
+ 
+@@ -51,6 +89,8 @@ struct cache_req_input {
+ 
+     /* Fully qualified object name used in debug messages. */
+     const char *debug_fqn;
++    /* Time when the request started. Useful for by-filter lookups */
++    time_t req_start;
+ };
+ 
+ struct cache_req_input *
+@@ -68,11 +108,14 @@ cache_req_input_create(TALLOC_CTX *mem_ctx,
+     }
+ 
+     input->type = type;
++    input->req_start = time(NULL);
+ 
+     /* Check that input parameters match selected type. */
+     switch (input->type) {
+     case CACHE_REQ_USER_BY_NAME:
+     case CACHE_REQ_GROUP_BY_NAME:
++    case CACHE_REQ_USER_BY_FILTER:
++    case CACHE_REQ_GROUP_BY_FILTER:
+     case CACHE_REQ_INITGROUPS:
+         if (name == NULL) {
+             DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL!\n");
+@@ -121,9 +164,18 @@ cache_req_input_create(TALLOC_CTX *mem_ctx,
+     case CACHE_REQ_INITGROUPS:
+         input->dp_type = SSS_DP_INITGROUPS;
+         break;
++
+     case CACHE_REQ_USER_BY_CERT:
+         input->dp_type = SSS_DP_CERT;
+         break;
++
++    case CACHE_REQ_USER_BY_FILTER:
++        input->dp_type = SSS_DP_WILDCARD_USER;
++        break;
++
++    case CACHE_REQ_GROUP_BY_FILTER:
++        input->dp_type = SSS_DP_WILDCARD_GROUP;
++        break;
+     }
+ 
+     return input;
+@@ -157,7 +209,7 @@ cache_req_input_set_domain(struct cache_req_input *input,
+ {
+     TALLOC_CTX *tmp_ctx = NULL;
+     const char *name = NULL;
+-    const char *fqn = NULL;
++    const char *debug_fqn = NULL;
+     errno_t ret;
+ 
+     tmp_ctx = talloc_new(NULL);
+@@ -171,6 +223,8 @@ cache_req_input_set_domain(struct cache_req_input *input,
+     switch (input->type) {
+     case CACHE_REQ_USER_BY_NAME:
+     case CACHE_REQ_GROUP_BY_NAME:
++    case CACHE_REQ_USER_BY_FILTER:
++    case CACHE_REQ_GROUP_BY_FILTER:
+     case CACHE_REQ_INITGROUPS:
+         name = sss_get_cased_name(tmp_ctx, input->orig_name,
+                                   domain->case_sensitive);
+@@ -185,8 +239,8 @@ cache_req_input_set_domain(struct cache_req_input *input,
+             goto done;
+         }
+ 
+-        fqn = talloc_asprintf(tmp_ctx, "%s@%s", name, domain->name);
+-        if (fqn == NULL) {
++        debug_fqn = talloc_asprintf(tmp_ctx, "%s@%s", name, domain->name);
++        if (debug_fqn == NULL) {
+             ret = ENOMEM;
+             goto done;
+         }
+@@ -194,16 +248,16 @@ cache_req_input_set_domain(struct cache_req_input *input,
+         break;
+ 
+     case CACHE_REQ_USER_BY_ID:
+-        fqn = talloc_asprintf(tmp_ctx, "UID:%d@%s", input->id, domain->name);
+-        if (fqn == NULL) {
++        debug_fqn = talloc_asprintf(tmp_ctx, "UID:%d@%s", input->id, domain->name);
++        if (debug_fqn == NULL) {
+             ret = ENOMEM;
+             goto done;
+         }
+         break;
+ 
+     case CACHE_REQ_GROUP_BY_ID:
+-        fqn = talloc_asprintf(tmp_ctx, "GID:%d@%s", input->id, domain->name);
+-        if (fqn == NULL) {
++        debug_fqn = talloc_asprintf(tmp_ctx, "GID:%d@%s", input->id, domain->name);
++        if (debug_fqn == NULL) {
+             ret = ENOMEM;
+             goto done;
+         }
+@@ -211,10 +265,10 @@ cache_req_input_set_domain(struct cache_req_input *input,
+     case CACHE_REQ_USER_BY_CERT:
+         /* certificates might be quite long, only use the last 10 charcters
+          * for logging */
+-        fqn = talloc_asprintf(tmp_ctx, "CERT:%s@%s",
+-                              get_last_x_chars(input->cert, 10),
+-                              domain->name);
+-        if (fqn == NULL) {
++        debug_fqn = talloc_asprintf(tmp_ctx, "CERT:%s@%s",
++                                    get_last_x_chars(input->cert, 10),
++                                    domain->name);
++        if (debug_fqn == NULL) {
+             ret = ENOMEM;
+             goto done;
+         }
+@@ -223,7 +277,7 @@ cache_req_input_set_domain(struct cache_req_input *input,
+ 
+     input->domain = domain;
+     input->dom_objname = talloc_steal(input, name);
+-    input->debug_fqn = talloc_steal(input, fqn);
++    input->debug_fqn = talloc_steal(input, debug_fqn);
+ 
+     ret = EOK;
+ 
+@@ -257,6 +311,10 @@ static errno_t cache_req_check_ncache(struct cache_req_input *input,
+     case CACHE_REQ_USER_BY_CERT:
+         ret = sss_ncache_check_cert(ncache, neg_timeout, input->cert);
+         break;
++    case CACHE_REQ_USER_BY_FILTER:
++    case CACHE_REQ_GROUP_BY_FILTER:
++        ret = EOK;
++        break;
+     }
+ 
+     if (ret == EEXIST) {
+@@ -282,6 +340,10 @@ static void cache_req_add_to_ncache(struct cache_req_input *input,
+         ret = sss_ncache_set_group(ncache, false, input->domain,
+                                    input->dom_objname);
+         break;
++    case CACHE_REQ_USER_BY_FILTER:
++    case CACHE_REQ_GROUP_BY_FILTER:
++        /* Nothing to do, adding a wildcard request to ncache doesn't
++         * make sense */
+     case CACHE_REQ_USER_BY_ID:
+     case CACHE_REQ_GROUP_BY_ID:
+     case CACHE_REQ_USER_BY_CERT:
+@@ -308,6 +370,10 @@ static void cache_req_add_to_ncache_global(struct cache_req_input *input,
+     errno_t ret = ERR_INTERNAL;
+ 
+     switch (input->type) {
++    case CACHE_REQ_USER_BY_FILTER:
++    case CACHE_REQ_GROUP_BY_FILTER:
++        /* Nothing to do, adding a wildcard request to ncache doesn't
++         * make sense */
+     case CACHE_REQ_USER_BY_NAME:
+     case CACHE_REQ_GROUP_BY_NAME:
+     case CACHE_REQ_INITGROUPS:
+@@ -377,6 +443,18 @@ static errno_t cache_req_get_object(TALLOC_CTX *mem_ctx,
+         ret = sysdb_search_user_by_cert(mem_ctx, input->domain,
+                                         input->cert, &result);
+         break;
++    case CACHE_REQ_USER_BY_FILTER:
++        one_item_only = false;
++        ret = updated_users_by_filter(mem_ctx, input->domain,
++                                      input->dom_objname, input->req_start,
++                                      &result);
++        break;
++    case CACHE_REQ_GROUP_BY_FILTER:
++        one_item_only = false;
++        ret = updated_groups_by_filter(mem_ctx, input->domain,
++                                       input->dom_objname, input->req_start,
++                                       &result);
++        break;
+     }
+ 
+     if (ret != EOK) {
+@@ -397,6 +475,19 @@ done:
+     return ret;
+ }
+ 
++/* Return true if the request bypasses cache or false if the cache_req
++ * code can leverage sysdb for this request.
++ */
++static bool cache_req_bypass_cache(struct cache_req_input *input)
++{
++    if (input->type == CACHE_REQ_USER_BY_FILTER ||
++            input->type == CACHE_REQ_GROUP_BY_FILTER) {
++        return true;
++    }
++
++    return false;
++}
++
+ struct cache_req_cache_state {
+     /* input data */
+     struct tevent_context *ev;
+@@ -504,7 +595,8 @@ static errno_t cache_req_cache_check(struct tevent_req *req)
+ 
+     state = tevent_req_data(req, struct cache_req_cache_state);
+ 
+-    if (state->result == NULL || state->result->count == 0) {
++    if (state->result == NULL || state->result->count == 0 ||
++            cache_req_bypass_cache(state->input) == true) {
+         ret = ENOENT;
+     } else {
+         if (state->input->type == CACHE_REQ_INITGROUPS) {
+@@ -1059,3 +1151,41 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx,
+                                           neg_timeout, cache_refresh_percent,
+                                           domain, input);
+ }
++
++struct tevent_req *
++cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx,
++                              struct tevent_context *ev,
++                              struct resp_ctx *rctx,
++                              const char *domain,
++                              const char *filter)
++{
++    struct cache_req_input *input;
++
++    input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_FILTER,
++                                   filter, 0, NULL);
++    if (input == NULL) {
++        return NULL;
++    }
++
++    return cache_req_steal_input_and_send(mem_ctx, ev, rctx, NULL,
++                                          0, 0, domain, input);
++}
++
++struct tevent_req *
++cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx,
++                               struct tevent_context *ev,
++                               struct resp_ctx *rctx,
++                               const char *domain,
++                               const char *filter)
++{
++    struct cache_req_input *input;
++
++    input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_FILTER,
++                                   filter, 0, NULL);
++    if (input == NULL) {
++        return NULL;
++    }
++
++    return cache_req_steal_input_and_send(mem_ctx, ev, rctx, NULL,
++                                          0, 0, domain, input);
++}
+diff --git a/src/responder/common/responder_cache_req.h b/src/responder/common/responder_cache_req.h
+index 84a9dde7d9df066e44b1352e0a4557f02d08cc15..9e3f88a1427f3dcbde9f81df2ec647821b7aa931 100644
+--- a/src/responder/common/responder_cache_req.h
++++ b/src/responder/common/responder_cache_req.h
+@@ -33,7 +33,9 @@ enum cache_req_type {
+     CACHE_REQ_GROUP_BY_NAME,
+     CACHE_REQ_GROUP_BY_ID,
+     CACHE_REQ_INITGROUPS,
+-    CACHE_REQ_USER_BY_CERT
++    CACHE_REQ_USER_BY_CERT,
++    CACHE_REQ_USER_BY_FILTER,
++    CACHE_REQ_GROUP_BY_FILTER,
+ };
+ 
+ struct cache_req_input;
+@@ -143,4 +145,24 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx,
+ #define cache_req_initgr_by_name_recv(mem_ctx, req, _result, _domain, _name) \
+     cache_req_recv(mem_ctx, req, _result, _domain, _name)
+ 
++struct tevent_req *
++cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx,
++                              struct tevent_context *ev,
++                              struct resp_ctx *rctx,
++                              const char *domain,
++                              const char *filter);
++
++#define cache_req_user_by_filter_recv(mem_ctx, req, _result, _domain) \
++    cache_req_recv(mem_ctx, req, _result, _domain, NULL)
++
++struct tevent_req *
++cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx,
++                              struct tevent_context *ev,
++                              struct resp_ctx *rctx,
++                              const char *domain,
++                              const char *filter);
++
++#define cache_req_group_by_filter_recv(mem_ctx, req, _result, _domain) \
++    cache_req_recv(mem_ctx, req, _result, _domain, NULL)
++
+ #endif /* RESPONDER_CACHE_H_ */
+diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c
+index e30deed1c6bc4023a4f2154db21fe1339e9bb3c5..31b6694668607815652f45bc93210554fd2ac918 100644
+--- a/src/tests/cmocka/test_responder_cache_req.c
++++ b/src/tests/cmocka/test_responder_cache_req.c
+@@ -38,6 +38,9 @@
+ #define TEST_GROUP_NAME "test-group"
+ #define TEST_GROUP_ID 1000
+ 
++#define TEST_USER_NAME2 "test-user2"
++#define TEST_GROUP_NAME2 "test-group2"
++
+ #define new_single_domain_test(test) \
+     cmocka_unit_test_setup_teardown(test_ ## test, \
+                                     test_single_domain_setup, \
+@@ -1694,6 +1697,405 @@ void test_group_by_id_missing_notfound(void **state)
+     assert_true(test_ctx->dp_called);
+ }
+ 
++static void cache_req_user_by_filter_test_done(struct tevent_req *req)
++{
++    struct cache_req_test_ctx *ctx = NULL;
++
++    ctx = tevent_req_callback_data(req, struct cache_req_test_ctx);
++
++    ctx->tctx->error = cache_req_user_by_filter_recv(ctx, req,
++                                                     &ctx->result,
++                                                     &ctx->domain);
++    talloc_zfree(req);
++    ctx->tctx->done = true;
++}
++
++void test_users_by_filter_valid(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    const char *ldbname = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++    test_ctx->create_user = true;
++
++    ret = sysdb_store_user(test_ctx->tctx->dom, TEST_USER_NAME2, "pwd", 1001, 1001,
++                           NULL, NULL, NULL, "cn="TEST_USER_NAME2",dc=test", NULL,
++                           NULL, 1000, time(NULL));
++    assert_int_equal(ret, EOK);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                        test_ctx->rctx,
++                                        test_ctx->tctx->dom->name,
++                                        "test*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ERR_OK);
++    assert_true(check_leaks_pop(req_mem_ctx));
++
++    assert_non_null(test_ctx->result);
++    assert_int_equal(test_ctx->result->count, 2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_USER_NAME2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_USER_NAME);
++}
++
++void test_users_by_filter_filter_old(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    const char *ldbname = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++    test_ctx->create_user = true;
++
++    /* This user was updated in distant past, so it wont't be reported by
++     * the filter search */
++    ret = sysdb_store_user(test_ctx->tctx->dom, TEST_USER_NAME2, "pwd", 1001, 1001,
++                           NULL, NULL, NULL, "cn="TEST_USER_NAME2",dc=test", NULL,
++                           NULL, 1000, 1);
++    assert_int_equal(ret, EOK);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                        test_ctx->rctx,
++                                        test_ctx->tctx->dom->name,
++                                        "test*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ERR_OK);
++    assert_true(check_leaks_pop(req_mem_ctx));
++
++    assert_non_null(test_ctx->result);
++    assert_int_equal(test_ctx->result->count, 1);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_USER_NAME);
++}
++
++void test_users_by_filter_notfound(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                        test_ctx->rctx,
++                                        test_ctx->tctx->dom->name,
++                                        "nosuchuser*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ENOENT);
++    assert_true(check_leaks_pop(req_mem_ctx));
++}
++
++static void test_users_by_filter_multiple_domains_valid(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    struct sss_domain_info *domain = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    const char *ldbname = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++
++    domain = find_domain_by_name(test_ctx->tctx->dom,
++                                 "responder_cache_req_test_d", true);
++    assert_non_null(domain);
++
++    ret = sysdb_store_user(domain, TEST_USER_NAME, "pwd", 1000, 1000,
++                           NULL, NULL, NULL, "cn="TEST_USER_NAME",dc=test", NULL,
++                           NULL, 1000, time(NULL));
++    assert_int_equal(ret, EOK);
++
++    ret = sysdb_store_user(domain, TEST_USER_NAME2, "pwd", 1001, 1001,
++                           NULL, NULL, NULL, "cn="TEST_USER_NAME2",dc=test", NULL,
++                           NULL, 1000, time(NULL));
++    assert_int_equal(ret, EOK);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                        test_ctx->rctx,
++                                        domain->name,
++                                        "test*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ERR_OK);
++    assert_true(check_leaks_pop(req_mem_ctx));
++
++    assert_non_null(test_ctx->result);
++    assert_int_equal(test_ctx->result->count, 2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_USER_NAME2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_USER_NAME);
++}
++
++static void test_users_by_filter_multiple_domains_notfound(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    struct sss_domain_info *domain = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++
++    domain = find_domain_by_name(test_ctx->tctx->dom,
++                                 "responder_cache_req_test_d", true);
++    assert_non_null(domain);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                        test_ctx->rctx,
++                                        domain->name,
++                                        "nosuchuser*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ENOENT);
++    assert_true(check_leaks_pop(req_mem_ctx));
++}
++
++static void cache_req_group_by_filter_test_done(struct tevent_req *req)
++{
++    struct cache_req_test_ctx *ctx = NULL;
++
++    ctx = tevent_req_callback_data(req, struct cache_req_test_ctx);
++
++    ctx->tctx->error = cache_req_group_by_filter_recv(ctx, req,
++                                                      &ctx->result,
++                                                      &ctx->domain);
++    talloc_zfree(req);
++    ctx->tctx->done = true;
++}
++
++void test_groups_by_filter_valid(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    const char *ldbname = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++    test_ctx->create_group = true;
++
++    ret = sysdb_store_group(test_ctx->tctx->dom, TEST_GROUP_NAME2,
++                            1001, NULL, 1001, time(NULL));
++    assert_int_equal(ret, EOK);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                         test_ctx->rctx,
++                                         test_ctx->tctx->dom->name,
++                                         "test*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ERR_OK);
++    assert_true(check_leaks_pop(req_mem_ctx));
++
++    assert_non_null(test_ctx->result);
++    assert_int_equal(test_ctx->result->count, 2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_GROUP_NAME2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_GROUP_NAME);
++}
++
++void test_groups_by_filter_notfound(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                        test_ctx->rctx,
++                                        test_ctx->tctx->dom->name,
++                                        "nosuchgroup*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ENOENT);
++    assert_true(check_leaks_pop(req_mem_ctx));
++}
++
++void test_groups_by_filter_multiple_domains_valid(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    struct sss_domain_info *domain = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    const char *ldbname = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++
++    domain = find_domain_by_name(test_ctx->tctx->dom,
++                                 "responder_cache_req_test_d", true);
++    assert_non_null(domain);
++
++    ret = sysdb_store_group(domain, TEST_GROUP_NAME,
++                            1000, NULL, 1000, time(NULL));
++    assert_int_equal(ret, EOK);
++
++    ret = sysdb_store_group(domain, TEST_GROUP_NAME2,
++                            1001, NULL, 1001, time(NULL));
++    assert_int_equal(ret, EOK);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                         test_ctx->rctx,
++                                         domain->name,
++                                         "test*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ERR_OK);
++    assert_true(check_leaks_pop(req_mem_ctx));
++
++    assert_non_null(test_ctx->result);
++    assert_int_equal(test_ctx->result->count, 2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_GROUP_NAME2);
++
++    ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1],
++                                          SYSDB_NAME, NULL);
++    assert_non_null(ldbname);
++    assert_string_equal(ldbname, TEST_GROUP_NAME);
++}
++
++void test_groups_by_filter_multiple_domains_notfound(void **state)
++{
++    struct cache_req_test_ctx *test_ctx = NULL;
++    struct sss_domain_info *domain = NULL;
++    TALLOC_CTX *req_mem_ctx = NULL;
++    struct tevent_req *req = NULL;
++    errno_t ret;
++
++    test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx);
++    domain = find_domain_by_name(test_ctx->tctx->dom,
++                                 "responder_cache_req_test_d", true);
++    assert_non_null(domain);
++
++    req_mem_ctx = talloc_new(global_talloc_context);
++    check_leaks_push(req_mem_ctx);
++
++    /* Filters always go to DP */
++    will_return(__wrap_sss_dp_get_account_send, test_ctx);
++    mock_account_recv_simple();
++
++    req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev,
++                                        test_ctx->rctx,
++                                        domain->name,
++                                        "nosuchgroup*");
++    assert_non_null(req);
++    tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ENOENT);
++    assert_true(check_leaks_pop(req_mem_ctx));
++}
++
+ int main(int argc, const char *argv[])
+ {
+     poptContext pc;
+@@ -1741,7 +2143,17 @@ int main(int argc, const char *argv[])
+         new_single_domain_test(group_by_id_missing_found),
+         new_single_domain_test(group_by_id_missing_notfound),
+         new_multi_domain_test(group_by_id_multiple_domains_found),
+-        new_multi_domain_test(group_by_id_multiple_domains_notfound)
++        new_multi_domain_test(group_by_id_multiple_domains_notfound),
++
++        new_single_domain_test(users_by_filter_valid),
++        new_single_domain_test(users_by_filter_filter_old),
++        new_single_domain_test(users_by_filter_notfound),
++        new_multi_domain_test(users_by_filter_multiple_domains_valid),
++        new_multi_domain_test(users_by_filter_multiple_domains_notfound),
++        new_single_domain_test(groups_by_filter_valid),
++        new_single_domain_test(groups_by_filter_notfound),
++        new_multi_domain_test(groups_by_filter_multiple_domains_valid),
++        new_multi_domain_test(groups_by_filter_multiple_domains_notfound),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+-- 
+2.4.3
+
diff --git a/SOURCES/0006-UTIL-Add-sss_filter_sanitize_ex.patch b/SOURCES/0006-UTIL-Add-sss_filter_sanitize_ex.patch
new file mode 100644
index 0000000..2c48cf8
--- /dev/null
+++ b/SOURCES/0006-UTIL-Add-sss_filter_sanitize_ex.patch
@@ -0,0 +1,118 @@
+From f736b14f1e308d67e091d3ee56ef0384d618130e Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 4 May 2015 13:10:01 +0200
+Subject: [PATCH 06/13] UTIL: Add sss_filter_sanitize_ex
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+In order to support wildcard request, we need to introduce an optionally
+relaxed version of sss_filter_sanitize that allows to select which
+characters are exempt from sanitizing.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/tests/util-tests.c |  9 +++++++++
+ src/util/util.c        | 28 +++++++++++++++++++++++++---
+ src/util/util.h        |  5 +++++
+ 3 files changed, 39 insertions(+), 3 deletions(-)
+
+diff --git a/src/tests/util-tests.c b/src/tests/util-tests.c
+index 3d42f0193a677200d5cb4a46805892bed978305c..bfdf078027250b8ff0ce0da2d37fbb20f391d06b 100644
+--- a/src/tests/util-tests.c
++++ b/src/tests/util-tests.c
+@@ -406,6 +406,15 @@ START_TEST(test_sss_filter_sanitize)
+                 "Expected [%s], got [%s]",
+                 has_all_expected, sanitized);
+ 
++    /* Input is reused from previous test - "\\(user)*name" */
++    const char has_all_allow_asterisk_expected[] = "\\5c\\28user\\29*name";
++    ret = sss_filter_sanitize_ex(test_ctx, has_all, &sanitized, "*");
++    fail_unless(ret == EOK, "has_all error [%d][%s]",
++                ret, strerror(ret));
++    fail_unless(strcmp(has_all_allow_asterisk_expected, sanitized)==0,
++                "Expected [%s], got [%s]",
++                has_all_expected, sanitized);
++
+     talloc_free(test_ctx);
+ }
+ END_TEST
+diff --git a/src/util/util.c b/src/util/util.c
+index cfd26a58b31048996e9669163b821282b219b2de..782cd026b7928e607a8980fb5f333c794feb5b1a 100644
+--- a/src/util/util.c
++++ b/src/util/util.c
+@@ -525,13 +525,15 @@ errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count,
+     return sss_hash_create_ex(mem_ctx, count, tbl, 0, 0, 0, 0, NULL, NULL);
+ }
+ 
+-errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
+-                            const char *input,
+-                            char **sanitized)
++errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
++                               const char *input,
++                               char **sanitized,
++                               const char *ignore)
+ {
+     char *output;
+     size_t i = 0;
+     size_t j = 0;
++    char *allowed;
+ 
+     /* Assume the worst-case. We'll resize it later, once */
+     output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
+@@ -540,6 +542,19 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
+     }
+ 
+     while (input[i]) {
++        /* Even though this character might have a special meaning, if it's
++         * expliticly allowed, just copy it and move on
++         */
++        if (ignore == NULL) {
++            allowed = NULL;
++        } else {
++            allowed = strchr(ignore, input[i]);
++        }
++        if (allowed) {
++            output[j++] = input[i++];
++            continue;
++        }
++
+         switch(input[i]) {
+         case '\t':
+             output[j++] = '\\';
+@@ -587,6 +602,13 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
+     return EOK;
+ }
+ 
++errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
++                            const char *input,
++                            char **sanitized)
++{
++    return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
++}
++
+ char *
+ sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr)
+ {
+diff --git a/src/util/util.h b/src/util/util.h
+index 3d90cf0d1024b93016987a4d3e8a515359fd974d..94a3ddea839f0998cb7796f1d2fe13f743de3aaf 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -485,6 +485,11 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
+                             const char *input,
+                             char **sanitized);
+ 
++errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
++                               const char *input,
++                               char **sanitized,
++                               const char *ignore);
++
+ errno_t sss_filter_sanitize_for_dom(TALLOC_CTX *mem_ctx,
+                                     const char *input,
+                                     struct sss_domain_info *dom,
+-- 
+2.4.3
+
diff --git a/SOURCES/0006-UTIL-Use-a-custom-PID_PATH-and-DB_PATH-when-unit-tes.patch b/SOURCES/0006-UTIL-Use-a-custom-PID_PATH-and-DB_PATH-when-unit-tes.patch
deleted file mode 100644
index 23fb933..0000000
--- a/SOURCES/0006-UTIL-Use-a-custom-PID_PATH-and-DB_PATH-when-unit-tes.patch
+++ /dev/null
@@ -1,80 +0,0 @@
-From a2fbe2b9de23e91835c10153d048c1b0c5ec7fee Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 3 Oct 2014 16:09:38 +0200
-Subject: [PATCH 06/22] UTIL: Use a custom PID_PATH and DB_PATH when unit
- testing server.c
-
-server.c used hardcoded PID_PATH and DB_PATH from config.h. Normally,
-this path resides in a system directory (like /var/) and should not be
-written to by tests. In order to specify a different one for tests, we
-need to conditionalize normal builds and unit test builds.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/util/server.c | 35 +++++++++++++++++++++++++++++++----
- 1 file changed, 31 insertions(+), 4 deletions(-)
-
-diff --git a/src/util/server.c b/src/util/server.c
-index a908470cdcf2cb85a6742e44905ae12d136c83d5..03f4b9588e6c5322d9b68b8cac90128bcb5cfcb6 100644
---- a/src/util/server.c
-+++ b/src/util/server.c
-@@ -411,6 +411,32 @@ errno_t server_common_rotate_logs(struct confdb_ctx *confdb,
-     return EOK;
- }
- 
-+static const char *get_db_path(void)
-+{
-+#ifdef UNIT_TESTING
-+#ifdef TEST_DB_PATH
-+    return TEST_DB_PATH;
-+#else
-+    #error "TEST_DB_PATH must be defined when unit testing server.c!"
-+#endif /* TEST_DB_PATH */
-+#else
-+    return DB_PATH;
-+#endif /* UNIT_TESTING */
-+}
-+
-+static const char *get_pid_path(void)
-+{
-+#ifdef UNIT_TESTING
-+#ifdef TEST_PID_PATH
-+    return TEST_PID_PATH;
-+#else
-+    #error "TEST_PID_PATH must be defined when unit testing server.c!"
-+#endif /* TEST_PID_PATH */
-+#else
-+    return PID_PATH;
-+#endif
-+}
-+
- int server_setup(const char *name, int flags,
-                  uid_t uid, gid_t gid,
-                  const char *conf_entry,
-@@ -468,10 +494,10 @@ int server_setup(const char *name, int flags,
-     }
- 
-     if (flags & FLAGS_PID_FILE) {
--        ret = pidfile(PID_PATH, name);
-+        ret = pidfile(get_pid_path(), name);
-         if (ret != EOK) {
--            DEBUG(SSSDBG_FATAL_FAILURE, "Error creating pidfile: %s/%s! "
--                  "(%d [%s])\n", PID_PATH, name, ret, strerror(ret));
-+            DEBUG(SSSDBG_FATAL_FAILURE, "Error creating pidfile: %s/%s.pid! "
-+                  "(%d [%s])\n", get_pid_path(), name, ret, strerror(ret));
-             return ret;
-         }
-     }
-@@ -513,7 +539,8 @@ int server_setup(const char *name, int flags,
-     ctx->parent_pid = getppid();
-     ctx->event_ctx = event_ctx;
- 
--    conf_db = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
-+    conf_db = talloc_asprintf(ctx, "%s/%s",
-+                              get_db_path(), CONFDB_FILE);
-     if (conf_db == NULL) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory, aborting!\n");
-         return ENOMEM;
--- 
-1.9.3
-
diff --git a/SOURCES/0007-LDAP-Fetch-users-and-groups-using-wildcards.patch b/SOURCES/0007-LDAP-Fetch-users-and-groups-using-wildcards.patch
new file mode 100644
index 0000000..d02553f
--- /dev/null
+++ b/SOURCES/0007-LDAP-Fetch-users-and-groups-using-wildcards.patch
@@ -0,0 +1,147 @@
+From 9604ff1731ab7bd067bef62a0df6000eca091856 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 4 May 2015 15:16:44 +0200
+Subject: [PATCH 07/13] LDAP: Fetch users and groups using wildcards
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Adds handler for the BE_FILTER_WILDCARD in the LDAP provider. So far
+it's the same code as if enumeration was used, so there are no limits.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/providers/ldap/ldap_common.h |  3 +++
+ src/providers/ldap/ldap_id.c     | 50 ++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 51 insertions(+), 2 deletions(-)
+
+diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
+index 424eacb1da0a6934b132ccb2a5bb175233fa1a80..8294d1db23bdca8d94a098533d93405c4d55226b 100644
+--- a/src/providers/ldap/ldap_common.h
++++ b/src/providers/ldap/ldap_common.h
+@@ -39,6 +39,9 @@
+ #define LDAP_SSL_URI "ldaps://"
+ #define LDAP_LDAPI_URI "ldapi://"
+ 
++/* Only the asterisk is allowed in wildcard requests */
++#define LDAP_ALLOWED_WILDCARDS "*"
++
+ /* a fd the child process would log into */
+ extern int ldap_child_debug_fd;
+ 
+diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
+index 3245e1b12a69483f961f01210d13654b1c7c5345..61f09fc41d3210af5044f5338dd90db67e0123a7 100644
+--- a/src/providers/ldap/ldap_id.c
++++ b/src/providers/ldap/ldap_id.c
+@@ -114,6 +114,14 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
+                                                           sdom->dom->name,
+                                                           sdom->dom->domain_id);
+     switch (filter_type) {
++    case BE_FILTER_WILDCARD:
++        attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
++        ret = sss_filter_sanitize_ex(state, name, &clean_name,
++                                     LDAP_ALLOWED_WILDCARDS);
++        if (ret != EOK) {
++            goto done;
++        }
++        break;
+     case BE_FILTER_NAME:
+         if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) {
+             attr_name = ctx->opts->user_map[SDAP_AT_USER_PRINC].name;
+@@ -388,6 +396,13 @@ static void users_get_search(struct tevent_req *req)
+     struct users_get_state *state = tevent_req_data(req,
+                                                      struct users_get_state);
+     struct tevent_req *subreq;
++    bool multiple_results;
++
++    if (state->filter_type == BE_FILTER_WILDCARD) {
++        multiple_results = true;
++    } else {
++        multiple_results = false;
++    }
+ 
+     subreq = sdap_get_users_send(state, state->ev,
+                                  state->domain, state->sysdb,
+@@ -397,7 +412,7 @@ static void users_get_search(struct tevent_req *req)
+                                  state->attrs, state->filter,
+                                  dp_opt_get_int(state->ctx->opts->basic,
+                                                 SDAP_SEARCH_TIMEOUT),
+-                                 false);
++                                 multiple_results);
+     if (!subreq) {
+         tevent_req_error(req, ENOMEM);
+         return;
+@@ -508,6 +523,13 @@ static void users_get_done(struct tevent_req *subreq)
+              * group we have nothing to do here. */
+             break;
+ 
++        case BE_FILTER_WILDCARD:
++            /* We can't know if all users are up-to-date, especially in a large
++             * environment. Do not delete any records, let the responder fetch
++             * the entries they are requested in
++             */
++            break;
++
+         default:
+             tevent_req_error(req, EINVAL);
+             return;
+@@ -619,6 +641,14 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
+                                                           sdom->dom->domain_id);
+ 
+     switch(filter_type) {
++    case BE_FILTER_WILDCARD:
++        attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
++        ret = sss_filter_sanitize_ex(state, name, &clean_name,
++                                     LDAP_ALLOWED_WILDCARDS);
++        if (ret != EOK) {
++            goto done;
++        }
++        break;
+     case BE_FILTER_NAME:
+         attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
+ 
+@@ -871,6 +901,13 @@ static void groups_get_search(struct tevent_req *req)
+     struct groups_get_state *state = tevent_req_data(req,
+                                                      struct groups_get_state);
+     struct tevent_req *subreq;
++    bool multiple_results;
++
++    if (state->filter_type == BE_FILTER_WILDCARD) {
++        multiple_results = true;
++    } else {
++        multiple_results = false;
++    }
+ 
+     subreq = sdap_get_groups_send(state, state->ev,
+                                   state->sdom,
+@@ -879,7 +916,8 @@ static void groups_get_search(struct tevent_req *req)
+                                   state->attrs, state->filter,
+                                   dp_opt_get_int(state->ctx->opts->basic,
+                                                  SDAP_SEARCH_TIMEOUT),
+-                                  false, state->no_members);
++                                  multiple_results,
++                                  state->no_members);
+     if (!subreq) {
+         tevent_req_error(req, ENOMEM);
+         return;
+@@ -953,6 +991,14 @@ static void groups_get_done(struct tevent_req *subreq)
+              * group we have nothing to do here. */
+             break;
+ 
++        case BE_FILTER_WILDCARD:
++            /* We can't know if all groups are up-to-date, especially in
++             * a large environment. Do not delete any records, let the
++             * responder fetch the entries they are requested in.
++             */
++            break;
++
++
+         default:
+             tevent_req_error(req, EINVAL);
+             return;
+-- 
+2.4.3
+
diff --git a/SOURCES/0007-TESTS-Unit-tests-can-use-confdb-without-using-sysdb.patch b/SOURCES/0007-TESTS-Unit-tests-can-use-confdb-without-using-sysdb.patch
deleted file mode 100644
index baf9afa..0000000
--- a/SOURCES/0007-TESTS-Unit-tests-can-use-confdb-without-using-sysdb.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-From 9dd73e9ad92b2905271cd5466ac237c829f1a608 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 3 Oct 2014 16:11:08 +0200
-Subject: [PATCH 07/22] TESTS: Unit tests can use confdb without using sysdb
-
-Previously, if a test used the utility functions for setting up a test,
-it had to use both sysdb and confdb. Some unit tests only need to use of
-of them, for example the unit tests for the server module only need
-confdb.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/tests/common_dom.c | 52 +++++++++++++++++++++++++++-----------------------
- 1 file changed, 28 insertions(+), 24 deletions(-)
-
-diff --git a/src/tests/common_dom.c b/src/tests/common_dom.c
-index b96db8d9084fea9ec07be88d9c5f72c6885d8f09..bc69c5a093e17fc56e42ccedd998ab6434d85003 100644
---- a/src/tests/common_dom.c
-+++ b/src/tests/common_dom.c
-@@ -159,34 +159,38 @@ void test_dom_suite_cleanup(const char *tests_path,
-         return;
-     }
- 
--    conf_db = talloc_asprintf(tmp_ctx, "%s/%s", tests_path, confdb_path);
--    if (!conf_db) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not construct conf_db path\n");
--        goto done;
--    }
-+    if (confdb_path != NULL) {
-+        conf_db = talloc_asprintf(tmp_ctx, "%s/%s", tests_path, confdb_path);
-+        if (!conf_db) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                "Could not construct conf_db path\n");
-+            goto done;
-+        }
- 
--    errno = 0;
--    ret = unlink(conf_db);
--    if (ret != 0 && errno != ENOENT) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not delete the test config ldb file (%d) (%s)\n",
--               errno, strerror(errno));
-+        errno = 0;
-+        ret = unlink(conf_db);
-+        if (ret != 0 && errno != ENOENT) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                "Could not delete the test config ldb file (%d) (%s)\n",
-+                errno, strerror(errno));
-+        }
-     }
- 
--    sys_db = talloc_asprintf(tmp_ctx, "%s/%s", tests_path, sysdb_path);
--    if (!sys_db) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not construct sys_db path\n");
--        goto done;
--    }
-+    if (sysdb_path != NULL) {
-+        sys_db = talloc_asprintf(tmp_ctx, "%s/%s", tests_path, sysdb_path);
-+        if (!sys_db) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                "Could not construct sys_db path\n");
-+            goto done;
-+        }
- 
--    errno = 0;
--    ret = unlink(sys_db);
--    if (ret != 0 && errno != ENOENT) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Could not delete the test ldb file (%d) (%s)\n",
--               errno, strerror(errno));
-+        errno = 0;
-+        ret = unlink(sys_db);
-+        if (ret != 0 && errno != ENOENT) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                "Could not delete the test ldb file (%d) (%s)\n",
-+                errno, strerror(errno));
-+        }
-     }
- 
-     errno = 0;
--- 
-1.9.3
-
diff --git a/SOURCES/0008-LDAP-Add-sdap_get_and_parse_generic_send.patch b/SOURCES/0008-LDAP-Add-sdap_get_and_parse_generic_send.patch
new file mode 100644
index 0000000..b2a8e01
--- /dev/null
+++ b/SOURCES/0008-LDAP-Add-sdap_get_and_parse_generic_send.patch
@@ -0,0 +1,298 @@
+From fceab48ac589473216067e40d8577e19a02d3b45 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 4 May 2015 16:27:06 +0200
+Subject: [PATCH 08/13] LDAP: Add sdap_get_and_parse_generic_send
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+So far we had a simple sdap_get_generic_send() request that uses the
+right defaults around the low-level sdap_get_generic_ext_send() request
+and calls the parser.
+
+This patch adds also sdap_get_and_parse_generic_send() that exposes all
+options that sdap_get_generic_ext_send() offers but also calls the
+parser.
+
+In this patch the function is not used at all.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/providers/ldap/sdap_async.c | 185 ++++++++++++++++++++++++++++------------
+ src/providers/ldap/sdap_async.h |  22 +++++
+ 2 files changed, 154 insertions(+), 53 deletions(-)
+
+diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
+index 5263c250b8a15a98e685ca81e636def27ea05894..c5be8561a197c96f62bb2582a4d30c28de71f580 100644
+--- a/src/providers/ldap/sdap_async.c
++++ b/src/providers/ldap/sdap_async.c
+@@ -1656,9 +1656,8 @@ static void generic_ext_search_handler(struct tevent_req *subreq,
+     tevent_req_done(req);
+ }
+ 
+-
+-/* ==Generic Search============================================ */
+-struct sdap_get_generic_state {
++/* ==Generic Search exposing all options======================= */
++struct sdap_get_and_parse_generic_state {
+     struct sdap_attr_map *map;
+     int map_num_attrs;
+ 
+@@ -1666,10 +1665,119 @@ struct sdap_get_generic_state {
+     struct sdap_options *opts;
+ };
+ 
++static void sdap_get_and_parse_generic_done(struct tevent_req *subreq);
++static errno_t sdap_get_and_parse_generic_parse_entry(struct sdap_handle *sh,
++                                                      struct sdap_msg *msg,
++                                                      void *pvt);
++
++struct tevent_req *sdap_get_and_parse_generic_send(TALLOC_CTX *memctx,
++                                                   struct tevent_context *ev,
++                                                   struct sdap_options *opts,
++                                                   struct sdap_handle *sh,
++                                                   const char *search_base,
++                                                   int scope,
++                                                   const char *filter,
++                                                   const char **attrs,
++                                                   struct sdap_attr_map *map,
++                                                   int map_num_attrs,
++                                                   int attrsonly,
++                                                   LDAPControl **serverctrls,
++                                                   LDAPControl **clientctrls,
++                                                   int sizelimit,
++                                                   int timeout,
++                                                   bool allow_paging)
++{
++    struct tevent_req *req = NULL;
++    struct tevent_req *subreq = NULL;
++    struct sdap_get_and_parse_generic_state *state = NULL;
++
++    req = tevent_req_create(memctx, &state,
++                            struct sdap_get_and_parse_generic_state);
++    if (!req) return NULL;
++
++    state->map = map;
++    state->map_num_attrs = map_num_attrs;
++    state->opts = opts;
++
++    subreq = sdap_get_generic_ext_send(state, ev, opts, sh, search_base,
++                                       scope, filter, attrs, false, NULL,
++                                       NULL, sizelimit, timeout, allow_paging,
++                                       sdap_get_and_parse_generic_parse_entry, state);
++    if (!subreq) {
++        talloc_zfree(req);
++        return NULL;
++    }
++    tevent_req_set_callback(subreq, sdap_get_and_parse_generic_done, req);
++
++    return req;
++}
++
++static errno_t sdap_get_and_parse_generic_parse_entry(struct sdap_handle *sh,
++                                                      struct sdap_msg *msg,
++                                                      void *pvt)
++{
++    errno_t ret;
++    struct sysdb_attrs *attrs;
++    struct sdap_get_and_parse_generic_state *state =
++                talloc_get_type(pvt, struct sdap_get_and_parse_generic_state);
++
++    bool disable_range_rtrvl = dp_opt_get_bool(state->opts->basic,
++                                               SDAP_DISABLE_RANGE_RETRIEVAL);
++
++    ret = sdap_parse_entry(state, sh, msg,
++                           state->map, state->map_num_attrs,
++                           &attrs, disable_range_rtrvl);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "sdap_parse_entry failed [%d]: %s\n", ret, strerror(ret));
++        return ret;
++    }
++
++    ret = add_to_reply(state, &state->sreply, attrs);
++    if (ret != EOK) {
++        talloc_free(attrs);
++        DEBUG(SSSDBG_CRIT_FAILURE, "add_to_reply failed.\n");
++        return ret;
++    }
++
++    /* add_to_reply steals attrs, no need to free them here */
++    return EOK;
++}
++
++static void sdap_get_and_parse_generic_done(struct tevent_req *subreq)
++{
++    struct tevent_req *req = tevent_req_callback_data(subreq,
++                                                      struct tevent_req);
++    struct sdap_get_and_parse_generic_state *state =
++                tevent_req_data(req, struct sdap_get_and_parse_generic_state);
++
++    return generic_ext_search_handler(subreq, state->opts);
++}
++
++int sdap_get_and_parse_generic_recv(struct tevent_req *req,
++                                    TALLOC_CTX *mem_ctx,
++                                    size_t *reply_count,
++                                    struct sysdb_attrs ***reply)
++{
++    struct sdap_get_and_parse_generic_state *state = tevent_req_data(req,
++                                     struct sdap_get_and_parse_generic_state);
++
++    TEVENT_REQ_RETURN_ON_ERROR(req);
++
++    *reply_count = state->sreply.reply_count;
++    *reply = talloc_steal(mem_ctx, state->sreply.reply);
++
++    return EOK;
++}
++
++
++/* ==Simple generic search============================================== */
++struct sdap_get_generic_state {
++    size_t reply_count;
++    struct sysdb_attrs **reply;
++};
++
+ static void sdap_get_generic_done(struct tevent_req *subreq);
+-static errno_t sdap_get_generic_parse_entry(struct sdap_handle *sh,
+-                                            struct sdap_msg *msg,
+-                                            void *pvt);
+ 
+ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
+                                          struct tevent_context *ev,
+@@ -1691,16 +1799,12 @@ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
+     req = tevent_req_create(memctx, &state, struct sdap_get_generic_state);
+     if (!req) return NULL;
+ 
+-    state->map = map;
+-    state->map_num_attrs = map_num_attrs;
+-    state->opts = opts;
+-
+-    subreq = sdap_get_generic_ext_send(state, ev, opts, sh, search_base,
+-                                       scope, filter, attrs, false, NULL,
+-                                       NULL, 0, timeout, allow_paging,
+-                                       sdap_get_generic_parse_entry, state);
+-    if (!subreq) {
+-        talloc_zfree(req);
++    subreq = sdap_get_and_parse_generic_send(memctx, ev, opts, sh, search_base,
++                                             scope, filter, attrs,
++                                             map, map_num_attrs,
++                                             false, NULL, NULL, 0, timeout,
++                                             allow_paging);
++    if (subreq == NULL) {
+         return NULL;
+     }
+     tevent_req_set_callback(subreq, sdap_get_generic_done, req);
+@@ -1708,46 +1812,21 @@ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
+     return req;
+ }
+ 
+-static errno_t sdap_get_generic_parse_entry(struct sdap_handle *sh,
+-                                            struct sdap_msg *msg,
+-                                            void *pvt)
+-{
+-    errno_t ret;
+-    struct sysdb_attrs *attrs;
+-    struct sdap_get_generic_state *state =
+-                talloc_get_type(pvt, struct sdap_get_generic_state);
+-
+-    bool disable_range_rtrvl = dp_opt_get_bool(state->opts->basic,
+-                                               SDAP_DISABLE_RANGE_RETRIEVAL);
+-
+-    ret = sdap_parse_entry(state, sh, msg,
+-                           state->map, state->map_num_attrs,
+-                           &attrs, disable_range_rtrvl);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_MINOR_FAILURE,
+-              "sdap_parse_entry failed [%d]: %s\n", ret, strerror(ret));
+-        return ret;
+-    }
+-
+-    ret = add_to_reply(state, &state->sreply, attrs);
+-    if (ret != EOK) {
+-        talloc_free(attrs);
+-        DEBUG(SSSDBG_CRIT_FAILURE, "add_to_reply failed.\n");
+-        return ret;
+-    }
+-
+-    /* add_to_reply steals attrs, no need to free them here */
+-    return EOK;
+-}
+-
+ static void sdap_get_generic_done(struct tevent_req *subreq)
+ {
+     struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                       struct tevent_req);
+     struct sdap_get_generic_state *state =
+                 tevent_req_data(req, struct sdap_get_generic_state);
++    errno_t ret;
+ 
+-    return generic_ext_search_handler(subreq, state->opts);
++    ret = sdap_get_and_parse_generic_recv(subreq, state,
++                                          &state->reply_count, &state->reply);
++    if (ret != EOK) {
++        tevent_req_error(req, ret);
++        return;
++    }
++    tevent_req_done(req);
+ }
+ 
+ int sdap_get_generic_recv(struct tevent_req *req,
+@@ -1755,13 +1834,13 @@ int sdap_get_generic_recv(struct tevent_req *req,
+                           size_t *reply_count,
+                           struct sysdb_attrs ***reply)
+ {
+-    struct sdap_get_generic_state *state = tevent_req_data(req,
+-                                            struct sdap_get_generic_state);
++    struct sdap_get_generic_state *state =
++                tevent_req_data(req, struct sdap_get_generic_state);
+ 
+     TEVENT_REQ_RETURN_ON_ERROR(req);
+ 
+-    *reply_count = state->sreply.reply_count;
+-    *reply = talloc_steal(mem_ctx, state->sreply.reply);
++    *reply_count = state->reply_count;
++    *reply = talloc_steal(mem_ctx, state->reply);
+ 
+     return EOK;
+ }
+diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
+index b5db64d7fa3c852fba60e07db19e823e818d29f3..b23dfc313905d01caedd1eace6bcb525481b9ebe 100644
+--- a/src/providers/ldap/sdap_async.h
++++ b/src/providers/ldap/sdap_async.h
+@@ -181,6 +181,28 @@ int sdap_cli_connect_recv(struct tevent_req *req,
+                           struct sdap_handle **gsh,
+                           struct sdap_server_opts **srv_opts);
+ 
++/* Exposes all options of generic send while allowing to parse by map */
++struct tevent_req *sdap_get_and_parse_generic_send(TALLOC_CTX *memctx,
++                                                   struct tevent_context *ev,
++                                                   struct sdap_options *opts,
++                                                   struct sdap_handle *sh,
++                                                   const char *search_base,
++                                                   int scope,
++                                                   const char *filter,
++                                                   const char **attrs,
++                                                   struct sdap_attr_map *map,
++                                                   int map_num_attrs,
++                                                   int attrsonly,
++                                                   LDAPControl **serverctrls,
++                                                   LDAPControl **clientctrls,
++                                                   int sizelimit,
++                                                   int timeout,
++                                                   bool allow_paging);
++int sdap_get_and_parse_generic_recv(struct tevent_req *req,
++                                    TALLOC_CTX *mem_ctx,
++                                    size_t *reply_count,
++                                    struct sysdb_attrs ***reply);
++
+ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
+                                          struct tevent_context *ev,
+                                          struct sdap_options *opts,
+-- 
+2.4.3
+
diff --git a/SOURCES/0008-TESTS-Add-std-gnu99-to-cwrap-tests-CFLAGS.patch b/SOURCES/0008-TESTS-Add-std-gnu99-to-cwrap-tests-CFLAGS.patch
deleted file mode 100644
index f3bf0c4..0000000
--- a/SOURCES/0008-TESTS-Add-std-gnu99-to-cwrap-tests-CFLAGS.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From b4c6efddae7159a08ece5b2d94aabf7a629c0455 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Tue, 14 Oct 2014 18:02:47 +0100
-Subject: [PATCH 08/22] TESTS: Add -std=gnu99 to cwrap tests CFLAGS
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-../../../../src/tests/cwrap/../../../src/util/domain_info_utils.c: In function ‘subdomain_enumerates’:
-../../../../src/tests/cwrap/../../../src/util/domain_info_utils.c:77:9: error: ‘for’ loop initial declarations are only allowed in C99 mode
-         for (int i=0; parent->sd_enumerate[i]; i++) {
-         ^
-../../../../src/tests/cwrap/../../../src/util/domain_info_utils.c:77:9: note: use option -std=c99 or -std=gnu99 to compile your code
-make[3]: *** [../../../src/util/server_tests-domain_info_utils.o] Error 1
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/tests/cwrap/Makefile.am | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
-index 34aec92c197a60c47067c72df9c8f3644e1a3c45..96b9a52435d9e80bea3ec132cc86c3e6abd0adf2 100644
---- a/src/tests/cwrap/Makefile.am
-+++ b/src/tests/cwrap/Makefile.am
-@@ -1,4 +1,5 @@
- AM_CPPFLAGS = \
-+    -std=gnu99 \
-     -Wall \
-     -I$(top_srcdir)/src \
-     -I. \
--- 
-1.9.3
-
diff --git a/SOURCES/0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch b/SOURCES/0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch
new file mode 100644
index 0000000..293d522
--- /dev/null
+++ b/SOURCES/0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch
@@ -0,0 +1,87 @@
+From 02813c46feb5484a2e171514c7ba9dd9b1b34006 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 4 May 2015 16:33:37 +0200
+Subject: [PATCH 09/13] LDAP: Use sdap_get_and_parse_generic_/_recv
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Using the new request sdap_get_and_parse_generic_send is a separate
+commit so that we can audit where the function is used during a code
+review.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/providers/ldap/sdap_async_groups.c | 8 ++++----
+ src/providers/ldap/sdap_async_users.c  | 8 ++++----
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
+index 73caa9b5bd662477cd29b5220f6b437991831578..e785307e60d0df5be96a5b2de2c07baabaf1e371 100644
+--- a/src/providers/ldap/sdap_async_groups.c
++++ b/src/providers/ldap/sdap_async_groups.c
+@@ -1870,14 +1870,14 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+           "Searching for groups with base [%s]\n",
+            state->search_bases[state->base_iter]->basedn);
+ 
+-    subreq = sdap_get_generic_send(
++    subreq = sdap_get_and_parse_generic_send(
+             state, state->ev, state->opts,
+             state->ldap_sh != NULL ? state->ldap_sh : state->sh,
+             state->search_bases[state->base_iter]->basedn,
+             state->search_bases[state->base_iter]->scope,
+             state->filter, state->attrs,
+             state->opts->group_map, SDAP_OPTS_GROUP,
+-            state->timeout,
++            0, NULL, NULL, 0, state->timeout,
+             state->enumeration); /* If we're enumerating, we need paging */
+     if (!subreq) {
+         return ENOMEM;
+@@ -1903,8 +1903,8 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
+     struct sysdb_attrs **groups;
+     char **groupnamelist;
+ 
+-    ret = sdap_get_generic_recv(subreq, state,
+-                                &count, &groups);
++    ret = sdap_get_and_parse_generic_recv(subreq, state,
++                                          &count, &groups);
+     talloc_zfree(subreq);
+     if (ret) {
+         tevent_req_error(req, ret);
+diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
+index 416bedda8491fae5385e6b6a074b4cf05ae86b65..216b49477bf21481265444c5c03df0aac7ee84e4 100644
+--- a/src/providers/ldap/sdap_async_users.c
++++ b/src/providers/ldap/sdap_async_users.c
+@@ -688,13 +688,13 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+           "Searching for users with base [%s]\n",
+            state->search_bases[state->base_iter]->basedn);
+ 
+-    subreq = sdap_get_generic_send(
++    subreq = sdap_get_and_parse_generic_send(
+             state, state->ev, state->opts, state->sh,
+             state->search_bases[state->base_iter]->basedn,
+             state->search_bases[state->base_iter]->scope,
+             state->filter, state->attrs,
+             state->opts->user_map, state->opts->user_map_cnt,
+-            state->timeout,
++            0, NULL, NULL, 0, state->timeout,
+             state->enumeration); /* If we're enumerating, we need paging */
+     if (subreq == NULL) {
+         return ENOMEM;
+@@ -715,8 +715,8 @@ static void sdap_search_user_process(struct tevent_req *subreq)
+     struct sysdb_attrs **users;
+     bool next_base = false;
+ 
+-    ret = sdap_get_generic_recv(subreq, state,
+-                                &count, &users);
++    ret = sdap_get_and_parse_generic_recv(subreq, state,
++                                          &count, &users);
+     talloc_zfree(subreq);
+     if (ret) {
+         tevent_req_error(req, ret);
+-- 
+2.4.3
+
diff --git a/SOURCES/0009-TESTS-Unit-tests-for-server_setup.patch b/SOURCES/0009-TESTS-Unit-tests-for-server_setup.patch
deleted file mode 100644
index 384197a..0000000
--- a/SOURCES/0009-TESTS-Unit-tests-for-server_setup.patch
+++ /dev/null
@@ -1,322 +0,0 @@
-From dd8c2ad0efbd6bb4d1f942ce45e3b87d5ecb83b7 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 3 Oct 2014 16:12:01 +0200
-Subject: [PATCH 09/22] TESTS: Unit tests for server_setup
-
-We changed server_setup, so we must make sure the function continues to
-work as expected.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/tests/cwrap/Makefile.am   |  63 ++++++++++++-
- src/tests/cwrap/test_server.c | 204 ++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 266 insertions(+), 1 deletion(-)
- create mode 100644 src/tests/cwrap/test_server.c
-
-diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
-index 96b9a52435d9e80bea3ec132cc86c3e6abd0adf2..28d60e7f5bc346543f51740ec4b2781a99a48909 100644
---- a/src/tests/cwrap/Makefile.am
-+++ b/src/tests/cwrap/Makefile.am
-@@ -3,7 +3,10 @@ AM_CPPFLAGS = \
-     -Wall \
-     -I$(top_srcdir)/src \
-     -I. \
-+    -DLOCALEDIR=\"$(localedir)\" \
-+    -DVARDIR=\"$(localstatedir)\" \
-     $(DBUS_CFLAGS) \
-+    $(GLIB2_CFLAGS) \
-     $(NULL)
- 
- TESTS_ENVIRONMENT = \
-@@ -16,6 +19,20 @@ dist_noinst_SCRIPTS = \
-     cwrap_test_setup.sh \
-     $(NULL)
- 
-+SSSD_LIBS = \
-+    $(TALLOC_LIBS) \
-+    $(TEVENT_LIBS) \
-+    $(POPT_LIBS) \
-+    $(LDB_LIBS) \
-+    $(DBUS_LIBS) \
-+    $(PCRE_LIBS) \
-+    $(INI_CONFIG_LIBS) \
-+    $(COLLECTION_LIBS) \
-+    $(DHASH_LIBS) \
-+    $(SSS_CRYPT_LIBS) \
-+    $(OPENLDAP_LIBS) \
-+    $(TDB_LIBS)
-+
- dist_noinst_DATA = \
-     group \
-     passwd \
-@@ -25,7 +42,10 @@ check_PROGRAMS =
- if HAVE_CMOCKA
- if HAVE_NSS_WRAPPER
- if HAVE_UID_WRAPPER
--check_PROGRAMS += become_user-tests
-+check_PROGRAMS = \
-+	become_user-tests \
-+	server-tests \
-+	$(NULL)
- endif # HAVE_UID_WRAPPER
- endif # HAVE_NSS_WRAPPER
- endif # HAVE_CMOCKA
-@@ -45,4 +65,45 @@ become_user_tests_LDADD = \
-     $(abs_top_builddir)/libsss_test_common.la \
-     $(NULL)
- 
-+server_tests_SOURCES = \
-+    test_server.c \
-+    ../../../src/util/server.c \
-+    ../../../src/util/become_user.c \
-+    ../../../src/util/backup_file.c \
-+    ../../../src/util/domain_info_utils.c \
-+    ../../../src/util/atomic_io.c \
-+    ../../../src/util/signal.c \
-+    ../../../src/util/util.c \
-+    ../../../src/util/strtonum.c \
-+    ../../../src/util/util_errors.c \
-+    ../../../src/util/safe-format-string.c \
-+    ../../../src/util/sss_tc_utf8.c \
-+    ../../../src/util/sss_utf8.c \
-+    ../../../src/util/usertools.c \
-+    ../../../src/confdb/confdb.c \
-+    ../../../src/db/sysdb.c \
-+    ../../../src/db/sysdb_upgrade.c \
-+    ../../../src/db/sysdb_ops.c \
-+    ../../../src/db/sysdb_search.c \
-+    ../../../src/db/sysdb_autofs.c \
-+    ../../../src/db/sysdb_services.c \
-+    ../../../src/db/sysdb_views.c \
-+    $(NULL)
-+server_tests_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(LIBCAPNG_CFLAGS) \
-+    -DTEST_DB_PATH=\"server_tests\" \
-+    -DTEST_PID_PATH=\"server_tests\" \
-+    -DUNIT_TESTING \
-+    $(NULL)
-+server_tests_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(LIBCAPNG_LIBS) \
-+    $(UNICODE_LIBS) \
-+    $(SSSD_LIBS) \
-+    $(abs_top_builddir)/libsss_debug.la \
-+    $(abs_top_builddir)/libsss_crypt.la \
-+    $(abs_top_builddir)/libsss_test_common.la \
-+    $(NULL)
-+
- tests: $(check_PROGRAMS)
-diff --git a/src/tests/cwrap/test_server.c b/src/tests/cwrap/test_server.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..26ecfee1e189b6a474ae52fdbfff6b8922b3f0d7
---- /dev/null
-+++ b/src/tests/cwrap/test_server.c
-@@ -0,0 +1,204 @@
-+/*
-+    Authors:
-+        Jakub Hrozek <jhrozek@redhat.com>
-+
-+    Copyright (C) 2014 Red Hat
-+
-+    SSSD tests: Server instantiation
-+
-+    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 <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+
-+#include <popt.h>
-+#include "util/util.h"
-+#include "tests/cmocka/common_mock.h"
-+
-+static void wait_for_fg_server(pid_t pid)
-+{
-+    pid_t wpid;
-+    int status;
-+
-+    assert_int_not_equal(pid, -1);
-+
-+    wpid = waitpid(pid, &status, 0);
-+    assert_int_equal(wpid, pid);
-+    assert_true(WIFEXITED(status));
-+    assert_int_equal(WEXITSTATUS(status), 0);
-+}
-+
-+static void wait_for_bg_server(const char *pidfile)
-+{
-+    int fd;
-+    long tmp;
-+    char buf[16];
-+    pid_t pid;
-+    int ret;
-+    int count;
-+
-+    count = 0;
-+    do {
-+        struct stat sb;
-+
-+        count++;
-+        if (count > 100) {
-+            break;
-+        }
-+
-+        ret = stat(pidfile, &sb);
-+        usleep(50);
-+    } while (ret != 0);
-+
-+    /* read the pidfile */
-+    fd = open(pidfile, O_RDONLY);
-+    assert_false(fd < 0);
-+
-+    ret = read(fd, buf, sizeof(buf));
-+    close(fd);
-+    assert_false(ret <= 0);
-+
-+    buf[sizeof(buf) - 1] = '\0';
-+
-+    tmp = strtol(buf, NULL, 10);
-+    assert_false(tmp == 0 || tmp > 0xFFFF || errno == ERANGE);
-+
-+    pid = (pid_t) (tmp & 0xFFFF);
-+
-+    /* Make sure the daemon goes away! */
-+    ret = kill(pid, SIGTERM);
-+    fprintf(stderr, "killing %u\n", pid);
-+    assert_true(ret == 0);
-+
-+    unlink(pidfile);
-+}
-+
-+void test_run_as_root_fg(void **state)
-+{
-+    int ret;
-+    struct main_context *main_ctx;
-+    pid_t pid;
-+
-+    /* Must root as root, real or fake */
-+    assert_int_equal(geteuid(), 0);
-+
-+    pid = fork();
-+    if (pid == 0) {
-+        ret = server_setup(__FUNCTION__, 0, 0, 0,
-+                           __FUNCTION__, &main_ctx);
-+        assert_int_equal(ret, 0);
-+        exit(0);
-+    }
-+    wait_for_fg_server(pid);
-+}
-+
-+void test_run_as_sssd_fg(void **state)
-+{
-+    int ret;
-+    struct main_context *main_ctx;
-+    struct passwd *sssd;
-+    pid_t pid;
-+
-+    /* Must root as root, real or fake */
-+    assert_int_equal(geteuid(), 0);
-+
-+    sssd = getpwnam("sssd");
-+    assert_non_null(sssd);
-+
-+    pid = fork();
-+    if (pid == 0) {
-+        ret = server_setup(__FUNCTION__, 0, sssd->pw_uid, sssd->pw_gid,
-+                           __FUNCTION__, &main_ctx);
-+        assert_int_equal(ret, 0);
-+        exit(0);
-+    }
-+    wait_for_fg_server(pid);
-+}
-+
-+void test_run_as_root_daemon(void **state)
-+{
-+    int ret;
-+    struct main_context *main_ctx;
-+    pid_t pid;
-+    char *pidfile;
-+
-+    /* Must root as root, real or fake */
-+    assert_int_equal(geteuid(), 0);
-+
-+    pidfile = talloc_asprintf(NULL, "%s/%s.pid", TEST_PID_PATH, __FUNCTION__);
-+
-+    /* Make sure there are no leftovers */
-+    unlink(pidfile);
-+
-+    pid = fork();
-+    if (pid == 0) {
-+        ret = server_setup(__FUNCTION__, FLAGS_PID_FILE,
-+                           0, 0, __FUNCTION__, &main_ctx);
-+        assert_int_equal(ret, 0);
-+
-+        server_loop(main_ctx);
-+        exit(0);
-+    }
-+
-+    wait_for_bg_server(pidfile);
-+    talloc_free(pidfile);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    poptContext pc;
-+    int opt;
-+    int rv;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test(test_run_as_root_fg),
-+        unit_test(test_run_as_sssd_fg),
-+        unit_test(test_run_as_root_daemon),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    /* Even though normally the tests should clean up after themselves
-+     * they might not after a failed run. Remove the old db to be sure */
-+    tests_set_cwd();
-+    test_dom_suite_cleanup(TEST_DB_PATH, CONFDB_FILE, NULL);
-+    test_dom_suite_setup(TEST_DB_PATH);
-+
-+    rv = run_tests(tests);
-+    test_dom_suite_cleanup(TEST_DB_PATH, CONFDB_FILE, NULL);
-+
-+    return rv;
-+}
--- 
-1.9.3
-
diff --git a/SOURCES/0010-LDAP-Add-sdap_lookup_type-enum.patch b/SOURCES/0010-LDAP-Add-sdap_lookup_type-enum.patch
new file mode 100644
index 0000000..9481f75
--- /dev/null
+++ b/SOURCES/0010-LDAP-Add-sdap_lookup_type-enum.patch
@@ -0,0 +1,395 @@
+From 179ac94a4910150b846ff1c959e766c5a31274cf Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Fri, 8 May 2015 14:49:09 +0200
+Subject: [PATCH 10/13] LDAP: Add sdap_lookup_type enum
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Change the boolan parameter of sdap_get_users_send and sdap_get_groups_send
+to a tri-state that controls whether we expect only a single entry
+(ie don't use the paging control), multiple entries with a search limit
+(wildcard request) or multiple entries with no limit (enumeration).
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/providers/ldap/ldap_auth.c         |  2 +-
+ src/providers/ldap/ldap_id.c           | 16 +++++++-------
+ src/providers/ldap/sdap_async.h        | 12 +++++++---
+ src/providers/ldap/sdap_async_enum.c   |  4 ++--
+ src/providers/ldap/sdap_async_groups.c | 40 ++++++++++++++++++++++++----------
+ src/providers/ldap/sdap_async_users.c  | 32 ++++++++++++++++++++-------
+ 6 files changed, 73 insertions(+), 33 deletions(-)
+
+diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
+index 81717942613b4a91ebab668ba2ecfe13caab38be..217e80fd07abc41f2594d19397783683d44600cd 100644
+--- a/src/providers/ldap/ldap_auth.c
++++ b/src/providers/ldap/ldap_auth.c
+@@ -418,7 +418,7 @@ static struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx,
+                                    sh, attrs, filter,
+                                    dp_opt_get_int(opts->basic,
+                                                   SDAP_SEARCH_TIMEOUT),
+-                                   false);
++                                   SDAP_LOOKUP_SINGLE);
+     if (!subreq) {
+         ret = ENOMEM;
+         goto done;
+diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
+index 61f09fc41d3210af5044f5338dd90db67e0123a7..73840d2885ed15a7a9dae2e9175d8361c8fdfe7d 100644
+--- a/src/providers/ldap/ldap_id.c
++++ b/src/providers/ldap/ldap_id.c
+@@ -396,12 +396,12 @@ static void users_get_search(struct tevent_req *req)
+     struct users_get_state *state = tevent_req_data(req,
+                                                      struct users_get_state);
+     struct tevent_req *subreq;
+-    bool multiple_results;
++    enum sdap_entry_lookup_type lookup_type;
+ 
+     if (state->filter_type == BE_FILTER_WILDCARD) {
+-        multiple_results = true;
++        lookup_type = SDAP_LOOKUP_WILDCARD;
+     } else {
+-        multiple_results = false;
++        lookup_type = SDAP_LOOKUP_SINGLE;
+     }
+ 
+     subreq = sdap_get_users_send(state, state->ev,
+@@ -412,7 +412,7 @@ static void users_get_search(struct tevent_req *req)
+                                  state->attrs, state->filter,
+                                  dp_opt_get_int(state->ctx->opts->basic,
+                                                 SDAP_SEARCH_TIMEOUT),
+-                                 multiple_results);
++                                 lookup_type);
+     if (!subreq) {
+         tevent_req_error(req, ENOMEM);
+         return;
+@@ -901,12 +901,12 @@ static void groups_get_search(struct tevent_req *req)
+     struct groups_get_state *state = tevent_req_data(req,
+                                                      struct groups_get_state);
+     struct tevent_req *subreq;
+-    bool multiple_results;
++    enum sdap_entry_lookup_type lookup_type;
+ 
+     if (state->filter_type == BE_FILTER_WILDCARD) {
+-        multiple_results = true;
++        lookup_type = SDAP_LOOKUP_WILDCARD;
+     } else {
+-        multiple_results = false;
++        lookup_type = SDAP_LOOKUP_SINGLE;
+     }
+ 
+     subreq = sdap_get_groups_send(state, state->ev,
+@@ -916,7 +916,7 @@ static void groups_get_search(struct tevent_req *req)
+                                   state->attrs, state->filter,
+                                   dp_opt_get_int(state->ctx->opts->basic,
+                                                  SDAP_SEARCH_TIMEOUT),
+-                                  multiple_results,
++                                  lookup_type,
+                                   state->no_members);
+     if (!subreq) {
+         tevent_req_error(req, ENOMEM);
+diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
+index b23dfc313905d01caedd1eace6bcb525481b9ebe..09bc0d65407253f93514b30877850cc38009c625 100644
+--- a/src/providers/ldap/sdap_async.h
++++ b/src/providers/ldap/sdap_async.h
+@@ -59,6 +59,12 @@ errno_t sdap_connect_host_recv(TALLOC_CTX *mem_ctx,
+                                struct sdap_handle **_sh);
+ 
+ /* Search users in LDAP, return them as attrs */
++enum sdap_entry_lookup_type {
++    SDAP_LOOKUP_SINGLE,         /* Direct single-user/group lookup */
++    SDAP_LOOKUP_WILDCARD,       /* Multiple entries with a limit */
++    SDAP_LOOKUP_ENUMERATE,      /* Fetch all entries from the server */
++};
++
+ struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx,
+                                          struct tevent_context *ev,
+                                          struct sss_domain_info *dom,
+@@ -68,7 +74,7 @@ struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx,
+                                          const char **attrs,
+                                          const char *filter,
+                                          int timeout,
+-                                         bool enumeration);
++                                         enum sdap_entry_lookup_type lookup_type);
+ int sdap_search_user_recv(TALLOC_CTX *memctx, struct tevent_req *req,
+                           char **higher_usn, struct sysdb_attrs ***users,
+                           size_t *count);
+@@ -84,7 +90,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
+                                        const char **attrs,
+                                        const char *filter,
+                                        int timeout,
+-                                       bool enumeration);
++                                       enum sdap_entry_lookup_type lookup_type);
+ int sdap_get_users_recv(struct tevent_req *req,
+                         TALLOC_CTX *mem_ctx, char **timestamp);
+ 
+@@ -96,7 +102,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx,
+                                        const char **attrs,
+                                        const char *filter,
+                                        int timeout,
+-                                       bool enumeration,
++                                       enum sdap_entry_lookup_type lookup_type,
+                                        bool no_members);
+ int sdap_get_groups_recv(struct tevent_req *req,
+                          TALLOC_CTX *mem_ctx, char **timestamp);
+diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c
+index 35afc55f809669a44aa2beda7d87dfe62d6ec10b..f22276c3ce6f839b765bbc1602fafb010cc37d89 100644
+--- a/src/providers/ldap/sdap_async_enum.c
++++ b/src/providers/ldap/sdap_async_enum.c
+@@ -635,7 +635,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
+                                  state->attrs, state->filter,
+                                  dp_opt_get_int(state->ctx->opts->basic,
+                                                 SDAP_ENUM_SEARCH_TIMEOUT),
+-                                 true);
++                                 SDAP_LOOKUP_ENUMERATE);
+     if (!subreq) {
+         ret = ENOMEM;
+         goto fail;
+@@ -811,7 +811,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
+                                   state->attrs, state->filter,
+                                   dp_opt_get_int(state->ctx->opts->basic,
+                                                  SDAP_ENUM_SEARCH_TIMEOUT),
+-                                  true, false);
++                                  SDAP_LOOKUP_ENUMERATE, false);
+     if (!subreq) {
+         ret = ENOMEM;
+         goto fail;
+diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
+index e785307e60d0df5be96a5b2de2c07baabaf1e371..ad0354df1fce9011c68cabb6049e7feee92a44c0 100644
+--- a/src/providers/ldap/sdap_async_groups.c
++++ b/src/providers/ldap/sdap_async_groups.c
+@@ -1721,7 +1721,7 @@ struct sdap_get_groups_state {
+     const char *base_filter;
+     char *filter;
+     int timeout;
+-    bool enumeration;
++    enum sdap_entry_lookup_type lookup_type;
+     bool no_members;
+ 
+     char *higher_usn;
+@@ -1752,7 +1752,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx,
+                                        const char **attrs,
+                                        const char *filter,
+                                        int timeout,
+-                                       bool enumeration,
++                                       enum sdap_entry_lookup_type lookup_type,
+                                        bool no_members)
+ {
+     errno_t ret;
+@@ -1775,7 +1775,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx,
+     state->groups =  NULL;
+     state->count = 0;
+     state->timeout = timeout;
+-    state->enumeration = enumeration;
++    state->lookup_type = lookup_type;
+     state->no_members = no_members;
+     state->base_filter = filter;
+     state->base_iter = 0;
+@@ -1855,6 +1855,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+ {
+     struct tevent_req *subreq;
+     struct sdap_get_groups_state *state;
++    bool need_paging = false;
+ 
+     state = tevent_req_data(req, struct sdap_get_groups_state);
+ 
+@@ -1870,6 +1871,19 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+           "Searching for groups with base [%s]\n",
+            state->search_bases[state->base_iter]->basedn);
+ 
++    switch (state->lookup_type) {
++    case SDAP_LOOKUP_SINGLE:
++        need_paging = false;
++        break;
++    /* Only requests that can return multiple entries should require
++     * the paging control
++     */
++    case SDAP_LOOKUP_WILDCARD:
++    case SDAP_LOOKUP_ENUMERATE:
++        need_paging = true;
++        break;
++    }
++
+     subreq = sdap_get_and_parse_generic_send(
+             state, state->ev, state->opts,
+             state->ldap_sh != NULL ? state->ldap_sh : state->sh,
+@@ -1878,7 +1892,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+             state->filter, state->attrs,
+             state->opts->group_map, SDAP_OPTS_GROUP,
+             0, NULL, NULL, 0, state->timeout,
+-            state->enumeration); /* If we're enumerating, we need paging */
++            need_paging);
+     if (!subreq) {
+         return ENOMEM;
+     }
+@@ -1914,14 +1928,17 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
+     DEBUG(SSSDBG_TRACE_FUNC,
+           "Search for groups, returned %zu results.\n", count);
+ 
+-    if (!state->enumeration && count > 1) {
++    if (state->lookup_type == SDAP_LOOKUP_SINGLE && count > 1) {
+         DEBUG(SSSDBG_MINOR_FAILURE,
+               "Individual group search returned multiple results\n");
+         tevent_req_error(req, EINVAL);
+         return;
+     }
+ 
+-    if (state->enumeration || count == 0) {
++    if (state->lookup_type == SDAP_LOOKUP_WILDCARD || \
++            state->lookup_type == SDAP_LOOKUP_ENUMERATE || \
++        count == 0) {
++        /* No users found in this search or looking up multiple entries */
+         next_base = true;
+     }
+ 
+@@ -2003,7 +2020,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
+      * LDAP_MATCHING_RULE_IN_CHAIN available in
+      * AD 2008 and later
+      */
+-    if (!state->enumeration) {
++    if (state->lookup_type == SDAP_LOOKUP_SINGLE) {
+         if ((state->opts->schema_type != SDAP_SCHEMA_RFC2307)
+                 && (dp_opt_get_int(state->opts->basic, SDAP_NESTING_LEVEL) != 0)
+                 && !dp_opt_get_bool(state->opts->basic, SDAP_AD_MATCHING_RULE_GROUPS)) {
+@@ -2026,7 +2043,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
+     /* If we're using LDAP_MATCHING_RULE_IN_CHAIN, start a subreq to
+      * retrieve the members so we can save them in a single step.
+      */
+-    if (!state->enumeration
++    if (state->lookup_type == SDAP_LOOKUP_SINGLE
+             && (state->opts->schema_type != SDAP_SCHEMA_RFC2307)
+             && state->opts->support_matching_rule
+             && dp_opt_get_bool(state->opts->basic, SDAP_AD_MATCHING_RULE_GROUPS)) {
+@@ -2050,7 +2067,8 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
+         return;
+     }
+ 
+-    if (state->enumeration
++    if ((state->lookup_type == SDAP_LOOKUP_ENUMERATE
++                || state->lookup_type == SDAP_LOOKUP_WILDCARD)
+             && state->opts->schema_type != SDAP_SCHEMA_RFC2307
+             && dp_opt_get_int(state->opts->basic, SDAP_NESTING_LEVEL) != 0) {
+         DEBUG(SSSDBG_TRACE_ALL, "Saving groups without members first "
+@@ -2069,7 +2087,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
+         subreq = sdap_process_group_send(state, state->ev, state->dom,
+                                          state->sysdb, state->opts,
+                                          state->sh, state->groups[i],
+-                                         state->enumeration);
++                                         state->lookup_type == SDAP_LOOKUP_ENUMERATE);
+ 
+         if (!subreq) {
+             tevent_req_error(req, ENOMEM);
+@@ -2116,7 +2134,7 @@ static void sdap_get_groups_done(struct tevent_req *subreq)
+         ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts,
+                                state->groups, state->count,
+                                !state->dom->ignore_group_members, NULL,
+-                               !state->enumeration,
++                               state->lookup_type == SDAP_LOOKUP_SINGLE,
+                                &state->higher_usn);
+         if (ret) {
+             DEBUG(SSSDBG_OP_FAILURE, "Failed to store groups.\n");
+diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
+index 216b49477bf21481265444c5c03df0aac7ee84e4..f66ae2604c867d4a5e8d223081ece9f1e474cf73 100644
+--- a/src/providers/ldap/sdap_async_users.c
++++ b/src/providers/ldap/sdap_async_users.c
+@@ -606,7 +606,7 @@ struct sdap_search_user_state {
+     const char *base_filter;
+     const char *filter;
+     int timeout;
+-    bool enumeration;
++    enum sdap_entry_lookup_type lookup_type;
+ 
+     char *higher_usn;
+     struct sysdb_attrs **users;
+@@ -628,7 +628,7 @@ struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx,
+                                          const char **attrs,
+                                          const char *filter,
+                                          int timeout,
+-                                         bool enumeration)
++                                         enum sdap_entry_lookup_type lookup_type)
+ {
+     errno_t ret;
+     struct tevent_req *req;
+@@ -649,7 +649,7 @@ struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx,
+     state->base_filter = filter;
+     state->base_iter = 0;
+     state->search_bases = search_bases;
+-    state->enumeration = enumeration;
++    state->lookup_type = lookup_type;
+ 
+     if (!state->search_bases) {
+         DEBUG(SSSDBG_CRIT_FAILURE,
+@@ -673,6 +673,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+ {
+     struct tevent_req *subreq;
+     struct sdap_search_user_state *state;
++    bool need_paging = false;
+ 
+     state = tevent_req_data(req, struct sdap_search_user_state);
+ 
+@@ -688,6 +689,19 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+           "Searching for users with base [%s]\n",
+            state->search_bases[state->base_iter]->basedn);
+ 
++    switch (state->lookup_type) {
++    case SDAP_LOOKUP_SINGLE:
++        need_paging = false;
++        break;
++    /* Only requests that can return multiple entries should require
++     * the paging control
++     */
++    case SDAP_LOOKUP_WILDCARD:
++    case SDAP_LOOKUP_ENUMERATE:
++        need_paging = true;
++        break;
++    }
++
+     subreq = sdap_get_and_parse_generic_send(
+             state, state->ev, state->opts, state->sh,
+             state->search_bases[state->base_iter]->basedn,
+@@ -695,7 +709,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+             state->filter, state->attrs,
+             state->opts->user_map, state->opts->user_map_cnt,
+             0, NULL, NULL, 0, state->timeout,
+-            state->enumeration); /* If we're enumerating, we need paging */
++            need_paging);
+     if (subreq == NULL) {
+         return ENOMEM;
+     }
+@@ -726,8 +740,10 @@ static void sdap_search_user_process(struct tevent_req *subreq)
+     DEBUG(SSSDBG_TRACE_FUNC,
+           "Search for users, returned %zu results.\n", count);
+ 
+-    if (state->enumeration || count == 0) {
+-        /* No users found in this search or enumerating */
++    if (state->lookup_type == SDAP_LOOKUP_WILDCARD || \
++            state->lookup_type == SDAP_LOOKUP_ENUMERATE || \
++        count == 0) {
++        /* No users found in this search or looking up multiple entries */
+         next_base = true;
+     }
+ 
+@@ -827,7 +843,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
+                                        const char **attrs,
+                                        const char *filter,
+                                        int timeout,
+-                                       bool enumeration)
++                                       enum sdap_entry_lookup_type lookup_type)
+ {
+     errno_t ret;
+     struct tevent_req *req;
+@@ -842,7 +858,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx,
+     state->dom = dom;
+ 
+     subreq = sdap_search_user_send(state, ev, dom, opts, search_bases,
+-                                   sh, attrs, filter, timeout, enumeration);
++                                   sh, attrs, filter, timeout, lookup_type);
+     if (subreq == NULL) {
+         ret = ENOMEM;
+         goto done;
+-- 
+2.4.3
+
diff --git a/SOURCES/0010-RPM-Package-the-libsss_semanage.so-library.patch b/SOURCES/0010-RPM-Package-the-libsss_semanage.so-library.patch
deleted file mode 100644
index 1e8e2b6..0000000
--- a/SOURCES/0010-RPM-Package-the-libsss_semanage.so-library.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From e1daa56df4c15874ae60c4bf4f2422d39d3a1654 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 20 Oct 2014 22:22:09 +0200
-Subject: [PATCH 10/22] RPM: Package the libsss_semanage.so library
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- contrib/sssd.spec.in | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
-index 529304205274ad39e4281e3d298222420d5eb439..74f7e950518841ec3cbd6e3fb4edf2eb873c7704 100644
---- a/contrib/sssd.spec.in
-+++ b/contrib/sssd.spec.in
-@@ -589,6 +589,7 @@ rm -rf $RPM_BUILD_ROOT
- %{_libdir}/%{name}/libsss_debug.so
- %{_libdir}/%{name}/libsss_ldap_common.so
- %{_libdir}/%{name}/libsss_util.so
-+%{_libdir}/%{name}/libsss_semanage.so
- 
- # 3rd party application libraries
- %{_libdir}/sssd/modules/libsss_autofs.so
--- 
-1.9.3
-
diff --git a/SOURCES/0011-LDAP-Add-the-wildcard_limit-option.patch b/SOURCES/0011-LDAP-Add-the-wildcard_limit-option.patch
new file mode 100644
index 0000000..c9145af
--- /dev/null
+++ b/SOURCES/0011-LDAP-Add-the-wildcard_limit-option.patch
@@ -0,0 +1,237 @@
+From 4e795d8ff3a1d1f5cd5a7dddaf364909c60d9191 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 17 Jun 2015 16:13:51 +0200
+Subject: [PATCH 11/13] LDAP: Add the wildcard_limit option
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Related:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Adds a new wildcard_limit option that is set by default to 1000 (one
+page). This option limits the number of entries that can by default be
+returned by a wildcard search.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/config/SSSDConfig/__init__.py.in     |  1 +
+ src/config/etc/sssd.api.d/sssd-ad.conf   |  1 +
+ src/config/etc/sssd.api.d/sssd-ipa.conf  |  1 +
+ src/config/etc/sssd.api.d/sssd-ldap.conf |  1 +
+ src/man/sssd-ldap.5.xml                  | 17 +++++++++++++++++
+ src/providers/ad/ad_opts.h               |  1 +
+ src/providers/ipa/ipa_opts.h             |  1 +
+ src/providers/ldap/ldap_opts.h           |  1 +
+ src/providers/ldap/sdap.h                |  1 +
+ src/providers/ldap/sdap_async_groups.c   |  8 +++++++-
+ src/providers/ldap/sdap_async_users.c    |  8 +++++++-
+ 11 files changed, 39 insertions(+), 2 deletions(-)
+
+diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
+index 4d45e42af4fa32717caa69cc621834cdffc27431..4b519eddd04cde83c209f5a1940832cc7f41c736 100644
+--- a/src/config/SSSDConfig/__init__.py.in
++++ b/src/config/SSSDConfig/__init__.py.in
+@@ -355,6 +355,7 @@ option_strings = {
+     'ldap_min_id' : _('Set lower boundary for allowed IDs from the LDAP server'),
+     'ldap_max_id' : _('Set upper boundary for allowed IDs from the LDAP server'),
+     'ldap_pwdlockout_dn' : _('DN for ppolicy queries'),
++    'wildcard_limit' : _('How many maximum entries to fetch during a wildcard request'),
+ 
+     # [provider/ldap/auth]
+     'ldap_pwd_policy' : _('Policy to evaluate the password expiration'),
+diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
+index faab3a51e54d6d498392021a8945501120870f70..b636d93108ef0a3831970d7827895c14b0f3571c 100644
+--- a/src/config/etc/sssd.api.d/sssd-ad.conf
++++ b/src/config/etc/sssd.api.d/sssd-ad.conf
+@@ -56,6 +56,7 @@ ldap_deref_threshold = int, None, false
+ ldap_connection_expire_timeout = int, None, false
+ ldap_disable_paging = bool, None, false
+ krb5_confd_path = str, None, false
++wildcard_limit = int, None, false
+ 
+ [provider/ad/id]
+ ldap_search_timeout = int, None, false
+diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
+index cfcc00f6f7ca768df861e8cf7face065f90e9e83..ab712fe55cdac6d247a085aeca5cc82d65966623 100644
+--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
++++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
+@@ -52,6 +52,7 @@ ldap_deref_threshold = int, None, false
+ ldap_connection_expire_timeout = int, None, false
+ ldap_disable_paging = bool, None, false
+ krb5_confd_path = str, None, false
++wildcard_limit = int, None, false
+ 
+ [provider/ipa/id]
+ ldap_search_timeout = int, None, false
+diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
+index c10290217b1b133792b893d9b80e2599969838a6..8fd45fd4093714f458161eb352157c845d926f06 100644
+--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
++++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
+@@ -37,6 +37,7 @@ ldap_sasl_minssf = int, None, false
+ ldap_connection_expire_timeout = int, None, false
+ ldap_disable_paging = bool, None, false
+ ldap_disable_range_retrieval = bool, None, false
++wildcard_limit = int, None, false
+ 
+ [provider/ldap/id]
+ ldap_search_timeout = int, None, false
+diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
+index f14090843fd32141ad4f491b69868aa7b2412301..9ac175f8d4a8aa01ca2434b800ebae1be88575f5 100644
+--- a/src/man/sssd-ldap.5.xml
++++ b/src/man/sssd-ldap.5.xml
+@@ -2135,6 +2135,23 @@ ldap_access_filter = (employeeType=admin)
+                     </listitem>
+                 </varlistentry>
+ 
++                <varlistentry>
++                    <term>wildcart_limit (integer)</term>
++                    <listitem>
++                        <para>
++                            Specifies an upper limit on the number of entries
++                            that are downloaded during a wildcard lookup.
++                        </para>
++                        <para>
++                            At the moment, only the InfoPipe responder supports
++                            wildcard lookups.
++                        </para>
++                        <para>
++                            Default: 1000 (often the size of one page)
++                        </para>
++                    </listitem>
++                </varlistentry>
++
+             </variablelist>
+         </para>
+     </refsect1>
+diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
+index cb4c05d846d9abe5eedb28013ad13fff6476d431..d685edcb44c771b0afc7a232a82c21fc9d1c89f9 100644
+--- a/src/providers/ad/ad_opts.h
++++ b/src/providers/ad/ad_opts.h
+@@ -146,6 +146,7 @@ struct dp_option ad_def_ldap_opts[] = {
+     { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+     { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+     { "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
++    { "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER},
+     DP_OPTION_TERMINATOR
+ };
+ 
+diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
+index 253c0715355536cc181c57beed5326a77e87e464..9576228d1bf3424c8867bda058b59c3ca6b2216b 100644
+--- a/src/providers/ipa/ipa_opts.h
++++ b/src/providers/ipa/ipa_opts.h
+@@ -157,6 +157,7 @@ struct dp_option ipa_def_ldap_opts[] = {
+     { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+     { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+     { "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
++    { "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER},
+     DP_OPTION_TERMINATOR
+ };
+ 
+diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
+index c1b9bf688ef0a92046195c13a11d2c17b2419d67..9f58db5bd9eef1391e97c1890cbff94c2a5406d6 100644
+--- a/src/providers/ldap/ldap_opts.h
++++ b/src/providers/ldap/ldap_opts.h
+@@ -122,6 +122,7 @@ struct dp_option default_basic_opts[] = {
+     { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+     { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
+     { "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
++    { "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER},
+     DP_OPTION_TERMINATOR
+ };
+ 
+diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
+index d9b2d18637bdb3e7823af9d1de2c042c8134780f..444502bf7159edcf4cebe530cce8b216c737ec30 100644
+--- a/src/providers/ldap/sdap.h
++++ b/src/providers/ldap/sdap.h
+@@ -231,6 +231,7 @@ enum sdap_basic_opt {
+     SDAP_MIN_ID,
+     SDAP_MAX_ID,
+     SDAP_PWDLOCKOUT_DN,
++    SDAP_WILDCARD_LIMIT,
+ 
+     SDAP_OPTS_BASIC /* opts counter */
+ };
+diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
+index ad0354df1fce9011c68cabb6049e7feee92a44c0..525c6fa09553d8c0232ce2317751184f83632d86 100644
+--- a/src/providers/ldap/sdap_async_groups.c
++++ b/src/providers/ldap/sdap_async_groups.c
+@@ -1856,6 +1856,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+     struct tevent_req *subreq;
+     struct sdap_get_groups_state *state;
+     bool need_paging = false;
++    int sizelimit = 0;
+ 
+     state = tevent_req_data(req, struct sdap_get_groups_state);
+ 
+@@ -1873,13 +1874,18 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+ 
+     switch (state->lookup_type) {
+     case SDAP_LOOKUP_SINGLE:
++        sizelimit = 1;
+         need_paging = false;
+         break;
+     /* Only requests that can return multiple entries should require
+      * the paging control
+      */
+     case SDAP_LOOKUP_WILDCARD:
++        sizelimit = dp_opt_get_int(state->opts->basic, SDAP_WILDCARD_LIMIT);
++        need_paging = true;
++        break;
+     case SDAP_LOOKUP_ENUMERATE:
++        sizelimit = 0;  /* unlimited */
+         need_paging = true;
+         break;
+     }
+@@ -1891,7 +1897,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+             state->search_bases[state->base_iter]->scope,
+             state->filter, state->attrs,
+             state->opts->group_map, SDAP_OPTS_GROUP,
+-            0, NULL, NULL, 0, state->timeout,
++            0, NULL, NULL, sizelimit, state->timeout,
+             need_paging);
+     if (!subreq) {
+         return ENOMEM;
+diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
+index f66ae2604c867d4a5e8d223081ece9f1e474cf73..a864a8b2187de7972aa963b355856e97f7c692a9 100644
+--- a/src/providers/ldap/sdap_async_users.c
++++ b/src/providers/ldap/sdap_async_users.c
+@@ -674,6 +674,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+     struct tevent_req *subreq;
+     struct sdap_search_user_state *state;
+     bool need_paging = false;
++    int sizelimit = 0;
+ 
+     state = tevent_req_data(req, struct sdap_search_user_state);
+ 
+@@ -691,13 +692,18 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+ 
+     switch (state->lookup_type) {
+     case SDAP_LOOKUP_SINGLE:
++        sizelimit = 1;
+         need_paging = false;
+         break;
+     /* Only requests that can return multiple entries should require
+      * the paging control
+      */
+     case SDAP_LOOKUP_WILDCARD:
++        sizelimit = dp_opt_get_int(state->opts->basic, SDAP_WILDCARD_LIMIT);
++        need_paging = true;
++        break;
+     case SDAP_LOOKUP_ENUMERATE:
++        sizelimit = 0;  /* unlimited */
+         need_paging = true;
+         break;
+     }
+@@ -708,7 +714,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+             state->search_bases[state->base_iter]->scope,
+             state->filter, state->attrs,
+             state->opts->user_map, state->opts->user_map_cnt,
+-            0, NULL, NULL, 0, state->timeout,
++            0, NULL, NULL, sizelimit, state->timeout,
+             need_paging);
+     if (subreq == NULL) {
+         return ENOMEM;
+-- 
+2.4.3
+
diff --git a/SOURCES/0011-ipa-fix-issues-with-older-servers-not-supporting-vie.patch b/SOURCES/0011-ipa-fix-issues-with-older-servers-not-supporting-vie.patch
deleted file mode 100644
index 4e95f7f..0000000
--- a/SOURCES/0011-ipa-fix-issues-with-older-servers-not-supporting-vie.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From d384cf52b5753c2409625eca906474b95edcbe9d Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 22 Oct 2014 10:03:09 +0200
-Subject: [PATCH 11/22] ipa: fix issues with older servers not supporting views
-
-Older FreeIPA servers which do not know about the ipaAssignedIDView
-attribute will return an error during the LDAP dereference request
-because SSSD marks LDAP extensions as critical. In this case we keep the
-view name empty and skip override lookups.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_subdomains.c    | 14 +++++++++++++-
- src/providers/ipa/ipa_subdomains_id.c |  4 +++-
- src/providers/ipa/ipa_views.c         | 17 ++++++++++++-----
- 3 files changed, 28 insertions(+), 7 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index bedc0f1a50e8a35ea65de45247b1814c9abc0bcd..eb172fdfc05ac4e482174f01d89ad28db1498fc1 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -1002,7 +1002,19 @@ static void ipa_get_view_name_done(struct tevent_req *req)
-     ret = sdap_deref_search_with_filter_recv(req, ctx, &reply_count, &reply);
-     talloc_zfree(req);
-     if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "get_view_name request failed.\n");
-+        if (ret == EOPNOTSUPP) {
-+            DEBUG(SSSDBG_TRACE_FUNC, "get_view_name request failed, looks " \
-+                                     "like server does not support views.\n");
-+            ret = ipa_check_master(ctx);
-+            if (ret == EAGAIN) {
-+                return;
-+            } else if (ret != EOK) {
-+                goto done;
-+            }
-+
-+        } else {
-+            DEBUG(SSSDBG_OP_FAILURE, "get_view_name request failed.\n");
-+        }
-         goto done;
-     }
- 
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index 36f8b239249e5f0146610cfab148be20c39c66c2..b67006ce6e0b4bf9c794016c1dfc923ac6da3624 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -106,11 +106,13 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx,
-      * have to check first if the request matches an override in the given
-      * view. But there are cases where this can be skipped and the AD object
-      * can be searched directly:
-+     * - if no view is defined, i.e. the server does not supprt views yet
-      * - searches by SID: because we do not override the SID
-      * - if the responder does not send the EXTRA_INPUT_MAYBE_WITH_VIEW flags,
-      *   because in this case the entry was found in the cache and the
-      *   original value is used for the search (e.g. during cache updates) */
--    if (state->ar->filter_type == BE_FILTER_SECID
-+    if (state->ipa_ctx->view_name == NULL
-+            || state->ar->filter_type == BE_FILTER_SECID
-             || (!state->ipa_server_mode
-                 && state->ar->extra_value != NULL
-                 && strcmp(state->ar->extra_value,
-diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
-index 33dbf7b1c17f188924ee7b50a77ab699f03392be..2eb77216ab9759d8b1d66fbdf0b2e90cd07a4604 100644
---- a/src/providers/ipa/ipa_views.c
-+++ b/src/providers/ipa/ipa_views.c
-@@ -208,16 +208,23 @@ struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx,
-     state->sdap_id_ctx = sdap_id_ctx;
-     state->ipa_options = ipa_options;
-     state->ipa_realm = ipa_realm;
--    if (strcmp(view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
--        state->ipa_view_name = IPA_DEFAULT_VIEW_NAME;
--    } else {
--        state->ipa_view_name = view_name;
--    }
-     state->ar = ar;
-     state->dp_error = -1;
-     state->override_attrs = NULL;
-     state->filter = NULL;
- 
-+    if (view_name == NULL) {
-+        DEBUG(SSSDBG_TRACE_ALL, "View not defined, nothing to do.\n");
-+        ret = EOK;
-+        goto done;
-+    }
-+
-+    if (strcmp(view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
-+        state->ipa_view_name = IPA_DEFAULT_VIEW_NAME;
-+    } else {
-+        state->ipa_view_name = view_name;
-+    }
-+
-     state->sdap_op = sdap_id_op_create(state,
-                                        state->sdap_id_ctx->conn->conn_cache);
-     if (state->sdap_op == NULL) {
--- 
-1.9.3
-
diff --git a/SOURCES/0012-IFP-Add-wildcard-requests.patch b/SOURCES/0012-IFP-Add-wildcard-requests.patch
new file mode 100644
index 0000000..d44b2a8
--- /dev/null
+++ b/SOURCES/0012-IFP-Add-wildcard-requests.patch
@@ -0,0 +1,663 @@
+From fe9a0097970d12ff261b7417f9e57db95957ab24 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 17 Jun 2015 13:39:43 +0200
+Subject: [PATCH 12/13] IFP: Add wildcard requests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves:
+    https://fedorahosted.org/sssd/ticket/2553
+
+Can be used as:
+
+dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \
+        /org/freedesktop/sssd/infopipe/Users \
+        org.freedesktop.sssd.infopipe.Users.ListByName \
+        string:r\* uint32:10
+
+dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \
+        /org/freedesktop/sssd/infopipe/Groups \
+        org.freedesktop.sssd.infopipe.Groups.ListByName \
+        string:r\* uint32:10
+
+dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \
+        /org/freedesktop/sssd/infopipe/Users \
+        org.freedesktop.sssd.infopipe.Users.ListByDomainAndName \
+        string:ipaldap string:r\* uint32:10
+
+dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \
+        /org/freedesktop/sssd/infopipe/Groups \
+        org.freedesktop.sssd.infopipe.Groups.ListByDomainAndName \
+        string:ipaldap string:r\* uint32:10
+
+By default the wildcard_limit is unset, that is, the request will return
+all cached entries that match.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/confdb/confdb.h             |   1 +
+ src/man/sssd-ifp.5.xml          |  15 ++++
+ src/responder/ifp/ifp_groups.c  | 175 ++++++++++++++++++++++++++++++++++++++
+ src/responder/ifp/ifp_private.h |  22 +++++
+ src/responder/ifp/ifp_users.c   | 184 ++++++++++++++++++++++++++++++++++++++++
+ src/responder/ifp/ifpsrv.c      |  23 +++++
+ src/responder/ifp/ifpsrv_util.c |  52 ++++++++++++
+ 7 files changed, 472 insertions(+)
+
+diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
+index b2ec2e0b98a9be2d50009df524a1072e9b1c15c7..36df6aea268cc5c82696f20b1a65963350d5e100 100644
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -140,6 +140,7 @@
+ /* InfoPipe */
+ #define CONFDB_IFP_CONF_ENTRY "config/ifp"
+ #define CONFDB_IFP_USER_ATTR_LIST "user_attributes"
++#define CONFDB_IFP_WILDCARD_LIMIT "wildcard_limit"
+ 
+ /* Domains */
+ #define CONFDB_DOMAIN_PATH_TMPL "config/domain/%s"
+diff --git a/src/man/sssd-ifp.5.xml b/src/man/sssd-ifp.5.xml
+index 867c117edccc3c000f7d9e8456298b72ebcdf693..da247f89dd2d9d08e0b1591d4c89f52197b278df 100644
+--- a/src/man/sssd-ifp.5.xml
++++ b/src/man/sssd-ifp.5.xml
+@@ -131,6 +131,21 @@ user_attributes = +telephoneNumber, -loginShell
+                         </para>
+                     </listitem>
+                 </varlistentry>
++
++                <varlistentry>
++                    <term>wildcart_limit (integer)</term>
++                    <listitem>
++                        <para>
++                            Specifies an upper limit on the number of entries
++                            that are downloaded during a wildcard lookup that
++                            overrides caller-supplied limit.
++                        </para>
++                        <para>
++                            Default: 0 (let the caller set an upper limit)
++                        </para>
++                    </listitem>
++                </varlistentry>
++
+             </variablelist>
+     </refsect1>
+ 
+diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c
+index 1b581b568f14362a47b4a80eb55d2de8eb936ae3..3060035924026641cc245f2a1970db9e2646e11c 100644
+--- a/src/responder/ifp/ifp_groups.c
++++ b/src/responder/ifp/ifp_groups.c
+@@ -81,6 +81,27 @@ done:
+     return ret;
+ }
+ 
++static int ifp_groups_list_copy(struct ifp_list_ctx *list_ctx,
++                                struct ldb_result *result)
++{
++    size_t copy_count, i;
++
++    copy_count = ifp_list_ctx_remaining_capacity(list_ctx, result->count);
++
++    for (i = 0; i < copy_count; i++) {
++        list_ctx->paths[list_ctx->path_count + i] = \
++            ifp_groups_build_path_from_msg(list_ctx->paths,
++                                           list_ctx->dom,
++                                           result->msgs[i]);
++        if (list_ctx->paths[list_ctx->path_count + i] == NULL) {
++            return ENOMEM;
++        }
++    }
++
++    list_ctx->path_count += copy_count;
++    return EOK;
++}
++
+ static void ifp_groups_find_by_name_done(struct tevent_req *req);
+ 
+ int ifp_groups_find_by_name(struct sbus_request *sbus_req,
+@@ -221,23 +242,177 @@ done:
+     return;
+ }
+ 
++static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx);
++static void ifp_groups_list_by_name_done(struct tevent_req *req);
++static void ifp_groups_list_by_name_reply(struct ifp_list_ctx *list_ctx);
++
+ int ifp_groups_list_by_name(struct sbus_request *sbus_req,
+                             void *data,
+                             const char *filter,
+                             uint32_t limit)
+ {
++    struct ifp_ctx *ctx;
++    struct ifp_list_ctx *list_ctx;
++
++    ctx = talloc_get_type(data, struct ifp_ctx);
++    if (ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
++        return ERR_INTERNAL;
++    }
++
++    list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit);
++    if (list_ctx == NULL) {
++        return ENOMEM;
++    }
++
++    return ifp_groups_list_by_name_step(list_ctx);
++}
++
++static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx)
++{
++    struct tevent_req *req;
++
++    req = cache_req_group_by_filter_send(list_ctx,
++                                        list_ctx->ctx->rctx->ev,
++                                        list_ctx->ctx->rctx,
++                                        list_ctx->dom->name,
++                                        list_ctx->filter);
++    if (req == NULL) {
++        return ENOMEM;
++    }
++    tevent_req_set_callback(req,
++                            ifp_groups_list_by_name_done, list_ctx);
++
+     return EOK;
+ }
+ 
++static void ifp_groups_list_by_name_done(struct tevent_req *req)
++{
++    DBusError *error;
++    struct ifp_list_ctx *list_ctx;
++    struct sbus_request *sbus_req;
++    struct ldb_result *result;
++    struct sss_domain_info *domain;
++    errno_t ret;
++
++    list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx);
++    sbus_req = list_ctx->sbus_req;
++
++    ret = cache_req_group_by_name_recv(sbus_req, req, &result, &domain, NULL);
++    talloc_zfree(req);
++    if (ret != EOK && ret != ENOENT) {
++        error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
++                               "groups by filter [%d]: %s\n", ret, sss_strerror(ret));
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++
++    ret = ifp_groups_list_copy(list_ctx, result);
++    if (ret != EOK) {
++        error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
++                               "Failed to copy domain result");
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++
++    list_ctx->dom = get_next_domain(list_ctx->dom, true);
++    if (list_ctx->dom == NULL) {
++        return ifp_groups_list_by_name_reply(list_ctx);
++    }
++
++    ret = ifp_groups_list_by_name_step(list_ctx);
++    if (ret != EOK) {
++        error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
++                               "Failed to start next-domain search");
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++}
++
++static void ifp_groups_list_by_name_reply(struct ifp_list_ctx *list_ctx)
++{
++    iface_ifp_groups_ListByDomainAndName_finish(list_ctx->sbus_req,
++                                               list_ctx->paths,
++                                               list_ctx->path_count);
++}
++
++static void ifp_groups_list_by_domain_and_name_done(struct tevent_req *req);
++
+ int ifp_groups_list_by_domain_and_name(struct sbus_request *sbus_req,
+                                        void *data,
+                                        const char *domain,
+                                        const char *filter,
+                                        uint32_t limit)
+ {
++    struct tevent_req *req;
++    struct ifp_ctx *ctx;
++    struct ifp_list_ctx *list_ctx;
++
++    ctx = talloc_get_type(data, struct ifp_ctx);
++    if (ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
++        return ERR_INTERNAL;
++    }
++
++    list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit);
++    if (list_ctx == NULL) {
++        return ENOMEM;
++    }
++
++    req = cache_req_group_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx,
++                                        domain, filter);
++    if (req == NULL) {
++        return ENOMEM;
++    }
++    tevent_req_set_callback(req,
++                            ifp_groups_list_by_domain_and_name_done, list_ctx);
++
+     return EOK;
+ }
+ 
++static void ifp_groups_list_by_domain_and_name_done(struct tevent_req *req)
++{
++    DBusError *error;
++    struct ifp_list_ctx *list_ctx;
++    struct sbus_request *sbus_req;
++    struct ldb_result *result;
++    struct sss_domain_info *domain;
++    errno_t ret;
++
++    list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx);
++    sbus_req = list_ctx->sbus_req;
++
++    ret = cache_req_user_by_name_recv(sbus_req, req, &result, &domain, NULL);
++    talloc_zfree(req);
++    if (ret == ENOENT) {
++        error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
++                               "User not found by filter");
++        goto done;
++    } else if (ret != EOK) {
++        error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
++                               "groups by filter [%d]: %s\n", ret, sss_strerror(ret));
++        goto done;
++    }
++
++    ret = ifp_groups_list_copy(list_ctx, result);
++    if (ret != EOK) {
++        error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
++                               "Failed to copy domain result");
++        goto done;
++    }
++
++done:
++    if (ret != EOK) {
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++
++    iface_ifp_groups_ListByDomainAndName_finish(sbus_req,
++                                                list_ctx->paths,
++                                                list_ctx->path_count);
++    return;
++}
++
+ static errno_t
+ ifp_groups_group_get(struct sbus_request *sbus_req,
+                      void *data,
+diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h
+index 304e4dc535aac4215cf318a0bea845c161c5f079..43519de6fef3033f1e47cecb787d6b02dc9c6e56 100644
+--- a/src/responder/ifp/ifp_private.h
++++ b/src/responder/ifp/ifp_private.h
+@@ -44,6 +44,7 @@ struct ifp_ctx {
+ 
+     struct sysbus_ctx *sysbus;
+     const char **user_whitelist;
++    uint32_t wildcard_limit;
+ };
+ 
+ errno_t ifp_register_sbus_interface(struct sbus_connection *conn,
+@@ -84,4 +85,25 @@ ifp_get_user_extra_attributes(TALLOC_CTX *mem_ctx, struct ifp_ctx *ifp_ctx);
+ bool ifp_attr_allowed(const char *whitelist[], const char *attr);
+ bool ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr);
+ 
++/* Used for list calls */
++struct ifp_list_ctx {
++    struct sbus_request *sbus_req;
++    const char *filter;
++    uint32_t limit;
++
++    struct sss_domain_info *dom;
++    struct ifp_ctx *ctx;
++
++    const char **paths;
++    size_t path_count;
++};
++
++struct ifp_list_ctx *ifp_list_ctx_new(struct sbus_request *sbus_req,
++                                      struct ifp_ctx *ctx,
++                                      const char *filter,
++                                      uint32_t limit);
++
++size_t ifp_list_ctx_remaining_capacity(struct ifp_list_ctx *list_ctx,
++                                       size_t entries);
++
+ #endif /* _IFPSRV_PRIVATE_H_ */
+diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c
+index 2ec74c30b348ac5f2b84cdc8e2dd406fd44a7da3..effefdc0435d794206dbe7358c61d2ea47760361 100644
+--- a/src/responder/ifp/ifp_users.c
++++ b/src/responder/ifp/ifp_users.c
+@@ -309,23 +309,207 @@ done:
+     return;
+ }
+ 
++static int ifp_users_list_copy(struct ifp_list_ctx *list_ctx,
++                               struct ldb_result *result)
++{
++    size_t copy_count, i;
++
++    copy_count = ifp_list_ctx_remaining_capacity(list_ctx, result->count);
++
++    for (i = 0; i < copy_count; i++) {
++        list_ctx->paths[list_ctx->path_count + i] = \
++                             ifp_users_build_path_from_msg(list_ctx->paths,
++                                                           list_ctx->dom,
++                                                           result->msgs[i]);
++        if (list_ctx->paths[list_ctx->path_count + i] == NULL) {
++            return ENOMEM;
++        }
++    }
++
++    list_ctx->path_count += copy_count;
++    return EOK;
++}
++
++static int ifp_users_list_by_name_step(struct ifp_list_ctx *list_ctx);
++static void ifp_users_list_by_name_done(struct tevent_req *req);
++static void ifp_users_list_by_name_reply(struct ifp_list_ctx *list_ctx);
++
+ int ifp_users_list_by_name(struct sbus_request *sbus_req,
+                            void *data,
+                            const char *filter,
+                            uint32_t limit)
+ {
++    struct ifp_ctx *ctx;
++    struct ifp_list_ctx *list_ctx;
++
++    ctx = talloc_get_type(data, struct ifp_ctx);
++    if (ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
++        return ERR_INTERNAL;
++    }
++
++    list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit);
++    if (list_ctx == NULL) {
++        return ENOMEM;
++    }
++
++    return ifp_users_list_by_name_step(list_ctx);
++}
++
++static int ifp_users_list_by_name_step(struct ifp_list_ctx *list_ctx)
++{
++    struct tevent_req *req;
++
++    req = cache_req_user_by_filter_send(list_ctx,
++                                        list_ctx->ctx->rctx->ev,
++                                        list_ctx->ctx->rctx,
++                                        list_ctx->dom->name,
++                                        list_ctx->filter);
++    if (req == NULL) {
++        return ENOMEM;
++    }
++    tevent_req_set_callback(req,
++                            ifp_users_list_by_name_done, list_ctx);
++
+     return EOK;
+ }
+ 
++static void ifp_users_list_by_name_done(struct tevent_req *req)
++{
++    DBusError *error;
++    struct ifp_list_ctx *list_ctx;
++    struct sbus_request *sbus_req;
++    struct ldb_result *result;
++    struct sss_domain_info *domain;
++    errno_t ret;
++
++    list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx);
++    sbus_req = list_ctx->sbus_req;
++
++    ret = cache_req_user_by_name_recv(sbus_req, req, &result, &domain, NULL);
++    talloc_zfree(req);
++    if (ret != EOK && ret != ENOENT) {
++        error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
++                               "users by filter [%d]: %s\n", ret, sss_strerror(ret));
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++
++    ret = ifp_users_list_copy(list_ctx, result);
++    if (ret != EOK) {
++        error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
++                               "Failed to copy domain result");
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++
++    list_ctx->dom = get_next_domain(list_ctx->dom, true);
++    if (list_ctx->dom == NULL) {
++        return ifp_users_list_by_name_reply(list_ctx);
++    }
++
++    ret = ifp_users_list_by_name_step(list_ctx);
++    if (ret != EOK) {
++        error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
++                               "Failed to start next-domain search");
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++}
++
++static void ifp_users_list_by_name_reply(struct ifp_list_ctx *list_ctx)
++{
++    iface_ifp_users_ListByName_finish(list_ctx->sbus_req,
++                                      list_ctx->paths,
++                                      list_ctx->path_count);
++}
++
++static void ifp_users_list_by_domain_and_name_done(struct tevent_req *req);
++
+ int ifp_users_list_by_domain_and_name(struct sbus_request *sbus_req,
+                                       void *data,
+                                       const char *domain,
+                                       const char *filter,
+                                       uint32_t limit)
+ {
++    struct tevent_req *req;
++    struct ifp_ctx *ctx;
++    struct ifp_list_ctx *list_ctx;
++
++    ctx = talloc_get_type(data, struct ifp_ctx);
++    if (ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
++        return ERR_INTERNAL;
++    }
++
++    list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit);
++    if (list_ctx == NULL) {
++        return ENOMEM;
++    }
++
++    req = cache_req_user_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx,
++                                        domain, filter);
++    if (req == NULL) {
++        return ENOMEM;
++    }
++    tevent_req_set_callback(req,
++                            ifp_users_list_by_domain_and_name_done, list_ctx);
++
+     return EOK;
+ }
+ 
++static void ifp_users_list_by_domain_and_name_done(struct tevent_req *req)
++{
++    DBusError *error;
++    struct ifp_list_ctx *list_ctx;
++    struct sbus_request *sbus_req;
++    struct ldb_result *result;
++    struct sss_domain_info *domain;
++    errno_t ret;
++    size_t copy_count, i;
++
++    list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx);
++    sbus_req = list_ctx->sbus_req;
++
++    ret = cache_req_user_by_name_recv(sbus_req, req, &result, &domain, NULL);
++    talloc_zfree(req);
++    if (ret == ENOENT) {
++        error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
++                               "User not found by filter");
++        goto done;
++    } else if (ret != EOK) {
++        error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
++                               "users by filter [%d]: %s\n", ret, sss_strerror(ret));
++        goto done;
++    }
++
++    copy_count = ifp_list_ctx_remaining_capacity(list_ctx, result->count);
++
++    for (i = 0; i < copy_count; i++) {
++        list_ctx->paths[i] = ifp_users_build_path_from_msg(list_ctx->paths,
++                                                           list_ctx->dom,
++                                                           result->msgs[i]);
++        if (list_ctx->paths[i] == NULL) {
++            error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL,
++                                   "Failed to compose object path");
++            goto done;
++        }
++    }
++
++    list_ctx->path_count += copy_count;
++
++done:
++    if (ret != EOK) {
++        sbus_request_fail_and_finish(sbus_req, error);
++        return;
++    }
++
++    iface_ifp_users_ListByDomainAndName_finish(sbus_req,
++                                               list_ctx->paths,
++                                               list_ctx->path_count);
++    return;
++}
++
+ static errno_t
+ ifp_users_user_get(struct sbus_request *sbus_req,
+                    struct ifp_ctx *ifp_ctx,
+diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
+index 631bcd266d7e06154dbf1f37f9f439119b2b8944..cdc411faa330dc2c063e52abe63cd68dbe16a5d9 100644
+--- a/src/responder/ifp/ifpsrv.c
++++ b/src/responder/ifp/ifpsrv.c
+@@ -34,6 +34,7 @@
+ #include <dbus/dbus.h>
+ 
+ #include "util/util.h"
++#include "util/strtonum.h"
+ #include "sbus/sssd_dbus.h"
+ #include "monitor/monitor_interfaces.h"
+ #include "confdb/confdb.h"
+@@ -228,6 +229,7 @@ int ifp_process_init(TALLOC_CTX *mem_ctx,
+     int max_retries;
+     char *uid_str;
+     char *attr_list_str;
++    char *wildcard_limit_str;
+ 
+     ifp_cmds = get_ifp_cmds();
+     ret = sss_process_init(mem_ctx, ev, cdb,
+@@ -321,6 +323,27 @@ int ifp_process_init(TALLOC_CTX *mem_ctx,
+         goto fail;
+     }
+ 
++    /* A bit convoluted way until we have a confdb_get_uint32 */
++    ret = confdb_get_string(ifp_ctx->rctx->cdb,
++                            ifp_ctx->rctx,
++                            CONFDB_IFP_CONF_ENTRY,
++                            CONFDB_IFP_WILDCARD_LIMIT,
++                            NULL, /* no limit by default */
++                            &wildcard_limit_str);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "Failed to retrieve limit for a wildcard search\n");
++        goto fail;
++    }
++
++    if (wildcard_limit_str) {
++        ifp_ctx->wildcard_limit = strtouint32(wildcard_limit_str, NULL, 10);
++        if (errno != 0) {
++            ret = errno;
++            goto fail;
++        }
++    }
++
+     for (iter = ifp_ctx->rctx->be_conns; iter; iter = iter->next) {
+         sbus_reconnect_init(iter->conn, max_retries,
+                             ifp_dp_reconnect_init, iter);
+diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c
+index 674165ee4901115c9e17458a75fdb3536b6468c2..3b02fd06f5227e4ffc3d40ffb20fed981c5028a7 100644
+--- a/src/responder/ifp/ifpsrv_util.c
++++ b/src/responder/ifp/ifpsrv_util.c
+@@ -21,6 +21,8 @@
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+ 
++#include <sys/param.h>
++
+ #include "db/sysdb.h"
+ #include "responder/ifp/ifp_private.h"
+ 
+@@ -269,3 +271,53 @@ ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr)
+ {
+     return ifp_attr_allowed(ifp_ctx->user_whitelist, attr);
+ }
++
++static uint32_t ifp_list_limit(struct ifp_ctx *ctx, uint32_t limit)
++{
++    if (ctx->wildcard_limit) {
++        return MIN(ctx->wildcard_limit, limit);
++    } else {
++        return limit;
++    }
++}
++
++struct ifp_list_ctx *ifp_list_ctx_new(struct sbus_request *sbus_req,
++                                      struct ifp_ctx *ctx,
++                                      const char *filter,
++                                      uint32_t limit)
++{
++    struct ifp_list_ctx *list_ctx;
++
++    list_ctx = talloc_zero(sbus_req, struct ifp_list_ctx);
++    if (list_ctx == NULL) {
++        return NULL;
++    }
++
++    list_ctx->sbus_req = sbus_req;
++    list_ctx->limit = ifp_list_limit(ctx, limit);
++    list_ctx->ctx = ctx;
++    list_ctx->dom = ctx->rctx->domains;
++    list_ctx->filter = filter;
++    list_ctx->paths = talloc_zero_array(list_ctx, const char *, limit);
++    if (list_ctx->paths == NULL) {
++        talloc_free(list_ctx);
++        return NULL;
++    }
++
++    return list_ctx;
++}
++
++size_t ifp_list_ctx_remaining_capacity(struct ifp_list_ctx *list_ctx,
++                                       size_t entries)
++{
++    size_t capacity = list_ctx->limit - list_ctx->path_count;
++
++    if (capacity < entries) {
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "IFP list request has limit of %"PRIu32" entries but back end "
++              "returned %zu entries\n", list_ctx->limit, entries);
++        return capacity;
++    } else {
++        return entries;
++    }
++}
+-- 
+2.4.3
+
diff --git a/SOURCES/0012-ipa-improve-error-reporting-for-extdom-LDAP-exop.patch b/SOURCES/0012-ipa-improve-error-reporting-for-extdom-LDAP-exop.patch
deleted file mode 100644
index 8120e60..0000000
--- a/SOURCES/0012-ipa-improve-error-reporting-for-extdom-LDAP-exop.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From de830a6c4b032ec21c2aad9f7b56fd80fe09817b Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 20 Oct 2014 17:09:34 +0200
-Subject: [PATCH 12/22] ipa: improve error reporting for extdom LDAP exop
-
-This patch fixes a typo when calling ldap_parse_result() which prevented
-the server-side error message to be used and adds a hint that more
-information might be available on the server side.
-
-Fixes: https://fedorahosted.org/sssd/ticket/2456
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 96528816a520b633f1f1caa975dee9b9515621c3..bd5c00b6a48018f8f904aaa03e8162425651b37a 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -133,7 +133,7 @@ static void ipa_s2n_exop_done(struct sdap_op *op,
-     }
- 
-     ret = ldap_parse_result(state->sh->ldap, reply->msg,
--                            &result, &errmsg, NULL, NULL,
-+                            &result, NULL, &errmsg, NULL,
-                             NULL, 0);
-     if (ret != LDAP_SUCCESS) {
-         DEBUG(SSSDBG_OP_FAILURE, "ldap_parse_result failed (%d)\n",
-@@ -142,10 +142,13 @@ static void ipa_s2n_exop_done(struct sdap_op *op,
-         goto done;
-     }
- 
--    DEBUG(SSSDBG_TRACE_FUNC, "ldap_extended_operation result: %s(%d), %s\n",
--            sss_ldap_err2string(result), result, errmsg);
-+    DEBUG(result == LDAP_SUCCESS ? SSSDBG_TRACE_FUNC : SSSDBG_OP_FAILURE,
-+          "ldap_extended_operation result: %s(%d), %s.\n",
-+          sss_ldap_err2string(result), result, errmsg);
- 
-     if (result != LDAP_SUCCESS) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldap_extended_operation failed, " \
-+                                 "server logs might contain more details.\n");
-         ret = ERR_NETWORK_IO;
-         goto done;
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0013-BUILD-Fix-automake-warning.patch b/SOURCES/0013-BUILD-Fix-automake-warning.patch
deleted file mode 100644
index 7c93e71..0000000
--- a/SOURCES/0013-BUILD-Fix-automake-warning.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 37d4520aea8d02701edc7a2c4d1407430b22860c Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 21 Oct 2014 19:31:24 +0200
-Subject: [PATCH 13/22] BUILD: Fix automake warning
-
-src/tests/cwrap/Makefile.am:45: warning: check_PROGRAMS was already
-        defined in condition TRUE, which includes condition HAVE_CMOCKA
-         and HAVE_NSS_WRAPPER and HAVE_UID_WRAPPER ...
-src/tests/cwrap/Makefile.am:41: ... 'check_PROGRAMS' previously defined here
-
-This patch also replace '\t' with spaces
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/tests/cwrap/Makefile.am | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
-index 28d60e7f5bc346543f51740ec4b2781a99a48909..d1f0e9e1b999814d8081af36f82e94f638452da4 100644
---- a/src/tests/cwrap/Makefile.am
-+++ b/src/tests/cwrap/Makefile.am
-@@ -42,10 +42,10 @@ check_PROGRAMS =
- if HAVE_CMOCKA
- if HAVE_NSS_WRAPPER
- if HAVE_UID_WRAPPER
--check_PROGRAMS = \
--	become_user-tests \
--	server-tests \
--	$(NULL)
-+check_PROGRAMS += \
-+    become_user-tests \
-+    server-tests \
-+    $(NULL)
- endif # HAVE_UID_WRAPPER
- endif # HAVE_NSS_WRAPPER
- endif # HAVE_CMOCKA
--- 
-1.9.3
-
diff --git a/SOURCES/0013-KRB5-Return-right-data-provider-error-code.patch b/SOURCES/0013-KRB5-Return-right-data-provider-error-code.patch
new file mode 100644
index 0000000..4d2aebf
--- /dev/null
+++ b/SOURCES/0013-KRB5-Return-right-data-provider-error-code.patch
@@ -0,0 +1,32 @@
+From aac1c3031aadce0682c4e3873634e405cdd41e69 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Tue, 14 Jul 2015 12:48:47 +0200
+Subject: [PATCH 13/13] KRB5: Return right data provider error code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2719
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+---
+ src/providers/krb5/krb5_wait_queue.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/providers/krb5/krb5_wait_queue.c b/src/providers/krb5/krb5_wait_queue.c
+index 126209620dcd22889cf7bcb1cbec1890b8891b41..b4d3f903a94c9fdfffc975f1dfd10a27ab653a8d 100644
+--- a/src/providers/krb5/krb5_wait_queue.c
++++ b/src/providers/krb5/krb5_wait_queue.c
+@@ -366,7 +366,7 @@ int krb5_auth_queue_recv(struct tevent_req *req,
+     }
+ 
+     if (_dp_err) {
+-        *_dp_err = state->pam_status;
++        *_dp_err = state->dp_err;
+     }
+ 
+     TEVENT_REQ_RETURN_ON_ERROR(req);
+-- 
+2.4.3
+
diff --git a/SOURCES/0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch b/SOURCES/0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch
new file mode 100644
index 0000000..936f1f5
--- /dev/null
+++ b/SOURCES/0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch
@@ -0,0 +1,183 @@
+From f9f227bb5a7fe6e5af83debbbd892bdb4e13894d Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Tue, 14 Jul 2015 14:41:34 +0200
+Subject: [PATCH 14/14] nss_check_name_of_well_known_sid() improve name
+ splitting
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Currently in the default configuration
+nss_check_name_of_well_known_sid() can only split fully-qualified names
+in the user@domain.name style. DOM\user style names will cause an error
+and terminate the whole request.
+
+With this patch both styles can be handled by default, additionally if
+the name could not be split nss_check_name_of_well_known_sid() returns
+ENOENT which can be handled more gracefully by the caller.
+
+Resolves https://fedorahosted.org/sssd/ticket/2717
+
+Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
+---
+ src/responder/nss/nsssrv_cmd.c  |  8 ++++
+ src/tests/cmocka/test_nss_srv.c | 90 ++++++++++++++++++++++++-----------------
+ src/util/usertools.c            |  3 +-
+ 3 files changed, 61 insertions(+), 40 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
+index 0129467302f16af318bbbb0a5be47ff2e235da65..b3998015fa621cad8e06a126a674f94d26158dda 100644
+--- a/src/responder/nss/nsssrv_cmd.c
++++ b/src/responder/nss/nsssrv_cmd.c
+@@ -1255,6 +1255,14 @@ static int nss_check_name_of_well_known_sid(struct nss_cmd_ctx *cmdctx,
+         return ret;
+     }
+ 
++    if (wk_dom_name == NULL || wk_name == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Unable to split [%s] in name and domain part. " \
++              "Skipping check for well-known name.\n", full_name);
++
++        return ENOENT;
++    }
++
+     ret = name_to_well_known_sid(wk_dom_name, wk_name, &wk_sid);
+     talloc_free(wk_dom_name);
+     talloc_free(wk_name);
+diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
+index 3ab8d39c44a8bb8cacae20f534dcbeb6ca7dec08..84d3413be70bc0af433b7fd23cf7d78b4b9298f1 100644
+--- a/src/tests/cmocka/test_nss_srv.c
++++ b/src/tests/cmocka/test_nss_srv.c
+@@ -1734,63 +1734,77 @@ void test_nss_well_known_getidbysid_failure(void **state)
+ void test_nss_well_known_getsidbyname(void **state)
+ {
+     errno_t ret;
++    const char *names[] = { "Cryptographic Operators@BUILTIN",
++                            "BUILTIN\\Cryptographic Operators", NULL};
++    size_t c;
+ 
+-    will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+-    will_return(__wrap_sss_packet_get_body, "Cryptographic Operators@BUILTIN");
+-    will_return(__wrap_sss_packet_get_body, 0);
+-    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
+-    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+-    will_return(test_nss_well_known_sid_check, "S-1-5-32-569");
++    for (c = 0; names[c] != NULL; c++) {
++        will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
++        will_return(__wrap_sss_packet_get_body, names[c]);
++        will_return(__wrap_sss_packet_get_body, 0);
++        will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
++        will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++        will_return(test_nss_well_known_sid_check, "S-1-5-32-569");
+ 
+-    set_cmd_cb(test_nss_well_known_sid_check);
+-    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
+-                          nss_test_ctx->nss_cmds);
+-    assert_int_equal(ret, EOK);
++        set_cmd_cb(test_nss_well_known_sid_check);
++        ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
++                              nss_test_ctx->nss_cmds);
++        assert_int_equal(ret, EOK);
+ 
+-    /* Wait until the test finishes with EOK */
+-    ret = test_ev_loop(nss_test_ctx->tctx);
+-    assert_int_equal(ret, EOK);
++        /* Wait until the test finishes with EOK */
++        ret = test_ev_loop(nss_test_ctx->tctx);
++        assert_int_equal(ret, EOK);
++    }
+ }
+ 
+ void test_nss_well_known_getsidbyname_nonexisting(void **state)
+ {
+     errno_t ret;
++    const char *names[] = { "Abc@BUILTIN", "BUILTIN\\Abc", NULL };
++    size_t c;
+ 
+-    will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+-    will_return(__wrap_sss_packet_get_body, "Abc@BUILTIN");
+-    will_return(__wrap_sss_packet_get_body, 0);
+-    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
+-    will_return(test_nss_well_known_sid_check, NULL);
++    for (c = 0; names[c] != NULL; c++) {
++        will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
++        will_return(__wrap_sss_packet_get_body, names[c]);
++        will_return(__wrap_sss_packet_get_body, 0);
++        will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
++        will_return(test_nss_well_known_sid_check, NULL);
+ 
+-    set_cmd_cb(test_nss_well_known_sid_check);
+-    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
+-                          nss_test_ctx->nss_cmds);
+-    assert_int_equal(ret, EOK);
++        set_cmd_cb(test_nss_well_known_sid_check);
++        ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
++                              nss_test_ctx->nss_cmds);
++        assert_int_equal(ret, EOK);
+ 
+-    /* Wait until the test finishes with EOK */
+-    ret = test_ev_loop(nss_test_ctx->tctx);
+-    assert_int_equal(ret, EOK);
++        /* Wait until the test finishes with EOK */
++        ret = test_ev_loop(nss_test_ctx->tctx);
++        assert_int_equal(ret, EOK);
++    }
+ }
+ 
+ void test_nss_well_known_getsidbyname_special(void **state)
+ {
+     errno_t ret;
++    const char *names[] = { "CREATOR OWNER@CREATOR AUTHORITY",
++                            "CREATOR AUTHORITY\\CREATOR OWNER", NULL };
++    size_t c;
+ 
+-    will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+-    will_return(__wrap_sss_packet_get_body, "CREATOR OWNER@CREATOR AUTHORITY");
+-    will_return(__wrap_sss_packet_get_body, 0);
+-    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
+-    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+-    will_return(test_nss_well_known_sid_check, "S-1-3-0");
++    for (c = 0; names[c] != NULL; c++) {
++        will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
++        will_return(__wrap_sss_packet_get_body, names[c]);
++        will_return(__wrap_sss_packet_get_body, 0);
++        will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
++        will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++        will_return(test_nss_well_known_sid_check, "S-1-3-0");
+ 
+-    set_cmd_cb(test_nss_well_known_sid_check);
+-    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
+-                          nss_test_ctx->nss_cmds);
+-    assert_int_equal(ret, EOK);
++        set_cmd_cb(test_nss_well_known_sid_check);
++        ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
++                              nss_test_ctx->nss_cmds);
++        assert_int_equal(ret, EOK);
+ 
+-    /* Wait until the test finishes with EOK */
+-    ret = test_ev_loop(nss_test_ctx->tctx);
+-    assert_int_equal(ret, EOK);
++        /* Wait until the test finishes with EOK */
++        ret = test_ev_loop(nss_test_ctx->tctx);
++        assert_int_equal(ret, EOK);
++    }
+ }
+ 
+ static int test_nss_getorigbyname_check(uint32_t status, uint8_t *body,
+diff --git a/src/util/usertools.c b/src/util/usertools.c
+index c43d420e31c6c690628ef6179d932eaf99826fee..87a8d7411312c3a80c32374a1fd93bbf0e767a91 100644
+--- a/src/util/usertools.c
++++ b/src/util/usertools.c
+@@ -249,8 +249,7 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
+     }
+ 
+     if (!re_pattern) {
+-        re_pattern = talloc_strdup(tmpctx,
+-                                   "(?P<name>[^@]+)@?(?P<domain>[^@]*$)");
++        re_pattern = talloc_strdup(tmpctx, IPA_AD_DEFAULT_RE);
+         if (!re_pattern) {
+             ret = ENOMEM;
+             goto done;
+-- 
+2.4.3
+
diff --git a/SOURCES/0014-test_server-Fix-waiting-for-background-process.patch b/SOURCES/0014-test_server-Fix-waiting-for-background-process.patch
deleted file mode 100644
index f4b8270..0000000
--- a/SOURCES/0014-test_server-Fix-waiting-for-background-process.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 74774cb436fc62d258d9642254f3029397062864 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 21 Oct 2014 20:29:15 +0200
-Subject: [PATCH 14/22] test_server: Fix waiting for background process
-
-A waiting loop for background process was very fast (just 5 milliseconds)
-It caused problem when test was executed with valgrind.
-The maximum time was increased to 10 seconds.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/tests/cwrap/test_server.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/src/tests/cwrap/test_server.c b/src/tests/cwrap/test_server.c
-index 26ecfee1e189b6a474ae52fdbfff6b8922b3f0d7..d0aeac47d0b067fdbc3399037c0a74f150337a23 100644
---- a/src/tests/cwrap/test_server.c
-+++ b/src/tests/cwrap/test_server.c
-@@ -55,12 +55,13 @@ static void wait_for_bg_server(const char *pidfile)
-         struct stat sb;
- 
-         count++;
--        if (count > 100) {
-+        if (count > 200) {
-+            fail();
-             break;
-         }
- 
-         ret = stat(pidfile, &sb);
--        usleep(50);
-+        usleep(50000);
-     } while (ret != 0);
- 
-     /* read the pidfile */
-@@ -198,7 +199,9 @@ int main(int argc, const char *argv[])
-     test_dom_suite_setup(TEST_DB_PATH);
- 
-     rv = run_tests(tests);
--    test_dom_suite_cleanup(TEST_DB_PATH, CONFDB_FILE, NULL);
-+    if (rv != 0) {
-+        test_dom_suite_cleanup(TEST_DB_PATH, CONFDB_FILE, NULL);
-+    }
- 
-     return rv;
- }
--- 
-1.9.3
-
diff --git a/SOURCES/0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch b/SOURCES/0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch
new file mode 100644
index 0000000..21b708e
--- /dev/null
+++ b/SOURCES/0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch
@@ -0,0 +1,98 @@
+From c7c762dc50c48cfa43551a3936dd46405e9d33ce Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Wed, 8 Jul 2015 09:01:24 -0400
+Subject: [PATCH 15/19] DYNDNS: sss_iface_addr_list_get return ENOENT
+
+If none of eligible interfaces matches ifname then ENOENT is returned.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2549
+---
+ src/providers/dp_dyndns.c        | 13 +++++++++++--
+ src/providers/ldap/sdap_dyndns.c |  6 +++++-
+ src/tests/cmocka/test_dyndns.c   | 20 ++++++++++++++++++++
+ 3 files changed, 36 insertions(+), 3 deletions(-)
+
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 1cac3d0fae2454cea823ed640a4325f27580353f..2ac43a108ff6197d9e2662198a6da976ca348e76 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -222,8 +222,17 @@ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname,
+         }
+     }
+ 
+-    ret = EOK;
+-    *_addrlist = addrlist;
++    if (addrlist != NULL) {
++        /* OK, some result was found */
++        ret = EOK;
++        *_addrlist = addrlist;
++    } else {
++        /* No result was found */
++        DEBUG(SSSDBG_TRACE_FUNC,
++              "No IPs usable for DNS was found for interface: %s.\n", ifname);
++        ret = ENOENT;
++    }
++
+ done:
+     freeifaddrs(ifaces);
+     return ret;
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index 0d9c9205792062378aa25aad6ac706058001433a..e99a4f6687035928f6775c38b9df6b2a06d38f38 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -502,8 +502,12 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx,
+     if (iface) {
+         ret = sss_iface_addr_list_get(state, iface, &state->addresses);
+         if (ret != EOK) {
+-            DEBUG(SSSDBG_OP_FAILURE,
++            DEBUG(ret == ENOENT ? SSSDBG_MINOR_FAILURE : SSSDBG_OP_FAILURE,
+                   "Cannot get list of addresses from interface %s\n", iface);
++            /* non critical failure */
++            if (ret == ENOENT) {
++                ret = EOK;
++            }
+         }
+         /* We're done. Just fake an async request completion */
+         goto done;
+diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c
+index 689e333d4e68c4a2582894d06b8b7b20c76b9be8..3214e90c063ea9a4cf6f6bc6507bf4e37b7d23a4 100644
+--- a/src/tests/cmocka/test_dyndns.c
++++ b/src/tests/cmocka/test_dyndns.c
+@@ -247,6 +247,23 @@ void dyndns_test_get_multi_ifaddr(void **state)
+     assert_true(check_leaks_pop(dyndns_test_ctx) == true);
+ }
+ 
++void dyndns_test_get_ifaddr_enoent(void **state)
++{
++    errno_t ret;
++    struct sss_iface_addr *addrlist = NULL;
++
++    check_leaks_push(dyndns_test_ctx);
++    will_return_getifaddrs("eth0", "192.168.0.1");
++    will_return_getifaddrs("eth1", "192.168.0.2");
++    will_return_getifaddrs(NULL, NULL); /* sentinel */
++    ret = sss_iface_addr_list_get(dyndns_test_ctx, "non_existing_interface",
++                                  &addrlist);
++    assert_int_equal(ret, ENOENT);
++    talloc_free(addrlist);
++
++    assert_true(check_leaks_pop(dyndns_test_ctx) == true);
++}
++
+ void dyndns_test_ok(void **state)
+ {
+     struct tevent_req *req;
+@@ -460,6 +477,9 @@ int main(int argc, const char *argv[])
+         cmocka_unit_test_setup_teardown(dyndns_test_get_multi_ifaddr,
+                                         dyndns_test_simple_setup,
+                                         dyndns_test_teardown),
++        cmocka_unit_test_setup_teardown(dyndns_test_get_ifaddr_enoent,
++                                        dyndns_test_simple_setup,
++                                        dyndns_test_teardown),
+ 
+         /* Dynamic DNS update unit tests*/
+         cmocka_unit_test_setup_teardown(dyndns_test_ok,
+-- 
+2.4.3
+
diff --git a/SOURCES/0015-ipa_subdomains_handler_master_done-initialize-reply_.patch b/SOURCES/0015-ipa_subdomains_handler_master_done-initialize-reply_.patch
deleted file mode 100644
index 5115210..0000000
--- a/SOURCES/0015-ipa_subdomains_handler_master_done-initialize-reply_.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From cb7813503506729a5595e23c575619bd89250dfd Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 14 Oct 2014 16:52:04 +0200
-Subject: [PATCH 15/22] ipa_subdomains_handler_master_done: initialize
- reply_count
-
-This patch should mainly silence a false-positive Coverity warning but
-since further processing depends on this variable I think it is a good
-idea anyways.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/providers/ipa/ipa_subdomains.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index eb172fdfc05ac4e482174f01d89ad28db1498fc1..c61c1c666908ec23f8a92e5568222e55ec47be0a 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -1276,7 +1276,7 @@ static void ipa_subdomains_handler_master_done(struct tevent_req *req)
- {
-     errno_t ret;
-     int dp_error = DP_ERR_FATAL;
--    size_t reply_count;
-+    size_t reply_count = 0;
-     struct sysdb_attrs **reply = NULL;
-     struct ipa_subdomains_req_ctx *ctx;
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch b/SOURCES/0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch
new file mode 100644
index 0000000..abf0e7f
--- /dev/null
+++ b/SOURCES/0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch
@@ -0,0 +1,194 @@
+From e1936ccbb810965e90d030c2ed8f420c084b6a22 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Wed, 8 Jul 2015 09:08:03 -0400
+Subject: [PATCH 16/19] DYNDNS: support mult. interfaces for dyndns_iface opt
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2549
+---
+ src/man/sssd-ad.5.xml            | 11 +++---
+ src/man/sssd-ipa.5.xml           | 10 ++++--
+ src/providers/dp_dyndns.c        |  6 ++++
+ src/providers/dp_dyndns.h        |  4 +++
+ src/providers/ldap/sdap_dyndns.c | 72 +++++++++++++++++++++++++++++++++++-----
+ 5 files changed, 87 insertions(+), 16 deletions(-)
+
+diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
+index 938a443e027b9bf83c75c240a7d6b2a0876b92c8..ff43ea37066514a87934d07b141e680416dcc05b 100644
+--- a/src/man/sssd-ad.5.xml
++++ b/src/man/sssd-ad.5.xml
+@@ -754,15 +754,16 @@ ad_gpo_map_deny = +my_pam_service
+                     <listitem>
+                         <para>
+                             Optional. Applicable only when dyndns_update
+-                            is true. Choose the interface whose IP address
+-                            should be used for dynamic DNS updates.
+-                        </para>
+-                        <para>
+-                            NOTE: This option currently supports only one interface.
++                            is true. Choose the interface or a list of interfaces
++                            whose IP addresses should be used for dynamic DNS
++                            updates.
+                         </para>
+                         <para>
+                             Default: Use the IP address of the AD LDAP connection
+                         </para>
++                        <para>
++                            Example: dyndns_iface = em1, vnet1, vnet2
++                        </para>
+                     </listitem>
+                 </varlistentry>
+ 
+diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
+index 0716b6235f93965170983856b930799bfded6258..d450c2fadbb1713096ff766bf536702195cfd137 100644
+--- a/src/man/sssd-ipa.5.xml
++++ b/src/man/sssd-ipa.5.xml
+@@ -166,11 +166,12 @@
+                     <listitem>
+                         <para>
+                             Optional. Applicable only when dyndns_update
+-                            is true. Choose the interface whose IP address
+-                            should be used for dynamic DNS updates.
++                            is true. Choose the interface or a list of interfaces
++                            whose IP addresses should be used for dynamic DNS
++                            updates.
+                         </para>
+                         <para>
+-                            NOTE: This option currently supports only one interface.
++                            NOTE: This option currently supports multiple interfaces.
+                         </para>
+                         <para>
+                             NOTE: While it is still possible to use the old
+@@ -181,6 +182,9 @@
+                         <para>
+                             Default: Use the IP address of the IPA LDAP connection
+                         </para>
++                        <para>
++                            Example: dyndns_iface = em1, vnet1, vnet2
++                        </para>
+                     </listitem>
+                 </varlistentry>
+ 
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 2ac43a108ff6197d9e2662198a6da976ca348e76..76562840ef1d427629e41617b871caaedab779d4 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -49,6 +49,12 @@ struct sss_iface_addr {
+     struct sockaddr_storage *addr;
+ };
+ 
++void sss_iface_addr_concatenate(struct sss_iface_addr **list,
++                                struct sss_iface_addr *list2)
++{
++    DLIST_CONCATENATE((*list), list2, struct sss_iface_addr*);
++}
++
+ struct sss_iface_addr *
+ sss_iface_addr_add(TALLOC_CTX *mem_ctx, struct sss_iface_addr **list,
+                    struct sockaddr_storage *ss)
+diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h
+index 23b833dace58a0ecbb1e2e21963a55186f1d06a8..deba112538ad22cd7f59be07934778ee9d4361e7 100644
+--- a/src/providers/dp_dyndns.h
++++ b/src/providers/dp_dyndns.h
+@@ -128,4 +128,8 @@ nsupdate_get_addrs_recv(struct tevent_req *req,
+                         struct sss_iface_addr **_addrlist,
+                         size_t *_count);
+ 
++void
++sss_iface_addr_concatenate(struct sss_iface_addr **list,
++                           struct sss_iface_addr *list2);
++
+ #endif /* DP_DYNDNS_H_ */
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index e99a4f6687035928f6775c38b9df6b2a06d38f38..f5929cff3db6f724efcedeb963e3a12d04f6e1d3 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -482,6 +482,65 @@ static void sdap_dyndns_get_addrs_done(struct tevent_req *subreq);
+ static errno_t sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state,
+                                          struct sdap_handle *sh);
+ 
++static errno_t get_ifaces_addrs(TALLOC_CTX *mem_ctx,
++                                const char *iface,
++                                struct sss_iface_addr **_result)
++{
++    struct sss_iface_addr *result_addrs = NULL;
++    struct sss_iface_addr *intf_addrs;
++    TALLOC_CTX *tmp_ctx;
++    char **list_of_intfs;
++    int num_of_intfs;
++    errno_t ret;
++    int i;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = split_on_separator(tmp_ctx, iface, ',', true, true, &list_of_intfs,
++                             &num_of_intfs);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "Parsing names of interfaces failed - %d:[%s].\n",
++              ret, sss_strerror(ret));
++        goto done;
++    }
++
++    for (i = 0; i < num_of_intfs; i++) {
++        ret = sss_iface_addr_list_get(tmp_ctx, list_of_intfs[i], &intf_addrs);
++        if (ret == EOK) {
++            if (result_addrs != NULL) {
++                /* If there is already an existing list, head of this existing
++                 * list will be considered as parent talloc context for the
++                 * new list.
++                 */
++                talloc_steal(result_addrs, intf_addrs);
++            }
++            sss_iface_addr_concatenate(&result_addrs, intf_addrs);
++        } else if (ret == ENOENT) {
++            /* non-critical failure */
++            DEBUG(SSSDBG_TRACE_FUNC,
++                  "Cannot get interface %s or there are no addresses "
++                  "bind to it.\n", list_of_intfs[i]);
++        } else {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "Cannot get list of addresses from interface %s - %d:[%s]\n",
++                  list_of_intfs[i], ret, sss_strerror(ret));
++            goto done;
++        }
++    }
++
++    ret = EOK;
++    *_result = talloc_steal(mem_ctx, result_addrs);
++
++done:
++    talloc_free(tmp_ctx);
++    return ret;
++}
++
+ static struct tevent_req *
+ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx,
+                            struct tevent_context *ev,
+@@ -500,14 +559,11 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx,
+     }
+ 
+     if (iface) {
+-        ret = sss_iface_addr_list_get(state, iface, &state->addresses);
+-        if (ret != EOK) {
+-            DEBUG(ret == ENOENT ? SSSDBG_MINOR_FAILURE : SSSDBG_OP_FAILURE,
+-                  "Cannot get list of addresses from interface %s\n", iface);
+-            /* non critical failure */
+-            if (ret == ENOENT) {
+-                ret = EOK;
+-            }
++        ret = get_ifaces_addrs(state, iface, &state->addresses);
++        if (ret != EOK || state->addresses == NULL) {
++            DEBUG(SSSDBG_MINOR_FAILURE,
++                  "get_ifaces_addrs() failed: %d:[%s]\n",
++                  ret, sss_strerror(ret));
+         }
+         /* We're done. Just fake an async request completion */
+         goto done;
+-- 
+2.4.3
+
diff --git a/SOURCES/0016-Fix-debug-messages-trailing.patch b/SOURCES/0016-Fix-debug-messages-trailing.patch
deleted file mode 100644
index 1812d97..0000000
--- a/SOURCES/0016-Fix-debug-messages-trailing.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From e66b32e80303ae40afb282f6e52962303a23e5f5 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Tue, 21 Oct 2014 13:41:17 +0100
-Subject: [PATCH 16/22] Fix debug messages - trailing '.'
-
-Fix debug messages where '\n' was wrongly followed by '.'.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/db/sysdb_views.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index 926cd847c8dd8ddc33c0b517642a11bbe78059b5..a42aa96ed3e0cd7c877ff0c42887ef3f03ef5e0e 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -721,7 +721,7 @@ static errno_t sysdb_search_override_by_name(TALLOC_CTX *mem_ctx,
-         goto done;
-     } else if (override_res->count > 1) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
--              "Found more than one override for name [%s]\n.", name);
-+              "Found more than one override for name [%s].\n", name);
-         ret = EINVAL;
-         goto done;
-     }
-@@ -878,7 +878,7 @@ static errno_t sysdb_search_override_by_id(TALLOC_CTX *mem_ctx,
-         goto done;
-     } else if (override_res->count > 1) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
--              "Found more than one override for id [%lu]\n.", id);
-+              "Found more than one override for id [%lu].\n", id);
-         ret = EINVAL;
-         goto done;
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0017-DYNDNS-special-value-for-dyndns_iface-option.patch b/SOURCES/0017-DYNDNS-special-value-for-dyndns_iface-option.patch
new file mode 100644
index 0000000..c7f7abc
--- /dev/null
+++ b/SOURCES/0017-DYNDNS-special-value-for-dyndns_iface-option.patch
@@ -0,0 +1,107 @@
+From 65976fe3f9db1fc9581bb00060be38c48512b672 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Tue, 14 Jul 2015 04:21:34 -0400
+Subject: [PATCH 17/19] DYNDNS: special value '*' for dyndns_iface option
+
+Option dyndns_iface has now special value '*' which implies that IPs
+from add interfaces should be sent during DDNS update.
+---
+ src/man/sssd-ad.5.xml     |  6 ++++--
+ src/man/sssd-ipa.5.xml    |  9 ++++-----
+ src/providers/dp_dyndns.c | 20 ++++++++++++++++----
+ 3 files changed, 24 insertions(+), 11 deletions(-)
+
+diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
+index ff43ea37066514a87934d07b141e680416dcc05b..3cbc10520098372d984d00425d03832d002d6672 100644
+--- a/src/man/sssd-ad.5.xml
++++ b/src/man/sssd-ad.5.xml
+@@ -756,10 +756,12 @@ ad_gpo_map_deny = +my_pam_service
+                             Optional. Applicable only when dyndns_update
+                             is true. Choose the interface or a list of interfaces
+                             whose IP addresses should be used for dynamic DNS
+-                            updates.
++                            updates. Special value <quote>*</quote> implies that
++                            IPs from all interfaces should be used.
+                         </para>
+                         <para>
+-                            Default: Use the IP address of the AD LDAP connection
++                            Default: Use the IP addresses of the interface which
++                            is used for AD LDAP connection
+                         </para>
+                         <para>
+                             Example: dyndns_iface = em1, vnet1, vnet2
+diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
+index d450c2fadbb1713096ff766bf536702195cfd137..2e985991fde10827aff0e7c8e67f29a009683450 100644
+--- a/src/man/sssd-ipa.5.xml
++++ b/src/man/sssd-ipa.5.xml
+@@ -168,10 +168,8 @@
+                             Optional. Applicable only when dyndns_update
+                             is true. Choose the interface or a list of interfaces
+                             whose IP addresses should be used for dynamic DNS
+-                            updates.
+-                        </para>
+-                        <para>
+-                            NOTE: This option currently supports multiple interfaces.
++                            updates. Special value <quote>*</quote> implies that
++                            IPs from all interfaces should be used.
+                         </para>
+                         <para>
+                             NOTE: While it is still possible to use the old
+@@ -180,7 +178,8 @@
+                             in their config file.
+                         </para>
+                         <para>
+-                            Default: Use the IP address of the IPA LDAP connection
++                            Default: Use the IP addresses of the interface which
++                            is used for IPA LDAP connection
+                         </para>
+                         <para>
+                             Example: dyndns_iface = em1, vnet1, vnet2
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 76562840ef1d427629e41617b871caaedab779d4..03389acfba13e566540ca8b0570c0d009173575f 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -42,6 +42,9 @@
+ #define DYNDNS_TIMEOUT 15
+ #endif /* DYNDNS_TIMEOUT */
+ 
++/* MASK represents special value for matching all interfaces */
++#define MASK "*"
++
+ struct sss_iface_addr {
+     struct sss_iface_addr *next;
+     struct sss_iface_addr *prev;
+@@ -171,6 +174,16 @@ ok_for_dns(struct sockaddr *sa)
+     return true;
+ }
+ 
++static bool supported_address_family(sa_family_t sa_family)
++{
++    return sa_family == AF_INET || sa_family == AF_INET6;
++}
++
++static bool matching_name(const char *ifname, const char *ifname2)
++{
++    return (strcmp(MASK, ifname) == 0) || (strcasecmp(ifname, ifname2) == 0);
++}
++
+ /* Collect IP addresses associated with an interface */
+ errno_t
+ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname,
+@@ -200,10 +213,9 @@ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname,
+         if (!ifa->ifa_addr) continue;
+ 
+         /* Add IP addresses to the list */
+-        if ((ifa->ifa_addr->sa_family == AF_INET ||
+-             ifa->ifa_addr->sa_family == AF_INET6) &&
+-             strcasecmp(ifa->ifa_name, ifname) == 0 &&
+-             ok_for_dns(ifa->ifa_addr)) {
++        if (supported_address_family(ifa->ifa_addr->sa_family)
++                && matching_name(ifname, ifa->ifa_name)
++                && ok_for_dns(ifa->ifa_addr)) {
+ 
+             /* Add this address to the IP address list */
+             address = talloc_zero(mem_ctx, struct sss_iface_addr);
+-- 
+2.4.3
+
diff --git a/SOURCES/0017-IPA-Handle-NULL-members-in-process_members.patch b/SOURCES/0017-IPA-Handle-NULL-members-in-process_members.patch
deleted file mode 100644
index 1cdf793..0000000
--- a/SOURCES/0017-IPA-Handle-NULL-members-in-process_members.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 8eaafce7331a787bb2ae242eebe92ce8da342ca2 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 14 Oct 2014 14:15:25 +0200
-Subject: [PATCH 17/22] IPA: Handle NULL members in process_members()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index bd5c00b6a48018f8f904aaa03e8162425651b37a..2c31120b196353df52c87ef5b924a80bda134a17 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1196,6 +1196,11 @@ static errno_t process_members(struct sss_domain_info *domain,
-     struct sss_domain_info *obj_domain;
-     struct sss_domain_info *parent_domain;
- 
-+    if (members == NULL) {
-+        DEBUG(SSSDBG_TRACE_INTERNAL, "No members\n");
-+        return EOK;
-+    }
-+
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-@@ -1731,6 +1736,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                     goto done;
-                 }
-             }
-+            DEBUG(SSSDBG_TRACE_FUNC, "Processing group %s\n", name);
- 
-             ret = sysdb_attrs_add_lc_name_alias(attrs->sysdb_attrs, name);
-             if (ret != EOK) {
--- 
-1.9.3
-
diff --git a/SOURCES/0018-SPEC-Print-testsuite-log-for-failed-test.patch b/SOURCES/0018-SPEC-Print-testsuite-log-for-failed-test.patch
deleted file mode 100644
index 47f2cdc..0000000
--- a/SOURCES/0018-SPEC-Print-testsuite-log-for-failed-test.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 5662219fbd76c297b7137c1648fdb25e51777c92 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Thu, 16 Oct 2014 19:55:55 +0200
-Subject: [PATCH 18/22] SPEC: Print testsuite log for failed test
-
-Starting from Automake 1.13, the parallel testsuite harness has been made
-the default one; this harness is quite silent.
-
-VERBOSE=yes will displays the logs of the non-passed tests (i.e., only
-of the failed or skipped ones, or of the ones that passed unexpectedly).
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- contrib/sssd.spec.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
-index 74f7e950518841ec3cbd6e3fb4edf2eb873c7704..e5de4c44c4b4982f6819af363fdb8a32930f6137 100644
---- a/contrib/sssd.spec.in
-+++ b/contrib/sssd.spec.in
-@@ -467,7 +467,7 @@ make %{?_smp_mflags} docs
- 
- %check
- export CK_TIMEOUT_MULTIPLIER=10
--make %{?_smp_mflags} check
-+make %{?_smp_mflags} check VERBOSE=yes
- unset CK_TIMEOUT_MULTIPLIER
- 
- %install
--- 
-1.9.3
-
diff --git a/SOURCES/0018-TESTS-dyndns-tests-support-AAAA-addresses.patch b/SOURCES/0018-TESTS-dyndns-tests-support-AAAA-addresses.patch
new file mode 100644
index 0000000..aa8f434
--- /dev/null
+++ b/SOURCES/0018-TESTS-dyndns-tests-support-AAAA-addresses.patch
@@ -0,0 +1,130 @@
+From 73047b51048037689b21925f7d480ffd72a50485 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Wed, 15 Jul 2015 10:58:38 -0400
+Subject: [PATCH 18/19] TESTS: dyndns tests support AAAA addresses
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2558
+---
+ src/tests/cmocka/test_dyndns.c | 51 +++++++++++++++++++++++++++++++-----------
+ 1 file changed, 38 insertions(+), 13 deletions(-)
+
+diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c
+index 3214e90c063ea9a4cf6f6bc6507bf4e37b7d23a4..e9d42cea37472b38ae2eb900368f2ce3f409fefc 100644
+--- a/src/tests/cmocka/test_dyndns.c
++++ b/src/tests/cmocka/test_dyndns.c
+@@ -97,7 +97,9 @@ int __wrap_getifaddrs(struct ifaddrs **_ifap)
+     struct ifaddrs *ifap_head = NULL;
+     char *name;
+     char *straddr;
++    int ad_family;
+     struct sockaddr_in *sa;
++    void *dst;
+ 
+     while ((name = sss_mock_ptr_type(char *)) != NULL) {
+         straddr = sss_mock_ptr_type(char *);
+@@ -105,6 +107,7 @@ int __wrap_getifaddrs(struct ifaddrs **_ifap)
+             errno = EINVAL;
+             goto fail;
+         }
++        ad_family = sss_mock_type(int);
+ 
+         ifap = talloc_zero(global_mock_context, struct ifaddrs);
+         if (ifap == NULL) {
+@@ -127,15 +130,33 @@ int __wrap_getifaddrs(struct ifaddrs **_ifap)
+ 
+         /* Do not alocate directly on ifap->ifa_addr to
+          * avoid alignment warnings */
+-        sa = talloc(ifap, struct sockaddr_in);
++        if (ad_family == AF_INET) {
++            sa = talloc(ifap, struct sockaddr_in);
++        } else if (ad_family == AF_INET6) {
++            sa = (struct sockaddr_in *) talloc(ifap, struct sockaddr_in6);
++        } else {
++            errno = EINVAL;
++            goto fail;
++        }
++
+         if (sa == NULL) {
+             errno = ENOMEM;
+             goto fail;
+         }
+-        sa->sin_family = AF_INET;
++
++        sa->sin_family = ad_family;
++
++        if (ad_family == AF_INET) {
++            dst = &sa->sin_addr;
++        } else if (ad_family == AF_INET6) {
++            dst = &((struct sockaddr_in6 *)sa)->sin6_addr;
++        } else {
++            errno = EINVAL;
++            goto fail;
++        }
+ 
+         /* convert straddr into ifa_addr */
+-        if (inet_pton(AF_INET, straddr, &sa->sin_addr) != 1) {
++        if (inet_pton(ad_family, straddr, dst) != 1) {
+             goto fail;
+         }
+ 
+@@ -167,12 +188,16 @@ static void dyndns_test_done(struct tevent_req *req)
+     ctx->tctx->done = true;
+ }
+ 
+-void will_return_getifaddrs(const char *ifname, const char *straddr)
++void will_return_getifaddrs(const char *ifname, const char *straddr,
++                            int af_family)
+ {
+     will_return(__wrap_getifaddrs, ifname);
+     if (ifname) {
+         will_return(__wrap_getifaddrs, straddr);
+     }
++    if (straddr) {
++        will_return(__wrap_getifaddrs, af_family);
++    }
+ }
+ 
+ void dyndns_test_get_ifaddr(void **state)
+@@ -182,9 +207,9 @@ void dyndns_test_get_ifaddr(void **state)
+     char straddr[128];
+ 
+     check_leaks_push(dyndns_test_ctx);
+-    will_return_getifaddrs("eth0", "192.168.0.1");
+-    will_return_getifaddrs("eth1", "192.168.0.2");
+-    will_return_getifaddrs(NULL, NULL); /* sentinel */
++    will_return_getifaddrs("eth0", "192.168.0.1", AF_INET);
++    will_return_getifaddrs("eth1", "192.168.0.2", AF_INET);
++    will_return_getifaddrs(NULL, NULL, 0); /* sentinel */
+     ret = sss_iface_addr_list_get(dyndns_test_ctx, "eth0", &addrlist);
+     assert_int_equal(ret, EOK);
+ 
+@@ -212,9 +237,9 @@ void dyndns_test_get_multi_ifaddr(void **state)
+     char straddr[128];
+ 
+     check_leaks_push(dyndns_test_ctx);
+-    will_return_getifaddrs("eth0", "192.168.0.2");
+-    will_return_getifaddrs("eth0", "192.168.0.1");
+-    will_return_getifaddrs(NULL, NULL); /* sentinel */
++    will_return_getifaddrs("eth0", "192.168.0.2", AF_INET);
++    will_return_getifaddrs("eth0", "192.168.0.1", AF_INET);
++    will_return_getifaddrs(NULL, NULL, 0); /* sentinel */
+     ret = sss_iface_addr_list_get(dyndns_test_ctx, "eth0", &addrlist);
+     assert_int_equal(ret, EOK);
+ 
+@@ -253,9 +278,9 @@ void dyndns_test_get_ifaddr_enoent(void **state)
+     struct sss_iface_addr *addrlist = NULL;
+ 
+     check_leaks_push(dyndns_test_ctx);
+-    will_return_getifaddrs("eth0", "192.168.0.1");
+-    will_return_getifaddrs("eth1", "192.168.0.2");
+-    will_return_getifaddrs(NULL, NULL); /* sentinel */
++    will_return_getifaddrs("eth0", "192.168.0.1", AF_INET);
++    will_return_getifaddrs("eth1", "192.168.0.2", AF_INET);
++    will_return_getifaddrs(NULL, NULL, 0); /* sentinel */
+     ret = sss_iface_addr_list_get(dyndns_test_ctx, "non_existing_interface",
+                                   &addrlist);
+     assert_int_equal(ret, ENOENT);
+-- 
+2.4.3
+
diff --git a/SOURCES/0019-DYNDNS-support-for-dualstack.patch b/SOURCES/0019-DYNDNS-support-for-dualstack.patch
new file mode 100644
index 0000000..75f53f2
--- /dev/null
+++ b/SOURCES/0019-DYNDNS-support-for-dualstack.patch
@@ -0,0 +1,437 @@
+From 856cb96e313c164aa80915410ba758ad21cb6173 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Tue, 14 Jul 2015 09:56:59 -0400
+Subject: [PATCH 19/19] DYNDNS: support for dualstack
+
+When dyndns_iface option was not used, address of connection to LDAP
+was used. This patch proposes following change:
+  * Interface containing address of connection is found.
+  * All A and AAAA addresses of this interface are collected.
+  * Collected addresses are sent during DDNS update.
+  * Function sss_iface_addr_add() is removed.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2558
+---
+ src/providers/dp_dyndns.c        | 135 +++++++++++++++++++++++------
+ src/providers/dp_dyndns.h        |   8 +-
+ src/providers/ldap/sdap_dyndns.c |  20 ++---
+ src/tests/cmocka/test_dyndns.c   | 178 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 302 insertions(+), 39 deletions(-)
+
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 03389acfba13e566540ca8b0570c0d009173575f..c254d78936f412626db0533f559350de57017618 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -58,31 +58,6 @@ void sss_iface_addr_concatenate(struct sss_iface_addr **list,
+     DLIST_CONCATENATE((*list), list2, struct sss_iface_addr*);
+ }
+ 
+-struct sss_iface_addr *
+-sss_iface_addr_add(TALLOC_CTX *mem_ctx, struct sss_iface_addr **list,
+-                   struct sockaddr_storage *ss)
+-{
+-    struct sss_iface_addr *address;
+-
+-    address = talloc(mem_ctx, struct sss_iface_addr);
+-    if (address == NULL) {
+-        return NULL;
+-    }
+-
+-    address->addr = talloc_memdup(address, ss,
+-                                  sizeof(struct sockaddr_storage));
+-    if(address->addr == NULL) {
+-        talloc_zfree(address);
+-        return NULL;
+-    }
+-
+-    /* steal old dlist to the new head */
+-    talloc_steal(address, *list);
+-    DLIST_ADD(*list, address);
+-
+-    return address;
+-}
+-
+ errno_t
+ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx,
+                                 struct sss_iface_addr *ifaddr_list,
+@@ -1258,3 +1233,113 @@ errno_t be_nsupdate_init_timer(struct be_nsupdate_ctx *ctx,
+ 
+     return ERR_OK;
+ }
++
++static bool match_ip(const struct sockaddr *sa,
++                     const struct sockaddr *sb)
++{
++    size_t addrsize;
++    bool res;
++    const void *addr_a;
++    const void *addr_b;
++
++    if (sa->sa_family == AF_INET) {
++        addrsize = sizeof(struct in_addr);
++        addr_a = (const void *) &((const struct sockaddr_in *) sa)->sin_addr;
++        addr_b = (const void *) &((const struct sockaddr_in *) sb)->sin_addr;
++    } else if (sa->sa_family == AF_INET6) {
++        addrsize = sizeof(struct in6_addr);
++        addr_a = (const void *) &((const struct sockaddr_in6 *) sa)->sin6_addr;
++        addr_b = (const void *) &((const struct sockaddr_in6 *) sb)->sin6_addr;
++    } else {
++        res = false;
++        goto done;
++    }
++
++    if (sa->sa_family != sb->sa_family) {
++        res = false;
++        goto done;
++    }
++
++    res = memcmp(addr_a, addr_b, addrsize) == 0;
++
++done:
++    return res;
++}
++
++static errno_t find_iface_by_addr(TALLOC_CTX *mem_ctx,
++                                  const struct sockaddr *ss,
++                                  const char **_iface_name)
++{
++    struct ifaddrs *ifaces = NULL;
++    struct ifaddrs *ifa;
++    errno_t ret;
++
++    ret = getifaddrs(&ifaces);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Could not read interfaces [%d][%s]\n", ret, sss_strerror(ret));
++        goto done;
++    }
++
++    for (ifa = ifaces; ifa != NULL; ifa = ifa->ifa_next) {
++
++        /* Some interfaces don't have an ifa_addr */
++        if (!ifa->ifa_addr) continue;
++
++        if (match_ip(ss, ifa->ifa_addr)) {
++            const char *iface_name;
++            iface_name = talloc_strdup(mem_ctx, ifa->ifa_name);
++            if (iface_name == NULL) {
++                ret = ENOMEM;
++            } else {
++                *_iface_name = iface_name;
++                ret = EOK;
++            }
++            goto done;
++        }
++    }
++    ret = ENOENT;
++
++done:
++    freeifaddrs(ifaces);
++    return ret;
++}
++
++errno_t sss_get_dualstack_addresses(TALLOC_CTX *mem_ctx,
++                                    struct sockaddr *ss,
++                                    struct sss_iface_addr **_iface_addrs)
++{
++    struct sss_iface_addr *iface_addrs;
++    const char *iface_name = NULL;
++    TALLOC_CTX *tmp_ctx;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = find_iface_by_addr(tmp_ctx, ss, &iface_name);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_MINOR_FAILURE, "find_iface_by_addr failed: %d:[%s]\n",
++              ret, sss_strerror(ret));
++        goto done;
++    }
++
++    ret = sss_iface_addr_list_get(tmp_ctx, iface_name, &iface_addrs);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "sss_iface_addr_list_get failed: %d:[%s]\n",
++              ret, sss_strerror(ret));
++        goto done;
++    }
++
++    ret = EOK;
++    *_iface_addrs = talloc_steal(mem_ctx, iface_addrs);
++
++done:
++    talloc_free(tmp_ctx);
++    return ret;
++}
+diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h
+index deba112538ad22cd7f59be07934778ee9d4361e7..a8a20ec6f8a1a63cd8c85aaec3f54f9fddb42049 100644
+--- a/src/providers/dp_dyndns.h
++++ b/src/providers/dp_dyndns.h
+@@ -81,10 +81,6 @@ errno_t
+ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname,
+                         struct sss_iface_addr **_addrlist);
+ 
+-struct sss_iface_addr *
+-sss_iface_addr_add(TALLOC_CTX *mem_ctx, struct sss_iface_addr **list,
+-                   struct sockaddr_storage *ss);
+-
+ errno_t
+ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx,
+                                 struct sss_iface_addr *ifaddr_list,
+@@ -132,4 +128,8 @@ void
+ sss_iface_addr_concatenate(struct sss_iface_addr **list,
+                            struct sss_iface_addr *list2);
+ 
++errno_t
++sss_get_dualstack_addresses(TALLOC_CTX *mem_ctx,
++                            struct sockaddr *ss,
++                            struct sss_iface_addr **_iface_addrs);
+ #endif /* DP_DYNDNS_H_ */
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index f5929cff3db6f724efcedeb963e3a12d04f6e1d3..a463a2fce08f42b325010cd37c501ef23aee173f 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -644,7 +644,6 @@ sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state,
+ {
+     int ret;
+     int fd;
+-    struct sss_iface_addr *address;
+     struct sockaddr_storage ss;
+     socklen_t ss_len = sizeof(ss);
+ 
+@@ -666,20 +665,21 @@ sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state,
+         return ret;
+     }
+ 
+-    switch(ss.ss_family) {
+-    case AF_INET:
+-    case AF_INET6:
+-        address = sss_iface_addr_add(state, &state->addresses, &ss);
+-        if (address == NULL) {
+-            return ENOMEM;
+-        }
+-        break;
+-    default:
++    if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) {
+         DEBUG(SSSDBG_CRIT_FAILURE,
+               "Connection to LDAP is neither IPv4 nor IPv6\n");
+         return EIO;
+     }
+ 
++    ret = sss_get_dualstack_addresses(state, (struct sockaddr *) &ss,
++                                      &state->addresses);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "sss_get_dualstack_addresses failed: %d:[%s]\n",
++              ret, sss_strerror(ret));
++        return ret;
++    }
++
+     return EOK;
+ }
+ 
+diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c
+index e9d42cea37472b38ae2eb900368f2ce3f409fefc..8118e9438e89465674155c11f4523d2313f6a59c 100644
+--- a/src/tests/cmocka/test_dyndns.c
++++ b/src/tests/cmocka/test_dyndns.c
+@@ -289,6 +289,173 @@ void dyndns_test_get_ifaddr_enoent(void **state)
+     assert_true(check_leaks_pop(dyndns_test_ctx) == true);
+ }
+ 
++void dyndns_test_dualstack(void **state)
++{
++    errno_t ret;
++    struct sss_iface_addr *addrlist;
++    struct sss_iface_addr *sss_if_addrs;
++    char straddr[128];
++    int i;
++
++    check_leaks_push(dyndns_test_ctx);
++
++    /* getifaddrs is called twice in sss_get_dualstack_addresses() */
++    for (i = 0; i < 2; i++) {
++        will_return_getifaddrs("eth0", "192.168.0.2", AF_INET);
++        will_return_getifaddrs("eth1", "192.168.0.1", AF_INET);
++        will_return_getifaddrs("eth0", "2001:cdba::555", AF_INET6);
++        will_return_getifaddrs("eth1", "2001:cdba::444", AF_INET6);
++        will_return_getifaddrs(NULL, NULL, 0); /* sentinel */
++    }
++
++    struct sockaddr_in sin;
++    memset (&sin, 0, sizeof (sin));
++    sin.sin_family = AF_INET;
++    sin.sin_addr.s_addr = inet_addr ("192.168.0.2");
++    ret = sss_get_dualstack_addresses(dyndns_test_ctx,
++                                      (struct sockaddr *) &sin,
++                                      &addrlist);
++    assert_int_equal(ret, EOK);
++
++    sss_if_addrs = addrlist;
++    assert_non_null(sss_if_addrs);
++    assert_non_null(sss_if_addrs->addr);
++    assert_non_null(sss_if_addrs->next);
++    assert_null(sss_if_addrs->prev);
++
++    assert_non_null(inet_ntop(AF_INET6,
++                              &((struct sockaddr_in6 *) sss_if_addrs->addr)->sin6_addr,
++                              straddr, INET6_ADDRSTRLEN));
++    /* ip addresses are returned in different order */
++    assert_string_equal(straddr, "2001:cdba::555");
++
++    sss_if_addrs = addrlist->next;
++    assert_non_null(sss_if_addrs);
++    assert_non_null(sss_if_addrs->addr);
++    assert_null(sss_if_addrs->next);
++    assert_non_null(sss_if_addrs->prev);
++
++    assert_non_null(inet_ntop(AF_INET,
++                              &((struct sockaddr_in *) sss_if_addrs->addr)->sin_addr,
++                              straddr, INET_ADDRSTRLEN));
++    /* ip addresses are returned in different order */
++    assert_string_equal(straddr, "192.168.0.2");
++
++    talloc_free(addrlist);
++
++    assert_true(check_leaks_pop(dyndns_test_ctx) == true);
++}
++
++void dyndns_test_dualstack_multiple_addresses(void **state)
++{
++    errno_t ret;
++    struct sss_iface_addr *addrlist;
++    struct sss_iface_addr *sss_if_addrs;
++    char straddr[128];
++    int i;
++
++    check_leaks_push(dyndns_test_ctx);
++
++    /* getifaddrs is called twice in sss_get_dualstack_addresses() */
++    for (i = 0; i < 2; i++) {
++        will_return_getifaddrs("eth0", "192.168.0.2", AF_INET);
++        will_return_getifaddrs("eth0", "192.168.0.1", AF_INET);
++        /* loopback - invalid for dns (should be skipped) */
++        will_return_getifaddrs("eth0", "::1", AF_INET6);
++        /* linklocal - invalid for dns (should be skipped) */
++        will_return_getifaddrs("eth0", "fe80::5054:ff:fe4a:65ae", AF_INET6);
++        will_return_getifaddrs("eth0", "2001:cdba::555", AF_INET6);
++        will_return_getifaddrs("eth0", "2001:cdba::444", AF_INET6);
++        will_return_getifaddrs(NULL, NULL, 0); /* sentinel */
++    }
++
++    struct sockaddr_in sin;
++    memset (&sin, 0, sizeof (sin));
++    sin.sin_family = AF_INET;
++    sin.sin_addr.s_addr = inet_addr ("192.168.0.2");
++    ret = sss_get_dualstack_addresses(dyndns_test_ctx,
++                                      (struct sockaddr *) &sin,
++                                      &addrlist);
++    assert_int_equal(ret, EOK);
++
++    sss_if_addrs = addrlist;
++    assert_non_null(sss_if_addrs);
++    assert_non_null(sss_if_addrs->addr);
++    assert_non_null(sss_if_addrs->next);
++    assert_null(sss_if_addrs->prev);
++
++    assert_non_null(inet_ntop(AF_INET6,
++                              &((struct sockaddr_in6 *) sss_if_addrs->addr)->sin6_addr,
++                              straddr, INET6_ADDRSTRLEN));
++    /* ip addresses are returned in different order */
++    assert_string_equal(straddr, "2001:cdba::444");
++
++    sss_if_addrs = sss_if_addrs->next;
++    assert_non_null(sss_if_addrs);
++    assert_non_null(sss_if_addrs->addr);
++    assert_non_null(sss_if_addrs->prev);
++    assert_non_null(sss_if_addrs->next);
++
++    assert_non_null(inet_ntop(AF_INET6,
++                              &((struct sockaddr_in6 *) sss_if_addrs->addr)->sin6_addr,
++                              straddr, INET6_ADDRSTRLEN));
++    /* ip addresses are returned in different order */
++    assert_string_equal(straddr, "2001:cdba::555");
++
++    sss_if_addrs = sss_if_addrs->next;
++    assert_non_null(sss_if_addrs);
++    assert_non_null(sss_if_addrs->addr);
++    assert_non_null(sss_if_addrs->next);
++    assert_non_null(sss_if_addrs->prev);
++
++    assert_non_null(inet_ntop(AF_INET,
++                              &((struct sockaddr_in *) sss_if_addrs->addr)->sin_addr,
++                              straddr, INET_ADDRSTRLEN));
++    /* ip addresses are returned in different order */
++    assert_string_equal(straddr, "192.168.0.1");
++
++    sss_if_addrs = sss_if_addrs->next;
++    assert_non_null(sss_if_addrs);
++    assert_non_null(sss_if_addrs->addr);
++    assert_null(sss_if_addrs->next);
++    assert_non_null(sss_if_addrs->prev);
++
++    assert_non_null(inet_ntop(AF_INET,
++                              &((struct sockaddr_in *) sss_if_addrs->addr)->sin_addr,
++                              straddr, INET_ADDRSTRLEN));
++    /* ip addresses are returned in different order */
++    assert_string_equal(straddr, "192.168.0.2");
++
++    talloc_free(addrlist);
++
++    assert_true(check_leaks_pop(dyndns_test_ctx) == true);
++}
++
++void dyndns_test_dualstack_no_iface(void **state)
++{
++    errno_t ret;
++    struct sss_iface_addr *addrlist;
++
++    check_leaks_push(dyndns_test_ctx);
++
++    will_return_getifaddrs("eth0", "192.168.0.2", AF_INET);
++    will_return_getifaddrs("eth1", "192.168.0.1", AF_INET);
++    will_return_getifaddrs("eth0", "2001:cdba::555", AF_INET6);
++    will_return_getifaddrs("eth1", "2001:cdba::444", AF_INET6);
++    will_return_getifaddrs(NULL, NULL, 0); /* sentinel */
++
++    struct sockaddr_in sin;
++    memset (&sin, 0, sizeof (sin));
++    sin.sin_family = AF_INET;
++    sin.sin_addr.s_addr = inet_addr ("192.168.0.3");
++    ret = sss_get_dualstack_addresses(dyndns_test_ctx,
++                                      (struct sockaddr *) &sin,
++                                      &addrlist);
++    assert_int_equal(ret, ENOENT);
++
++    assert_true(check_leaks_pop(dyndns_test_ctx) == true);
++}
++
+ void dyndns_test_ok(void **state)
+ {
+     struct tevent_req *req;
+@@ -519,6 +686,17 @@ int main(int argc, const char *argv[])
+         cmocka_unit_test_setup_teardown(dyndns_test_interval,
+                                         dyndns_test_setup,
+                                         dyndns_test_teardown),
++
++        /* Dynamic DNS dualstack unit tests*/
++        cmocka_unit_test_setup_teardown(dyndns_test_dualstack,
++                                        dyndns_test_simple_setup,
++                                        dyndns_test_teardown),
++        cmocka_unit_test_setup_teardown(dyndns_test_dualstack_multiple_addresses,
++                                        dyndns_test_simple_setup,
++                                        dyndns_test_teardown),
++        cmocka_unit_test_setup_teardown(dyndns_test_dualstack_no_iface,
++                                        dyndns_test_simple_setup,
++                                        dyndns_test_teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+-- 
+2.4.3
+
diff --git a/SOURCES/0019-MAN-PAGE-modified-sssd-ldap.5.xml-for-sssd-ticket-24.patch b/SOURCES/0019-MAN-PAGE-modified-sssd-ldap.5.xml-for-sssd-ticket-24.patch
deleted file mode 100644
index c611e9b..0000000
--- a/SOURCES/0019-MAN-PAGE-modified-sssd-ldap.5.xml-for-sssd-ticket-24.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From ad51468ac53ff073efeaf28733b596004433721d Mon Sep 17 00:00:00 2001
-From: Dan Lavu <dlavu@redhat.com>
-Date: Mon, 13 Oct 2014 15:06:53 -0400
-Subject: [PATCH 19/22] MAN PAGE: modified sssd-ldap.5.xml for sssd ticket
- #2451
-
-https://fedorahosted.org/sssd/ticket/2451
-
-Added a configuration example at the bottom for
-'ldap_access_order = lockout'. Also added a line
-to note that 'ldap_access_provider = ldap' must
-be specified for this feature to work.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/man/sssd-ldap.5.xml | 26 +++++++++++++++++++++++++-
- 1 file changed, 25 insertions(+), 1 deletion(-)
-
-diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
-index a21ffc12986c4af10f4c0a5950eb43b88dac9d47..9a9410b415a7419ee303aea6ec2f9f3d41509647 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -1449,7 +1449,7 @@
-                     <listitem>
-                         <para>
-                             Specifies acceptable cipher suites.  Typically this
--                            is a colon sperated list.  See 
-+                            is a colon sperated list.  See
-                             <citerefentry><refentrytitle>ldap.conf</refentrytitle>
-                             <manvolnum>5</manvolnum></citerefentry> for format.
-                         </para>
-@@ -1922,6 +1922,9 @@ ldap_access_filter = (employeeType=admin)
-                             attribute 'pwdAccountLockedTime' is present and has
-                             value of '000001010000Z'. Please see the option
-                             ldap_pwdlockout_dn.
-+
-+                            Please note that 'access_provider = ldap' must
-+                            be set for this feature to work.
-                         </para>
-                         <para>
-                             <emphasis>expire</emphasis>: use
-@@ -2491,6 +2494,27 @@ ldap_access_filter = (employeeType=admin)
- </programlisting>
-         </para>
-     </refsect1>
-+    <refsect1 id='ldap_access_filter_example'>
-+        <title>LDAP ACCESS FILTER EXAMPLE</title>
-+        <para>
-+            The following example assumes that SSSD is correctly
-+            configured and to use the ldap_access_order=lockout.
-+        </para>
-+        <para>
-+<programlisting>
-+    [domain/LDAP]
-+    id_provider = ldap
-+    auth_provider = ldap
-+    access_provider = ldap
-+    ldap_access_order = lockout
-+    ldap_pwdlockout_dn = cn=ppolicy,ou=policies,dc=mydomain,dc=org
-+    ldap_uri = ldap://ldap.mydomain.org
-+    ldap_search_base = dc=mydomain,dc=org
-+    ldap_tls_reqcert = demand
-+    cache_credentials = true
-+</programlisting>
-+        </para>
-+    </refsect1>
- 
-     <refsect1 id='notes'>
-         <title>NOTES</title>
--- 
-1.9.3
-
diff --git a/SOURCES/0020-NSS-Possibility-to-use-any-shells-in-allowed_shells.patch b/SOURCES/0020-NSS-Possibility-to-use-any-shells-in-allowed_shells.patch
deleted file mode 100644
index 9007059..0000000
--- a/SOURCES/0020-NSS-Possibility-to-use-any-shells-in-allowed_shells.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 96f96e74926f48ae5a023af9bed36ba813a7d024 Mon Sep 17 00:00:00 2001
-From: Denis Kutin <dekutin@ya.ru>
-Date: Sat, 16 Nov 2013 16:48:21 +0400
-Subject: [PATCH 20/22] NSS: Possibility to use any shells in 'allowed_shells'
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2219
-
-Signed-off-by: Pavel Reichl <preichl@redhat.com>
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/man/sssd.conf.5.xml        | 10 ++++++++++
- src/responder/nss/nsssrv_cmd.c | 19 +++++++++++++------
- 2 files changed, 23 insertions(+), 6 deletions(-)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index d5734166144a7c3ce7e62914558f8e69121bf774..77690432b841221328d65403830cf4a1ac12dba0 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -617,6 +617,16 @@ fallback_homedir = /home/%u
-                             is used.
-                         </para>
-                         <para>
-+                            The wildcard (*) can be used to allow any shell.
-+                        </para>
-+                        <para>
-+                            The (*) is useful if you want to use
-+                            shell_fallback in case that user's shell is not
-+                            in <quote>/etc/shells</quote> and maintaining list
-+                            of all allowed shells in allowed_shells would be
-+                            to much overhead.
-+                        </para>
-+                        <para>
-                             An empty string for shell is passed as-is to libc.
-                         </para>
-                         <para>
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index 616f83dda58b11bb7b715e1eb6a2c43e91d2d9da..4ec99c153b25db26d482eec8da6ca52487967abc 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -284,12 +284,19 @@ static const char *get_shell_override(TALLOC_CTX *mem_ctx,
-     }
- 
-     if (nctx->allowed_shells) {
--        for (i=0; nctx->allowed_shells[i]; i++) {
--            if (strcmp(nctx->allowed_shells[i], user_shell) == 0) {
--                DEBUG(SSSDBG_FUNC_DATA,
--                      "The shell '%s' is allowed but does not exist. "
--                        "Using fallback\n", user_shell);
--                return talloc_strdup(mem_ctx, nctx->shell_fallback);
-+        if (strcmp(nctx->allowed_shells[0], "*") == 0) {
-+            DEBUG(SSSDBG_FUNC_DATA,
-+                  "The shell '%s' is allowed but does not exist. "
-+                  "Using fallback\n", user_shell);
-+            return talloc_strdup(mem_ctx, nctx->shell_fallback);
-+        } else {
-+            for (i=0; nctx->allowed_shells[i]; i++) {
-+                if (strcmp(nctx->allowed_shells[i], user_shell) == 0) {
-+                    DEBUG(SSSDBG_FUNC_DATA,
-+                          "The shell '%s' is allowed but does not exist. "
-+                          "Using fallback\n", user_shell);
-+                    return talloc_strdup(mem_ctx, nctx->shell_fallback);
-+                }
-             }
-         }
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0020-VIEWS-TEST-add-null-check.patch b/SOURCES/0020-VIEWS-TEST-add-null-check.patch
new file mode 100644
index 0000000..912c030
--- /dev/null
+++ b/SOURCES/0020-VIEWS-TEST-add-null-check.patch
@@ -0,0 +1,53 @@
+From 681fd36964b873135b2b8dd5200ddcfd1e420214 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Mon, 27 Jul 2015 17:24:45 +0200
+Subject: [PATCH 20/23] VIEWS TEST: add null-check
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/tests/cmocka/test_sysdb_views.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
+index 1fb598219e9ee581e465ddbb32ba9f2544600c26..123d4c5cb613f41e1bca9e89feed701a1e86f8d3 100644
+--- a/src/tests/cmocka/test_sysdb_views.c
++++ b/src/tests/cmocka/test_sysdb_views.c
+@@ -225,10 +225,12 @@ void test_sysdb_add_overrides_to_object(void **state)
+     assert_non_null(orig);
+ 
+     tmp_str = talloc_strdup(orig,  "ORIGNAME");
++    assert_non_null(tmp_str);
+     ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str);
+     assert_int_equal(ret, EOK);
+ 
+     tmp_str = talloc_strdup(orig,  "ORIGGECOS");
++    assert_non_null(tmp_str);
+     ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str);
+     assert_int_equal(ret, EOK);
+ 
+@@ -236,18 +238,22 @@ void test_sysdb_add_overrides_to_object(void **state)
+     assert_non_null(override);
+ 
+     tmp_str = talloc_strdup(override, "OVERRIDENAME");
++    assert_non_null(tmp_str);
+     ret = ldb_msg_add_string(override, SYSDB_NAME, tmp_str);
+     assert_int_equal(ret, EOK);
+ 
+     tmp_str = talloc_strdup(override, "OVERRIDEGECOS");
++    assert_non_null(tmp_str);
+     ret = ldb_msg_add_string(override, SYSDB_GECOS, tmp_str);
+     assert_int_equal(ret, EOK);
+ 
+     tmp_str = talloc_strdup(override, "OVERRIDEKEY1");
++    assert_non_null(tmp_str);
+     ret = ldb_msg_add_string(override, SYSDB_SSH_PUBKEY, tmp_str);
+     assert_int_equal(ret, EOK);
+ 
+     tmp_str = talloc_strdup(override, "OVERRIDEKEY2");
++    assert_non_null(tmp_str);
+     ret = ldb_msg_add_string(override, SYSDB_SSH_PUBKEY, tmp_str);
+     assert_int_equal(ret, EOK);
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0021-GPO-Terminate-request-on-error.patch b/SOURCES/0021-GPO-Terminate-request-on-error.patch
deleted file mode 100644
index c087e3e..0000000
--- a/SOURCES/0021-GPO-Terminate-request-on-error.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From f979db8ea926cd51093a0f2406ddfc49540b392e Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 21 Oct 2014 16:18:02 +0200
-Subject: [PATCH 21/22] GPO: Terminate request on error
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/providers/ad/ad_gpo.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 3f5df75c5a9de53eac11ffcf785e929cf9b3165e..4dfbd4b6943b477bd93fdd730dfa5b1c5828a10a 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -3954,11 +3954,13 @@ static void gpo_cse_done(struct tevent_req *subreq)
-               "ad_gpo_parse_gpo_child_response failed: [%d][%s]\n",
-               ret, strerror(ret));
-         tevent_req_error(req, ret);
-+        return;
-     } else if (child_result != 0){
-         DEBUG(SSSDBG_CRIT_FAILURE,
-               "Error in gpo_child: [%d][%s]\n",
-               child_result, strerror(child_result));
-         tevent_req_error(req, child_result);
-+        return;
-     }
- 
-     now = time(NULL);
--- 
-1.9.3
-
diff --git a/SOURCES/0021-SYSDB-prepare-for-LOCAL-view.patch b/SOURCES/0021-SYSDB-prepare-for-LOCAL-view.patch
new file mode 100644
index 0000000..43ac1e7
--- /dev/null
+++ b/SOURCES/0021-SYSDB-prepare-for-LOCAL-view.patch
@@ -0,0 +1,177 @@
+From ea6cfe4e1d7c84370bfcc86251ea10b2658b52d3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Fri, 24 Jul 2015 09:55:28 +0200
+Subject: [PATCH 21/23] SYSDB: prepare for LOCAL view
+
+Objects doesn't have to have overrideDN specified when using LOCAL view.
+Since the view is not stored on the server we do not want to contact
+LDAP therefore we special case LOCAL view saying that it is OK that
+this attribute is missing.
+
+Preparation for:
+https://fedorahosted.org/sssd/ticket/2584
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/db/sysdb.h                      | 14 +++++++-
+ src/db/sysdb_views.c                |  7 ++++
+ src/providers/ipa/ipa_subdomains.c  |  3 +-
+ src/tests/cmocka/test_sysdb_views.c | 66 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 88 insertions(+), 2 deletions(-)
+
+diff --git a/src/db/sysdb.h b/src/db/sysdb.h
+index 0f745ccb1a646d77ba4ad3d714d5f4dce0a51211..9e28b5c6691f3710e3051d9746ac5fa47aff8424 100644
+--- a/src/db/sysdb.h
++++ b/src/db/sysdb.h
+@@ -157,9 +157,10 @@
+ #define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires"
+ #define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl"
+ 
++#define SYSDB_DEFAULT_VIEW_NAME "default"
++#define SYSDB_LOCAL_VIEW_NAME "LOCAL" /* reserved for client-side overrides */
+ #define SYSDB_VIEW_CLASS "view"
+ #define SYSDB_VIEW_NAME "viewName"
+-#define SYSDB_DEFAULT_VIEW_NAME "default"
+ #define SYSDB_OVERRIDE_CLASS "overrride"
+ #define SYSDB_OVERRIDE_ANCHOR_UUID "overrideAnchorUUID"
+ #define SYSDB_OVERRIDE_USER_CLASS "userOverride"
+@@ -473,6 +474,17 @@ static inline bool is_default_view(const char *view_name)
+     }
+ }
+ 
++static inline bool is_local_view(const char *view_name)
++{
++    /* NULL is treated as default */
++    if (view_name != NULL
++            && strcmp(view_name, SYSDB_LOCAL_VIEW_NAME) == 0) {
++        return true;
++    } else {
++        return false;
++    }
++}
++
+ errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name);
+ 
+ errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb);
+diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
+index aadd6018f4d1e2ca33e2e00dd8b13b55a8c03f3e..1db6c892de9e4764b673608166830800744b1148 100644
+--- a/src/db/sysdb_views.c
++++ b/src/db/sysdb_views.c
+@@ -1186,9 +1186,16 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
+         override_dn_str = ldb_msg_find_attr_as_string(obj,
+                                                       SYSDB_OVERRIDE_DN, NULL);
+         if (override_dn_str == NULL) {
++            if (is_local_view(domain->view_name)) {
++                /* LOCAL view doesn't have to have overrideDN specified. */
++                ret = EOK;
++                goto done;
++            }
++
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "Missing override DN for objext [%s].\n",
+                   ldb_dn_get_linearized(obj->dn));
++
+             ret = ENOENT;
+             goto done;
+         }
+diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
+index cf72784473747c67d44a5d887faf867cfe62ce2b..cec8b3918b8f832e2c7376a867448fe876da6ffc 100644
+--- a/src/providers/ipa/ipa_subdomains.c
++++ b/src/providers/ipa/ipa_subdomains.c
+@@ -905,7 +905,8 @@ static void ipa_get_view_name_done(struct tevent_req *req)
+                     goto done;
+                 }
+ 
+-                if (!is_default_view(ctx->sd_ctx->id_ctx->view_name)) {
++                if (!is_default_view(ctx->sd_ctx->id_ctx->view_name)
++                        && !is_local_view(ctx->sd_ctx->id_ctx->view_name)) {
+                     /* Old view was not the default view, delete view tree */
+                     ret = sysdb_delete_view_tree(
+                                              ctx->sd_ctx->be_ctx->domain->sysdb,
+diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
+index 123d4c5cb613f41e1bca9e89feed701a1e86f8d3..83007b76a625edef67109850648b2d71645e22bb 100644
+--- a/src/tests/cmocka/test_sysdb_views.c
++++ b/src/tests/cmocka/test_sysdb_views.c
+@@ -281,6 +281,68 @@ void test_sysdb_add_overrides_to_object(void **state)
+     assert_int_equal(ldb_val_string_cmp(&el->values[1], "OVERRIDEKEY2"), 0);
+ }
+ 
++void test_sysdb_add_overrides_to_object_local(void **state)
++{
++    int ret;
++    struct ldb_message *orig;
++    struct ldb_message_element *el;
++    char *tmp_str;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                         struct sysdb_test_ctx);
++
++    orig = ldb_msg_new(test_ctx);
++    assert_non_null(orig);
++
++    tmp_str = talloc_strdup(orig,  "ORIGNAME");
++    assert_non_null(tmp_str);
++    ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str);
++    assert_int_equal(ret, EOK);
++
++    tmp_str = talloc_strdup(orig,  "ORIGGECOS");
++    assert_non_null(tmp_str);
++    ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str);
++    assert_int_equal(ret, EOK);
++
++    test_ctx->domain->has_views = true;
++    test_ctx->domain->view_name = "LOCAL";
++
++    ret = sysdb_add_overrides_to_object(test_ctx->domain, orig, NULL, NULL);
++    assert_int_equal(ret, EOK);
++}
++
++void test_sysdb_add_overrides_to_object_missing_overridedn(void **state)
++{
++    int ret;
++    struct ldb_message *orig;
++    struct ldb_message_element *el;
++    char *tmp_str;
++    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
++                                                         struct sysdb_test_ctx);
++
++    orig = ldb_msg_new(test_ctx);
++    assert_non_null(orig);
++
++    orig->dn = ldb_dn_new(orig, test_ctx->domain->sysdb->ldb,
++                          "cn=somedn,dc=example,dc=com");
++    assert_non_null(orig->dn);
++
++    tmp_str = talloc_strdup(orig,  "ORIGNAME");
++    assert_non_null(tmp_str);
++    ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str);
++    assert_int_equal(ret, EOK);
++
++    tmp_str = talloc_strdup(orig,  "ORIGGECOS");
++    assert_non_null(tmp_str);
++    ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str);
++    assert_int_equal(ret, EOK);
++
++    test_ctx->domain->has_views = true;
++    test_ctx->domain->view_name = "NON-LOCAL";
++
++    ret = sysdb_add_overrides_to_object(test_ctx->domain, orig, NULL, NULL);
++    assert_int_equal(ret, ENOENT);
++}
++
+ void test_split_ipa_anchor(void **state)
+ {
+     int ret;
+@@ -923,6 +985,10 @@ int main(int argc, const char *argv[])
+                                         test_sysdb_setup, test_sysdb_teardown),
+         cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object,
+                                         test_sysdb_setup, test_sysdb_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object_local,
++                                        test_sysdb_setup, test_sysdb_teardown),
++        cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object_missing_overridedn,
++                                        test_sysdb_setup, test_sysdb_teardown),
+         cmocka_unit_test_setup_teardown(test_split_ipa_anchor,
+                                         test_sysdb_setup, test_sysdb_teardown),
+         cmocka_unit_test_setup_teardown(test_sysdb_delete_view_tree,
+-- 
+2.4.3
+
diff --git a/SOURCES/0022-TOOLS-add-common-command-framework.patch b/SOURCES/0022-TOOLS-add-common-command-framework.patch
new file mode 100644
index 0000000..b5689c8
--- /dev/null
+++ b/SOURCES/0022-TOOLS-add-common-command-framework.patch
@@ -0,0 +1,555 @@
+From edb91d864b48bf6e6240fe7eee84e68cdaaf012a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 22 Jul 2015 10:02:02 +0200
+Subject: [PATCH 22/23] TOOLS: add common command framework
+
+Add general framework to simplify creating "cmd COMMAND [OPTIONS...]"
+style tools.
+
+Preparation for:
+https://fedorahosted.org/sssd/ticket/2584
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                  |   5 +-
+ src/tools/common/sss_tools.c | 406 +++++++++++++++++++++++++++++++++++++++++++
+ src/tools/common/sss_tools.h |  91 ++++++++++
+ 3 files changed, 501 insertions(+), 1 deletion(-)
+ create mode 100644 src/tools/common/sss_tools.c
+ create mode 100644 src/tools/common/sss_tools.h
+
+diff --git a/Makefile.am b/Makefile.am
+index b8cbc6df23ded1edb945a709b6dbe1c44eb54017..1edecc483c61d04562b7bfd9086146e93963b74e 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -445,7 +445,9 @@ SSSD_TOOLS_OBJ = \
+     src/tools/tools_util.c \
+     src/tools/files.c \
+     src/tools/selinux.c \
+-    src/util/nscd.c
++    src/tools/common/sss_tools.c \
++    src/util/nscd.c \
++    $(NULL)
+ 
+ SSSD_LCL_TOOLS_OBJ = \
+     src/sss_client/common.c \
+@@ -641,6 +643,7 @@ dist_noinst_HEADERS = \
+     src/lib/idmap/sss_idmap_private.h \
+     src/lib/sifp/sss_sifp_private.h \
+     src/tests/cmocka/test_utils.h \
++    src/tools/common/sss_tools.h \
+     $(NULL)
+ 
+ 
+diff --git a/src/tools/common/sss_tools.c b/src/tools/common/sss_tools.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..6bbce3a25ddddc0b23ebc108a917a38e94981b65
+--- /dev/null
++++ b/src/tools/common/sss_tools.c
+@@ -0,0 +1,406 @@
++/*
++    Authors:
++        Pavel Březina <pbrezina@redhat.com>
++
++    Copyright (C) 2015 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 <talloc.h>
++#include <stdlib.h>
++#include <string.h>
++#include <popt.h>
++
++#include "config.h"
++#include "util/util.h"
++#include "confdb/confdb.h"
++#include "db/sysdb.h"
++#include "tools/common/sss_tools.h"
++
++struct sss_cmdline {
++    const char *exec; /* argv[0] */
++    const char *command; /* command name */
++    int argc; /* rest of arguments */
++    const char **argv;
++};
++
++static void sss_tool_common_opts(struct sss_tool_ctx *tool_ctx,
++                                 int *argc, const char **argv)
++{
++    poptContext pc;
++    int debug = SSSDBG_DEFAULT;
++    int orig_argc = *argc;
++    int opt;
++
++    struct poptOption options[] = {
++        {"debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_STRIP, &debug,
++            0, _("The debug level to run with"), NULL },
++        POPT_TABLEEND
++    };
++
++    pc = poptGetContext(argv[0], orig_argc, argv, options, 0);
++    while ((opt = poptGetNextOpt(pc)) != -1) {
++        /* do nothing */
++    }
++
++    /* Strip common options from arguments. We will discard_const here,
++     * since it is not worth the trouble to convert it back and forth. */
++    *argc = poptStrippedArgv(pc, orig_argc, discard_const_p(char *, argv));
++
++    DEBUG_CLI_INIT(debug);
++
++    poptFreeContext(pc);
++}
++
++static errno_t sss_tool_confdb_init(TALLOC_CTX *mem_ctx,
++                                    struct confdb_ctx **_confdb)
++{
++    struct confdb_ctx *confdb;
++    char *path;
++    errno_t ret;
++
++    path = talloc_asprintf(mem_ctx, "%s/%s", DB_PATH, CONFDB_FILE);
++    if (path == NULL) {
++        return ENOMEM;
++    }
++
++    ret = confdb_init(mem_ctx, &confdb, path);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Could not initialize connection to the confdb\n");
++        talloc_free(path);
++        return ret;
++    }
++
++    if (_confdb != NULL) {
++        *_confdb = confdb;
++    }
++
++    return EOK;
++}
++
++static errno_t sss_tool_domains_init(TALLOC_CTX *mem_ctx,
++                                     struct confdb_ctx *confdb,
++                                     struct sss_domain_info **_domains)
++{
++    struct sss_domain_info *domains;
++    struct sss_domain_info *dom;
++    errno_t ret;
++
++    ret = confdb_get_domains(confdb, &domains);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup domains [%d]: %s\n",
++                                   ret, sss_strerror(ret));
++        return ret;
++    }
++
++    ret = sysdb_init(mem_ctx, domains, false);
++    SYSDB_VERSION_ERROR(ret);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Could not initialize connection to the sysdb\n");
++        return ret;
++    }
++
++    for (dom = domains; dom != NULL; dom = get_next_domain(dom, true)) {
++        if (!IS_SUBDOMAIN(dom)) {
++            /* Update list of subdomains for this domain */
++            ret = sysdb_update_subdomains(dom);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_MINOR_FAILURE,
++                      "Failed to update subdomains for domain %s.\n",
++                      dom->name);
++            }
++        }
++    }
++
++    for (dom = domains; dom != NULL; dom = get_next_domain(dom, true)) {
++        ret = sss_names_init(mem_ctx, confdb, dom->name, &dom->names);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "sss_names_init() failed\n");
++            return ret;
++        }
++    }
++
++    *_domains = domains;
++
++    return ret;
++}
++
++struct sss_tool_ctx *sss_tool_init(TALLOC_CTX *mem_ctx,
++                                   int *argc, const char **argv)
++{
++    struct sss_tool_ctx *tool_ctx;
++    errno_t ret;
++
++    tool_ctx = talloc_zero(mem_ctx, struct sss_tool_ctx);
++    if (tool_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n");
++        return NULL;
++    }
++
++    sss_tool_common_opts(tool_ctx, argc, argv);
++
++    /* Connect to confdb. */
++    ret = sss_tool_confdb_init(tool_ctx, &tool_ctx->confdb);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to open confdb [%d]: %s\n",
++                                   ret, sss_strerror(ret));
++        goto done;
++    }
++
++    /* Setup domains. */
++    ret = sss_tool_domains_init(tool_ctx, tool_ctx->confdb, &tool_ctx->domains);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup domains [%d]: %s\n",
++                                   ret, sss_strerror(ret));
++        goto done;
++    }
++
++    ret = confdb_get_string(tool_ctx->confdb, tool_ctx,
++                            CONFDB_MONITOR_CONF_ENTRY,
++                            CONFDB_MONITOR_DEFAULT_DOMAIN,
++                            NULL, &tool_ctx->default_domain);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "Cannot get the default domain [%d]: %s\n",
++                                 ret, strerror(ret));
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        talloc_zfree(tool_ctx);
++    }
++
++    return tool_ctx;
++}
++
++int sss_tool_usage(const char *tool_name,
++                   struct sss_route_cmd *commands)
++{
++    int i;
++
++    fprintf(stderr, _("Usage:\n%s COMMAND COMMAND-ARGS\n\n"), tool_name);
++    fprintf(stderr, _("Available commands:\n"));
++
++    for (i = 0; commands[i].command != NULL; i++) {
++        fprintf(stderr, "* %s\n", commands[i].command);
++    }
++
++    return EXIT_FAILURE;
++}
++
++int sss_tool_route(int argc, const char **argv,
++                   struct sss_tool_ctx *tool_ctx,
++                   struct sss_route_cmd *commands,
++                   void *pvt)
++{
++    struct sss_cmdline cmdline;
++    const char *cmd;
++    int i;
++
++    if (commands == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Bug: commands can't be NULL!\n");
++        return EXIT_FAILURE;
++    }
++
++    if (argc < 2) {
++        return sss_tool_usage(argv[0], commands);
++    }
++
++    cmd = argv[1];
++    for (i = 0; commands[i].command != NULL; i++) {
++        if (strcmp(commands[i].command, cmd) == 0) {
++            cmdline.exec = argv[0];
++            cmdline.command = argv[1];
++            cmdline.argc = argc - 2;
++            cmdline.argv = argv + 2;
++
++            return commands[i].fn(&cmdline, tool_ctx, pvt);
++        }
++    }
++
++    return sss_tool_usage(argv[0], commands);
++}
++
++int sss_tool_popt_ex(struct sss_cmdline *cmdline,
++                     struct poptOption *options,
++                     enum sss_tool_opt require_option,
++                     sss_popt_fn popt_fn,
++                     void *popt_fn_pvt,
++                     const char *fopt_name,
++                     const char *fopt_help,
++                     const char **_fopt)
++{
++    const char *optstr;
++    char *help;
++    poptContext pc;
++    int ret;
++
++    /* Create help option string. We always need to append command name since
++     * we use POPT_CONTEXT_KEEP_FIRST. */
++    optstr = options == NULL ? "" : _(" [OPTIONS...]");
++    if (fopt_name == NULL) {
++        help = talloc_asprintf(NULL, "%s %s%s",
++                               cmdline->exec, cmdline->command, optstr);
++    } else {
++        help = talloc_asprintf(NULL, "%s %s %s%s",
++                           cmdline->exec, cmdline->command, fopt_name, optstr);
++    }
++    if (help == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
++        return EXIT_FAILURE;
++    }
++
++    /* Create popt context. This function is supposed to be called on
++     * command argv which does not contain executable (argv[0]), therefore
++     * we need to use KEEP_FIRST that ensures argv[0] is also processed. */
++    pc = poptGetContext(cmdline->exec, cmdline->argc, cmdline->argv,
++                        options, POPT_CONTEXT_KEEP_FIRST);
++
++    poptSetOtherOptionHelp(pc, help);
++
++    /* Parse options. Invoke custom function if provided. If no parsing
++     * function is provided, print error on unknown option. */
++    while ((ret = poptGetNextOpt(pc)) != -1) {
++        if (popt_fn != NULL) {
++            ret = popt_fn(pc, ret, popt_fn_pvt);
++            if (ret != EOK) {
++                ret = EXIT_FAILURE;
++                goto done;
++            }
++        } else {
++            fprintf(stderr, _("Invalid option %s: %s\n\n"),
++                    poptBadOption(pc, 0), poptStrerror(ret));
++            poptPrintHelp(pc, stderr, 0);
++            ret = EXIT_FAILURE;
++            goto done;
++        }
++    }
++
++    /* Parse free option which is always required if requested. */
++    if (_fopt != NULL) {
++        *_fopt = poptGetArg(pc);
++        if (*_fopt == NULL) {
++            fprintf(stderr, _("Missing option: %s\n\n"), fopt_help);
++            poptPrintHelp(pc, stderr, 0);
++            ret = EXIT_FAILURE;
++            goto done;
++        }
++
++        /* No more arguments expected. If something follows it is an error. */
++        if (poptGetArg(pc)) {
++            fprintf(stderr, _("Only one free argument is expected!\n\n"));
++            poptPrintHelp(pc, stderr, 0);
++            ret = EXIT_FAILURE;
++            goto done;
++        }
++    }
++
++    /* If at least one option is required and not provided, print error. */
++    if (require_option == SSS_TOOL_OPT_REQUIRED
++            && ((_fopt != NULL && cmdline->argc < 2) || cmdline->argc < 1)) {
++        fprintf(stderr, _("At least one option is required!\n\n"));
++        poptPrintHelp(pc, stderr, 0);
++        ret = EXIT_FAILURE;
++        goto done;
++    }
++
++    ret = EXIT_SUCCESS;
++
++done:
++    poptFreeContext(pc);
++    talloc_free(help);
++    return ret;
++}
++
++int sss_tool_popt(struct sss_cmdline *cmdline,
++                  struct poptOption *options,
++                  enum sss_tool_opt require_option,
++                  sss_popt_fn popt_fn,
++                  void *popt_fn_pvt)
++{
++    return sss_tool_popt_ex(cmdline, options, require_option,
++                            popt_fn, popt_fn_pvt, NULL, NULL, NULL);
++}
++
++int sss_tool_main(int argc, const char **argv,
++                  struct sss_route_cmd *commands,
++                  void *pvt)
++{
++    struct sss_tool_ctx *tool_ctx;
++    uid_t uid;
++    int ret;
++
++    uid = getuid();
++    if (uid != 0) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Running under %d, must be root\n", uid);
++        ERROR("%1$s must be run as root\n", argv[0]);
++        return EXIT_FAILURE;
++    }
++
++    tool_ctx = sss_tool_init(NULL, &argc, argv);
++    if (tool_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tool context\n");
++        return EXIT_FAILURE;
++    }
++
++    ret = sss_tool_route(argc, argv, tool_ctx, commands, pvt);
++    talloc_free(tool_ctx);
++
++    return ret;
++}
++
++int sss_tool_parse_name(TALLOC_CTX *mem_ctx,
++                        struct sss_tool_ctx *tool_ctx,
++                        const char *input,
++                        const char **_username,
++                        struct sss_domain_info **_domain)
++{
++    char *username = NULL;
++    char *domname = NULL;
++    struct sss_domain_info *domain;
++    int ret;
++
++    ret = sss_parse_name_for_domains(mem_ctx, tool_ctx->domains,
++                                     tool_ctx->default_domain, input,
++                                     &domname, &username);
++    if (ret == EAGAIN) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find domain. The domain name may "
++              "be a subdomain that was not yet found.\n");
++        goto done;
++    } else if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name [%d]: %s\n",
++              ret, sss_strerror(ret));
++        goto done;
++    }
++
++    domain = find_domain_by_name(tool_ctx->domains, domname, true);
++
++    *_username = username;
++    *_domain = domain;
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        talloc_zfree(username);
++        talloc_zfree(domname);
++    }
++
++    return ret;
++}
+diff --git a/src/tools/common/sss_tools.h b/src/tools/common/sss_tools.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..cfe11d06e1dadf8e49efe155c8a53f99a31e97fb
+--- /dev/null
++++ b/src/tools/common/sss_tools.h
+@@ -0,0 +1,91 @@
++/*
++    Authors:
++        Pavel Březina <pbrezina@redhat.com>
++
++    Copyright (C) 2015 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 _SSS_TOOLS_H_
++#define _SSS_TOOLS_H_
++
++#include <talloc.h>
++#include <popt.h>
++
++#include "confdb/confdb.h"
++
++struct sss_tool_ctx {
++    struct confdb_ctx *confdb;
++
++    char *default_domain;
++    struct sss_domain_info *domains;
++};
++
++struct sss_tool_ctx *sss_tool_init(TALLOC_CTX *mem_ctx,
++                                   int *argc, const char **argv);
++
++struct sss_cmdline;
++
++typedef int
++(*sss_route_fn)(struct sss_cmdline *cmdline,
++                struct sss_tool_ctx *tool_ctx,
++                void *pvt);
++
++struct sss_route_cmd {
++    const char *command;
++    sss_route_fn fn;
++};
++
++int sss_tool_usage(const char *tool_name,
++                   struct sss_route_cmd *commands);
++
++int sss_tool_route(int argc, const char **argv,
++                   struct sss_tool_ctx *tool_ctx,
++                   struct sss_route_cmd *commands,
++                   void *pvt);
++
++typedef int (*sss_popt_fn)(poptContext pc, char option, void *pvt);
++
++enum sss_tool_opt {
++    SSS_TOOL_OPT_REQUIRED,
++    SSS_TOOL_OPT_OPTIONAL
++};
++
++int sss_tool_popt_ex(struct sss_cmdline *cmdline,
++                     struct poptOption *options,
++                     enum sss_tool_opt require_option,
++                     sss_popt_fn popt_fn,
++                     void *popt_fn_pvt,
++                     const char *free_opt_name,
++                     const char *free_opt_help,
++                     const char **_free_opt);
++
++int sss_tool_popt(struct sss_cmdline *cmdline,
++                  struct poptOption *options,
++                  enum sss_tool_opt require_option,
++                  sss_popt_fn popt_fn,
++                  void *popt_fn_pvt);
++
++int sss_tool_main(int argc, const char **argv,
++                  struct sss_route_cmd *commands,
++                  void *pvt);
++
++int sss_tool_parse_name(TALLOC_CTX *mem_ctx,
++                        struct sss_tool_ctx *tool_ctx,
++                        const char *input,
++                        const char **_username,
++                        struct sss_domain_info **_domain);
++
++#endif /* SRC_TOOLS_COMMON_SSS_TOOLS_H_ */
+-- 
+2.4.3
+
diff --git a/SOURCES/0022-pyhbac-pysss-fix-reference-leaks.patch b/SOURCES/0022-pyhbac-pysss-fix-reference-leaks.patch
deleted file mode 100644
index 180d730..0000000
--- a/SOURCES/0022-pyhbac-pysss-fix-reference-leaks.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-From b615258d6df8ad867cee99bdccffff05127fbc92 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Mon, 29 Sep 2014 16:40:53 +0100
-Subject: [PATCH 22/22] pyhbac,pysss: fix reference leaks
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/1195
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/python/pyhbac.c | 22 +++++++++++++---------
- src/python/pysss.c  | 10 +++++++---
- 2 files changed, 20 insertions(+), 12 deletions(-)
-
-diff --git a/src/python/pyhbac.c b/src/python/pyhbac.c
-index e9dce9b01b78401516b5c21141be8007b4a94aec..dd345a6eb4db8ac6104251d5b9c8f11a160e280d 100644
---- a/src/python/pyhbac.c
-+++ b/src/python/pyhbac.c
-@@ -139,14 +139,17 @@ sequence_as_string_list(PyObject *seq, const char *paramname)
- 
-         utf_item = get_utf8_string(item, p);
-         if (utf_item == NULL) {
-+            Py_DECREF(item);
-             return NULL;
-         }
- 
-         ret[i] = py_strdup(PyString_AsString(utf_item));
-         Py_DECREF(utf_item);
-         if (!ret[i]) {
-+            Py_DECREF(item);
-             return NULL;
-         }
-+        Py_DECREF(item);
-     }
- 
-     ret[i] = NULL;
-@@ -242,10 +245,7 @@ str_concat_sequence(PyObject *seq, const char *delim)
-         if (item == NULL) goto fail;
- 
-         part = PyString_AsString(item);
--        if (part == NULL) {
--            Py_DECREF(item);
--            goto fail;
--        }
-+        if (part == NULL) goto fail;
- 
-         if (s) {
-             s = py_strcat_realloc(s, delim);
-@@ -260,7 +260,9 @@ str_concat_sequence(PyObject *seq, const char *delim)
-     }
- 
-     return s;
-+
- fail:
-+    Py_XDECREF(item);
-     PyMem_Free(s);
-     return NULL;
- }
-@@ -269,11 +271,13 @@ fail:
- static void
- set_hbac_exception(PyObject *exc, struct hbac_info *error)
- {
--    PyErr_SetObject(exc,
--                    Py_BuildValue(sss_py_const_p(char, "(i,s)"),
--                                  error->code,
--                                  error->rule_name ? \
--                                        error->rule_name : "no rule"));
-+    PyObject *obj;
-+
-+    obj = Py_BuildValue(sss_py_const_p(char, "(i,s)"), error->code,
-+                        error->rule_name ? error->rule_name : "no rule");
-+
-+    PyErr_SetObject(exc, obj);
-+    Py_XDECREF(obj);
- }
- 
- /* ==================== HBAC Rule Element ========================*/
-diff --git a/src/python/pysss.c b/src/python/pysss.c
-index 8f98f081c9600b74f5953faef40cb40b30388319..9e899f1399553a950e41e157612a7360de4c07b5 100644
---- a/src/python/pysss.c
-+++ b/src/python/pysss.c
-@@ -850,7 +850,7 @@ static PyObject *PySssLocalObject_new(PyTypeObject *type,
-     if (confdb_path == NULL) {
-         talloc_free(mem_ctx);
-         PyErr_NoMemory();
--        return NULL;
-+        goto fail;
-     }
- 
-     /* Connect to the conf db */
-@@ -859,7 +859,7 @@ static PyObject *PySssLocalObject_new(PyTypeObject *type,
-         talloc_free(mem_ctx);
-         PyErr_SetSssErrorWithMessage(ret,
-                 "Could not initialize connection to the confdb\n");
--        return NULL;
-+        goto fail;
-     }
- 
-     ret = sssd_domain_init(self->mem_ctx, self->confdb, "local",
-@@ -868,7 +868,7 @@ static PyObject *PySssLocalObject_new(PyTypeObject *type,
-         talloc_free(mem_ctx);
-         PyErr_SetSssErrorWithMessage(ret,
-                 "Could not initialize connection to the sysdb\n");
--        return NULL;
-+        goto fail;
-     }
-     self->sysdb = self->local->sysdb;
- 
-@@ -876,6 +876,10 @@ static PyObject *PySssLocalObject_new(PyTypeObject *type,
-     self->unlock = DO_UNLOCK;
- 
-     return (PyObject *) self;
-+
-+fail:
-+    Py_DECREF(self);
-+    return NULL;
- }
- 
- /*
--- 
-1.9.3
-
diff --git a/SOURCES/0023-TOOLS-add-sss_override-for-local-overrides.patch b/SOURCES/0023-TOOLS-add-sss_override-for-local-overrides.patch
new file mode 100644
index 0000000..ebf1051
--- /dev/null
+++ b/SOURCES/0023-TOOLS-add-sss_override-for-local-overrides.patch
@@ -0,0 +1,939 @@
+From a3b608a72f2cba3cece3a28dbc1c5d532d91ce14 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Fri, 24 Jul 2015 09:58:11 +0200
+Subject: [PATCH 23/23] TOOLS: add sss_override for local overrides
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2584
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                |  16 +-
+ contrib/sssd.spec.in       |   2 +
+ src/man/Makefile.am        |   1 +
+ src/man/po/po4a.cfg        |   1 +
+ src/man/sss_override.8.xml | 108 +++++++
+ src/tools/sss_override.c   | 718 +++++++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 845 insertions(+), 1 deletion(-)
+ create mode 100644 src/man/sss_override.8.xml
+ create mode 100644 src/tools/sss_override.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 1edecc483c61d04562b7bfd9086146e93963b74e..912bfc6641465ef5cd2ff2cce9975b4027c3218d 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -117,7 +117,9 @@ sbin_PROGRAMS = \
+     sss_groupshow \
+     sss_cache \
+     sss_debuglevel \
+-    sss_seed
++    sss_override \
++    sss_seed \
++    $(NULL)
+ 
+ sssdlibexec_PROGRAMS = \
+     sssd_nss \
+@@ -1297,6 +1299,18 @@ sss_signal_LDADD = \
+     $(SSSD_INTERNAL_LTLIBS) \
+     $(NULL)
+ 
++sss_override_SOURCES = \
++    src/tools/sss_override.c \
++    $(SSSD_TOOLS_OBJ) \
++    $(NULL)
++sss_override_LDADD = \
++    $(TOOLS_LIBS) \
++    $(SSSD_INTERNAL_LTLIBS) \
++    $(NULL)
++sss_override_CFLAGS = \
++    $(AM_CFLAGS) \
++    $(NULL)
++
+ if BUILD_SUDO
+ sss_sudo_cli_SOURCES = \
+     src/sss_client/common.c \
+diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
+index 15f7c582cba1b9052e180596625be7dd5749599f..f050501ff9d0711a0da7f094ee968cae87a3f49b 100644
+--- a/contrib/sssd.spec.in
++++ b/contrib/sssd.spec.in
+@@ -837,6 +837,7 @@ rm -rf $RPM_BUILD_ROOT
+ %{_sbindir}/sss_groupmod
+ %{_sbindir}/sss_groupshow
+ %{_sbindir}/sss_obfuscate
++%{_sbindir}/sss_override
+ %{_sbindir}/sss_debuglevel
+ %{_sbindir}/sss_seed
+ %{_mandir}/man8/sss_groupadd.8*
+@@ -847,6 +848,7 @@ rm -rf $RPM_BUILD_ROOT
+ %{_mandir}/man8/sss_userdel.8*
+ %{_mandir}/man8/sss_usermod.8*
+ %{_mandir}/man8/sss_obfuscate.8*
++%{_mandir}/man8/sss_override.8*
+ %{_mandir}/man8/sss_debuglevel.8*
+ %{_mandir}/man8/sss_seed.8*
+ 
+diff --git a/src/man/Makefile.am b/src/man/Makefile.am
+index 1ef1da48cce74f7d1ad77e3751ee6ac3450f0259..70cadf5951f56b78ff0bfbcb303e255478af5fec 100644
+--- a/src/man/Makefile.am
++++ b/src/man/Makefile.am
+@@ -51,6 +51,7 @@ man_MANS = \
+     sssd-krb5.5 sssd-simple.5 \
+     sssd_krb5_locator_plugin.8 sss_groupshow.8 \
+     pam_sss.8 sss_obfuscate.8 sss_cache.8 sss_debuglevel.8 sss_seed.8 \
++    sss_override.8
+     $(NULL)
+ 
+ if BUILD_SAMBA
+diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg
+index 25d20c6f0c23a0900469573d47ab96ebc8898e50..67e87ba7006f0bb1346e5b845428f2bed1a324db 100644
+--- a/src/man/po/po4a.cfg
++++ b/src/man/po/po4a.cfg
+@@ -11,6 +11,7 @@
+ [type:docbook] sssd-sudo.5.xml $lang:$(builddir)/$lang/sssd-sudo.5.xml
+ [type:docbook] sssd.8.xml $lang:$(builddir)/$lang/sssd.8.xml
+ [type:docbook] sss_obfuscate.8.xml $lang:$(builddir)/$lang/sss_obfuscate.8.xml
++[type:docbook] sss_override.8.xml $lang:$(builddir)/$lang/sss_override.8.xml
+ [type:docbook] sss_useradd.8.xml $lang:$(builddir)/$lang/sss_useradd.8.xml
+ [type:docbook] sssd-krb5.5.xml $lang:$(builddir)/$lang/sssd-krb5.5.xml
+ [type:docbook] sss_groupadd.8.xml $lang:$(builddir)/$lang/sss_groupadd.8.xml
+diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml
+new file mode 100644
+index 0000000000000000000000000000000000000000..ec9a7bb75c13f4f18ece7f5f84baede14a8a1e2e
+--- /dev/null
++++ b/src/man/sss_override.8.xml
+@@ -0,0 +1,108 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.4//EN"
++"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
++<reference>
++<title>SSSD Manual pages</title>
++<refentry>
++    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/upstream.xml" />
++
++    <refmeta>
++        <refentrytitle>sss_override</refentrytitle>
++        <manvolnum>8</manvolnum>
++    </refmeta>
++
++    <refnamediv id='name'>
++        <refname>sss_override</refname>
++        <refpurpose>create local overrides of user and group attributes</refpurpose>
++    </refnamediv>
++
++    <refsynopsisdiv id='synopsis'>
++        <cmdsynopsis>
++            <command>sss_override</command>
++            <arg choice='plain'><replaceable>COMMAND</replaceable></arg>
++            <arg choice='opt'>
++                <replaceable>options</replaceable>
++            </arg>
++        </cmdsynopsis>
++    </refsynopsisdiv>
++
++    <refsect1 id='description'>
++        <title>DESCRIPTION</title>
++        <para>
++            <command>sss_override</command> enables to create a client-side
++            view and allows to change selected values of specific user
++            and groups. This change takes effect only on local machine.
++        </para>
++        <para>
++            Overrides data are stored in SSSD cache. If the cache is deleted
++            all local overrides are lost.
++        </para>
++    </refsect1>
++
++    <refsect1 id='commands'>
++        <title>AVAILABLE COMMANDS</title>
++        <para>
++            Argument <emphasis>NAME</emphasis> is the name of original object
++            in all commands. It is not possible to override
++            <emphasis>uid</emphasis> or <emphasis>gid</emphasis> to 0.
++        </para>
++        <variablelist remap='IP'>
++            <varlistentry>
++                <term>
++                    <option>user-add</option>
++                    <emphasis>NAME</emphasis>
++                    <optional><option>-n,--name</option> NAME</optional>
++                    <optional><option>-u,--uid</option> UID</optional>
++                    <optional><option>-g,--gid</option> GID</optional>
++                    <optional><option>-h,--home</option> HOME</optional>
++                    <optional><option>-s,--shell</option> SHELL</optional>
++                    <optional><option>-c,--gecos</option> GECOS</optional>
++                </term>
++                <listitem>
++                    <para>
++                        Override attributes of an user.
++                    </para>
++                </listitem>
++            </varlistentry>
++            <varlistentry>
++                <term>
++                    <option>user-del</option>
++                    <emphasis>NAME</emphasis>
++                </term>
++                <listitem>
++                    <para>
++                        Remove user overrides.
++                    </para>
++                </listitem>
++            </varlistentry>
++            <varlistentry>
++                <term>
++                    <option>group-add</option>
++                    <emphasis>NAME</emphasis>
++                    <optional><option>-n,--name</option> NAME</optional>
++                    <optional><option>-g,--gid</option> GID</optional>
++                </term>
++                <listitem>
++                    <para>
++                        Override attributes of a group.
++                    </para>
++                </listitem>
++            </varlistentry>
++            <varlistentry>
++                <term>
++                    <option>group-del</option>
++                    <emphasis>NAME</emphasis>
++                </term>
++                <listitem>
++                    <para>
++                        Remove group overrides.
++                    </para>
++                </listitem>
++            </varlistentry>
++        </variablelist>
++    </refsect1>
++
++    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/seealso.xml" />
++
++</refentry>
++</reference>
+diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..5e901e2e31de64dacb171337defc03d428f8ed57
+--- /dev/null
++++ b/src/tools/sss_override.c
+@@ -0,0 +1,718 @@
++/*
++    Authors:
++        Pavel Březina <pbrezina@redhat.com>
++
++    Copyright (C) 2015 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 <stdlib.h>
++
++#include "util/util.h"
++#include "db/sysdb.h"
++#include "tools/common/sss_tools.h"
++
++#define LOCALVIEW SYSDB_LOCAL_VIEW_NAME
++
++struct override_user {
++    const char *input_name;
++    const char *orig_name;
++    struct sss_domain_info *domain;
++
++    const char *name;
++    uid_t uid;
++    gid_t gid;
++    const char *home;
++    const char *shell;
++    const char *gecos;
++};
++
++struct override_group {
++    const char *input_name;
++    const char *orig_name;
++    struct sss_domain_info *domain;
++
++    const char *name;
++    gid_t gid;
++};
++
++static int parse_cmdline(struct sss_cmdline *cmdline,
++                         struct sss_tool_ctx *tool_ctx,
++                         struct poptOption *options,
++                         const char **_input_name,
++                         const char **_orig_name,
++                         struct sss_domain_info **_domain)
++{
++    enum sss_tool_opt require;
++    const char *input_name;
++    const char *orig_name;
++    struct sss_domain_info *domain;
++    int ret;
++
++    require = options == NULL ? SSS_TOOL_OPT_OPTIONAL : SSS_TOOL_OPT_REQUIRED;
++
++    ret = sss_tool_popt_ex(cmdline, options, require,
++                           NULL, NULL, "NAME", _("Specify name of modified "
++                           "object."), &input_name);
++    if (ret != EXIT_SUCCESS) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
++        return ret;
++    }
++
++    ret = sss_tool_parse_name(tool_ctx, tool_ctx, input_name,
++                              &orig_name, &domain);
++    if (ret != EOK) {
++        fprintf(stderr, _("Unable to parse name.\n"));
++        return ret;
++    }
++
++    *_input_name = input_name;
++    *_orig_name = orig_name;
++    *_domain = domain;
++
++    return EXIT_SUCCESS;
++}
++
++static int parse_cmdline_user_add(struct sss_cmdline *cmdline,
++                                  struct sss_tool_ctx *tool_ctx,
++                                  struct override_user *user)
++{
++    struct poptOption options[] = {
++        POPT_AUTOHELP
++        {"name", 'n', POPT_ARG_STRING, &user->name, 0, _("Override name"), NULL },
++        {"uid", 'u', POPT_ARG_INT, &user->uid, 0, _("Override uid (non-zero value)"), NULL },
++        {"gid", 'g', POPT_ARG_INT, &user->gid, 0, _("Override gid (non-zero value)"), NULL },
++        {"home", 'h', POPT_ARG_STRING, &user->home, 0, _("Override home directory"), NULL },
++        {"shell", 's', POPT_ARG_STRING, &user->shell, 0, _("Override shell"), NULL },
++        {"gecos", 'c', POPT_ARG_STRING, &user->gecos, 0, _("Override gecos"), NULL },
++        POPT_TABLEEND
++    };
++
++    return parse_cmdline(cmdline, tool_ctx, options, &user->input_name,
++                         &user->orig_name, &user->domain);
++}
++
++static int parse_cmdline_user_del(struct sss_cmdline *cmdline,
++                                  struct sss_tool_ctx *tool_ctx,
++                                  struct override_user *user)
++{
++    return parse_cmdline(cmdline, tool_ctx, NULL, &user->input_name,
++                         &user->orig_name, &user->domain);
++}
++
++static int parse_cmdline_group_add(struct sss_cmdline *cmdline,
++                                   struct sss_tool_ctx *tool_ctx,
++                                   struct override_group *group)
++{
++    struct poptOption options[] = {
++        POPT_AUTOHELP
++        {"name", 'n', POPT_ARG_STRING, &group->name, 0, _("Override name"), NULL },
++        {"gid", 'g', POPT_ARG_INT, &group->gid, 0, _("Override gid"), NULL },
++        POPT_TABLEEND
++    };
++
++    return parse_cmdline(cmdline, tool_ctx, options, &group->input_name,
++                         &group->orig_name, &group->domain);
++}
++
++static int parse_cmdline_group_del(struct sss_cmdline *cmdline,
++                                   struct sss_tool_ctx *tool_ctx,
++                                   struct override_group *group)
++{
++    return parse_cmdline(cmdline, tool_ctx, NULL, &group->input_name,
++                         &group->orig_name, &group->domain);
++}
++
++static errno_t prepare_view(struct sss_domain_info *domain)
++{
++    char *viewname = NULL;
++    errno_t ret;
++
++    ret = sysdb_get_view_name(NULL, domain->sysdb, &viewname);
++    if (ret != EOK && ret != ENOENT) {
++        DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name() failed.\n");
++        return ret;
++    }
++
++    if (ret == EOK) {
++        if (is_local_view(viewname)) {
++            DEBUG(SSSDBG_TRACE_FUNC, "%s view is already present.\n", viewname);
++            ret = EOK;
++            goto done;
++        } else if (viewname != NULL) {
++            DEBUG(SSSDBG_MINOR_FAILURE, "There already exists view %s. "
++                  "Only one view is supported. Nothing to do.\n", viewname);
++            ret = EEXIST;
++            goto done;
++        }
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Creating %s view.\n", LOCALVIEW);
++
++    ret = sysdb_update_view_name(domain->sysdb, LOCALVIEW);
++    if (ret == EOK) {
++        printf("SSSD needs to be restarted for the changes to take effect.\n");
++    }
++
++done:
++    talloc_free(viewname);
++    return ret;
++}
++
++static char *build_anchor(TALLOC_CTX *mem_ctx, const char *obj_dn)
++{
++    char *anchor;
++    char *safe_dn;
++    errno_t ret;
++
++    ret = sysdb_dn_sanitize(mem_ctx, obj_dn, &safe_dn);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_dn_sanitize() failed\n");
++        return NULL;
++    }
++
++    anchor = talloc_asprintf(mem_ctx, ":%s:%s", LOCALVIEW, safe_dn);
++
++    talloc_free(safe_dn);
++
++    return anchor;
++}
++
++static struct sysdb_attrs *build_attrs(TALLOC_CTX *mem_ctx,
++                                       const char *name,
++                                       uid_t uid,
++                                       gid_t gid,
++                                       const char *home,
++                                       const char *shell,
++                                       const char *gecos)
++{
++    struct sysdb_attrs *attrs;
++    errno_t ret;
++
++    attrs = sysdb_new_attrs(mem_ctx);
++    if (attrs == NULL) {
++        return NULL;
++    }
++
++    if (name != NULL) {
++        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name);
++        if (ret != EOK) {
++            goto done;
++        }
++    }
++
++    if (uid != 0) {
++        ret = sysdb_attrs_add_uint32(attrs, SYSDB_UIDNUM, uid);
++        if (ret != EOK) {
++            goto done;
++        }
++    }
++
++    if (gid != 0) {
++        ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
++        if (ret != EOK) {
++            goto done;
++        }
++    }
++
++    if (home != NULL) {
++        ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, home);
++        if (ret != EOK) {
++            goto done;
++        }
++    }
++
++    if (shell != NULL) {
++        ret = sysdb_attrs_add_string(attrs, SYSDB_SHELL, shell);
++        if (ret != EOK) {
++            goto done;
++        }
++    }
++
++    if (gecos != NULL) {
++        ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, gecos);
++        if (ret != EOK) {
++            goto done;
++        }
++    }
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        talloc_free(attrs);
++        return NULL;
++    }
++
++    return attrs;
++}
++
++static struct sysdb_attrs *build_user_attrs(TALLOC_CTX *mem_ctx,
++                                            struct override_user *user)
++{
++    return build_attrs(mem_ctx, user->name, user->uid, user->gid, user->home,
++                       user->shell, user->gecos);
++}
++
++static struct sysdb_attrs *build_group_attrs(TALLOC_CTX *mem_ctx,
++                                             struct override_group *group)
++{
++    return build_attrs(mem_ctx, group->name, 0, group->gid, 0, NULL, NULL);
++}
++
++static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx,
++                                         enum sysdb_member_type type,
++                                         const char *name,
++                                         struct sss_domain_info *domain,
++                                         struct sss_domain_info *domains,
++                                         struct sss_domain_info **_new_domain)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct sss_domain_info *dom;
++    struct ldb_result *res;
++    const char *dn;
++    const char *strtype;
++    bool check_next;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        return NULL;
++    }
++
++    /* Ensure that the object is in cache. */
++    switch (type) {
++    case SYSDB_MEMBER_USER:
++        if (getpwnam(name) == NULL) {
++            ret = ENOENT;
++            goto done;
++        }
++        break;
++    case SYSDB_MEMBER_GROUP:
++        if (getgrnam(name) == NULL) {
++            ret = ENOENT;
++            goto done;
++        }
++        break;
++    default:
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type);
++        ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    /* Find domain if it is unknown. */
++    if (domain == NULL) {
++        check_next = true;
++        dom = domains;
++    } else {
++        check_next = false;
++        dom = domain;
++    }
++
++    do {
++        switch (type) {
++        case SYSDB_MEMBER_USER:
++            DEBUG(SSSDBG_TRACE_FUNC, "Trying to find user %s@%s\n",
++                  name, dom->name);
++            ret = sysdb_getpwnam(tmp_ctx, dom, name, &res);
++            strtype = "user";
++            break;
++        case SYSDB_MEMBER_GROUP:
++            DEBUG(SSSDBG_TRACE_FUNC, "Trying to find group %s@%s\n",
++                  name, dom->name);
++            ret = sysdb_getgrnam(tmp_ctx, dom, name, &res);
++            strtype = "group";
++            break;
++        default:
++            DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type);
++            ret = ERR_INTERNAL;
++            goto done;
++        }
++
++        if (ret == EOK && res->count == 0) {
++            ret = ENOENT;
++
++            if (check_next) {
++                dom = dom->next;
++                continue;
++            }
++        }
++
++        if (ret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find %s %s@%s [%d]: %s\n",
++                  strtype, name, dom->name, ret, sss_strerror(ret));
++            goto done;
++        } else if (res->count != 1) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "More than one %s found?\n", strtype);
++            ret = ERR_INTERNAL;
++            goto done;
++        }
++
++        check_next = false;
++    } while (check_next && dom != NULL);
++
++    if (dom == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "No domain match for %s\n", name);
++        ret = ENOENT;
++        goto done;
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Domain of %s %s is %s\n",
++          strtype, name, dom->name);
++
++    dn = ldb_dn_get_linearized(res->msgs[0]->dn);
++    if (dn == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized() failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    talloc_steal(mem_ctx, dn);
++    *_new_domain = dom;
++
++    ret = EOK;
++
++done:
++    talloc_free(tmp_ctx);
++
++    if (ret != EOK) {
++        return NULL;
++    }
++
++    return dn;
++}
++
++static const char * get_user_dn_and_domain(TALLOC_CTX *mem_ctx,
++                                           struct sss_domain_info *domains,
++                                           struct override_user *user)
++{
++    return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_USER,
++                         user->orig_name, user->domain, domains,
++                         &user->domain);
++}
++
++static const char * get_group_dn_and_domain(TALLOC_CTX *mem_ctx,
++                                            struct sss_domain_info *domains,
++                                            struct override_group *group)
++{
++    return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_GROUP,
++                         group->orig_name, group->domain, domains,
++                         &group->domain);
++}
++
++static errno_t override_object_add(struct sss_domain_info *domain,
++                                   enum sysdb_member_type type,
++                                   struct sysdb_attrs *attrs,
++                                   const char *obj_dn)
++{
++    TALLOC_CTX *tmp_ctx;
++    const char *anchor;
++    struct ldb_dn *ldb_dn;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        return ENOMEM;
++    }
++
++    ldb_dn = ldb_dn_new(tmp_ctx, sysdb_ctx_get_ldb(domain->sysdb), obj_dn);
++    if (ldb_dn == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    anchor = build_anchor(tmp_ctx, obj_dn);
++    if (anchor == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, anchor);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Creating override for %s\n", obj_dn);
++
++    ret = sysdb_store_override(domain, LOCALVIEW, type, attrs, ldb_dn);
++
++done:
++    talloc_free(tmp_ctx);
++    return ret;
++}
++
++static errno_t override_object_del(struct sss_domain_info *domain,
++                                   const char *obj_dn)
++{
++    TALLOC_CTX *tmp_ctx;
++    const char *anchor;
++    struct ldb_dn *override_dn;
++    struct ldb_message *msg;
++    errno_t ret;
++    int sret;
++    bool in_transaction = false;
++    struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        return ENOMEM;
++    }
++
++    anchor = build_anchor(tmp_ctx, obj_dn);
++    if (anchor == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    override_dn = ldb_dn_new_fmt(tmp_ctx, ldb,
++                        SYSDB_TMPL_OVERRIDE, anchor, LOCALVIEW);
++    if (override_dn == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Removing override for %s\n", obj_dn);
++
++    ret = sysdb_transaction_start(domain->sysdb);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start() failed.\n");
++        goto done;
++    }
++    in_transaction = true;
++
++    ret = sysdb_delete_entry(domain->sysdb, override_dn, true);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_entry() failed.\n");
++        goto done;
++    }
++
++    msg = ldb_msg_new(tmp_ctx);
++    if (msg == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    msg->dn = ldb_dn_new(msg, ldb, obj_dn);
++    if (msg->dn == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_DELETE, NULL);
++    if (ret != LDB_SUCCESS) {
++        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty() failed\n");
++        ret = sysdb_error_to_errno(ret);
++        goto done;
++    }
++
++    ret = ldb_modify(ldb, msg);
++    if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "ldb_modify() failed: [%s](%d)[%s]\n",
++              ldb_strerror(ret), ret, ldb_errstring(ldb));
++        ret = sysdb_error_to_errno(ret);
++        goto done;
++    }
++
++    ret = sysdb_transaction_commit(domain->sysdb);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
++        goto done;
++    }
++    in_transaction = false;
++
++    ret = EOK;
++
++done:
++    if (in_transaction) {
++        sret = sysdb_transaction_cancel(domain->sysdb);
++        if (sret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
++        }
++    }
++
++    talloc_free(tmp_ctx);
++    return ret;
++}
++
++static int override_user_add(struct sss_cmdline *cmdline,
++                             struct sss_tool_ctx *tool_ctx,
++                             void *pvt)
++{
++    struct override_user user = {NULL};
++    struct sysdb_attrs *attrs;
++    const char *dn;
++    int ret;
++
++    ret = parse_cmdline_user_add(cmdline, tool_ctx, &user);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        return EXIT_FAILURE;
++    }
++
++    dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user);
++    if (dn == NULL) {
++        fprintf(stderr, _("Unable to find user %s@%s.\n"),
++                user.orig_name,
++                user.domain == NULL ? "[unknown]" : user.domain->name);
++        return EXIT_FAILURE;
++    }
++
++    ret = prepare_view(user.domain);
++    if (ret == EEXIST) {
++        fprintf(stderr, _("Other than LOCAL view already exist in "
++                "domain %s.\n"), user.domain->name);
++        return EXIT_FAILURE;
++    } else if (ret != EOK) {
++        fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"),
++                ret, sss_strerror(ret));
++        return EXIT_FAILURE;
++    }
++
++    attrs = build_user_attrs(tool_ctx, &user);
++    if (attrs == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
++        return EXIT_FAILURE;
++    }
++
++    ret = override_object_add(user.domain, SYSDB_MEMBER_USER, attrs, dn);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        return EXIT_FAILURE;
++    }
++
++    return EXIT_SUCCESS;
++}
++
++static int override_user_del(struct sss_cmdline *cmdline,
++                             struct sss_tool_ctx *tool_ctx,
++                             void *pvt)
++{
++    struct override_user user = {NULL};
++    const char *dn;
++    int ret;
++
++    ret = parse_cmdline_user_del(cmdline, tool_ctx, &user);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        return EXIT_FAILURE;
++    }
++
++    dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user);
++    if (dn == NULL) {
++        fprintf(stderr, _("Unable to find user %s@%s.\n"),
++                user.orig_name, user.domain->name);
++        return EXIT_FAILURE;
++    }
++
++    ret = override_object_del(user.domain, dn);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        return EXIT_FAILURE;
++    }
++
++    return EXIT_SUCCESS;
++}
++
++static int override_group_add(struct sss_cmdline *cmdline,
++                              struct sss_tool_ctx *tool_ctx,
++                              void *pvt)
++{
++    struct override_group group = {NULL};
++    struct sysdb_attrs *attrs;
++    const char *dn;
++    int ret;
++
++    ret = parse_cmdline_group_add(cmdline, tool_ctx, &group);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        return EXIT_FAILURE;
++    }
++
++    dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group);
++    if (dn == NULL) {
++        fprintf(stderr, _("Unable to find group %s@%s.\n"),
++                group.orig_name, group.domain->name);
++        return EXIT_FAILURE;
++    }
++
++    ret = prepare_view(group.domain);
++    if (ret == EEXIST) {
++        fprintf(stderr, _("Other than LOCAL view already exist in "
++                "domain %s.\n"), group.domain->name);
++        return EXIT_FAILURE;
++    } else if (ret != EOK) {
++        fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"),
++                ret, sss_strerror(ret));
++        return EXIT_FAILURE;
++    }
++
++    attrs = build_group_attrs(tool_ctx, &group);
++    if (attrs == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
++        return EXIT_FAILURE;
++    }
++
++    ret = override_object_add(group.domain, SYSDB_MEMBER_GROUP, attrs, dn);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        return EXIT_FAILURE;
++    }
++
++    return EXIT_SUCCESS;
++}
++
++static int override_group_del(struct sss_cmdline *cmdline,
++                              struct sss_tool_ctx *tool_ctx,
++                              void *pvt)
++{
++    struct override_group group = {NULL};
++    const char *dn;
++    int ret;
++
++    ret = parse_cmdline_group_del(cmdline, tool_ctx, &group);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        return EXIT_FAILURE;
++    }
++
++    dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group);
++    if (dn == NULL) {
++        fprintf(stderr, _("Unable to find group %s@%s.\n"),
++                group.orig_name, group.domain->name);
++        return EXIT_FAILURE;
++    }
++
++    ret = override_object_del(group.domain, dn);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        return EXIT_FAILURE;
++    }
++
++    return EXIT_SUCCESS;
++}
++
++int main(int argc, const char **argv)
++{
++    struct sss_route_cmd commands[] = {
++        {"user-add", override_user_add},
++        {"user-del", override_user_del},
++        {"group-add", override_group_add},
++        {"group-del", override_group_del},
++        {NULL, NULL}
++    };
++
++    return sss_tool_main(argc, argv, commands, NULL);
++}
+-- 
+2.4.3
+
diff --git a/SOURCES/0023-UTIL-Add-a-function-to-convert-id_t-from-a-number-or.patch b/SOURCES/0023-UTIL-Add-a-function-to-convert-id_t-from-a-number-or.patch
deleted file mode 100644
index 5bdce3c..0000000
--- a/SOURCES/0023-UTIL-Add-a-function-to-convert-id_t-from-a-number-or.patch
+++ /dev/null
@@ -1,518 +0,0 @@
-From bb0970825fa8702d8b5dea94d9fc97c1041db338 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 23 Sep 2014 16:27:23 +0200
-Subject: [PATCH 23/46] UTIL: Add a function to convert id_t from a number or a
- name
-
-We need a custom function that would convert a numeric or string input
-into uid_t. The function will be used to drop privileges in servers and
-also in the PAC and IFP responders.
-
-Includes a unit test to test all code that changed as well as a fix for
-a misnamed attribute in the csv_to_uid_list function synopsis.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 5eda23c28c582b43b2a0a165b1750f3875c0fa84)
----
- src/responder/common/responder.h        |   2 +-
- src/responder/common/responder_common.c |  17 ++--
- src/tests/cwrap/Makefile.am             |  54 ++++++++++++
- src/tests/cwrap/passwd                  |   3 +-
- src/tests/cwrap/test_responder_common.c | 144 ++++++++++++++++++++++++++++++++
- src/tests/cwrap/test_usertools.c        | 106 +++++++++++++++++++++++
- src/util/usertools.c                    |  44 ++++++++++
- src/util/util.c                         |   1 +
- src/util/util.h                         |   2 +
- 9 files changed, 360 insertions(+), 13 deletions(-)
- create mode 100644 src/tests/cwrap/test_responder_common.c
- create mode 100644 src/tests/cwrap/test_usertools.c
-
-diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
-index 3674d13f2303d0ce248f765a638aaa83d0c16cf3..97552ec472c5baa285b41cc48b51149f3ef6adb5 100644
---- a/src/responder/common/responder.h
-+++ b/src/responder/common/responder.h
-@@ -308,7 +308,7 @@ errno_t schedule_get_domains_task(TALLOC_CTX *mem_ctx,
-                                   struct tevent_context *ev,
-                                   struct resp_ctx *rctx);
- 
--errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *cvs_string,
-+errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
-                                 bool allow_sss_loop,
-                                 size_t *_uid_count, uid_t **_uids);
- 
-diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
-index b7331ac8ab1de51839937d117968e92062af76d7..0ec2372e8d08f1002b303b5edc6897f17cee9699 100644
---- a/src/responder/common/responder_common.c
-+++ b/src/responder/common/responder_common.c
-@@ -159,7 +159,7 @@ errno_t check_allowed_uids(uid_t uid, size_t allowed_uids_count,
-     return EACCES;
- }
- 
--errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *cvs_string,
-+errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
-                                 bool allow_sss_loop,
-                                 size_t *_uid_count, uid_t **_uids)
- {
-@@ -169,9 +169,8 @@ errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *cvs_string,
-     int list_size;
-     uid_t *uids = NULL;
-     char *endptr;
--    struct passwd *pwd;
- 
--    ret = split_on_separator(mem_ctx, cvs_string, ',', true, false,
-+    ret = split_on_separator(mem_ctx, csv_string, ',', true, false,
-                              &list, &list_size);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed [%d][%s].\n",
-@@ -211,17 +210,13 @@ errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *cvs_string,
-                 goto done;
-             }
- 
--            errno = 0;
--            pwd = getpwnam(list[c]);
--            if (pwd == NULL) {
-+            ret = sss_user_by_name_or_uid(list[c], &uids[c], NULL);
-+            if (ret != EOK) {
-                 DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is neither a valid "
--                                          "UID nor a user name which cloud be "
--                                          "resolved by getpwnam().\n", list[c]);
--                ret = EINVAL;
-+                                         "UID nor a user name which could be "
-+                                         "resolved by getpwnam().\n", list[c]);
-                 goto done;
-             }
--
--            uids[c] = pwd->pw_uid;
-         }
-     }
- 
-diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
-index d1f0e9e1b999814d8081af36f82e94f638452da4..02be67387110c0a440b647c35bba0c10e89e699d 100644
---- a/src/tests/cwrap/Makefile.am
-+++ b/src/tests/cwrap/Makefile.am
-@@ -45,6 +45,8 @@ if HAVE_UID_WRAPPER
- check_PROGRAMS += \
-     become_user-tests \
-     server-tests \
-+    usertools-tests \
-+    responder_common-tests \
-     $(NULL)
- endif # HAVE_UID_WRAPPER
- endif # HAVE_NSS_WRAPPER
-@@ -106,4 +108,56 @@ server_tests_LDADD = \
-     $(abs_top_builddir)/libsss_test_common.la \
-     $(NULL)
- 
-+usertools_tests_SOURCES = \
-+    test_usertools.c \
-+    ../../../src/util/domain_info_utils.c \
-+    ../../../src/util/safe-format-string.c \
-+    ../../../src/util/usertools.c \
-+    ../../../src/util/strtonum.c \
-+    ../../../src/util/backup_file.c \
-+    ../../../src/util/atomic_io.c \
-+    ../../../src/util/util.c \
-+    ../../../src/util/util_errors.c \
-+    ../../../src/util/sss_tc_utf8.c \
-+    ../../../src/util/sss_utf8.c \
-+    ../../../src/confdb/confdb.c \
-+    ../../../src/db/sysdb.c \
-+    ../../../src/db/sysdb_upgrade.c \
-+    ../../../src/db/sysdb_autofs.c \
-+    ../../../src/db/sysdb_search.c \
-+    ../../../src/db/sysdb_services.c \
-+    ../../../src/db/sysdb_ops.c \
-+    ../../../src/db/sysdb_views.c \
-+    $(NULL)
-+usertools_tests_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(NULL)
-+usertools_tests_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(UNICODE_LIBS) \
-+    $(SSSD_LIBS) \
-+    $(abs_top_builddir)/libsss_debug.la \
-+    $(abs_top_builddir)/libsss_crypt.la \
-+    $(abs_top_builddir)/libsss_test_common.la \
-+    $(NULL)
-+
-+responder_common_tests_SOURCES =\
-+    test_responder_common.c \
-+    ../../../src/responder/common/responder_common.c \
-+    ../../../src/responder/common/responder_packet.c \
-+    ../../../src/responder/common/responder_cmd.c \
-+    $(NULL)
-+responder_common_tests_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(NULL)
-+responder_common_tests_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(UNICODE_LIBS) \
-+    $(SSSD_LIBS) \
-+    $(abs_top_builddir)/libsss_debug.la \
-+    $(abs_top_builddir)/libsss_crypt.la \
-+    $(abs_top_builddir)/libsss_util.la \
-+    $(abs_top_builddir)/libsss_test_common.la \
-+    $(NULL)
-+
- tests: $(check_PROGRAMS)
-diff --git a/src/tests/cwrap/passwd b/src/tests/cwrap/passwd
-index aa0a97db5259172c0b4ab47c7c2346fa5c2aa88e..862ccfe03e40d43c60c56b0c50f328f494d7e6b9 100644
---- a/src/tests/cwrap/passwd
-+++ b/src/tests/cwrap/passwd
-@@ -1 +1,2 @@
--sssd:x:123:123:sssd unprivileged user:/:/sbin/nologin
-+sssd:x:123:456:sssd unprivileged user:/:/sbin/nologin
-+foobar:x:10001:10001:User for SSSD testing:/home/foobar:/bin/bash
-diff --git a/src/tests/cwrap/test_responder_common.c b/src/tests/cwrap/test_responder_common.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..23dcf753f184cdecaf39c73c6e9be0e23e6df968
---- /dev/null
-+++ b/src/tests/cwrap/test_responder_common.c
-@@ -0,0 +1,144 @@
-+/*
-+    Authors:
-+        Jakub Hrozek <jhrozek@redhat.com>
-+
-+    Copyright (C) 2014 Red Hat
-+
-+    SSSD tests: User utilities
-+
-+    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 <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+
-+#include <popt.h>
-+#include "util/util.h"
-+#include "responder/common/responder.h"
-+#include "tests/cmocka/common_mock.h"
-+
-+/* Just to satisfy dependencies */
-+struct cli_protocol_version *register_cli_protocol_version(void)
-+{
-+    static struct cli_protocol_version responder_test_cli_protocol_version[] = {
-+        {0, NULL, NULL}
-+    };
-+
-+    return responder_test_cli_protocol_version;
-+}
-+
-+void test_uid_csv_to_uid_list(void **state)
-+{
-+    TALLOC_CTX *tmp_ctx;
-+    errno_t ret;
-+    size_t count;
-+    uid_t *list;
-+
-+    tmp_ctx = talloc_new(global_talloc_context);
-+    assert_non_null(tmp_ctx);
-+
-+    check_leaks_push(tmp_ctx);
-+
-+    ret = csv_string_to_uid_array(tmp_ctx, "1, 2, 3", false, &count, &list);
-+    assert_int_equal(ret, EOK);
-+    assert_int_equal(count, 3);
-+    assert_int_equal(list[0], 1);
-+    assert_int_equal(list[1], 2);
-+    assert_int_equal(list[2], 3);
-+
-+    talloc_free(list);
-+    check_leaks_pop(tmp_ctx);
-+    talloc_free(tmp_ctx);
-+}
-+
-+void test_name_csv_to_uid_list(void **state)
-+{
-+    TALLOC_CTX *tmp_ctx;
-+    errno_t ret;
-+    size_t count;
-+    uid_t *list;
-+
-+    tmp_ctx = talloc_new(global_talloc_context);
-+    assert_non_null(tmp_ctx);
-+
-+    check_leaks_push(tmp_ctx);
-+
-+    ret = csv_string_to_uid_array(tmp_ctx, "sssd, foobar", true, &count, &list);
-+    assert_int_equal(ret, EOK);
-+    assert_int_equal(count, 2);
-+    assert_int_equal(list[0], 123);
-+    assert_int_equal(list[1], 10001);
-+
-+    talloc_free(list);
-+    check_leaks_pop(tmp_ctx);
-+    talloc_free(tmp_ctx);
-+}
-+
-+void test_csv_to_uid_list_neg(void **state)
-+{
-+    TALLOC_CTX *tmp_ctx;
-+    errno_t ret;
-+    size_t count;
-+    uid_t *list = NULL;
-+
-+    tmp_ctx = talloc_new(global_talloc_context);
-+    assert_non_null(tmp_ctx);
-+
-+    check_leaks_push(tmp_ctx);
-+
-+    ret = csv_string_to_uid_array(tmp_ctx, "nosuchuser", true, &count, &list);
-+    assert_int_not_equal(ret, EOK);
-+
-+    check_leaks_pop(tmp_ctx);
-+    talloc_free(tmp_ctx);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    poptContext pc;
-+    int opt;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test(test_uid_csv_to_uid_list),
-+        unit_test(test_name_csv_to_uid_list),
-+        unit_test(test_csv_to_uid_list_neg),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    tests_set_cwd();
-+
-+    return run_tests(tests);
-+}
-diff --git a/src/tests/cwrap/test_usertools.c b/src/tests/cwrap/test_usertools.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..6423059456a06f0c8f8ebdd803641b7207e862fd
---- /dev/null
-+++ b/src/tests/cwrap/test_usertools.c
-@@ -0,0 +1,106 @@
-+/*
-+    Authors:
-+        Jakub Hrozek <jhrozek@redhat.com>
-+
-+    Copyright (C) 2014 Red Hat
-+
-+    SSSD tests: User utilities
-+
-+    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 <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+
-+#include <popt.h>
-+#include "util/util.h"
-+#include "tests/cmocka/common_mock.h"
-+
-+void test_get_user_num(void **state)
-+{
-+    uid_t uid;
-+    gid_t gid;
-+    errno_t ret;
-+
-+    ret = sss_user_by_name_or_uid("123", &uid, &gid);
-+    assert_int_equal(ret, EOK);
-+    assert_int_equal(uid, 123);
-+    assert_int_equal(gid, 456);
-+}
-+
-+void test_get_user_str(void **state)
-+{
-+    uid_t uid;
-+    gid_t gid;
-+    errno_t ret;
-+
-+    ret = sss_user_by_name_or_uid("sssd", &uid, &gid);
-+    assert_int_equal(ret, EOK);
-+    assert_int_equal(uid, 123);
-+    assert_int_equal(gid, 456);
-+}
-+
-+void test_get_user_nullparm(void **state)
-+{
-+    uid_t uid;
-+    gid_t gid;
-+    errno_t ret;
-+
-+    ret = sss_user_by_name_or_uid("sssd", &uid, NULL);
-+    assert_int_equal(ret, EOK);
-+    assert_int_equal(uid, 123);
-+
-+    ret = sss_user_by_name_or_uid("sssd", NULL, &gid);
-+    assert_int_equal(ret, EOK);
-+    assert_int_equal(gid, 456);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    poptContext pc;
-+    int opt;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test(test_get_user_num),
-+        unit_test(test_get_user_str),
-+        unit_test(test_get_user_nullparm),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    tests_set_cwd();
-+
-+    return run_tests(tests);
-+}
-diff --git a/src/util/usertools.c b/src/util/usertools.c
-index 809b42d67c7b1cdfa0729c3a7e835fab37297596..a0b914e2fe8f65a71015944e63cb2d2813345d84 100644
---- a/src/util/usertools.c
-+++ b/src/util/usertools.c
-@@ -23,8 +23,11 @@
- #include <pcre.h>
- #include <errno.h>
- #include <talloc.h>
-+#include <pwd.h>
-+#include <grp.h>
- 
- #include "confdb/confdb.h"
-+#include "util/strtonum.h"
- #include "util/util.h"
- #include "util/safe-format-string.h"
- #include "responder/common/responder.h"
-@@ -659,3 +662,44 @@ sss_get_domain_name(TALLOC_CTX *mem_ctx,
- 
-     return user_name;
- }
-+
-+errno_t sss_user_by_name_or_uid(const char *input, uid_t *_uid, gid_t *_gid)
-+{
-+    uid_t uid;
-+    errno_t ret;
-+    char *endptr;
-+    struct passwd *pwd;
-+
-+    /* Try if it's an ID first */
-+    errno = 0;
-+    uid = strtouint32(input, &endptr, 10);
-+    if (errno != 0 || *endptr != '\0') {
-+        ret = errno;
-+        if (ret == ERANGE) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "UID [%s] is out of range.\n", input);
-+            return ret;
-+        }
-+
-+        /* Nope, maybe a username? */
-+        pwd = getpwnam(input);
-+    } else {
-+        pwd = getpwuid(uid);
-+    }
-+
-+    if (pwd == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "[%s] is neither a valid UID nor a user name which could be "
-+              "resolved by getpwnam().\n", input);
-+        return EINVAL;
-+    }
-+
-+    if (_uid) {
-+        *_uid = pwd->pw_uid;
-+    }
-+
-+    if (_gid) {
-+        *_gid = pwd->pw_gid;
-+    }
-+    return EOK;
-+}
-diff --git a/src/util/util.c b/src/util/util.c
-index 7f80771ecd9868feaf43e34cbd61e44dd8ae5f3a..d78d37d975e6591bca6ac3f2fa36b5b9f4659a29 100644
---- a/src/util/util.c
-+++ b/src/util/util.c
-@@ -21,6 +21,7 @@
- #include <ctype.h>
- #include <netdb.h>
- #include <poll.h>
-+#include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <talloc.h>
-diff --git a/src/util/util.h b/src/util/util.h
-index df83aac7d53ccadb806e8a1be90f0e45abb829ae..69074c93c1640a1e4a7e590b7f9feb6cc04804a4 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -404,6 +404,8 @@ bool check_ipv6_addr(struct in6_addr *addr, uint8_t check);
- 
- const char * const * get_known_services(void);
- 
-+errno_t sss_user_by_name_or_uid(const char *input, uid_t *_uid, gid_t *_gid);
-+
- int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
-                        const char sep, bool trim, bool skip_empty,
-                        char ***_list, int *size);
--- 
-1.9.3
-
diff --git a/SOURCES/0024-BUILD-Add-a-config-option-for-sssd-user-own-private-.patch b/SOURCES/0024-BUILD-Add-a-config-option-for-sssd-user-own-private-.patch
deleted file mode 100644
index b75f699..0000000
--- a/SOURCES/0024-BUILD-Add-a-config-option-for-sssd-user-own-private-.patch
+++ /dev/null
@@ -1,116 +0,0 @@
-From f504126d3d54b5b1b5467b59616255ef4c46d1be Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 1 Oct 2014 14:47:09 +0200
-Subject: [PATCH 24/46] BUILD: Add a config option for sssd user, own private
- directories as the user
-
-Adds a new configure-time option that lets you select the user to run
-SSSD as. The default is 'root' for backwards compatibility.
-
-The directories the deamon stores its private data at are also created
-as owned by this user during install time.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit bc13c352ba9c2877f1e9bc62e55ad60fc000a55d)
----
- Makefile.am        | 23 +++++++++++++++++------
- configure.ac       |  1 +
- src/conf_macros.m4 | 19 +++++++++++++++++++
- 3 files changed, 37 insertions(+), 6 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index b949c9c24070026570de970b545918a7eb279c6d..61bf5cf957d4024b67f48cf42f5735b5fa368945 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -78,6 +78,14 @@ sudolibdir = @sudolibpath@
- UNICODE_LIBS=@UNICODE_LIBS@
- 
- MKDIR_P = @MKDIR_P@
-+INSTALL = @INSTALL@
-+
-+SSSD_USER = @SSSD_USER@
-+
-+INSTALL_USER_DIR_FLAGS = -d
-+if SSSD_USER
-+INSTALL_USER_DIR_FLAGS += -o $(SSSD_USER) -g $(SSSD_USER)
-+endif
- 
- AM_CFLAGS =
- if WANT_AUX_INFO
-@@ -2740,24 +2748,27 @@ installsssddirs::
-     $(DESTDIR)$(bindir) \
-     $(DESTDIR)$(sbindir) \
-     $(DESTDIR)$(mandir) \
-+    $(DESTDIR)$(pidpath) \
-     $(DESTDIR)$(pluginpath) \
-     $(DESTDIR)$(libdir)/ldb \
-     $(DESTDIR)$(dbuspolicydir) \
-     $(DESTDIR)$(dbusservicedir) \
--    $(DESTDIR)$(pipepath)/private \
-     $(DESTDIR)$(sssdlibdir) \
-     $(DESTDIR)$(pkglibdir) \
--    $(DESTDIR)$(sssdconfdir) \
-     $(DESTDIR)$(sssddatadir) \
-+    $(DESTDIR)$(sudolibdir) \
-+    $(DESTDIR)$(autofslibdir) \
-+    $(NULL); \
-+	$(INSTALL) $(INSTALL_USER_DIR_FLAGS) \
-     $(DESTDIR)$(dbpath) \
-     $(DESTDIR)$(mcpath) \
--    $(DESTDIR)$(pidpath) \
--    $(DESTDIR)$(logpath) \
-+    $(DESTDIR)$(pipepath) \
-+    $(DESTDIR)$(pipepath)/private \
-     $(DESTDIR)$(pubconfpath) \
-     $(DESTDIR)$(pubconfpath)/krb5.include.d \
-     $(DESTDIR)$(gpocachepath) \
--    $(DESTDIR)$(sudolibdir) \
--    $(DESTDIR)$(autofslibdir) \
-+    $(DESTDIR)$(sssdconfdir) \
-+    $(DESTDIR)$(logpath) \
-     $(NULL)
- 
- if HAVE_DOXYGEN
-diff --git a/configure.ac b/configure.ac
-index e6745cb454624d1d62e1a827c2fbf557f6502ae9..e5ec204ad9671d15deb1830c60168e066a66f198 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -137,6 +137,7 @@ WITH_SAMBA
- WITH_NFS
- WITH_NFS_LIB_PATH
- WITH_LIBWBCLIENT
-+WITH_SSSD_USER
- 
- m4_include([src/external/pkg.m4])
- m4_include([src/external/libpopt.m4])
-diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
-index 4aa58138c85db9266fd3f1765fc357b3fd104941..fbee81f56e484b618379f7c987ecee50ae48917e 100644
---- a/src/conf_macros.m4
-+++ b/src/conf_macros.m4
-@@ -737,3 +737,22 @@ AC_DEFUN([WITH_NFS_LIB_PATH],
-     fi
-     AC_SUBST(nfslibpath)
-   ])
-+
-+AC_DEFUN([WITH_SSSD_USER],
-+  [ AC_ARG_WITH([sssd-user],
-+                [AS_HELP_STRING([--with-sssd-user=<user>],
-+                                [User for running SSSD (root)]
-+                               )
-+                ]
-+               )
-+
-+    SSSD_USER=root
-+
-+    if test x"$with_sssd_user" != x; then
-+        SSSD_USER=$with_sssd_user
-+    fi
-+
-+    AC_SUBST(SSSD_USER)
-+    AC_DEFINE_UNQUOTED(SSSD_USER, "$SSSD_USER", ["The default user to run SSSD as"])
-+    AM_CONDITIONAL([SSSD_USER], [test x"$with_sssd_user" != x])
-+  ])
--- 
-1.9.3
-
diff --git a/SOURCES/0024-IPA-Better-debugging.patch b/SOURCES/0024-IPA-Better-debugging.patch
new file mode 100644
index 0000000..d589ad3
--- /dev/null
+++ b/SOURCES/0024-IPA-Better-debugging.patch
@@ -0,0 +1,27 @@
+From a42ad73cc1aca7b923c3a7ebd01580378888f002 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 22 Jul 2015 15:17:57 +0200
+Subject: [PATCH 24/27] IPA: Better debugging
+
+Reviewed-by: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ src/providers/ipa/ipa_subdomains_server.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
+index cd8c6301c4e4fbbf194ca98ce7a7bfe6215b381c..a9e2c1f700ef47716be868bad68590b8d5d0d42a 100644
+--- a/src/providers/ipa/ipa_subdomains_server.c
++++ b/src/providers/ipa/ipa_subdomains_server.c
+@@ -623,6 +623,9 @@ ipa_server_trust_add_send(TALLOC_CTX *mem_ctx,
+ 
+ immediate:
+     if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Could not add trusted subdomain %s from forest %s\n",
++              subdom->name, state->forest);
+         tevent_req_error(req, ret);
+     } else {
+         tevent_req_done(req);
+-- 
+2.4.3
+
diff --git a/SOURCES/0025-RPM-Change-file-ownership-to-sssd.sssd.patch b/SOURCES/0025-RPM-Change-file-ownership-to-sssd.sssd.patch
deleted file mode 100644
index ff8be93..0000000
--- a/SOURCES/0025-RPM-Change-file-ownership-to-sssd.sssd.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From d140aa913a0aad28b151c79f4c6f7ff5d8fee6c9 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 5 Aug 2014 13:53:20 +0200
-Subject: [PATCH 25/46] RPM: Change file ownership to sssd.sssd
-
-Adds a private SSSD user in the %pre section of SSSD specfile. Also
-changes the ownership of SSSD private directories to sssd.sssd.
-
-Does not change the configure time default, so SSSD will still run as
-root. The file and directory ownership does not widen, because the
-directories are still only accessible by the private user (whose shell
-is /sbin/nologin) and of course the root user.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit fa24dabfd480e1ce346009336c7979ab59520c44)
----
- contrib/sssd.spec.in | 26 +++++++++++++++-----------
- 1 file changed, 15 insertions(+), 11 deletions(-)
-
-diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
-index e5de4c44c4b4982f6819af363fdb8a32930f6137..db3bbcb09d6b27ca785f511ce6414fbeaaf445c6 100644
---- a/contrib/sssd.spec.in
-+++ b/contrib/sssd.spec.in
-@@ -604,17 +604,17 @@ rm -rf $RPM_BUILD_ROOT
- 
- %dir %{sssdstatedir}
- %dir %{_localstatedir}/cache/krb5rcache
--%attr(700,root,root) %dir %{dbpath}
--%attr(755,root,root) %dir %{mcpath}
--%ghost %attr(0644,root,root) %verify(not md5 size mtime) %{mcpath}/passwd
--%ghost %attr(0644,root,root) %verify(not md5 size mtime) %{mcpath}/group
--%attr(755,root,root) %dir %{pipepath}
--%attr(755,root,root) %dir %{pubconfpath}
--%attr(755,root,root) %dir %{gpocachepath}
--%attr(700,root,root) %dir %{pipepath}/private
--%attr(750,root,root) %dir %{_var}/log/%{name}
--%attr(711,root,root) %dir %{_sysconfdir}/sssd
--%ghost %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/sssd/sssd.conf
-+%attr(700,sssd,sssd) %dir %{dbpath}
-+%attr(755,sssd,sssd) %dir %{mcpath}
-+%ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/passwd
-+%ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/group
-+%attr(755,sssd,sssd) %dir %{pipepath}
-+%attr(755,sssd,sssd) %dir %{pubconfpath}
-+%attr(755,sssd,sssd) %dir %{gpocachepath}
-+%attr(700,sssd,sssd) %dir %{pipepath}/private
-+%attr(750,sssd,sssd) %dir %{_var}/log/%{name}
-+%attr(711,sssd,sssd) %dir %{_sysconfdir}/sssd
-+%ghost %attr(0600,sssd,sssd) %config(noreplace) %{_sysconfdir}/sssd/sssd.conf
- %if (0%{?use_systemd} == 1)
- %attr(755,root,root) %dir %{_sysconfdir}/systemd/system/sssd.service.d
- %config(noreplace) %{_sysconfdir}/systemd/system/sssd.service.d/journal.conf
-@@ -803,6 +803,10 @@ rm -rf $RPM_BUILD_ROOT
- %{_libdir}/%{name}/modules/libwbclient.so
- %{_libdir}/pkgconfig/wbclient_sssd.pc
- 
-+%pre common
-+getent group sssd >/dev/null || groupadd -r sssd
-+getent passwd sssd >/dev/null || useradd -r -g sssd -d / -s /sbin/nologin -c "User for sssd" sssd
-+
- %if (0%{?use_systemd} == 1)
- # systemd
- %post common
--- 
-1.9.3
-
diff --git a/SOURCES/0025-UTIL-Lower-debug-level-in-perform_checks.patch b/SOURCES/0025-UTIL-Lower-debug-level-in-perform_checks.patch
new file mode 100644
index 0000000..c0b93de
--- /dev/null
+++ b/SOURCES/0025-UTIL-Lower-debug-level-in-perform_checks.patch
@@ -0,0 +1,50 @@
+From ce03dffa77053f837ff4d7e0fbb3208118f2d768 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 22 Jul 2015 16:29:09 +0200
+Subject: [PATCH 25/27] UTIL: Lower debug level in perform_checks()
+
+Failures in perform_checks() don't have to be fatal, therefore the debug
+messages shouldn't be either.
+
+Reviewed-by: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ src/util/check_and_open.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/util/check_and_open.c b/src/util/check_and_open.c
+index 59b90bf4b96731e385fcf92ed8bc251cb94abfda..b40ae2003e3de22ce9e4ca07cecc68e18a7abab4 100644
+--- a/src/util/check_and_open.c
++++ b/src/util/check_and_open.c
+@@ -99,12 +99,12 @@ static errno_t perform_checks(struct stat *stat_buf,
+     }
+ 
+     if ((mode & S_IFMT) != (st_mode & S_IFMT)) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "File is not the right type.\n");
++        DEBUG(SSSDBG_TRACE_LIBS, "File is not the right type.\n");
+         return EINVAL;
+     }
+ 
+     if ((st_mode & ALLPERMS) != (mode & ALLPERMS)) {
+-        DEBUG(SSSDBG_CRIT_FAILURE,
++        DEBUG(SSSDBG_TRACE_LIBS,
+               "File has the wrong (bit masked) mode [%.7o], "
+               "expected [%.7o].\n",
+               (st_mode & ALLPERMS), (mode & ALLPERMS));
+@@ -112,12 +112,12 @@ static errno_t perform_checks(struct stat *stat_buf,
+     }
+ 
+     if (uid != (uid_t)(-1) && stat_buf->st_uid != uid) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "File must be owned by uid [%d].\n", uid);
++        DEBUG(SSSDBG_TRACE_LIBS, "File must be owned by uid [%d].\n", uid);
+         return EINVAL;
+     }
+ 
+     if (gid != (gid_t)(-1) && stat_buf->st_gid != gid) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "File must be owned by gid [%d].\n", gid);
++        DEBUG(SSSDBG_TRACE_LIBS, "File must be owned by gid [%d].\n", gid);
+         return EINVAL;
+     }
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch b/SOURCES/0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch
new file mode 100644
index 0000000..fceec58
--- /dev/null
+++ b/SOURCES/0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch
@@ -0,0 +1,116 @@
+From dba7ccc7594be1881967aa274090d61a97aec5fa Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 22 Jul 2015 17:20:11 +0200
+Subject: [PATCH 26/27] IPA: Handle sssd-owned keytabs when running as root
+
+https://fedorahosted.org/sssd/ticket/2718
+
+This patch handles the case where the keytab is created with sssd:sssd
+ownership (perhaps by the IPA oddjob script) but SSSD runs as root,
+which is the default in many distributions.
+
+Reviewed-by: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ src/providers/ipa/ipa_subdomains.h        |  3 ++
+ src/providers/ipa/ipa_subdomains_server.c | 46 +++++++++++++++++++++++++------
+ 2 files changed, 41 insertions(+), 8 deletions(-)
+
+diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h
+index 5bc63a173a1a8967eb5de30a2da84a81377d3900..2302c5f03e80de2ea1efad424769e777cd6dd8d5 100644
+--- a/src/providers/ipa/ipa_subdomains.h
++++ b/src/providers/ipa/ipa_subdomains.h
+@@ -94,6 +94,9 @@ struct ipa_server_mode_ctx {
+ 
+     struct ipa_ad_server_ctx *trusts;
+     struct ipa_ext_groups *ext_groups;
++
++    uid_t kt_owner_uid;
++    uid_t kt_owner_gid;
+ };
+ 
+ int ipa_ad_subdom_init(struct be_ctx *be_ctx,
+diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
+index a9e2c1f700ef47716be868bad68590b8d5d0d42a..4bfea61e6dd0a02f6b723a39f7ba236c914009b0 100644
+--- a/src/providers/ipa/ipa_subdomains_server.c
++++ b/src/providers/ipa/ipa_subdomains_server.c
+@@ -520,16 +520,28 @@ static errno_t ipa_getkeytab_recv(struct tevent_req *req, int *child_status)
+     return EOK;
+ }
+ 
+-static errno_t ipa_check_keytab(const char *keytab)
++static errno_t ipa_check_keytab(const char *keytab,
++                                uid_t kt_owner_uid,
++                                gid_t kt_owner_gid)
+ {
+     errno_t ret;
+ 
+     ret = check_file(keytab, getuid(), getgid(), S_IFREG|0600, 0, NULL, false);
+-    if (ret != EOK) {
+-        if (ret != ENOENT) {
+-            DEBUG(SSSDBG_OP_FAILURE, "Failed to check for %s\n", keytab);
+-        } else {
+-            DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab);
++    if (ret == ENOENT) {
++        DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab);
++        goto done;
++    } else if (ret != EOK) {
++        if (kt_owner_uid) {
++            ret = check_file(keytab, kt_owner_uid, kt_owner_gid,
++                             S_IFREG|0600, 0, NULL, false);
++        }
++
++        if (ret != EOK) {
++            if (ret != ENOENT) {
++                DEBUG(SSSDBG_OP_FAILURE, "Failed to check for %s\n", keytab);
++            } else {
++                DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab);
++            }
+         }
+         goto done;
+     }
+@@ -648,7 +660,9 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req)
+         return EIO;
+     }
+ 
+-    ret = ipa_check_keytab(state->keytab);
++    ret = ipa_check_keytab(state->keytab,
++                           state->id_ctx->server_mode->kt_owner_uid,
++                           state->id_ctx->server_mode->kt_owner_gid);
+     if (ret == EOK) {
+         DEBUG(SSSDBG_TRACE_FUNC,
+               "Keytab already present, can add the trust\n");
+@@ -704,7 +718,9 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq)
+     DEBUG(SSSDBG_TRACE_FUNC,
+           "Keytab successfully retrieved to %s\n", state->keytab);
+ 
+-    ret = ipa_check_keytab(state->keytab);
++    ret = ipa_check_keytab(state->keytab,
++                           state->id_ctx->server_mode->kt_owner_uid,
++                           state->id_ctx->server_mode->kt_owner_gid);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "ipa_check_keytab failed: %d\n", ret);
+         tevent_req_error(req, ret);
+@@ -1029,6 +1045,20 @@ int ipa_ad_subdom_init(struct be_ctx *be_ctx,
+     id_ctx->server_mode->hostname = hostname;
+     id_ctx->server_mode->trusts = NULL;
+     id_ctx->server_mode->ext_groups = NULL;
++    id_ctx->server_mode->kt_owner_uid = 0;
++    id_ctx->server_mode->kt_owner_gid = 0;
++
++    if (getuid() == 0) {
++        /* We need to handle keytabs created by IPA oddjob script gracefully
++         * even if we're running as root and IPA creates them as the SSSD user
++         */
++        ret = sss_user_by_name_or_uid(SSSD_USER,
++                                      &id_ctx->server_mode->kt_owner_uid,
++                                      &id_ctx->server_mode->kt_owner_gid);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_MINOR_FAILURE, "Failed to get ID of %s\n", SSSD_USER);
++        }
++    }
+ 
+     ret = ipa_ad_subdom_reinit(be_ctx, be_ctx->ev,
+                                be_ctx, id_ctx, be_ctx->domain);
+-- 
+2.4.3
+
diff --git a/SOURCES/0026-SSSD-Load-a-user-to-run-a-service-as-from-configurat.patch b/SOURCES/0026-SSSD-Load-a-user-to-run-a-service-as-from-configurat.patch
deleted file mode 100644
index 646f2f7..0000000
--- a/SOURCES/0026-SSSD-Load-a-user-to-run-a-service-as-from-configurat.patch
+++ /dev/null
@@ -1,216 +0,0 @@
-From b8a3625690f39e22d8cd699598384bad472b6373 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 5 Aug 2014 13:52:48 +0200
-Subject: [PATCH 26/46] SSSD: Load a user to run a service as from
- configuration
-
-Related:
-    https://fedorahosted.org/sssd/ticket/2370
-
-Adds a option, user to run as, that is specified in the [sssd] section. When
-this option is specified, SSSD will run as this user and his private
-group. When these are not specified, SSSD will run as the configure-time
-user and group (usually root).
-
-Currently all services and providers are started as root. There is a
-temporary svc_supported_as_nonroot() function that returns true for a
-service if that service runs and was tested as nonroot and false
-otherwise. Currently this function always returns false, but will be
-amended in future patches.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit a10ac1d0a7210def232205a48c53a075930e82f6)
----
- src/confdb/confdb.h                  |  1 +
- src/config/SSSDConfig/__init__.py.in |  1 +
- src/config/SSSDConfigTest.py         |  1 +
- src/config/etc/sssd.api.conf         |  1 +
- src/man/sssd.conf.5.xml              | 13 +++++++++
- src/monitor/monitor.c                | 56 ++++++++++++++++++++++++++++++++++++
- 6 files changed, 73 insertions(+)
-
-diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
-index 34d4610654c24017bcad8608332c71232d665d40..159aa9f2c44ed91c94a40c98d5a7710793f0aa85 100644
---- a/src/confdb/confdb.h
-+++ b/src/confdb/confdb.h
-@@ -69,6 +69,7 @@
- #define CONFDB_MONITOR_KRB5_RCACHEDIR "krb5_rcache_dir"
- #define CONFDB_MONITOR_DEFAULT_DOMAIN "default_domain_suffix"
- #define CONFDB_MONITOR_OVERRIDE_SPACE "override_space"
-+#define CONFDB_MONITOR_USER_RUNAS "user"
- 
- /* Both monitor and domains */
- #define CONFDB_NAME_REGEX   "re_expression"
-diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
-index 6c95530868d7c078ccf13622f3ba916392b0c732..b4560ea2b33f2c3b82bff42fb6a36302a146c99f 100644
---- a/src/config/SSSDConfig/__init__.py.in
-+++ b/src/config/SSSDConfig/__init__.py.in
-@@ -56,6 +56,7 @@ option_strings = {
-     'full_name_format' : _('Printf-compatible format for displaying fully-qualified names'),
-     'krb5_rcache_dir' : _('Directory on the filesystem where SSSD should store Kerberos replay cache files.'),
-     'default_domain_suffix' : _('Domain to add to names without a domain component.'),
-+    'user' : _('The user to drop privileges to'),
- 
-     # [nss]
-     'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'),
-diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
-index 2d12bc02af1768d22c8bfa9a21b1fc24bf199af4..78e22f6eff19aac8289d769dc9f565b2d548f4b3 100755
---- a/src/config/SSSDConfigTest.py
-+++ b/src/config/SSSDConfigTest.py
-@@ -280,6 +280,7 @@ class SSSDConfigTestSSSDService(unittest.TestCase):
-             're_expression',
-             'full_name_format',
-             'krb5_rcache_dir',
-+            'user',
-             'default_domain_suffix',
-             'debug_level',
-             'debug_timestamps',
-diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
-index a20f5aa44dbadd24f644bffc9954df9e088979b9..c16769a3985f495922d255dacebccc11f6a0ea1d 100644
---- a/src/config/etc/sssd.api.conf
-+++ b/src/config/etc/sssd.api.conf
-@@ -23,6 +23,7 @@ sbus_timeout = int, None, false
- re_expression = str, None, false
- full_name_format = str, None, false
- krb5_rcache_dir = str, None, false
-+user = str, None, false
- default_domain_suffix = str, None, false
- 
- [nss]
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index 77690432b841221328d65403830cf4a1ac12dba0..e2cb0b81b61063750995064b6ce83f9615049534 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -297,6 +297,19 @@
-                         </listitem>
-                     </varlistentry>
-                     <varlistentry>
-+                        <term>user (string)</term>
-+                        <listitem>
-+                            <para>
-+                                The user to drop the privileges to where
-+                                appropriate to avoid running as the
-+                                root user.
-+                            </para>
-+                            <para>
-+                                Default: not set, process will run as root
-+                            </para>
-+                        </listitem>
-+                    </varlistentry>
-+                    <varlistentry>
-                         <term>default_domain_suffix (string)</term>
-                         <listitem>
-                             <para>
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index edd1c2dfc674d8a7ca9d069d6499c0dcc959f210..df1cd5ca14c759f7aab98094a2b8ad35731c35e6 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -170,6 +170,10 @@ struct mt_ctx {
-     struct sss_sigchild_ctx *sigchld_ctx;
-     bool is_daemon;
-     pid_t parent_pid;
-+
-+    /* For running unprivileged services */
-+    uid_t uid;
-+    gid_t gid;
- };
- 
- static int start_service(struct mt_svc *mt_svc);
-@@ -910,6 +914,29 @@ static char *check_services(char **services)
-     return NULL;
- }
- 
-+static int get_service_user(struct mt_ctx *ctx)
-+{
-+    errno_t ret;
-+    char *user_str;
-+
-+    ret = confdb_get_string(ctx->cdb, ctx, CONFDB_MONITOR_CONF_ENTRY,
-+                            CONFDB_MONITOR_USER_RUNAS,
-+                            SSSD_USER, &user_str);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get the user to run as\n");
-+        return ret;
-+    }
-+
-+    ret = sss_user_by_name_or_uid(user_str, &ctx->uid, &ctx->gid);
-+    talloc_free(user_str);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n");
-+        return ret;
-+    }
-+
-+    return EOK;
-+}
-+
- static int get_monitor_config(struct mt_ctx *ctx)
- {
-     int ret;
-@@ -955,6 +982,12 @@ static int get_monitor_config(struct mt_ctx *ctx)
-         ctx->num_services++;
-     }
- 
-+    ret = get_service_user(ctx);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get the unprivileged user\n");
-+        return ret;
-+    }
-+
-     ret = confdb_get_domains(ctx->cdb, &ctx->domains);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured.\n");
-@@ -1020,6 +1053,14 @@ static errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
-     return EOK;
- }
- 
-+/* This is a temporary function that returns false if the service
-+ * being started was only tested when running as root.
-+ */
-+static bool svc_supported_as_nonroot(const char *svc_name)
-+{
-+    return false;
-+}
-+
- static int get_service_config(struct mt_ctx *ctx, const char *name,
-                               struct mt_svc **svc_cfg)
- {
-@@ -1027,6 +1068,8 @@ static int get_service_config(struct mt_ctx *ctx, const char *name,
-     char *path;
-     struct mt_svc *svc;
-     time_t now = time(NULL);
-+    uid_t uid = 0;
-+    gid_t gid = 0;
- 
-     *svc_cfg = NULL;
- 
-@@ -1066,6 +1109,11 @@ static int get_service_config(struct mt_ctx *ctx, const char *name,
-         return ret;
-     }
- 
-+    if (svc_supported_as_nonroot(svc->name)) {
-+        uid = ctx->uid;
-+        gid = ctx->gid;
-+    }
-+
-     if (!svc->command) {
-         svc->command = talloc_asprintf(
-             svc, "%s/sssd_%s", SSSD_LIBEXEC_PATH, svc->name
-@@ -1075,6 +1123,14 @@ static int get_service_config(struct mt_ctx *ctx, const char *name,
-             return ENOMEM;
-         }
- 
-+        svc->command = talloc_asprintf_append(svc->command,
-+                " --uid %"SPRIuid" --gid %"SPRIgid,
-+                uid, gid);
-+        if (!svc->command) {
-+            talloc_free(svc);
-+            return ENOMEM;
-+        }
-+
-         if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
-             svc->command = talloc_asprintf_append(
-                 svc->command, " -d %#.4x", cmdline_debug_level
--- 
-1.9.3
-
diff --git a/SOURCES/0027-SBUS-Chown-the-sbus-socket-if-needed.patch b/SOURCES/0027-SBUS-Chown-the-sbus-socket-if-needed.patch
deleted file mode 100644
index 0398ee0..0000000
--- a/SOURCES/0027-SBUS-Chown-the-sbus-socket-if-needed.patch
+++ /dev/null
@@ -1,165 +0,0 @@
-From 2b8bb71a6f17dd0348ae07f0488d3de76b791c7f Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 7 Oct 2014 11:30:01 +0200
-Subject: [PATCH 27/46] SBUS: Chown the sbus socket if needed
-
-When setting up the sbus server, we might need to chown the sbus socket
-to make sure non-root peers, running as the SSSD user are able to access
-the file.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 5960687483a5d3d99093c9d6ab64e11c9bde7f7b)
----
- src/monitor/monitor.c            |  6 +++++-
- src/providers/data_provider_be.c |  2 +-
- src/providers/proxy/proxy_init.c |  2 +-
- src/sbus/sbus_client.c           | 15 +++++++++++++--
- src/sbus/sssd_dbus.h             |  1 +
- src/sbus/sssd_dbus_server.c      | 18 ++++++++++++++++--
- src/tests/common_dbus.c          |  4 ++--
- 7 files changed, 39 insertions(+), 9 deletions(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index df1cd5ca14c759f7aab98094a2b8ad35731c35e6..b6777784cd289e85c865fc16490d0287a63192a5 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -515,7 +515,11 @@ static int monitor_dbus_init(struct mt_ctx *ctx)
-         return ret;
-     }
- 
--    ret = sbus_new_server(ctx, ctx->ev, monitor_address,
-+    /* If a service is running as unprivileged user, we need to make sure this
-+     * user can access the monitor sbus server. root is still king, so we don't
-+     * lose any access.
-+     */
-+    ret = sbus_new_server(ctx, ctx->ev, monitor_address, ctx->uid, ctx->gid,
-                           false, &ctx->sbus_srv, monitor_service_init, ctx);
- 
-     talloc_free(monitor_address);
-diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
-index 18b50214b0795709d583d5891bf4f6fd220bcb11..122c5b091751b641f815ddff5c56ac99ace69939 100644
---- a/src/providers/data_provider_be.c
-+++ b/src/providers/data_provider_be.c
-@@ -2263,7 +2263,7 @@ static int be_srv_init(struct be_ctx *ctx)
-         return ret;
-     }
- 
--    ret = sbus_new_server(ctx, ctx->ev, sbus_address,
-+    ret = sbus_new_server(ctx, ctx->ev, sbus_address, 0, 0,
-                           true, &ctx->sbus_srv, be_client_init, ctx);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set up sbus server.\n");
-diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c
-index dd1b75826fbfc384dd37ba659a8653547cc35bcf..1e734511766f2c0f58cffc7d726a26ecfd6c9a27 100644
---- a/src/providers/proxy/proxy_init.c
-+++ b/src/providers/proxy/proxy_init.c
-@@ -522,7 +522,7 @@ int sssm_proxy_auth_init(struct be_ctx *bectx,
-         goto done;
-     }
- 
--    ret = sbus_new_server(ctx, bectx->ev, sbus_address,
-+    ret = sbus_new_server(ctx, bectx->ev, sbus_address, 0, 0,
-                           false, &ctx->sbus_srv, proxy_client_init, ctx);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set up sbus server.\n");
-diff --git a/src/sbus/sbus_client.c b/src/sbus/sbus_client.c
-index 6cf5002dc2b8f3b85a3110298db8255b82172ddd..8ad4c0f36a929e341793cca61fe12808e14f6bc6 100644
---- a/src/sbus/sbus_client.c
-+++ b/src/sbus/sbus_client.c
-@@ -32,6 +32,8 @@ int sbus_client_init(TALLOC_CTX *mem_ctx,
-     struct sbus_connection *conn = NULL;
-     int ret;
-     char *filename;
-+    uid_t check_uid;
-+    gid_t check_gid;
- 
-     /* Validate input */
-     if (server_address == NULL) {
-@@ -45,8 +47,17 @@ int sbus_client_init(TALLOC_CTX *mem_ctx,
-         return EIO;
-     }
- 
--    ret = check_file(filename,
--                     0, 0, S_IFSOCK|S_IRUSR|S_IWUSR, 0, NULL, true);
-+    check_uid = geteuid();
-+    check_gid = getegid();
-+
-+    /* Ignore ownership checks when the server runs as root. This is the
-+     * case when privileged monitor is setting up sockets for unprivileged
-+     * responders */
-+    if (check_uid == 0) check_uid = -1;
-+    if (check_gid == 0) check_gid = -1;
-+
-+    ret = check_file(filename, check_uid, check_gid,
-+                     S_IFSOCK|S_IRUSR|S_IWUSR, 0, NULL, true);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "check_file failed for [%s].\n", filename);
-         return EIO;
-diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
-index 372521a3575f967b751c9e13a7d830d9c3b43584..d01926368ce0ae5312d8ea0057a89d9a7176836b 100644
---- a/src/sbus/sssd_dbus.h
-+++ b/src/sbus/sssd_dbus.h
-@@ -132,6 +132,7 @@ sbus_new_interface(TALLOC_CTX *mem_ctx,
- int sbus_new_server(TALLOC_CTX *mem_ctx,
-                     struct tevent_context *ev,
-                     const char *address,
-+                    uid_t uid, gid_t gid,
-                     bool use_symlink,
-                     struct sbus_connection **server,
-                     sbus_server_conn_init_fn init_fn, void *init_pvt_data);
-diff --git a/src/sbus/sssd_dbus_server.c b/src/sbus/sssd_dbus_server.c
-index 3a7de8ff019160b2305516945740dfb6453d578b..18fb98df61f1740898f725cb0ae9924f5e2f7716 100644
---- a/src/sbus/sssd_dbus_server.c
-+++ b/src/sbus/sssd_dbus_server.c
-@@ -181,6 +181,7 @@ remove_socket_symlink(const char *symlink_name)
- int sbus_new_server(TALLOC_CTX *mem_ctx,
-                     struct tevent_context *ev,
-                     const char *address,
-+                    uid_t uid, gid_t gid,
-                     bool use_symlink,
-                     struct sbus_connection **_server,
-                     sbus_server_conn_init_fn init_fn,
-@@ -260,9 +261,22 @@ int sbus_new_server(TALLOC_CTX *mem_ctx,
-     if ((stat_buf.st_mode & ~S_IFMT) != (S_IRUSR|S_IWUSR)) {
-         ret = chmod(filename, (S_IRUSR|S_IWUSR));
-         if (ret != EOK) {
-+            ret = errno;
-             DEBUG(SSSDBG_CRIT_FAILURE,
--                  "chmod failed for [%s]: [%d][%s].\n", filename, errno,
--                                                         strerror(errno));
-+                  "chmod failed for [%s]: [%d][%s].\n", filename, ret,
-+                                                        sss_strerror(ret));
-+            ret = EIO;
-+            goto done;
-+        }
-+    }
-+
-+    if (stat_buf.st_uid != uid || stat_buf.st_gid != gid) {
-+        ret = chown(filename, uid, gid);
-+        if (ret != EOK) {
-+            ret = errno;
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "chown failed for [%s]: [%d][%s].\n", filename, ret,
-+                                                        sss_strerror(ret));
-             ret = EIO;
-             goto done;
-         }
-diff --git a/src/tests/common_dbus.c b/src/tests/common_dbus.c
-index 3117c080dc3106517bee933a458583f35b04fa63..1b0ae88dc05a1514938218e97a50e9ef7b54b193 100644
---- a/src/tests/common_dbus.c
-+++ b/src/tests/common_dbus.c
-@@ -112,8 +112,8 @@ mock_server_child(void *data)
-     ctx = talloc_new(NULL);
-     loop = tevent_context_init(ctx);
- 
--    verify_eq (sbus_new_server(ctx, loop, mock->dbus_address, false,
--                               &server, on_accept_connection, mock), EOK);
-+    verify_eq (sbus_new_server(ctx, loop, mock->dbus_address, geteuid(), getegid(),
-+                               false, &server, on_accept_connection, mock), EOK);
- 
-     tevent_add_fd(loop, ctx, mock->sync_fds[1], TEVENT_FD_READ,
-                   on_sync_fd_written, &stop_server);
--- 
-1.9.3
-
diff --git a/SOURCES/0027-TESTS-fix-compiler-warnings.patch b/SOURCES/0027-TESTS-fix-compiler-warnings.patch
new file mode 100644
index 0000000..92545e5
--- /dev/null
+++ b/SOURCES/0027-TESTS-fix-compiler-warnings.patch
@@ -0,0 +1,50 @@
+From b211247a005257a4e2dec0d43b719600c51a14d4 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Tue, 28 Jul 2015 04:12:48 -0400
+Subject: [PATCH 27/27] TESTS: fix compiler warnings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
+---
+ src/confdb/confdb.h                 | 2 +-
+ src/tests/cmocka/test_sysdb_views.c | 2 --
+ 2 files changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
+index 36df6aea268cc5c82696f20b1a65963350d5e100..0b0ae0dcf2cd26462a9b0c895d833faf5c85b4e5 100644
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -266,7 +266,7 @@ struct sss_domain_info {
+     struct timeval subdomains_last_checked;
+ 
+     bool has_views;
+-    char *view_name;
++    const char *view_name;
+ 
+     struct sss_domain_info *prev;
+     struct sss_domain_info *next;
+diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
+index 83007b76a625edef67109850648b2d71645e22bb..c53d8187b181a5937f642eec32af28e8207b292b 100644
+--- a/src/tests/cmocka/test_sysdb_views.c
++++ b/src/tests/cmocka/test_sysdb_views.c
+@@ -285,7 +285,6 @@ void test_sysdb_add_overrides_to_object_local(void **state)
+ {
+     int ret;
+     struct ldb_message *orig;
+-    struct ldb_message_element *el;
+     char *tmp_str;
+     struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                          struct sysdb_test_ctx);
+@@ -314,7 +313,6 @@ void test_sysdb_add_overrides_to_object_missing_overridedn(void **state)
+ {
+     int ret;
+     struct ldb_message *orig;
+-    struct ldb_message_element *el;
+     char *tmp_str;
+     struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                          struct sysdb_test_ctx);
+-- 
+2.4.3
+
diff --git a/SOURCES/0028-SBUS-Allow-connections-from-other-UIDs.patch b/SOURCES/0028-SBUS-Allow-connections-from-other-UIDs.patch
deleted file mode 100644
index e410782..0000000
--- a/SOURCES/0028-SBUS-Allow-connections-from-other-UIDs.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From 1017fbf75cc0859c691b120482fd13b52b44780b Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 7 Oct 2014 19:44:44 +0200
-Subject: [PATCH 28/46] SBUS: Allow connections from other UIDs
-
-Unless dbus_connection_set_unix_user_function() is used, D-Bus only
-allows connections from UID 0. This patch adds a custom checker function
-that allows either UID 0 or the pre-configured SSSD user ID.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit aa871e019f00493dfa53b48f906132bf94eeae9f)
----
- src/monitor/monitor.c           |  3 +++
- src/sbus/sssd_dbus.h            |  4 ++++
- src/sbus/sssd_dbus_connection.c | 20 ++++++++++++++++++++
- 3 files changed, 27 insertions(+)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index b6777784cd289e85c865fc16490d0287a63192a5..fc6b2963fff41a2a2aefdaf502817f6764e95b1e 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -2392,6 +2392,9 @@ static int monitor_service_init(struct sbus_connection *conn, void *data)
-     mini->ctx = ctx;
-     mini->conn = conn;
- 
-+    /* Allow access from the SSSD user */
-+    sbus_allow_uid(conn, &ctx->uid);
-+
-     /* 10 seconds should be plenty */
-     tv = tevent_timeval_current_ofs(10, 0);
- 
-diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
-index d01926368ce0ae5312d8ea0057a89d9a7176836b..5b128eaedb320cb745c1b635867e1b53ca556ec9 100644
---- a/src/sbus/sssd_dbus.h
-+++ b/src/sbus/sssd_dbus.h
-@@ -209,6 +209,10 @@ int sbus_conn_send(struct sbus_connection *conn,
- void sbus_conn_send_reply(struct sbus_connection *conn,
-                           DBusMessage *reply);
- 
-+/* Set up D-BUS access control. If there is a SSSD user, we must allow
-+ * him to connect. root is always allowed */
-+void sbus_allow_uid(struct sbus_connection *conn, uid_t *uid);
-+
- /*
-  * This structure is passed to all dbus method and property
-  * handlers. It is a talloc context which will be valid until
-diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c
-index 06256a85b5e81b39d50923db6d41b64015114ce1..6102ef9ae4715d36a623b802b9095ec1c99c1a39 100644
---- a/src/sbus/sssd_dbus_connection.c
-+++ b/src/sbus/sssd_dbus_connection.c
-@@ -922,3 +922,23 @@ void sbus_conn_send_reply(struct sbus_connection *conn, DBusMessage *reply)
- {
-     dbus_connection_send(conn->dbus.conn, reply, NULL);
- }
-+
-+dbus_bool_t is_uid_sssd_user(DBusConnection *connection,
-+                             unsigned long   uid,
-+                             void           *data)
-+{
-+    uid_t sssd_user = * (uid_t *) data;
-+
-+    if (uid == 0 || uid == sssd_user) {
-+        return TRUE;
-+    }
-+
-+    return FALSE;
-+}
-+
-+void sbus_allow_uid(struct sbus_connection *conn, uid_t *uid)
-+{
-+    dbus_connection_set_unix_user_function(sbus_get_connection(conn),
-+                                           is_uid_sssd_user,
-+                                           uid, NULL);
-+}
--- 
-1.9.3
-
diff --git a/SOURCES/0028-intg-Invalidate-memory-cache-before-removing-files.patch b/SOURCES/0028-intg-Invalidate-memory-cache-before-removing-files.patch
new file mode 100644
index 0000000..80cc677
--- /dev/null
+++ b/SOURCES/0028-intg-Invalidate-memory-cache-before-removing-files.patch
@@ -0,0 +1,31 @@
+From daf44387652fe46a2c8e694720f6b14436a6f31f Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Fri, 24 Jul 2015 12:31:42 +0200
+Subject: [PATCH 28/37] intg: Invalidate memory cache before removing files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Workaround for:
+https://fedorahosted.org/sssd/ticket/2726
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+---
+ src/tests/intg/ldap_test.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/tests/intg/ldap_test.py b/src/tests/intg/ldap_test.py
+index afc77d7023ea31757def84f21e5d15997ba72013..bfe4e65ee54e232cd37d91f8ca5b6e9edf42b49d 100644
+--- a/src/tests/intg/ldap_test.py
++++ b/src/tests/intg/ldap_test.py
+@@ -90,6 +90,7 @@ def create_sssd_fixture(request):
+                 time.sleep(1)
+         except:
+             pass
++        subprocess.call(["sss_cache", "-E"])
+         for path in os.listdir(config.DB_PATH):
+             os.unlink(config.DB_PATH + "/" + path)
+         for path in os.listdir(config.MCACHE_PATH):
+-- 
+2.4.3
+
diff --git a/SOURCES/0029-BE-Own-the-sbus-socket-as-the-SSSD-user.patch b/SOURCES/0029-BE-Own-the-sbus-socket-as-the-SSSD-user.patch
deleted file mode 100644
index 18c8342..0000000
--- a/SOURCES/0029-BE-Own-the-sbus-socket-as-the-SSSD-user.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-From 2bb5d331997232e5b1c589062b7960215fd08047 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 15 Oct 2014 15:58:58 +0200
-Subject: [PATCH 29/46] BE: Own the sbus socket as the SSSD user
-
-In some cases, the back end might still be running as root, but the
-responder would be running unprivileged. In this case, we need to allow
-connecting from the SSSD user ID.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 19e9c1c1a21790974400db9349637788727b6564)
----
- src/monitor/monitor.c            |  8 ++++++++
- src/providers/data_provider_be.c | 16 ++++++++++++----
- src/providers/dp_backend.h       |  2 ++
- 3 files changed, 22 insertions(+), 4 deletions(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index fc6b2963fff41a2a2aefdaf502817f6764e95b1e..905e66f25601d155557487ae9c7eb6d3145d3a83 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1306,6 +1306,14 @@ static int get_provider_config(struct mt_ctx *ctx, const char *name,
-             return ENOMEM;
-         }
- 
-+        svc->command = talloc_asprintf_append(svc->command,
-+                " --uid %"SPRIuid" --gid %"SPRIgid,
-+                ctx->uid, ctx->gid);
-+        if (!svc->command) {
-+            talloc_free(svc);
-+            return ENOMEM;
-+        }
-+
-         if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
-             svc->command = talloc_asprintf_append(
-                 svc->command, " -d %#.4x", cmdline_debug_level
-diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
-index 122c5b091751b641f815ddff5c56ac99ace69939..2716e4a8b38f3ff9a5b48a861ecc31f18f9fcbce 100644
---- a/src/providers/data_provider_be.c
-+++ b/src/providers/data_provider_be.c
-@@ -2226,6 +2226,9 @@ static int be_client_init(struct sbus_connection *conn, void *data)
-     becli->conn = conn;
-     becli->initialized = false;
- 
-+    /* Allow access from the SSSD user */
-+    sbus_allow_uid(conn, &bectx->uid);
-+
-     /* 5 seconds should be plenty */
-     tv = tevent_timeval_current_ofs(5, 0);
- 
-@@ -2251,7 +2254,8 @@ static int be_client_init(struct sbus_connection *conn, void *data)
- 
- /* be_srv_init
-  * set up per-domain sbus channel */
--static int be_srv_init(struct be_ctx *ctx)
-+static int be_srv_init(struct be_ctx *ctx,
-+                       uid_t uid, gid_t gid)
- {
-     char *sbus_address;
-     int ret;
-@@ -2263,7 +2267,10 @@ static int be_srv_init(struct be_ctx *ctx)
-         return ret;
-     }
- 
--    ret = sbus_new_server(ctx, ctx->ev, sbus_address, 0, 0,
-+    ctx->uid = uid;
-+    ctx->gid = gid;
-+
-+    ret = sbus_new_server(ctx, ctx->ev, sbus_address, uid, gid,
-                           true, &ctx->sbus_srv, be_client_init, ctx);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set up sbus server.\n");
-@@ -2554,6 +2561,7 @@ done:
- 
- int be_process_init(TALLOC_CTX *mem_ctx,
-                     const char *be_domain,
-+                    uid_t uid, gid_t gid,
-                     struct tevent_context *ev,
-                     struct confdb_ctx *cdb)
- {
-@@ -2609,7 +2617,7 @@ int be_process_init(TALLOC_CTX *mem_ctx,
-         goto fail;
-     }
- 
--    ret = be_srv_init(ctx);
-+    ret = be_srv_init(ctx, uid, gid);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up server bus\n");
-         goto fail;
-@@ -2870,7 +2878,7 @@ int main(int argc, const char *argv[])
-     }
- 
-     ret = be_process_init(main_ctx,
--                          be_domain,
-+                          be_domain, uid, gid,
-                           main_ctx->event_ctx,
-                           main_ctx->confdb_ctx);
-     if (ret != EOK) {
-diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
-index 075681ff9dd641daf56929c05cb94170cd1b292a..e4213b44b32e8b9cb942dfcfef4998aa732d113c 100644
---- a/src/providers/dp_backend.h
-+++ b/src/providers/dp_backend.h
-@@ -116,6 +116,8 @@ struct be_ctx {
-     struct sss_domain_info *domain;
-     const char *identity;
-     const char *conf_path;
-+    uid_t uid;
-+    gid_t gid;
-     struct be_failover_ctx *be_fo;
-     struct be_resolv_ctx *be_res;
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch b/SOURCES/0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch
new file mode 100644
index 0000000..1399bd5
--- /dev/null
+++ b/SOURCES/0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch
@@ -0,0 +1,33 @@
+From 8ffbe4698421aaafa59f0813232883c4fc41514d Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Thu, 23 Jul 2015 15:56:44 +0200
+Subject: [PATCH 29/37] krb5: do not send SSS_OTP if two factors were used
+
+Resolves https://fedorahosted.org/sssd/ticket/2729
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/providers/krb5/krb5_auth.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index 8886456c00c86914da364fd08efc25a488b0e686..d1bf4025b052d82413d1f370a36b0b99720d6f05 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -1091,7 +1091,12 @@ static void krb5_auth_done(struct tevent_req *subreq)
+         krb5_auth_store_creds(state->domain, pd);
+     }
+ 
+-    if (res->otp == true && pd->cmd == SSS_PAM_AUTHENTICATE) {
++    /* The SSS_OTP message will prevent pam_sss from putting the entered
++     * password on the PAM stack for other modules to use. This is not needed
++     * when both factors were entered separately because here the first factor
++     * (long term password) can be passed to the other modules. */
++    if (res->otp == true && pd->cmd == SSS_PAM_AUTHENTICATE
++            && sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_2FA) {
+         uint32_t otp_flag = 1;
+         ret = pam_add_response(pd, SSS_OTP, sizeof(uint32_t),
+                                (const uint8_t *) &otp_flag);
+-- 
+2.4.3
+
diff --git a/SOURCES/0030-MONITOR-Allow-confdb-to-be-accessed-by-nonroot-user.patch b/SOURCES/0030-MONITOR-Allow-confdb-to-be-accessed-by-nonroot-user.patch
deleted file mode 100644
index b111c2d..0000000
--- a/SOURCES/0030-MONITOR-Allow-confdb-to-be-accessed-by-nonroot-user.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 1c27362249606583545f7b0c465a3088879439a1 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Thu, 9 Oct 2014 17:15:56 +0200
-Subject: [PATCH 30/46] MONITOR: Allow confdb to be accessed by nonroot user
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 579e5d4b7a3ca161ea7518b2996905fa22c15995)
----
- src/monitor/monitor.c | 13 ++++++++++++-
- 1 file changed, 12 insertions(+), 1 deletion(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 905e66f25601d155557487ae9c7eb6d3145d3a83..37f6e928be3508762e1c3afadbb67762f5cc1d38 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1696,7 +1696,6 @@ static errno_t load_configuration(TALLOC_CTX *mem_ctx,
-         DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error initializing confdb\n");
-         goto done;
-     }
--    talloc_zfree(cdb_file);
- 
-     ret = confdb_init_db(config_file, ctx->cdb);
-     if (ret != EOK) {
-@@ -1712,11 +1711,23 @@ static errno_t load_configuration(TALLOC_CTX *mem_ctx,
-         goto done;
-     }
- 
-+    /* Allow configuration database to be accessible
-+     * when SSSD runs as nonroot */
-+    ret = chown(cdb_file, ctx->uid, ctx->gid);
-+    if (ret != 0) {
-+        ret = errno;
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "chown failed for [%s]: [%d][%s].\n",
-+              cdb_file, ret, sss_strerror(ret));
-+        goto done;
-+    }
-+
-     *monitor = ctx;
- 
-     ret = EOK;
- 
- done:
-+    talloc_free(cdb_file);
-     if (ret != EOK) {
-         talloc_free(ctx);
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0030-utils-add-NSS-version-of-cert-utils.patch b/SOURCES/0030-utils-add-NSS-version-of-cert-utils.patch
new file mode 100644
index 0000000..d66d074
--- /dev/null
+++ b/SOURCES/0030-utils-add-NSS-version-of-cert-utils.patch
@@ -0,0 +1,345 @@
+From cbbdb6250744154bf9b5d0718ec68f2b63dfaff0 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Mon, 22 Jun 2015 16:36:36 +0200
+Subject: [PATCH 30/37] utils: add NSS version of cert utils
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                        |  29 ++++-
+ configure.ac                       |   4 +-
+ contrib/sssd.spec.in               |   1 -
+ src/tests/cmocka/test_cert_utils.c |   4 +
+ src/util/cert/nss/cert.c           | 212 +++++++++++++++++++++++++++++++++++++
+ 5 files changed, 244 insertions(+), 6 deletions(-)
+ create mode 100644 src/util/cert/nss/cert.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 912bfc6641465ef5cd2ff2cce9975b4027c3218d..277166ec66b3d67101e628990e68704c886b0c59 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -709,6 +709,17 @@ if HAVE_NSS
+                         src/util/crypto/nss/nss_util.c
+     SSS_CRYPT_CFLAGS = $(NSS_CFLAGS)
+     SSS_CRYPT_LIBS = $(NSS_LIBS)
++
++    SSS_CERT_SOURCES = \
++        src/util/cert/cert_common.c \
++        src/util/cert/nss/cert.c \
++        $(NULL)
++    SSS_CERT_CFLAGS = \
++        $(NSS_CFLAGS) \
++        $(NULL)
++    SSS_CERT_LIBS = \
++        $(NSS_LIBS) \
++        $(NULL)
+ else
+     SSS_CRYPT_SOURCES = src/util/crypto/libcrypto/crypto_base64.c \
+                         src/util/crypto/libcrypto/crypto_hmac_sha1.c \
+@@ -716,6 +727,17 @@ else
+                         src/util/crypto/libcrypto/crypto_obfuscate.c
+     SSS_CRYPT_CFLAGS = $(CRYPTO_CFLAGS)
+     SSS_CRYPT_LIBS = $(CRYPTO_LIBS)
++
++    SSS_CERT_SOURCES = \
++        src/util/cert/cert_common.c \
++        src/util/cert/libcrypto/cert.c \
++        $(NULL)
++    SSS_CERT_CFLAGS = \
++        $(CRYPTO_CFLAGS) \
++        $(NULL)
++    SSS_CERT_LIBS = \
++        $(CRYPTO_LIBS) \
++        $(NULL)
+ endif
+ 
+ libsss_crypt_la_SOURCES = \
+@@ -735,14 +757,13 @@ libsss_crypt_la_LDFLAGS = \
+ pkglib_LTLIBRARIES += libsss_cert.la
+ 
+ libsss_cert_la_SOURCES = \
+-    src/util/cert/cert_common.c \
+-    src/util/cert/libcrypto/cert.c \
++    $(SSS_CERT_SOURCES) \
+     $(NULL)
+ libsss_cert_la_CFLAGS = \
+-    $(CRYPTO_CFLAGS) \
++    $(SSS_CERT_CFLAGS) \
+     $(NULL)
+ libsss_cert_la_LIBADD = \
+-    $(CRYPTO_LIBS) \
++    $(SSS_CERT_LIBS) \
+     $(TALLOC_LIBS) \
+     libsss_crypt.la \
+     libsss_debug.la \
+diff --git a/configure.ac b/configure.ac
+index 29bedf74db6594b5788d51570514a07e082d5e42..4b4f8f3228bf13c594c86e1e39474a1d02ffd984 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -341,7 +341,9 @@ if test x$cryptolib = xnss; then
+     AM_CHECK_NSS
+ fi
+ 
+-AM_CHECK_LIBCRYPTO
++if test x$cryptolib = xlibcrypto; then
++    AM_CHECK_LIBCRYPTO
++fi
+ 
+ AM_CHECK_INOTIFY
+ 
+diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
+index f050501ff9d0711a0da7f094ee968cae87a3f49b..54260e32e24ece372ed7130ab29d766bb1923f77 100644
+--- a/contrib/sssd.spec.in
++++ b/contrib/sssd.spec.in
+@@ -106,7 +106,6 @@ BuildRequires: dbus-libs
+ BuildRequires: openldap-devel
+ BuildRequires: pam-devel
+ BuildRequires: nss-devel
+-BuildRequires: openssl-devel
+ BuildRequires: nspr-devel
+ BuildRequires: pcre-devel
+ BuildRequires: libxslt
+diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c
+index 5bcbafb27dbdff596c07b8aad10ca15a35ff4ef5..8063b1a65e8692142cbb3cf82fe41afa6567bc91 100644
+--- a/src/tests/cmocka/test_cert_utils.c
++++ b/src/tests/cmocka/test_cert_utils.c
+@@ -23,7 +23,9 @@
+ */
+ 
+ #include <popt.h>
++#ifdef HAVE_LIBCRYPTO
+ #include <openssl/objects.h>
++#endif
+ 
+ #include "util/cert.h"
+ #include "tests/cmocka/common_mock.h"
+@@ -349,7 +351,9 @@ int main(int argc, const char *argv[])
+ 
+     ret = cmocka_run_group_tests(tests, NULL, NULL);
+ 
++#ifdef HAVE_LIBCRYPTO
+     CRYPTO_cleanup_all_ex_data(); /* to make valgrind happy */
++#endif
+ 
+ #ifdef HAVE_NSS
+     /* Cleanup NSS and NSPR to make valgrind happy. */
+diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..a20abf63a10de9a5e9810f1c7d56686d063d60c7
+--- /dev/null
++++ b/src/util/cert/nss/cert.c
+@@ -0,0 +1,212 @@
++
++/*
++   SSSD - certificate handling utils - NSS version
++
++   Copyright (C) Sumit Bose <sbose@redhat.com> 2015
++
++   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 <cert.h>
++#include <base64.h>
++
++#include "util/crypto/nss/nss_util.h"
++
++#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
++#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
++#define NS_CERT_HEADER_LEN  ((sizeof NS_CERT_HEADER) - 1)
++#define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1)
++
++errno_t sss_cert_der_to_pem(TALLOC_CTX *mem_ctx, const uint8_t *der_blob,
++                            size_t der_size, char **pem, size_t *pem_size)
++{
++
++    CERTCertDBHandle *handle;
++    CERTCertificate *cert = NULL;
++    SECItem der_item;
++    char *ascii_crlf = NULL;
++    size_t ascii_crlf_len;
++    char *ascii_lf = NULL;
++    char *pem_cert_str = NULL;
++    int ret;
++    size_t c;
++    size_t d;
++
++    /* initialize NSS if needed */
++    ret = nspr_nss_init();
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n");
++        return ret;
++    }
++
++    handle = CERT_GetDefaultCertDB();
++
++    der_item.len = der_size;
++    der_item.data = discard_const(der_blob);
++
++    cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
++    if (cert == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
++        return EINVAL;
++    }
++
++    ascii_crlf = BTOA_DataToAscii(cert->derCert.data, cert->derCert.len);
++    if (ascii_crlf == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "BTOA_DataToAscii failed.\n");
++        ret = EIO;
++        goto done;
++    }
++
++    ascii_crlf_len = strlen(ascii_crlf) + 1;
++    ascii_lf = talloc_size(mem_ctx, ascii_crlf_len * sizeof(char));
++    if (ascii_lf == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "malloc failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    d = 0;
++    for (c = 0; c < ascii_crlf_len; c++) {
++        if (ascii_crlf[c] != '\r') {
++            ascii_lf[d++] = ascii_crlf[c];
++        }
++    }
++
++    pem_cert_str = talloc_asprintf(mem_ctx, "%s\n%s\n%s\n", NS_CERT_HEADER,
++                                                            ascii_lf,
++                                                            NS_CERT_TRAILER);
++    if (pem_cert_str == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    if (pem_size != NULL) {
++        *pem_size = strlen(pem_cert_str);
++    }
++
++    if (pem != NULL) {
++        *pem = pem_cert_str;
++        pem_cert_str = NULL;
++    }
++
++    ret = EOK;
++done:
++    talloc_free(pem_cert_str);
++    talloc_free(ascii_lf);
++    PORT_Free(ascii_crlf);
++    CERT_DestroyCertificate(cert);
++
++    return ret;
++}
++
++errno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem,
++                            uint8_t **_der_blob, size_t *_der_size)
++{
++    const char *ps;
++    const char *pe;
++    size_t pem_len;
++    uint8_t *der_blob = NULL;
++    unsigned int der_size; /* unsigned int to match 2nd parameter of
++                              ATOB_AsciiToData */
++    CERTCertDBHandle *handle;
++    CERTCertificate *cert = NULL;
++    SECItem der_item;
++    int ret;
++    char *b64 = NULL;
++
++    /* initialize NSS if needed */
++    ret = nspr_nss_init();
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n");
++        return ret;
++    }
++
++    if (pem == NULL || *pem == '\0') {
++        return EINVAL;
++    }
++
++    pem_len = strlen(pem);
++    if (pem_len <= NS_CERT_HEADER_LEN + NS_CERT_TRAILER_LEN) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "PEM data too short.\n");
++        return EINVAL;
++    }
++
++    if (strncmp(pem, NS_CERT_HEADER, NS_CERT_HEADER_LEN) != 0) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM header.\n");
++        return EINVAL;
++    }
++    if (pem[NS_CERT_HEADER_LEN] != '\n') {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Missing newline in PEM data.\n");
++        return EINVAL;
++    }
++
++    pe = pem + pem_len - NS_CERT_TRAILER_LEN;
++    if (pem[pem_len - 1] == '\n') {
++        pe--;
++    }
++    if (strncmp(pe, NS_CERT_TRAILER, NS_CERT_TRAILER_LEN) != 0) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM trailer.\n");
++        return EINVAL;
++    }
++
++    ps = pem + NS_CERT_HEADER_LEN + 1;
++
++    b64 = talloc_strndup(mem_ctx, ps, pe - ps);
++    if(b64 == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    der_blob = ATOB_AsciiToData(b64, &der_size);
++    if (der_blob == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "ATOB_AsciiToData failed.\n");
++        return EIO;
++    }
++
++    handle = CERT_GetDefaultCertDB();
++
++    der_item.len = der_size;
++    der_item.data = der_blob;
++
++    cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
++    if (cert == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
++        ret = EINVAL;
++        goto done;
++    }
++
++    if (_der_blob != NULL) {
++        *_der_blob = talloc_memdup(mem_ctx, cert->derCert.data,
++                                   cert->derCert.len);
++        if (*_der_blob == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "talloc_memdup failed.\n");
++            ret = ENOMEM;
++            goto done;
++        }
++    }
++
++    if (_der_size != NULL) {
++        *_der_size = cert->derCert.len;
++    }
++done:
++    PORT_Free(der_blob);
++    talloc_free(b64);
++    CERT_DestroyCertificate(cert);
++
++    return ret;
++}
+-- 
+2.4.3
+
diff --git a/SOURCES/0031-Add-NSS-version-of-p11_child.patch b/SOURCES/0031-Add-NSS-version-of-p11_child.patch
new file mode 100644
index 0000000..81896fc
--- /dev/null
+++ b/SOURCES/0031-Add-NSS-version-of-p11_child.patch
@@ -0,0 +1,720 @@
+From 95bea503429c3f44654265486a07f1696b017e84 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 10 Jul 2015 12:10:53 +0200
+Subject: [PATCH 31/37] Add NSS version of p11_child
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                   |  25 +-
+ contrib/sssd.spec.in          |   1 +
+ src/p11_child/p11_child_nss.c | 636 ++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 661 insertions(+), 1 deletion(-)
+ create mode 100644 src/p11_child/p11_child_nss.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 277166ec66b3d67101e628990e68704c886b0c59..e4add9757058773915f1971786b8a9ad584ec51f 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -148,7 +148,9 @@ endif
+ if BUILD_SEMANAGE
+ sssdlibexec_PROGRAMS += selinux_child
+ endif
+-
++if HAVE_NSS
++sssdlibexec_PROGRAMS += p11_child
++endif
+ 
+ if BUILD_PAC_RESPONDER
+     sssdlibexec_PROGRAMS += sssd_pac
+@@ -3146,6 +3148,23 @@ proxy_child_LDADD = \
+     $(SSSD_LIBS) \
+     $(SSSD_INTERNAL_LTLIBS)
+ 
++p11_child_SOURCES = \
++    src/p11_child/p11_child_nss.c \
++    src/util/atomic_io.c \
++    $(NULL)
++p11_child_CFLAGS = \
++    $(AM_CFLAGS) \
++    $(POPT_CFLAGS) \
++    $(NSS_CFLAGS) \
++    $(NULL)
++p11_child_LDADD = \
++    libsss_debug.la \
++    $(TALLOC_LIBS) \
++    $(POPT_LIBS) \
++    $(NSS_LIBS) \
++    libsss_crypt.la \
++    $(NULL)
++
+ memberof_la_SOURCES = \
+     src/ldb_modules/memberof.c \
+     src/util/util.c
+@@ -3541,6 +3560,10 @@ if BUILD_SEMANAGE
+ 	-chgrp $(SSSD_USER) $(DESTDIR)$(sssdlibexecdir)/selinux_child
+ 	chmod 4750 $(DESTDIR)$(sssdlibexecdir)/selinux_child
+ endif
++if HAVE_NSS
++	-chgrp $(SSSD_USER) $(DESTDIR)$(sssdlibexecdir)/p11_child
++	chmod 4750 $(DESTDIR)$(sssdlibexecdir)/p11_child
++endif
+ endif
+ 
+ install-data-hook:
+diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
+index 54260e32e24ece372ed7130ab29d766bb1923f77..9ca9a8b4dce5c5d70fb4df268270bcfb0c9b17bb 100644
+--- a/contrib/sssd.spec.in
++++ b/contrib/sssd.spec.in
+@@ -684,6 +684,7 @@ rm -rf $RPM_BUILD_ROOT
+ %{_libexecdir}/%{servicename}/sssd_autofs
+ %{_libexecdir}/%{servicename}/sssd_ssh
+ %{_libexecdir}/%{servicename}/sssd_sudo
++%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/p11_child
+ 
+ %dir %{_libdir}/%{name}
+ %{_libdir}/%{name}/libsss_simple.so
+diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..6948c142aa7843cda5ff6d18f5853b10c387c224
+--- /dev/null
++++ b/src/p11_child/p11_child_nss.c
+@@ -0,0 +1,636 @@
++/*
++    SSSD
++
++    Helper child to commmunicate with SmartCard via NSS
++
++    Authors:
++        Sumit Bose <sbose@redhat.com>
++
++    Copyright (C) 2015 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 <unistd.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <popt.h>
++
++#include "util/util.h"
++
++#include <nss.h>
++#include <base64.h>
++#include <cryptohi.h>
++#include <secmod.h>
++#include <cert.h>
++#include <keyhi.h>
++#include <pk11pub.h>
++#include <prerror.h>
++
++#include "util/child_common.h"
++#include "providers/dp_backend.h"
++#include "util/crypto/sss_crypto.h"
++
++enum op_mode {
++    OP_NONE,
++    OP_AUTH,
++    OP_PREAUTH
++};
++
++enum pin_mode {
++    PIN_NONE,
++    PIN_STDIN,
++    PIN_KEYPAD
++};
++
++static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg)
++{
++  /* give up if 1) no password was supplied, or 2) the password has already
++   * been rejected once by this token. */
++  if (retry || (arg == NULL)) {
++    return NULL;
++  }
++  return PL_strdup((char *)arg);
++}
++
++
++
++int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in,
++            enum op_mode mode, const char *pin, char **cert,
++            char **token_name_out)
++{
++    int ret;
++    SECStatus rv;
++    NSSInitContext *nss_ctx;
++    SECMODModuleList *mod_list;
++    SECMODModuleList *mod_list_item;
++    const char *slot_name;
++    const char *token_name;
++    uint32_t flags = NSS_INIT_READONLY
++                                   | NSS_INIT_FORCEOPEN
++                                   | NSS_INIT_NOROOTINIT
++                                   | NSS_INIT_OPTIMIZESPACE
++                                   | NSS_INIT_PK11RELOAD;
++    NSSInitParameters parameters = { 0 };
++    parameters.length =  sizeof (parameters);
++    PK11SlotInfo *slot = NULL;
++    CK_SLOT_ID slot_id;
++    SECMODModuleID module_id;
++    CERTCertList *cert_list = NULL;
++    CERTCertListNode *cert_list_node;
++    const PK11DefaultArrayEntry friendly_attr = { "Publicly-readable certs",
++                                                  SECMOD_FRIENDLY_FLAG,
++                                                  CKM_INVALID_MECHANISM };
++    CERTCertDBHandle *handle;
++    unsigned char random_value[128];
++    SECKEYPrivateKey *priv_key;
++    SECOidTag algtag;
++    SECItem signed_random_value = {0};
++    SECKEYPublicKey *pub_key;
++    CERTCertificate *found_cert = NULL;
++    PK11SlotList *list = NULL;
++    PK11SlotListElement *le;
++
++
++    nss_ctx = NSS_InitContext(nss_db, "", "", SECMOD_DB, &parameters, flags);
++    if (nss_ctx == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "NSS_InitContext failed [%d].\n",
++                                 PR_GetError());
++        return EIO;
++    }
++
++    PK11_SetPasswordFunc(password_passthrough);
++
++    DEBUG(SSSDBG_TRACE_ALL, "Default Module List:\n");
++    mod_list = SECMOD_GetDefaultModuleList();
++    for (mod_list_item = mod_list; mod_list_item != NULL;
++                                   mod_list_item = mod_list_item->next) {
++        DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n",
++                                mod_list_item->module->commonName);
++        DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n",
++                                mod_list_item->module->dllName);
++    }
++
++    DEBUG(SSSDBG_TRACE_ALL, "Dead Module List:\n");
++    mod_list = SECMOD_GetDeadModuleList();
++    for (mod_list_item = mod_list; mod_list_item != NULL;
++                                   mod_list_item = mod_list_item->next) {
++        DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n",
++                                mod_list_item->module->commonName);
++        DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n",
++                                mod_list_item->module->dllName);
++    }
++
++    DEBUG(SSSDBG_TRACE_ALL, "DB Module List:\n");
++    mod_list = SECMOD_GetDBModuleList();
++    for (mod_list_item = mod_list; mod_list_item != NULL;
++                                   mod_list_item = mod_list_item->next) {
++        DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n",
++                                mod_list_item->module->commonName);
++        DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n",
++                                mod_list_item->module->dllName);
++    }
++
++    if (slot_name_in != NULL) {
++        slot = PK11_FindSlotByName(slot_name_in);
++        if (slot == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "PK11_FindSlotByName failed for [%s]: [%d].\n",
++                                     slot_name_in, PR_GetError());
++            return EIO;
++        }
++    } else {
++
++        list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE,
++                                 NULL);
++        if (list == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "PK11_GetAllTokens failed.\n");
++            return EIO;
++        }
++
++        for (le = list->head; le; le = le->next) {
++            CK_SLOT_INFO slInfo;
++
++            slInfo.flags = 0;
++            rv = PK11_GetSlotInfo(le->slot, &slInfo);
++            DEBUG(SSSDBG_TRACE_ALL,
++                  "Description [%s] Manufacturer [%s] flags [%lu].\n",
++                  slInfo.slotDescription, slInfo.manufacturerID, slInfo.flags);
++            if (rv == SECSuccess && (slInfo.flags & CKF_REMOVABLE_DEVICE)) {
++                slot = PK11_ReferenceSlot(le->slot);
++                break;
++           }
++        }
++        PK11_FreeSlotList(list);
++        if (slot == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "No removable slots found.\n");
++            return EIO;
++        }
++    }
++
++
++    slot_id = PK11_GetSlotID(slot);
++    module_id = PK11_GetModuleID(slot);
++    slot_name = PK11_GetSlotName(slot);
++    token_name = PK11_GetTokenName(slot);
++    DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d].\n",
++          token_name, slot_name, (int) slot_id, (int) module_id);
++
++    if (PK11_IsFriendly(slot)) {
++        DEBUG(SSSDBG_TRACE_ALL, "Token is friendly.\n");
++    } else {
++        DEBUG(SSSDBG_TRACE_ALL,
++              "Token is NOT friendly.\n");
++        if (mode == OP_PREAUTH) {
++            DEBUG(SSSDBG_TRACE_ALL, "Trying to switch to friendly to read certificate.\n");
++            rv = PK11_UpdateSlotAttribute(slot, &friendly_attr, PR_TRUE);
++            if (rv != SECSuccess) {
++                DEBUG(SSSDBG_OP_FAILURE,
++                      "PK11_UpdateSlotAttribute failed, continue.\n");
++            }
++        }
++    }
++
++    /* TODO: check  PK11_ProtectedAuthenticationPath() and return the result */
++    if (mode == OP_AUTH || PK11_NeedLogin(slot)) {
++        DEBUG(SSSDBG_TRACE_ALL, "Login required.\n");
++        if (pin != NULL) {
++            rv = PK11_Authenticate(slot, PR_FALSE, discard_const(pin));
++            if (rv !=  SECSuccess) {
++                DEBUG(SSSDBG_OP_FAILURE, "PK11_Authenticate failed: [%d].\n",
++                                         PR_GetError());
++                return EIO;
++            }
++        } else {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Login required but no pin available, continue.\n");
++        }
++    } else {
++        DEBUG(SSSDBG_TRACE_ALL, "Login NOT required.\n");
++    }
++
++    cert_list = PK11_ListCertsInSlot(slot);
++    if (cert_list == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "PK11_ListCertsInSlot failed: [%d].\n",
++                                 PR_GetError());
++        return EIO;
++    }
++
++    for (cert_list_node = CERT_LIST_HEAD(cert_list);
++                !CERT_LIST_END(cert_list_node, cert_list);
++                cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
++        if (cert_list_node->cert) {
++            DEBUG(SSSDBG_TRACE_ALL, "found cert[%s][%s]\n",
++                             cert_list_node->cert->nickname,
++                             cert_list_node->cert->subjectName);
++        } else {
++            DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
++        }
++    }
++
++    rv = CERT_FilterCertListByUsage(cert_list, certUsageSSLClient, PR_FALSE);
++    if (rv != SECSuccess) {
++        DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListByUsage failed: [%d].\n",
++                                 PR_GetError());
++        return EIO;
++    }
++
++    rv = CERT_FilterCertListForUserCerts(cert_list);
++    if (rv != SECSuccess) {
++        DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListForUserCerts failed: [%d].\n",
++                                 PR_GetError());
++        return EIO;
++    }
++
++
++    handle = CERT_GetDefaultCertDB();
++    if (handle == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "CERT_GetDefaultCertDB failed: [%d].\n",
++                                 PR_GetError());
++        return EIO;
++    }
++
++
++    found_cert = NULL;
++    DEBUG(SSSDBG_TRACE_ALL, "Filtered certificates:\n");
++    for (cert_list_node = CERT_LIST_HEAD(cert_list);
++                !CERT_LIST_END(cert_list_node, cert_list);
++                cert_list_node = CERT_LIST_NEXT(cert_list_node)) {
++        if (cert_list_node->cert) {
++            DEBUG(SSSDBG_TRACE_ALL, "found cert[%s][%s]\n",
++                             cert_list_node->cert->nickname,
++                             cert_list_node->cert->subjectName);
++
++            if (found_cert == NULL) {
++                found_cert = cert_list_node->cert;
++            } else {
++                DEBUG(SSSDBG_TRACE_ALL, "More than one certificate found, " \
++                                        "using just the first one.\n");
++            }
++        } else {
++            DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n");
++        }
++    }
++
++    if (found_cert == NULL) {
++        DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n");
++        *cert = NULL;
++        *token_name_out = NULL;
++        ret = EOK;
++        goto done;
++    }
++
++    rv = CERT_VerifyCertificateNow(handle, found_cert, PR_TRUE,
++                                   certificateUsageSSLClient, NULL, NULL);
++    if (rv != SECSuccess) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "CERT_VerifyCertificateNow failed [%d].\n",
++              PR_GetError());
++        ret = EIO;
++        goto done;
++    }
++
++    if (mode == OP_AUTH) {
++        rv = PK11_GenerateRandom(random_value, sizeof(random_value));
++        if (rv != SECSuccess) {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "PK11_GenerateRandom failed [%d].\n", PR_GetError());
++            return EIO;
++        }
++
++        priv_key = PK11_FindPrivateKeyFromCert(slot, found_cert, NULL);
++        if (priv_key == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "PK11_FindPrivateKeyFromCert failed [%d]." \
++                  "Maybe pin is missing.\n", PR_GetError());
++            ret = EIO;
++            goto done;
++        }
++
++        algtag = SEC_GetSignatureAlgorithmOidTag(priv_key->keyType,
++                                                  SEC_OID_SHA1);
++        if (algtag == SEC_OID_UNKNOWN) {
++            SECKEY_DestroyPrivateKey(priv_key);
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "SEC_GetSignatureAlgorithmOidTag failed [%d].",
++                  PR_GetError());
++            ret = EIO;
++            goto done;
++        }
++
++        rv = SEC_SignData(&signed_random_value,
++                          random_value, sizeof(random_value),
++                          priv_key, algtag);
++        SECKEY_DestroyPrivateKey(priv_key);
++        if (rv != SECSuccess) {
++            DEBUG(SSSDBG_OP_FAILURE, "SEC_SignData failed [%d].",
++                                     PR_GetError());
++            ret = EIO;
++            goto done;
++        }
++
++        pub_key = CERT_ExtractPublicKey(found_cert);
++        if (pub_key == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "CERT_ExtractPublicKey failed [%d].", PR_GetError());
++            ret = EIO;
++            goto done;
++        }
++
++        rv = VFY_VerifyData(random_value, sizeof(random_value),
++                            pub_key, &signed_random_value, algtag,
++                            NULL);
++        SECKEY_DestroyPublicKey(pub_key);
++        if (rv != SECSuccess) {
++            DEBUG(SSSDBG_OP_FAILURE, "VFY_VerifyData failed [%d].",
++                                     PR_GetError());
++            ret = EACCES;
++            goto done;
++        }
++
++        DEBUG(SSSDBG_TRACE_ALL,
++              "Certificate verified and validated.\n");
++    }
++
++    *cert = sss_base64_encode(mem_ctx, found_cert->derCert.data,
++                                       found_cert->derCert.len);
++    if (*cert == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "sss_base64_encode failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    *token_name_out = talloc_strdup(mem_ctx, token_name);
++    if (*token_name_out == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy slot name.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    if (slot != NULL) {
++        PK11_FreeSlot(slot);
++    }
++
++    if (cert_list != NULL) {
++        CERT_DestroyCertList(cert_list);
++    }
++
++    PORT_Free(signed_random_value.data);
++
++    rv = NSS_ShutdownContext(nss_ctx);
++    if (rv != SECSuccess) {
++        DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n",
++                                 PR_GetError());
++    }
++
++    return ret;
++}
++
++static errno_t p11c_recv_data(TALLOC_CTX *mem_ctx, int fd, char **pin)
++{
++    uint8_t buf[IN_BUF_SIZE];
++    ssize_t len;
++    errno_t ret;
++    char *str;
++
++    errno = 0;
++    len = sss_atomic_read_s(fd, buf, IN_BUF_SIZE);
++    if (len == -1) {
++        ret = errno;
++        ret = (ret == 0) ? EINVAL: ret;
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "read failed [%d][%s].\n", ret, strerror(ret));
++        return ret;
++    }
++
++    if (len == 0 || *buf == '\0') {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Missing PIN.\n");
++        return EINVAL;
++    }
++
++    str = talloc_strndup(mem_ctx, (char *) buf, len);
++    if (str == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
++        return ENOMEM;
++    }
++
++    if (strlen(str) != len) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Input contains additional data, only PIN expected.\n");
++        talloc_free(str);
++        return EINVAL;
++    }
++
++    *pin = str;
++
++    return EOK;
++}
++
++int main(int argc, const char *argv[])
++{
++    int opt;
++    poptContext pc;
++    int debug_fd = -1;
++    errno_t ret;
++    TALLOC_CTX *main_ctx = NULL;
++    char *cert;
++    enum op_mode mode = OP_NONE;
++    enum pin_mode pin_mode = PIN_NONE;
++    char *pin = NULL;
++    char *slot_name_in = NULL;
++    char *token_name_out = NULL;
++    char *nss_db = NULL;
++
++    struct poptOption long_options[] = {
++        POPT_AUTOHELP
++        {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
++         _("Debug level"), NULL},
++        {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
++         _("Add debug timestamps"), NULL},
++        {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
++         _("Show timestamps with microseconds"), NULL},
++        {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
++         _("An open file descriptor for the debug logs"), NULL},
++        {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
++         &debug_to_stderr, 0,
++         _("Send the debug output to stderr directly."), NULL },
++        {"auth", 0, POPT_ARG_NONE, NULL, 'a', _("Run in auth mode"), NULL},
++        {"pre", 0, POPT_ARG_NONE, NULL, 'p', _("Run in pre-auth mode"), NULL},
++        {"pin", 0, POPT_ARG_NONE, NULL, 'i', _("Expect PIN on stdin"), NULL},
++        {"keypad", 0, POPT_ARG_NONE, NULL, 'k', _("Expect PIN on keypad"),
++         NULL},
++        {"nssdb", 0, POPT_ARG_STRING, &nss_db, 0, _("NSS DB to use"),
++         NULL},
++        POPT_TABLEEND
++    };
++
++    /* 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) {
++        case 'a':
++            if (mode != OP_NONE) {
++                fprintf(stderr,
++                        "\n--auth and --pre are mutually exclusive and " \
++                        "should be only used once.\n\n");
++                poptPrintUsage(pc, stderr, 0);
++                _exit(-1);
++            }
++            mode = OP_AUTH;
++            break;
++        case 'p':
++            if (mode != OP_NONE) {
++                fprintf(stderr,
++                        "\n--auth and --pre are mutually exclusive and " \
++                        "should be only used once.\n\n");
++                poptPrintUsage(pc, stderr, 0);
++                _exit(-1);
++            }
++            mode = OP_PREAUTH;
++            break;
++        case 'i':
++            if (pin_mode != PIN_NONE) {
++                fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \
++                                "and should be only used once.\n\n");
++                poptPrintUsage(pc, stderr, 0);
++                _exit(-1);
++            }
++            pin_mode = PIN_STDIN;
++            break;
++        case 'k':
++            if (pin_mode != PIN_NONE) {
++                fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \
++                                "and should be only used once.\n\n");
++                poptPrintUsage(pc, stderr, 0);
++                _exit(-1);
++            }
++            pin_mode = PIN_KEYPAD;
++            break;
++        default:
++            fprintf(stderr, "\nInvalid option %s: %s\n\n",
++                  poptBadOption(pc, 0), poptStrerror(opt));
++            poptPrintUsage(pc, stderr, 0);
++            _exit(-1);
++        }
++    }
++
++    if (nss_db == NULL) {
++        fprintf(stderr, "\nMissing NSS DB --nssdb must be specified.\n\n");
++        poptPrintUsage(pc, stderr, 0);
++        _exit(-1);
++    }
++
++    if (mode == OP_NONE) {
++        fprintf(stderr, "\nMissing operation mode, " \
++                        "either --auth or --pre must be specified.\n\n");
++        poptPrintUsage(pc, stderr, 0);
++        _exit(-1);
++    } else if (mode == OP_AUTH && pin_mode == PIN_NONE) {
++        fprintf(stderr, "\nMissing pin mode for authentication, " \
++                        "either --pin or --keypad must be specified.\n");
++        poptPrintUsage(pc, stderr, 0);
++        _exit(-1);
++    }
++
++    poptFreeContext(pc);
++
++    DEBUG_INIT(debug_level);
++
++    debug_prg_name = talloc_asprintf(NULL, "[sssd[p11_child[%d]]]", getpid());
++    if (debug_prg_name == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
++        goto fail;
++    }
++
++    if (debug_fd != -1) {
++        ret = set_debug_file_from_fd(debug_fd);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n");
++        }
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "p11_child started.\n");
++
++    DEBUG(SSSDBG_TRACE_INTERNAL, "Running in [%s] mode.\n",
++          mode == OP_AUTH ? "auth"
++                          : (mode == OP_PREAUTH ? "pre-auth" : "unknown"));
++
++    DEBUG(SSSDBG_TRACE_INTERNAL,
++          "Running with effective IDs: [%"SPRIuid"][%"SPRIgid"].\n",
++          geteuid(), getegid());
++
++    if (getuid() != 0) {
++        ret = setuid(0);
++        if (ret == -1) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "setuid failed: %d, p11_child might not work!\n", ret);
++        }
++    }
++
++    if (getgid() != 0) {
++        ret = setgid(0);
++        if (ret == -1) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "setgid failed: %d, p11_child might not work!\n", ret);
++        }
++    }
++
++    DEBUG(SSSDBG_TRACE_INTERNAL,
++          "Running with real IDs [%"SPRIuid"][%"SPRIgid"].\n",
++          getuid(), getgid());
++
++    main_ctx = talloc_new(NULL);
++    if (main_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
++        talloc_free(discard_const(debug_prg_name));
++        goto fail;
++    }
++    talloc_steal(main_ctx, debug_prg_name);
++
++
++    if (mode == OP_AUTH && pin_mode == PIN_STDIN) {
++        ret = p11c_recv_data(main_ctx, STDIN_FILENO, &pin);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read pin.\n");
++            goto fail;
++        }
++    }
++
++    ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, &cert,
++                  &token_name_out);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n");
++        goto fail;
++    }
++
++    if (cert != NULL) {
++        fprintf(stdout, "%s\n", token_name_out);
++        fprintf(stdout, "%s\n", cert);
++    }
++
++    talloc_free(main_ctx);
++    return EXIT_SUCCESS;
++fail:
++    DEBUG(SSSDBG_CRIT_FAILURE, "p11_child failed!\n");
++    close(STDOUT_FILENO);
++    talloc_free(main_ctx);
++    return EXIT_FAILURE;
++}
+-- 
+2.4.3
+
diff --git a/SOURCES/0031-SYSDB-Allow-calling-chown-on-the-sysdb-file-from-mon.patch b/SOURCES/0031-SYSDB-Allow-calling-chown-on-the-sysdb-file-from-mon.patch
deleted file mode 100644
index 5d69f05..0000000
--- a/SOURCES/0031-SYSDB-Allow-calling-chown-on-the-sysdb-file-from-mon.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From 3c97e3ab74309934687e65a768fb843d8b4608fa Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Thu, 9 Oct 2014 17:21:30 +0200
-Subject: [PATCH 31/46] SYSDB: Allow calling chown on the sysdb file from
- monitor
-
-Sysdb must be accessible for the nonroot sssd
-processes.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 0887c35bdb85adf0a4376dc8963294ea5a9d6da6)
----
- src/db/sysdb.c        | 21 +++++++++++++++++++++
- src/db/sysdb.h        |  9 +++++++++
- src/monitor/monitor.c |  3 ++-
- 3 files changed, 32 insertions(+), 1 deletion(-)
-
-diff --git a/src/db/sysdb.c b/src/db/sysdb.c
-index 8d6f00b52976228bfc9dfdc93503148837677346..1f02585e747dda6aadde772f76f30d3d69c4cfc0 100644
---- a/src/db/sysdb.c
-+++ b/src/db/sysdb.c
-@@ -1322,6 +1322,16 @@ int sysdb_init(TALLOC_CTX *mem_ctx,
-                struct sss_domain_info *domains,
-                bool allow_upgrade)
- {
-+    return sysdb_init_ext(mem_ctx, domains, allow_upgrade, false, 0, 0);
-+}
-+
-+int sysdb_init_ext(TALLOC_CTX *mem_ctx,
-+                   struct sss_domain_info *domains,
-+                   bool allow_upgrade,
-+                   bool chown_dbfile,
-+                   uid_t uid,
-+                   gid_t gid)
-+{
-     struct sss_domain_info *dom;
-     struct sysdb_ctx *sysdb;
-     int ret;
-@@ -1343,6 +1353,17 @@ int sysdb_init(TALLOC_CTX *mem_ctx,
-             return ret;
-         }
- 
-+        if (chown_dbfile) {
-+            ret = chown(sysdb->ldb_file, uid, gid);
-+            if (ret != 0) {
-+                ret = errno;
-+                DEBUG(SSSDBG_CRIT_FAILURE,
-+                      "Cannot set sysdb ownership to %"SPRIuid":%"SPRIgid"\n",
-+                      uid, gid);
-+                return ret;
-+            }
-+        }
-+
-         dom->sysdb = talloc_move(dom, &sysdb);
-     }
- 
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index 0d0971d98dd684e47ae8ec067447169f41ebba67..ebb1bbedaf2df3030a012f1f0be8c5a069399cc3 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -533,6 +533,15 @@ uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom,
- int sysdb_init(TALLOC_CTX *mem_ctx,
-                struct sss_domain_info *domains,
-                bool allow_upgrade);
-+
-+/* Same as sysdb_init, but additionally allows to change
-+ * file ownership of the sysdb databases. */
-+int sysdb_init_ext(TALLOC_CTX *mem_ctx,
-+                   struct sss_domain_info *domains,
-+                   bool allow_upgrade,
-+                   bool chown_dbfile,
-+                   uid_t uid, gid_t gid);
-+
- /* used to initialize only one domain database.
-  * Do NOT use if sysdb_init has already been called */
- int sysdb_domain_init(TALLOC_CTX *mem_ctx,
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 37f6e928be3508762e1c3afadbb67762f5cc1d38..04702428c4ed7fd1d77c6f18e491fa69b3700f4f 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -2312,7 +2312,8 @@ static int monitor_process_init(struct mt_ctx *ctx,
-     if (!tmp_ctx) {
-         return ENOMEM;
-     }
--    ret = sysdb_init(tmp_ctx, ctx->domains, true);
-+    ret = sysdb_init_ext(tmp_ctx, ctx->domains, true,
-+                         true, ctx->uid, ctx->gid);
-     if (ret != EOK) {
-         SYSDB_VERSION_ERROR_DAEMON(ret);
-         return ret;
--- 
-1.9.3
-
diff --git a/SOURCES/0032-NSS-Run-as-a-user-specified-by-monitor.patch b/SOURCES/0032-NSS-Run-as-a-user-specified-by-monitor.patch
deleted file mode 100644
index 4ac28ba..0000000
--- a/SOURCES/0032-NSS-Run-as-a-user-specified-by-monitor.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From d4bbfc12cae1eb2efe2451885605c37ec7702a21 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 21 Sep 2014 13:52:05 +0200
-Subject: [PATCH 32/46] NSS: Run as a user specified by monitor
-
-Adds the NSS responder to the list of services known to work as a
-non-root user and becomes the specified user after starting the NSS
-responder.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 5d19966eda424bd71964c6913b84d705dce3b350)
----
- src/monitor/monitor.c      | 3 +++
- src/responder/nss/nsssrv.c | 3 ++-
- 2 files changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 04702428c4ed7fd1d77c6f18e491fa69b3700f4f..297648a60836cec1bd95c0a2972c8d14be32675a 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1062,6 +1062,9 @@ static errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
-  */
- static bool svc_supported_as_nonroot(const char *svc_name)
- {
-+    if (strcmp(svc_name, "nss") == 0) {
-+        return true;
-+    }
-     return false;
- }
- 
-diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
-index 420fd3d316959a67737f23e9a8b3d1c797583ea3..dbbdb4f844410eabe01f184ccdf8d9deb41833f4 100644
---- a/src/responder/nss/nsssrv.c
-+++ b/src/responder/nss/nsssrv.c
-@@ -568,7 +568,8 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_nss";
- 
--    ret = server_setup("sssd[nss]", 0, 0, 0, CONFDB_NSS_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[nss]", 0, uid, gid, CONFDB_NSS_CONF_ENTRY,
-+                       &main_ctx);
-     if (ret != EOK) return 2;
- 
-     ret = die_if_parent_died();
--- 
-1.9.3
-
diff --git a/SOURCES/0032-pack_message_v3-allow-empty-name.patch b/SOURCES/0032-pack_message_v3-allow-empty-name.patch
new file mode 100644
index 0000000..695df0f
--- /dev/null
+++ b/SOURCES/0032-pack_message_v3-allow-empty-name.patch
@@ -0,0 +1,31 @@
+From 1b9a3d516341560ccf8b5f9fab0886f3d05defce Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 26 Jun 2015 14:45:21 +0200
+Subject: [PATCH 32/37] pack_message_v3: allow empty name
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/sss_client/pam_message.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/sss_client/pam_message.c b/src/sss_client/pam_message.c
+index b8104c680d0e733b713c665e6206dc4b0d379237..b239f6f53da54054c52e484bdd076193709cb003 100644
+--- a/src/sss_client/pam_message.c
++++ b/src/sss_client/pam_message.c
+@@ -107,9 +107,10 @@ int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer)
+     uint8_t *buf;
+     size_t rp;
+ 
+-    len = sizeof(uint32_t) +
+-          2*sizeof(uint32_t) + pi->pam_user_size +
+-          sizeof(uint32_t);
++    len = sizeof(uint32_t) + sizeof(uint32_t);
++
++    len +=  *pi->pam_user != '\0' ?
++                2*sizeof(uint32_t) + pi->pam_user_size : 0;
+     len += *pi->pam_service != '\0' ?
+                 2*sizeof(uint32_t) + pi->pam_service_size : 0;
+     len += *pi->pam_tty != '\0' ?
+-- 
+2.4.3
+
diff --git a/SOURCES/0033-authok-add-support-for-Smart-Card-related-authtokens.patch b/SOURCES/0033-authok-add-support-for-Smart-Card-related-authtokens.patch
new file mode 100644
index 0000000..891e411
--- /dev/null
+++ b/SOURCES/0033-authok-add-support-for-Smart-Card-related-authtokens.patch
@@ -0,0 +1,287 @@
+From f9a027877ecdd697a052f6135963fb3726692310 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 26 Jun 2015 17:55:23 +0200
+Subject: [PATCH 33/37] authok: add support for Smart Card related authtokens
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/sss_client/sss_cli.h        |  7 ++++
+ src/tests/cmocka/test_authtok.c | 75 +++++++++++++++++++++++++++++++++++++++++
+ src/util/authtok.c              | 64 +++++++++++++++++++++++++++++++++++
+ src/util/authtok.h              | 41 ++++++++++++++++++++++
+ 4 files changed, 187 insertions(+)
+
+diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
+index 0dfb525bacba5f6928e8ece76e05f60d7f2eebd5..3c4e938ae37c042879b1ae26fe389fa37cef682c 100644
+--- a/src/sss_client/sss_cli.h
++++ b/src/sss_client/sss_cli.h
+@@ -308,6 +308,13 @@ enum sss_authtok_type {
+     SSS_AUTHTOK_TYPE_2FA =       0x0003, /**< Authentication token has two
+                                           * factors, they may or may no contain
+                                           * a trailing \\0 */
++    SSS_AUTHTOK_TYPE_SC_PIN =    0x0004, /**< Authentication token is a Smart
++                                          * Card pin, it may or may no contain
++                                          * a trailing \\0 */
++    SSS_AUTHTOK_TYPE_SC_KEYPAD = 0x0005, /**< Authentication token indicates
++                                          * Smart Card authentication is used
++                                          * and that the pin will be entered
++                                          * at the card reader. */
+ };
+ 
+ /**
+diff --git a/src/tests/cmocka/test_authtok.c b/src/tests/cmocka/test_authtok.c
+index 5aa47c7b6b8c955666a9c73d5f9627d6378d13e0..30dcc9c8401103a275bd592fe8afd2c2f396ffb1 100644
+--- a/src/tests/cmocka/test_authtok.c
++++ b/src/tests/cmocka/test_authtok.c
+@@ -488,6 +488,77 @@ void test_sss_authtok_2fa_blobs_missing_null(void **state)
+     MISSING_NULL_CHECK;
+ }
+ 
++void test_sss_authtok_sc_keypad(void **state)
++{
++    struct test_state *ts;
++
++    ts = talloc_get_type_abort(*state, struct test_state);
++
++    sss_authtok_set_sc_keypad(NULL);
++
++    sss_authtok_set_sc_keypad(ts->authtoken);
++    assert_int_equal(sss_authtok_get_type(ts->authtoken),
++                     SSS_AUTHTOK_TYPE_SC_KEYPAD);
++    assert_int_equal(sss_authtok_get_size(ts->authtoken), 0);
++    assert_null(sss_authtok_get_data(ts->authtoken));
++}
++
++void test_sss_authtok_sc_pin(void **state)
++{
++    struct test_state *ts;
++    int ret;
++    size_t size;
++    const char *pin;
++    size_t len;
++
++    ts = talloc_get_type_abort(*state, struct test_state);
++
++    ret = sss_authtok_set_sc_pin(NULL, NULL, 0);
++    assert_int_equal(ret, EFAULT);
++
++    ret = sss_authtok_set_sc_pin(ts->authtoken, NULL, 0);
++    assert_int_equal(ret, EINVAL);
++
++    ret = sss_authtok_set_sc_pin(ts->authtoken, "12345678", 0);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(sss_authtok_get_type(ts->authtoken),
++                     SSS_AUTHTOK_TYPE_SC_PIN);
++    size = sss_authtok_get_size(ts->authtoken);
++    assert_int_equal(size, 9);
++    assert_memory_equal(sss_authtok_get_data(ts->authtoken), "12345678\0",
++                                             size);
++
++    ret = sss_authtok_set_sc_pin(ts->authtoken, "12345678", 5);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(sss_authtok_get_type(ts->authtoken),
++                     SSS_AUTHTOK_TYPE_SC_PIN);
++    size = sss_authtok_get_size(ts->authtoken);
++    assert_int_equal(size, 6);
++    assert_memory_equal(sss_authtok_get_data(ts->authtoken), "12345\0",
++                                             size);
++
++    ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(len, 5);
++    assert_string_equal(pin, "12345");
++
++    sss_authtok_set_empty(ts->authtoken);
++
++    ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len);
++    assert_int_equal(ret, ENOENT);
++
++    ret = sss_authtok_set_password(ts->authtoken, "12345", 0);
++    assert_int_equal(ret, EOK);
++
++    ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len);
++    assert_int_equal(ret, EACCES);
++
++    sss_authtok_set_empty(ts->authtoken);
++
++    ret = sss_authtok_get_sc_pin(NULL, &pin, &len);
++    assert_int_equal(ret, EFAULT);
++}
++
+ int main(int argc, const char *argv[])
+ {
+     poptContext pc;
+@@ -517,6 +588,10 @@ int main(int argc, const char *argv[])
+                                         setup, teardown),
+         cmocka_unit_test_setup_teardown(test_sss_authtok_2fa_blobs_missing_null,
+                                         setup, teardown),
++        cmocka_unit_test_setup_teardown(test_sss_authtok_sc_keypad,
++                                        setup, teardown),
++        cmocka_unit_test_setup_teardown(test_sss_authtok_sc_pin,
++                                        setup, teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+diff --git a/src/util/authtok.c b/src/util/authtok.c
+index 45761df80175fded8a6c6e5dac8a90180b11d225..6062cd875ce2c6b541ef237e7f7bdddac80366c5 100644
+--- a/src/util/authtok.c
++++ b/src/util/authtok.c
+@@ -39,6 +39,8 @@ size_t sss_authtok_get_size(struct sss_auth_token *tok)
+     case SSS_AUTHTOK_TYPE_PASSWORD:
+     case SSS_AUTHTOK_TYPE_CCFILE:
+     case SSS_AUTHTOK_TYPE_2FA:
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+         return tok->length;
+     case SSS_AUTHTOK_TYPE_EMPTY:
+         return 0;
+@@ -72,6 +74,8 @@ errno_t sss_authtok_get_password(struct sss_auth_token *tok,
+         return EOK;
+     case SSS_AUTHTOK_TYPE_CCFILE:
+     case SSS_AUTHTOK_TYPE_2FA:
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+         return EACCES;
+     }
+ 
+@@ -95,6 +99,8 @@ errno_t sss_authtok_get_ccfile(struct sss_auth_token *tok,
+         return EOK;
+     case SSS_AUTHTOK_TYPE_PASSWORD:
+     case SSS_AUTHTOK_TYPE_2FA:
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+         return EACCES;
+     }
+ 
+@@ -144,9 +150,11 @@ void sss_authtok_set_empty(struct sss_auth_token *tok)
+         return;
+     case SSS_AUTHTOK_TYPE_PASSWORD:
+     case SSS_AUTHTOK_TYPE_2FA:
++    case SSS_AUTHTOK_TYPE_SC_PIN:
+         safezero(tok->data, tok->length);
+         break;
+     case SSS_AUTHTOK_TYPE_CCFILE:
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
+         break;
+     }
+ 
+@@ -187,6 +195,11 @@ errno_t sss_authtok_set(struct sss_auth_token *tok,
+         return sss_authtok_set_ccfile(tok, (const char *)data, len);
+     case SSS_AUTHTOK_TYPE_2FA:
+         return sss_authtok_set_2fa_from_blob(tok, data, len);
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++        return sss_authtok_set_sc_pin(tok, (const char*)data, len);
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++        sss_authtok_set_sc_keypad(tok);
++        return EOK;
+     case SSS_AUTHTOK_TYPE_EMPTY:
+         sss_authtok_set_empty(tok);
+         return EOK;
+@@ -411,3 +424,54 @@ errno_t sss_authtok_set_2fa(struct sss_auth_token *tok,
+ 
+     return EOK;
+ }
++
++errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin,
++                               size_t len)
++{
++    if (tok == NULL) {
++        return EFAULT;
++    }
++    if (pin == NULL) {
++        return EINVAL;
++    }
++
++    sss_authtok_set_empty(tok);
++
++    return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_SC_PIN,
++                                  "sc_pin", pin, len);
++}
++
++errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin,
++                               size_t *len)
++{
++    if (!tok) {
++        return EFAULT;
++    }
++    switch (tok->type) {
++    case SSS_AUTHTOK_TYPE_EMPTY:
++        return ENOENT;
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++        *pin = (const char *)tok->data;
++        if (len) {
++            *len = tok->length - 1;
++        }
++        return EOK;
++    case SSS_AUTHTOK_TYPE_PASSWORD:
++    case SSS_AUTHTOK_TYPE_CCFILE:
++    case SSS_AUTHTOK_TYPE_2FA:
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++        return EACCES;
++    }
++
++    return EINVAL;
++}
++
++void sss_authtok_set_sc_keypad(struct sss_auth_token *tok)
++{
++    if (!tok) {
++        return;
++    }
++    sss_authtok_set_empty(tok);
++
++    tok->type = SSS_AUTHTOK_TYPE_SC_KEYPAD;
++}
+diff --git a/src/util/authtok.h b/src/util/authtok.h
+index cb366270832852281a222018f8e27feb1500ff01..f1a01a42306a720fc39e701078550a071835e980 100644
+--- a/src/util/authtok.h
++++ b/src/util/authtok.h
+@@ -223,4 +223,45 @@ errno_t sss_authtok_set_2fa(struct sss_auth_token *tok,
+ errno_t sss_authtok_get_2fa(struct sss_auth_token *tok,
+                             const char **fa1, size_t *fa1_len,
+                             const char **fa2, size_t *fa2_len);
++
++/**
++ * @brief Set a Smart Card pin into a an auth token, replacing any previous data
++ *
++ * @param tok        A pointer to a sss_auth_token structure to change, also
++ *                   used as a memory context to allocate the internal data.
++ * @param pin        A string
++ * @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_sc_pin(struct sss_auth_token *tok, const char *pin,
++                               size_t len);
++
++/**
++ * @brief Returns a Smart Card pin as const string if the auth token is of
++ *        type SSS_AUTHTOK_TYPE_SC_PIN, otherwise it returns an error
++ *
++ * @param tok    A pointer to an sss_auth_token
++ * @param pin    A pointer to a const char *, that will point to a null
++ *               terminated string
++ * @param len    The length of the pin string
++ *
++ * @return       EOK on success
++ *               ENOENT if the token is empty
++ *               EACCESS if the token is not a Smart Card pin token
++ */
++errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin,
++                               size_t *len);
++
++/**
++ * @brief Sets an auth token to type SSS_AUTHTOK_TYPE_SC_KEYPAD, replacing any
++ *        previous data
++ *
++ * @param tok        A pointer to a sss_auth_token structure to change, also
++ *                   used as a memory context to allocate the internal data.
++ */
++void sss_authtok_set_sc_keypad(struct sss_auth_token *tok);
++
+ #endif /*  __AUTHTOK_H__ */
+-- 
+2.4.3
+
diff --git a/SOURCES/0033-responder_common-Create-fd-for-pipe-in-helper.patch b/SOURCES/0033-responder_common-Create-fd-for-pipe-in-helper.patch
deleted file mode 100644
index 06adf5c..0000000
--- a/SOURCES/0033-responder_common-Create-fd-for-pipe-in-helper.patch
+++ /dev/null
@@ -1,212 +0,0 @@
-From 2d5dbb5dbe674f012fc044f03441538b9b400983 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Wed, 15 Oct 2014 17:35:12 +0200
-Subject: [PATCH 33/46] responder_common: Create fd for pipe in helper
-
-Move creating of file descriptor for pipes into
-helper function and make this function public.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 2ce29e05e62b2702ba4df5f3316eaf250b0ada7f)
----
- src/responder/common/responder.h        |   2 +
- src/responder/common/responder_common.c | 135 +++++++++++++++-----------------
- 2 files changed, 65 insertions(+), 72 deletions(-)
-
-diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
-index 97552ec472c5baa285b41cc48b51149f3ef6adb5..d233710782fe7df1bbcc338e3815d1701557519e 100644
---- a/src/responder/common/responder.h
-+++ b/src/responder/common/responder.h
-@@ -176,6 +176,8 @@ responder_get_domain(struct resp_ctx *rctx, const char *domain);
- errno_t responder_get_domain_by_id(struct resp_ctx *rctx, const char *id,
-                                    struct sss_domain_info **_ret_dom);
- 
-+int create_pipe_fd(const char *sock_name, int *fd, mode_t umaskval);
-+
- /* responder_cmd.c */
- int sss_cmd_empty_packet(struct sss_packet *packet);
- int sss_cmd_send_empty(struct cli_ctx *cctx, TALLOC_CTX *freectx);
-diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
-index 0ec2372e8d08f1002b303b5edc6897f17cee9699..a262a2c1487c786404b6d0d4c720edd1679279d0 100644
---- a/src/responder/common/responder_common.c
-+++ b/src/responder/common/responder_common.c
-@@ -584,10 +584,69 @@ static int sss_dp_init(struct resp_ctx *rctx,
-     return EOK;
- }
- 
-+int create_pipe_fd(const char *sock_name, int *fd, mode_t umaskval)
-+{
-+    struct sockaddr_un addr;
-+    errno_t ret;
-+
-+    *fd = socket(AF_UNIX, SOCK_STREAM, 0);
-+    if (*fd == -1) {
-+        return EIO;
-+    }
-+
-+    umask(umaskval);
-+
-+    ret = set_nonblocking(*fd);
-+    if (ret != EOK) {
-+        goto done;
-+    }
-+
-+    ret = set_close_on_exec(*fd);
-+    if (ret != EOK) {
-+        goto done;
-+    }
-+
-+    memset(&addr, 0, sizeof(addr));
-+    addr.sun_family = AF_UNIX;
-+    strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path) - 1);
-+    addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
-+
-+    /* make sure we have no old sockets around */
-+    ret = unlink(sock_name);
-+    if (ret != 0 && errno != ENOENT) {
-+        ret = errno;
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Cannot remove old socket (errno=%d), bind might fail!\n", ret);
-+    }
-+
-+    if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Unable to bind on socket '%s'\n", sock_name);
-+        ret = EIO;
-+        goto done;
-+    }
-+    if (listen(*fd, 10) != 0) {
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Unable to listen on socket '%s'\n", sock_name);
-+        ret = EIO;
-+        goto done;
-+    }
-+
-+    ret = EOK;
-+
-+done:
-+    /* we want default permissions on created files to be very strict,
-+       so set our umask to 0177 */
-+    umask(0177);
-+    if (ret != EOK) {
-+        close(*fd);
-+    }
-+    return ret;
-+}
-+
- /* create a unix socket and listen to it */
- static int set_unix_socket(struct resp_ctx *rctx)
- {
--    struct sockaddr_un addr;
-     errno_t ret;
-     struct accept_fd_ctx *accept_ctx;
- 
-@@ -628,42 +687,11 @@ static int set_unix_socket(struct resp_ctx *rctx)
- #endif
- 
-     if (rctx->sock_name != NULL ) {
--        rctx->lfd = socket(AF_UNIX, SOCK_STREAM, 0);
--        if (rctx->lfd == -1) {
--            return EIO;
--        }
--
-         /* Set the umask so that permissions are set right on the socket.
-          * It must be readable and writable by anybody on the system. */
--        umask(0111);
--
--        ret = set_nonblocking(rctx->lfd);
-+        ret = create_pipe_fd(rctx->sock_name, &rctx->lfd, 0111);
-         if (ret != EOK) {
--            goto failed;
--        }
--
--        ret = set_close_on_exec(rctx->lfd);
--        if (ret != EOK) {
--            goto failed;
--        }
--
--        memset(&addr, 0, sizeof(addr));
--        addr.sun_family = AF_UNIX;
--        strncpy(addr.sun_path, rctx->sock_name, sizeof(addr.sun_path)-1);
--        addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
--
--        /* make sure we have no old sockets around */
--        unlink(rctx->sock_name);
--
--        if (bind(rctx->lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "Unable to bind on socket '%s'\n", rctx->sock_name);
--            goto failed;
--        }
--        if (listen(rctx->lfd, 10) != 0) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "Unable to listen on socket '%s'\n", rctx->sock_name);
--            goto failed;
-+            return ret;
-         }
- 
-         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
-@@ -682,42 +710,11 @@ static int set_unix_socket(struct resp_ctx *rctx)
- 
-     if (rctx->priv_sock_name != NULL ) {
-         /* create privileged pipe */
--        rctx->priv_lfd = socket(AF_UNIX, SOCK_STREAM, 0);
--        if (rctx->priv_lfd == -1) {
--            close(rctx->lfd);
--            return EIO;
--        }
--
--        umask(0177);
--
--        ret = set_nonblocking(rctx->priv_lfd);
-+        ret = create_pipe_fd(rctx->priv_sock_name, &rctx->priv_lfd, 0177);
-         if (ret != EOK) {
-             goto failed;
-         }
- 
--        ret = set_close_on_exec(rctx->priv_lfd);
--        if (ret != EOK) {
--            goto failed;
--        }
--
--        memset(&addr, 0, sizeof(addr));
--        addr.sun_family = AF_UNIX;
--        strncpy(addr.sun_path, rctx->priv_sock_name, sizeof(addr.sun_path)-1);
--        addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
--
--        unlink(rctx->priv_sock_name);
--
--        if (bind(rctx->priv_lfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "Unable to bind on socket '%s'\n", rctx->priv_sock_name);
--            goto failed;
--        }
--        if (listen(rctx->priv_lfd, 10) != 0) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "Unable to listen on socket '%s'\n", rctx->priv_sock_name);
--            goto failed;
--        }
--
-         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
-         if(!accept_ctx) goto failed;
-         accept_ctx->rctx = rctx;
-@@ -733,15 +730,9 @@ static int set_unix_socket(struct resp_ctx *rctx)
-         }
-     }
- 
--    /* we want default permissions on created files to be very strict,
--       so set our umask to 0177 */
--    umask(0177);
-     return EOK;
- 
- failed:
--    /* we want default permissions on created files to be very strict,
--       so set our umask to 0177 */
--    umask(0177);
-     close(rctx->lfd);
-     close(rctx->priv_lfd);
-     return EIO;
--- 
-1.9.3
-
diff --git a/SOURCES/0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch b/SOURCES/0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch
new file mode 100644
index 0000000..8f70539
--- /dev/null
+++ b/SOURCES/0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch
@@ -0,0 +1,1732 @@
+unchanged:
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -115,6 +115,8 @@
+ #define CONFDB_PAM_TRUSTED_USERS "pam_trusted_users"
+ #define CONFDB_PAM_PUBLIC_DOMAINS "pam_public_domains"
+ #define CONFDB_PAM_ACCOUNT_EXPIRED_MESSAGE "pam_account_expired_message"
++#define CONFDB_PAM_CERT_AUTH "pam_cert_auth"
++#define CONFDB_PAM_CERT_DB_PATH "pam_cert_db_path"
+ 
+ /* SUDO */
+ #define CONFDB_SUDO_CONF_ENTRY "config/sudo"
+unchanged:
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -382,6 +382,8 @@ dist_noinst_DATA = \
+     contrib/ci/distro.sh \
+     contrib/ci/misc.sh \
+     contrib/ci/sssd.supp \
++    src/tests/cmocka/p11_nssdb/cert9.db \
++    src/tests/cmocka/p11_nssdb/key4.db \
+     $(NULL)
+ 
+ ###############################
+@@ -1086,6 +1088,7 @@ sssd_pam_SOURCES = \
+     src/responder/pam/pam_LOCAL_domain.c \
+     src/responder/pam/pamsrv.c \
+     src/responder/pam/pamsrv_cmd.c \
++    src/responder/pam/pamsrv_p11.c \
+     src/responder/pam/pamsrv_dp.c \
+     src/responder/pam/pam_helpers.c \
+     $(SSSD_RESPONDER_OBJ)
+@@ -1877,11 +1880,13 @@ pam_srv_tests_SOURCES = \
+     src/tests/cmocka/test_pam_srv.c \
+     src/sss_client/pam_message.c \
+     src/responder/pam/pamsrv_cmd.c \
++    src/responder/pam/pamsrv_p11.c \
+     src/responder/pam/pam_helpers.c \
+     src/responder/pam/pamsrv_dp.c \
+     src/responder/pam/pam_LOCAL_domain.c \
+     $(NULL)
+ pam_srv_tests_CFLAGS = \
++    -U SSSD_LIBEXEC_PATH -DSSSD_LIBEXEC_PATH=\"$(abs_builddir)\" \
+     $(AM_CFLAGS) \
+     $(NULL)
+ pam_srv_tests_LDFLAGS = \
+unchanged:
+--- a/configure.ac
++++ b/configure.ac
+@@ -400,6 +400,9 @@ abs_build_dir=`pwd`
+ AC_DEFINE_UNQUOTED([ABS_BUILD_DIR], ["$abs_build_dir"], [Absolute path to the build directory])
+ AC_SUBST([abs_builddir], $abs_build_dir)
+ 
++my_srcdir=`readlink -f $srcdir`
++AC_DEFINE_UNQUOTED([ABS_SRC_DIR], ["$my_srcdir"], [Absolute path to the source directory])
++
+ AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/doxy.config
+                  src/sysv/sssd src/sysv/gentoo/sssd src/sysv/SUSE/sssd
+                  po/Makefile.in src/man/Makefile src/tests/cwrap/Makefile
+unchanged:
+--- a/src/responder/pam/pamsrv.c
++++ b/src/responder/pam/pamsrv.c
+@@ -50,6 +50,8 @@
+ #define ALL_DOMAIMS_ARE_PUBLIC "all"
+ #define NO_DOMAIMS_ARE_PUBLIC "none"
+ #define DEFAULT_ALLOWED_UIDS ALL_UIDS_ALLOWED
++#define DEFAULT_PAM_CERT_AUTH false
++#define DEFAULT_PAM_CERT_DB_PATH SYSCONFDIR"/pki/nssdb"
+ 
+ struct mon_cli_iface monitor_pam_methods = {
+     { &mon_cli_iface_meta, 0 },
+@@ -302,6 +304,38 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
+         goto done;
+     }
+ 
++    /* Check if certificate based authentication is enabled */
++    ret = confdb_get_bool(pctx->rctx->cdb,
++                          CONFDB_PAM_CONF_ENTRY,
++                          CONFDB_PAM_CERT_AUTH,
++                          DEFAULT_PAM_CERT_AUTH,
++                          &pctx->cert_auth);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to determine get cert db path.\n");
++        goto done;
++    }
++
++    pctx->p11_child_debug_fd = -1;
++    if (pctx->cert_auth) {
++        ret = p11_child_init(pctx);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_FATAL_FAILURE, "p11_child_init failed.\n");
++            goto done;
++        }
++
++        ret = confdb_get_string(pctx->rctx->cdb, pctx,
++                                CONFDB_PAM_CONF_ENTRY,
++                                CONFDB_PAM_CERT_DB_PATH,
++                                DEFAULT_PAM_CERT_DB_PATH,
++                                &pctx->nss_db);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_FATAL_FAILURE,
++                  "Failed to determine if certificate based authentication is " \
++                  "enabled or not.\n");
++            goto done;
++        }
++    }
++
+     ret = EOK;
+ 
+ done:
+unchanged:
+--- a/src/responder/pam/pamsrv.h
++++ b/src/responder/pam/pamsrv.h
+@@ -43,6 +43,10 @@ struct pam_ctx {
+     /* List of domains that are accessible even for untrusted users. */
+     char **public_domains;
+     int public_domains_count;
++
++    bool cert_auth;
++    int p11_child_debug_fd;
++    char *nss_db;
+ };
+ 
+ struct pam_auth_dp_req {
+@@ -65,6 +69,9 @@ struct pam_auth_req {
+     bool cached_auth_failed;
+ 
+     struct pam_auth_dp_req *dpreq_spy;
++
++    struct ldb_message *cert_user_obj;
++    char *token_name;
+ };
+ 
+ struct sss_cmd_table *get_pam_cmds(void);
+@@ -73,4 +80,19 @@ int pam_dp_send_req(struct pam_auth_req *preq, int timeout);
+ 
+ int LOCAL_pam_handler(struct pam_auth_req *preq);
+ 
++errno_t p11_child_init(struct pam_ctx *pctx);
++
++struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
++                                       struct tevent_context *ev,
++                                       int child_debug_fd,
++                                       const char *nss_db,
++                                       time_t timeout,
++                                       struct pam_data *pd);
++errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
++                            char **cert, char **token_name);
++
++errno_t add_pam_cert_response(struct pam_data *pd, const char *user,
++                              const char *token_name);
++
++bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd);
+ #endif /* __PAMSRV_H__ */
+unchanged:
+--- a/src/responder/pam/pamsrv_cmd.c
++++ b/src/responder/pam/pamsrv_cmd.c
+@@ -31,6 +31,7 @@
+ #include "providers/data_provider.h"
+ #include "responder/pam/pamsrv.h"
+ #include "responder/pam/pam_helpers.h"
++#include "responder/common/responder_cache_req.h"
+ #include "db/sysdb.h"
+ 
+ enum pam_verbosity {
+@@ -49,6 +50,7 @@ static errno_t
+ pam_get_last_online_auth_with_curr_token(struct sss_domain_info *domain,
+                                          const char *name,
+                                          uint64_t *_value);
++
+ static void pam_reply(struct pam_auth_req *preq);
+ 
+ static errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx,
+@@ -154,6 +156,13 @@ static int extract_authtok_v2(struct sss_auth_token *tok,
+         ret = sss_authtok_set(tok, SSS_AUTHTOK_TYPE_2FA,
+                               auth_token_data, auth_token_length);
+         break;
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++        ret = sss_authtok_set_sc_pin(tok, (const char *) auth_token_data,
++                                     auth_token_length);
++        break;
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++        sss_authtok_set_sc_keypad(tok);
++        break;
+     default:
+         return EINVAL;
+     }
+@@ -892,6 +901,7 @@ static void pam_handle_cached_login(struct pam_auth_req *preq, int ret,
+ }
+ 
+ static void pam_forwarder_cb(struct tevent_req *req);
++static void pam_forwarder_cert_cb(struct tevent_req *req);
+ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min,
+                                        const char *err_msg, void *ptr);
+ static int pam_check_user_search(struct pam_auth_req *preq);
+@@ -939,9 +949,22 @@ static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *p
+         goto done;
+     }
+ 
+-    ret = sss_parse_name_for_domains(pd, cctx->rctx->domains,
+-                                     cctx->rctx->default_domain, pd->logon_name,
+-                                     &pd->domain, &pd->user);
++    if (pd->logon_name != NULL) {
++        ret = sss_parse_name_for_domains(pd, cctx->rctx->domains,
++                                         cctx->rctx->default_domain,
++                                         pd->logon_name,
++                                         &pd->domain, &pd->user);
++    } else {
++        /* Only SSS_PAM_PREAUTH request may have a missing name, e.g. if the
++         * name is determined with the help of a certificate */
++        if (pd->cmd == SSS_PAM_PREAUTH) {
++            ret = EOK;
++        } else {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n");
++            ret = EINVAL;
++            goto done;
++        }
++    }
+ 
+     DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
+ 
+@@ -1052,49 +1075,66 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
+         goto done;
+     }
+ 
+-    /* now check user is valid */
+-    if (pd->domain) {
+-        preq->domain = responder_get_domain(cctx->rctx, pd->domain);
+-        if (!preq->domain) {
+-            ret = ENOENT;
+-            goto done;
+-        }
+-
+-        ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
+-                                      preq->domain, pd->user);
+-        if (ncret == EEXIST) {
+-            /* User found in the negative cache */
+-            ret = ENOENT;
+-            goto done;
+-        }
+-    } else {
+-        for (dom = preq->cctx->rctx->domains;
+-             dom;
+-             dom = get_next_domain(dom, false)) {
+-            if (dom->fqnames) continue;
++    if (pd->user != NULL) {
++        /* now check user is valid */
++        if (pd->domain) {
++            preq->domain = responder_get_domain(cctx->rctx, pd->domain);
++            if (!preq->domain) {
++                ret = ENOENT;
++                goto done;
++            }
+ 
+             ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
+-                                          dom, pd->user);
+-            if (ncret == ENOENT) {
+-                /* User not found in the negative cache
+-                 * Proceed with PAM actions
+-                 */
+-                break;
++                                          preq->domain, pd->user);
++            if (ncret == EEXIST) {
++                /* User found in the negative cache */
++                ret = ENOENT;
++                goto done;
+             }
++        } else {
++            for (dom = preq->cctx->rctx->domains;
++                 dom;
++                 dom = get_next_domain(dom, false)) {
++                if (dom->fqnames) continue;
+ 
+-            /* Try the next domain */
+-            DEBUG(SSSDBG_TRACE_FUNC,
+-                  "User [%s@%s] filtered out (negative cache). "
+-                   "Trying next domain.\n", pd->user, dom->name);
++                ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
++                                              dom, pd->user);
++                if (ncret == ENOENT) {
++                    /* User not found in the negative cache
++                     * Proceed with PAM actions
++                     */
++                    break;
++                }
++
++                /* Try the next domain */
++                DEBUG(SSSDBG_TRACE_FUNC,
++                      "User [%s@%s] filtered out (negative cache). "
++                       "Trying next domain.\n", pd->user, dom->name);
++            }
++
++            if (!dom) {
++                ret = ENOENT;
++                goto done;
++            }
++            preq->domain = dom;
+         }
++    }
+ 
+-        if (!dom) {
+-            ret = ENOENT;
+-            goto done;
++    if (may_do_cert_auth(pctx, pd)) {
++        req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd,
++                                  pctx->nss_db, 10, pd);
++        if (req == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n");
++            ret = ENOMEM;
++        } else {
++            tevent_req_set_callback(req, pam_forwarder_cert_cb, preq);
++            ret = EAGAIN;
+         }
+-        preq->domain = dom;
++
++        goto done;
+     }
+ 
++
+     if (preq->domain->provider == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE,
+               "Domain [%s] has no auth provider.\n", preq->domain->name);
+@@ -1113,6 +1153,142 @@ done:
+     return pam_check_user_done(preq, ret);
+ }
+ 
++static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req);
++static void pam_forwarder_cert_cb(struct tevent_req *req)
++{
++    struct pam_auth_req *preq = tevent_req_callback_data(req,
++                                                         struct pam_auth_req);
++    struct cli_ctx *cctx = preq->cctx;
++    struct pam_data *pd;
++    errno_t ret = EOK;
++    char *cert;
++    struct pam_ctx *pctx =
++            talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
++
++    ret = pam_check_cert_recv(req, preq, &cert, &preq->token_name);
++    talloc_free(req);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "get_cert request failed.\n");
++        goto done;
++    }
++
++    pd = preq->pd;
++
++    if (cert == NULL) {
++        if (pd->logon_name == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "No certificate found and no logon name given, " \
++                  "authentication not possible.\n");;
++            ret = ENOENT;
++        } else {
++            if (pd->cmd == SSS_PAM_AUTHENTICATE) {
++                DEBUG(SSSDBG_CRIT_FAILURE,
++                      "No certificate returned, authentication failed.\n");
++                ret = ENOENT;
++            } else {
++                ret = pam_check_user_search(preq);
++                if (ret == EOK) {
++                    pam_dom_forwarder(preq);
++                }
++            }
++
++        }
++        goto done;
++    }
++
++
++    req = cache_req_user_by_cert_send(preq, cctx->ev, cctx->rctx,
++                                      pctx->ncache, pctx->neg_timeout,
++                                      0, NULL, cert);
++    if (req == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++    tevent_req_set_callback(req, pam_forwarder_lookup_by_cert_done, preq);
++    return;
++
++done:
++    pam_check_user_done(preq, ret);
++}
++
++static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req)
++{
++    int ret;
++    struct ldb_result *res;
++    struct sss_domain_info *domain;
++    struct pam_auth_req *preq = tevent_req_callback_data(req,
++                                                         struct pam_auth_req);
++    const char *cert_user;
++
++
++    ret = cache_req_user_by_cert_recv(preq, req, &res, &domain, NULL);
++    talloc_zfree(req);
++    if (ret != EOK && ret != ENOENT) {
++        DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert request failed.\n");
++        goto done;
++    }
++
++    if (ret == EOK && res->count > 1) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Search by certificate returned more than one result.\n");
++        ret = EINVAL;
++        goto done;
++    }
++
++    if (ret == EOK) {
++        if (preq->domain == NULL) {
++            preq->domain = domain;
++        }
++
++        preq->cert_user_obj = talloc_steal(preq, res->msgs[0]);
++
++        if (preq->pd->logon_name == NULL) {
++            cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj,
++                                                    SYSDB_NAME, NULL);
++            if (cert_user == NULL) {
++                DEBUG(SSSDBG_CRIT_FAILURE,
++                      "Certificate user object has not name.\n");
++                ret = ENOENT;
++                goto done;
++            }
++
++            DEBUG(SSSDBG_FUNC_DATA, "Found certificate user [%s].\n",
++                                    cert_user);
++
++            ret = add_pam_cert_response(preq->pd, cert_user, preq->token_name);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n");
++            }
++
++            preq->pd->domain = talloc_strdup(preq->pd, domain->name);
++            if (preq->pd->domain == NULL) {
++                DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
++                ret = ENOMEM;
++                goto done;
++            }
++            preq->pd->pam_status = PAM_SUCCESS;
++            pam_reply(preq);
++            return;
++        }
++    } else {
++        if (preq->pd->logon_name == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Missing logon name and no certificate user found.\n");
++            ret = ENOENT;
++            goto done;
++        }
++    }
++
++    ret = pam_check_user_search(preq);
++    if (ret == EOK) {
++        pam_dom_forwarder(preq);
++    }
++
++done:
++    pam_check_user_done(preq, ret);
++}
++
+ static void pam_forwarder_cb(struct tevent_req *req)
+ {
+     struct pam_auth_req *preq = tevent_req_callback_data(req,
+@@ -1120,6 +1296,8 @@ static void pam_forwarder_cb(struct tevent_req *req)
+     struct cli_ctx *cctx = preq->cctx;
+     struct pam_data *pd;
+     errno_t ret = EOK;
++    struct pam_ctx *pctx =
++            talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
+ 
+     ret = sss_dp_get_domains_recv(req);
+     talloc_free(req);
+@@ -1158,6 +1336,20 @@ static void pam_forwarder_cb(struct tevent_req *req)
+         }
+     }
+ 
++    if (may_do_cert_auth(pctx, pd)) {
++        req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd,
++                                  pctx->nss_db, 10, pd);
++        if (req == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n");
++            ret = ENOMEM;
++        } else {
++            tevent_req_set_callback(req, pam_forwarder_cert_cb, preq);
++            ret = EAGAIN;
++        }
++
++        goto done;
++    }
++
+     ret = pam_check_user_search(preq);
+     if (ret == EOK) {
+         pam_dom_forwarder(preq);
+@@ -1542,6 +1734,7 @@ static void pam_dom_forwarder(struct pam_auth_req *preq)
+     int ret;
+     struct pam_ctx *pctx =
+             talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
++    const char *cert_user;
+ 
+     if (!preq->pd->domain) {
+         preq->pd->domain = preq->domain->name;
+@@ -1579,6 +1772,51 @@ static void pam_dom_forwarder(struct pam_auth_req *preq)
+         return;
+     }
+ 
++    if (may_do_cert_auth(pctx, preq->pd) && preq->cert_user_obj != NULL) {
++        /* Check if user matches certificate user */
++        cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj, SYSDB_NAME,
++                                                NULL);
++        if (cert_user == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Certificate user object has not name.\n");
++            preq->pd->pam_status = PAM_USER_UNKNOWN;
++            pam_reply(preq);
++            return;
++        }
++
++        /* pam_check_user_search() calls pd_set_primary_name() is the search
++         * was successful, so pd->user contains the canonical name as well */
++        if (strcmp(cert_user, preq->pd->user) == 0) {
++
++            preq->pd->pam_status = PAM_SUCCESS;
++
++            if (preq->pd->cmd == SSS_PAM_PREAUTH) {
++                ret = add_pam_cert_response(preq->pd, cert_user,
++                                            preq->token_name);
++                if (ret != EOK) {
++                    DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n");
++                    preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
++                }
++            }
++
++            preq->callback = pam_reply;
++            pam_reply(preq);
++            return;
++        } else {
++            if (preq->pd->cmd == SSS_PAM_PREAUTH) {
++                DEBUG(SSSDBG_TRACE_FUNC,
++                      "User and certificate user do not match, " \
++                      "continue with other authentication methods.\n");
++            } else {
++                DEBUG(SSSDBG_CRIT_FAILURE,
++                      "User and certificate user do not match.\n");
++                preq->pd->pam_status = PAM_AUTH_ERR;
++                pam_reply(preq);
++                return;
++            }
++        }
++    }
++
+     if (!NEED_CHECK_PROVIDER(preq->domain->provider) ) {
+         preq->callback = pam_reply;
+         ret = LOCAL_pam_handler(preq);
+unchanged:
+--- /dev/null
++++ b/src/responder/pam/pamsrv_p11.c
+@@ -0,0 +1,527 @@
++/*
++   SSSD
++
++   PAM Responder - certificate realted requests
++
++   Copyright (C) Sumit Bose <sbose@redhat.com> 2015
++
++   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 <time.h>
++
++#include "util/util.h"
++#include "providers/data_provider.h"
++#include "util/child_common.h"
++#include "util/strtonum.h"
++#include "responder/pam/pamsrv.h"
++
++
++#ifndef SSSD_LIBEXEC_PATH
++#error "SSSD_LIBEXEC_PATH not defined"
++#endif  /* SSSD_LIBEXEC_PATH */
++
++#define P11_CHILD_LOG_FILE "p11_child"
++#define P11_CHILD_PATH SSSD_LIBEXEC_PATH"/p11_child"
++
++errno_t p11_child_init(struct pam_ctx *pctx)
++{
++    return child_debug_init(P11_CHILD_LOG_FILE, &pctx->p11_child_debug_fd);
++}
++
++bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd)
++{
++    size_t c;
++    const char *sc_services[] = { "login", "su", "su-l", "gdm-smartcard",
++                                  "gdm-password", "kdm", "sudo", "sudo-i",
++                                  NULL };
++    if (!pctx->cert_auth) {
++        return false;
++    }
++
++    if (pd->cmd != SSS_PAM_PREAUTH && pd->cmd != SSS_PAM_AUTHENTICATE) {
++        return false;
++    }
++
++    if (pd->cmd == SSS_PAM_AUTHENTICATE
++           && sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_SC_PIN
++           && sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_SC_KEYPAD) {
++        return false;
++    }
++
++    /* TODO: make services configurable */
++    if (pd->service == NULL || *pd->service == '\0') {
++        return false;
++    }
++    for (c = 0; sc_services[c] != NULL; c++) {
++        if (strcmp(pd->service, sc_services[c]) == 0) {
++            break;
++        }
++    }
++    if  (sc_services[c] == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Smartcard authentication for service [%s] not supported.\n",
++              pd->service);
++        return false;
++    }
++
++    return true;
++}
++
++static errno_t get_p11_child_write_buffer(TALLOC_CTX *mem_ctx,
++                                          struct pam_data *pd,
++                                          uint8_t **_buf, size_t *_len)
++{
++    int ret;
++    uint8_t *buf;
++    size_t len;
++    const char *pin = NULL;
++
++    if (pd == NULL || pd->authtok == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Missing authtok.\n");
++        return EINVAL;
++    }
++
++    switch (sss_authtok_get_type(pd->authtok)) {
++    case SSS_AUTHTOK_TYPE_SC_PIN:
++        ret = sss_authtok_get_sc_pin(pd->authtok, &pin, &len);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc_pin failed.\n");
++            return ret;
++        }
++        if (pin == NULL || len == 0) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Missing PIN.\n");
++            return EINVAL;
++        }
++
++        buf = talloc_size(mem_ctx, len);
++        if (buf == NULL) {
++            DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
++            return ENOMEM;
++        }
++
++        safealign_memcpy(buf, pin, len, NULL);
++
++        break;
++    case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++        /* Nothing to send */
++        len = 0;
++        buf = NULL;
++        break;
++    default:
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported authtok type [%d].\n",
++                                   sss_authtok_get_type(pd->authtok));
++        return EINVAL;
++    }
++
++    *_len = len;
++    *_buf = buf;
++
++    return EOK;
++}
++
++static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf,
++                                        ssize_t buf_len, char **_cert,
++                                        char **_token_name)
++{
++    int ret;
++    TALLOC_CTX *tmp_ctx = NULL;
++    uint8_t *p;
++    uint8_t *pn;
++    char *cert = NULL;
++    char *token_name = NULL;
++
++    if (buf_len < 0) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Error occured while reading data from p11_child.\n");
++        return EIO;
++    }
++
++    if (buf_len == 0) {
++        DEBUG(SSSDBG_TRACE_LIBS, "No certificate found.\n");
++        ret = EOK;
++        goto done;
++    }
++
++    p = memchr(buf, '\n', buf_len);
++    if (p == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "Missing new-line in p11_child response.\n");
++        return EINVAL;
++    }
++    if (p == buf) {
++        DEBUG(SSSDBG_OP_FAILURE, "Missing counter in p11_child response.\n");
++        return EINVAL;
++    }
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
++        return ENOMEM;
++    }
++
++    token_name = talloc_strndup(tmp_ctx, (char*) buf, (p - buf));
++    if (token_name == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    p++;
++    pn = memchr(p, '\n', buf_len - (p - buf));
++    if (pn == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Missing new-line in p11_child response.\n");
++        ret = EINVAL;
++        goto done;
++    }
++
++    if (pn == p) {
++        DEBUG(SSSDBG_OP_FAILURE, "Missing cert in p11_child response.\n");
++        ret = EINVAL;
++        goto done;
++    }
++
++    cert = talloc_strndup(tmp_ctx, (char *) p, (pn - p));
++    if(cert == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++    DEBUG(SSSDBG_TRACE_ALL, "Found cert [%s].\n", cert);
++
++    ret = EOK;
++
++done:
++    if (ret == EOK) {
++        *_token_name = talloc_steal(mem_ctx, token_name);
++        *_cert = talloc_steal(mem_ctx, cert);
++    }
++
++    talloc_free(tmp_ctx);
++
++    return ret;
++}
++
++struct pam_check_cert_state {
++    int child_status;
++    struct sss_child_ctx_old *child_ctx;
++    struct tevent_timer *timeout_handler;
++    struct tevent_context *ev;
++
++    int write_to_child_fd;
++    int read_from_child_fd;
++    char *cert;
++    char *token_name;
++};
++
++static void p11_child_write_done(struct tevent_req *subreq);
++static void p11_child_done(struct tevent_req *subreq);
++static void p11_child_timeout(struct tevent_context *ev,
++                              struct tevent_timer *te,
++                              struct timeval tv, void *pvt);
++
++struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx,
++                                       struct tevent_context *ev,
++                                       int child_debug_fd,
++                                       const char *nss_db,
++                                       time_t timeout,
++                                       struct pam_data *pd)
++{
++    errno_t ret;
++    struct tevent_req *req;
++    struct tevent_req *subreq;
++    struct pam_check_cert_state *state;
++    pid_t child_pid;
++    struct timeval tv;
++    int pipefd_to_child[2];
++    int pipefd_from_child[2];
++    const char *extra_args[5] = {NULL, NULL, NULL, NULL, NULL};
++    uint8_t *write_buf = NULL;
++    size_t write_buf_len = 0;
++
++    req = tevent_req_create(mem_ctx, &state, struct pam_check_cert_state);
++    if (req == NULL) {
++        return NULL;
++    }
++
++    if (nss_db == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Missing NSS DB.\n");
++        ret = EINVAL;
++        goto done;
++    }
++
++    /* extra_args are added in revers order */
++    extra_args[1] = "--nssdb";
++    extra_args[0] = nss_db;
++    if (pd->cmd == SSS_PAM_AUTHENTICATE) {
++        extra_args[2] = "--auth";
++        switch (sss_authtok_get_type(pd->authtok)) {
++        case SSS_AUTHTOK_TYPE_SC_PIN:
++            extra_args[3] = "--pin";
++            break;
++        case SSS_AUTHTOK_TYPE_SC_KEYPAD:
++            extra_args[3] = "--keypad";
++            break;
++        default:
++            DEBUG(SSSDBG_OP_FAILURE, "Unsupported authtok type.\n");
++            ret = EINVAL;
++            goto done;
++        }
++    } else if (pd->cmd == SSS_PAM_PREAUTH) {
++        extra_args[2] = "--pre";
++    } else {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected PAM command [%d}.\n", pd->cmd);
++        ret = EINVAL;
++        goto done;
++    }
++
++    state->ev = ev;
++    state->child_status = EFAULT;
++    state->read_from_child_fd = -1;
++    state->write_to_child_fd = -1;
++    state->cert = NULL;
++    state->token_name = NULL;
++
++    ret = pipe(pipefd_from_child);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "pipe failed [%d][%s].\n", ret, strerror(ret));
++        goto done;
++    }
++    ret = pipe(pipefd_to_child);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "pipe failed [%d][%s].\n", ret, strerror(ret));
++        goto done;
++    }
++
++    if (child_debug_fd == -1) {
++        child_debug_fd = STDERR_FILENO;
++    }
++
++    child_pid = fork();
++    if (child_pid == 0) { /* child */
++        ret = exec_child_ex(state, pipefd_to_child, pipefd_from_child,
++                            P11_CHILD_PATH, child_debug_fd, extra_args,
++                            STDIN_FILENO, STDOUT_FILENO);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec p11 child: [%d][%s].\n",
++                                       ret, strerror(ret));
++            goto done;
++        }
++    } else if (child_pid > 0) { /* parent */
++
++        state->read_from_child_fd = pipefd_from_child[0];
++        close(pipefd_from_child[1]);
++        sss_fd_nonblocking(state->read_from_child_fd);
++
++        state->write_to_child_fd = pipefd_to_child[1];
++        close(pipefd_to_child[0]);
++        sss_fd_nonblocking(state->write_to_child_fd);
++
++        /* Set up SIGCHLD handler */
++        ret = child_handler_setup(ev, child_pid, NULL, NULL, &state->child_ctx);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_OP_FAILURE, "Could not set up child handlers [%d]: %s\n",
++                ret, sss_strerror(ret));
++            ret = ERR_P11_CHILD;
++            goto done;
++        }
++
++        /* Set up timeout handler */
++        tv = tevent_timeval_current_ofs(timeout, 0);
++        state->timeout_handler = tevent_add_timer(ev, req, tv,
++                                                  p11_child_timeout, req);
++        if(state->timeout_handler == NULL) {
++            ret = ERR_P11_CHILD;
++            goto done;
++        }
++
++        if (pd->cmd == SSS_PAM_AUTHENTICATE) {
++            ret = get_p11_child_write_buffer(state, pd, &write_buf,
++                                             &write_buf_len);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_OP_FAILURE,
++                      "get_p11_child_write_buffer failed.\n");
++                goto done;
++            }
++        }
++
++        if (write_buf_len != 0) {
++            subreq = write_pipe_send(state, ev, write_buf, write_buf_len,
++                                     state->write_to_child_fd);
++            if (subreq == NULL) {
++                DEBUG(SSSDBG_OP_FAILURE, "write_pipe_send failed.\n");
++                ret = ERR_P11_CHILD;
++                goto done;
++            }
++            tevent_req_set_callback(subreq, p11_child_write_done, req);
++        } else {
++            subreq = read_pipe_send(state, ev, state->read_from_child_fd);
++            if (subreq == NULL) {
++                DEBUG(SSSDBG_OP_FAILURE, "read_pipe_send failed.\n");
++                ret = ERR_P11_CHILD;
++                goto done;
++            }
++            tevent_req_set_callback(subreq, p11_child_done, req);
++        }
++
++        /* Now either wait for the timeout to fire or the child
++         * to finish
++         */
++    } else { /* error */
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE, "fork failed [%d][%s].\n",
++                                   ret, sss_strerror(ret));
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        tevent_req_error(req, ret);
++        tevent_req_post(req, ev);
++    }
++    return req;
++}
++
++static void p11_child_write_done(struct tevent_req *subreq)
++{
++    struct tevent_req *req = tevent_req_callback_data(subreq,
++                                                      struct tevent_req);
++    struct pam_check_cert_state *state = tevent_req_data(req,
++                                                   struct pam_check_cert_state);
++    int ret;
++
++    ret = write_pipe_recv(subreq);
++    talloc_zfree(subreq);
++    if (ret != EOK) {
++        tevent_req_error(req, ret);
++        return;
++    }
++
++    close(state->write_to_child_fd);
++    state->write_to_child_fd = -1;
++
++    subreq = read_pipe_send(state, state->ev, state->read_from_child_fd);
++    if (subreq == NULL) {
++        tevent_req_error(req, ENOMEM);
++        return;
++    }
++    tevent_req_set_callback(subreq, p11_child_done, req);
++}
++
++static void p11_child_done(struct tevent_req *subreq)
++{
++    uint8_t *buf;
++    ssize_t buf_len;
++    struct tevent_req *req = tevent_req_callback_data(subreq,
++                                                      struct tevent_req);
++    struct pam_check_cert_state *state = tevent_req_data(req,
++                                                   struct pam_check_cert_state);
++    int ret;
++
++    talloc_zfree(state->timeout_handler);
++
++    ret = read_pipe_recv(subreq, state, &buf, &buf_len);
++    talloc_zfree(subreq);
++    if (ret != EOK) {
++        tevent_req_error(req, ret);
++        return;
++    }
++
++    close(state->read_from_child_fd);
++    state->read_from_child_fd = -1;
++
++    ret = parse_p11_child_response(state, buf, buf_len, &state->cert,
++                                   &state->token_name);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "parse_p11_child_respose failed.\n");
++        tevent_req_error(req, ret);
++        return;
++    }
++
++    tevent_req_done(req);
++    return;
++}
++
++static void p11_child_timeout(struct tevent_context *ev,
++                              struct tevent_timer *te,
++                              struct timeval tv, void *pvt)
++{
++    struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
++    struct pam_check_cert_state *state =
++                              tevent_req_data(req, struct pam_check_cert_state);
++
++    DEBUG(SSSDBG_CRIT_FAILURE, "Timeout reached for p11_child.\n");
++    child_handler_destroy(state->child_ctx);
++    state->child_ctx = NULL;
++    state->child_status = ETIMEDOUT;
++    tevent_req_error(req, ERR_P11_CHILD);
++}
++
++errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
++                            char **cert, char **token_name)
++{
++    struct pam_check_cert_state *state =
++                              tevent_req_data(req, struct pam_check_cert_state);
++
++    TEVENT_REQ_RETURN_ON_ERROR(req);
++
++    if (cert != NULL) {
++        *cert = talloc_steal(mem_ctx, state->cert);
++    }
++
++    if (token_name != NULL) {
++        *token_name = talloc_steal(mem_ctx, state->token_name);
++    }
++
++    return EOK;
++}
++
++errno_t add_pam_cert_response(struct pam_data *pd, const char *user,
++                              const char *token_name)
++{
++    uint8_t *msg = NULL;
++    size_t user_len;
++    size_t msg_len;
++    size_t slot_len;
++    int ret;
++
++    if (user == NULL || token_name == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Missing mandatory user or slot name.\n");
++        return EINVAL;
++    }
++
++    user_len = strlen(user) + 1;
++    slot_len = strlen(token_name) + 1;
++    msg_len = user_len + slot_len;
++
++    msg = talloc_zero_size(pd, msg_len);
++    if (msg == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n");
++        return ENOMEM;
++    }
++
++    memcpy(msg, user, user_len);
++    memcpy(msg + user_len, token_name, slot_len);
++
++    ret = pam_add_response(pd, SSS_PAM_CERT_INFO, msg_len, msg);
++    talloc_free(msg);
++
++    return ret;
++}
+unchanged:
+--- a/src/sss_client/sss_cli.h
++++ b/src/sss_client/sss_cli.h
+@@ -417,6 +417,7 @@ enum response_type {
+                           * @param Three zero terminated strings, if one of the
+                           * strings is missing the message will contain only
+                           * an empty string (\0) for that component. */
++    SSS_PAM_CERT_INFO,
+     SSS_OTP,             /**< Indicates that the autotok was a OTP, so don't
+                           * cache it. There is no message.
+                           * @param None. */
+unchanged:
+--- a/src/tests/cmocka/test_pam_srv.c
++++ b/src/tests/cmocka/test_pam_srv.c
+@@ -32,7 +32,10 @@
+ #include "sss_client/pam_message.h"
+ #include "sss_client/sss_cli.h"
+ 
++#include "util/crypto/sss_crypto.h"
++#ifdef HAVE_NSS
+ #include "util/crypto/nss/nss_util.h"
++#endif
+ 
+ #define TESTS_PATH "tests_pam"
+ #define TEST_CONF_DB "test_pam_conf.ldb"
+@@ -40,6 +43,34 @@
+ #define TEST_SUBDOM_NAME "test.subdomain"
+ #define TEST_ID_PROVIDER "ldap"
+ 
++#define NSS_DB_PATH "./sssd_test_nssdb"
++#define NSS_DB "sql:"NSS_DB_PATH
++
++#define TEST_TOKEN_NAME "SSSD Test Token"
++#define TEST_TOKEN_CERT \
++"MIIECTCCAvGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \
++"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA2MjMx" \
++"NjMyMDdaFw0xNzA2MjMxNjMyMDdaMDIxEjAQBgNVBAoMCUlQQS5ERVZFTDEcMBoG" \
++"A1UEAwwTaXBhLWRldmVsLmlwYS5kZXZlbDCCASIwDQYJKoZIhvcNAQEBBQADggEP" \
++"ADCCAQoCggEBALXUq56VlY+Z0aWLLpFAjFfbElPBXGQsbZb85J3cGyPjaMHC9wS+" \
++"wjB6Ve4HmQyPLx8hbINdDmbawMHYQvTScLYfsqLtj0Lqw20sUUmedk+Es5Oh9VHo" \
++"nd8MavYx25Du2u+T0iSgNIDikXguiwCmtAj8VC49ebbgITcjJGzMmiiuJkV3o93Y" \
++"vvYF0VjLGDQbQWOy7IxzYJeNVJnZWKo67CHdok6qOrm9rxQt81rzwV/mGLbCMUbr" \
++"+N4M8URtd7EmzaYZQmNm//s2owFrCYMxpLiURPj+URZVuB72504/Ix7X0HCbA/AV" \
++"26J27fPY5nc8DMwfhUDCbTqPH/JEjd3mvY8CAwEAAaOCASYwggEiMB8GA1UdIwQY" \
++"MBaAFJOq+KAQmPEnNp8Wok23eGTdE7aDMDsGCCsGAQUFBwEBBC8wLTArBggrBgEF" \
++"BQcwAYYfaHR0cDovL2lwYS1jYS5pcGEuZGV2ZWwvY2Evb2NzcDAOBgNVHQ8BAf8E" \
++"BAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHQGA1UdHwRtMGsw" \
++"aaAxoC+GLWh0dHA6Ly9pcGEtY2EuaXBhLmRldmVsL2lwYS9jcmwvTWFzdGVyQ1JM" \
++"LmJpbqI0pDIwMDEOMAwGA1UECgwFaXBhY2ExHjAcBgNVBAMMFUNlcnRpZmljYXRl" \
++"IEF1dGhvcml0eTAdBgNVHQ4EFgQUFaDNd5a53QGpaw5m63hnwXicMQ8wDQYJKoZI" \
++"hvcNAQELBQADggEBADH7Nj00qqGhGJeXJQAsepqSskz/wooqXh8vgVyb8SS4N0/c" \
++"0aQtVmY81xamlXE12ZFpwDX43d+EufBkwCUKFX/+8JFDd2doAyeJxv1xM22kKRpc" \
++"AqITPgMsa9ToGMWxjbVpc/X/5YfZixWPF0/eZUTotBj9oaR039UrhGfyN7OguF/G" \
++"rzmxtB5y4ZrMpcD/Oe90mkd9HY7sA/fB8OWOUgeRfQoh97HNS0UiDWsPtfxmjQG5" \
++"zotpoBIZmdH+ipYsu58HohHVlM9Wi5H4QmiiXl+Soldkq7eXYlafcmT7wv8+cKwz" \
++"Nz0Tm3+eYpFqRo3skr6QzXi525Jkg3r6r+kkhxU=" \
++
+ struct pam_test_ctx {
+     struct sss_test_ctx *tctx;
+     struct sss_domain_info *subdom;
+@@ -56,6 +87,84 @@ struct pam_test_ctx {
+ /* Must be global because it is needed in some wrappers */
+ struct pam_test_ctx *pam_test_ctx;
+ 
++static errno_t setup_nss_db(void)
++{
++    int ret;
++    FILE *fp;
++    int status;
++    pid_t child_pid;
++
++    ret = mkdir(NSS_DB_PATH, 0775);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Failed to create " NSS_DB_PATH ".\n");
++        return ret;
++    }
++
++    child_pid = fork();
++    if (child_pid == 0) { /* child */
++        ret = execlp("certutil", "certutil", "-N", "--empty-password", "-d",
++                     NSS_DB, NULL);
++        if (ret == -1) {
++            DEBUG(SSSDBG_FATAL_FAILURE, "execl() failed.\n");
++            exit(-1);
++        }
++    } else if (child_pid > 0) {
++        wait(&status);
++    } else {
++        ret = errno;
++        DEBUG(SSSDBG_FATAL_FAILURE, "fork() failed\n");
++        return ret;
++    }
++
++    fp = fopen(NSS_DB_PATH"/pkcs11.txt", "w");
++    if (fp == NULL) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "fopen() failed.\n");
++        return ret;
++    }
++    ret = fprintf(fp, "library=libsoftokn3.so\nname=soft\n");
++    if (ret < 0) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "fprintf() failed.\n");
++        return ret;
++    }
++    ret = fprintf(fp, "parameters=configdir='sql:%s/src/tests/cmocka/p11_nssdb' dbSlotDescription='SSSD Test Slot' dbTokenDescription='SSSD Test Token' secmod='secmod.db' flags=readOnly \n\n", ABS_SRC_DIR);
++    if (ret < 0) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "fprintf() failed.\n");
++        return ret;
++    }
++    ret = fclose(fp);
++    if (ret != 0) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "fclose() failed.\n");
++        return ret;
++    }
++
++    return EOK;
++}
++
++static void cleanup_nss_db(void)
++{
++    int ret;
++
++    ret = unlink(NSS_DB_PATH"/cert9.db");
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "Failed to remove cert9.db.\n");
++    }
++
++    ret = unlink(NSS_DB_PATH"/key4.db");
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "Failed to remove key4.db.\n");
++    }
++
++    ret = unlink(NSS_DB_PATH"/pkcs11.txt");
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "Failed to remove pkcs11.db.\n");
++    }
++
++    ret = rmdir(NSS_DB_PATH);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "Failed to remove " NSS_DB_PATH "\n");
++    }
++}
++
+ struct pam_ctx *mock_pctx(TALLOC_CTX *mem_ctx)
+ {
+     struct pam_ctx *pctx;
+@@ -113,6 +222,7 @@ void test_pam_setup(struct sss_test_conf_param params[],
+     assert_non_null(pam_test_ctx->cctx);
+ 
+     pam_test_ctx->cctx->cli_protocol_version = register_cli_protocol_version();
++    pam_test_ctx->cctx->ev = pam_test_ctx->tctx->ev;
+ }
+ 
+ static int pam_test_setup(void **state)
+@@ -141,6 +251,22 @@ static int pam_test_setup(void **state)
+                                discard_const("pamuser"),
+                                pam_test_ctx->pctx->id_timeout);
+     assert_int_equal(ret, EOK);
++
++    /* Prime the cache with a user for wrong matches */
++    ret = sysdb_add_user(pam_test_ctx->tctx->dom,
++                         "wronguser", 321, 654, "wrong user",
++                         "/home/wringuser", "/bin/sh", NULL,
++                         NULL, 300, 0);
++    assert_int_equal(ret, EOK);
++
++    /* Add entry to the initgr cache to make sure no initgr request is sent to
++     * the backend */
++    ret = pam_initgr_cache_set(pam_test_ctx->pctx->rctx->ev,
++                               pam_test_ctx->pctx->id_table,
++                               discard_const("wronguser"),
++                               pam_test_ctx->pctx->id_timeout);
++    assert_int_equal(ret, EOK);
++
+     return 0;
+ }
+ 
+@@ -151,12 +277,19 @@ static int pam_test_teardown(void **state)
+     ret = sysdb_delete_user(pam_test_ctx->tctx->dom, "pamuser", 0);
+     assert_int_equal(ret, EOK);
+ 
++    ret = sysdb_delete_user(pam_test_ctx->tctx->dom, "wronguser", 0);
++    assert_int_equal(ret, EOK);
++
+     talloc_free(pam_test_ctx);
+     return 0;
+ }
+ 
+ typedef int (*cmd_cb_fn_t)(uint32_t, uint8_t *, size_t);
+ 
++
++int __real_read_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
++                          uint8_t **buf, ssize_t *len);
++
+ void __real_sss_packet_get_body(struct sss_packet *packet,
+                                 uint8_t **body, size_t *blen);
+ 
+@@ -239,8 +372,13 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name,
+     size_t needed_size;
+     uint8_t *authtok;
+ 
+-    pi.pam_user = name;
+-    pi.pam_user_size = strlen(pi.pam_user) + 1;
++    if (name != NULL) {
++        pi.pam_user = name;
++        pi.pam_user_size = strlen(pi.pam_user) + 1;
++    } else {
++        pi.pam_user = "";
++        pi.pam_user_size = 0;
++    }
+ 
+     if (pwd != NULL) {
+         if (fa2 != NULL) {
+@@ -287,6 +425,52 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name,
+     will_return(__wrap_sss_packet_get_body, buf_size);
+ }
+ 
++static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
++                                const char *pin)
++{
++    size_t buf_size;
++    uint8_t *m_buf;
++    uint8_t *buf;
++    struct pam_items pi = { 0 };
++    int ret;
++
++    if (name != NULL) {
++        pi.pam_user = name;
++        pi.pam_user_size = strlen(pi.pam_user) + 1;
++    } else {
++        pi.pam_user = "";
++        pi.pam_user_size = 0;
++    }
++
++    if (pin != NULL) {
++        pi.pam_authtok = discard_const(pin);
++        pi.pam_authtok_size = strlen(pi.pam_authtok) + 1;
++        pi.pam_authtok_type = SSS_AUTHTOK_TYPE_SC_PIN;
++    }
++
++    pi.pam_service = "login";
++    pi.pam_service_size = strlen(pi.pam_service) + 1;
++    pi.pam_tty = "/dev/tty";
++    pi.pam_tty_size = strlen(pi.pam_tty) + 1;
++    pi.pam_ruser = "remuser";
++    pi.pam_ruser_size = strlen(pi.pam_ruser) + 1;
++    pi.pam_rhost = "remhost";
++    pi.pam_rhost_size = strlen(pi.pam_rhost) + 1;
++    pi.requested_domains = "";
++    pi.cli_pid = 12345;
++
++    ret = pack_message_v3(&pi, &buf_size, &m_buf);
++    assert_int_equal(ret, 0);
++
++    buf = talloc_memdup(mem_ctx, m_buf, buf_size);
++    free(m_buf);
++    assert_non_null(buf);
++
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
++    will_return(__wrap_sss_packet_get_body, buf);
++    will_return(__wrap_sss_packet_get_body, buf_size);
++}
++
+ static int test_pam_simple_check(uint32_t status, uint8_t *body, size_t blen)
+ {
+     size_t rp = 0;
+@@ -312,6 +496,46 @@ static int test_pam_simple_check(uint32_t status, uint8_t *body, size_t blen)
+     return EOK;
+ }
+ 
++static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen)
++{
++    size_t rp = 0;
++    uint32_t val;
++
++    assert_int_equal(status, 0);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, pam_test_ctx->exp_pam_status);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, 2);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, SSS_PAM_DOMAIN_NAME);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, 9);
++
++    assert_int_equal(*(body + rp + val - 1), 0);
++    assert_string_equal(body + rp, TEST_DOM_NAME);
++    rp += val;
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, SSS_PAM_CERT_INFO);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, (sizeof("pamuser") + sizeof(TEST_TOKEN_NAME)));
++
++    assert_int_equal(*(body + rp + sizeof("pamuser") - 1), 0);
++    assert_string_equal(body + rp, "pamuser");
++    rp += sizeof("pamuser");
++
++    assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0);
++    assert_string_equal(body + rp, TEST_TOKEN_NAME);
++
++    return EOK;
++}
++
++
+ static int test_pam_offline_chauthtok_check(uint32_t status,
+                                             uint8_t *body, size_t blen)
+ {
+@@ -372,6 +596,23 @@ static int test_pam_wrong_pw_offline_auth_check(uint32_t status,
+     return test_pam_simple_check(status, body, blen);
+ }
+ 
++static int test_pam_user_unknown_check(uint32_t status,
++                                       uint8_t *body, size_t blen)
++{
++    size_t rp = 0;
++    uint32_t val;
++
++    assert_int_equal(status, 0);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, PAM_USER_UNKNOWN);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, 0);
++
++    return EOK;
++}
++
+ void test_pam_authenticate(void **state)
+ {
+     int ret;
+@@ -859,6 +1100,245 @@ void test_pam_offline_chauthtok(void **state)
+     assert_int_equal(ret, EOK);
+ }
+ 
++static void set_cert_auth_param(struct pam_ctx *pctx, const char *dbpath)
++{
++    pam_test_ctx->pctx->cert_auth = true;
++    pam_test_ctx->pctx->nss_db = discard_const(dbpath);
++}
++
++void test_pam_preauth_cert_nocert(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, "/no/path");
++
++    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++
++    set_cmd_cb(test_pam_simple_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++static int test_lookup_by_cert_cb(void *pvt)
++{
++    int ret;
++    struct sysdb_attrs *attrs;
++    unsigned char *der = NULL;
++    size_t der_size;
++
++    if (pvt != NULL) {
++
++        attrs = sysdb_new_attrs(pam_test_ctx);
++        assert_non_null(attrs);
++
++        der = sss_base64_decode(pam_test_ctx, pvt, &der_size);
++        assert_non_null(der);
++
++        ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size);
++        talloc_free(der);
++        assert_int_equal(ret, EOK);
++
++        ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, "pamuser", attrs,
++                                  LDB_FLAG_MOD_ADD);
++        assert_int_equal(ret, EOK);
++    }
++
++    return EOK;
++}
++
++static int test_lookup_by_cert_wrong_user_cb(void *pvt)
++{
++    int ret;
++    struct sysdb_attrs *attrs;
++    unsigned char *der = NULL;
++    size_t der_size;
++
++    if (pvt != NULL) {
++        attrs = sysdb_new_attrs(pam_test_ctx);
++        assert_non_null(attrs);
++
++        der = sss_base64_decode(pam_test_ctx, pvt, &der_size);
++        assert_non_null(der);
++
++        ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size);
++        talloc_free(der);
++        assert_int_equal(ret, EOK);
++
++        ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, "wronguser", attrs,
++                                  LDB_FLAG_MOD_ADD);
++        assert_int_equal(ret, EOK);
++    }
++
++    return EOK;
++}
++
++
++void test_pam_preauth_cert_nomatch(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
++
++    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++    mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, NULL);
++
++    set_cmd_cb(test_pam_simple_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++void test_pam_preauth_cert_match(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
++
++    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++    mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb,
++                      discard_const(TEST_TOKEN_CERT));
++
++    set_cmd_cb(test_pam_cert_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++void test_pam_preauth_cert_match_wrong_user(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
++
++    mock_input_pam_cert(pam_test_ctx, "pamuser", NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++    mock_account_recv(0, 0, NULL, test_lookup_by_cert_wrong_user_cb,
++                      discard_const(TEST_TOKEN_CERT));
++
++    set_cmd_cb(test_pam_simple_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++
++void test_pam_preauth_cert_no_logon_name(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
++
++    mock_input_pam_cert(pam_test_ctx, NULL, NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++    mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb,
++                      discard_const(TEST_TOKEN_CERT));
++
++    set_cmd_cb(test_pam_cert_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++void test_pam_preauth_no_cert_no_logon_name(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, "/no/path");
++
++    mock_input_pam_cert(pam_test_ctx, NULL, NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++
++    set_cmd_cb(test_pam_user_unknown_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++void test_pam_preauth_cert_no_logon_name_no_match(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
++
++    mock_input_pam_cert(pam_test_ctx, NULL, NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++    mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, NULL);
++
++    set_cmd_cb(test_pam_user_unknown_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++void test_pam_cert_auth(void **state)
++{
++    int ret;
++
++    set_cert_auth_param(pam_test_ctx->pctx, NSS_DB);
++
++    mock_input_pam_cert(pam_test_ctx, "pamuser", "123456");
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++    mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb,
++                      discard_const(TEST_TOKEN_CERT));
++
++    set_cmd_cb(test_pam_simple_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
+ int main(int argc, const char *argv[])
+ {
+     int rv;
+@@ -925,6 +1405,23 @@ int main(int argc, const char *argv[])
+                                         pam_test_setup, pam_test_teardown),
+         cmocka_unit_test_setup_teardown(test_pam_offline_chauthtok,
+                                         pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nocert,
++                                        pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nomatch,
++                                        pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_preauth_cert_match,
++                                        pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_preauth_cert_match_wrong_user,
++                                        pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_preauth_cert_no_logon_name,
++                                        pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_preauth_no_cert_no_logon_name,
++                                        pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(
++                                   test_pam_preauth_cert_no_logon_name_no_match,
++                                   pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_cert_auth,
++                                        pam_test_setup, pam_test_teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+@@ -950,8 +1447,16 @@ int main(int argc, const char *argv[])
+     test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME);
+     test_dom_suite_setup(TESTS_PATH);
+ 
++    cleanup_nss_db();
++    rv = setup_nss_db();
++    if (rv != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "setup_nss_db failed.\n");
++        exit(-1);
++    }
++
+     rv = cmocka_run_group_tests(tests, NULL, NULL);
+     if (rv == 0 && !no_cleanup) {
++        cleanup_nss_db();
+         test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME);
+     }
+ 
+unchanged:
+--- a/src/util/util_errors.c
++++ b/src/util/util_errors.c
+@@ -78,6 +78,7 @@ struct err_string error_to_str[] = {
+     { "Unsupported trust direction" }, /* ERR_TRUST_NOT_SUPPORTED */
+     { "Retrieving keytab failed" }, /* ERR_IPA_GETKEYTAB_FAILED */
+     { "Trusted forest root unknown" }, /* ERR_TRUST_FOREST_UNKNOWN */
++    { "p11_child failed" }, /* ERR_P11_CHILD */
+     { "ERR_LAST" } /* ERR_LAST */
+ };
+ 
+only in patch2:
+unchanged:
+--- a/src/util/util_errors.h
++++ b/src/util/util_errors.h
+@@ -100,6 +100,7 @@ enum sssd_errors {
+     ERR_TRUST_NOT_SUPPORTED,
+     ERR_IPA_GETKEYTAB_FAILED,
+     ERR_TRUST_FOREST_UNKNOWN,
++    ERR_P11_CHILD,
+     ERR_LAST            /* ALWAYS LAST */
+ };
+ 
diff --git a/SOURCES/0034-TEST-Unit-test-for-create_pipe_fd.patch b/SOURCES/0034-TEST-Unit-test-for-create_pipe_fd.patch
deleted file mode 100644
index dd2c9a4..0000000
--- a/SOURCES/0034-TEST-Unit-test-for-create_pipe_fd.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-From 92cf06af1c5ee8be33722e76c79a3c290b9f67c8 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 17 Oct 2014 16:44:05 +0200
-Subject: [PATCH 34/46] TEST: Unit test for create_pipe_fd
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 4a5cced91df68a85ef0b30de8efe104c8a0aab7a)
----
- src/tests/cwrap/test_responder_common.c | 91 +++++++++++++++++++++++++++++++++
- 1 file changed, 91 insertions(+)
-
-diff --git a/src/tests/cwrap/test_responder_common.c b/src/tests/cwrap/test_responder_common.c
-index 23dcf753f184cdecaf39c73c6e9be0e23e6df968..7e3f2e025a0dce15cc93e560a42bb566eff9fb30 100644
---- a/src/tests/cwrap/test_responder_common.c
-+++ b/src/tests/cwrap/test_responder_common.c
-@@ -23,6 +23,7 @@
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-+#include <talloc.h>
- 
- #include <popt.h>
- #include "util/util.h"
-@@ -105,6 +106,93 @@ void test_csv_to_uid_list_neg(void **state)
-     talloc_free(tmp_ctx);
- }
- 
-+struct create_pipe_ctx {
-+    int fd;
-+    const char *sock_name;
-+};
-+
-+void test_create_pipe_fd_setup(void **state)
-+{
-+    struct create_pipe_ctx *ctx;
-+
-+    ctx = talloc(global_talloc_context, struct create_pipe_ctx);
-+    assert_non_null(ctx);
-+    ctx->fd = -1;
-+
-+    *state = ctx;
-+}
-+
-+void check_sock_properties(struct create_pipe_ctx *ctx, mode_t mode)
-+{
-+    int ret;
-+    int optval;
-+    socklen_t optlen;
-+    struct stat sbuf;
-+
-+    /* Check existence of the file and the permissions */
-+    ret = stat(ctx->sock_name, &sbuf);
-+    assert_int_equal(ret, 0);
-+    assert_true(S_ISSOCK(sbuf.st_mode));
-+    assert_true((sbuf.st_mode & ~S_IFMT) == mode);
-+
-+    /* Check it's a UNIX socket */
-+    optlen = sizeof(optval);
-+    ret = getsockopt(ctx->fd, SOL_SOCKET, SO_DOMAIN, &optval, &optlen);
-+    assert_int_equal(ret, 0);
-+    assert_int_equal(optval, AF_UNIX);
-+
-+    optlen = sizeof(optval);
-+    ret = getsockopt(ctx->fd, SOL_SOCKET, SO_TYPE, &optval, &optlen);
-+    assert_int_equal(ret, 0);
-+    assert_int_equal(optval, SOCK_STREAM);
-+
-+    /* Make sure this is a listening socket */
-+    optlen = sizeof(optval);
-+    ret = getsockopt(ctx->fd, SOL_SOCKET, SO_ACCEPTCONN, &optval, &optlen);
-+    assert_int_equal(ret, 0);
-+    assert_int_equal(optval, 1);
-+
-+    /* Check the right protocol */
-+    optlen = sizeof(optval);
-+    ret = getsockopt(ctx->fd, SOL_SOCKET, SO_PROTOCOL, &optval, &optlen);
-+    assert_int_equal(ret, 0);
-+    assert_int_equal(optval, 0);
-+
-+}
-+
-+void test_create_pipe_fd(void **state)
-+{
-+    int ret;
-+    struct create_pipe_ctx *ctx;
-+
-+    ctx = talloc_get_type(*state, struct create_pipe_ctx);
-+
-+    ctx->sock_name = __FUNCTION__;
-+
-+    ret = create_pipe_fd(ctx->sock_name, &ctx->fd, 0111);
-+    assert_int_equal(ret, EOK);
-+    assert_int_not_equal(ctx->fd, -1);
-+    check_sock_properties(ctx, 0666);
-+
-+    /* Make sure we can overwrite an existing socket */
-+    ret = create_pipe_fd(ctx->sock_name, &ctx->fd, 0000);
-+    assert_int_equal(ret, EOK);
-+    assert_int_not_equal(ctx->fd, -1);
-+    check_sock_properties(ctx, 0777);
-+}
-+
-+void test_create_pipe_fd_teardown(void **state)
-+{
-+    struct create_pipe_ctx *ctx;
-+
-+    ctx = talloc_get_type(*state, struct create_pipe_ctx);
-+
-+    if (ctx->fd != -1) {
-+        unlink(ctx->sock_name);
-+        close(ctx->fd);
-+    }
-+}
-+
- int main(int argc, const char *argv[])
- {
-     poptContext pc;
-@@ -119,6 +207,9 @@ int main(int argc, const char *argv[])
-         unit_test(test_uid_csv_to_uid_list),
-         unit_test(test_name_csv_to_uid_list),
-         unit_test(test_csv_to_uid_list_neg),
-+        unit_test_setup_teardown(test_create_pipe_fd,
-+                                 test_create_pipe_fd_setup,
-+                                 test_create_pipe_fd_teardown)
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-1.9.3
-
diff --git a/SOURCES/0035-pam_sss-add-sc-support.patch b/SOURCES/0035-pam_sss-add-sc-support.patch
new file mode 100644
index 0000000..d5a550d
--- /dev/null
+++ b/SOURCES/0035-pam_sss-add-sc-support.patch
@@ -0,0 +1,168 @@
+From 98be4f0858e7c38f18b73fda6949edf7790bcad6 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 3 Jul 2015 14:05:11 +0200
+Subject: [PATCH 35/37] pam_sss: add sc support
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/sss_client/pam_message.h |  3 ++
+ src/sss_client/pam_sss.c     | 94 +++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 96 insertions(+), 1 deletion(-)
+
+diff --git a/src/sss_client/pam_message.h b/src/sss_client/pam_message.h
+index 3b3841a2c66b46d78855164099684ef2ac98ed77..f0a7a076cf38a4efc8befcc2fb835ae26e9415a4 100644
+--- a/src/sss_client/pam_message.h
++++ b/src/sss_client/pam_message.h
+@@ -56,6 +56,9 @@ struct pam_items {
+     char *otp_token_id;
+     char *otp_challenge;
+     char *first_factor;
++
++    char *cert_user;
++    char *token_name;
+ };
+ 
+ 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 e4fa83e12c71bb05dd329686cf2d2df6323ff3bd..431f5dc62655dd1e6901f16f72dcad9703f037ac 100644
+--- a/src/sss_client/pam_sss.c
++++ b/src/sss_client/pam_sss.c
+@@ -155,6 +155,12 @@ static void overwrite_and_free_pam_items(struct pam_items *pi)
+ 
+     free(pi->otp_challenge);
+     pi->otp_challenge = NULL;
++
++    free(pi->cert_user);
++    pi->cert_user = NULL;
++
++    free(pi->token_name);
++    pi->token_name = NULL;
+ }
+ 
+ static int null_strcmp(const char *s1, const char *s2) {
+@@ -922,7 +928,7 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
+                 break;
+             case SSS_PAM_OTP_INFO:
+                 if (buf[p + (len - 1)] != '\0') {
+-                    D(("system info does not end with \\0."));
++                    D(("otp info does not end with \\0."));
+                     break;
+                 }
+ 
+@@ -959,6 +965,33 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
+                 }
+ 
+                 break;
++            case SSS_PAM_CERT_INFO:
++                if (buf[p + (len - 1)] != '\0') {
++                    D(("cert info does not end with \\0."));
++                    break;
++                }
++
++                pi->cert_user = strdup((char *) &buf[p]);
++                if (pi->cert_user == NULL) {
++                    D(("strdup failed"));
++                    break;
++                }
++
++                offset = strlen(pi->cert_user) + 1;
++                if (offset >= len) {
++                    D(("Cert message size mismatch"));
++                    free(pi->cert_user);
++                    pi->cert_user = NULL;
++                    break;
++                }
++                pi->token_name = strdup((char *) &buf[p + offset]);
++                if (pi->token_name == NULL) {
++                    D(("strdup failed"));
++                    break;
++                }
++                D(("cert user: [%s] token name: [%s]", pi->cert_user,
++                                                       pi->token_name));
++                break;
+             default:
+                 D(("Unknown response type [%d]", type));
+         }
+@@ -1039,6 +1072,9 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi)
+     pi->otp_token_id = NULL;
+     pi->otp_challenge = NULL;
+ 
++    pi->cert_user = NULL;
++    pi->token_name = NULL;
++
+     return PAM_SUCCESS;
+ }
+ 
+@@ -1345,6 +1381,60 @@ done:
+     return ret;
+ }
+ 
++#define SC_PROMPT_FMT "PIN for %s for user %s"
++static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi)
++{
++    int ret;
++    char *answer = NULL;
++    char *prompt;
++    size_t size;
++
++    if (pi->token_name == NULL || *pi->token_name == '\0'
++            || pi->cert_user == NULL || *pi->cert_user == '\0') {
++        return EINVAL;
++    }
++
++    size = sizeof(SC_PROMPT_FMT) + strlen(pi->token_name) +
++           strlen(pi->cert_user);
++    prompt = malloc(size);
++    if (prompt == NULL) {
++        D(("malloc failed."));
++        return ENOMEM;
++    }
++
++    ret = snprintf(prompt, size, SC_PROMPT_FMT, pi->token_name, pi->cert_user);
++    if (ret < 0 || ret >= size) {
++        D(("snprintf failed."));
++        free(prompt);
++        return EFAULT;
++    }
++
++    ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer);
++    free(prompt);
++    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_SC_PIN;
++        pi->pam_authtok_size=strlen(pi->pam_authtok);
++    }
++
++    return PAM_SUCCESS;
++}
++
+ static int prompt_new_password(pam_handle_t *pamh, struct pam_items *pi)
+ {
+     int ret;
+@@ -1458,6 +1548,8 @@ static int get_authtok_for_authentication(pam_handle_t *pamh,
+                         && pi->otp_challenge != NULL)) {
+             ret = prompt_2fa(pamh, pi, _("First Factor: "),
+                              _("Second Factor: "));
++        } else if (pi->cert_user != NULL) {
++            ret = prompt_sc_pin(pamh, pi);
+         } else {
+             ret = prompt_password(pamh, pi, _("Password: "));
+         }
+-- 
+2.4.3
+
diff --git a/SOURCES/0035-responders-Do-not-initialize-pipe-fd-if-already-pres.patch b/SOURCES/0035-responders-Do-not-initialize-pipe-fd-if-already-pres.patch
deleted file mode 100644
index db698b6..0000000
--- a/SOURCES/0035-responders-Do-not-initialize-pipe-fd-if-already-pres.patch
+++ /dev/null
@@ -1,187 +0,0 @@
-From 4bab32c01bce266c68838c9edac9a567f8b1f413 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Wed, 15 Oct 2014 18:01:55 +0200
-Subject: [PATCH 35/46] responders: Do not initialize pipe fd if already
- present
-
-Allow to skip initialization of pipe file descriptor
-if the responder context already has one.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 8bccd95e275fae760a991da394235e4e70e57bbd)
----
- src/responder/autofs/autofssrv.c        |  2 +-
- src/responder/common/responder.h        |  2 ++
- src/responder/common/responder_common.c | 20 ++++++++++++++------
- src/responder/ifp/ifpsrv.c              |  2 +-
- src/responder/nss/nsssrv.c              |  2 +-
- src/responder/pac/pacsrv.c              |  2 +-
- src/responder/pam/pamsrv.c              |  4 ++--
- src/responder/ssh/sshsrv.c              |  2 +-
- src/responder/sudo/sudosrv.c            |  2 +-
- 9 files changed, 24 insertions(+), 14 deletions(-)
-
-diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
-index 931cf018bfe15b37bf8e5f93a21c7ab61d238c18..12a7a777e214fa4c3821eb58ff602b3f3efb987a 100644
---- a/src/responder/autofs/autofssrv.c
-+++ b/src/responder/autofs/autofssrv.c
-@@ -132,7 +132,7 @@ autofs_process_init(TALLOC_CTX *mem_ctx,
-     autofs_cmds = get_autofs_cmds();
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            autofs_cmds,
--                           SSS_AUTOFS_SOCKET_NAME, NULL,
-+                           SSS_AUTOFS_SOCKET_NAME, -1, NULL, -1,
-                            CONFDB_AUTOFS_CONF_ENTRY,
-                            SSS_AUTOFS_SBUS_SERVICE_NAME,
-                            SSS_AUTOFS_SBUS_SERVICE_VERSION,
-diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
-index d233710782fe7df1bbcc338e3815d1701557519e..8837e11425be36c67da038287de48c069ae335cd 100644
---- a/src/responder/common/responder.h
-+++ b/src/responder/common/responder.h
-@@ -159,7 +159,9 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
-                      struct confdb_ctx *cdb,
-                      struct sss_cmd_table sss_cmds[],
-                      const char *sss_pipe_name,
-+                     int pipe_fd,
-                      const char *sss_priv_pipe_name,
-+                     int priv_pipe_fd,
-                      const char *confdb_service_path,
-                      const char *svc_name,
-                      uint16_t svc_version,
-diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
-index a262a2c1487c786404b6d0d4c720edd1679279d0..85aa04335b72c38fb7a128f04315e3c4189c5d56 100644
---- a/src/responder/common/responder_common.c
-+++ b/src/responder/common/responder_common.c
-@@ -689,9 +689,11 @@ static int set_unix_socket(struct resp_ctx *rctx)
-     if (rctx->sock_name != NULL ) {
-         /* Set the umask so that permissions are set right on the socket.
-          * It must be readable and writable by anybody on the system. */
--        ret = create_pipe_fd(rctx->sock_name, &rctx->lfd, 0111);
--        if (ret != EOK) {
--            return ret;
-+        if (rctx->lfd == -1) {
-+            ret = create_pipe_fd(rctx->sock_name, &rctx->lfd, 0111);
-+            if (ret != EOK) {
-+                return ret;
-+            }
-         }
- 
-         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
-@@ -710,9 +712,11 @@ static int set_unix_socket(struct resp_ctx *rctx)
- 
-     if (rctx->priv_sock_name != NULL ) {
-         /* create privileged pipe */
--        ret = create_pipe_fd(rctx->priv_sock_name, &rctx->priv_lfd, 0177);
--        if (ret != EOK) {
--            goto failed;
-+        if (rctx->priv_lfd == -1) {
-+            ret = create_pipe_fd(rctx->priv_sock_name, &rctx->priv_lfd, 0177);
-+            if (ret != EOK) {
-+                goto failed;
-+            }
-         }
- 
-         accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
-@@ -755,7 +759,9 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
-                      struct confdb_ctx *cdb,
-                      struct sss_cmd_table sss_cmds[],
-                      const char *sss_pipe_name,
-+                     int pipe_fd,
-                      const char *sss_priv_pipe_name,
-+                     int priv_pipe_fd,
-                      const char *confdb_service_path,
-                      const char *svc_name,
-                      uint16_t svc_version,
-@@ -779,6 +785,8 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
-     rctx->sss_cmds = sss_cmds;
-     rctx->sock_name = sss_pipe_name;
-     rctx->priv_sock_name = sss_priv_pipe_name;
-+    rctx->lfd = pipe_fd;
-+    rctx->priv_lfd = priv_pipe_fd;
-     rctx->confdb_service_path = confdb_service_path;
-     rctx->shutting_down = false;
- 
-diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
-index 8d8fe885abb8ef53ee7f49e763ba78c4dda9a983..eddeec9812bdd650bfbfb78ede91bf3704113504 100644
---- a/src/responder/ifp/ifpsrv.c
-+++ b/src/responder/ifp/ifpsrv.c
-@@ -310,7 +310,7 @@ int ifp_process_init(TALLOC_CTX *mem_ctx,
-     ifp_cmds = get_ifp_cmds();
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            ifp_cmds,
--                           NULL, NULL,
-+                           NULL, -1, NULL, -1,
-                            CONFDB_IFP_CONF_ENTRY,
-                            SSS_IFP_SBUS_SERVICE_NAME,
-                            SSS_IFP_SBUS_SERVICE_VERSION,
-diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
-index dbbdb4f844410eabe01f184ccdf8d9deb41833f4..cfb146464d224cdb8b517d23a86421da7eaccd1f 100644
---- a/src/responder/nss/nsssrv.c
-+++ b/src/responder/nss/nsssrv.c
-@@ -392,7 +392,7 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
- 
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            nss_cmds,
--                           SSS_NSS_SOCKET_NAME, NULL,
-+                           SSS_NSS_SOCKET_NAME, -1, NULL, -1,
-                            CONFDB_NSS_CONF_ENTRY,
-                            NSS_SBUS_SERVICE_NAME,
-                            NSS_SBUS_SERVICE_VERSION,
-diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
-index b76691de829b4f40937a07ea83825a606950aa1e..e427cd756f4031218a8fb99c30bf709e21680039 100644
---- a/src/responder/pac/pacsrv.c
-+++ b/src/responder/pac/pacsrv.c
-@@ -119,7 +119,7 @@ int pac_process_init(TALLOC_CTX *mem_ctx,
- 
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            pac_cmds,
--                           SSS_PAC_SOCKET_NAME, NULL,
-+                           SSS_PAC_SOCKET_NAME, -1, NULL, -1,
-                            CONFDB_PAC_CONF_ENTRY,
-                            PAC_SBUS_SERVICE_NAME,
-                            PAC_SBUS_SERVICE_VERSION,
-diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
-index 91b395080820b27f5d57341e59dd739e674be31a..a3f8662738c26a537bc21d8d419e65e49c4828c9 100644
---- a/src/responder/pam/pamsrv.c
-+++ b/src/responder/pam/pamsrv.c
-@@ -194,8 +194,8 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
-     pam_cmds = get_pam_cmds();
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            pam_cmds,
--                           SSS_PAM_SOCKET_NAME,
--                           SSS_PAM_PRIV_SOCKET_NAME,
-+                           SSS_PAM_SOCKET_NAME, -1,
-+                           SSS_PAM_PRIV_SOCKET_NAME, -1,
-                            CONFDB_PAM_CONF_ENTRY,
-                            SSS_PAM_SBUS_SERVICE_NAME,
-                            SSS_PAM_SBUS_SERVICE_VERSION,
-diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
-index 1328d1746b9e2d6474d6c2f8ce2825be463ca3e7..b154ee1baa16de68f642d2e967b8e7c873c8d4e7 100644
---- a/src/responder/ssh/sshsrv.c
-+++ b/src/responder/ssh/sshsrv.c
-@@ -92,7 +92,7 @@ int ssh_process_init(TALLOC_CTX *mem_ctx,
-     ssh_cmds = get_ssh_cmds();
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            ssh_cmds,
--                           SSS_SSH_SOCKET_NAME, NULL,
-+                           SSS_SSH_SOCKET_NAME, -1, NULL, -1,
-                            CONFDB_SSH_CONF_ENTRY,
-                            SSS_SSH_SBUS_SERVICE_NAME,
-                            SSS_SSH_SBUS_SERVICE_VERSION,
-diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
-index 30752c9dacdc390b24fe837c0630333b5e171448..038e3fd7da0829ce554a31694725c3dddaf5c038 100644
---- a/src/responder/sudo/sudosrv.c
-+++ b/src/responder/sudo/sudosrv.c
-@@ -93,7 +93,7 @@ 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, NULL,
-+                           SSS_SUDO_SOCKET_NAME, -1, NULL, -1,
-                            CONFDB_SUDO_CONF_ENTRY,
-                            SSS_SUDO_SBUS_SERVICE_NAME,
-                            SSS_SUDO_SBUS_SERVICE_VERSION,
--- 
-1.9.3
-
diff --git a/SOURCES/0036-PAM-Create-pipe-file-descriptors-before-privileges-a.patch b/SOURCES/0036-PAM-Create-pipe-file-descriptors-before-privileges-a.patch
deleted file mode 100644
index bbf32df..0000000
--- a/SOURCES/0036-PAM-Create-pipe-file-descriptors-before-privileges-a.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-From 69c41ad3d74684dac43a1f767bc00ca97b4518b5 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Wed, 15 Oct 2014 18:15:53 +0200
-Subject: [PATCH 36/46] PAM: Create pipe file descriptors before privileges are
- dropped
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit b547bd685cb71bb450b0c86487767f02e66f6cea)
----
- src/responder/pam/pamsrv.c | 30 ++++++++++++++++++++++++++----
- 1 file changed, 26 insertions(+), 4 deletions(-)
-
-diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
-index a3f8662738c26a537bc21d8d419e65e49c4828c9..d3cf0c770ad2978e101f40453137ade8d826b8e1 100644
---- a/src/responder/pam/pamsrv.c
-+++ b/src/responder/pam/pamsrv.c
-@@ -181,7 +181,8 @@ done:
- 
- static int pam_process_init(TALLOC_CTX *mem_ctx,
-                             struct tevent_context *ev,
--                            struct confdb_ctx *cdb)
-+                            struct confdb_ctx *cdb,
-+                            int pipe_fd, int priv_pipe_fd)
- {
-     struct resp_ctx *rctx;
-     struct sss_cmd_table *pam_cmds;
-@@ -194,8 +195,8 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
-     pam_cmds = get_pam_cmds();
-     ret = sss_process_init(mem_ctx, ev, cdb,
-                            pam_cmds,
--                           SSS_PAM_SOCKET_NAME, -1,
--                           SSS_PAM_PRIV_SOCKET_NAME, -1,
-+                           SSS_PAM_SOCKET_NAME, pipe_fd,
-+                           SSS_PAM_PRIV_SOCKET_NAME, priv_pipe_fd,
-                            CONFDB_PAM_CONF_ENTRY,
-                            SSS_PAM_SBUS_SERVICE_NAME,
-                            SSS_PAM_SBUS_SERVICE_VERSION,
-@@ -318,6 +319,8 @@ int main(int argc, const char *argv[])
-     int ret;
-     uid_t uid;
-     gid_t gid;
-+    int pipe_fd;
-+    int priv_pipe_fd;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-@@ -347,6 +350,24 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_pam";
- 
-+    /* Crate pipe file descriptors here before privileges are dropped
-+     * in server_setup() */
-+    ret = create_pipe_fd(SSS_PAM_SOCKET_NAME, &pipe_fd, 0111);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "create_pipe_fd failed [%d]: %s.\n",
-+              ret, sss_strerror(ret));
-+        return 2;
-+    }
-+
-+    ret = create_pipe_fd(SSS_PAM_PRIV_SOCKET_NAME, &priv_pipe_fd, 0177);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "create_pipe_fd failed (priviledged pipe) [%d]: %s.\n",
-+              ret, sss_strerror(ret));
-+        return 2;
-+    }
-+
-     ret = server_setup("sssd[pam]", 0, 0, 0, CONFDB_PAM_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) return 2;
- 
-@@ -359,7 +380,8 @@ int main(int argc, const char *argv[])
- 
-     ret = pam_process_init(main_ctx,
-                            main_ctx->event_ctx,
--                           main_ctx->confdb_ctx);
-+                           main_ctx->confdb_ctx,
-+                           pipe_fd, priv_pipe_fd);
-     if (ret != EOK) return 3;
- 
-     /* loop on main */
--- 
-1.9.3
-
diff --git a/SOURCES/0036-ssh-generate-public-keys-from-certificate.patch b/SOURCES/0036-ssh-generate-public-keys-from-certificate.patch
new file mode 100644
index 0000000..d01d9e7
--- /dev/null
+++ b/SOURCES/0036-ssh-generate-public-keys-from-certificate.patch
@@ -0,0 +1,618 @@
+From ace8a2f80fe5bb755512e4a7281146ce4fe311a6 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 15 Jul 2015 09:40:00 +0200
+Subject: [PATCH 36/37] ssh: generate public keys from certificate
+
+Resolves: https://fedorahosted.org/sssd/ticket/2711
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                          |   7 +-
+ src/confdb/confdb.h                  |   2 +
+ src/config/SSSDConfig/__init__.py.in |   1 +
+ src/config/etc/sssd.api.conf         |   1 +
+ src/man/sssd.conf.5.xml              |  13 ++++
+ src/responder/ssh/sshsrv.c           |   9 +++
+ src/responder/ssh/sshsrv_cmd.c       |  54 ++++++++++++---
+ src/responder/ssh/sshsrv_private.h   |   1 +
+ src/tests/cmocka/test_cert_utils.c   |  62 +++++++++++++++++
+ src/util/cert.h                      |   4 ++
+ src/util/cert/libcrypto/cert.c       |  93 +++++++++++++++++++++++++
+ src/util/cert/nss/cert.c             | 130 +++++++++++++++++++++++++++++++++++
+ 12 files changed, 364 insertions(+), 13 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index fd78c1bb770b98adee9a6c1ead3b0d6f4345fb9b..5345d90d22cd285a5268ac50a6b527645acdb351 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1129,10 +1129,13 @@ sssd_ssh_SOURCES = \
+     src/responder/ssh/sshsrv.c \
+     src/responder/ssh/sshsrv_dp.c \
+     src/responder/ssh/sshsrv_cmd.c \
+-    $(SSSD_RESPONDER_OBJ)
++    $(SSSD_RESPONDER_OBJ) \
++    $(NULL)
+ sssd_ssh_LDADD = \
+     $(SSSD_LIBS) \
+-    $(SSSD_INTERNAL_LTLIBS)
++    $(SSSD_INTERNAL_LTLIBS) \
++    libsss_cert.la \
++    $(NULL)
+ endif
+ 
+ sssd_pac_SOURCES = \
+diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
+index c3cdf49e08d10367e9e98c093a4aa2569b985170..df454337ab4d89c5857e73ee0e5392c2b4bba8b4 100644
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -135,6 +135,8 @@
+ #define CONFDB_DEFAULT_SSH_HASH_KNOWN_HOSTS true
+ #define CONFDB_SSH_KNOWN_HOSTS_TIMEOUT "ssh_known_hosts_timeout"
+ #define CONFDB_DEFAULT_SSH_KNOWN_HOSTS_TIMEOUT 180
++#define CONFDB_SSH_CA_DB "ca_db"
++#define CONFDB_DEFAULT_SSH_CA_DB SYSCONFDIR"/pki/nssdb"
+ 
+ /* PAC */
+ #define CONFDB_PAC_CONF_ENTRY "config/pac"
+diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
+index 4b519eddd04cde83c209f5a1940832cc7f41c736..7d361026c09ce8fd8d6a69f6bb3f3817bc3d68ba 100644
+--- a/src/config/SSSDConfig/__init__.py.in
++++ b/src/config/SSSDConfig/__init__.py.in
+@@ -99,6 +99,7 @@ option_strings = {
+     # [ssh]
+     'ssh_hash_known_hosts': _('Whether to hash host names and addresses in the known_hosts file'),
+     'ssh_known_hosts_timeout': _('How many seconds to keep a host in the known_hosts file after its host keys were requested'),
++    'ca_db': _('Path to storage of trusted CA certificates'),
+ 
+     # [pac]
+     'allowed_uids': _('List of UIDs or user names allowed to access the PAC responder'),
+diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
+index 29fd896ccd7a3aa5ff81e15b771746a80ffc01af..cf6ce63012176d49f757afbc8a343b24aef869e8 100644
+--- a/src/config/etc/sssd.api.conf
++++ b/src/config/etc/sssd.api.conf
+@@ -72,6 +72,7 @@ autofs_negative_timeout = int, None, false
+ # ssh service
+ ssh_hash_known_hosts = bool, None, false
+ ssh_known_hosts_timeout = int, None, false
++ca_db = str, None, false
+ 
+ [pac]
+ # PAC responder
+diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
+index 7d3a57b0eadec48d64cc9ddcb226b89a1600b432..37e73515fbfcae0da492533de72ad3208c870e9b 100644
+--- a/src/man/sssd.conf.5.xml
++++ b/src/man/sssd.conf.5.xml
+@@ -1082,6 +1082,19 @@ pam_account_expired_message = Account expired, please call help desk.
+                         </para>
+                     </listitem>
+                 </varlistentry>
++                <varlistentry>
++                    <term>ca_db (string)</term>
++                    <listitem>
++                        <para>
++                            Path to a storage of trusted CA certificates. The
++                            option is used to validate user certificates before
++                            deriving public ssh keys from them.
++                        </para>
++                        <para>
++                            Default: /etc/pki/nssdb
++                        </para>
++                    </listitem>
++                </varlistentry>
+             </variablelist>
+         </refsect2>
+ 
+diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
+index 9439b9d89ae47dc66d392f0c434f4de1c1c0b4ea..d4e202d87f520f1bdcd521733592027773a821d6 100644
+--- a/src/responder/ssh/sshsrv.c
++++ b/src/responder/ssh/sshsrv.c
+@@ -163,6 +163,15 @@ int ssh_process_init(TALLOC_CTX *mem_ctx,
+         goto fail;
+     }
+ 
++    ret = confdb_get_string(ssh_ctx->rctx->cdb, ssh_ctx,
++                            CONFDB_SSH_CONF_ENTRY, CONFDB_SSH_CA_DB,
++                            CONFDB_DEFAULT_SSH_CA_DB, &ssh_ctx->ca_db);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Error reading CA DB from confdb (%d) [%s]\n",
++              ret, strerror(ret));
++        goto fail;
++    }
++
+     ret = schedule_get_domains_task(rctx, rctx->ev, rctx, NULL);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "schedule_get_domains_tasks failed.\n");
+diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
+index 4833587910cade32ecb0b5f65b417d58a498b01e..f630e5f0311dadc69bee59afb672720f7018169d 100644
+--- a/src/responder/ssh/sshsrv_cmd.c
++++ b/src/responder/ssh/sshsrv_cmd.c
+@@ -27,6 +27,7 @@
+ #include "util/util.h"
+ #include "util/crypto/sss_crypto.h"
+ #include "util/sss_ssh.h"
++#include "util/cert.h"
+ #include "db/sysdb.h"
+ #include "db/sysdb_ssh.h"
+ #include "providers/data_provider.h"
+@@ -219,7 +220,8 @@ static errno_t
+ ssh_user_pubkeys_search_next(struct ssh_cmd_ctx *cmd_ctx)
+ {
+     errno_t ret;
+-    const char *attrs[] = { SYSDB_NAME, SYSDB_SSH_PUBKEY, NULL };
++    const char *attrs[] = { SYSDB_NAME, SYSDB_SSH_PUBKEY, SYSDB_USER_CERT,
++                            NULL };
+     struct ldb_result *res;
+ 
+     DEBUG(SSSDBG_TRACE_FUNC,
+@@ -794,6 +796,8 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
+ 
+ static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx,
+                                           struct ldb_message_element *el,
++                                          bool cert_data,
++                                          struct ssh_ctx *ssh_ctx,
+                                           size_t fqname_len,
+                                           const char *fqname,
+                                           size_t *c)
+@@ -819,12 +823,22 @@ static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx,
+     }
+ 
+     for (d = 0; d < el->num_values; d++) {
+-        key = sss_base64_decode(tmp_ctx, (const char *) el->values[d].data,
+-                                &key_len);
+-        if (key == NULL) {
+-            DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n");
+-            ret = ENOMEM;
+-            goto done;
++        if (cert_data) {
++            ret = cert_to_ssh_key(tmp_ctx, ssh_ctx->ca_db,
++                                  el->values[d].data, el->values[d].length,
++                                  &key, &key_len);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_OP_FAILURE, "cert_to_ssh_key failed.\n");
++                return ret;
++            }
++        } else  {
++            key = sss_base64_decode(tmp_ctx, (const char *) el->values[d].data,
++                                    &key_len);
++            if (key == NULL) {
++                DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n");
++                ret = ENOMEM;
++                goto done;
++            }
+         }
+ 
+         ret = sss_packet_grow(cctx->creq->out,
+@@ -862,10 +876,13 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
+     struct ldb_message_element *el = NULL;
+     struct ldb_message_element *el_override = NULL;
+     struct ldb_message_element *el_orig = NULL;
++    struct ldb_message_element *el_user_cert = NULL;
+     uint32_t count = 0;
+     const char *name;
+     char *fqname;
+     uint32_t fqname_len;
++    struct ssh_ctx *ssh_ctx = talloc_get_type(cctx->rctx->pvt_ctx,
++                                              struct ssh_ctx);
+ 
+     ret = sss_packet_new(cctx->creq, 0,
+                          sss_packet_get_cmd(cctx->creq->in),
+@@ -893,6 +910,12 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
+         }
+     }
+ 
++    el_user_cert = ldb_msg_find_element(cmd_ctx->result, SYSDB_USER_CERT);
++    if (el_user_cert) {
++        /* TODO check if cert is valid */
++        count += el_user_cert->num_values;
++    }
++
+     ret = sss_packet_grow(cctx->creq->out, 2*sizeof(uint32_t));
+     if (ret != EOK) {
+         return ret;
+@@ -922,20 +945,29 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
+ 
+     fqname_len = strlen(fqname)+1;
+ 
+-    ret = decode_and_add_base64_data(cmd_ctx, el, fqname_len, fqname, &c);
++    ret = decode_and_add_base64_data(cmd_ctx, el, false, ssh_ctx,
++                                     fqname_len, fqname, &c);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
+         return ret;
+     }
+ 
+-    ret = decode_and_add_base64_data(cmd_ctx, el_orig, fqname_len, fqname, &c);
++    ret = decode_and_add_base64_data(cmd_ctx, el_orig, false, ssh_ctx,
++                                     fqname_len, fqname, &c);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
+         return ret;
+     }
+ 
+-    ret = decode_and_add_base64_data(cmd_ctx, el_override, fqname_len, fqname,
+-                                     &c);
++    ret = decode_and_add_base64_data(cmd_ctx, el_override, false, ssh_ctx,
++                                     fqname_len, fqname, &c);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
++        return ret;
++    }
++
++    ret = decode_and_add_base64_data(cmd_ctx, el_user_cert, true, ssh_ctx,
++                                     fqname_len, fqname, &c);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
+         return ret;
+diff --git a/src/responder/ssh/sshsrv_private.h b/src/responder/ssh/sshsrv_private.h
+index ebb30ce7cbc982bb29b73592d5873e7d3652228a..beb8e18db77d8224e49df141748484ce61b11dac 100644
+--- a/src/responder/ssh/sshsrv_private.h
++++ b/src/responder/ssh/sshsrv_private.h
+@@ -32,6 +32,7 @@ struct ssh_ctx {
+ 
+     bool hash_known_hosts;
+     int known_hosts_timeout;
++    char *ca_db;
+ };
+ 
+ struct ssh_cmd_ctx {
+diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c
+index 8063b1a65e8692142cbb3cf82fe41afa6567bc91..7bd8cf2344003421e9ec84dc5e1b2305a861ab38 100644
+--- a/src/tests/cmocka/test_cert_utils.c
++++ b/src/tests/cmocka/test_cert_utils.c
+@@ -21,15 +21,18 @@
+     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>
+ #ifdef HAVE_LIBCRYPTO
+ #include <openssl/objects.h>
++#include <openssl/crypto.h>
+ #endif
+ 
+ #include "util/cert.h"
+ #include "tests/cmocka/common_mock.h"
+ #include "util/crypto/nss/nss_util.h"
++#include "util/crypto/sss_crypto.h"
+ 
+ 
+ /* TODO: create a certificate for this test */
+@@ -306,6 +309,63 @@ void test_sss_cert_derb64_to_ldap_filter(void **state)
+     talloc_free(filter);
+ }
+ 
++
++#define SSH_TEST_CERT \
++"MIIECTCCAvGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \
++"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA2MjMx" \
++"NjMyMDdaFw0xNzA2MjMxNjMyMDdaMDIxEjAQBgNVBAoMCUlQQS5ERVZFTDEcMBoG" \
++"A1UEAwwTaXBhLWRldmVsLmlwYS5kZXZlbDCCASIwDQYJKoZIhvcNAQEBBQADggEP" \
++"ADCCAQoCggEBALXUq56VlY+Z0aWLLpFAjFfbElPBXGQsbZb85J3cGyPjaMHC9wS+" \
++"wjB6Ve4HmQyPLx8hbINdDmbawMHYQvTScLYfsqLtj0Lqw20sUUmedk+Es5Oh9VHo" \
++"nd8MavYx25Du2u+T0iSgNIDikXguiwCmtAj8VC49ebbgITcjJGzMmiiuJkV3o93Y" \
++"vvYF0VjLGDQbQWOy7IxzYJeNVJnZWKo67CHdok6qOrm9rxQt81rzwV/mGLbCMUbr" \
++"+N4M8URtd7EmzaYZQmNm//s2owFrCYMxpLiURPj+URZVuB72504/Ix7X0HCbA/AV" \
++"26J27fPY5nc8DMwfhUDCbTqPH/JEjd3mvY8CAwEAAaOCASYwggEiMB8GA1UdIwQY" \
++"MBaAFJOq+KAQmPEnNp8Wok23eGTdE7aDMDsGCCsGAQUFBwEBBC8wLTArBggrBgEF" \
++"BQcwAYYfaHR0cDovL2lwYS1jYS5pcGEuZGV2ZWwvY2Evb2NzcDAOBgNVHQ8BAf8E" \
++"BAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHQGA1UdHwRtMGsw" \
++"aaAxoC+GLWh0dHA6Ly9pcGEtY2EuaXBhLmRldmVsL2lwYS9jcmwvTWFzdGVyQ1JM" \
++"LmJpbqI0pDIwMDEOMAwGA1UECgwFaXBhY2ExHjAcBgNVBAMMFUNlcnRpZmljYXRl" \
++"IEF1dGhvcml0eTAdBgNVHQ4EFgQUFaDNd5a53QGpaw5m63hnwXicMQ8wDQYJKoZI" \
++"hvcNAQELBQADggEBADH7Nj00qqGhGJeXJQAsepqSskz/wooqXh8vgVyb8SS4N0/c" \
++"0aQtVmY81xamlXE12ZFpwDX43d+EufBkwCUKFX/+8JFDd2doAyeJxv1xM22kKRpc" \
++"AqITPgMsa9ToGMWxjbVpc/X/5YfZixWPF0/eZUTotBj9oaR039UrhGfyN7OguF/G" \
++"rzmxtB5y4ZrMpcD/Oe90mkd9HY7sA/fB8OWOUgeRfQoh97HNS0UiDWsPtfxmjQG5" \
++"zotpoBIZmdH+ipYsu58HohHVlM9Wi5H4QmiiXl+Soldkq7eXYlafcmT7wv8+cKwz" \
++"Nz0Tm3+eYpFqRo3skr6QzXi525Jkg3r6r+kkhxU="
++
++#define SSH_PUB_KEY "AAAAB3NzaC1yc2EAAAADAQABAAABAQC11KuelZWPmdGliy6RQIxX2xJTwVxkLG2W/OSd3Bsj42jBwvcEvsIwelXuB5kMjy8fIWyDXQ5m2sDB2EL00nC2H7Ki7Y9C6sNtLFFJnnZPhLOTofVR6J3fDGr2MduQ7trvk9IkoDSA4pF4LosAprQI/FQuPXm24CE3IyRszJooriZFd6Pd2L72BdFYyxg0G0FjsuyMc2CXjVSZ2ViqOuwh3aJOqjq5va8ULfNa88Ff5hi2wjFG6/jeDPFEbXexJs2mGUJjZv/7NqMBawmDMaS4lET4/lEWVbge9udOPyMe19BwmwPwFduidu3z2OZ3PAzMH4VAwm06jx/yRI3d5r2P"
++
++void test_cert_to_ssh_key(void **state)
++{
++    int ret;
++    uint8_t *key;
++    size_t key_size;
++    uint8_t *exp_key;
++    size_t exp_key_size;
++    uint8_t *der;
++    size_t der_size;
++
++    struct test_state *ts = talloc_get_type_abort(*state, struct test_state);
++    assert_non_null(ts);
++
++    der = sss_base64_decode(ts, SSH_TEST_CERT, &der_size);
++    assert_non_null(der);
++
++    exp_key = sss_base64_decode(ts, SSH_PUB_KEY, &exp_key_size);
++    assert_non_null(exp_key);
++
++    ret = cert_to_ssh_key(ts, "sql:" ABS_SRC_DIR "/src/tests/cmocka/p11_nssdb",
++                          der, der_size, &key, &key_size);
++    assert_int_equal(ret, EOK);
++    assert_int_equal(key_size, exp_key_size);
++    assert_memory_equal(key, exp_key, exp_key_size);
++
++    talloc_free(der);
++    talloc_free(key);
++    talloc_free(exp_key);
++}
++
+ int main(int argc, const char *argv[])
+ {
+     poptContext pc;
+@@ -330,6 +390,8 @@ int main(int argc, const char *argv[])
+                                         setup, teardown),
+         cmocka_unit_test_setup_teardown(test_sss_cert_derb64_to_ldap_filter,
+                                         setup, teardown),
++        cmocka_unit_test_setup_teardown(test_cert_to_ssh_key,
++                                        setup, teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+diff --git a/src/util/cert.h b/src/util/cert.h
+index 79ea1a4ab58149a312bece265798ab3a3f459114..edbafc492a1ed42ad616d0bf2fae882046711746 100644
+--- a/src/util/cert.h
++++ b/src/util/cert.h
+@@ -44,4 +44,8 @@ errno_t sss_cert_derb64_to_ldap_filter(TALLOC_CTX *mem_ctx, const char *derb64,
+ errno_t bin_to_ldap_filter_value(TALLOC_CTX *mem_ctx,
+                                  const uint8_t *blob, size_t blob_size,
+                                  char **_str);
++
++errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
++                        const uint8_t *der_blob, size_t der_size,
++                        uint8_t **key, size_t *key_size);
+ #endif /* __CERT_H__ */
+diff --git a/src/util/cert/libcrypto/cert.c b/src/util/cert/libcrypto/cert.c
+index 1a250f60d1a7dfd5c883ec7e9b1f9491fb74c9b0..01f9554b990d6a139bb9a1d8d558c1c3f6bb745c 100644
+--- a/src/util/cert/libcrypto/cert.c
++++ b/src/util/cert/libcrypto/cert.c
+@@ -166,3 +166,96 @@ done:
+     return ret;
+ 
+ }
++
++#define SSH_RSA_HEADER "ssh-rsa"
++#define SSH_RSA_HEADER_LEN (sizeof(SSH_RSA_HEADER) - 1)
++
++errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
++                        const uint8_t *der_blob, size_t der_size,
++                        uint8_t **key, size_t *key_size)
++{
++    int ret;
++    size_t size;
++    const unsigned char *d;
++    uint8_t *buf = NULL;
++    size_t c;
++    X509 *cert = NULL;
++    EVP_PKEY *cert_pub_key = NULL;
++    int modulus_len;
++    unsigned char modulus[OPENSSL_RSA_MAX_MODULUS_BITS/8];
++    int exponent_len;
++    unsigned char exponent[OPENSSL_RSA_MAX_PUBEXP_BITS/8];
++
++    if (der_blob == NULL || der_size == 0) {
++        return EINVAL;
++    }
++
++    d = (const unsigned char *) der_blob;
++
++    cert = d2i_X509(NULL, &d, (int) der_size);
++    if (cert == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "d2i_X509 failed.\n");
++        return EINVAL;
++    }
++
++    /* TODO: verify certificate !!!!! */
++
++    cert_pub_key = X509_get_pubkey(cert);
++    if (cert_pub_key == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "X509_get_pubkey failed.\n");
++        ret = EIO;
++        goto done;
++    }
++
++    if (cert_pub_key->type != EVP_PKEY_RSA) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Expected RSA public key, found unsupported [%d].\n",
++              cert_pub_key->type);
++        ret = EINVAL;
++        goto done;
++    }
++
++    modulus_len = BN_bn2bin(cert_pub_key->pkey.rsa->n, modulus);
++    exponent_len = BN_bn2bin(cert_pub_key->pkey.rsa->e, exponent);
++
++    size = SSH_RSA_HEADER_LEN + 3 * sizeof(uint32_t)
++                + modulus_len
++                + exponent_len
++                + 1; /* see comment about missing 00 below */
++
++    buf = talloc_size(mem_ctx, size);
++    if (buf == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    c = 0;
++
++    SAFEALIGN_SET_UINT32(buf, htobe32(SSH_RSA_HEADER_LEN), &c);
++    safealign_memcpy(&buf[c], SSH_RSA_HEADER, SSH_RSA_HEADER_LEN, &c);
++    SAFEALIGN_SET_UINT32(&buf[c], htobe32(exponent_len), &c);
++    safealign_memcpy(&buf[c], exponent, exponent_len, &c);
++
++    /* Adding missing 00 which afaik is added to make sure
++     * the bigint is handled as positive number */
++    /* TODO: make a better check if 00 must be added or not, e.g. ... & 0x80)
++     */
++    SAFEALIGN_SET_UINT32(&buf[c], htobe32(modulus_len + 1), &c);
++    SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
++    safealign_memcpy(&buf[c], modulus, modulus_len, &c);
++
++    *key = buf;
++    *key_size = size;
++
++    ret = EOK;
++
++done:
++    if (ret != EOK)  {
++        talloc_free(buf);
++    }
++    EVP_PKEY_free(cert_pub_key);
++    X509_free(cert);
++
++    return ret;
++}
+diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c
+index a20abf63a10de9a5e9810f1c7d56686d063d60c7..1ada35b6321b9e0f3daf87b3412cf7a124cbf2c7 100644
+--- a/src/util/cert/nss/cert.c
++++ b/src/util/cert/nss/cert.c
+@@ -20,9 +20,13 @@
+ 
+ #include "util/util.h"
+ 
++#include <nss.h>
+ #include <cert.h>
+ #include <base64.h>
++#include <key.h>
++#include <prerror.h>
+ 
++#include "util/crypto/sss_crypto.h"
+ #include "util/crypto/nss/nss_util.h"
+ 
+ #define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
+@@ -210,3 +214,129 @@ done:
+ 
+     return ret;
+ }
++
++#define SSH_RSA_HEADER "ssh-rsa"
++#define SSH_RSA_HEADER_LEN (sizeof(SSH_RSA_HEADER) - 1)
++
++errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
++                        const uint8_t *der_blob, size_t der_size,
++                        uint8_t **key, size_t *key_size)
++{
++    CERTCertDBHandle *handle;
++    CERTCertificate *cert = NULL;
++    SECItem der_item;
++    SECKEYPublicKey *cert_pub_key = NULL;
++    int ret;
++    size_t size;
++    uint8_t *buf = NULL;
++    size_t c;
++    NSSInitContext *nss_ctx;
++    NSSInitParameters parameters = { 0 };
++    parameters.length =  sizeof (parameters);
++    SECStatus rv;
++
++    if (der_blob == NULL || der_size == 0) {
++        return EINVAL;
++    }
++
++    /* initialize NSS with context, we might have already called
++     * NSS_NoDB_Init() but for validation we need to have access to a DB with
++     * the trusted issuer cert. Only NSS_InitContext will really open the DB
++     * in this case. I'm not sure about how long validation might need e.g. if
++     * CRLs or OSCP is enabled, maybe it would be better to run validation in
++     * p11_child ? */
++    nss_ctx = NSS_InitContext(ca_db, "", "", SECMOD_DB, &parameters,
++                              NSS_INIT_READONLY);
++    if (nss_ctx == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "NSS_InitContext failed [%d].\n",
++                                 PR_GetError());
++        return EIO;
++    }
++
++    handle = CERT_GetDefaultCertDB();
++
++    der_item.len = der_size;
++    der_item.data = discard_const(der_blob);
++
++    cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
++    if (cert == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
++        ret = EINVAL;
++        goto done;
++    }
++
++    rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
++                                   certificateUsageSSLClient, NULL, NULL);
++    if (rv != SECSuccess) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "CERT_VerifyCertificateNow failed [%d].\n",
++                                   PR_GetError());
++        ret = EACCES;
++        goto done;
++    }
++
++    cert_pub_key = CERT_ExtractPublicKey(cert);
++    if (cert_pub_key == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "CERT_ExtractPublicKey failed.\n");
++        ret = EIO;
++        goto done;
++    }
++
++    if (cert_pub_key->keyType != rsaKey) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Expected RSA public key, found unsupported [%d].\n",
++              cert_pub_key->keyType);
++        ret = EINVAL;
++        goto done;
++    }
++
++    size = SSH_RSA_HEADER_LEN + 3 * sizeof(uint32_t)
++                + cert_pub_key->u.rsa.modulus.len
++                + cert_pub_key->u.rsa.publicExponent.len
++                + 1; /* see comment about missing 00 below */
++
++    buf = talloc_size(mem_ctx, size);
++    if (buf == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    c = 0;
++
++    SAFEALIGN_SET_UINT32(buf, htobe32(SSH_RSA_HEADER_LEN), &c);
++    safealign_memcpy(&buf[c], SSH_RSA_HEADER, SSH_RSA_HEADER_LEN, &c);
++    SAFEALIGN_SET_UINT32(&buf[c],
++                         htobe32(cert_pub_key->u.rsa.publicExponent.len), &c);
++    safealign_memcpy(&buf[c], cert_pub_key->u.rsa.publicExponent.data,
++                     cert_pub_key->u.rsa.publicExponent.len, &c);
++
++    /* Looks like nss drops the leading 00 which afaik is added to make sure
++     * the bigint is handled as positive number */
++    /* TODO: make a better check if 00 must be added or not, e.g. ... & 0x80)
++     */
++    SAFEALIGN_SET_UINT32(&buf[c],
++                         htobe32(cert_pub_key->u.rsa.modulus.len + 1 ), &c);
++    SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
++    safealign_memcpy(&buf[c], cert_pub_key->u.rsa.modulus.data,
++                     cert_pub_key->u.rsa.modulus.len, &c);
++
++    *key = buf;
++    *key_size = size;
++
++    ret = EOK;
++
++done:
++    if (ret != EOK)  {
++        talloc_free(buf);
++    }
++    SECKEY_DestroyPublicKey(cert_pub_key);
++    CERT_DestroyCertificate(cert);
++
++    rv = NSS_ShutdownContext(nss_ctx);
++    if (rv != SECSuccess) {
++        DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n",
++                                 PR_GetError());
++    }
++
++    return ret;
++}
+-- 
+2.4.3
+
diff --git a/SOURCES/0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch b/SOURCES/0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch
new file mode 100644
index 0000000..222e9e3
--- /dev/null
+++ b/SOURCES/0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch
@@ -0,0 +1,88 @@
+From e10bcf99c6105b733b043a50ea96223a46784581 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 21 Jul 2015 11:44:03 +0200
+Subject: [PATCH 37/37] IPA: Remove MPG groups if getgrgid was called before
+ getpw()
+
+https://fedorahosted.org/sssd/ticket/2724
+
+This bug only affects IPA clients that are connected to IPA servers with
+AD trust and ID mapping in effect.
+
+If an IPA client calls getgrgid() for an ID that matches a user, the
+user's private group would be returned and stored as a group entry.
+
+Subsequent queries for that user would fail, because MPG domains impose
+uniqueness restriction for both the ID and name space across groups and
+users.
+
+To work around that, we remove the UPG groups in MPG domains during a
+group lookup.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+---
+ src/providers/ipa/ipa_s2n_exop.c | 41 ++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 39 insertions(+), 2 deletions(-)
+
+diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
+index 812a4bbd707faf5c184594b562c148d1e704fd58..1e6368dc7ef1a6f60b541409f7f6740d602f0d43 100644
+--- a/src/providers/ipa/ipa_s2n_exop.c
++++ b/src/providers/ipa/ipa_s2n_exop.c
+@@ -1764,6 +1764,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
+     int tret;
+     struct sysdb_attrs *gid_override_attrs = NULL;
+     char ** exop_grouplist;
++    struct ldb_message *msg;
+ 
+     tmp_ctx = talloc_new(NULL);
+     if (tmp_ctx == NULL) {
+@@ -2005,8 +2006,44 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
+                                    attrs->a.user.pw_dir, attrs->a.user.pw_shell,
+                                    NULL, attrs->sysdb_attrs, NULL,
+                                    timeout, now);
+-            if (ret != EOK) {
+-                DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_user failed.\n");
++            if (ret == EEXIST && dom->mpg == true) {
++                /* This handles the case where getgrgid() was called for
++                 * this user, so a group was created in the cache
++                 */
++                ret = sysdb_search_group_by_name(tmp_ctx, dom, name, NULL, &msg);
++                if (ret != EOK) {
++                    /* Fail even on ENOENT, the group must be around */
++                    DEBUG(SSSDBG_OP_FAILURE,
++                          "Could not delete MPG group [%d]: %s\n",
++                          ret, sss_strerror(ret));
++                    goto done;
++                }
++
++                ret = sysdb_delete_group(dom, NULL, attrs->a.user.pw_uid);
++                if (ret != EOK) {
++                    DEBUG(SSSDBG_OP_FAILURE,
++                          "sysdb_delete_group failed for MPG group [%d]: %s\n",
++                          ret, sss_strerror(ret));
++                    goto done;
++                }
++
++                ret = sysdb_store_user(dom, name, NULL,
++                                       attrs->a.user.pw_uid,
++                                       gid, attrs->a.user.pw_gecos,
++                                       attrs->a.user.pw_dir,
++                                       attrs->a.user.pw_shell,
++                                       NULL, attrs->sysdb_attrs, NULL,
++                                       timeout, now);
++                if (ret != EOK) {
++                    DEBUG(SSSDBG_OP_FAILURE,
++                          "sysdb_store_user failed for MPG user [%d]: %s\n",
++                          ret, sss_strerror(ret));
++                    goto done;
++                }
++            } else if (ret != EOK) {
++                DEBUG(SSSDBG_OP_FAILURE,
++                      "sysdb_store_user failed [%d]: %s\n",
++                      ret, sss_strerror(ret));
+                 goto done;
+             }
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0037-PAM-Run-pam-responder-as-nonroot.patch b/SOURCES/0037-PAM-Run-pam-responder-as-nonroot.patch
deleted file mode 100644
index 78d50f8..0000000
--- a/SOURCES/0037-PAM-Run-pam-responder-as-nonroot.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 157250faaf48514f1580c3de4abb224c190d243b Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Thu, 9 Oct 2014 17:25:34 +0200
-Subject: [PATCH 37/46] PAM: Run pam responder as nonroot
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 4e1892cdfcc5300d6632200c38ba67f2783d15f2)
----
- src/monitor/monitor.c      | 3 ++-
- src/responder/pam/pamsrv.c | 2 +-
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 297648a60836cec1bd95c0a2972c8d14be32675a..2f622e571478b2a71ef29ed518ca3b80c077b766 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1062,7 +1062,8 @@ static errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
-  */
- static bool svc_supported_as_nonroot(const char *svc_name)
- {
--    if (strcmp(svc_name, "nss") == 0) {
-+    if ((strcmp(svc_name, "nss") == 0)
-+        || (strcmp(svc_name, "pam") == 0)) {
-         return true;
-     }
-     return false;
-diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
-index d3cf0c770ad2978e101f40453137ade8d826b8e1..c7e3c20b2731efb9393bc820ab09486c48e0a9ea 100644
---- a/src/responder/pam/pamsrv.c
-+++ b/src/responder/pam/pamsrv.c
-@@ -368,7 +368,7 @@ int main(int argc, const char *argv[])
-         return 2;
-     }
- 
--    ret = server_setup("sssd[pam]", 0, 0, 0, CONFDB_PAM_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[pam]", 0, uid, gid, CONFDB_PAM_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) return 2;
- 
-     ret = die_if_parent_died();
--- 
-1.9.3
-
diff --git a/SOURCES/0038-AUTOFS-Run-the-autofs-responder-as-the-SSSD-user.patch b/SOURCES/0038-AUTOFS-Run-the-autofs-responder-as-the-SSSD-user.patch
deleted file mode 100644
index 87f2823..0000000
--- a/SOURCES/0038-AUTOFS-Run-the-autofs-responder-as-the-SSSD-user.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From f39e5c757a4f3b244d0372f5a57e1714bc890bc3 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 17 Oct 2014 17:30:07 +0200
-Subject: [PATCH 38/46] AUTOFS: Run the autofs responder as the SSSD user
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 287cc55b9086dd3c4e2a5fb84784e09767860142)
----
- src/monitor/monitor.c            | 3 ++-
- src/responder/autofs/autofssrv.c | 2 +-
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 2f622e571478b2a71ef29ed518ca3b80c077b766..4e461aa78e47ec6cedb77dd030f72c273a00a495 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1063,7 +1063,8 @@ static errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
- static bool svc_supported_as_nonroot(const char *svc_name)
- {
-     if ((strcmp(svc_name, "nss") == 0)
--        || (strcmp(svc_name, "pam") == 0)) {
-+        || (strcmp(svc_name, "pam") == 0)
-+        || (strcmp(svc_name, "autofs") == 0)) {
-         return true;
-     }
-     return false;
-diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
-index 12a7a777e214fa4c3821eb58ff602b3f3efb987a..44474ee0858d92fb5965de07773e3ad1e020ebfd 100644
---- a/src/responder/autofs/autofssrv.c
-+++ b/src/responder/autofs/autofssrv.c
-@@ -238,7 +238,7 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_autofs";
- 
--    ret = server_setup("sssd[autofs]", 0, 0, 0,
-+    ret = server_setup("sssd[autofs]", 0, uid, gid,
-                        CONFDB_AUTOFS_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) {
-         return 2;
--- 
-1.9.3
-
diff --git a/SOURCES/0038-mmap_cache-Rename-variables.patch b/SOURCES/0038-mmap_cache-Rename-variables.patch
new file mode 100644
index 0000000..3b5f30a
--- /dev/null
+++ b/SOURCES/0038-mmap_cache-Rename-variables.patch
@@ -0,0 +1,122 @@
+From fca34746951f740c544e62a5b60929c41a198fd1 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Thu, 16 Jul 2015 16:54:00 +0200
+Subject: [PATCH 38/47] mmap_cache: Rename variables
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit 39b31427e2d11ca318df11fd48db33a7cc610aa7)
+---
+ src/responder/nss/nsssrv_mmap_cache.c | 16 ++++++++--------
+ src/responder/nss/nsssrv_mmap_cache.h |  4 ++--
+ src/sss_client/nss_mc_initgr.c        | 10 +++++-----
+ src/util/mmap_cache.h                 |  2 +-
+ 4 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
+index ebda8ac6fab3dd87f5a1d8e43717bf7a5b5a9878..16bc926f3ba4f5ab096bd0fb43895edef2b57c50 100644
+--- a/src/responder/nss/nsssrv_mmap_cache.c
++++ b/src/responder/nss/nsssrv_mmap_cache.c
+@@ -959,8 +959,8 @@ done:
+ 
+ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                                     struct sized_string *name,
+-                                    uint32_t memnum,
+-                                    uint8_t *membuf)
++                                    uint32_t num_groups,
++                                    uint8_t *gids_buf)
+ {
+     struct sss_mc_ctx *mcc = *_mcc;
+     struct sss_mc_rec *rec;
+@@ -974,8 +974,8 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+         return EINVAL;
+     }
+ 
+-    /* memnum + reserved + array of members + name*/
+-    data_len = (2 + memnum) * sizeof(uint32_t) + name->len;
++    /* num_groups + reserved + array of gids + name*/
++    data_len = (2 + num_groups) * sizeof(uint32_t) + name->len;
+     rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data)
+               + data_len;
+     if (rec_len > mcc->dt_size) {
+@@ -998,10 +998,10 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                             name->str, name->len, name->str, name->len);
+ 
+     /* initgroups struct */
+-    data->members = memnum;
+-    memcpy(data->gids, membuf, memnum * sizeof(uint32_t));
+-    memcpy(&data->gids[memnum], name->str, name->len);
+-    data->name = MC_PTR_DIFF(&data->gids[memnum], data);
++    data->num_groups = num_groups;
++    memcpy(data->gids, gids_buf, num_groups * sizeof(uint32_t));
++    memcpy(&data->gids[num_groups], name->str, name->len);
++    data->name = MC_PTR_DIFF(&data->gids[num_groups], data);
+ 
+     MC_LOWER_BARRIER(rec);
+ 
+diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h
+index 3a6764dd36bf3346d789bb287b3a94df120f36ee..b09e4a6f8efa364ae7a6407bab9d8a2a2143c812 100644
+--- a/src/responder/nss/nsssrv_mmap_cache.h
++++ b/src/responder/nss/nsssrv_mmap_cache.h
+@@ -53,8 +53,8 @@ errno_t sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc,
+ 
+ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                                     struct sized_string *name,
+-                                    uint32_t memnum,
+-                                    uint8_t *membuf);
++                                    uint32_t num_groups,
++                                    uint8_t *gids_buf);
+ 
+ errno_t sss_mmap_cache_pw_invalidate(struct sss_mc_ctx *mcc,
+                                      struct sized_string *name);
+diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c
+index bfb09d6550c310fbab254dc9b3ab7b306b7d3f06..e21b9f40aba00f9cc2385a561fc2bcc163c5791a 100644
+--- a/src/sss_client/nss_mc_initgr.c
++++ b/src/sss_client/nss_mc_initgr.c
+@@ -42,7 +42,7 @@ static errno_t sss_nss_mc_parse_result(struct sss_mc_rec *rec,
+     struct sss_mc_initgr_data *data;
+     time_t expire;
+     long int i;
+-    uint32_t gid_count;
++    uint32_t num_groups;
+     long int max_ret;
+ 
+     /* additional checks before filling result*/
+@@ -53,15 +53,15 @@ static errno_t sss_nss_mc_parse_result(struct sss_mc_rec *rec,
+     }
+ 
+     data = (struct sss_mc_initgr_data *)rec->data;
+-    gid_count = data->members;
+-    max_ret = gid_count;
++    num_groups = data->num_groups;
++    max_ret = num_groups;
+ 
+     /* check we have enough space in the buffer */
+-    if ((*size - *start) < gid_count) {
++    if ((*size - *start) < num_groups) {
+         long int newsize;
+         gid_t *newgroups;
+ 
+-        newsize = *size + gid_count;
++        newsize = *size + num_groups;
+         if ((limit > 0) && (newsize > limit)) {
+             newsize = limit;
+             max_ret = newsize - *start;
+diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
+index 438e28a3d217041278fc1bb60aa553d098516035..a8703d5da4022e11c4bc2f3e2f8710e7f9d982bf 100644
+--- a/src/util/mmap_cache.h
++++ b/src/util/mmap_cache.h
+@@ -139,7 +139,7 @@ struct sss_mc_grp_data {
+ 
+ struct sss_mc_initgr_data {
+     rel_ptr_t name;         /* ptr to name string, rel. to struct base addr */
+-    uint32_t members;       /* number of members in groups */
++    uint32_t num_groups;    /* number of groups */
+     uint32_t gids[0];       /* array of all groups
+                              * string with name is stored after gids */
+ };
+-- 
+2.4.3
+
diff --git a/SOURCES/0039-PAC-Run-the-pac-responder-as-the-SSSD-user.patch b/SOURCES/0039-PAC-Run-the-pac-responder-as-the-SSSD-user.patch
deleted file mode 100644
index d57f2b7..0000000
--- a/SOURCES/0039-PAC-Run-the-pac-responder-as-the-SSSD-user.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 1afda474301754a095c55497aaee1fd038a8dcd0 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 17 Oct 2014 17:31:31 +0200
-Subject: [PATCH 39/46] PAC: Run the pac responder as the SSSD user
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 22f4bcbb211bf800af647ad1fc9595a8020a6fe6)
----
- src/monitor/monitor.c      | 3 ++-
- src/responder/pac/pacsrv.c | 3 ++-
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 4e461aa78e47ec6cedb77dd030f72c273a00a495..61a9f0b849a460da88b393b4f08795fb7a571886 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1064,7 +1064,8 @@ static bool svc_supported_as_nonroot(const char *svc_name)
- {
-     if ((strcmp(svc_name, "nss") == 0)
-         || (strcmp(svc_name, "pam") == 0)
--        || (strcmp(svc_name, "autofs") == 0)) {
-+        || (strcmp(svc_name, "autofs") == 0)
-+        || (strcmp(svc_name, "pac") == 0)) {
-         return true;
-     }
-     return false;
-diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
-index e427cd756f4031218a8fb99c30bf709e21680039..3eb21c8fff85343249494bcc06d97cda4b738034 100644
---- a/src/responder/pac/pacsrv.c
-+++ b/src/responder/pac/pacsrv.c
-@@ -247,7 +247,8 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_pac";
- 
--    ret = server_setup("sssd[pac]", 0, 0, 0, CONFDB_PAC_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[pac]", 0, uid, gid,
-+                       CONFDB_PAC_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) return 2;
- 
-     ret = die_if_parent_died();
--- 
-1.9.3
-
diff --git a/SOURCES/0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch b/SOURCES/0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch
new file mode 100644
index 0000000..209ff16
--- /dev/null
+++ b/SOURCES/0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch
@@ -0,0 +1,146 @@
+From 8ca168c6f459d77cdf8f46d27a392d0847343703 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Thu, 16 Jul 2015 17:00:12 +0200
+Subject: [PATCH 39/47] mmap_cache: "Override" functions for initgr mmap cache
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Functions sss_mc_get_strs_offset and sss_mc_get_strs_len provides
+data about strings for individual memory caches (passwd, ...)
+Their are used in generic responder mmap cache code to find a record
+in mmap cache (sss_mc_find_record). Data provided from functions sss_mc_get_*
+are used for checking the validity of record. So in case of corrupted record
+the whole mmap cache can be invalidated.
+
+Functions sss_mc_get_strs_offset and sss_mc_get_strs_len did not provide
+data for initgroups mmap cache and therefore particular record could not be
+invalidated.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2716
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit 225dc6914cdc8920b02a129b98ece1ed97b99c03)
+---
+ src/responder/nss/nsssrv_mmap_cache.c | 15 ++++++++++++---
+ src/sss_client/nss_mc_initgr.c        | 16 +++++++++++-----
+ src/util/mmap_cache.h                 |  6 +++++-
+ 3 files changed, 28 insertions(+), 9 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
+index 16bc926f3ba4f5ab096bd0fb43895edef2b57c50..ab9e769b1f4d5d17a8c41429afce292298239bc5 100644
+--- a/src/responder/nss/nsssrv_mmap_cache.c
++++ b/src/responder/nss/nsssrv_mmap_cache.c
+@@ -475,6 +475,9 @@ static errno_t sss_mc_get_strs_offset(struct sss_mc_ctx *mcc,
+     case SSS_MC_GROUP:
+         *_offset = offsetof(struct sss_mc_grp_data, strs);
+         return EOK;
++    case SSS_MC_INITGROUPS:
++        *_offset = offsetof(struct sss_mc_initgr_data, gids);
++        return EOK;
+     default:
+         DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n");
+         return EINVAL;
+@@ -492,6 +495,9 @@ static errno_t sss_mc_get_strs_len(struct sss_mc_ctx *mcc,
+     case SSS_MC_GROUP:
+         *_len = ((struct sss_mc_grp_data *)&rec->data)->strs_len;
+         return EOK;
++    case SSS_MC_INITGROUPS:
++        *_len = ((struct sss_mc_initgr_data *)&rec->data)->data_len;
++        return EOK;
+     default:
+         DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n");
+         return EINVAL;
+@@ -974,8 +980,8 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+         return EINVAL;
+     }
+ 
+-    /* num_groups + reserved + array of gids + name*/
+-    data_len = (2 + num_groups) * sizeof(uint32_t) + name->len;
++    /* array of gids + name */
++    data_len = num_groups * sizeof(uint32_t) + name->len;
+     rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data)
+               + data_len;
+     if (rec_len > mcc->dt_size) {
+@@ -998,10 +1004,13 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                             name->str, name->len, name->str, name->len);
+ 
+     /* initgroups struct */
++    data->strs_len = name->len;
++    data->data_len = data_len;
++    data->reserved = MC_INVALID_VAL32;
+     data->num_groups = num_groups;
+     memcpy(data->gids, gids_buf, num_groups * sizeof(uint32_t));
+     memcpy(&data->gids[num_groups], name->str, name->len);
+-    data->name = MC_PTR_DIFF(&data->gids[num_groups], data);
++    data->strs = data->name = MC_PTR_DIFF(&data->gids[num_groups], data);
+ 
+     MC_LOWER_BARRIER(rec);
+ 
+diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c
+index e21b9f40aba00f9cc2385a561fc2bcc163c5791a..153617ea9c6489b7439b9676904b42b042f6697c 100644
+--- a/src/sss_client/nss_mc_initgr.c
++++ b/src/sss_client/nss_mc_initgr.c
+@@ -93,6 +93,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+     uint32_t hash;
+     uint32_t slot;
+     int ret;
++    const size_t data_offset = offsetof(struct sss_mc_initgr_data, gids);
+     uint8_t *max_addr;
+ 
+     ret = sss_nss_mc_get_ctx("initgroups", &initgr_mc_ctx);
+@@ -128,16 +129,21 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+         }
+ 
+         data = (struct sss_mc_initgr_data *)rec->data;
++        rec_name = (char *)data + data->name;
+         /* Integrity check
+-         * - array with gids must be within data_table
+-         * - string must be within data_table */
+-        if ((uint8_t *)data->gids > max_addr
+-                || (uint8_t *)data + data->name + name_len > max_addr) {
++         * - name_len cannot be longer than all strings or data
++         * - data->name cannot point outside strings
++         * - all data must be within data_table
++         * - name must be within data_table */
++        if (name_len > data->data_len
++            || name_len > data->strs_len
++            || (data->strs + name_len) > (data_offset + data->data_len)
++            || (uint8_t *)data->gids + data->data_len > max_addr
++            || (uint8_t *)rec_name + name_len > max_addr) {
+             ret = ENOENT;
+             goto done;
+         }
+ 
+-        rec_name = (char *)data + data->name;
+         if (strcmp(name, rec_name) == 0) {
+             break;
+         }
+diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
+index a8703d5da4022e11c4bc2f3e2f8710e7f9d982bf..b5917b3c0973276e43e9fe160cec7528b1224f8f 100644
+--- a/src/util/mmap_cache.h
++++ b/src/util/mmap_cache.h
+@@ -79,7 +79,7 @@ typedef uint32_t rel_ptr_t;
+ 
+ 
+ #define SSS_MC_MAJOR_VNO    1
+-#define SSS_MC_MINOR_VNO    0
++#define SSS_MC_MINOR_VNO    1
+ 
+ #define SSS_MC_HEADER_UNINIT    0   /* after ftruncate or before reset */
+ #define SSS_MC_HEADER_ALIVE     1   /* current and in use */
+@@ -139,6 +139,10 @@ struct sss_mc_grp_data {
+ 
+ struct sss_mc_initgr_data {
+     rel_ptr_t name;         /* ptr to name string, rel. to struct base addr */
++    rel_ptr_t strs;         /* ptr to concatenation of all strings */
++    uint32_t reserved;
++    uint32_t strs_len;      /* length of strs */
++    uint32_t data_len;      /* all initgroups data len */
+     uint32_t num_groups;    /* number of groups */
+     uint32_t gids[0];       /* array of all groups
+                              * string with name is stored after gids */
+-- 
+2.4.3
+
diff --git a/SOURCES/0040-SUDO-Run-the-sudo-responder-as-the-SSSD-user.patch b/SOURCES/0040-SUDO-Run-the-sudo-responder-as-the-SSSD-user.patch
deleted file mode 100644
index 2fc6840..0000000
--- a/SOURCES/0040-SUDO-Run-the-sudo-responder-as-the-SSSD-user.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 88b6f5da86301ac3f76cacdc99d7ab5045a5a3a6 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 17 Oct 2014 18:14:45 +0200
-Subject: [PATCH 40/46] SUDO: Run the sudo responder as the SSSD user
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 3f9e2c24dbc14b2eafbe4f5a5ee16fe9af3c3f75)
----
- src/monitor/monitor.c        | 3 ++-
- src/responder/sudo/sudosrv.c | 2 +-
- 2 files changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 61a9f0b849a460da88b393b4f08795fb7a571886..d09aeba9033ff1460f9d4a6c51f35edbf2e67fa6 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1065,7 +1065,8 @@ static bool svc_supported_as_nonroot(const char *svc_name)
-     if ((strcmp(svc_name, "nss") == 0)
-         || (strcmp(svc_name, "pam") == 0)
-         || (strcmp(svc_name, "autofs") == 0)
--        || (strcmp(svc_name, "pac") == 0)) {
-+        || (strcmp(svc_name, "pac") == 0)
-+        || (strcmp(svc_name, "sudo") == 0)) {
-         return true;
-     }
-     return false;
-diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
-index 038e3fd7da0829ce554a31694725c3dddaf5c038..a25f98ecabaa952a7cd87c54cd302903cb563faf 100644
---- a/src/responder/sudo/sudosrv.c
-+++ b/src/responder/sudo/sudosrv.c
-@@ -195,7 +195,7 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_sudo";
- 
--    ret = server_setup("sssd[sudo]", 0, 0, 0, CONFDB_SUDO_CONF_ENTRY,
-+    ret = server_setup("sssd[sudo]", 0, uid, gid, CONFDB_SUDO_CONF_ENTRY,
-                        &main_ctx);
-     if (ret != EOK) {
-         return 2;
--- 
-1.9.3
-
diff --git a/SOURCES/0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch b/SOURCES/0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch
new file mode 100644
index 0000000..579937b
--- /dev/null
+++ b/SOURCES/0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch
@@ -0,0 +1,59 @@
+From 999edf37f10c90f8a2e87c16183bac2d0c6fe833 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Mon, 3 Aug 2015 12:58:03 +0200
+Subject: [PATCH 40/47] mmap: Invalidate initgroups memory cache after any
+ change
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Initgroups memory cache was invalidated only in case on removed user.
+it should be invalidated also after changes in group membership.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2716
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit ea7839cec593b4a7c678fab52ab864518db6699b)
+---
+ src/responder/nss/nsssrv_cmd.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
+index b3998015fa621cad8e06a126a674f94d26158dda..0bfbf0eab115826ebde53b4cfcf6661f2f6328c7 100644
+--- a/src/responder/nss/nsssrv_cmd.c
++++ b/src/responder/nss/nsssrv_cmd.c
+@@ -3903,14 +3903,6 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx,
+                   ret, strerror(ret));
+         }
+ 
+-        ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx,
+-                                               &delete_name);
+-        if (ret != EOK && ret != ENOENT) {
+-            DEBUG(SSSDBG_CRIT_FAILURE,
+-                  "Internal failure in memory cache code: %d [%s]\n",
+-                  ret, strerror(ret));
+-        }
+-
+         /* Also invalidate his groups */
+         changed = true;
+     } else {
+@@ -3958,6 +3950,15 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx,
+                        ret, strerror(ret));
+             }
+         }
++
++        to_sized_string(&delete_name, name);
++        ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx,
++                                               &delete_name);
++        if (ret != EOK && ret != ENOENT) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Internal failure in memory cache code: %d [%s]\n",
++                  ret, strerror(ret));
++        }
+     }
+ 
+ done:
+-- 
+2.4.3
+
diff --git a/SOURCES/0041-SSH-Run-the-ssh-responder-as-the-SSSD-user.patch b/SOURCES/0041-SSH-Run-the-ssh-responder-as-the-SSSD-user.patch
deleted file mode 100644
index 86d2d0b..0000000
--- a/SOURCES/0041-SSH-Run-the-ssh-responder-as-the-SSSD-user.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 48db24e8e576c2bde0acdf41c4228fc2a29b4db4 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 17 Oct 2014 18:14:53 +0200
-Subject: [PATCH 41/46] SSH: Run the ssh responder as the SSSD user
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-(cherry picked from commit 76c8dafad2a18cf1514635aa766062085c23a5c8)
----
- src/monitor/monitor.c      | 3 ++-
- src/responder/ssh/sshsrv.c | 3 ++-
- 2 files changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index d09aeba9033ff1460f9d4a6c51f35edbf2e67fa6..0dea327213a1ad04b6f69c0ffb0fb87254420796 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -1066,7 +1066,8 @@ static bool svc_supported_as_nonroot(const char *svc_name)
-         || (strcmp(svc_name, "pam") == 0)
-         || (strcmp(svc_name, "autofs") == 0)
-         || (strcmp(svc_name, "pac") == 0)
--        || (strcmp(svc_name, "sudo") == 0)) {
-+        || (strcmp(svc_name, "sudo") == 0)
-+        || (strcmp(svc_name, "ssh") == 0)) {
-         return true;
-     }
-     return false;
-diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
-index b154ee1baa16de68f642d2e967b8e7c873c8d4e7..b1969b49de8579f0136c3afa78eb16d68c81ee4e 100644
---- a/src/responder/ssh/sshsrv.c
-+++ b/src/responder/ssh/sshsrv.c
-@@ -215,7 +215,8 @@ int main(int argc, const char *argv[])
-     /* set up things like debug, signals, daemonization, etc... */
-     debug_log_file = "sssd_ssh";
- 
--    ret = server_setup("sssd[ssh]", 0, 0, 0, CONFDB_SSH_CONF_ENTRY, &main_ctx);
-+    ret = server_setup("sssd[ssh]", 0, uid, gid,
-+                       CONFDB_SSH_CONF_ENTRY, &main_ctx);
-     if (ret != EOK) {
-         return 2;
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0041-sss_client-Update-integrity-check-of-records-in-mmap.patch b/SOURCES/0041-sss_client-Update-integrity-check-of-records-in-mmap.patch
new file mode 100644
index 0000000..c59a460
--- /dev/null
+++ b/SOURCES/0041-sss_client-Update-integrity-check-of-records-in-mmap.patch
@@ -0,0 +1,227 @@
+From e115f70d717ab8232172b358739ba7a0e1102caa Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Thu, 30 Jul 2015 10:50:47 +0200
+Subject: [PATCH 41/47] sss_client: Update integrity check of records in mmap
+ cache
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function sss_nss_mc_get_record return copy of record from memory
+cache in last argument. Because we should not access data directly
+to avoid problems with consistency of record.
+The function sss_nss_mc_get_record also check whether length of record
+is within data area (with macro MC_CHECK_RECORD_LENGTH)
+
+However we also tried to do the same check in functions sss_nss_mc_get{gr, pw}*
+Pointer to end of strings in record was compared to pointer to the end
+of data table. But these two pointers are not within the same allocated area
+and does not make sense to compare them. Sometimes record can be allocated
+before mmaped area and sometime after. Sometimes it will return cached data
+and other time will fall back to responder.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2743
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit ba847347cade817ee927397d82c952b51b0dcb2b)
+---
+ src/sss_client/nss_mc_group.c  | 19 ++++++++++---------
+ src/sss_client/nss_mc_initgr.c | 26 +++++++++++++-------------
+ src/sss_client/nss_mc_passwd.c | 20 ++++++++++----------
+ 3 files changed, 33 insertions(+), 32 deletions(-)
+
+diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c
+index e0fdb97f628ac19741409be29566e4af5a391f74..aacf59d9fd8b81ea895f4660de08f3e44f0ce645 100644
+--- a/src/sss_client/nss_mc_group.c
++++ b/src/sss_client/nss_mc_group.c
+@@ -112,16 +112,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
+     uint32_t hash;
+     uint32_t slot;
+     int ret;
+-    size_t strs_offset;
+-    uint8_t *max_addr;
++    const size_t strs_offset = offsetof(struct sss_mc_grp_data, strs);
++    size_t data_size;
+ 
+     ret = sss_nss_mc_get_ctx("group", &gr_mc_ctx);
+     if (ret) {
+         return ret;
+     }
+ 
+-    /* Get max address of data table. */
+-    max_addr = gr_mc_ctx.data_table + gr_mc_ctx.dt_size;
++    /* Get max size of data table. */
++    data_size = gr_mc_ctx.dt_size;
+ 
+     /* hashes are calculated including the NULL terminator */
+     hash = sss_nss_mc_hash(&gr_mc_ctx, name, name_len + 1);
+@@ -130,7 +130,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
+     /* If slot is not within the bounds of mmaped region and
+      * it's value is not MC_INVALID_VAL, then the cache is
+      * probbably corrupted. */
+-    while (MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) {
++    while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
+         /* free record from previous iteration */
+         free(rec);
+         rec = NULL;
+@@ -147,15 +147,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
+             continue;
+         }
+ 
+-        strs_offset = offsetof(struct sss_mc_grp_data, strs);
+         data = (struct sss_mc_grp_data *)rec->data;
+         /* Integrity check
+          * - name_len cannot be longer than all strings
+          * - data->name cannot point outside strings
+-         * - all strings must be within data_table */
++         * - all strings must be within copy of record
++         * - size of record must be lower that data table size */
+         if (name_len > data->strs_len
+             || (data->name + name_len) > (strs_offset + data->strs_len)
+-            || (uint8_t *)data->strs + data->strs_len > max_addr) {
++            || data->strs_len > rec->len
++            || rec->len > data_size) {
+             ret = ENOENT;
+             goto done;
+         }
+@@ -168,7 +169,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
+         slot = sss_nss_mc_next_slot_with_hash(rec, hash);
+     }
+ 
+-    if (!MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) {
++    if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
+         ret = ENOENT;
+         goto done;
+     }
+diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c
+index 153617ea9c6489b7439b9676904b42b042f6697c..74143d9fb3c674c3116d7f4cf0b4c03d993743a2 100644
+--- a/src/sss_client/nss_mc_initgr.c
++++ b/src/sss_client/nss_mc_initgr.c
+@@ -94,15 +94,15 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+     uint32_t slot;
+     int ret;
+     const size_t data_offset = offsetof(struct sss_mc_initgr_data, gids);
+-    uint8_t *max_addr;
++    size_t data_size;
+ 
+     ret = sss_nss_mc_get_ctx("initgroups", &initgr_mc_ctx);
+     if (ret) {
+         return ret;
+     }
+ 
+-    /* Get max address of data table. */
+-    max_addr = initgr_mc_ctx.data_table + initgr_mc_ctx.dt_size;
++    /* Get max size of data table. */
++    data_size = initgr_mc_ctx.dt_size;
+ 
+     /* hashes are calculated including the NULL terminator */
+     hash = sss_nss_mc_hash(&initgr_mc_ctx, name, name_len + 1);
+@@ -111,7 +111,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+     /* If slot is not within the bounds of mmaped region and
+      * it's value is not MC_INVALID_VAL, then the cache is
+      * probbably corrupted. */
+-    while (MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) {
++    while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
+         /* free record from previous iteration */
+         free(rec);
+         rec = NULL;
+@@ -132,14 +132,14 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+         rec_name = (char *)data + data->name;
+         /* Integrity check
+          * - name_len cannot be longer than all strings or data
+-         * - data->name cannot point outside strings
+-         * - all data must be within data_table
+-         * - name must be within data_table */
+-        if (name_len > data->data_len
+-            || name_len > data->strs_len
+-            || (data->strs + name_len) > (data_offset + data->data_len)
+-            || (uint8_t *)data->gids + data->data_len > max_addr
+-            || (uint8_t *)rec_name + name_len > max_addr) {
++         * - all data must be within copy of record
++         * - size of record must be lower that data table size
++         * - data->strs cannot point outside strings */
++        if (name_len > data->strs_len
++            || data->strs_len > data->data_len
++            || data->data_len > rec->len
++            || rec->len > data_size
++            || (data->strs + name_len) > (data_offset + data->data_len)) {
+             ret = ENOENT;
+             goto done;
+         }
+@@ -151,7 +151,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+         slot = sss_nss_mc_next_slot_with_hash(rec, hash);
+     }
+ 
+-    if (!MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) {
++    if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
+         ret = ENOENT;
+         goto done;
+     }
+diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c
+index 10e43e2af43c5e7f1738e281b3ed260d89f3a004..0da7ad0aeece7d38ca34bb3fde64adc898eaf0ae 100644
+--- a/src/sss_client/nss_mc_passwd.c
++++ b/src/sss_client/nss_mc_passwd.c
+@@ -105,16 +105,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
+     uint32_t hash;
+     uint32_t slot;
+     int ret;
+-    size_t strs_offset;
+-    uint8_t *max_addr;
++    const size_t strs_offset = offsetof(struct sss_mc_pwd_data, strs);
++    size_t data_size;
+ 
+     ret = sss_nss_mc_get_ctx("passwd", &pw_mc_ctx);
+     if (ret) {
+         return ret;
+     }
+ 
+-    /* Get max address of data table. */
+-    max_addr = pw_mc_ctx.data_table + pw_mc_ctx.dt_size;
++    /* Get max size of data table. */
++    data_size = pw_mc_ctx.dt_size;
+ 
+     /* hashes are calculated including the NULL terminator */
+     hash = sss_nss_mc_hash(&pw_mc_ctx, name, name_len + 1);
+@@ -123,7 +123,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
+     /* If slot is not within the bounds of mmaped region and
+      * it's value is not MC_INVALID_VAL, then the cache is
+      * probbably corrupted. */
+-    while (MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) {
++    while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
+         /* free record from previous iteration */
+         free(rec);
+         rec = NULL;
+@@ -140,16 +140,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
+             continue;
+         }
+ 
+-        strs_offset = offsetof(struct sss_mc_pwd_data, strs);
+-
+         data = (struct sss_mc_pwd_data *)rec->data;
+         /* Integrity check
+          * - name_len cannot be longer than all strings
+          * - data->name cannot point outside strings
+-         * - all strings must be within data_table */
++         * - all strings must be within copy of record
++         * - size of record must be lower that data table size */
+         if (name_len > data->strs_len
+             || (data->name + name_len) > (strs_offset + data->strs_len)
+-            || (uint8_t *)data->strs + data->strs_len > max_addr) {
++            || data->strs_len > rec->len
++            || rec->len > data_size) {
+             ret = ENOENT;
+             goto done;
+         }
+@@ -162,7 +162,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
+         slot = sss_nss_mc_next_slot_with_hash(rec, hash);
+     }
+ 
+-    if (!MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) {
++    if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
+         ret = ENOENT;
+         goto done;
+     }
+-- 
+2.4.3
+
diff --git a/SOURCES/0042-SBUS-Fix-error-handling-after-closing-container.patch b/SOURCES/0042-SBUS-Fix-error-handling-after-closing-container.patch
deleted file mode 100644
index b7ed294..0000000
--- a/SOURCES/0042-SBUS-Fix-error-handling-after-closing-container.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 06db46d511ea4d5cce23354ed3c3a0069f06e27f Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 10 Oct 2014 19:23:33 +0200
-Subject: [PATCH 42/46] SBUS: Fix error handling after closing container
-
-If function dbus_message_iter_close_container fail the return variable ret will
-be set to EINVAL, but function will not be immediately terminated.
-"goto done" was missing.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 82b5395c1519b9392ddd323ece0845b51a994bbc)
----
- src/sbus/sssd_dbus_request.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/src/sbus/sssd_dbus_request.c b/src/sbus/sssd_dbus_request.c
-index 7729d4e0d7bf6e517e2efce4dbeb064f6f471b87..677ed532f7555f6aeba378ebd9a0b06167ddfa1b 100644
---- a/src/sbus/sssd_dbus_request.c
-+++ b/src/sbus/sssd_dbus_request.c
-@@ -286,6 +286,7 @@ int sbus_request_return_array_as_variant(struct sbus_request *dbus_req,
-                                         DBUS_ERROR_FAILED,
-                                         "Could not close array\n"));
-         ret = EINVAL;
-+        goto done;
-     }
- 
-     dbret = dbus_message_iter_close_container(&iter, &variant_iter);
-@@ -298,6 +299,7 @@ int sbus_request_return_array_as_variant(struct sbus_request *dbus_req,
-                                         DBUS_ERROR_FAILED,
-                                         "Could not close variant\n"));
-         ret = EINVAL;
-+        goto done;
-     }
- 
- done:
--- 
-1.9.3
-
diff --git a/SOURCES/0042-intg_test-Add-module-for-simulation-of-utility-id.patch b/SOURCES/0042-intg_test-Add-module-for-simulation-of-utility-id.patch
new file mode 100644
index 0000000..71ff852
--- /dev/null
+++ b/SOURCES/0042-intg_test-Add-module-for-simulation-of-utility-id.patch
@@ -0,0 +1,155 @@
+From b47156c92867daaa2c30a7f4ad884a27273e54ff Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Wed, 29 Jul 2015 14:35:52 +0200
+Subject: [PATCH 42/47] intg_test: Add module for simulation of utility id
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit 38b07019861240cf5107f5d51fc0027519e21619)
+---
+ src/tests/intg/Makefile.am |   1 +
+ src/tests/intg/sssd_id.py  | 119 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 120 insertions(+)
+ create mode 100644 src/tests/intg/sssd_id.py
+
+diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am
+index 9383e112002baa7b0d200a3dc205aa2856089c97..7488022ed59dd894ba7b6808c5573706412098c7 100644
+--- a/src/tests/intg/Makefile.am
++++ b/src/tests/intg/Makefile.am
+@@ -1,5 +1,6 @@
+ dist_noinst_DATA = \
+     config.py.m4 \
++    sssd_id.py \
+     ds.py \
+     ds_openldap.py \
+     ent.py \
+diff --git a/src/tests/intg/sssd_id.py b/src/tests/intg/sssd_id.py
+new file mode 100644
+index 0000000000000000000000000000000000000000..45f2822b5b33d99b6a7cbbbba0450c774e05ff11
+--- /dev/null
++++ b/src/tests/intg/sssd_id.py
+@@ -0,0 +1,119 @@
++#
++# Module for simulation of utility "id" from coreutils
++#
++# Copyright (c) 2015 Red Hat, Inc.
++# Author: Lukas Slebodnik <lslebodn@redhat.com>
++#
++# 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 config
++import pwd
++import grp
++from ctypes import (cdll, c_int, c_char, c_uint32, c_long, c_char_p,
++                    POINTER, pointer)
++
++
++class NssReturnCode(object):
++    """ 'enum' class for name service switch retrn code """
++    TRYAGAIN = -2,
++    UNAVAIL = -1
++    NOTFOUND = 0
++    SUCCESS = 1
++    RETURN = 2
++
++
++def call_sssd_initgroups(user, gid):
++    """
++    Function will initialize the supplementary group access list
++    for given user. It will gather groups only provided by sssd.
++
++    Arguments are the same as for C function initgroups
++    @param string user name of user
++    @param int gid the additional gid will be also added to the list.
++
++    @return (int, int, List[int]) (err, errno, gids)
++        gids shoudl contain user group IDs if err is NssReturnCode.SUCCESS
++        otherwise errno will contain non-zero vlaue.
++    """
++    libnss_sss_path = config.PREFIX + "/lib/libnss_sss.so.2"
++    libnss_sss = cdll.LoadLibrary(libnss_sss_path)
++
++    func = libnss_sss._nss_sss_initgroups_dyn
++    func.restype = c_int
++    func.argtypes = [POINTER(c_char), c_uint32, POINTER(c_long),
++                     POINTER(c_long), POINTER(POINTER(c_uint32)), c_long,
++                     POINTER(c_int)]
++
++    start = POINTER(c_long)(c_long(0))
++    size = POINTER(c_long)(c_long(0))
++    groups = POINTER(c_uint32)()
++    p_groups = pointer(groups)
++    limit = c_long(-1)
++    errno = POINTER(c_int)(c_int(0))
++
++    res = func(c_char_p(user), c_uint32(gid), start, size, p_groups, limit,
++               errno)
++
++    gids = []
++    if res == NssReturnCode.SUCCESS:
++        gids_count = size[0]
++        assert gids_count > 0, "_nss_sss_initgroups_dyn shoulld return " \
++                               "one gid"
++
++        for i in range(0, gids_count):
++            gids.append(int(p_groups.contents[i]))
++
++    return (int(res), errno[0], gids)
++
++
++def get_user_gids(user):
++    """
++    Function will initialize the supplementary group access list
++    for given user. It will gather groups only provided by sssd.
++
++    Arguments are the same as for C function initgroups
++    @param string user name of user
++
++    @return (int, int, List[int]) (err, errno, gids)
++        gids shoudl contain user group IDs if err is NssReturnCode.SUCCESS
++        otherwise errno will contain non-zero vlaue.
++    """
++    pwd_user = pwd.getpwnam(user)
++    uid = pwd_user.pw_uid
++    gid = pwd_user.pw_gid
++
++    user = pwd.getpwuid(uid).pw_name
++
++    return call_sssd_initgroups(user, gid)
++
++
++def get_user_groups(user):
++    """
++    Function will initialize the supplementary group access list
++    for given user. It will gather groups only provided by sssd.
++
++    Arguments are the same as for C function initgroups
++    @param string user name of user
++
++    @return (int, int, List[string]) (err, errno, groups)
++        roups shoudl contain names of user groups
++        if err is NssReturnCode.SUCCESS
++        otherwise errno will contain non-zero vlaue.
++    """
++    (res, errno, gids) = get_user_gids(user)
++    groups = []
++
++    if res == NssReturnCode.SUCCESS:
++        groups = [grp.getgrgid(gid).gr_name for gid in gids]
++
++    return (res, errno, groups)
+-- 
+2.4.3
+
diff --git a/SOURCES/0043-TESTS-Add-tests-for-the-views-related-option-maps.patch b/SOURCES/0043-TESTS-Add-tests-for-the-views-related-option-maps.patch
deleted file mode 100644
index 5ea2aa3..0000000
--- a/SOURCES/0043-TESTS-Add-tests-for-the-views-related-option-maps.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From f44e8711e3e1b81132d11084feb34ba62919429e Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 2 Oct 2014 11:10:47 +0200
-Subject: [PATCH 43/46] TESTS: Add tests for the views-related option maps
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit b1593daeecdb40c72ef8c58546bda65c57d4e35c)
----
- src/tests/ipa_ldap_opt-tests.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c
-index 3504092d444d89ab59e074237a3f8589aeebbcda..8587e8df77cf30cfef9cf2e5ca6484c3bc881876 100644
---- a/src/tests/ipa_ldap_opt-tests.c
-+++ b/src/tests/ipa_ldap_opt-tests.c
-@@ -228,12 +228,13 @@ START_TEST(test_sdap_opt_sentinel)
- 
-     fail_unless_sdap_opt_is_terminator(&netgroup_map[SDAP_OPTS_NETGROUP]);
-     fail_unless_sdap_opt_is_terminator(&ad_netgroup_map[SDAP_OPTS_NETGROUP]);
--
-     fail_unless_sdap_opt_is_terminator(&ipa_netgroup_map[IPA_OPTS_NETGROUP]);
- 
-     fail_unless_sdap_opt_is_terminator(&ipa_host_map[IPA_OPTS_HOST]);
-     fail_unless_sdap_opt_is_terminator(&ipa_hostgroup_map[IPA_OPTS_HOSTGROUP]);
-     fail_unless_sdap_opt_is_terminator(&ipa_selinux_user_map[IPA_OPTS_SELINUX_USERMAP]);
-+    fail_unless_sdap_opt_is_terminator(&ipa_view_map[IPA_OPTS_VIEW]);
-+    fail_unless_sdap_opt_is_terminator(&ipa_override_map[IPA_OPTS_OVERRIDE]);
- 
-     fail_unless_sdap_opt_is_terminator(&service_map[SDAP_OPTS_SERVICES]);
-     fail_unless_sdap_opt_is_terminator(&ad_service_map[SDAP_OPTS_SERVICES]);
--- 
-1.9.3
-
diff --git a/SOURCES/0043-intg_test-Add-integration-test-for-memory-cache.patch b/SOURCES/0043-intg_test-Add-integration-test-for-memory-cache.patch
new file mode 100644
index 0000000..67012ce
--- /dev/null
+++ b/SOURCES/0043-intg_test-Add-integration-test-for-memory-cache.patch
@@ -0,0 +1,384 @@
+From a45f9034e912b6242459a8d576f60ff829508bc3 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Tue, 21 Jul 2015 08:55:14 +0200
+Subject: [PATCH 43/47] intg_test: Add integration test for memory cache
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit a2c10cf31d14bac598f5cd008973375c3f9575a6)
+---
+ src/tests/intg/Makefile.am          |   1 +
+ src/tests/intg/test_memory_cache.py | 347 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 348 insertions(+)
+ create mode 100644 src/tests/intg/test_memory_cache.py
+
+diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am
+index 7488022ed59dd894ba7b6808c5573706412098c7..6819c2f2cea137c7544e94b0b29391611533b20c 100644
+--- a/src/tests/intg/Makefile.am
++++ b/src/tests/intg/Makefile.am
+@@ -8,6 +8,7 @@ dist_noinst_DATA = \
+     ldap_ent.py \
+     ldap_test.py \
+     util.py \
++    test_memory_cache.py \
+     $(NULL)
+ 
+ config.py: config.py.m4
+diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py
+new file mode 100644
+index 0000000000000000000000000000000000000000..5a1f07651b70a5bf1fbacceeae6825ea4341e3b5
+--- /dev/null
++++ b/src/tests/intg/test_memory_cache.py
+@@ -0,0 +1,347 @@
++#
++# LDAP integration test
++#
++# Copyright (c) 2015 Red Hat, Inc.
++# Author: Lukas Slebodnik <lslebodn@redhat.com>
++#
++# 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 ent
++import config
++import signal
++import subprocess
++import time
++import pytest
++import ds_openldap
++import ldap_ent
++import sssd_id
++from util import unindent
++
++LDAP_BASE_DN = "dc=example,dc=com"
++
++
++@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(lambda: 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(lambda: ldap_conn.unbind_s())
++    return ldap_conn
++
++
++def create_ldap_fixture(request, ldap_conn, ent_list):
++    """Add LDAP entries and add teardown for removing them"""
++    for entry in ent_list:
++        ldap_conn.add_s(entry[0], entry[1])
++
++    def teardown():
++        for entry in ent_list:
++            ldap_conn.delete_s(entry[0])
++    request.addfinalizer(teardown)
++
++
++def create_conf_fixture(request, contents):
++    """Generate sssd.conf and add teardown for removing it"""
++    conf = open(config.CONF_PATH, "w")
++    conf.write(contents)
++    conf.close()
++    os.chmod(config.CONF_PATH, stat.S_IRUSR | stat.S_IWUSR)
++    request.addfinalizer(lambda: os.unlink(config.CONF_PATH))
++
++
++def stop_sssd():
++    pid_file = open(config.PIDFILE_PATH, "r")
++    pid = int(pid_file.read())
++    os.kill(pid, signal.SIGTERM)
++    while True:
++        try:
++            os.kill(pid, signal.SIGCONT)
++        except:
++            break
++        time.sleep(1)
++
++
++def create_sssd_fixture(request):
++    """Start sssd and add teardown for stopping it and removing state"""
++    if subprocess.call(["sssd", "-D", "-f"]) != 0:
++        raise Exception("sssd start failed")
++
++    def teardown():
++        try:
++            stop_sssd()
++        except:
++            pass
++        subprocess.call(["sss_cache", "-E"])
++        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)
++    request.addfinalizer(teardown)
++
++
++@pytest.fixture
++def sanity_rfc2307(request, ldap_conn):
++    ent_list = ldap_ent.List(LDAP_BASE_DN)
++    ent_list.add_user("user1", 1001, 2001)
++    ent_list.add_user("user2", 1002, 2002)
++    ent_list.add_user("user3", 1003, 2003)
++    ent_list.add_user("user11", 1011, 2001)
++    ent_list.add_user("user12", 1012, 2002)
++    ent_list.add_user("user13", 1013, 2003)
++    ent_list.add_user("user21", 1021, 2001)
++    ent_list.add_user("user22", 1022, 2002)
++    ent_list.add_user("user23", 1023, 2003)
++
++    ent_list.add_group("group1", 2001, ["user1", "user11", "user21"])
++    ent_list.add_group("group2", 2002, ["user2", "user12", "user22"])
++    ent_list.add_group("group3", 2003, ["user3", "user13", "user23"])
++
++    ent_list.add_group("group0x", 2000, ["user1", "user2", "user3"])
++    ent_list.add_group("group1x", 2010, ["user11", "user12", "user13"])
++    ent_list.add_group("group2x", 2020, ["user21", "user22", "user23"])
++    create_ldap_fixture(request, ldap_conn, ent_list)
++
++    conf = unindent("""\
++        [sssd]
++        config_file_version = 2
++        domains             = LDAP
++        services            = nss
++
++        [nss]
++
++        [domain/LDAP]
++        ldap_auth_disable_tls_never_use_in_production = true
++        ldap_schema         = rfc2307
++        id_provider         = ldap
++        auth_provider       = ldap
++        sudo_provider       = ldap
++        ldap_uri            = {ldap_conn.ds_inst.ldap_url}
++        ldap_search_base    = {ldap_conn.ds_inst.base_dn}
++    """).format(**locals())
++    create_conf_fixture(request, conf)
++    create_sssd_fixture(request)
++    return None
++
++
++def test_getpwnam(ldap_conn, sanity_rfc2307):
++    ent.assert_passwd_by_name(
++        'user1',
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1001,
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user2',
++        dict(name='user2', passwd='*', uid=1002, gid=2002,
++             gecos='1002', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1002,
++        dict(name='user2', passwd='*', uid=1002, gid=2002,
++             gecos='1002', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user3',
++        dict(name='user3', passwd='*', uid=1003, gid=2003,
++             gecos='1003', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1003,
++        dict(name='user3', passwd='*', uid=1003, gid=2003,
++             gecos='1003', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user11',
++        dict(name='user11', passwd='*', uid=1011, gid=2001,
++             gecos='1011', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1011,
++        dict(name='user11', passwd='*', uid=1011, gid=2001,
++             gecos='1011', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user12',
++        dict(name='user12', passwd='*', uid=1012, gid=2002,
++             gecos='1012', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1012,
++        dict(name='user12', passwd='*', uid=1012, gid=2002,
++             gecos='1012', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user13',
++        dict(name='user13', passwd='*', uid=1013, gid=2003,
++             gecos='1013', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1013,
++        dict(name='user13', passwd='*', uid=1013, gid=2003,
++             gecos='1013', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user21',
++        dict(name='user21', passwd='*', uid=1021, gid=2001,
++             gecos='1021', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1021,
++        dict(name='user21', passwd='*', uid=1021, gid=2001,
++             gecos='1021', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user22',
++        dict(name='user22', passwd='*', uid=1022, gid=2002,
++             gecos='1022', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1022,
++        dict(name='user22', passwd='*', uid=1022, gid=2002,
++             gecos='1022', shell='/bin/bash'))
++
++    ent.assert_passwd_by_name(
++        'user23',
++        dict(name='user23', passwd='*', uid=1023, gid=2003,
++             gecos='1023', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1023,
++        dict(name='user23', passwd='*', uid=1023, gid=2003,
++             gecos='1023', shell='/bin/bash'))
++
++
++def test_getpwnam_with_mc(ldap_conn, sanity_rfc2307):
++    test_getpwnam(ldap_conn, sanity_rfc2307)
++    stop_sssd()
++    test_getpwnam(ldap_conn, sanity_rfc2307)
++
++
++def test_getgrnam_simple(ldap_conn, sanity_rfc2307):
++    ent.assert_group_by_name("group1", dict(name="group1", gid=2001))
++    ent.assert_group_by_gid(2001, dict(name="group1", gid=2001))
++
++    ent.assert_group_by_name("group2", dict(name="group2", gid=2002))
++    ent.assert_group_by_gid(2002, dict(name="group2", gid=2002))
++
++    ent.assert_group_by_name("group3", dict(name="group3", gid=2003))
++    ent.assert_group_by_gid(2003, dict(name="group3", gid=2003))
++
++    ent.assert_group_by_name("group0x", dict(name="group0x", gid=2000))
++    ent.assert_group_by_gid(2000, dict(name="group0x", gid=2000))
++
++    ent.assert_group_by_name("group1x", dict(name="group1x", gid=2010))
++    ent.assert_group_by_gid(2010, dict(name="group1x", gid=2010))
++
++    ent.assert_group_by_name("group2x", dict(name="group2x", gid=2020))
++    ent.assert_group_by_gid(2020, dict(name="group2x", gid=2020))
++
++
++def test_getgrnam_simple_with_mc(ldap_conn, sanity_rfc2307):
++    test_getgrnam_simple(ldap_conn, sanity_rfc2307)
++    stop_sssd()
++    test_getgrnam_simple(ldap_conn, sanity_rfc2307)
++
++
++def test_getgrnam_membership(ldap_conn, sanity_rfc2307):
++    ent.assert_group_by_name(
++        "group1",
++        dict(mem=ent.contains_only("user1", "user11", "user21")))
++    ent.assert_group_by_gid(
++        2001,
++        dict(mem=ent.contains_only("user1", "user11", "user21")))
++
++    ent.assert_group_by_name(
++        "group2",
++        dict(mem=ent.contains_only("user2", "user12", "user22")))
++    ent.assert_group_by_gid(
++        2002,
++        dict(mem=ent.contains_only("user2", "user12", "user22")))
++
++    ent.assert_group_by_name(
++        "group3",
++        dict(mem=ent.contains_only("user3", "user13", "user23")))
++    ent.assert_group_by_gid(
++        2003,
++        dict(mem=ent.contains_only("user3", "user13", "user23")))
++
++    ent.assert_group_by_name(
++        "group0x",
++        dict(mem=ent.contains_only("user1", "user2", "user3")))
++    ent.assert_group_by_gid(
++        2000,
++        dict(mem=ent.contains_only("user1", "user2", "user3")))
++
++    ent.assert_group_by_name(
++        "group1x",
++        dict(mem=ent.contains_only("user11", "user12", "user13")))
++    ent.assert_group_by_gid(
++        2010,
++        dict(mem=ent.contains_only("user11", "user12", "user13")))
++
++    ent.assert_group_by_name(
++        "group2x",
++        dict(mem=ent.contains_only("user21", "user22", "user23")))
++    ent.assert_group_by_gid(
++        2020,
++        dict(mem=ent.contains_only("user21", "user22", "user23")))
++
++
++def test_getgrnam_membership_with_mc(ldap_conn, sanity_rfc2307):
++    test_getgrnam_membership(ldap_conn, sanity_rfc2307)
++    stop_sssd()
++    test_getgrnam_membership(ldap_conn, sanity_rfc2307)
++
++
++def assert_user_gids_equal(user, expected_gids):
++    (res, errno, gids) = sssd_id.get_user_gids(user)
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user %s, %d" % (user, errno)
++
++    assert sorted(gids) == sorted(expected_gids), \
++        "result: %s\n expected %s" % (
++            ", ".join(["%s" % s for s in sorted(gids)]),
++            ", ".join(["%s" % s for s in sorted(expected_gids)])
++        )
++
++
++def test_initgroups(ldap_conn, sanity_rfc2307):
++    assert_user_gids_equal('user1', [2000, 2001])
++    assert_user_gids_equal('user2', [2000, 2002])
++    assert_user_gids_equal('user3', [2000, 2003])
++
++    assert_user_gids_equal('user11', [2010, 2001])
++    assert_user_gids_equal('user12', [2010, 2002])
++    assert_user_gids_equal('user13', [2010, 2003])
++
++    assert_user_gids_equal('user21', [2020, 2001])
++    assert_user_gids_equal('user22', [2020, 2002])
++    assert_user_gids_equal('user23', [2020, 2003])
++
++
++def test_initgroups_with_mc(ldap_conn, sanity_rfc2307):
++    test_initgroups(ldap_conn, sanity_rfc2307)
++    stop_sssd()
++    test_initgroups(ldap_conn, sanity_rfc2307)
+-- 
+2.4.3
+
diff --git a/SOURCES/0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch b/SOURCES/0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch
new file mode 100644
index 0000000..ce3e241
--- /dev/null
+++ b/SOURCES/0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch
@@ -0,0 +1,257 @@
+From 5c5a094438ac6c81d99066ec58778cab23e0a939 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Mon, 13 Jul 2015 10:40:06 +0200
+Subject: [PATCH 44/47] NSS: Initgr memory cache should work with fq names
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We need to stored two versions of name to the initgroups memory cache.
+Otherwise it could be stored many times if sssd is configured with
+case_sensitive = false. It would be impossible to invalidate all
+version of names after user login. As a result of this wrong user
+groups could be returned from initgroups memory cache.
+
+Therefore we store raw name provided by glibc function
+and internal sanitized fully qualified name,
+which is unique for particular user.
+
+This patch also increase average space for initgroups
+because there are also stored two quite long names in case of
+fq names.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2712
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit dda0258705de7255e6ec54b7f9adbde83a220996)
+---
+ src/responder/nss/nsssrv_cmd.c        | 30 +++++++++++++++++++++++++-----
+ src/responder/nss/nsssrv_mmap_cache.c | 32 +++++++++++++++++++++-----------
+ src/responder/nss/nsssrv_mmap_cache.h |  1 +
+ src/responder/nss/nsssrv_private.h    |  2 ++
+ src/util/mmap_cache.h                 |  7 ++++---
+ 5 files changed, 53 insertions(+), 19 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
+index 0bfbf0eab115826ebde53b4cfcf6661f2f6328c7..aa64432d51f15ed17212b8c40eebf5c9322bc784 100644
+--- a/src/responder/nss/nsssrv_cmd.c
++++ b/src/responder/nss/nsssrv_cmd.c
+@@ -1354,6 +1354,7 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx)
+     }
+ 
+     rawname = (const char *)body;
++    dctx->mc_name = rawname;
+ 
+     DEBUG(SSSDBG_TRACE_FUNC, "Running command [%d] with input [%s].\n",
+                                dctx->cmdctx->cmd, rawname);
+@@ -3940,6 +3941,13 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx,
+     }
+ 
+     if (changed) {
++        char *fq_name = sss_tc_fqname(tmp_ctx, dom->names, dom, name);
++        if (!fq_name) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Could not create fq name\n");
++            goto done;
++        }
++
+         for (i = 0; i < gnum; i++) {
+             id = groups[i];
+ 
+@@ -3951,7 +3959,7 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx,
+             }
+         }
+ 
+-        to_sized_string(&delete_name, name);
++        to_sized_string(&delete_name, fq_name);
+         ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx,
+                                                &delete_name);
+         if (ret != EOK && ret != ENOENT) {
+@@ -3971,6 +3979,7 @@ static int fill_initgr(struct sss_packet *packet,
+                        struct sss_domain_info *dom,
+                        struct ldb_result *res,
+                        struct nss_ctx *nctx,
++                       const char *mc_name,
+                        const char *name)
+ {
+     uint8_t *body;
+@@ -4059,9 +4068,18 @@ static int fill_initgr(struct sss_packet *packet,
+     }
+ 
+     if (nctx->initgr_mc_ctx) {
+-        to_sized_string(&rawname, name);
++        struct sized_string unique_name;
++        char *fq_name = sss_tc_fqname(packet, dom->names, dom, name);
++        if (!fq_name) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Could not create fq name\n");
++            return ENOMEM;
++        }
++
++        to_sized_string(&rawname, mc_name);
++        to_sized_string(&unique_name, fq_name);
+         ret = sss_mmap_cache_initgr_store(&nctx->initgr_mc_ctx, &rawname,
+-                                          num - skipped, gids);
++                                          &unique_name, num - skipped, gids);
+         if (ret != EOK && ret != ENOMEM) {
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "Failed to store user %s(%s) in mmap cache!\n",
+@@ -4089,7 +4107,7 @@ static int nss_cmd_initgr_send_reply(struct nss_dom_ctx *dctx)
+     }
+ 
+     ret = fill_initgr(cctx->creq->out, dctx->domain, dctx->res, nctx,
+-                      dctx->rawname);
++                      dctx->mc_name, cmdctx->name);
+     if (ret) {
+         return ret;
+     }
+@@ -4137,8 +4155,10 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
+         name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive);
+         if (!name) return ENOMEM;
+ 
+-        name = sss_reverse_replace_space(dctx, name,
++        name = sss_reverse_replace_space(cmdctx, name,
+                                          nctx->rctx->override_space);
++        /* save name so it can be used in initgr reply */
++        cmdctx->name = name;
+         if (name == NULL) {
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "sss_reverse_replace_space failed\n");
+diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
+index ab9e769b1f4d5d17a8c41429afce292298239bc5..62f4c543c628712810b6dfbc669c586c39ca609d 100644
+--- a/src/responder/nss/nsssrv_mmap_cache.c
++++ b/src/responder/nss/nsssrv_mmap_cache.c
+@@ -31,8 +31,8 @@
+ #define SSS_AVG_PASSWD_PAYLOAD (MC_SLOT_SIZE * 4)
+ /* short group name and no gids (private user group */
+ #define SSS_AVG_GROUP_PAYLOAD (MC_SLOT_SIZE * 3)
+-/* average place for 40 supplementary groups */
+-#define SSS_AVG_INITGROUP_PAYLOAD (MC_SLOT_SIZE * 4)
++/* average place for 40 supplementary groups + 2 names */
++#define SSS_AVG_INITGROUP_PAYLOAD (MC_SLOT_SIZE * 5)
+ 
+ #define MC_NEXT_BARRIER(val) ((((val) + 1) & 0x00ffffff) | 0xf0000000)
+ 
+@@ -965,6 +965,7 @@ done:
+ 
+ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                                     struct sized_string *name,
++                                    struct sized_string *unique_name,
+                                     uint32_t num_groups,
+                                     uint8_t *gids_buf)
+ {
+@@ -973,6 +974,7 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+     struct sss_mc_initgr_data *data;
+     size_t data_len;
+     size_t rec_len;
++    size_t pos;
+     int ret;
+ 
+     if (mcc == NULL) {
+@@ -980,20 +982,22 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+         return EINVAL;
+     }
+ 
+-    /* array of gids + name */
+-    data_len = num_groups * sizeof(uint32_t) + name->len;
++    /* array of gids + name + unique_name */
++    data_len = num_groups * sizeof(uint32_t) + name->len + unique_name->len;
+     rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data)
+               + data_len;
+     if (rec_len > mcc->dt_size) {
+         return ENOMEM;
+     }
+ 
+-    ret = sss_mc_get_record(_mcc, rec_len, name, &rec);
++    /* use unique name for searching potential old records */
++    ret = sss_mc_get_record(_mcc, rec_len, unique_name, &rec);
+     if (ret != EOK) {
+         return ret;
+     }
+ 
+     data = (struct sss_mc_initgr_data *)rec->data;
++    pos = 0;
+ 
+     MC_RAISE_BARRIER(rec);
+ 
+@@ -1001,16 +1005,22 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+      * Use the first key twice.
+      */
+     sss_mmap_set_rec_header(mcc, rec, rec_len, mcc->valid_time_slot,
+-                            name->str, name->len, name->str, name->len);
++                            name->str, name->len,
++                            unique_name->str, unique_name->len);
+ 
+     /* initgroups struct */
+-    data->strs_len = name->len;
++    data->strs_len = name->len + unique_name->len;
+     data->data_len = data_len;
+-    data->reserved = MC_INVALID_VAL32;
+     data->num_groups = num_groups;
+-    memcpy(data->gids, gids_buf, num_groups * sizeof(uint32_t));
+-    memcpy(&data->gids[num_groups], name->str, name->len);
+-    data->strs = data->name = MC_PTR_DIFF(&data->gids[num_groups], data);
++    memcpy((char *)data->gids + pos, gids_buf, num_groups * sizeof(uint32_t));
++    pos += num_groups * sizeof(uint32_t);
++
++    memcpy((char *)data->gids + pos, unique_name->str, unique_name->len);
++    data->strs = data->unique_name = MC_PTR_DIFF((char *)data->gids + pos, data);
++    pos += unique_name->len;
++
++    memcpy((char *)data->gids + pos, name->str, name->len);
++    data->name = MC_PTR_DIFF((char *)data->gids + pos, data);
+ 
+     MC_LOWER_BARRIER(rec);
+ 
+diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h
+index b09e4a6f8efa364ae7a6407bab9d8a2a2143c812..b84fbc8edef69db96c17a48a4862d63942297c66 100644
+--- a/src/responder/nss/nsssrv_mmap_cache.h
++++ b/src/responder/nss/nsssrv_mmap_cache.h
+@@ -53,6 +53,7 @@ errno_t sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc,
+ 
+ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                                     struct sized_string *name,
++                                    struct sized_string *unique_name,
+                                     uint32_t num_groups,
+                                     uint8_t *gids_buf);
+ 
+diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h
+index e9f00b114975ef760aaaac45e6e91f6e40c52b9a..e5a2486f1fb9a8de39ec90f802f596b2c2f6af7f 100644
+--- a/src/responder/nss/nsssrv_private.h
++++ b/src/responder/nss/nsssrv_private.h
+@@ -79,6 +79,8 @@ struct nss_dom_ctx {
+ 
+     /* Service-specific */
+     const char *protocol;
++
++    const char *mc_name;
+ };
+ 
+ struct setent_step_ctx {
+diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
+index b5917b3c0973276e43e9fe160cec7528b1224f8f..22c1ae62d1ff0c816c23bd8b26140990d692134c 100644
+--- a/src/util/mmap_cache.h
++++ b/src/util/mmap_cache.h
+@@ -138,14 +138,15 @@ struct sss_mc_grp_data {
+ };
+ 
+ struct sss_mc_initgr_data {
+-    rel_ptr_t name;         /* ptr to name string, rel. to struct base addr */
++    rel_ptr_t unique_name;  /* ptr to unique name string, rel. to struct base addr */
++    rel_ptr_t name;         /* ptr to raw name string, rel. to struct base addr */
+     rel_ptr_t strs;         /* ptr to concatenation of all strings */
+-    uint32_t reserved;
+     uint32_t strs_len;      /* length of strs */
+     uint32_t data_len;      /* all initgroups data len */
+     uint32_t num_groups;    /* number of groups */
+     uint32_t gids[0];       /* array of all groups
+-                             * string with name is stored after gids */
++                             * string with name and unique_name is stored
++                             * after gids */
+ };
+ 
+ #pragma pack()
+-- 
+2.4.3
+
diff --git a/SOURCES/0044-RESPONDERS-refactor-create_pipe_fd.patch b/SOURCES/0044-RESPONDERS-refactor-create_pipe_fd.patch
deleted file mode 100644
index 28f0ad7..0000000
--- a/SOURCES/0044-RESPONDERS-refactor-create_pipe_fd.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From efcfaeed63cff84f547c5ae9e5fd8ee02d0bae21 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Thu, 23 Oct 2014 15:05:05 +0100
-Subject: [PATCH 44/46] RESPONDERS: refactor create_pipe_fd()
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2470
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit f3b9a5b3cf62124bdb5fc11ae2fe6a89ff921539)
----
- src/responder/common/responder.h        |  2 +-
- src/responder/common/responder_common.c | 21 ++++++++++++---------
- 2 files changed, 13 insertions(+), 10 deletions(-)
-
-diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
-index 8837e11425be36c67da038287de48c069ae335cd..cd2b3232c53e919c7d47170ccd1016a8604c9742 100644
---- a/src/responder/common/responder.h
-+++ b/src/responder/common/responder.h
-@@ -178,7 +178,7 @@ responder_get_domain(struct resp_ctx *rctx, const char *domain);
- errno_t responder_get_domain_by_id(struct resp_ctx *rctx, const char *id,
-                                    struct sss_domain_info **_ret_dom);
- 
--int create_pipe_fd(const char *sock_name, int *fd, mode_t umaskval);
-+int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval);
- 
- /* responder_cmd.c */
- int sss_cmd_empty_packet(struct sss_packet *packet);
-diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
-index 85aa04335b72c38fb7a128f04315e3c4189c5d56..9a13c95d63d93df96ffceb51f969eb562c3a6b08 100644
---- a/src/responder/common/responder_common.c
-+++ b/src/responder/common/responder_common.c
-@@ -584,24 +584,25 @@ static int sss_dp_init(struct resp_ctx *rctx,
-     return EOK;
- }
- 
--int create_pipe_fd(const char *sock_name, int *fd, mode_t umaskval)
-+int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval)
- {
-     struct sockaddr_un addr;
-     errno_t ret;
-+    int fd;
- 
--    *fd = socket(AF_UNIX, SOCK_STREAM, 0);
--    if (*fd == -1) {
-+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
-+    if (fd == -1) {
-         return EIO;
-     }
- 
-     umask(umaskval);
- 
--    ret = set_nonblocking(*fd);
-+    ret = set_nonblocking(fd);
-     if (ret != EOK) {
-         goto done;
-     }
- 
--    ret = set_close_on_exec(*fd);
-+    ret = set_close_on_exec(fd);
-     if (ret != EOK) {
-         goto done;
-     }
-@@ -619,13 +620,13 @@ int create_pipe_fd(const char *sock_name, int *fd, mode_t umaskval)
-               "Cannot remove old socket (errno=%d), bind might fail!\n", ret);
-     }
- 
--    if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-+    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-         DEBUG(SSSDBG_FATAL_FAILURE,
-               "Unable to bind on socket '%s'\n", sock_name);
-         ret = EIO;
-         goto done;
-     }
--    if (listen(*fd, 10) != 0) {
-+    if (listen(fd, 10) == -1) {
-         DEBUG(SSSDBG_FATAL_FAILURE,
-               "Unable to listen on socket '%s'\n", sock_name);
-         ret = EIO;
-@@ -638,8 +639,10 @@ done:
-     /* we want default permissions on created files to be very strict,
-        so set our umask to 0177 */
-     umask(0177);
--    if (ret != EOK) {
--        close(*fd);
-+    if (ret == EOK) {
-+        *_fd = fd;
-+    } else {
-+        close(fd);
-     }
-     return ret;
- }
--- 
-1.9.3
-
diff --git a/SOURCES/0045-RESPONDERS-Don-t-hard-code-umask-value-in-utility-fu.patch b/SOURCES/0045-RESPONDERS-Don-t-hard-code-umask-value-in-utility-fu.patch
deleted file mode 100644
index 706c165..0000000
--- a/SOURCES/0045-RESPONDERS-Don-t-hard-code-umask-value-in-utility-fu.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 39087a3cbdadb2f61aee6f2f81e365f5e0e65fb0 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Fri, 24 Oct 2014 10:06:55 +0100
-Subject: [PATCH 45/46] RESPONDERS: Don't hard-code umask value in utility
- function
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2468
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit cbcb834028794a4c658a85965516113f8c0760c1)
----
- src/responder/common/responder_common.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
-index 9a13c95d63d93df96ffceb51f969eb562c3a6b08..6646fa2587a8299de40eaef35830351136b8149a 100644
---- a/src/responder/common/responder_common.c
-+++ b/src/responder/common/responder_common.c
-@@ -587,6 +587,7 @@ static int sss_dp_init(struct resp_ctx *rctx,
- int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval)
- {
-     struct sockaddr_un addr;
-+    mode_t orig_umaskval;
-     errno_t ret;
-     int fd;
- 
-@@ -595,7 +596,7 @@ int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval)
-         return EIO;
-     }
- 
--    umask(umaskval);
-+    orig_umaskval = umask(umaskval);
- 
-     ret = set_nonblocking(fd);
-     if (ret != EOK) {
-@@ -636,9 +637,8 @@ int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval)
-     ret = EOK;
- 
- done:
--    /* we want default permissions on created files to be very strict,
--       so set our umask to 0177 */
--    umask(0177);
-+    /* restore previous umask value */
-+    umask(orig_umaskval);
-     if (ret == EOK) {
-         *_fd = fd;
-     } else {
--- 
-1.9.3
-
diff --git a/SOURCES/0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch b/SOURCES/0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch
new file mode 100644
index 0000000..af7a5dd
--- /dev/null
+++ b/SOURCES/0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch
@@ -0,0 +1,187 @@
+From b54fa4dacbb9cb225159d21976b637a78e461060 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Fri, 24 Jul 2015 15:13:01 +0200
+Subject: [PATCH 45/47] test_memory_cache: Add test for initgroups mc with fq
+ names
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+(cherry picked from commit cb8c24707275c5bda7310d67e7f46c75d3ac36ea)
+---
+ src/tests/intg/test_memory_cache.py | 140 +++++++++++++++++++++++++++++++++++-
+ 1 file changed, 138 insertions(+), 2 deletions(-)
+
+diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py
+index 5a1f07651b70a5bf1fbacceeae6825ea4341e3b5..12ce3c5054fe76560e31137d88043baf20641d3a 100644
+--- a/src/tests/intg/test_memory_cache.py
++++ b/src/tests/intg/test_memory_cache.py
+@@ -106,8 +106,7 @@ def create_sssd_fixture(request):
+     request.addfinalizer(teardown)
+ 
+ 
+-@pytest.fixture
+-def sanity_rfc2307(request, ldap_conn):
++def load_data_to_ldap(request, ldap_conn):
+     ent_list = ldap_ent.List(LDAP_BASE_DN)
+     ent_list.add_user("user1", 1001, 2001)
+     ent_list.add_user("user2", 1002, 2002)
+@@ -128,6 +127,64 @@ def sanity_rfc2307(request, ldap_conn):
+     ent_list.add_group("group2x", 2020, ["user21", "user22", "user23"])
+     create_ldap_fixture(request, ldap_conn, ent_list)
+ 
++
++@pytest.fixture
++def sanity_rfc2307(request, ldap_conn):
++    load_data_to_ldap(request, ldap_conn)
++
++    conf = unindent("""\
++        [sssd]
++        config_file_version = 2
++        domains             = LDAP
++        services            = nss
++
++        [nss]
++
++        [domain/LDAP]
++        ldap_auth_disable_tls_never_use_in_production = true
++        ldap_schema         = rfc2307
++        id_provider         = ldap
++        auth_provider       = ldap
++        sudo_provider       = ldap
++        ldap_uri            = {ldap_conn.ds_inst.ldap_url}
++        ldap_search_base    = {ldap_conn.ds_inst.base_dn}
++    """).format(**locals())
++    create_conf_fixture(request, conf)
++    create_sssd_fixture(request)
++    return None
++
++
++@pytest.fixture
++def fqname_rfc2307(request, ldap_conn):
++    load_data_to_ldap(request, ldap_conn)
++
++    conf = unindent("""\
++        [sssd]
++        config_file_version = 2
++        domains             = LDAP
++        services            = nss
++
++        [nss]
++
++        [domain/LDAP]
++        ldap_auth_disable_tls_never_use_in_production = true
++        ldap_schema         = rfc2307
++        id_provider         = ldap
++        auth_provider       = ldap
++        sudo_provider       = ldap
++        ldap_uri            = {ldap_conn.ds_inst.ldap_url}
++        ldap_search_base    = {ldap_conn.ds_inst.base_dn}
++        use_fully_qualified_names = true
++    """).format(**locals())
++    create_conf_fixture(request, conf)
++    create_sssd_fixture(request)
++    return None
++
++
++@pytest.fixture
++def fqname_case_insensitive_rfc2307(request, ldap_conn):
++    load_data_to_ldap(request, ldap_conn)
++
+     conf = unindent("""\
+         [sssd]
+         config_file_version = 2
+@@ -144,6 +201,8 @@ def sanity_rfc2307(request, ldap_conn):
+         sudo_provider       = ldap
+         ldap_uri            = {ldap_conn.ds_inst.ldap_url}
+         ldap_search_base    = {ldap_conn.ds_inst.base_dn}
++        use_fully_qualified_names = true
++        case_sensitive = false
+     """).format(**locals())
+     create_conf_fixture(request, conf)
+     create_sssd_fixture(request)
+@@ -345,3 +404,80 @@ def test_initgroups_with_mc(ldap_conn, sanity_rfc2307):
+     test_initgroups(ldap_conn, sanity_rfc2307)
+     stop_sssd()
+     test_initgroups(ldap_conn, sanity_rfc2307)
++
++
++def test_initgroups_fqname_with_mc(ldap_conn, fqname_rfc2307):
++    assert_user_gids_equal('user1@LDAP', [2000, 2001])
++    stop_sssd()
++    assert_user_gids_equal('user1@LDAP', [2000, 2001])
++
++
++def assert_initgroups_equal(user, primary_gid, expected_gids):
++    (res, errno, gids) = sssd_id.call_sssd_initgroups(user, primary_gid)
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user %s, %d" % (user, errno)
++
++    assert sorted(gids) == sorted(expected_gids), \
++        "result: %s\n expected %s" % (
++            ", ".join(["%s" % s for s in sorted(gids)]),
++            ", ".join(["%s" % s for s in sorted(expected_gids)])
++        )
++
++
++def assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last,
++                                  primary_gid, expected_gids):
++
++    assert_initgroups_equal(user1_case1, primary_gid, expected_gids)
++    assert_initgroups_equal(user1_case2, primary_gid, expected_gids)
++    assert_initgroups_equal(user1_case_last, primary_gid, expected_gids)
++    stop_sssd()
++
++    user = user1_case1
++    (res, errno, gids) = sssd_id.call_sssd_initgroups(user, primary_gid)
++    assert res == sssd_id.NssReturnCode.UNAVAIL, \
++        "Initgroups for user shoudl fail user %s, %d" % (user, res)
++
++    user = user1_case2
++    (res, errno, gids) = sssd_id.call_sssd_initgroups(user, primary_gid)
++    assert res == sssd_id.NssReturnCode.UNAVAIL, \
++        "Initgroups for user shoudl fail user %s, %d" % (user, res)
++
++    # Just last invocation of initgroups shoudl PASS
++    # Otherwise, we would not be able to invalidate it
++    assert_initgroups_equal(user1_case_last, primary_gid, expected_gids)
++
++
++def test_initgroups_case_insensitive_with_mc1(ldap_conn,
++                                              fqname_case_insensitive_rfc2307):
++    user1_case1 = 'User1@LDAP'
++    user1_case2 = 'uSer1@LDAP'
++    user1_case_last = 'usEr1@LDAP'
++    primary_gid = 2001
++    expected_gids = [2000, 2001]
++
++    assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last,
++                                  primary_gid, expected_gids)
++
++
++def test_initgroups_case_insensitive_with_mc2(ldap_conn,
++                                              fqname_case_insensitive_rfc2307):
++    user1_case1 = 'usEr1@LDAP'
++    user1_case2 = 'User1@LDAP'
++    user1_case_last = 'uSer1@LDAP'
++    primary_gid = 2001
++    expected_gids = [2000, 2001]
++
++    assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last,
++                                  primary_gid, expected_gids)
++
++
++def test_initgroups_case_insensitive_with_mc3(ldap_conn,
++                                              fqname_case_insensitive_rfc2307):
++    user1_case1 = 'uSer1@LDAP'
++    user1_case2 = 'usEr1@LDAP'
++    user1_case_last = 'User1@LDAP'
++    primary_gid = 2001
++    expected_gids = [2000, 2001]
++
++    assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last,
++                                  primary_gid, expected_gids)
+-- 
+2.4.3
+
diff --git a/SOURCES/0046-RESPONDERS-Set-default-value-for-umask.patch b/SOURCES/0046-RESPONDERS-Set-default-value-for-umask.patch
deleted file mode 100644
index fdb94a3..0000000
--- a/SOURCES/0046-RESPONDERS-Set-default-value-for-umask.patch
+++ /dev/null
@@ -1,129 +0,0 @@
-From 7c30e5abf469134253d5bdec29cda7b47c41ca3e Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Fri, 24 Oct 2014 12:42:50 +0100
-Subject: [PATCH 46/46] RESPONDERS: Set default value for umask
-
-Resolves: https://fedorahosted.org/sssd/ticket/2468
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 458f5245dd5130d12666cce6faf8ef1ec7f80169)
----
- src/responder/autofs/autofssrv.c | 2 ++
- src/responder/common/responder.h | 4 ++++
- src/responder/ifp/ifpsrv.c       | 2 ++
- src/responder/nss/nsssrv.c       | 2 ++
- src/responder/pac/pacsrv.c       | 2 ++
- src/responder/pam/pamsrv.c       | 2 ++
- src/responder/ssh/sshsrv.c       | 2 ++
- src/responder/sudo/sudosrv.c     | 2 ++
- 8 files changed, 18 insertions(+)
-
-diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c
-index 44474ee0858d92fb5965de07773e3ad1e020ebfd..91f529135e9bd74a5cf89edadd98fb2368630b5e 100644
---- a/src/responder/autofs/autofssrv.c
-+++ b/src/responder/autofs/autofssrv.c
-@@ -220,6 +220,8 @@ int main(int argc, const char *argv[])
-     /* Set debug level to invalid value so we can decide if -d 0 was used. */
-     debug_level = SSSDBG_INVALID;
- 
-+    umask(DFL_RSP_UMASK);
-+
-     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-     while((opt = poptGetNextOpt(pc)) != -1) {
-         switch(opt) {
-diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
-index cd2b3232c53e919c7d47170ccd1016a8604c9742..e3c0f226775d279ea8c0f300cc2de54d2f7f9b72 100644
---- a/src/responder/common/responder.h
-+++ b/src/responder/common/responder.h
-@@ -38,6 +38,10 @@
- 
- extern hash_table_t *dp_requests;
- 
-+/* we want default permissions on created files to be very strict,
-+ * so set our umask to 0177 */
-+#define DFL_RSP_UMASK 0177
-+
- /* if there is a provider other than the special local */
- #define NEED_CHECK_PROVIDER(provider) \
-     (provider != NULL && strcmp(provider, "local") != 0)
-diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
-index eddeec9812bdd650bfbfb78ede91bf3704113504..367438c71b77576f1c7c3054061db684fd134c20 100644
---- a/src/responder/ifp/ifpsrv.c
-+++ b/src/responder/ifp/ifpsrv.c
-@@ -454,6 +454,8 @@ int main(int argc, const char *argv[])
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-     debug_level = SSSDBG_INVALID;
- 
-+    umask(DFL_RSP_UMASK);
-+
-     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-     while((opt = poptGetNextOpt(pc)) != -1) {
-         switch(opt) {
-diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
-index cfb146464d224cdb8b517d23a86421da7eaccd1f..1bbeaa1534ee3e0db72dda13ff9d01ef7fba6adf 100644
---- a/src/responder/nss/nsssrv.c
-+++ b/src/responder/nss/nsssrv.c
-@@ -550,6 +550,8 @@ int main(int argc, const char *argv[])
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-     debug_level = SSSDBG_INVALID;
- 
-+    umask(DFL_RSP_UMASK);
-+
-     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-     while((opt = poptGetNextOpt(pc)) != -1) {
-         switch(opt) {
-diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c
-index 3eb21c8fff85343249494bcc06d97cda4b738034..859ae86a54daf268c73ab97b0a1f67967d7e714f 100644
---- a/src/responder/pac/pacsrv.c
-+++ b/src/responder/pac/pacsrv.c
-@@ -229,6 +229,8 @@ int main(int argc, const char *argv[])
-     /* Set debug level to invalid value so we can decide if -d 0 was used. */
-     debug_level = SSSDBG_INVALID;
- 
-+    umask(DFL_RSP_UMASK);
-+
-     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-     while((opt = poptGetNextOpt(pc)) != -1) {
-         switch(opt) {
-diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
-index c7e3c20b2731efb9393bc820ab09486c48e0a9ea..886136b420b6184a86ce6e0d9ac84dd3dea9a94b 100644
---- a/src/responder/pam/pamsrv.c
-+++ b/src/responder/pam/pamsrv.c
-@@ -332,6 +332,8 @@ int main(int argc, const char *argv[])
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-     debug_level = SSSDBG_INVALID;
- 
-+    umask(DFL_RSP_UMASK);
-+
-     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-     while((opt = poptGetNextOpt(pc)) != -1) {
-         switch(opt) {
-diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
-index b1969b49de8579f0136c3afa78eb16d68c81ee4e..1bcf4e21a89e4e7b7697e9d90ab239cbf9d231e9 100644
---- a/src/responder/ssh/sshsrv.c
-+++ b/src/responder/ssh/sshsrv.c
-@@ -197,6 +197,8 @@ int main(int argc, const char *argv[])
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-     debug_level = SSSDBG_INVALID;
- 
-+    umask(DFL_RSP_UMASK);
-+
-     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-     while((opt = poptGetNextOpt(pc)) != -1) {
-         switch(opt) {
-diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
-index a25f98ecabaa952a7cd87c54cd302903cb563faf..e480c7a43d453cffcd6ca07e41402c1cf6eef91c 100644
---- a/src/responder/sudo/sudosrv.c
-+++ b/src/responder/sudo/sudosrv.c
-@@ -177,6 +177,8 @@ int main(int argc, const char *argv[])
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-     debug_level = SSSDBG_INVALID;
- 
-+    umask(DFL_RSP_UMASK);
-+
-     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-     while((opt = poptGetNextOpt(pc)) != -1) {
-         switch(opt) {
--- 
-1.9.3
-
diff --git a/SOURCES/0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch b/SOURCES/0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch
new file mode 100644
index 0000000..e258a2f
--- /dev/null
+++ b/SOURCES/0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch
@@ -0,0 +1,120 @@
+From 2d4478e11739f3934d788a9c47c8d990e41afd67 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Tue, 4 Aug 2015 11:59:35 +0200
+Subject: [PATCH 46/47] test_memory_cache: Test mmap cache after initgroups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+---
+ src/tests/intg/test_memory_cache.py | 89 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 89 insertions(+)
+
+diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py
+index 12ce3c5054fe76560e31137d88043baf20641d3a..c809a4b6daacfd04834db46d21bfb97ad025ada6 100644
+--- a/src/tests/intg/test_memory_cache.py
++++ b/src/tests/intg/test_memory_cache.py
+@@ -19,6 +19,7 @@
+ import os
+ import stat
+ import ent
++import grp
+ import config
+ import signal
+ import subprocess
+@@ -481,3 +482,91 @@ def test_initgroups_case_insensitive_with_mc3(ldap_conn,
+ 
+     assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last,
+                                   primary_gid, expected_gids)
++
++
++def run_simple_test_with_initgroups():
++    ent.assert_passwd_by_name(
++        'user1',
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1001,
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++
++    ent.assert_group_by_name(
++        "group1",
++        dict(mem=ent.contains_only("user1", "user11", "user21")))
++    ent.assert_group_by_gid(
++        2001,
++        dict(mem=ent.contains_only("user1", "user11", "user21")))
++
++    # unrelated group to user1
++    ent.assert_group_by_name(
++        "group2",
++        dict(mem=ent.contains_only("user2", "user12", "user22")))
++    ent.assert_group_by_gid(
++        2002,
++        dict(mem=ent.contains_only("user2", "user12", "user22")))
++
++    assert_initgroups_equal("user1", 2001, [2000, 2001])
++
++
++def test_invalidation_of_gids_after_initgroups(ldap_conn, sanity_rfc2307):
++
++    # the sssd cache was empty and not all user's group were
++    # resolved with getgr{nm,gid}. Therefore there is a change in
++    # group membership => user groups should be invalidated
++    run_simple_test_with_initgroups()
++    assert_initgroups_equal("user1", 2001, [2000, 2001])
++
++    stop_sssd()
++
++    ent.assert_passwd_by_name(
++        'user1',
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1001,
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++
++    # unrelated group to user1 must be returned
++    ent.assert_group_by_name(
++        "group2",
++        dict(mem=ent.contains_only("user2", "user12", "user22")))
++    ent.assert_group_by_gid(
++        2002,
++        dict(mem=ent.contains_only("user2", "user12", "user22")))
++
++    assert_initgroups_equal("user1", 2001, [2000, 2001])
++
++    # user groups must be invalidated
++    for group in ["group1", "group0x"]:
++        with pytest.raises(KeyError):
++            grp.getgrnam(group)
++
++    for gid in [2000, 2001]:
++        with pytest.raises(KeyError):
++            grp.getgrgid(gid)
++
++
++def test_initgroups_without_change_in_membership(ldap_conn, sanity_rfc2307):
++
++    # the sssd cache was empty and not all user's group were
++    # resolved with getgr{nm,gid}. Therefore there is a change in
++    # group membership => user groups should be invalidated
++    run_simple_test_with_initgroups()
++
++    # invalidate cache
++    subprocess.call(["sss_cache", "-E"])
++
++    # all users and groups will be just refreshed from LDAP
++    # but there will not be a change in group membership
++    # user groups should not be invlaidated
++    run_simple_test_with_initgroups()
++
++    stop_sssd()
++
++    # everything should be in memory cache
++    run_simple_test_with_initgroups()
+-- 
+2.4.3
+
diff --git a/SOURCES/0047-nss-group-enumeration-fix.patch b/SOURCES/0047-nss-group-enumeration-fix.patch
deleted file mode 100644
index ce1f157..0000000
--- a/SOURCES/0047-nss-group-enumeration-fix.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From d8d007c12bac73df4931722c4f7b57fa778bf105 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 24 Oct 2014 11:28:54 +0200
-Subject: [PATCH 47/48] nss: group enumeration fix
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The view/override patches introduced and issue with group enumeration
-where all groups are returned with the same name. This patch should fix
-it.
-
-Fixes: https://fedorahosted.org/sssd/ticket/2475
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
-(cherry picked from commit 4b2b722319f11c81c06f488f3962a6b6280f4b9f)
----
- src/responder/nss/nsssrv_cmd.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index 4ec99c153b25db26d482eec8da6ca52487967abc..9fca644be164e682f787bda61ea39afa8b703874 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -2669,6 +2669,9 @@ static int fill_grent(struct sss_packet *packet,
-         rsize = 0;
- 
-         /* find group name/gid */
-+
-+        /* start with an empty name for each iteration */
-+        orig_name = NULL;
-         if (DOM_HAS_VIEWS(dom)) {
-             orig_name = ldb_msg_find_attr_as_string(msg,
-                                                     OVERRIDE_PREFIX SYSDB_NAME,
--- 
-1.9.3
-
diff --git a/SOURCES/0047-test_memory_cache-Test-invalidation-with-sss_cache.patch b/SOURCES/0047-test_memory_cache-Test-invalidation-with-sss_cache.patch
new file mode 100644
index 0000000..9706b50
--- /dev/null
+++ b/SOURCES/0047-test_memory_cache-Test-invalidation-with-sss_cache.patch
@@ -0,0 +1,207 @@
+From aae797abf3bfcfda124f111d8b4e805e77bee691 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Tue, 4 Aug 2015 12:47:58 +0200
+Subject: [PATCH 47/47] test_memory_cache: Test invalidation with sss_cache
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+---
+ src/tests/intg/test_memory_cache.py | 176 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 176 insertions(+)
+
+diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py
+index c809a4b6daacfd04834db46d21bfb97ad025ada6..1fd577e652d278c35211b55c871797a3dee98b13 100644
+--- a/src/tests/intg/test_memory_cache.py
++++ b/src/tests/intg/test_memory_cache.py
+@@ -20,6 +20,7 @@ import os
+ import stat
+ import ent
+ import grp
++import pwd
+ import config
+ import signal
+ import subprocess
+@@ -570,3 +571,178 @@ def test_initgroups_without_change_in_membership(ldap_conn, sanity_rfc2307):
+ 
+     # everything should be in memory cache
+     run_simple_test_with_initgroups()
++
++
++def assert_mc_records_for_user1():
++    ent.assert_passwd_by_name(
++        'user1',
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++    ent.assert_passwd_by_uid(
++        1001,
++        dict(name='user1', passwd='*', uid=1001, gid=2001,
++             gecos='1001', shell='/bin/bash'))
++
++    ent.assert_group_by_name(
++        "group1",
++        dict(mem=ent.contains_only("user1", "user11", "user21")))
++    ent.assert_group_by_gid(
++        2001,
++        dict(mem=ent.contains_only("user1", "user11", "user21")))
++    ent.assert_group_by_name(
++        "group0x",
++        dict(mem=ent.contains_only("user1", "user2", "user3")))
++    ent.assert_group_by_gid(
++        2000,
++        dict(mem=ent.contains_only("user1", "user2", "user3")))
++
++    assert_initgroups_equal("user1", 2001, [2000, 2001])
++
++
++def assert_missing_mc_records_for_user1():
++    with pytest.raises(KeyError):
++        pwd.getpwnam("user1")
++    with pytest.raises(KeyError):
++        pwd.getpwuid(1001)
++
++    for gid in [2000, 2001]:
++        with pytest.raises(KeyError):
++            grp.getgrgid(gid)
++    for group in ["group0x", "group1"]:
++        with pytest.raises(KeyError):
++            grp.getgrnam(group)
++
++    (res, err, _) = sssd_id.call_sssd_initgroups("user1", 2001)
++    assert res == sssd_id.NssReturnCode.UNAVAIL, \
++        "Initgroups should not find anything after invalidation of mc.\n" \
++        "User %s, errno:%d" % (user, err)
++
++
++def test_invalidate_user_before_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    subprocess.call(["sss_cache", "-u", "user1"])
++    stop_sssd()
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_user_after_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    stop_sssd()
++    subprocess.call(["sss_cache", "-u", "user1"])
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_users_before_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    subprocess.call(["sss_cache", "-U"])
++    stop_sssd()
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_users_after_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    stop_sssd()
++    subprocess.call(["sss_cache", "-U"])
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_group_before_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    subprocess.call(["sss_cache", "-g", "group1"])
++    stop_sssd()
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_group_after_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    stop_sssd()
++    subprocess.call(["sss_cache", "-g", "group1"])
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_groups_before_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    subprocess.call(["sss_cache", "-G"])
++    stop_sssd()
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_groups_after_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    stop_sssd()
++    subprocess.call(["sss_cache", "-G"])
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_everything_before_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    subprocess.call(["sss_cache", "-E"])
++    stop_sssd()
++
++    assert_missing_mc_records_for_user1()
++
++
++def test_invalidate_everything_after_stop(ldap_conn, sanity_rfc2307):
++    # initialize cache with full ID
++    (res, errno, _) = sssd_id.get_user_groups("user1")
++    assert res == sssd_id.NssReturnCode.SUCCESS, \
++        "Could not find groups for user1 %s, %d" % errno
++    assert_mc_records_for_user1()
++
++    stop_sssd()
++    subprocess.call(["sss_cache", "-E"])
++
++    assert_missing_mc_records_for_user1()
+-- 
+2.4.3
+
diff --git a/SOURCES/0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch b/SOURCES/0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch
new file mode 100644
index 0000000..5ffa313
--- /dev/null
+++ b/SOURCES/0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch
@@ -0,0 +1,163 @@
+From 5654903a0be960a2ec5be5bfb77cc3263e11e58c Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Thu, 30 Jul 2015 16:52:42 +0200
+Subject: [PATCH 48/57] krb5 utils: add sss_krb5_realm_has_proxy()
+
+Reviewed-by: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                               |  1 +
+ src/tests/krb5_proxy_check_test_data.conf |  8 +++++
+ src/tests/krb5_utils-tests.c              | 17 +++++++++
+ src/util/sss_krb5.c                       | 57 +++++++++++++++++++++++++++++++
+ src/util/sss_krb5.h                       |  2 ++
+ 5 files changed, 85 insertions(+)
+ create mode 100644 src/tests/krb5_proxy_check_test_data.conf
+
+diff --git a/Makefile.am b/Makefile.am
+index 5345d90d22cd285a5268ac50a6b527645acdb351..8b64317d6dce9a1ee8614916395b9afd9f11f382 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -366,6 +366,7 @@ dist_noinst_SCRIPTS = \
+     src/tests/pysss_murmur-test.py2.sh \
+     src/tests/pysss_murmur-test.py3.sh \
+     src/tests/python-test.py \
++    src/tests/krb5_proxy_check_test_data.conf \
+     $(NULL)
+ 
+ dist_noinst_DATA = \
+diff --git a/src/tests/krb5_proxy_check_test_data.conf b/src/tests/krb5_proxy_check_test_data.conf
+new file mode 100644
+index 0000000000000000000000000000000000000000..eb74dbfa47d643668688d5c789b5962698c3d17c
+--- /dev/null
++++ b/src/tests/krb5_proxy_check_test_data.conf
+@@ -0,0 +1,8 @@
++[realms]
++  REALM = {
++    kdc = hello
++  }
++
++  REALM_PROXY = {
++    kdc = https://hello
++  }
+diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
+index 650ed48592768c214156d5274e654a447be98e36..9a25b09cdc136651a7117327036dd51b8ff23606 100644
+--- a/src/tests/krb5_utils-tests.c
++++ b/src/tests/krb5_utils-tests.c
+@@ -684,6 +684,22 @@ START_TEST(test_parse_krb5_map_user)
+ }
+ END_TEST
+ 
++START_TEST(test_sss_krb5_realm_has_proxy)
++{
++    krb5_error_code kerr;
++    long perr;
++
++    fail_unless(sss_krb5_realm_has_proxy(NULL) == false);
++
++    setenv("KRB5_CONFIG", "/dev/null", 1);
++    fail_unless(sss_krb5_realm_has_proxy("REALM") == false);
++
++    setenv("KRB5_CONFIG", ABS_SRC_DIR"/src/tests/krb5_proxy_check_test_data.conf", 1);
++    fail_unless(sss_krb5_realm_has_proxy("REALM") == false);
++    fail_unless(sss_krb5_realm_has_proxy("REALM_PROXY") == true);
++}
++END_TEST
++
+ Suite *krb5_utils_suite (void)
+ {
+     Suite *s = suite_create ("krb5_utils");
+@@ -723,6 +739,7 @@ Suite *krb5_utils_suite (void)
+     TCase *tc_krb5_helpers = tcase_create("Helper functions");
+     tcase_add_test(tc_krb5_helpers, test_compare_principal_realm);
+     tcase_add_test(tc_krb5_helpers, test_parse_krb5_map_user);
++    tcase_add_test(tc_krb5_helpers, test_sss_krb5_realm_has_proxy);
+     suite_add_tcase(s, tc_krb5_helpers);
+ 
+     return s;
+diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
+index e5c2121da575b174c8b6a9a90835f2c97f807f37..2e128db3c9fcb0dfa88cab1ed799abd714ad8ba6 100644
+--- a/src/util/sss_krb5.c
++++ b/src/util/sss_krb5.c
+@@ -20,6 +20,7 @@
+ #include <stdio.h>
+ #include <errno.h>
+ #include <talloc.h>
++#include <profile.h>
+ 
+ #include "config.h"
+ 
+@@ -1069,3 +1070,59 @@ krb5_error_code sss_krb5_kt_have_content(krb5_context context,
+     return 0;
+ #endif
+ }
++
++#define KDC_PROXY_INDICATOR "https://"
++#define KDC_PROXY_INDICATOR_LEN (sizeof(KDC_PROXY_INDICATOR) - 1)
++
++bool sss_krb5_realm_has_proxy(const char *realm)
++{
++    krb5_context context = NULL;
++    krb5_error_code kerr;
++    struct _profile_t *profile = NULL;
++    const char  *profile_path[4] = {"realms", NULL, "kdc", NULL};
++    char **list = NULL;
++    bool res = false;
++    size_t c;
++
++    if (realm == NULL) {
++        return false;
++    }
++
++    kerr = krb5_init_context(&context);
++    if (kerr != 0) {
++        DEBUG(SSSDBG_OP_FAILURE, "krb5_init_context failed.\n");
++        return false;
++    }
++
++    kerr = krb5_get_profile(context, &profile);
++    if (kerr != 0) {
++        DEBUG(SSSDBG_OP_FAILURE, "krb5_get_profile failed.\n");
++        goto done;
++    }
++
++    profile_path[1] = realm;
++
++    kerr = profile_get_values(profile, profile_path, &list);
++    if (kerr != 0) {
++        DEBUG(SSSDBG_OP_FAILURE, "profile_get_values failed.\n");
++        goto done;
++    }
++
++    for (c = 0; list[c] != NULL; c++) {
++        if (strncasecmp(KDC_PROXY_INDICATOR, list[c],
++                        KDC_PROXY_INDICATOR_LEN) == 0) {
++            DEBUG(SSSDBG_TRACE_ALL,
++                  "Found KDC Proxy indicator [%s] in [%s].\n",
++                  KDC_PROXY_INDICATOR, list[c]);
++            res = true;
++            break;
++        }
++    }
++
++done:
++    profile_free_list(list);
++    profile_release(profile);
++    krb5_free_context(context);
++
++    return res;
++}
+diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
+index 462dbbe0bda8969432c8ac2f062a0123c1f098f0..fdaeb49314764e096448f342a054dc6938f0c248 100644
+--- a/src/util/sss_krb5.h
++++ b/src/util/sss_krb5.h
+@@ -189,4 +189,6 @@ sss_krb5_get_primary(TALLOC_CTX *mem_ctx,
+ 
+ krb5_error_code sss_krb5_kt_have_content(krb5_context context,
+                                          krb5_keytab keytab);
++
++bool sss_krb5_realm_has_proxy(const char *realm);
+ #endif /* __SSS_KRB5_H__ */
+-- 
+2.4.3
+
diff --git a/SOURCES/0048-nss-preserve-service-name-in-getsrv-call.patch b/SOURCES/0048-nss-preserve-service-name-in-getsrv-call.patch
deleted file mode 100644
index 4c0b651..0000000
--- a/SOURCES/0048-nss-preserve-service-name-in-getsrv-call.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From e6c49e90d752fdbdf5d12ac18ccb9f297baaa8f1 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Thu, 23 Oct 2014 20:27:57 +0200
-Subject: [PATCH 48/48] nss: preserve service name in getsrv call
-
-About case_sensitive=preserving and services.
-
-The name of the service can be preserved in
-result of 'getent service'. However we
-should still lowercase the protocol and
-service aliases because they serve as keys
-in some queries to sysdb. The lowercasing is done
-by the provider already. If we did not do that,
-we would lose case insesnsitivity.
-
-With this patch the responder preserves the
-case of service name and protocol, to match
-the case that is stored in the sysdb (however
-the protocol is already lowercased by provider,
-so it was done only for consistent use of the
-case_sensitive=preserve option in the responders
-and only the case of name is the same as in
-ldap).
-
-Fixes:
-https://fedorahosted.org/sssd/ticket/2460
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit c4e278c2637547640d28bda007c9c38a17956fcc)
----
- src/responder/nss/nsssrv_services.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_services.c b/src/responder/nss/nsssrv_services.c
-index 7741768021cc4a669bd3eda286cd1f25876a55f6..f6abc445c82d268dafb4d1e1fa7336ad01912f9e 100644
---- a/src/responder/nss/nsssrv_services.c
-+++ b/src/responder/nss/nsssrv_services.c
-@@ -642,7 +642,7 @@ fill_service(struct sss_packet *packet,
- 
-         /* Get the service name */
-         orig_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
--        tmpstr = sss_get_cased_name(tmp_ctx, orig_name, dom->case_sensitive);
-+        tmpstr = sss_get_cased_name(tmp_ctx, orig_name, dom->case_preserve);
-         if (tmpstr == NULL) {
-             DEBUG(SSSDBG_CRIT_FAILURE,
-                   "Could not identify service name, skipping\n");
-@@ -677,7 +677,7 @@ fill_service(struct sss_packet *packet,
-             orig_proto = (const char *)el->values[0].data;
-         }
- 
--        tmpstr = sss_get_cased_name(tmp_ctx, orig_proto, dom->case_sensitive);
-+        tmpstr = sss_get_cased_name(tmp_ctx, orig_proto, dom->case_preserve);
-         if (tmpstr == NULL) {
-             DEBUG(SSSDBG_CRIT_FAILURE,
-                   "sss_get_cased_name failed, skipping\n");
--- 
-1.9.3
-
diff --git a/SOURCES/0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch b/SOURCES/0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch
new file mode 100644
index 0000000..86016bd
--- /dev/null
+++ b/SOURCES/0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch
@@ -0,0 +1,35 @@
+From 61faa93f3ad91afdeba09d4e248d596875aa6d5a Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 31 Jul 2015 11:05:48 +0200
+Subject: [PATCH 49/57] krb5: do not create kdcinfo file if proxy configuration
+ exists
+
+Resolves https://fedorahosted.org/sssd/ticket/2652
+
+Reviewed-by: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/providers/krb5/krb5_common.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
+index 81d4048b63dba98706bbef1936df7f10f79e1ae5..be6c9e3540ad470307f4edb168f0ff6cc581632f 100644
+--- a/src/providers/krb5/krb5_common.c
++++ b/src/providers/krb5/krb5_common.c
+@@ -428,6 +428,13 @@ errno_t write_krb5info_file(const char *realm, const char *server,
+         return EINVAL;
+     }
+ 
++    if (sss_krb5_realm_has_proxy(realm)) {
++        DEBUG(SSSDBG_CONF_SETTINGS,
++              "KDC Proxy available for realm [%s], no kdcinfo file created.\n",
++              realm);
++        return EOK;
++    }
++
+     if (strcmp(service, SSS_KRB5KDC_FO_SRV) == 0) {
+         name_tmpl = KDCINFO_TMPL;
+     } else if (strcmp(service, SSS_KRB5KPASSWD_FO_SRV) == 0) {
+-- 
+2.4.3
+
diff --git a/SOURCES/0049-sdap_print_server-use-getpeername-to-get-server-addr.patch b/SOURCES/0049-sdap_print_server-use-getpeername-to-get-server-addr.patch
deleted file mode 100644
index 3b644fa..0000000
--- a/SOURCES/0049-sdap_print_server-use-getpeername-to-get-server-addr.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 29ee270deee5f3c0b049f612245a734e626b6b33 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 24 Oct 2014 18:27:07 +0200
-Subject: [PATCH 49/64] sdap_print_server: use getpeername() to get server
- address
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ldap/sdap_async.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
-index 560d13789b88b7b7f3a09558fa2d2844f0fa036e..a6954620bd0f27b5f2d2e45563af9d1440d9cf7c 100644
---- a/src/providers/ldap/sdap_async.c
-+++ b/src/providers/ldap/sdap_async.c
-@@ -1107,7 +1107,7 @@ static void sdap_print_server(struct sdap_handle *sh)
-         return;
-     }
- 
--    ret = getsockname(fd, (struct sockaddr *) &ss, &ss_len);
-+    ret = getpeername(fd, (struct sockaddr *) &ss, &ss_len);
-     if (ret == -1) {
-         DEBUG(SSSDBG_MINOR_FAILURE, "getsockname failed\n");
-         return;
--- 
-1.9.3
-
diff --git a/SOURCES/0050-IPA-Don-t-fail-the-request-when-BE-doesn-t-find-the-.patch b/SOURCES/0050-IPA-Don-t-fail-the-request-when-BE-doesn-t-find-the-.patch
deleted file mode 100644
index 0cd0508..0000000
--- a/SOURCES/0050-IPA-Don-t-fail-the-request-when-BE-doesn-t-find-the-.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From 07ca52cf9c0727c42880ed03b4ffb3e6c5f7b97d Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 29 Oct 2014 20:30:20 +0100
-Subject: [PATCH 50/64] IPA: Don't fail the request when BE doesn't find the
- object
-
-The IPA subdomain code treated ENOENT as a fatal error, which resulted
-in a loud error message and the whole request being aborted. This patch
-ignores ENOENT.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/providers/ipa/ipa_subdomains_id.c | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index b67006ce6e0b4bf9c794016c1dfc923ac6da3624..0a1c4c17eed37b2eb12a8c758e49fc17c3b642b5 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -942,7 +942,7 @@ static errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
-         goto done;
-     }
- 
--    if (ret != EOK) {
-+    if (ret != EOK && ret != ENOENT) {
-         DEBUG(SSSDBG_OP_FAILURE,
-               "Failed to make request to our cache: [%d]: [%s]\n",
-                ret, sss_strerror(ret));
-@@ -951,8 +951,6 @@ static errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
- 
-     *_msg = msg;
- 
--    ret = EOK;
--
- done:
-     return ret;
- }
-@@ -978,7 +976,11 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
- 
-     ret = get_object_from_cache(state, state->user_dom, state->ar,
-                                 &state->obj_msg);
--    if (ret != EOK) {
-+    if (ret == ENOENT) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n");
-+        tevent_req_done(req);
-+        return;
-+    } else if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
-         goto fail;
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch b/SOURCES/0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch
new file mode 100644
index 0000000..dc90393
--- /dev/null
+++ b/SOURCES/0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch
@@ -0,0 +1,37 @@
+From 860b0e5e2f34a270a5e40912fd07efbe093a29f8 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Fri, 31 Jul 2015 11:06:54 +0200
+Subject: [PATCH 50/57] krb5: assume online state if KDC proxy is configured
+
+If a KDC proxy is configured a request in the KRB5 provider will assume
+online state even if the backend is offline without changing the state
+of the backend.
+
+Resolves https://fedorahosted.org/sssd/ticket/2700
+
+Reviewed-by: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/providers/krb5/krb5_auth.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index d1bf4025b052d82413d1f370a36b0b99720d6f05..da8309d0504a6815902513693343a3500f454557 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -754,6 +754,12 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
+         kr->is_offline = be_is_offline(state->be_ctx);
+     }
+ 
++    if (kr->is_offline
++            && sss_krb5_realm_has_proxy(dp_opt_get_cstring(kr->krb5_ctx->opts,
++                                        KRB5_REALM))) {
++        kr->is_offline = false;
++    }
++
+     subreq = handle_child_send(state, state->ev, kr);
+     if (subreq == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "handle_child_send failed.\n");
+-- 
+2.4.3
+
diff --git a/SOURCES/0051-memberof-check-for-empty-arrays-to-avoid-segfaults.patch b/SOURCES/0051-memberof-check-for-empty-arrays-to-avoid-segfaults.patch
deleted file mode 100644
index a7eb747..0000000
--- a/SOURCES/0051-memberof-check-for-empty-arrays-to-avoid-segfaults.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 61b6c497901004e34f1bdf6d3c04c2943720a500 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 29 Oct 2014 15:20:12 +0100
-Subject: [PATCH 51/64] memberof: check for empty arrays to avoid segfaults
-
-The arrays with members to add or delete may be empty, i.e. have 0
-entries. In this case further processing should be skipped to avoid
-segfaults later on.
-
-Fixes (hopefully) https://fedorahosted.org/sssd/ticket/2430
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/ldb_modules/memberof.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
-index ceeba0e474dfbe53f7133df996e3bad454fdac9e..995c382a8ee36bfc010f2761010db1fb48343d5d 100644
---- a/src/ldb_modules/memberof.c
-+++ b/src/ldb_modules/memberof.c
-@@ -3654,7 +3654,7 @@ static int mbof_mod_add(struct mbof_mod_ctx *mod_ctx,
-         }
-     }
- 
--    if (ael != NULL) {
-+    if (ael != NULL && ael->num > 0) {
-         /* Add itself to the list of the parents to also get the memberuid */
-         parents->dns = talloc_realloc(parents, parents->dns,
-                                     struct ldb_dn *, parents->num + 1);
-@@ -3724,7 +3724,7 @@ static int mbof_mod_delete(struct mbof_mod_ctx *mod_ctx,
-     }
- 
-     /* prepare del sets */
--    if (del != NULL) {
-+    if (del != NULL && del->num > 0) {
-         for (i = 0; i < del->num; i++) {
-             ret = mbof_append_delop(first, del->dns[i]);
-             if (ret != LDB_SUCCESS) {
--- 
-1.9.3
-
diff --git a/SOURCES/0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch b/SOURCES/0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch
new file mode 100644
index 0000000..78a6176
--- /dev/null
+++ b/SOURCES/0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch
@@ -0,0 +1,88 @@
+From a09b3853da819cc773c0098100f9dd96af08f933 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Mon, 10 Aug 2015 10:16:58 +0200
+Subject: [PATCH 51/57] sss_cache: Wait a while for invalidation of mc by nss
+ responder
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The sss_cache cannot invalidate memory cache directly
+because the nss responder owns file locks to memory caches.
+Therefore sss_cache just "tell" nss responder to invalidate
+memory cache.
+
+However there might be short interval between calling
+the utility sss_cache and stopping sssd. So nss responder
+needn't be so fast and therefore memory cache needn't be invalidated.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2748
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+---
+ src/tools/tools_mc_util.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/src/tools/tools_mc_util.c b/src/tools/tools_mc_util.c
+index c1b5c616d0e6d50147ecd81308aaa1e69304af92..65c461093e859d4da73761782a3a694bf5bda8fb 100644
+--- a/src/tools/tools_mc_util.c
++++ b/src/tools/tools_mc_util.c
+@@ -21,6 +21,7 @@
+ 
+ #include <talloc.h>
+ #include <fcntl.h>
++#include <sys/stat.h>
+ 
+ #include "db/sysdb.h"
+ #include "util/util.h"
+@@ -161,6 +162,33 @@ static int clear_fastcache(bool *sssd_nss_is_off)
+     return EOK;
+ }
+ 
++static errno_t wait_till_nss_responder_invalidate_cache(void)
++{
++    struct stat stat_buf = { 0 };
++    const time_t max_wait = 1000000; /* 1 second */
++    const time_t step_time = 5000; /* 5 miliseconds */
++    const size_t steps_count = max_wait / step_time;
++    int ret;
++
++    for (size_t i = 0; i < steps_count; ++i) {
++        ret = stat(SSS_NSS_MCACHE_DIR "/" CLEAR_MC_FLAG, &stat_buf);
++        if (ret == -1) {
++            ret = errno;
++            if (ret == ENOENT) {
++                /* nss responder has already invalidated memory caches */
++                return EOK;
++            }
++
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "stat failed: %s (%d)\n", sss_strerror(ret), ret);
++        }
++
++        usleep(step_time);
++    }
++
++    return EAGAIN;
++}
++
+ errno_t sss_memcache_clear_all(void)
+ {
+     errno_t ret;
+@@ -196,6 +224,12 @@ errno_t sss_memcache_clear_all(void)
+                   "Failed to send SIGHUP to monitor.\n");
+             return EIO;
+         }
++
++        ret = wait_till_nss_responder_invalidate_cache();
++        if (ret != EOK) {
++            ERROR("The fast memory caches was not invalidated by NSS "
++                  "responder.\n");
++        }
+     }
+ 
+     return EOK;
+-- 
+2.4.3
+
diff --git a/SOURCES/0052-CONFDB-Detect-fix-misconf-opt-refresh_expired_interv.patch b/SOURCES/0052-CONFDB-Detect-fix-misconf-opt-refresh_expired_interv.patch
deleted file mode 100644
index bcbefd1..0000000
--- a/SOURCES/0052-CONFDB-Detect-fix-misconf-opt-refresh_expired_interv.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 8d0b8a15a56f1fd12655e838cc17004d12dff8dd Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Thu, 30 Oct 2014 16:50:27 +0000
-Subject: [PATCH 52/64] CONFDB: Detect&fix misconf opt refresh_expired_interval
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Related to:
-https://fedorahosted.org/sssd/ticket/2102
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
----
- src/confdb/confdb.c | 15 +++++++++++++++
- 1 file changed, 15 insertions(+)
-
-diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
-index 8443fe5539e1fd7b6deee6dca7cc689868933757..c55a945a4d3ab4b4070963889a8421d7c78bcad7 100644
---- a/src/confdb/confdb.c
-+++ b/src/confdb/confdb.c
-@@ -1058,6 +1058,21 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
-         goto done;
-     }
- 
-+    /* detect and fix misconfiguration */
-+    if (domain->refresh_expired_interval > entry_cache_timeout) {
-+        DEBUG(SSSDBG_CONF_SETTINGS,
-+              "refresh_expired_interval (%d) cannot be greater then "
-+              "entry_cache_timeout (%u)\n",
-+              domain->refresh_expired_interval, entry_cache_timeout);
-+
-+        domain->refresh_expired_interval = 0.75 * entry_cache_timeout;
-+
-+        DEBUG(SSSDBG_CONF_SETTINGS,
-+              "refresh_expired_interval is being set to recommended value "
-+              "entry_cache_timeout * 0.75 (%u).\n",
-+              domain->refresh_expired_interval);
-+    }
-+
-     /* Set the PAM warning time, if specified. If not specified, pass on
-      * the "not set" value of "-1" which means "use provider default". The
-      * value 0 means "always display the warning if server sends one" */
--- 
-1.9.3
-
diff --git a/SOURCES/0052-IFP-use-default-limit-if-provided-is-0.patch b/SOURCES/0052-IFP-use-default-limit-if-provided-is-0.patch
new file mode 100644
index 0000000..3c45595
--- /dev/null
+++ b/SOURCES/0052-IFP-use-default-limit-if-provided-is-0.patch
@@ -0,0 +1,31 @@
+From 504604a3e90c8bad36d1919e13e0bf37f094ee2a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Thu, 13 Aug 2015 12:46:59 +0200
+Subject: [PATCH 52/57] IFP: use default limit if provided is 0
+
+Returning zero values doesn't make any sense, so we may use it as
+"use sssd configuration instead".
+
+Reviewed-by: Petr Cech <pcech@redhat.com>
+---
+ src/responder/ifp/ifpsrv_util.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c
+index 3b02fd06f5227e4ffc3d40ffb20fed981c5028a7..904c4f62ec5653a534877fd6870832128720b694 100644
+--- a/src/responder/ifp/ifpsrv_util.c
++++ b/src/responder/ifp/ifpsrv_util.c
+@@ -274,7 +274,9 @@ ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr)
+ 
+ static uint32_t ifp_list_limit(struct ifp_ctx *ctx, uint32_t limit)
+ {
+-    if (ctx->wildcard_limit) {
++    if (limit == 0) {
++        return ctx->wildcard_limit;
++    } else if (ctx->wildcard_limit) {
+         return MIN(ctx->wildcard_limit, limit);
+     } else {
+         return limit;
+-- 
+2.4.3
+
diff --git a/SOURCES/0053-NSS-disable-midpoint-refresh-for-netgroups.patch b/SOURCES/0053-NSS-disable-midpoint-refresh-for-netgroups.patch
deleted file mode 100644
index 21fc8ca..0000000
--- a/SOURCES/0053-NSS-disable-midpoint-refresh-for-netgroups.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From ff71a9ad628ec66e36ccc7c9c49c1306fbe0d25c Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Thu, 30 Oct 2014 17:02:45 +0000
-Subject: [PATCH 53/64] NSS: disable midpoint refresh for netgroups
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Disable midpoint refresh for netgroups if periodical refresh of expired
-netgroups is enabled (refresh_expired_interval)
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2102
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
----
- src/responder/nss/nsssrv_cmd.c | 57 +++++++++++++++++++++++++++++++-----------
- 1 file changed, 43 insertions(+), 14 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index 9fca644be164e682f787bda61ea39afa8b703874..4ac5eb91eab80291e60afad2bf9c65edfbc21e7d 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -559,6 +559,25 @@ static int nss_cmd_getpw_send_reply(struct nss_dom_ctx *dctx, bool filter)
-     return EOK;
- }
- 
-+/* Currently only refreshing expired netgroups is supported. */
-+static bool
-+is_refreshed_on_bg(int req_type,
-+                   enum sss_dp_acct_type refresh_expired_interval)
-+{
-+    if (refresh_expired_interval == 0) {
-+        return false;
-+    }
-+
-+    switch (req_type) {
-+    case SSS_DP_NETGR:
-+        return true;
-+    default:
-+        return false;
-+    }
-+
-+    return false;
-+}
-+
- static void nsssrv_dp_send_acct_req_done(struct tevent_req *req);
- 
- /* FIXME: do not check res->count, but get in a msgs and check in parent */
-@@ -585,25 +604,35 @@ errno_t check_cache(struct nss_dom_ctx *dctx,
-     if ((req_type == SSS_DP_USER || req_type == SSS_DP_NETGR) &&
-             (res->count > 1)) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
--              "getpwXXX call returned more than one result!"
--                  " DB Corrupted?\n");
-+              "getpwXXX call returned more than one result! DB Corrupted?\n");
-         return ENOENT;
-     }
- 
--    /* if we have any reply let's check cache validity */
-+    /* if we have any reply let's check cache validity, but ignore netgroups
-+     * if refresh_expired_interval is set (which implies that another method
-+     * is used to refresh netgroups)
-+     */
-     if (res->count > 0) {
--        if (req_type == SSS_DP_INITGROUPS) {
--            cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
--                                                      SYSDB_INITGR_EXPIRE, 1);
--        }
--        if (cacheExpire == 0) {
--            cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
--                                                      SYSDB_CACHE_EXPIRE, 0);
--        }
-+        if (is_refreshed_on_bg(req_type,
-+                               dctx->domain->refresh_expired_interval)) {
-+            ret = EOK;
-+        } else {
-+            if (req_type == SSS_DP_INITGROUPS) {
-+                cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
-+                                                          SYSDB_INITGR_EXPIRE,
-+                                                          1);
-+            }
-+            if (cacheExpire == 0) {
-+                cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0],
-+                                                          SYSDB_CACHE_EXPIRE,
-+                                                          0);
-+            }
- 
--        /* if we have any reply let's check cache validity */
--        ret = sss_cmd_check_cache(res->msgs[0], nctx->cache_refresh_percent,
--                                  cacheExpire);
-+            /* if we have any reply let's check cache validity */
-+            ret = sss_cmd_check_cache(res->msgs[0],
-+                                      nctx->cache_refresh_percent,
-+                                      cacheExpire);
-+        }
-         if (ret == EOK) {
-             DEBUG(SSSDBG_TRACE_FUNC, "Cached entry is valid, returning..\n");
-             return EOK;
--- 
-1.9.3
-
diff --git a/SOURCES/0053-sudo-use-higher-value-wins-when-ordering-rules.patch b/SOURCES/0053-sudo-use-higher-value-wins-when-ordering-rules.patch
new file mode 100644
index 0000000..b28cdf5
--- /dev/null
+++ b/SOURCES/0053-sudo-use-higher-value-wins-when-ordering-rules.patch
@@ -0,0 +1,217 @@
+From 7c3fefc9c840fd0eb46048d7d2be0a0b8347f713 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 29 Jul 2015 14:51:30 +0200
+Subject: [PATCH 53/57] sudo: use "higher value wins" when ordering rules
+
+This commit changes the default ordering logic (lower value wins) to
+a correct one that is used by native ldap support. It also adds a new
+option sudo_inverse_order to switch to the original SSSD (incorrect)
+behaviour if needed.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2682
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/confdb/confdb.h                        |  2 ++
+ src/config/SSSDConfig/__init__.py.in       |  1 +
+ src/config/etc/sssd.api.conf               |  1 +
+ src/responder/sudo/sudosrv.c               | 11 ++++++
+ src/responder/sudo/sudosrv_get_sudorules.c | 54 ++++++++++++++++++++++++------
+ src/responder/sudo/sudosrv_private.h       |  1 +
+ 6 files changed, 60 insertions(+), 10 deletions(-)
+
+diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
+index df454337ab4d89c5857e73ee0e5392c2b4bba8b4..9aa264899e789f2491b9873daf44bb55aff1c95d 100644
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -124,6 +124,8 @@
+ #define CONFDB_DEFAULT_SUDO_CACHE_TIMEOUT 180
+ #define CONFDB_SUDO_TIMED "sudo_timed"
+ #define CONFDB_DEFAULT_SUDO_TIMED false
++#define CONFDB_SUDO_INVERSE_ORDER "sudo_inverse_order"
++#define CONFDB_DEFAULT_SUDO_INVERSE_ORDER false
+ 
+ /* autofs */
+ #define CONFDB_AUTOFS_CONF_ENTRY "config/autofs"
+diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
+index 7d361026c09ce8fd8d6a69f6bb3f3817bc3d68ba..fed2682f121103cefa27e689b29ce29b7d28f968 100644
+--- a/src/config/SSSDConfig/__init__.py.in
++++ b/src/config/SSSDConfig/__init__.py.in
+@@ -92,6 +92,7 @@ option_strings = {
+ 
+     # [sudo]
+     'sudo_timed' : _('Whether to evaluate the time-based attributes in sudo rules'),
++    'sudo_inverse_order' : _('If true, SSSD will switch back to lower-wins ordering logic'),
+ 
+     # [autofs]
+     'autofs_negative_timeout' : _('Negative cache timeout length (seconds)'),
+diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
+index cf6ce63012176d49f757afbc8a343b24aef869e8..2e5b02e3e30c13f805e172eab481f7501f57bb05 100644
+--- a/src/config/etc/sssd.api.conf
++++ b/src/config/etc/sssd.api.conf
+@@ -63,6 +63,7 @@ pam_account_expired_message = str, None, false
+ [sudo]
+ # sudo service
+ sudo_timed = bool, None, false
++sudo_inverse_order = bool, None, false
+ 
+ [autofs]
+ # autofs service
+diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c
+index 2499586eb11e49f8652ce62e53c88d7a2e54fb32..ff5d92e7005db9f6e883c78cf1a6218e9a150e0a 100644
+--- a/src/responder/sudo/sudosrv.c
++++ b/src/responder/sudo/sudosrv.c
+@@ -167,6 +167,17 @@ int sudo_process_init(TALLOC_CTX *mem_ctx,
+         goto fail;
+     }
+ 
++    /* Get sudo_inverse_order option */
++    ret = confdb_get_bool(sudo_ctx->rctx->cdb,
++                          CONFDB_SUDO_CONF_ENTRY, CONFDB_SUDO_INVERSE_ORDER,
++                          CONFDB_DEFAULT_SUDO_INVERSE_ORDER,
++                          &sudo_ctx->inverse_order);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) [%s]\n",
++              ret, strerror(ret));
++        goto fail;
++    }
++
+     ret = schedule_get_domains_task(rctx, rctx->ev, rctx, NULL);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "schedule_get_domains_tasks failed.\n");
+diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
+index 34d63bd74741c3cab5168fd0b0108cb05528d218..a0b09e69b71f963c353c9c6331c0708cc364924c 100644
+--- a/src/responder/sudo/sudosrv_get_sudorules.c
++++ b/src/responder/sudo/sudosrv_get_sudorules.c
+@@ -325,6 +325,7 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
+                                                  const char *username,
+                                                  uid_t uid,
+                                                  char **groupnames,
++                                                 bool inverse_order,
+                                                  struct sysdb_attrs ***_rules,
+                                                  uint32_t *_count);
+ 
+@@ -386,6 +387,7 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx)
+                                             cmd_ctx->domain, attrs, flags,
+                                             cmd_ctx->orig_username,
+                                             cmd_ctx->uid, groupnames,
++                                            cmd_ctx->sudo_ctx->inverse_order,
+                                             &expired_rules, &expired_rules_num);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve expired sudo rules "
+@@ -597,6 +599,7 @@ static errno_t sudosrv_get_sudorules_from_cache(TALLOC_CTX *mem_ctx,
+                                             cmd_ctx->domain, attrs, flags,
+                                             cmd_ctx->orig_username,
+                                             cmd_ctx->uid, groupnames,
++                                            cmd_ctx->sudo_ctx->inverse_order,
+                                             &rules, &num_rules);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_CRIT_FAILURE,
+@@ -622,7 +625,7 @@ done:
+ }
+ 
+ static errno_t
+-sort_sudo_rules(struct sysdb_attrs **rules, size_t count);
++sort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool higher_wins);
+ 
+ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
+                                                  struct sss_domain_info *domain,
+@@ -631,6 +634,7 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
+                                                  const char *username,
+                                                  uid_t uid,
+                                                  char **groupnames,
++                                                 bool inverse_order,
+                                                  struct sysdb_attrs ***_rules,
+                                                  uint32_t *_count)
+ {
+@@ -680,7 +684,7 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx,
+         goto done;
+     }
+ 
+-    ret = sort_sudo_rules(rules, count);
++    ret = sort_sudo_rules(rules, count, inverse_order);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE,
+               "Could not sort rules by sudoOrder\n");
+@@ -697,7 +701,7 @@ done:
+ }
+ 
+ static int
+-sudo_order_cmp_fn(const void *a, const void *b)
++sudo_order_cmp(const void *a, const void *b, bool lower_wins)
+ {
+     struct sysdb_attrs *r1, *r2;
+     uint32_t o1, o2;
+@@ -730,19 +734,49 @@ sudo_order_cmp_fn(const void *a, const void *b)
+         return 0;
+     }
+ 
+-    if (o1 > o2) {
+-        return 1;
+-    } else if (o1 < o2) {
+-        return -1;
++    if (lower_wins) {
++        /* The lowest value takes priority. Original wrong SSSD behaviour. */
++        if (o1 > o2) {
++            return 1;
++        } else if (o1 < o2) {
++            return -1;
++        }
++    } else {
++        /* The higher value takes priority. Standard LDAP behaviour. */
++        if (o1 < o2) {
++            return 1;
++        } else if (o1 > o2) {
++            return -1;
++        }
+     }
+ 
+     return 0;
+ }
+ 
++static int
++sudo_order_low_cmp_fn(const void *a, const void *b)
++{
++    return sudo_order_cmp(a, b, true);
++}
++
++static int
++sudo_order_high_cmp_fn(const void *a, const void *b)
++{
++    return sudo_order_cmp(a, b, false);
++}
++
+ static errno_t
+-sort_sudo_rules(struct sysdb_attrs **rules, size_t count)
++sort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool lower_wins)
+ {
+-    qsort(rules, count, sizeof(struct sysdb_attrs *),
+-          sudo_order_cmp_fn);
++    if (lower_wins) {
++        DEBUG(SSSDBG_TRACE_FUNC, "Sorting rules with lower-wins logic\n");
++        qsort(rules, count, sizeof(struct sysdb_attrs *),
++              sudo_order_low_cmp_fn);
++    } else {
++        DEBUG(SSSDBG_TRACE_FUNC, "Sorting rules with higher-wins logic\n");
++        qsort(rules, count, sizeof(struct sysdb_attrs *),
++              sudo_order_high_cmp_fn);
++    }
++
+     return EOK;
+ }
+diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
+index 3c53755f9e8ec56f3dea52021d14b50f715a54e7..186ed2cb5114d00524b41b801b5f32bac50f7153 100644
+--- a/src/responder/sudo/sudosrv_private.h
++++ b/src/responder/sudo/sudosrv_private.h
+@@ -50,6 +50,7 @@ struct sudo_ctx {
+      * options
+      */
+     bool timed;
++    bool inverse_order;
+ };
+ 
+ struct sudo_cmd_ctx {
+-- 
+2.4.3
+
diff --git a/SOURCES/0054-IPA-use-ipaUserGroup-object-class-for-groups.patch b/SOURCES/0054-IPA-use-ipaUserGroup-object-class-for-groups.patch
deleted file mode 100644
index a6d6b35..0000000
--- a/SOURCES/0054-IPA-use-ipaUserGroup-object-class-for-groups.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 65679aaa24942edb448077eb172361b45b4f2a71 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
-Date: Fri, 31 Oct 2014 14:26:30 +0100
-Subject: [PATCH 54/64] IPA: use ipaUserGroup object class for groups
-
-dfb34c6c82ed5014599bf70de6791e6d79106fc2 changed object class
-of IPA groups from posixGroups to more general groupOfNames.
-However, this object class is used also for roles, permissions and
-privileges which caused SSSD to consider those objects to be groups as
-well during initgroups.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2471
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_opts.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index 4785e0164bf6d9efb574a8703b573f4e8086cab6..0e0eed49cd397fe88ce7bf41579c066088947d04 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -205,7 +205,7 @@ struct sdap_attr_map ipa_user_map[] = {
- };
- 
- struct sdap_attr_map ipa_group_map[] = {
--    { "ldap_group_object_class", "groupOfNames", SYSDB_GROUP_CLASS, NULL },
-+    { "ldap_group_object_class", "ipaUserGroup", SYSDB_GROUP_CLASS, NULL },
-     { "ldap_group_object_class_alt", "posixGroup", SYSDB_GROUP_CLASS, NULL },
-     { "ldap_group_name", "cn", SYSDB_NAME, NULL },
-     { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL },
--- 
-1.9.3
-
diff --git a/SOURCES/0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch b/SOURCES/0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch
new file mode 100644
index 0000000..6c277fd
--- /dev/null
+++ b/SOURCES/0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch
@@ -0,0 +1,47 @@
+From 1d42e3c3a4f9536ee3539683a810c95314fd1c5d Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 10 Aug 2015 12:40:30 +0200
+Subject: [PATCH 54/57] LDAP: use ldb_binary_encode when printing attribute
+ values
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/providers/ldap/sdap_utils.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c
+index f5ce8ee54f60a6c4c4cdbd5e50b20d973c175e83..9da46ea70bf80e7f4d12fdfc7d1c97e99de8d000 100644
+--- a/src/providers/ldap/sdap_utils.c
++++ b/src/providers/ldap/sdap_utils.c
+@@ -35,6 +35,7 @@ sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs,
+     const char *objname = name ?: "object";
+     const char *desc = attr_desc ?: attr_name;
+     unsigned int num_values, i;
++    char *printable;
+ 
+     ret = sysdb_attrs_get_el(ldap_attrs, attr_name, &el);
+     if (ret) {
+@@ -50,8 +51,16 @@ sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs,
+     } else {
+         num_values = multivalued ? el->num_values : 1;
+         for (i = 0; i < num_values; i++) {
++            printable = ldb_binary_encode(ldap_attrs, el->values[i]);
++            if (printable == NULL) {
++                DEBUG(SSSDBG_MINOR_FAILURE, "ldb_binary_encode failed..\n");
++                continue;
++            }
++
+             DEBUG(SSSDBG_TRACE_INTERNAL, "Adding %s [%s] to attributes "
+-                  "of [%s].\n", desc, el->values[i].data, objname);
++                  "of [%s].\n", desc, printable, objname);
++
++            talloc_zfree(printable);
+ 
+             ret = sysdb_attrs_add_mem(attrs, attr_name, el->values[i].data,
+                                       el->values[i].length);
+-- 
+2.4.3
+
diff --git a/SOURCES/0055-Add-add_strings_lists-utility-function.patch b/SOURCES/0055-Add-add_strings_lists-utility-function.patch
deleted file mode 100644
index 981804b..0000000
--- a/SOURCES/0055-Add-add_strings_lists-utility-function.patch
+++ /dev/null
@@ -1,246 +0,0 @@
-From a624616892da3dc0ee39659e24cbd5a40ae98e9e Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 27 Oct 2014 16:53:44 +0100
-Subject: [PATCH 55/64] Add add_strings_lists() utility function
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/tests/cmocka/test_utils.c | 111 ++++++++++++++++++++++++++++++++++++++++++
- src/util/util.c               |  65 +++++++++++++++++++++++++
- src/util/util.h               |  18 +++++++
- 3 files changed, 194 insertions(+)
-
-diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
-index 9d6cbf35f7c2e33c57b3a539b409848c22cf263e..d9781377be70a0d58b0fd1fff2145483dbeb199c 100644
---- a/src/tests/cmocka/test_utils.c
-+++ b/src/tests/cmocka/test_utils.c
-@@ -875,6 +875,114 @@ void test_expand_homedir_template(void **state)
-     talloc_free(tmp_ctx);
- }
- 
-+void setup_add_strings_lists(void **state)
-+{
-+    assert_true(leak_check_setup());
-+
-+    check_leaks_push(global_talloc_context);
-+}
-+
-+void teardown_add_strings_lists(void **state)
-+{
-+    assert_true(check_leaks_pop(global_talloc_context) == true);
-+    assert_true(leak_check_teardown());
-+}
-+
-+void test_add_strings_lists(void **state)
-+{
-+    const char *l1[] = {"a", "b", "c", NULL};
-+    const char *l2[] = {"1", "2", "3", NULL};
-+    char **res;
-+    int ret;
-+    size_t c;
-+    size_t d;
-+
-+    ret = add_strings_lists(global_talloc_context, NULL, NULL, true, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    assert_null(res[0]);
-+    talloc_free(res);
-+
-+    ret = add_strings_lists(global_talloc_context, NULL, NULL, false, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    assert_null(res[0]);
-+    talloc_free(res);
-+
-+    ret = add_strings_lists(global_talloc_context, l1, NULL, false, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    for (c = 0; l1[c] != NULL; c++) {
-+        /* 'copy_strings' is 'false', pointers must be equal */
-+        assert_int_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
-+    }
-+    assert_null(res[c]);
-+    talloc_free(res);
-+
-+    ret = add_strings_lists(global_talloc_context, l1, NULL, true, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    for (c = 0; l1[c] != NULL; c++) {
-+        /* 'copy_strings' is 'true', pointers must be different, but strings
-+         * must be equal */
-+        assert_int_not_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
-+        assert_string_equal(l1[c], res[c]);
-+    }
-+    assert_null(res[c]);
-+    talloc_free(res);
-+
-+    ret = add_strings_lists(global_talloc_context, NULL, l1, false, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    for (c = 0; l1[c] != NULL; c++) {
-+        /* 'copy_strings' is 'false', pointers must be equal */
-+        assert_int_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
-+    }
-+    assert_null(res[c]);
-+    talloc_free(res);
-+
-+    ret = add_strings_lists(global_talloc_context, NULL, l1, true, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    for (c = 0; l1[c] != NULL; c++) {
-+        /* 'copy_strings' is 'true', pointers must be different, but strings
-+         * must be equal */
-+        assert_int_not_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
-+        assert_string_equal(l1[c], res[c]);
-+    }
-+    assert_null(res[c]);
-+    talloc_free(res);
-+
-+    ret = add_strings_lists(global_talloc_context, l1, l2, false, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    for (c = 0; l1[c] != NULL; c++) {
-+        /* 'copy_strings' is 'false', pointers must be equal */
-+        assert_int_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
-+    }
-+    for (d = 0; l2[d] != NULL; d++) {
-+        assert_int_equal(memcmp(&l2[d], &res[c+d], sizeof(char *)), 0);
-+    }
-+    assert_null(res[c+d]);
-+    talloc_free(res);
-+
-+    ret = add_strings_lists(global_talloc_context, l1, l2, true, &res);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(res);
-+    for (c = 0; l1[c] != NULL; c++) {
-+        /* 'copy_strings' is 'true', pointers must be different, but strings
-+         * must be equal */
-+        assert_int_not_equal(memcmp(&l1[c], &res[c], sizeof(char *)), 0);
-+        assert_string_equal(l1[c], res[c]);
-+    }
-+    for (d = 0; l2[d] != NULL; d++) {
-+        assert_int_not_equal(memcmp(&l2[d], &res[c+d], sizeof(char *)), 0);
-+        assert_string_equal(l2[d], res[c+d]);
-+    }
-+    assert_null(res[c+d]);
-+    talloc_free(res);
-+}
-+
- int main(int argc, const char *argv[])
- {
-     poptContext pc;
-@@ -919,6 +1027,9 @@ int main(int argc, const char *argv[])
-         unit_test(test_textual_public_key),
-         unit_test(test_replace_whitespaces),
-         unit_test(test_reverse_replace_whitespaces),
-+        unit_test_setup_teardown(test_add_strings_lists,
-+                                 setup_add_strings_lists,
-+                                 teardown_add_strings_lists),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-diff --git a/src/util/util.c b/src/util/util.c
-index d78d37d975e6591bca6ac3f2fa36b5b9f4659a29..2acb8604ac0c2bc7b83ee578c7bbead9a7fd44b3 100644
---- a/src/util/util.c
-+++ b/src/util/util.c
-@@ -815,3 +815,68 @@ const char * const * get_known_services(void)
- 
-     return svc;
- }
-+
-+errno_t add_strings_lists(TALLOC_CTX *mem_ctx, const char **l1, const char **l2,
-+                          bool copy_strings, char ***_new_list)
-+{
-+    size_t c;
-+    size_t l1_count = 0;
-+    size_t l2_count = 0;
-+    size_t new_count = 0;
-+    char **new;
-+    int ret;
-+
-+    if (l1 != NULL) {
-+        for (l1_count = 0; l1[l1_count] != NULL; l1_count++);
-+    }
-+
-+    if (l2 != NULL) {
-+        for (l2_count = 0; l2[l2_count] != NULL; l2_count++);
-+    }
-+
-+    new_count = l1_count + l2_count;
-+
-+    new = talloc_array(mem_ctx, char *, new_count + 1);
-+    if (new == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-+        return ENOMEM;
-+    }
-+    new [new_count] = NULL;
-+
-+    if (copy_strings) {
-+        for(c = 0; c < l1_count; c++) {
-+            new[c] = talloc_strdup(new, l1[c]);
-+            if (new[c] == NULL) {
-+                DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+                ret = ENOMEM;
-+                goto done;
-+            }
-+        }
-+        for(c = 0; c < l2_count; c++) {
-+            new[l1_count + c] = talloc_strdup(new, l2[c]);
-+            if (new[l1_count + c] == NULL) {
-+                DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+                ret = ENOMEM;
-+                goto done;
-+            }
-+        }
-+    } else {
-+        if (l1 != NULL) {
-+            memcpy(new, l1, sizeof(char *) * l1_count);
-+        }
-+
-+        if (l2 != NULL) {
-+            memcpy(&new[l1_count], l2, sizeof(char *) * l2_count);
-+        }
-+    }
-+
-+    *_new_list = new;
-+    ret = EOK;
-+
-+done:
-+    if (ret != EOK) {
-+        talloc_free(new);
-+    }
-+
-+    return ret;
-+}
-diff --git a/src/util/util.h b/src/util/util.h
-index 69074c93c1640a1e4a7e590b7f9feb6cc04804a4..ffc8a87eafa4c4b8271d195c7d27fd10f5aa3568 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -426,6 +426,24 @@ errno_t sss_hash_create_ex(TALLOC_CTX *mem_ctx,
-                            hash_delete_callback *delete_callback,
-                            void *delete_private_data);
- 
-+/**
-+ * @brief Add two list of strings
-+ *
-+ * Create a new NULL-termintated list of strings by adding two lists together.
-+ *
-+ * @param[in] mem_ctx      Talloc memory context for the new list.
-+ * @param[in] l1           First NULL-termintated list of strings.
-+ * @param[in] l2           Second NULL-termintated list of strings.
-+ * @param[in] copy_strings If set to 'true' the list items will be copied
-+ *                         otherwise only the pointers to the items are
-+ *                         copied.
-+ * @param[out] new_list    New NULL-terminated list of strings. Must be freed
-+ *                         with talloc_free() by the caller. If copy_strings
-+ *                         is 'true' the new elements will be freed as well.
-+ */
-+errno_t add_strings_lists(TALLOC_CTX *mem_ctx, const char **l1, const char **l2,
-+                          bool copy_strings, char ***_new_list);
-+
- /* Copy a NULL-terminated string list
-  * Returns NULL on out of memory error or invalid input
-  */
--- 
-1.9.3
-
diff --git a/SOURCES/0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch b/SOURCES/0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch
new file mode 100644
index 0000000..14f2998
--- /dev/null
+++ b/SOURCES/0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch
@@ -0,0 +1,50 @@
+From 4d400c7374e0ca6af7c8f990e27c1e58a18ad7d4 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 10 Aug 2015 12:40:39 +0200
+Subject: [PATCH 55/57] IPA: Change the default of ldap_user_certificate to
+ userCertificate;binary
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is safe from ldb point of view, because ldb gurantees the data is
+NULL-terminated. We must be careful before we save the data, though.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2742
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/man/sssd-ldap.5.xml      | 2 +-
+ src/providers/ipa/ipa_opts.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
+index 9ac175f8d4a8aa01ca2434b800ebae1be88575f5..49e84560f825b1bff255c1ad131487ba3243300d 100644
+--- a/src/man/sssd-ldap.5.xml
++++ b/src/man/sssd-ldap.5.xml
+@@ -821,7 +821,7 @@
+                             certificate of the user.
+                         </para>
+                         <para>
+-                            Default: no set in the general case, userCertificate
++                            Default: no set in the general case, userCertificate;binary
+                             for IPA
+                         </para>
+                     </listitem>
+diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
+index 9576228d1bf3424c8867bda058b59c3ca6b2216b..f6c40dddbb58cd8af1079a351137422083e26cfe 100644
+--- a/src/providers/ipa/ipa_opts.h
++++ b/src/providers/ipa/ipa_opts.h
+@@ -204,7 +204,7 @@ struct sdap_attr_map ipa_user_map[] = {
+     { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
+     { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL },
+     { "ldap_user_auth_type", "ipaUserAuthType", SYSDB_AUTH_TYPE, NULL },
+-    { "ldap_user_certificate", "userCertificate", SYSDB_USER_CERT, NULL },
++    { "ldap_user_certificate", "userCertificate;binary", SYSDB_USER_CERT, NULL },
+     SDAP_ATTR_MAP_TERMINATOR
+ };
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0056-IPA-inherit-ldap_user_extra_attrs-to-AD-subdomains.patch b/SOURCES/0056-IPA-inherit-ldap_user_extra_attrs-to-AD-subdomains.patch
deleted file mode 100644
index 585391e..0000000
--- a/SOURCES/0056-IPA-inherit-ldap_user_extra_attrs-to-AD-subdomains.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From 4d1985342d51075f0842c2221c034bbf7cc3d5af Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 24 Oct 2014 15:41:04 +0200
-Subject: [PATCH 56/64] IPA: inherit ldap_user_extra_attrs to AD subdomains
-
-Currently the component of the IPA provider which reads the AD user and
-group attributes in ipa-server-mode uses  default settings for the LDAP
-related attributes. As a result even if ldap_user_extra_attrs is defined
-in sssd.conf no extra attributes are read from AD.
-
-With the patch the value if ldap_user_extra_attrs is inherited to the AD
-subdomains to allow them to read extra attributes as well.
-
-Related to https://fedorahosted.org/sssd/ticket/2464
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_subdomains.c | 31 +++++++++++++++++++++++++++++++
- 1 file changed, 31 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index c61c1c666908ec23f8a92e5568222e55ec47be0a..9281aab1b028ebcaee8044b2768c6918efa4e514 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -109,6 +109,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
-     char *ad_domain;
-     struct sdap_domain *sdom;
-     errno_t ret;
-+    const char *extra_attrs;
- 
-     ad_options = ad_create_default_options(id_ctx, id_ctx->server_mode->realm,
-                                            id_ctx->server_mode->hostname);
-@@ -135,6 +136,36 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
-         return ret;
-     }
- 
-+    extra_attrs = dp_opt_get_string(id_ctx->sdap_id_ctx->opts->basic,
-+                            SDAP_USER_EXTRA_ATTRS);
-+    if (extra_attrs != NULL) {
-+        DEBUG(SSSDBG_TRACE_ALL,
-+              "Setting extra attrs for subdomain [%s] to [%s].\n", ad_domain,
-+                                                                   extra_attrs);
-+
-+        ret = dp_opt_set_string(ad_options->id->basic, SDAP_USER_EXTRA_ATTRS,
-+                                extra_attrs);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "dp_opt_get_string failed.\n");
-+            talloc_free(ad_options);
-+            return ret;
-+        }
-+
-+        ret = sdap_extend_map_with_list(ad_options->id, ad_options->id,
-+                                        SDAP_USER_EXTRA_ATTRS,
-+                                        ad_options->id->user_map,
-+                                        SDAP_OPTS_USER,
-+                                        &ad_options->id->user_map,
-+                                        &ad_options->id->user_map_cnt);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sdap_extend_map_with_list failed.\n");
-+            talloc_free(ad_options);
-+            return ret;
-+        }
-+    } else {
-+        DEBUG(SSSDBG_TRACE_ALL, "No extra attrs set.\n");
-+    }
-+
-     gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name);
-     if (gc_service_name == NULL) {
-         talloc_free(ad_options);
--- 
-1.9.3
-
diff --git a/SOURCES/0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch b/SOURCES/0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch
new file mode 100644
index 0000000..0d73afe
--- /dev/null
+++ b/SOURCES/0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch
@@ -0,0 +1,377 @@
+From 2b13d8192f0d7a08bb16a3e488e772d54b10d81a Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 12 Aug 2015 12:41:44 +0200
+Subject: [PATCH 56/57] UTIL: Provide a common interface to safely create
+ temporary files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/tests/cmocka/test_utils.c | 175 ++++++++++++++++++++++++++++++++++++++++++
+ src/util/util.c               | 127 ++++++++++++++++++++++++++++++
+ src/util/util.h               |  21 +++++
+ 3 files changed, 323 insertions(+)
+
+diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
+index d3d00feda0bdd4048519f90ba48ae9d1042a95a1..c7ebe0997ec00197e8852bedbcf26ef1f6394fc3 100644
+--- a/src/tests/cmocka/test_utils.c
++++ b/src/tests/cmocka/test_utils.c
+@@ -1212,6 +1212,168 @@ void test_fix_domain_in_name_list(void **state)
+     talloc_free(dom);
+ }
+ 
++struct unique_file_test_ctx {
++    char *filename;
++};
++
++static int unique_file_test_setup(void **state)
++{
++    struct unique_file_test_ctx *test_ctx;
++
++    assert_true(leak_check_setup());
++    check_leaks_push(global_talloc_context);
++
++    test_ctx = talloc_zero(global_talloc_context, struct unique_file_test_ctx);
++    assert_non_null(test_ctx);
++
++    test_ctx->filename = talloc_strdup(test_ctx, "test_unique_file_XXXXXX");
++    assert_non_null(test_ctx);
++
++    *state = test_ctx;
++    return 0;
++}
++
++static int unique_file_test_teardown(void **state)
++{
++    struct unique_file_test_ctx *test_ctx;
++    errno_t ret;
++
++    test_ctx = talloc_get_type(*state, struct unique_file_test_ctx);
++
++    errno = 0;
++    ret = unlink(test_ctx->filename);
++    if (ret != 0 && errno != ENOENT) {
++        fail();
++    }
++
++    talloc_free(test_ctx);
++    assert_true(check_leaks_pop(global_talloc_context) == true);
++    assert_true(leak_check_teardown());
++    return 0;
++}
++
++static void assert_destructor(TALLOC_CTX *owner,
++                              struct unique_file_test_ctx *test_ctx)
++{
++    int fd;
++    errno_t ret;
++    char *check_filename;
++
++    /* Test that the destructor works */
++    if (owner == NULL) {
++        return;
++    }
++
++    check_filename = talloc_strdup(test_ctx, test_ctx->filename);
++    assert_non_null(check_filename);
++
++    talloc_free(owner);
++
++    ret = check_and_open_readonly(test_ctx->filename, &fd,
++                                  geteuid(), getegid(),
++                                  (S_IRUSR | S_IWUSR | S_IFREG), 0);
++    close(fd);
++    assert_int_not_equal(ret, EOK);
++}
++
++static void sss_unique_file_test(struct unique_file_test_ctx *test_ctx,
++                                 bool test_destructor)
++{
++    int fd;
++    errno_t ret;
++    struct stat sb;
++    TALLOC_CTX *owner = NULL;
++
++    if (test_destructor) {
++        owner = talloc_new(test_ctx);
++        assert_non_null(owner);
++    }
++
++    fd = sss_unique_file(owner, test_ctx->filename, &ret);
++    assert_int_not_equal(fd, -1);
++    assert_int_equal(ret, EOK);
++
++    ret = check_fd(fd, geteuid(), getegid(),
++                   (S_IRUSR | S_IWUSR | S_IFREG), 0, &sb);
++    close(fd);
++    assert_int_equal(ret, EOK);
++
++    assert_destructor(owner, test_ctx);
++}
++
++static void test_sss_unique_file(void **state)
++{
++    struct unique_file_test_ctx *test_ctx;
++    test_ctx = talloc_get_type(*state, struct unique_file_test_ctx);
++    sss_unique_file_test(test_ctx, false);
++}
++
++static void test_sss_unique_file_destruct(void **state)
++{
++    struct unique_file_test_ctx *test_ctx;
++    test_ctx = talloc_get_type(*state, struct unique_file_test_ctx);
++    sss_unique_file_test(test_ctx, true);
++}
++
++static void test_sss_unique_file_neg(void **state)
++{
++    int fd;
++    errno_t ret;
++
++    fd = sss_unique_file(NULL, discard_const("badpattern"), &ret);
++    assert_int_equal(fd, -1);
++    assert_int_equal(ret, EINVAL);
++}
++
++static void sss_unique_filename_test(struct unique_file_test_ctx *test_ctx,
++                                     bool test_destructor)
++{
++    int fd;
++    errno_t ret;
++    char *tmp_filename;
++    TALLOC_CTX *owner = NULL;
++
++    tmp_filename = talloc_strdup(test_ctx, test_ctx->filename);
++    assert_non_null(tmp_filename);
++
++    if (test_destructor) {
++        owner = talloc_new(test_ctx);
++        assert_non_null(owner);
++    }
++
++    ret = sss_unique_filename(owner, test_ctx->filename);
++    assert_int_equal(ret, EOK);
++
++    assert_int_equal(strncmp(test_ctx->filename,
++                             tmp_filename,
++                             strlen(tmp_filename) - sizeof("XXXXXX")),
++                     0);
++
++    ret = check_and_open_readonly(test_ctx->filename, &fd,
++                                  geteuid(), getegid(),
++                                  (S_IRUSR | S_IWUSR | S_IFREG), 0);
++    close(fd);
++    assert_int_equal(ret, EOK);
++
++    assert_destructor(owner, test_ctx);
++}
++
++static void test_sss_unique_filename(void **state)
++{
++    struct unique_file_test_ctx *test_ctx;
++
++    test_ctx = talloc_get_type(*state, struct unique_file_test_ctx);
++    sss_unique_filename_test(test_ctx, false);
++}
++
++static void test_sss_unique_filename_destruct(void **state)
++{
++    struct unique_file_test_ctx *test_ctx;
++
++    test_ctx = talloc_get_type(*state, struct unique_file_test_ctx);
++    sss_unique_filename_test(test_ctx, true);
++}
++
+ int main(int argc, const char *argv[])
+ {
+     poptContext pc;
+@@ -1275,6 +1437,19 @@ int main(int argc, const char *argv[])
+         cmocka_unit_test_setup_teardown(test_fix_domain_in_name_list,
+                                         confdb_test_setup,
+                                         confdb_test_teardown),
++        cmocka_unit_test_setup_teardown(test_sss_unique_file,
++                                        unique_file_test_setup,
++                                        unique_file_test_teardown),
++        cmocka_unit_test_setup_teardown(test_sss_unique_file_destruct,
++                                        unique_file_test_setup,
++                                        unique_file_test_teardown),
++        cmocka_unit_test(test_sss_unique_file_neg),
++        cmocka_unit_test_setup_teardown(test_sss_unique_filename,
++                                        unique_file_test_setup,
++                                        unique_file_test_teardown),
++        cmocka_unit_test_setup_teardown(test_sss_unique_filename_destruct,
++                                        unique_file_test_setup,
++                                        unique_file_test_teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+diff --git a/src/util/util.c b/src/util/util.c
+index 782cd026b7928e607a8980fb5f333c794feb5b1a..f0925051a08970b191f61a533cd49dd53ae128e0 100644
+--- a/src/util/util.c
++++ b/src/util/util.c
+@@ -979,3 +979,130 @@ errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *_unix_tim
+     *_unix_time = ut;
+     return EOK;
+ }
++
++struct tmpfile_watch {
++    const char *filename;
++};
++
++static int unlink_dbg(const char *filename)
++{
++    errno_t ret;
++
++    ret = unlink(filename);
++    if (ret != 0) {
++        if (errno == 2) {
++            DEBUG(SSSDBG_TRACE_INTERNAL,
++                  "File already removed: [%s]\n", filename);
++            return 0;
++        } else {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Cannot remove temporary file [%s]\n", filename);
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++static int unique_filename_destructor(void *memptr)
++{
++    struct tmpfile_watch *tw = talloc_get_type(memptr, struct tmpfile_watch);
++
++    if (tw == NULL || tw->filename == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Wrong private pointer\n");
++        return -1;
++    }
++
++    DEBUG(SSSDBG_TRACE_INTERNAL, "Unlinking [%s]\n", tw->filename);
++
++    return unlink_dbg(tw->filename);
++}
++
++static struct tmpfile_watch *tmpfile_watch_set(TALLOC_CTX *owner,
++                                               const char *filename)
++{
++    struct tmpfile_watch *tw = NULL;
++
++    tw = talloc_zero(owner, struct tmpfile_watch);
++    if (tw == NULL) {
++        return NULL;
++    }
++
++    tw->filename = talloc_strdup(tw, filename);
++    if (tw->filename == NULL) {
++        talloc_free(tw);
++        return NULL;
++    }
++
++    talloc_set_destructor((TALLOC_CTX *) tw,
++                          unique_filename_destructor);
++    return tw;
++}
++
++int sss_unique_file_ex(TALLOC_CTX *owner,
++                       char *path_tmpl,
++                       mode_t file_umask,
++                       errno_t *_err)
++{
++    size_t tmpl_len;
++    errno_t ret;
++    int fd = -1;
++    mode_t old_umask;
++    struct tmpfile_watch *tw = NULL;
++
++    tmpl_len = strlen(path_tmpl);
++    if (tmpl_len < 6 || strcmp(path_tmpl + (tmpl_len - 6), "XXXXXX") != 0) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Template too short or doesn't end with XXXXXX!\n");
++        ret = EINVAL;
++        goto done;
++    }
++
++    old_umask = umask(file_umask);
++    fd = mkstemp(path_tmpl);
++    umask(old_umask);
++    if (fd == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_OP_FAILURE,
++              "mkstemp(\"%s\") failed [%d]: %s!\n",
++              path_tmpl, ret, strerror(ret));
++        goto done;
++    }
++
++    if (owner != NULL) {
++        tw = tmpfile_watch_set(owner, path_tmpl);
++        if (tw == NULL) {
++            unlink_dbg(path_tmpl);
++            ret = ENOMEM;
++            goto done;
++        }
++    }
++
++    ret = EOK;
++done:
++    if (_err) {
++        *_err = ret;
++    }
++    return fd;
++}
++
++int sss_unique_file(TALLOC_CTX *owner,
++                    char *path_tmpl,
++                    errno_t *_err)
++{
++    return sss_unique_file_ex(owner, path_tmpl, 077, _err);
++}
++
++errno_t sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl)
++{
++    int fd;
++    errno_t ret;
++
++    fd = sss_unique_file(owner, path_tmpl, &ret);
++    /* We only care about a unique file name */
++    if (fd >= 0) {
++        close(fd);
++    }
++
++    return ret;
++}
+diff --git a/src/util/util.h b/src/util/util.h
+index 94a3ddea839f0998cb7796f1d2fe13f743de3aaf..a20d1d82eb8f10dac515ad25e7e424713bb1c099 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -658,4 +658,25 @@ int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name,
+ /* 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);
+ 
++/* Creates a unique file using mkstemp with provided umask. The template
++ * must end with XXXXXX. Returns the fd, sets _err to an errno value on error.
++ *
++ * Prefer using sss_unique_file() as it uses a secure umask internally.
++ */
++int sss_unique_file_ex(TALLOC_CTX *mem_ctx,
++                       char *path_tmpl,
++                       mode_t file_umask,
++                       errno_t *_err);
++int sss_unique_file(TALLOC_CTX *owner,
++                    char *path_tmpl,
++                    errno_t *_err);
++
++/* Creates a unique filename using mkstemp with secure umask. The template
++ * must end with XXXXXX
++ *
++ * path_tmpl must be a talloc context. Destructor would be set on the filename
++ * so that it's guaranteed the file is removed.
++ */
++int sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl);
++
+ #endif /* __SSSD_UTIL_H__ */
+-- 
+2.4.3
+
diff --git a/SOURCES/0057-Add-parse_attr_list_ex-helper-function.patch b/SOURCES/0057-Add-parse_attr_list_ex-helper-function.patch
deleted file mode 100644
index 56a75c9..0000000
--- a/SOURCES/0057-Add-parse_attr_list_ex-helper-function.patch
+++ /dev/null
@@ -1,432 +0,0 @@
-From b86a642a321d3763d997f07c47ec515acbe72cf0 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 28 Oct 2014 19:40:02 +0100
-Subject: [PATCH 57/64] Add parse_attr_list_ex() helper function
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                            |   5 +-
- src/responder/common/responder.h       |   2 +
- src/responder/common/responder_utils.c | 151 +++++++++++++++++++++++++++++++++
- src/responder/ifp/ifp_private.h        |   3 +
- src/responder/ifp/ifpsrv_util.c        | 117 +------------------------
- src/tests/cmocka/test_ifp.c            |  51 +++++++++++
- 6 files changed, 212 insertions(+), 117 deletions(-)
- create mode 100644 src/responder/common/responder_utils.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 61bf5cf957d4024b67f48cf42f5735b5fa368945..ac8ad1566a5c931bf43526e2d29a57a5f8ade1cf 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -409,6 +409,7 @@ SSSD_RESPONDER_OBJ = \
-     src/responder/common/responder_dp.c \
-     src/responder/common/responder_packet.c \
-     src/responder/common/responder_get_domains.c \
-+    src/responder/common/responder_utils.c \
-     src/monitor/monitor_iface_generated.c \
-     src/monitor/monitor_iface_generated.h \
-     src/providers/data_provider_iface_generated.c \
-@@ -2025,7 +2026,9 @@ ifp_tests_SOURCES = \
-     src/tests/cmocka/test_ifp.c \
-     src/responder/ifp/ifpsrv_cmd.c \
-     src/responder/ifp/ifp_iface_generated.c \
--    src/responder/ifp/ifpsrv_util.c
-+    src/responder/ifp/ifpsrv_util.c \
-+    src/responder/common/responder_utils.c \
-+    $(NULL)
- ifp_tests_CFLAGS = \
-     $(AM_CFLAGS)
- ifp_tests_LDADD = \
-diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
-index e3c0f226775d279ea8c0f300cc2de54d2f7f9b72..02a215ced435c87ec0439807ab5e575de0d0fe04 100644
---- a/src/responder/common/responder.h
-+++ b/src/responder/common/responder.h
-@@ -329,4 +329,6 @@ sss_parse_inp_send(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
- errno_t sss_parse_inp_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
-                            char **_name, char **_domname);
- 
-+const char **parse_attr_list_ex(TALLOC_CTX *mem_ctx, const char *conf_str,
-+                                const char **defaults);
- #endif /* __SSS_RESPONDER_H__ */
-diff --git a/src/responder/common/responder_utils.c b/src/responder/common/responder_utils.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..815b61b3971cfda2eda4efc643ea21c3b035b36d
---- /dev/null
-+++ b/src/responder/common/responder_utils.c
-@@ -0,0 +1,151 @@
-+
-+/*
-+   SSSD
-+
-+   Common Responder utility functions
-+
-+   Copyright (C) Sumit Bose <sbose@redhat.com> 2014
-+
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 3 of the License, or
-+   (at your option) any later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+*/
-+
-+#include <talloc.h>
-+
-+#include "util/util.h"
-+
-+static inline bool
-+attr_in_list(const char **list, size_t nlist, const char *str)
-+{
-+    size_t i;
-+
-+    for (i = 0; i < nlist; i++) {
-+        if (strcasecmp(list[i], str) == 0) {
-+            break;
-+        }
-+    }
-+
-+    return (i < nlist) ? true : false;
-+}
-+
-+const char **parse_attr_list_ex(TALLOC_CTX *mem_ctx, const char *conf_str,
-+                                const char **defaults)
-+{
-+    TALLOC_CTX *tmp_ctx;
-+    errno_t ret;
-+    const char **list = NULL;
-+    const char **res = NULL;
-+    int list_size;
-+    char **conf_list = NULL;
-+    int conf_list_size = 0;
-+    const char **allow = NULL;
-+    const char **deny = NULL;
-+    int ai = 0, di = 0, li = 0;
-+    int i;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        return NULL;
-+    }
-+
-+    if (conf_str) {
-+        ret = split_on_separator(tmp_ctx, conf_str, ',', true, true,
-+                                 &conf_list, &conf_list_size);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "Cannot parse attribute ACL list  %s: %d\n", conf_str, ret);
-+            goto done;
-+        }
-+
-+        allow = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
-+        deny = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
-+        if (allow == NULL || deny == NULL) {
-+            goto done;
-+        }
-+    }
-+
-+    for (i = 0; i < conf_list_size; i++) {
-+        switch (conf_list[i][0]) {
-+            case '+':
-+                allow[ai] = conf_list[i] + 1;
-+                ai++;
-+                continue;
-+            case '-':
-+                deny[di] = conf_list[i] + 1;
-+                di++;
-+                continue;
-+            default:
-+                DEBUG(SSSDBG_CRIT_FAILURE, "ACL values must start with "
-+                      "either '+' (allow) or '-' (deny), got '%s'\n",
-+                      conf_list[i]);
-+                goto done;
-+        }
-+    }
-+
-+    /* Assume the output will have to hold defaults and all the configured,
-+     * values, resize later
-+     */
-+    list_size = 0;
-+    if (defaults != NULL) {
-+        while (defaults[list_size]) {
-+            list_size++;
-+        }
-+    }
-+    list_size += conf_list_size;
-+
-+    list = talloc_zero_array(tmp_ctx, const char *, list_size + 1);
-+    if (list == NULL) {
-+        goto done;
-+    }
-+
-+    /* Start by copying explicitly allowed attributes */
-+    for (i = 0; i < ai; i++) {
-+        /* if the attribute is explicitly denied, skip it */
-+        if (attr_in_list(deny, di, allow[i])) {
-+            continue;
-+        }
-+
-+        list[li] = talloc_strdup(list, allow[i]);
-+        if (list[li] == NULL) {
-+            goto done;
-+        }
-+        li++;
-+
-+        DEBUG(SSSDBG_TRACE_INTERNAL,
-+              "Added allowed attr %s to whitelist\n", allow[i]);
-+    }
-+
-+    /* Add defaults */
-+    if (defaults != NULL) {
-+        for (i = 0; defaults[i]; i++) {
-+            /* if the attribute is explicitly denied, skip it */
-+            if (attr_in_list(deny, di, defaults[i])) {
-+                continue;
-+            }
-+
-+            list[li] = talloc_strdup(list, defaults[i]);
-+            if (list[li] == NULL) {
-+                goto done;
-+            }
-+            li++;
-+
-+            DEBUG(SSSDBG_TRACE_INTERNAL,
-+                  "Added default attr %s to whitelist\n", defaults[i]);
-+        }
-+    }
-+
-+    res = talloc_steal(mem_ctx, list);
-+done:
-+    talloc_free(tmp_ctx);
-+    return res;
-+}
-diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h
-index bf2015a9722ff4b4f831cb63cd528881f0f259a8..fb1639c8dfd00f547a666dce67ee7a94c3143618 100644
---- a/src/responder/ifp/ifp_private.h
-+++ b/src/responder/ifp/ifp_private.h
-@@ -82,5 +82,8 @@ char *_ifp_reply_objpath(TALLOC_CTX *mem_ctx, const char *base,
- errno_t ifp_add_ldb_el_to_dict(DBusMessageIter *iter_dict,
-                                struct ldb_message_element *el);
- const char **ifp_parse_attr_list(TALLOC_CTX *mem_ctx, const char *conf_str);
-+const char **
-+ifp_parse_attr_list_ex(TALLOC_CTX *mem_ctx, const char *conf_str,
-+                       const char **defaults);
- bool ifp_attr_allowed(const char *whitelist[], const char *attr);
- #endif /* _IFPSRV_PRIVATE_H_ */
-diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c
-index c0ab686e4527a2508f67b789151365dfdbb89f25..909bc54870d6442ea9daf8e86d2dc97acfe4b93d 100644
---- a/src/responder/ifp/ifpsrv_util.c
-+++ b/src/responder/ifp/ifpsrv_util.c
-@@ -356,127 +356,12 @@ errno_t ifp_add_ldb_el_to_dict(DBusMessageIter *iter_dict,
-     return EOK;
- }
- 
--static inline bool
--attr_in_list(const char **list, size_t nlist, const char *str)
--{
--    size_t i;
--
--    for (i = 0; i < nlist; i++) {
--        if (strcasecmp(list[i], str) == 0) {
--            break;
--        }
--    }
--
--    return (i < nlist) ? true : false;
--}
--
- const char **
- ifp_parse_attr_list(TALLOC_CTX *mem_ctx, const char *conf_str)
- {
--    TALLOC_CTX *tmp_ctx;
--    errno_t ret;
--    const char **list = NULL;
--    const char **res = NULL;
--    int list_size;
--    char **conf_list = NULL;
--    int conf_list_size = 0;
--    const char **allow = NULL;
--    const char **deny = NULL;
--    int ai = 0, di = 0, li = 0;
--    int i;
-     const char *defaults[] = IFP_DEFAULT_ATTRS;
- 
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        return NULL;
--    }
--
--    if (conf_str) {
--        ret = split_on_separator(tmp_ctx, conf_str, ',', true, true,
--                                 &conf_list, &conf_list_size);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_OP_FAILURE,
--                  "Cannot parse attribute ACL list  %s: %d\n", conf_str, ret);
--            goto done;
--        }
--
--        allow = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
--        deny = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
--        if (allow == NULL || deny == NULL) {
--            goto done;
--        }
--    }
--
--    for (i = 0; i < conf_list_size; i++) {
--        switch (conf_list[i][0]) {
--            case '+':
--                allow[ai] = conf_list[i] + 1;
--                ai++;
--                continue;
--            case '-':
--                deny[di] = conf_list[i] + 1;
--                di++;
--                continue;
--            default:
--                DEBUG(SSSDBG_CRIT_FAILURE, "ACL values must start with "
--                      "either '+' (allow) or '-' (deny), got '%s'\n",
--                      conf_list[i]);
--                goto done;
--        }
--    }
--
--    /* Assume the output will have to hold defauls and all the configured,
--     * values, resize later
--     */
--    list_size = 0;
--    while (defaults[list_size]) {
--        list_size++;
--    }
--    list_size += conf_list_size;
--
--    list = talloc_zero_array(tmp_ctx, const char *, list_size + 1);
--    if (list == NULL) {
--        goto done;
--    }
--
--    /* Start by copying explicitly allowed attributes */
--    for (i = 0; i < ai; i++) {
--        /* if the attribute is explicitly denied, skip it */
--        if (attr_in_list(deny, di, allow[i])) {
--            continue;
--        }
--
--        list[li] = talloc_strdup(list, allow[i]);
--        if (list[li] == NULL) {
--            goto done;
--        }
--        li++;
--
--        DEBUG(SSSDBG_TRACE_INTERNAL,
--              "Added allowed attr %s to whitelist\n", allow[i]);
--    }
--
--    /* Add defaults */
--    for (i = 0; defaults[i]; i++) {
--        /* if the attribute is explicitly denied, skip it */
--        if (attr_in_list(deny, di, defaults[i])) {
--            continue;
--        }
--
--        list[li] = talloc_strdup(list, defaults[i]);
--        if (list[li] == NULL) {
--            goto done;
--        }
--        li++;
--
--        DEBUG(SSSDBG_TRACE_INTERNAL,
--              "Added default attr %s to whitelist\n", defaults[i]);
--    }
--
--    res = talloc_steal(mem_ctx, list);
--done:
--    talloc_free(tmp_ctx);
--    return res;
-+    return parse_attr_list_ex(mem_ctx, conf_str, defaults);
- }
- 
- bool
-diff --git a/src/tests/cmocka/test_ifp.c b/src/tests/cmocka/test_ifp.c
-index b0f6e09900a956a51c17d1c4cf1a7772dccc3a68..d6e41706d5f55414c0376bd04d299ec6ad73c11e 100644
---- a/src/tests/cmocka/test_ifp.c
-+++ b/src/tests/cmocka/test_ifp.c
-@@ -246,6 +246,29 @@ static void attr_parse_test(const char *expected[], const char *input)
-     talloc_free(test_ctx);
- }
- 
-+static void attr_parse_test_ex(const char *expected[], const char *input,
-+                               const char **defaults)
-+{
-+    const char **res;
-+    TALLOC_CTX *test_ctx;
-+
-+    test_ctx = talloc_new(NULL);
-+    assert_non_null(test_ctx);
-+
-+    res = parse_attr_list_ex(test_ctx, input, defaults);
-+
-+    if (expected) {
-+        /* Positive test */
-+        assert_non_null(res);
-+        assert_string_list_equal(res, expected);
-+    } else {
-+        /* Negative test */
-+        assert_null(res);
-+    }
-+
-+    talloc_free(test_ctx);
-+}
-+
- void test_attr_acl(void **state)
- {
-     /* Test defaults */
-@@ -296,6 +319,33 @@ void test_attr_acl(void **state)
-     attr_parse_test(NULL,  "missing_plus_or_minus");
- }
- 
-+void test_attr_acl_ex(void **state)
-+{
-+    /* Test defaults */
-+    const char *exp_defaults[] = { "abc", "123", "xyz", NULL };
-+    attr_parse_test_ex(exp_defaults, NULL, exp_defaults);
-+
-+    /* Test adding some attributes to the defaults */
-+    const char *exp_add[] = { "telephoneNumber", "streetAddress",
-+                              "abc", "123", "xyz",
-+                              NULL };
-+    attr_parse_test_ex(exp_add, "+telephoneNumber, +streetAddress",
-+                       exp_defaults);
-+
-+    /* Test removing some attributes to the defaults */
-+    const char *exp_rm[] = { "123", NULL };
-+    attr_parse_test_ex(exp_rm, "-abc, -xyz", exp_defaults);
-+
-+    /* Test adding with empty defaults */
-+    const char *exp_add_empty[] = { "telephoneNumber", "streetAddress",
-+                                    NULL };
-+    attr_parse_test_ex(exp_add_empty, "+telephoneNumber, +streetAddress", NULL);
-+
-+    /* Test removing with empty defaults */
-+    const char *rm_all[] = { NULL };
-+    attr_parse_test_ex(rm_all, "-telephoneNumber, -streetAddress", NULL);
-+}
-+
- void test_attr_allowed(void **state)
- {
-     const char *whitelist[] = { "name", "gecos", NULL };
-@@ -452,6 +502,7 @@ int main(int argc, const char *argv[])
-         unit_test(test_path_prefix),
-         unit_test(test_el_to_dict),
-         unit_test(test_attr_acl),
-+        unit_test(test_attr_acl_ex),
-         unit_test(test_attr_allowed),
-         unit_test(test_path_escape_unescape),
-         unit_test_setup_teardown(test_reply_path,
--- 
-1.9.3
-
diff --git a/SOURCES/0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch b/SOURCES/0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch
new file mode 100644
index 0000000..dabccbf
--- /dev/null
+++ b/SOURCES/0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch
@@ -0,0 +1,447 @@
+From 366631d15723db68fdb5c47e18ff9253689648ab Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Fri, 24 Jul 2015 13:13:08 +0200
+Subject: [PATCH 57/57] IPA: Always re-fetch the keytab from the IPA server
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Even if a keytab for one-way trust exists, re-fetch the keytab again and
+try to use it. Fall back to the previous one if it exists.
+
+This is in order to allow the admin to re-establish the trust keytabs
+with a simple sssd restart.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ Makefile.am                                   |   2 +
+ src/providers/ipa/ipa_subdomains.c            |   4 +-
+ src/providers/ipa/ipa_subdomains_server.c     |  83 +++++++++----
+ src/tests/cmocka/test_ipa_subdomains_server.c | 166 ++++++++++++++++++++++++--
+ 4 files changed, 221 insertions(+), 34 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 8b64317d6dce9a1ee8614916395b9afd9f11f382..ed107fd5dc76b768176a3d7236b0bf1c75f212bf 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -2550,6 +2550,8 @@ test_ipa_subdom_server_LDFLAGS = \
+     -Wl,-wrap,krb5_kt_default \
+     -Wl,-wrap,execle \
+     -Wl,-wrap,execve \
++    -Wl,-wrap,rename \
++    -Wl,-wrap,sss_unique_filename \
+     $(NULL)
+ test_ipa_subdom_server_LDADD = \
+     $(PAM_LIBS) \
+diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
+index cec8b3918b8f832e2c7376a867448fe876da6ffc..b2e2fec353f7b168d28a880cb0f1b6181abb1ccb 100644
+--- a/src/providers/ipa/ipa_subdomains.c
++++ b/src/providers/ipa/ipa_subdomains.c
+@@ -264,7 +264,7 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx,
+         ret = get_idmap_data_from_range(r, domain_name, &name1, &sid1, &rid1,
+                                         &range1, &mapping1);
+         if (ret != EOK) {
+-            DEBUG(SSSDBG_OP_FAILURE, ("get_idmap_data_from_range failed.\n"));
++            DEBUG(SSSDBG_OP_FAILURE, "get_idmap_data_from_range failed.\n");
+             goto done;
+         }
+         for (d = 0; d < c; d++) {
+@@ -272,7 +272,7 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx,
+                                             &sid2, &rid2, &range2, &mapping2);
+             if (ret != EOK) {
+                 DEBUG(SSSDBG_OP_FAILURE,
+-                      ("get_idmap_data_from_range failed.\n"));
++                      "get_idmap_data_from_range failed.\n");
+                 goto done;
+             }
+ 
+diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
+index 4bfea61e6dd0a02f6b723a39f7ba236c914009b0..dfecab1bc362b5772379bae6d51f9cef8443f225 100644
+--- a/src/providers/ipa/ipa_subdomains_server.c
++++ b/src/providers/ipa/ipa_subdomains_server.c
+@@ -445,6 +445,17 @@ static void ipa_getkeytab_exec(const char *ccache,
+         exit(1);
+     }
+ 
++    /* ipa-getkeytab cannot add keys to an empty file, let's unlink it and only
++     * use the filename */
++    ret = unlink(keytab_path);
++    if (ret == -1) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Failed to unlink the temporary ccname [%d][%s]\n",
++              ret, sss_strerror(ret));
++        exit(1);
++    }
++
+     errno = 0;
+     ret = execle(IPA_GETKEYTAB_PATH, IPA_GETKEYTAB_PATH,
+                  "-r", "-s", server, "-p", principal, "-k", keytab_path, NULL,
+@@ -561,6 +572,7 @@ struct ipa_server_trust_add_state {
+     uint32_t direction;
+     const char *forest;
+     const char *keytab;
++    char *new_keytab;
+     const char *principal;
+     const char *forest_realm;
+     const char *ccache;
+@@ -660,21 +672,20 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req)
+         return EIO;
+     }
+ 
+-    ret = ipa_check_keytab(state->keytab,
+-                           state->id_ctx->server_mode->kt_owner_uid,
+-                           state->id_ctx->server_mode->kt_owner_gid);
+-    if (ret == EOK) {
+-        DEBUG(SSSDBG_TRACE_FUNC,
+-              "Keytab already present, can add the trust\n");
+-        return EOK;
+-    } else if (ret != ENOENT) {
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              "Failed to check for keytab: %d\n", ret);
++    state->new_keytab = talloc_asprintf(state, "%sXXXXXX", state->keytab);
++    if (state->new_keytab == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up ipa_get_keytab\n");
++        return ENOMEM;
++    }
++
++    ret = sss_unique_filename(state, state->new_keytab);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create temporary keytab name\n");
+         return ret;
+     }
+ 
+     DEBUG(SSSDBG_TRACE_FUNC,
+-          "No keytab for %s\n", state->subdom->name);
++          "Will re-fetch keytab for %s\n", state->subdom->name);
+ 
+     hostname = dp_opt_get_string(state->id_ctx->ipa_options->basic,
+                                  IPA_HOSTNAME);
+@@ -691,7 +702,7 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req)
+                                 state->ccache,
+                                 hostname,
+                                 state->principal,
+-                                state->keytab);
++                                state->new_keytab);
+     if (subreq == NULL) {
+         return ENOMEM;
+     }
+@@ -710,23 +721,49 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq)
+     ret = ipa_getkeytab_recv(subreq, NULL);
+     talloc_zfree(subreq);
+     if (ret != EOK) {
+-        DEBUG(SSSDBG_OP_FAILURE, "ipa_getkeytab_recv failed: %d\n", ret);
+-        tevent_req_error(req, ret);
+-        return;
++        /* Do not fail here, but try to check and use the previous keytab,
++         * if any */
++        DEBUG(SSSDBG_MINOR_FAILURE, "ipa_getkeytab_recv failed: %d\n", ret);
++    } else {
++        DEBUG(SSSDBG_TRACE_FUNC,
++              "Keytab successfully retrieved to %s\n", state->new_keytab);
+     }
+ 
+-    DEBUG(SSSDBG_TRACE_FUNC,
+-          "Keytab successfully retrieved to %s\n", state->keytab);
+-
+-    ret = ipa_check_keytab(state->keytab,
++    ret = ipa_check_keytab(state->new_keytab,
+                            state->id_ctx->server_mode->kt_owner_uid,
+                            state->id_ctx->server_mode->kt_owner_gid);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_OP_FAILURE, "ipa_check_keytab failed: %d\n", ret);
+-        tevent_req_error(req, ret);
+-        return;
++    if (ret == EOK) {
++        ret = rename(state->new_keytab, state->keytab);
++        if (ret == -1) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                "rename failed [%d][%s].\n", ret, strerror(ret));
++            tevent_req_error(req, ret);
++            return;
++        }
++        DEBUG(SSSDBG_TRACE_INTERNAL, "Keytab renamed to %s\n", state->keytab);
++    } else if (ret != EOK) {
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "Trying to recover and use the previous keytab, if available\n");
++        ret = ipa_check_keytab(state->keytab,
++                               state->id_ctx->server_mode->kt_owner_uid,
++                               state->id_ctx->server_mode->kt_owner_gid);
++        if (ret == EOK) {
++            DEBUG(SSSDBG_TRACE_FUNC,
++                  "The previous keytab %s contains the expected principal\n",
++                  state->keytab);
++        } else {
++            DEBUG(SSSDBG_OP_FAILURE,
++                  "Cannot use the old keytab: %d\n", ret);
++            /* Nothing we can do now */
++            tevent_req_error(req, ret);
++            return;
++        }
+     }
+ 
++    DEBUG(SSSDBG_TRACE_FUNC,
++          "Keytab %s contains the expected principals\n", state->new_keytab);
++
+     ret = ipa_server_trust_add_step(req);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE,
+diff --git a/src/tests/cmocka/test_ipa_subdomains_server.c b/src/tests/cmocka/test_ipa_subdomains_server.c
+index a4cb8c2b7538dc84b74e0227205b73780844b652..fb9bd80e299c05fa230599d442fa361ae757dcd3 100644
+--- a/src/tests/cmocka/test_ipa_subdomains_server.c
++++ b/src/tests/cmocka/test_ipa_subdomains_server.c
+@@ -66,33 +66,79 @@
+ #define ONEWAY_PRINC    DOM_FLAT"$"
+ #define ONEWAY_AUTHID   ONEWAY_PRINC"@"SUBDOM_REALM
+ 
++static bool global_rename_called;
++
+ krb5_error_code __wrap_krb5_kt_default(krb5_context context, krb5_keytab *id)
+ {
+     return krb5_kt_resolve(context, KEYTAB_PATH, id);
+ }
+ 
+-static void create_dummy_keytab(void)
++static void create_dummy_keytab(const char *dummy_kt)
+ {
+     errno_t ret;
+ 
+-    assert_non_null(ONEWAY_KEYTAB);
++    assert_non_null(dummy_kt);
+     mock_keytab_with_contents(global_talloc_context,
+-                              ONEWAY_KEYTAB, ONEWAY_AUTHID);
++                              dummy_kt, ONEWAY_AUTHID);
+ 
+-    ret = access(ONEWAY_KEYTAB, R_OK);
++    ret = access(dummy_kt, R_OK);
+     assert_int_equal(ret, 0);
+ }
+ 
++static int wrap_exec(void)
++{
++    const char *test_kt;
++    const char *fail_creating_kt;
++
++    test_kt = getenv("TEST_KT_ENV");
++    if (test_kt == NULL) {
++        _exit(1);
++    }
++    unsetenv("TEST_KT_ENV");
++
++    fail_creating_kt = getenv("KT_CREATE_FAIL");
++    if (fail_creating_kt != NULL) {
++        _exit(1);
++    }
++
++    create_dummy_keytab(test_kt);
++    _exit(0);
++
++    return 1;   /* Should not happen */
++}
++
+ int __wrap_execle(const char *path, const char *arg, ...)
+ {
+-    create_dummy_keytab();
+-    _exit(0);
++    return wrap_exec();
+ }
+ 
+ int __wrap_execve(const char *path, const char *arg, ...)
+ {
+-    create_dummy_keytab();
+-    _exit(0);
++    return wrap_exec();
++}
++
++errno_t __real_sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl);
++
++errno_t __wrap_sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl)
++{
++    int ret;
++    int sret;
++
++    ret = __real_sss_unique_filename(owner, path_tmpl);
++    if (ret == EOK) {
++
++        sret = setenv("TEST_KT_ENV", path_tmpl, 1);
++        assert_int_equal(sret, 0);
++    }
++    return ret;
++}
++
++int __real_rename(const char *old, const char *new);
++
++int __wrap_rename(const char *old, const char *new)
++{
++    global_rename_called = true;
++    return __real_rename(old, new);
+ }
+ 
+ struct trust_test_ctx {
+@@ -100,6 +146,7 @@ struct trust_test_ctx {
+     struct be_ctx *be_ctx;
+ 
+     struct ipa_id_ctx *ipa_ctx;
++    bool expect_rename;
+ };
+ 
+ static struct ipa_id_ctx *mock_ipa_ctx(TALLOC_CTX *mem_ctx,
+@@ -244,6 +291,8 @@ static int test_ipa_server_create_trusts_setup(void **state)
+ 
+     mock_keytab_with_contents(test_ctx, KEYTAB_PATH, KEYTAB_TEST_PRINC);
+ 
++    global_rename_called = false;
++
+     *state = test_ctx;
+     return 0;
+ }
+@@ -260,6 +309,11 @@ static int test_ipa_server_create_trusts_teardown(void **state)
+     unlink(ONEWAY_KEYTAB);
+     /* Ignore failures */
+ 
++    /* If a test needs this variable, it should be set again in
++     * each test
++     */
++    unsetenv("KT_CREATE_FAIL");
++
+     talloc_free(test_ctx);
+     return 0;
+ }
+@@ -612,6 +666,8 @@ static void test_ipa_server_create_oneway(void **state)
+ 
+     assert_null(test_ctx->ipa_ctx->server_mode->trusts);
+ 
++    test_ctx->expect_rename = true;
++
+     req = ipa_server_create_trusts_send(test_ctx,
+                                         test_ctx->tctx->ev,
+                                         test_ctx->be_ctx,
+@@ -635,6 +691,8 @@ static void test_ipa_server_create_trusts_oneway(struct tevent_req *req)
+     talloc_zfree(req);
+     assert_int_equal(ret, EOK);
+ 
++    assert_true(test_ctx->expect_rename == global_rename_called);
++
+     ret = access(ONEWAY_KEYTAB, R_OK);
+     assert_int_equal(ret, 0);
+ 
+@@ -674,10 +732,46 @@ static void test_ipa_server_create_oneway_kt_exists(void **state)
+ 
+     add_test_1way_subdomains(test_ctx);
+ 
+-    create_dummy_keytab();
++    create_dummy_keytab(ONEWAY_KEYTAB);
+     ret = access(ONEWAY_KEYTAB, R_OK);
+     assert_int_equal(ret, 0);
+ 
++    test_ctx->expect_rename = true;
++
++    assert_null(test_ctx->ipa_ctx->server_mode->trusts);
++
++    req = ipa_server_create_trusts_send(test_ctx,
++                                        test_ctx->tctx->ev,
++                                        test_ctx->be_ctx,
++                                        test_ctx->ipa_ctx,
++                                        test_ctx->be_ctx->domain);
++    assert_non_null(req);
++
++    tevent_req_set_callback(req, test_ipa_server_create_trusts_oneway, test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ERR_OK);
++}
++
++/* Test scenario where a keytab already exists, but refresh fails. In this case,
++ * sssd should attempt to reuse the previous keytab
++ */
++static void test_ipa_server_create_oneway_kt_refresh_fallback(void **state)
++{
++    struct trust_test_ctx *test_ctx =
++        talloc_get_type(*state, struct trust_test_ctx);
++    struct tevent_req *req;
++    errno_t ret;
++
++    add_test_1way_subdomains(test_ctx);
++
++    create_dummy_keytab(ONEWAY_KEYTAB);
++    ret = access(ONEWAY_KEYTAB, R_OK);
++    assert_int_equal(ret, 0);
++
++    setenv("KT_CREATE_FAIL", "1", 1);
++    test_ctx->expect_rename = false;
++
+     assert_null(test_ctx->ipa_ctx->server_mode->trusts);
+ 
+     req = ipa_server_create_trusts_send(test_ctx,
+@@ -693,6 +787,54 @@ static void test_ipa_server_create_oneway_kt_exists(void **state)
+     assert_int_equal(ret, ERR_OK);
+ }
+ 
++/* Tests case where there's no keytab and retrieving fails. Just fail the
++ * request in that case
++ */
++static void test_ipa_server_create_trusts_oneway_fail(struct tevent_req *req);
++
++static void test_ipa_server_create_oneway_kt_refresh_fail(void **state)
++{
++    struct trust_test_ctx *test_ctx =
++        talloc_get_type(*state, struct trust_test_ctx);
++    struct tevent_req *req;
++    errno_t ret;
++
++    add_test_1way_subdomains(test_ctx);
++
++    setenv("KT_CREATE_FAIL", "1", 1);
++    test_ctx->expect_rename = false;
++
++    assert_null(test_ctx->ipa_ctx->server_mode->trusts);
++
++    req = ipa_server_create_trusts_send(test_ctx,
++                                        test_ctx->tctx->ev,
++                                        test_ctx->be_ctx,
++                                        test_ctx->ipa_ctx,
++                                        test_ctx->be_ctx->domain);
++    assert_non_null(req);
++
++    tevent_req_set_callback(req,
++                            test_ipa_server_create_trusts_oneway_fail,
++                            test_ctx);
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, ERR_OK);
++}
++
++static void test_ipa_server_create_trusts_oneway_fail(struct tevent_req *req)
++{
++    struct trust_test_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct trust_test_ctx);
++    errno_t ret;
++
++    ret = ipa_server_create_trusts_recv(req);
++    assert_int_not_equal(ret, EOK);
++
++    assert_true(test_ctx->expect_rename == global_rename_called);
++
++    test_ev_done(test_ctx->tctx, EOK);
++}
++
+ static void test_ipa_server_trust_oneway_init(void **state)
+ {
+     struct trust_test_ctx *test_ctx =
+@@ -749,6 +891,12 @@ int main(int argc, const char *argv[])
+         cmocka_unit_test_setup_teardown(test_ipa_server_create_oneway_kt_exists,
+                                         test_ipa_server_create_trusts_setup,
+                                         test_ipa_server_create_trusts_teardown),
++        cmocka_unit_test_setup_teardown(test_ipa_server_create_oneway_kt_refresh_fallback,
++                                        test_ipa_server_create_trusts_setup,
++                                        test_ipa_server_create_trusts_teardown),
++        cmocka_unit_test_setup_teardown(test_ipa_server_create_oneway_kt_refresh_fail,
++                                        test_ipa_server_create_trusts_setup,
++                                        test_ipa_server_create_trusts_teardown),
+         cmocka_unit_test_setup_teardown(test_ipa_server_trust_oneway_init,
+                                         test_ipa_server_create_trusts_setup,
+                                         test_ipa_server_create_trusts_teardown),
+-- 
+2.4.3
+
diff --git a/SOURCES/0058-nss-parse-user_attributes-option.patch b/SOURCES/0058-nss-parse-user_attributes-option.patch
deleted file mode 100644
index c332b66..0000000
--- a/SOURCES/0058-nss-parse-user_attributes-option.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From 3cae708a6deae902ec961e6eef552eeb632bd3ca Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 28 Oct 2014 19:42:47 +0100
-Subject: [PATCH 58/64] nss: parse user_attributes option
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/man/sssd.conf.5.xml    | 26 ++++++++++++++++++++++++++
- src/responder/nss/nsssrv.c | 20 ++++++++++++++++++++
- src/responder/nss/nsssrv.h |  2 ++
- 3 files changed, 48 insertions(+)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index e2cb0b81b61063750995064b6ce83f9615049534..fbaca66724f7023dfa6068c225d6f61af0e662bb 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -711,6 +711,32 @@ fallback_homedir = /home/%u
-                         </para>
-                     </listitem>
-                 </varlistentry>
-+                <varlistentry>
-+                    <term>user_attributes (string)</term>
-+                    <listitem>
-+                        <para>
-+                            Some of the additional NSS responder requests can
-+                            return more attributes than just the POSIX ones
-+                            defined by the NSS interface. The list of attributes
-+                            is controlled by this option. It is handle the same
-+                            way as the <quote>user_attributes</quote> option of
-+                            the InfoPipe responder (see
-+                            <citerefentry>
-+                                <refentrytitle>sssd-ifp</refentrytitle>
-+                                <manvolnum>5</manvolnum>
-+                            </citerefentry>
-+                            for details) but with no default values.
-+                        </para>
-+                        <para>
-+                            To make configuration more easy the NSS responder
-+                            will check the InfoPipe option if it is not set for
-+                            the NSS responder.
-+                        </para>
-+                        <para>
-+                            Default: not set, fallback to InfoPipe option
-+                        </para>
-+                    </listitem>
-+                </varlistentry>
-             </variablelist>
-         </refsect2>
-         <refsect2 id='PAM'>
-diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
-index 1bbeaa1534ee3e0db72dda13ff9d01ef7fba6adf..bce06c3e8b56f3b09126f43a194c1cd6a60efb2c 100644
---- a/src/responder/nss/nsssrv.c
-+++ b/src/responder/nss/nsssrv.c
-@@ -214,6 +214,7 @@ static int nss_get_config(struct nss_ctx *nctx,
-                           struct confdb_ctx *cdb)
- {
-     int ret;
-+    char *tmp_str;
- 
-     ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
-                          CONFDB_NSS_ENUM_CACHE_TIMEOUT, 120,
-@@ -298,6 +299,25 @@ static int nss_get_config(struct nss_ctx *nctx,
-                             &nctx->homedir_substr);
-     if (ret != EOK) goto done;
- 
-+
-+    ret = confdb_get_string(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
-+                            CONFDB_IFP_USER_ATTR_LIST, NULL, &tmp_str);
-+    if (ret != EOK) goto done;
-+
-+    if (tmp_str == NULL) {
-+        ret = confdb_get_string(cdb, nctx, CONFDB_IFP_CONF_ENTRY,
-+                                CONFDB_IFP_USER_ATTR_LIST, NULL, &tmp_str);
-+        if (ret != EOK) goto done;
-+    }
-+
-+    if (tmp_str != NULL) {
-+        nctx->extra_attributes = parse_attr_list_ex(nctx, tmp_str, NULL);
-+        if (nctx->extra_attributes == NULL) {
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+    }
-+
-     ret = 0;
- done:
-     return ret;
-diff --git a/src/responder/nss/nsssrv.h b/src/responder/nss/nsssrv.h
-index a5b946b7e4a38d7d8b35ec5df1b6644d01896470..784eba2e0c6b15b106a2323bba1de5523e2937c1 100644
---- a/src/responder/nss/nsssrv.h
-+++ b/src/responder/nss/nsssrv.h
-@@ -75,6 +75,8 @@ struct nss_ctx {
- 
-     struct sss_idmap_ctx *idmap_ctx;
-     struct sss_names_ctx *global_names;
-+
-+    const char **extra_attributes;
- };
- 
- struct nss_packet;
--- 
-1.9.3
-
diff --git a/SOURCES/0058-p11child-set-restrictive-umask-and-clear-environment.patch b/SOURCES/0058-p11child-set-restrictive-umask-and-clear-environment.patch
new file mode 100644
index 0000000..e2448b9
--- /dev/null
+++ b/SOURCES/0058-p11child-set-restrictive-umask-and-clear-environment.patch
@@ -0,0 +1,35 @@
+From 5845a325b10e48b1e4c21976b0856ad1d012bbb4 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 5 Aug 2015 17:25:20 +0200
+Subject: [PATCH 58/59] p11child: set restrictive umask and clear environment
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://fedorahosted.org/sssd/ticket/2754
+
+Before doing any calls, set a very restrictive umask and clear
+environment variables to harden p11child execution.
+
+Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
+---
+ src/p11_child/p11_child_nss.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c
+index 6948c142aa7843cda5ff6d18f5853b10c387c224..44ba6678893408dbfc0c6c7cfd5edcdaa789f518 100644
+--- a/src/p11_child/p11_child_nss.c
++++ b/src/p11_child/p11_child_nss.c
+@@ -481,6 +481,9 @@ int main(int argc, const char *argv[])
+     /* Set debug level to invalid value so we can decide if -d 0 was used. */
+     debug_level = SSSDBG_INVALID;
+ 
++    clearenv();
++    umask(077);
++
+     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+     while ((opt = poptGetNextOpt(pc)) != -1) {
+         switch(opt) {
+-- 
+2.4.3
+
diff --git a/SOURCES/0059-nss-return-user_attributes-in-origbyname-request.patch b/SOURCES/0059-nss-return-user_attributes-in-origbyname-request.patch
deleted file mode 100644
index 81ce0c0..0000000
--- a/SOURCES/0059-nss-return-user_attributes-in-origbyname-request.patch
+++ /dev/null
@@ -1,383 +0,0 @@
-From 9b6c5e3233cdbd5fce7b6beed0cf057fe3d5da61 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 24 Oct 2014 11:30:33 +0200
-Subject: [PATCH 59/64] nss: return user_attributes in origbyname request
-
-To allow IPA clients to offer special attributes of AD users form
-trusted domain the extdom plugin on the IPA server must send them to the
-clients. The extdom plugin already uses sss_nss_getorigbyname() to get
-attributes like the SID and the user principal name. This patch adds the
-attributes given by the NSS/IFP user_attributes option to the list of
-attributes returned by sss_nss_getorigbyname().
-
-Fixes https://fedorahosted.org/sssd/ticket/2464
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/responder/nss/nsssrv_cmd.c  | 120 +++++++++++++++++++++++++++---------
- src/tests/cmocka/test_nss_srv.c | 133 ++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 223 insertions(+), 30 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index 4ac5eb91eab80291e60afad2bf9c65edfbc21e7d..b100aae08fc04ccf1a295745767c5445cf2e01be 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4148,18 +4148,19 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
-     struct nss_ctx *nctx;
-     int ret;
-     int err;
--    const char *attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR,
--                           ORIGINALAD_PREFIX SYSDB_NAME,
--                           ORIGINALAD_PREFIX SYSDB_UIDNUM,
--                           ORIGINALAD_PREFIX SYSDB_GIDNUM,
--                           ORIGINALAD_PREFIX SYSDB_GECOS,
--                           ORIGINALAD_PREFIX SYSDB_HOMEDIR,
--                           ORIGINALAD_PREFIX SYSDB_SHELL,
--                           SYSDB_UPN,
--                           SYSDB_DEFAULT_OVERRIDE_NAME,
--                           SYSDB_AD_ACCOUNT_EXPIRES,
--                           SYSDB_AD_USER_ACCOUNT_CONTROL,
--                           SYSDB_DEFAULT_ATTRS, NULL};
-+    const char *default_attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR,
-+                                   ORIGINALAD_PREFIX SYSDB_NAME,
-+                                   ORIGINALAD_PREFIX SYSDB_UIDNUM,
-+                                   ORIGINALAD_PREFIX SYSDB_GIDNUM,
-+                                   ORIGINALAD_PREFIX SYSDB_GECOS,
-+                                   ORIGINALAD_PREFIX SYSDB_HOMEDIR,
-+                                   ORIGINALAD_PREFIX SYSDB_SHELL,
-+                                   SYSDB_UPN,
-+                                   SYSDB_DEFAULT_OVERRIDE_NAME,
-+                                   SYSDB_AD_ACCOUNT_EXPIRES,
-+                                   SYSDB_AD_USER_ACCOUNT_CONTROL,
-+                                   SYSDB_DEFAULT_ATTRS, NULL};
-+    const char **attrs;
-     bool user_found = false;
-     bool group_found = false;
-     struct ldb_message *msg = NULL;
-@@ -4281,6 +4282,18 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
-             goto done;
-         }
- 
-+        attrs = default_attrs;
-+        if (cmdctx->cmd == SSS_NSS_GETORIGBYNAME
-+                && nctx->extra_attributes != NULL) {
-+            ret = add_strings_lists(cmdctx, default_attrs,
-+                                    nctx->extra_attributes, false,
-+                                    discard_const(&attrs));
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "add_strings_lists failed.\n");
-+                goto done;
-+            }
-+        }
-+
-         if (cmdctx->cmd == SSS_NSS_GETSIDBYID) {
-             ret = sysdb_search_user_by_uid(cmdctx, dom, cmdctx->id, attrs,
-                                            &msg);
-@@ -4593,16 +4606,21 @@ static errno_t fill_sid(struct sss_packet *packet,
- }
- 
- static errno_t fill_orig(struct sss_packet *packet,
-+                         struct resp_ctx *rctx,
-                          enum sss_id_type id_type,
-                          struct ldb_message *msg)
- {
-     int ret;
-+    TALLOC_CTX *tmp_ctx;
-     const char *tmp_str;
-     uint8_t *body;
-     size_t blen;
-     size_t pctr = 0;
-     size_t c;
-     size_t sum;
-+    size_t found;
-+    size_t extra_attrs_count = 0;
-+    const char **extra_attrs_list = NULL;
-     const char *orig_attr_list[] = {SYSDB_SID_STR,
-                                     ORIGINALAD_PREFIX SYSDB_NAME,
-                                     ORIGINALAD_PREFIX SYSDB_UIDNUM,
-@@ -4615,42 +4633,83 @@ static errno_t fill_orig(struct sss_packet *packet,
-                                     SYSDB_AD_ACCOUNT_EXPIRES,
-                                     SYSDB_AD_USER_ACCOUNT_CONTROL,
-                                     NULL};
--    struct sized_string keys[sizeof(orig_attr_list)];
--    struct sized_string vals[sizeof(orig_attr_list)];
-+    struct sized_string *keys;
-+    struct sized_string *vals;
-+    struct nss_ctx *nctx;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx);
-+    if (nctx->extra_attributes != NULL) {
-+        extra_attrs_list = nctx->extra_attributes;
-+            for(extra_attrs_count = 0;
-+                extra_attrs_list[extra_attrs_count] != NULL;
-+                extra_attrs_count++);
-+    }
-+
-+    keys = talloc_array(tmp_ctx, struct sized_string,
-+                        sizeof(orig_attr_list) + extra_attrs_count);
-+    vals = talloc_array(tmp_ctx, struct sized_string,
-+                        sizeof(orig_attr_list) + extra_attrs_count);
-+    if (keys == NULL || vals == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
- 
-     sum = 0;
-+    found = 0;
-     for (c = 0; orig_attr_list[c] != NULL; c++) {
-         tmp_str = ldb_msg_find_attr_as_string(msg, orig_attr_list[c], NULL);
-         if (tmp_str != NULL) {
--            to_sized_string(&keys[c], orig_attr_list[c]);
--            sum += keys[c].len;
--            to_sized_string(&vals[c], tmp_str);
--            sum += vals[c].len;
--        } else {
--            vals[c].len = 0;
-+            to_sized_string(&keys[found], orig_attr_list[c]);
-+            sum += keys[found].len;
-+            to_sized_string(&vals[found], tmp_str);
-+            sum += vals[found].len;
-+
-+            found++;
-+        }
-+    }
-+
-+    for (c = 0; c < extra_attrs_count; c++) {
-+        tmp_str = ldb_msg_find_attr_as_string(msg, extra_attrs_list[c], NULL);
-+        if (tmp_str != NULL) {
-+            to_sized_string(&keys[found], extra_attrs_list[c]);
-+            sum += keys[found].len;
-+            to_sized_string(&vals[found], tmp_str);
-+            sum += vals[found].len;
-+
-+            found++;
-         }
-     }
- 
-     ret = sss_packet_grow(packet, sum +  3 * sizeof(uint32_t));
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
--        return ret;
-+        goto done;
-     }
- 
-     sss_packet_get_body(packet, &body, &blen);
-     SAFEALIGN_SETMEM_UINT32(body, 1, &pctr); /* Num results */
-     SAFEALIGN_SETMEM_UINT32(body + pctr, 0, &pctr); /* reserved */
-     SAFEALIGN_COPY_UINT32(body + pctr, &id_type, &pctr);
--    for (c = 0; orig_attr_list[c] != NULL; c++) {
--        if (vals[c].len != 0) {
--            memcpy(&body[pctr], keys[c].str, keys[c].len);
--            pctr+= keys[c].len;
--            memcpy(&body[pctr], vals[c].str, vals[c].len);
--            pctr+= vals[c].len;
--        }
-+    for (c = 0; c < found; c++) {
-+        memcpy(&body[pctr], keys[c].str, keys[c].len);
-+        pctr+= keys[c].len;
-+        memcpy(&body[pctr], vals[c].str, vals[c].len);
-+        pctr+= vals[c].len;
-     }
- 
--    return EOK;
-+    ret = EOK;
-+
-+done:
-+    talloc_free(tmp_ctx);
-+
-+    return ret;
- }
- 
- static errno_t fill_name(struct sss_packet *packet,
-@@ -4818,7 +4877,8 @@ static errno_t nss_cmd_getbysid_send_reply(struct nss_dom_ctx *dctx)
-         ret = fill_sid(cctx->creq->out, id_type, dctx->res->msgs[0]);
-         break;
-     case SSS_NSS_GETORIGBYNAME:
--        ret = fill_orig(cctx->creq->out, id_type, dctx->res->msgs[0]);
-+        ret = fill_orig(cctx->creq->out, cctx->rctx, id_type,
-+                        dctx->res->msgs[0]);
-         break;
-     default:
-         DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type.\n");
-diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
-index 65298cdf04e37e85820d3308c773f1c95a21ce31..c318d94be867bbb9991de288cdae45d2ddc29b24 100644
---- a/src/tests/cmocka/test_nss_srv.c
-+++ b/src/tests/cmocka/test_nss_srv.c
-@@ -52,6 +52,8 @@ struct nss_test_ctx {
-     bool ncache_hit;
- };
- 
-+const char *global_extra_attrs[] = {"phone", "mobile", NULL};
-+
- struct nss_test_ctx *nss_test_ctx;
- 
- /* Mock NSS structure */
-@@ -1000,6 +1002,7 @@ void test_nss_setup(struct sss_test_conf_param params[],
-     nss_test_ctx->rctx = mock_rctx(nss_test_ctx, nss_test_ctx->tctx->ev,
-                                    nss_test_ctx->tctx->dom, nss_test_ctx->nctx);
-     assert_non_null(nss_test_ctx->rctx);
-+    nss_test_ctx->rctx->cdb = nss_test_ctx->tctx->confdb;
-     nss_test_ctx->nctx->rctx = nss_test_ctx->rctx;
- 
-     /* Create client context */
-@@ -1827,6 +1830,122 @@ void test_nss_getorigbyname(void **state)
-     assert_int_equal(ret, EOK);
- }
- 
-+static int test_nss_getorigbyname_extra_check(uint32_t status, uint8_t *body,
-+                                              size_t blen)
-+{
-+    const char *s;
-+    enum sss_id_type id_type;
-+    size_t rp = 2 * sizeof(uint32_t);
-+
-+    assert_int_equal(status, EOK);
-+
-+    SAFEALIGN_COPY_UINT32(&id_type, body+rp, &rp);
-+    assert_int_equal(id_type, SSS_ID_TYPE_UID);
-+
-+    /* Sequence of null terminated strings */
-+    s = (char *) body+rp;
-+    assert_string_equal(s, SYSDB_SID_STR);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "S-1-2-3-4");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_NAME);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "orig_name");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_UIDNUM);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "1234");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "phone");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "+12-34 56 78");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "mobile");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "+98-76 54 32");
-+    rp += strlen(s) + 1;
-+    assert_int_equal(rp, blen);
-+
-+    return EOK;
-+}
-+
-+void test_nss_getorigbyname_extra_attrs(void **state)
-+{
-+    errno_t ret;
-+    struct sysdb_attrs *attrs;
-+
-+    attrs = sysdb_new_attrs(nss_test_ctx);
-+    assert_non_null(attrs);
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, "S-1-2-3-4");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, ORIGINALAD_PREFIX SYSDB_NAME,
-+                                 "orig_name");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_uint32(attrs, ORIGINALAD_PREFIX SYSDB_UIDNUM, 1234);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, "phone", "+12-34 56 78");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, "mobile", "+98-76 54 32");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, "not_extra", "abc");
-+    assert_int_equal(ret, EOK);
-+
-+    /* Prime the cache with a valid user */
-+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
-+                         "testuserorigextra", 2345, 6789,
-+                         "test user orig extra",
-+                         "/home/testuserorigextra", "/bin/sh", NULL,
-+                         attrs, 300, 0);
-+    assert_int_equal(ret, EOK);
-+
-+    mock_input_user_or_group("testuserorigextra");
-+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETORIGBYNAME);
-+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
-+
-+    /* Query for that user, call a callback when command finishes */
-+    set_cmd_cb(test_nss_getorigbyname_extra_check);
-+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETORIGBYNAME,
-+                          nss_test_ctx->nss_cmds);
-+    assert_int_equal(ret, EOK);
-+
-+    /* Wait until the test finishes with EOK */
-+    ret = test_ev_loop(nss_test_ctx->tctx);
-+    assert_int_equal(ret, EOK);
-+}
-+
- void nss_test_setup(void **state)
- {
-     struct sss_test_conf_param params[] = {
-@@ -1848,6 +1967,18 @@ void nss_fqdn_test_setup(void **state)
-     test_nss_setup(params, state);
- }
- 
-+void nss_test_setup_extra_attr(void **state)
-+{
-+    struct sss_test_conf_param params[] = {
-+        { "enumerate", "false" },
-+        { NULL, NULL },             /* Sentinel */
-+    };
-+
-+    test_nss_setup(params, state);
-+
-+    nss_test_ctx->nctx->extra_attributes = global_extra_attrs;
-+}
-+
- void nss_subdom_test_setup(void **state)
- {
-     const char *const testdom[4] = { TEST_SUBDOM_NAME, "TEST.SUB", "test", "S-3" };
-@@ -1963,6 +2094,8 @@ int main(int argc, const char *argv[])
-                                  nss_test_setup, nss_test_teardown),
-         unit_test_setup_teardown(test_nss_getorigbyname,
-                                  nss_test_setup, nss_test_teardown),
-+        unit_test_setup_teardown(test_nss_getorigbyname_extra_attrs,
-+                                 nss_test_setup_extra_attr, nss_test_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-1.9.3
-
diff --git a/SOURCES/0059-pam-Incerease-p11-child-timeout.patch b/SOURCES/0059-pam-Incerease-p11-child-timeout.patch
new file mode 100644
index 0000000..8ff29a0
--- /dev/null
+++ b/SOURCES/0059-pam-Incerease-p11-child-timeout.patch
@@ -0,0 +1,68 @@
+From 8cc5a9b94d6d660d61cce62543b6714d95e19697 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
+Date: Thu, 13 Aug 2015 14:03:24 +0200
+Subject: [PATCH 59/59] pam: Incerease p11 child timeout
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Ticket:
+https://fedorahosted.org/sssd/ticket/2746
+
+It was timeouting often in CI machines.
+
+Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
+---
+ Makefile.am                    | 1 +
+ src/responder/pam/pamsrv_cmd.c | 9 +++++++--
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index ed107fd5dc76b768176a3d7236b0bf1c75f212bf..7dc4875c9cb05bf146505c0dc0dab543fb326bd3 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1892,6 +1892,7 @@ pam_srv_tests_SOURCES = \
+ pam_srv_tests_CFLAGS = \
+     -U SSSD_LIBEXEC_PATH -DSSSD_LIBEXEC_PATH=\"$(abs_builddir)\" \
+     $(AM_CFLAGS) \
++    -DSSS_P11_CHILD_TIMEOUT=30 \
+     $(NULL)
+ pam_srv_tests_LDFLAGS = \
+     -Wl,-wrap,sss_packet_get_body \
+diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
+index 3b84fb864c5a1b08dc4126ff97e258a792f312bc..aa5c20906a36351e425304122517c81676e730b7 100644
+--- a/src/responder/pam/pamsrv_cmd.c
++++ b/src/responder/pam/pamsrv_cmd.c
+@@ -43,6 +43,11 @@ enum pam_verbosity {
+ 
+ #define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT
+ 
++/* TODO: Should we make this configurable? */
++#ifndef SSS_P11_CHILD_TIMEOUT
++#define SSS_P11_CHILD_TIMEOUT 10
++#endif
++
+ static errno_t
+ pam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain,
+                                           const char *username);
+@@ -1122,7 +1127,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
+ 
+     if (may_do_cert_auth(pctx, pd)) {
+         req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd,
+-                                  pctx->nss_db, 10, pd);
++                                  pctx->nss_db, SSS_P11_CHILD_TIMEOUT, pd);
+         if (req == NULL) {
+             DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n");
+             ret = ENOMEM;
+@@ -1338,7 +1343,7 @@ static void pam_forwarder_cb(struct tevent_req *req)
+ 
+     if (may_do_cert_auth(pctx, pd)) {
+         req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd,
+-                                  pctx->nss_db, 10, pd);
++                                  pctx->nss_db, SSS_P11_CHILD_TIMEOUT, pd);
+         if (req == NULL) {
+             DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n");
+             ret = ENOMEM;
+-- 
+2.4.3
+
diff --git a/SOURCES/0060-SYSDB-Index-the-objectSIDString-attribute.patch b/SOURCES/0060-SYSDB-Index-the-objectSIDString-attribute.patch
new file mode 100644
index 0000000..660e3a1
--- /dev/null
+++ b/SOURCES/0060-SYSDB-Index-the-objectSIDString-attribute.patch
@@ -0,0 +1,130 @@
+From c50681fc7a1296c278466e834eaddfbf2bc54afb Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 25 Jun 2015 17:33:47 +0200
+Subject: [PATCH] SYSDB: Index the objectSIDString attribute
+
+---
+ src/db/sysdb.c         |  7 +++++++
+ src/db/sysdb_private.h |  5 ++++-
+ src/db/sysdb_upgrade.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 61 insertions(+), 1 deletion(-)
+
+diff --git a/src/db/sysdb.c b/src/db/sysdb.c
+index 9da655759c0c35d52854b668693195b3360c5f8b..07a83a8a8e30df1b8e461a8d04866f2dbc53baf8 100644
+--- a/src/db/sysdb.c
++++ b/src/db/sysdb.c
+@@ -1265,6 +1265,13 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
+             }
+         }
+ 
++        if (strcmp(version, SYSDB_VERSION_0_16) == 0) {
++            ret = sysdb_upgrade_16(sysdb, &version);
++            if (ret != EOK) {
++                goto done;
++            }
++        }
++
+         /* The version should now match SYSDB_VERSION.
+          * If not, it means we didn't match any of the
+          * known older versions. The DB might be
+diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
+index 2adb9ff9166441014a8b446ffc170225f2a9629d..c2c8d7a0585463806997c43bd020436edddd8517 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_17 "0.17"
+ #define SYSDB_VERSION_0_16 "0.16"
+ #define SYSDB_VERSION_0_15 "0.15"
+ #define SYSDB_VERSION_0_14 "0.14"
+@@ -40,7 +41,7 @@
+ #define SYSDB_VERSION_0_2 "0.2"
+ #define SYSDB_VERSION_0_1 "0.1"
+ 
+-#define SYSDB_VERSION SYSDB_VERSION_0_16
++#define SYSDB_VERSION SYSDB_VERSION_0_17
+ 
+ #define SYSDB_BASE_LDIF \
+      "dn: @ATTRIBUTES\n" \
+@@ -68,6 +69,7 @@
+      "@IDXATTR: serviceProtocol\n" \
+      "@IDXATTR: sudoUser\n" \
+      "@IDXATTR: sshKnownHostsExpire\n" \
++     "@IDXATTR: objectSIDString\n" \
+      "@IDXONE: 1\n" \
+      "\n" \
+      "dn: @MODULES\n" \
+@@ -120,6 +122,7 @@ int sysdb_upgrade_12(struct sysdb_ctx *sysdb, const char **ver);
+ int sysdb_upgrade_13(struct sysdb_ctx *sysdb, const char **ver);
+ int sysdb_upgrade_14(struct sysdb_ctx *sysdb, const char **ver);
+ int sysdb_upgrade_15(struct sysdb_ctx *sysdb, const char **ver);
++int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver);
+ 
+ int add_string(struct ldb_message *msg, int flags,
+                const char *attr, const char *value);
+diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
+index 6cebc877b86df7a8035bf95cfa51aa4dae464372..113f24644e3e3de1d4c46d375492c2fe1e6b2f83 100644
+--- a/src/db/sysdb_upgrade.c
++++ b/src/db/sysdb_upgrade.c
+@@ -1584,6 +1584,56 @@ done:
+     return ret;
+ }
+ 
++int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver)
++{
++    struct ldb_message *msg;
++    struct upgrade_ctx *ctx;
++    errno_t ret;
++
++    ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_17, &ctx);
++    if (ret) {
++        return ret;
++    }
++
++    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;
++    }
++
++    /* add index for objectSIDString */
++    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", "objectSIDString");
++    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;
++    }
++
++    /* conversion done, update version number */
++    ret = update_version(ctx);
++
++done:
++    ret = finish_upgrade(ret, &ctx, ver);
++    return ret;
++}
++
+ /*
+  * Example template for future upgrades.
+  * Copy and change version numbers as appropriate.
+-- 
+2.4.3
+
diff --git a/SOURCES/0060-sysdb_get_user_attr_with_views-add-mandatory-overrid.patch b/SOURCES/0060-sysdb_get_user_attr_with_views-add-mandatory-overrid.patch
deleted file mode 100644
index 2be9d08..0000000
--- a/SOURCES/0060-sysdb_get_user_attr_with_views-add-mandatory-overrid.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From ac992d1ae46ec5ff44a1300718f12c10b1cbd60a Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 27 Oct 2014 13:33:08 +0100
-Subject: [PATCH 60/64] sysdb_get_user_attr_with_views: add mandatory override
- attributes
-
-This patch add another attribute with is needs for override processing
-to the attribute list of sysdb_get_user_attr_with_views(). With two
-attribute it does not seem useful to check for existence and add each of
-the attributes conditionally. With this patch they are added
-unconditionally if the domain has views. Additionally the attributes are
-not removed in the end because it is expected that they do not cause any
-harm.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/db/sysdb_search.c | 47 ++++++++---------------------------------------
- 1 file changed, 8 insertions(+), 39 deletions(-)
-
-diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
-index bbc5af8a02777c1519a9d0b5d77c50559e66f462..dacbd239db6be7e4c738d5bd6b495b613411b126 100644
---- a/src/db/sysdb_search.c
-+++ b/src/db/sysdb_search.c
-@@ -1037,11 +1037,11 @@ int sysdb_get_user_attr_with_views(TALLOC_CTX *mem_ctx,
-     int ret;
-     struct ldb_result *orig_obj = NULL;
-     struct ldb_result *override_obj = NULL;
--    struct ldb_message_element *el = NULL;
-     const char **attrs = NULL;
--    bool has_override_dn;
-+    const char *mandatory_override_attrs[] = {SYSDB_OVERRIDE_DN,
-+                                              SYSDB_OVERRIDE_OBJECT_DN,
-+                                              NULL};
-     TALLOC_CTX *tmp_ctx;
--    int count;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -1049,35 +1049,15 @@ int sysdb_get_user_attr_with_views(TALLOC_CTX *mem_ctx,
-         return ENOMEM;
-     }
- 
--    /* Assume that overrideDN is requested to simplify the code. If no view
--     * is applied it doesn't really matter. */
--    has_override_dn = true;
-     attrs = attributes;
- 
-     /* If there are views we first have to search the overrides for matches */
-     if (DOM_HAS_VIEWS(domain)) {
--        /* We need overrideDN for views, so append it if missing. */
--        has_override_dn = false;
--        for (count = 0; attributes[count] != NULL; count++) {
--            if (strcmp(attributes[count], SYSDB_OVERRIDE_DN) == 0) {
--                has_override_dn = true;
--                break;
--            }
--        }
--
--        if (!has_override_dn) {
--            /* Copy original attributes and add overrideDN. */
--            attrs = talloc_zero_array(tmp_ctx, const char *, count + 2);
--            if (attrs == NULL) {
--                ret = ENOMEM;
--                goto done;
--            }
--
--            for (count = 0; attributes[count] != NULL; count++) {
--                attrs[count] = attributes[count];
--            }
--
--            attrs[count] = SYSDB_OVERRIDE_DN;
-+        ret = add_strings_lists(tmp_ctx, attributes, mandatory_override_attrs,
-+                                false, discard_const(&attrs));
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "add_strings_lists failed.\n");
-+            goto done;
-         }
- 
-         ret = sysdb_search_user_override_attrs_by_name(tmp_ctx, domain, name,
-@@ -1121,17 +1101,6 @@ int sysdb_get_user_attr_with_views(TALLOC_CTX *mem_ctx,
-         }
-     }
- 
--    /* Remove overrideDN if needed. */
--    if (!has_override_dn && orig_obj != NULL && orig_obj->count == 1) {
--        el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_OVERRIDE_DN);
--        if (el == NULL) {
--            ret = EINVAL;
--            goto done;
--        }
--
--        ldb_msg_remove_element(orig_obj->msgs[0], el);
--    }
--
-     *_res = talloc_steal(mem_ctx, orig_obj);
-     ret = EOK;
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0061-sss_override-print-input-name-if-unable-to-parse-it.patch b/SOURCES/0061-sss_override-print-input-name-if-unable-to-parse-it.patch
new file mode 100644
index 0000000..88aa0bb
--- /dev/null
+++ b/SOURCES/0061-sss_override-print-input-name-if-unable-to-parse-it.patch
@@ -0,0 +1,26 @@
+From 90c45ac5b4e67703455b2cf04334ae0fc90188b3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Sat, 15 Aug 2015 13:53:25 +0200
+Subject: [PATCH 61/66] sss_override: print input name if unable to parse it
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/tools/sss_override.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c
+index 5e901e2e31de64dacb171337defc03d428f8ed57..e84a7b922dfcf179f8010dc4cced0eafd89a2c76 100644
+--- a/src/tools/sss_override.c
++++ b/src/tools/sss_override.c
+@@ -74,7 +74,7 @@ static int parse_cmdline(struct sss_cmdline *cmdline,
+     ret = sss_tool_parse_name(tool_ctx, tool_ctx, input_name,
+                               &orig_name, &domain);
+     if (ret != EOK) {
+-        fprintf(stderr, _("Unable to parse name.\n"));
++        fprintf(stderr, _("Unable to parse name %s.\n"), input_name);
+         return ret;
+     }
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0061-sysdb_add_overrides_to_object-add-new-parameter-and-.patch b/SOURCES/0061-sysdb_add_overrides_to_object-add-new-parameter-and-.patch
deleted file mode 100644
index 378f73f..0000000
--- a/SOURCES/0061-sysdb_add_overrides_to_object-add-new-parameter-and-.patch
+++ /dev/null
@@ -1,214 +0,0 @@
-From 6f86800fde61c3cd61d8d7884f0da342a616bde4 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 27 Oct 2014 15:11:08 +0100
-Subject: [PATCH 61/64] sysdb_add_overrides_to_object: add new parameter and
- multi-value support
-
-With the new parameter an attribute list other than the default one can
-be used.
-
-Override attributes with multiple values (e.g. SSH public keys) are now
-supported as well.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/db/sysdb.h                 |  3 ++-
- src/db/sysdb_search.c          | 24 ++++++++++++++++--------
- src/db/sysdb_views.c           | 41 +++++++++++++++++++++++++----------------
- src/responder/nss/nsssrv_cmd.c |  2 +-
- 4 files changed, 44 insertions(+), 26 deletions(-)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index ebb1bbedaf2df3030a012f1f0be8c5a069399cc3..f582f6a516e43a453741acacbe3ca6957e23fc37 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -487,7 +487,8 @@ errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx,
- 
- errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
-                                       struct ldb_message *obj,
--                                      struct ldb_message *override_obj);
-+                                      struct ldb_message *override_obj,
-+                                      const char **req_attrs);
- 
- errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
-                                          struct ldb_message *obj);
-diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
-index dacbd239db6be7e4c738d5bd6b495b613411b126..677257405fae51774d4cd0c17516238e74fb7592 100644
---- a/src/db/sysdb_search.c
-+++ b/src/db/sysdb_search.c
-@@ -124,7 +124,8 @@ errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx,
-      * the original object. */
-     if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
-         ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
--                          override_obj == NULL ? NULL : override_obj ->msgs[0]);
-+                          override_obj == NULL ? NULL : override_obj->msgs[0],
-+                          NULL);
-         if (ret != EOK && ret != ENOENT) {
-             DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
-             goto done;
-@@ -229,7 +230,8 @@ errno_t sysdb_getpwuid_with_views(TALLOC_CTX *mem_ctx,
-      * the original object. */
-     if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
-         ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
--                           override_obj == NULL ? NULL : override_obj->msgs[0]);
-+                           override_obj == NULL ? NULL : override_obj->msgs[0],
-+                           NULL);
-         if (ret != EOK && ret != ENOENT) {
-             DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
-             goto done;
-@@ -314,7 +316,8 @@ int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx,
- 
-     if (DOM_HAS_VIEWS(domain)) {
-         for (c = 0; c < res->count; c++) {
--            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL);
-+            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL,
-+                                                NULL);
-             /* enumeration assumes that the cache is up-to-date, hence we do not
-              * need to handle ENOENT separately. */
-             if (ret != EOK) {
-@@ -426,7 +429,8 @@ int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx,
-         }
- 
-         ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
--                          override_obj == NULL ? NULL : override_obj ->msgs[0]);
-+                          override_obj == NULL ? NULL : override_obj ->msgs[0],
-+                          NULL);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
-             goto done;
-@@ -578,7 +582,8 @@ int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx,
-         }
- 
-         ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
--                          override_obj == NULL ? NULL : override_obj ->msgs[0]);
-+                          override_obj == NULL ? NULL : override_obj ->msgs[0],
-+                          NULL);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
-             goto done;
-@@ -734,7 +739,8 @@ int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx,
- 
-     if (DOM_HAS_VIEWS(domain)) {
-         for (c = 0; c < res->count; c++) {
--            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL);
-+            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL,
-+                                                NULL);
-             /* enumeration assumes that the cache is up-to-date, hence we do not
-              * need to handle ENOENT separately. */
-             if (ret != EOK) {
-@@ -956,7 +962,8 @@ int sysdb_initgroups_with_views(TALLOC_CTX *mem_ctx,
-     if (DOM_HAS_VIEWS(domain)) {
-         /* Skip user entry because it already has override values added */
-         for (c = 1; c < res->count; c++) {
--            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL);
-+            ret = sysdb_add_overrides_to_object(domain, res->msgs[c], NULL,
-+                                                NULL);
-             if (ret != EOK) {
-                 DEBUG(SSSDBG_OP_FAILURE,
-                       "sysdb_add_overrides_to_object failed.\n");
-@@ -1083,7 +1090,8 @@ int sysdb_get_user_attr_with_views(TALLOC_CTX *mem_ctx,
-      * the original object. */
-     if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
-         ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
--                          override_obj == NULL ? NULL : override_obj ->msgs[0]);
-+                          override_obj == NULL ? NULL : override_obj ->msgs[0],
-+                          attrs);
-         if (ret != EOK && ret != ENOENT) {
-             DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n");
-             return ret;
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index a42aa96ed3e0cd7c877ff0c42887ef3f03ef5e0e..f2cf370231b57c3cd2b563eec4ea2a0f3a0935bd 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -948,6 +948,8 @@ errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx,
-  * @param[in] domain Domain struct, needed to access the cache
-  * @oaram[in] obj The original object
-  * @param[in] override_obj The object with the override data, may be NULL
-+ * @param[in] req_attrs List of attributes to be requested, if not set a
-+ *                      default list dependig on the object type will be used
-  *
-  * @return EOK - Override data was added successfully
-  * @return ENOMEM - There was insufficient memory to complete the operation
-@@ -958,7 +960,8 @@ errno_t sysdb_search_group_override_by_gid(TALLOC_CTX *mem_ctx,
-  */
- errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
-                                       struct ldb_message *obj,
--                                      struct ldb_message *override_obj)
-+                                      struct ldb_message *override_obj,
-+                                      const char **req_attrs)
- {
-     int ret;
-     const char *override_dn_str;
-@@ -983,7 +986,8 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
-         {NULL, NULL}
-     };
-     size_t c;
--    const char *tmp_str;
-+    size_t d;
-+    struct ldb_message_element *tmp_el;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -1016,12 +1020,15 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
-             goto done;
-         }
- 
--        uid = ldb_msg_find_attr_as_uint64(obj, SYSDB_UIDNUM, 0);
--        if (uid == 0) {
--            /* No UID hence group object */
--            attrs = group_attrs;
--        } else {
--            attrs = user_attrs;
-+        attrs = req_attrs;
-+        if (attrs == NULL) {
-+            uid = ldb_msg_find_attr_as_uint64(obj, SYSDB_UIDNUM, 0);
-+            if (uid == 0) {
-+                /* No UID hence group object */
-+                attrs = group_attrs;
-+            } else {
-+                attrs = user_attrs;
-+            }
-         }
- 
-         ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, override_dn,
-@@ -1050,14 +1057,16 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
-     }
- 
-     for (c = 0; attr_map[c].attr != NULL; c++) {
--        tmp_str = ldb_msg_find_attr_as_string(override, attr_map[c].attr, NULL);
--        if (tmp_str != NULL) {
--            talloc_steal(obj, tmp_str);
--            ret = ldb_msg_add_string(obj, attr_map[c].new_attr, tmp_str);
--            if (ret != LDB_SUCCESS) {
--                DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
--                ret = sysdb_error_to_errno(ret);
--                goto done;
-+        tmp_el = ldb_msg_find_element(override, attr_map[c].attr);
-+        if (tmp_el != NULL) {
-+            for (d = 0; d < tmp_el->num_values; d++) {
-+                ret = ldb_msg_add_steal_value(obj, attr_map[c].new_attr,
-+                                              &tmp_el->values[d]);
-+                if (ret != LDB_SUCCESS) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_value failed.\n");
-+                    ret = sysdb_error_to_errno(ret);
-+                    goto done;
-+                }
-             }
-         }
-     }
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index b100aae08fc04ccf1a295745767c5445cf2e01be..ff7b6a334f4c1d9dc854296746b0ff83949acd68 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4064,7 +4064,7 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
-             if (ret == EOK && DOM_HAS_VIEWS(dom)) {
-                 for (c = 0; c < dctx->res->count; c++) {
-                     ret = sysdb_add_overrides_to_object(dom, dctx->res->msgs[c],
--                                                        NULL);
-+                                                        NULL, NULL);
-                     if (ret != EOK) {
-                         DEBUG(SSSDBG_OP_FAILURE,
-                               "sysdb_add_overrides_to_object failed.\n");
--- 
-1.9.3
-
diff --git a/SOURCES/0062-Views-apply-user-SSH-public-key-override.patch b/SOURCES/0062-Views-apply-user-SSH-public-key-override.patch
deleted file mode 100644
index d61f8f8..0000000
--- a/SOURCES/0062-Views-apply-user-SSH-public-key-override.patch
+++ /dev/null
@@ -1,317 +0,0 @@
-From a5a3aaafd0c1399f83bd3144344eb9a0da436307 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 16 Oct 2014 13:17:37 +0200
-Subject: [PATCH 62/64] Views: apply user SSH public key override
-
-With this patch the SSH public key override attribute is read from the
-FreeIPA server and saved in the cache with the other override data.
-
-Since it is possible to have multiple public SSH keys this override
-value does not replace any other data but will be added to existing
-values.
-
-Fixes https://fedorahosted.org/sssd/ticket/2454
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/db/sysdb_views.c           |  38 +++++++++----
- src/man/sssd-ipa.5.xml         |   3 +
- src/providers/ipa/ipa_common.h |   1 +
- src/providers/ipa/ipa_opts.h   |   1 +
- src/responder/ssh/sshsrv_cmd.c | 123 +++++++++++++++++++++++++++++++----------
- 5 files changed, 126 insertions(+), 40 deletions(-)
-
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index f2cf370231b57c3cd2b563eec4ea2a0f3a0935bd..27b58701fe0f9a4f545df5e4bfb884c04517d0d3 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -560,6 +560,8 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
-     TALLOC_CTX *tmp_ctx;
-     struct sysdb_attrs *attrs;
-     size_t c;
-+    size_t d;
-+    size_t num_values;
-     struct ldb_message_element *el = NULL;
-     const char *allowed_attrs[] = { SYSDB_UIDNUM,
-                                     SYSDB_GIDNUM,
-@@ -567,6 +569,7 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
-                                     SYSDB_HOMEDIR,
-                                     SYSDB_SHELL,
-                                     SYSDB_NAME,
-+                                    SYSDB_SSH_PUBKEY,
-                                     NULL };
-     bool override_attrs_found = false;
- 
-@@ -584,7 +587,6 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
-     }
- 
-     for (c = 0; allowed_attrs[c] != NULL; c++) {
--        /* TODO: add nameAlias for case-insentitive searches */
-         ret = sysdb_attrs_get_el_ext(override_attrs, allowed_attrs[c], false,
-                                      &el);
-         if (ret == EOK) {
-@@ -607,17 +609,30 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
-                     goto done;
-                 }
-             } else {
--                ret = sysdb_attrs_add_val(attrs,  allowed_attrs[c],
--                                          &el->values[0]);
--                if (ret != EOK) {
--                    DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n");
--                    goto done;
-+                num_values = el->num_values;
-+                /* Only SYSDB_SSH_PUBKEY is allowed to have multiple values. */
-+                if (strcmp(allowed_attrs[c], SYSDB_SSH_PUBKEY) != 0
-+                        && num_values != 1) {
-+                    DEBUG(SSSDBG_MINOR_FAILURE,
-+                          "Override attribute for [%s] has more [%zd] " \
-+                          "than one value, using only the first.\n",
-+                          allowed_attrs[c], num_values);
-+                    num_values = 1;
-+                }
-+
-+                for (d = 0; d < num_values; d++) {
-+                    ret = sysdb_attrs_add_val(attrs,  allowed_attrs[c],
-+                                              &el->values[d]);
-+                    if (ret != EOK) {
-+                        DEBUG(SSSDBG_OP_FAILURE,
-+                              "sysdb_attrs_add_val failed.\n");
-+                        goto done;
-+                    }
-+                    DEBUG(SSSDBG_TRACE_ALL,
-+                          "Override [%s] with [%.*s] for [%s].\n",
-+                          allowed_attrs[c], (int) el->values[d].length,
-+                          el->values[d].data, ldb_dn_get_linearized(obj_dn));
-                 }
--                DEBUG(SSSDBG_TRACE_ALL, "Override [%s] with [%.*s] for [%s].\n",
--                                        allowed_attrs[c],
--                                        (int) el->values[0].length,
--                                        el->values[0].data,
--                                        ldb_dn_get_linearized(obj_dn));
-             }
-         } else if (ret != ENOENT) {
-             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el_ext failed.\n");
-@@ -983,6 +998,7 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
-         {SYSDB_HOMEDIR, OVERRIDE_PREFIX SYSDB_HOMEDIR},
-         {SYSDB_SHELL, OVERRIDE_PREFIX SYSDB_SHELL},
-         {SYSDB_NAME, OVERRIDE_PREFIX SYSDB_NAME},
-+        {SYSDB_SSH_PUBKEY, OVERRIDE_PREFIX SYSDB_SSH_PUBKEY},
-         {NULL, NULL}
-     };
-     size_t c;
-diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
-index 51f14f8fc16bd2843ef4b426938172c63608176e..e8a716c4104b8038e354b8ae544a04d6773e708b 100644
---- a/src/man/sssd-ipa.5.xml
-+++ b/src/man/sssd-ipa.5.xml
-@@ -626,6 +626,9 @@
-                                     <listitem>
-                                         <para>ldap_user_shell</para>
-                                     </listitem>
-+                                    <listitem>
-+                                        <para>ldap_user_ssh_public_key</para>
-+                                    </listitem>
-                                 </itemizedlist>
-                             </para>
-                             <para>
-diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
-index 0e9324f5b362085153abebcc4894bef607173607..495276548e57e91f9744dda6d8866971b627b4da 100644
---- a/src/providers/ipa/ipa_common.h
-+++ b/src/providers/ipa/ipa_common.h
-@@ -128,6 +128,7 @@ enum ipa_override_attrs {
-     IPA_AT_OVERRIDE_SHELL,
-     IPA_AT_OVERRIDE_GROUP_NAME,
-     IPA_AT_OVERRIDE_GROUP_GID_NUMBER,
-+    IPA_AT_OVERRIDE_USER_SSH_PUBLIC_KEY,
- 
-     IPA_OPTS_OVERRIDE
- };
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index 0e0eed49cd397fe88ce7bf41579c066088947d04..473eca4f77727e008663d082e954820a9fb0c427 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -283,6 +283,7 @@ struct sdap_attr_map ipa_override_map[] = {
-     { "ldap_user_shell", "loginShell", SYSDB_SHELL, NULL },
-     { "ldap_group_name", "cn", SYSDB_NAME, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-+    { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL },
-     SDAP_ATTR_MAP_TERMINATOR
- };
- 
-diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
-index ad831639841d42417008ea6c40c1dea045e5d6cf..5bed2e0adca0e6961337bb744729dd3e5a23c629 100644
---- a/src/responder/ssh/sshsrv_cmd.c
-+++ b/src/responder/ssh/sshsrv_cmd.c
-@@ -232,8 +232,8 @@ ssh_user_pubkeys_search_next(struct ssh_cmd_ctx *cmd_ctx)
-         return EFAULT;
-     }
- 
--    ret = sysdb_get_user_attr(cmd_ctx, cmd_ctx->domain,
--                              cmd_ctx->name, attrs, &res);
-+    ret = sysdb_get_user_attr_with_views(cmd_ctx, cmd_ctx->domain,
-+                                         cmd_ctx->name, attrs, &res);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
-               "Failed to make request to our cache!\n");
-@@ -782,6 +782,65 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
-     return EOK;
- }
- 
-+static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx,
-+                                          struct ldb_message_element *el,
-+                                          size_t fqname_len,
-+                                          const char *fqname,
-+                                          size_t *c)
-+{
-+    struct cli_ctx *cctx = cmd_ctx->cctx;
-+    uint8_t *key;
-+    size_t key_len;
-+    uint8_t *body;
-+    size_t body_len;
-+    int ret;
-+    size_t d;
-+    TALLOC_CTX *tmp_ctx;
-+
-+    if (el == NULL) {
-+        DEBUG(SSSDBG_TRACE_ALL, "Mssing element, nothing to do.\n");
-+        return EOK;
-+    }
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    for (d = 0; d < el->num_values; d++) {
-+        key = sss_base64_decode(tmp_ctx, (const char *) el->values[d].data,
-+                                &key_len);
-+        if (key == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+
-+        ret = sss_packet_grow(cctx->creq->out,
-+                              3*sizeof(uint32_t) + key_len + fqname_len);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
-+            goto done;
-+        }
-+        sss_packet_get_body(cctx->creq->out, &body, &body_len);
-+
-+        SAFEALIGN_SET_UINT32(body+(*c), 0, c);
-+        SAFEALIGN_SET_UINT32(body+(*c), fqname_len, c);
-+        safealign_memcpy(body+(*c), fqname, fqname_len, c);
-+        SAFEALIGN_SET_UINT32(body+(*c), key_len, c);
-+        safealign_memcpy(body+(*c), key, key_len, c);
-+
-+    }
-+
-+    ret = EOK;
-+
-+done:
-+    talloc_free(tmp_ctx);
-+
-+    return ret;
-+}
-+
- static errno_t
- ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
- {
-@@ -790,14 +849,13 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
-     uint8_t *body;
-     size_t body_len;
-     size_t c = 0;
--    unsigned int i;
--    struct ldb_message_element *el;
-+    struct ldb_message_element *el = NULL;
-+    struct ldb_message_element *el_override = NULL;
-+    struct ldb_message_element *el_orig = NULL;
-     uint32_t count = 0;
-     const char *name;
-     char *fqname;
-     uint32_t fqname_len;
--    uint8_t *key;
--    size_t key_len;
- 
-     ret = sss_packet_new(cctx->creq, 0,
-                          sss_packet_get_cmd(cctx->creq->in),
-@@ -811,6 +869,20 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
-         count = el->num_values;
-     }
- 
-+    el_orig = ldb_msg_find_element(cmd_ctx->result,
-+                                  ORIGINALAD_PREFIX SYSDB_SSH_PUBKEY);
-+    if (el_orig) {
-+        count = el_orig->num_values;
-+    }
-+
-+    if (DOM_HAS_VIEWS(cmd_ctx->domain)) {
-+        el_override = ldb_msg_find_element(cmd_ctx->result,
-+                                           OVERRIDE_PREFIX SYSDB_SSH_PUBKEY);
-+        if (el_override) {
-+            count += el_override->num_values;
-+        }
-+    }
-+
-     ret = sss_packet_grow(cctx->creq->out, 2*sizeof(uint32_t));
-     if (ret != EOK) {
-         return ret;
-@@ -820,7 +892,7 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
-     SAFEALIGN_SET_UINT32(body+c, count, &c);
-     SAFEALIGN_SET_UINT32(body+c, 0, &c);
- 
--    if (!el) {
-+    if (count == 0) {
-         return EOK;
-     }
- 
-@@ -840,30 +912,23 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
- 
-     fqname_len = strlen(fqname)+1;
- 
--    for (i = 0; i < el->num_values; i++) {
--        key = sss_base64_decode(cmd_ctx,
--                                (const char *)el->values[i].data,
--                                &key_len);
--        if (!key) {
--            return ENOMEM;
--        }
-+    ret = decode_and_add_base64_data(cmd_ctx, el, fqname_len, fqname, &c);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
-+        return ret;
-+    }
- 
--        ret = sss_packet_grow(cctx->creq->out,
--                              3*sizeof(uint32_t) + key_len + fqname_len);
--        if (ret != EOK) {
--            talloc_free(key);
--            return ret;
--        }
--        sss_packet_get_body(cctx->creq->out, &body, &body_len);
-+    ret = decode_and_add_base64_data(cmd_ctx, el_orig, fqname_len, fqname, &c);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
-+        return ret;
-+    }
- 
--        SAFEALIGN_SET_UINT32(body+c, 0, &c);
--        SAFEALIGN_SET_UINT32(body+c, fqname_len, &c);
--        safealign_memcpy(body+c, fqname, fqname_len, &c);
--        SAFEALIGN_SET_UINT32(body+c, key_len, &c);
--        safealign_memcpy(body+c, key, key_len, &c);
--
--        talloc_free(key);
--        count++;
-+    ret = decode_and_add_base64_data(cmd_ctx, el_override, fqname_len, fqname,
-+                                     &c);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
-+        return ret;
-     }
- 
-     return EOK;
--- 
-1.9.3
-
diff --git a/SOURCES/0062-sss_override-support-domains-that-require-fqname.patch b/SOURCES/0062-sss_override-support-domains-that-require-fqname.patch
new file mode 100644
index 0000000..366c47c
--- /dev/null
+++ b/SOURCES/0062-sss_override-support-domains-that-require-fqname.patch
@@ -0,0 +1,108 @@
+From 83e150a2b200ec50f2f02229d9662e1468e286df Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 19 Aug 2015 12:28:21 +0200
+Subject: [PATCH 62/66] sss_override: support domains that require fqname
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2757
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/tools/sss_override.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 57 insertions(+), 2 deletions(-)
+
+diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c
+index e84a7b922dfcf179f8010dc4cced0eafd89a2c76..84b51c537842b7281a523f58c2cfbdfd38e54c72 100644
+--- a/src/tools/sss_override.c
++++ b/src/tools/sss_override.c
+@@ -272,6 +272,54 @@ static struct sysdb_attrs *build_group_attrs(TALLOC_CTX *mem_ctx,
+     return build_attrs(mem_ctx, group->name, 0, group->gid, 0, NULL, NULL);
+ }
+ 
++static char *get_fqname(TALLOC_CTX *mem_ctx,
++                        struct sss_domain_info *domain,
++                        const char *name)
++{
++    char *fqname;
++    size_t fqlen;
++    size_t check;
++
++    if (domain == NULL) {
++        return NULL;
++    }
++
++    /* Get length. */
++    fqlen = sss_fqname(NULL, 0, domain->names, domain, name);
++    if (fqlen > 0) {
++        fqlen++; /* \0 */
++    } else {
++        return NULL;
++    }
++
++    fqname = talloc_zero_array(mem_ctx, char, fqlen);
++    if (fqname == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
++        return NULL;
++    }
++
++    check = sss_fqname(fqname, fqlen, domain->names, domain, name);
++    if (check != fqlen - 1) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate a fully qualified name "
++              "for user [%s] in [%s]! Skipping user.\n", name, domain->name);
++        talloc_free(fqname);
++        return NULL;
++    }
++
++    return fqname;
++}
++
++static char *get_sysname(TALLOC_CTX *mem_ctx,
++                         struct sss_domain_info *domain,
++                         const char *name)
++{
++    if (domain == NULL || !domain->fqnames) {
++        return talloc_strdup(mem_ctx, name);
++    }
++
++    return get_fqname(mem_ctx, domain, name);
++}
++
+ static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx,
+                                          enum sysdb_member_type type,
+                                          const char *name,
+@@ -284,6 +332,7 @@ static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx,
+     struct ldb_result *res;
+     const char *dn;
+     const char *strtype;
++    char *sysname;
+     bool check_next;
+     errno_t ret;
+ 
+@@ -292,16 +341,22 @@ static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx,
+         return NULL;
+     }
+ 
++    sysname = get_sysname(tmp_ctx, domain, name);
++    if (sysname == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
+     /* Ensure that the object is in cache. */
+     switch (type) {
+     case SYSDB_MEMBER_USER:
+-        if (getpwnam(name) == NULL) {
++        if (getpwnam(sysname) == NULL) {
+             ret = ENOENT;
+             goto done;
+         }
+         break;
+     case SYSDB_MEMBER_GROUP:
+-        if (getgrnam(name) == NULL) {
++        if (getgrnam(sysname) == NULL) {
+             ret = ENOENT;
+             goto done;
+         }
+-- 
+2.4.3
+
diff --git a/SOURCES/0063-Add-test-for-sysdb_add_overrides_to_object.patch b/SOURCES/0063-Add-test-for-sysdb_add_overrides_to_object.patch
deleted file mode 100644
index 0d8d7d3..0000000
--- a/SOURCES/0063-Add-test-for-sysdb_add_overrides_to_object.patch
+++ /dev/null
@@ -1,290 +0,0 @@
-From de4be65f95ae8bd10995948e086bb71f047c2887 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 28 Oct 2014 15:53:16 +0100
-Subject: [PATCH 63/64] Add test for sysdb_add_overrides_to_object()
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                         |  16 +++
- src/tests/cmocka/test_sysdb_views.c | 235 ++++++++++++++++++++++++++++++++++++
- 2 files changed, 251 insertions(+)
- create mode 100644 src/tests/cmocka/test_sysdb_views.c
-
-diff --git a/Makefile.am b/Makefile.am
-index ac8ad1566a5c931bf43526e2d29a57a5f8ade1cf..60bc67f1ac60c72dc64b3d1adccc9ef1ec989ad5 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -215,6 +215,7 @@ if HAVE_CMOCKA
-         sss_sifp-tests \
-         test_search_bases \
-         sdap-tests \
-+        test_sysdb_views \
-         $(NULL)
- 
- if BUILD_IFP
-@@ -2060,6 +2061,21 @@ sss_sifp_tests_LDADD = \
-     $(SSSD_INTERNAL_LTLIBS)
- endif # BUILD_IFP
- 
-+test_sysdb_views_SOURCES = \
-+    src/tests/cmocka/test_sysdb_views.c \
-+    $(NULL)
-+test_sysdb_views_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(NULL)
-+test_sysdb_views_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(LDB_LIBS) \
-+    $(POPT_LIBS) \
-+    $(TALLOC_LIBS) \
-+    $(SSSD_INTERNAL_LTLIBS) \
-+    libsss_test_common.la \
-+    $(NULL)
-+
- endif # HAVE_CMOCKA
- 
- noinst_PROGRAMS = pam_test_client
-diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..38525d6ded8fdbbd1a657f8ca742e51d6ba2b102
---- /dev/null
-+++ b/src/tests/cmocka/test_sysdb_views.c
-@@ -0,0 +1,235 @@
-+/*
-+    SSSD
-+
-+    sysdb_views - Tests for view and override related sysdb calls
-+
-+    Authors:
-+        Sumit Bose <sbose@redhat.com>
-+
-+    Copyright (C) 2014 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 <stdarg.h>
-+#include <stddef.h>
-+#include <setjmp.h>
-+#include <cmocka.h>
-+#include <popt.h>
-+
-+#include "tests/cmocka/common_mock.h"
-+
-+#define TESTS_PATH "tests_sysdb"
-+#define TEST_CONF_FILE "tests_conf.ldb"
-+
-+struct sysdb_test_ctx {
-+    struct sysdb_ctx *sysdb;
-+    struct confdb_ctx *confdb;
-+    struct tevent_context *ev;
-+    struct sss_domain_info *domain;
-+};
-+
-+static int _setup_sysdb_tests(struct sysdb_test_ctx **ctx, bool enumerate)
-+{
-+    struct sysdb_test_ctx *test_ctx;
-+    char *conf_db;
-+    int ret;
-+
-+    const char *val[2];
-+    val[1] = NULL;
-+
-+    /* Create tests directory if it doesn't exist */
-+    /* (relative to current dir) */
-+    ret = mkdir(TESTS_PATH, 0775);
-+    assert_true(ret == 0 || errno == EEXIST);
-+
-+    test_ctx = talloc_zero(global_talloc_context, struct sysdb_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    /* Create an event context
-+     * It will not be used except in confdb_init and sysdb_init
-+     */
-+    test_ctx->ev = tevent_context_init(test_ctx);
-+    assert_non_null(test_ctx->ev);
-+
-+    conf_db = talloc_asprintf(test_ctx, "%s/%s", TESTS_PATH, TEST_CONF_FILE);
-+    assert_non_null(conf_db);
-+    DEBUG(SSSDBG_MINOR_FAILURE, "CONFDB: %s\n", conf_db);
-+
-+    /* Connect to the conf db */
-+    ret = confdb_init(test_ctx, &test_ctx->confdb, conf_db);
-+    assert_int_equal(ret, EOK);
-+
-+    val[0] = "LOCAL";
-+    ret = confdb_add_param(test_ctx->confdb, true,
-+                           "config/sssd", "domains", val);
-+    assert_int_equal(ret, EOK);
-+
-+    val[0] = "local";
-+    ret = confdb_add_param(test_ctx->confdb, true,
-+                           "config/domain/LOCAL", "id_provider", val);
-+    assert_int_equal(ret, EOK);
-+
-+    val[0] = enumerate ? "TRUE" : "FALSE";
-+    ret = confdb_add_param(test_ctx->confdb, true,
-+                           "config/domain/LOCAL", "enumerate", val);
-+    assert_int_equal(ret, EOK);
-+
-+    val[0] = "TRUE";
-+    ret = confdb_add_param(test_ctx->confdb, true,
-+                           "config/domain/LOCAL", "cache_credentials", val);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sssd_domain_init(test_ctx, test_ctx->confdb, "local",
-+                           TESTS_PATH, &test_ctx->domain);
-+    assert_int_equal(ret, EOK);
-+
-+    test_ctx->sysdb = test_ctx->domain->sysdb;
-+
-+    *ctx = test_ctx;
-+    return EOK;
-+}
-+
-+#define setup_sysdb_tests(ctx) _setup_sysdb_tests((ctx), false)
-+
-+static void test_sysdb_setup(void **state)
-+{
-+    int ret;
-+    struct sysdb_test_ctx *test_ctx;
-+
-+    assert_true(leak_check_setup());
-+
-+    ret = setup_sysdb_tests(&test_ctx);
-+    assert_int_equal(ret, EOK);
-+
-+    *state = (void *) test_ctx;
-+}
-+
-+static void test_sysdb_teardown(void **state)
-+{
-+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                                         struct sysdb_test_ctx);
-+
-+    talloc_free(test_ctx);
-+    assert_true(leak_check_teardown());
-+}
-+
-+void test_sysdb_add_overrides_to_object(void **state)
-+{
-+    int ret;
-+    struct ldb_message *orig;
-+    struct ldb_message *override;
-+    struct ldb_message_element *el;
-+    char *tmp_str;
-+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                                         struct sysdb_test_ctx);
-+
-+    orig = ldb_msg_new(test_ctx);
-+    assert_non_null(orig);
-+
-+    tmp_str = talloc_strdup(orig,  "ORIGNAME");
-+    ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str);
-+    assert_int_equal(ret, EOK);
-+
-+    tmp_str = talloc_strdup(orig,  "ORIGGECOS");
-+    ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str);
-+    assert_int_equal(ret, EOK);
-+
-+    override = ldb_msg_new(test_ctx);
-+    assert_non_null(override);
-+
-+    tmp_str = talloc_strdup(override, "OVERRIDENAME");
-+    ret = ldb_msg_add_string(override, SYSDB_NAME, tmp_str);
-+    assert_int_equal(ret, EOK);
-+
-+    tmp_str = talloc_strdup(override, "OVERRIDEGECOS");
-+    ret = ldb_msg_add_string(override, SYSDB_GECOS, tmp_str);
-+    assert_int_equal(ret, EOK);
-+
-+    tmp_str = talloc_strdup(override, "OVERRIDEKEY1");
-+    ret = ldb_msg_add_string(override, SYSDB_SSH_PUBKEY, tmp_str);
-+    assert_int_equal(ret, EOK);
-+
-+    tmp_str = talloc_strdup(override, "OVERRIDEKEY2");
-+    ret = ldb_msg_add_string(override, SYSDB_SSH_PUBKEY, tmp_str);
-+    assert_int_equal(ret, EOK);
-+
-+
-+    ret = sysdb_add_overrides_to_object(test_ctx->domain, orig, override, NULL);
-+    assert_int_equal(ret, EOK);
-+
-+    assert_string_equal(ldb_msg_find_attr_as_string(orig, SYSDB_NAME, NULL),
-+                        "ORIGNAME");
-+    assert_string_equal(ldb_msg_find_attr_as_string(orig, SYSDB_GECOS, NULL),
-+                        "ORIGGECOS");
-+    assert_string_equal(ldb_msg_find_attr_as_string(orig,
-+                                                    OVERRIDE_PREFIX SYSDB_NAME,
-+                                                    NULL),
-+                        "OVERRIDENAME");
-+    assert_string_equal(ldb_msg_find_attr_as_string(orig,
-+                                                    OVERRIDE_PREFIX SYSDB_GECOS,
-+                                                    NULL),
-+                        "OVERRIDEGECOS");
-+
-+    el = ldb_msg_find_element(orig, OVERRIDE_PREFIX SYSDB_SSH_PUBKEY);
-+    assert_non_null(el);
-+    assert_int_equal(el->num_values, 2);
-+    assert_int_equal(ldb_val_string_cmp(&el->values[0], "OVERRIDEKEY1"), 0);
-+    assert_int_equal(ldb_val_string_cmp(&el->values[1], "OVERRIDEKEY2"), 0);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    int rv;
-+    int no_cleanup = 0;
-+    poptContext pc;
-+    int opt;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0,
-+         _("Do not delete the test database after a test run"), NULL },
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test_setup_teardown(test_sysdb_add_overrides_to_object,
-+                                 test_sysdb_setup, test_sysdb_teardown),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    tests_set_cwd();
-+    rv = run_tests(tests);
-+
-+    if (rv == 0 && no_cleanup == 0) {
-+        test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_FILE, LOCAL_SYSDB_FILE);
-+    }
-+    return rv;
-+}
--- 
-1.9.3
-
diff --git a/SOURCES/0063-TOOLS-add-sss_colondb-API.patch b/SOURCES/0063-TOOLS-add-sss_colondb-API.patch
new file mode 100644
index 0000000..0ca7cd6
--- /dev/null
+++ b/SOURCES/0063-TOOLS-add-sss_colondb-API.patch
@@ -0,0 +1,408 @@
+From d28ed42ad2030090bc511f5b3381b5137885175d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 19 Aug 2015 12:34:08 +0200
+Subject: [PATCH 63/66] TOOLS: add sss_colondb API
+
+To simplify import/export users and groups.
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/tools/common/sss_colondb.c | 305 +++++++++++++++++++++++++++++++++++++++++
+ src/tools/common/sss_colondb.h |  73 ++++++++++
+ 2 files changed, 378 insertions(+)
+ create mode 100644 src/tools/common/sss_colondb.c
+ create mode 100644 src/tools/common/sss_colondb.h
+
+diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..6b340c80e703342defb8582537db2e4ef3926155
+--- /dev/null
++++ b/src/tools/common/sss_colondb.c
+@@ -0,0 +1,305 @@
++/*
++    Authors:
++        Pavel Březina <pbrezina@redhat.com>
++
++    Copyright (C) 2015 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 <stdlib.h>
++
++#include "util/util.h"
++#include "util/strtonum.h"
++#include "tools/common/sss_colondb.h"
++
++#define IS_STD_FILE(db) ((db)->file == stdin || (db)->file == stdout)
++
++static char *read_field_as_string(char *line,
++                                  const char **_value)
++{
++    char *rest;
++    char *value;
++
++    if (line == NULL || *line == '\n' || *line == '\0') {
++        /* There is nothing else to read. */
++        rest = NULL;
++        value = NULL;
++        goto done;
++    }
++
++    if (*line == ':') {
++        /* Special case for empty value. */
++        *line = '\0';
++        rest = line + 1;
++        value = NULL;
++        goto done;
++    }
++
++    /* Value starts at current position. */
++    value = line;
++
++    /* Find next field delimiter. */
++    rest = strchr(line, ':');
++    if (rest == NULL) {
++        /* There is no more field. Remove \n from the end. */
++        rest = strchr(line, '\n');
++        if (rest != NULL) {
++            *rest = '\0';
++            rest = NULL;
++        }
++        goto done;
++    }
++
++    /* Remove it and step one character further. */
++    *rest = '\0';
++    rest++;
++
++done:
++    *_value = value;
++
++    return rest;
++}
++
++static char *read_field_as_uint32(char *line,
++                                  uint32_t *_value)
++{
++    const char *str;
++    char *rest;
++    errno_t ret;
++
++    rest = read_field_as_string(line, &str);
++    if (str == NULL) {
++        *_value = 0;
++        return rest;
++    }
++
++    *_value = strtouint32(str, NULL, 10);
++    if (errno != 0) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse number [%d]: %s\n",
++              ret, sss_strerror(ret));
++
++        *_value = 0;
++    }
++
++    return rest;
++}
++
++struct sss_colondb {
++    FILE *file;
++    enum sss_colondb_mode mode;
++};
++
++errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx,
++                             struct sss_colondb *db,
++                             struct sss_colondb_read_field *table)
++{
++    int readchars;
++    size_t linelen = 0;
++    char *line = NULL;
++    char *tcline;
++    char *rest;
++    errno_t ret;
++    int i;
++
++    if (db->mode != SSS_COLONDB_READ) {
++        return ERR_INTERNAL;
++    }
++
++    readchars = getline(&line, &linelen, db->file);
++    if (readchars == -1) {
++        /* Nothing was read. */
++        if (errno != 0) {
++            ret = errno;
++            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read line [%d]: %s",
++                  ret, sss_strerror(ret));
++            return ret;
++        }
++
++        return EOF;
++    }
++
++    /* Copy line to mem_ctx. */
++    tcline = talloc_strdup(mem_ctx, line);
++
++    free(line);
++    line = NULL;
++
++    if (tcline == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
++        return ENOMEM;
++    }
++
++    rest = tcline;
++    for (i = 0; table[i].type != SSS_COLONDB_SENTINEL; i++) {
++        switch (table[i].type) {
++        case SSS_COLONDB_UINT32:
++            rest = read_field_as_uint32(rest, table[i].data.uint32);
++            break;
++        case SSS_COLONDB_STRING:
++            rest = read_field_as_string(rest, table[i].data.str);
++            break;
++        case SSS_COLONDB_SENTINEL:
++            DEBUG(SSSDBG_CRIT_FAILURE, "Trying to process sentinel?!\n");
++            ret = ERR_INTERNAL;
++            goto done;
++        }
++
++        if (rest == NULL && table[i + 1].type != SSS_COLONDB_SENTINEL) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Line contains less values than expected!\n");
++            ret = EINVAL;
++            goto done;
++        } else if (rest != NULL && table[i + 1].type == SSS_COLONDB_SENTINEL) {
++            DEBUG(SSSDBG_CRIT_FAILURE,
++                  "Line contains more values than expected!\n");
++            ret = EINVAL;
++            goto done;
++        }
++    }
++
++    ret = EOK;
++
++done:
++    if (ret != EOK) {
++        talloc_free(tcline);
++    }
++
++    return ret;
++}
++
++errno_t sss_colondb_writeline(struct sss_colondb *db,
++                              struct sss_colondb_write_field *table)
++{
++    TALLOC_CTX *tmp_ctx;
++    char *line = NULL;
++    errno_t ret;
++    int i;
++
++    if (db->mode != SSS_COLONDB_WRITE) {
++        return ERR_INTERNAL;
++    }
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
++        return ENOMEM;
++    }
++
++    for (i = 0; table[i].type != SSS_COLONDB_SENTINEL; i++) {
++        switch (table[i].type) {
++        case SSS_COLONDB_UINT32:
++            if (table[i].data.uint32 == 0) {
++                line = talloc_asprintf_append(line, ":");
++            } else {
++                line = talloc_asprintf_append(line, ":%u", table[i].data.uint32);
++            }
++            break;
++        case SSS_COLONDB_STRING:
++            if (table[i].data.str == NULL) {
++                line = talloc_asprintf_append(line, ":");
++            } else {
++                line = talloc_asprintf_append(line, ":%s", table[i].data.str);
++            }
++            break;
++        case SSS_COLONDB_SENTINEL:
++            DEBUG(SSSDBG_CRIT_FAILURE, "Trying to process sentinel?!\n");
++            ret = ERR_INTERNAL;
++            goto done;
++        }
++
++        if (line == NULL) {
++            ret = ENOMEM;
++            goto done;
++        }
++    }
++
++    /* Remove starting : */
++    line++;
++
++    fprintf(db->file, "%s\n", line);
++    fflush(db->file);
++
++    ret = EOK;
++
++done:
++    talloc_free(tmp_ctx);
++
++    return ret;
++}
++
++static int sss_colondb_close(void *pvt)
++{
++    struct sss_colondb *db = talloc_get_type(pvt, struct sss_colondb);
++
++    if (db->file == NULL || IS_STD_FILE(db)) {
++        return 0;
++    }
++
++    fclose(db->file);
++    db->file = NULL;
++
++    return 0;
++}
++
++static FILE *open_db(const char *filename, enum sss_colondb_mode mode)
++{
++    FILE *fp = NULL;
++    errno_t ret;
++
++    errno = 0;
++
++    switch (mode) {
++    case SSS_COLONDB_READ:
++        fp = filename == NULL ? stdin : fopen(filename, "r");
++        break;
++    case SSS_COLONDB_WRITE:
++        fp = filename == NULL ? stdout : fopen(filename, "w");
++        break;
++    }
++
++    if (fp == NULL && filename != NULL) {
++        ret = errno;
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to open file %s [%d]: %s\n",
++              filename, ret, sss_strerror(ret));
++    }
++
++    return fp;
++}
++
++struct sss_colondb *sss_colondb_open(TALLOC_CTX *mem_ctx,
++                                     enum sss_colondb_mode mode,
++                                     const char *filename)
++{
++    struct sss_colondb *db;
++
++    db = talloc_zero(mem_ctx, struct sss_colondb);
++    if (db == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n");
++        return NULL;
++    }
++
++    db->file = open_db(filename, mode);
++    db->mode = mode;
++
++    if (db->file == NULL) {
++        talloc_free(db);
++        return NULL;
++    }
++
++    talloc_set_destructor((TALLOC_CTX *)db, sss_colondb_close);
++
++    return db;
++}
+diff --git a/src/tools/common/sss_colondb.h b/src/tools/common/sss_colondb.h
+new file mode 100644
+index 0000000000000000000000000000000000000000..6edd99cbe3b9ef5c86a48632ac3fc71e8a3e55fe
+--- /dev/null
++++ b/src/tools/common/sss_colondb.h
+@@ -0,0 +1,73 @@
++/*
++    Authors:
++        Pavel Březina <pbrezina@redhat.com>
++
++    Copyright (C) 2015 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 _SSS_COLONDB_H_
++#define _SSS_COLONDB_H_
++
++#include <stdlib.h>
++#include <stdint.h>
++#include <errno.h>
++#include <talloc.h>
++
++struct sss_colondb;
++
++enum sss_colondb_mode {
++    SSS_COLONDB_READ,
++    SSS_COLONDB_WRITE
++};
++
++enum sss_colondb_type {
++    SSS_COLONDB_UINT32,
++    SSS_COLONDB_STRING,
++    SSS_COLONDB_SENTINEL
++};
++
++union sss_colondb_write_data {
++    uint32_t uint32;
++    const char *str;
++};
++
++union sss_colondb_read_data {
++    uint32_t *uint32;
++    const char **str;
++};
++
++struct sss_colondb_write_field {
++    enum sss_colondb_type type;
++    union sss_colondb_write_data data;
++};
++
++struct sss_colondb_read_field {
++    enum sss_colondb_type type;
++    union sss_colondb_read_data data;
++};
++
++struct sss_colondb *sss_colondb_open(TALLOC_CTX *mem_ctx,
++                                     enum sss_colondb_mode mode,
++                                     const char *filename);
++
++errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx,
++                             struct sss_colondb *db,
++                             struct sss_colondb_read_field *table);
++
++errno_t sss_colondb_writeline(struct sss_colondb *db,
++                              struct sss_colondb_write_field *table);
++
++#endif /* _SSS_COLONDB_H_ */
+-- 
+2.4.3
+
diff --git a/SOURCES/0064-Add-ssh-pubkey-to-origbyname-request.patch b/SOURCES/0064-Add-ssh-pubkey-to-origbyname-request.patch
deleted file mode 100644
index c9cd2be..0000000
--- a/SOURCES/0064-Add-ssh-pubkey-to-origbyname-request.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From c6a29b0121b64bbe6b81f2d61c81c480bbf1a858 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 4 Nov 2014 13:58:39 +0100
-Subject: [PATCH 64/64] Add ssh pubkey to origbyname request
-
-Since the IPA clients expects that the extdom plugin delivers the
-default view data for a given user this patch adds the public SSH key to
-the list of returned attributes of the getorigbyname request so that it
-can be send back to the clients.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/responder/nss/nsssrv_cmd.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index ff7b6a334f4c1d9dc854296746b0ff83949acd68..c9c09a082b67741e1d229b419aa7c3ecbf195ddd 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4159,6 +4159,7 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
-                                    SYSDB_DEFAULT_OVERRIDE_NAME,
-                                    SYSDB_AD_ACCOUNT_EXPIRES,
-                                    SYSDB_AD_USER_ACCOUNT_CONTROL,
-+                                   SYSDB_SSH_PUBKEY,
-                                    SYSDB_DEFAULT_ATTRS, NULL};
-     const char **attrs;
-     bool user_found = false;
-@@ -4632,6 +4633,7 @@ static errno_t fill_orig(struct sss_packet *packet,
-                                     SYSDB_DEFAULT_OVERRIDE_NAME,
-                                     SYSDB_AD_ACCOUNT_EXPIRES,
-                                     SYSDB_AD_USER_ACCOUNT_CONTROL,
-+                                    SYSDB_SSH_PUBKEY,
-                                     NULL};
-     struct sized_string *keys;
-     struct sized_string *vals;
--- 
-1.9.3
-
diff --git a/SOURCES/0064-sss_override-decompose-code-better.patch b/SOURCES/0064-sss_override-decompose-code-better.patch
new file mode 100644
index 0000000..d1d078a
--- /dev/null
+++ b/SOURCES/0064-sss_override-decompose-code-better.patch
@@ -0,0 +1,478 @@
+From fdc64e169e988c4d1bc105ad6ccdfe4817db4c53 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 19 Aug 2015 12:43:15 +0200
+Subject: [PATCH 64/66] sss_override: decompose code better
+
+Preparation for:
+https://fedorahosted.org/sssd/ticket/2737
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/tools/sss_override.c | 290 +++++++++++++++++++++++++++++------------------
+ 1 file changed, 181 insertions(+), 109 deletions(-)
+
+diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c
+index 84b51c537842b7281a523f58c2cfbdfd38e54c72..9e2ce3325c0bfa33fadb970f725098d7d12ac432 100644
+--- a/src/tools/sss_override.c
++++ b/src/tools/sss_override.c
+@@ -171,6 +171,22 @@ done:
+     return ret;
+ }
+ 
++errno_t prepare_view_msg(struct sss_domain_info *domain)
++{
++    errno_t ret;
++
++    ret = prepare_view(domain);
++    if (ret == EEXIST) {
++        fprintf(stderr, _("Other than " LOCALVIEW " view already exist "
++                "in domain %s.\n"), domain->name);
++    } else if (ret != EOK) {
++        fprintf(stderr, _("Unable to prepare " LOCALVIEW
++                " view in domain %s.\n"), domain->name);
++    }
++
++    return ret;
++}
++
+ static char *build_anchor(TALLOC_CTX *mem_ctx, const char *obj_dn)
+ {
+     char *anchor;
+@@ -320,17 +336,15 @@ static char *get_sysname(TALLOC_CTX *mem_ctx,
+     return get_fqname(mem_ctx, domain, name);
+ }
+ 
+-static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx,
+-                                         enum sysdb_member_type type,
+-                                         const char *name,
+-                                         struct sss_domain_info *domain,
+-                                         struct sss_domain_info *domains,
+-                                         struct sss_domain_info **_new_domain)
++static struct sss_domain_info *
++get_object_domain(enum sysdb_member_type type,
++                  const char *name,
++                  struct sss_domain_info *domain,
++                  struct sss_domain_info *domains)
+ {
+     TALLOC_CTX *tmp_ctx;
+     struct sss_domain_info *dom;
+     struct ldb_result *res;
+-    const char *dn;
+     const char *strtype;
+     char *sysname;
+     bool check_next;
+@@ -427,18 +441,6 @@ static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx,
+     DEBUG(SSSDBG_TRACE_FUNC, "Domain of %s %s is %s\n",
+           strtype, name, dom->name);
+ 
+-    dn = ldb_dn_get_linearized(res->msgs[0]->dn);
+-    if (dn == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized() failed.\n");
+-        ret = ENOMEM;
+-        goto done;
+-    }
+-
+-    talloc_steal(mem_ctx, dn);
+-    *_new_domain = dom;
+-
+-    ret = EOK;
+-
+ done:
+     talloc_free(tmp_ctx);
+ 
+@@ -446,35 +448,94 @@ done:
+         return NULL;
+     }
+ 
+-    return dn;
++    return dom;
+ }
+ 
+-static const char * get_user_dn_and_domain(TALLOC_CTX *mem_ctx,
+-                                           struct sss_domain_info *domains,
+-                                           struct override_user *user)
++static errno_t get_user_domain_msg(struct sss_tool_ctx *tool_ctx,
++                                   struct override_user *user)
+ {
+-    return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_USER,
+-                         user->orig_name, user->domain, domains,
+-                         &user->domain);
++    struct sss_domain_info *newdom;
++    const char *domname;
++
++    newdom = get_object_domain(SYSDB_MEMBER_USER, user->orig_name,
++                               user->domain, tool_ctx->domains);
++    if (newdom == NULL) {
++        domname = user->domain == NULL ? "[unknown]" : user->domain->name;
++        fprintf(stderr, _("Unable to find user %s@%s.\n"),
++                user->orig_name, domname);
++        return ENOENT;
++    }
++
++    user->domain = newdom;
++    return EOK;
++}
++
++static errno_t get_group_domain_msg(struct sss_tool_ctx *tool_ctx,
++                                    struct override_group *group)
++{
++    struct sss_domain_info *newdom;
++    const char *domname;
++
++    newdom = get_object_domain(SYSDB_MEMBER_GROUP, group->orig_name,
++                               group->domain, tool_ctx->domains);
++    if (newdom == NULL) {
++        domname = group->domain == NULL ? "[unknown]" : group->domain->name;
++        fprintf(stderr, _("Unable to find group %s@%s.\n"),
++                group->orig_name, domname);
++        return ENOENT;
++    }
++
++    group->domain = newdom;
++    return EOK;
+ }
+ 
+-static const char * get_group_dn_and_domain(TALLOC_CTX *mem_ctx,
+-                                            struct sss_domain_info *domains,
+-                                            struct override_group *group)
++static errno_t get_object_dn(TALLOC_CTX *mem_ctx,
++                             struct sss_domain_info *domain,
++                             enum sysdb_member_type type,
++                             const char *name,
++                             struct ldb_dn **_ldb_dn,
++                             const char **_str_dn)
+ {
+-    return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_GROUP,
+-                         group->orig_name, group->domain, domains,
+-                         &group->domain);
++    struct ldb_dn *ldb_dn;
++
++    switch (type) {
++    case SYSDB_MEMBER_USER:
++       ldb_dn = sysdb_user_dn(mem_ctx, domain, name);
++       break;
++    case SYSDB_MEMBER_GROUP:
++       ldb_dn = sysdb_group_dn(mem_ctx, domain, name);
++       break;
++    default:
++       DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type);
++       return ERR_INTERNAL;
++    }
++
++    if (ldb_dn == NULL) {
++        return ENOMEM;
++    }
++
++    if (_str_dn != NULL) {
++        *_str_dn = ldb_dn_get_linearized(ldb_dn);
++    }
++
++    if (_ldb_dn != NULL) {
++        *_ldb_dn = ldb_dn;
++    } else {
++        talloc_free(ldb_dn);
++    }
++
++    return EOK;
+ }
+ 
+ static errno_t override_object_add(struct sss_domain_info *domain,
+                                    enum sysdb_member_type type,
+                                    struct sysdb_attrs *attrs,
+-                                   const char *obj_dn)
++                                   const char *name)
+ {
+     TALLOC_CTX *tmp_ctx;
+     const char *anchor;
+     struct ldb_dn *ldb_dn;
++    const char *str_dn;
+     errno_t ret;
+ 
+     tmp_ctx = talloc_new(NULL);
+@@ -482,13 +543,12 @@ static errno_t override_object_add(struct sss_domain_info *domain,
+         return ENOMEM;
+     }
+ 
+-    ldb_dn = ldb_dn_new(tmp_ctx, sysdb_ctx_get_ldb(domain->sysdb), obj_dn);
+-    if (ldb_dn == NULL) {
+-        ret = ENOMEM;
++    ret = get_object_dn(tmp_ctx, domain, type, name, &ldb_dn, &str_dn);
++    if (ret != EOK) {
+         goto done;
+     }
+ 
+-    anchor = build_anchor(tmp_ctx, obj_dn);
++    anchor = build_anchor(tmp_ctx, str_dn);
+     if (anchor == NULL) {
+         ret = ENOMEM;
+         goto done;
+@@ -499,7 +559,7 @@ static errno_t override_object_add(struct sss_domain_info *domain,
+         goto done;
+     }
+ 
+-    DEBUG(SSSDBG_TRACE_FUNC, "Creating override for %s\n", obj_dn);
++    DEBUG(SSSDBG_TRACE_FUNC, "Creating override for %s\n", str_dn);
+ 
+     ret = sysdb_store_override(domain, LOCALVIEW, type, attrs, ldb_dn);
+ 
+@@ -508,13 +568,70 @@ done:
+     return ret;
+ }
+ 
++static errno_t override_user(struct sss_tool_ctx *tool_ctx,
++                             struct override_user *user)
++{
++    struct sysdb_attrs *attrs;
++    errno_t ret;
++
++    ret = prepare_view_msg(user->domain);
++    if (ret != EOK) {
++        return ret;
++    }
++
++    attrs = build_user_attrs(tool_ctx, user);
++    if (attrs == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
++        return ENOMEM;
++    }
++
++    ret = override_object_add(user->domain, SYSDB_MEMBER_USER, attrs,
++                              user->orig_name);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        return ret;
++    }
++
++    return EOK;
++}
++
++static errno_t override_group(struct sss_tool_ctx *tool_ctx,
++                              struct override_group *group)
++{
++    struct sysdb_attrs *attrs;
++    errno_t ret;
++
++    ret = prepare_view_msg(group->domain);
++    if (ret != EOK) {
++        return ret;
++    }
++
++    attrs = build_group_attrs(tool_ctx, group);
++    if (attrs == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
++        return ENOMEM;
++    }
++
++    ret = override_object_add(group->domain, SYSDB_MEMBER_GROUP, attrs,
++                              group->orig_name);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        return ret;
++    }
++
++    return EOK;
++}
++
+ static errno_t override_object_del(struct sss_domain_info *domain,
+-                                   const char *obj_dn)
++                                   enum sysdb_member_type type,
++                                   const char *name)
+ {
+     TALLOC_CTX *tmp_ctx;
+-    const char *anchor;
+-    struct ldb_dn *override_dn;
+     struct ldb_message *msg;
++    struct ldb_dn *override_dn;
++    struct ldb_dn *ldb_dn;
++    const char *str_dn;
++    const char *anchor;
+     errno_t ret;
+     int sret;
+     bool in_transaction = false;
+@@ -525,7 +642,12 @@ static errno_t override_object_del(struct sss_domain_info *domain,
+         return ENOMEM;
+     }
+ 
+-    anchor = build_anchor(tmp_ctx, obj_dn);
++    ret = get_object_dn(tmp_ctx, domain, type, name, &ldb_dn, &str_dn);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    anchor = build_anchor(tmp_ctx, str_dn);
+     if (anchor == NULL) {
+         ret = ENOMEM;
+         goto done;
+@@ -538,7 +660,7 @@ static errno_t override_object_del(struct sss_domain_info *domain,
+         goto done;
+     }
+ 
+-    DEBUG(SSSDBG_TRACE_FUNC, "Removing override for %s\n", obj_dn);
++    DEBUG(SSSDBG_TRACE_FUNC, "Removing override for %s\n", str_dn);
+ 
+     ret = sysdb_transaction_start(domain->sysdb);
+     if (ret != EOK) {
+@@ -559,7 +681,7 @@ static errno_t override_object_del(struct sss_domain_info *domain,
+         goto done;
+     }
+ 
+-    msg->dn = ldb_dn_new(msg, ldb, obj_dn);
++    msg->dn = talloc_steal(msg, ldb_dn);
+     if (msg->dn == NULL) {
+         ret = ENOMEM;
+         goto done;
+@@ -607,8 +729,6 @@ static int override_user_add(struct sss_cmdline *cmdline,
+                              void *pvt)
+ {
+     struct override_user user = {NULL};
+-    struct sysdb_attrs *attrs;
+-    const char *dn;
+     int ret;
+ 
+     ret = parse_cmdline_user_add(cmdline, tool_ctx, &user);
+@@ -617,34 +737,13 @@ static int override_user_add(struct sss_cmdline *cmdline,
+         return EXIT_FAILURE;
+     }
+ 
+-    dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user);
+-    if (dn == NULL) {
+-        fprintf(stderr, _("Unable to find user %s@%s.\n"),
+-                user.orig_name,
+-                user.domain == NULL ? "[unknown]" : user.domain->name);
+-        return EXIT_FAILURE;
+-    }
+-
+-    ret = prepare_view(user.domain);
+-    if (ret == EEXIST) {
+-        fprintf(stderr, _("Other than LOCAL view already exist in "
+-                "domain %s.\n"), user.domain->name);
+-        return EXIT_FAILURE;
+-    } else if (ret != EOK) {
+-        fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"),
+-                ret, sss_strerror(ret));
+-        return EXIT_FAILURE;
+-    }
+-
+-    attrs = build_user_attrs(tool_ctx, &user);
+-    if (attrs == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
++    ret = get_user_domain_msg(tool_ctx, &user);
++    if (ret != EOK) {
+         return EXIT_FAILURE;
+     }
+ 
+-    ret = override_object_add(user.domain, SYSDB_MEMBER_USER, attrs, dn);
++    ret = override_user(tool_ctx, &user);
+     if (ret != EOK) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
+         return EXIT_FAILURE;
+     }
+ 
+@@ -656,7 +755,6 @@ static int override_user_del(struct sss_cmdline *cmdline,
+                              void *pvt)
+ {
+     struct override_user user = {NULL};
+-    const char *dn;
+     int ret;
+ 
+     ret = parse_cmdline_user_del(cmdline, tool_ctx, &user);
+@@ -665,16 +763,14 @@ static int override_user_del(struct sss_cmdline *cmdline,
+         return EXIT_FAILURE;
+     }
+ 
+-    dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user);
+-    if (dn == NULL) {
+-        fprintf(stderr, _("Unable to find user %s@%s.\n"),
+-                user.orig_name, user.domain->name);
++    ret = get_user_domain_msg(tool_ctx, &user);
++    if (ret != EOK) {
+         return EXIT_FAILURE;
+     }
+ 
+-    ret = override_object_del(user.domain, dn);
++    ret = override_object_del(user.domain, SYSDB_MEMBER_USER, user.orig_name);
+     if (ret != EOK) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to delete override object.\n");
+         return EXIT_FAILURE;
+     }
+ 
+@@ -686,8 +782,6 @@ static int override_group_add(struct sss_cmdline *cmdline,
+                               void *pvt)
+ {
+     struct override_group group = {NULL};
+-    struct sysdb_attrs *attrs;
+-    const char *dn;
+     int ret;
+ 
+     ret = parse_cmdline_group_add(cmdline, tool_ctx, &group);
+@@ -696,33 +790,13 @@ static int override_group_add(struct sss_cmdline *cmdline,
+         return EXIT_FAILURE;
+     }
+ 
+-    dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group);
+-    if (dn == NULL) {
+-        fprintf(stderr, _("Unable to find group %s@%s.\n"),
+-                group.orig_name, group.domain->name);
+-        return EXIT_FAILURE;
+-    }
+-
+-    ret = prepare_view(group.domain);
+-    if (ret == EEXIST) {
+-        fprintf(stderr, _("Other than LOCAL view already exist in "
+-                "domain %s.\n"), group.domain->name);
+-        return EXIT_FAILURE;
+-    } else if (ret != EOK) {
+-        fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"),
+-                ret, sss_strerror(ret));
+-        return EXIT_FAILURE;
+-    }
+-
+-    attrs = build_group_attrs(tool_ctx, &group);
+-    if (attrs == NULL) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
++    ret = get_group_domain_msg(tool_ctx, &group);
++    if (ret != EOK) {
+         return EXIT_FAILURE;
+     }
+ 
+-    ret = override_object_add(group.domain, SYSDB_MEMBER_GROUP, attrs, dn);
++    ret = override_group(tool_ctx, &group);
+     if (ret != EOK) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
+         return EXIT_FAILURE;
+     }
+ 
+@@ -734,7 +808,6 @@ static int override_group_del(struct sss_cmdline *cmdline,
+                               void *pvt)
+ {
+     struct override_group group = {NULL};
+-    const char *dn;
+     int ret;
+ 
+     ret = parse_cmdline_group_del(cmdline, tool_ctx, &group);
+@@ -743,16 +816,15 @@ static int override_group_del(struct sss_cmdline *cmdline,
+         return EXIT_FAILURE;
+     }
+ 
+-    dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group);
+-    if (dn == NULL) {
+-        fprintf(stderr, _("Unable to find group %s@%s.\n"),
+-                group.orig_name, group.domain->name);
++    ret = get_group_domain_msg(tool_ctx, &group);
++    if (ret != EOK) {
+         return EXIT_FAILURE;
+     }
+ 
+-    ret = override_object_del(group.domain, dn);
++    ret = override_object_del(group.domain, SYSDB_MEMBER_GROUP,
++                              group.orig_name);
+     if (ret != EOK) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to delete override object.\n");
+         return EXIT_FAILURE;
+     }
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0065-BUILD-Install-ldap_child-and-as-setuid-if-running-un.patch b/SOURCES/0065-BUILD-Install-ldap_child-and-as-setuid-if-running-un.patch
deleted file mode 100644
index a15d69a..0000000
--- a/SOURCES/0065-BUILD-Install-ldap_child-and-as-setuid-if-running-un.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From fe5108b091e77dac505fd433c2df9c8b5736b21f Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sat, 11 Oct 2014 20:22:42 +0200
-Subject: [PATCH 65/71] BUILD: Install ldap_child and as setuid if running
- under non-privileged user
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The ldap_child permissions should be 4750, owned by root.sssd,
-to make sure only root and sssd can execute the child and if executed by
-sssd, the child will run as root.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- Makefile.am          | 5 +++++
- contrib/sssd.spec.in | 2 +-
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 60bc67f1ac60c72dc64b3d1adccc9ef1ec989ad5..02b087ea37b4e55da7eeb7fb199d282d72129e40 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2844,6 +2844,11 @@ else
- 	$(MKDIR_P) $(DESTDIR)$(initdir)
- endif
- 
-+if SSSD_USER
-+	chgrp $(SSSD_USER) $(sssdlibexecdir)/ldap_child
-+	chmod 4750 $(sssdlibexecdir)/ldap_child
-+endif
-+
- install-data-hook:
- 	rm $(DESTDIR)/$(nsslibdir)/libnss_sss.so.2 \
-        $(DESTDIR)/$(nsslibdir)/libnss_sss.so
-diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
-index db3bbcb09d6b27ca785f511ce6414fbeaaf445c6..d2e6cec2610e4c00cb376683cf7e64eb5cdafc5c 100644
---- a/contrib/sssd.spec.in
-+++ b/contrib/sssd.spec.in
-@@ -645,7 +645,7 @@ rm -rf $RPM_BUILD_ROOT
- %defattr(-,root,root,-)
- %doc COPYING
- %{_libdir}/%{name}/libsss_krb5_common.so
--%{_libexecdir}/%{servicename}/ldap_child
-+%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/ldap_child
- %{_libexecdir}/%{servicename}/krb5_child
- 
- %files krb5 -f sssd_krb5.lang
--- 
-1.9.3
-
diff --git a/SOURCES/0065-sss_override-support-import-and-export.patch b/SOURCES/0065-sss_override-support-import-and-export.patch
new file mode 100644
index 0000000..f9d2098
--- /dev/null
+++ b/SOURCES/0065-sss_override-support-import-and-export.patch
@@ -0,0 +1,794 @@
+From ee8f6d929ab3a047e05b4522cb0d61273293e2c4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Wed, 19 Aug 2015 12:35:12 +0200
+Subject: [PATCH 65/66] sss_override: support import and export
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2737
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ Makefile.am                |   2 +
+ src/man/sss_override.8.xml |  88 +++++++
+ src/tools/sss_override.c   | 588 ++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 675 insertions(+), 3 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 7dc4875c9cb05bf146505c0dc0dab543fb326bd3..e1102333b019e32c516c59c5fa969c970b688737 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -651,6 +651,7 @@ dist_noinst_HEADERS = \
+     src/lib/sifp/sss_sifp_private.h \
+     src/tests/cmocka/test_utils.h \
+     src/tools/common/sss_tools.h \
++    src/tools/common/sss_colondb.h \
+     $(NULL)
+ 
+ 
+@@ -1331,6 +1332,7 @@ sss_signal_LDADD = \
+ 
+ sss_override_SOURCES = \
+     src/tools/sss_override.c \
++    src/tools/common/sss_colondb.c \
+     $(SSSD_TOOLS_OBJ) \
+     $(NULL)
+ sss_override_LDADD = \
+diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml
+index ec9a7bb75c13f4f18ece7f5f84baede14a8a1e2e..d289f5b7dfa7fbd328831b4c71d45b4c555225cf 100644
+--- a/src/man/sss_override.8.xml
++++ b/src/man/sss_override.8.xml
+@@ -77,6 +77,50 @@
+             </varlistentry>
+             <varlistentry>
+                 <term>
++                    <option>user-import</option>
++                    <emphasis>FILE</emphasis>
++                </term>
++                <listitem>
++                    <para>
++                        Import user overrides from <emphasis>FILE</emphasis>.
++                        Data format is similar to standard passwd file.
++                        The format is:
++                    </para>
++                    <para>
++                        original_name:name:uid:gid:gecos:home:shell
++                    </para>
++                    <para>
++                        where original_name is original name of the user whose
++                        attributes should be overridden. The rest of fields
++                        correspond to new values. You can omit a value simply
++                        by leaving corresponding field empty.
++                    </para>
++                    <para>
++                        Examples:
++                    </para>
++                    <para>
++                        ckent:superman::::::
++                    </para>
++                    <para>
++                        ckent@krypton.com::501:501:Superman:/home/earth:/bin/bash
++                    </para>
++                </listitem>
++            </varlistentry>
++            <varlistentry>
++                <term>
++                    <option>user-export</option>
++                    <emphasis>FILE</emphasis>
++                </term>
++                <listitem>
++                    <para>
++                        Export all overridden attributes and store them in
++                        <emphasis>FILE</emphasis>. See
++                        <emphasis>user-import</emphasis> for data format.
++                    </para>
++                </listitem>
++            </varlistentry>
++            <varlistentry>
++                <term>
+                     <option>group-add</option>
+                     <emphasis>NAME</emphasis>
+                     <optional><option>-n,--name</option> NAME</optional>
+@@ -99,6 +143,50 @@
+                     </para>
+                 </listitem>
+             </varlistentry>
++            <varlistentry>
++                <term>
++                    <option>group-import</option>
++                    <emphasis>FILE</emphasis>
++                </term>
++                <listitem>
++                    <para>
++                        Import group overrides from <emphasis>FILE</emphasis>.
++                        Data format is similar to standard group file.
++                        The format is:
++                    </para>
++                    <para>
++                        original_name:name:gid
++                    </para>
++                    <para>
++                        where original_name is original name of the group whose
++                        attributes should be overridden. The rest of fields
++                        correspond to new values. You can omit a value simply
++                        by leaving corresponding field empty.
++                    </para>
++                    <para>
++                        Examples:
++                    </para>
++                    <para>
++                        admins:administrators:
++                    </para>
++                    <para>
++                        Domain Users:Users:501
++                    </para>
++                </listitem>
++            </varlistentry>
++            <varlistentry>
++                <term>
++                    <option>group-export</option>
++                    <emphasis>FILE</emphasis>
++                </term>
++                <listitem>
++                    <para>
++                        Export all overridden attributes and store them in
++                        <emphasis>FILE</emphasis>. See
++                        <emphasis>group-import</emphasis> for data format.
++                    </para>
++                </listitem>
++            </varlistentry>
+         </variablelist>
+     </refsect1>
+ 
+diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c
+index 9e2ce3325c0bfa33fadb970f725098d7d12ac432..ee8351ea97e5efe0d449dc646c6136b32ceec2c6 100644
+--- a/src/tools/sss_override.c
++++ b/src/tools/sss_override.c
+@@ -23,8 +23,10 @@
+ #include "util/util.h"
+ #include "db/sysdb.h"
+ #include "tools/common/sss_tools.h"
++#include "tools/common/sss_colondb.h"
+ 
+ #define LOCALVIEW SYSDB_LOCAL_VIEW_NAME
++#define ORIGNAME "originalName"
+ 
+ struct override_user {
+     const char *input_name;
+@@ -135,6 +137,40 @@ static int parse_cmdline_group_del(struct sss_cmdline *cmdline,
+                          &group->orig_name, &group->domain);
+ }
+ 
++static int parse_cmdline_import(struct sss_cmdline *cmdline,
++                                struct sss_tool_ctx *tool_ctx,
++                                const char **_file)
++{
++    int ret;
++
++    ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL,
++                           NULL, NULL, "FILE", "File to import the data from.",
++                           _file);
++    if (ret != EXIT_SUCCESS) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
++        return ret;
++    }
++
++    return EXIT_SUCCESS;
++}
++
++static int parse_cmdline_export(struct sss_cmdline *cmdline,
++                                struct sss_tool_ctx *tool_ctx,
++                                const char **_file)
++{
++    int ret;
++
++    ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL,
++                           NULL, NULL, "FILE", "File to export the data to.",
++                           _file);
++    if (ret != EXIT_SUCCESS) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
++        return ret;
++    }
++
++    return EXIT_SUCCESS;
++}
++
+ static errno_t prepare_view(struct sss_domain_info *domain)
+ {
+     char *viewname = NULL;
+@@ -293,8 +329,8 @@ static char *get_fqname(TALLOC_CTX *mem_ctx,
+                         const char *name)
+ {
+     char *fqname;
+-    size_t fqlen;
+-    size_t check;
++    int fqlen;
++    int check;
+ 
+     if (domain == NULL) {
+         return NULL;
+@@ -315,7 +351,7 @@ static char *get_fqname(TALLOC_CTX *mem_ctx,
+     }
+ 
+     check = sss_fqname(fqname, fqlen, domain->names, domain, name);
+-    if (check != fqlen - 1) {
++    if (check < 0 || check != fqlen - 1) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate a fully qualified name "
+               "for user [%s] in [%s]! Skipping user.\n", name, domain->name);
+         talloc_free(fqname);
+@@ -724,6 +760,246 @@ done:
+     return ret;
+ }
+ 
++static errno_t append_name(struct sss_domain_info *domain,
++                           struct ldb_message *override)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
++    struct ldb_dn *dn;
++    struct ldb_message **msgs;
++    const char *attrs[] = {SYSDB_NAME, NULL};
++    const char *name;
++    const char *fqname;
++    size_t count;
++    errno_t ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
++        return ENOMEM;
++    }
++
++    dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, override,
++                                 SYSDB_OVERRIDE_OBJECT_DN);
++    if (dn == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Missing overrideObjectDN?\n");
++        ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_BASE,
++                             NULL, attrs, &count, &msgs);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n",
++              ret, sss_strerror(ret));
++        goto done;
++    } else if (count != 1) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "More than one user found?\n");
++        ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
++    if (name == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Object with no name?\n");
++        ret = ERR_INTERNAL;
++        goto done;
++    }
++
++    fqname = get_fqname(tmp_ctx, domain, name);
++    if (fqname == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get fqname\n");
++        ret = ENOMEM;
++        goto done;
++    }
++
++    ret = ldb_msg_add_string(override, ORIGNAME, fqname);
++    if (ret != LDB_SUCCESS) {
++        ret = sysdb_error_to_errno(ret);
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute to msg\n");
++        goto done;
++    }
++
++    talloc_steal(override, fqname);
++
++done:
++    talloc_free(tmp_ctx);
++
++    return ret;
++}
++
++static errno_t list_overrides(TALLOC_CTX *mem_ctx,
++                              const char *filter,
++                              const char **attrs,
++                              struct sss_domain_info *domain,
++                              size_t *_count,
++                              struct ldb_message ***_msgs)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct ldb_dn *dn;
++    struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
++    size_t count;
++    struct ldb_message **msgs;
++    size_t i;
++    int ret;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
++        return ENOMEM;
++    }
++
++    /* Acquire list of override objects. */
++    dn = ldb_dn_new_fmt(tmp_ctx, ldb, SYSDB_TMPL_VIEW_SEARCH_BASE, LOCALVIEW);
++    if (dn == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt() failed.\n");
++        ret = EIO;
++        goto done;
++    }
++
++    ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_SUBTREE,
++                             filter, attrs, &count, &msgs);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n",
++              ret, sss_strerror(ret));
++        goto done;
++    }
++
++    /* Amend messages with original name. */
++    for (i = 0; i < count; i++) {
++        ret = append_name(domain, msgs[i]);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to append name [%d]: %s\n",
++                  ret, sss_strerror(ret));
++            goto done;
++        }
++    }
++
++    *_msgs = talloc_steal(mem_ctx, msgs);
++    *_count = count;
++
++    ret = EOK;
++
++done:
++    talloc_free(tmp_ctx);
++
++    return ret;
++}
++
++static struct override_user *
++list_user_overrides(TALLOC_CTX *mem_ctx,
++                    struct sss_domain_info *domain)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct override_user *objs;
++    struct ldb_message **msgs;
++    size_t count;
++    size_t i;
++    errno_t ret;
++    const char *attrs[] = SYSDB_PW_ATTRS;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
++        return NULL;
++    }
++
++    ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_USER_CLASS ")",
++                         attrs, domain, &count, &msgs);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    objs = talloc_zero_array(tmp_ctx, struct override_user, count + 1);
++    if (objs == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    for (i = 0; i < count; i++) {
++        objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME,
++                                                        NULL);
++        if (objs[i].orig_name == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n");
++            ret = ERR_INTERNAL;
++            goto done;
++        }
++
++        objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
++        objs[i].uid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_UIDNUM, 0);
++        objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0);
++        objs[i].home = ldb_msg_find_attr_as_string(msgs[i], SYSDB_HOMEDIR, NULL);
++        objs[i].shell = ldb_msg_find_attr_as_string(msgs[i], SYSDB_SHELL, NULL);
++        objs[i].gecos = ldb_msg_find_attr_as_string(msgs[i], SYSDB_GECOS, NULL);
++    }
++
++    talloc_steal(mem_ctx, objs);
++
++done:
++    talloc_free(tmp_ctx);
++
++    if (ret != EOK) {
++        return NULL;
++    }
++
++    return objs;
++}
++
++static struct override_group *
++list_group_overrides(TALLOC_CTX *mem_ctx,
++                     struct sss_domain_info *domain)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct override_group *objs;
++    struct ldb_message **msgs;
++    size_t count;
++    size_t i;
++    errno_t ret;
++    const char *attrs[] = SYSDB_GRSRC_ATTRS;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
++        return NULL;
++    }
++
++    ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_GROUP_CLASS ")",
++                         attrs, domain, &count, &msgs);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    objs = talloc_zero_array(tmp_ctx, struct override_group, count + 1);
++    if (objs == NULL) {
++        ret = ENOMEM;
++        goto done;
++    }
++
++    for (i = 0; i < count; i++) {
++        objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME,
++                                                        NULL);
++        if (objs[i].orig_name == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n");
++            ret = ERR_INTERNAL;
++            goto done;
++        }
++
++        objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
++        objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0);
++    }
++
++    talloc_steal(mem_ctx, objs);
++
++done:
++    talloc_free(tmp_ctx);
++
++    if (ret != EOK) {
++        return NULL;
++    }
++
++    return objs;
++}
++
+ static int override_user_add(struct sss_cmdline *cmdline,
+                              struct sss_tool_ctx *tool_ctx,
+                              void *pvt)
+@@ -777,6 +1053,161 @@ static int override_user_del(struct sss_cmdline *cmdline,
+     return EXIT_SUCCESS;
+ }
+ 
++static int override_user_import(struct sss_cmdline *cmdline,
++                                struct sss_tool_ctx *tool_ctx,
++                                void *pvt)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct sss_colondb *db;
++    const char *filename;
++    struct override_user obj;
++    int linenum = 1;
++    errno_t ret;
++    int exit;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
++        return EXIT_FAILURE;
++    }
++
++    /**
++     * Format: orig_name:name:uid:gid:gecos:home:shell
++     */
++    struct sss_colondb_read_field table[] = {
++        {SSS_COLONDB_STRING, {.str = &obj.input_name}},
++        {SSS_COLONDB_STRING, {.str = &obj.name}},
++        {SSS_COLONDB_UINT32, {.uint32 = &obj.uid}},
++        {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}},
++        {SSS_COLONDB_STRING, {.str = &obj.gecos}},
++        {SSS_COLONDB_STRING, {.str = &obj.home}},
++        {SSS_COLONDB_STRING, {.str = &obj.shell}},
++        {SSS_COLONDB_SENTINEL, {0}}
++    };
++
++    ret = parse_cmdline_import(cmdline, tool_ctx, &filename);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename);
++    if (db == NULL) {
++        fprintf(stderr, _("Unable to open %s.\n"), filename);
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) {
++        linenum++;
++
++        ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name,
++                                  &obj.orig_name, &obj.domain);
++        if (ret != EOK) {
++            fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name);
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        ret = get_user_domain_msg(tool_ctx, &obj);
++        if (ret != EOK) {
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        ret = override_user(tool_ctx, &obj);
++        if (ret != EOK) {
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        talloc_free_children(tmp_ctx);
++    }
++
++    if (ret != EOF) {
++        fprintf(stderr, _("Invalid format on line %d. "
++                "Use --debug option for more information.\n"), linenum);
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    exit = EXIT_SUCCESS;
++
++done:
++    talloc_free(tmp_ctx);
++    return exit;
++}
++
++static int override_user_export(struct sss_cmdline *cmdline,
++                                struct sss_tool_ctx *tool_ctx,
++                                void *pvt)
++{
++    struct sss_colondb *db;
++    const char *filename;
++    struct override_user *objs;
++    struct sss_domain_info *dom;
++    errno_t ret;
++    int exit;
++    int i;
++
++    ret = parse_cmdline_export(cmdline, tool_ctx, &filename);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename);
++    if (db == NULL) {
++        fprintf(stderr, _("Unable to open %s.\n"), filename);
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    dom = tool_ctx->domains;
++    do {
++        objs = list_user_overrides(tool_ctx, tool_ctx->domains);
++        if (objs == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n");
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        for (i = 0; objs[i].orig_name != NULL; i++) {
++            /**
++             * Format: orig_name:name:uid:gid:gecos:home:shell
++             */
++            struct sss_colondb_write_field table[] = {
++                {SSS_COLONDB_STRING, {.str = objs[i].orig_name}},
++                {SSS_COLONDB_STRING, {.str = objs[i].name}},
++                {SSS_COLONDB_UINT32, {.uint32 = objs[i].uid}},
++                {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}},
++                {SSS_COLONDB_STRING, {.str = objs[i].gecos}},
++                {SSS_COLONDB_STRING, {.str = objs[i].home}},
++                {SSS_COLONDB_STRING, {.str = objs[i].shell}},
++                {SSS_COLONDB_SENTINEL, {0}}
++            };
++
++            ret = sss_colondb_writeline(db, table);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n");
++                exit = EXIT_FAILURE;
++                goto done;
++            }
++        }
++
++        /* All overrides are under the same subtree, so we don't want to
++         * descent into subdomains. */
++        dom = get_next_domain(dom, false);
++    } while (dom != NULL);
++
++    exit = EXIT_SUCCESS;
++
++done:
++    return exit;
++}
++
+ static int override_group_add(struct sss_cmdline *cmdline,
+                               struct sss_tool_ctx *tool_ctx,
+                               void *pvt)
+@@ -831,13 +1262,164 @@ static int override_group_del(struct sss_cmdline *cmdline,
+     return EXIT_SUCCESS;
+ }
+ 
++static int override_group_import(struct sss_cmdline *cmdline,
++                                 struct sss_tool_ctx *tool_ctx,
++                                 void *pvt)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct sss_colondb *db;
++    const char *filename;
++    struct override_group obj;
++    int linenum = 1;
++    errno_t ret;
++    int exit;
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
++        return EXIT_FAILURE;
++    }
++
++    /**
++     * Format: orig_name:name:gid
++     */
++    struct sss_colondb_read_field table[] = {
++        {SSS_COLONDB_STRING, {.str = &obj.input_name}},
++        {SSS_COLONDB_STRING, {.str = &obj.name}},
++        {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}},
++        {SSS_COLONDB_SENTINEL, {0}}
++    };
++
++    ret = parse_cmdline_import(cmdline, tool_ctx, &filename);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename);
++    if (db == NULL) {
++        fprintf(stderr, _("Unable to open %s.\n"), filename);
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) {
++        linenum++;
++
++        ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name,
++                                  &obj.orig_name, &obj.domain);
++        if (ret != EOK) {
++            fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name);
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        ret = get_group_domain_msg(tool_ctx, &obj);
++        if (ret != EOK) {
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        ret = override_group(tool_ctx, &obj);
++        if (ret != EOK) {
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        talloc_free_children(tmp_ctx);
++    }
++
++    if (ret != EOF) {
++        fprintf(stderr, _("Invalid format on line %d. "
++                "Use --debug option for more information.\n"), linenum);
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    exit = EXIT_SUCCESS;
++
++done:
++    talloc_free(tmp_ctx);
++    return exit;
++}
++
++static int override_group_export(struct sss_cmdline *cmdline,
++                                 struct sss_tool_ctx *tool_ctx,
++                                 void *pvt)
++{
++    struct sss_colondb *db;
++    const char *filename;
++    struct override_group *objs;
++    struct sss_domain_info *dom;
++    errno_t ret;
++    int exit;
++    int i;
++
++    ret = parse_cmdline_export(cmdline, tool_ctx, &filename);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename);
++    if (db == NULL) {
++        fprintf(stderr, _("Unable to open %s.\n"), filename);
++        exit = EXIT_FAILURE;
++        goto done;
++    }
++
++    dom = tool_ctx->domains;
++    do {
++        objs = list_group_overrides(tool_ctx, tool_ctx->domains);
++        if (objs == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n");
++            exit = EXIT_FAILURE;
++            goto done;
++        }
++
++        for (i = 0; objs[i].orig_name != NULL; i++) {
++            /**
++             * Format: orig_name:name:uid:gid:gecos:home:shell
++             */
++            struct sss_colondb_write_field table[] = {
++                {SSS_COLONDB_STRING, {.str = objs[i].orig_name}},
++                {SSS_COLONDB_STRING, {.str = objs[i].name}},
++                {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}},
++                {SSS_COLONDB_SENTINEL, {0}}
++            };
++
++            ret = sss_colondb_writeline(db, table);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n");
++                exit = EXIT_FAILURE;
++                goto done;
++            }
++        }
++
++        /* All overrides are under the same subtree, so we don't want to
++         * descent into subdomains. */
++        dom = get_next_domain(dom, false);
++    } while (dom != NULL);
++
++    exit = EXIT_SUCCESS;
++
++done:
++    return exit;
++}
++
+ int main(int argc, const char **argv)
+ {
+     struct sss_route_cmd commands[] = {
+         {"user-add", override_user_add},
+         {"user-del", override_user_del},
++        {"user-import", override_user_import},
++        {"user-export", override_user_export},
+         {"group-add", override_group_add},
+         {"group-del", override_group_del},
++        {"group-import", override_group_import},
++        {"group-export", override_group_export},
+         {NULL, NULL}
+     };
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0066-LDAP-Move-sss_krb5_verify_keytab_ex-to-ldap_child.patch b/SOURCES/0066-LDAP-Move-sss_krb5_verify_keytab_ex-to-ldap_child.patch
deleted file mode 100644
index f11e54f..0000000
--- a/SOURCES/0066-LDAP-Move-sss_krb5_verify_keytab_ex-to-ldap_child.patch
+++ /dev/null
@@ -1,220 +0,0 @@
-From 73bd041e84e13ac96af4c057882c386fa437b202 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sat, 11 Oct 2014 17:39:21 +0200
-Subject: [PATCH 66/71] LDAP: Move sss_krb5_verify_keytab_ex to ldap_child
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The function was called from one place only, so it makes no sense to
-keep it in a shared module. Moreover, the function should only be
-called from code that runs as root.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/providers/ldap/ldap_child.c | 79 ++++++++++++++++++++++++++++++++++++++++-
- src/util/sss_krb5.c             | 76 ---------------------------------------
- src/util/sss_krb5.h             |  3 --
- 3 files changed, 78 insertions(+), 80 deletions(-)
-
-diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
-index e5779b70906d90ab855677f04a154e179f2163c6..b8b4b0ad7cfffc7db52b5ca3d9b9a74f12480070 100644
---- a/src/providers/ldap/ldap_child.c
-+++ b/src/providers/ldap/ldap_child.c
-@@ -160,6 +160,83 @@ set_child_debugging(krb5_context ctx)
-     return EOK;
- }
- 
-+static int lc_verify_keytab_ex(const char *principal,
-+                               const char *keytab_name,
-+                               krb5_context context,
-+                               krb5_keytab keytab)
-+{
-+    bool found;
-+    char *kt_principal;
-+    krb5_error_code krberr;
-+    krb5_kt_cursor cursor;
-+    krb5_keytab_entry entry;
-+
-+    krberr = krb5_kt_start_seq_get(context, keytab, &cursor);
-+    if (krberr) {
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Cannot read keytab [%s].\n", KEYTAB_CLEAN_NAME);
-+
-+        sss_log(SSS_LOG_ERR, "Error reading keytab file [%s]: [%d][%s]. "
-+                             "Unable to create GSSAPI-encrypted LDAP "
-+                             "connection.",
-+                             KEYTAB_CLEAN_NAME, krberr,
-+                             sss_krb5_get_error_message(context, krberr));
-+
-+        return EIO;
-+    }
-+
-+    found = false;
-+    while ((krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
-+        krberr = krb5_unparse_name(context, entry.principal, &kt_principal);
-+        if (krberr) {
-+            DEBUG(SSSDBG_FATAL_FAILURE,
-+                  "Could not parse keytab entry\n");
-+            sss_log(SSS_LOG_ERR, "Could not parse keytab entry\n");
-+            return EIO;
-+        }
-+
-+        if (strcmp(principal, kt_principal) == 0) {
-+            found = true;
-+        }
-+        free(kt_principal);
-+        krberr = sss_krb5_free_keytab_entry_contents(context, &entry);
-+        if (krberr) {
-+            /* This should never happen. The API docs for this function
-+             * specify only success for this function
-+             */
-+            DEBUG(SSSDBG_CRIT_FAILURE,"Could not free keytab entry contents\n");
-+            /* This is non-fatal, so we'll continue here */
-+        }
-+
-+        if (found) {
-+            break;
-+        }
-+    }
-+
-+    krberr = krb5_kt_end_seq_get(context, keytab, &cursor);
-+    if (krberr) {
-+        DEBUG(SSSDBG_FATAL_FAILURE, "Could not close keytab.\n");
-+        sss_log(SSS_LOG_ERR, "Could not close keytab file [%s].",
-+                             KEYTAB_CLEAN_NAME);
-+        return EIO;
-+    }
-+
-+    if (!found) {
-+        DEBUG(SSSDBG_FATAL_FAILURE,
-+              "Principal [%s] not found in keytab [%s]\n",
-+               principal,
-+               KEYTAB_CLEAN_NAME);
-+        sss_log(SSS_LOG_ERR, "Error processing keytab file [%s]: "
-+                             "Principal [%s] was not found. "
-+                             "Unable to create GSSAPI-encrypted LDAP connection.",
-+                             KEYTAB_CLEAN_NAME, principal);
-+
-+        return EFAULT;
-+    }
-+
-+    return EOK;
-+}
-+
- static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-                                                const char *realm_str,
-                                                const char *princ_str,
-@@ -287,7 +364,7 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-     }
- 
-     /* Verify the keytab */
--    ret = sss_krb5_verify_keytab_ex(full_princ, keytab_name, context, keytab);
-+    ret = lc_verify_keytab_ex(full_princ, keytab_name, context, keytab);
-     if (ret) {
-         DEBUG(SSSDBG_OP_FAILURE,
-                 "Unable to verify principal is present in the keytab\n");
-diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
-index b4012593d96bc951143e4bb2ba7a91d118b1a53c..9eb34e17dc1059da9c346d4635a9f3e283308328 100644
---- a/src/util/sss_krb5.c
-+++ b/src/util/sss_krb5.c
-@@ -247,82 +247,6 @@ done:
-     return ret;
- }
- 
--int sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
--                              krb5_context context, krb5_keytab keytab)
--{
--    bool found;
--    char *kt_principal;
--    krb5_error_code krberr;
--    krb5_kt_cursor cursor;
--    krb5_keytab_entry entry;
--
--    krberr = krb5_kt_start_seq_get(context, keytab, &cursor);
--    if (krberr) {
--        DEBUG(SSSDBG_FATAL_FAILURE,
--              "Cannot read keytab [%s].\n", KEYTAB_CLEAN_NAME);
--
--        sss_log(SSS_LOG_ERR, "Error reading keytab file [%s]: [%d][%s]. "
--                             "Unable to create GSSAPI-encrypted LDAP "
--                             "connection.",
--                             KEYTAB_CLEAN_NAME, krberr,
--                             sss_krb5_get_error_message(context, krberr));
--
--        return EIO;
--    }
--
--    found = false;
--    while((krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
--        krberr = krb5_unparse_name(context, entry.principal, &kt_principal);
--        if (krberr) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "Could not parse keytab entry\n");
--            sss_log(SSS_LOG_ERR, "Could not parse keytab entry\n");
--            return EIO;
--        }
--
--        if (strcmp(principal, kt_principal) == 0) {
--            found = true;
--        }
--        free(kt_principal);
--        krberr = sss_krb5_free_keytab_entry_contents(context, &entry);
--        if (krberr) {
--            /* This should never happen. The API docs for this function
--             * specify only success for this function
--             */
--            DEBUG(SSSDBG_CRIT_FAILURE,"Could not free keytab entry contents\n");
--            /* This is non-fatal, so we'll continue here */
--        }
--
--        if (found) {
--            break;
--        }
--    }
--
--    krberr = krb5_kt_end_seq_get(context, keytab, &cursor);
--    if (krberr) {
--        DEBUG(SSSDBG_FATAL_FAILURE, "Could not close keytab.\n");
--        sss_log(SSS_LOG_ERR, "Could not close keytab file [%s].",
--                             KEYTAB_CLEAN_NAME);
--        return EIO;
--    }
--
--    if (!found) {
--        DEBUG(SSSDBG_FATAL_FAILURE,
--              "Principal [%s] not found in keytab [%s]\n",
--               principal,
--               KEYTAB_CLEAN_NAME);
--        sss_log(SSS_LOG_ERR, "Error processing keytab file [%s]: "
--                             "Principal [%s] was not found. "
--                             "Unable to create GSSAPI-encrypted LDAP connection.",
--                             KEYTAB_CLEAN_NAME, principal);
--
--        return EFAULT;
--    }
--
--    return EOK;
--}
--
--
- enum matching_mode {MODE_NORMAL, MODE_PREFIX, MODE_POSTFIX};
- /**
-  * We only have primary and instances stored separately, we need to
-diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
-index 83c72097594dc24de1f8ac93d5394b6766a449f4..afa0d1943d8a23ae1543ae3874b5abbfbb4b3372 100644
---- a/src/util/sss_krb5.h
-+++ b/src/util/sss_krb5.h
-@@ -70,9 +70,6 @@ void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
- 
- void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name);
- 
--int sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
--                              krb5_context context, krb5_keytab keytab);
--
- krb5_error_code find_principal_in_keytab(krb5_context ctx,
-                                          krb5_keytab keytab,
-                                          const char *pattern_primary,
--- 
-1.9.3
-
diff --git a/SOURCES/0066-NSS-Fix-use-after-free.patch b/SOURCES/0066-NSS-Fix-use-after-free.patch
new file mode 100644
index 0000000..8b2a8f4
--- /dev/null
+++ b/SOURCES/0066-NSS-Fix-use-after-free.patch
@@ -0,0 +1,89 @@
+From ddcdb9ecfbbfb7e3ce57c7b97eefa3e59b5a0e78 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Fri, 7 Aug 2015 14:29:45 +0200
+Subject: [PATCH 66/66] NSS: Fix use after free
+
+It can happed if there are two domains and user is not found
+in the first one.
+
+==29279== Invalid read of size 1
+==29279==    at 0x4C2CBA2: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==29279==    by 0x89A7AC4: talloc_strdup (in /usr/lib64/libtalloc.so.2.1.2)
+==29279==    by 0x11668A: nss_cmd_initgroups_search (nsssrv_cmd.c:4191)
+==29279==    by 0x118B27: nss_cmd_getby_dp_callback (nsssrv_cmd.c:1208)
+==29279==    by 0x10F2B4: nsssrv_dp_send_acct_req_done (nsssrv_cmd.c:759)
+==29279==    by 0x126AFB: sss_dp_internal_get_done (responder_dp.c:802)
+==29279==    by 0x56EA861: ??? (in /usr/lib64/libdbus-1.so.3.7.4)
+==29279==    by 0x56EDB50: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.7.4)
+==29279==    by 0x50721E1: sbus_dispatch (sssd_dbus_connection.c:96)
+==29279==    by 0x879B22E: tevent_common_loop_timer_delay (tevent_timed.c:341)
+==29279==    by 0x879C239: epoll_event_loop_once (tevent_epoll.c:911)
+==29279==    by 0x879A936: std_event_loop_once (tevent_standard.c:114)
+==29279==  Address 0xbbad240 is 96 bytes inside a block of size 106 free'd
+==29279==    at 0x4C2AD17: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
+==29279==    by 0x89A46E3: _talloc_free (in /usr/lib64/libtalloc.so.2.1.2)
+==29279==    by 0x116679: nss_cmd_initgroups_search (nsssrv_cmd.c:4190)
+==29279==    by 0x118B27: nss_cmd_getby_dp_callback (nsssrv_cmd.c:1208)
+==29279==    by 0x10F2B4: nsssrv_dp_send_acct_req_done (nsssrv_cmd.c:759)
+==29279==    by 0x126AFB: sss_dp_internal_get_done (responder_dp.c:802)
+==29279==    by 0x56EA861: ??? (in /usr/lib64/libdbus-1.so.3.7.4)
+==29279==    by 0x56EDB50: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.7.4)
+==29279==    by 0x50721E1: sbus_dispatch (sssd_dbus_connection.c:96)
+==29279==    by 0x879B22E: tevent_common_loop_timer_delay (tevent_timed.c:341)
+==29279==    by 0x879C239: epoll_event_loop_once (tevent_epoll.c:911)
+==29279==    by 0x879A936: std_event_loop_once (tevent_standard.c:114)
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2749
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/responder/nss/nsssrv_cmd.c     | 6 +++---
+ src/responder/nss/nsssrv_private.h | 1 +
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
+index aa64432d51f15ed17212b8c40eebf5c9322bc784..459634b8d7a590a196ad47a17cd52729fc633ee2 100644
+--- a/src/responder/nss/nsssrv_cmd.c
++++ b/src/responder/nss/nsssrv_cmd.c
+@@ -4107,7 +4107,7 @@ static int nss_cmd_initgr_send_reply(struct nss_dom_ctx *dctx)
+     }
+ 
+     ret = fill_initgr(cctx->creq->out, dctx->domain, dctx->res, nctx,
+-                      dctx->mc_name, cmdctx->name);
++                      dctx->mc_name, cmdctx->normalized_name);
+     if (ret) {
+         return ret;
+     }
+@@ -4151,14 +4151,14 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx)
+         /* make sure to update the dctx if we changed domain */
+         dctx->domain = dom;
+ 
+-        talloc_free(name);
++        talloc_zfree(cmdctx->normalized_name);
+         name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive);
+         if (!name) return ENOMEM;
+ 
+         name = sss_reverse_replace_space(cmdctx, name,
+                                          nctx->rctx->override_space);
+         /* save name so it can be used in initgr reply */
+-        cmdctx->name = name;
++        cmdctx->normalized_name = name;
+         if (name == NULL) {
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "sss_reverse_replace_space failed\n");
+diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h
+index e5a2486f1fb9a8de39ec90f802f596b2c2f6af7f..72f7b75604567f9b95937018e54ba2d60b771f9b 100644
+--- a/src/responder/nss/nsssrv_private.h
++++ b/src/responder/nss/nsssrv_private.h
+@@ -31,6 +31,7 @@ struct nss_cmd_ctx {
+     struct cli_ctx *cctx;
+     enum sss_cli_command cmd;
+     char *name;
++    const char *normalized_name;
+     bool name_is_upn;
+     uint32_t id;
+     char *secid;
+-- 
+2.4.3
+
diff --git a/SOURCES/0067-LDAP-read-the-correct-data-type-from-ldap_child-s-in.patch b/SOURCES/0067-LDAP-read-the-correct-data-type-from-ldap_child-s-in.patch
deleted file mode 100644
index 4b66c75..0000000
--- a/SOURCES/0067-LDAP-read-the-correct-data-type-from-ldap_child-s-in.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 9524f859a730ef39852ecbba5638f26ab677cdd7 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 19 Oct 2014 19:20:28 +0200
-Subject: [PATCH 67/71] LDAP: read the correct data type from ldap_child's
- input buffer
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The back end wrote uint32_t, the ldap_child process would read int32_t.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/providers/ldap/ldap_child.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
-index b8b4b0ad7cfffc7db52b5ca3d9b9a74f12480070..e1abc9fd73f2ae95f0a0c28159589ebd36d2cf06 100644
---- a/src/providers/ldap/ldap_child.c
-+++ b/src/providers/ldap/ldap_child.c
-@@ -96,8 +96,8 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
-     }
- 
-     /* ticket lifetime */
--    SAFEALIGN_COPY_INT32_CHECK(&ibuf->lifetime, buf + p, size, &p);
--    DEBUG(SSSDBG_TRACE_LIBS, "lifetime: %d\n", ibuf->lifetime);
-+    SAFEALIGN_COPY_UINT32_CHECK(&ibuf->lifetime, buf + p, size, &p);
-+    DEBUG(SSSDBG_TRACE_LIBS, "lifetime: %u\n", ibuf->lifetime);
- 
-     return EOK;
- }
--- 
-1.9.3
-
diff --git a/SOURCES/0067-sss_override-document-debug-options.patch b/SOURCES/0067-sss_override-document-debug-options.patch
new file mode 100644
index 0000000..3dadc13
--- /dev/null
+++ b/SOURCES/0067-sss_override-document-debug-options.patch
@@ -0,0 +1,122 @@
+From c8fcc0597ad6399fe42111512d5dc2ff1362f3c8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Tue, 25 Aug 2015 12:58:45 +0200
+Subject: [PATCH 67/68] sss_override: document --debug options
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2758
+
+Reviewed-by: Petr Cech <pcech@redhat.com>
+---
+ src/man/sss_override.8.xml   | 16 ++++++++++++++++
+ src/tools/common/sss_tools.c | 25 +++++++++++++++++++++----
+ 2 files changed, 37 insertions(+), 4 deletions(-)
+
+diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml
+index d289f5b7dfa7fbd328831b4c71d45b4c555225cf..c2ec5dd41703c7272acf7c9d2c30f20351099791 100644
+--- a/src/man/sss_override.8.xml
++++ b/src/man/sss_override.8.xml
+@@ -190,6 +190,22 @@
+         </variablelist>
+     </refsect1>
+ 
++    <refsect1 id='options'>
++        <title>COMMON OPTIONS</title>
++        <para>
++            Those options are available with all commands.
++        </para>
++        <variablelist remap='IP'>
++            <varlistentry>
++                <term>
++                    <option>-d</option>,<option>--debug</option>
++                    <replaceable>LEVEL</replaceable>
++                </term>
++                <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/debug_levels.xml" />
++            </varlistentry>
++        </variablelist>
++    </refsect1>
++
+     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/seealso.xml" />
+ 
+ </refentry>
+diff --git a/src/tools/common/sss_tools.c b/src/tools/common/sss_tools.c
+index 6bbce3a25ddddc0b23ebc108a917a38e94981b65..d50e9af7d348e984687108895f0fd3448ee9add0 100644
+--- a/src/tools/common/sss_tools.c
++++ b/src/tools/common/sss_tools.c
+@@ -36,6 +36,13 @@ struct sss_cmdline {
+     const char **argv;
+ };
+ 
++static void sss_tool_print_common_opts(void)
++{
++    fprintf(stderr, _("Common options:\n"));
++    fprintf(stderr, "  --debug=INT            %s\n",
++                    _("Enable debug at level"));
++}
++
+ static void sss_tool_common_opts(struct sss_tool_ctx *tool_ctx,
+                                  int *argc, const char **argv)
+ {
+@@ -201,6 +208,9 @@ int sss_tool_usage(const char *tool_name,
+         fprintf(stderr, "* %s\n", commands[i].command);
+     }
+ 
++    fprintf(stderr, _("\n"));
++    sss_tool_print_common_opts();
++
+     return EXIT_FAILURE;
+ }
+ 
+@@ -237,6 +247,13 @@ int sss_tool_route(int argc, const char **argv,
+     return sss_tool_usage(argv[0], commands);
+ }
+ 
++static void sss_tool_popt_print_help(poptContext pc)
++{
++    poptPrintHelp(pc, stderr, 0);
++    fprintf(stderr, "\n");
++    sss_tool_print_common_opts();
++}
++
+ int sss_tool_popt_ex(struct sss_cmdline *cmdline,
+                      struct poptOption *options,
+                      enum sss_tool_opt require_option,
+@@ -286,7 +303,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline,
+         } else {
+             fprintf(stderr, _("Invalid option %s: %s\n\n"),
+                     poptBadOption(pc, 0), poptStrerror(ret));
+-            poptPrintHelp(pc, stderr, 0);
++            sss_tool_popt_print_help(pc);
+             ret = EXIT_FAILURE;
+             goto done;
+         }
+@@ -297,7 +314,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline,
+         *_fopt = poptGetArg(pc);
+         if (*_fopt == NULL) {
+             fprintf(stderr, _("Missing option: %s\n\n"), fopt_help);
+-            poptPrintHelp(pc, stderr, 0);
++            sss_tool_popt_print_help(pc);
+             ret = EXIT_FAILURE;
+             goto done;
+         }
+@@ -305,7 +322,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline,
+         /* No more arguments expected. If something follows it is an error. */
+         if (poptGetArg(pc)) {
+             fprintf(stderr, _("Only one free argument is expected!\n\n"));
+-            poptPrintHelp(pc, stderr, 0);
++            sss_tool_popt_print_help(pc);
+             ret = EXIT_FAILURE;
+             goto done;
+         }
+@@ -315,7 +332,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline,
+     if (require_option == SSS_TOOL_OPT_REQUIRED
+             && ((_fopt != NULL && cmdline->argc < 2) || cmdline->argc < 1)) {
+         fprintf(stderr, _("At least one option is required!\n\n"));
+-        poptPrintHelp(pc, stderr, 0);
++        sss_tool_popt_print_help(pc);
+         ret = EXIT_FAILURE;
+         goto done;
+     }
+-- 
+2.4.3
+
diff --git a/SOURCES/0068-LDAP-Drop-privileges-after-kinit-in-ldap_child.patch b/SOURCES/0068-LDAP-Drop-privileges-after-kinit-in-ldap_child.patch
deleted file mode 100644
index fef3059..0000000
--- a/SOURCES/0068-LDAP-Drop-privileges-after-kinit-in-ldap_child.patch
+++ /dev/null
@@ -1,214 +0,0 @@
-From 954637494fc8453f71e2b5d93b3d1ea97e31d646 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 19 Oct 2014 19:15:52 +0200
-Subject: [PATCH 68/71] LDAP: Drop privileges after kinit in ldap_child
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-After ldap_child initializes privileges using root-owned keytab, it
-drops privileges to the SSSD user, minimizing the amount of code that
-runs as root.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- Makefile.am                             |  4 +-
- src/providers/ldap/ldap_child.c         | 96 ++++++++++++++++++++-------------
- src/providers/ldap/sdap_child_helpers.c |  8 ++-
- 3 files changed, 70 insertions(+), 38 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 02b087ea37b4e55da7eeb7fb199d282d72129e40..ea296c40f89c552d5825cbce8e95afdc517e8bb5 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2517,7 +2517,9 @@ ldap_child_SOURCES = \
-     src/util/atomic_io.c \
-     src/util/authtok.c \
-     src/util/util.c \
--    src/util/signal.c
-+    src/util/signal.c \
-+    src/util/become_user.c \
-+    $(NULL)
- ldap_child_CFLAGS = \
-     $(AM_CFLAGS) \
-     $(POPT_CFLAGS) \
-diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
-index e1abc9fd73f2ae95f0a0c28159589ebd36d2cf06..a922b181715c5e89301e9f50bdb81723d1ff2a6a 100644
---- a/src/providers/ldap/ldap_child.c
-+++ b/src/providers/ldap/ldap_child.c
-@@ -49,6 +49,8 @@ struct input_buffer {
-     const char *princ_str;
-     const char *keytab_name;
-     krb5_deltat lifetime;
-+    uid_t uid;
-+    gid_t gid;
- };
- 
- static errno_t unpack_buffer(uint8_t *buf, size_t size,
-@@ -99,6 +101,12 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
-     SAFEALIGN_COPY_UINT32_CHECK(&ibuf->lifetime, buf + p, size, &p);
-     DEBUG(SSSDBG_TRACE_LIBS, "lifetime: %u\n", ibuf->lifetime);
- 
-+    /* UID and GID to run as */
-+    SAFEALIGN_COPY_UINT32_CHECK(&ibuf->uid, buf + p, size, &p);
-+    SAFEALIGN_COPY_UINT32_CHECK(&ibuf->gid, buf + p, size, &p);
-+    DEBUG(SSSDBG_FUNC_DATA,
-+          "Will run as [%"SPRIuid"][%"SPRIgid"].\n", ibuf->uid, ibuf->gid);
-+
-     return EOK;
- }
- 
-@@ -242,6 +250,8 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-                                                const char *princ_str,
-                                                const char *keytab_name,
-                                                const krb5_deltat lifetime,
-+                                               uid_t uid,
-+                                               gid_t gid,
-                                                const char **ccname_out,
-                                                time_t *expire_time_out)
- {
-@@ -372,42 +382,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-         goto done;
-     }
- 
--    ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
--                                        DB_PATH, realm_name);
--    ccname_file = talloc_asprintf(tmp_ctx, "%s/ccache_%s",
--                                  DB_PATH, realm_name);
--    if (ccname_file_dummy == NULL || ccname_file == NULL) {
--        ret = ENOMEM;
--        goto done;
--    }
--
--    old_umask = umask(077);
--    fd = mkstemp(ccname_file_dummy);
--    umask(old_umask);
--    if (fd == -1) {
--        ret = errno;
--        goto done;
--    }
--    /* We only care about creating a unique file name here, we don't
--     * need the fd
--     */
--    close(fd);
--
--    ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
--    ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
--    if (ccname_dummy == NULL || ccname == NULL) {
--        krberr = ENOMEM;
--        goto done;
--    }
--    DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname_dummy);
--
--    krberr = krb5_cc_resolve(context, ccname_dummy, &ccache);
--    if (krberr) {
--        DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n",
--                  sss_krb5_get_error_message(context, krberr));
--        goto done;
--    }
--
-     memset(&my_creds, 0, sizeof(my_creds));
-     memset(&options, 0, sizeof(options));
- 
-@@ -423,8 +397,36 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-     }
-     sss_krb5_get_init_creds_opt_set_canonicalize(&options, canonicalize);
- 
-+    ccname_file = talloc_asprintf(tmp_ctx, "%s/ccache_%s",
-+                                  DB_PATH, realm_name);
-+    if (ccname_file == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    ccname_file_dummy = talloc_asprintf(tmp_ctx, "%s/ccache_%s_XXXXXX",
-+                                        DB_PATH, realm_name);
-+    if (ccname_file_dummy == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    old_umask = umask(077);
-+    fd = mkstemp(ccname_file_dummy);
-+    umask(old_umask);
-+    if (fd == -1) {
-+        ret = errno;
-+        goto done;
-+    }
-+    /* We only care about creating a unique file name here, we don't
-+     * need the fd
-+     */
-+    close(fd);
-+
-     krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc,
-                                         keytab, 0, NULL, &options);
-+    krb5_kt_close(context, keytab);
-+    keytab = NULL;
-     if (krberr) {
-         DEBUG(SSSDBG_FATAL_FAILURE,
-               "Failed to init credentials: %s\n",
-@@ -438,6 +440,27 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-     }
-     DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n");
- 
-+    krberr = become_user(uid, gid);
-+    if (krberr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
-+        goto done;
-+    }
-+
-+    ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
-+    ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
-+    if (ccname_dummy == NULL || ccname == NULL) {
-+        krberr = ENOMEM;
-+        goto done;
-+    }
-+    DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname_dummy);
-+
-+    krberr = krb5_cc_resolve(context, ccname_dummy, &ccache);
-+    if (krberr) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n",
-+                  sss_krb5_get_error_message(context, krberr));
-+        goto done;
-+    }
-+
-     /* Use updated principal if changed due to canonicalization. */
-     krberr = krb5_cc_initialize(context, ccache, my_creds.client);
-     if (krberr) {
-@@ -643,6 +666,7 @@ int main(int argc, const char *argv[])
-     kerr = ldap_child_get_tgt_sync(main_ctx,
-                                    ibuf->realm_str, ibuf->princ_str,
-                                    ibuf->keytab_name, ibuf->lifetime,
-+                                   ibuf->uid, ibuf->gid,
-                                    &ccname, &expire_time);
-     if (kerr != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "ldap_child_get_tgt_sync failed.\n");
-diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
-index 448c5af10e9da8949bcaa39d8a3fa05ec309e16f..e5d46b9b756cd50fadb212da72ad1cc9bdd93330 100644
---- a/src/providers/ldap/sdap_child_helpers.c
-+++ b/src/providers/ldap/sdap_child_helpers.c
-@@ -152,7 +152,7 @@ static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx,
-         return ENOMEM;
-     }
- 
--    buf->size = 4 * sizeof(uint32_t);
-+    buf->size = 6 * sizeof(uint32_t);
-     if (realm_str) {
-         buf->size += strlen(realm_str);
-     }
-@@ -201,6 +201,12 @@ static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx,
-     /* lifetime */
-     SAFEALIGN_SET_UINT32(&buf->data[rp], lifetime, &rp);
- 
-+    /* UID and GID to drop privileges to, if needed. The ldap_child process runs as
-+     * setuid if the back end runs unprivileged as it needs to access the keytab
-+     */
-+    SAFEALIGN_SET_UINT32(&buf->data[rp], geteuid(), &rp);
-+    SAFEALIGN_SET_UINT32(&buf->data[rp], getegid(), &rp);
-+
-     *io_buf = buf;
-     return EOK;
- }
--- 
-1.9.3
-
diff --git a/SOURCES/0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch b/SOURCES/0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch
new file mode 100644
index 0000000..e3ac8f9
--- /dev/null
+++ b/SOURCES/0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch
@@ -0,0 +1,97 @@
+From eaccdcf75b651a0cc4fc02526180f5991a16c553 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Fri, 28 Aug 2015 07:07:40 +0200
+Subject: [PATCH 68/68] NSS: Don't ignore backslash in usernames with ldap
+ provider
+
+The regression was caused by changing default domain regex
+for ldap provider in ticket #2717
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2772
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+---
+ src/responder/nss/nsssrv.c      |  4 ++--
+ src/tests/cmocka/test_nss_srv.c |  4 ++--
+ src/util/usertools.c            | 11 ++++++++++-
+ src/util/util.h                 |  3 +++
+ 4 files changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
+index 2b3bca892a5b9c483d1f6f099fd4a6493e9afcab..d8eff7968c4929663412aa56d08414689b921a22 100644
+--- a/src/responder/nss/nsssrv.c
++++ b/src/responder/nss/nsssrv.c
+@@ -552,9 +552,9 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
+         goto fail;
+     }
+ 
+-    ret = sss_names_init(nctx, nctx->rctx->cdb, NULL, &nctx->global_names);
++    ret = sss_ad_default_names_ctx(nctx, &nctx->global_names);
+     if (ret != EOK) {
+-        DEBUG(SSSDBG_CRIT_FAILURE, "sss_names_init failed.\n");
++        DEBUG(SSSDBG_CRIT_FAILURE, "sss_ad_default_names_ctx failed.\n");
+         goto fail;
+     }
+ 
+diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
+index 84d3413be70bc0af433b7fd23cf7d78b4b9298f1..3cf9f06e61b9e4f13d5d755f7cbd8020194d52d6 100644
+--- a/src/tests/cmocka/test_nss_srv.c
++++ b/src/tests/cmocka/test_nss_srv.c
+@@ -1043,8 +1043,8 @@ void test_nss_setup(struct sss_test_conf_param params[],
+     nss_test_ctx->nctx = mock_nctx(nss_test_ctx);
+     assert_non_null(nss_test_ctx->nctx);
+ 
+-    ret = sss_names_init(nss_test_ctx->nctx, nss_test_ctx->tctx->confdb,
+-                         NULL, &nss_test_ctx->nctx->global_names);
++    ret = sss_ad_default_names_ctx(nss_test_ctx->nctx,
++                                   &nss_test_ctx->nctx->global_names);
+     assert_int_equal(ret, EOK);
+     assert_non_null(nss_test_ctx->nctx->global_names);
+ 
+diff --git a/src/util/usertools.c b/src/util/usertools.c
+index 87a8d7411312c3a80c32374a1fd93bbf0e767a91..ccbf7a0c8c2fb6d1d07afbfe46d978fc33093432 100644
+--- a/src/util/usertools.c
++++ b/src/util/usertools.c
+@@ -249,7 +249,8 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
+     }
+ 
+     if (!re_pattern) {
+-        re_pattern = talloc_strdup(tmpctx, IPA_AD_DEFAULT_RE);
++        re_pattern = talloc_strdup(tmpctx,
++                                   "(?P<name>[^@]+)@?(?P<domain>[^@]*$)");
+         if (!re_pattern) {
+             ret = ENOMEM;
+             goto done;
+@@ -294,6 +295,14 @@ done:
+     return ret;
+ }
+ 
++int sss_ad_default_names_ctx(TALLOC_CTX *mem_ctx,
++                             struct sss_names_ctx **_out)
++{
++    return sss_names_init_from_args(mem_ctx, IPA_AD_DEFAULT_RE,
++                                    CONFDB_DEFAULT_FULL_NAME_FORMAT,
++                                    _out);
++}
++
+ int sss_parse_name(TALLOC_CTX *memctx,
+                    struct sss_names_ctx *snctx,
+                    const char *orig, char **_domain, char **_name)
+diff --git a/src/util/util.h b/src/util/util.h
+index a20d1d82eb8f10dac515ad25e7e424713bb1c099..c998e91f92b0a86e0f4308ff0c07ff802588b5cf 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -298,6 +298,9 @@ int sss_names_init(TALLOC_CTX *mem_ctx,
+                    const char *domain,
+                    struct sss_names_ctx **out);
+ 
++int sss_ad_default_names_ctx(TALLOC_CTX *mem_ctx,
++                             struct sss_names_ctx **_out);
++
+ int sss_parse_name(TALLOC_CTX *memctx,
+                    struct sss_names_ctx *snctx,
+                    const char *orig, char **_domain, char **_name);
+-- 
+2.4.3
+
diff --git a/SOURCES/0069-GPO-fix-memory-leak.patch b/SOURCES/0069-GPO-fix-memory-leak.patch
new file mode 100644
index 0000000..7eb04e9
--- /dev/null
+++ b/SOURCES/0069-GPO-fix-memory-leak.patch
@@ -0,0 +1,49 @@
+From 69bf6ed59e73e92a52c080b4af57f554f703ab52 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Thu, 3 Sep 2015 04:46:50 -0400
+Subject: [PATCH 69/73] GPO: fix memory leak
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2777
+
+Reviewed-by: Michal Židek <mzidek@redhat.com>
+---
+ src/providers/ad/ad_gpo.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
+index 974fd04b99709055f25ed2a3b77821b3caec09ad..a7ba4b2210115a19a3e4430744d36fe76da20f09 100644
+--- a/src/providers/ad/ad_gpo.c
++++ b/src/providers/ad/ad_gpo.c
+@@ -560,14 +560,14 @@ ad_gpo_get_sids(TALLOC_CTX *mem_ctx,
+         DEBUG(SSSDBG_OP_FAILURE,
+               "sysdb_initgroups failed: [%d](%s)\n",
+               ret, sss_strerror(ret));
+-        return ret;
++        goto done;
+     }
+ 
+     if (res->count == 0) {
+         ret = ENOENT;
+         DEBUG(SSSDBG_OP_FAILURE,
+               "sysdb_initgroups returned empty result\n");
+-        return ret;
++        goto done;
+     }
+ 
+     user_sid = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SID_STR, NULL);
+@@ -602,7 +602,7 @@ ad_gpo_get_sids(TALLOC_CTX *mem_ctx,
+     *_group_size = num_group_sids + 1;
+     *_group_sids = talloc_steal(mem_ctx, group_sids);
+     *_user_sid = talloc_steal(mem_ctx, user_sid);
+-    return EOK;
++    ret = EOK;
+ 
+  done:
+     talloc_free(tmp_ctx);
+-- 
+2.4.3
+
diff --git a/SOURCES/0069-UTIL-Remove-code-duplication-of-struct-io.patch b/SOURCES/0069-UTIL-Remove-code-duplication-of-struct-io.patch
deleted file mode 100644
index 6f7d29d..0000000
--- a/SOURCES/0069-UTIL-Remove-code-duplication-of-struct-io.patch
+++ /dev/null
@@ -1,218 +0,0 @@
-From 093ac8b41e4baefd2c1102fb897367318de12fb3 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 21 Oct 2014 12:29:55 +0200
-Subject: [PATCH 69/71] UTIL: Remove code duplication of struct io
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-We had struct io and the associated destructor copied twice in the code
-already and need it again in the SELinux provider. Instead of adding
-another copy, move the code to a shared subtree under util/
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/providers/ad/ad_gpo.c               | 43 +++------------------------------
- src/providers/krb5/krb5_child_handler.c | 38 ++---------------------------
- src/util/child_common.c                 | 29 ++++++++++++++++++++++
- src/util/child_common.h                 |  7 ++++++
- 4 files changed, 41 insertions(+), 76 deletions(-)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 4dfbd4b6943b477bd93fdd730dfa5b1c5828a10a..80b0d45c2861a64f01fe7835cccee4348084c7da 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -3756,46 +3756,9 @@ struct ad_gpo_process_cse_state {
-     pid_t child_pid;
-     uint8_t *buf;
-     ssize_t len;
--    struct io *io;
-+    struct child_io_fds *io;
- };
- 
--struct io {
--    int read_from_child_fd;
--    int write_to_child_fd;
--};
--
--static errno_t
--gpo_child_io_destructor(void *ptr)
--{
--    int ret;
--    struct io *io;
--
--    io = talloc_get_type(ptr, struct io);
--    if (io == NULL) return EOK;
--
--    if (io->write_to_child_fd != -1) {
--        ret = close(io->write_to_child_fd);
--        io->write_to_child_fd = -1;
--        if (ret != EOK) {
--            ret = errno;
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "close failed [%d][%s].\n", ret, strerror(ret));
--        }
--    }
--
--    if (io->read_from_child_fd != -1) {
--        ret = close(io->read_from_child_fd);
--        io->read_from_child_fd = -1;
--        if (ret != EOK) {
--            ret = errno;
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "close failed [%d][%s].\n", ret, strerror(ret));
--        }
--    }
--
--    return EOK;
--}
--
- static errno_t gpo_fork_child(struct tevent_req *req);
- static void gpo_cse_step(struct tevent_req *subreq);
- static void gpo_cse_done(struct tevent_req *subreq);
-@@ -3849,7 +3812,7 @@ ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
-     state->gpo_guid = gpo_guid;
-     state->smb_path = smb_path;
-     state->smb_cse_suffix = smb_cse_suffix;
--    state->io = talloc(state, struct io);
-+    state->io = talloc(state, struct child_io_fds);
-     if (state->io == NULL) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
-         ret = ENOMEM;
-@@ -3858,7 +3821,7 @@ ad_gpo_process_cse_send(TALLOC_CTX *mem_ctx,
- 
-     state->io->write_to_child_fd = -1;
-     state->io->read_from_child_fd = -1;
--    talloc_set_destructor((void *) state->io, gpo_child_io_destructor);
-+    talloc_set_destructor((void *) state->io, child_io_destructor);
- 
-     /* prepare the data to pass to child */
-     ret = create_cse_send_buffer(state, smb_server, smb_share, smb_path,
-diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
-index 114e72a33e48da299647c2fe3096b9bf61cf294a..4ba939deb3e0e282b3ca9b2b21226ea7e64e311b 100644
---- a/src/providers/krb5/krb5_child_handler.c
-+++ b/src/providers/krb5/krb5_child_handler.c
-@@ -41,11 +41,6 @@
- #define TIME_T_MAX LONG_MAX
- #define int64_to_time_t(val) ((time_t)((val) < TIME_T_MAX ? val : TIME_T_MAX))
- 
--struct io {
--    int read_from_child_fd;
--    int write_to_child_fd;
--};
--
- struct handle_child_state {
-     struct tevent_context *ev;
-     struct krb5child_req *kr;
-@@ -55,38 +50,9 @@ struct handle_child_state {
-     struct tevent_timer *timeout_handler;
-     pid_t child_pid;
- 
--    struct io *io;
-+    struct child_io_fds *io;
- };
- 
--static int child_io_destructor(void *ptr)
--{
--    int ret;
--    struct io *io = talloc_get_type(ptr, struct io);
--    if (io == NULL) return EOK;
--
--    if (io->write_to_child_fd != -1) {
--        ret = close(io->write_to_child_fd);
--        io->write_to_child_fd = -1;
--        if (ret != EOK) {
--            ret = errno;
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "close failed [%d][%s].\n", ret, strerror(ret));
--        }
--    }
--
--    if (io->read_from_child_fd != -1) {
--        ret = close(io->read_from_child_fd);
--        io->read_from_child_fd = -1;
--        if (ret != EOK) {
--            ret = errno;
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "close failed [%d][%s].\n", ret, strerror(ret));
--        }
--    }
--
--    return EOK;
--}
--
- static errno_t pack_authtok(struct io_buffer *buf, size_t *rp,
-                             struct sss_auth_token *tok)
- {
-@@ -391,7 +357,7 @@ struct tevent_req *handle_child_send(TALLOC_CTX *mem_ctx,
-     state->child_pid = -1;
-     state->timeout_handler = NULL;
- 
--    state->io = talloc(state, struct io);
-+    state->io = talloc(state, struct child_io_fds);
-     if (state->io == NULL) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
-         ret = ENOMEM;
-diff --git a/src/util/child_common.c b/src/util/child_common.c
-index 81bbab70ed44a6c0a4410909924aec195c643bea..e4a885b6e6e4a1a8a0cabd12ba1544a7c8f0f160 100644
---- a/src/util/child_common.c
-+++ b/src/util/child_common.c
-@@ -772,3 +772,32 @@ void child_cleanup(int readfd, int writefd)
-         }
-     }
- }
-+
-+int child_io_destructor(void *ptr)
-+{
-+    int ret;
-+    struct child_io_fds *io = talloc_get_type(ptr, struct child_io_fds);
-+    if (io == NULL) return EOK;
-+
-+    if (io->write_to_child_fd != -1) {
-+        ret = close(io->write_to_child_fd);
-+        io->write_to_child_fd = -1;
-+        if (ret != EOK) {
-+            ret = errno;
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "close failed [%d][%s].\n", ret, strerror(ret));
-+        }
-+    }
-+
-+    if (io->read_from_child_fd != -1) {
-+        ret = close(io->read_from_child_fd);
-+        io->read_from_child_fd = -1;
-+        if (ret != EOK) {
-+            ret = errno;
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "close failed [%d][%s].\n", ret, strerror(ret));
-+        }
-+    }
-+
-+    return EOK;
-+}
-diff --git a/src/util/child_common.h b/src/util/child_common.h
-index 95865bb529b6b282a57b138d7a85ce93649faa2e..261da7f9c546ddfdb38506e5285024ad201bdd4d 100644
---- a/src/util/child_common.h
-+++ b/src/util/child_common.h
-@@ -45,6 +45,11 @@ struct io_buffer {
-     size_t size;
- };
- 
-+struct child_io_fds {
-+    int read_from_child_fd;
-+    int write_to_child_fd;
-+};
-+
- /* COMMON SIGCHLD HANDLING */
- typedef void (*sss_child_fn_t)(int pid, int wait_status, void *pvt);
- 
-@@ -113,4 +118,6 @@ errno_t exec_child(TALLOC_CTX *mem_ctx,
- 
- void child_cleanup(int readfd, int writefd);
- 
-+int child_io_destructor(void *ptr);
-+
- #endif /* __CHILD_COMMON_H__ */
--- 
-1.9.3
-
diff --git a/SOURCES/0070-UTIL-Remove-more-code-duplication-setting-up-child-p.patch b/SOURCES/0070-UTIL-Remove-more-code-duplication-setting-up-child-p.patch
deleted file mode 100644
index c12d4ca..0000000
--- a/SOURCES/0070-UTIL-Remove-more-code-duplication-setting-up-child-p.patch
+++ /dev/null
@@ -1,184 +0,0 @@
-From b95d9cbd6959a3174c4fb963be642f770938e4b7 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 21 Oct 2014 22:36:59 +0200
-Subject: [PATCH 70/71] UTIL: Remove more code duplication setting up child
- processes
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-All our child processes duplicated the same code that set up the
-debugging all around. Instead of adding yet another copy for the
-selinux_child, add a common utility function.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/providers/ad/ad_gpo.c               | 23 ++---------------------
- src/providers/krb5/krb5_init_shared.c   | 24 ++++++++----------------
- src/providers/ldap/sdap_child_helpers.c | 22 +---------------------
- src/util/child_common.c                 | 29 +++++++++++++++++++++++++++++
- src/util/child_common.h                 |  2 ++
- 5 files changed, 42 insertions(+), 58 deletions(-)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 80b0d45c2861a64f01fe7835cccee4348084c7da..83edbe4fb5a7e617cab95c0330ceae31392b18b2 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -1313,29 +1313,10 @@ ad_gpo_access_check(TALLOC_CTX *mem_ctx,
- }
- 
- #define GPO_CHILD_LOG_FILE "gpo_child"
-+
- static errno_t gpo_child_init(void)
- {
--    int ret;
--    FILE *debug_filep;
--
--    if (debug_to_file != 0 && gpo_child_debug_fd == -1) {
--        ret = open_debug_file_ex(GPO_CHILD_LOG_FILE, &debug_filep, false);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_FATAL_FAILURE, "Error setting up logging (%d) [%s]\n",
--                        ret, strerror(ret));
--            return ret;
--        }
--
--        gpo_child_debug_fd = fileno(debug_filep);
--        if (gpo_child_debug_fd == -1) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "fileno failed [%d][%s]\n", errno, strerror(errno));
--            ret = errno;
--            return ret;
--        }
--    }
--
--    return EOK;
-+    return child_debug_init(GPO_CHILD_LOG_FILE, &gpo_child_debug_fd);
- }
- 
- /*
-diff --git a/src/providers/krb5/krb5_init_shared.c b/src/providers/krb5/krb5_init_shared.c
-index 340eab1f0d432d411e2b807f66b03bffcbd14d1d..3b4bf096ef49d0f2d369fda20462b7fd56d61127 100644
---- a/src/providers/krb5/krb5_init_shared.c
-+++ b/src/providers/krb5/krb5_init_shared.c
-@@ -30,7 +30,6 @@ errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx,
-                         struct be_ctx *bectx)
- {
-     errno_t ret;
--    FILE *debug_filep;
-     time_t renew_intv = 0;
-     krb5_deltat renew_interval_delta;
-     char *renew_interval_str;
-@@ -83,23 +82,16 @@ errno_t krb5_child_init(struct krb5_ctx *krb5_auth_ctx,
-         goto done;
-     }
- 
--    if (debug_to_file != 0) {
--        ret = open_debug_file_ex(KRB5_CHILD_LOG_FILE, &debug_filep, false);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_FATAL_FAILURE, "Error setting up logging (%d) [%s]\n",
--                    ret, strerror(ret));
--            goto done;
--        }
--
--        krb5_auth_ctx->child_debug_fd = fileno(debug_filep);
--        if (krb5_auth_ctx->child_debug_fd == -1) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "fileno failed [%d][%s]\n", errno, strerror(errno));
--            ret = errno;
--            goto done;
--        }
-+    krb5_auth_ctx->child_debug_fd = -1; /* -1 means not initialized */
-+    ret = child_debug_init(KRB5_CHILD_LOG_FILE,
-+                           &krb5_auth_ctx->child_debug_fd);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Could not set krb5_child debugging!\n");
-+        goto done;
-     }
- 
-+    ret = EOK;
-+
- done:
-     return ret;
- }
-diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
-index e5d46b9b756cd50fadb212da72ad1cc9bdd93330..40010989021eb7cf77b96876b2d1c4119ed39163 100644
---- a/src/providers/ldap/sdap_child_helpers.c
-+++ b/src/providers/ldap/sdap_child_helpers.c
-@@ -466,25 +466,5 @@ static errno_t set_tgt_child_timeout(struct tevent_req *req,
- /* Setup child logging */
- int sdap_setup_child(void)
- {
--    int ret;
--    FILE *debug_filep;
--
--    if (debug_to_file != 0 && ldap_child_debug_fd == -1) {
--        ret = open_debug_file_ex(LDAP_CHILD_LOG_FILE, &debug_filep, false);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_FATAL_FAILURE, "Error setting up logging (%d) [%s]\n",
--                        ret, strerror(ret));
--            return ret;
--        }
--
--        ldap_child_debug_fd = fileno(debug_filep);
--        if (ldap_child_debug_fd == -1) {
--            DEBUG(SSSDBG_FATAL_FAILURE,
--                  "fileno failed [%d][%s]\n", errno, strerror(errno));
--            ret = errno;
--            return ret;
--        }
--    }
--
--    return EOK;
-+    return child_debug_init(LDAP_CHILD_LOG_FILE, &ldap_child_debug_fd);
- }
-diff --git a/src/util/child_common.c b/src/util/child_common.c
-index e4a885b6e6e4a1a8a0cabd12ba1544a7c8f0f160..cc6a8fa758bfa6efa511c28cd9121e759b590342 100644
---- a/src/util/child_common.c
-+++ b/src/util/child_common.c
-@@ -801,3 +801,32 @@ int child_io_destructor(void *ptr)
- 
-     return EOK;
- }
-+
-+errno_t child_debug_init(const char *logfile, int *debug_fd)
-+{
-+    int ret;
-+    FILE *debug_filep;
-+
-+    if (debug_fd == NULL) {
-+        return EOK;
-+    }
-+
-+    if (debug_to_file != 0 && *debug_fd == -1) {
-+        ret = open_debug_file_ex(logfile, &debug_filep, false);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_FATAL_FAILURE, "Error setting up logging (%d) [%s]\n",
-+                        ret, sss_strerror(ret));
-+            return ret;
-+        }
-+
-+        *debug_fd = fileno(debug_filep);
-+        if (*debug_fd == -1) {
-+            DEBUG(SSSDBG_FATAL_FAILURE,
-+                  "fileno failed [%d][%s]\n", errno, strerror(errno));
-+            ret = errno;
-+            return ret;
-+        }
-+    }
-+
-+    return EOK;
-+}
-diff --git a/src/util/child_common.h b/src/util/child_common.h
-index 261da7f9c546ddfdb38506e5285024ad201bdd4d..e159719a2fca70a4ea044d79530a0d21cb3577e8 100644
---- a/src/util/child_common.h
-+++ b/src/util/child_common.h
-@@ -120,4 +120,6 @@ void child_cleanup(int readfd, int writefd);
- 
- int child_io_destructor(void *ptr);
- 
-+errno_t child_debug_init(const char *logfile, int *debug_fd);
-+
- #endif /* __CHILD_COMMON_H__ */
--- 
-1.9.3
-
diff --git a/SOURCES/0070-sss_override-support-fqn-in-override-name.patch b/SOURCES/0070-sss_override-support-fqn-in-override-name.patch
new file mode 100644
index 0000000..838a47e
--- /dev/null
+++ b/SOURCES/0070-sss_override-support-fqn-in-override-name.patch
@@ -0,0 +1,172 @@
+From 90611687b8b7b9a4d2be4625c97301660412b605 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Tue, 15 Sep 2015 11:38:40 +0200
+Subject: [PATCH 70/73] sss_override: support fqn in override name
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2782
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+---
+ src/tools/sss_override.c | 111 +++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 93 insertions(+), 18 deletions(-)
+
+diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c
+index ee8351ea97e5efe0d449dc646c6136b32ceec2c6..0d7a4690634a3993dee2119ee09fea328e494f1a 100644
+--- a/src/tools/sss_override.c
++++ b/src/tools/sss_override.c
+@@ -604,58 +604,133 @@ done:
+     return ret;
+ }
+ 
++static errno_t override_fqn(TALLOC_CTX *mem_ctx,
++                            struct sss_tool_ctx *tool_ctx,
++                            struct sss_domain_info *domain,
++                            const char *input,
++                            const char **_name)
++{
++    struct sss_domain_info *dom;
++    errno_t ret;
++
++    if (input == NULL) {
++        return EOK;
++    }
++
++    ret = sss_tool_parse_name(mem_ctx, tool_ctx, input, _name, &dom);
++    if (ret == EAGAIN) {
++        DEBUG(SSSDBG_OP_FAILURE, "Unable to find domain from "
++              "fqn %s\n", input);
++        fprintf(stderr, _("Changing domain is not allowed!\n"));
++        ret = EINVAL;
++    } else if (ret == EOK && dom != NULL && dom != domain) {
++        DEBUG(SSSDBG_OP_FAILURE, "Trying to change domain from "
++              "%s to %s, not allowed!\n", domain->name, dom->name);
++        fprintf(stderr, _("Changing domain is not allowed!\n"));
++        ret = EINVAL;
++    } else if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name %s [%d]: %s\n",
++              input, ret, sss_strerror(ret));
++    }
++
++    return ret;
++}
++
+ static errno_t override_user(struct sss_tool_ctx *tool_ctx,
+-                             struct override_user *user)
++                             struct override_user *input_user)
+ {
++    TALLOC_CTX *tmp_ctx;
++    struct override_user user;
+     struct sysdb_attrs *attrs;
+     errno_t ret;
+ 
+-    ret = prepare_view_msg(user->domain);
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
++        return ENOMEM;
++    }
++
++    user = *input_user;
++
++    /* We need to parse the name and ensure that domain did not change. */
++    ret = override_fqn(tmp_ctx, tool_ctx, user.domain, user.name, &user.name);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    ret = prepare_view_msg(user.domain);
+     if (ret != EOK) {
+-        return ret;
++        goto done;
+     }
+ 
+-    attrs = build_user_attrs(tool_ctx, user);
++    attrs = build_user_attrs(tool_ctx, &user);
+     if (attrs == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
+-        return ENOMEM;
++        ret = ENOMEM;
++        goto done;
+     }
+ 
+-    ret = override_object_add(user->domain, SYSDB_MEMBER_USER, attrs,
+-                              user->orig_name);
++    ret = override_object_add(user.domain, SYSDB_MEMBER_USER, attrs,
++                              user.orig_name);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
+-        return ret;
++        goto done;
+     }
+ 
+-    return EOK;
++    ret = EOK;
++
++done:
++    talloc_free(tmp_ctx);
++    return ret;
+ }
+ 
+ static errno_t override_group(struct sss_tool_ctx *tool_ctx,
+-                              struct override_group *group)
++                              struct override_group *input_group)
+ {
++    TALLOC_CTX *tmp_ctx;
++    struct override_group group;
+     struct sysdb_attrs *attrs;
+     errno_t ret;
+ 
+-    ret = prepare_view_msg(group->domain);
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
++        return ENOMEM;
++    }
++
++    group = *input_group;
++
++    /* We need to parse the name and ensure that domain did not change. */
++    ret = override_fqn(tmp_ctx, tool_ctx, group.domain, group.name,
++                       &group.name);
++    if (ret != EOK) {
++        goto done;
++    }
++
++    ret = prepare_view_msg(group.domain);
+     if (ret != EOK) {
+-        return ret;
++        goto done;
+     }
+ 
+-    attrs = build_group_attrs(tool_ctx, group);
++    attrs = build_group_attrs(tool_ctx, &group);
+     if (attrs == NULL) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
+-        return ENOMEM;
++        ret = ENOMEM;
++        goto done;
+     }
+ 
+-    ret = override_object_add(group->domain, SYSDB_MEMBER_GROUP, attrs,
+-                              group->orig_name);
++    ret = override_object_add(group.domain, SYSDB_MEMBER_GROUP, attrs,
++                              group.orig_name);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
+-        return ret;
++        goto done;
+     }
+ 
+-    return EOK;
++    ret = EOK;
++
++done:
++    talloc_free(tmp_ctx);
++    return ret;
+ }
+ 
+ static errno_t override_object_del(struct sss_domain_info *domain,
+-- 
+2.4.3
+
diff --git a/SOURCES/0071-IPA-Move-setting-the-SELinux-context-to-a-child-proc.patch b/SOURCES/0071-IPA-Move-setting-the-SELinux-context-to-a-child-proc.patch
deleted file mode 100644
index f19dd79..0000000
--- a/SOURCES/0071-IPA-Move-setting-the-SELinux-context-to-a-child-proc.patch
+++ /dev/null
@@ -1,927 +0,0 @@
-From e08eb3e3b0586b331a688a4eded2d7f13611016c Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 20 Oct 2014 23:16:40 +0200
-Subject: [PATCH 71/71] IPA: Move setting the SELinux context to a child
- process
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In order for the sssd_be process to run as unprivileged user, we need to
-move the semanage processing to a process that runs as the root user
-using setuid privileges.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- Makefile.am                       |  27 +++
- contrib/sssd.spec.in              |   1 +
- src/providers/ipa/ipa_selinux.c   | 425 +++++++++++++++++++++++++++++++++++---
- src/providers/ipa/selinux_child.c | 272 ++++++++++++++++++++++++
- src/util/util_errors.c            |   1 +
- src/util/util_errors.h            |   1 +
- 6 files changed, 699 insertions(+), 28 deletions(-)
- create mode 100644 src/providers/ipa/selinux_child.c
-
-diff --git a/Makefile.am b/Makefile.am
-index ea296c40f89c552d5825cbce8e95afdc517e8bb5..b85341f5845c3cffab8a2c95b1be1d32517316e8 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -146,6 +146,9 @@ endif
- if BUILD_SAMBA
- sssdlibexec_PROGRAMS += gpo_child
- endif
-+if BUILD_SEMANAGE
-+sssdlibexec_PROGRAMS += selinux_child
-+endif
- 
- 
- if BUILD_PAC_RESPONDER
-@@ -2531,6 +2534,26 @@ ldap_child_LDADD = \
-     $(DHASH_LIBS) \
-     $(KRB5_LIBS)
- 
-+if BUILD_SEMANAGE
-+selinux_child_SOURCES = \
-+    src/providers/ipa/selinux_child.c \
-+    src/util/sss_semanage.c \
-+    src/util/atomic_io.c \
-+    src/util/util.c \
-+    $(NULL)
-+selinux_child_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(POPT_CFLAGS) \
-+    $(NULL)
-+selinux_child_LDADD = \
-+    libsss_debug.la \
-+    $(TALLOC_LIBS) \
-+    $(POPT_LIBS) \
-+    $(DHASH_LIBS) \
-+    $(SEMANAGE_LIBS) \
-+    $(NULL)
-+endif
-+
- gpo_child_SOURCES = \
-     src/providers/ad/ad_gpo_child.c \
-     src/util/atomic_io.c \
-@@ -2849,6 +2872,10 @@ endif
- if SSSD_USER
- 	chgrp $(SSSD_USER) $(sssdlibexecdir)/ldap_child
- 	chmod 4750 $(sssdlibexecdir)/ldap_child
-+if BUILD_SEMANAGE
-+	chgrp $(SSSD_USER) $(sssdlibexecdir)/selinux_child
-+	chmod 4750 $(sssdlibexecdir)/selinux_child
-+endif
- endif
- 
- install-data-hook:
-diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
-index d2e6cec2610e4c00cb376683cf7e64eb5cdafc5c..5bfb16707c22dc65376581c88b8eb898949e726f 100644
---- a/contrib/sssd.spec.in
-+++ b/contrib/sssd.spec.in
-@@ -665,6 +665,7 @@ rm -rf $RPM_BUILD_ROOT
- %doc COPYING
- %attr(755,root,root) %dir %{pubconfpath}/krb5.include.d
- %{_libdir}/%{name}/libsss_ipa.so
-+%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/selinux_child
- %{_mandir}/man5/sssd-ipa.5*
- 
- %files ad -f sssd_ad.lang
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index 7db1c6ed2981e4c4a85d892171bbfa60b006980e..b392d82a61cd523cd5e73e5246013bdbc448ddd5 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -24,6 +24,7 @@
- #include <security/pam_modules.h>
- 
- #include "db/sysdb_selinux.h"
-+#include "util/child_common.h"
- #include "util/sss_selinux.h"
- #include "providers/ldap/sdap_async.h"
- #include "providers/ipa/ipa_common.h"
-@@ -37,8 +38,23 @@
- #include "providers/ipa/ipa_subdomains.h"
- 
- #if defined HAVE_SELINUX && defined HAVE_SELINUX_LOGIN_DIR
-+
-+#ifndef SELINUX_CHILD_DIR
-+#ifndef SSSD_LIBEXEC_PATH
-+#error "SSSD_LIBEXEC_PATH not defined"
-+#endif  /* SSSD_LIBEXEC_PATH */
-+
-+#define SELINUX_CHILD_DIR SSSD_LIBEXEC_PATH
-+#endif /* SELINUX_CHILD_DIR */
-+
-+#define SELINUX_CHILD SELINUX_CHILD_DIR"/selinux_child"
-+#define SELINUX_CHILD_LOG_FILE "selinux_child"
-+
- #include <selinux/selinux.h>
- 
-+/* fd used by the selinux_child process for logging */
-+int selinux_child_debug_fd = -1;
-+
- static struct tevent_req *
- ipa_get_selinux_send(TALLOC_CTX *mem_ctx,
-                      struct be_ctx *be_ctx,
-@@ -274,12 +290,27 @@ struct map_order_ctx {
- 
- static errno_t init_map_order_ctx(TALLOC_CTX *mem_ctx, const char *map_order,
-                                   struct map_order_ctx **_mo_ctx);
--static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
-+
-+struct selinux_child_input {
-+    const char *seuser;
-+    const char *mls_range;
-+    const char *username;
-+};
-+
-+static errno_t choose_best_seuser(TALLOC_CTX *mem_ctx,
-+                                  struct sysdb_attrs **usermaps,
-                                   struct pam_data *pd,
-                                   struct sss_domain_info *user_domain,
-                                   struct map_order_ctx *mo_ctx,
--                                  const char *default_user);
-+                                  const char *default_user,
-+                                  struct selinux_child_input **_sci);
- 
-+static struct tevent_req *selinux_child_send(TALLOC_CTX *mem_ctx,
-+                                             struct tevent_context *ev,
-+                                             struct selinux_child_input *sci);
-+static errno_t selinux_child_recv(struct tevent_req *req);
-+
-+static void ipa_selinux_child_done(struct tevent_req *child_req);
- 
- static void ipa_selinux_handler_done(struct tevent_req *req)
- {
-@@ -299,6 +330,8 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
-     struct sysdb_attrs **hbac_rules = 0;
-     struct sysdb_attrs **best_match_maps;
-     struct map_order_ctx *map_order_ctx;
-+    struct selinux_child_input *sci;
-+    struct tevent_req *child_req;
- 
-     ret = ipa_get_selinux_recv(req, breq, &map_count, &maps,
-                                &hbac_count, &hbac_rules,
-@@ -360,14 +393,61 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
-         goto fail;
-     }
- 
--    ret = choose_best_seuser(best_match_maps, pd, op_ctx->user_domain,
--                             map_order_ctx, default_user);
-+    ret = choose_best_seuser(breq,
-+                             best_match_maps, pd, op_ctx->user_domain,
-+                             map_order_ctx, default_user, &sci);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
-               "Failed to evaluate ordered SELinux users array.\n");
-         goto fail;
-     }
- 
-+    /* Update the SELinux context in a privileged child as the back end is
-+     * running unprivileged
-+     */
-+    child_req = selinux_child_send(breq, be_ctx->ev, sci);
-+    if (child_req == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "selinux_child_send() failed\n");
-+        ret = ENOMEM;
-+        goto fail;
-+    }
-+    tevent_req_set_callback(child_req, ipa_selinux_child_done, op_ctx);
-+    return;
-+
-+fail:
-+    if (in_transaction) {
-+        sret = sysdb_transaction_cancel(sysdb);
-+        if (sret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
-+        }
-+    }
-+    if (ret == EAGAIN) {
-+        be_req_terminate(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
-+    } else {
-+        be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
-+    }
-+}
-+
-+static void ipa_selinux_child_done(struct tevent_req *child_req)
-+{
-+    errno_t ret;
-+    struct ipa_selinux_op_ctx *op_ctx;
-+    struct be_req *breq;
-+    struct pam_data *pd;
-+    struct be_ctx *be_ctx;
-+
-+    op_ctx = tevent_req_callback_data(child_req, struct ipa_selinux_op_ctx);
-+    breq = op_ctx->be_req;
-+    pd = talloc_get_type(be_req_get_data(breq), struct pam_data);
-+    be_ctx = be_req_get_be_ctx(breq);
-+
-+    ret = selinux_child_recv(child_req);
-+    talloc_free(child_req);
-+    if (ret != EOK) {
-+        be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
-+        return;
-+    }
-+
-     /* If we got here in online mode, set last_update to current time */
-     if (!be_is_offline(be_ctx)) {
-         op_ctx->selinux_ctx->last_update = time(NULL);
-@@ -375,20 +455,6 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
- 
-     pd->pam_status = PAM_SUCCESS;
-     be_req_terminate(breq, DP_ERR_OK, EOK, "Success");
--    return;
--
--fail:
--    if (in_transaction) {
--        sret = sysdb_transaction_cancel(sysdb);
--        if (sret != EOK) {
--            DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n");
--        }
--    }
--    if (ret == EAGAIN) {
--        be_req_terminate(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
--    } else {
--        be_req_terminate(breq, DP_ERR_FATAL, ret, NULL);
--    }
- }
- 
- static errno_t
-@@ -652,24 +718,28 @@ done:
-     return ret;
- }
- 
--static errno_t
--set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
--                  const char *seuser_mls_string);
--
-+static errno_t selinux_child_setup(TALLOC_CTX *mem_ctx,
-+                                   const char *orig_name,
-+                                   struct sss_domain_info *dom,
-+                                   const char *seuser_mls_string,
-+                                   struct selinux_child_input **_sci);
- 
- /* Choose best selinux user based on given order and write
-  * the user to selinux login file. */
--static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
-+static errno_t choose_best_seuser(TALLOC_CTX *mem_ctx,
-+                                  struct sysdb_attrs **usermaps,
-                                   struct pam_data *pd,
-                                   struct sss_domain_info *user_domain,
-                                   struct map_order_ctx *mo_ctx,
--                                  const char *default_user)
-+                                  const char *default_user,
-+                                  struct selinux_child_input **_sci)
- {
-     TALLOC_CTX *tmp_ctx;
-     char *seuser_mls_str = NULL;
-     const char *tmp_str;
-     errno_t ret;
-     int i, j;
-+    struct selinux_child_input *sci;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -716,15 +786,25 @@ static errno_t choose_best_seuser(struct sysdb_attrs **usermaps,
-         }
-     }
- 
--    ret = set_seuser_helper(pd->user, user_domain, seuser_mls_str);
-+    ret = selinux_child_setup(tmp_ctx, pd->user, user_domain, seuser_mls_str, &sci);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Cannot set up child input buffer");
-+        goto done;
-+    }
-+
-+    *_sci = talloc_steal(mem_ctx, sci);
-+    ret = EOK;
- done:
-     talloc_free(tmp_ctx);
-     return ret;
- }
- 
- static errno_t
--set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
--                  const char *seuser_mls_string)
-+selinux_child_setup(TALLOC_CTX *mem_ctx,
-+                    const char *orig_name,
-+                    struct sss_domain_info *dom,
-+                    const char *seuser_mls_string,
-+                    struct selinux_child_input **_sci)
- {
-     errno_t ret;
-     char *seuser;
-@@ -733,6 +813,7 @@ set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
-     char *username;
-     char *username_final;
-     TALLOC_CTX *tmp_ctx;
-+    struct selinux_child_input *sci;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -778,12 +859,300 @@ set_seuser_helper(const char *orig_name, struct sss_domain_info *dom,
-         username_final = username;
-     }
- 
--    ret = set_seuser(username_final, seuser, mls_range);
-+    sci = talloc(tmp_ctx, struct selinux_child_input);
-+    if (sci == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    sci->seuser = talloc_strdup(sci, seuser);
-+    sci->mls_range = talloc_strdup(sci, mls_range);
-+    sci->username = talloc_strdup(sci, username);
-+    if (sci->seuser == NULL || sci->mls_range == NULL
-+        || sci->username == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    *_sci = talloc_steal(mem_ctx, sci);
-+    ret = EOK;
- done:
-     talloc_free(tmp_ctx);
-     return ret;
- }
- 
-+struct selinux_child_state {
-+    struct selinux_child_input *sci;
-+    struct tevent_context *ev;
-+    struct io_buffer *buf;
-+    struct child_io_fds *io;
-+};
-+
-+static errno_t selinux_child_init(void);
-+static errno_t selinux_child_create_buffer(struct selinux_child_state *state);
-+static errno_t selinux_fork_child(struct selinux_child_state *state);
-+static void selinux_child_step(struct tevent_req *subreq);
-+static void selinux_child_done(struct tevent_req *subreq);
-+static errno_t selinux_child_parse_response(uint8_t *buf, ssize_t len,
-+                                            uint32_t *_child_result);
-+
-+static struct tevent_req *selinux_child_send(TALLOC_CTX *mem_ctx,
-+                                             struct tevent_context *ev,
-+                                             struct selinux_child_input *sci)
-+{
-+    struct tevent_req *req;
-+    struct tevent_req *subreq;
-+    struct selinux_child_state *state;
-+    errno_t ret;
-+
-+    req = tevent_req_create(mem_ctx, &state, struct selinux_child_state);
-+    if (req == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
-+        return NULL;
-+    }
-+
-+    state->sci = sci;
-+    state->ev = ev;
-+    state->io = talloc(state, struct child_io_fds);
-+    state->buf = talloc(state, struct io_buffer);
-+    if (state->io == NULL || state->buf == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+
-+    state->io->write_to_child_fd = -1;
-+    state->io->read_from_child_fd = -1;
-+    talloc_set_destructor((void *) state->io, child_io_destructor);
-+
-+    ret = selinux_child_init();
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Failed to init the child\n");
-+        goto immediately;
-+    }
-+
-+    ret = selinux_child_create_buffer(state);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Failed to create the send buffer\n");
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+
-+    ret = selinux_fork_child(state);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Failed to fork the child\n");
-+        goto immediately;
-+    }
-+
-+    subreq = write_pipe_send(state, ev, state->buf->data, state->buf->size,
-+                             state->io->write_to_child_fd);
-+    if (subreq == NULL) {
-+        ret = ENOMEM;
-+        goto immediately;
-+    }
-+    tevent_req_set_callback(subreq, selinux_child_step, req);
-+
-+    ret = EOK;
-+immediately:
-+    if (ret != EOK) {
-+        tevent_req_error(req, ret);
-+        tevent_req_post(req, ev);
-+    }
-+    return req;
-+}
-+
-+static errno_t selinux_child_init(void)
-+{
-+    return child_debug_init(SELINUX_CHILD_LOG_FILE, &selinux_child_debug_fd);
-+}
-+
-+static errno_t selinux_child_create_buffer(struct selinux_child_state *state)
-+{
-+    size_t rp;
-+    size_t seuser_len;
-+    size_t mls_range_len;
-+    size_t username_len;
-+
-+    seuser_len = strlen(state->sci->seuser);
-+    mls_range_len = strlen(state->sci->mls_range);
-+    username_len = strlen(state->sci->username);
-+
-+    state->buf->size = 3 * sizeof(uint32_t);
-+    state->buf->size += seuser_len + mls_range_len + username_len;
-+
-+    DEBUG(SSSDBG_TRACE_ALL, "buffer size: %zu\n", state->buf->size);
-+
-+    state->buf->data = talloc_size(state->buf, state->buf->size);
-+    if (state->buf->data == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    rp = 0;
-+
-+    /* seuser */
-+    SAFEALIGN_SET_UINT32(&state->buf->data[rp], seuser_len, &rp);
-+    safealign_memcpy(&state->buf->data[rp], state->sci->seuser,
-+                     seuser_len, &rp);
-+
-+    /* mls_range */
-+    SAFEALIGN_SET_UINT32(&state->buf->data[rp], mls_range_len, &rp);
-+    safealign_memcpy(&state->buf->data[rp], state->sci->mls_range,
-+                     mls_range_len, &rp);
-+
-+    /* username */
-+    SAFEALIGN_SET_UINT32(&state->buf->data[rp], username_len, &rp);
-+    safealign_memcpy(&state->buf->data[rp], state->sci->username,
-+                     username_len, &rp);
-+
-+    return EOK;
-+}
-+
-+static errno_t selinux_fork_child(struct selinux_child_state *state)
-+{
-+    int pipefd_to_child[2];
-+    int pipefd_from_child[2];
-+    pid_t pid;
-+    errno_t ret;
-+
-+    ret = pipe(pipefd_from_child);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "pipe failed [%d][%s].\n", errno, sss_strerror(errno));
-+        return ret;
-+    }
-+
-+    ret = pipe(pipefd_to_child);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "pipe failed [%d][%s].\n", errno, sss_strerror(errno));
-+        return ret;
-+    }
-+
-+    pid = fork();
-+
-+    if (pid == 0) { /* child */
-+        ret = exec_child(state,
-+                         pipefd_to_child, pipefd_from_child,
-+                         SELINUX_CHILD, selinux_child_debug_fd);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec selinux_child: [%d][%s].\n",
-+              ret, sss_strerror(ret));
-+        return ret;
-+    } else if (pid > 0) { /* parent */
-+        state->io->read_from_child_fd = pipefd_from_child[0];
-+        close(pipefd_from_child[1]);
-+        state->io->write_to_child_fd = pipefd_to_child[1];
-+        close(pipefd_to_child[0]);
-+        fd_nonblocking(state->io->read_from_child_fd);
-+        fd_nonblocking(state->io->write_to_child_fd);
-+
-+        ret = child_handler_setup(state->ev, pid, NULL, NULL, NULL);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "Could not set up child signal handler\n");
-+            return ret;
-+        }
-+    } else { /* error */
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "fork failed [%d][%s].\n", errno, sss_strerror(errno));
-+        return ret;
-+    }
-+
-+    return EOK;
-+}
-+
-+static void selinux_child_step(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req;
-+    errno_t ret;
-+    struct selinux_child_state *state;
-+
-+
-+    req = tevent_req_callback_data(subreq, struct tevent_req);
-+    state = tevent_req_data(req, struct selinux_child_state);
-+
-+    ret = write_pipe_recv(subreq);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    close(state->io->write_to_child_fd);
-+    state->io->write_to_child_fd = -1;
-+
-+    subreq = read_pipe_send(state, state->ev, state->io->read_from_child_fd);
-+    if (subreq == NULL) {
-+        tevent_req_error(req, ENOMEM);
-+        return;
-+    }
-+    tevent_req_set_callback(subreq, selinux_child_done, req);
-+}
-+
-+static void selinux_child_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req;
-+    struct selinux_child_state *state;
-+    uint32_t child_result;
-+    errno_t ret;
-+    ssize_t len;
-+    uint8_t *buf;
-+
-+    req = tevent_req_callback_data(subreq, struct tevent_req);
-+    state = tevent_req_data(req, struct selinux_child_state);
-+
-+    ret = read_pipe_recv(subreq, state, &buf, &len);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    close(state->io->read_from_child_fd);
-+    state->io->read_from_child_fd = -1;
-+
-+    ret = selinux_child_parse_response(buf, len, &child_result);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "selinux_child_parse_response failed: [%d][%s]\n",
-+              ret, strerror(ret));
-+        tevent_req_error(req, ret);
-+        return;
-+    } else if (child_result != 0){
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Error in selinux_child: [%d][%s]\n",
-+              child_result, strerror(child_result));
-+        tevent_req_error(req, ERR_SELINUX_CONTEXT);
-+        return;
-+    }
-+
-+    tevent_req_done(req);
-+    return;
-+}
-+
-+static errno_t selinux_child_parse_response(uint8_t *buf,
-+                                            ssize_t len,
-+                                            uint32_t *_child_result)
-+{
-+    size_t p = 0;
-+    uint32_t child_result;
-+
-+    /* semanage retval */
-+    SAFEALIGN_COPY_UINT32_CHECK(&child_result, buf + p, len, &p);
-+
-+    *_child_result = child_result;
-+    return EOK;
-+}
-+
-+static errno_t selinux_child_recv(struct tevent_req *req)
-+{
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+    return EOK;
-+}
-+
- /* A more generic request to gather all SELinux and HBAC rules. Updates
-  * cache if necessary
-  */
-diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..a624cfd30d6795c305b7673d849213c74de95cd8
---- /dev/null
-+++ b/src/providers/ipa/selinux_child.c
-@@ -0,0 +1,272 @@
-+/*
-+    SSSD
-+
-+    IPA back end -- set SELinux context in a child module
-+
-+    Authors:
-+        Jakub Hrozek <jhrozek@redhat.com>
-+
-+    Copyright (C) 2014 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 <sys/types.h>
-+#include <unistd.h>
-+#include <sys/stat.h>
-+#include <popt.h>
-+
-+#include "util/util.h"
-+#include "util/child_common.h"
-+#include "providers/dp_backend.h"
-+
-+struct input_buffer {
-+    const char *seuser;
-+    const char *mls_range;
-+    const char *username;
-+};
-+
-+static errno_t unpack_buffer(uint8_t *buf,
-+                             size_t size,
-+                             struct input_buffer *ibuf)
-+{
-+    size_t p = 0;
-+    uint32_t len;
-+
-+    /* seuser */
-+    SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-+    DEBUG(SSSDBG_TRACE_INTERNAL, "seuser length: %d\n", len);
-+    if (len == 0) {
-+        return EINVAL;
-+    } else {
-+        if ((p + len ) > size) return EINVAL;
-+        ibuf->seuser = talloc_strndup(ibuf, (char *)(buf + p), len);
-+        if (ibuf->seuser == NULL) return ENOMEM;
-+        DEBUG(SSSDBG_TRACE_INTERNAL, "seuser: %s\n", ibuf->seuser);
-+        p += len;
-+    }
-+
-+    /* MLS range */
-+    SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-+    DEBUG(SSSDBG_TRACE_INTERNAL, "mls_range length: %d\n", len);
-+    if (len == 0) {
-+        return EINVAL;
-+    } else {
-+        if ((p + len ) > size) return EINVAL;
-+        ibuf->mls_range = talloc_strndup(ibuf, (char *)(buf + p), len);
-+        if (ibuf->mls_range == NULL) return ENOMEM;
-+        DEBUG(SSSDBG_TRACE_INTERNAL, "mls_range: %s\n", ibuf->mls_range);
-+        p += len;
-+    }
-+
-+    /* username */
-+    SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-+    DEBUG(SSSDBG_TRACE_INTERNAL, "username length: %d\n", len);
-+    if (len == 0) {
-+        return EINVAL;
-+    } else {
-+        if ((p + len ) > size) return EINVAL;
-+        ibuf->username = talloc_strndup(ibuf, (char *)(buf + p), len);
-+        if (ibuf->username == NULL) return ENOMEM;
-+        DEBUG(SSSDBG_TRACE_INTERNAL, "username: %s\n", ibuf->username);
-+        p += len;
-+    }
-+
-+    return EOK;
-+}
-+
-+static errno_t pack_buffer(struct response *r, int result)
-+{
-+    size_t p = 0;
-+
-+    /* A buffer with the following structure must be created:
-+     *   uint32_t status of the request (required)
-+     */
-+    r->size =  sizeof(uint32_t);
-+
-+    r->buf = talloc_array(r, uint8_t, r->size);
-+    if(r->buf == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_FUNC, "result [%d]\n", result);
-+
-+    /* result */
-+    SAFEALIGN_SET_UINT32(&r->buf[p], result, &p);
-+
-+    return EOK;
-+}
-+
-+static errno_t prepare_response(TALLOC_CTX *mem_ctx,
-+                                int result,
-+                                struct response **rsp)
-+{
-+    int ret;
-+    struct response *r = NULL;
-+
-+    r = talloc_zero(mem_ctx, struct response);
-+    if (r == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    r->buf = NULL;
-+    r->size = 0;
-+
-+    ret = pack_buffer(r, result);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "pack_buffer failed\n");
-+        return ret;
-+    }
-+
-+    *rsp = r;
-+    DEBUG(SSSDBG_TRACE_ALL, "r->size: %zu\n", r->size);
-+    return EOK;
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    int opt;
-+    poptContext pc;
-+    int debug_fd = -1;
-+    errno_t ret;
-+    TALLOC_CTX *main_ctx = NULL;
-+    uint8_t *buf = NULL;
-+    ssize_t len = 0;
-+    struct input_buffer *ibuf = NULL;
-+    struct response *resp = NULL;
-+    size_t written;
-+
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
-+         _("Debug level"), NULL},
-+        {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
-+         _("Add debug timestamps"), NULL},
-+        {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
-+         _("Show timestamps with microseconds"), NULL},
-+        {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
-+         _("An open file descriptor for the debug logs"), NULL},
-+        {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
-+         &debug_to_stderr, 0,
-+         _("Send the debug output to stderr directly."), NULL },
-+        POPT_TABLEEND
-+    };
-+
-+    /* 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);
-+            _exit(-1);
-+        }
-+    }
-+
-+    poptFreeContext(pc);
-+
-+    DEBUG_INIT(debug_level);
-+
-+    debug_prg_name = talloc_asprintf(NULL, "[sssd[selinux_child[%d]]]", getpid());
-+    if (debug_prg_name == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
-+        goto fail;
-+    }
-+
-+    if (debug_fd != -1) {
-+        ret = set_debug_file_from_fd(debug_fd);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n");
-+        }
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_FUNC, "selinux_child started.\n");
-+    DEBUG(SSSDBG_TRACE_INTERNAL,
-+          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
-+
-+    main_ctx = talloc_new(NULL);
-+    if (main_ctx == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
-+        talloc_free(discard_const(debug_prg_name));
-+        goto fail;
-+    }
-+    talloc_steal(main_ctx, debug_prg_name);
-+
-+    buf = talloc_size(main_ctx, sizeof(uint8_t)*IN_BUF_SIZE);
-+    if (buf == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n");
-+        goto fail;
-+    }
-+
-+    ibuf = talloc_zero(main_ctx, struct input_buffer);
-+    if (ibuf == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
-+        goto fail;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_FUNC, "context initialized\n");
-+
-+    errno = 0;
-+    len = sss_atomic_read_s(STDIN_FILENO, buf, IN_BUF_SIZE);
-+    if (len == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "read failed [%d][%s].\n", ret, strerror(ret));
-+        goto fail;
-+    }
-+
-+    close(STDIN_FILENO);
-+
-+    ret = unpack_buffer(buf, len, ibuf);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "unpack_buffer failed.[%d][%s].\n", ret, strerror(ret));
-+        goto fail;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_FUNC, "performing selinux operations\n");
-+
-+    ret = set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
-+
-+    ret = prepare_response(main_ctx, ret, &resp);
-+
-+    errno = 0;
-+
-+    written = sss_atomic_write_s(STDOUT_FILENO, resp->buf, resp->size);
-+    if (written == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "write failed [%d][%s].\n", ret,
-+                    strerror(ret));
-+        goto fail;
-+    }
-+
-+    if (written != resp->size) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Expected to write %zu bytes, wrote %zu\n",
-+              resp->size, written);
-+        goto fail;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_FUNC, "selinux_child completed successfully\n");
-+    close(STDOUT_FILENO);
-+    talloc_free(main_ctx);
-+    return EXIT_SUCCESS;
-+fail:
-+    DEBUG(SSSDBG_CRIT_FAILURE, "selinux_child failed!\n");
-+    close(STDOUT_FILENO);
-+    talloc_free(main_ctx);
-+    return EXIT_FAILURE;
-+}
-diff --git a/src/util/util_errors.c b/src/util/util_errors.c
-index 5b36780ffcdc6733241cdb942865ecdf38da3bca..d5da64622eebe7f779816c7f2090da5b9a9b13f0 100644
---- a/src/util/util_errors.c
-+++ b/src/util/util_errors.c
-@@ -62,6 +62,7 @@ struct err_string error_to_str[] = {
-     { "Bus method not supported" }, /* ERR_SBUS_NOSUP */
-     { "Cannot connect to system bus" }, /* ERR_NO_SYSBUS */
-     { "LDAP search returned a referral" }, /* ERR_REFERRAL */
-+    { "Error setting SELinux user context" }, /* ERR_SELINUX_CONTEXT */
- };
- 
- 
-diff --git a/src/util/util_errors.h b/src/util/util_errors.h
-index e040ba903b27d06ec75cea31485d2f3111ca5302..2bc576605e613d674d38b54aae1604c0b044635f 100644
---- a/src/util/util_errors.h
-+++ b/src/util/util_errors.h
-@@ -84,6 +84,7 @@ enum sssd_errors {
-     ERR_SBUS_NOSUP,
-     ERR_NO_SYSBUS,
-     ERR_REFERRAL,
-+    ERR_SELINUX_CONTEXT,
-     ERR_LAST            /* ALWAYS LAST */
- };
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch b/SOURCES/0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch
new file mode 100644
index 0000000..a92663d
--- /dev/null
+++ b/SOURCES/0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch
@@ -0,0 +1,34 @@
+From 58c6f691bed13095a48b4587e5baa7bb4dc7dae5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Thu, 17 Sep 2015 11:34:40 +0200
+Subject: [PATCH 71/73] views: do not require overrideDN in grous when LOCAL
+ view is set
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2790
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+---
+ src/db/sysdb_views.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
+index 1db6c892de9e4764b673608166830800744b1148..82b1f187dbc6aab032403854714474301ae3324c 100644
+--- a/src/db/sysdb_views.c
++++ b/src/db/sysdb_views.c
+@@ -1337,6 +1337,12 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
+         override_dn_str = ldb_msg_find_attr_as_string(member_obj->msgs[0],
+                                                       SYSDB_OVERRIDE_DN, NULL);
+         if (override_dn_str == NULL) {
++            if (is_local_view(domain->view_name)) {
++                /* LOCAL view doesn't have to have overrideDN specified. */
++                ret = EOK;
++                goto done;
++            }
++
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "Missing override DN for objext [%s].\n",
+                   ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+-- 
+2.4.3
+
diff --git a/SOURCES/0072-test_sysdb_views-Use-unique-directory-for-cache.patch b/SOURCES/0072-test_sysdb_views-Use-unique-directory-for-cache.patch
deleted file mode 100644
index 904977c..0000000
--- a/SOURCES/0072-test_sysdb_views-Use-unique-directory-for-cache.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 06e85cb08343ec902f0978ab0b6b373f1f1817f3 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Wed, 5 Nov 2014 22:18:05 +0100
-Subject: [PATCH 72/75] test_sysdb_views: Use unique directory for cache
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Two tests stored cache in the same directory, It can cause failures with
-parallel execution of tests.
-
-sh$ git grep tests_sysdb
-src/tests/cmocka/test_sysdb_views.c:#define TESTS_PATH "tests_sysdb"
-src/tests/sysdb-tests.c:#define TESTS_PATH "tests_sysdb"
-
-This patch also clean up potential leftovers after previous failed
-test_sysdb_views before execution of test suite.
-
-Reviewed-by: Pavel Březina <pbrezina@redhat.com>
----
- src/tests/cmocka/test_sysdb_views.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
-index 38525d6ded8fdbbd1a657f8ca742e51d6ba2b102..9fb2d7201d06e84be83d6a516c5e3a0f15ec0639 100644
---- a/src/tests/cmocka/test_sysdb_views.c
-+++ b/src/tests/cmocka/test_sysdb_views.c
-@@ -30,7 +30,7 @@
- 
- #include "tests/cmocka/common_mock.h"
- 
--#define TESTS_PATH "tests_sysdb"
-+#define TESTS_PATH "tests_sysdb_views"
- #define TEST_CONF_FILE "tests_conf.ldb"
- 
- struct sysdb_test_ctx {
-@@ -226,6 +226,8 @@ int main(int argc, const char *argv[])
-     DEBUG_CLI_INIT(debug_level);
- 
-     tests_set_cwd();
-+    test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_FILE, LOCAL_SYSDB_FILE);
-+    test_dom_suite_setup(TESTS_PATH);
-     rv = run_tests(tests);
- 
-     if (rv == 0 && no_cleanup == 0) {
--- 
-1.9.3
-
diff --git a/SOURCES/0072-views-fix-two-typos-in-debug-messages.patch b/SOURCES/0072-views-fix-two-typos-in-debug-messages.patch
new file mode 100644
index 0000000..454537c
--- /dev/null
+++ b/SOURCES/0072-views-fix-two-typos-in-debug-messages.patch
@@ -0,0 +1,35 @@
+From 82a09d64a35e560d3715484b2f3f8e6e7c0af48c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Thu, 17 Sep 2015 11:35:56 +0200
+Subject: [PATCH 72/73] views: fix two typos in debug messages
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+---
+ src/db/sysdb_views.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
+index 82b1f187dbc6aab032403854714474301ae3324c..f0459fc174b94d7a735b7c416555eb5aaac42b7c 100644
+--- a/src/db/sysdb_views.c
++++ b/src/db/sysdb_views.c
+@@ -1193,7 +1193,7 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
+             }
+ 
+             DEBUG(SSSDBG_CRIT_FAILURE,
+-                  "Missing override DN for objext [%s].\n",
++                  "Missing override DN for object [%s].\n",
+                   ldb_dn_get_linearized(obj->dn));
+ 
+             ret = ENOENT;
+@@ -1344,7 +1344,7 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
+             }
+ 
+             DEBUG(SSSDBG_CRIT_FAILURE,
+-                  "Missing override DN for objext [%s].\n",
++                  "Missing override DN for object [%s].\n",
+                   ldb_dn_get_linearized(member_obj->msgs[0]->dn));
+             ret = ENOENT;
+             goto done;
+-- 
+2.4.3
+
diff --git a/SOURCES/0073-selinux_child-Do-not-ignore-return-values.patch b/SOURCES/0073-selinux_child-Do-not-ignore-return-values.patch
deleted file mode 100644
index fcc0efb..0000000
--- a/SOURCES/0073-selinux_child-Do-not-ignore-return-values.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 863f4705e8961cfc7a21c276d186d3059d20f53e Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Thu, 6 Nov 2014 16:35:11 +0100
-Subject: [PATCH 73/75] selinux_child: Do not ignore return values.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/ipa/selinux_child.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
-index a624cfd30d6795c305b7673d849213c74de95cd8..a38ffcb26f890349f47478063103e603fe6304cf 100644
---- a/src/providers/ipa/selinux_child.c
-+++ b/src/providers/ipa/selinux_child.c
-@@ -241,8 +241,16 @@ int main(int argc, const char *argv[])
-     DEBUG(SSSDBG_TRACE_FUNC, "performing selinux operations\n");
- 
-     ret = set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set SELinux login context.\n");
-+        goto fail;
-+    }
- 
-     ret = prepare_response(main_ctx, ret, &resp);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to prepare response buffer.\n");
-+        goto fail;
-+    }
- 
-     errno = 0;
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0073-views-allow-ghost-members-for-LOCAL-view.patch b/SOURCES/0073-views-allow-ghost-members-for-LOCAL-view.patch
new file mode 100644
index 0000000..ade6944
--- /dev/null
+++ b/SOURCES/0073-views-allow-ghost-members-for-LOCAL-view.patch
@@ -0,0 +1,89 @@
+From 8d728461964488b29cdcd431210872eaee9bc9f7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Thu, 17 Sep 2015 14:46:34 +0200
+Subject: [PATCH 73/73] views: allow ghost members for LOCAL view
+
+LOCAL view does not allow the case when both ghost member and
+user override is created so it is safe to allow ghost members
+for this view.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2790
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+---
+ src/db/sysdb_search.c          | 36 ++++++++++++++++++++----------------
+ src/responder/nss/nsssrv_cmd.c |  3 ++-
+ 2 files changed, 22 insertions(+), 17 deletions(-)
+
+diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
+index 4f617b841bf3b3760d9cb05a06f4b46ea0c58ff5..efd583beefe78bb6bb26263a9833bf3bfafd0083 100644
+--- a/src/db/sysdb_search.c
++++ b/src/db/sysdb_search.c
+@@ -482,14 +482,16 @@ int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx,
+     /* If there are views we have to check if override values must be added to
+      * the original object. */
+     if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
+-        el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
+-        if (el != NULL && el->num_values != 0) {
+-            DEBUG(SSSDBG_TRACE_ALL,
+-                  "Group object [%s], contains ghost entries which must be " \
+-                  "resolved before overrides can be applied.\n",
+-                   ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
+-            ret = ENOENT;
+-            goto done;
++        if (!is_local_view(domain->view_name)) {
++            el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
++            if (el != NULL && el->num_values != 0) {
++                DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost "
++                      "entries which must be resolved before overrides can be "
++                      "applied.\n",
++                      ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
++                ret = ENOENT;
++                goto done;
++            }
+         }
+ 
+         ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
+@@ -634,14 +636,16 @@ int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx,
+     /* If there are views we have to check if override values must be added to
+      * the original object. */
+     if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) {
+-        el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
+-        if (el != NULL && el->num_values != 0) {
+-            DEBUG(SSSDBG_TRACE_ALL,
+-                  "Group object [%s], contains ghost entries which must be " \
+-                  "resolved before overrides can be applied.\n",
+-                   ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
+-            ret = ENOENT;
+-            goto done;
++        if (!is_local_view(domain->view_name)) {
++            el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST);
++            if (el != NULL && el->num_values != 0) {
++                DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost "
++                      "entries which must be resolved before overrides can be "
++                      "applied.\n",
++                      ldb_dn_get_linearized(orig_obj->msgs[0]->dn));
++                ret = ENOENT;
++                goto done;
++            }
+         }
+ 
+         ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0],
+diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
+index 459634b8d7a590a196ad47a17cd52729fc633ee2..d177135db00369c2af69eb62f6a4a4aaf54ba510 100644
+--- a/src/responder/nss/nsssrv_cmd.c
++++ b/src/responder/nss/nsssrv_cmd.c
+@@ -2909,7 +2909,8 @@ static int fill_grent(struct sss_packet *packet,
+             }
+             el = ldb_msg_find_element(msg, SYSDB_GHOST);
+             if (el) {
+-                if (DOM_HAS_VIEWS(dom) && el->num_values != 0) {
++                if (DOM_HAS_VIEWS(dom) && !is_local_view(dom->view_name)
++                        && el->num_values != 0) {
+                     DEBUG(SSSDBG_CRIT_FAILURE,
+                           "Domain has a view [%s] but group [%s] still has " \
+                           "ghost members.\n", dom->view_name, orig_name);
+-- 
+2.4.3
+
diff --git a/SOURCES/0074-IPA-Store-right-username-to-selinux-child-context.patch b/SOURCES/0074-IPA-Store-right-username-to-selinux-child-context.patch
deleted file mode 100644
index 968b699..0000000
--- a/SOURCES/0074-IPA-Store-right-username-to-selinux-child-context.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 66d12b25e5976041f7298b94c9cfe03ee77aa2bb Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Thu, 6 Nov 2014 12:12:04 +0100
-Subject: [PATCH 74/75] IPA: Store right username to selinux child context
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Wrong name would be used with fully qualified names.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/providers/ipa/ipa_selinux.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index b392d82a61cd523cd5e73e5246013bdbc448ddd5..30ad6f0a7c4622ca5eb9a75ae4f57183543515c6 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -867,7 +867,7 @@ selinux_child_setup(TALLOC_CTX *mem_ctx,
- 
-     sci->seuser = talloc_strdup(sci, seuser);
-     sci->mls_range = talloc_strdup(sci, mls_range);
--    sci->username = talloc_strdup(sci, username);
-+    sci->username = talloc_strdup(sci, username_final);
-     if (sci->seuser == NULL || sci->mls_range == NULL
-         || sci->username == NULL) {
-         ret = ENOMEM;
--- 
-1.9.3
-
diff --git a/SOURCES/0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch b/SOURCES/0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch
new file mode 100644
index 0000000..55c4880
--- /dev/null
+++ b/SOURCES/0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch
@@ -0,0 +1,303 @@
+From 875a41bcd24d1deb2bd190eaaaf7a366de128cee Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 18 Aug 2015 15:15:44 +0000
+Subject: [PATCH 74/87] UTIL: Convert domain->disabled into tri-state with
+ domain states
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Required for:
+https://fedorahosted.org/sssd/ticket/2637
+
+This is a first step towards making it possible for domain to be around,
+but not contacted by Data Provider.
+
+Also explicitly create domains as active, previously we only relied on
+talloc_zero marking dom->disabled as false.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ src/confdb/confdb.c                      |  2 ++
+ src/confdb/confdb.h                      | 19 ++++++++++++++++++-
+ src/db/sysdb_subdomains.c                |  7 +++++--
+ src/providers/ad/ad_subdomains.c         |  2 +-
+ src/providers/ipa/ipa_subdomains.c       |  2 +-
+ src/responder/common/responder_common.c  |  5 +++--
+ src/tests/cmocka/test_sysdb_subdomains.c |  6 +++++-
+ src/tests/cmocka/test_utils.c            |  6 +++---
+ src/util/domain_info_utils.c             | 20 +++++++++++++++++---
+ src/util/util.h                          |  3 +++
+ src/util/util_errors.c                   |  1 +
+ src/util/util_errors.h                   |  1 +
+ 12 files changed, 60 insertions(+), 14 deletions(-)
+
+diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
+index 3a8a1c01b92e62302ac4f787ccd085be9d8f05c3..c097aad7745eda4fff051c7da027776f95db0f03 100644
+--- a/src/confdb/confdb.c
++++ b/src/confdb/confdb.c
+@@ -1342,6 +1342,8 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
+     domain->has_views = false;
+     domain->view_name = NULL;
+ 
++    domain->state = DOM_ACTIVE;
++
+     *_domain = domain;
+     ret = EOK;
+ done:
+diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
+index 9aa264899e789f2491b9873daf44bb55aff1c95d..e8c1caa67852a8f3d9d74fc61dbe6f8b4169daf7 100644
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -215,6 +215,23 @@
+ struct confdb_ctx;
+ struct config_file_ctx;
+ 
++/** sssd domain state */
++enum sss_domain_state {
++    /** Domain is usable by both responders and providers. This
++     * is the default state after creating a new domain
++     */
++    DOM_ACTIVE,
++    /** Domain was removed, should not be used be neither responders
++     * not providers.
++     */
++    DOM_DISABLED,
++    /** Domain cannot be contacted. Providers return an offline error code
++     * when receiving request for inactive domain, but responders should
++     * return cached data
++     */
++    DOM_INACTIVE,
++};
++
+ /**
+  * Data structure storing all of the basic features
+  * of a domain.
+@@ -277,7 +294,7 @@ struct sss_domain_info {
+     struct sss_domain_info *prev;
+     struct sss_domain_info *next;
+ 
+-    bool disabled;
++    enum sss_domain_state state;
+     char **sd_inherit;
+ 
+     /* Do not use the forest pointer directly in new code, but rather the
+diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
+index 142520c1836d74ef7bc5c5269487b8971f261b88..546dc1c8d7e5e30ce9e0b56b097894d24d8c94a7 100644
+--- a/src/db/sysdb_subdomains.c
++++ b/src/db/sysdb_subdomains.c
+@@ -111,6 +111,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
+     dom->enumerate = enumerate;
+     dom->fqnames = true;
+     dom->mpg = mpg;
++    dom->state = DOM_ACTIVE;
++
+     /* If the parent domain filters out group members, the subdomain should
+      * as well if configured */
+     inherit_option = string_in_list(CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS,
+@@ -268,7 +270,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
+     /* disable all domains,
+      * let the search result refresh any that are still valid */
+     for (dom = domain->subdomains; dom; dom = get_next_domain(dom, false)) {
+-        dom->disabled = true;
++        sss_domain_set_state(dom, DOM_DISABLED);
+     }
+ 
+     if (res->count == 0) {
+@@ -312,7 +314,8 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain)
+         /* explicitly use dom->next as we need to check 'disabled' domains */
+         for (dom = domain->subdomains; dom; dom = dom->next) {
+             if (strcasecmp(dom->name, name) == 0) {
+-                dom->disabled = false;
++                sss_domain_set_state(dom, DOM_ACTIVE);
++
+                 /* in theory these may change, but it should never happen */
+                 if (strcasecmp(dom->realm, realm) != 0) {
+                     DEBUG(SSSDBG_TRACE_INTERNAL,
+diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
+index 9b42f03a0067ab5844432a0f19dd2930dcc200c9..d1d468043410c80e6bf7f0f48a13bd9e962552af 100644
+--- a/src/providers/ad/ad_subdomains.c
++++ b/src/providers/ad/ad_subdomains.c
+@@ -376,7 +376,7 @@ static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx,
+ 
+         if (c >= count) {
+             /* ok this subdomain does not exist anymore, let's clean up */
+-            dom->disabled = true;
++            sss_domain_set_state(dom, DOM_DISABLED);
+             ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
+             if (ret != EOK) {
+                 goto done;
+diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
+index b2e2fec353f7b168d28a880cb0f1b6181abb1ccb..089736b47d8f384a8024682dd203d324292df9ce 100644
+--- a/src/providers/ipa/ipa_subdomains.c
++++ b/src/providers/ipa/ipa_subdomains.c
+@@ -528,7 +528,7 @@ static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx,
+ 
+         if (c >= count) {
+             /* ok this subdomain does not exist anymore, let's clean up */
+-            dom->disabled = true;
++            sss_domain_set_state(dom, DOM_DISABLED);
+             ret = sysdb_subdomain_delete(dom->sysdb, dom->name);
+             if (ret != EOK) {
+                 goto done;
+diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
+index 36e7f15948632e9c637886dee259b494e46ceecb..2097004cb0fc24d8b356f9d924243f948227ef58 100644
+--- a/src/responder/common/responder_common.c
++++ b/src/responder/common/responder_common.c
+@@ -923,7 +923,7 @@ responder_get_domain(struct resp_ctx *rctx, const char *name)
+     struct sss_domain_info *ret_dom = NULL;
+ 
+     for (dom = rctx->domains; dom; dom = get_next_domain(dom, true)) {
+-        if (dom->disabled) {
++        if (sss_domain_get_state(dom) == DOM_DISABLED) {
+             continue;
+         }
+ 
+@@ -958,7 +958,8 @@ errno_t responder_get_domain_by_id(struct resp_ctx *rctx, const char *id,
+     id_len = strlen(id);
+ 
+     for (dom = rctx->domains; dom; dom = get_next_domain(dom, true)) {
+-        if (dom->disabled || dom->domain_id == NULL) {
++        if (sss_domain_get_state(dom) == DOM_DISABLED ||
++                dom->domain_id == NULL) {
+             continue;
+         }
+ 
+diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c
+index 82e77815ec848afcdedc90e35e440f7532b5c0b2..8d1a26a5918eaa9dec975c360f69840400e4bd2c 100644
+--- a/src/tests/cmocka/test_sysdb_subdomains.c
++++ b/src/tests/cmocka/test_sysdb_subdomains.c
+@@ -151,7 +151,11 @@ static void test_sysdb_subdomain_create(void **state)
+     ret = sysdb_update_subdomains(test_ctx->tctx->dom);
+     assert_int_equal(ret, EOK);
+ 
+-    assert_true(test_ctx->tctx->dom->subdomains->disabled);
++    assert_int_equal(sss_domain_get_state(test_ctx->tctx->dom->subdomains),
++                     DOM_DISABLED);
++    assert_int_equal(
++            sss_domain_get_state(test_ctx->tctx->dom->subdomains->next),
++            DOM_DISABLED);
+ }
+ 
+ static void test_sysdb_master_domain_ops(void **state)
+diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
+index c7ebe0997ec00197e8852bedbcf26ef1f6394fc3..0f72434ca77fbfe1bd88a75fd932719dbfc59444 100644
+--- a/src/tests/cmocka/test_utils.c
++++ b/src/tests/cmocka/test_utils.c
+@@ -259,7 +259,7 @@ void test_find_domain_by_name_disabled(void **state)
+         dom = dom->next;
+     }
+     assert_non_null(dom);
+-    dom->disabled = true;
++    sss_domain_set_state(dom, DOM_DISABLED);
+ 
+     for (c = 0; c < test_ctx->dom_count; c++) {
+         name = talloc_asprintf(global_talloc_context, DOMNAME_TMPL, c);
+@@ -426,7 +426,7 @@ void test_find_domain_by_sid_disabled(void **state)
+         dom = dom->next;
+     }
+     assert_non_null(dom);
+-    dom->disabled = true;
++    sss_domain_set_state(dom, DOM_DISABLED);
+ 
+     for (c = 0; c < test_ctx->dom_count; c++) {
+         name = talloc_asprintf(global_talloc_context, DOMNAME_TMPL, c);
+@@ -578,7 +578,7 @@ static void test_get_next_domain_disabled(void **state)
+     struct sss_domain_info *dom = NULL;
+ 
+     for (dom = test_ctx->dom_list; dom; dom = get_next_domain(dom, true)) {
+-        dom->disabled = true;
++        sss_domain_set_state(dom, DOM_DISABLED);
+     }
+ 
+     dom = get_next_domain(test_ctx->dom_list, true);
+diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
+index 4eabcff7a0e0af342ec3833d24da26ede0cb5148..ffbb9475b27a45c07e2e0936464c6e68ed682052 100644
+--- a/src/util/domain_info_utils.c
++++ b/src/util/domain_info_utils.c
+@@ -50,7 +50,10 @@ struct sss_domain_info *get_next_domain(struct sss_domain_info *domain,
+         } else {
+             dom = NULL;
+         }
+-        if (dom && !dom->disabled) break;
++
++        if (dom && sss_domain_get_state(dom) != DOM_DISABLED) {
++            break;
++        }
+     }
+ 
+     return dom;
+@@ -91,7 +94,7 @@ struct sss_domain_info *find_domain_by_name(struct sss_domain_info *domain,
+         return NULL;
+     }
+ 
+-    while (dom && dom->disabled) {
++    while (dom && sss_domain_get_state(dom) == DOM_DISABLED) {
+         dom = get_next_domain(dom, true);
+     }
+     while (dom) {
+@@ -119,7 +122,7 @@ struct sss_domain_info *find_domain_by_sid(struct sss_domain_info *domain,
+ 
+     sid_len = strlen(sid);
+ 
+-    while (dom && dom->disabled) {
++    while (dom && sss_domain_get_state(dom) == DOM_DISABLED) {
+         dom = get_next_domain(dom, true);
+     }
+ 
+@@ -730,3 +733,14 @@ done:
+ 
+     return ret;
+ }
++
++enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom)
++{
++    return dom->state;
++}
++
++void sss_domain_set_state(struct sss_domain_info *dom,
++                          enum sss_domain_state state)
++{
++    dom->state = state;
++}
+diff --git a/src/util/util.h b/src/util/util.h
+index c998e91f92b0a86e0f4308ff0c07ff802588b5cf..4655e90a89b0ff3c457b80c943aefc4d6cf8e21f 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -565,6 +565,9 @@ struct sss_domain_info *find_domain_by_name(struct sss_domain_info *domain,
+                                             bool match_any);
+ struct sss_domain_info *find_domain_by_sid(struct sss_domain_info *domain,
+                                            const char *sid);
++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);
+ 
+ struct sss_domain_info*
+ sss_get_domain_by_sid_ldap_fallback(struct sss_domain_info *domain,
+diff --git a/src/util/util_errors.c b/src/util/util_errors.c
+index 735f6dcfc7af33edcc886fd106cb3655bcc9566a..0e288e3908bf03b4906bb449bd0f3445d22a303e 100644
+--- a/src/util/util_errors.c
++++ b/src/util/util_errors.c
+@@ -79,6 +79,7 @@ struct err_string error_to_str[] = {
+     { "Retrieving keytab failed" }, /* ERR_IPA_GETKEYTAB_FAILED */
+     { "Trusted forest root unknown" }, /* ERR_TRUST_FOREST_UNKNOWN */
+     { "p11_child failed" }, /* ERR_P11_CHILD */
++    { "Subdomain is inactive" }, /* ERR_SUBDOM_INACTIVE */
+     { "ERR_LAST" } /* ERR_LAST */
+ };
+ 
+diff --git a/src/util/util_errors.h b/src/util/util_errors.h
+index fbfbdef334be1fb8a525b78ab6336d616b31a189..da926db00121f569048ec515e95f0547ae6c4e35 100644
+--- a/src/util/util_errors.h
++++ b/src/util/util_errors.h
+@@ -101,6 +101,7 @@ enum sssd_errors {
+     ERR_IPA_GETKEYTAB_FAILED,
+     ERR_TRUST_FOREST_UNKNOWN,
+     ERR_P11_CHILD,
++    ERR_SUBDOM_INACTIVE,
+     ERR_LAST            /* ALWAYS LAST */
+ };
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch b/SOURCES/0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch
new file mode 100644
index 0000000..32ad0fd
--- /dev/null
+++ b/SOURCES/0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch
@@ -0,0 +1,499 @@
+From 6c1e606c3e9da9910554e48a6409a9b3001deedb Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Fri, 4 Sep 2015 09:27:17 +0200
+Subject: [PATCH 75/87] DP: Provide a way to mark subdomain as disabled and
+ auto-enable it later with offline_timeout
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://fedorahosted.org/sssd/ticket/2637
+
+Adds a new Data Provider function be_mark_dom_offline() that is a
+replacement for be_mark_offline(). When called, the function would
+either set the whole back end offline, just like be_mark_offline or just
+set the subdomain status to inactive.
+
+When a subdomain is inactive, there is a singleton timed task that would
+re-set the subdomin after offline_timeout seconds.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+---
+ Makefile.am                              |  26 +++
+ src/providers/data_provider_be.c         | 102 +++++++++++-
+ src/providers/dp_backend.h               |   1 +
+ src/tests/cmocka/test_data_provider_be.c | 275 +++++++++++++++++++++++++++++++
+ 4 files changed, 395 insertions(+), 9 deletions(-)
+ create mode 100644 src/tests/cmocka/test_data_provider_be.c
+
+diff --git a/Makefile.am b/Makefile.am
+index e1102333b019e32c516c59c5fa969c970b688737..4e80701872c0e4e1391f0c6de8a2f68e719f8236 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -236,6 +236,7 @@ if HAVE_CMOCKA
+         test_ipa_subdom_server \
+         test_krb5_wait_queue \
+         test_cert_utils \
++        test_data_provider_be \
+         $(NULL)
+ 
+ if HAVE_LIBRESOLV
+@@ -2603,6 +2604,31 @@ test_cert_utils_LDADD = \
+     libsss_cert.la \
+     libsss_crypt.la \
+     $(NULL)
++
++test_data_provider_be_SOURCES = \
++    $(sssd_be_SOURCES) \
++    src/tests/cmocka/test_data_provider_be.c \
++    src/tests/cmocka/common_mock_be.c \
++    $(NULL)
++test_data_provider_be_CFLAGS = \
++    $(AM_CFLAGS) \
++    -DUNIT_TESTING \
++    $(CRYPTO_CFLAGS) \
++    $(NULL)
++test_data_provider_be_LDFLAGS = \
++    -Wl,-wrap,_tevent_add_timer \
++    $(NULL)
++test_data_provider_be_LDADD = \
++    $(CMOCKA_LIBS) \
++    $(CARES_LIBS) \
++    $(POPT_LIBS) \
++    $(PAM_LIBS) \
++    $(TALLOC_LIBS) \
++    $(SSSD_INTERNAL_LTLIBS) \
++    libsss_debug.la \
++    libsss_test_common.la \
++    $(NULL)
++
+ endif # HAVE_CMOCKA
+ 
+ noinst_PROGRAMS = pam_test_client
+diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
+index d147630248f0a24f5a632760b55b9284a6928e40..f477ac8bde2b1e3eea862e8e8f503566282ea8f3 100644
+--- a/src/providers/data_provider_be.c
++++ b/src/providers/data_provider_be.c
+@@ -478,6 +478,24 @@ try_to_go_online(TALLOC_CTX *mem_ctx,
+     return EOK;
+ }
+ 
++static int get_offline_timeout(struct be_ctx *ctx)
++{
++    errno_t ret;
++    int offline_timeout;
++
++    ret = confdb_get_int(ctx->cdb, ctx->conf_path,
++                         CONFDB_DOMAIN_OFFLINE_TIMEOUT, 60,
++                         &offline_timeout);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Failed to get offline_timeout from confdb. "
++              "Will use 60 seconds.\n");
++        offline_timeout = 60;
++    }
++
++    return offline_timeout;
++}
++
+ void be_mark_offline(struct be_ctx *ctx)
+ {
+     int offline_timeout;
+@@ -493,15 +511,9 @@ void be_mark_offline(struct be_ctx *ctx)
+         /* This is the first time we go offline - create a periodic task
+          * to check if we can switch to online. */
+         DEBUG(SSSDBG_TRACE_INTERNAL, "Initialize check_if_online_ptask.\n");
+-        ret = confdb_get_int(ctx->cdb, ctx->conf_path,
+-                             CONFDB_DOMAIN_OFFLINE_TIMEOUT, 60,
+-                             &offline_timeout);
+-        if (ret != EOK) {
+-            DEBUG(SSSDBG_CRIT_FAILURE,
+-                  "Failed to get offline_timeout from confdb. "
+-                  "Will use 60 seconds.\n");
+-            offline_timeout = 60;
+-        }
++
++        offline_timeout = get_offline_timeout(ctx);
++
+         ret = be_ptask_create_sync(ctx, ctx,
+                                    offline_timeout, offline_timeout,
+                                    offline_timeout, 30, offline_timeout,
+@@ -524,10 +536,82 @@ void be_mark_offline(struct be_ctx *ctx)
+     be_run_offline_cb(ctx);
+ }
+ 
++static void be_subdom_reset_status(struct tevent_context *ev,
++                                  struct tevent_timer *te,
++                                  struct timeval current_time,
++                                  void *pvt)
++{
++    struct sss_domain_info *subdom = talloc_get_type(pvt,
++                                                     struct sss_domain_info);
++
++    DEBUG(SSSDBG_TRACE_LIBS, "Resetting subdomain %s\n", subdom->name);
++    subdom->state = DOM_ACTIVE;
++}
++
++static void be_mark_subdom_offline(struct sss_domain_info *subdom,
++                                   struct be_ctx *be_ctx)
++{
++    struct timeval tv;
++    struct tevent_timer *timeout = NULL;
++    int reset_status_timeout;
++
++    reset_status_timeout = get_offline_timeout(be_ctx);
++    tv = tevent_timeval_current_ofs(reset_status_timeout, 0);
++
++    switch (subdom->state) {
++    case DOM_DISABLED:
++        DEBUG(SSSDBG_MINOR_FAILURE, "Won't touch disabled subdomain\n");
++        return;
++    case DOM_INACTIVE:
++        DEBUG(SSSDBG_TRACE_ALL, "Subdomain already inactive\n");
++        return;
++    case DOM_ACTIVE:
++        DEBUG(SSSDBG_TRACE_LIBS,
++              "Marking subdomain %s as inactive\n", subdom->name);
++        break;
++    }
++
++    timeout = tevent_add_timer(be_ctx->ev, be_ctx, tv,
++                               be_subdom_reset_status, subdom);
++    if (timeout == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "Cannot create timer\n");
++        return;
++    }
++
++    subdom->state = DOM_INACTIVE;
++}
++
++void be_mark_dom_offline(struct sss_domain_info *dom, struct be_ctx *ctx)
++{
++    if (IS_SUBDOMAIN(dom) == false) {
++        DEBUG(SSSDBG_TRACE_LIBS, "Marking back end offline\n");
++        be_mark_offline(ctx);
++    } else {
++        DEBUG(SSSDBG_TRACE_LIBS, "Marking subdomain %s offline\n", dom->name);
++        be_mark_subdom_offline(dom, ctx);
++    }
++}
++
++static void reactivate_subdoms(struct sss_domain_info *head)
++{
++    struct sss_domain_info *dom;
++
++    DEBUG(SSSDBG_TRACE_LIBS, "Resetting all subdomains");
++
++    for (dom = head; dom; dom = get_next_domain(dom, true)) {
++        if (sss_domain_get_state(dom) == DOM_INACTIVE) {
++            sss_domain_set_state(dom, DOM_ACTIVE);
++        }
++    }
++}
++
+ static void be_reset_offline(struct be_ctx *ctx)
+ {
+     ctx->offstat.went_offline = 0;
+     ctx->offstat.offline = false;
++
++    reactivate_subdoms(ctx->domain);
++
+     be_ptask_disable(ctx->check_if_online_ptask);
+     be_run_online_cb(ctx);
+ }
+diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
+index e4e22ea343a5cbf4c75f176c3002dc579c2893fe..4d54bf547682379bcb8cf855b8fae39214495728 100644
+--- a/src/providers/dp_backend.h
++++ b/src/providers/dp_backend.h
+@@ -189,6 +189,7 @@ struct be_host_req {
+ 
+ bool be_is_offline(struct be_ctx *ctx);
+ void be_mark_offline(struct be_ctx *ctx);
++void be_mark_dom_offline(struct sss_domain_info *dom, struct be_ctx *ctx);
+ 
+ int be_add_reconnect_cb(TALLOC_CTX *mem_ctx,
+                         struct be_ctx *ctx,
+diff --git a/src/tests/cmocka/test_data_provider_be.c b/src/tests/cmocka/test_data_provider_be.c
+new file mode 100644
+index 0000000000000000000000000000000000000000..68eb5841bee568bef64cb62461403036b1320bec
+--- /dev/null
++++ b/src/tests/cmocka/test_data_provider_be.c
+@@ -0,0 +1,275 @@
++/*
++    Copyright (C) 2015 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 <talloc.h>
++#include <tevent.h>
++#include <errno.h>
++#include <popt.h>
++#include <time.h>
++
++#include "providers/dp_backend.h"
++#include "tests/cmocka/common_mock.h"
++#include "tests/cmocka/common_mock_be.h"
++#include "tests/common.h"
++
++#define TESTS_PATH "tests_dp_be"
++#define TEST_CONF_DB "test_dp_be_conf.ldb"
++#define TEST_DOM_NAME "dp_be_test"
++#define TEST_ID_PROVIDER "ldap"
++
++#define OFFLINE_TIMEOUT 2
++#define AS_STR(param) (#param)
++
++static TALLOC_CTX *global_mock_context = NULL;
++static bool global_timer_added;
++
++struct tevent_timer *__real__tevent_add_timer(struct tevent_context *ev,
++                                              TALLOC_CTX *mem_ctx,
++                                              struct timeval next_event,
++                                              tevent_timer_handler_t handler,
++                                              void *private_data,
++                                              const char *handler_name,
++                                              const char *location);
++
++struct tevent_timer *__wrap__tevent_add_timer(struct tevent_context *ev,
++                                              TALLOC_CTX *mem_ctx,
++                                              struct timeval next_event,
++                                              tevent_timer_handler_t handler,
++                                              void *private_data,
++                                              const char *handler_name,
++                                              const char *location)
++{
++    global_timer_added = true;
++
++    return __real__tevent_add_timer(ev, mem_ctx, next_event,
++                                    handler, private_data, handler_name,
++                                    location);
++}
++
++
++struct test_ctx {
++    struct sss_test_ctx *tctx;
++    struct be_ctx *be_ctx;
++};
++
++static struct sss_domain_info *named_domain(TALLOC_CTX *mem_ctx,
++                                            const char *name,
++                                            struct sss_domain_info *parent)
++{
++    struct sss_domain_info *dom = NULL;
++
++    dom = talloc_zero(mem_ctx, struct sss_domain_info);
++    assert_non_null(dom);
++
++    dom->name = talloc_strdup(dom, name);
++    assert_non_null(dom->name);
++
++    dom->parent = parent;
++
++    return dom;
++}
++
++static int test_setup(void **state)
++{
++    struct test_ctx *test_ctx = NULL;
++    struct sss_test_conf_param params[] = {
++        { "offline_timeout", AS_STR(OFFLINE_TIMEOUT) },
++        { NULL, NULL },             /* Sentinel */
++    };
++
++    assert_true(leak_check_setup());
++    global_mock_context = talloc_new(global_talloc_context);
++    assert_non_null(global_mock_context);
++
++    test_ctx = talloc_zero(global_talloc_context, struct test_ctx);
++    assert_non_null(test_ctx);
++
++    test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH,
++                                         TEST_CONF_DB, TEST_DOM_NAME,
++                                         TEST_ID_PROVIDER, params);
++    assert_non_null(test_ctx->tctx);
++
++    test_ctx->be_ctx = mock_be_ctx(test_ctx, test_ctx->tctx);
++    assert_non_null(test_ctx->be_ctx);
++
++    test_ctx->be_ctx->domain->subdomains = named_domain(test_ctx,
++                                                        "subdomains",
++                                                        test_ctx->be_ctx->domain);
++    assert_non_null(test_ctx->be_ctx->domain->subdomains);
++
++    *state = test_ctx;
++
++    return 0;
++}
++
++static int test_teardown(void **state)
++{
++    talloc_zfree(*state);
++    assert_true(leak_check_teardown());
++    return 0;
++}
++
++static void assert_domain_state(struct sss_domain_info *dom,
++                                enum sss_domain_state expected_state)
++{
++    enum sss_domain_state dom_state;
++
++    dom_state = sss_domain_get_state(dom);
++    assert_int_equal(dom_state, expected_state);
++}
++
++static void test_mark_subdom_offline_check(struct tevent_context *ev,
++                                           struct tevent_timer *te,
++                                           struct timeval current_time,
++                                           void *pvt)
++{
++    struct test_ctx *test_ctx = talloc_get_type(pvt, struct test_ctx);
++
++    assert_domain_state(test_ctx->be_ctx->domain->subdomains,
++                        DOM_ACTIVE);
++
++    test_ctx->tctx->done = true;
++    test_ctx->tctx->error = EOK;
++}
++
++static void test_mark_dom_offline(void **state)
++{
++    struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx);
++
++    assert_domain_state(test_ctx->be_ctx->domain, DOM_ACTIVE);
++    assert_false(be_is_offline(test_ctx->be_ctx));
++
++    be_mark_dom_offline(test_ctx->be_ctx->domain, test_ctx->be_ctx);
++
++    assert_true(be_is_offline(test_ctx->be_ctx));
++    assert_domain_state(test_ctx->be_ctx->domain, DOM_ACTIVE);
++}
++
++static void test_mark_subdom_offline(void **state)
++{
++    struct timeval tv;
++    struct tevent_timer *check_ev = NULL;
++    struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx);
++    errno_t ret;
++
++    assert_domain_state(test_ctx->be_ctx->domain->subdomains,
++                        DOM_ACTIVE);
++    assert_false(be_is_offline(test_ctx->be_ctx));
++
++    global_timer_added = false;
++    be_mark_dom_offline(test_ctx->be_ctx->domain->subdomains, test_ctx->be_ctx);
++    assert_domain_state(test_ctx->be_ctx->domain->subdomains,
++                        DOM_INACTIVE);
++
++    /* A timer must be added that resets the state back */
++    assert_true(global_timer_added);
++
++    /* Global offline state must not change */
++    assert_false(be_is_offline(test_ctx->be_ctx));
++
++    /* Make sure we don't add a second timer */
++    global_timer_added = false;
++    be_mark_dom_offline(test_ctx->be_ctx->domain->subdomains, test_ctx->be_ctx);
++    assert_domain_state(test_ctx->be_ctx->domain->subdomains,
++                        DOM_INACTIVE);
++    assert_false(global_timer_added);
++
++    /* Wait for the internal timer to reset our subdomain back */
++    tv = tevent_timeval_current_ofs(OFFLINE_TIMEOUT + 1, 0);
++
++    check_ev = tevent_add_timer(test_ctx->tctx->ev, test_ctx, tv,
++                                test_mark_subdom_offline_check,
++                                test_ctx);
++    if (check_ev == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "Cannot create timer\n");
++        return;
++    }
++
++    ret = test_ev_loop(test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
++static void test_mark_subdom_offline_disabled(void **state)
++{
++    struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx);
++
++    sss_domain_set_state(test_ctx->be_ctx->domain->subdomains, DOM_DISABLED);
++    assert_domain_state(test_ctx->be_ctx->domain->subdomains,
++                        DOM_DISABLED);
++
++    be_mark_dom_offline(test_ctx->be_ctx->domain->subdomains, test_ctx->be_ctx);
++    assert_domain_state(test_ctx->be_ctx->domain->subdomains,
++                        DOM_DISABLED);
++}
++
++int main(int argc, const char *argv[])
++{
++    poptContext pc;
++    int opt;
++    int rv;
++    int no_cleanup = 0;
++    struct poptOption long_options[] = {
++        POPT_AUTOHELP
++        SSSD_DEBUG_OPTS
++        {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0,
++         _("Do not delete the test database after a test run"), NULL },
++        POPT_TABLEEND
++    };
++
++    const struct CMUnitTest tests[] = {
++        cmocka_unit_test_setup_teardown(test_mark_dom_offline,
++                                        test_setup,
++                                        test_teardown),
++        cmocka_unit_test_setup_teardown(test_mark_subdom_offline,
++                                        test_setup,
++                                        test_teardown),
++        cmocka_unit_test_setup_teardown(test_mark_subdom_offline_disabled,
++                                        test_setup,
++                                        test_teardown),
++    };
++
++    /* Set debug level to invalid value so we can deside if -d 0 was used. */
++    debug_level = SSSDBG_INVALID;
++
++    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
++    while((opt = poptGetNextOpt(pc)) != -1) {
++        switch(opt) {
++        default:
++            fprintf(stderr, "\nInvalid option %s: %s\n\n",
++                    poptBadOption(pc, 0), poptStrerror(opt));
++            poptPrintUsage(pc, stderr, 0);
++            return 1;
++        }
++    }
++    poptFreeContext(pc);
++
++    DEBUG_CLI_INIT(debug_level);
++
++    /* Even though normally the tests should clean up after themselves
++     * they might not after a failed run. Remove the old db to be sure */
++    tests_set_cwd();
++    test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME);
++    test_dom_suite_setup(TESTS_PATH);
++
++    rv = cmocka_run_group_tests(tests, NULL, NULL);
++    if (rv == 0 && !no_cleanup) {
++        test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME);
++    }
++    return rv;
++
++    return cmocka_run_group_tests(tests, NULL, NULL);
++}
+-- 
+2.4.3
+
diff --git a/SOURCES/0075-PAM-Remove-authtok-from-PAM-stack-with-OTP.patch b/SOURCES/0075-PAM-Remove-authtok-from-PAM-stack-with-OTP.patch
deleted file mode 100644
index a8c6200..0000000
--- a/SOURCES/0075-PAM-Remove-authtok-from-PAM-stack-with-OTP.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-From 5af7fea571868eed16655adffcc9314911e12417 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Mon, 20 Oct 2014 22:21:25 +0200
-Subject: [PATCH 75/87] PAM: Remove authtok from PAM stack with OTP
-
-We remove the password from the PAM stack when OTP is used to make sure
-that other pam modules (pam-gnome-keyring, pam_mount) cannot use it anymore
-and have to request a password on their own.
-
-Resolves:
-    https://fedorahosted.org/sssd/ticket/2287
-
-Reviewed-by: Nathaniel McCallum <npmccallum@redhat.com>
----
- src/providers/krb5/krb5_auth.c | 14 ++++++++++++++
- src/sss_client/pam_sss.c       | 16 +++++++++++++++-
- 2 files changed, 29 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
-index f539d5068ec29f7b06f734a3417864b43122b1b7..c96b7aee99da8c3d43a67a04bb1f67ee048d4705 100644
---- a/src/providers/krb5/krb5_auth.c
-+++ b/src/providers/krb5/krb5_auth.c
-@@ -1161,6 +1161,20 @@ static void krb5_auth_done(struct tevent_req *subreq)
-         krb5_auth_store_creds(state->domain, pd);
-     }
- 
-+    if (res->otp == true && pd->cmd == SSS_PAM_AUTHENTICATE) {
-+        uint32_t otp_flag = 1;
-+        ret = pam_add_response(pd, SSS_OTP, sizeof(uint32_t),
-+                               (const uint8_t *) &otp_flag);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "pam_add_response failed: %d (%s).\n",
-+                  ret, sss_strerror(ret));
-+            state->pam_status = PAM_SYSTEM_ERR;
-+            state->dp_err = DP_ERR_OK;
-+            goto done;
-+        }
-+    }
-+
-     state->pam_status = PAM_SUCCESS;
-     state->dp_err = DP_ERR_OK;
-     ret = EOK;
-diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
-index abe9b05478cbf480b3430dccd1951e9bfb0e29c1..d64e826daeb80be8998ef3b410047e3a44051b07 100644
---- a/src/sss_client/pam_sss.c
-+++ b/src/sss_client/pam_sss.c
-@@ -206,7 +206,7 @@ static size_t add_string_item(enum pam_item_type type, const char *str,
-     return rp;
- }
- 
--static void overwrite_and_free_pam_items(struct pam_items *pi)
-+static void overwrite_and_free_authtoks(struct pam_items *pi)
- {
-     if (pi->pam_authtok != NULL) {
-         _pam_overwrite_n((void *)pi->pam_authtok, pi->pam_authtok_size);
-@@ -222,6 +222,11 @@ static void overwrite_and_free_pam_items(struct pam_items *pi)
- 
-     pi->pamstack_authtok = NULL;
-     pi->pamstack_oldauthtok = NULL;
-+}
-+
-+static void overwrite_and_free_pam_items(struct pam_items *pi)
-+{
-+    overwrite_and_free_authtoks(pi);
- 
-     free(pi->domain_name);
-     pi->domain_name = NULL;
-@@ -998,6 +1003,15 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf,
-                     D(("do_pam_conversation failed."));
-                 }
-                 break;
-+            case SSS_OTP:
-+                D(("OTP was used, removing authtokens."));
-+                overwrite_and_free_authtoks(pi);
-+                ret = pam_set_item(pamh, PAM_AUTHTOK, NULL);
-+                if (ret != PAM_SUCCESS) {
-+                    D(("Failed to remove PAM_AUTHTOK after using otp [%s]",
-+                       pam_strerror(pamh,ret)));
-+                }
-+                break;
-             default:
-                 D(("Unknown response type [%d]", type));
-         }
--- 
-1.9.3
-
diff --git a/SOURCES/0076-Revert-LDAP-Remove-unused-option-ldap_user_uuid.patch b/SOURCES/0076-Revert-LDAP-Remove-unused-option-ldap_user_uuid.patch
deleted file mode 100644
index 8ef2540..0000000
--- a/SOURCES/0076-Revert-LDAP-Remove-unused-option-ldap_user_uuid.patch
+++ /dev/null
@@ -1,176 +0,0 @@
-From 60720e16c292cd944677a675728d11d405d8885d Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 5 Nov 2014 17:35:45 +0100
-Subject: [PATCH 76/79] Revert "LDAP: Remove unused option ldap_user_uuid"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This reverts commit dfb2960ab251f609466fa660449703835c97f99a.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/config/SSSDConfig/__init__.py.in         |  1 +
- src/config/SSSDConfig/sssd_upgrade_config.py |  1 +
- src/config/etc/sssd.api.d/sssd-ad.conf       |  1 +
- src/config/etc/sssd.api.d/sssd-ipa.conf      |  1 +
- src/config/etc/sssd.api.d/sssd-ldap.conf     |  1 +
- src/man/sssd-ldap.5.xml                      | 13 +++++++++++++
- src/providers/ad/ad_opts.h                   |  1 +
- src/providers/ipa/ipa_opts.h                 |  1 +
- src/providers/ldap/ldap_opts.h               |  4 ++++
- src/providers/ldap/sdap.h                    |  1 +
- 10 files changed, 25 insertions(+)
-
-diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
-index b4560ea2b33f2c3b82bff42fb6a36302a146c99f..73195bc46688e14bfdd456f6345e45bdc3d0a8f0 100644
---- a/src/config/SSSDConfig/__init__.py.in
-+++ b/src/config/SSSDConfig/__init__.py.in
-@@ -272,6 +272,7 @@ option_strings = {
-     'ldap_user_gecos' : _('GECOS attribute'),
-     'ldap_user_home_directory' : _('Home directory attribute'),
-     'ldap_user_shell' : _('Shell attribute'),
-+    'ldap_user_uuid' : _('UUID attribute'),
-     'ldap_user_objectsid' : _("objectSID attribute"),
-     'ldap_user_primary_group' : _('Active Directory primary group attribute for ID-mapping'),
-     'ldap_user_principal' : _('User principal attribute (for Kerberos)'),
-diff --git a/src/config/SSSDConfig/sssd_upgrade_config.py b/src/config/SSSDConfig/sssd_upgrade_config.py
-index 3d9f788c3b4707a8b6e8958d11d5068437d31156..97be6543f8f86eb0189843003f675d2efcfcc8a5 100644
---- a/src/config/SSSDConfig/sssd_upgrade_config.py
-+++ b/src/config/SSSDConfig/sssd_upgrade_config.py
-@@ -170,6 +170,7 @@ class SSSDConfigFile(SSSDChangeConf):
-                     'ldap_user_gecos' : 'userGecos',
-                     'ldap_user_home_directory' : 'userHomeDirectory',
-                     'ldap_user_shell' : 'userShell',
-+                    'ldap_user_uuid' : 'userUUID',
-                     'ldap_user_principal' : 'userPrincipal',
-                     'ldap_force_upper_case_realm' : 'force_upper_case_realm',
-                     'ldap_user_fullname' : 'userFullname',
-diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
-index 5dd4fb43526849e6b74fbe7cd354afda9af695b0..f8b200eaaf2f1b2ee17214faf2df70b14a2ec93c 100644
---- a/src/config/etc/sssd.api.d/sssd-ad.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
-@@ -72,6 +72,7 @@ ldap_user_gid_number = str, None, false
- ldap_user_gecos = str, None, false
- ldap_user_home_directory = str, None, false
- ldap_user_shell = str, None, false
-+ldap_user_uuid = str, None, false
- ldap_user_objectsid = str, None, false
- ldap_user_primary_group = str, None, false
- ldap_user_principal = str, None, false
-diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
-index 8713385fc2b6d3b03b75cd5c6557968fdcdad892..91dc9ec9d158758be32f8a3eb5d36be2446fc254 100644
---- a/src/config/etc/sssd.api.d/sssd-ipa.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
-@@ -69,6 +69,7 @@ ldap_user_gid_number = str, None, false
- ldap_user_gecos = str, None, false
- ldap_user_home_directory = str, None, false
- ldap_user_shell = str, None, false
-+ldap_user_uuid = str, None, false
- ldap_user_objectsid = str, None, false
- ldap_user_primary_group = str, None, false
- ldap_user_principal = str, None, false
-diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
-index 29276bfd74b9fcc67042a138006959896c34fbae..68d5b4953a07398b159f3374ccba7380a642d818 100644
---- a/src/config/etc/sssd.api.d/sssd-ldap.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
-@@ -56,6 +56,7 @@ ldap_user_gid_number = str, None, false
- ldap_user_gecos = str, None, false
- ldap_user_home_directory = str, None, false
- ldap_user_shell = str, None, false
-+ldap_user_uuid = str, None, false
- ldap_user_objectsid = str, None, false
- ldap_user_primary_group = str, None, false
- ldap_user_principal = str, None, false
-diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
-index 9a9410b415a7419ee303aea6ec2f9f3d41509647..24bc34d3b9ca7a93b241a14ef712d4187306a347 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -338,6 +338,19 @@
-                 </varlistentry>
- 
-                 <varlistentry>
-+                    <term>ldap_user_uuid (string)</term>
-+                    <listitem>
-+                        <para>
-+                            The LDAP attribute that contains the UUID/GUID of
-+                            an LDAP user object.
-+                        </para>
-+                        <para>
-+                            Default: nsUniqueId
-+                        </para>
-+                    </listitem>
-+                </varlistentry>
-+
-+                <varlistentry>
-                     <term>ldap_user_objectsid (string)</term>
-                     <listitem>
-                         <para>
-diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
-index 452516cd24aba4dfbf74376767deb8f5f487253d..ee70b3c4b71b87ab31ac07310a448d7960f8e9a8 100644
---- a/src/providers/ad/ad_opts.h
-+++ b/src/providers/ad/ad_opts.h
-@@ -187,6 +187,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = {
-     { "ldap_user_principal", "userPrincipalName", SYSDB_UPN, NULL },
-     { "ldap_user_fullname", "name", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
-+    { "ldap_user_uuid", "objectGUID", SYSDB_UUID, NULL },
-     { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_user_primary_group", "primaryGroupID", SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL },
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index 473eca4f77727e008663d082e954820a9fb0c427..3fe858ca384015b3ffabe7ce391fa51089354719 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -178,6 +178,7 @@ struct sdap_attr_map ipa_user_map[] = {
-     { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL },
-     { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
-+    { "ldap_user_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-     { "ldap_user_objectsid", "ipaNTSecurityIdentifier", SYSDB_SID_STR, NULL },
-     { "ldap_user_primary_group", NULL, SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
-index 61e3309fe73e72e82ecb471d9b608db7bea1d2e6..2e937412635e16b4bc541c59055b1c4e7896f045 100644
---- a/src/providers/ldap/ldap_opts.h
-+++ b/src/providers/ldap/ldap_opts.h
-@@ -155,6 +155,7 @@ struct sdap_attr_map rfc2307_user_map[] = {
-     { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL },
-     { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", NULL, SYSDB_MEMBEROF, NULL },
-+    { "ldap_user_uuid", NULL, SYSDB_UUID, NULL },
-     { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_user_primary_group", NULL, SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-@@ -207,6 +208,8 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
-     { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL },
-     { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
-+    /* FIXME: this is 389ds specific */
-+    { "ldap_user_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-     { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_user_primary_group", NULL, SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-@@ -259,6 +262,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = {
-     { "ldap_user_principal", "userPrincipalName", SYSDB_UPN, NULL },
-     { "ldap_user_fullname", "name", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
-+    { "ldap_user_uuid", "objectGUID", SYSDB_UUID, NULL },
-     { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_user_primary_group", "primaryGroupID", SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL },
-diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
-index e9e23561c4c74d3b33ebe35aab86fc257bde6237..906fd74090509802909b300d26234f96d324a769 100644
---- a/src/providers/ldap/sdap.h
-+++ b/src/providers/ldap/sdap.h
-@@ -256,6 +256,7 @@ enum sdap_user_attrs {
-     SDAP_AT_USER_PRINC,
-     SDAP_AT_USER_FULLNAME,
-     SDAP_AT_USER_MEMBEROF,
-+    SDAP_AT_USER_UUID,
-     SDAP_AT_USER_OBJECTSID,
-     SDAP_AT_USER_PRIMARY_GROUP,
-     SDAP_AT_USER_MODSTAMP,
--- 
-1.9.3
-
diff --git a/SOURCES/0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch b/SOURCES/0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch
new file mode 100644
index 0000000..58bc0b3
--- /dev/null
+++ b/SOURCES/0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch
@@ -0,0 +1,43 @@
+From d170e144a1ae702ba55c508599ffbda4e95919e5 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 2 Sep 2015 13:40:48 +0200
+Subject: [PATCH 76/87] SDAP: Do not set is_offline if ignore_mark_offline is
+ set
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Required for:
+https://fedorahosted.org/sssd/ticket/2637
+
+The caller of the sdap_id_op requests can set the ignore_mark_offline
+flag to avoid the sdap_id_op from marking the whole back end as offline.
+
+However, there was a small bug - the is_offline internal sdap_id_op flag
+was still being set. As a consequence, the error code from the
+connection was ignored and EAGAIN was always returned.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 0561d532cf76b035b73cfed929a6896071dac407)
+---
+ src/providers/ldap/sdap_id_op.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c
+index 508bbd2ad3ebb3f9159a8b7f48258ff31a7cd6e2..0474a9cb7828ef43ef76cf6bebac077315296875 100644
+--- a/src/providers/ldap/sdap_id_op.c
++++ b/src/providers/ldap/sdap_id_op.c
+@@ -567,9 +567,9 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq)
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "Failed to connect, going offline (%d [%s])\n",
+                    ret, strerror(ret));
++            is_offline = true;
+             be_mark_offline(conn_cache->id_conn->id_ctx->be);
+         }
+-        is_offline = true;
+     }
+ 
+     if (ret == EOK) {
+-- 
+2.4.3
+
diff --git a/SOURCES/0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch b/SOURCES/0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch
new file mode 100644
index 0000000..2cf3e51
--- /dev/null
+++ b/SOURCES/0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch
@@ -0,0 +1,41 @@
+From 4b9db04661f30625fb00bb22dc7ff84e77d2efb2 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 2 Sep 2015 13:42:06 +0200
+Subject: [PATCH 77/87] AD: Only ignore errors from SDAP lookups if there's
+ another connection to fallback to
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Required for:
+https://fedorahosted.org/sssd/ticket/2637
+
+The AD lookup code honors the ignore_mark_offline flag in the sense that
+if it's set, the sdap return code is not reported to the upper layer,
+but EOK is returned as request status and the sdap return code is
+returned separately.
+
+This patch modifies the behaviour further to only apply if there is
+another connection to fall back to.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 7fc8692d49cdaa0368072f196433c07b475da679)
+---
+ src/providers/ad/ad_id.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
+index 7a0c6eccd2d2f0d4f8a545a9d4873a9447179a00..4f327f823173eb113153a556322dae4cc4b42f3e 100644
+--- a/src/providers/ad/ad_id.c
++++ b/src/providers/ad/ad_id.c
+@@ -146,6 +146,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
+ 
+     ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err, &sdap_err);
+     if (dp_error == DP_ERR_OFFLINE
++        && state->conn[state->cindex+1] != NULL
+         && state->conn[state->cindex]->ignore_mark_offline) {
+          /* This is a special case: GC does not work.
+           *  We need to Fall back to ldap
+-- 
+2.4.3
+
diff --git a/SOURCES/0077-Revert-LDAP-Remove-unused-option-ldap_group_uuid.patch b/SOURCES/0077-Revert-LDAP-Remove-unused-option-ldap_group_uuid.patch
deleted file mode 100644
index ff902cb..0000000
--- a/SOURCES/0077-Revert-LDAP-Remove-unused-option-ldap_group_uuid.patch
+++ /dev/null
@@ -1,176 +0,0 @@
-From cce184b46a1109d8e1e318b4538ee960ba67619d Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 5 Nov 2014 17:38:05 +0100
-Subject: [PATCH 77/79] Revert "LDAP: Remove unused option ldap_group_uuid"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This reverts commit b5242c146cc0ca96e2b898a74fb060efda15bc77.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/config/SSSDConfig/__init__.py.in         |  1 +
- src/config/SSSDConfig/sssd_upgrade_config.py |  1 +
- src/config/etc/sssd.api.d/sssd-ad.conf       |  1 +
- src/config/etc/sssd.api.d/sssd-ipa.conf      |  1 +
- src/config/etc/sssd.api.d/sssd-ldap.conf     |  1 +
- src/man/sssd-ldap.5.xml                      | 13 +++++++++++++
- src/providers/ad/ad_opts.h                   |  1 +
- src/providers/ipa/ipa_opts.h                 |  1 +
- src/providers/ldap/ldap_opts.h               |  4 ++++
- src/providers/ldap/sdap.h                    |  1 +
- 10 files changed, 25 insertions(+)
-
-diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
-index 73195bc46688e14bfdd456f6345e45bdc3d0a8f0..283ed2d37c894db95bac38c23d25c4ac8d1f4a40 100644
---- a/src/config/SSSDConfig/__init__.py.in
-+++ b/src/config/SSSDConfig/__init__.py.in
-@@ -309,6 +309,7 @@ option_strings = {
-     'ldap_group_pwd' : _('Group password'),
-     'ldap_group_gid_number' : _('GID attribute'),
-     'ldap_group_member' : _('Group member attribute'),
-+    'ldap_group_uuid' : _('Group UUID attribute'),
-     'ldap_group_objectsid' : _("objectSID attribute"),
-     'ldap_group_modify_timestamp' : _('Modification time attribute for groups'),
-     'ldap_group_type' : _('Type of the group and other flags'),
-diff --git a/src/config/SSSDConfig/sssd_upgrade_config.py b/src/config/SSSDConfig/sssd_upgrade_config.py
-index 97be6543f8f86eb0189843003f675d2efcfcc8a5..33d9fed74424a7d3ee28e888aaed724d0a8a94ff 100644
---- a/src/config/SSSDConfig/sssd_upgrade_config.py
-+++ b/src/config/SSSDConfig/sssd_upgrade_config.py
-@@ -184,6 +184,7 @@ class SSSDConfigFile(SSSDChangeConf):
-                     'ldap_group_pwd' : 'userPassword',
-                     'ldap_group_gid_number' : 'groupGidNumber',
-                     'ldap_group_member' : 'groupMember',
-+                    'ldap_group_uuid' : 'groupUUID',
-                     'ldap_group_modify_timestamp' : 'modifyTimestamp',
-                     'ldap_network_timeout' : 'network_timeout',
-                     'ldap_offline_timeout' : 'offline_timeout',
-diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
-index f8b200eaaf2f1b2ee17214faf2df70b14a2ec93c..3daa2560b14d74f7686ed47cf1b09e2005eb8917 100644
---- a/src/config/etc/sssd.api.d/sssd-ad.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
-@@ -98,6 +98,7 @@ ldap_group_object_class = str, None, false
- ldap_group_name = str, None, false
- ldap_group_gid_number = str, None, false
- ldap_group_member = str, None, false
-+ldap_group_uuid = str, None, false
- ldap_group_objectsid = str, None, false
- ldap_group_modify_timestamp = str, None, false
- ldap_group_entry_usn = str, None, false
-diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
-index 91dc9ec9d158758be32f8a3eb5d36be2446fc254..5df52581e67657e41e2f08820b885f100ccd7ca9 100644
---- a/src/config/etc/sssd.api.d/sssd-ipa.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
-@@ -95,6 +95,7 @@ ldap_group_object_class = str, None, false
- ldap_group_name = str, None, false
- ldap_group_gid_number = str, None, false
- ldap_group_member = str, None, false
-+ldap_group_uuid = str, None, false
- ldap_group_objectsid = str, None, false
- ldap_group_modify_timestamp = str, None, false
- ldap_group_entry_usn = str, None, false
-diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
-index 68d5b4953a07398b159f3374ccba7380a642d818..ba5f56f1942da552fc6ab8f82851714756683a8f 100644
---- a/src/config/etc/sssd.api.d/sssd-ldap.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
-@@ -90,6 +90,7 @@ ldap_group_object_class = str, None, false
- ldap_group_name = str, None, false
- ldap_group_gid_number = str, None, false
- ldap_group_member = str, None, false
-+ldap_group_uuid = str, None, false
- ldap_group_objectsid = str, None, false
- ldap_group_modify_timestamp = str, None, false
- ldap_group_entry_usn = str, None, false
-diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
-index 24bc34d3b9ca7a93b241a14ef712d4187306a347..f45522bd5f6c599bce7a38d8821cb0a08f6b5df3 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -859,6 +859,19 @@
-                 </varlistentry>
- 
-                 <varlistentry>
-+                    <term>ldap_group_uuid (string)</term>
-+                    <listitem>
-+                        <para>
-+                            The LDAP attribute that contains the UUID/GUID of
-+                            an LDAP group object.
-+                        </para>
-+                        <para>
-+                            Default: nsUniqueId
-+                        </para>
-+                    </listitem>
-+                </varlistentry>
-+
-+                <varlistentry>
-                     <term>ldap_group_objectsid (string)</term>
-                     <listitem>
-                         <para>
-diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
-index ee70b3c4b71b87ab31ac07310a448d7960f8e9a8..ac6006c9200464956ccedb17ff53050fed5fc6ea 100644
---- a/src/providers/ad/ad_opts.h
-+++ b/src/providers/ad/ad_opts.h
-@@ -221,6 +221,7 @@ struct sdap_attr_map ad_2008r2_group_map[] = {
-     { "ldap_group_pwd", NULL, SYSDB_PWD, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
-+    { "ldap_group_uuid", "objectGUID", SYSDB_UUID, NULL },
-     { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_group_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL },
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index 3fe858ca384015b3ffabe7ce391fa51089354719..e0478db39913b87c071d8f4daf9c2a0b33a0b0f4 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -212,6 +212,7 @@ struct sdap_attr_map ipa_group_map[] = {
-     { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
-+    { "ldap_group_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-     { "ldap_group_objectsid", "ipaNTSecurityIdentifier", SYSDB_SID_STR, NULL },
-     { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL },
-diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
-index 2e937412635e16b4bc541c59055b1c4e7896f045..096a63bd53918ba79378c01257a18e543597209a 100644
---- a/src/providers/ldap/ldap_opts.h
-+++ b/src/providers/ldap/ldap_opts.h
-@@ -189,6 +189,7 @@ struct sdap_attr_map rfc2307_group_map[] = {
-     { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "memberuid", SYSDB_MEMBER, NULL },
-+    { "ldap_group_uuid", NULL, SYSDB_UUID, NULL },
-     { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL },
-@@ -243,6 +244,8 @@ struct sdap_attr_map rfc2307bis_group_map[] = {
-     { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
-+    /* FIXME: this is 389ds specific */
-+    { "ldap_group_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-     { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL },
-@@ -296,6 +299,7 @@ struct sdap_attr_map gen_ad2008r2_group_map[] = {
-     { "ldap_group_pwd", NULL, SYSDB_PWD, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
-+    { "ldap_group_uuid", "objectGUID", SYSDB_UUID, NULL },
-     { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_group_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL },
-diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
-index 906fd74090509802909b300d26234f96d324a769..aa10623a58d7d667205b09e744dc2b924ca821ed 100644
---- a/src/providers/ldap/sdap.h
-+++ b/src/providers/ldap/sdap.h
-@@ -295,6 +295,7 @@ enum sdap_group_attrs {
-     SDAP_AT_GROUP_PWD,
-     SDAP_AT_GROUP_GID,
-     SDAP_AT_GROUP_MEMBER,
-+    SDAP_AT_GROUP_UUID,
-     SDAP_AT_GROUP_OBJECTSID,
-     SDAP_AT_GROUP_MODSTAMP,
-     SDAP_AT_GROUP_USN,
--- 
-1.9.3
-
diff --git a/SOURCES/0078-Fix-uuid-defaults.patch b/SOURCES/0078-Fix-uuid-defaults.patch
deleted file mode 100644
index dd94248..0000000
--- a/SOURCES/0078-Fix-uuid-defaults.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From 2d9a33aaa3ecae4af7fb64c64fc2ada176b26a02 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 5 Nov 2014 18:01:07 +0100
-Subject: [PATCH 78/79] Fix uuid defaults
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Recently the uuid attributes for user and groups were removed because
-it was found that there are not used at all and that some of them where
-causing issues (https://fedorahosted.org/sssd/ticket/2383).
-
-The new views/overrides feature of FreeIPA uses the ipaUniqueID attribute
-to relate overrides with the original IPA objects. The previous two
-patches revert the removal of the uuid attributes from users and groups
-with this patch set the default value of these attributes to
-ipaUniqueID from the IPA provider, to objectGUID for the AD provider and
-leaves them unset for the general LDAP case to avoid issues like the one
-from ticket #2383.
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/man/sssd-ldap.5.xml        | 6 ++++--
- src/providers/ipa/ipa_opts.h   | 4 ++--
- src/providers/ldap/ldap_opts.h | 6 ++----
- 3 files changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
-index f45522bd5f6c599bce7a38d8821cb0a08f6b5df3..dad6f27933ced506fed7cd040e9fe91968295632 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -345,7 +345,8 @@
-                             an LDAP user object.
-                         </para>
-                         <para>
--                            Default: nsUniqueId
-+                            Default: not set in the general case, objectGUID for
-+                            AD and ipaUniqueID for IPA
-                         </para>
-                     </listitem>
-                 </varlistentry>
-@@ -866,7 +867,8 @@
-                             an LDAP group object.
-                         </para>
-                         <para>
--                            Default: nsUniqueId
-+                            Default: not set in the general case, objectGUID for
-+                            AD and ipaUniqueID for IPA
-                         </para>
-                     </listitem>
-                 </varlistentry>
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index e0478db39913b87c071d8f4daf9c2a0b33a0b0f4..59282e8699091fbccf08ddfc6825034d4f81a87f 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -178,7 +178,7 @@ struct sdap_attr_map ipa_user_map[] = {
-     { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL },
-     { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
--    { "ldap_user_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-+    { "ldap_user_uuid", "ipaUniqueID", SYSDB_UUID, NULL },
-     { "ldap_user_objectsid", "ipaNTSecurityIdentifier", SYSDB_SID_STR, NULL },
-     { "ldap_user_primary_group", NULL, SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-@@ -212,7 +212,7 @@ struct sdap_attr_map ipa_group_map[] = {
-     { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
--    { "ldap_group_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-+    { "ldap_group_uuid", "ipaUniqueID", SYSDB_UUID, NULL },
-     { "ldap_group_objectsid", "ipaNTSecurityIdentifier", SYSDB_SID_STR, NULL },
-     { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL },
-diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
-index 096a63bd53918ba79378c01257a18e543597209a..29d9faf99784bfc3526398488be837a2716ee11d 100644
---- a/src/providers/ldap/ldap_opts.h
-+++ b/src/providers/ldap/ldap_opts.h
-@@ -209,8 +209,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
-     { "ldap_user_principal", "krbPrincipalName", SYSDB_UPN, NULL },
-     { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
--    /* FIXME: this is 389ds specific */
--    { "ldap_user_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-+    { "ldap_user_uuid", NULL, SYSDB_UUID, NULL },
-     { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_user_primary_group", NULL, SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-@@ -244,8 +243,7 @@ struct sdap_attr_map rfc2307bis_group_map[] = {
-     { "ldap_group_pwd", "userPassword", SYSDB_PWD, NULL },
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
--    /* FIXME: this is 389ds specific */
--    { "ldap_group_uuid", "nsUniqueId", SYSDB_UUID, NULL },
-+    { "ldap_group_uuid", NULL, SYSDB_UUID, NULL },
-     { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
-     { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL },
--- 
-1.9.3
-
diff --git a/SOURCES/0078-KRB5-Offline-operation-with-disabled-domain.patch b/SOURCES/0078-KRB5-Offline-operation-with-disabled-domain.patch
new file mode 100644
index 0000000..690f4ac
--- /dev/null
+++ b/SOURCES/0078-KRB5-Offline-operation-with-disabled-domain.patch
@@ -0,0 +1,59 @@
+From adbeda40c0b39918b12c4f72c97a89156c6360c2 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 2 Sep 2015 15:53:34 +0200
+Subject: [PATCH 78/87] KRB5: Offline operation with disabled domain
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://fedorahosted.org/sssd/ticket/2637
+
+If a subdomain is in the disabled state, switch krb5_child operation
+into offline mode.
+
+Similarly, instead of marking the whole back end as offline, mark just
+the domain as offline -- depending on the domain type, this would mark
+the whole back end or just inactivate subdomain.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit dd0a21738e1b71940bba11134734b5999e9fd8e9)
+---
+ src/providers/krb5/krb5_auth.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
+index da8309d0504a6815902513693343a3500f454557..7ee7fa738db32abeb4709927956d1297325e2d5b 100644
+--- a/src/providers/krb5/krb5_auth.c
++++ b/src/providers/krb5/krb5_auth.c
+@@ -720,7 +720,7 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
+              * was found good, setting offline,
+              * but we still have to call the child to setup
+              * the ccache file if we are performing auth */
+-            be_mark_offline(state->be_ctx);
++            be_mark_dom_offline(state->domain, state->be_ctx);
+             kr->is_offline = true;
+ 
+             if (kr->pd->cmd == SSS_PAM_CHAUTHTOK ||
+@@ -754,9 +754,19 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
+         kr->is_offline = be_is_offline(state->be_ctx);
+     }
+ 
++    if (!kr->is_offline
++            && sss_domain_get_state(state->domain) == DOM_INACTIVE) {
++        DEBUG(SSSDBG_TRACE_INTERNAL,
++              "Subdomain %s is inactive, will proceed offline\n",
++              state->domain->name);
++        kr->is_offline = true;
++    }
++
+     if (kr->is_offline
+             && sss_krb5_realm_has_proxy(dp_opt_get_cstring(kr->krb5_ctx->opts,
+                                         KRB5_REALM))) {
++        DEBUG(SSSDBG_TRACE_FUNC,
++              "Resetting offline status, KDC proxy is in use\n");
+         kr->is_offline = false;
+     }
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch b/SOURCES/0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch
new file mode 100644
index 0000000..f299514
--- /dev/null
+++ b/SOURCES/0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch
@@ -0,0 +1,197 @@
+From 1055c11f7cafae490221e9203f33ddfa94f47c48 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 2 Sep 2015 15:52:51 +0200
+Subject: [PATCH 79/87] AD: Do not mark the whole back end as offline if
+ subdomain lookup fails
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Required for:
+https://fedorahosted.org/sssd/ticket/2637
+
+Rather mark the domain as inactive. It will be marked as active later,
+in the meantime the main domain can continue to work online and
+subdomain requests will be answered from cache.
+
+The lookup request itself just returns a special error code and lets the
+caller handle the error code as appropriate (normally by disabling the
+subdomain temporarily).
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 64d4b1e5fd4a3c99ef8d8fef6ad0db52c5152c1c)
+---
+ src/providers/ad/ad_id.c | 81 +++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 67 insertions(+), 14 deletions(-)
+
+diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
+index 4f327f823173eb113153a556322dae4cc4b42f3e..ecaf6c993bf7ddb7ba565d40ef0ad250114f5536 100644
+--- a/src/providers/ad/ad_id.c
++++ b/src/providers/ad/ad_id.c
+@@ -91,17 +91,27 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx,
+     state->ad_options = ad_options;
+     state->cindex = 0;
+ 
++    if (sss_domain_get_state(sdom->dom) == DOM_INACTIVE) {
++        ret = ERR_SUBDOM_INACTIVE;
++        goto immediate;
++    }
++
+     ret = ad_handle_acct_info_step(req);
+-    if (ret == EOK) {
+-        tevent_req_done(req);
+-        tevent_req_post(req, be_ctx->ev);
+-    } else if (ret != EAGAIN) {
+-        tevent_req_error(req, ret);
+-        tevent_req_post(req, be_ctx->ev);
++    if (ret != EAGAIN) {
++        goto immediate;
+     }
+ 
+     /* Lookup in progress */
+     return req;
++
++immediate:
++    if (ret != EOK) {
++        tevent_req_error(req, ret);
++    } else {
++        tevent_req_done(req);
++    }
++    tevent_req_post(req, be_ctx->ev);
++    return req;
+ }
+ 
+ static errno_t
+@@ -160,8 +170,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
+         state->dp_error = dp_error;
+         state->err = err;
+ 
+-        tevent_req_error(req, ret);
+-        return;
++        goto fail;
+     }
+ 
+     if (sdap_err == EOK) {
+@@ -170,8 +179,8 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
+     } else if (sdap_err == ERR_NO_POSIX) {
+         disable_gc(state->ad_options);
+     } else if (sdap_err != ENOENT) {
+-        tevent_req_error(req, EIO);
+-        return;
++        ret = EIO;
++        goto fail;
+     }
+ 
+     /* Ret is only ENOENT or ERR_NO_POSIX now. Try the next connection */
+@@ -188,12 +197,27 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
+             /* No more connections */
+             tevent_req_done(req);
+         } else {
+-            tevent_req_error(req, ret);
++            goto fail;
+         }
+         return;
+     }
+ 
+     /* Another lookup in progress */
++    return;
++
++fail:
++    if (IS_SUBDOMAIN(state->sdom->dom)) {
++        /* Deactivate subdomain on lookup errors instead of going
++         * offline completely.
++         * This is a stopgap, until our failover is per-domain,
++         * not per-backend. Unfortunately, we can't rewrite the error
++         * code on some reported codes only, because sdap_id_op code
++         * encapsulated the failover as well..
++         */
++        ret = ERR_SUBDOM_INACTIVE;
++    }
++    tevent_req_error(req, ret);
++    return;
+ }
+ 
+ errno_t
+@@ -258,6 +282,16 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
+         break;
+     }
+ 
++    /* Regardless of connection types, a subdomain error must not be allowed
++     * to set the whole back end offline, rather report an error and let the
++     * caller deal with it (normally disable the subdomain
++     */
++    if (IS_SUBDOMAIN(dom)) {
++        for (cindex = 0; clist[cindex] != NULL; cindex++) {
++            clist[cindex]->ignore_mark_offline = true;
++        }
++    }
++
+     return clist;
+ }
+ 
+@@ -328,6 +362,11 @@ done:
+ 
+ static void ad_account_info_complete(struct tevent_req *req);
+ 
++struct ad_account_info_state {
++    struct be_req *be_req;
++    struct sss_domain_info *dom;
++};
++
+ void
+ ad_account_info_handler(struct be_req *be_req)
+ {
+@@ -341,6 +380,7 @@ ad_account_info_handler(struct be_req *be_req)
+     struct sdap_id_conn_ctx **clist;
+     bool shortcut;
+     errno_t ret;
++    struct ad_account_info_state *state;
+ 
+     ad_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
+                              struct ad_id_ctx);
+@@ -391,13 +431,21 @@ ad_account_info_handler(struct be_req *be_req)
+         goto fail;
+     }
+ 
++    state = talloc(be_req, struct ad_account_info_state);
++    if (state == NULL) {
++        ret = ENOMEM;
++        goto fail;
++    }
++    state->dom = sdom->dom;
++    state->be_req = be_req;
++
+     req = ad_handle_acct_info_send(be_req, be_req, ar, sdap_id_ctx,
+                                    ad_ctx->ad_options, sdom, clist);
+     if (req == NULL) {
+         ret = ENOMEM;
+         goto fail;
+     }
+-    tevent_req_set_callback(req, ad_account_info_complete, be_req);
++    tevent_req_set_callback(req, ad_account_info_complete, state);
+     return;
+ 
+ fail:
+@@ -412,12 +460,17 @@ ad_account_info_complete(struct tevent_req *req)
+     int dp_error;
+     const char *error_text = "Internal error";
+     const char *req_error_text;
++    struct ad_account_info_state *state;
+ 
+-    be_req = tevent_req_callback_data(req, struct be_req);
++    state = tevent_req_callback_data(req, struct ad_account_info_state);
++    be_req = state->be_req;
+ 
+     ret = ad_handle_acct_info_recv(req, &dp_error, &req_error_text);
+     talloc_zfree(req);
+-    if (dp_error == DP_ERR_OK) {
++    if (ret == ERR_SUBDOM_INACTIVE) {
++        be_mark_dom_offline(state->dom, be_req_get_be_ctx(be_req));
++        return be_req_terminate(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline");
++    } else if (dp_error == DP_ERR_OK) {
+         if (ret == EOK) {
+             error_text = NULL;
+         } else {
+-- 
+2.4.3
+
diff --git a/SOURCES/0079-Revert-LDAP-Change-defaults-for-ldap_user-group_obje.patch b/SOURCES/0079-Revert-LDAP-Change-defaults-for-ldap_user-group_obje.patch
deleted file mode 100644
index fca592e..0000000
--- a/SOURCES/0079-Revert-LDAP-Change-defaults-for-ldap_user-group_obje.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-From 7f88b3a46f296520c1d73bb431c5960ba5daeba7 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 7 Nov 2014 13:27:53 +0100
-Subject: [PATCH 79/79] Revert "LDAP: Change defaults for
- ldap_user/group_objectsid"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This reverts commit f834f712548db811695ea0fd6d6b31d3bd03e2a3.
-
-OpenLDAP server cannot dereference unknown attributes. The attribute objectSID
-isn't in any standard objectclass on OpenLDAP server. This is a reason why
-objectSID cannot be set by default in rfc2307 map and rfc2307bis map.
-It is the same problem as using non standard attribute "nsUniqueId"
-in ticket https://fedorahosted.org/sssd/ticket/2383
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/man/sssd-ldap.5.xml        | 4 ++--
- src/providers/ldap/ldap_opts.h | 8 ++++----
- 2 files changed, 6 insertions(+), 6 deletions(-)
-
-diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
-index dad6f27933ced506fed7cd040e9fe91968295632..2dcf7e3f8ab5c307e0262efdebfc148c30ea3679 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -360,7 +360,7 @@
-                             necessary for ActiveDirectory servers.
-                         </para>
-                         <para>
--                            Default: ipaNTSecurityIdentifier for IPA, objectSID
-+                            Default: objectSid for ActiveDirectory, not set
-                             for other servers.
-                         </para>
-                     </listitem>
-@@ -882,7 +882,7 @@
-                             necessary for ActiveDirectory servers.
-                         </para>
-                         <para>
--                            Default: ipaNTSecurityIdentifier for IPA, objectSID
-+                            Default: objectSid for ActiveDirectory, not set
-                             for other servers.
-                         </para>
-                     </listitem>
-diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
-index 29d9faf99784bfc3526398488be837a2716ee11d..dedbdac0bcf647337d4c00b1fbb82d6b46be5b54 100644
---- a/src/providers/ldap/ldap_opts.h
-+++ b/src/providers/ldap/ldap_opts.h
-@@ -156,7 +156,7 @@ struct sdap_attr_map rfc2307_user_map[] = {
-     { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", NULL, SYSDB_MEMBEROF, NULL },
-     { "ldap_user_uuid", NULL, SYSDB_UUID, NULL },
--    { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
-+    { "ldap_user_objectsid", NULL, SYSDB_SID, NULL },
-     { "ldap_user_primary_group", NULL, SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_user_entry_usn", NULL, SYSDB_USN, NULL },
-@@ -190,7 +190,7 @@ struct sdap_attr_map rfc2307_group_map[] = {
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "memberuid", SYSDB_MEMBER, NULL },
-     { "ldap_group_uuid", NULL, SYSDB_UUID, NULL },
--    { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
-+    { "ldap_group_objectsid", NULL, SYSDB_SID, NULL },
-     { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL },
-     { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL },
-@@ -210,7 +210,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
-     { "ldap_user_fullname", "cn", SYSDB_FULLNAME, NULL },
-     { "ldap_user_member_of", "memberOf", SYSDB_MEMBEROF, NULL },
-     { "ldap_user_uuid", NULL, SYSDB_UUID, NULL },
--    { "ldap_user_objectsid", "objectSID", SYSDB_SID, NULL },
-+    { "ldap_user_objectsid", NULL, SYSDB_SID, NULL },
-     { "ldap_user_primary_group", NULL, SYSDB_PRIMARY_GROUP, NULL },
-     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_user_entry_usn", NULL, SYSDB_USN, NULL },
-@@ -244,7 +244,7 @@ struct sdap_attr_map rfc2307bis_group_map[] = {
-     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
-     { "ldap_group_member", "member", SYSDB_MEMBER, NULL },
-     { "ldap_group_uuid", NULL, SYSDB_UUID, NULL },
--    { "ldap_group_objectsid", "objectSID", SYSDB_SID, NULL },
-+    { "ldap_group_objectsid", NULL, SYSDB_SID, NULL },
-     { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
-     { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL },
-     { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL },
--- 
-1.9.3
-
diff --git a/SOURCES/0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch b/SOURCES/0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch
new file mode 100644
index 0000000..61941b7
--- /dev/null
+++ b/SOURCES/0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch
@@ -0,0 +1,157 @@
+From d89c2dc276a8974b20a77b54ba663d4a1fa5acd2 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 2 Sep 2015 12:10:03 +0000
+Subject: [PATCH 80/87] AD: Set ignore_mark_offline=false when resolving AD
+ root domain
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://fedorahosted.org/sssd/ticket/2637
+
+Avoid going offline in cases where SSSD is connected to a child domain
+but the root domain is not accessible.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit ece345a74cec793e6d970a4955beb3d4a05935b3)
+---
+ src/providers/ad/ad_subdomains.c | 56 +++++++++++++++++++++++-----------------
+ 1 file changed, 33 insertions(+), 23 deletions(-)
+
+diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
+index d1d468043410c80e6bf7f0f48a13bd9e962552af..8ed3dab0995f78a16f4a7df2e729ea88a39a782c 100644
+--- a/src/providers/ad/ad_subdomains.c
++++ b/src/providers/ad/ad_subdomains.c
+@@ -80,7 +80,8 @@ struct ad_subdomains_req_ctx {
+     struct ad_id_ctx *root_id_ctx;
+     struct sdap_id_op *root_op;
+     size_t root_base_iter;
+-    struct sysdb_attrs *root_domain;
++    struct sysdb_attrs *root_domain_attrs;
++    struct sss_domain_info *root_domain;
+ 
+     size_t reply_count;
+     struct sysdb_attrs **reply;
+@@ -689,6 +690,7 @@ static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx)
+     return EAGAIN;
+ }
+ 
++static struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx);
+ static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx);
+ static void ad_subdomains_root_conn_done(struct tevent_req *req);
+ 
+@@ -769,7 +771,14 @@ static void ad_subdomains_get_root_domain_done(struct tevent_req *req)
+         }
+     }
+ 
+-    ctx->root_domain = reply[0];
++    ctx->root_domain_attrs = reply[0];
++    ctx->root_domain = ads_get_root_domain(ctx);
++    if (ctx->root_domain == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
++        ret = EFAULT;
++        goto fail;
++    }
++
+     ctx->root_id_ctx = ads_get_root_id_ctx(ctx);
+     if (ctx->root_id_ctx == NULL) {
+         DEBUG(SSSDBG_OP_FAILURE, "Cannot create id ctx for the root domain\n");
+@@ -803,15 +812,13 @@ fail:
+     be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+ }
+ 
+-static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx)
++static struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx)
+ {
+     errno_t ret;
+     const char *name;
+     struct sss_domain_info *root;
+-    struct sdap_domain *sdom;
+-    struct ad_id_ctx *root_id_ctx;
+ 
+-    ret = sysdb_attrs_get_string(ctx->root_domain, AD_AT_TRUST_PARTNER, &name);
++    ret = sysdb_attrs_get_string(ctx->root_domain_attrs, AD_AT_TRUST_PARTNER, &name);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
+         return NULL;
+@@ -820,32 +827,40 @@ static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx)
+     /* With a subsequent run, the root should already be known */
+     root = find_domain_by_name(ctx->sd_ctx->be_ctx->domain,
+                                name, false);
+-    if (root == NULL) {
+-        DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n");
+-        return NULL;
+-    }
+ 
+-    sdom = sdap_domain_get(ctx->sd_ctx->ad_id_ctx->sdap_id_ctx->opts, root);
++    return root;
++}
++
++static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx)
++{
++    errno_t ret;
++    struct sdap_domain *sdom;
++    struct ad_id_ctx *root_id_ctx;
++
++    sdom = sdap_domain_get(ctx->sd_ctx->ad_id_ctx->sdap_id_ctx->opts,
++                           ctx->root_domain);
+     if (sdom == NULL) {
+         DEBUG(SSSDBG_OP_FAILURE,
+-              "Cannot get the sdom for %s!\n", root->name);
++              "Cannot get the sdom for %s!\n", ctx->root_domain->name);
+         return NULL;
+     }
+ 
+     if (sdom->pvt == NULL) {
+         ret = ad_subdom_ad_ctx_new(ctx->sd_ctx->be_ctx,
+                                    ctx->sd_ctx->ad_id_ctx,
+-                                   root,
++                                   ctx->root_domain,
+                                    &root_id_ctx);
+         if (ret != EOK) {
+             DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n");
+             return NULL;
+         }
++
+         sdom->pvt = root_id_ctx;
+     } else {
+         root_id_ctx = sdom->pvt;
+     }
+ 
++    root_id_ctx->ldap_ctx->ignore_mark_offline = true;
+     return root_id_ctx;
+ }
+ 
+@@ -860,16 +875,11 @@ static void ad_subdomains_root_conn_done(struct tevent_req *req)
+     ret = sdap_id_op_connect_recv(req, &dp_error);
+     talloc_zfree(req);
+     if (ret) {
+-        if (dp_error == DP_ERR_OFFLINE) {
+-            DEBUG(SSSDBG_MINOR_FAILURE,
+-                  "No AD server is available, cannot get the "
+-                  "subdomain list while offline\n");
+-        } else {
+-            DEBUG(SSSDBG_OP_FAILURE,
+-                  "Failed to connect to AD server: [%d](%s)\n",
+-                  ret, strerror(ret));
+-        }
++        be_mark_dom_offline(ctx->root_domain, be_req_get_be_ctx(ctx->be_req));
+ 
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Failed to connect to AD server: [%d](%s)\n",
++              ret, strerror(ret));
+         goto fail;
+     }
+ 
+@@ -1040,7 +1050,7 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req)
+      */
+     ret = ad_subdomains_process(ctx, ctx->sd_ctx->be_ctx->domain,
+                                 ctx->reply_count, ctx->reply,
+-                                ctx->root_domain, &nsubdoms, &subdoms);
++                                ctx->root_domain_attrs, &nsubdoms, &subdoms);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, ("Cannot process subdomain list\n"));
+         tevent_req_error(req, ret);
+-- 
+2.4.3
+
diff --git a/SOURCES/0080-LDAP-Disable-token-groups-by-default.patch b/SOURCES/0080-LDAP-Disable-token-groups-by-default.patch
deleted file mode 100644
index dd0bbcb..0000000
--- a/SOURCES/0080-LDAP-Disable-token-groups-by-default.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-From 1ded5712eb3ed631e9787beffdf9cda4d44ae6b5 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 7 Nov 2014 13:58:17 +0100
-Subject: [PATCH 80/80] LDAP: Disable token groups by default
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-We tried to speed up processing of initgroup lookups with tokenGroups even for
-the LDAP provider (if remote server is Active Directory), but it turns out that
-there are too many corner cases that we didn't catch during development that
-break. For instance, groups from other trusted domains might appear in TG and
-the LDAP provider isn't equipped to handle them.
-
-Overall, users who wish to use the added speed benefits of tokenGroups are
-advised to use the AD provider.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2483
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/man/sssd-ldap.5.xml        | 2 +-
- src/providers/ldap/ldap_opts.h | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
-index 2dcf7e3f8ab5c307e0262efdebfc148c30ea3679..d7a2a4ac9fa2497a4c347a2a7e77703e53b8a46c 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -1022,7 +1022,7 @@
-                           Active Directory Server 2008 and later.
-                         </para>
-                         <para>
--                            Default: True
-+                            Default: True for AD and IPA otherwise False.
-                         </para>
-                     </listitem>
-                 </varlistentry>
-diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
-index dedbdac0bcf647337d4c00b1fbb82d6b46be5b54..f46381e9fac7b93730ce0767154989f2e3b7ebbf 100644
---- a/src/providers/ldap/ldap_opts.h
-+++ b/src/providers/ldap/ldap_opts.h
-@@ -116,7 +116,7 @@ struct dp_option default_basic_opts[] = {
-     { "ldap_idmap_default_domain_sid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-     { "ldap_groups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
-     { "ldap_initgroups_use_matching_rule_in_chain", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
--    { "ldap_use_tokengroups", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE},
-+    { "ldap_use_tokengroups", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE},
-     { "ldap_rfc2307_fallback_to_local_users", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
-     { "ldap_disable_range_retrieval", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
-     { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
--- 
-1.9.3
-
diff --git a/SOURCES/0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch b/SOURCES/0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch
new file mode 100644
index 0000000..8b3f8b2
--- /dev/null
+++ b/SOURCES/0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch
@@ -0,0 +1,57 @@
+From fbf7fe9a713948eaf5e47518c776f2ad664b9e46 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Wed, 2 Sep 2015 13:41:26 +0200
+Subject: [PATCH 81/87] IPA: Do not allow the AD lookup code to set backend as
+ offline in server mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://fedorahosted.org/sssd/ticket/2637
+
+In server mode, we should not allow the AD lookups to set the backend
+offline. Rather just let them report an error and deal with the error
+separately.
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 20162352030d1c577bb69d44e967d2c5839e5c0e)
+---
+ src/providers/ipa/ipa_subdomains_id.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
+index 610b1c58b3b180201cfb5b22f870f8937673e02e..ff14b4a4c68cb5c6e9865a66931ee4ecd6e49211 100644
+--- a/src/providers/ipa/ipa_subdomains_id.c
++++ b/src/providers/ipa/ipa_subdomains_id.c
+@@ -633,6 +633,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+             ret = ENOMEM;
+             goto fail;
+         }
++        clist[1]->ignore_mark_offline = true;
+         break;
+     default:
+         clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2);
+@@ -641,6 +642,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+             goto fail;
+         }
+         clist[0] = ad_id_ctx->ldap_ctx;
++        clist[0]->ignore_mark_offline = true;
+         clist[1] = NULL;
+     }
+ 
+@@ -1036,7 +1038,11 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
+ 
+     ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL);
+     talloc_zfree(subreq);
+-    if (ret != EOK) {
++    if (ret == ERR_SUBDOM_INACTIVE) {
++        be_mark_dom_offline(state->obj_dom, be_req_get_be_ctx(state->be_req));
++        tevent_req_error(req, ret);
++        return;
++    } else if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "AD lookup failed: %d\n", ret);
+         tevent_req_error(req, ret);
+         return;
+-- 
+2.4.3
+
diff --git a/SOURCES/0081-proxy-Do-not-try-to-store-same-alias-twice.patch b/SOURCES/0081-proxy-Do-not-try-to-store-same-alias-twice.patch
deleted file mode 100644
index bd7330c..0000000
--- a/SOURCES/0081-proxy-Do-not-try-to-store-same-alias-twice.patch
+++ /dev/null
@@ -1,161 +0,0 @@
-From aeb6e3d066122621e1ec043f0c7848363539ca5f Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Fri, 31 Oct 2014 16:39:25 +0100
-Subject: [PATCH 81/82] proxy: Do not try to store same alias twice
-
-LDB does not store attributes if they have the
-same name and value and errors out instead.
-
-Fixes:
-https://fedorahosted.org/sssd/ticket/2461
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/proxy/proxy_id.c | 77 +++++++++++++++++++++++++++---------------
- 1 file changed, 49 insertions(+), 28 deletions(-)
-
-diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c
-index d867ec45f633fb5869f5658e0ac1b54bcbab8369..96d9910f7c81d8e1d4245adc69ebc8af6b5b7112 100644
---- a/src/providers/proxy/proxy_id.c
-+++ b/src/providers/proxy/proxy_id.c
-@@ -222,6 +222,7 @@ static int save_user(struct sss_domain_info *domain,
-     struct sysdb_attrs *attrs = NULL;
-     errno_t ret;
-     const char *cased_alias;
-+    const char *lc_pw_name = NULL;
- 
-     if (pwd->pw_shell && pwd->pw_shell[0] != '\0') {
-         shell = pwd->pw_shell;
-@@ -239,31 +240,42 @@ static int save_user(struct sss_domain_info *domain,
-         attrs = sysdb_new_attrs(NULL);
-         if (!attrs) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n");
--            return ENOMEM;
-+            ret = ENOMEM;
-+            goto done;
-         }
-     }
- 
-     if (lowercase) {
--        ret = sysdb_attrs_add_lc_name_alias(attrs, pwd->pw_name);
-+        lc_pw_name = sss_tc_utf8_str_tolower(attrs, pwd->pw_name);
-+        if (lc_pw_name == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+
-+        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lc_pw_name);
-         if (ret) {
-             DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
--            talloc_zfree(attrs);
--            return ret;
-+            ret = ENOMEM;
-+            goto done;
-         }
-+
-     }
- 
-     if (alias) {
-         cased_alias = sss_get_cased_name(attrs, alias, !lowercase);
-         if (!cased_alias) {
--            talloc_zfree(attrs);
--            return ENOMEM;
-+            ret = ENOMEM;
-+            goto done;
-         }
- 
--        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
--        if (ret) {
--            DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
--            talloc_zfree(attrs);
--            return ret;
-+        /* Add the alias only if it differs from lowercased pw_name */
-+        if (lc_pw_name == NULL || strcmp(cased_alias, lc_pw_name) != 0) {
-+            ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
-+            if (ret) {
-+                DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
-+                goto done;
-+            }
-         }
-     }
- 
-@@ -280,13 +292,14 @@ static int save_user(struct sss_domain_info *domain,
-                            NULL,
-                            cache_timeout,
-                            0);
--    talloc_zfree(attrs);
-     if (ret) {
-         DEBUG(SSSDBG_OP_FAILURE, "Could not add user to cache\n");
--        return ret;
-+        goto done;
-     }
- 
--    return EOK;
-+done:
-+    talloc_zfree(attrs);
-+    return ret;
- }
- 
- /* =Getpwuid-wrapper======================================================*/
-@@ -527,6 +540,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
-     errno_t ret, sret;
-     struct sysdb_attrs *attrs = NULL;
-     const char *cased_alias;
-+    const char *lc_gr_name = NULL;
-     TALLOC_CTX *tmp_ctx;
-     time_t now = time(NULL);
-     bool in_transaction = false;
-@@ -578,27 +592,34 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom,
-                 goto done;
-             }
-         }
-+    }
- 
--        if (dom->case_sensitive == false) {
--            ret = sysdb_attrs_add_lc_name_alias(attrs, grp->gr_name);
--            if (ret) {
--                DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
--                ret = ENOMEM;
--                goto done;
--            }
-+    if (dom->case_sensitive == false) {
-+        lc_gr_name = sss_tc_utf8_str_tolower(attrs, grp->gr_name);
-+        if (lc_gr_name == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
-+            ret = ENOMEM;
-+            goto done;
-         }
- 
--        if (alias) {
--            cased_alias = sss_get_cased_name(attrs, alias, dom->case_sensitive);
--            if (!cased_alias) {
--                talloc_zfree(attrs);
--                return ENOMEM;
--            }
-+        ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lc_gr_name);
-+        if (ret != EOK) {
-+            goto done;
-+        }
-+    }
-+
-+    if (alias) {
-+        cased_alias = sss_get_cased_name(attrs, alias, dom->case_sensitive);
-+        if (!cased_alias) {
-+            ret = ENOMEM;
-+            DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
-+            goto done;
-+        }
- 
-+        if (lc_gr_name == NULL || strcmp(cased_alias, lc_gr_name)) {
-             ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
-             if (ret) {
-                 DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n");
--                ret = ENOMEM;
-                 goto done;
-             }
-         }
--- 
-1.9.3
-
diff --git a/SOURCES/0082-PROXY-Preserve-service-name-in-proxy-provider.patch b/SOURCES/0082-PROXY-Preserve-service-name-in-proxy-provider.patch
deleted file mode 100644
index cb209dc..0000000
--- a/SOURCES/0082-PROXY-Preserve-service-name-in-proxy-provider.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 6505a4a36592efe94bfbdbfb07ca4d198a699a8b Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Thu, 6 Nov 2014 19:25:59 +0100
-Subject: [PATCH 82/82] PROXY: Preserve service name in proxy provider
-
-Fixes:
-https://fedorahosted.org/sssd/ticket/2461
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/proxy/proxy_services.c | 22 +++++++++++++++++++++-
- 1 file changed, 21 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/proxy/proxy_services.c b/src/providers/proxy/proxy_services.c
-index 16e90b009cba86ea17d8d29a4fbeb19efe6947fc..2aa44dbf7f061b99a551b199d0265393e5399a06 100644
---- a/src/providers/proxy/proxy_services.c
-+++ b/src/providers/proxy/proxy_services.c
-@@ -38,12 +38,14 @@ proxy_save_service(struct sss_domain_info *domain,
-     const char **protocols;
-     const char **cased_aliases;
-     TALLOC_CTX *tmp_ctx;
-+    char *lc_alias = NULL;
-     time_t now = time(NULL);
- 
-     tmp_ctx = talloc_new(NULL);
-     if (!tmp_ctx) return ENOMEM;
- 
--    cased_name = sss_get_cased_name(tmp_ctx, svc->s_name, !lowercase);
-+    cased_name = sss_get_cased_name(tmp_ctx, svc->s_name,
-+                                    domain->case_preserve);
-     if (!cased_name) {
-         ret = ENOMEM;
-         goto done;
-@@ -71,6 +73,24 @@ proxy_save_service(struct sss_domain_info *domain,
-         goto done;
-     }
- 
-+    if (domain->case_preserve) {
-+        /* Add lowercased alias to allow case-insensitive lookup */
-+        lc_alias = sss_tc_utf8_str_tolower(tmp_ctx, svc->s_name);
-+        if (lc_alias == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+
-+        ret = add_string_to_list(tmp_ctx, lc_alias,
-+                                 discard_const_p(char **, &cased_aliases));
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "Failed to add lowercased name alias.\n");
-+            goto done;
-+        }
-+    }
-+
-     ret = sysdb_store_service(domain,
-                               cased_name,
-                               ntohs(svc->s_port),
--- 
-1.9.3
-
diff --git a/SOURCES/0082-sss_override-remove-d-from-manpage.patch b/SOURCES/0082-sss_override-remove-d-from-manpage.patch
new file mode 100644
index 0000000..0d6456c
--- /dev/null
+++ b/SOURCES/0082-sss_override-remove-d-from-manpage.patch
@@ -0,0 +1,29 @@
+From 76eb4e29154a9cea4b9189db0b6a0c4ee19e5231 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Fri, 18 Sep 2015 15:55:13 +0200
+Subject: [PATCH 82/87] sss_override: remove -d from manpage
+
+Short version of --debug is not acepted.
+
+Reviewed-by: Pavel Reichl <preichl@redhat.com>
+(cherry picked from commit 8ca1a503cf82fe2c9ed6af9d5903a158496be122)
+---
+ src/man/sss_override.8.xml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml
+index c2ec5dd41703c7272acf7c9d2c30f20351099791..6381d7731761d3aa9e976475bae40941eb2264eb 100644
+--- a/src/man/sss_override.8.xml
++++ b/src/man/sss_override.8.xml
+@@ -198,7 +198,7 @@
+         <variablelist remap='IP'>
+             <varlistentry>
+                 <term>
+-                    <option>-d</option>,<option>--debug</option>
++                    <option>--debug</option>
+                     <replaceable>LEVEL</replaceable>
+                 </term>
+                 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/debug_levels.xml" />
+-- 
+2.4.3
+
diff --git a/SOURCES/0083-BUILD-Install-krb5_child-as-suid-if-running-under-no.patch b/SOURCES/0083-BUILD-Install-krb5_child-as-suid-if-running-under-no.patch
deleted file mode 100644
index 26f66d8..0000000
--- a/SOURCES/0083-BUILD-Install-krb5_child-as-suid-if-running-under-no.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From f28c0df2ba8d3ba4632e3fa5cb395635470d3639 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 24 Oct 2014 22:44:17 +0200
-Subject: [PATCH 83/92] BUILD: Install krb5_child as suid if running under
- non-privileged user
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-If sssd_be is running unprivileged, then krb5_child must be setuid to be
-able to access the keytab and become arbitrary user.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am          | 2 ++
- contrib/sssd.spec.in | 2 +-
- 2 files changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index b85341f5845c3cffab8a2c95b1be1d32517316e8..5f265dcefd16ce4efdde4d62f3cd5d02dbce255f 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2872,6 +2872,8 @@ endif
- if SSSD_USER
- 	chgrp $(SSSD_USER) $(sssdlibexecdir)/ldap_child
- 	chmod 4750 $(sssdlibexecdir)/ldap_child
-+	chgrp $(SSSD_USER) $(sssdlibexecdir)/krb5_child
-+	chmod 4750 $(sssdlibexecdir)/krb5_child
- if BUILD_SEMANAGE
- 	chgrp $(SSSD_USER) $(sssdlibexecdir)/selinux_child
- 	chmod 4750 $(sssdlibexecdir)/selinux_child
-diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
-index 5bfb16707c22dc65376581c88b8eb898949e726f..4734d124817cac860b7f6d9633b043df5aa591e8 100644
---- a/contrib/sssd.spec.in
-+++ b/contrib/sssd.spec.in
-@@ -646,7 +646,7 @@ rm -rf $RPM_BUILD_ROOT
- %doc COPYING
- %{_libdir}/%{name}/libsss_krb5_common.so
- %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/ldap_child
--%{_libexecdir}/%{servicename}/krb5_child
-+%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/krb5_child
- 
- %files krb5 -f sssd_krb5.lang
- %defattr(-,root,root,-)
--- 
-1.9.3
-
diff --git a/SOURCES/0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch b/SOURCES/0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch
new file mode 100644
index 0000000..ecc6841
--- /dev/null
+++ b/SOURCES/0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch
@@ -0,0 +1,90 @@
+From 075a5e689eb6983f412724b0324cec59726ae6e9 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Tue, 21 Jul 2015 21:00:27 +0200
+Subject: [PATCH 83/86] LDAP: imposing sizelimit=1 for single-entry searches
+ breaks overlapping domains
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://fedorahosted.org/sssd/ticket/2723
+
+In case there are overlapping sdap domains, a search for a single user
+might match and return multiple entries. For instance, with AD domains
+represented by search bases:
+    DC=win,DC=trust,DC=test
+    DC=child,DC=win,DC=trust,DC=test
+
+A search for user from win.trust.test would be based at:
+    DC=win,DC=trust,DC=test
+but would match both search bases and return both users.
+
+Instead of performing complex filtering, just save both users. The
+responder would select the entry that matches the user's search.
+
+Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
+(cherry picked from commit 67625b1b4f856510bf4e169649b3fb30c2c14152)
+---
+ src/providers/ldap/sdap_async_groups.c | 10 ----------
+ src/providers/ldap/sdap_async_users.c  |  3 ---
+ 2 files changed, 13 deletions(-)
+
+diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
+index 525c6fa09553d8c0232ce2317751184f83632d86..57a53af3f4eb46e6f31af9ee7c4d4625239d2a54 100644
+--- a/src/providers/ldap/sdap_async_groups.c
++++ b/src/providers/ldap/sdap_async_groups.c
+@@ -1874,8 +1874,6 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+ 
+     switch (state->lookup_type) {
+     case SDAP_LOOKUP_SINGLE:
+-        sizelimit = 1;
+-        need_paging = false;
+         break;
+     /* Only requests that can return multiple entries should require
+      * the paging control
+@@ -1885,7 +1883,6 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req)
+         need_paging = true;
+         break;
+     case SDAP_LOOKUP_ENUMERATE:
+-        sizelimit = 0;  /* unlimited */
+         need_paging = true;
+         break;
+     }
+@@ -1934,13 +1931,6 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
+     DEBUG(SSSDBG_TRACE_FUNC,
+           "Search for groups, returned %zu results.\n", count);
+ 
+-    if (state->lookup_type == SDAP_LOOKUP_SINGLE && count > 1) {
+-        DEBUG(SSSDBG_MINOR_FAILURE,
+-              "Individual group search returned multiple results\n");
+-        tevent_req_error(req, EINVAL);
+-        return;
+-    }
+-
+     if (state->lookup_type == SDAP_LOOKUP_WILDCARD || \
+             state->lookup_type == SDAP_LOOKUP_ENUMERATE || \
+         count == 0) {
+diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
+index a864a8b2187de7972aa963b355856e97f7c692a9..e38f4cd1610e62aa2cf9f4add3a5f7ad5290e748 100644
+--- a/src/providers/ldap/sdap_async_users.c
++++ b/src/providers/ldap/sdap_async_users.c
+@@ -692,8 +692,6 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+ 
+     switch (state->lookup_type) {
+     case SDAP_LOOKUP_SINGLE:
+-        sizelimit = 1;
+-        need_paging = false;
+         break;
+     /* Only requests that can return multiple entries should require
+      * the paging control
+@@ -703,7 +701,6 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req)
+         need_paging = true;
+         break;
+     case SDAP_LOOKUP_ENUMERATE:
+-        sizelimit = 0;  /* unlimited */
+         need_paging = true;
+         break;
+     }
+-- 
+2.4.3
+
diff --git a/SOURCES/0084-DYNDNS-Add-a-new-option-dyndns_server.patch b/SOURCES/0084-DYNDNS-Add-a-new-option-dyndns_server.patch
new file mode 100644
index 0000000..8fa1811
--- /dev/null
+++ b/SOURCES/0084-DYNDNS-Add-a-new-option-dyndns_server.patch
@@ -0,0 +1,208 @@
+From b280fc0d8287e9bee25516eddc1a6670691c24a1 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Sun, 6 Jul 2014 22:53:27 +0200
+Subject: [PATCH 84/90] DYNDNS: Add a new option dyndns_server
+
+Some environments use a different DNS server than identity server. For
+these environments, it would be useful to be able to override the DNS
+server used to perform DNS updates.
+
+This patch adds a new option dyndns_server that, if set, would be used
+to hardcode a DNS server address into the nsupdate message.
+
+Reviewed-by: Pavel Reichl <preichl@redhat.com>
+(cherry picked from commit 8145ab51b05aa86b2f1a21b49383f55e50b0a2e3)
+---
+ src/config/SSSDConfig/__init__.py.in |  1 +
+ src/config/SSSDConfigTest.py         |  2 ++
+ src/config/etc/sssd.api.conf         |  1 +
+ src/man/sssd-ad.5.xml                | 20 ++++++++++++++++++++
+ src/man/sssd-ipa.5.xml               | 19 +++++++++++++++++++
+ src/providers/ad/ad_opts.h           |  1 +
+ src/providers/dp_dyndns.c            |  1 +
+ src/providers/dp_dyndns.h            |  1 +
+ src/providers/ipa/ipa_opts.h         |  1 +
+ src/providers/ldap/sdap_dyndns.c     |  7 +++++++
+ 10 files changed, 54 insertions(+)
+
+diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
+index fed2682f121103cefa27e689b29ce29b7d28f968..a7cd1dd243a53e7038dc69628475c76ccdd93260 100644
+--- a/src/config/SSSDConfig/__init__.py.in
++++ b/src/config/SSSDConfig/__init__.py.in
+@@ -148,6 +148,7 @@ option_strings = {
+     'dyndns_update_ptr' : _("Whether the provider should explicitly update the PTR record as well"),
+     'dyndns_force_tcp' : _("Whether the nsupdate utility should default to using TCP"),
+     'dyndns_auth' : _("What kind of authentication should be used to perform the DNS update"),
++    'dyndns_server' : _("Override the DNS server used to perform the DNS update"),
+     'subdomain_enumerate' : _('Control enumeration of trusted domains'),
+     'subdomain_refresh_interval' : _('How often should subdomains list be refreshed'),
+     'subdomain_inherit' : _('List of options that should be inherited into a subdomain'),
+diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
+index 1d6107ceac1bde7acbfd2682cc144a4ef0881311..166ecd0ff0f5cfb38eefb1711e4ac5dd9f805d43 100755
+--- a/src/config/SSSDConfigTest.py
++++ b/src/config/SSSDConfigTest.py
+@@ -527,6 +527,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
+             'dyndns_update_ptr',
+             'dyndns_force_tcp',
+             'dyndns_auth',
++            'dyndns_server',
+             'subdomain_enumerate',
+             'override_gid',
+             'case_sensitive',
+@@ -891,6 +892,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
+             'dyndns_update_ptr',
+             'dyndns_force_tcp',
+             'dyndns_auth',
++            'dyndns_server',
+             'subdomain_enumerate',
+             'override_gid',
+             'case_sensitive',
+diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
+index 2e5b02e3e30c13f805e172eab481f7501f57bb05..f28054860205831b0452e409c109e3c62aa8d28a 100644
+--- a/src/config/etc/sssd.api.conf
++++ b/src/config/etc/sssd.api.conf
+@@ -155,6 +155,7 @@ dyndns_refresh_interval = int, None, false
+ dyndns_update_ptr = bool, None, false
+ dyndns_force_tcp = bool, None, false
+ dyndns_auth = str, None, false
++dyndns_server = str, None, false
+ 
+ # Special providers
+ [provider/permit]
+diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
+index 3cbc10520098372d984d00425d03832d002d6672..7ccd29794a89fa6b69b744a47da04f908efc7ef9 100644
+--- a/src/man/sssd-ad.5.xml
++++ b/src/man/sssd-ad.5.xml
+@@ -812,6 +812,26 @@ ad_gpo_map_deny = +my_pam_service
+                     </listitem>
+                 </varlistentry>
+ 
++                <varlistentry>
++                    <term>dyndns_server (string)</term>
++                    <listitem>
++                        <para>
++                            The DNS server to use when performing a DNS
++                            update. In most setups, it's recommended to leave
++                            this option unset.
++                        </para>
++                        <para>
++                            Setting this option makes sense for environments
++                            where the DNS server is different from the identity
++                            server.
++                        </para>
++                        <para>
++                            Default: None (let nsupdate choose the server)
++                        </para>
++                    </listitem>
++                </varlistentry>
++
++
+                 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/override_homedir.xml" />
+                 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/homedir_substring.xml" />
+ 
+diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
+index 2e985991fde10827aff0e7c8e67f29a009683450..871c41607b97bd24fe5feaa282258def0fd0cc8b 100644
+--- a/src/man/sssd-ipa.5.xml
++++ b/src/man/sssd-ipa.5.xml
+@@ -263,6 +263,25 @@
+                 </varlistentry>
+ 
+                 <varlistentry>
++                    <term>dyndns_server (string)</term>
++                    <listitem>
++                        <para>
++                            The DNS server to use when performing a DNS
++                            update. In most setups, it's recommended to leave
++                            this option unset.
++                        </para>
++                        <para>
++                            Setting this option makes sense for environments
++                            where the DNS server is different from the identity
++                            server.
++                        </para>
++                        <para>
++                            Default: None (let nsupdate choose the server)
++                        </para>
++                    </listitem>
++                </varlistentry>
++
++                <varlistentry>
+                     <term>ipa_hbac_search_base (string)</term>
+                     <listitem>
+                         <para>
+diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
+index d685edcb44c771b0afc7a232a82c21fc9d1c89f9..00586a7ada63ad4c89630e9589d3ff75d1726703 100644
+--- a/src/providers/ad/ad_opts.h
++++ b/src/providers/ad/ad_opts.h
+@@ -275,6 +275,7 @@ struct dp_option ad_dyndns_opts[] = {
+     { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
+     { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING },
++    { "dyndns_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     DP_OPTION_TERMINATOR
+ };
+ 
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index c254d78936f412626db0533f559350de57017618..9a726bd431854342993212ce0a9759b86069cd5e 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -1180,6 +1180,7 @@ static struct dp_option default_dyndns_opts[] = {
+     { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE },
+     { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING },
++    { "dyndns_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+ 
+     DP_OPTION_TERMINATOR
+ };
+diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h
+index a8a20ec6f8a1a63cd8c85aaec3f54f9fddb42049..3cc8d122646590365a3fb6dafa6a0f699b620ad9 100644
+--- a/src/providers/dp_dyndns.h
++++ b/src/providers/dp_dyndns.h
+@@ -55,6 +55,7 @@ enum dp_dyndns_opts {
+     DP_OPT_DYNDNS_UPDATE_PTR,
+     DP_OPT_DYNDNS_FORCE_TCP,
+     DP_OPT_DYNDNS_AUTH,
++    DP_OPT_DYNDNS_SERVER,
+ 
+     DP_OPT_DYNDNS /* attrs counter */
+ };
+diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
+index f6c40dddbb58cd8af1079a351137422083e26cfe..78949e3ddec95f7f4303eab905bbbf6ec14ed6ae 100644
+--- a/src/providers/ipa/ipa_opts.h
++++ b/src/providers/ipa/ipa_opts.h
+@@ -62,6 +62,7 @@ struct dp_option ipa_dyndns_opts[] = {
+     { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+     { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING },
++    { "dyndns_server", DP_OPT_STRING, NULL_STRING, NULL_STRING },
+     DP_OPTION_TERMINATOR
+ };
+ 
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index a463a2fce08f42b325010cd37c501ef23aee173f..01f4f17226f1b7dd417699403b425c571b780c3a 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -92,6 +92,7 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+     struct tevent_req *req;
+     struct tevent_req *subreq;
+     struct sdap_dyndns_update_state *state;
++    const char *conf_servername;
+ 
+     req = tevent_req_create(mem_ctx, &state, struct sdap_dyndns_update_state);
+     if (req == NULL) {
+@@ -111,6 +112,12 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+     state->auth_type = auth_type;
+     state->pass_num = 0;
+ 
++    conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER);
++    if (conf_servername != NULL) {
++        state->servername = conf_servername;
++        state->use_server_with_nsupdate = true;
++    }
++
+     if (ifname) {
+        /* Unless one family is restricted, just replace all
+         * address families during the update
+-- 
+2.4.3
+
diff --git a/SOURCES/0084-KRB5-Drop-privileges-in-the-child-not-the-back-end.patch b/SOURCES/0084-KRB5-Drop-privileges-in-the-child-not-the-back-end.patch
deleted file mode 100644
index 9168a2d..0000000
--- a/SOURCES/0084-KRB5-Drop-privileges-in-the-child-not-the-back-end.patch
+++ /dev/null
@@ -1,142 +0,0 @@
-From 6422e4a1fea8176fab2f92711cd593904d549cfe Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 13 Oct 2014 21:13:38 +0200
-Subject: [PATCH 84/92] KRB5: Drop privileges in the child, not the back end
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In future patches, sssd_be will be running as a non-privileged user, who
-will execute the setuid krb5_child. In this case, the child will start
-as root and drop the privileges as soon as possible.
-
-However, we need to also remove the privilege drop in sssd_be, because
-if we dropped to the user who is authenticating, we wouldn't be even
-allowed to execute krb5_child. The krb5_child permissions should be
-4750, owned by root.sssd, to make sure only root and sssd can execute
-the child and if executed by sssd, the child will run as root.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/krb5/krb5_child.c         | 71 ++++++++++++++++++++++++++-------
- src/providers/krb5/krb5_child_handler.c |  8 ----
- 2 files changed, 57 insertions(+), 22 deletions(-)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 3234a4e6c740db5e05f7db8eb7f4ea0cc126e7ce..b0bf76fb3b8a77831b114c47acff8cd0d3fd780d 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -1840,11 +1840,60 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
-     return EOK;
- }
- 
--static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-+enum k5c_fast_opt {
-+    K5C_FAST_NEVER,
-+    K5C_FAST_TRY,
-+    K5C_FAST_DEMAND,
-+};
-+
-+static errno_t check_use_fast(enum k5c_fast_opt *_fast_val)
- {
--    krb5_error_code kerr;
-     char *use_fast_str;
-+    enum k5c_fast_opt fast_val;
-+
-+    use_fast_str = getenv(SSSD_KRB5_USE_FAST);
-+    if (use_fast_str == NULL || strcasecmp(use_fast_str, "never") == 0) {
-+        DEBUG(SSSDBG_CONF_SETTINGS, "Not using FAST.\n");
-+        fast_val = K5C_FAST_NEVER;
-+    } else if (strcasecmp(use_fast_str, "try") == 0) {
-+        fast_val = K5C_FAST_TRY;
-+    } else if (strcasecmp(use_fast_str, "demand") == 0) {
-+        fast_val = K5C_FAST_DEMAND;
-+    } else {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+                "Unsupported value [%s] for krb5_use_fast.\n",
-+                use_fast_str);
-+        return EINVAL;
-+    }
-+
-+    *_fast_val = fast_val;
-+    return EOK;
-+}
-+
-+static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-+{
-+    krb5_error_code kerr;
-     int parse_flags;
-+    enum k5c_fast_opt fast_val;
-+
-+    kerr = check_use_fast(&fast_val);
-+    if (kerr != EOK) {
-+        return kerr;
-+    }
-+
-+    if (offline || (fast_val == K5C_FAST_NEVER && kr->validate == false)) {
-+        /* If krb5_child was started as setuid, but we don't need to
-+         * perform either validation or FAST, just drop privileges to
-+         * the user who is logging in. The same applies to the offline case
-+         */
-+        kerr = become_user(kr->uid, kr->gid);
-+        if (kerr != 0) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
-+            return kerr;
-+        }
-+    }
-+    DEBUG(SSSDBG_TRACE_INTERNAL,
-+          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
- 
-     kr->realm = getenv(SSSD_KRB5_REALM);
-     if (kr->realm == NULL) {
-@@ -1931,18 +1980,12 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-     if (!offline) {
-         set_canonicalize_option(kr->options);
- 
--        use_fast_str = getenv(SSSD_KRB5_USE_FAST);
--        if (use_fast_str == NULL || strcasecmp(use_fast_str, "never") == 0) {
--            DEBUG(SSSDBG_CONF_SETTINGS, "Not using FAST.\n");
--        } else if (strcasecmp(use_fast_str, "try") == 0) {
--            kerr = k5c_setup_fast(kr, false);
--        } else if (strcasecmp(use_fast_str, "demand") == 0) {
--            kerr = k5c_setup_fast(kr, true);
--        } else {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "Unsupported value [%s] for krb5_use_fast.\n",
--                   use_fast_str);
--            return EINVAL;
-+        if (fast_val != K5C_FAST_NEVER) {
-+            kerr = k5c_setup_fast(kr, fast_val == K5C_FAST_DEMAND);
-+            if (kerr != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "Cannot set up FAST\n");
-+                return kerr;
-+            }
-         }
-     }
- 
-diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
-index 4ba939deb3e0e282b3ca9b2b21226ea7e64e311b..71c7f9c9f662e16b94afda0c8c0ae24666f0ba15 100644
---- a/src/providers/krb5/krb5_child_handler.c
-+++ b/src/providers/krb5/krb5_child_handler.c
-@@ -284,14 +284,6 @@ static errno_t fork_child(struct tevent_req *req)
-     pid = fork();
- 
-     if (pid == 0) { /* child */
--        if (state->kr->run_as_user) {
--            ret = become_user(state->kr->uid, state->kr->gid);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
--                return ret;
--            }
--        }
--
-         err = exec_child(state,
-                          pipefd_to_child, pipefd_from_child,
-                          KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd);
--- 
-1.9.3
-
diff --git a/SOURCES/0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch b/SOURCES/0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch
new file mode 100644
index 0000000..5e9f538
--- /dev/null
+++ b/SOURCES/0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch
@@ -0,0 +1,77 @@
+From 6d1ba78ff110ee424e54025c3d823fb5c504aefa Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Thu, 23 Jul 2015 04:40:03 -0400
+Subject: [PATCH 85/90] DYNDNS: Don't use server cmd in nsupdate by default
+
+nsupdate command `server` should not be used for the first attempt
+to udpate DNS. It should be used only in subsequent attempts after the
+first attempt failed.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2495
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 7c3cc1ee2914bc7b38a992c1af254fc76af5a1ad)
+---
+ src/man/sssd-ad.5.xml            | 6 +++++-
+ src/man/sssd-ipa.5.xml           | 5 +++++
+ src/providers/ldap/sdap_dyndns.c | 2 +-
+ 3 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
+index 7ccd29794a89fa6b69b744a47da04f908efc7ef9..127e96582d71e8216db88d37a16d37d01748131d 100644
+--- a/src/man/sssd-ad.5.xml
++++ b/src/man/sssd-ad.5.xml
+@@ -826,12 +826,16 @@ ad_gpo_map_deny = +my_pam_service
+                             server.
+                         </para>
+                         <para>
++                            Please note that this option will be only used in
++                            fallback attempt when previous attempt using
++                            autodetected settings failed.
++                        </para>
++                        <para>
+                             Default: None (let nsupdate choose the server)
+                         </para>
+                     </listitem>
+                 </varlistentry>
+ 
+-
+                 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/override_homedir.xml" />
+                 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/homedir_substring.xml" />
+ 
+diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
+index 871c41607b97bd24fe5feaa282258def0fd0cc8b..be390d58dd3ce5a6ca6d5212d2c7aa176d3a74c4 100644
+--- a/src/man/sssd-ipa.5.xml
++++ b/src/man/sssd-ipa.5.xml
+@@ -276,6 +276,11 @@
+                             server.
+                         </para>
+                         <para>
++                            Please note that this option will be only used in
++                            fallback attempt when previous attempt using
++                            autodetected settings failed.
++                        </para>
++                        <para>
+                             Default: None (let nsupdate choose the server)
+                         </para>
+                     </listitem>
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index 01f4f17226f1b7dd417699403b425c571b780c3a..0f0e63ee2259d017c3e94afca5f3148f4fc2ce04 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -112,10 +112,10 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+     state->auth_type = auth_type;
+     state->pass_num = 0;
+ 
++    /* fallback servername is overriden by user option */
+     conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER);
+     if (conf_servername != NULL) {
+         state->servername = conf_servername;
+-        state->use_server_with_nsupdate = true;
+     }
+ 
+     if (ifname) {
+-- 
+2.4.3
+
diff --git a/SOURCES/0085-KRB5-Move-ccache-related-functions-to-krb5_ccache.c.patch b/SOURCES/0085-KRB5-Move-ccache-related-functions-to-krb5_ccache.c.patch
deleted file mode 100644
index 73c0db0..0000000
--- a/SOURCES/0085-KRB5-Move-ccache-related-functions-to-krb5_ccache.c.patch
+++ /dev/null
@@ -1,1794 +0,0 @@
-From b53c6d5adcd51869fe2d84b6149b4894fa18a436 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sat, 18 Oct 2014 20:52:43 +0200
-Subject: [PATCH 85/92] KRB5: Move ccache-related functions to krb5_ccache.c
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Add a new module krb5_ccache.c that contains all ccache-related
-operations. The only user of this module shall be krb5_child.c as the
-other modules will run unprivileged and accessing the ccache requires
-either privileges of root or the ccache owner.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am                                        |   4 +
- src/providers/krb5/krb5_auth.c                     |  16 +-
- src/providers/krb5/krb5_auth.h                     |   1 +
- src/providers/krb5/{krb5_utils.c => krb5_ccache.c} | 720 +++++----------------
- src/providers/krb5/{krb5_utils.h => krb5_ccache.h} |  49 +-
- src/providers/krb5/krb5_child.c                    |   1 +
- src/providers/krb5/krb5_common.h                   |   7 -
- src/providers/krb5/krb5_renew_tgt.c                |   1 +
- src/providers/krb5/krb5_utils.c                    | 674 +------------------
- src/providers/krb5/krb5_utils.h                    |  15 -
- src/tests/krb5_child-test.c                        |   1 +
- src/tests/krb5_utils-tests.c                       |   1 +
- 12 files changed, 198 insertions(+), 1292 deletions(-)
- copy src/providers/krb5/{krb5_utils.c => krb5_ccache.c} (57%)
- copy src/providers/krb5/{krb5_utils.h => krb5_ccache.h} (53%)
-
-diff --git a/Makefile.am b/Makefile.am
-index 5f265dcefd16ce4efdde4d62f3cd5d02dbce255f..4a69ecb0cfe48e20bde958c9351c2a5ece5ffffa 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -568,6 +568,7 @@ dist_noinst_HEADERS = \
-     src/providers/krb5/krb5_utils.h \
-     src/providers/krb5/krb5_init_shared.h \
-     src/providers/krb5/krb5_opts.h \
-+    src/providers/krb5/krb5_ccache.h \
-     src/providers/ldap/ldap_common.h \
-     src/providers/ldap/sdap.h \
-     src/providers/ldap/sdap_access.h \
-@@ -1322,6 +1323,7 @@ strtonum_tests_LDADD = \
- krb5_utils_tests_SOURCES = \
-     src/tests/krb5_utils-tests.c \
-     src/providers/krb5/krb5_utils.c \
-+    src/providers/krb5/krb5_ccache.c \
-     src/providers/krb5/krb5_common.c \
-     src/util/sss_krb5.c \
-     src/providers/data_provider_fo.c \
-@@ -1603,6 +1605,7 @@ stress_tests_LDADD = \
- krb5_child_test_SOURCES = \
-     src/tests/krb5_child-test.c \
-     src/providers/krb5/krb5_utils.c \
-+    src/providers/krb5/krb5_ccache.c \
-     src/providers/krb5/krb5_child_handler.c \
-     src/providers/krb5/krb5_common.c \
-     src/util/sss_krb5.c \
-@@ -2306,6 +2309,7 @@ libsss_krb5_common_la_SOURCES = \
-     src/providers/krb5/krb5_access.c \
-     src/providers/krb5/krb5_child_handler.c \
-     src/providers/krb5/krb5_init_shared.c \
-+    src/providers/krb5/krb5_ccache.c \
-     src/util/sss_krb5.c \
-     src/util/become_user.c \
-     $(NULL)
-diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
-index c96b7aee99da8c3d43a67a04bb1f67ee048d4705..bd8b51f47462f1eaef8da61b42caedda3475a4e7 100644
---- a/src/providers/krb5/krb5_auth.c
-+++ b/src/providers/krb5/krb5_auth.c
-@@ -39,21 +39,7 @@
- #include "util/child_common.h"
- #include "providers/krb5/krb5_auth.h"
- #include "providers/krb5/krb5_utils.h"
--
--static errno_t safe_remove_old_ccache_file(const char *old_ccache,
--                                           const char *new_ccache,
--                                           uid_t uid, gid_t gid)
--{
--    if ((old_ccache == new_ccache)
--        || (old_ccache && new_ccache
--            && (strcmp(old_ccache, new_ccache) == 0))) {
--        DEBUG(SSSDBG_TRACE_FUNC, "New and old ccache file are the same, "
--                                  "none will be deleted.\n");
--        return EOK;
--    }
--
--    return sss_krb5_cc_destroy(old_ccache, uid, gid);
--}
-+#include "providers/krb5/krb5_ccache.h"
- 
- static errno_t
- check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
-diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
-index 022dc9b7645f18d01a8a334371e178aa470d92a1..00cb658c418ade2e6a1d9b5362a40f97e0dc6c6b 100644
---- a/src/providers/krb5/krb5_auth.h
-+++ b/src/providers/krb5/krb5_auth.h
-@@ -32,6 +32,7 @@
- #include "providers/dp_backend.h"
- #include "util/child_common.h"
- #include "providers/krb5/krb5_common.h"
-+#include "providers/krb5/krb5_ccache.h"
- 
- #define CCACHE_ENV_NAME "KRB5CCNAME"
- 
-diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_ccache.c
-similarity index 57%
-copy from src/providers/krb5/krb5_utils.c
-copy to src/providers/krb5/krb5_ccache.c
-index 0d2e281198390043068e21b412b57de04df6a12b..5586963338616519f36e5d75e796a597d3ac2f22 100644
---- a/src/providers/krb5/krb5_utils.c
-+++ b/src/providers/krb5/krb5_ccache.c
-@@ -1,12 +1,13 @@
- /*
-     SSSD
- 
--    Kerberos 5 Backend Module -- Utilities
-+    Kerberos 5 Backend Module -- ccache related utilities
- 
-     Authors:
-         Sumit Bose <sbose@redhat.com>
-+        Jakub Hrozek <jhrozek@redhat.com>
- 
--    Copyright (C) 2009 Red Hat
-+    Copyright (C) 2014 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
-@@ -21,427 +22,37 @@
-     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 <stdlib.h>
--#include <libgen.h>
- 
--#include "providers/krb5/krb5_utils.h"
--#include "providers/krb5/krb5_auth.h"
--#include "src/util/find_uid.h"
-+#ifdef HAVE_KRB5_KRB5_H
-+#include <krb5/krb5.h>
-+#else
-+#include <krb5.h>
-+#endif
-+
-+#include "providers/krb5/krb5_ccache.h"
-+#include "util/sss_krb5.h"
- #include "util/util.h"
- 
--errno_t find_or_guess_upn(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
--                          struct krb5_ctx *krb5_ctx,
--                          struct sss_domain_info *dom, const char *user,
--                          const char *user_dom, char **_upn)
-+static errno_t
-+check_ccache_re(const char *filename, pcre *illegal_re)
- {
--    const char *upn = NULL;
--    int ret;
-+    errno_t ret;
- 
--    if (krb5_ctx == NULL || dom == NULL || user == NULL || _upn == NULL) {
--        return EINVAL;
--    }
--
--    if (msg != NULL) {
--        upn = ldb_msg_find_attr_as_string(msg, SYSDB_CANONICAL_UPN, NULL);
--        if (upn != NULL) {
--            ret = EOK;
--            goto done;
--        }
--
--        upn = ldb_msg_find_attr_as_string(msg, SYSDB_UPN, NULL);
--        if (upn != NULL) {
--            ret = EOK;
--            goto done;
--        }
--    }
--
--    ret = krb5_get_simple_upn(mem_ctx, krb5_ctx, dom, user,
--                              user_dom, _upn);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "krb5_get_simple_upn failed.\n");
--        return ret;
--    }
--
--done:
--    if (ret == EOK && upn != NULL) {
--        *_upn = talloc_strdup(mem_ctx, upn);
--        if (*_upn == NULL) {
--            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
--            return ENOMEM;
--        }
--    }
--
--    return ret;
--}
--
--errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
--                                         struct sss_domain_info *domain,
--                                         const char *user,
--                                         const char *upn)
--{
--    TALLOC_CTX *tmp_ctx;
--    int ret;
--    int sret;
--    const char *attrs[] = {SYSDB_UPN, SYSDB_CANONICAL_UPN, NULL};
--    struct sysdb_attrs *new_attrs;
--    struct ldb_result *res;
--    bool in_transaction = false;
--    const char *cached_upn;
--    const char *cached_canonical_upn;
--
--    if (sysdb == NULL || user == NULL || upn == NULL) {
--        return EINVAL;
--    }
--
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
--        return ENOMEM;
--    }
--
--    ret = sysdb_get_user_attr(tmp_ctx, domain, user, attrs, &res);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_user_attr failed.\n");
--        goto done;
--    }
--
--    if (res->count != 1) {
--        DEBUG(SSSDBG_OP_FAILURE, "[%d] user objects for name [%s] found, " \
--                                  "expected 1.\n", res->count, user);
--        ret = EINVAL;
--        goto done;
--    }
--
--    cached_upn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_UPN, NULL);
--
--    if (cached_upn != NULL && strcmp(cached_upn, upn) == 0) {
--        DEBUG(SSSDBG_TRACE_ALL, "Cached UPN and new one match, "
--                                 "nothing to do.\n");
--        ret = EOK;
--        goto done;
--    }
--
--    cached_canonical_upn = ldb_msg_find_attr_as_string(res->msgs[0],
--                                                       SYSDB_CANONICAL_UPN,
--                                                       NULL);
--
--    if (cached_canonical_upn != NULL
--            && strcmp(cached_canonical_upn, upn) == 0) {
--        DEBUG(SSSDBG_TRACE_ALL, "Cached canonical UPN and new one match, "
--                                 "nothing to do.\n");
--        ret = EOK;
--        goto done;
--    }
--
--    DEBUG(SSSDBG_TRACE_LIBS, "Replacing canonical UPN [%s] with [%s] " \
--                              "for user [%s].\n",
--                              cached_canonical_upn == NULL ?
--                                                 "empty" : cached_canonical_upn,
--                              upn, user);
--
--    new_attrs = sysdb_new_attrs(tmp_ctx);
--    if (new_attrs == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
--        ret = ENOMEM;
--        goto done;
--    }
--
--    ret = sysdb_attrs_add_string(new_attrs, SYSDB_CANONICAL_UPN, upn);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
--        goto done;
--    }
--
--    ret = sysdb_transaction_start(sysdb);
--    if (ret != EOK) {
-+    ret = pcre_exec(illegal_re, NULL, filename, strlen(filename),
-+                    0, 0, NULL, 0);
-+    if (ret == 0) {
-         DEBUG(SSSDBG_OP_FAILURE,
--              "Error %d starting transaction (%s)\n", ret, strerror(ret));
--        goto done;
--    }
--    in_transaction = true;
--
--    ret = sysdb_set_entry_attr(sysdb, res->msgs[0]->dn, new_attrs,
--                               cached_canonical_upn == NULL ? SYSDB_MOD_ADD :
--                                                              SYSDB_MOD_REP);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_entry_attr failed [%d][%s].\n",
--                                  ret, strerror(ret));
--        goto done;
--    }
--
--    ret = sysdb_transaction_commit(sysdb);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "Failed to commit transaction!\n");
--        goto done;
--    }
--    in_transaction = false;
--
--    ret = EOK;
--
--done:
--    if (in_transaction) {
--        sret = sysdb_transaction_cancel(sysdb);
--        if (sret != EOK) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
--        }
--    }
--
--    talloc_free(tmp_ctx);
--
--    return ret;
--}
--
--#define S_EXP_UID "{uid}"
--#define L_EXP_UID (sizeof(S_EXP_UID) - 1)
--#define S_EXP_USERID "{USERID}"
--#define L_EXP_USERID (sizeof(S_EXP_USERID) - 1)
--#define S_EXP_EUID "{euid}"
--#define L_EXP_EUID (sizeof(S_EXP_EUID) - 1)
--#define S_EXP_USERNAME "{username}"
--#define L_EXP_USERNAME (sizeof(S_EXP_USERNAME) - 1)
--
--char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
--                             const char *template, bool file_mode,
--                             bool case_sensitive)
--{
--    char *copy;
--    char *p;
--    char *n;
--    char *result = NULL;
--    char *dummy;
--    char *name;
--    char *res = NULL;
--    const char *cache_dir_tmpl;
--    TALLOC_CTX *tmp_ctx = NULL;
--    char action;
--    bool rerun;
--
--    if (template == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Missing template.\n");
--        return NULL;
--    }
--
--    tmp_ctx = talloc_new(NULL);
--    if (!tmp_ctx) return NULL;
--
--    copy = talloc_strdup(tmp_ctx, template);
--    if (copy == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
--        goto done;
--    }
--
--    result = talloc_strdup(tmp_ctx, "");
--    if (result == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
--        goto done;
--    }
--
--    p = copy;
--    while ( (n = strchr(p, '%')) != NULL) {
--        *n = '\0';
--        n++;
--        if ( *n == '\0' ) {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "format error, single %% at the end of the template.\n");
--            goto done;
--        }
--
--        rerun = true;
--        action = *n;
--        while (rerun) {
--            rerun = false;
--            switch (action) {
--            case 'u':
--                if (kr->pd->user == NULL) {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "Cannot expand user name template "
--                              "because user name is empty.\n");
--                    goto done;
--                }
--                name = sss_get_cased_name(tmp_ctx, kr->pd->user,
--                                          case_sensitive);
--                if (!name) {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "sss_get_cased_name failed\n");
--                    goto done;
--                }
--
--                result = talloc_asprintf_append(result, "%s%s", p,
--                                                name);
--                break;
--            case 'U':
--                if (kr->uid <= 0) {
--                    DEBUG(SSSDBG_CRIT_FAILURE, "Cannot expand uid template "
--                              "because uid is invalid.\n");
--                    goto done;
--                }
--                result = talloc_asprintf_append(result, "%s%"SPRIuid, p,
--                                                kr->uid);
--                break;
--            case 'p':
--                if (kr->upn == NULL) {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "Cannot expand user principal name template "
--                              "because upn is empty.\n");
--                    goto done;
--                }
--                result = talloc_asprintf_append(result, "%s%s", p, kr->upn);
--                break;
--            case '%':
--                result = talloc_asprintf_append(result, "%s%%", p);
--                break;
--            case 'r':
--                dummy = dp_opt_get_string(kr->krb5_ctx->opts, KRB5_REALM);
--                if (dummy == NULL) {
--                    DEBUG(SSSDBG_CRIT_FAILURE, "Missing kerberos realm.\n");
--                    goto done;
--                }
--                result = talloc_asprintf_append(result, "%s%s", p, dummy);
--                break;
--            case 'h':
--                if (kr->homedir == NULL) {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "Cannot expand home directory template "
--                              "because the path is not available.\n");
--                    goto done;
--                }
--                result = talloc_asprintf_append(result, "%s%s", p, kr->homedir);
--                break;
--            case 'd':
--                if (file_mode) {
--                    cache_dir_tmpl = dp_opt_get_string(kr->krb5_ctx->opts,
--                                                       KRB5_CCACHEDIR);
--                    if (cache_dir_tmpl == NULL) {
--                        DEBUG(SSSDBG_CRIT_FAILURE,
--                              "Missing credential cache directory.\n");
--                        goto done;
--                    }
--
--                    dummy = expand_ccname_template(tmp_ctx, kr, cache_dir_tmpl,
--                                                   false, case_sensitive);
--                    if (dummy == NULL) {
--                        DEBUG(SSSDBG_CRIT_FAILURE,
--                              "Expanding credential cache directory "
--                                  "template failed.\n");
--                        goto done;
--                    }
--                    result = talloc_asprintf_append(result, "%s%s", p, dummy);
--                    talloc_zfree(dummy);
--                } else {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "'%%d' is not allowed in this template.\n");
--                    goto done;
--                }
--                break;
--            case 'P':
--                if (!file_mode) {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "'%%P' is not allowed in this template.\n");
--                    goto done;
--                }
--                if (kr->pd->cli_pid == 0) {
--                    DEBUG(SSSDBG_CRIT_FAILURE, "Cannot expand PID template "
--                              "because PID is not available.\n");
--                    goto done;
--                }
--                result = talloc_asprintf_append(result, "%s%d", p,
--                                                kr->pd->cli_pid);
--                break;
--
--            /* Additional syntax from krb5.conf default_ccache_name */
--            case '{':
--                if (strncmp(n , S_EXP_UID, L_EXP_UID) == 0) {
--                    action = 'U';
--                    n += L_EXP_UID - 1;
--                    rerun = true;
--                    continue;
--                } else if (strncmp(n , S_EXP_USERID, L_EXP_USERID) == 0) {
--                    action = 'U';
--                    n += L_EXP_USERID - 1;
--                    rerun = true;
--                    continue;
--                } else if (strncmp(n , S_EXP_EUID, L_EXP_EUID) == 0) {
--                    /* SSSD does not distinguish betwen uid and euid,
--                     * so we treat both the same way */
--                    action = 'U';
--                    n += L_EXP_EUID - 1;
--                    rerun = true;
--                    continue;
--                } else if (strncmp(n , S_EXP_USERNAME, L_EXP_USERNAME) == 0) {
--                    action = 'u';
--                    n += L_EXP_USERNAME - 1;
--                    rerun = true;
--                    continue;
--                } else {
--                    /* ignore any expansion variable we do not understand and
--                     * let libkrb5 hndle it or fail */
--                    name = n;
--                    n = strchr(name, '}');
--                    if (!n) {
--                        DEBUG(SSSDBG_CRIT_FAILURE, 
--                              "Invalid substitution sequence in cache "
--                              "template. Missing closing '}' in [%s].\n",
--                              template);
--                        goto done;
--                    }
--                    result = talloc_asprintf_append(result, "%s%%%.*s", p,
--                                                    (int)(n - name + 1), name);
--                }
--                break;
--            default:
--                DEBUG(SSSDBG_CRIT_FAILURE,
--                      "format error, unknown template [%%%c].\n", *n);
--                goto done;
--            }
--        }
--
--        if (result == NULL) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf_append failed.\n");
--            goto done;
--        }
--
--        p = n + 1;
--    }
--
--    result = talloc_asprintf_append(result, "%s", p);
--    if (result == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf_append failed.\n");
--        goto done;
--    }
--
--    res = talloc_move(mem_ctx, &result);
--done:
--    talloc_zfree(tmp_ctx);
--    return res;
--}
--
--static errno_t check_parent_stat(struct stat *parent_stat, uid_t uid)
--{
--    if (parent_stat->st_uid != 0 && parent_stat->st_uid != uid) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Private directory can only be created below a directory "
--              "belonging to root or to [%"SPRIuid"].\n", uid);
-+              "Illegal pattern in ccache directory name [%s].\n", filename);
-         return EINVAL;
-+    } else if (ret == PCRE_ERROR_NOMATCH) {
-+        DEBUG(SSSDBG_TRACE_LIBS,
-+              "Ccache directory name [%s] does not contain "
-+               "illegal patterns.\n", filename);
-+        return EOK;
-     }
- 
--    if (parent_stat->st_uid == uid) {
--        if (!(parent_stat->st_mode & S_IXUSR)) {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "Parent directory does not have the search bit set for "
--                   "the owner.\n");
--            return EINVAL;
--        }
--    } else {
--        if (!(parent_stat->st_mode & S_IXOTH)) {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "Parent directory does not have the search bit set for "
--                   "others.\n");
--            return EINVAL;
--        }
--    }
--
--    return EOK;
-+    DEBUG(SSSDBG_CRIT_FAILURE, "pcre_exec failed [%d].\n", ret);
-+    return EFAULT;
- }
- 
- struct string_list {
-@@ -523,31 +134,37 @@ done:
-     return ret;
- }
- 
--static errno_t
--check_ccache_re(const char *filename, pcre *illegal_re)
-+static errno_t check_parent_stat(struct stat *parent_stat, uid_t uid)
- {
--    errno_t ret;
--
--    ret = pcre_exec(illegal_re, NULL, filename, strlen(filename),
--                    0, 0, NULL, 0);
--    if (ret == 0) {
--        DEBUG(SSSDBG_OP_FAILURE,
--              "Illegal pattern in ccache directory name [%s].\n", filename);
-+    if (parent_stat->st_uid != 0 && parent_stat->st_uid != uid) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Private directory can only be created below a directory "
-+              "belonging to root or to [%"SPRIuid"].\n", uid);
-         return EINVAL;
--    } else if (ret == PCRE_ERROR_NOMATCH) {
--        DEBUG(SSSDBG_TRACE_LIBS,
--              "Ccache directory name [%s] does not contain "
--               "illegal patterns.\n", filename);
--        return EOK;
-     }
- 
--    DEBUG(SSSDBG_CRIT_FAILURE, "pcre_exec failed [%d].\n", ret);
--    return EFAULT;
-+    if (parent_stat->st_uid == uid) {
-+        if (!(parent_stat->st_mode & S_IXUSR)) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "Parent directory does not have the search bit set for "
-+                   "the owner.\n");
-+            return EINVAL;
-+        }
-+    } else {
-+        if (!(parent_stat->st_mode & S_IXOTH)) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "Parent directory does not have the search bit set for "
-+                   "others.\n");
-+            return EINVAL;
-+        }
-+    }
-+
-+    return EOK;
- }
- 
--errno_t
--create_ccache_dir(const char *ccdirname, pcre *illegal_re,
--                  uid_t uid, gid_t gid)
-+errno_t create_ccache_dir(const char *ccdirname,
-+                          pcre *illegal_re,
-+                          uid_t uid, gid_t gid)
- {
-     int ret = EFAULT;
-     struct stat parent_stat;
-@@ -625,113 +242,6 @@ done:
-     return ret;
- }
- 
--errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
--                             struct tgt_times *tgtt)
--{
--    krb5_error_code kerr;
--    krb5_context ctx = NULL;
--    krb5_ccache cc = NULL;
--    krb5_principal client_princ = NULL;
--    krb5_principal server_princ = NULL;
--    char *server_name;
--    krb5_creds mcred;
--    krb5_creds cred;
--    const char *realm_name;
--    int realm_length;
--
--    kerr = krb5_init_context(&ctx);
--    if (kerr != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_init_context failed.\n");
--        goto done;
--    }
--
--    kerr = krb5_parse_name(ctx, client_name, &client_princ);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
--        goto done;
--    }
--
--    sss_krb5_princ_realm(ctx, client_princ, &realm_name, &realm_length);
--
--    server_name = talloc_asprintf(NULL, "krbtgt/%.*s@%.*s",
--                                  realm_length, realm_name,
--                                  realm_length, realm_name);
--    if (server_name == NULL) {
--        kerr = KRB5_CC_NOMEM;
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
--        goto done;
--    }
--
--    kerr = krb5_parse_name(ctx, server_name, &server_princ);
--    talloc_free(server_name);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
--        goto done;
--    }
--
--    kerr = krb5_cc_resolve(ctx, ccache_file, &cc);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_resolve failed.\n");
--        goto done;
--    }
--
--    memset(&mcred, 0, sizeof(mcred));
--    memset(&cred, 0, sizeof(mcred));
--
--    mcred.server = server_princ;
--    mcred.client = client_princ;
--
--    kerr = krb5_cc_retrieve_cred(ctx, cc, 0, &mcred, &cred);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_retrieve_cred failed.\n");
--        goto done;
--    }
--
--    tgtt->authtime = cred.times.authtime;
--    tgtt->starttime = cred.times.starttime;
--    tgtt->endtime = cred.times.endtime;
--    tgtt->renew_till = cred.times.renew_till;
--
--    krb5_free_cred_contents(ctx, &cred);
--
--    kerr = krb5_cc_close(ctx, cc);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_close failed.\n");
--        goto done;
--    }
--    cc = NULL;
--
--    kerr = 0;
--
--done:
--    if (cc != NULL) {
--        krb5_cc_close(ctx, cc);
--    }
--
--    if (client_princ != NULL) {
--        krb5_free_principal(ctx, client_princ);
--    }
--
--    if (server_princ != NULL) {
--        krb5_free_principal(ctx, server_princ);
--    }
--
--    if (ctx != NULL) {
--        krb5_free_context(ctx);
--    }
--
--    if (kerr != 0) {
--        return EIO;
--    }
--
--    return EOK;
--}
--
- errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
-                                   uid_t uid, gid_t gid)
- {
-@@ -783,7 +293,6 @@ done:
-     return ret;
- }
- 
--
- struct sss_krb5_ccache {
-     struct sss_creds *creds;
-     krb5_context context;
-@@ -895,7 +404,6 @@ done:
-     return ret;
- }
- 
--
- /* This function is called only as a way to validate that we have the
-  * right cache */
- errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
-@@ -1086,22 +594,124 @@ done:
-     return ret;
- }
- 
--
--errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
--                                char *domain_name,
--                                struct sss_domain_info **dom)
-+errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
-+                             struct tgt_times *tgtt)
- {
-+    krb5_error_code kerr;
-+    krb5_context ctx = NULL;
-+    krb5_ccache cc = NULL;
-+    krb5_principal client_princ = NULL;
-+    krb5_principal server_princ = NULL;
-+    char *server_name;
-+    krb5_creds mcred;
-+    krb5_creds cred;
-+    const char *realm_name;
-+    int realm_length;
- 
--    if (domain_name != NULL &&
--        strcasecmp(domain_name, be_ctx->domain->name) != 0) {
--        *dom = find_domain_by_name(be_ctx->domain, domain_name, true);
--        if (*dom == NULL) {
--            DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
--            return ENOMEM;
--        }
--    } else {
--        *dom = be_ctx->domain;
-+    kerr = krb5_init_context(&ctx);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_init_context failed.\n");
-+        goto done;
-+    }
-+
-+    kerr = krb5_parse_name(ctx, client_name, &client_princ);
-+    if (kerr != 0) {
-+        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
-+        goto done;
-+    }
-+
-+    sss_krb5_princ_realm(ctx, client_princ, &realm_name, &realm_length);
-+
-+    server_name = talloc_asprintf(NULL, "krbtgt/%.*s@%.*s",
-+                                  realm_length, realm_name,
-+                                  realm_length, realm_name);
-+    if (server_name == NULL) {
-+        kerr = KRB5_CC_NOMEM;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
-+        goto done;
-+    }
-+
-+    kerr = krb5_parse_name(ctx, server_name, &server_princ);
-+    talloc_free(server_name);
-+    if (kerr != 0) {
-+        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
-+        goto done;
-+    }
-+
-+    kerr = krb5_cc_resolve(ctx, ccache_file, &cc);
-+    if (kerr != 0) {
-+        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_resolve failed.\n");
-+        goto done;
-+    }
-+
-+    memset(&mcred, 0, sizeof(mcred));
-+    memset(&cred, 0, sizeof(mcred));
-+
-+    mcred.server = server_princ;
-+    mcred.client = client_princ;
-+
-+    kerr = krb5_cc_retrieve_cred(ctx, cc, 0, &mcred, &cred);
-+    if (kerr != 0) {
-+        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_retrieve_cred failed.\n");
-+        goto done;
-+    }
-+
-+    tgtt->authtime = cred.times.authtime;
-+    tgtt->starttime = cred.times.starttime;
-+    tgtt->endtime = cred.times.endtime;
-+    tgtt->renew_till = cred.times.renew_till;
-+
-+    krb5_free_cred_contents(ctx, &cred);
-+
-+    kerr = krb5_cc_close(ctx, cc);
-+    if (kerr != 0) {
-+        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_close failed.\n");
-+        goto done;
-+    }
-+    cc = NULL;
-+
-+    kerr = 0;
-+
-+done:
-+    if (cc != NULL) {
-+        krb5_cc_close(ctx, cc);
-+    }
-+
-+    if (client_princ != NULL) {
-+        krb5_free_principal(ctx, client_princ);
-+    }
-+
-+    if (server_princ != NULL) {
-+        krb5_free_principal(ctx, server_princ);
-+    }
-+
-+    if (ctx != NULL) {
-+        krb5_free_context(ctx);
-+    }
-+
-+    if (kerr != 0) {
-+        return EIO;
-     }
- 
-     return EOK;
- }
-+
-+errno_t safe_remove_old_ccache_file(const char *old_ccache,
-+                                    const char *new_ccache,
-+                                    uid_t uid, gid_t gid)
-+{
-+    if ((old_ccache == new_ccache)
-+        || (old_ccache && new_ccache
-+            && (strcmp(old_ccache, new_ccache) == 0))) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "New and old ccache file are the same, "
-+                                  "none will be deleted.\n");
-+        return EOK;
-+    }
-+
-+    return sss_krb5_cc_destroy(old_ccache, uid, gid);
-+}
-diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_ccache.h
-similarity index 53%
-copy from src/providers/krb5/krb5_utils.h
-copy to src/providers/krb5/krb5_ccache.h
-index f54a07f7936a361c21ca933026ee753a89fe5808..9f0b3ac84b7af118c315ca00a7c52f200534d97e 100644
---- a/src/providers/krb5/krb5_utils.h
-+++ b/src/providers/krb5/krb5_ccache.h
-@@ -1,13 +1,13 @@
- /*
-     SSSD
- 
--    Kerberos Backend, header file for utilities
-+    Kerberos 5 Backend Module -- ccache related utilities
- 
-     Authors:
-         Sumit Bose <sbose@redhat.com>
-+        Jakub Hrozek <jhrozek@redhat.com>
- 
--    Copyright (C) 2009 Red Hat
--
-+    Copyright (C) 2014 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
-@@ -23,45 +23,38 @@
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
- 
--#ifndef __KRB5_UTILS_H__
--#define __KRB5_UTILS_H__
-+#ifndef __KRB5_CCACHE_H__
-+#define __KRB5_CCACHE_H__
- 
--#include <talloc.h>
--#include "config.h"
-+#include "util/util.h"
- 
--#include "providers/krb5/krb5_auth.h"
--#include "providers/data_provider.h"
-+struct tgt_times {
-+    time_t authtime;
-+    time_t starttime;
-+    time_t endtime;
-+    time_t renew_till;
-+};
- 
--errno_t find_or_guess_upn(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
--                          struct krb5_ctx *krb5_ctx,
--                          struct sss_domain_info *dom, const char *user,
--                          const char *user_dom, char **_upn);
--
--errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
--                                         struct sss_domain_info *domain,
--                                         const char *user,
--                                         const char *upn);
--
--errno_t create_ccache_dir(const char *dirname, pcre *illegal_re,
-+errno_t create_ccache_dir(const char *ccdirname,
-+                          pcre *illegal_re,
-                           uid_t uid, gid_t gid);
- 
--char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
--                             const char *template, bool file_mode,
--                             bool case_sensitive);
--
- errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
-                                   uid_t uid, gid_t gid);
-+
- errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
-+
- errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
-                                     const char *ccname, const char *principal);
-+
- errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
-                                   const char *realm, const char *principal);
- 
- errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
-                              struct tgt_times *tgtt);
- 
-+errno_t safe_remove_old_ccache_file(const char *old_ccache,
-+                                    const char *new_ccache,
-+                                    uid_t uid, gid_t gid);
- 
--errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
--                                char *domain_name,
--                                struct sss_domain_info **dom);
--#endif /* __KRB5_UTILS_H__ */
-+#endif /* __KRB5_CCACHE_H__ */
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index b0bf76fb3b8a77831b114c47acff8cd0d3fd780d..7fa5f0c344a4afe110afa08f479f283aefce8d23 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -1885,6 +1885,7 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-         /* If krb5_child was started as setuid, but we don't need to
-          * perform either validation or FAST, just drop privileges to
-          * the user who is logging in. The same applies to the offline case
-+         * the user who is logging in. The same applies to the offline case.
-          */
-         kerr = become_user(kr->uid, kr->gid);
-         if (kerr != 0) {
-diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
-index eac0d6b1f0c0fec4a107a7b830d8b0c927f4fe42..a5cee6497e4930b16b1102a525d9fa3452845a58 100644
---- a/src/providers/krb5/krb5_common.h
-+++ b/src/providers/krb5/krb5_common.h
-@@ -73,13 +73,6 @@ enum krb5_opts {
- 
- typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
- 
--struct tgt_times {
--    time_t authtime;
--    time_t starttime;
--    time_t endtime;
--    time_t renew_till;
--};
--
- struct krb5_service {
-     char *name;
-     char *realm;
-diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c
-index 12963549829c4bbb0f799c5d00b9b8986ccfd485..5277c0f7691dd272a69b3024cb2c0bd7545a8fbd 100644
---- a/src/providers/krb5/krb5_renew_tgt.c
-+++ b/src/providers/krb5/krb5_renew_tgt.c
-@@ -27,6 +27,7 @@
- #include "providers/krb5/krb5_common.h"
- #include "providers/krb5/krb5_auth.h"
- #include "providers/krb5/krb5_utils.h"
-+#include "providers/krb5/krb5_ccache.h"
- 
- #define INITIAL_TGT_TABLE_SIZE 10
- 
-diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
-index 0d2e281198390043068e21b412b57de04df6a12b..ae72b04be236cfce9b6f794c602887491ba487a9 100644
---- a/src/providers/krb5/krb5_utils.c
-+++ b/src/providers/krb5/krb5_utils.c
-@@ -26,6 +26,7 @@
- #include <libgen.h>
- 
- #include "providers/krb5/krb5_utils.h"
-+#include "providers/krb5/krb5_ccache.h"
- #include "providers/krb5/krb5_auth.h"
- #include "src/util/find_uid.h"
- #include "util/util.h"
-@@ -379,7 +380,7 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
-                     name = n;
-                     n = strchr(name, '}');
-                     if (!n) {
--                        DEBUG(SSSDBG_CRIT_FAILURE, 
-+                        DEBUG(SSSDBG_CRIT_FAILURE,
-                               "Invalid substitution sequence in cache "
-                               "template. Missing closing '}' in [%s].\n",
-                               template);
-@@ -416,677 +417,6 @@ done:
-     return res;
- }
- 
--static errno_t check_parent_stat(struct stat *parent_stat, uid_t uid)
--{
--    if (parent_stat->st_uid != 0 && parent_stat->st_uid != uid) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Private directory can only be created below a directory "
--              "belonging to root or to [%"SPRIuid"].\n", uid);
--        return EINVAL;
--    }
--
--    if (parent_stat->st_uid == uid) {
--        if (!(parent_stat->st_mode & S_IXUSR)) {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "Parent directory does not have the search bit set for "
--                   "the owner.\n");
--            return EINVAL;
--        }
--    } else {
--        if (!(parent_stat->st_mode & S_IXOTH)) {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "Parent directory does not have the search bit set for "
--                   "others.\n");
--            return EINVAL;
--        }
--    }
--
--    return EOK;
--}
--
--struct string_list {
--    struct string_list *next;
--    struct string_list *prev;
--    char *s;
--};
--
--static errno_t find_ccdir_parent_data(TALLOC_CTX *mem_ctx,
--                                      const char *ccdirname,
--                                      struct stat *parent_stat,
--                                      struct string_list **missing_parents)
--{
--    int ret = EFAULT;
--    char *parent = NULL;
--    char *end;
--    struct string_list *li;
--
--    ret = stat(ccdirname, parent_stat);
--    if (ret == EOK) {
--        if ( !S_ISDIR(parent_stat->st_mode) ) {
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "[%s] is not a directory.\n", ccdirname);
--            return EINVAL;
--        }
--        return EOK;
--    } else {
--        if (errno != ENOENT) {
--            ret = errno;
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "stat for [%s] failed: [%d][%s].\n", ccdirname, ret,
--                   strerror(ret));
--            return ret;
--        }
--    }
--
--    li = talloc_zero(mem_ctx, struct string_list);
--    if (li == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "talloc_zero failed.\n");
--        return ENOMEM;
--    }
--
--    li->s = talloc_strdup(li, ccdirname);
--    if (li->s == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "talloc_strdup failed.\n");
--        return ENOMEM;
--    }
--
--    DLIST_ADD(*missing_parents, li);
--
--    parent = talloc_strdup(mem_ctx, ccdirname);
--    if (parent == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "talloc_strdup failed.\n");
--        return ENOMEM;
--    }
--
--    /* We'll remove all trailing slashes from the back so that
--     * we only pass /some/path to find_ccdir_parent_data, not
--     * /some/path */
--    do {
--        end = strrchr(parent, '/');
--        if (end == NULL || end == parent) {
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "Cannot find parent directory of [%s], / is not allowed.\n",
--                   ccdirname);
--            ret = EINVAL;
--            goto done;
--        }
--        *end = '\0';
--    } while (*(end+1) == '\0');
--
--    ret = find_ccdir_parent_data(mem_ctx, parent, parent_stat, missing_parents);
--
--done:
--    talloc_free(parent);
--    return ret;
--}
--
--static errno_t
--check_ccache_re(const char *filename, pcre *illegal_re)
--{
--    errno_t ret;
--
--    ret = pcre_exec(illegal_re, NULL, filename, strlen(filename),
--                    0, 0, NULL, 0);
--    if (ret == 0) {
--        DEBUG(SSSDBG_OP_FAILURE,
--              "Illegal pattern in ccache directory name [%s].\n", filename);
--        return EINVAL;
--    } else if (ret == PCRE_ERROR_NOMATCH) {
--        DEBUG(SSSDBG_TRACE_LIBS,
--              "Ccache directory name [%s] does not contain "
--               "illegal patterns.\n", filename);
--        return EOK;
--    }
--
--    DEBUG(SSSDBG_CRIT_FAILURE, "pcre_exec failed [%d].\n", ret);
--    return EFAULT;
--}
--
--errno_t
--create_ccache_dir(const char *ccdirname, pcre *illegal_re,
--                  uid_t uid, gid_t gid)
--{
--    int ret = EFAULT;
--    struct stat parent_stat;
--    struct string_list *missing_parents = NULL;
--    struct string_list *li = NULL;
--    mode_t old_umask;
--    mode_t new_dir_mode;
--    TALLOC_CTX *tmp_ctx = NULL;
--
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "talloc_new failed.\n");
--        return ENOMEM;
--    }
--
--    if (*ccdirname != '/') {
--        DEBUG(SSSDBG_MINOR_FAILURE,
--              "Only absolute paths are allowed, not [%s] .\n", ccdirname);
--        ret = EINVAL;
--        goto done;
--    }
--
--    if (illegal_re != NULL) {
--        ret = check_ccache_re(ccdirname, illegal_re);
--        if (ret != EOK) {
--            goto done;
--        }
--    }
--
--    ret = find_ccdir_parent_data(tmp_ctx, ccdirname, &parent_stat,
--                                 &missing_parents);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_MINOR_FAILURE,
--              "find_ccdir_parent_data failed.\n");
--        goto done;
--    }
--
--    ret = check_parent_stat(&parent_stat, uid);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_FATAL_FAILURE,
--              "Check the ownership and permissions of krb5_ccachedir: [%s].\n",
--              ccdirname);
--        goto done;
--    }
--
--    DLIST_FOR_EACH(li, missing_parents) {
--        DEBUG(SSSDBG_TRACE_INTERNAL,
--              "Creating directory [%s].\n", li->s);
--        new_dir_mode = 0700;
--
--        old_umask = umask(0000);
--        ret = mkdir(li->s, new_dir_mode);
--        umask(old_umask);
--        if (ret != EOK) {
--            ret = errno;
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "mkdir [%s] failed: [%d][%s].\n", li->s, ret,
--                   strerror(ret));
--            goto done;
--        }
--        ret = chown(li->s, uid, gid);
--        if (ret != EOK) {
--            ret = errno;
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "chown failed [%d][%s].\n", ret, strerror(ret));
--            goto done;
--        }
--    }
--
--    ret = EOK;
--
--done:
--    talloc_free(tmp_ctx);
--    return ret;
--}
--
--errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
--                             struct tgt_times *tgtt)
--{
--    krb5_error_code kerr;
--    krb5_context ctx = NULL;
--    krb5_ccache cc = NULL;
--    krb5_principal client_princ = NULL;
--    krb5_principal server_princ = NULL;
--    char *server_name;
--    krb5_creds mcred;
--    krb5_creds cred;
--    const char *realm_name;
--    int realm_length;
--
--    kerr = krb5_init_context(&ctx);
--    if (kerr != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_init_context failed.\n");
--        goto done;
--    }
--
--    kerr = krb5_parse_name(ctx, client_name, &client_princ);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
--        goto done;
--    }
--
--    sss_krb5_princ_realm(ctx, client_princ, &realm_name, &realm_length);
--
--    server_name = talloc_asprintf(NULL, "krbtgt/%.*s@%.*s",
--                                  realm_length, realm_name,
--                                  realm_length, realm_name);
--    if (server_name == NULL) {
--        kerr = KRB5_CC_NOMEM;
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
--        goto done;
--    }
--
--    kerr = krb5_parse_name(ctx, server_name, &server_princ);
--    talloc_free(server_name);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
--        goto done;
--    }
--
--    kerr = krb5_cc_resolve(ctx, ccache_file, &cc);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_resolve failed.\n");
--        goto done;
--    }
--
--    memset(&mcred, 0, sizeof(mcred));
--    memset(&cred, 0, sizeof(mcred));
--
--    mcred.server = server_princ;
--    mcred.client = client_princ;
--
--    kerr = krb5_cc_retrieve_cred(ctx, cc, 0, &mcred, &cred);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_retrieve_cred failed.\n");
--        goto done;
--    }
--
--    tgtt->authtime = cred.times.authtime;
--    tgtt->starttime = cred.times.starttime;
--    tgtt->endtime = cred.times.endtime;
--    tgtt->renew_till = cred.times.renew_till;
--
--    krb5_free_cred_contents(ctx, &cred);
--
--    kerr = krb5_cc_close(ctx, cc);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, ctx, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_close failed.\n");
--        goto done;
--    }
--    cc = NULL;
--
--    kerr = 0;
--
--done:
--    if (cc != NULL) {
--        krb5_cc_close(ctx, cc);
--    }
--
--    if (client_princ != NULL) {
--        krb5_free_principal(ctx, client_princ);
--    }
--
--    if (server_princ != NULL) {
--        krb5_free_principal(ctx, server_princ);
--    }
--
--    if (ctx != NULL) {
--        krb5_free_context(ctx);
--    }
--
--    if (kerr != 0) {
--        return EIO;
--    }
--
--    return EOK;
--}
--
--errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
--                                  uid_t uid, gid_t gid)
--{
--    TALLOC_CTX *tmp_ctx = NULL;
--    const char *filename;
--    char *ccdirname;
--    char *end;
--    errno_t ret;
--
--    if (ccname[0] == '/') {
--        filename = ccname;
--    } else if (strncmp(ccname, "FILE:", 5) == 0) {
--        filename = ccname + 5;
--    } else if (strncmp(ccname, "DIR:", 4) == 0) {
--        filename = ccname + 4;
--    } else {
--        /* only FILE and DIR types need precreation so far, we ignore any
--         * other type */
--        return EOK;
--    }
--
--    tmp_ctx = talloc_new(NULL);
--    if (!tmp_ctx) return ENOMEM;
--
--    ccdirname = talloc_strdup(tmp_ctx, filename);
--    if (ccdirname == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
--        ret = ENOMEM;
--        goto done;
--    }
--
--    /* We'll remove all trailing slashes from the back so that
--     * we only pass /some/path to find_ccdir_parent_data, not
--     * /some/path/ */
--    do {
--        end = strrchr(ccdirname, '/');
--        if (end == NULL || end == ccdirname) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find parent directory of [%s], "
--                  "/ is not allowed.\n", ccdirname);
--            ret = EINVAL;
--            goto done;
--        }
--        *end = '\0';
--    } while (*(end+1) == '\0');
--
--    ret = create_ccache_dir(ccdirname, illegal_re, uid, gid);
--done:
--    talloc_free(tmp_ctx);
--    return ret;
--}
--
--
--struct sss_krb5_ccache {
--    struct sss_creds *creds;
--    krb5_context context;
--    krb5_ccache ccache;
--};
--
--static int sss_free_krb5_ccache(void *mem)
--{
--    struct sss_krb5_ccache *cc = talloc_get_type(mem, struct sss_krb5_ccache);
--
--    if (cc->ccache) {
--        krb5_cc_close(cc->context, cc->ccache);
--    }
--    krb5_free_context(cc->context);
--    restore_creds(cc->creds);
--    return 0;
--}
--
--static errno_t sss_open_ccache_as_user(TALLOC_CTX *mem_ctx,
--                                       const char *ccname,
--                                       uid_t uid, gid_t gid,
--                                       struct sss_krb5_ccache **ccache)
--{
--    struct sss_krb5_ccache *cc;
--    krb5_error_code kerr;
--    errno_t ret;
--
--    cc = talloc_zero(mem_ctx, struct sss_krb5_ccache);
--    if (!cc) {
--        return ENOMEM;
--    }
--    talloc_set_destructor((TALLOC_CTX *)cc, sss_free_krb5_ccache);
--
--    ret = switch_creds(cc, uid, gid, 0, NULL, &cc->creds);
--    if (ret) {
--        goto done;
--    }
--
--    kerr = krb5_init_context(&cc->context);
--    if (kerr) {
--        ret = EIO;
--        goto done;
--    }
--
--    kerr = krb5_cc_resolve(cc->context, ccname, &cc->ccache);
--    if (kerr == KRB5_FCC_NOFILE || cc->ccache == NULL) {
--        DEBUG(SSSDBG_TRACE_FUNC, "ccache %s is missing or empty\n", ccname);
--        ret = ERR_NOT_FOUND;
--        goto done;
--    } else if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_resolve failed.\n");
--        ret = ERR_INTERNAL;
--        goto done;
--    }
--
--    ret = EOK;
--
--done:
--    if (ret) {
--        talloc_free(cc);
--    } else {
--        *ccache = cc;
--    }
--    return ret;
--}
--
--static errno_t sss_destroy_ccache(struct sss_krb5_ccache *cc)
--{
--    krb5_error_code kerr;
--    errno_t ret;
--
--    kerr = krb5_cc_destroy(cc->context, cc->ccache);
--    if (kerr) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_destroy failed.\n");
--        ret = EIO;
--    } else {
--        ret = EOK;
--    }
--
--    /* krb5_cc_destroy frees cc->ccache in all events */
--    cc->ccache = NULL;
--
--    return ret;
--}
--
--errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid)
--{
--    struct sss_krb5_ccache *cc = NULL;
--    TALLOC_CTX *tmp_ctx;
--    errno_t ret;
--
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
--        return ENOMEM;
--    }
--
--    ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
--    if (ret) {
--        goto done;
--    }
--
--    ret = sss_destroy_ccache(cc);
--
--done:
--    talloc_free(tmp_ctx);
--    return ret;
--}
--
--
--/* This function is called only as a way to validate that we have the
-- * right cache */
--errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
--                                    const char *ccname, const char *principal)
--{
--    struct sss_krb5_ccache *cc = NULL;
--    krb5_principal ccprinc = NULL;
--    krb5_principal kprinc = NULL;
--    krb5_error_code kerr;
--    const char *cc_type;
--    TALLOC_CTX *tmp_ctx;
--    errno_t ret;
--
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
--        return ENOMEM;
--    }
--
--    ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
--    if (ret) {
--        goto done;
--    }
--
--    cc_type = krb5_cc_get_type(cc->context, cc->ccache);
--
--    DEBUG(SSSDBG_TRACE_INTERNAL,
--          "Searching for [%s] in cache of type [%s]\n", principal, cc_type);
--
--    kerr = krb5_parse_name(cc->context, principal, &kprinc);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
--        ret = ERR_INTERNAL;
--        goto done;
--    }
--
--    kerr = krb5_cc_get_principal(cc->context, cc->ccache, &ccprinc);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_get_principal failed.\n");
--    }
--
--    if (ccprinc) {
--        if (krb5_principal_compare(cc->context, kprinc, ccprinc) == TRUE) {
--            /* found in the primary ccache */
--            ret = EOK;
--            goto done;
--        }
--    }
--
--#ifdef HAVE_KRB5_CC_COLLECTION
--
--    if (krb5_cc_support_switch(cc->context, cc_type)) {
--
--        krb5_cc_close(cc->context, cc->ccache);
--        cc->ccache = NULL;
--
--        kerr = krb5_cc_set_default_name(cc->context, ccname);
--        if (kerr != 0) {
--            KRB5_DEBUG(SSSDBG_MINOR_FAILURE, cc->context, kerr);
--            /* try to continue despite failure */
--        }
--
--        kerr = krb5_cc_cache_match(cc->context, kprinc, &cc->ccache);
--        if (kerr == 0) {
--            ret = EOK;
--            goto done;
--        }
--        KRB5_DEBUG(SSSDBG_TRACE_INTERNAL, cc->context, kerr);
--    }
--
--#endif /* HAVE_KRB5_CC_COLLECTION */
--
--    ret = ERR_NOT_FOUND;
--
--done:
--    if (cc) {
--        krb5_free_principal(cc->context, ccprinc);
--        krb5_free_principal(cc->context, kprinc);
--    }
--    talloc_free(tmp_ctx);
--    return ret;
--}
--
--static errno_t sss_low_level_path_check(const char *ccname)
--{
--    const char *filename;
--    struct stat buf;
--    int ret;
--
--    if (ccname[0] == '/') {
--        filename = ccname;
--    } else if (strncmp(ccname, "FILE:", 5) == 0) {
--        filename = ccname + 5;
--    } else if (strncmp(ccname, "DIR:", 4) == 0) {
--        filename = ccname + 4;
--        if (filename[0] == ':') filename += 1;
--    } else {
--        /* only FILE and DIR types need file checks so far, we ignore any
--         * other type */
--        return EOK;
--    }
--
--    ret = stat(filename, &buf);
--    if (ret == -1) return errno;
--    return EOK;
--}
--
--errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
--                                  const char *realm, const char *principal)
--{
--    struct sss_krb5_ccache *cc = NULL;
--    TALLOC_CTX *tmp_ctx = NULL;
--    krb5_principal tgt_princ = NULL;
--    krb5_principal princ = NULL;
--    char *tgt_name;
--    krb5_creds mcred = { 0 };
--    krb5_creds cred = { 0 };
--    krb5_error_code kerr;
--    errno_t ret;
--
--    /* first of all verify if the old ccache file/dir exists as we may be
--     * trying to verify if an old ccache exists at all. If no file/dir
--     * exists bail out immediately otherwise a following krb5_cc_resolve()
--     * call may actually create paths and files we do not want to have
--     * around */
--    ret = sss_low_level_path_check(ccname);
--    if (ret) {
--        return ret;
--    }
--
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
--        return ENOMEM;
--    }
--
--    ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
--    if (ret) {
--        goto done;
--    }
--
--    tgt_name = talloc_asprintf(tmp_ctx, "krbtgt/%s@%s", realm, realm);
--    if (!tgt_name) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n");
--        ret = ENOMEM;
--        goto done;
--    }
--
--    kerr = krb5_parse_name(cc->context, tgt_name, &tgt_princ);
--    if (kerr) {
--        KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
--        if (kerr == KRB5_PARSE_MALFORMED) ret = EINVAL;
--        else ret = ERR_INTERNAL;
--        goto done;
--    }
--
--    kerr = krb5_parse_name(cc->context, principal, &princ);
--    if (kerr) {
--        KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
--        if (kerr == KRB5_PARSE_MALFORMED) ret = EINVAL;
--        else ret = ERR_INTERNAL;
--        goto done;
--    }
--
--    mcred.client = princ;
--    mcred.server = tgt_princ;
--    mcred.times.endtime = time(NULL);
--
--    kerr = krb5_cc_retrieve_cred(cc->context, cc->ccache,
--                                 KRB5_TC_MATCH_TIMES, &mcred, &cred);
--    if (kerr) {
--        if (kerr == KRB5_CC_NOTFOUND || kerr == KRB5_FCC_NOFILE) {
--            DEBUG(SSSDBG_TRACE_INTERNAL, "TGT not found or expired.\n");
--            ret = EINVAL;
--        } else {
--            KRB5_DEBUG(SSSDBG_CRIT_FAILURE, cc->context, kerr);
--            ret = ERR_INTERNAL;
--        }
--    }
--    krb5_free_cred_contents(cc->context, &cred);
--
--done:
--    if (tgt_princ) krb5_free_principal(cc->context, tgt_princ);
--    if (princ) krb5_free_principal(cc->context, princ);
--    talloc_free(tmp_ctx);
--    return ret;
--}
--
--
- errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
-                                 char *domain_name,
-                                 struct sss_domain_info **dom)
-diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
-index f54a07f7936a361c21ca933026ee753a89fe5808..ce5ce1ebcf6db14579191840600e684d41a2fdbe 100644
---- a/src/providers/krb5/krb5_utils.h
-+++ b/src/providers/krb5/krb5_utils.h
-@@ -42,25 +42,10 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
-                                          const char *user,
-                                          const char *upn);
- 
--errno_t create_ccache_dir(const char *dirname, pcre *illegal_re,
--                          uid_t uid, gid_t gid);
--
- char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
-                              const char *template, bool file_mode,
-                              bool case_sensitive);
- 
--errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
--                                  uid_t uid, gid_t gid);
--errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
--errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
--                                    const char *ccname, const char *principal);
--errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
--                                  const char *realm, const char *principal);
--
--errno_t get_ccache_file_data(const char *ccache_file, const char *client_name,
--                             struct tgt_times *tgtt);
--
--
- errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
-                                 char *domain_name,
-                                 struct sss_domain_info **dom);
-diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
-index 63caa5f6c97f3e5c0df459b7549e681e51fcc108..09f23d5386e3c70efc5ce54fa199c1a6e8656eec 100644
---- a/src/tests/krb5_child-test.c
-+++ b/src/tests/krb5_child-test.c
-@@ -37,6 +37,7 @@
- #include "providers/krb5/krb5_auth.h"
- #include "providers/krb5/krb5_common.h"
- #include "providers/krb5/krb5_utils.h"
-+#include "providers/krb5/krb5_ccache.h"
- 
- extern struct dp_option default_krb5_opts[];
- 
-diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
-index 18d2bd230ab1170da2caf685cead46c1390c0851..52d8a18576b23c627c7ef3358bd34f4b2dbae6f7 100644
---- a/src/tests/krb5_utils-tests.c
-+++ b/src/tests/krb5_utils-tests.c
-@@ -27,6 +27,7 @@
- #include <check.h>
- 
- #include "providers/krb5/krb5_utils.h"
-+#include "providers/krb5/krb5_ccache.h"
- #include "providers/krb5/krb5_auth.h"
- #include "tests/common.h"
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0086-DYNDNS-remove-redundant-talloc_steal.patch b/SOURCES/0086-DYNDNS-remove-redundant-talloc_steal.patch
new file mode 100644
index 0000000..8bbb5ed
--- /dev/null
+++ b/SOURCES/0086-DYNDNS-remove-redundant-talloc_steal.patch
@@ -0,0 +1,31 @@
+From efbf0e362238eaf0330384caf057521968f25758 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Thu, 23 Jul 2015 04:50:38 -0400
+Subject: [PATCH 86/90] DYNDNS: remove redundant talloc_steal()
+
+String 'update_msg' was already allocated on mem_ctx, so, there is no
+need to steal it.
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit e4d6e9ccac14044d6bcd5a0dce7f45fdfab6bf3d)
+---
+ src/providers/dp_dyndns.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 9a726bd431854342993212ce0a9759b86069cd5e..3171e6909e5f92a98cd506278e6e8c3418b979fe 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -525,7 +525,8 @@ be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm,
+           update_msg);
+ 
+     ret = ERR_OK;
+-    *_update_msg = talloc_steal(mem_ctx, update_msg);
++    *_update_msg = update_msg;
++
+ done:
+     return ret;
+ }
+-- 
+2.4.3
+
diff --git a/SOURCES/0086-KRB5-Move-checking-for-illegal-RE-to-krb5_utils.c.patch b/SOURCES/0086-KRB5-Move-checking-for-illegal-RE-to-krb5_utils.c.patch
deleted file mode 100644
index f8e95e4..0000000
--- a/SOURCES/0086-KRB5-Move-checking-for-illegal-RE-to-krb5_utils.c.patch
+++ /dev/null
@@ -1,487 +0,0 @@
-From f72856736ac39c7e926c02c11f854f43400366d4 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sat, 18 Oct 2014 22:03:01 +0200
-Subject: [PATCH 86/92] KRB5: Move checking for illegal RE to krb5_utils.c
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Otherwise we would have to link krb5_child with pcre and transfer the
-regex, which would be cumbersome. Check for illegal patterns when
-expanding the template instead.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/krb5/krb5_auth.c   |  5 +--
- src/providers/krb5/krb5_ccache.c | 38 ++------------------
- src/providers/krb5/krb5_ccache.h |  7 +---
- src/providers/krb5/krb5_utils.c  | 36 +++++++++++++++++--
- src/providers/krb5/krb5_utils.h  |  4 +--
- src/tests/krb5_child-test.c      |  2 +-
- src/tests/krb5_utils-tests.c     | 78 ++++++++++++++++------------------------
- 7 files changed, 73 insertions(+), 97 deletions(-)
-
-diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
-index bd8b51f47462f1eaef8da61b42caedda3475a4e7..5ed561601ac80e53ee795b458c5bf0ca410951bc 100644
---- a/src/providers/krb5/krb5_auth.c
-+++ b/src/providers/krb5/krb5_auth.c
-@@ -302,7 +302,9 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
-             DEBUG(SSSDBG_TRACE_ALL, "Recreating  ccache file.\n");
-             ccname_template = dp_opt_get_cstring(kr->krb5_ctx->opts,
-                                                  KRB5_CCNAME_TMPL);
--            kr->ccname = expand_ccname_template(kr, kr, ccname_template, true,
-+            kr->ccname = expand_ccname_template(kr, kr, ccname_template,
-+                                                kr->krb5_ctx->illegal_path_re,
-+                                                true,
-                                                 be_ctx->domain->case_sensitive);
-             if (kr->ccname == NULL) {
-                 DEBUG(SSSDBG_CRIT_FAILURE, "expand_ccname_template failed.\n");
-@@ -310,7 +312,6 @@ static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
-             }
- 
-             ret = sss_krb5_precreate_ccache(kr->ccname,
--                                            kr->krb5_ctx->illegal_path_re,
-                                             kr->uid, kr->gid);
-             if (ret != EOK) {
-                 DEBUG(SSSDBG_OP_FAILURE, "ccache creation failed.\n");
-diff --git a/src/providers/krb5/krb5_ccache.c b/src/providers/krb5/krb5_ccache.c
-index 5586963338616519f36e5d75e796a597d3ac2f22..c0f5b7b8ced3fd2d6d8cbbf4e3339caba60888ff 100644
---- a/src/providers/krb5/krb5_ccache.c
-+++ b/src/providers/krb5/krb5_ccache.c
-@@ -33,28 +33,6 @@
- #include "util/sss_krb5.h"
- #include "util/util.h"
- 
--static errno_t
--check_ccache_re(const char *filename, pcre *illegal_re)
--{
--    errno_t ret;
--
--    ret = pcre_exec(illegal_re, NULL, filename, strlen(filename),
--                    0, 0, NULL, 0);
--    if (ret == 0) {
--        DEBUG(SSSDBG_OP_FAILURE,
--              "Illegal pattern in ccache directory name [%s].\n", filename);
--        return EINVAL;
--    } else if (ret == PCRE_ERROR_NOMATCH) {
--        DEBUG(SSSDBG_TRACE_LIBS,
--              "Ccache directory name [%s] does not contain "
--               "illegal patterns.\n", filename);
--        return EOK;
--    }
--
--    DEBUG(SSSDBG_CRIT_FAILURE, "pcre_exec failed [%d].\n", ret);
--    return EFAULT;
--}
--
- struct string_list {
-     struct string_list *next;
-     struct string_list *prev;
-@@ -162,9 +140,7 @@ static errno_t check_parent_stat(struct stat *parent_stat, uid_t uid)
-     return EOK;
- }
- 
--errno_t create_ccache_dir(const char *ccdirname,
--                          pcre *illegal_re,
--                          uid_t uid, gid_t gid)
-+static errno_t create_ccache_dir(const char *ccdirname, uid_t uid, gid_t gid)
- {
-     int ret = EFAULT;
-     struct stat parent_stat;
-@@ -188,13 +164,6 @@ errno_t create_ccache_dir(const char *ccdirname,
-         goto done;
-     }
- 
--    if (illegal_re != NULL) {
--        ret = check_ccache_re(ccdirname, illegal_re);
--        if (ret != EOK) {
--            goto done;
--        }
--    }
--
-     ret = find_ccdir_parent_data(tmp_ctx, ccdirname, &parent_stat,
-                                  &missing_parents);
-     if (ret != EOK) {
-@@ -242,8 +211,7 @@ done:
-     return ret;
- }
- 
--errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
--                                  uid_t uid, gid_t gid)
-+errno_t sss_krb5_precreate_ccache(const char *ccname, uid_t uid, gid_t gid)
- {
-     TALLOC_CTX *tmp_ctx = NULL;
-     const char *filename;
-@@ -287,7 +255,7 @@ errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
-         *end = '\0';
-     } while (*(end+1) == '\0');
- 
--    ret = create_ccache_dir(ccdirname, illegal_re, uid, gid);
-+    ret = create_ccache_dir(ccdirname, uid, gid);
- done:
-     talloc_free(tmp_ctx);
-     return ret;
-diff --git a/src/providers/krb5/krb5_ccache.h b/src/providers/krb5/krb5_ccache.h
-index 9f0b3ac84b7af118c315ca00a7c52f200534d97e..e39f96cad6f46c4003103dce4eadf007bc0f8920 100644
---- a/src/providers/krb5/krb5_ccache.h
-+++ b/src/providers/krb5/krb5_ccache.h
-@@ -35,12 +35,7 @@ struct tgt_times {
-     time_t renew_till;
- };
- 
--errno_t create_ccache_dir(const char *ccdirname,
--                          pcre *illegal_re,
--                          uid_t uid, gid_t gid);
--
--errno_t sss_krb5_precreate_ccache(const char *ccname, pcre *illegal_re,
--                                  uid_t uid, gid_t gid);
-+errno_t sss_krb5_precreate_ccache(const char *ccname, uid_t uid, gid_t gid);
- 
- errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
- 
-diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c
-index ae72b04be236cfce9b6f794c602887491ba487a9..de2d94503744b80b0a3365efb227cd05434579ff 100644
---- a/src/providers/krb5/krb5_utils.c
-+++ b/src/providers/krb5/krb5_utils.c
-@@ -202,9 +202,31 @@ done:
- #define S_EXP_USERNAME "{username}"
- #define L_EXP_USERNAME (sizeof(S_EXP_USERNAME) - 1)
- 
-+static errno_t
-+check_ccache_re(const char *filename, pcre *illegal_re)
-+{
-+    errno_t ret;
-+
-+    ret = pcre_exec(illegal_re, NULL, filename, strlen(filename),
-+                    0, 0, NULL, 0);
-+    if (ret == 0) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "Illegal pattern in ccache directory name [%s].\n", filename);
-+        return EINVAL;
-+    } else if (ret == PCRE_ERROR_NOMATCH) {
-+        DEBUG(SSSDBG_TRACE_LIBS,
-+              "Ccache directory name [%s] does not contain "
-+               "illegal patterns.\n", filename);
-+        return EOK;
-+    }
-+
-+    DEBUG(SSSDBG_CRIT_FAILURE, "pcre_exec failed [%d].\n", ret);
-+    return EFAULT;
-+}
-+
- char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
--                             const char *template, bool file_mode,
--                             bool case_sensitive)
-+                             const char *template, pcre *illegal_re,
-+                             bool file_mode, bool case_sensitive)
- {
-     char *copy;
-     char *p;
-@@ -217,6 +239,7 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
-     TALLOC_CTX *tmp_ctx = NULL;
-     char action;
-     bool rerun;
-+    int ret;
- 
-     if (template == NULL) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Missing template.\n");
-@@ -320,7 +343,7 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
-                     }
- 
-                     dummy = expand_ccname_template(tmp_ctx, kr, cache_dir_tmpl,
--                                                   false, case_sensitive);
-+                                                   illegal_re, false, case_sensitive);
-                     if (dummy == NULL) {
-                         DEBUG(SSSDBG_CRIT_FAILURE,
-                               "Expanding credential cache directory "
-@@ -411,6 +434,13 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
-         goto done;
-     }
- 
-+    if (illegal_re != NULL) {
-+        ret = check_ccache_re(result, illegal_re);
-+        if (ret != EOK) {
-+            goto done;
-+        }
-+    }
-+
-     res = talloc_move(mem_ctx, &result);
- done:
-     talloc_zfree(tmp_ctx);
-diff --git a/src/providers/krb5/krb5_utils.h b/src/providers/krb5/krb5_utils.h
-index ce5ce1ebcf6db14579191840600e684d41a2fdbe..0155905b5bc7469d09aecbd51cae0e8cc61b3952 100644
---- a/src/providers/krb5/krb5_utils.h
-+++ b/src/providers/krb5/krb5_utils.h
-@@ -43,8 +43,8 @@ errno_t check_if_cached_upn_needs_update(struct sysdb_ctx *sysdb,
-                                          const char *upn);
- 
- char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
--                             const char *template, bool file_mode,
--                             bool case_sensitive);
-+                             const char *template, pcre *illegal_re,
-+                             bool file_mode, bool case_sensitive);
- 
- errno_t get_domain_or_subdomain(struct be_ctx *be_ctx,
-                                 char *domain_name,
-diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
-index 09f23d5386e3c70efc5ce54fa199c1a6e8656eec..8826a28ed5ea064317c62682003dc0e9a6df01b6 100644
---- a/src/tests/krb5_child-test.c
-+++ b/src/tests/krb5_child-test.c
-@@ -239,6 +239,7 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
-         kr->ccname = expand_ccname_template(kr, kr,
-                                         dp_opt_get_cstring(kr->krb5_ctx->opts,
-                                                            KRB5_CCNAME_TMPL),
-+                                            kr->krb5_ctx->illegal_path_re,
-                                             true, true);
-         if (!kr->ccname) goto fail;
- 
-@@ -254,7 +255,6 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
-             kr->ccname, kr->uid, kr->gid);
- 
-     ret = sss_krb5_precreate_ccache(kr->ccname,
--                                    kr->krb5_ctx->illegal_path_re,
-                                     kr->uid, kr->gid);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "create_ccache_dir failed.\n");
-diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c
-index 52d8a18576b23c627c7ef3358bd34f4b2dbae6f7..409c0f01d2cce9c24a648306007b9fa7f5bc8372 100644
---- a/src/tests/krb5_utils-tests.c
-+++ b/src/tests/krb5_utils-tests.c
-@@ -131,13 +131,13 @@ START_TEST(test_private_ccache_dir_in_user_dir)
- 
-     ret = chmod(user_dir, 0600);
-     fail_unless(ret == EOK, "chmod failed.");
--    ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid);
-+    ret = sss_krb5_precreate_ccache(filename, uid, gid);
-     fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL "
-                                "while x-bit is missing.");
- 
-     ret = chmod(user_dir, 0700);
-     fail_unless(ret == EOK, "chmod failed.");
--    ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid);
-+    ret = sss_krb5_precreate_ccache(filename, uid, gid);
-     fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed.");
- 
-     check_dir(dn3, uid, gid, 0700);
-@@ -175,7 +175,7 @@ START_TEST(test_private_ccache_dir_in_wrong_user_dir)
-     filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname);
-     fail_unless(filename != NULL, "talloc_asprintf failed.");
- 
--    ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345);
-+    ret = sss_krb5_precreate_ccache(filename, 12345, 12345);
-     fail_unless(ret == EINVAL, "Creating private ccache dir in wrong user "
-                                "dir does not failed with EINVAL.");
- 
-@@ -185,16 +185,14 @@ END_TEST
- 
- START_TEST(test_illegal_patterns)
- {
--    int ret;
-     char *cwd;
-     char *dirname;
-     char *filename;
--    uid_t uid = getuid();
--    gid_t gid = getgid();
-     pcre *illegal_re;
-     const char *errstr;
-     int errval;
-     int errpos;
-+    char *result = NULL;
- 
-     illegal_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0,
-                                &errval, &errstr, &errpos, NULL);
-@@ -209,33 +207,28 @@ START_TEST(test_illegal_patterns)
-     free(cwd);
-     fail_unless(dirname != NULL, "talloc_asprintf failed.");
- 
--
--    filename = talloc_asprintf(tmp_ctx, "abc/./ccfile");
--    fail_unless(filename != NULL, "talloc_asprintf failed.");
--    ret = create_ccache_dir(filename, illegal_re, uid, gid);
--    fail_unless(ret == EINVAL, "create_ccache_dir allowed relative path [%s].",
--                               filename);
-+    result = expand_ccname_template(tmp_ctx, kr, "abc/./ccfile", illegal_re, true, true);
-+    fail_unless(result == NULL, "expand_ccname_template allowed relative path\n");
- 
-     filename = talloc_asprintf(tmp_ctx, "%s/abc/./ccfile", dirname);
-     fail_unless(filename != NULL, "talloc_asprintf failed.");
--    ret = create_ccache_dir(filename, illegal_re, uid, gid);
--    fail_unless(ret == EINVAL, "create_ccache_dir allowed "
--                               "illegal pattern '/./' in filename [%s].",
--                               filename);
-+    result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
-+    fail_unless(result == NULL, "expand_ccname_template allowed "
-+                                "illegal pattern '/./'\n");
- 
-     filename = talloc_asprintf(tmp_ctx, "%s/abc/../ccfile", dirname);
-     fail_unless(filename != NULL, "talloc_asprintf failed.");
--    ret = create_ccache_dir(filename, illegal_re, uid, gid);
--    fail_unless(ret == EINVAL, "create_ccache_dir allowed "
--                               "illegal pattern '/../' in filename [%s].",
--                               filename);
-+    result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
-+    fail_unless(result == NULL, "expand_ccname_template allowed "
-+                                "illegal pattern '/../' in filename [%s].",
-+                                filename);
- 
-     filename = talloc_asprintf(tmp_ctx, "%s/abc//ccfile", dirname);
-     fail_unless(filename != NULL, "talloc_asprintf failed.");
--    ret = create_ccache_dir(filename, illegal_re, uid, gid);
--    fail_unless(ret == EINVAL, "create_ccache_dir allowed "
--                               "illegal pattern '//' in filename [%s].",
--                               filename);
-+    result = expand_ccname_template(tmp_ctx, kr, filename, illegal_re, true, true);
-+    fail_unless(result == NULL, "expand_ccname_template allowed "
-+                                "illegal pattern '//' in filename [%s].",
-+                                filename);
- 
-     pcre_free(illegal_re);
- }
-@@ -248,17 +241,7 @@ START_TEST(test_cc_dir_create)
-     char *cwd;
-     uid_t uid = getuid();
-     gid_t gid = getgid();
--    pcre *illegal_re;
-     errno_t ret;
--    const char *errstr;
--    int errval;
--    int errpos;
--
--    illegal_re = pcre_compile2(ILLEGAL_PATH_PATTERN, 0,
--                               &errval, &errstr, &errpos, NULL);
--    fail_unless(illegal_re != NULL, "Invalid Regular Expression pattern at "
--                                    " position %d. (Error: %d [%s])\n",
--                                    errpos, errval, errstr);
- 
-     cwd = getcwd(NULL, 0);
-     fail_unless(cwd != NULL, "getcwd failed.");
-@@ -269,7 +252,7 @@ START_TEST(test_cc_dir_create)
-     residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir");
-     fail_unless(residual != NULL, "talloc_asprintf failed.");
- 
--    ret = sss_krb5_precreate_ccache(residual, illegal_re, uid, gid);
-+    ret = sss_krb5_precreate_ccache(residual, uid, gid);
-     fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
-     ret = rmdir(dirname);
-     if (ret < 0) ret = errno;
-@@ -282,14 +265,13 @@ START_TEST(test_cc_dir_create)
-     residual = talloc_asprintf(tmp_ctx, "DIR:%s/%s", dirname, "ccdir/");
-     fail_unless(residual != NULL, "talloc_asprintf failed.");
- 
--    ret = sss_krb5_precreate_ccache(residual, illegal_re, uid, gid);
-+    ret = sss_krb5_precreate_ccache(residual, uid, gid);
-     fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed\n");
-     ret = rmdir(dirname);
-     if (ret < 0) ret = errno;
-     fail_unless(ret == 0, "Cannot remove %s: %s\n", dirname, strerror(ret));
-     talloc_free(residual);
-     free(cwd);
--    pcre_free(illegal_re);
- }
- END_TEST
- 
-@@ -356,7 +338,7 @@ static void do_test(const char *file_template, const char *dir_template,
-     ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, dir_template);
-     fail_unless(ret == EOK, "Failed to set Ccache dir");
- 
--    result = expand_ccname_template(tmp_ctx, kr, file_template, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
- 
-     fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
-     fail_unless(strcmp(result, expected) == 0,
-@@ -391,14 +373,14 @@ START_TEST(test_case_sensitive)
-     ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, CCACHE_DIR);
-     fail_unless(ret == EOK, "Failed to set Ccache dir");
- 
--    result = expand_ccname_template(tmp_ctx, kr, file_template, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
- 
-     fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
-     fail_unless(strcmp(result, expected_cs) == 0,
-                 "Expansion failed, result [%s], expected [%s].",
-                 result, expected_cs);
- 
--    result = expand_ccname_template(tmp_ctx, kr, file_template, true, false);
-+    result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, false);
- 
-     fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
-     fail_unless(strcmp(result, expected_ci) == 0,
-@@ -445,7 +427,7 @@ START_TEST(test_ccache_dir)
-     ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%d");
-     fail_unless(ret == EOK, "Failed to set Ccache dir");
- 
--    result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, NULL, true, true);
- 
-     fail_unless(result == NULL, "Using %%d in ccache dir should fail.");
- }
-@@ -461,7 +443,7 @@ START_TEST(test_pid)
-     ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%P");
-     fail_unless(ret == EOK, "Failed to set Ccache dir");
- 
--    result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, "%d/"FILENAME, NULL, true, true);
- 
-     fail_unless(result == NULL, "Using %%P in ccache dir should fail.");
- }
-@@ -480,7 +462,7 @@ START_TEST(test_unknown_template)
-     char *result;
-     int ret;
- 
--    result = expand_ccname_template(tmp_ctx, kr, test_template, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
- 
-     fail_unless(result == NULL, "Unknown template [%s] should fail.",
-                 test_template);
-@@ -488,7 +470,7 @@ START_TEST(test_unknown_template)
-     ret = dp_opt_set_string(kr->krb5_ctx->opts, KRB5_CCACHEDIR, BASE"_%X");
-     fail_unless(ret == EOK, "Failed to set Ccache dir");
-     test_template = "%d/"FILENAME;
--    result = expand_ccname_template(tmp_ctx, kr, test_template, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
- 
-     fail_unless(result == NULL, "Unknown template [%s] should fail.",
-                 test_template);
-@@ -500,7 +482,7 @@ START_TEST(test_NULL)
-     char *test_template = NULL;
-     char *result;
- 
--    result = expand_ccname_template(tmp_ctx, kr, test_template, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
- 
-     fail_unless(result == NULL, "Expected NULL as a result for an empty input.",
-                 test_template);
-@@ -512,7 +494,7 @@ START_TEST(test_no_substitution)
-     const char *test_template = BASE;
-     char *result;
- 
--    result = expand_ccname_template(tmp_ctx, kr, test_template, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, test_template, NULL, true, true);
- 
-     fail_unless(result != NULL, "Cannot expand template [%s].", test_template);
-     fail_unless(strcmp(result, test_template) == 0,
-@@ -529,7 +511,7 @@ START_TEST(test_krb5_style_expansion)
- 
-     file_template = BASE"/%{uid}/%{USERID}/%{euid}/%{username}";
-     expected = BASE"/"UID"/"UID"/"UID"/"USERNAME;
--    result = expand_ccname_template(tmp_ctx, kr, file_template, true, true);
-+    result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
- 
-     fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
-     fail_unless(strcmp(result, expected) == 0,
-@@ -538,7 +520,7 @@ START_TEST(test_krb5_style_expansion)
- 
-     file_template = BASE"/%{unknown}";
-     expected = BASE"/%{unknown}";
--    result = expand_ccname_template(tmp_ctx, kr, file_template, true, false);
-+    result = expand_ccname_template(tmp_ctx, kr, file_template, NULL, true, true);
- 
-     fail_unless(result != NULL, "Cannot expand template [%s].", file_template);
-     fail_unless(strcmp(result, expected) == 0,
--- 
-1.9.3
-
diff --git a/SOURCES/0087-DYNDNS-remove-zone-command.patch b/SOURCES/0087-DYNDNS-remove-zone-command.patch
new file mode 100644
index 0000000..db57a1b
--- /dev/null
+++ b/SOURCES/0087-DYNDNS-remove-zone-command.patch
@@ -0,0 +1,213 @@
+From 17f136d85a5ce0e2a6fa71d32eb2b048853b4800 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Thu, 23 Jul 2015 05:30:34 -0400
+Subject: [PATCH 87/90] DYNDNS: remove zone command
+
+Remove zone command from message to nsupsate. This command is generally
+used to hint nsupdate. In correctly configured environment such
+information should be obtained via DNS.
+
+If DNS does not provide necessary information we give other hints.
+
+For more details see:
+https://fedorahosted.org/sssd/wiki/DesignDocs/DDNSMessagesUpdate
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2495
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 4f2a07c422fa357ef6651bca8c48b8005280fa1d)
+---
+ src/providers/ad/ad_dyndns.c     |  1 -
+ src/providers/dp_dyndns.c        | 12 +-----------
+ src/providers/dp_dyndns.h        |  2 +-
+ src/providers/ipa/ipa_dyndns.c   | 16 ----------------
+ src/providers/ldap/sdap_dyndns.c | 13 +------------
+ src/providers/ldap/sdap_dyndns.h |  1 -
+ 6 files changed, 3 insertions(+), 42 deletions(-)
+
+diff --git a/src/providers/ad/ad_dyndns.c b/src/providers/ad/ad_dyndns.c
+index aac7d8b0a170e07cba0cd150a6f19c538948d657..5f8638128b966f0981c85a44e50e3201c73d561e 100644
+--- a/src/providers/ad/ad_dyndns.c
++++ b/src/providers/ad/ad_dyndns.c
+@@ -233,7 +233,6 @@ ad_dyndns_update_send(struct ad_options *ctx)
+                                                        DP_OPT_DYNDNS_IFACE),
+                                      dp_opt_get_string(ctx->basic,
+                                                        AD_HOSTNAME),
+-                                     NULL,
+                                      dp_opt_get_string(ctx->basic,
+                                                        AD_KRB5_REALM),
+                                      state->servername,
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 3171e6909e5f92a98cd506278e6e8c3418b979fe..ae3f913ee392a6513f75aab497e7f2d784784748 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -436,7 +436,7 @@ fail:
+ 
+ errno_t
+ be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm,
+-                           const char *zone, const char *servername,
++                           const char *servername,
+                            const char *hostname, const unsigned int ttl,
+                            uint8_t remove_af, struct sss_iface_addr *addresses,
+                            char **_update_msg)
+@@ -459,16 +459,6 @@ be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm,
+         goto done;
+     }
+ 
+-    if (zone) {
+-        DEBUG(SSSDBG_FUNC_DATA,
+-              "Setting the zone explicitly to [%s].\n", zone);
+-        update_msg = talloc_asprintf_append(update_msg, "zone %s.\n", zone);
+-        if (update_msg == NULL) {
+-            ret = ENOMEM;
+-            goto done;
+-        }
+-    }
+-
+     update_msg = nsupdate_msg_add_fwd(update_msg, addresses, hostname,
+                                       ttl, remove_af);
+     if (update_msg == NULL) {
+diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h
+index 3cc8d122646590365a3fb6dafa6a0f699b620ad9..9f72331b6fd68e17e9eb91505a13fc839d3f54e1 100644
+--- a/src/providers/dp_dyndns.h
++++ b/src/providers/dp_dyndns.h
+@@ -89,7 +89,7 @@ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx,
+ 
+ errno_t
+ be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm,
+-                           const char *zone, const char *servername,
++                           const char *servername,
+                            const char *hostname, const unsigned int ttl,
+                            uint8_t remove_af, struct sss_iface_addr *addresses,
+                            char **_update_msg);
+diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c
+index 83009ff2a08cb8e4ae2b7a1e89039539b23b6d79..e7026eb275798f0ed21fb8490295b6e6d419d8ee 100644
+--- a/src/providers/ipa/ipa_dyndns.c
++++ b/src/providers/ipa/ipa_dyndns.c
+@@ -153,9 +153,7 @@ ipa_dyndns_update_send(struct ipa_options *ctx)
+     struct ipa_dyndns_update_state *state;
+     struct tevent_req *req, *subreq;
+     struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx;
+-    char *dns_zone;
+     const char *servername;
+-    int i;
+ 
+     DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n");
+ 
+@@ -175,19 +173,6 @@ ipa_dyndns_update_send(struct ipa_options *ctx)
+     }
+     state->ipa_ctx->dyndns_ctx->last_refresh = time(NULL);
+ 
+-    dns_zone = dp_opt_get_string(ctx->basic, IPA_DOMAIN);
+-    if (!dns_zone) {
+-        ret = EIO;
+-        goto done;
+-    }
+-
+-    /* The DNS zone for IPA is the lower-case
+-     * version of the IPA domain
+-     */
+-    for (i = 0; dns_zone[i] != '\0'; i++) {
+-        dns_zone[i] = tolower(dns_zone[i]);
+-    }
+-
+     if (strncmp(ctx->service->sdap->uri,
+                 "ldap://", 7) != 0) {
+         DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected format of LDAP URI.\n");
+@@ -209,7 +194,6 @@ ipa_dyndns_update_send(struct ipa_options *ctx)
+                                                        DP_OPT_DYNDNS_IFACE),
+                                      dp_opt_get_string(ctx->basic,
+                                                        IPA_HOSTNAME),
+-                                     dns_zone,
+                                      dp_opt_get_string(ctx->basic,
+                                                        IPA_KRB5_REALM),
+                                      servername,
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index 0f0e63ee2259d017c3e94afca5f3148f4fc2ce04..f0e3dd855005d00ea19cb5dc283375f58b0d2cca 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -47,7 +47,6 @@ struct sdap_dyndns_update_state {
+     struct dp_option *opts;
+ 
+     const char *hostname;
+-    const char *dns_zone;
+     const char *realm;
+     const char *servername;
+     int ttl;
+@@ -61,7 +60,6 @@ struct sdap_dyndns_update_state {
+     enum be_nsupdate_auth auth_type;
+     bool use_server_with_nsupdate;
+     char *update_msg;
+-    size_t pass_num;
+ };
+ 
+ static void sdap_dyndns_update_addrs_done(struct tevent_req *subreq);
+@@ -82,7 +80,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+                         enum be_nsupdate_auth auth_type,
+                         const char *ifname,
+                         const char *hostname,
+-                        const char *dns_zone,
+                         const char *realm,
+                         const char *servername,
+                         const int ttl,
+@@ -101,7 +98,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+     state->check_diff = check_diff;
+     state->update_ptr = dp_opt_get_bool(opts, DP_OPT_DYNDNS_UPDATE_PTR);
+     state->hostname = hostname;
+-    state->dns_zone = dns_zone;
+     state->realm = realm;
+     state->servername = servername;
+     state->use_server_with_nsupdate = false;
+@@ -110,7 +106,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+     state->ev = ev;
+     state->opts = opts;
+     state->auth_type = auth_type;
+-    state->pass_num = 0;
+ 
+     /* fallback servername is overriden by user option */
+     conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER);
+@@ -317,7 +312,6 @@ sdap_dyndns_update_step(struct tevent_req *req)
+     struct sdap_dyndns_update_state *state;
+     const char *servername;
+     struct tevent_req *subreq;
+-    const char *dns_zone = NULL;
+ 
+     state = tevent_req_data(req, struct sdap_dyndns_update_state);
+ 
+@@ -327,11 +321,7 @@ sdap_dyndns_update_step(struct tevent_req *req)
+         servername = state->servername;
+     }
+ 
+-    if (state->pass_num > 0) {
+-        dns_zone = state->dns_zone;
+-    }
+-
+-    ret = be_nsupdate_create_fwd_msg(state, state->realm, dns_zone,
++    ret = be_nsupdate_create_fwd_msg(state, state->realm,
+                                      servername, state->hostname,
+                                      state->ttl, state->remove_af,
+                                      state->addresses,
+@@ -340,7 +330,6 @@ sdap_dyndns_update_step(struct tevent_req *req)
+         DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n");
+         return ret;
+     }
+-    state->pass_num++;
+ 
+     /* Fork a child process to perform the DNS update */
+     subreq = be_nsupdate_send(state, state->ev, state->auth_type,
+diff --git a/src/providers/ldap/sdap_dyndns.h b/src/providers/ldap/sdap_dyndns.h
+index 7aaff5d2c69fbda55fff5208c97b953b970c55cc..a9481b7941be6af0f172afce5f4d54f57ef85e48 100644
+--- a/src/providers/ldap/sdap_dyndns.h
++++ b/src/providers/ldap/sdap_dyndns.h
+@@ -39,7 +39,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+                         enum be_nsupdate_auth auth_type,
+                         const char *ifname,
+                         const char *hostname,
+-                        const char *dns_zone,
+                         const char *realm,
+                         const char *servername,
+                         const int ttl,
+-- 
+2.4.3
+
diff --git a/SOURCES/0087-KRB5-Move-all-ccache-operations-to-krb5_child.c.patch b/SOURCES/0087-KRB5-Move-all-ccache-operations-to-krb5_child.c.patch
deleted file mode 100644
index da6bae6..0000000
--- a/SOURCES/0087-KRB5-Move-all-ccache-operations-to-krb5_child.c.patch
+++ /dev/null
@@ -1,889 +0,0 @@
-From 663c5a61e6ab5aeee901684b8b43176711d5554e Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sat, 18 Oct 2014 22:03:13 +0200
-Subject: [PATCH 87/92] KRB5: Move all ccache operations to krb5_child.c
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The credential cache operations must be now performed by the krb5_child
-completely, because the sssd_be process might be running as the sssd
-user who doesn't have access to the ccaches.
-
-src/providers/krb5/krb5_ccache.c is still linked against libsss_krb5
-until we fix Kerberos ticket renewal as non-root.
-
-Also includes a new error code that indicates that the back end should
-remove the old ccache attribute -- the child can't do that if it's
-running as the user.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am                             |  13 +-
- src/providers/krb5/krb5_auth.c          | 223 ++++----------------------------
- src/providers/krb5/krb5_ccache.c        |  62 ++++-----
- src/providers/krb5/krb5_ccache.h        |   5 +-
- src/providers/krb5/krb5_child.c         | 208 +++++++++++++++++++++++++++--
- src/providers/krb5/krb5_child_handler.c |  13 ++
- src/tests/krb5_child-test.c             |   3 +-
- src/util/util_errors.c                  |   1 +
- src/util/util_errors.h                  |   1 +
- 9 files changed, 281 insertions(+), 248 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 4a69ecb0cfe48e20bde958c9351c2a5ece5ffffa..5325d51e7240ae39a546e68b2a2aea202b3dfdfa 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2496,27 +2496,36 @@ libsss_ad_la_LDFLAGS = \
- 
- krb5_child_SOURCES = \
-     src/providers/krb5/krb5_child.c \
-+    src/providers/krb5/krb5_ccache.c \
-     src/providers/dp_pam_data_util.c \
-     src/util/user_info_msg.c \
-     src/util/sss_krb5.c \
-+    src/util/find_uid.c \
-     src/util/atomic_io.c \
-     src/util/authtok.c \
-     src/util/util.c \
-     src/util/signal.c \
-+    src/util/strtonum.c \
-     src/util/become_user.c \
-     src/sss_client/common.c \
-     $(NULL)
- krb5_child_CFLAGS = \
-     $(AM_CFLAGS) \
-     $(POPT_CFLAGS) \
--    $(KRB5_CFLAGS)
-+    $(KRB5_CFLAGS) \
-+    $(PCRE_CFLAGS) \
-+    $(SYSTEMD_LOGIN_CFLAGS) \
-+    $(NULL)
- krb5_child_LDADD = \
-     libsss_debug.la \
-     $(TALLOC_LIBS) \
-     $(POPT_LIBS) \
-     $(DHASH_LIBS) \
-     $(KRB5_LIBS) \
--    $(CLIENT_LIBS)
-+    $(CLIENT_LIBS) \
-+    $(PCRE_LIBS) \
-+    $(SYSTEMD_LOGIN_LIBS) \
-+    $(NULL)
- 
- ldap_child_SOURCES = \
-     src/providers/ldap/ldap_child.c \
-diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
-index 5ed561601ac80e53ee795b458c5bf0ca410951bc..e791aee1c2d83f84ba617db1d5d93948c0e4e2a1 100644
---- a/src/providers/krb5/krb5_auth.c
-+++ b/src/providers/krb5/krb5_auth.c
-@@ -41,45 +41,6 @@
- #include "providers/krb5/krb5_utils.h"
- #include "providers/krb5/krb5_ccache.h"
- 
--static errno_t
--check_old_ccache(const char *old_ccache, struct krb5child_req *kr,
--                 const char *realm, bool *active, bool *valid)
--{
--    errno_t ret;
--
--    *active = false;
--    *valid = false;
--
--    ret = sss_krb5_cc_verify_ccache(old_ccache,
--                                    kr->uid, kr->gid,
--                                    realm, kr->upn);
--    switch (ret) {
--    case ERR_NOT_FOUND:
--    case ENOENT:
--        DEBUG(SSSDBG_TRACE_FUNC,
--              "Saved ccache %s doesn't exist.\n", old_ccache);
--        return ENOENT;
--    case EINVAL:
--        /* cache found but no tgt or expired */
--    case EOK:
--        *valid = true;
--        break;
--    default:
--        DEBUG(SSSDBG_OP_FAILURE,
--              "Cannot check if saved ccache %s is valid\n",
--               old_ccache);
--        return ret;
--    }
--
--    ret = check_if_uid_is_active(kr->uid, active);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "check_if_uid_is_active failed.\n");
--        return ret;
--    }
--
--    return EOK;
--}
--
- static int krb5_mod_ccname(TALLOC_CTX *mem_ctx,
-                            struct sysdb_ctx *sysdb,
-                            struct sss_domain_info *domain,
-@@ -225,7 +186,6 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd,
-         return ENOMEM;
-     }
-     kr->is_offline = false;
--    kr->active_ccache = true;
-     kr->run_as_user = true;
-     talloc_set_destructor((TALLOC_CTX *) kr, krb5_cleanup);
- 
-@@ -276,47 +236,26 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
- }
- 
- static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
-+                                             struct ldb_message *user_msg,
-                                              struct be_ctx *be_ctx)
- {
-     const char *ccname_template;
--    errno_t ret;
- 
--    if (!kr->is_offline) {
--        kr->is_offline = be_is_offline(be_ctx);
-+    ccname_template = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_CCNAME_TMPL);
-+
-+    kr->ccname = expand_ccname_template(kr, kr, ccname_template,
-+                                        kr->krb5_ctx->illegal_path_re, true,
-+                                        be_ctx->domain->case_sensitive);
-+    if (kr->ccname == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "expand_ccname_template failed.\n");
-+        return ENOMEM;
-     }
- 
--    /* The ccache file should be (re)created if one of the following conditions
--     * is true:
--     * - it doesn't exist (kr->ccname == NULL)
--     * - the backend is online and the current ccache file is not used, i.e
--     *   the related user is currently not logged in and it is not a renewal
--     *   request
--     *   (!kr->is_offline && !kr->active_ccache && kr->pd->cmd != SSS_CMD_RENEW)
--     * - the backend is offline and the current cache file not used and
--     *   it does not contain a valid tgt
--     *   (kr->is_offline && !kr->active_ccache && !kr->valid_tgt)
--     */
--    if (kr->ccname == NULL ||
--        (kr->is_offline && !kr->active_ccache && !kr->valid_tgt) ||
--        (!kr->is_offline && !kr->active_ccache && kr->pd->cmd != SSS_CMD_RENEW)) {
--            DEBUG(SSSDBG_TRACE_ALL, "Recreating  ccache file.\n");
--            ccname_template = dp_opt_get_cstring(kr->krb5_ctx->opts,
--                                                 KRB5_CCNAME_TMPL);
--            kr->ccname = expand_ccname_template(kr, kr, ccname_template,
--                                                kr->krb5_ctx->illegal_path_re,
--                                                true,
--                                                be_ctx->domain->case_sensitive);
--            if (kr->ccname == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "expand_ccname_template failed.\n");
--                return ENOMEM;
--            }
--
--            ret = sss_krb5_precreate_ccache(kr->ccname,
--                                            kr->uid, kr->gid);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "ccache creation failed.\n");
--                return ret;
--            }
-+    kr->old_ccname = ldb_msg_find_attr_as_string(user_msg,
-+                                                 SYSDB_CCACHE_FILE, NULL);
-+    if (kr->old_ccname == NULL) {
-+        DEBUG(SSSDBG_TRACE_LIBS,
-+                "No ccache file for user [%s] found.\n", kr->pd->user);
-     }
- 
-     return EOK;
-@@ -402,7 +341,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-     struct krb5_auth_state *state;
-     struct ldb_result *res;
-     struct krb5child_req *kr = NULL;
--    const char *ccache_file = NULL;
-     const char *realm;
-     struct tevent_req *req;
-     struct tevent_req *subreq;
-@@ -588,45 +526,10 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-             goto done;
-         }
- 
--        ccache_file = ldb_msg_find_attr_as_string(res->msgs[0],
--                                                  SYSDB_CCACHE_FILE,
--                                                  NULL);
--        if (ccache_file != NULL) {
--            ret = check_old_ccache(ccache_file, kr, realm,
--                                   &kr->active_ccache,
--                                   &kr->valid_tgt);
--            if (ret == ENOENT) {
--                DEBUG(SSSDBG_FUNC_DATA,
--                      "Ignoring ccache attribute [%s], because it doesn't"
--                       "exist.\n", ccache_file);
--                ccache_file = NULL;
--            } else if (ret != EOK) {
--                DEBUG(SSSDBG_CRIT_FAILURE,
--                      "check_if_ccache_file_is_used failed.\n");
--                ccache_file = NULL;
--            }
--        } else {
--            kr->active_ccache = false;
--            kr->valid_tgt = false;
--            DEBUG(SSSDBG_CONF_SETTINGS,
--                  "No ccache file for user [%s] found.\n", pd->user);
--        }
--        DEBUG(SSSDBG_TRACE_ALL,
--              "Ccache_file is [%s] and is %s active and TGT is %s valid.\n",
--                  ccache_file ? ccache_file : "not set",
--                  kr->active_ccache ? "" : "not",
--                  kr->valid_tgt ? "" : "not");
--        if (ccache_file != NULL) {
--            kr->ccname = ccache_file;
--            kr->old_ccname = talloc_strdup(kr, ccache_file);
--            if (kr->old_ccname == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
--                ret = ENOMEM;
--                goto done;
--            }
--        } else {
--            kr->ccname = NULL;
--            kr->old_ccname = NULL;
-+        ret = krb5_auth_prepare_ccache_name(kr, res->msgs[0], state->be_ctx);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot prepare ccache names!\n");
-+            goto done;
-         }
-         break;
- 
-@@ -669,7 +572,6 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
-     struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req);
-     struct krb5_auth_state *state = tevent_req_data(req, struct krb5_auth_state);
-     struct krb5child_req *kr = state->kr;
--    char *msg;
-     int ret;
- 
-     if (!state->search_kpasswd) {
-@@ -728,45 +630,8 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
-         }
-     }
- 
--    ret = krb5_auth_prepare_ccache_name(kr, state->be_ctx);
--    if (ret) {
--        goto done;
--    }
--
--    if (kr->is_offline) {
--        DEBUG(SSSDBG_TRACE_ALL, "Preparing for offline operation.\n");
--
--        if (kr->valid_tgt || kr->active_ccache) {
--            DEBUG(SSSDBG_TRACE_ALL, "Valid TGT available or "
--                      "ccache file is already in use.\n");
--            kr->ccname = kr->old_ccname;
--            msg = talloc_asprintf(kr->pd,
--                                  "%s=%s", CCACHE_ENV_NAME, kr->ccname);
--            if (msg == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
--            } else {
--                ret = pam_add_response(kr->pd, SSS_PAM_ENV_ITEM,
--                                       strlen(msg) + 1, (uint8_t *) msg);
--                if (ret != EOK) {
--                    DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
--                }
--            }
--
--            if (dp_opt_get_bool(kr->krb5_ctx->opts,
--                                KRB5_STORE_PASSWORD_IF_OFFLINE)) {
--                krb5_auth_cache_creds(state->kr->krb5_ctx,
--                                      state->domain,
--                                      state->be_ctx->cdb,
--                                      kr->pd, kr->uid,
--                                      &state->pam_status, &state->dp_err);
--            } else {
--                state->pam_status = PAM_AUTHINFO_UNAVAIL;
--                state->dp_err = DP_ERR_OFFLINE;
--            }
--            ret = EOK;
--            goto done;
--
--        }
-+    if (!kr->is_offline) {
-+        kr->is_offline = be_is_offline(state->be_ctx);
-     }
- 
-     /* We need to keep the root privileges to read the keytab file if
-@@ -814,7 +679,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
-     char *renew_interval_str;
-     time_t renew_interval_time = 0;
-     bool use_enterprise_principal;
--    uint32_t user_info_type;
- 
-     ret = handle_child_recv(subreq, pd, &buf, &len);
-     talloc_zfree(subreq);
-@@ -974,6 +838,14 @@ static void krb5_auth_done(struct tevent_req *subreq)
-         }
-         break;
- 
-+    case ERR_CREDS_EXPIRED_CCACHE:
-+        ret = krb5_delete_ccname(state, state->sysdb, state->domain,
-+                pd->user, kr->old_ccname);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "krb5_delete_ccname failed.\n");
-+        }
-+        /* FALLTHROUGH */
-+
-     case ERR_CREDS_EXPIRED:
-         /* If the password is expired we can safely remove the ccache from the
-          * cache and disk if it is not actively used anymore. This will allow
-@@ -981,14 +853,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
-          * used. */
-         if (pd->cmd == SSS_PAM_AUTHENTICATE && !kr->active_ccache) {
-             if (kr->old_ccname != NULL) {
--                ret = safe_remove_old_ccache_file(kr->old_ccname, NULL,
--                                                  kr->uid, kr->gid);
--                if (ret != EOK) {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "Failed to remove old ccache file [%s], "
--                              "please remove it manually.\n", kr->old_ccname);
--                }
--
-                 ret = krb5_delete_ccname(state, state->sysdb, state->domain,
-                                          pd->user, kr->old_ccname);
-                 if (ret != EOK) {
-@@ -1062,37 +926,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
-         goto done;
-     }
- 
--    ret = sss_krb5_check_ccache_princ(kr->uid, kr->gid, kr->ccname, kr->upn);
--    if (ret) {
--        if (res->otp == true && pd->cmd == SSS_PAM_CHAUTHTOK) {
--            DEBUG(SSSDBG_IMPORTANT_INFO,
--                  "Password change succeeded but currently "
--                  "post-chpass kinit is not implemented\n");
--
--            user_info_type = SSS_PAM_USER_INFO_OTP_CHPASS;
--            ret = pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
--                                   (const uint8_t *) &user_info_type);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
--                /* Not fatal */
--            }
--        } else {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "No ccache for %s in %s?\n", kr->upn, kr->ccname);
--            goto done;
--        }
--    }
--
--    if (kr->old_ccname) {
--        ret = safe_remove_old_ccache_file(kr->old_ccname, kr->ccname,
--                                          kr->uid, kr->gid);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "Failed to remove old ccache file [%s], "
--                   "please remove it manually.\n", kr->old_ccname);
--        }
--    }
--
-     ret = krb5_save_ccname(state, state->sysdb, state->domain,
-                            pd->user, kr->ccname);
-     if (ret) {
-diff --git a/src/providers/krb5/krb5_ccache.c b/src/providers/krb5/krb5_ccache.c
-index c0f5b7b8ced3fd2d6d8cbbf4e3339caba60888ff..7aa36b744ddcf7e46edcc26405a5101645b8b546 100644
---- a/src/providers/krb5/krb5_ccache.c
-+++ b/src/providers/krb5/krb5_ccache.c
-@@ -374,49 +374,32 @@ done:
- 
- /* This function is called only as a way to validate that we have the
-  * right cache */
--errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
--                                    const char *ccname, const char *principal)
-+errno_t sss_krb5_check_ccache_princ(krb5_context kctx,
-+                                    const char *ccname,
-+                                    krb5_principal user_princ)
- {
--    struct sss_krb5_ccache *cc = NULL;
-+    krb5_ccache kcc = NULL;
-     krb5_principal ccprinc = NULL;
--    krb5_principal kprinc = NULL;
-     krb5_error_code kerr;
-     const char *cc_type;
--    TALLOC_CTX *tmp_ctx;
-     errno_t ret;
- 
--    tmp_ctx = talloc_new(NULL);
--    if (tmp_ctx == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
--        return ENOMEM;
--    }
--
--    ret = sss_open_ccache_as_user(tmp_ctx, ccname, uid, gid, &cc);
--    if (ret) {
--        goto done;
--    }
--
--    cc_type = krb5_cc_get_type(cc->context, cc->ccache);
--
--    DEBUG(SSSDBG_TRACE_INTERNAL,
--          "Searching for [%s] in cache of type [%s]\n", principal, cc_type);
--
--    kerr = krb5_parse_name(cc->context, principal, &kprinc);
--    if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_parse_name failed.\n");
-+    kerr = krb5_cc_resolve(kctx, ccname, &kcc);
-+    if (kerr) {
-         ret = ERR_INTERNAL;
-         goto done;
-     }
- 
--    kerr = krb5_cc_get_principal(cc->context, cc->ccache, &ccprinc);
-+    cc_type = krb5_cc_get_type(kctx, kcc);
-+
-+    kerr = krb5_cc_get_principal(kctx, kcc, &ccprinc);
-     if (kerr != 0) {
--        KRB5_DEBUG(SSSDBG_OP_FAILURE, cc->context, kerr);
-+        KRB5_DEBUG(SSSDBG_OP_FAILURE, kctx, kerr);
-         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_get_principal failed.\n");
-     }
- 
-     if (ccprinc) {
--        if (krb5_principal_compare(cc->context, kprinc, ccprinc) == TRUE) {
-+        if (krb5_principal_compare(kctx, user_princ, ccprinc) == TRUE) {
-             /* found in the primary ccache */
-             ret = EOK;
-             goto done;
-@@ -425,23 +408,23 @@ errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
- 
- #ifdef HAVE_KRB5_CC_COLLECTION
- 
--    if (krb5_cc_support_switch(cc->context, cc_type)) {
-+    if (krb5_cc_support_switch(kctx, cc_type)) {
- 
--        krb5_cc_close(cc->context, cc->ccache);
--        cc->ccache = NULL;
-+        krb5_cc_close(kctx, kcc);
-+        kcc = NULL;
- 
--        kerr = krb5_cc_set_default_name(cc->context, ccname);
-+        kerr = krb5_cc_set_default_name(kctx, ccname);
-         if (kerr != 0) {
--            KRB5_DEBUG(SSSDBG_MINOR_FAILURE, cc->context, kerr);
-+            KRB5_DEBUG(SSSDBG_MINOR_FAILURE, kctx, kerr);
-             /* try to continue despite failure */
-         }
- 
--        kerr = krb5_cc_cache_match(cc->context, kprinc, &cc->ccache);
-+        kerr = krb5_cc_cache_match(kctx, user_princ, &kcc);
-         if (kerr == 0) {
-             ret = EOK;
-             goto done;
-         }
--        KRB5_DEBUG(SSSDBG_TRACE_INTERNAL, cc->context, kerr);
-+        KRB5_DEBUG(SSSDBG_TRACE_INTERNAL, kctx, kerr);
-     }
- 
- #endif /* HAVE_KRB5_CC_COLLECTION */
-@@ -449,11 +432,12 @@ errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
-     ret = ERR_NOT_FOUND;
- 
- done:
--    if (cc) {
--        krb5_free_principal(cc->context, ccprinc);
--        krb5_free_principal(cc->context, kprinc);
-+    if (ccprinc) {
-+        krb5_free_principal(kctx, ccprinc);
-+    }
-+    if (kcc) {
-+        krb5_cc_close(kctx, kcc);
-     }
--    talloc_free(tmp_ctx);
-     return ret;
- }
- 
-diff --git a/src/providers/krb5/krb5_ccache.h b/src/providers/krb5/krb5_ccache.h
-index e39f96cad6f46c4003103dce4eadf007bc0f8920..e47df3665e3f325cc56d34767b416662577cc048 100644
---- a/src/providers/krb5/krb5_ccache.h
-+++ b/src/providers/krb5/krb5_ccache.h
-@@ -39,8 +39,9 @@ errno_t sss_krb5_precreate_ccache(const char *ccname, uid_t uid, gid_t gid);
- 
- errno_t sss_krb5_cc_destroy(const char *ccname, uid_t uid, gid_t gid);
- 
--errno_t sss_krb5_check_ccache_princ(uid_t uid, gid_t gid,
--                                    const char *ccname, const char *principal);
-+errno_t sss_krb5_check_ccache_princ(krb5_context kctx,
-+                                    const char *ccname,
-+                                    krb5_principal user_princ);
- 
- errno_t sss_krb5_cc_verify_ccache(const char *ccname, uid_t uid, gid_t gid,
-                                   const char *realm, const char *principal);
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 7fa5f0c344a4afe110afa08f479f283aefce8d23..94cd34e433cf6a197860d233fbf9ca30cd3eb535 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -33,6 +33,7 @@
- #include "util/sss_krb5.h"
- #include "util/user_info_msg.h"
- #include "util/child_common.h"
-+#include "util/find_uid.h"
- #include "providers/dp_backend.h"
- #include "providers/krb5/krb5_auth.h"
- #include "providers/krb5/krb5_utils.h"
-@@ -61,6 +62,10 @@ struct krb5_req {
-     const char *upn;
-     uid_t uid;
-     gid_t gid;
-+
-+    char *old_ccname;
-+    bool old_cc_valid;
-+    bool old_cc_active;
- };
- 
- static krb5_context krb5_error_ctx;
-@@ -1021,6 +1026,24 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
-         goto done;
-     }
- 
-+    /* Successfull authentication! Check if ccache contains the
-+     * right principal...
-+     */
-+    kerr = sss_krb5_check_ccache_princ(kr->ctx, kr->ccname, kr->creds->client);
-+    if (kerr) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "No ccache for %s in %s?\n", kr->upn, kr->ccname);
-+        goto done;
-+    }
-+
-+    kerr = safe_remove_old_ccache_file(kr->old_ccname, kr->ccname,
-+                                       kr->uid, kr->gid);
-+    if (kerr != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Failed to remove old ccache file [%s], "
-+              "please remove it manually.\n", kr->old_ccname);
-+    }
-+
-     kerr = add_ticket_times_and_upn_to_response(kr);
-     if (kerr != 0) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
-@@ -1094,6 +1117,7 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim)
-     int realm_length;
-     size_t msg_len;
-     uint8_t *msg;
-+    uint32_t user_info_type;
- 
-     DEBUG(SSSDBG_TRACE_LIBS, "Password change operation\n");
- 
-@@ -1222,6 +1246,14 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim)
-     krb5_free_cred_contents(kr->ctx, kr->creds);
- 
-     if (kr->otp == true) {
-+        user_info_type = SSS_PAM_USER_INFO_OTP_CHPASS;
-+        ret = pam_add_response(kr->pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
-+                               (const uint8_t *) &user_info_type);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
-+            /* Not fatal */
-+        }
-+
-         sss_authtok_set_empty(kr->pd->newauthtok);
-         return map_krb5_error(kerr);
-     }
-@@ -1298,6 +1330,21 @@ static errno_t tgt_req_child(struct krb5_req *kr)
-     krb5_free_cred_contents(kr->ctx, kr->creds);
-     if (kerr == 0) {
-         ret = ERR_CREDS_EXPIRED;
-+
-+        /* If the password is expired we can safely remove the ccache from the
-+         * cache and disk if it is not actively used anymore. This will allow
-+         * to create a new random ccache if sshd with privilege separation is
-+         * used. */
-+        if (kr->old_cc_active == false && kr->old_ccname) {
-+            ret = safe_remove_old_ccache_file(kr->old_ccname, NULL,
-+                    kr->uid, kr->gid);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_CRIT_FAILURE,
-+                        "Failed to remove old ccache file [%s], "
-+                        "please remove it manually.\n", kr->old_ccname);
-+            }
-+            ret = ERR_CREDS_EXPIRED_CCACHE;
-+        }
-     } else {
-         ret = map_krb5_error(kerr);
-     }
-@@ -1423,12 +1470,17 @@ static errno_t create_empty_ccache(struct krb5_req *kr)
-     krb5_creds *creds = NULL;
-     krb5_error_code kerr;
- 
--    DEBUG(SSSDBG_TRACE_LIBS, "Creating empty ccache\n");
--
--    kerr = create_empty_cred(kr->ctx, kr->princ, &creds);
--    if (kerr == 0) {
--        kerr = create_ccache(kr->ccname, creds);
-+    if (kr->old_cc_valid == false) {
-+        DEBUG(SSSDBG_TRACE_LIBS, "Creating empty ccache\n");
-+        kerr = create_empty_cred(kr->ctx, kr->princ, &creds);
-+        if (kerr == 0) {
-+            kerr = create_ccache(kr->ccname, creds);
-+        }
-+    } else {
-+        DEBUG(SSSDBG_TRACE_LIBS, "Existing ccache still valid, reusing\n");
-+        kerr = 0;
-     }
-+
-     if (kerr != 0) {
-         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
-     } else {
-@@ -1529,6 +1581,17 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
- 
-         SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-         if ((p + len ) > size) return EINVAL;
-+
-+        if (len > 0) {
-+            kr->old_ccname = talloc_strndup(pd, (char *)(buf + p), len);
-+            if (kr->old_ccname == NULL) return ENOMEM;
-+            p += len;
-+        } else {
-+            DEBUG(SSSDBG_TRACE_INTERNAL, "No old ccache\n");
-+        }
-+
-+        SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-+        if ((p + len ) > size) return EINVAL;
-         kr->keytab = talloc_strndup(pd, (char *)(buf + p), len);
-         if (kr->keytab == NULL) return ENOMEM;
-         p += len;
-@@ -1538,10 +1601,14 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size,
-             return ret;
-         }
- 
--        DEBUG(SSSDBG_CONF_SETTINGS, "ccname: [%s] keytab: [%s]\n",
--              kr->ccname, kr->keytab);
-+        DEBUG(SSSDBG_CONF_SETTINGS,
-+              "ccname: [%s] old_ccname: [%s] keytab: [%s]\n",
-+              kr->ccname,
-+              kr->old_ccname ? kr->old_ccname : "not set",
-+              kr->keytab);
-     } else {
-         kr->ccname = NULL;
-+        kr->old_ccname = NULL;
-         kr->keytab = NULL;
-         sss_authtok_set_empty(pd->authtok);
-     }
-@@ -1870,6 +1937,126 @@ static errno_t check_use_fast(enum k5c_fast_opt *_fast_val)
-     return EOK;
- }
- 
-+static errno_t old_ccache_valid(struct krb5_req *kr, bool *_valid)
-+{
-+    errno_t ret;
-+    bool valid;
-+
-+    valid = false;
-+
-+    ret = sss_krb5_cc_verify_ccache(kr->old_ccname,
-+                                    kr->uid, kr->gid,
-+                                    kr->realm, kr->upn);
-+    switch (ret) {
-+        case ERR_NOT_FOUND:
-+        case ENOENT:
-+            DEBUG(SSSDBG_TRACE_FUNC,
-+                  "Saved ccache %s doesn't exist, ignoring\n", kr->old_ccname);
-+            break;
-+        case EINVAL:
-+            /* cache found but no tgt or expired */
-+        case EOK:
-+            valid = true;
-+            break;
-+        default:
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "Cannot check if saved ccache %s is valid\n",
-+                   kr->old_ccname);
-+            return ret;
-+    }
-+
-+    *_valid = valid;
-+    return EOK;
-+}
-+
-+static int k5c_check_old_ccache(struct krb5_req *kr)
-+{
-+    errno_t ret;
-+
-+    if (kr->old_ccname) {
-+        ret = old_ccache_valid(kr, &kr->old_cc_valid);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "old_ccache_valid failed.\n");
-+            return ret;
-+        }
-+
-+        ret = check_if_uid_is_active(kr->uid, &kr->old_cc_active);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "check_if_uid_is_active failed.\n");
-+            return ret;
-+        }
-+
-+        DEBUG(SSSDBG_TRACE_ALL,
-+                "Ccache_file is [%s] and is %s active and TGT is %s valid.\n",
-+                kr->old_ccname ? kr->old_ccname : "not set",
-+                kr->old_cc_active ? "" : "not",
-+                kr->old_cc_valid ? "" : "not");
-+    }
-+
-+    return EOK;
-+}
-+
-+static int k5c_precreate_ccache(struct krb5_req *kr, uint32_t offline)
-+{
-+    errno_t ret;
-+
-+    /* The ccache file should be (re)created if one of the following conditions
-+     * is true:
-+     * - it doesn't exist (kr->old_ccname == NULL)
-+     * - the backend is online and the current ccache file is not used, i.e
-+     * the related user is currently not logged in and it is not a renewal
-+     * request
-+     * (offline && !kr->old_cc_active && kr->pd->cmd != SSS_CMD_RENEW)
-+     * - the backend is offline and the current cache file not used and
-+     * it does not contain a valid tgt
-+     * (offline && !kr->old_cc_active && !kr->valid_tgt)
-+     */
-+    if (kr->old_ccname == NULL ||
-+            (offline && !kr->old_cc_active && !kr->old_cc_valid) ||
-+            (!offline && !kr->old_cc_active && kr->pd->cmd != SSS_CMD_RENEW)) {
-+        DEBUG(SSSDBG_TRACE_ALL, "Recreating ccache\n");
-+
-+        ret = sss_krb5_precreate_ccache(kr->ccname, kr->uid, kr->gid);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ccache creation failed.\n");
-+            return ret;
-+        }
-+    } else {
-+        /* We can reuse the old ccache */
-+        kr->ccname = kr->old_ccname;
-+    }
-+
-+    return EOK;
-+}
-+
-+static int k5c_ccache_setup(struct krb5_req *kr, uint32_t offline)
-+{
-+    errno_t ret;
-+
-+    if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) {
-+        return EOK;
-+    }
-+
-+    ret = k5c_check_old_ccache(kr);
-+    if (ret != 0) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Cannot check old ccache\n");
-+        return ret;
-+    }
-+
-+    /* Pre-creating the ccache must be done as root, otherwise we can't mkdir
-+     * some of the DIR: cache components. One example is /run/user/$UID because
-+     * logind doesn't create the directory until the session phase, whereas
-+     * we need the directory during the auth phase already
-+     */
-+    ret = k5c_precreate_ccache(kr, offline);
-+    if (ret != 0) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Cannot precreate ccache\n");
-+        return ret;
-+    }
-+
-+    return EOK;
-+}
-+
- static int k5c_setup(struct krb5_req *kr, uint32_t offline)
- {
-     krb5_error_code kerr;
-@@ -1881,6 +2068,11 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-         return kerr;
-     }
- 
-+    kerr = k5c_ccache_setup(kr, offline);
-+    if (kerr != EOK) {
-+        return kerr;
-+    }
-+
-     if (offline || (fast_val == K5C_FAST_NEVER && kr->validate == false)) {
-         /* If krb5_child was started as setuid, but we don't need to
-          * perform either validation or FAST, just drop privileges to
-@@ -1974,7 +2166,7 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
- 
-     kerr = set_lifetime_options(kr->options);
-     if (kerr != 0) {
--        DEBUG(SSSDBG_OP_FAILURE, ("set_lifetime_options failed.\n"));
-+        DEBUG(SSSDBG_OP_FAILURE, "set_lifetime_options failed.\n");
-         return kerr;
-     }
- 
-diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
-index 71c7f9c9f662e16b94afda0c8c0ae24666f0ba15..93961172c7a3a5d8f2a4fb320370037f188b5909 100644
---- a/src/providers/krb5/krb5_child_handler.c
-+++ b/src/providers/krb5/krb5_child_handler.c
-@@ -144,6 +144,11 @@ static errno_t create_send_buffer(struct krb5child_req *kr,
-         kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
-         buf->size += 4*sizeof(uint32_t) + strlen(kr->ccname) + strlen(keytab) +
-                      sss_authtok_get_size(kr->pd->authtok);
-+
-+        buf->size += sizeof(uint32_t);
-+        if (kr->old_ccname) {
-+            buf->size += strlen(kr->old_ccname);
-+        }
-     }
- 
-     if (kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
-@@ -182,6 +187,14 @@ static errno_t create_send_buffer(struct krb5child_req *kr,
-         SAFEALIGN_SET_UINT32(&buf->data[rp], strlen(kr->ccname), &rp);
-         safealign_memcpy(&buf->data[rp], kr->ccname, strlen(kr->ccname), &rp);
- 
-+        if (kr->old_ccname) {
-+            SAFEALIGN_SET_UINT32(&buf->data[rp], strlen(kr->old_ccname), &rp);
-+            safealign_memcpy(&buf->data[rp], kr->old_ccname,
-+                             strlen(kr->old_ccname), &rp);
-+        } else {
-+            SAFEALIGN_SET_UINT32(&buf->data[rp], 0, &rp);
-+        }
-+
-         SAFEALIGN_SET_UINT32(&buf->data[rp], strlen(keytab), &rp);
-         safealign_memcpy(&buf->data[rp], keytab, strlen(keytab), &rp);
- 
-diff --git a/src/tests/krb5_child-test.c b/src/tests/krb5_child-test.c
-index 8826a28ed5ea064317c62682003dc0e9a6df01b6..a59863b4d8aa8bdcc241c87befd672a5e5c876a3 100644
---- a/src/tests/krb5_child-test.c
-+++ b/src/tests/krb5_child-test.c
-@@ -239,8 +239,7 @@ create_dummy_req(TALLOC_CTX *mem_ctx, const char *user,
-         kr->ccname = expand_ccname_template(kr, kr,
-                                         dp_opt_get_cstring(kr->krb5_ctx->opts,
-                                                            KRB5_CCNAME_TMPL),
--                                            kr->krb5_ctx->illegal_path_re,
--                                            true, true);
-+                                            kr->krb5_ctx->illegal_path_re, true, true);
-         if (!kr->ccname) goto fail;
- 
-         DEBUG(SSSDBG_FUNC_DATA, "ccname [%s] uid [%llu] gid [%llu]\n",
-diff --git a/src/util/util_errors.c b/src/util/util_errors.c
-index d5da64622eebe7f779816c7f2090da5b9a9b13f0..c1ed0fb634c447904b63335d1cd161b7e7914a08 100644
---- a/src/util/util_errors.c
-+++ b/src/util/util_errors.c
-@@ -31,6 +31,7 @@ struct err_string error_to_str[] = {
-     { "Invalid credential type" },  /* ERR_INVALID_CRED_TYPE */
-     { "No credentials available" }, /* ERR_NO_CREDS */
-     { "Credentials are expired" }, /* ERR_CREDS_EXPIRED */
-+    { "Credentials are expired, old ccache was removed" }, /* ERR_CREDS_EXPIRED_CCACHE */
-     { "Failure setting user credentials"}, /* ERR_CREDS_INVALID */
-     { "No cached credentials available" }, /* ERR_NO_CACHED_CREDS */
-     { "Cached credentials are expired" }, /* ERR_CACHED_CREDS_EXPIRED */
-diff --git a/src/util/util_errors.h b/src/util/util_errors.h
-index 2bc576605e613d674d38b54aae1604c0b044635f..f71ede8d0fa000627a1bd994ec8bd94a632b35b2 100644
---- a/src/util/util_errors.h
-+++ b/src/util/util_errors.h
-@@ -56,6 +56,7 @@ enum sssd_errors {
-     ERR_CREDS_INVALID,
-     ERR_NO_CACHED_CREDS,
-     ERR_CACHED_CREDS_EXPIRED,
-+    ERR_CREDS_EXPIRED_CCACHE,
-     ERR_AUTH_DENIED,
-     ERR_AUTH_FAILED,
-     ERR_CHPASS_DENIED,
--- 
-1.9.3
-
diff --git a/SOURCES/0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch b/SOURCES/0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch
new file mode 100644
index 0000000..d8bae19
--- /dev/null
+++ b/SOURCES/0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch
@@ -0,0 +1,83 @@
+From 9941803301b127d9326283b7eee9ad29f462574f Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Thu, 23 Jul 2015 09:52:47 -0400
+Subject: [PATCH 88/90] DYNDNS: rename field of sdap_dyndns_update_state
+
+Rename 'use_server_with_nsupdate' to more general name 'fallback_mode'.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2495
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 76604931b11594394a05df10f8370a1b8bb3e54b)
+---
+ src/providers/ldap/sdap_dyndns.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index f0e3dd855005d00ea19cb5dc283375f58b0d2cca..2a179fd1b5e88bdf2442657ff6fa1dcc55417467 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -58,7 +58,7 @@ struct sdap_dyndns_update_state {
+     bool update_ptr;
+     bool check_diff;
+     enum be_nsupdate_auth auth_type;
+-    bool use_server_with_nsupdate;
++    bool fallback_mode;
+     char *update_msg;
+ };
+ 
+@@ -100,7 +100,7 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+     state->hostname = hostname;
+     state->realm = realm;
+     state->servername = servername;
+-    state->use_server_with_nsupdate = false;
++    state->fallback_mode = false;
+     state->ttl = ttl;
+     state->be_res = be_ctx->be_res;
+     state->ev = ev;
+@@ -316,7 +316,7 @@ sdap_dyndns_update_step(struct tevent_req *req)
+     state = tevent_req_data(req, struct sdap_dyndns_update_state);
+ 
+     servername = NULL;
+-    if (state->use_server_with_nsupdate == true &&
++    if (state->fallback_mode == true &&
+         state->servername) {
+         servername = state->servername;
+     }
+@@ -359,9 +359,9 @@ sdap_dyndns_update_done(struct tevent_req *subreq)
+     talloc_zfree(subreq);
+     if (ret != EOK) {
+         /* If the update didn't succeed, we can retry using the server name */
+-        if (state->use_server_with_nsupdate == false && state->servername &&
++        if (state->fallback_mode == false && state->servername &&
+             WIFEXITED(child_status) && WEXITSTATUS(child_status) != 0) {
+-            state->use_server_with_nsupdate = true;
++            state->fallback_mode = true;
+             DEBUG(SSSDBG_MINOR_FAILURE,
+                    "nsupdate failed, retrying with server name\n");
+             ret = sdap_dyndns_update_step(req);
+@@ -400,7 +400,7 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req)
+     state = tevent_req_data(req, struct sdap_dyndns_update_state);
+ 
+     servername = NULL;
+-    if (state->use_server_with_nsupdate == true &&
++    if (state->fallback_mode == true &&
+         state->servername) {
+         servername = state->servername;
+     }
+@@ -443,9 +443,9 @@ sdap_dyndns_update_ptr_done(struct tevent_req *subreq)
+     talloc_zfree(subreq);
+     if (ret != EOK) {
+         /* If the update didn't succeed, we can retry using the server name */
+-        if (state->use_server_with_nsupdate == false && state->servername &&
++        if (state->fallback_mode == false && state->servername &&
+             WIFEXITED(child_status) && WEXITSTATUS(child_status) != 0) {
+-            state->use_server_with_nsupdate = true;
++            state->fallback_mode = true;
+             DEBUG(SSSDBG_MINOR_FAILURE,
+                    "nsupdate failed, retrying with server name\n");
+             ret = sdap_dyndns_update_ptr_step(req);
+-- 
+2.4.3
+
diff --git a/SOURCES/0088-KRB5-Do-not-switch_creds-if-already-the-specified-us.patch b/SOURCES/0088-KRB5-Do-not-switch_creds-if-already-the-specified-us.patch
deleted file mode 100644
index 8f3e925..0000000
--- a/SOURCES/0088-KRB5-Do-not-switch_creds-if-already-the-specified-us.patch
+++ /dev/null
@@ -1,124 +0,0 @@
-From 458ab6652130ebea1f305b5d383e263a2fbbcedc Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 19 Oct 2014 12:28:13 +0200
-Subject: [PATCH 88/92] KRB5: Do not switch_creds() if already the specified
- user
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The code didn't have to handle this case previously as sssd_be was always
-running as root and switching to the ccache as the user logging in.
-
-Also handle NULL creds on restore_creds() in case there was no switch.
-One less if-condition and fewer indentation levels.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/tests/cwrap/test_become_user.c |  7 +++++++
- src/util/become_user.c             | 29 +++++++++++++++++++++--------
- 2 files changed, 28 insertions(+), 8 deletions(-)
-
-diff --git a/src/tests/cwrap/test_become_user.c b/src/tests/cwrap/test_become_user.c
-index 06d3ad425c4928e9e9bff661fbb8f7b4536b8896..7ecea5aac34bb73ca81d94ad481f05b338e65ed0 100644
---- a/src/tests/cwrap/test_become_user.c
-+++ b/src/tests/cwrap/test_become_user.c
-@@ -76,6 +76,7 @@ void test_switch_user(void **state)
-     struct passwd *sssd;
-     TALLOC_CTX *tmp_ctx;
-     struct sss_creds *saved_creds;
-+    struct sss_creds *saved_creds2 = NULL;
- 
-     check_leaks_push(global_talloc_context);
-     tmp_ctx = talloc_new(global_talloc_context);
-@@ -102,6 +103,12 @@ void test_switch_user(void **state)
-     assert_int_equal(saved_creds->uid, 0);
-     assert_int_equal(saved_creds->gid, 0);
- 
-+    /* Attempt to restore creds again */
-+    ret = switch_creds(tmp_ctx, sssd->pw_uid, sssd->pw_gid,
-+                       0, NULL, &saved_creds2);
-+    assert_int_equal(ret, EOK);
-+    assert_null(saved_creds2);
-+
-     /* restore root */
-     ret = restore_creds(saved_creds);
-     assert_int_equal(ret, EOK);
-diff --git a/src/util/become_user.c b/src/util/become_user.c
-index b5f94f993cd2c23bd3340fc502d36a530aa729fa..7dd2c752b1d0f289e7d82feee6d93e5974823f95 100644
---- a/src/util/become_user.c
-+++ b/src/util/become_user.c
-@@ -90,9 +90,14 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
-     struct sss_creds *ssc = NULL;
-     int size;
-     int ret;
-+    uid_t myuid;
-+    uid_t mygid;
- 
-     DEBUG(SSSDBG_FUNC_DATA, "Switch user to [%d][%d].\n", uid, gid);
- 
-+    myuid = geteuid();
-+    mygid = getegid();
-+
-     if (saved_creds) {
-         /* save current user credentials */
-         size = getgroups(0, NULL);
-@@ -124,8 +129,8 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
-         }
- 
-         /* we care only about effective ids */
--        ssc->uid = geteuid();
--        ssc->gid = getegid();
-+        ssc->uid = myuid;
-+        ssc->gid = mygid;
-     }
- 
-     /* if we are regaining root set euid first so that we have CAP_SETUID back,
-@@ -141,7 +146,12 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
-         }
-     }
- 
--    /* TODO: use prctl to get/set capabilities too ? */
-+    /* TODO: use libcap-ng if we need to get/set capabilities too ? */
-+
-+    if (myuid == uid && mygid == gid) {
-+        DEBUG(SSSDBG_FUNC_DATA, "Already user [%"SPRIuid"].\n", uid);
-+        return EOK;
-+    }
- 
-     /* try to setgroups first should always work if CAP_SETUID is set,
-      * otherwise it will always fail, failure is not critical though as
-@@ -177,11 +187,9 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
- 
- done:
-     if (ret) {
--        if (ssc) {
--            /* attempt to restore creds first */
--            restore_creds(ssc);
--            talloc_free(ssc);
--        }
-+        /* attempt to restore creds first */
-+        restore_creds(ssc);
-+        talloc_free(ssc);
-     } else if (saved_creds) {
-         *saved_creds = ssc;
-     }
-@@ -190,6 +198,11 @@ done:
- 
- errno_t restore_creds(struct sss_creds *saved_creds)
- {
-+    if (saved_creds == NULL) {
-+        /* In case save_creds was saved with the UID already dropped */
-+        return EOK;
-+    }
-+
-     return switch_creds(saved_creds,
-                         saved_creds->uid,
-                         saved_creds->gid,
--- 
-1.9.3
-
diff --git a/SOURCES/0089-BUILD-Use-separate-chown-to-make-changing-ownership-.patch b/SOURCES/0089-BUILD-Use-separate-chown-to-make-changing-ownership-.patch
deleted file mode 100644
index bdda2a6..0000000
--- a/SOURCES/0089-BUILD-Use-separate-chown-to-make-changing-ownership-.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-From 29d7f951999d0c8aad33fd1d0cb25a9b50db693f Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 5 Nov 2014 17:57:44 +0100
-Subject: [PATCH 89/92] BUILD: Use separate chown to make changing ownership to
- the sssd user non-fatal
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When the SSSD is built in the build system using a non-root user, the
-user doesn't exist in the build system and file ownership will be
-maintained by the downstream packaging instead.
-
-We need to make sure that setting the ownership to the sssd user is a
-separate step from creating the directories in this case in order to
-make failure to set the ownership non-fatal.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am | 35 ++++++++++++++++++-----------------
- 1 file changed, 18 insertions(+), 17 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 5325d51e7240ae39a546e68b2a2aea202b3dfdfa..6ce3a42f3833fc9041efd908c2e3de4a85193d42 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -82,11 +82,6 @@ INSTALL = @INSTALL@
- 
- SSSD_USER = @SSSD_USER@
- 
--INSTALL_USER_DIR_FLAGS = -d
--if SSSD_USER
--INSTALL_USER_DIR_FLAGS += -o $(SSSD_USER) -g $(SSSD_USER)
--endif
--
- AM_CFLAGS =
- if WANT_AUX_INFO
-     AM_CFLAGS += -aux-info $@.X
-@@ -2798,6 +2793,18 @@ src/sysv/systemd/journal.conf: src/sysv/systemd/journal.conf.in Makefile
- 	@$(MKDIR_P) src/sysv/systemd/
- 	$(replace_script)
- 
-+SSSD_USER_DIRS = \
-+    $(DESTDIR)$(dbpath) \
-+    $(DESTDIR)$(mcpath) \
-+    $(DESTDIR)$(pipepath) \
-+    $(DESTDIR)$(pipepath)/private \
-+    $(DESTDIR)$(pubconfpath) \
-+    $(DESTDIR)$(pubconfpath)/krb5.include.d \
-+    $(DESTDIR)$(gpocachepath) \
-+    $(DESTDIR)$(sssdconfdir) \
-+    $(DESTDIR)$(logpath) \
-+    $(NULL)
-+
- installsssddirs::
- 	$(MKDIR_P) \
-     $(DESTDIR)$(includedir) \
-@@ -2815,18 +2822,12 @@ installsssddirs::
-     $(DESTDIR)$(sssddatadir) \
-     $(DESTDIR)$(sudolibdir) \
-     $(DESTDIR)$(autofslibdir) \
--    $(NULL); \
--	$(INSTALL) $(INSTALL_USER_DIR_FLAGS) \
--    $(DESTDIR)$(dbpath) \
--    $(DESTDIR)$(mcpath) \
--    $(DESTDIR)$(pipepath) \
--    $(DESTDIR)$(pipepath)/private \
--    $(DESTDIR)$(pubconfpath) \
--    $(DESTDIR)$(pubconfpath)/krb5.include.d \
--    $(DESTDIR)$(gpocachepath) \
--    $(DESTDIR)$(sssdconfdir) \
--    $(DESTDIR)$(logpath) \
--    $(NULL)
-+    $(SSSD_USER_DIRS) \
-+    $(NULL);
-+if SSSD_USER
-+	-chown $(SSSD_USER):$(SSSD_USER) \
-+	$(SSSD_USER_DIRS)
-+endif
- 
- if HAVE_DOXYGEN
- docs:
--- 
-1.9.3
-
diff --git a/SOURCES/0089-DYNDNS-remove-code-duplication.patch b/SOURCES/0089-DYNDNS-remove-code-duplication.patch
new file mode 100644
index 0000000..89270d9
--- /dev/null
+++ b/SOURCES/0089-DYNDNS-remove-code-duplication.patch
@@ -0,0 +1,195 @@
+From 194e127156332dcd29a7e2aa4a142b574e8b7eac Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Fri, 24 Jul 2015 08:24:48 -0400
+Subject: [PATCH 89/90] DYNDNS: remove code duplication
+
+Move copy pasted code for converting sockaddr_storage to string into
+function.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2495
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit b42bf6c0c01db08208fb81d8295a2909d307284a)
+---
+ src/providers/dp_dyndns.c | 99 +++++++++++++++++++++--------------------------
+ src/util/util_errors.c    |  1 +
+ src/util/util_errors.h    |  1 +
+ 3 files changed, 46 insertions(+), 55 deletions(-)
+
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index ae3f913ee392a6513f75aab497e7f2d784784748..0577743cb2daca9c0e86b5beb6bf059ee7b5783f 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -58,6 +58,39 @@ void sss_iface_addr_concatenate(struct sss_iface_addr **list,
+     DLIST_CONCATENATE((*list), list2, struct sss_iface_addr*);
+ }
+ 
++static errno_t addr_to_str(struct sockaddr_storage *addr,
++                           char *dst, size_t size)
++{
++    const void *src;
++    const char *res;
++    errno_t ret;
++
++    switch(addr->ss_family) {
++    case AF_INET:
++        src = &(((struct sockaddr_in *)addr)->sin_addr);
++        break;
++    case AF_INET6:
++        src = &(((struct sockaddr_in6 *)addr)->sin6_addr);
++        break;
++    default:
++        ret = ERR_ADDR_FAMILY_NOT_SUPPORTED;
++        goto done;
++    }
++
++    res = inet_ntop(addr->ss_family, src, dst, size);
++    if (res == NULL) {
++        ret = errno;
++        DEBUG(SSSDBG_OP_FAILURE, "inet_ntop failed [%d]: %s\n",
++              ret, sss_strerror(ret));
++        goto done;
++    }
++
++    ret = EOK;
++
++done:
++    return ret;
++}
++
+ errno_t
+ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx,
+                                 struct sss_iface_addr *ifaddr_list,
+@@ -67,7 +100,6 @@ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx,
+     size_t count;
+     int ai;
+     char **straddrs;
+-    const char *ip;
+     char ip_addr[INET6_ADDRSTRLEN];
+     errno_t ret;
+ 
+@@ -83,35 +115,17 @@ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx,
+ 
+     ai = 0;
+     DLIST_FOR_EACH(ifaddr, ifaddr_list) {
+-        switch(ifaddr->addr->ss_family) {
+-        case AF_INET:
+-            errno = 0;
+-            ip = inet_ntop(ifaddr->addr->ss_family,
+-                           &(((struct sockaddr_in *)ifaddr->addr)->sin_addr),
+-                           ip_addr, INET6_ADDRSTRLEN);
+-            if (ip == NULL) {
+-                ret = errno;
+-                goto fail;
+-            }
+-            break;
+ 
+-        case AF_INET6:
+-            errno = 0;
+-            ip = inet_ntop(ifaddr->addr->ss_family,
+-                           &(((struct sockaddr_in6 *)ifaddr->addr)->sin6_addr),
+-                           ip_addr, INET6_ADDRSTRLEN);
+-            if (ip == NULL) {
+-                ret = errno;
+-                goto fail;
+-            }
+-            break;
+-
+-        default:
+-            DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n");
++        ret = addr_to_str(ifaddr->addr, ip_addr, INET6_ADDRSTRLEN);
++        if (ret == ERR_ADDR_FAMILY_NOT_SUPPORTED) {
+             continue;
++        } else if (ret != EOK) {
++            DEBUG(SSSDBG_MINOR_FAILURE, "addr_to_str failed: %d:[%s],\n",
++                  ret, sss_strerror(ret));
++            goto fail;
+         }
+ 
+-        straddrs[ai] = talloc_strdup(straddrs, ip);
++        straddrs[ai] = talloc_strdup(straddrs, ip_addr);
+         if (straddrs[ai] == NULL) {
+             ret = ENOMEM;
+             goto fail;
+@@ -237,7 +251,6 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses,
+ {
+     struct sss_iface_addr *new_record;
+     char ip_addr[INET6_ADDRSTRLEN];
+-    const char *ip;
+     errno_t ret;
+ 
+     /* Remove existing entries as needed */
+@@ -259,33 +272,10 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses,
+     }
+ 
+     DLIST_FOR_EACH(new_record, addresses) {
+-        switch(new_record->addr->ss_family) {
+-        case AF_INET:
+-            ip = inet_ntop(new_record->addr->ss_family,
+-                           &(((struct sockaddr_in *)new_record->addr)->sin_addr),
+-                           ip_addr, INET6_ADDRSTRLEN);
+-            if (ip == NULL) {
+-                ret = errno;
+-                DEBUG(SSSDBG_OP_FAILURE,
+-                      "inet_ntop failed [%d]: %s\n", ret, strerror(ret));
+-                return NULL;
+-            }
+-            break;
+-
+-        case AF_INET6:
+-            ip = inet_ntop(new_record->addr->ss_family,
+-                           &(((struct sockaddr_in6 *)new_record->addr)->sin6_addr),
+-                           ip_addr, INET6_ADDRSTRLEN);
+-            if (ip == NULL) {
+-                ret = errno;
+-                DEBUG(SSSDBG_OP_FAILURE,
+-                      "inet_ntop failed [%d]: %s\n", ret, strerror(ret));
+-                return NULL;
+-            }
+-            break;
+-
+-        default:
+-            DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n");
++        ret = addr_to_str(new_record->addr, ip_addr, INET6_ADDRSTRLEN);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_MINOR_FAILURE, "addr_to_str failed: %d:[%s],\n",
++                  ret, sss_strerror(ret));
+             return NULL;
+         }
+ 
+@@ -298,7 +288,6 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses,
+         if (update_msg == NULL) {
+             return NULL;
+         }
+-
+     }
+ 
+     return talloc_asprintf_append(update_msg, "send\n");
+diff --git a/src/util/util_errors.c b/src/util/util_errors.c
+index 0e288e3908bf03b4906bb449bd0f3445d22a303e..3041a1a28481aa8916bc1f5d972365e3c8007a4a 100644
+--- a/src/util/util_errors.c
++++ b/src/util/util_errors.c
+@@ -80,6 +80,7 @@ struct err_string error_to_str[] = {
+     { "Trusted forest root unknown" }, /* ERR_TRUST_FOREST_UNKNOWN */
+     { "p11_child failed" }, /* ERR_P11_CHILD */
+     { "Subdomain is inactive" }, /* ERR_SUBDOM_INACTIVE */
++    { "Address family not supported" }, /* ERR_ADDR_FAMILY_NOT_SUPPORTED */
+     { "ERR_LAST" } /* ERR_LAST */
+ };
+ 
+diff --git a/src/util/util_errors.h b/src/util/util_errors.h
+index da926db00121f569048ec515e95f0547ae6c4e35..660c370d600f6373d4515181cf88f62b42bcb7d7 100644
+--- a/src/util/util_errors.h
++++ b/src/util/util_errors.h
+@@ -102,6 +102,7 @@ enum sssd_errors {
+     ERR_TRUST_FOREST_UNKNOWN,
+     ERR_P11_CHILD,
+     ERR_SUBDOM_INACTIVE,
++    ERR_ADDR_FAMILY_NOT_SUPPORTED,
+     ERR_LAST            /* ALWAYS LAST */
+ };
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0090-BUILD-Make-chown-of-files-to-sssd-user-non-fatal.patch b/SOURCES/0090-BUILD-Make-chown-of-files-to-sssd-user-non-fatal.patch
deleted file mode 100644
index d6262bb..0000000
--- a/SOURCES/0090-BUILD-Make-chown-of-files-to-sssd-user-non-fatal.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From f716f3b0876edfd94be6f46f6390d7286fcf8443 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 11 Nov 2014 15:39:57 +0100
-Subject: [PATCH 90/92] BUILD: Make chown of files to sssd user non-fatal
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In build environments, we can't assume the sssd user will be created
-prior to installing the package, so we can't chown the files.
-
-RPM will own the files instead in this case.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 6ce3a42f3833fc9041efd908c2e3de4a85193d42..d58fcb9501c44ccf0d5814e1f2070cd82fa8be61 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2884,12 +2884,12 @@ else
- endif
- 
- if SSSD_USER
--	chgrp $(SSSD_USER) $(sssdlibexecdir)/ldap_child
-+	-chgrp $(SSSD_USER) $(sssdlibexecdir)/ldap_child
- 	chmod 4750 $(sssdlibexecdir)/ldap_child
--	chgrp $(SSSD_USER) $(sssdlibexecdir)/krb5_child
-+	-chgrp $(SSSD_USER) $(sssdlibexecdir)/krb5_child
- 	chmod 4750 $(sssdlibexecdir)/krb5_child
- if BUILD_SEMANAGE
--	chgrp $(SSSD_USER) $(sssdlibexecdir)/selinux_child
-+	-chgrp $(SSSD_USER) $(sssdlibexecdir)/selinux_child
- 	chmod 4750 $(sssdlibexecdir)/selinux_child
- endif
- endif
--- 
-1.9.3
-
diff --git a/SOURCES/0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch b/SOURCES/0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch
new file mode 100644
index 0000000..7883663
--- /dev/null
+++ b/SOURCES/0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch
@@ -0,0 +1,471 @@
+From 514240c29da65f8bbfc6d17e225655a5ac0f1b3c Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Sat, 12 Sep 2015 09:09:35 -0400
+Subject: [PATCH 90/90] DDNS: execute nsupdate for single update of PTR rec
+
+nsupdate fails definitely if any of update request fails when GSSAPI is used.
+
+As tmp solution nsupdate is executed for each update.
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2783
+
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit eeac17ebbe38f16deaa8599231cccfc97aaac85c)
+---
+ src/providers/dp_dyndns.c        | 128 ++++++++++++++++++++-------------------
+ src/providers/dp_dyndns.h        |  13 +++-
+ src/providers/ldap/sdap_dyndns.c | 121 ++++++++++++++++++++++++++++++++++--
+ src/tests/cmocka/test_dyndns.c   |  29 +++++++++
+ 4 files changed, 219 insertions(+), 72 deletions(-)
+
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 0577743cb2daca9c0e86b5beb6bf059ee7b5783f..50b087446f9437466de355e4d72b39a69512da03 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -52,6 +52,25 @@ struct sss_iface_addr {
+     struct sockaddr_storage *addr;
+ };
+ 
++struct sockaddr_storage*
++sss_iface_addr_get_address(struct sss_iface_addr *address)
++{
++    if (address == NULL) {
++        return NULL;
++    }
++
++    return address->addr;
++}
++
++struct sss_iface_addr *sss_iface_addr_get_next(struct sss_iface_addr *address)
++{
++    if (address) {
++        return address->next;
++    }
++
++    return NULL;
++}
++
+ void sss_iface_addr_concatenate(struct sss_iface_addr **list,
+                                 struct sss_iface_addr *list2)
+ {
+@@ -293,80 +312,63 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses,
+     return talloc_asprintf_append(update_msg, "send\n");
+ }
+ 
+-static char *
+-nsupdate_msg_add_ptr(char *update_msg, struct sss_iface_addr *addresses,
+-                     const char *hostname, int ttl, uint8_t remove_af,
+-                     struct sss_iface_addr *old_addresses)
++static uint8_t *nsupdate_convert_address(struct sockaddr_storage *add_address)
++{
++    uint8_t *addr;
++
++    switch(add_address->ss_family) {
++    case AF_INET:
++        addr = (uint8_t *) &((struct sockaddr_in *) add_address)->sin_addr;
++        break;
++    case AF_INET6:
++        addr = (uint8_t *) &((struct sockaddr_in6 *) add_address)->sin6_addr;
++        break;
++    default:
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n");
++        addr = NULL;
++        break;
++    }
++
++    return addr;
++}
++
++static char *nsupdate_msg_add_ptr(char *update_msg,
++                                  struct sockaddr_storage *address,
++                                  const char *hostname,
++                                  int ttl,
++                                  bool delete)
+ {
+-    struct sss_iface_addr *new_record, *old_record;
+     char *strptr;
+     uint8_t *addr;
+ 
+-    DLIST_FOR_EACH(old_record, old_addresses) {
+-        switch(old_record->addr->ss_family) {
+-        case AF_INET:
+-            if (!(remove_af & DYNDNS_REMOVE_A)) {
+-                continue;
+-            }
+-            addr = (uint8_t *) &((struct sockaddr_in *) old_record->addr)->sin_addr;
+-            break;
+-        case AF_INET6:
+-            if (!(remove_af & DYNDNS_REMOVE_AAAA)) {
+-                continue;
+-            }
+-            addr = (uint8_t *) &((struct sockaddr_in6 *) old_record->addr)->sin6_addr;
+-            break;
+-        default:
+-            DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n");
+-            return NULL;
+-        }
++    addr = nsupdate_convert_address(address);
++    if (addr == NULL) {
++        return NULL;
++    }
+ 
+-        strptr = resolv_get_string_ptr_address(update_msg, old_record->addr->ss_family,
+-                                               addr);
+-        if (strptr == NULL) {
+-            return NULL;
+-        }
++    strptr = resolv_get_string_ptr_address(update_msg, address->ss_family,
++                                           addr);
++    if (strptr == NULL) {
++        return NULL;
++    }
+ 
++    if (delete) {
+         /* example: update delete 38.78.16.10.in-addr.arpa. in PTR */
+         update_msg = talloc_asprintf_append(update_msg,
+                                             "update delete %s in PTR\n"
+                                             "send\n",
+                                             strptr);
+-        talloc_free(strptr);
+-        if (update_msg == NULL) {
+-            return NULL;
+-        }
+-    }
+-
+-    /* example: update add 11.78.16.10.in-addr.arpa. 85000 in PTR testvm.example.com */
+-    DLIST_FOR_EACH(new_record, addresses) {
+-        switch(new_record->addr->ss_family) {
+-        case AF_INET:
+-            addr = (uint8_t *) &((struct sockaddr_in *) new_record->addr)->sin_addr;
+-            break;
+-        case AF_INET6:
+-            addr = (uint8_t *) &((struct sockaddr_in6 *) new_record->addr)->sin6_addr;
+-            break;
+-        default:
+-            DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n");
+-            return NULL;
+-        }
+-
+-        strptr = resolv_get_string_ptr_address(update_msg, new_record->addr->ss_family,
+-                                               addr);
+-        if (strptr == NULL) {
+-            return NULL;
+-        }
+-
++    } else {
+         /* example: update delete 38.78.16.10.in-addr.arpa. in PTR */
+         update_msg = talloc_asprintf_append(update_msg,
+                                             "update add %s %d in PTR %s.\n"
+                                             "send\n",
+                                             strptr, ttl, hostname);
+-        talloc_free(strptr);
+-        if (update_msg == NULL) {
+-            return NULL;
+-        }
++    }
++
++    talloc_free(strptr);
++    if (update_msg == NULL) {
++        return NULL;
+     }
+ 
+     return update_msg;
+@@ -471,9 +473,9 @@ done:
+ errno_t
+ be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm,
+                            const char *servername, const char *hostname,
+-                           const unsigned int ttl, uint8_t remove_af,
+-                           struct sss_iface_addr *addresses,
+-                           struct sss_iface_addr *old_addresses,
++                           const unsigned int ttl,
++                           struct sockaddr_storage *address,
++                           bool delete,
+                            char **_update_msg)
+ {
+     errno_t ret;
+@@ -490,8 +492,8 @@ be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm,
+         goto done;
+     }
+ 
+-    update_msg = nsupdate_msg_add_ptr(update_msg, addresses, hostname,
+-                                      ttl, remove_af, old_addresses);
++    update_msg = nsupdate_msg_add_ptr(update_msg, address, hostname, ttl,
++                                      delete);
+     if (update_msg == NULL) {
+         ret = ENOMEM;
+         goto done;
+diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h
+index 9f72331b6fd68e17e9eb91505a13fc839d3f54e1..9f39e5d48ed46e69d4052f2139ea5f13b9e5d12c 100644
+--- a/src/providers/dp_dyndns.h
++++ b/src/providers/dp_dyndns.h
+@@ -97,9 +97,9 @@ be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm,
+ errno_t
+ be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm,
+                            const char *servername, const char *hostname,
+-                           const unsigned int ttl, uint8_t remove_af,
+-                           struct sss_iface_addr *addresses,
+-                           struct sss_iface_addr *old_addresses,
++                           const unsigned int ttl,
++                           struct sockaddr_storage *address,
++                           bool delete,
+                            char **_update_msg);
+ 
+ /* Returns:
+@@ -133,4 +133,11 @@ errno_t
+ sss_get_dualstack_addresses(TALLOC_CTX *mem_ctx,
+                             struct sockaddr *ss,
+                             struct sss_iface_addr **_iface_addrs);
++
++struct sss_iface_addr *
++sss_iface_addr_get_next(struct sss_iface_addr *address);
++
++struct sockaddr_storage*
++sss_iface_addr_get_address(struct sss_iface_addr *address);
++
+ #endif /* DP_DYNDNS_H_ */
+diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
+index 2a179fd1b5e88bdf2442657ff6fa1dcc55417467..3a52a11d1e1c86ee7b26cf6affd81f7cf1bb7d03 100644
+--- a/src/providers/ldap/sdap_dyndns.c
++++ b/src/providers/ldap/sdap_dyndns.c
+@@ -60,6 +60,8 @@ struct sdap_dyndns_update_state {
+     enum be_nsupdate_auth auth_type;
+     bool fallback_mode;
+     char *update_msg;
++    struct sss_iface_addr *ptr_addr_iter;
++    bool del_phase;
+ };
+ 
+ static void sdap_dyndns_update_addrs_done(struct tevent_req *subreq);
+@@ -70,6 +72,12 @@ static errno_t sdap_dyndns_update_step(struct tevent_req *req);
+ static errno_t sdap_dyndns_update_ptr_step(struct tevent_req *req);
+ static void sdap_dyndns_update_done(struct tevent_req *subreq);
+ static void sdap_dyndns_update_ptr_done(struct tevent_req *subreq);
++static errno_t
++sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state,
++                            struct tevent_req *req);
++static struct sss_iface_addr*
++sdap_get_address_to_delete(struct sss_iface_addr *address_it,
++                           uint8_t remove_af);
+ 
+ struct tevent_req *
+ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+@@ -106,6 +114,8 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
+     state->ev = ev;
+     state->opts = opts;
+     state->auth_type = auth_type;
++    state->ptr_addr_iter = NULL;
++    state->del_phase = true;
+ 
+     /* fallback servername is overriden by user option */
+     conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER);
+@@ -381,6 +391,16 @@ sdap_dyndns_update_done(struct tevent_req *subreq)
+     }
+ 
+     talloc_free(state->update_msg);
++
++    /* init iterator for addresses to be deleted */
++    state->ptr_addr_iter = sdap_get_address_to_delete(state->dns_addrlist,
++                                                      state->remove_af);
++    if (state->ptr_addr_iter == NULL) {
++        /* init iterator for addresses to be added */
++        state->del_phase = false;
++        state->ptr_addr_iter = state->addresses;
++    }
++
+     ret = sdap_dyndns_update_ptr_step(req);
+     if (ret != EOK) {
+         tevent_req_error(req, ret);
+@@ -389,6 +409,50 @@ sdap_dyndns_update_done(struct tevent_req *subreq)
+     /* Execution will resume in sdap_dyndns_update_ptr_done */
+ }
+ 
++
++static bool remove_addr(int address_family, uint8_t remove_af)
++{
++    bool ret = false;
++
++    switch(address_family) {
++    case AF_INET:
++        if (remove_af & DYNDNS_REMOVE_A) {
++            ret = true;
++        }
++        break;
++    case AF_INET6:
++        if (remove_af & DYNDNS_REMOVE_AAAA) {
++            ret = true;
++        }
++        break;
++    default:
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n");
++        ret = false;
++    }
++
++    return ret;
++}
++
++static struct sss_iface_addr*
++sdap_get_address_to_delete(struct sss_iface_addr *address_it,
++                           uint8_t remove_af)
++{
++    struct sockaddr_storage* address;
++
++    while (address_it != NULL) {
++        address = sss_iface_addr_get_address(address_it);
++
++        /* skip addresses that are not to be deleted */
++        if (remove_addr(address->ss_family, remove_af)) {
++            break;
++        }
++
++        address_it = sss_iface_addr_get_next(address_it);
++    }
++
++    return address_it;
++}
++
+ static errno_t
+ sdap_dyndns_update_ptr_step(struct tevent_req *req)
+ {
+@@ -396,6 +460,7 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req)
+     struct sdap_dyndns_update_state *state;
+     const char *servername;
+     struct tevent_req *subreq;
++    struct sockaddr_storage *address;
+ 
+     state = tevent_req_data(req, struct sdap_dyndns_update_state);
+ 
+@@ -405,11 +470,14 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req)
+         servername = state->servername;
+     }
+ 
+-    ret = be_nsupdate_create_ptr_msg(state, state->realm,
+-                                     servername, state->hostname,
+-                                     state->ttl, state->remove_af,
+-                                     state->addresses, state->dns_addrlist,
+-                                     &state->update_msg);
++    address = sss_iface_addr_get_address(state->ptr_addr_iter);
++    if (address == NULL) {
++        return EIO;
++    }
++
++    ret = be_nsupdate_create_ptr_msg(state, state->realm, servername,
++                                     state->hostname, state->ttl, address,
++                                     state->del_phase, &state->update_msg);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n");
+         return ret;
+@@ -454,13 +522,55 @@ sdap_dyndns_update_ptr_done(struct tevent_req *subreq)
+             }
+         }
+ 
++        ret = sdap_dyndns_next_ptr_record(state, req);
++        if (ret == EAGAIN) {
++            return;
++        }
++
+         tevent_req_error(req, ret);
+         return;
+     }
+ 
++    ret = sdap_dyndns_next_ptr_record(state, req);
++    if (ret == EAGAIN) {
++        return;
++    }
++
+     tevent_req_done(req);
+ }
+ 
++static errno_t
++sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state,
++                            struct tevent_req *req)
++{
++    errno_t ret;
++
++    if (state->del_phase) {
++        /* iterate to next address to delete */
++        state->ptr_addr_iter = sdap_get_address_to_delete(
++            sss_iface_addr_get_next(state->ptr_addr_iter), state->remove_af);
++        if (state->ptr_addr_iter == NULL) {
++            /* init iterator for addresses to be added */
++            state->del_phase = false;
++            state->ptr_addr_iter = state->addresses;
++        }
++    } else {
++        /* iterate to next address to add */
++        state->ptr_addr_iter = sss_iface_addr_get_next(state->ptr_addr_iter);
++    }
++
++    if (state->ptr_addr_iter != NULL) {
++
++        state->fallback_mode = false;
++        ret = sdap_dyndns_update_ptr_step(req);
++        if (ret == EOK) {
++            return EAGAIN;
++        }
++    }
++
++    return EOK;
++}
++
+ errno_t
+ sdap_dyndns_update_recv(struct tevent_req *req)
+ {
+@@ -755,7 +865,6 @@ fail:
+     return req;
+ }
+ 
+-
+ static void
+ sdap_dyndns_timer_conn_done(struct tevent_req *subreq)
+ {
+diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c
+index 8118e9438e89465674155c11f4523d2313f6a59c..0a2fd1227c84c7783207444e21269026d268f993 100644
+--- a/src/tests/cmocka/test_dyndns.c
++++ b/src/tests/cmocka/test_dyndns.c
+@@ -200,6 +200,32 @@ void will_return_getifaddrs(const char *ifname, const char *straddr,
+     }
+ }
+ 
++void dyndns_test_sss_iface_addr_get_misc(void **state)
++{
++    struct sss_iface_addr addrs[3];
++    struct sockaddr_storage ss[3];
++
++    addrs[0].prev = NULL;
++    addrs[0].next = &addrs[1];
++    addrs[0].addr = &ss[0];
++    addrs[1].prev = &addrs[0];
++    addrs[1].next = &addrs[2];
++    addrs[1].addr = &ss[1];
++    addrs[2].prev = &addrs[1];
++    addrs[2].next = NULL;
++    addrs[2].addr = &ss[2];
++
++    assert_ptr_equal(sss_iface_addr_get_address(NULL), NULL);
++    assert_ptr_equal(sss_iface_addr_get_address(&addrs[0]), &ss[0]);
++    assert_ptr_equal(sss_iface_addr_get_address(&addrs[1]), &ss[1]);
++    assert_ptr_equal(sss_iface_addr_get_address(&addrs[2]), &ss[2]);
++
++    assert_ptr_equal(sss_iface_addr_get_next(NULL), NULL);
++    assert_ptr_equal(sss_iface_addr_get_next(&addrs[0]), &addrs[1]);
++    assert_ptr_equal(sss_iface_addr_get_next(&addrs[1]), &addrs[2]);
++    assert_ptr_equal(sss_iface_addr_get_next(&addrs[2]), NULL);
++}
++
+ void dyndns_test_get_ifaddr(void **state)
+ {
+     errno_t ret;
+@@ -663,6 +689,9 @@ int main(int argc, const char *argv[])
+ 
+     const struct CMUnitTest tests[] = {
+         /* Utility functions unit test */
++        cmocka_unit_test_setup_teardown(dyndns_test_sss_iface_addr_get_misc,
++                                        dyndns_test_simple_setup,
++                                        dyndns_test_teardown),
+         cmocka_unit_test_setup_teardown(dyndns_test_get_ifaddr,
+                                         dyndns_test_simple_setup,
+                                         dyndns_test_teardown),
+-- 
+2.4.3
+
diff --git a/SOURCES/0091-BUILD-Touch-files-in-DESTDIR.patch b/SOURCES/0091-BUILD-Touch-files-in-DESTDIR.patch
deleted file mode 100644
index 0fb4940..0000000
--- a/SOURCES/0091-BUILD-Touch-files-in-DESTDIR.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 6686822567fba8dd25ed0bd2e235c30c60eeccf2 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 11 Nov 2014 15:59:22 +0100
-Subject: [PATCH 91/92] BUILD: Touch files in DESTDIR
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index d58fcb9501c44ccf0d5814e1f2070cd82fa8be61..156ef3c4eab1510126d2bfb47c06163885b8acfe 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2884,13 +2884,13 @@ else
- endif
- 
- if SSSD_USER
--	-chgrp $(SSSD_USER) $(sssdlibexecdir)/ldap_child
--	chmod 4750 $(sssdlibexecdir)/ldap_child
--	-chgrp $(SSSD_USER) $(sssdlibexecdir)/krb5_child
--	chmod 4750 $(sssdlibexecdir)/krb5_child
-+	-chgrp $(SSSD_USER) $(DESTDIR)$(sssdlibexecdir)/ldap_child
-+	chmod 4750 $(DESTDIR)$(sssdlibexecdir)/ldap_child
-+	-chgrp $(SSSD_USER) $(DESTDIR)$(sssdlibexecdir)/krb5_child
-+	chmod 4750 $(DESTDIR)$(sssdlibexecdir)/krb5_child
- if BUILD_SEMANAGE
--	-chgrp $(SSSD_USER) $(sssdlibexecdir)/selinux_child
--	chmod 4750 $(sssdlibexecdir)/selinux_child
-+	-chgrp $(SSSD_USER) $(DESTDIR)$(sssdlibexecdir)/selinux_child
-+	chmod 4750 $(DESTDIR)$(sssdlibexecdir)/selinux_child
- endif
- endif
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch b/SOURCES/0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch
new file mode 100644
index 0000000..a448123
--- /dev/null
+++ b/SOURCES/0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch
@@ -0,0 +1,30 @@
+From 02e61ddc6986c6ada9c702bf2dd4ef42d20425c1 Mon Sep 17 00:00:00 2001
+From: Lukas Slebodnik <lslebodn@redhat.com>
+Date: Wed, 23 Sep 2015 13:50:22 +0200
+Subject: [PATCH 91/96] DYNDNS: Return right error code in case of failure
+
+The variable will be zero if getifaddrs succeeds
+and therefore wrong error code will be returned
+in case of insufficient memory (talloc_zero failed)
+
+Reviewed-by: Pavel Reichl <preichl@redhat.com>
+(cherry picked from commit 75889713afc99ea52f4ff13b40672a12b28bdd41)
+---
+ src/providers/dp_dyndns.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c
+index 50b087446f9437466de355e4d72b39a69512da03..a5eb383bd4f6c08b846a69f0588b9c25647dc5c8 100644
+--- a/src/providers/dp_dyndns.c
++++ b/src/providers/dp_dyndns.c
+@@ -228,6 +228,7 @@ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname,
+             /* Add this address to the IP address list */
+             address = talloc_zero(mem_ctx, struct sss_iface_addr);
+             if (!address) {
++                ret = ENOMEM;
+                 goto done;
+             }
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0092-BE-Become-a-regular-user-after-initialization.patch b/SOURCES/0092-BE-Become-a-regular-user-after-initialization.patch
deleted file mode 100644
index c6df42f..0000000
--- a/SOURCES/0092-BE-Become-a-regular-user-after-initialization.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From edd6a6f65c1f1472632c263bdbd0946ff7fa8849 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 27 Oct 2014 16:14:51 +0100
-Subject: [PATCH 92/92] BE: Become a regular user after initialization
-
-Some parts of initialization (Kerberos ticket renewal, checking the
-keytab for the right principal) still require the root privileges. Drop
-privileges after initializing the back ends.
-
-Related:
-https://fedorahosted.org/sssd/ticket/2370
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/data_provider_be.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
-diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
-index 2716e4a8b38f3ff9a5b48a861ecc31f18f9fcbce..267f5f1d89cdfd0d8c69f90bc44b0f06f7e007ff 100644
---- a/src/providers/data_provider_be.c
-+++ b/src/providers/data_provider_be.c
-@@ -2886,6 +2886,19 @@ int main(int argc, const char *argv[])
-         return 3;
-     }
- 
-+    ret = chown_debug_file(NULL, uid, gid);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Cannot chown the debug files, debugging might not work!\n");
-+    }
-+
-+    ret = become_user(uid, gid);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_FUNC_DATA,
-+              "Cannot become user [%"SPRIuid"][%"SPRIgid"].\n", uid, gid);
-+        return ret;
-+    }
-+
-     DEBUG(SSSDBG_TRACE_FUNC, "Backend provider (%s) started!\n", be_domain);
- 
-     /* loop on main */
--- 
-1.9.3
-
diff --git a/SOURCES/0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch b/SOURCES/0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch
new file mode 100644
index 0000000..797fd6a
--- /dev/null
+++ b/SOURCES/0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch
@@ -0,0 +1,270 @@
+From ce69c907f04214e16c07c5a05fb8dac12b271aba Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 17 Sep 2015 17:09:24 +0200
+Subject: [PATCH 92/96] IPA: Change ipa_server_trust_add_send request to be
+ reusable from ID code
+
+Required for:
+    https://fedorahosted.org/sssd/ticket/2639
+
+Expose a request ipa_server_trusted_dom_setup_send that sets up a
+trusted domain. The setup might include actions like retrieving a keytab
+for one-way trusts.
+
+Creating the AD ID context for the trused domain is now done in the
+caller of this new request.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 1ccfd8e2e5cf4cdb6807d9809c150b7f6ba3e0eb)
+---
+ src/providers/ipa/ipa_subdomains.h        |  11 +++
+ src/providers/ipa/ipa_subdomains_server.c | 122 ++++++++++++++++--------------
+ 2 files changed, 75 insertions(+), 58 deletions(-)
+
+diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h
+index 2302c5f03e80de2ea1efad424769e777cd6dd8d5..0c13f8ed2eeda87237dfb097f532c7137095ddf1 100644
+--- a/src/providers/ipa/ipa_subdomains.h
++++ b/src/providers/ipa/ipa_subdomains.h
+@@ -52,6 +52,17 @@ struct ipa_ad_server_ctx {
+     struct ipa_ad_server_ctx *next, *prev;
+ };
+ 
++/* Can be used to set up trusted subdomain, for example fetch
++ * keytab in server mode
++ */
++struct tevent_req *
++ipa_server_trusted_dom_setup_send(TALLOC_CTX *mem_ctx,
++                                  struct tevent_context *ev,
++                                  struct be_ctx *be_ctx,
++                                  struct ipa_id_ctx *id_ctx,
++                                  struct sss_domain_info *subdom);
++errno_t ipa_server_trusted_dom_setup_recv(struct tevent_req *req);
++
+ /* To be used by ipa_subdomains.c only */
+ struct tevent_req *
+ ipa_server_create_trusts_send(TALLOC_CTX *mem_ctx,
+diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
+index dfecab1bc362b5772379bae6d51f9cef8443f225..c561118946e2ba76b2b4076e5057b1b5c0075a41 100644
+--- a/src/providers/ipa/ipa_subdomains_server.c
++++ b/src/providers/ipa/ipa_subdomains_server.c
+@@ -563,7 +563,7 @@ done:
+     return ret;
+ }
+ 
+-struct ipa_server_trust_add_state {
++struct ipa_server_trusted_dom_setup_state {
+     struct tevent_context *ev;
+     struct be_ctx *be_ctx;
+     struct ipa_id_ctx *id_ctx;
+@@ -578,22 +578,22 @@ struct ipa_server_trust_add_state {
+     const char *ccache;
+ };
+ 
+-static errno_t ipa_server_trust_add_1way(struct tevent_req *req);
++static errno_t ipa_server_trusted_dom_setup_1way(struct tevent_req *req);
+ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq);
+-static errno_t ipa_server_trust_add_step(struct tevent_req *req);
+ 
+-static struct tevent_req *
+-ipa_server_trust_add_send(TALLOC_CTX *mem_ctx,
+-                          struct tevent_context *ev,
+-                          struct be_ctx *be_ctx,
+-                          struct ipa_id_ctx *id_ctx,
+-                          struct sss_domain_info *subdom)
++struct tevent_req *
++ipa_server_trusted_dom_setup_send(TALLOC_CTX *mem_ctx,
++                                  struct tevent_context *ev,
++                                  struct be_ctx *be_ctx,
++                                  struct ipa_id_ctx *id_ctx,
++                                  struct sss_domain_info *subdom)
+ {
+     struct tevent_req *req = NULL;
+-    struct ipa_server_trust_add_state *state = NULL;
++    struct ipa_server_trusted_dom_setup_state *state = NULL;
+     errno_t ret;
+ 
+-    req = tevent_req_create(mem_ctx, &state, struct ipa_server_trust_add_state);
++    req = tevent_req_create(mem_ctx, &state,
++                            struct ipa_server_trusted_dom_setup_state);
+     if (req == NULL) {
+         return NULL;
+     }
+@@ -626,16 +626,19 @@ ipa_server_trust_add_send(TALLOC_CTX *mem_ctx,
+           ipa_trust_dir2str(state->direction));
+ 
+     if (state->direction & LSA_TRUST_DIRECTION_OUTBOUND) {
+-        /* Use system keytab */
+-        ret = ipa_server_trust_add_step(req);
++        /* Use system keytab, nothing to do here */
++        ret = EOK;
++        goto immediate;
+     } else if (state->direction & LSA_TRUST_DIRECTION_INBOUND) {
+         /* Need special keytab */
+-        ret = ipa_server_trust_add_1way(req);
++        ret = ipa_server_trusted_dom_setup_1way(req);
+         if (ret == EAGAIN) {
+             /* In progress.. */
+             return req;
+         } else if (ret == EOK) {
+-            ret = ipa_server_trust_add_step(req);
++            /* Keytab available, shortcut */
++            ret = EOK;
++            goto immediate;
+         }
+     } else {
+         /* Even unset is an error at this point */
+@@ -658,12 +661,12 @@ immediate:
+     return req;
+ }
+ 
+-static errno_t ipa_server_trust_add_1way(struct tevent_req *req)
++static errno_t ipa_server_trusted_dom_setup_1way(struct tevent_req *req)
+ {
+     errno_t ret;
+     struct tevent_req *subreq = NULL;
+-    struct ipa_server_trust_add_state *state =
+-            tevent_req_data(req, struct ipa_server_trust_add_state);
++    struct ipa_server_trusted_dom_setup_state *state =
++            tevent_req_data(req, struct ipa_server_trusted_dom_setup_state);
+     const char *hostname;
+ 
+     state->keytab = forest_keytab(state, state->forest);
+@@ -715,8 +718,8 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq)
+     errno_t ret;
+     struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                       struct tevent_req);
+-    struct ipa_server_trust_add_state *state =
+-            tevent_req_data(req, struct ipa_server_trust_add_state);
++    struct ipa_server_trusted_dom_setup_state *state =
++            tevent_req_data(req, struct ipa_server_trusted_dom_setup_state);
+ 
+     ret = ipa_getkeytab_recv(subreq, NULL);
+     talloc_zfree(subreq);
+@@ -764,46 +767,12 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq)
+     DEBUG(SSSDBG_TRACE_FUNC,
+           "Keytab %s contains the expected principals\n", state->new_keytab);
+ 
+-    ret = ipa_server_trust_add_step(req);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              "ipa_server_trust_add_step failed: %d\n", ret);
+-        tevent_req_error(req, ret);
+-        return;
+-    }
+-
+     DEBUG(SSSDBG_TRACE_FUNC,
+           "Established trust context for %s\n", state->subdom->name);
+     tevent_req_done(req);
+ }
+ 
+-static errno_t ipa_server_trust_add_step(struct tevent_req *req)
+-{
+-    struct ipa_ad_server_ctx *trust_ctx;
+-    struct ad_id_ctx *ad_id_ctx;
+-    errno_t ret;
+-    struct ipa_server_trust_add_state *state =
+-            tevent_req_data(req, struct ipa_server_trust_add_state);
+-
+-    ret = ipa_ad_ctx_new(state->be_ctx, state->id_ctx, state->subdom, &ad_id_ctx);
+-    if (ret != EOK) {
+-        DEBUG(SSSDBG_OP_FAILURE,
+-              "Cannot create ad_id_ctx for subdomain %s\n", state->subdom->name);
+-        return ret;
+-    }
+-
+-    trust_ctx = talloc(state->id_ctx->server_mode, struct ipa_ad_server_ctx);
+-    if (trust_ctx == NULL) {
+-        return ENOMEM;
+-    }
+-    trust_ctx->dom = state->subdom;
+-    trust_ctx->ad_id_ctx = ad_id_ctx;
+-
+-    DLIST_ADD(state->id_ctx->server_mode->trusts, trust_ctx);
+-    return EOK;
+-}
+-
+-static errno_t ipa_server_trust_add_recv(struct tevent_req *req)
++errno_t ipa_server_trusted_dom_setup_recv(struct tevent_req *req)
+ {
+     TEVENT_REQ_RETURN_ON_ERROR(req);
+     return EOK;
+@@ -817,6 +786,7 @@ struct ipa_server_create_trusts_state {
+ };
+ 
+ static errno_t ipa_server_create_trusts_step(struct tevent_req *req);
++static errno_t ipa_server_create_trusts_ctx(struct tevent_req *req);
+ static void ipa_server_create_trusts_done(struct tevent_req *subreq);
+ 
+ struct tevent_req *
+@@ -879,8 +849,11 @@ static errno_t ipa_server_create_trusts_step(struct tevent_req *req)
+ 
+         /* Newly detected trust */
+         if (trust_iter == NULL) {
+-            subreq = ipa_server_trust_add_send(state, state->ev, state->be_ctx,
+-                                               state->id_ctx, state->domiter);
++            subreq = ipa_server_trusted_dom_setup_send(state,
++                                                       state->ev,
++                                                       state->be_ctx,
++                                                       state->id_ctx,
++                                                       state->domiter);
+             if (subreq == NULL) {
+                 return ENOMEM;
+             }
+@@ -898,13 +871,19 @@ static void ipa_server_create_trusts_done(struct tevent_req *subreq)
+     struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                       struct tevent_req);
+ 
+-    ret = ipa_server_trust_add_recv(subreq);
++    ret = ipa_server_trusted_dom_setup_recv(subreq);
+     talloc_zfree(subreq);
+     if (ret != EOK) {
+         tevent_req_error(req, ret);
+         return;
+     }
+ 
++    ret = ipa_server_create_trusts_ctx(req);
++    if (ret != EOK) {
++        tevent_req_error(req, ret);
++        return;
++    }
++
+     ret = ipa_server_create_trusts_step(req);
+     if (ret == EOK) {
+         tevent_req_done(req);
+@@ -917,6 +896,33 @@ static void ipa_server_create_trusts_done(struct tevent_req *subreq)
+     /* Will cycle back */
+ }
+ 
++static errno_t ipa_server_create_trusts_ctx(struct tevent_req *req)
++{
++    struct ipa_ad_server_ctx *trust_ctx;
++    struct ad_id_ctx *ad_id_ctx;
++    errno_t ret;
++    struct ipa_server_create_trusts_state *state = NULL;
++
++    state = tevent_req_data(req, struct ipa_server_create_trusts_state);
++
++    ret = ipa_ad_ctx_new(state->be_ctx, state->id_ctx, state->domiter, &ad_id_ctx);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Cannot create ad_id_ctx for subdomain %s\n", state->domiter->name);
++        return ret;
++    }
++
++    trust_ctx = talloc(state->id_ctx->server_mode, struct ipa_ad_server_ctx);
++    if (trust_ctx == NULL) {
++        return ENOMEM;
++    }
++    trust_ctx->dom = state->domiter;
++    trust_ctx->ad_id_ctx = ad_id_ctx;
++
++    DLIST_ADD(state->id_ctx->server_mode->trusts, trust_ctx);
++    return EOK;
++}
++
+ errno_t ipa_server_create_trusts_recv(struct tevent_req *req)
+ {
+     TEVENT_REQ_RETURN_ON_ERROR(req);
+-- 
+2.4.3
+
diff --git a/SOURCES/0093-DEBUG-Add-new-debug-category-for-fail-over.patch b/SOURCES/0093-DEBUG-Add-new-debug-category-for-fail-over.patch
new file mode 100644
index 0000000..6e4651f
--- /dev/null
+++ b/SOURCES/0093-DEBUG-Add-new-debug-category-for-fail-over.patch
@@ -0,0 +1,129 @@
+From ac77db34a46e36f42e917f1b6d66fee39234d5f8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michal=20=C5=BDidek?= <mzidek@redhat.com>
+Date: Mon, 10 Aug 2015 18:35:16 +0200
+Subject: [PATCH 93/96] DEBUG: Add new debug category for fail over.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
+(cherry picked from commit c4fb8f55f2894de431478ccfec63f9a97e090d0e)
+---
+ src/providers/data_provider_fo.c | 30 ++++++++++++++++++++++++++----
+ src/providers/dp_backend.h       | 15 +++++++++++----
+ src/tests/debug-tests.c          |  2 +-
+ src/util/debug.c                 |  2 +-
+ src/util/util.h                  |  1 +
+ 5 files changed, 40 insertions(+), 10 deletions(-)
+
+diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
+index dab796d4647a552c2fd1c626c490278de91c2e81..41d70de065260f31dcea4c2b664a1f436823ccc1 100644
+--- a/src/providers/data_provider_fo.c
++++ b/src/providers/data_provider_fo.c
+@@ -743,13 +743,35 @@ void reset_fo(struct be_ctx *be_ctx)
+     fo_reset_services(be_ctx->be_fo->fo_ctx);
+ }
+ 
+-void be_fo_set_port_status(struct be_ctx *ctx,
+-                           const char *service_name,
+-                           struct fo_server *server,
+-                           enum port_status status)
++void _be_fo_set_port_status(struct be_ctx *ctx,
++                            const char *service_name,
++                            struct fo_server *server,
++                            enum port_status status,
++                            int line,
++                            const char *file,
++                            const char *function)
+ {
+     struct be_svc_data *be_svc;
+ 
++    /* Print debug info */
++    switch (status) {
++    case PORT_NEUTRAL:
++        DEBUG(SSSDBG_BE_FO,
++              "Setting status: PORT_NEUTRAL. Called from: %s: %s: %d\n",
++              file, function, line);
++        break;
++    case PORT_WORKING:
++        DEBUG(SSSDBG_BE_FO,
++              "Setting status: PORT_WORKING. Called from: %s: %s: %d\n",
++              file, function, line);
++        break;
++    case PORT_NOT_WORKING:
++        DEBUG(SSSDBG_BE_FO,
++              "Setting status: PORT_NOT_WORKING. Called from: %s: %s: %d\n",
++              file, function, line);
++        break;
++    }
++
+     be_svc = be_fo_find_svc_data(ctx, service_name);
+     if (be_svc == NULL) {
+         DEBUG(SSSDBG_OP_FAILURE,
+diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
+index 4d54bf547682379bcb8cf855b8fae39214495728..4bffcee9e8739302343b7813d3540eb43e966581 100644
+--- a/src/providers/dp_backend.h
++++ b/src/providers/dp_backend.h
+@@ -260,10 +260,17 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
+                                           bool first_try);
+ int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv);
+ 
+-void be_fo_set_port_status(struct be_ctx *ctx,
+-                           const char *service_name,
+-                           struct fo_server *server,
+-                           enum port_status status);
++#define be_fo_set_port_status(ctx, service_name, server, status) \
++    _be_fo_set_port_status(ctx, service_name, server, status, \
++                           __LINE__, __FILE__, __FUNCTION__)
++
++void _be_fo_set_port_status(struct be_ctx *ctx,
++                            const char *service_name,
++                            struct fo_server *server,
++                            enum port_status status,
++                            int line,
++                            const char *file,
++                            const char *function);
+ 
+ /*
+  * Instruct fail-over to try next server on the next connect attempt.
+diff --git a/src/tests/debug-tests.c b/src/tests/debug-tests.c
+index 2b91c149d79483316794240498e7fe33545dede0..067209b1dda1c445b971bcec7108d0b886d55e53 100644
+--- a/src/tests/debug-tests.c
++++ b/src/tests/debug-tests.c
+@@ -48,7 +48,7 @@ START_TEST(test_debug_convert_old_level_old_format)
+         SSSDBG_TRACE_FUNC,
+         SSSDBG_TRACE_LIBS,
+         SSSDBG_TRACE_INTERNAL,
+-        SSSDBG_TRACE_ALL
++        SSSDBG_TRACE_ALL | SSSDBG_BE_FO
+     };
+ 
+     for (old_level = 0; old_level <= 9; old_level++) {
+diff --git a/src/util/debug.c b/src/util/debug.c
+index bf83624c98769c4c53d9c25522712a9705b26ed2..69df54386101973548108c3194a1bfd111f046f0 100644
+--- a/src/util/debug.c
++++ b/src/util/debug.c
+@@ -114,7 +114,7 @@ int debug_convert_old_level(int old_level)
+         new_level |= SSSDBG_TRACE_INTERNAL;
+ 
+     if (old_level >= 9)
+-        new_level |= SSSDBG_TRACE_ALL;
++        new_level |= SSSDBG_TRACE_ALL | SSSDBG_BE_FO;
+ 
+     return new_level;
+ }
+diff --git a/src/util/util.h b/src/util/util.h
+index 4655e90a89b0ff3c457b80c943aefc4d6cf8e21f..f9fe1ca7189c6b2cdcb29f143005b20a2d969fee 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -92,6 +92,7 @@ int get_fd_from_debug_file(void);
+ #define SSSDBG_TRACE_LIBS     0x1000   /* level 7 */
+ #define SSSDBG_TRACE_INTERNAL 0x2000   /* level 8 */
+ #define SSSDBG_TRACE_ALL      0x4000   /* level 9 */
++#define SSSDBG_BE_FO          0x8000   /* level 9 */
+ #define SSSDBG_IMPORTANT_INFO SSSDBG_OP_FAILURE
+ 
+ #define SSSDBG_INVALID        -1
+-- 
+2.4.3
+
diff --git a/SOURCES/0093-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-speci.patch b/SOURCES/0093-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-speci.patch
deleted file mode 100644
index f24afe3..0000000
--- a/SOURCES/0093-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-speci.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 8d38a4b28ab7af15406b244910f369ba1aff02db Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 30 Oct 2014 15:59:17 +0100
-Subject: [PATCH 93/93] NOUPSTREAM: Default to root if sssd user is not
- specified
-
----
- src/monitor/monitor.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
-index 0dea327213a1ad04b6f69c0ffb0fb87254420796..20b4aef4ee94fd42de1585d7d7c2e01ea01845ac 100644
---- a/src/monitor/monitor.c
-+++ b/src/monitor/monitor.c
-@@ -925,7 +925,7 @@ static int get_service_user(struct mt_ctx *ctx)
- 
-     ret = confdb_get_string(ctx->cdb, ctx, CONFDB_MONITOR_CONF_ENTRY,
-                             CONFDB_MONITOR_USER_RUNAS,
--                            SSSD_USER, &user_str);
-+                            "root", &user_str);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get the user to run as\n");
-         return ret;
--- 
-1.9.3
-
diff --git a/SOURCES/0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch b/SOURCES/0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch
new file mode 100644
index 0000000..dfe3da8
--- /dev/null
+++ b/SOURCES/0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch
@@ -0,0 +1,128 @@
+From 3551dd5c2c2c75ce68ef95b91fc2420f17c92b92 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 21 Sep 2015 12:31:18 +0200
+Subject: [PATCH 94/96] FO: Add an API to reset all servers in a single service
+
+Required for:
+    https://fedorahosted.org/sssd/ticket/2639
+
+Previously, we had a function that allowed the caller to reset the
+status of all services in the global fail over context. This patch adds
+a new function that allows the caller to reset a single service instead.
+
+The main user would be IPA subdomain provider that might need to reset
+the status of an AD trusted domain on demand.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 3ac3b5746f08970c109664b95340c556057e3c6a)
+---
+ src/providers/data_provider_fo.c | 19 +++++++++++++++++++
+ src/providers/dp_backend.h       |  1 +
+ src/providers/fail_over.c        | 30 ++++++++++++++++++++----------
+ src/providers/fail_over.h        |  2 ++
+ 4 files changed, 42 insertions(+), 10 deletions(-)
+
+diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
+index 41d70de065260f31dcea4c2b664a1f436823ccc1..cd57340a0ba0ac7e474dc502bf1f1b4de0e1f778 100644
+--- a/src/providers/data_provider_fo.c
++++ b/src/providers/data_provider_fo.c
+@@ -743,6 +743,25 @@ void reset_fo(struct be_ctx *be_ctx)
+     fo_reset_services(be_ctx->be_fo->fo_ctx);
+ }
+ 
++void be_fo_reset_svc(struct be_ctx *be_ctx,
++                     const char *svc_name)
++{
++    struct fo_service *service;
++    int ret;
++
++    DEBUG(SSSDBG_TRACE_LIBS,
++          "Resetting all servers in service %s\n", svc_name);
++
++    ret = fo_get_service(be_ctx->be_fo->fo_ctx, svc_name, &service);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "Cannot retrieve service [%s]\n", svc_name);
++        return;
++    }
++
++    fo_reset_servers(service);
++}
++
+ void _be_fo_set_port_status(struct be_ctx *ctx,
+                             const char *service_name,
+                             struct fo_server *server,
+diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
+index 4bffcee9e8739302343b7813d3540eb43e966581..0ced851be8468ce21a9d283e26461fc47194557e 100644
+--- a/src/providers/dp_backend.h
++++ b/src/providers/dp_backend.h
+@@ -283,6 +283,7 @@ int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
+                                         const char *service_name);
+ 
+ void reset_fo(struct be_ctx *be_ctx);
++void be_fo_reset_svc(struct be_ctx *be_ctx, const char *svc_name);
+ 
+ errno_t be_res_init(struct be_ctx *ctx);
+ 
+diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
+index 6d835ae0efdfdf96532e8458e12238ba17910a4f..562f0b3fd7870387a80c889b245cda0d39dea509 100644
+--- a/src/providers/fail_over.c
++++ b/src/providers/fail_over.c
+@@ -1547,21 +1547,31 @@ time_t fo_get_service_retry_timeout(struct fo_service *svc)
+     return svc->ctx->opts->retry_timeout;
+ }
+ 
++void fo_reset_servers(struct fo_service *service)
++{
++    struct fo_server *server;
++
++    DLIST_FOR_EACH(server, service->server_list) {
++        if (server->srv_data != NULL) {
++            set_srv_data_status(server->srv_data, SRV_NEUTRAL);
++        } else {
++            fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED);
++        }
++
++        fo_set_port_status(server, PORT_NEUTRAL);
++    }
++}
++
++
+ void fo_reset_services(struct fo_ctx *fo_ctx)
+ {
+     struct fo_service *service;
+-    struct fo_server *server;
++
++    DEBUG(SSSDBG_TRACE_LIBS,
++          "Resetting all servers in all services\n");
+ 
+     DLIST_FOR_EACH(service, fo_ctx->service_list) {
+-        DLIST_FOR_EACH(server, service->server_list) {
+-            if (server->srv_data != NULL) {
+-                set_srv_data_status(server->srv_data, SRV_NEUTRAL);
+-            } else {
+-                fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED);
+-            }
+-
+-            fo_set_port_status(server, PORT_NEUTRAL);
+-        }
++        fo_reset_servers(service);
+     }
+ }
+ 
+diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h
+index d44ad2ff145dc6b3617e6f2ea665c7d82d923ddb..e49c6414a14eb6ca2cad333f8efbb58576811345 100644
+--- a/src/providers/fail_over.h
++++ b/src/providers/fail_over.h
+@@ -198,6 +198,8 @@ time_t fo_get_service_retry_timeout(struct fo_service *svc);
+ 
+ void fo_reset_services(struct fo_ctx *fo_ctx);
+ 
++void fo_reset_servers(struct fo_service *svc);
++
+ bool fo_svc_has_server(struct fo_service *service, struct fo_server *server);
+ 
+ /*
+-- 
+2.4.3
+
diff --git a/SOURCES/0094-MAN-page-edit-for-ldap_use_tokengroups.patch b/SOURCES/0094-MAN-page-edit-for-ldap_use_tokengroups.patch
deleted file mode 100644
index 1900f08..0000000
--- a/SOURCES/0094-MAN-page-edit-for-ldap_use_tokengroups.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From d3b1ed808665ba63bbb45cd4d9aa380916ed1b65 Mon Sep 17 00:00:00 2001
-From: Dan Lavu <dlavu@redhat.com>
-Date: Tue, 11 Nov 2014 15:46:51 -0500
-Subject: [PATCH 094/104] MAN: page edit for ldap_use_tokengroups
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2448
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- 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 d7a2a4ac9fa2497a4c347a2a7e77703e53b8a46c..5b36f69a679a1362290d8fea1f4c8fc29cc548d8 100644
---- a/src/man/sssd-ldap.5.xml
-+++ b/src/man/sssd-ldap.5.xml
-@@ -2482,7 +2482,18 @@ ldap_access_filter = (employeeType=admin)
-                     <term>ldap_group_search_base (string)</term>
-                     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/ldap_search_bases.xml" />
-                 </varlistentry>
--
-+            </variablelist>
-+            <variablelist>
-+                <note>
-+                    <para>
-+                        If the option <quote>ldap_use_tokengroups</quote> is
-+                        enabled. The searches against Active Directory will
-+                        not be restricted and return all groups memberships,
-+                        even with no gid mapping. It is recommended to disable
-+                        this feature, if group names are not being displayed
-+                        correctly.
-+                    </para>
-+                </note>
-                 <varlistentry condition="with_sudo">
-                     <term>ldap_sudo_search_base (string)</term>
-                     <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/ldap_search_bases.xml" />
--- 
-1.9.3
-
diff --git a/SOURCES/0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch b/SOURCES/0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch
new file mode 100644
index 0000000..ea5b245
--- /dev/null
+++ b/SOURCES/0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch
@@ -0,0 +1,426 @@
+From 1f861441042380362345d8ce3f9e81151664c6c0 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 21 Sep 2015 12:31:38 +0200
+Subject: [PATCH 95/96] FO: Also reset the server common data in addition to
+ SRV
+
+In a server that is expanded from a SRV query was reset, only it's
+'meta-server' status was set to neutral, but the server->common
+structure still retained its not_working status.
+
+This patch also resets the status of the common structure so that both
+the SRV query and resolving the server are retried next time.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 6ac6e8f83da241458742b7f8a3406ed66bded292)
+---
+ src/providers/fail_over.c      |   4 +-
+ src/tests/cmocka/test_fo_srv.c | 188 ++++++++++++++++++++++++++++++-----------
+ 2 files changed, 142 insertions(+), 50 deletions(-)
+
+diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
+index 562f0b3fd7870387a80c889b245cda0d39dea509..b076687ac6e571f7e27402fd11ac60183ea46951 100644
+--- a/src/providers/fail_over.c
++++ b/src/providers/fail_over.c
+@@ -1554,7 +1554,9 @@ void fo_reset_servers(struct fo_service *service)
+     DLIST_FOR_EACH(server, service->server_list) {
+         if (server->srv_data != NULL) {
+             set_srv_data_status(server->srv_data, SRV_NEUTRAL);
+-        } else {
++        }
++
++        if (server->common) {
+             fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED);
+         }
+ 
+diff --git a/src/tests/cmocka/test_fo_srv.c b/src/tests/cmocka/test_fo_srv.c
+index e5c5e4fe3b818ca2df0ab7bcd1a83719fefba191..e892bab0a261779363ea78a10038b15acefc49b7 100644
+--- a/src/tests/cmocka/test_fo_srv.c
++++ b/src/tests/cmocka/test_fo_srv.c
+@@ -194,7 +194,7 @@ errno_t resolv_get_domain_recv(TALLOC_CTX *mem_ctx,
+ }
+ 
+ /* The unit test */
+-struct test_fo_srv_ctx {
++struct test_fo_ctx {
+     struct resolv_ctx *resolv;
+     struct fo_ctx *fo_ctx;
+     struct fo_resolve_srv_dns_ctx *srv_ctx;
+@@ -208,19 +208,18 @@ int test_fo_srv_data_cmp(void *ud1, void *ud2)
+     return strcasecmp((char*) ud1, (char*) ud2);
+ }
+ 
+-static int test_fo_srv_setup(void **state)
++static int test_fo_setup(void **state)
+ {
+-    struct test_fo_srv_ctx *test_ctx;
++    struct test_fo_ctx *test_ctx;
+     errno_t ret;
+     struct fo_options fopts;
+-    bool ok;
+ 
+     assert_true(leak_check_setup());
+     global_mock_context = talloc_new(global_talloc_context);
+     assert_non_null(global_mock_context);
+ 
+     test_ctx = talloc_zero(global_mock_context,
+-                           struct test_fo_srv_ctx);
++                           struct test_fo_ctx);
+     assert_non_null(test_ctx);
+ 
+     test_ctx->ctx = create_ev_test_ctx(test_ctx);
+@@ -237,6 +236,34 @@ static int test_fo_srv_setup(void **state)
+     test_ctx->fo_ctx = fo_context_init(test_ctx, &fopts);
+     assert_non_null(test_ctx->fo_ctx);
+ 
++    ret = fo_new_service(test_ctx->fo_ctx, "ldap",
++                         test_fo_srv_data_cmp,
++                         &test_ctx->fo_svc);
++    assert_int_equal(ret, ERR_OK);
++
++    *state = test_ctx;
++    return 0;
++}
++
++static int test_fo_teardown(void **state)
++{
++    struct test_fo_ctx *test_ctx =
++        talloc_get_type(*state, struct test_fo_ctx);
++
++    talloc_free(test_ctx);
++    talloc_free(global_mock_context);
++    assert_true(leak_check_teardown());
++    return 0;
++}
++
++static int test_fo_srv_setup(void **state)
++{
++    struct test_fo_ctx *test_ctx;
++    bool ok;
++
++    test_fo_setup(state);
++    test_ctx = *state;
++
+     test_ctx->srv_ctx = fo_resolve_srv_dns_ctx_init(test_ctx, test_ctx->resolv,
+                                                     IPV4_FIRST, default_host_dbs,
+                                                     "client.sssd.com", "sssd.local");
+@@ -248,23 +275,13 @@ static int test_fo_srv_setup(void **state)
+                                   test_ctx->srv_ctx);
+     assert_true(ok);
+ 
+-    ret = fo_new_service(test_ctx->fo_ctx, "ldap",
+-                         test_fo_srv_data_cmp,
+-                         &test_ctx->fo_svc);
+-    assert_int_equal(ret, ERR_OK);
+-
+     *state = test_ctx;
+     return 0;
+ }
+ 
+ static int test_fo_srv_teardown(void **state)
+ {
+-    struct test_fo_srv_ctx *test_ctx =
+-        talloc_get_type(*state, struct test_fo_srv_ctx);
+-
+-    talloc_free(test_ctx);
+-    talloc_free(global_mock_context);
+-    assert_true(leak_check_teardown());
++    test_fo_teardown(state);
+     return 0;
+ }
+ 
+@@ -280,25 +297,30 @@ static void mock_srv_results(struct ares_srv_reply *reply_list,
+     will_return(resolv_discover_srv_recv, dns_domain);
+ }
+ 
+-static void check_server(struct fo_server *srv, int port, const char *name)
++static void check_server(struct test_fo_ctx *ctx,
++                         struct fo_server *srv,
++                         int port,
++                         const char *name)
+ {
+     assert_non_null(srv);
+-    assert_true(fo_is_srv_lookup(srv));
+     assert_int_equal(fo_get_server_port(srv), port);
+     assert_string_equal(fo_get_server_name(srv), name);
++
++
++    if (ctx->srv_ctx) {
++        assert_true(fo_is_srv_lookup(srv));
++    }
+ }
+ 
++static void test_fo_srv_step1(struct test_fo_ctx *test_ctx);
+ static void test_fo_srv_done1(struct tevent_req *req);
+ static void test_fo_srv_done2(struct tevent_req *req);
+ static void test_fo_srv_done3(struct tevent_req *req);
+ static void test_fo_srv_done4(struct tevent_req *req);
++static void test_fo_srv_done5(struct tevent_req *req);
+ 
+-void test_fo_srv(void **state)
++static void test_fo_srv_mock_dns(struct test_fo_ctx *test_ctx)
+ {
+-    errno_t ret;
+-    struct tevent_req *req;
+-    struct test_fo_srv_ctx *test_ctx =
+-        talloc_get_type(*state, struct test_fo_srv_ctx);
+     struct ares_srv_reply *s1;
+     struct ares_srv_reply *s2;
+     char *dns_domain;
+@@ -325,25 +347,41 @@ void test_fo_srv(void **state)
+     assert_non_null(dns_domain);
+ 
+     mock_srv_results(s1, TEST_SRV_TTL, dns_domain);
++}
++
++static void test_fo_srv(void **state)
++{
++    errno_t ret;
++    struct test_fo_ctx *test_ctx =
++        talloc_get_type(*state, struct test_fo_ctx);
++
++    test_fo_srv_mock_dns(test_ctx);
+ 
+     ret = fo_add_srv_server(test_ctx->fo_svc, "_ldap", "sssd.com",
+                             "sssd.local", "tcp", test_ctx);
+     assert_int_equal(ret, ERR_OK);
+ 
++    test_fo_srv_step1(test_ctx);
++
++    ret = test_ev_loop(test_ctx->ctx);
++    assert_int_equal(ret, ERR_OK);
++}
++
++static void test_fo_srv_step1(struct test_fo_ctx *test_ctx)
++{
++    struct tevent_req *req;
++
+     req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
+                                   test_ctx->resolv, test_ctx->fo_ctx,
+                                   test_ctx->fo_svc);
+     assert_non_null(req);
+     tevent_req_set_callback(req, test_fo_srv_done1, test_ctx);
+-
+-    ret = test_ev_loop(test_ctx->ctx);
+-    assert_int_equal(ret, ERR_OK);
+ }
+ 
+ static void test_fo_srv_done1(struct tevent_req *req)
+ {
+-    struct test_fo_srv_ctx *test_ctx = \
+-        tevent_req_callback_data(req, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct test_fo_ctx);
+     struct fo_server *srv;
+     errno_t ret;
+ 
+@@ -352,7 +390,7 @@ static void test_fo_srv_done1(struct tevent_req *req)
+     assert_int_equal(ret, ERR_OK);
+ 
+     /* ldap1.sssd.com has lower priority, it must always be first */
+-    check_server(srv, 389, "ldap1.sssd.com");
++    check_server(test_ctx, srv, 389, "ldap1.sssd.com");
+ 
+     /* Mark the server as working and request the service again. The same server
+      * must be returned */
+@@ -367,8 +405,8 @@ static void test_fo_srv_done1(struct tevent_req *req)
+ 
+ static void test_fo_srv_done2(struct tevent_req *req)
+ {
+-    struct test_fo_srv_ctx *test_ctx = \
+-        tevent_req_callback_data(req, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct test_fo_ctx);
+     struct fo_server *srv;
+     errno_t ret;
+ 
+@@ -377,7 +415,7 @@ static void test_fo_srv_done2(struct tevent_req *req)
+     assert_int_equal(ret, ERR_OK);
+ 
+     /* Must be ldap1 again */
+-    check_server(srv, 389, "ldap1.sssd.com");
++    check_server(test_ctx, srv, 389, "ldap1.sssd.com");
+ 
+     /* Mark it at wrong, next lookup should yield ldap2 */
+     fo_set_server_status(srv, SERVER_NOT_WORKING);
+@@ -391,8 +429,8 @@ static void test_fo_srv_done2(struct tevent_req *req)
+ 
+ static void test_fo_srv_done3(struct tevent_req *req)
+ {
+-    struct test_fo_srv_ctx *test_ctx = \
+-        tevent_req_callback_data(req, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct test_fo_ctx);
+     struct fo_server *srv;
+     errno_t ret;
+ 
+@@ -401,7 +439,7 @@ static void test_fo_srv_done3(struct tevent_req *req)
+     assert_int_equal(ret, ERR_OK);
+ 
+     /* Must be ldap2 now */
+-    check_server(srv, 389, "ldap2.sssd.com");
++    check_server(test_ctx, srv, 389, "ldap2.sssd.com");
+ 
+     /* Mark is at wrong, next lookup must reach the end of the server list */
+     fo_set_server_status(srv, SERVER_NOT_WORKING);
+@@ -415,8 +453,8 @@ static void test_fo_srv_done3(struct tevent_req *req)
+ 
+ static void test_fo_srv_done4(struct tevent_req *req)
+ {
+-    struct test_fo_srv_ctx *test_ctx = \
+-        tevent_req_callback_data(req, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct test_fo_ctx);
+     struct fo_server *srv;
+     errno_t ret;
+ 
+@@ -425,6 +463,35 @@ static void test_fo_srv_done4(struct tevent_req *req)
+     /* No servers are left..*/
+     assert_int_equal(ret, ENOENT);
+ 
++    /* reset the server status and try again.. */
++    fo_reset_servers(test_ctx->fo_svc);
++    if (test_ctx->srv_ctx) {
++        test_fo_srv_mock_dns(test_ctx);
++    }
++
++    req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev,
++                                  test_ctx->resolv, test_ctx->fo_ctx,
++                                  test_ctx->fo_svc);
++    assert_non_null(req);
++    tevent_req_set_callback(req, test_fo_srv_done5, test_ctx);
++}
++
++static void test_fo_srv_done5(struct tevent_req *req)
++{
++    struct test_fo_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct test_fo_ctx);
++    struct fo_server *srv;
++    errno_t ret;
++
++    ret = fo_resolve_service_recv(req, &srv);
++    talloc_zfree(req);
++
++    assert_int_equal(ret, ERR_OK);
++
++    /* ldap1.sssd.com has lower priority, it must always be first */
++    check_server(test_ctx, srv, 389, "ldap1.sssd.com");
++
++    /* OK, we made a full circle with the test, done */
+     test_ctx->ctx->error = ERR_OK;
+     test_ctx->ctx->done = true;
+ }
+@@ -432,20 +499,20 @@ static void test_fo_srv_done4(struct tevent_req *req)
+ /* Make sure that two queries more than TTL seconds apart resolve
+  * into two different lists
+  */
+-static void test_fo_srv_ttl_change_step(struct test_fo_srv_ctx *test_ctx);
++static void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx);
+ static void test_fo_srv_before(struct tevent_req *req);
+ static void test_fo_srv_after(struct tevent_req *req);
+ 
+ void test_fo_srv_ttl_change(void **state)
+ {
+-    struct test_fo_srv_ctx *test_ctx =
+-        talloc_get_type(*state, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx =
++        talloc_get_type(*state, struct test_fo_ctx);
+ 
+     test_ctx->ttl = TEST_SRV_SHORT_TTL;
+     test_fo_srv_ttl_change_step(test_ctx);
+ }
+ 
+-static void test_fo_srv_ttl_change_step(struct test_fo_srv_ctx *test_ctx)
++static void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx)
+ {
+     errno_t ret;
+     struct tevent_req *req;
+@@ -497,8 +564,8 @@ static void test_fo_srv_ttl_change_step(struct test_fo_srv_ctx *test_ctx)
+ 
+ static void test_fo_srv_before(struct tevent_req *req)
+ {
+-    struct test_fo_srv_ctx *test_ctx = \
+-        tevent_req_callback_data(req, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct test_fo_ctx);
+     struct fo_server *srv;
+     struct ares_srv_reply *s1;
+     struct ares_srv_reply *s2;
+@@ -511,7 +578,7 @@ static void test_fo_srv_before(struct tevent_req *req)
+ 
+     DEBUG(SSSDBG_TRACE_FUNC, "Before TTL change\n");
+ 
+-    check_server(srv, 389, "ldap1.sssd.com");
++    check_server(test_ctx, srv, 389, "ldap1.sssd.com");
+     fo_set_server_status(srv, SERVER_WORKING);
+ 
+     /* Simulate changing the DNS environment. Change the host names */
+@@ -548,8 +615,8 @@ static void test_fo_srv_before(struct tevent_req *req)
+ 
+ static void test_fo_srv_after(struct tevent_req *req)
+ {
+-    struct test_fo_srv_ctx *test_ctx = \
+-        tevent_req_callback_data(req, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx = \
++        tevent_req_callback_data(req, struct test_fo_ctx);
+     struct fo_server *srv;
+     errno_t ret;
+ 
+@@ -558,7 +625,7 @@ static void test_fo_srv_after(struct tevent_req *req)
+     assert_int_equal(ret, ERR_OK);
+ 
+     /* Must be a different server now */
+-    check_server(srv, 389, "ldap3.sssd.com");
++    check_server(test_ctx, srv, 389, "ldap3.sssd.com");
+ 
+     test_ctx->ctx->error = ERR_OK;
+     test_ctx->ctx->done = true;
+@@ -566,13 +633,33 @@ static void test_fo_srv_after(struct tevent_req *req)
+ 
+ void test_fo_srv_ttl_zero(void **state)
+ {
+-    struct test_fo_srv_ctx *test_ctx =
+-        talloc_get_type(*state, struct test_fo_srv_ctx);
++    struct test_fo_ctx *test_ctx =
++        talloc_get_type(*state, struct test_fo_ctx);
+ 
+     test_ctx->ttl = 0;
+     test_fo_srv_ttl_change_step(test_ctx);
+ }
+ 
++static void test_fo_hostlist(void **state)
++{
++    errno_t ret;
++    struct test_fo_ctx *test_ctx =
++        talloc_get_type(*state, struct test_fo_ctx);
++
++    ret = fo_add_server(test_ctx->fo_svc,
++                        "ldap1.sssd.com", 389, test_ctx, true);
++    assert_int_equal(ret, ERR_OK);
++
++    ret = fo_add_server(test_ctx->fo_svc,
++                        "ldap2.sssd.com", 389, test_ctx, true);
++    assert_int_equal(ret, ERR_OK);
++
++    test_fo_srv_step1(test_ctx);
++
++    ret = test_ev_loop(test_ctx->ctx);
++    assert_int_equal(ret, ERR_OK);
++}
++
+ int main(int argc, const char *argv[])
+ {
+     int rv;
+@@ -585,6 +672,9 @@ int main(int argc, const char *argv[])
+     };
+ 
+     const struct CMUnitTest tests[] = {
++        cmocka_unit_test_setup_teardown(test_fo_hostlist,
++                                        test_fo_setup,
++                                        test_fo_teardown),
+         cmocka_unit_test_setup_teardown(test_fo_srv,
+                                         test_fo_srv_setup,
+                                         test_fo_srv_teardown),
+-- 
+2.4.3
+
diff --git a/SOURCES/0095-sysdb-add-sysdb_search_object_by_uuid.patch b/SOURCES/0095-sysdb-add-sysdb_search_object_by_uuid.patch
deleted file mode 100644
index 01d0903..0000000
--- a/SOURCES/0095-sysdb-add-sysdb_search_object_by_uuid.patch
+++ /dev/null
@@ -1,209 +0,0 @@
-From 1f5796f2ab0a848712a7f5bc85c9f7c2f22a8a0f Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 5 Nov 2014 21:01:08 +0100
-Subject: [PATCH 095/104] sysdb: add sysdb_search_object_by_uuid()
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/db/sysdb.h          |  7 +++++
- src/db/sysdb_ops.c      | 77 +++++++++++++++++++++++++++++++++++++++++++++++++
- src/tests/sysdb-tests.c | 51 ++++++++++++++++++++++++++++++++
- 3 files changed, 135 insertions(+)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index f582f6a516e43a453741acacbe3ca6957e23fc37..7a51117f439dc54ded3433c230d2d262a4d660dc 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -185,6 +185,7 @@
- #define SYSDB_NETGR_TRIPLES_FILTER "(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_MEMBEROF"=%s))"
- 
- #define SYSDB_SID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_SID_STR"=%s))"
-+#define SYSDB_UUID_FILTER "(&(|("SYSDB_UC")("SYSDB_GC"))("SYSDB_UUID"=%s))"
- 
- #define SYSDB_HAS_ENUMERATED "has_enumerated"
- 
-@@ -1030,6 +1031,12 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
-                                    const char **attrs,
-                                    struct ldb_result **msg);
- 
-+errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx,
-+                                    struct sss_domain_info *domain,
-+                                    const char *uuid_str,
-+                                    const char **attrs,
-+                                    struct ldb_result **res);
-+
- /* === Functions related to GPOs === */
- 
- #define SYSDB_GPO_CONTAINER "cn=gpos,cn=ad,cn=custom"
-diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
-index c88ff9b4bf39c649bc7993f3ed56729b7bfde310..998046a2ca1c746b2032f430e5f9c4a7151e1dbc 100644
---- a/src/db/sysdb_ops.c
-+++ b/src/db/sysdb_ops.c
-@@ -3499,12 +3499,79 @@ done:
-     return ret;
- }
- 
-+static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx,
-+                                   struct sss_domain_info *domain,
-+                                   const char *filter_tmpl,
-+                                   const char *str,
-+                                   const char **attrs,
-+                                   struct ldb_result **_res)
-+{
-+    TALLOC_CTX *tmp_ctx;
-+    const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM,
-+                                ORIGINALAD_PREFIX SYSDB_NAME,
-+                                SYSDB_OBJECTCLASS, NULL };
-+    struct ldb_dn *basedn;
-+    int ret;
-+    struct ldb_result *res = NULL;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (!tmp_ctx) {
-+        return ENOMEM;
-+    }
-+
-+    basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, SYSDB_DOM_BASE,
-+                            domain->name);
-+    if (basedn == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
-+                     basedn, LDB_SCOPE_SUBTREE, attrs?attrs:def_attrs,
-+                     filter_tmpl, str);
-+    if (ret != EOK) {
-+        ret = sysdb_error_to_errno(ret);
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_search failed.\n");
-+        goto done;
-+    }
-+
-+    if (res->count > 1) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Search for [%s]  with filter [%s] " \
-+                                   "returned more than one object.\n",
-+                                   str, filter_tmpl);
-+        ret = EINVAL;
-+        goto done;
-+    } else if (res->count == 0) {
-+        ret = ENOENT;
-+        goto done;
-+    }
-+
-+    *_res = talloc_steal(mem_ctx, res);
-+
-+done:
-+    if (ret == ENOENT) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "No such entry.\n");
-+    } else if (ret) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
-+    }
-+
-+    talloc_zfree(tmp_ctx);
-+    return ret;
-+}
-+
- errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
-                                    struct sss_domain_info *domain,
-                                    const char *sid_str,
-                                    const char **attrs,
-                                    struct ldb_result **msg)
- {
-+/* TODO: use
-+    return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_SID_FILTER,
-+                                           sid_str, attrs, res);
-+
-+    when verified that all callers can handle ENOENT correctly. */
-+
-     TALLOC_CTX *tmp_ctx;
-     const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM,
-                                 ORIGINALAD_PREFIX SYSDB_NAME,
-@@ -3553,3 +3620,13 @@ done:
-     talloc_zfree(tmp_ctx);
-     return ret;
- }
-+
-+errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx,
-+                                    struct sss_domain_info *domain,
-+                                    const char *uuid_str,
-+                                    const char **attrs,
-+                                    struct ldb_result **res)
-+{
-+    return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_UUID_FILTER,
-+                                           uuid_str, attrs, res);
-+}
-diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
-index e01ddf4782c0a5a557f39d1adc2efd74b6234461..e9618727d4f8f4c544b28cce9d98b82000de3aad 100644
---- a/src/tests/sysdb-tests.c
-+++ b/src/tests/sysdb-tests.c
-@@ -5026,6 +5026,54 @@ START_TEST(test_sysdb_search_sid_str)
- }
- END_TEST
- 
-+START_TEST(test_sysdb_search_object_by_uuid)
-+{
-+    errno_t ret;
-+    struct sysdb_test_ctx *test_ctx;
-+    struct ldb_result *res;
-+    struct sysdb_attrs *attrs = NULL;
-+
-+    /* Setup */
-+    ret = setup_sysdb_tests(&test_ctx);
-+    fail_if(ret != EOK, "Could not set up the test");
-+
-+    attrs = sysdb_new_attrs(test_ctx);
-+    fail_unless(attrs != NULL, "sysdb_new_attrs failed");
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_UUID,
-+                                 "11111111-2222-3333-4444-555555555555");
-+    fail_unless(ret == EOK, "sysdb_attrs_add_string failed with [%d][%s].",
-+                ret, strerror(ret));
-+
-+    ret = sysdb_add_user(test_ctx->domain, "UUIDuser",
-+                         123456, 0, "UUID user", "/home/uuiduser", "/bin/bash",
-+                         NULL, attrs, 0, 0);
-+    fail_unless(ret == EOK, "sysdb_add_user failed with [%d][%s].",
-+                ret, strerror(ret));
-+
-+    ret = sysdb_search_object_by_uuid(test_ctx, test_ctx->domain,
-+                                      "11111111-2222-3333-4444-555555555556",
-+                                      NULL, &res);
-+    fail_unless(ret == ENOENT,
-+                "Unexpected return code from sysdb_search_object_by_uuid for "
-+                "missing object, expected [%d], got [%d].", ENOENT, ret);
-+
-+    ret = sysdb_search_object_by_uuid(test_ctx, test_ctx->domain,
-+                                      "11111111-2222-3333-4444-555555555555",
-+                                      NULL, &res);
-+    fail_unless(ret == EOK, "sysdb_search_object_by_uuid failed with [%d][%s].",
-+                ret, strerror(ret));
-+    fail_unless(res->count == 1, "Unexpected number of results, " \
-+                                 "expected [%u], get [%u].", 1, res->count);
-+    fail_unless(strcmp(ldb_msg_find_attr_as_string(res->msgs[0],
-+                                                   SYSDB_NAME, ""),
-+                      "UUIDuser") == 0, "Unexpected object found, " \
-+                      "expected [%s], got [%s].", "UUIDuser",
-+                      ldb_msg_find_attr_as_string(res->msgs[0],SYSDB_NAME, ""));
-+
-+    talloc_free(test_ctx);
-+}
-+END_TEST
- 
- START_TEST(test_sysdb_subdomain_create)
- {
-@@ -6090,6 +6138,9 @@ Suite *create_sysdb_suite(void)
-     /* Test SID string searches */
-     tcase_add_test(tc_sysdb, test_sysdb_search_sid_str);
- 
-+    /* Test UUID string searches */
-+    tcase_add_test(tc_sysdb, test_sysdb_search_object_by_uuid);
-+
-     /* Test canonicalizing names */
-     tcase_add_test(tc_sysdb, test_sysdb_get_real_name);
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch b/SOURCES/0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch
new file mode 100644
index 0000000..f5b2c27
--- /dev/null
+++ b/SOURCES/0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch
@@ -0,0 +1,296 @@
+From 569233a9db93bfd2926bb1ecf73d9b67a634e840 Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 17 Sep 2015 17:11:34 +0200
+Subject: [PATCH 96/96] IPA: Retry fetching keytab if IPA user lookup fails
+
+Required for:
+    https://fedorahosted.org/sssd/ticket/2639
+
+Instead of calling ipa_get_ad_acct_send directly, call a new request
+ipa_srv_ad_acct_send. The new request wraps ipa_get_ad_acct_send and
+either tries to request a new keytab every time the lookup fails but the
+domain is online.
+
+be_mark_dom_offline() is called when the retry fails with the new code.
+
+The retry tries to re-setup the trusted domain. With two-way setups, the
+request is a no-op. With one-way trust setups, the request re-fetches
+new keytab unconditionally.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 0aff5b651a414a1fd58ab3eb2f029399c0278a18)
+---
+ src/providers/ipa/ipa_id.h            |   9 --
+ src/providers/ipa/ipa_subdomains_id.c | 190 +++++++++++++++++++++++++++++++++-
+ 2 files changed, 185 insertions(+), 14 deletions(-)
+
+diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
+index c03ca037a2850478a8f4933bac4fcf8bd70ada04..91a94115386955f63eca706bf6f4ac41884445eb 100644
+--- a/src/providers/ipa/ipa_id.h
++++ b/src/providers/ipa/ipa_id.h
+@@ -70,15 +70,6 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
+                                             struct be_acct_req *ar);
+ int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out);
+ 
+-struct tevent_req *ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+-                                        struct tevent_context *ev,
+-                                        struct ipa_id_ctx *ipa_ctx,
+-                                        struct be_req *be_req,
+-                                        struct sysdb_attrs *override_attrs,
+-                                        struct be_acct_req *ar);
+-
+-errno_t ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out);
+-
+ errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
+                                 const char *domain_name,
+                                 struct be_acct_req **_ar);
+diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
+index ff14b4a4c68cb5c6e9865a66931ee4ecd6e49211..86dd71f3cc09f11de88c4269d49552718c5ba027 100644
+--- a/src/providers/ipa/ipa_subdomains_id.c
++++ b/src/providers/ipa/ipa_subdomains_id.c
+@@ -34,6 +34,16 @@
+ #include "providers/ad/ad_id.h"
+ #include "providers/ipa/ipa_subdomains.h"
+ 
++static struct tevent_req *
++ipa_srv_ad_acct_send(TALLOC_CTX *mem_ctx,
++                     struct tevent_context *ev,
++                     struct ipa_id_ctx *ipa_ctx,
++                     struct be_req *be_req,
++                     struct sysdb_attrs *override_attrs,
++                     struct be_acct_req *ar);
++static errno_t
++ipa_srv_ad_acct_recv(struct tevent_req *req, int *dp_error_out);
++
+ struct ipa_subdomain_account_state {
+     struct tevent_context *ev;
+     struct ipa_id_ctx *ipa_ctx;
+@@ -45,6 +55,7 @@ struct ipa_subdomain_account_state {
+     struct be_acct_req *ar;
+ 
+     bool ipa_server_mode;
++    bool server_retry;
+     int entry_type;
+     const char *filter;
+     int filter_type;
+@@ -263,7 +274,7 @@ static errno_t ipa_subdomain_account_get_original_step(struct tevent_req *req,
+     struct tevent_req *subreq;
+ 
+     if (state->ipa_server_mode) {
+-        subreq = ipa_get_ad_acct_send(state, state->ev, state->ipa_ctx,
++        subreq = ipa_srv_ad_acct_send(state, state->ev, state->ipa_ctx,
+                                       state->be_req, state->override_attrs, ar);
+     } else {
+         subreq = ipa_get_subdom_acct_send(state, state->ev, state->ipa_ctx,
+@@ -291,7 +302,7 @@ static void ipa_subdomain_account_done(struct tevent_req *subreq)
+     int ret;
+ 
+     if (state->ipa_server_mode) {
+-        ret = ipa_get_ad_acct_recv(subreq, &dp_error);
++        ret = ipa_srv_ad_acct_recv(subreq, &dp_error);
+     } else {
+         ret = ipa_get_subdom_acct_recv(subreq, &dp_error);
+     }
+@@ -575,7 +586,7 @@ 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);
+ 
+-struct tevent_req *
++static struct tevent_req *
+ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+                      struct tevent_context *ev,
+                      struct ipa_id_ctx *ipa_ctx,
+@@ -1039,7 +1050,6 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
+     ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL);
+     talloc_zfree(subreq);
+     if (ret == ERR_SUBDOM_INACTIVE) {
+-        be_mark_dom_offline(state->obj_dom, be_req_get_be_ctx(state->be_req));
+         tevent_req_error(req, ret);
+         return;
+     } else if (ret != EOK) {
+@@ -1324,7 +1334,7 @@ ipa_get_ad_acct_done(struct tevent_req *subreq)
+     tevent_req_done(req);
+ }
+ 
+-errno_t
++static errno_t
+ ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out)
+ {
+     struct ipa_get_ad_acct_state *state = tevent_req_data(req,
+@@ -1338,3 +1348,173 @@ ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out)
+ 
+     return EOK;
+ }
++
++struct ipa_srv_ad_acct_state {
++    struct tevent_context *ev;
++    struct ipa_id_ctx *ipa_ctx;
++    struct be_req *be_req;
++    struct sysdb_attrs *override_attrs;
++    struct be_acct_req *ar;
++
++    struct sss_domain_info *obj_dom;
++    struct be_ctx *be_ctx;
++    bool retry;
++
++    int dp_error;
++};
++
++static int ipa_srv_ad_acct_lookup_step(struct tevent_req *req);
++static void ipa_srv_ad_acct_lookup_done(struct tevent_req *subreq);
++static void ipa_srv_ad_acct_retried(struct tevent_req *subreq);
++
++static struct tevent_req *
++ipa_srv_ad_acct_send(TALLOC_CTX *mem_ctx,
++                     struct tevent_context *ev,
++                     struct ipa_id_ctx *ipa_ctx,
++                     struct be_req *be_req,
++                     struct sysdb_attrs *override_attrs,
++                     struct be_acct_req *ar)
++{
++    errno_t ret;
++    struct tevent_req *req;
++    struct ipa_srv_ad_acct_state *state;
++
++    req = tevent_req_create(mem_ctx, &state, struct ipa_srv_ad_acct_state);
++    if (req == NULL) {
++        return NULL;
++    }
++
++    state->ev = ev;
++    state->ipa_ctx = ipa_ctx;
++    state->be_req = be_req;
++    state->override_attrs = override_attrs;
++    state->ar = ar;
++    state->retry = true;
++    state->dp_error = DP_ERR_FATAL;
++    state->be_ctx = be_req_get_be_ctx(state->be_req);
++
++    state->obj_dom = find_domain_by_name(
++                                  state->ipa_ctx->sdap_id_ctx->be->domain,
++                                  state->ar->domain, true);
++    if (state->obj_dom == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "Domain not found\n");
++        ret = ERR_DOMAIN_NOT_FOUND;
++        goto fail;
++    }
++
++    ret = ipa_srv_ad_acct_lookup_step(req);
++    if (ret != EOK) {
++        goto fail;
++    }
++
++    return req;
++
++fail:
++    tevent_req_error(req, ret);
++    tevent_req_post(req, ev);
++    return req;
++}
++
++static int ipa_srv_ad_acct_lookup_step(struct tevent_req *req)
++{
++    struct tevent_req *subreq;
++    struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
++                                            struct ipa_srv_ad_acct_state);
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Looking up AD account\n");
++    subreq = ipa_get_ad_acct_send(state, state->ev, state->ipa_ctx,
++                                  state->be_req, state->override_attrs,
++                                  state->ar);
++    if (subreq == NULL) {
++        return ENOMEM;
++    }
++    tevent_req_set_callback(subreq, ipa_srv_ad_acct_lookup_done, req);
++
++    return EOK;
++}
++
++static void ipa_srv_ad_acct_lookup_done(struct tevent_req *subreq)
++{
++    errno_t ret;
++    int dp_error = DP_ERR_FATAL;
++    struct tevent_req *req = tevent_req_callback_data(subreq,
++                                                struct tevent_req);
++    struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
++                                            struct ipa_srv_ad_acct_state);
++
++    ret = ipa_get_ad_acct_recv(subreq, &dp_error);
++    talloc_free(subreq);
++    if (ret == ERR_SUBDOM_INACTIVE && state->retry == true) {
++
++        state->retry = false;
++
++        DEBUG(SSSDBG_MINOR_FAILURE,
++              "Sudomain lookup failed, will try to reset sudomain..\n");
++        subreq = ipa_server_trusted_dom_setup_send(state, state->ev,
++                                                   state->be_ctx,
++                                                   state->ipa_ctx,
++                                                   state->obj_dom);
++        if (subreq == NULL) {
++            goto fail;
++        }
++        tevent_req_set_callback(subreq, ipa_srv_ad_acct_retried, req);
++        return;
++    } else if (ret != EOK) {
++        be_mark_dom_offline(state->obj_dom, state->be_ctx);
++
++        DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct request failed: [%d]: %s.\n",
++              ret, sss_strerror(ret));
++        goto fail;
++    }
++
++    state->dp_error = DP_ERR_OK;
++    tevent_req_done(req);
++    return;
++
++fail:
++    state->dp_error = dp_error;
++    tevent_req_error(req, ret);
++}
++
++static void ipa_srv_ad_acct_retried(struct tevent_req *subreq)
++{
++    errno_t ret;
++    struct tevent_req *req = tevent_req_callback_data(subreq,
++                                                struct tevent_req);
++    struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
++                                            struct ipa_srv_ad_acct_state);
++
++    ret = ipa_server_trusted_dom_setup_recv(subreq);
++    talloc_free(subreq);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Failed to re-set subdomain [%d]: %s\n", ret, sss_strerror(ret));
++        state->dp_error = DP_ERR_FATAL;
++        tevent_req_error(req, ret);
++    }
++
++    DEBUG(SSSDBG_TRACE_FUNC, "Sudomain re-set, will retry lookup\n");
++    be_fo_reset_svc(state->be_ctx, state->obj_dom->name);
++
++    ret = ipa_srv_ad_acct_lookup_step(req);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Failed to look up AD acct [%d]: %s\n", ret, sss_strerror(ret));
++        state->dp_error = DP_ERR_FATAL;
++        tevent_req_error(req, ret);
++    }
++}
++
++static errno_t
++ipa_srv_ad_acct_recv(struct tevent_req *req, int *dp_error_out)
++{
++    struct ipa_srv_ad_acct_state *state = tevent_req_data(req,
++                                                struct ipa_srv_ad_acct_state);
++
++    if (dp_error_out) {
++        *dp_error_out = state->dp_error;
++    }
++
++    TEVENT_REQ_RETURN_ON_ERROR(req);
++    return EOK;
++}
+-- 
+2.4.3
+
diff --git a/SOURCES/0096-ipa-add-split_ipa_anchor.patch b/SOURCES/0096-ipa-add-split_ipa_anchor.patch
deleted file mode 100644
index fd7df7e..0000000
--- a/SOURCES/0096-ipa-add-split_ipa_anchor.patch
+++ /dev/null
@@ -1,179 +0,0 @@
-From 7c8abc07058b37e743b1530c9e4a66e2d517e3c3 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 6 Nov 2014 13:13:27 +0100
-Subject: [PATCH 096/104] ipa: add split_ipa_anchor()
-
-This call extracts the domain and the UUID part from an IPA override
-anchor.
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                         |  2 ++
- src/providers/ipa/ipa_id.h          |  2 ++
- src/providers/ipa/ipa_utils.c       | 63 +++++++++++++++++++++++++++++++++++++
- src/tests/cmocka/test_sysdb_views.c | 32 +++++++++++++++++++
- 4 files changed, 99 insertions(+)
- create mode 100644 src/providers/ipa/ipa_utils.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 156ef3c4eab1510126d2bfb47c06163885b8acfe..53ace65b9a9647ffdaff0776d5a55d3e7393a38c 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2064,6 +2064,7 @@ endif # BUILD_IFP
- 
- test_sysdb_views_SOURCES = \
-     src/tests/cmocka/test_sysdb_views.c \
-+    src/providers/ipa/ipa_utils.c \
-     $(NULL)
- test_sysdb_views_CFLAGS = \
-     $(AM_CFLAGS) \
-@@ -2387,6 +2388,7 @@ libsss_ipa_la_SOURCES = \
-     src/providers/ipa/ipa_subdomains_id.c \
-     src/providers/ipa/ipa_subdomains_ext_groups.c \
-     src/providers/ipa/ipa_views.c \
-+    src/providers/ipa/ipa_utils.c \
-     src/providers/ipa/ipa_s2n_exop.c \
-     src/providers/ipa/ipa_hbac_hosts.c \
-     src/providers/ipa/ipa_hbac_private.h \
-diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
-index e13aded213ace8557dfccfc68e04d9ff69fae221..033ac40f1d7a7d8c4a968374ee190a5bcb17819c 100644
---- a/src/providers/ipa/ipa_id.h
-+++ b/src/providers/ipa/ipa_id.h
-@@ -103,4 +103,6 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx,
- 
- errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out);
- 
-+errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor,
-+                         char **_anchor_domain, char **_ipa_uuid);
- #endif
-diff --git a/src/providers/ipa/ipa_utils.c b/src/providers/ipa/ipa_utils.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..86ba51c8adb49c4e0cabccf1ade522b582a8f4d7
---- /dev/null
-+++ b/src/providers/ipa/ipa_utils.c
-@@ -0,0 +1,63 @@
-+/*
-+    SSSD
-+
-+    IPA Module utility functions
-+
-+    Authors:
-+        Sumit Bose <sbose@redhat.com>
-+
-+    Copyright (C) 2014 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 "util/util.h"
-+
-+#define OVERRIDE_ANCHOR_IPA_PREFIX ":IPA:"
-+#define OVERRIDE_ANCHOR_IPA_PREFIX_LEN (sizeof(OVERRIDE_ANCHOR_IPA_PREFIX) -1 )
-+
-+errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor,
-+                         char **_anchor_domain, char **_ipa_uuid)
-+{
-+    const char *sep;
-+
-+    if (anchor == NULL) {
-+        return EINVAL;
-+    }
-+    if (strncmp(OVERRIDE_ANCHOR_IPA_PREFIX, anchor,
-+                OVERRIDE_ANCHOR_IPA_PREFIX_LEN) != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "No IPA anchor [%s].\n", anchor);
-+        return ENOMSG;
-+    }
-+
-+    sep = strchr(anchor + OVERRIDE_ANCHOR_IPA_PREFIX_LEN, ':');
-+    if (sep == NULL || sep[1] == '\0') {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Broken IPA anchor [%s].\n", anchor);
-+        return EINVAL;
-+    }
-+
-+    *_anchor_domain = talloc_strndup(mem_ctx,
-+                                 anchor + OVERRIDE_ANCHOR_IPA_PREFIX_LEN,
-+                                 sep - anchor - OVERRIDE_ANCHOR_IPA_PREFIX_LEN);
-+    *_ipa_uuid = talloc_strdup(mem_ctx, sep + 1);
-+
-+    if (*_anchor_domain == NULL || *_ipa_uuid == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
-+        talloc_free(*_anchor_domain);
-+        talloc_free(*_ipa_uuid);
-+        return ENOMEM;
-+    }
-+
-+    return EOK;
-+}
-diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
-index 9fb2d7201d06e84be83d6a516c5e3a0f15ec0639..0dc51443b406673f131cc69be4d781f7c49e538c 100644
---- a/src/tests/cmocka/test_sysdb_views.c
-+++ b/src/tests/cmocka/test_sysdb_views.c
-@@ -29,6 +29,7 @@
- #include <popt.h>
- 
- #include "tests/cmocka/common_mock.h"
-+#include "providers/ipa/ipa_id.h"
- 
- #define TESTS_PATH "tests_sysdb_views"
- #define TEST_CONF_FILE "tests_conf.ldb"
-@@ -189,6 +190,35 @@ void test_sysdb_add_overrides_to_object(void **state)
-     assert_int_equal(ldb_val_string_cmp(&el->values[1], "OVERRIDEKEY2"), 0);
- }
- 
-+void test_split_ipa_anchor(void **state)
-+{
-+    int ret;
-+    char *dom;
-+    char *uuid;
-+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                                         struct sysdb_test_ctx);
-+
-+    ret = split_ipa_anchor(test_ctx, NULL, &dom, &uuid);
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = split_ipa_anchor(test_ctx, "fwfkwjfkw", &dom, &uuid);
-+    assert_int_equal(ret, ENOMSG);
-+
-+    ret = split_ipa_anchor(test_ctx, ":IPA:", &dom, &uuid);
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = split_ipa_anchor(test_ctx, ":IPA:abc", &dom, &uuid);
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = split_ipa_anchor(test_ctx, ":IPA:abc:", &dom, &uuid);
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = split_ipa_anchor(test_ctx, ":IPA:abc:def", &dom, &uuid);
-+    assert_int_equal(ret, EOK);
-+    assert_string_equal(dom, "abc");
-+    assert_string_equal(uuid, "def");
-+}
-+
- int main(int argc, const char *argv[])
- {
-     int rv;
-@@ -206,6 +236,8 @@ int main(int argc, const char *argv[])
-     const UnitTest tests[] = {
-         unit_test_setup_teardown(test_sysdb_add_overrides_to_object,
-                                  test_sysdb_setup, test_sysdb_teardown),
-+        unit_test_setup_teardown(test_split_ipa_anchor,
-+                                 test_sysdb_setup, test_sysdb_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-1.9.3
-
diff --git a/SOURCES/0097-AD-inicialize-root_domain_attrs-field.patch b/SOURCES/0097-AD-inicialize-root_domain_attrs-field.patch
new file mode 100644
index 0000000..2537ab2
--- /dev/null
+++ b/SOURCES/0097-AD-inicialize-root_domain_attrs-field.patch
@@ -0,0 +1,41 @@
+From d97d6d3acc32d0e4914a1d2c39bfb7fa8ecc7197 Mon Sep 17 00:00:00 2001
+From: Pavel Reichl <preichl@redhat.com>
+Date: Thu, 24 Sep 2015 11:03:12 -0400
+Subject: [PATCH 97/97] AD: inicialize root_domain_attrs field
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2805
+
+Reviewed-by: Pavel Březina <pbrezina@redhat.com>
+(cherry picked from commit 101628a48d25ffae3b13c75d0b0b01577188c803)
+---
+ src/providers/ad/ad_subdomains.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
+index 8ed3dab0995f78a16f4a7df2e729ea88a39a782c..c2a6544fb7f146058acee9baca9b0cc6ee50aa3f 100644
+--- a/src/providers/ad/ad_subdomains.c
++++ b/src/providers/ad/ad_subdomains.c
+@@ -505,7 +505,7 @@ static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
+     int dp_error = DP_ERR_FATAL;
+     int ret;
+ 
+-    req_ctx = talloc(be_req, struct ad_subdomains_req_ctx);
++    req_ctx = talloc_zero(be_req, struct ad_subdomains_req_ctx);
+     if (req_ctx == NULL) {
+         ret = ENOMEM;
+         goto done;
+@@ -519,6 +519,7 @@ static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
+     req_ctx->root_id_ctx = NULL;
+     req_ctx->root_op = NULL;
+     req_ctx->root_domain = NULL;
++    req_ctx->root_domain_attrs = NULL;
+     req_ctx->reply_count = 0;
+     req_ctx->reply = NULL;
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0097-LDAP-add-support-for-lookups-by-UUID.patch b/SOURCES/0097-LDAP-add-support-for-lookups-by-UUID.patch
deleted file mode 100644
index f731fb0..0000000
--- a/SOURCES/0097-LDAP-add-support-for-lookups-by-UUID.patch
+++ /dev/null
@@ -1,147 +0,0 @@
-From 21bc70002db718c353724d3aea2121a2bac23218 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 7 Nov 2014 13:55:01 +0100
-Subject: [PATCH 097/104] LDAP: add support for lookups by UUID
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/data_provider.h |  2 ++
- src/providers/ldap/ldap_id.c  | 58 +++++++++++++++++++++++++++++++++++++++----
- 2 files changed, 55 insertions(+), 5 deletions(-)
-
-diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
-index e1cb4befadba7e24a418790b10ff361b3092ec6a..5df493e9d1ae21ada6f5fd6198a6d9c36680d044 100644
---- a/src/providers/data_provider.h
-+++ b/src/providers/data_provider.h
-@@ -127,6 +127,7 @@
- #define BE_FILTER_IDNUM 2
- #define BE_FILTER_ENUM 3
- #define BE_FILTER_SECID 4
-+#define BE_FILTER_UUID 5
- 
- #define BE_REQ_USER          0x0001
- #define BE_REQ_GROUP         0x0002
-@@ -139,6 +140,7 @@
- #define BE_REQ_HOST          0x0010
- #define BE_REQ_BY_SECID      0x0011
- #define BE_REQ_USER_AND_GROUP 0x0012
-+#define BE_REQ_BY_UUID      0x0013
- #define BE_REQ_TYPE_MASK     0x00FF
- #define BE_REQ_FAST          0x1000
- 
-diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
-index e8b3a0e1e1dce6e0c8a9b21aa7c6299108dad24d..2e58f4e49eb33a85cbb8b4144c69004c6b5b312b 100644
---- a/src/providers/ldap/ldap_id.c
-+++ b/src/providers/ldap/ldap_id.c
-@@ -179,6 +179,20 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
-             goto done;
-         }
-         break;
-+    case BE_FILTER_UUID:
-+        attr_name = ctx->opts->user_map[SDAP_AT_USER_UUID].name;
-+        if (attr_name == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "UUID search not configured for this backend.\n");
-+            ret = EINVAL;
-+            goto done;
-+        }
-+
-+        ret = sss_filter_sanitize(state, name, &clean_name);
-+        if (ret != EOK) {
-+            goto done;
-+        }
-+        break;
-     default:
-         ret = EINVAL;
-         goto done;
-@@ -458,8 +472,9 @@ static void users_get_done(struct tevent_req *subreq)
-             break;
- 
-         case BE_FILTER_SECID:
--            /* Since it is not clear if the SID belongs to a user or a group
--             * we have nothing to do here. */
-+        case BE_FILTER_UUID:
-+            /* Since it is not clear if the SID/UUID belongs to a user or a
-+             * group we have nothing to do here. */
-             break;
- 
-         default:
-@@ -635,6 +650,20 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
-             goto done;
-         }
-         break;
-+    case BE_FILTER_UUID:
-+        attr_name = ctx->opts->group_map[SDAP_AT_GROUP_UUID].name;
-+        if (attr_name == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "UUID search not configured for this backend.\n");
-+            ret = EINVAL;
-+            goto done;
-+        }
-+
-+        ret = sss_filter_sanitize(state, name, &clean_name);
-+        if (ret != EOK) {
-+            goto done;
-+        }
-+        break;
-     default:
-         ret = EINVAL;
-         goto done;
-@@ -884,8 +913,9 @@ static void groups_get_done(struct tevent_req *subreq)
-             break;
- 
-         case BE_FILTER_SECID:
--            /* Since it is not clear if the SID belongs to a user or a group
--             * we have nothing to do here. */
-+        case BE_FILTER_UUID:
-+            /* Since it is not clear if the SID/UUID belongs to a user or a
-+             * group we have nothing to do here. */
-             break;
- 
-         default:
-@@ -1401,7 +1431,8 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
-             goto done;
-         }
- 
--        if (ar->filter_type == BE_FILTER_SECID) {
-+        if (ar->filter_type == BE_FILTER_SECID
-+                || ar->filter_type == BE_FILTER_UUID) {
-             ret = EINVAL;
-             state->err = "Invalid filter type";
-             goto done;
-@@ -1430,6 +1461,21 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
-                                          noexist_delete);
-         break;
- 
-+    case BE_REQ_BY_UUID:
-+        if (ar->filter_type != BE_FILTER_UUID) {
-+            ret = EINVAL;
-+            state->err = "Invalid filter type";
-+            goto done;
-+        }
-+
-+        subreq = get_user_and_group_send(breq, be_ctx->ev, id_ctx,
-+                                         sdom, conn,
-+                                         ar->filter_value,
-+                                         ar->filter_type,
-+                                         ar->attr_type,
-+                                         noexist_delete);
-+        break;
-+
-     case BE_REQ_USER_AND_GROUP:
-         if (!(ar->filter_type == BE_FILTER_NAME ||
-               ar->filter_type == BE_FILTER_IDNUM)) {
-@@ -1504,6 +1550,8 @@ sdap_handle_acct_req_done(struct tevent_req *subreq)
-         break;
-     case BE_REQ_BY_SECID:
-         /* Fallthrough */
-+    case BE_REQ_BY_UUID:
-+        /* Fallthrough */
-     case BE_REQ_USER_AND_GROUP:
-         err = "Lookup by SID failed";
-         ret = sdap_get_user_and_group_recv(subreq, &state->dp_error,
--- 
-1.9.3
-
diff --git a/SOURCES/0098-LDAP-always-store-UUID-if-available.patch b/SOURCES/0098-LDAP-always-store-UUID-if-available.patch
deleted file mode 100644
index 21921b4..0000000
--- a/SOURCES/0098-LDAP-always-store-UUID-if-available.patch
+++ /dev/null
@@ -1,200 +0,0 @@
-From 8c68296b9e5d50951e19877bcad46444157d8fc5 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 7 Nov 2014 21:33:36 +0100
-Subject: [PATCH 098/104] LDAP: always store UUID if available
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ldap/sdap_async_groups.c | 42 +++++++++++++++++++++++++---------
- src/providers/ldap/sdap_async_users.c  | 23 +++++++++++++++++--
- 2 files changed, 52 insertions(+), 13 deletions(-)
-
-diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
-index a82d2aa3418cf5d59181e4be5a1ed6aaeb0b05e9..8cf7f7ff1d414049f0694c7d2873556fc9dad741 100644
---- a/src/providers/ldap/sdap_async_groups.c
-+++ b/src/providers/ldap/sdap_async_groups.c
-@@ -511,6 +511,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     bool posix_group;
-     bool use_id_mapping;
-     char *sid_str;
-+    const char *uuid;
-     struct sss_domain_info *subdomain;
-     int32_t ad_group_type;
- 
-@@ -534,7 +535,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-         ret = sysdb_attrs_add_string(group_attrs, SYSDB_SID_STR, sid_str);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_MINOR_FAILURE, "Could not add SID string: [%s]\n",
--                                         strerror(ret));
-+                                         sss_strerror(ret));
-             goto done;
-         }
-     } else if (ret == ENOENT) {
-@@ -543,10 +544,29 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-         sid_str = NULL;
-     } else {
-         DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify objectSID: [%s]\n",
--                                     strerror(ret));
-+                                     sss_strerror(ret));
-         sid_str = NULL;
-     }
- 
-+    /* Always store UUID if available */
-+    ret = sysdb_attrs_get_string(attrs,
-+                                 opts->group_map[SDAP_AT_GROUP_UUID].sys_name,
-+                                 &uuid);
-+    if (ret == EOK) {
-+        ret = sysdb_attrs_add_string(group_attrs, SYSDB_UUID, uuid);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n",
-+                                         sss_strerror(ret));
-+            goto done;
-+        }
-+    } else if (ret == ENOENT) {
-+        DEBUG(SSSDBG_TRACE_ALL, "UUID not available for group [%s].\n",
-+                                 group_name);
-+    } else {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n",
-+                                     sss_strerror(ret));
-+    }
-+
-     /* If this object has a SID available, we will determine the correct
-      * domain by its SID. */
-     if (sid_str != NULL) {
-@@ -633,7 +653,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-             } else if (ret != EOK) {
-                 DEBUG(SSSDBG_MINOR_FAILURE,
-                       "Could not convert SID string: [%s]\n",
--                       strerror(ret));
-+                       sss_strerror(ret));
-                 goto done;
-             }
- 
-@@ -652,7 +672,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-             } else if (ret != EOK) {
-                 DEBUG(SSSDBG_MINOR_FAILURE,
-                       "Error reading posix attribute: [%s]\n",
--                       strerror(ret));
-+                       sss_strerror(ret));
-                 goto done;
-             }
- 
-@@ -662,7 +682,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-             if (ret != EOK) {
-                 DEBUG(SSSDBG_MINOR_FAILURE,
-                       "Error setting posix attribute: [%s]\n",
--                       strerror(ret));
-+                       sss_strerror(ret));
-                 goto done;
-             }
- 
-@@ -695,7 +715,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     if (ret != EOK) {
-         DEBUG(SSSDBG_MINOR_FAILURE,
-               "Error setting original DN: [%s]\n",
--               strerror(ret));
-+               sss_strerror(ret));
-         goto done;
-     }
- 
-@@ -706,7 +726,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     if (ret != EOK) {
-         DEBUG(SSSDBG_MINOR_FAILURE,
-               "Error setting mod timestamp: [%s]\n",
--               strerror(ret));
-+               sss_strerror(ret));
-         goto done;
-     }
- 
-@@ -715,7 +735,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     if (ret) {
-         DEBUG(SSSDBG_MINOR_FAILURE,
-               "Error looking up group USN: [%s]\n",
--               strerror(ret));
-+               sss_strerror(ret));
-         goto done;
-     }
-     if (el->num_values == 0) {
-@@ -728,7 +748,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-         if (ret) {
-             DEBUG(SSSDBG_MINOR_FAILURE,
-                   "Error setting group USN: [%s]\n",
--                   strerror(ret));
-+                   sss_strerror(ret));
-             goto done;
-         }
-         usn_value = talloc_strdup(tmpctx, (const char*)el->values[0].data);
-@@ -759,7 +779,7 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     if (ret) {
-         DEBUG(SSSDBG_MINOR_FAILURE,
-               "Could not store group with GID: [%s]\n",
--               strerror(ret));
-+               sss_strerror(ret));
-         goto done;
-     }
- 
-@@ -775,7 +795,7 @@ done:
-         DEBUG(SSSDBG_MINOR_FAILURE,
-               "Failed to save group [%s]: [%s]\n",
-                group_name ? group_name : "Unknown",
--               strerror(ret));
-+               sss_strerror(ret));
-     }
-     talloc_free(tmpctx);
-     return ret;
-diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
-index 2331ba9df90cdbf8fdb9ae85bd97485b0bcf8bb2..367e3d795ddd0db5c1c2f8e57d700419f371cd15 100644
---- a/src/providers/ldap/sdap_async_users.c
-+++ b/src/providers/ldap/sdap_async_users.c
-@@ -140,6 +140,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
-     TALLOC_CTX *tmpctx = NULL;
-     bool use_id_mapping;
-     char *sid_str;
-+    const char *uuid;
-     char *dom_sid_str = NULL;
-     struct sss_domain_info *subdomain;
- 
-@@ -165,7 +166,7 @@ int sdap_save_user(TALLOC_CTX *memctx,
-         ret = sysdb_attrs_add_string(user_attrs, SYSDB_SID_STR, sid_str);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_MINOR_FAILURE, "Could not add SID string: [%s]\n",
--                                         strerror(ret));
-+                                         sss_strerror(ret));
-             goto done;
-         }
-     } else if (ret == ENOENT) {
-@@ -173,10 +174,28 @@ int sdap_save_user(TALLOC_CTX *memctx,
-         sid_str = NULL;
-     } else {
-         DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify objectSID: [%s]\n",
--                                     strerror(ret));
-+                                     sss_strerror(ret));
-         sid_str = NULL;
-     }
- 
-+    /* Always store UUID if available */
-+    ret = sysdb_attrs_get_string(attrs,
-+                                 opts->user_map[SDAP_AT_USER_UUID].sys_name,
-+                                 &uuid);
-+    if (ret == EOK) {
-+        ret = sysdb_attrs_add_string(user_attrs, SYSDB_UUID, uuid);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n",
-+                                         sss_strerror(ret));
-+            goto done;
-+        }
-+    } else if (ret == ENOENT) {
-+        DEBUG(SSSDBG_TRACE_ALL, "UUID not available for user.\n");
-+    } else {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n",
-+                                     sss_strerror(ret));
-+    }
-+
-     /* If this object has a SID available, we will determine the correct
-      * domain by its SID. */
-     if (sid_str != NULL) {
--- 
-1.9.3
-
diff --git a/SOURCES/0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch b/SOURCES/0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch
new file mode 100644
index 0000000..2168ab2
--- /dev/null
+++ b/SOURCES/0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch
@@ -0,0 +1,136 @@
+From 63c52299e122a05e7b25b5ee94b528fe64a6c6ef Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Thu, 1 Oct 2015 10:10:22 +0200
+Subject: [PATCH 98/99] PAM: only allow missing user name for certificate
+ authentication
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2811
+
+Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
+(cherry picked from commit 2e76b32e74abedb23665808bacc73cafd1097c37)
+(cherry picked from commit ba9d5c0456a2fbb9adf9b4b4dffbfb190628a273)
+---
+ src/responder/pam/pamsrv_cmd.c  | 12 +++++++++---
+ src/tests/cmocka/test_pam_srv.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 50 insertions(+), 3 deletions(-)
+
+diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
+index aa5c20906a36351e425304122517c81676e730b7..ae14b9287268ffb36500b0cfdb38e69adb0ecce9 100644
+--- a/src/responder/pam/pamsrv_cmd.c
++++ b/src/responder/pam/pamsrv_cmd.c
+@@ -962,11 +962,13 @@ static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *p
+     } else {
+         /* Only SSS_PAM_PREAUTH request may have a missing name, e.g. if the
+          * name is determined with the help of a certificate */
+-        if (pd->cmd == SSS_PAM_PREAUTH) {
++        if (pd->cmd == SSS_PAM_PREAUTH
++                && may_do_cert_auth(talloc_get_type(cctx->rctx->pvt_ctx,
++                                                    struct pam_ctx), pd)) {
+             ret = EOK;
+         } else {
+             DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n");
+-            ret = EINVAL;
++            ret = ERR_NO_CREDS;
+             goto done;
+         }
+     }
+@@ -1076,7 +1078,6 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
+         }
+         goto done;
+     } else if (ret != EOK) {
+-        ret = EINVAL;
+         goto done;
+     }
+ 
+@@ -1597,6 +1598,11 @@ static int pam_check_user_done(struct pam_auth_req *preq, int ret)
+         pam_reply(preq);
+         break;
+ 
++    case ERR_NO_CREDS:
++        preq->pd->pam_status = PAM_CRED_INSUFFICIENT;
++        pam_reply(preq);
++        break;
++
+     default:
+         preq->pd->pam_status = PAM_SYSTEM_ERR;
+         pam_reply(preq);
+diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
+index 3c70c599060e09125ab5b73ce3d2698eaa3006bd..0ae2554032d28329ebb1d6ad09cfd859cf9b4260 100644
+--- a/src/tests/cmocka/test_pam_srv.c
++++ b/src/tests/cmocka/test_pam_srv.c
+@@ -596,6 +596,23 @@ static int test_pam_wrong_pw_offline_auth_check(uint32_t status,
+     return test_pam_simple_check(status, body, blen);
+ }
+ 
++static int test_pam_creds_insufficient_check(uint32_t status,
++                                             uint8_t *body, size_t blen)
++{
++    size_t rp = 0;
++    uint32_t val;
++
++    assert_int_equal(status, 0);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, PAM_CRED_INSUFFICIENT);
++
++    SAFEALIGN_COPY_UINT32(&val, body + rp, &rp);
++    assert_int_equal(val, 0);
++
++    return EOK;
++}
++
+ static int test_pam_user_unknown_check(uint32_t status,
+                                        uint8_t *body, size_t blen)
+ {
+@@ -1100,6 +1117,25 @@ void test_pam_offline_chauthtok(void **state)
+     assert_int_equal(ret, EOK);
+ }
+ 
++void test_pam_preauth_no_logon_name(void **state)
++{
++    int ret;
++
++    mock_input_pam_cert(pam_test_ctx, NULL, NULL);
++
++    will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH);
++    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
++
++    set_cmd_cb(test_pam_creds_insufficient_check);
++    ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH,
++                          pam_test_ctx->pam_cmds);
++    assert_int_equal(ret, EOK);
++
++    /* Wait until the test finishes with EOK */
++    ret = test_ev_loop(pam_test_ctx->tctx);
++    assert_int_equal(ret, EOK);
++}
++
+ static void set_cert_auth_param(struct pam_ctx *pctx, const char *dbpath)
+ {
+     pam_test_ctx->pctx->cert_auth = true;
+@@ -1405,6 +1441,8 @@ int main(int argc, const char *argv[])
+                                         pam_test_setup, pam_test_teardown),
+         cmocka_unit_test_setup_teardown(test_pam_offline_chauthtok,
+                                         pam_test_setup, pam_test_teardown),
++/* p11_child is not built without NSS */
++#ifdef HAVE_NSS
+         cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nocert,
+                                         pam_test_setup, pam_test_teardown),
+         cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nomatch,
+@@ -1422,6 +1460,9 @@ int main(int argc, const char *argv[])
+                                    pam_test_setup, pam_test_teardown),
+         cmocka_unit_test_setup_teardown(test_pam_cert_auth,
+                                         pam_test_setup, pam_test_teardown),
++        cmocka_unit_test_setup_teardown(test_pam_preauth_no_logon_name,
++                                        pam_test_setup, pam_test_teardown),
++#endif
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+-- 
+2.4.3
+
diff --git a/SOURCES/0099-Fix-memory-leak-in-sssdpac_verify.patch b/SOURCES/0099-Fix-memory-leak-in-sssdpac_verify.patch
new file mode 100644
index 0000000..3324d44
--- /dev/null
+++ b/SOURCES/0099-Fix-memory-leak-in-sssdpac_verify.patch
@@ -0,0 +1,30 @@
+From d600e8bedf05d447ba84d9a89be7d46ba34f1b5d Mon Sep 17 00:00:00 2001
+From: Thomas Oulevey <thomas.oulevey@cern.ch>
+Date: Wed, 23 Sep 2015 10:55:59 +0200
+Subject: [PATCH 99/99] Fix memory leak in sssdpac_verify()
+
+Resolves https://fedorahosted.org/sssd/ticket/2803
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit b4c44ebb8997d3debb33607c123ccfd9926e0cba)
+---
+ src/sss_client/sssd_pac.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/sss_client/sssd_pac.c b/src/sss_client/sssd_pac.c
+index 1939f61b18398f62a3e3d6b29cc4fef151b1c3b7..1d98e38826b36aed199b32880a7e27de905a4592 100644
+--- a/src/sss_client/sssd_pac.c
++++ b/src/sss_client/sssd_pac.c
+@@ -150,6 +150,9 @@ static krb5_error_code sssdpac_verify(krb5_context kcontext,
+     kerr = krb5_pac_verify(kcontext, pac,
+                            req->ticket->enc_part2->times.authtime,
+                            req->ticket->enc_part2->client, key, NULL);
++    /* deallocate pac */
++    krb5_pac_free(kcontext, pac);
++    pac = NULL;
+     if (kerr != 0) {
+         /* The krb5 documentation says:
+          * A checksum mismatch can occur if the PAC was copied from a
+-- 
+2.4.3
+
diff --git a/SOURCES/0099-ipa-add-get_be_acct_req_for_uuid.patch b/SOURCES/0099-ipa-add-get_be_acct_req_for_uuid.patch
deleted file mode 100644
index 503f95d..0000000
--- a/SOURCES/0099-ipa-add-get_be_acct_req_for_uuid.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From 0e1c39d4f66c80a510d13cf73273ee87ec998a0a Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 7 Nov 2014 15:05:41 +0100
-Subject: [PATCH 099/104] ipa: add get_be_acct_req_for_uuid()
-
-This new call creates the needs data for a lookup by UUID which is
-needed when trying to find the original object for an IPA override
-object.
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_id.h    |  4 ++++
- src/providers/ipa/ipa_views.c | 42 ++++++++++++++++++++++++++++++++++++------
- 2 files changed, 40 insertions(+), 6 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
-index 033ac40f1d7a7d8c4a968374ee190a5bcb17819c..890d00d49097555acce62ecc5fa300c71c6c9981 100644
---- a/src/providers/ipa/ipa_id.h
-+++ b/src/providers/ipa/ipa_id.h
-@@ -83,6 +83,10 @@ errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
-                                 const char *domain_name,
-                                 struct be_acct_req **_ar);
- 
-+errno_t get_be_acct_req_for_uuid(TALLOC_CTX *mem_ctx, const char *uuid,
-+                                 const char *domain_name,
-+                                 struct be_acct_req **_ar);
-+
- struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx,
-                                             struct tevent_context *ev,
-                                             struct sdap_id_ctx *sdap_id_ctx,
-diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
-index 2eb77216ab9759d8b1d66fbdf0b2e90cd07a4604..ee586894ec61b1b1330816c628bbc9617d58e31e 100644
---- a/src/providers/ipa/ipa_views.c
-+++ b/src/providers/ipa/ipa_views.c
-@@ -140,9 +140,10 @@ static errno_t be_acct_req_to_override_filter(TALLOC_CTX *mem_ctx,
-     return EOK;
- }
- 
--errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
--                                const char *domain_name,
--                                struct be_acct_req **_ar)
-+static errno_t get_be_acct_req_for_xyz(TALLOC_CTX *mem_ctx, const char *val,
-+                                       const char *domain_name,
-+                                       int type,
-+                                       struct be_acct_req **_ar)
- {
-     struct be_acct_req *ar;
- 
-@@ -152,9 +153,22 @@ errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
-         return ENOMEM;
-     }
- 
--    ar->entry_type = BE_REQ_BY_SECID;
--    ar->filter_type = BE_FILTER_SECID;
--    ar->filter_value = talloc_strdup(ar, sid);
-+    switch (type) {
-+    case BE_REQ_BY_SECID:
-+        ar->entry_type = BE_REQ_BY_SECID;
-+        ar->filter_type = BE_FILTER_SECID;
-+        break;
-+    case BE_REQ_BY_UUID:
-+        ar->entry_type = BE_REQ_BY_UUID;
-+        ar->filter_type = BE_FILTER_UUID;
-+        break;
-+    default:
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type [%d].\n", type);
-+        talloc_free(ar);
-+        return EINVAL;
-+    }
-+
-+    ar->filter_value = talloc_strdup(ar, val);
-     ar->domain = talloc_strdup(ar, domain_name);
-     if (ar->filter_value == NULL || ar->domain == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-@@ -168,6 +182,22 @@ errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
-     return EOK;
- }
- 
-+errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
-+                                const char *domain_name,
-+                                struct be_acct_req **_ar)
-+{
-+    return get_be_acct_req_for_xyz(mem_ctx, sid, domain_name, BE_REQ_BY_SECID,
-+                                   _ar);
-+}
-+
-+errno_t get_be_acct_req_for_uuid(TALLOC_CTX *mem_ctx, const char *uuid,
-+                                 const char *domain_name,
-+                                 struct be_acct_req **_ar)
-+{
-+    return get_be_acct_req_for_xyz(mem_ctx, uuid, domain_name, BE_REQ_BY_UUID,
-+                                   _ar);
-+}
-+
- struct ipa_get_ad_override_state {
-     struct tevent_context *ev;
-     struct sdap_id_ctx *sdap_id_ctx;
--- 
-1.9.3
-
diff --git a/SOURCES/0100-AD-Provide-common-connection-list-construction-funct.patch b/SOURCES/0100-AD-Provide-common-connection-list-construction-funct.patch
new file mode 100644
index 0000000..33f2ef6
--- /dev/null
+++ b/SOURCES/0100-AD-Provide-common-connection-list-construction-funct.patch
@@ -0,0 +1,241 @@
+From 809f139ac4c23dd9db20ea6068e18682f32eb1db Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 1 Oct 2015 13:13:05 +0200
+Subject: [PATCH 100/101] AD: Provide common connection list construction
+ functions
+
+https://fedorahosted.org/sssd/ticket/2810
+
+Provides a new AD common function ad_ldap_conn_list() that creates a
+list of AD connection to use along with properties to avoid mistakes
+when manually constructing these lists.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit 309aa83d16b5919f727af04850bcd0799ba0962f)
+(cherry picked from commit 15a4b34ccfcfbcec2c9ba529d0113adf251abc16)
+---
+ src/providers/ad/ad_common.c          | 26 +++++++++++++++++++
+ src/providers/ad/ad_common.h          |  5 ++++
+ src/providers/ad/ad_id.c              | 17 +------------
+ src/providers/ipa/ipa_subdomains_id.c | 21 ++++++----------
+ src/tests/cmocka/test_ad_common.c     | 47 ++++++++++++++++++++++++++++++-----
+ 5 files changed, 81 insertions(+), 35 deletions(-)
+
+diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
+index 130cdeb613aae3843f7453a478815daaae6aab77..df277e55e234d4d4efe34d5f5d8efdfe7267fb60 100644
+--- a/src/providers/ad/ad_common.c
++++ b/src/providers/ad/ad_common.c
+@@ -1236,6 +1236,14 @@ ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom)
+     subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx);
+     conn = subdom_id_ctx->ldap_ctx;
+ 
++    if (IS_SUBDOMAIN(sdom->dom) == true && conn != NULL) {
++        /* Regardless of connection types, a subdomain error must not be
++         * allowed to set the whole back end offline, rather report an error
++         * and let the caller deal with it (normally disable the subdomain
++         */
++        conn->ignore_mark_offline = true;
++    }
++
+     return conn;
+ }
+ 
+@@ -1260,3 +1268,21 @@ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
+ 
+     return clist;
+ }
++
++struct sdap_id_conn_ctx **
++ad_ldap_conn_list(TALLOC_CTX *mem_ctx,
++                  struct ad_id_ctx *ad_ctx,
++                  struct sss_domain_info *dom)
++{
++    struct sdap_id_conn_ctx **clist;
++
++    clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 2);
++    if (clist == NULL) {
++        return NULL;
++    }
++
++    clist[0] = ad_get_dom_ldap_conn(ad_ctx, dom);
++
++    clist[1] = NULL;
++    return clist;
++}
+diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
+index 817f5b42cad7cad6a88244fd43bd91a4358d56c0..701e461987cb286ca7add2766ffb4dc496bde01e 100644
+--- a/src/providers/ad/ad_common.h
++++ b/src/providers/ad/ad_common.h
+@@ -148,6 +148,11 @@ struct sdap_id_conn_ctx **
+ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
+                struct sss_domain_info *dom);
+ 
++struct sdap_id_conn_ctx **
++ad_ldap_conn_list(TALLOC_CTX *mem_ctx,
++                  struct ad_id_ctx *ad_ctx,
++                  struct sss_domain_info *dom);
++
+ struct sdap_id_conn_ctx *
+ ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom);
+ 
+diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
+index ecaf6c993bf7ddb7ba565d40ef0ad250114f5536..be0cb3b12f2e3a2b53d740ecf3befc07fd853f8b 100644
+--- a/src/providers/ad/ad_id.c
++++ b/src/providers/ad/ad_id.c
+@@ -269,29 +269,14 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
+     case BE_REQ_GROUP: /* group */
+     case BE_REQ_INITGROUPS: /* init groups for user */
+         clist = ad_gc_conn_list(breq, ad_ctx, dom);
+-        if (clist == NULL) return NULL;
+         break;
+ 
+     default:
+         /* Requests for other object should only contact LDAP by default */
+-        clist = talloc_zero_array(breq, struct sdap_id_conn_ctx *, 2);
+-        if (clist == NULL) return NULL;
+-
+-        clist[0] = ad_ctx->ldap_ctx;
+-        clist[1] = NULL;
++        clist = ad_ldap_conn_list(breq, ad_ctx, dom);
+         break;
+     }
+ 
+-    /* Regardless of connection types, a subdomain error must not be allowed
+-     * to set the whole back end offline, rather report an error and let the
+-     * caller deal with it (normally disable the subdomain
+-     */
+-    if (IS_SUBDOMAIN(dom)) {
+-        for (cindex = 0; clist[cindex] != NULL; cindex++) {
+-            clist[cindex]->ignore_mark_offline = true;
+-        }
+-    }
+-
+     return clist;
+ }
+ 
+diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
+index 86dd71f3cc09f11de88c4269d49552718c5ba027..7acbb38e66c2c36ff230ae35b236544195a8104b 100644
+--- a/src/providers/ipa/ipa_subdomains_id.c
++++ b/src/providers/ipa/ipa_subdomains_id.c
+@@ -640,21 +640,16 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
+     case BE_REQ_BY_SECID:
+     case BE_REQ_GROUP:
+         clist = ad_gc_conn_list(req, ad_id_ctx, state->obj_dom);
+-        if (clist == NULL) {
+-            ret = ENOMEM;
+-            goto fail;
+-        }
+-        clist[1]->ignore_mark_offline = true;
+         break;
+     default:
+-        clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2);
+-        if (clist == NULL) {
+-            ret = ENOMEM;
+-            goto fail;
+-        }
+-        clist[0] = ad_id_ctx->ldap_ctx;
+-        clist[0]->ignore_mark_offline = true;
+-        clist[1] = NULL;
++        clist = ad_ldap_conn_list(req, ad_id_ctx, state->obj_dom);
++        break;
++    }
++
++    if (clist == NULL) {
++        DEBUG(SSSDBG_OP_FAILURE, "Cannot generate AD connection list!\n");
++        ret = ENOMEM;
++        goto fail;
+     }
+ 
+     /* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */
+diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
+index 985a05fae5a4d09ab102ed611c7d03ca8e4d955b..c7bcc0f7cfde7164672123a35940327ee3ca4aba 100644
+--- a/src/tests/cmocka/test_ad_common.c
++++ b/src/tests/cmocka/test_ad_common.c
+@@ -337,7 +337,7 @@ __wrap_sdap_set_sasl_options(struct sdap_options *id_opts,
+     return EOK;
+ }
+ 
+-void test_ldap_conn_list(void **state)
++void test_ad_get_dom_ldap_conn(void **state)
+ {
+     struct sdap_id_conn_ctx *conn;
+ 
+@@ -352,7 +352,7 @@ void test_ldap_conn_list(void **state)
+     assert_true(conn == test_ctx->subdom_ad_ctx->ldap_ctx);
+ }
+ 
+-void test_conn_list(void **state)
++void test_gc_conn_list(void **state)
+ {
+     struct sdap_id_conn_ctx **conn_list;
+ 
+@@ -379,7 +379,8 @@ void test_conn_list(void **state)
+     assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
+     assert_true(conn_list[0]->ignore_mark_offline);
+     assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx);
+-    assert_false(conn_list[1]->ignore_mark_offline);
++    /* Subdomain error should not set the backend offline! */
++    assert_true(conn_list[1]->ignore_mark_offline);
+     talloc_free(conn_list);
+ 
+     dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false);
+@@ -398,6 +399,37 @@ void test_conn_list(void **state)
+     assert_non_null(conn_list);
+ 
+     assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx);
++    assert_true(conn_list[0]->ignore_mark_offline);
++    assert_null(conn_list[1]);
++    talloc_free(conn_list);
++}
++
++void test_ldap_conn_list(void **state)
++{
++    struct sdap_id_conn_ctx **conn_list;
++
++    struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
++                                                     struct ad_common_test_ctx);
++    assert_non_null(test_ctx);
++
++    conn_list = ad_ldap_conn_list(test_ctx,
++                                  test_ctx->ad_ctx,
++                                  test_ctx->dom);
++    assert_non_null(conn_list);
++
++    assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx);
++    assert_false(conn_list[0]->ignore_mark_offline);
++    assert_null(conn_list[1]);
++    talloc_free(conn_list);
++
++    conn_list = ad_ldap_conn_list(test_ctx,
++                                  test_ctx->ad_ctx,
++                                  test_ctx->subdom);
++    assert_non_null(conn_list);
++
++    assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx);
++    assert_true(conn_list[0]->ignore_mark_offline);
++    assert_null(conn_list[1]);
+     talloc_free(conn_list);
+ }
+ 
+@@ -419,12 +451,15 @@ int main(int argc, const char *argv[])
+         cmocka_unit_test_setup_teardown(test_ad_create_2way_trust_options,
+                                         test_ad_common_setup,
+                                         test_ad_common_teardown),
++        cmocka_unit_test_setup_teardown(test_ad_get_dom_ldap_conn,
++                                        test_ldap_conn_setup,
++                                        test_ldap_conn_teardown),
++        cmocka_unit_test_setup_teardown(test_gc_conn_list,
++                                        test_ldap_conn_setup,
++                                        test_ldap_conn_teardown),
+         cmocka_unit_test_setup_teardown(test_ldap_conn_list,
+                                         test_ldap_conn_setup,
+                                         test_ldap_conn_teardown),
+-        cmocka_unit_test_setup_teardown(test_conn_list,
+-                                        test_ldap_conn_setup,
+-                                        test_ldap_conn_teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+-- 
+2.4.3
+
diff --git a/SOURCES/0100-IPA-make-get_object_from_cache-public.patch b/SOURCES/0100-IPA-make-get_object_from_cache-public.patch
deleted file mode 100644
index 371eb07..0000000
--- a/SOURCES/0100-IPA-make-get_object_from_cache-public.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 0f15a623392fa66832e8cbbc8e9293830e1fb0f8 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 7 Nov 2014 21:34:55 +0100
-Subject: [PATCH 100/104] IPA: make get_object_from_cache() public
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_id.h            | 5 +++++
- src/providers/ipa/ipa_subdomains_id.c | 9 +++++----
- 2 files changed, 10 insertions(+), 4 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
-index 890d00d49097555acce62ecc5fa300c71c6c9981..9d219f281847df0ba4ac24061e598eb6915f9c38 100644
---- a/src/providers/ipa/ipa_id.h
-+++ b/src/providers/ipa/ipa_id.h
-@@ -109,4 +109,9 @@ errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out);
- 
- errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor,
-                          char **_anchor_domain, char **_ipa_uuid);
-+
-+errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
-+                              struct sss_domain_info *dom,
-+                              struct be_acct_req *ar,
-+                              struct ldb_message **_msg);
- #endif
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index 0a1c4c17eed37b2eb12a8c758e49fc17c3b642b5..891fc336483b507fd284b0c84b118534910ed9fc 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -848,10 +848,10 @@ done:
-     return ret;
- }
- 
--static errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
--                                     struct sss_domain_info *dom,
--                                     struct be_acct_req *ar,
--                                     struct ldb_message **_msg)
-+errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
-+                              struct sss_domain_info *dom,
-+                              struct be_acct_req *ar,
-+                              struct ldb_message **_msg)
- {
-     errno_t ret;
-     uint32_t id;
-@@ -861,6 +861,7 @@ static errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
-                             SYSDB_UIDNUM,
-                             SYSDB_SID_STR,
-                             SYSDB_OBJECTCLASS,
-+                            SYSDB_UUID,
-                             NULL };
-     char *name;
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0101-AD-Consolidate-connection-list-construction-on-ad_co.patch b/SOURCES/0101-AD-Consolidate-connection-list-construction-on-ad_co.patch
new file mode 100644
index 0000000..9e4fbf4
--- /dev/null
+++ b/SOURCES/0101-AD-Consolidate-connection-list-construction-on-ad_co.patch
@@ -0,0 +1,165 @@
+From 64b1b88acacf4004acdfca1a6cda9763e017dfbf Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Mon, 5 Oct 2015 16:11:14 +0200
+Subject: [PATCH 101/101] AD: Consolidate connection list construction on
+ ad_common.c
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+(cherry picked from commit afb21fd06690a0bec288a7970abf74ed2ea7dfdc)
+(cherry picked from commit f1742784d9b1cffd74f67beeb26375124183428a)
+---
+ src/providers/ad/ad_common.c      | 31 +++++++++++++++++++++++++++++++
+ src/providers/ad/ad_common.h      |  5 +++++
+ src/providers/ad/ad_id.c          | 18 +-----------------
+ src/tests/cmocka/test_ad_common.c | 34 ++++++++++++++++++++++++++++++++++
+ 4 files changed, 71 insertions(+), 17 deletions(-)
+
+diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
+index df277e55e234d4d4efe34d5f5d8efdfe7267fb60..650ec41578297f7b3a59df118b71a6bb8bc6d6ed 100644
+--- a/src/providers/ad/ad_common.c
++++ b/src/providers/ad/ad_common.c
+@@ -1286,3 +1286,34 @@ ad_ldap_conn_list(TALLOC_CTX *mem_ctx,
+     clist[1] = NULL;
+     return clist;
+ }
++
++struct sdap_id_conn_ctx **
++ad_user_conn_list(TALLOC_CTX *mem_ctx,
++                  struct ad_id_ctx *ad_ctx,
++                  struct sss_domain_info *dom)
++{
++    struct sdap_id_conn_ctx **clist;
++    int cindex = 0;
++
++    clist = talloc_zero_array(ad_ctx, struct sdap_id_conn_ctx *, 3);
++    if (clist == NULL) {
++        return NULL;
++    }
++
++    /* Try GC first for users from trusted domains, but go to LDAP
++     * for users from non-trusted domains to get all POSIX attrs
++     */
++    if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)
++            && IS_SUBDOMAIN(dom)) {
++        clist[cindex] = ad_ctx->gc_ctx;
++        clist[cindex]->ignore_mark_offline = true;
++        cindex++;
++    }
++
++    /* Users from primary domain can be just downloaded from LDAP.
++     * The domain's LDAP connection also works as a fallback
++     */
++    clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom);
++
++    return clist;
++}
+diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
+index 701e461987cb286ca7add2766ffb4dc496bde01e..0cefa1859aaa75731267917e66ab9a1905528e91 100644
+--- a/src/providers/ad/ad_common.h
++++ b/src/providers/ad/ad_common.h
+@@ -153,6 +153,11 @@ ad_ldap_conn_list(TALLOC_CTX *mem_ctx,
+                   struct ad_id_ctx *ad_ctx,
+                   struct sss_domain_info *dom);
+ 
++struct sdap_id_conn_ctx **
++ad_user_conn_list(TALLOC_CTX *mem_ctx,
++                  struct ad_id_ctx *ad_ctx,
++                  struct sss_domain_info *dom);
++
+ struct sdap_id_conn_ctx *
+ ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom);
+ 
+diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
+index be0cb3b12f2e3a2b53d740ecf3befc07fd853f8b..51d378863a5c7394ca3a2b8bd72f8c131a2b02b1 100644
+--- a/src/providers/ad/ad_id.c
++++ b/src/providers/ad/ad_id.c
+@@ -244,25 +244,10 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
+               struct sss_domain_info *dom, struct be_acct_req *ar)
+ {
+     struct sdap_id_conn_ctx **clist;
+-    int cindex = 0;
+ 
+     switch (ar->entry_type & BE_REQ_TYPE_MASK) {
+     case BE_REQ_USER: /* user */
+-        clist = talloc_zero_array(ad_ctx, struct sdap_id_conn_ctx *, 3);
+-        if (clist == NULL) return NULL;
+-
+-        /* Try GC first for users from trusted domains */
+-        if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)
+-                && IS_SUBDOMAIN(dom)) {
+-            clist[cindex] = ad_ctx->gc_ctx;
+-            clist[cindex]->ignore_mark_offline = true;
+-            cindex++;
+-        }
+-
+-        /* Users from primary domain can be just downloaded from LDAP.
+-         * The domain's LDAP connection also works as a fallback
+-         */
+-        clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom);
++        clist = ad_user_conn_list(breq, ad_ctx, dom);
+         break;
+     case BE_REQ_BY_SECID:   /* by SID */
+     case BE_REQ_USER_AND_GROUP: /* get SID */
+@@ -270,7 +255,6 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
+     case BE_REQ_INITGROUPS: /* init groups for user */
+         clist = ad_gc_conn_list(breq, ad_ctx, dom);
+         break;
+-
+     default:
+         /* Requests for other object should only contact LDAP by default */
+         clist = ad_ldap_conn_list(breq, ad_ctx, dom);
+diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c
+index c7bcc0f7cfde7164672123a35940327ee3ca4aba..f6a4c0db413bbe9c79e6d41f3de5ac75d080c225 100644
+--- a/src/tests/cmocka/test_ad_common.c
++++ b/src/tests/cmocka/test_ad_common.c
+@@ -433,6 +433,37 @@ void test_ldap_conn_list(void **state)
+     talloc_free(conn_list);
+ }
+ 
++void test_user_conn_list(void **state)
++{
++    struct sdap_id_conn_ctx **conn_list;
++
++    struct ad_common_test_ctx *test_ctx = talloc_get_type(*state,
++                                                     struct ad_common_test_ctx);
++    assert_non_null(test_ctx);
++
++    conn_list = ad_user_conn_list(test_ctx,
++                                  test_ctx->ad_ctx,
++                                  test_ctx->dom);
++    assert_non_null(conn_list);
++
++    assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx);
++    assert_false(conn_list[0]->ignore_mark_offline);
++    assert_null(conn_list[1]);
++    talloc_free(conn_list);
++
++    conn_list = ad_user_conn_list(test_ctx,
++                                  test_ctx->ad_ctx,
++                                  test_ctx->subdom);
++    assert_non_null(conn_list);
++
++    assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx);
++    assert_true(conn_list[0]->ignore_mark_offline);
++    assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx);
++    /* Subdomain error should not set the backend offline! */
++    assert_true(conn_list[1]->ignore_mark_offline);
++    talloc_free(conn_list);
++}
++
+ int main(int argc, const char *argv[])
+ {
+     poptContext pc;
+@@ -460,6 +491,9 @@ int main(int argc, const char *argv[])
+         cmocka_unit_test_setup_teardown(test_ldap_conn_list,
+                                         test_ldap_conn_setup,
+                                         test_ldap_conn_teardown),
++        cmocka_unit_test_setup_teardown(test_user_conn_list,
++                                        test_ldap_conn_setup,
++                                        test_ldap_conn_teardown),
+     };
+ 
+     /* Set debug level to invalid value so we can deside if -d 0 was used. */
+-- 
+2.4.3
+
diff --git a/SOURCES/0101-IPA-check-overrrides-for-IPA-users-as-well.patch b/SOURCES/0101-IPA-check-overrrides-for-IPA-users-as-well.patch
deleted file mode 100644
index f1432a8..0000000
--- a/SOURCES/0101-IPA-check-overrrides-for-IPA-users-as-well.patch
+++ /dev/null
@@ -1,517 +0,0 @@
-From 2dfd383413d1c5bfc031f8396eccd1108c899e68 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 5 Nov 2014 15:58:04 +0100
-Subject: [PATCH 101/104] IPA: check overrrides for IPA users as well
-
-Currently overrides were only available for sub-domains, e.g. trusted AD
-domains. With this patch overrides can be used for IPA users as well.
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_id.c            | 405 +++++++++++++++++++++++++++++++++-
- src/providers/ipa/ipa_subdomains_id.c |  16 +-
- src/providers/ipa/ipa_views.c         |  15 ++
- 3 files changed, 432 insertions(+), 4 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
-index cd65f5b462c102ed502a014789a7232a93389b68..5665a1835e8b0ab18325bfc68a8d8b5650730943 100644
---- a/src/providers/ipa/ipa_id.c
-+++ b/src/providers/ipa/ipa_id.c
-@@ -56,6 +56,13 @@ static const char *ipa_account_info_error_text(int ret, int *dp_error,
-     return default_text;
- }
- 
-+static struct tevent_req *
-+ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-+                             struct ipa_id_ctx *ipa_ctx, struct be_req *be_req,
-+                             struct be_acct_req *ar);
-+
-+static int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error);
-+
- static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx,
-                                                    struct tevent_context *ev,
-                                                    struct ipa_id_ctx *ipa_ctx,
-@@ -100,7 +107,9 @@ void ipa_account_info_handler(struct be_req *breq)
-     } else {
-         /* any account request is handled by sdap,
-          * any invalid request is caught there. */
--        return sdap_handle_account_info(breq, ctx, ctx->conn);
-+
-+        req = ipa_id_get_account_info_send(breq, be_ctx->ev, ipa_ctx, breq,
-+                                           ar);
-     }
- 
-     if (!req) {
-@@ -115,13 +124,18 @@ static void ipa_account_info_done(struct tevent_req *req)
-     struct be_req *breq = tevent_req_callback_data(req, struct be_req);
-     struct be_acct_req *ar = talloc_get_type(be_req_get_data(breq),
-                                              struct be_acct_req);
-+    struct be_ctx *be_ctx = be_req_get_be_ctx(breq);
-     const char *error_text;
-     int ret, dp_error;
- 
-     if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) {
-         ret = ipa_id_get_netgroup_recv(req, &dp_error);
-     } else {
--        ret = ipa_subdomain_account_recv(req, &dp_error);
-+        if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) {
-+            ret = ipa_subdomain_account_recv(req, &dp_error);
-+        } else {
-+            ret = ipa_id_get_account_info_recv(req, &dp_error);
-+        }
-     }
-     talloc_zfree(req);
- 
-@@ -130,6 +144,393 @@ static void ipa_account_info_done(struct tevent_req *req)
-     sdap_handler_done(breq, dp_error, ret, error_text);
- }
- 
-+struct ipa_id_get_account_info_state {
-+    struct tevent_context *ev;
-+    struct ipa_id_ctx *ipa_ctx;
-+    struct sdap_id_ctx *ctx;
-+    struct sdap_id_op *op;
-+    struct sysdb_ctx *sysdb;
-+    struct sss_domain_info *domain;
-+    struct be_req *be_req;
-+    struct be_acct_req *ar;
-+    const char *realm;
-+
-+    struct sysdb_attrs *override_attrs;
-+    struct ldb_message *obj_msg;
-+    int dp_error;
-+};
-+
-+static void ipa_id_get_account_info_connected(struct tevent_req *subreq);
-+static void ipa_id_get_account_info_got_override(struct tevent_req *subreq);
-+static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req,
-+                                                        struct be_acct_req *ar);
-+static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq);
-+static void ipa_id_get_account_info_done(struct tevent_req *subreq);
-+
-+static struct tevent_req *
-+ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-+                             struct ipa_id_ctx *ipa_ctx, struct be_req *be_req,
-+                             struct be_acct_req *ar)
-+{
-+    int ret;
-+    struct tevent_req *req;
-+    struct tevent_req *subreq;
-+    struct ipa_id_get_account_info_state *state;
-+
-+    req = tevent_req_create(memctx, &state,
-+                            struct ipa_id_get_account_info_state);
-+    if (req == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
-+        return NULL;
-+    }
-+
-+    state->ev = ev;
-+    state->ipa_ctx = ipa_ctx;
-+    state->ctx = ipa_ctx->sdap_id_ctx;
-+    state->dp_error = DP_ERR_FATAL;
-+
-+    state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
-+    if (state->op == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed.\n");
-+        ret = ENOMEM;
-+        goto fail;
-+    }
-+
-+    state->domain = find_domain_by_name(state->ctx->be->domain,
-+                                        ar->domain, true);
-+    if (state->domain == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
-+        ret = ENOMEM;
-+        goto fail;
-+    }
-+    state->sysdb = state->domain->sysdb;
-+    state->be_req = be_req;
-+    state->ar = ar;
-+    state->realm = dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
-+                                     IPA_KRB5_REALM);
-+    if (state->realm == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
-+        ret = EINVAL;
-+        goto fail;
-+    }
-+
-+    /* We can skip the override lookup and go directly to the original object
-+     * if
-+     * - the lookup is by SID
-+     * - there is no view set of it is the default view
-+     * - if the EXTRA_INPUT_MAYBE_WITH_VIEW flag is not set
-+     */
-+    if (state->ipa_ctx->view_name == NULL
-+            || state->ar->filter_type == BE_FILTER_SECID
-+            || strcmp(state->ipa_ctx->view_name,
-+                      SYSDB_DEFAULT_VIEW_NAME) == 0
-+            || state->ar->extra_value == NULL
-+            || strcmp(state->ar->extra_value,
-+                      EXTRA_INPUT_MAYBE_WITH_VIEW) != 0 ) {
-+        ret = ipa_id_get_account_info_get_original_step(req, ar);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "ipa_subdomain_account_get_original_step failed.\n");
-+            goto fail;
-+        }
-+    } else {
-+        subreq = sdap_id_op_connect_send(state->op, state, &ret);
-+        if (subreq == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n");
-+            goto fail;
-+        }
-+        tevent_req_set_callback(subreq, ipa_id_get_account_info_connected, req);
-+    }
-+
-+    return req;
-+
-+fail:
-+    tevent_req_error(req, ret);
-+    tevent_req_post(req, ev);
-+    return req;
-+}
-+
-+static void ipa_id_get_account_info_connected(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+    int dp_error = DP_ERR_FATAL;
-+    int ret;
-+
-+    ret = sdap_id_op_connect_recv(subreq, &dp_error);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n");
-+        goto fail;
-+    }
-+
-+    subreq = ipa_get_ad_override_send(state, state->ev, state->ctx,
-+                                      state->ipa_ctx->ipa_options, state->realm,
-+                                      state->ipa_ctx->view_name, state->ar);
-+    if (subreq == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
-+        ret = ENOMEM;
-+        goto fail;
-+    }
-+
-+    tevent_req_set_callback(subreq, ipa_id_get_account_info_got_override, req);
-+
-+    return;
-+
-+fail:
-+    state->dp_error = dp_error;
-+    tevent_req_error(req, ret);
-+    return;
-+}
-+
-+static void ipa_id_get_account_info_got_override(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+    int dp_error = DP_ERR_FATAL;
-+    int ret;
-+    const char *anchor = NULL;
-+    char *anchor_domain;
-+    char *ipa_uuid;
-+
-+    ret = ipa_get_ad_override_recv(subreq, &dp_error, state,
-+                                   &state->override_attrs);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
-+        goto fail;
-+    }
-+
-+    if (state->override_attrs != NULL) {
-+        ret = sysdb_attrs_get_string(state->override_attrs,
-+                                     SYSDB_OVERRIDE_ANCHOR_UUID,
-+                                     &anchor);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n");
-+            goto fail;
-+        }
-+
-+        ret = split_ipa_anchor(state, anchor, &anchor_domain, &ipa_uuid);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "Unsupported override anchor [%s].\n", anchor);
-+            ret = EINVAL;
-+            goto fail;
-+        }
-+
-+        if (strcmp(state->ar->domain, anchor_domain) == 0) {
-+
-+            ret = get_be_acct_req_for_uuid(state, ipa_uuid,
-+                                           state->ar->domain,
-+                                           &state->ar);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
-+                goto fail;
-+            }
-+        } else {
-+            DEBUG(SSSDBG_MINOR_FAILURE,
-+                  "Anchor from a different domain [%s], expected [%s]. " \
-+                  "This is currently not supported, continue lookup in " \
-+                  "local IPA domain.\n",
-+                  anchor_domain, state->ar->domain);
-+        }
-+    }
-+
-+    ret = ipa_id_get_account_info_get_original_step(req, state->ar);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "ipa_subdomain_account_get_original_step failed.\n");
-+        goto fail;
-+    }
-+
-+    return;
-+
-+fail:
-+    state->dp_error = dp_error;
-+    tevent_req_error(req, ret);
-+    return;
-+}
-+
-+static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req,
-+                                                         struct be_acct_req *ar)
-+{
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+    struct tevent_req *subreq;
-+
-+    subreq = sdap_handle_acct_req_send(state, state->be_req, ar,
-+                                       state->ipa_ctx->sdap_id_ctx,
-+                                       state->ipa_ctx->sdap_id_ctx->opts->sdom,
-+                                       state->ipa_ctx->sdap_id_ctx->conn, true);
-+    if (subreq == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n");
-+        return ENOMEM;
-+    }
-+    tevent_req_set_callback(subreq, ipa_id_get_account_info_orig_done, req);
-+
-+    return EOK;
-+}
-+
-+static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+    int dp_error = DP_ERR_FATAL;
-+    int ret;
-+    const char *uuid;
-+    const char *class;
-+    enum sysdb_member_type type;
-+
-+    ret = sdap_handle_acct_req_recv(subreq, &dp_error, NULL, NULL);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
-+        goto fail;
-+    }
-+
-+    ret = get_object_from_cache(state, state->domain, state->ar,
-+                                &state->obj_msg);
-+    if (ret == ENOENT) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n");
-+        tevent_req_done(req);
-+        return;
-+    } else if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
-+        goto fail;
-+    }
-+
-+    if (state->override_attrs == NULL) {
-+        uuid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_UUID, NULL);
-+        if (uuid == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find a UUID.\n");
-+            ret = EINVAL;
-+            goto fail;
-+        }
-+
-+        ret = get_be_acct_req_for_uuid(state, uuid, state->domain->name,
-+                                       &state->ar);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
-+            goto fail;
-+        }
-+
-+        subreq = ipa_get_ad_override_send(state, state->ev,
-+                                          state->ipa_ctx->sdap_id_ctx,
-+                                          state->ipa_ctx->ipa_options,
-+                                          state->realm,
-+                                          state->ipa_ctx->view_name,
-+                                          state->ar);
-+        if (subreq == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
-+            ret = ENOMEM;
-+            goto fail;
-+        }
-+        tevent_req_set_callback(subreq, ipa_id_get_account_info_done, req);
-+        return;
-+    } else {
-+        class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
-+                                            NULL);
-+        if (class == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
-+            ret = EINVAL;
-+            goto fail;
-+        }
-+
-+        if (strcmp(class, SYSDB_USER_CLASS) == 0) {
-+            type = SYSDB_MEMBER_USER;
-+        } else {
-+            type = SYSDB_MEMBER_GROUP;
-+        }
-+
-+        ret = sysdb_store_override(state->domain, state->ipa_ctx->view_name,
-+                                   type,
-+                                   state->override_attrs, state->obj_msg->dn);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
-+            goto fail;
-+        }
-+    }
-+
-+    state->dp_error = DP_ERR_OK;
-+    tevent_req_done(req);
-+    return;
-+
-+fail:
-+    state->dp_error = dp_error;
-+    tevent_req_error(req, ret);
-+    return;
-+}
-+
-+static void ipa_id_get_account_info_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+    int dp_error = DP_ERR_FATAL;
-+    int ret;
-+    const char *class;
-+    enum sysdb_member_type type;
-+
-+    ret = ipa_get_ad_override_recv(subreq, &dp_error, state,
-+                                   &state->override_attrs);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
-+        goto fail;
-+    }
-+
-+    class = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_OBJECTCLASS,
-+                                        NULL);
-+    if (class == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find an objectclass.\n");
-+        ret = EINVAL;
-+        goto fail;
-+    }
-+
-+    if (strcmp(class, SYSDB_USER_CLASS) == 0) {
-+        type = SYSDB_MEMBER_USER;
-+    } else {
-+        type = SYSDB_MEMBER_GROUP;
-+    }
-+
-+    ret = sysdb_store_override(state->domain, state->ipa_ctx->view_name,
-+                               type,
-+                               state->override_attrs, state->obj_msg->dn);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
-+        goto fail;
-+    }
-+
-+    state->dp_error = DP_ERR_OK;
-+    tevent_req_done(req);
-+    return;
-+
-+fail:
-+    state->dp_error = dp_error;
-+    tevent_req_error(req, ret);
-+    return;
-+}
-+
-+static int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error)
-+{
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+
-+    if (dp_error) {
-+        *dp_error = state->dp_error;
-+    }
-+
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+
-+    return EOK;
-+}
- 
- /* Request for netgroups
-  * - first start here and then go to ipa_netgroups.c
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index 891fc336483b507fd284b0c84b118534910ed9fc..ce5a6d1a1048eda4d8b7017bd92bc7ee76e66ef9 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -879,9 +879,21 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
- 
-         ret = EOK;
-         goto done;
--    }
-+    } else if (ar->filter_type == BE_FILTER_UUID) {
-+        ret = sysdb_search_object_by_uuid(mem_ctx, dom, ar->filter_value, attrs,
-+                                          &res);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "Failed to make request to our cache: [%d]: [%s]\n",
-+                   ret, sss_strerror(ret));
-+            goto done;
-+        }
- 
--    if (ar->filter_type == BE_FILTER_IDNUM) {
-+        *_msg = res->msgs[0];
-+
-+        ret = EOK;
-+        goto done;
-+    } else if (ar->filter_type == BE_FILTER_IDNUM) {
-         errno = 0;
-         id = strtouint32(ar->filter_value, NULL, 10);
-         if (errno != 0) {
-diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
-index ee586894ec61b1b1330816c628bbc9617d58e31e..c768186d7cf5e5a997e2ca27a167b62c8dc99b3f 100644
---- a/src/providers/ipa/ipa_views.c
-+++ b/src/providers/ipa/ipa_views.c
-@@ -125,6 +125,21 @@ static errno_t be_acct_req_to_override_filter(TALLOC_CTX *mem_ctx,
-         }
-         break;
- 
-+    case BE_FILTER_UUID:
-+        if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_BY_UUID) {
-+            filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=:IPA:%s:%s))",
-+                       ipa_opts->override_map[IPA_OC_OVERRIDE].name,
-+                       ipa_opts->override_map[IPA_AT_OVERRIDE_ANCHOR_UUID].name,
-+                       dp_opt_get_string(ipa_opts->basic, IPA_DOMAIN),
-+                       ar->filter_value);
-+        } else {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "Unexpected entry type [%d] for UUID filter.\n",
-+                  ar->entry_type);
-+            return EINVAL;
-+        }
-+        break;
-+
-     default:
-         DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain filter type.\n");
-         return EINVAL;
--- 
-1.9.3
-
diff --git a/SOURCES/0102-Enable-views-for-all-domains.patch b/SOURCES/0102-Enable-views-for-all-domains.patch
deleted file mode 100644
index 877c138..0000000
--- a/SOURCES/0102-Enable-views-for-all-domains.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 0271a86e2c1efd248b3c8df14178d0d401f92d08 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 7 Nov 2014 21:36:12 +0100
-Subject: [PATCH 102/104] Enable views for all domains
-
-Currently views and overrides were only available for sub-domains, this
-patch enables the lookup for the configured domains as well.
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/util/util.h | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/src/util/util.h b/src/util/util.h
-index ffc8a87eafa4c4b8271d195c7d27fd10f5aa3568..7c335b9a2ac2599304731082845fd382dc62465f 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -574,8 +574,7 @@ errno_t sssd_domain_init(TALLOC_CTX *mem_ctx,
- 
- #define IS_SUBDOMAIN(dom) ((dom)->parent != NULL)
- 
--/* Currently views are only supported for subdomains */
--#define DOM_HAS_VIEWS(dom) ((dom)->has_views && IS_SUBDOMAIN(dom))
-+#define DOM_HAS_VIEWS(dom) ((dom)->has_views)
- 
- errno_t sss_write_domain_mappings(struct sss_domain_info *domain);
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0102-nss-send-original-name-and-id-with-local-views-if-po.patch b/SOURCES/0102-nss-send-original-name-and-id-with-local-views-if-po.patch
new file mode 100644
index 0000000..475bf31
--- /dev/null
+++ b/SOURCES/0102-nss-send-original-name-and-id-with-local-views-if-po.patch
@@ -0,0 +1,191 @@
+From c12a2635adacbb321c4c2208160f2eb306333e71 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Sun, 11 Oct 2015 16:45:19 +0200
+Subject: [PATCH 102/104] nss: send original name and id with local views if
+ possible
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2833
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 2f793681b4debbe015815f908dc12c0463711609)
+---
+ src/responder/nss/nsssrv_cmd.c | 131 ++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 128 insertions(+), 3 deletions(-)
+
+diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
+index d177135db00369c2af69eb62f6a4a4aaf54ba510..39fd5b41a31796a05a1790e78cb6c425b39c47cb 100644
+--- a/src/responder/nss/nsssrv_cmd.c
++++ b/src/responder/nss/nsssrv_cmd.c
+@@ -599,6 +599,124 @@ is_refreshed_on_bg(enum sss_dp_acct_type req_type,
+ 
+ static void nsssrv_dp_send_acct_req_done(struct tevent_req *req);
+ 
++static void get_dp_name_and_id(TALLOC_CTX *mem_ctx,
++                              struct sss_domain_info *dom,
++                              enum sss_dp_acct_type req_type,
++                              const char *opt_name,
++                              uint32_t opt_id,
++                              const char **_name,
++                              uint32_t *_id)
++{
++    TALLOC_CTX *tmp_ctx;
++    struct ldb_result *res = NULL;
++    const char *attr;
++    const char *name;
++    uint32_t id;
++    errno_t ret;
++
++    /* First set the same values to make things easier. */
++    *_name = opt_name;
++    *_id = opt_id;
++
++    if (!DOM_HAS_VIEWS(dom) || !is_local_view(dom->view_name)) {
++        DEBUG(SSSDBG_TRACE_FUNC, "Not a LOCAL view, continuing with "
++              "provided values.\n");
++        return;
++    }
++
++    tmp_ctx = talloc_new(NULL);
++    if (tmp_ctx == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
++        return;
++    }
++
++    if (opt_name != NULL) {
++        switch (req_type) {
++        case SSS_DP_USER:
++        case SSS_DP_INITGROUPS:
++            ret = sysdb_getpwnam_with_views(tmp_ctx, dom, opt_name, &res);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_CONF_SETTINGS,
++                      "sysdb_getpwnam_with_views() failed [%d]: %s\n",
++                      ret, sss_strerror(ret));
++                goto done;
++            }
++            break;
++        case SSS_DP_GROUP:
++            ret = sysdb_getgrnam_with_views(tmp_ctx, dom, opt_name, &res);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_CONF_SETTINGS,
++                      "sysdb_getgrnam_with_views() failed [%d]: %s\n",
++                      ret, sss_strerror(ret));
++                goto done;
++            }
++            break;
++        default:
++            goto done;
++        }
++
++        if (res == NULL || res->count != 1) {
++            /* This should not happen with LOCAL view and overridden value. */
++            DEBUG(SSSDBG_TRACE_FUNC, "Entry is missing?! Continuing with "
++                  "provided values.\n");
++            goto done;
++        }
++
++        name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
++        if (name == NULL) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n");
++            goto done;
++        }
++
++        *_name = talloc_steal(mem_ctx, name);
++    } else if (opt_id != 0) {
++        switch (req_type) {
++        case SSS_DP_USER:
++            ret = sysdb_getpwuid_with_views(tmp_ctx, dom, opt_id, &res);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_CONF_SETTINGS,
++                      "sysdb_getpwuid_with_views() failed [%d]: %s\n",
++                      ret, sss_strerror(ret));
++                goto done;
++            }
++
++            attr = SYSDB_UIDNUM;
++            break;
++        case SSS_DP_GROUP:
++            ret = sysdb_getgrgid_with_views(tmp_ctx, dom, opt_id, &res);
++            if (ret != EOK) {
++                DEBUG(SSSDBG_CONF_SETTINGS,
++                      "sysdb_getgrgid_with_views() failed [%d]: %s\n",
++                      ret, sss_strerror(ret));
++                goto done;
++            }
++
++            attr = SYSDB_GIDNUM;
++            break;
++        default:
++            goto done;
++        }
++
++        if (res == NULL || res->count != 1) {
++            /* This should not happen with LOCAL view and overridden value. */
++            DEBUG(SSSDBG_TRACE_FUNC, "Entry is missing?! Continuing with "
++                  "provided values.\n");
++            goto done;
++        }
++
++        id = ldb_msg_find_attr_as_uint64(res->msgs[0], attr, 0);
++        if (id == 0) {
++            DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n");
++            goto done;
++        }
++
++        *_id = id;
++    }
++
++done:
++    talloc_free(tmp_ctx);
++}
++
+ /* FIXME: do not check res->count, but get in a msgs and check in parent */
+ errno_t check_cache(struct nss_dom_ctx *dctx,
+                     struct nss_ctx *nctx,
+@@ -616,6 +734,8 @@ errno_t check_cache(struct nss_dom_ctx *dctx,
+     struct tevent_req *req = NULL;
+     struct dp_callback_ctx *cb_ctx = NULL;
+     uint64_t cacheExpire = 0;
++    const char *name = opt_name;
++    uint32_t id = opt_id;
+ 
+     /* when searching for a user or netgroup, more than one reply is a
+      * db error
+@@ -627,6 +747,11 @@ errno_t check_cache(struct nss_dom_ctx *dctx,
+         return ENOENT;
+     }
+ 
++    /* In case of local view we have to always contant DP with the original
++     * name or id. */
++    get_dp_name_and_id(dctx->cmdctx, dctx->domain, req_type, opt_name, opt_id,
++                       &name, &id);
++
+     /* if we have any reply let's check cache validity, but ignore netgroups
+      * if refresh_expired_interval is set (which implies that another method
+      * is used to refresh netgroups)
+@@ -671,10 +796,10 @@ errno_t check_cache(struct nss_dom_ctx *dctx,
+          * immediately.
+          */
+         DEBUG(SSSDBG_TRACE_FUNC,
+-             "Performing midpoint cache update on [%s]\n", opt_name);
++             "Performing midpoint cache update on [%s]\n", name);
+ 
+         req = sss_dp_get_account_send(cctx, cctx->rctx, dctx->domain, true,
+-                                      req_type, opt_name, opt_id, extra);
++                                      req_type, name, id, extra);
+         if (!req) {
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "Out of memory sending out-of-band data provider "
+@@ -703,7 +828,7 @@ errno_t check_cache(struct nss_dom_ctx *dctx,
+         }
+ 
+         req = sss_dp_get_account_send(cctx, cctx->rctx, dctx->domain, true,
+-                                      req_type, opt_name, opt_id, extra);
++                                      req_type, name, id, extra);
+         if (!req) {
+             DEBUG(SSSDBG_CRIT_FAILURE,
+                   "Out of memory sending data provider request\n");
+-- 
+2.4.3
+
diff --git a/SOURCES/0103-MAN-Update-case_sensitive-Preserving-in-man-pages.patch b/SOURCES/0103-MAN-Update-case_sensitive-Preserving-in-man-pages.patch
deleted file mode 100644
index e91c003..0000000
--- a/SOURCES/0103-MAN-Update-case_sensitive-Preserving-in-man-pages.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 834ab87e8f5a3f9937e0997cb5427e205959d344 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Wed, 12 Nov 2014 15:47:11 +0100
-Subject: [PATCH 103/104] MAN: Update case_sensitive=Preserving in man pages.
-
-https://fedorahosted.org/sssd/ticket/2462
----
- src/man/sssd.conf.5.xml | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index fbaca66724f7023dfa6068c225d6f61af0e662bb..5f801f25690f4f7c15b8e030968c6d052daa3812 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -2013,8 +2013,11 @@ fallback_homedir = /home/%u
-                                 <listitem>
-                                     <para>
-                                         Same as False (case insensitive), but
--                                        does not lowercase names in the output
--                                        of getpwnam and getgrnam.
-+                                        does not lowercase names in the result
-+                                        of NSS operations. Note that name
-+                                        aliases (and in case of services also
-+                                        protocol names) are still lowercased in
-+                                        the output.
-                                     </para>
-                                 </listitem>
-                             </varlistentry>
--- 
-1.9.3
-
diff --git a/SOURCES/0103-sudo-search-with-view-even-if-user-is-found.patch b/SOURCES/0103-sudo-search-with-view-even-if-user-is-found.patch
new file mode 100644
index 0000000..fe9f9bf
--- /dev/null
+++ b/SOURCES/0103-sudo-search-with-view-even-if-user-is-found.patch
@@ -0,0 +1,35 @@
+From f69e9a566540896682c1021de92e5eec6a95dd9d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Sun, 11 Oct 2015 17:38:34 +0200
+Subject: [PATCH 103/104] sudo: search with view even if user is found
+
+If an overriden name is provided and the user is already cache we fail
+to refresh it since we won't search with VIEW flag. This patch fix
+it.
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit 51a0e3a2ef9186d19cbc28d87fe6fc5d5998a0a7)
+---
+ src/responder/sudo/sudosrv_get_sudorules.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
+index a0b09e69b71f963c353c9c6331c0708cc364924c..cc06977d97e3319584251bdab26e85855d275e8a 100644
+--- a/src/responder/sudo/sudosrv_get_sudorules.c
++++ b/src/responder/sudo/sudosrv_get_sudorules.c
+@@ -160,7 +160,10 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
+         if ((user->count == 0 || cache_expire < time(NULL))
+             && dctx->check_provider) {
+ 
+-            if (DOM_HAS_VIEWS(dom) && user->count == 0) {
++            if (DOM_HAS_VIEWS(dom) && (user->count == 0
++                    || ldb_msg_find_attr_as_string(user->msgs[0],
++                                                   OVERRIDE_PREFIX SYSDB_NAME,
++                                                   NULL) != NULL)) {
+                 extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
+             }
+ 
+-- 
+2.4.3
+
diff --git a/SOURCES/0104-Man-debug_timestamps-and-debug_microseconds.patch b/SOURCES/0104-Man-debug_timestamps-and-debug_microseconds.patch
deleted file mode 100644
index f8d95aa..0000000
--- a/SOURCES/0104-Man-debug_timestamps-and-debug_microseconds.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 4eca230459561aa3b9bac96eebcbdd03b65777b2 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Thu, 13 Nov 2014 17:41:56 +0100
-Subject: [PATCH 104/104] Man: debug_timestamps and debug_microseconds
-
-Add note that these two options are ignored if
-journald is used.
-
-https://fedorahosted.org/sssd/ticket/2498
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/man/sssd.conf.5.xml | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index 5f801f25690f4f7c15b8e030968c6d052daa3812..3525d78caff28fd05cc18061d023fec3c50d1a47 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -73,7 +73,9 @@
-                     <term>debug_timestamps (bool)</term>
-                     <listitem>
-                         <para>
--                            Add a timestamp to the debug messages
-+                            Add a timestamp to the debug messages.
-+                            If journald is enabled for SSSD debug logging this
-+                            option is ignored.
-                         </para>
-                         <para>
-                             Default: true
-@@ -84,7 +86,9 @@
-                     <term>debug_microseconds (bool)</term>
-                     <listitem>
-                         <para>
--                            Add microseconds to the timestamp in debug messages
-+                            Add microseconds to the timestamp in debug messages.
-+                            If journald is enabled for SSSD debug logging this
-+                            option is ignored.
-                         </para>
-                         <para>
-                             Default: false
--- 
-1.9.3
-
diff --git a/SOURCES/0104-sudo-send-original-name-and-id-with-local-views-if-p.patch b/SOURCES/0104-sudo-send-original-name-and-id-with-local-views-if-p.patch
new file mode 100644
index 0000000..241248c
--- /dev/null
+++ b/SOURCES/0104-sudo-send-original-name-and-id-with-local-views-if-p.patch
@@ -0,0 +1,60 @@
+From ea4b1387c604093036559a1bfc0368c70d73fc4f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Sun, 11 Oct 2015 17:53:28 +0200
+Subject: [PATCH 104/104] sudo: send original name and id with local views if
+ possible
+
+Resolves:
+https://fedorahosted.org/sssd/ticket/2833
+
+Reviewed-by: Sumit Bose <sbose@redhat.com>
+Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
+(cherry picked from commit fb8985a3a3a267940760967beaf8af3979ce91ea)
+---
+ src/responder/sudo/sudosrv_get_sudorules.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
+index cc06977d97e3319584251bdab26e85855d275e8a..c3336960eeac18ee63167de81891984aa764540c 100644
+--- a/src/responder/sudo/sudosrv_get_sudorules.c
++++ b/src/responder/sudo/sudosrv_get_sudorules.c
+@@ -79,6 +79,7 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
+     struct dp_callback_ctx *cb_ctx;
+     const char *original_name = NULL;
+     const char *extra_flag = NULL;
++    const char *search_name = NULL;
+     char *name = NULL;
+     uid_t uid = 0;
+     errno_t ret;
+@@ -160,16 +161,23 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
+         if ((user->count == 0 || cache_expire < time(NULL))
+             && dctx->check_provider) {
+ 
+-            if (DOM_HAS_VIEWS(dom) && (user->count == 0
+-                    || ldb_msg_find_attr_as_string(user->msgs[0],
+-                                                   OVERRIDE_PREFIX SYSDB_NAME,
+-                                                   NULL) != NULL)) {
++            search_name = cmd_ctx->username;
++            if (is_local_view(dom->view_name)) {
++                /* Search with original name in case of local view. */
++                if (user->count != 0) {
++                    search_name = ldb_msg_find_attr_as_string(user->msgs[0],
++                                                              SYSDB_NAME, NULL);
++                }
++            } else if (DOM_HAS_VIEWS(dom) && (user->count == 0
++                || ldb_msg_find_attr_as_string(user->msgs[0],
++                                               OVERRIDE_PREFIX SYSDB_NAME,
++                                               NULL) != NULL)) {
+                 extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
+             }
+ 
+             dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx,
+                                             dom, false, SSS_DP_INITGROUPS,
+-                                            cmd_ctx->username, 0, extra_flag);
++                                            search_name, 0, extra_flag);
+             if (!dpreq) {
+                 DEBUG(SSSDBG_CRIT_FAILURE,
+                       "Out of memory sending data provider request\n");
+-- 
+2.4.3
+
diff --git a/SOURCES/0105-sss_client-Extract-destroying-of-mmap-cache-to-funct.patch b/SOURCES/0105-sss_client-Extract-destroying-of-mmap-cache-to-funct.patch
deleted file mode 100644
index dd197e2..0000000
--- a/SOURCES/0105-sss_client-Extract-destroying-of-mmap-cache-to-funct.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From 82d37e1a84202d3609ceb70aaf0893199ec0e464 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 21 Nov 2014 14:00:23 +0100
-Subject: [PATCH 105/112] sss_client: Extract destroying of mmap cache to
- function
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/sss_client/nss_mc_common.c | 30 ++++++++++++++----------------
- 1 file changed, 14 insertions(+), 16 deletions(-)
-
-diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c
-index 6c9b35de280c637bf957207993e539c889b16c23..9c6e1af1642275fc7738b51d7ca80d712d49b2ac 100644
---- a/src/sss_client/nss_mc_common.c
-+++ b/src/sss_client/nss_mc_common.c
-@@ -102,6 +102,18 @@ errno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx)
-     return 0;
- }
- 
-+static void sss_nss_mc_destroy_ctx(struct sss_cli_mc_ctx *ctx)
-+{
-+    if ((ctx->mmap_base != NULL) && (ctx->mmap_size != 0)) {
-+        munmap(ctx->mmap_base, ctx->mmap_size);
-+    }
-+    if (ctx->fd != -1) {
-+        close(ctx->fd);
-+    }
-+    memset(ctx, 0, sizeof(struct sss_cli_mc_ctx));
-+    ctx->fd = -1;
-+}
-+
- static errno_t sss_nss_mc_init_ctx(const char *name,
-                                    struct sss_cli_mc_ctx *ctx)
- {
-@@ -157,14 +169,7 @@ static errno_t sss_nss_mc_init_ctx(const char *name,
- 
- done:
-     if (ret) {
--        if ((ctx->mmap_base != NULL) && (ctx->mmap_size != 0)) {
--            munmap(ctx->mmap_base, ctx->mmap_size);
--        }
--        if (ctx->fd != -1) {
--            close(ctx->fd);
--        }
--        memset(ctx, 0, sizeof(struct sss_cli_mc_ctx));
--        ctx->fd = -1;
-+        sss_nss_mc_destroy_ctx(ctx);
-     }
-     free(file);
-     sss_nss_unlock();
-@@ -191,14 +196,7 @@ errno_t sss_nss_mc_get_ctx(const char *name, struct sss_cli_mc_ctx *ctx)
- 
- done:
-     if (ret) {
--        if ((ctx->mmap_base != NULL) && (ctx->mmap_size != 0)) {
--            munmap(ctx->mmap_base, ctx->mmap_size);
--        }
--        if (ctx->fd != -1) {
--            close(ctx->fd);
--        }
--        memset(ctx, 0, sizeof(struct sss_cli_mc_ctx));
--        ctx->fd = -1;
-+        sss_nss_mc_destroy_ctx(ctx);
-     }
-     return ret;
- }
--- 
-1.9.3
-
diff --git a/SOURCES/0106-sss_client-Fix-race-condition-in-memory-cache.patch b/SOURCES/0106-sss_client-Fix-race-condition-in-memory-cache.patch
deleted file mode 100644
index 40d08e9..0000000
--- a/SOURCES/0106-sss_client-Fix-race-condition-in-memory-cache.patch
+++ /dev/null
@@ -1,243 +0,0 @@
-From 15240b29d55cfd775221cc6482407c1172e2a5a1 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 21 Nov 2014 11:28:36 +0100
-Subject: [PATCH 106/112] sss_client: Fix race condition in memory cache
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Thread safe initialisation was fixed in ticket #2380, but there is
-still race condition in reinitialisation.
-
-If caches is invalidated with command sss_cache -U (-G or -E) then
-client code will need to reinitialize fast memory cache.
-Let say we have two threads. The 1st thread find out that memory cache
-should be reinitialized; therefore the fast memory cached is unmapped
-and context destroyed. In the same time, 2nd thread tried to check
-header of memory cache whether it is initialized and valid. As a result
-of previously unmapped memory the 2nd thread access
-out of bound memory (SEGFAULT).
-
-The destroying of fast memory cache cannot be done any time. We need
-to be sure that there isn't any other thread which uses mmaped memory.
-The new counter of active threads was added for this purpose. The state
-of fast memory cache was converted from boolean to three value state
-(UNINITIALIZED, INITIALIZED, RECYCLED)
-UNINITIALIZED
-    - the fast memory cache need to be initialized.
-    - if there is a problem with initialisation the state will not change
-    - after successful initialisation, the state will change to INITIALIZED
-INITIALIZED
-    - if the cahe was invalidated or there is any other problem was
-      detected in memory cache header the state will change to RECYCLED
-      and memory cache IS NOT destroyed.
-RECYCLED
-    - nothing will be done is there are any active threads which may use
-      the data from mmaped memory
-    - if there aren't active threads the fast memory cahe is destroyed and
-      state is changed to UNINITIALIZED.
-
-https://fedorahosted.org/sssd/ticket/2445
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/sss_client/nss_mc.h        | 10 ++++++++-
- src/sss_client/nss_mc_common.c | 46 ++++++++++++++++++++++++++++++++++--------
- src/sss_client/nss_mc_group.c  |  8 ++++++--
- src/sss_client/nss_mc_passwd.c |  8 ++++++--
- 4 files changed, 59 insertions(+), 13 deletions(-)
-
-diff --git a/src/sss_client/nss_mc.h b/src/sss_client/nss_mc.h
-index 685cc41c0530750d890050f0917dc88be14d96ea..050bd4100dec091cb096a7d97bfe6615b12654da 100644
---- a/src/sss_client/nss_mc.h
-+++ b/src/sss_client/nss_mc.h
-@@ -33,9 +33,15 @@
- typedef int errno_t;
- #endif
- 
-+enum sss_mc_state {
-+    UNINITIALIZED = 0,
-+    INITIALIZED,
-+    RECYCLED,
-+};
-+
- /* common stuff */
- struct sss_cli_mc_ctx {
--    bool initialized;
-+    enum sss_mc_state initialized;
-     int fd;
- 
-     uint32_t seed;          /* seed from the tables header */
-@@ -48,6 +54,8 @@ struct sss_cli_mc_ctx {
- 
-     uint32_t *hash_table;   /* hash table address (in mmap) */
-     uint32_t ht_size;       /* size of hash table */
-+
-+    uint32_t active_threads; /* count of threads which use memory cache */
- };
- 
- errno_t sss_nss_mc_get_ctx(const char *name, struct sss_cli_mc_ctx *ctx);
-diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c
-index 9c6e1af1642275fc7738b51d7ca80d712d49b2ac..89ff6b46e2abee03039cfd632ef50231eab92eec 100644
---- a/src/sss_client/nss_mc_common.c
-+++ b/src/sss_client/nss_mc_common.c
-@@ -123,7 +123,7 @@ static errno_t sss_nss_mc_init_ctx(const char *name,
- 
-     sss_nss_lock();
-     /* check if ctx is initialised by previous thread. */
--    if (ctx->initialized) {
-+    if (ctx->initialized != UNINITIALIZED) {
-         ret = sss_nss_check_header(ctx);
-         goto done;
-     }
-@@ -163,7 +163,7 @@ static errno_t sss_nss_mc_init_ctx(const char *name,
-         goto done;
-     }
- 
--    ctx->initialized = true;
-+    ctx->initialized = INITIALIZED;
- 
-     ret = 0;
- 
-@@ -181,22 +181,52 @@ errno_t sss_nss_mc_get_ctx(const char *name, struct sss_cli_mc_ctx *ctx)
- {
-     char *envval;
-     int ret;
-+    bool need_decrement = false;
- 
-     envval = getenv("SSS_NSS_USE_MEMCACHE");
-     if (envval && strcasecmp(envval, "NO") == 0) {
-         return EPERM;
-     }
- 
--    if (ctx->initialized) {
-+    switch (ctx->initialized) {
-+    case UNINITIALIZED:
-+        __sync_add_and_fetch(&ctx->active_threads, 1);
-+        ret = sss_nss_mc_init_ctx(name, ctx);
-+        if (ret) {
-+            need_decrement = true;
-+        }
-+        break;
-+    case INITIALIZED:
-+        __sync_add_and_fetch(&ctx->active_threads, 1);
-         ret = sss_nss_check_header(ctx);
--        goto done;
-+        if (ret) {
-+            need_decrement = true;
-+        }
-+        break;
-+    case RECYCLED:
-+        /* we need to safely destroy memory cache */
-+        ret = EAGAIN;
-+        break;
-+    default:
-+        ret = EFAULT;
-     }
- 
--    ret = sss_nss_mc_init_ctx(name, ctx);
--
--done:
-     if (ret) {
--        sss_nss_mc_destroy_ctx(ctx);
-+        if (ctx->initialized == INITIALIZED) {
-+            ctx->initialized = RECYCLED;
-+        }
-+        if (ctx->initialized == RECYCLED && ctx->active_threads == 0) {
-+            /* just one thread should call munmap */
-+            sss_nss_lock();
-+            if (ctx->initialized == RECYCLED) {
-+                sss_nss_mc_destroy_ctx(ctx);
-+            }
-+            sss_nss_unlock();
-+        }
-+        if (need_decrement) {
-+            /* In case of error, we will not touch mmapped area => decrement */
-+            __sync_sub_and_fetch(&ctx->active_threads, 1);
-+        }
-     }
-     return ret;
- }
-diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c
-index 268b40ef02f2a621c4f61755ce4dfe2c3786bfa6..e0fdb97f628ac19741409be29566e4af5a391f74 100644
---- a/src/sss_client/nss_mc_group.c
-+++ b/src/sss_client/nss_mc_group.c
-@@ -29,7 +29,8 @@
- #include "nss_mc.h"
- #include "util/util_safealign.h"
- 
--struct sss_cli_mc_ctx gr_mc_ctx = { false, -1, 0, NULL, 0, NULL, 0, NULL, 0 };
-+struct sss_cli_mc_ctx gr_mc_ctx = { UNINITIALIZED, -1, 0, NULL, 0, NULL, 0,
-+                                    NULL, 0, 0 };
- 
- static errno_t sss_nss_mc_parse_result(struct sss_mc_rec *rec,
-                                        struct group *result,
-@@ -176,6 +177,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
- 
- done:
-     free(rec);
-+    __sync_sub_and_fetch(&gr_mc_ctx.active_threads, 1);
-     return ret;
- }
- 
-@@ -198,7 +200,8 @@ errno_t sss_nss_mc_getgrgid(gid_t gid,
- 
-     len = snprintf(gidstr, 11, "%ld", (long)gid);
-     if (len > 10) {
--        return EINVAL;
-+        ret = EINVAL;
-+        goto done;
-     }
- 
-     /* hashes are calculated including the NULL terminator */
-@@ -242,6 +245,7 @@ errno_t sss_nss_mc_getgrgid(gid_t gid,
- 
- done:
-     free(rec);
-+    __sync_sub_and_fetch(&gr_mc_ctx.active_threads, 1);
-     return ret;
- }
- 
-diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c
-index fa19afc3c0e468430183ed3f13b80e086251ee01..10e43e2af43c5e7f1738e281b3ed260d89f3a004 100644
---- a/src/sss_client/nss_mc_passwd.c
-+++ b/src/sss_client/nss_mc_passwd.c
-@@ -28,7 +28,8 @@
- #include <time.h>
- #include "nss_mc.h"
- 
--struct sss_cli_mc_ctx pw_mc_ctx = { false, -1, 0, NULL, 0, NULL, 0, NULL, 0 };
-+struct sss_cli_mc_ctx pw_mc_ctx = { UNINITIALIZED, -1, 0, NULL, 0, NULL, 0,
-+                                    NULL, 0, 0 };
- 
- static errno_t sss_nss_mc_parse_result(struct sss_mc_rec *rec,
-                                        struct passwd *result,
-@@ -170,6 +171,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
- 
- done:
-     free(rec);
-+    __sync_sub_and_fetch(&pw_mc_ctx.active_threads, 1);
-     return ret;
- }
- 
-@@ -192,7 +194,8 @@ errno_t sss_nss_mc_getpwuid(uid_t uid,
- 
-     len = snprintf(uidstr, 11, "%ld", (long)uid);
-     if (len > 10) {
--        return EINVAL;
-+        ret = EINVAL;
-+        goto done;
-     }
- 
-     /* hashes are calculated including the NULL terminator */
-@@ -236,6 +239,7 @@ errno_t sss_nss_mc_getpwuid(uid_t uid,
- 
- done:
-     free(rec);
-+    __sync_sub_and_fetch(&pw_mc_ctx.active_threads, 1);
-     return ret;
- }
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0107-IPA-Handle-IPA-groups-returned-from-extop-plugin.patch b/SOURCES/0107-IPA-Handle-IPA-groups-returned-from-extop-plugin.patch
deleted file mode 100644
index fc3b5c3..0000000
--- a/SOURCES/0107-IPA-Handle-IPA-groups-returned-from-extop-plugin.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From de740042c4a03f5683567939e73f6a8eb10f3ff1 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 23 Nov 2014 20:47:59 +0100
-Subject: [PATCH 107/112] IPA: Handle IPA groups returned from extop plugin
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 13 +++++++++----
- 1 file changed, 9 insertions(+), 4 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 2c31120b196353df52c87ef5b924a80bda134a17..0eab1afc36e4d2c1d770c596c512a641fd276425 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -960,10 +960,15 @@ static errno_t ipa_s2n_get_groups_step(struct tevent_req *req)
-         return ret;
-     }
- 
--    state->obj_domain = find_domain_by_name(parent_domain, domain_name, true);
--    if (state->obj_domain == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
--        return ENOMEM;
-+    if (domain_name) {
-+        state->obj_domain = find_domain_by_name(parent_domain,
-+                                                domain_name, true);
-+        if (state->obj_domain == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "find_domain_by_name failed.\n");
-+            return ENOMEM;
-+        }
-+    } else {
-+        state->obj_domain = parent_domain;
-     }
- 
-     state->req_input.inp.name = group_name;
--- 
-1.9.3
-
diff --git a/SOURCES/0108-Fix-KRB5_CONF_PATH.patch b/SOURCES/0108-Fix-KRB5_CONF_PATH.patch
deleted file mode 100644
index 92e907b..0000000
--- a/SOURCES/0108-Fix-KRB5_CONF_PATH.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 6b67b3bd49b826e572a1d136f8da48f947a79313 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 21 Nov 2014 15:22:24 +0100
-Subject: [PATCH 108/112] Fix KRB5_CONF_PATH
-
-Currently a shell/Makefile variable is used in the definition of
-KRB5_CONF_PATH for C code. This patch replaces it with a complier macro.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                 | 1 +
- src/conf_macros.m4          | 2 +-
- src/tests/cwrap/Makefile.am | 2 ++
- 3 files changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 53ace65b9a9647ffdaff0776d5a55d3e7393a38c..56a562c761d39ff5f54bc034ede563c40bf21ef8 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -386,6 +386,7 @@ AM_CPPFLAGS = \
-     $(JOURNALD_CFLAGS) \
-     -DLIBDIR=\"$(libdir)\" \
-     -DVARDIR=\"$(localstatedir)\" \
-+    -DSYSCONFDIR=\"$(sysconfdir)\" \
-     -DSHLIBEXT=\"$(SHLIBEXT)\" \
-     -DSSSD_LIBEXEC_PATH=\"$(sssdlibexecdir)\" \
-     -DSSSD_CONF_DIR=\"$(sssdconfdir)\" \
-diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
-index fbee81f56e484b618379f7c987ecee50ae48917e..df9d1ddf89be38709e56ad4b214e5f7c6cbb0f97 100644
---- a/src/conf_macros.m4
-+++ b/src/conf_macros.m4
-@@ -353,7 +353,7 @@ AC_DEFUN([WITH_KRB5_CONF],
-                 ]
-                )
- 
--    KRB5_CONF_PATH="${sysconfdir}/krb5.conf"
-+    KRB5_CONF_PATH="\"SYSCONFDIR\"/krb5.conf"
-     if test x"$with_krb5_conf" != x; then
-         KRB5_CONF_PATH=$with_krb5_conf
-     fi
-diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
-index 02be67387110c0a440b647c35bba0c10e89e699d..46abab5ae32189b0561d1901407d2bb38a1ec4c0 100644
---- a/src/tests/cwrap/Makefile.am
-+++ b/src/tests/cwrap/Makefile.am
-@@ -4,7 +4,9 @@ AM_CPPFLAGS = \
-     -I$(top_srcdir)/src \
-     -I. \
-     -DLOCALEDIR=\"$(localedir)\" \
-+    -DLIBDIR=\"$(libdir)\" \
-     -DVARDIR=\"$(localstatedir)\" \
-+    -DSYSCONFDIR=\"$(sysconfdir)\" \
-     $(DBUS_CFLAGS) \
-     $(GLIB2_CFLAGS) \
-     $(NULL)
--- 
-1.9.3
-
diff --git a/SOURCES/0109-AD-IPA-add-krb5_confd_path-configuration-option.patch b/SOURCES/0109-AD-IPA-add-krb5_confd_path-configuration-option.patch
deleted file mode 100644
index e37de2c..0000000
--- a/SOURCES/0109-AD-IPA-add-krb5_confd_path-configuration-option.patch
+++ /dev/null
@@ -1,464 +0,0 @@
-From c230bce668a65649e9f2ca8b4424148ef9e19491 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 21 Nov 2014 18:07:10 +0100
-Subject: [PATCH 109/112] AD/IPA: add krb5_confd_path configuration option
-
-With this new parameter the directory where Kerberos configuration
-snippets are created can be specified.
-
-Fixes https://fedorahosted.org/sssd/ticket/2473
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/config/SSSDConfig/__init__.py.in    |   1 +
- src/config/etc/sssd.api.d/sssd-ad.conf  |   1 +
- src/config/etc/sssd.api.d/sssd-ipa.conf |   1 +
- src/man/sssd-ad.5.xml                   |  18 ++++
- src/man/sssd-ipa.5.xml                  |  18 ++++
- src/providers/ad/ad_common.h            |   1 +
- src/providers/ad/ad_opts.h              |   1 +
- src/providers/ad/ad_subdomains.c        |   8 ++
- src/providers/ipa/ipa_common.h          |   1 +
- src/providers/ipa/ipa_opts.h            |   1 +
- src/providers/ipa/ipa_subdomains.c      |   8 ++
- src/tests/cmocka/test_utils.c           |  48 +++++++++++
- src/util/domain_info_utils.c            | 146 +++++++++++++++++++++++++++++++-
- src/util/util.h                         |   6 ++
- 14 files changed, 256 insertions(+), 3 deletions(-)
-
-diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
-index 283ed2d37c894db95bac38c23d25c4ac8d1f4a40..500bd717fec7abcaafd5153ccca7847b91e208ad 100644
---- a/src/config/SSSDConfig/__init__.py.in
-+++ b/src/config/SSSDConfig/__init__.py.in
-@@ -195,6 +195,7 @@ option_strings = {
-     'krb5_realm' : _('Kerberos realm'),
-     'krb5_auth_timeout' : _('Authentication timeout'),
-     'krb5_use_kdcinfo' : _('Whether to create kdcinfo files'),
-+    'krb5_confd_path' : _('Where to drop krb5 config snippets'),
- 
-     # [provider/krb5/auth]
-     'krb5_ccachedir' : _('Directory to store credential caches'),
-diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
-index 3daa2560b14d74f7686ed47cf1b09e2005eb8917..3496fb4006697d380f7c9729ed9997272cbce2ea 100644
---- a/src/config/etc/sssd.api.d/sssd-ad.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
-@@ -54,6 +54,7 @@ ldap_page_size = int, None, false
- ldap_deref_threshold = int, None, false
- ldap_connection_expire_timeout = int, None, false
- ldap_disable_paging = bool, None, false
-+krb5_confd_path = str, None, false
- 
- [provider/ad/id]
- ldap_search_timeout = int, None, false
-diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
-index 5df52581e67657e41e2f08820b885f100ccd7ca9..2a3b7ef1519e3476cb4b432336da0c359b1844ba 100644
---- a/src/config/etc/sssd.api.d/sssd-ipa.conf
-+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
-@@ -51,6 +51,7 @@ ldap_page_size = int, None, false
- ldap_deref_threshold = int, None, false
- ldap_connection_expire_timeout = int, None, false
- ldap_disable_paging = bool, None, false
-+krb5_confd_path = str, None, false
- 
- [provider/ipa/id]
- ldap_search_timeout = int, None, false
-diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
-index f63a496d9c7294749fb046995985985e2cae4a57..4e29d4f75cae5bf17e4bb85fa46c921b25ee8047 100644
---- a/src/man/sssd-ad.5.xml
-+++ b/src/man/sssd-ad.5.xml
-@@ -778,6 +778,24 @@ FOREST:EXAMPLE.COM:(memberOf=cn=admins,ou=groups,dc=example,dc=com)
-                         </para>
-                     </listitem>
-                 </varlistentry>
-+
-+                <varlistentry>
-+                    <term>krb5_confd_path (string)</term>
-+                    <listitem>
-+                        <para>
-+                            Absolute path of a directory where SSSD should place
-+                            Kerberos configuration snippets.
-+                        </para>
-+                        <para>
-+                            To disable the creation of the configuration
-+                            snippets set the parameter to 'none'.
-+                        </para>
-+                        <para>
-+                            Default: not set (krb5.include.d subdirectory of
-+                            SSSD's pubconf directory)
-+                        </para>
-+                    </listitem>
-+                </varlistentry>
-             </variablelist>
-         </para>
-     </refsect1>
-diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
-index e8a716c4104b8038e354b8ae544a04d6773e708b..2d8654a3cde76ab205766f8fdcb836aa1002cd43 100644
---- a/src/man/sssd-ipa.5.xml
-+++ b/src/man/sssd-ipa.5.xml
-@@ -447,6 +447,24 @@
-                 </varlistentry>
- 
-                 <varlistentry>
-+                    <term>krb5_confd_path (string)</term>
-+                    <listitem>
-+                        <para>
-+                            Absolute path of a directory where SSSD should place
-+                            Kerberos configuration snippets.
-+                        </para>
-+                        <para>
-+                            To disable the creation of the configuration
-+                            snippets set the parameter to 'none'.
-+                        </para>
-+                        <para>
-+                            Default: not set (krb5.include.d subdirectory of
-+                            SSSD's pubconf directory)
-+                        </para>
-+                    </listitem>
-+                </varlistentry>
-+
-+                <varlistentry>
-                     <term>ipa_hbac_refresh (integer)</term>
-                     <listitem>
-                         <para>
-diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
-index df8dcffea5f98030f6d5a6c98e95a7d887ace7fd..b39ade40cd00ad5fccdb5d4bf4df8790eb634a51 100644
---- a/src/providers/ad/ad_common.h
-+++ b/src/providers/ad/ad_common.h
-@@ -60,6 +60,7 @@ enum ad_basic_opt {
-     AD_GPO_MAP_PERMIT,
-     AD_GPO_MAP_DENY,
-     AD_GPO_DEFAULT_RIGHT,
-+    AD_KRB5_CONFD_PATH,
- 
-     AD_OPTS_BASIC /* opts counter */
- };
-diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
-index ac6006c9200464956ccedb17ff53050fed5fc6ea..c3de3d94b1818665a86bba8a2432c699717b6a34 100644
---- a/src/providers/ad/ad_opts.h
-+++ b/src/providers/ad/ad_opts.h
-@@ -48,6 +48,7 @@ struct dp_option ad_basic_opts[] = {
-     { "ad_gpo_map_permit", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-     { "ad_gpo_map_deny", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-     { "ad_gpo_default_right", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-+    { "krb5_confd_path", DP_OPT_STRING, { KRB5_MAPPING_DIR }, NULL_STRING },
-     DP_OPTION_TERMINATOR
- };
- 
-diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
-index bc5bc8914ce84ecfbff69ff837250b5bf3a3515b..3c61d13522c7c773171ea8645dddb417e610745c 100644
---- a/src/providers/ad/ad_subdomains.c
-+++ b/src/providers/ad/ad_subdomains.c
-@@ -461,6 +461,14 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *ctx)
- {
-     errno_t ret;
- 
-+    ret = sss_write_krb5_conf_snippet(
-+                            dp_opt_get_string(ctx->ad_id_ctx->ad_options->basic,
-+                                              AD_KRB5_CONFD_PATH));
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
-+        /* Just continue */
-+    }
-+
-     ret = sysdb_update_subdomains(ctx->be_ctx->domain);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
-diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
-index 495276548e57e91f9744dda6d8866971b627b4da..33085197c2a4807d4546289ead4c30d891d0d2c0 100644
---- a/src/providers/ipa/ipa_common.h
-+++ b/src/providers/ipa/ipa_common.h
-@@ -54,6 +54,7 @@ enum ipa_basic_opt {
-     IPA_ENABLE_DNS_SITES,
-     IPA_SERVER_MODE,
-     IPA_VIEWS_SEARCH_BASE,
-+    IPA_KRB5_CONFD_PATH,
- 
-     IPA_OPTS_BASIC /* opts counter */
- };
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index 59282e8699091fbccf08ddfc6825034d4f81a87f..f77ff1d05b9540155db44d04d4fb3aac9d7b5988 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -51,6 +51,7 @@ struct dp_option ipa_basic_opts[] = {
-     { "ipa_enable_dns_sites", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
-     { "ipa_server_mode", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
-     { "ipa_views_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
-+    { "krb5_confd_path", DP_OPT_STRING, { KRB5_MAPPING_DIR }, NULL_STRING },
-     DP_OPTION_TERMINATOR
- };
- 
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index 9281aab1b028ebcaee8044b2768c6918efa4e514..883558c4d79d2da64ef6f010982ac89ccfae4e4f 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -312,6 +312,14 @@ ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx)
- {
-     errno_t ret;
- 
-+    ret = sss_write_krb5_conf_snippet(
-+                              dp_opt_get_string(ctx->id_ctx->ipa_options->basic,
-+                                                IPA_KRB5_CONFD_PATH));
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n");
-+        /* Just continue */
-+    }
-+
-     ret = sysdb_update_subdomains(ctx->be_ctx->domain);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
-diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
-index d9781377be70a0d58b0fd1fff2145483dbeb199c..5dc00c4cc9707776fabda50ad1eab8e582b16c0f 100644
---- a/src/tests/cmocka/test_utils.c
-+++ b/src/tests/cmocka/test_utils.c
-@@ -20,6 +20,8 @@
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
- 
-+#define _GNU_SOURCE
-+#include <stdio.h>
- #include <popt.h>
- 
- #include "tests/cmocka/common_mock.h"
-@@ -983,6 +985,51 @@ void test_add_strings_lists(void **state)
-     talloc_free(res);
- }
- 
-+void test_sss_write_krb5_conf_snippet(void **state)
-+{
-+    int ret;
-+    char buf[PATH_MAX];
-+    char *cwd;
-+    char *path;
-+    char *file;
-+
-+    ret = sss_write_krb5_conf_snippet(NULL);
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = sss_write_krb5_conf_snippet("abc");
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = sss_write_krb5_conf_snippet("");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sss_write_krb5_conf_snippet("none");
-+    assert_int_equal(ret, EOK);
-+
-+    cwd = getcwd(buf, PATH_MAX);
-+    assert_non_null(cwd);
-+
-+    ret = asprintf(&path, "%s/%s", cwd, TESTS_PATH);
-+    assert_true(ret > 0);
-+
-+    ret = asprintf(&file, "%s/%s/localauth_plugin", cwd, TESTS_PATH);
-+    assert_true(ret > 0);
-+
-+    ret = sss_write_krb5_conf_snippet(path);
-+    assert_int_equal(ret, EOK);
-+
-+    /* Check if writing a second time will work as well */
-+    ret = sss_write_krb5_conf_snippet(path);
-+    assert_int_equal(ret, EOK);
-+
-+#ifdef HAVE_KRB5_LOCALAUTH_PLUGIN
-+    ret = unlink(file);
-+    assert_int_equal(ret, EOK);
-+#endif
-+
-+    free(file);
-+    free(path);
-+}
-+
- int main(int argc, const char *argv[])
- {
-     poptContext pc;
-@@ -1030,6 +1077,7 @@ int main(int argc, const char *argv[])
-         unit_test_setup_teardown(test_add_strings_lists,
-                                  setup_add_strings_lists,
-                                  teardown_add_strings_lists),
-+        unit_test(test_sss_write_krb5_conf_snippet),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
-index 4e2c14c9432d38502422ddf2b0cb2b655a68d1cc..e04b905768078c503168f27327f974c0f19a6775 100644
---- a/src/util/domain_info_utils.c
-+++ b/src/util/domain_info_utils.c
-@@ -24,9 +24,6 @@
- #include "db/sysdb.h"
- #include "util/util.h"
- 
--/* the directory domain - realm mappings are written to */
--#define KRB5_MAPPING_DIR PUBCONF_PATH"/krb5.include.d"
--
- struct sss_domain_info *get_domains_head(struct sss_domain_info *domain)
- {
-     struct sss_domain_info *dom = NULL;
-@@ -637,3 +634,146 @@ done:
-     talloc_free(tmp_ctx);
-     return ret;
- }
-+
-+#define LOCALAUTH_PLUGIN_CONFIG \
-+"[plugins]\n" \
-+" localauth = {\n" \
-+"  module = sssd:"APP_MODULES_PATH"/sssd_krb5_localauth_plugin.so\n" \
-+"  enable_only = sssd\n" \
-+" }"
-+
-+static errno_t sss_write_krb5_localauth_snippet(const char *path)
-+{
-+#ifdef HAVE_KRB5_LOCALAUTH_PLUGIN
-+    int ret;
-+    errno_t err;
-+    TALLOC_CTX *tmp_ctx = NULL;
-+    char *tmp_file = NULL;
-+    const char *file_name;
-+    int fd = -1;
-+    mode_t old_mode;
-+    ssize_t written;
-+    size_t size;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    file_name = talloc_asprintf(tmp_ctx, "%s/localauth_plugin", path);
-+    if (file_name == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    DEBUG(SSSDBG_FUNC_DATA, "File for localauth plugin configuration is [%s]\n",
-+                             file_name);
-+
-+    tmp_file = talloc_asprintf(tmp_ctx, "%sXXXXXX", file_name);
-+    if (tmp_file == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    old_mode = umask(077);
-+    fd = mkstemp(tmp_file);
-+    umask(old_mode);
-+    if (fd < 0) {
-+        DEBUG(SSSDBG_OP_FAILURE, "creating the temp file [%s] for domain-realm "
-+                                  "mappings failed.", tmp_file);
-+        ret = EIO;
-+        talloc_zfree(tmp_ctx);
-+        goto done;
-+    }
-+
-+    size = sizeof(LOCALAUTH_PLUGIN_CONFIG) -1;
-+    written = sss_atomic_write_s(fd, discard_const(LOCALAUTH_PLUGIN_CONFIG),
-+                                 size);
-+    close(fd);
-+    if (written == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "write failed [%d][%s]\n", ret, sss_strerror(ret));
-+        goto done;
-+    }
-+
-+    if (written != size) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Wrote %zd bytes expected %zu\n", written, size);
-+        ret = EIO;
-+        goto done;
-+    }
-+
-+    ret = rename(tmp_file, file_name);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "rename failed [%d][%s].\n", ret, sss_strerror(ret));
-+        goto done;
-+    }
-+    tmp_file = NULL;
-+
-+    ret = chmod(file_name, 0644);
-+    if (ret == -1) {
-+        ret = errno;
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "chmod failed [%d][%s].\n", ret, sss_strerror(ret));
-+        goto done;
-+    }
-+
-+done:
-+    if (tmp_file != NULL) {
-+        err = unlink(tmp_file);
-+        if (err == -1) {
-+            err = errno;
-+            DEBUG(SSSDBG_MINOR_FAILURE,
-+                  "Could not remove file [%s]: [%d]: %s",
-+                   tmp_file, err, sss_strerror(err));
-+        }
-+    }
-+
-+    talloc_free(tmp_ctx);
-+    return ret;
-+#else
-+    DEBUG(SSSDBG_TRACE_ALL, "Kerberos localauth plugin not available.\n");
-+    return EOK;
-+#endif
-+}
-+
-+errno_t sss_write_krb5_conf_snippet(const char *path)
-+{
-+    errno_t ret;
-+    errno_t err;
-+
-+    if (path != NULL && (*path == '\0' || strcasecmp(path, "none") == 0)) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "Empty path, nothing to do.\n");
-+        return EOK;
-+    }
-+
-+    if (path == NULL || *path != '/') {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid or missing path [%s]-\n",
-+                                    path == NULL ? "missing" : path);
-+        return EINVAL;
-+    }
-+
-+    ret = sss_write_krb5_localauth_snippet(path);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sss_write_krb5_localauth_snippet failed.\n");
-+        goto done;
-+    }
-+
-+    ret = EOK;
-+
-+done:
-+    err = sss_krb5_touch_config();
-+    if (err != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to change last modification time "
-+              "of krb5.conf. Created mappings may not be loaded.\n");
-+        /* Ignore */
-+    }
-+
-+    return ret;
-+}
-diff --git a/src/util/util.h b/src/util/util.h
-index 7c335b9a2ac2599304731082845fd382dc62465f..45efd1aef94c2e058a435933e7c41adaecc676e2 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -576,8 +576,14 @@ errno_t sssd_domain_init(TALLOC_CTX *mem_ctx,
- 
- #define DOM_HAS_VIEWS(dom) ((dom)->has_views)
- 
-+/* the directory domain - realm mappings and other krb5 config snippers are
-+ * written to */
-+#define KRB5_MAPPING_DIR PUBCONF_PATH"/krb5.include.d"
-+
- errno_t sss_write_domain_mappings(struct sss_domain_info *domain);
- 
-+errno_t sss_write_krb5_conf_snippet(const char *path);
-+
- errno_t get_dom_names(TALLOC_CTX *mem_ctx,
-                       struct sss_domain_info *start_dom,
-                       char ***_dom_names,
--- 
-1.9.3
-
diff --git a/SOURCES/0110-test-Wrong-parameter-type-in-sss_parse_name_check.patch b/SOURCES/0110-test-Wrong-parameter-type-in-sss_parse_name_check.patch
deleted file mode 100644
index 5ac4004..0000000
--- a/SOURCES/0110-test-Wrong-parameter-type-in-sss_parse_name_check.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 781f2feea5aa4d08a8c68aa33910b4f83a988e85 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Mon, 24 Nov 2014 19:10:01 +0100
-Subject: [PATCH 110/112] test: Wrong parameter type in sss_parse_name_check
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This caused aritmetic overflow when SSSD specific error
-codes where used.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/tests/cmocka/test_fqnames.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/tests/cmocka/test_fqnames.c b/src/tests/cmocka/test_fqnames.c
-index 71429c8773ef199c72163837d4b313660cf813c2..de208437d3d11429ebb4fd92ac6b1469564d9174 100644
---- a/src/tests/cmocka/test_fqnames.c
-+++ b/src/tests/cmocka/test_fqnames.c
-@@ -326,7 +326,7 @@ void parse_name_test_teardown(void **state)
- 
- void sss_parse_name_check(struct parse_name_test_ctx *test_ctx,
-                           const char *input_name,
--                          const char exp_ret,
-+                          const int exp_ret,
-                           const char *exp_name,
-                           const char *exp_domain)
- {
--- 
-1.9.3
-
diff --git a/SOURCES/0111-util-Special-case-PCRE_ERROR_NOMATCH-in-sss_parse_na.patch b/SOURCES/0111-util-Special-case-PCRE_ERROR_NOMATCH-in-sss_parse_na.patch
deleted file mode 100644
index 0de6c3c..0000000
--- a/SOURCES/0111-util-Special-case-PCRE_ERROR_NOMATCH-in-sss_parse_na.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-From eedf2fc4c1432f805b16ae52939cf5e67e8df550 Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Mon, 24 Nov 2014 19:50:14 +0100
-Subject: [PATCH 111/112] util: Special-case PCRE_ERROR_NOMATCH in
- sss_parse_name
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Add new SSSD specific error code for the case when
-pcre_exec returns PCRE_ERROR_NOMATCH.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/tests/cmocka/test_fqnames.c | 14 +++++++-------
- src/util/usertools.c            |  2 +-
- src/util/util_errors.c          |  1 +
- src/util/util_errors.h          |  1 +
- 4 files changed, 10 insertions(+), 8 deletions(-)
-
-diff --git a/src/tests/cmocka/test_fqnames.c b/src/tests/cmocka/test_fqnames.c
-index de208437d3d11429ebb4fd92ac6b1469564d9174..b9b6230b9e2c86dafae159630d5202e46992f5f3 100644
---- a/src/tests/cmocka/test_fqnames.c
-+++ b/src/tests/cmocka/test_fqnames.c
-@@ -471,13 +471,13 @@ void sss_parse_name_fail(void **state)
-     struct parse_name_test_ctx *test_ctx = talloc_get_type(*state,
-                                                            struct parse_name_test_ctx);
- 
--    sss_parse_name_check(test_ctx, "", EINVAL, NULL, NULL);
--    sss_parse_name_check(test_ctx, "@", EINVAL, NULL, NULL);
--    sss_parse_name_check(test_ctx, "\\", EINVAL, NULL, NULL);
--    sss_parse_name_check(test_ctx, "\\"NAME, EINVAL, NULL, NULL);
--    sss_parse_name_check(test_ctx, "@"NAME, EINVAL, NULL, NULL);
--    sss_parse_name_check(test_ctx, NAME"@", EINVAL, NULL, NULL);
--    sss_parse_name_check(test_ctx, NAME"\\", EINVAL, NULL, NULL);
-+    sss_parse_name_check(test_ctx, "", ERR_REGEX_NOMATCH, NULL, NULL);
-+    sss_parse_name_check(test_ctx, "@", ERR_REGEX_NOMATCH, NULL, NULL);
-+    sss_parse_name_check(test_ctx, "\\", ERR_REGEX_NOMATCH, NULL, NULL);
-+    sss_parse_name_check(test_ctx, "\\"NAME, ERR_REGEX_NOMATCH, NULL, NULL);
-+    sss_parse_name_check(test_ctx, "@"NAME, ERR_REGEX_NOMATCH, NULL, NULL);
-+    sss_parse_name_check(test_ctx, NAME"@", ERR_REGEX_NOMATCH, NULL, NULL);
-+    sss_parse_name_check(test_ctx, NAME"\\", ERR_REGEX_NOMATCH, NULL, NULL);
- }
- 
- void test_sss_get_domain_name(void **state)
-diff --git a/src/util/usertools.c b/src/util/usertools.c
-index a0b914e2fe8f65a71015944e63cb2d2813345d84..09cfd6b35505b8496413258fd05808ac0d2c095b 100644
---- a/src/util/usertools.c
-+++ b/src/util/usertools.c
-@@ -309,7 +309,7 @@ int sss_parse_name(TALLOC_CTX *memctx,
- 
-     ret = pcre_exec(re, NULL, orig, origlen, 0, PCRE_NOTEMPTY, ovec, 30);
-     if (ret == PCRE_ERROR_NOMATCH) {
--        return EINVAL;
-+        return ERR_REGEX_NOMATCH;
-     } else if (ret < 0) {
-         DEBUG(SSSDBG_MINOR_FAILURE, "PCRE Matching error, %d\n", ret);
-         return EINVAL;
-diff --git a/src/util/util_errors.c b/src/util/util_errors.c
-index c1ed0fb634c447904b63335d1cd161b7e7914a08..16d16fc777fc3344db8a3bdfeb3633bd5db48530 100644
---- a/src/util/util_errors.c
-+++ b/src/util/util_errors.c
-@@ -64,6 +64,7 @@ struct err_string error_to_str[] = {
-     { "Cannot connect to system bus" }, /* ERR_NO_SYSBUS */
-     { "LDAP search returned a referral" }, /* ERR_REFERRAL */
-     { "Error setting SELinux user context" }, /* ERR_SELINUX_CONTEXT */
-+    { "Username format not allowed by re_expression" }, /* ERR_REGEX_NOMATCH */
- };
- 
- 
-diff --git a/src/util/util_errors.h b/src/util/util_errors.h
-index f71ede8d0fa000627a1bd994ec8bd94a632b35b2..39455dc8adfe8784bd3f06382d701b7f9e97f004 100644
---- a/src/util/util_errors.h
-+++ b/src/util/util_errors.h
-@@ -86,6 +86,7 @@ enum sssd_errors {
-     ERR_NO_SYSBUS,
-     ERR_REFERRAL,
-     ERR_SELINUX_CONTEXT,
-+    ERR_REGEX_NOMATCH,
-     ERR_LAST            /* ALWAYS LAST */
- };
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0112-util-sss_get_domain_name-regex-mismatch-not-fatal.patch b/SOURCES/0112-util-sss_get_domain_name-regex-mismatch-not-fatal.patch
deleted file mode 100644
index e4a8d6a..0000000
--- a/SOURCES/0112-util-sss_get_domain_name-regex-mismatch-not-fatal.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 751447267c61d70016fd9f2231096188ede8eabe Mon Sep 17 00:00:00 2001
-From: Michal Zidek <mzidek@redhat.com>
-Date: Fri, 21 Nov 2014 20:06:32 +0100
-Subject: [PATCH 112/112] util: sss_get_domain_name regex mismatch not fatal
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Assume name is not FQDN if sss_parse_name fails to
-match domain with regular expression.
-
-Fixes:
-https://fedorahosted.org/sssd/ticket/2487
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/util/usertools.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/src/util/usertools.c b/src/util/usertools.c
-index 09cfd6b35505b8496413258fd05808ac0d2c095b..ebe139e6cd3c9eb270033629dab362fefb3e2682 100644
---- a/src/util/usertools.c
-+++ b/src/util/usertools.c
-@@ -646,7 +646,13 @@ sss_get_domain_name(TALLOC_CTX *mem_ctx,
-     /* check if the name already contains domain part */
-     if (dom->names != NULL) {
-         ret = sss_parse_name(mem_ctx, dom->names, orig_name, &domain, NULL);
--        if (ret != EOK) {
-+        if (ret == ERR_REGEX_NOMATCH) {
-+            DEBUG(SSSDBG_TRACE_FUNC,
-+                  "sss_parse_name could not parse domain from [%s]. "
-+                  "Assuming it is not FQDN.\n", orig_name);
-+        } else if (ret != EOK) {
-+            DEBUG(SSSDBG_TRACE_FUNC,
-+                  "sss_parse_name failed [%d]: %s\n", ret, sss_strerror(ret));
-             return NULL;
-         }
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0113-sysdb-add-sysdb_delete_view_tree.patch b/SOURCES/0113-sysdb-add-sysdb_delete_view_tree.patch
deleted file mode 100644
index 8173280..0000000
--- a/SOURCES/0113-sysdb-add-sysdb_delete_view_tree.patch
+++ /dev/null
@@ -1,175 +0,0 @@
-From 68f94d995142fc1aadf278be2f6816566208e189 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 12 Nov 2014 12:43:23 +0100
-Subject: [PATCH 113/115] sysdb: add sysdb_delete_view_tree()
-
----
- src/db/sysdb.h                      |  2 +
- src/db/sysdb_views.c                | 34 +++++++++++++++++
- src/tests/cmocka/test_sysdb_views.c | 74 +++++++++++++++++++++++++++++++++++++
- 3 files changed, 110 insertions(+)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index 7a51117f439dc54ded3433c230d2d262a4d660dc..a3ffa7b759e8aa16fc8a60cb01c6f0cb49278cc0 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -444,6 +444,8 @@ errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb, const char *view_name);
- errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
-                             char **view_name);
- 
-+errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name);
-+
- errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
-                                      struct sysdb_attrs *override_attrs,
-                                      struct ldb_dn *obj_dn);
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index 27b58701fe0f9a4f545df5e4bfb884c04517d0d3..e17321455ad2ac4e4f17094f83c482d95bb00d8b 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -180,6 +180,40 @@ done:
-     return ret;
- }
- 
-+errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name)
-+{
-+    struct ldb_dn *dn;
-+    TALLOC_CTX *tmp_ctx;
-+    int ret;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_SEARCH_BASE,
-+                        view_name);
-+    if (dn == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
-+        ret = EIO;
-+        goto done;
-+    }
-+
-+    ret = sysdb_delete_recursive(sysdb, dn, true);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
-+        goto done;
-+    }
-+
-+    ret = EOK;
-+
-+done:
-+    talloc_free(tmp_ctx);
-+
-+    return ret;
-+}
-+
- static errno_t
- add_name_and_aliases_for_name_override(struct sss_domain_info *domain,
-                                        struct sysdb_attrs *attrs,
-diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
-index 0dc51443b406673f131cc69be4d781f7c49e538c..6be28e624d102060121f9afa91b282f7e8620676 100644
---- a/src/tests/cmocka/test_sysdb_views.c
-+++ b/src/tests/cmocka/test_sysdb_views.c
-@@ -30,10 +30,22 @@
- 
- #include "tests/cmocka/common_mock.h"
- #include "providers/ipa/ipa_id.h"
-+#include "db/sysdb_private.h" /* for sysdb->ldb member */
- 
- #define TESTS_PATH "tests_sysdb_views"
- #define TEST_CONF_FILE "tests_conf.ldb"
- 
-+#define TEST_ANCHOR_PREFIX ":ANCHOR:"
-+#define TEST_VIEW_NAME "test view"
-+#define TEST_VIEW_CONTAINER "cn=" TEST_VIEW_NAME ",cn=views,cn=sysdb"
-+#define TEST_USER_NAME "test_user"
-+#define TEST_USER_UID 1234
-+#define TEST_USER_GID 5678
-+#define TEST_USER_GECOS "Gecos field"
-+#define TEST_USER_HOMEDIR "/home/home"
-+#define TEST_USER_SHELL "/bin/shell"
-+#define TEST_USER_SID "S-1-2-3-4"
-+
- struct sysdb_test_ctx {
-     struct sysdb_ctx *sysdb;
-     struct confdb_ctx *confdb;
-@@ -219,6 +231,66 @@ void test_split_ipa_anchor(void **state)
-     assert_string_equal(uuid, "def");
- }
- 
-+void test_sysdb_delete_view_tree(void **state)
-+{
-+    int ret;
-+    struct ldb_message *msg;
-+    struct ldb_message **msgs = NULL;
-+    struct sysdb_attrs *attrs;
-+    size_t count;
-+    struct ldb_dn *views_dn;
-+
-+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                                         struct sysdb_test_ctx);
-+
-+    test_ctx->domain->mpg = false;
-+
-+    ret = sysdb_update_view_name(test_ctx->domain->sysdb, TEST_VIEW_NAME);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_store_user(test_ctx->domain, TEST_USER_NAME, NULL,
-+                           TEST_USER_UID, TEST_USER_GID, TEST_USER_GECOS,
-+                           TEST_USER_HOMEDIR, TEST_USER_SHELL, NULL, NULL, NULL,
-+                           0,0);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
-+                                    NULL, &msg);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(msg);
-+
-+    attrs = sysdb_new_attrs(test_ctx);
-+    assert_non_null(attrs);
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID,
-+                                 TEST_ANCHOR_PREFIX TEST_USER_SID);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
-+                               SYSDB_MEMBER_USER, attrs, msg->dn);
-+    assert_int_equal(ret, EOK);
-+
-+    views_dn = ldb_dn_new(test_ctx, test_ctx->domain->sysdb->ldb,
-+                          SYSDB_TMPL_VIEW_BASE);
-+    assert_non_null(views_dn);
-+
-+    ret = sysdb_search_entry(test_ctx, test_ctx->domain->sysdb, views_dn,
-+                             LDB_SCOPE_SUBTREE, NULL, NULL, &count, &msgs);
-+    assert_int_equal(ret, EOK);
-+    assert_true(count > 1);
-+    assert_non_null(msgs);
-+
-+    ret = sysdb_delete_view_tree(test_ctx->domain->sysdb, TEST_VIEW_NAME);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_search_entry(test_ctx, test_ctx->domain->sysdb, views_dn,
-+                             LDB_SCOPE_SUBTREE, NULL, NULL, &count, &msgs);
-+    assert_int_equal(ret, EOK);
-+    assert_int_equal(count, 1);
-+    assert_true(ldb_dn_compare(views_dn, msgs[0]->dn) == 0);
-+
-+}
-+
- int main(int argc, const char *argv[])
- {
-     int rv;
-@@ -238,6 +310,8 @@ int main(int argc, const char *argv[])
-                                  test_sysdb_setup, test_sysdb_teardown),
-         unit_test_setup_teardown(test_split_ipa_anchor,
-                                  test_sysdb_setup, test_sysdb_teardown),
-+        unit_test_setup_teardown(test_sysdb_delete_view_tree,
-+                                 test_sysdb_setup, test_sysdb_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-1.9.3
-
diff --git a/SOURCES/0114-sysdb-add-sysdb_invalidate_overrides.patch b/SOURCES/0114-sysdb-add-sysdb_invalidate_overrides.patch
deleted file mode 100644
index 8dadcc4..0000000
--- a/SOURCES/0114-sysdb-add-sysdb_invalidate_overrides.patch
+++ /dev/null
@@ -1,248 +0,0 @@
-From 26ae40bd74a00a9701f732a8957c06ff8fc857a4 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 12 Nov 2014 16:26:55 +0100
-Subject: [PATCH 114/115] sysdb: add sysdb_invalidate_overrides()
-
----
- src/db/sysdb.h                      |   2 +
- src/db/sysdb_views.c                | 123 ++++++++++++++++++++++++++++++++++++
- src/tests/cmocka/test_sysdb_views.c |  69 ++++++++++++++++++++
- 3 files changed, 194 insertions(+)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index a3ffa7b759e8aa16fc8a60cb01c6f0cb49278cc0..5bd7f90acb685bbaff5c98f433c7dce8175c33ca 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -446,6 +446,8 @@ errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
- 
- errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name);
- 
-+errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb);
-+
- errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
-                                      struct sysdb_attrs *override_attrs,
-                                      struct ldb_dn *obj_dn);
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index e17321455ad2ac4e4f17094f83c482d95bb00d8b..970d83e657d4fdfb73ac0e1fcc124ec690e29d4b 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -214,6 +214,129 @@ done:
-     return ret;
- }
- 
-+errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb)
-+{
-+    int ret;
-+    int sret;
-+    TALLOC_CTX *tmp_ctx;
-+    bool in_transaction = false;
-+    struct ldb_result *res;
-+    size_t c;
-+    struct ldb_message *msg;
-+    struct ldb_dn *base_dn;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    msg = ldb_msg_new(tmp_ctx);
-+    if (msg == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    base_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
-+    if (base_dn == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    ret = ldb_msg_add_empty(msg, SYSDB_CACHE_EXPIRE, LDB_FLAG_MOD_REPLACE,
-+                            NULL);
-+    if (ret != LDB_SUCCESS) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
-+        ret = sysdb_error_to_errno(ret);
-+        goto done;
-+    }
-+    ret = ldb_msg_add_string(msg, SYSDB_CACHE_EXPIRE, "1");
-+    if (ret != LDB_SUCCESS) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
-+        ret = sysdb_error_to_errno(ret);
-+        goto done;
-+    }
-+
-+    ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_DELETE, NULL);
-+    if (ret != LDB_SUCCESS) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
-+        ret = sysdb_error_to_errno(ret);
-+        goto done;
-+    }
-+
-+    ret = sysdb_transaction_start(sysdb);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
-+        goto done;
-+    }
-+    in_transaction = true;
-+
-+    ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
-+                     NULL, "%s", SYSDB_UC);
-+    if (ret != LDB_SUCCESS) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
-+        ret = sysdb_error_to_errno(ret);
-+        goto done;
-+    }
-+
-+    for (c = 0; c < res->count; c++) {
-+        msg->dn = res->msgs[c]->dn;
-+
-+        ret = ldb_modify(sysdb->ldb, msg);
-+        if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ldb_modify failed.\n");
-+            ret = sysdb_error_to_errno(ret);
-+            goto done;
-+        }
-+    }
-+
-+    talloc_free(res);
-+
-+    ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
-+                     NULL, "%s", SYSDB_GC);
-+    if (ret != LDB_SUCCESS) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
-+        ret = sysdb_error_to_errno(ret);
-+        goto done;
-+    }
-+
-+    for (c = 0; c < res->count; c++) {
-+        msg->dn = res->msgs[c]->dn;
-+
-+        ret = ldb_modify(sysdb->ldb, msg);
-+        if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ldb_modify failed.\n");
-+            ret = sysdb_error_to_errno(ret);
-+            goto done;
-+        }
-+    }
-+
-+    ret = EOK;
-+done:
-+    if (in_transaction) {
-+        if (ret == EOK) {
-+            sret = sysdb_transaction_commit(sysdb);
-+            if (sret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed, " \
-+                                         "nothing we can do about.\n");
-+                ret = sret;
-+            }
-+        } else {
-+            sret = sysdb_transaction_cancel(sysdb);
-+            if (sret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed, " \
-+                                         "nothing we can do about.\n");
-+            }
-+        }
-+    }
-+
-+    talloc_free(tmp_ctx);
-+
-+    return ret;
-+}
-+
- static errno_t
- add_name_and_aliases_for_name_override(struct sss_domain_info *domain,
-                                        struct sysdb_attrs *attrs,
-diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
-index 6be28e624d102060121f9afa91b282f7e8620676..7238467c3c9bf91fd0d48204dd7217d4d273e965 100644
---- a/src/tests/cmocka/test_sysdb_views.c
-+++ b/src/tests/cmocka/test_sysdb_views.c
-@@ -291,6 +291,73 @@ void test_sysdb_delete_view_tree(void **state)
- 
- }
- 
-+void test_sysdb_invalidate_overrides(void **state)
-+{
-+    int ret;
-+    struct ldb_message *msg;
-+    struct sysdb_attrs *attrs;
-+    struct ldb_dn *views_dn;
-+    const char *user_attrs[] = { SYSDB_NAME,
-+                                 SYSDB_CACHE_EXPIRE,
-+                                 SYSDB_OVERRIDE_DN,
-+                                 NULL};
-+
-+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                                         struct sysdb_test_ctx);
-+
-+    test_ctx->domain->mpg = false;
-+
-+    ret = sysdb_update_view_name(test_ctx->domain->sysdb, TEST_VIEW_NAME);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_store_user(test_ctx->domain, TEST_USER_NAME, NULL,
-+                           TEST_USER_UID, TEST_USER_GID, TEST_USER_GECOS,
-+                           TEST_USER_HOMEDIR, TEST_USER_SHELL, NULL, NULL, NULL,
-+                           10,0);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
-+                                    NULL, &msg);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(msg);
-+
-+    attrs = sysdb_new_attrs(test_ctx);
-+    assert_non_null(attrs);
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID,
-+                                 TEST_ANCHOR_PREFIX TEST_USER_SID);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
-+                               SYSDB_MEMBER_USER, attrs, msg->dn);
-+    assert_int_equal(ret, EOK);
-+
-+    views_dn = ldb_dn_new(test_ctx, test_ctx->domain->sysdb->ldb,
-+                          SYSDB_TMPL_VIEW_BASE);
-+    assert_non_null(views_dn);
-+
-+    ret = sysdb_delete_view_tree(test_ctx->domain->sysdb, TEST_VIEW_NAME);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
-+                                    user_attrs, &msg);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(msg);
-+    assert_true(ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0) > 1);
-+    assert_non_null(ldb_msg_find_attr_as_string(msg, SYSDB_OVERRIDE_DN, NULL));
-+
-+    ret = sysdb_invalidate_overrides(test_ctx->domain->sysdb);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
-+                                    user_attrs, &msg);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(msg);
-+    assert_int_equal(ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0),
-+                     1);
-+    assert_null(ldb_msg_find_attr_as_string(msg, SYSDB_OVERRIDE_DN, NULL));
-+}
-+
- int main(int argc, const char *argv[])
- {
-     int rv;
-@@ -312,6 +379,8 @@ int main(int argc, const char *argv[])
-                                  test_sysdb_setup, test_sysdb_teardown),
-         unit_test_setup_teardown(test_sysdb_delete_view_tree,
-                                  test_sysdb_setup, test_sysdb_teardown),
-+        unit_test_setup_teardown(test_sysdb_invalidate_overrides,
-+                                 test_sysdb_setup, test_sysdb_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-1.9.3
-
diff --git a/SOURCES/0115-views-allow-view-name-change-at-startup.patch b/SOURCES/0115-views-allow-view-name-change-at-startup.patch
deleted file mode 100644
index 71678f0..0000000
--- a/SOURCES/0115-views-allow-view-name-change-at-startup.patch
+++ /dev/null
@@ -1,231 +0,0 @@
-From af22737f9e8b31a6a0671d3e6b58df7863646380 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 12 Nov 2014 16:30:57 +0100
-Subject: [PATCH 115/115] views: allow view name change at startup
-
-Currently some manual steps are needed on a FreeIPA to switch from one
-view to another. With this patch the IPA provider checks at startup if
-the view name changed and does the needed steps automatically. Besides
-saving the new view name this includes removing the old view data and
-marking the user and group entries as invalid.
----
- src/db/sysdb_views.c               | 12 ++---
- src/providers/ipa/ipa_subdomains.c | 97 +++++++++++++++++++++++++++++++-------
- 2 files changed, 85 insertions(+), 24 deletions(-)
-
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index 970d83e657d4fdfb73ac0e1fcc124ec690e29d4b..3b3aac0dc1dea32cf3df5e29358f5dfefd8fde22 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -123,17 +123,13 @@ errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb,
-             goto done;
-         } else {
-             /* view name changed */
--            /* not supported atm */
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "View name changed from [%s] to [%s]. NOT SUPPORTED.\n",
--                  tmp_str, view_name);
--            ret = ENOTSUP;
--            goto done;
-+            DEBUG(SSSDBG_CONF_SETTINGS,
-+                  "View name changed from [%s] to [%s].\n", tmp_str, view_name);
-         }
-+    } else {
-+        add_view_name = true;
-     }
- 
--    add_view_name = true;
--
-     msg = ldb_msg_new(tmp_ctx);
-     if (msg == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index 883558c4d79d2da64ef6f010982ac89ccfae4e4f..6fdb0befa32f96d01c9b3666a3ef9c8331a83242 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -80,8 +80,17 @@ struct ipa_subdomains_ctx {
-     struct tevent_timer *timer_event;
-     bool configured_explicit;
-     time_t disabled_until;
-+    bool view_read_at_init;
- };
- 
-+static void ipa_subdomains_done(struct ipa_subdomains_ctx *sd_ctx,
-+                                struct be_req *req, int dp_err,
-+                                int error, const char *errstr)
-+{
-+    sd_ctx->view_read_at_init = true;
-+    return be_req_terminate(req, dp_err, error, errstr);
-+}
-+
- struct be_ctx *ipa_get_subdomains_be_ctx(struct be_ctx *be_ctx)
- {
-     struct ipa_subdomains_ctx *subdom_ctx;
-@@ -903,7 +912,7 @@ done:
-     if (ret == EOK) {
-         dp_error = DP_ERR_OK;
-     }
--    be_req_terminate(be_req, dp_error, ret, NULL);
-+    ipa_subdomains_done(ctx, be_req, dp_error, ret, NULL);
- }
- 
- static void ipa_subdomains_get_conn_done(struct tevent_req *req)
-@@ -938,7 +947,7 @@ static void ipa_subdomains_get_conn_done(struct tevent_req *req)
-     return;
- 
- fail:
--    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
-+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
- }
- 
- static errno_t
-@@ -1030,6 +1039,7 @@ static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx)
- static void ipa_get_view_name_done(struct tevent_req *req)
- {
-     int ret;
-+    int sret;
-     struct ipa_subdomains_req_ctx *ctx;
-     size_t reply_count;
-     struct sdap_deref_attrs **reply = NULL;
-@@ -1089,24 +1099,79 @@ static void ipa_get_view_name_done(struct tevent_req *req)
-         view_name = SYSDB_DEFAULT_VIEW_NAME;
-     }
- 
-+    DEBUG(SSSDBG_TRACE_ALL, "read_at_init [%s] current view  [%s].\n",
-+                             ctx->sd_ctx->view_read_at_init ? "true" : "false",
-+                             ctx->sd_ctx->id_ctx->view_name);
-+
-     if (ctx->sd_ctx->id_ctx->view_name != NULL
--            && strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0) {
-+            && strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0
-+            && ctx->sd_ctx->view_read_at_init) {
-         DEBUG(SSSDBG_CRIT_FAILURE,
--              "View name changed, this is currently not supported!\n");
-+              "View name changed, this is not supported at runtime. " \
-+              "Please restart SSSD to get the new view applied.\n");
-     } else {
-+        ctx->sd_ctx->view_read_at_init = true;
-+        /* View name changed */
-+        if (ctx->sd_ctx->id_ctx->view_name != NULL) {
-+            ret = sysdb_transaction_start(ctx->sd_ctx->be_ctx->domain->sysdb);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
-+                goto done;
-+            }
-+
-+            if (strcmp(ctx->sd_ctx->id_ctx->view_name,
-+                       SYSDB_DEFAULT_VIEW_NAME) != 0) {
-+                /* Old view was not the default view, delete view tree */
-+                ret = sysdb_delete_view_tree(ctx->sd_ctx->be_ctx->domain->sysdb,
-+                                             ctx->sd_ctx->id_ctx->view_name);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_delete_view_tree failed.\n");
-+                    sret = sysdb_transaction_cancel(
-+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
-+                    if (sret != EOK) {
-+                        DEBUG(SSSDBG_OP_FAILURE,
-+                              "sysdb_transaction_cancel failed.\n");
-+                        goto done;
-+                    }
-+                    goto done;
-+                }
-+            }
-+
-+            ret = sysdb_invalidate_overrides(
-+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE,
-+                      "sysdb_invalidate_overrides failed.\n");
-+                sret = sysdb_transaction_cancel(
-+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
-+                if (sret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed.\n");
-+                    goto done;
-+                }
-+                goto done;
-+            }
-+
-+            ret = sysdb_transaction_commit(ctx->sd_ctx->be_ctx->domain->sysdb);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed.\n");
-+                goto done;
-+            }
-+
-+            /* TODO: start referesh task */
-+        }
-+
-         ret = sysdb_update_view_name(ctx->sd_ctx->be_ctx->domain->sysdb,
-                                      view_name);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_CRIT_FAILURE,
-                   "Cannot add/update view name to sysdb.\n");
-         } else {
-+            talloc_free(ctx->sd_ctx->id_ctx->view_name);
-+            ctx->sd_ctx->id_ctx->view_name = talloc_strdup(ctx->sd_ctx->id_ctx,
-+                                                           view_name);
-             if (ctx->sd_ctx->id_ctx->view_name == NULL) {
--                ctx->sd_ctx->id_ctx->view_name =
--                                              talloc_strdup(ctx->sd_ctx->id_ctx,
--                                                            view_name);
--                if (ctx->sd_ctx->id_ctx->view_name == NULL) {
--                    DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
--                }
-+                DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
-             }
-         }
-     }
-@@ -1122,7 +1187,7 @@ done:
-     if (ret == EOK) {
-         dp_error = DP_ERR_OK;
-     }
--    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
-+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
- }
- 
- static void ipa_subdomains_handler_done(struct tevent_req *req)
-@@ -1222,7 +1287,7 @@ done:
-     if (ret == EOK) {
-         dp_error = DP_ERR_OK;
-     }
--    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
-+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
- }
- 
- static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx)
-@@ -1308,7 +1373,7 @@ done:
-     if (ret == EOK) {
-         dp_error = DP_ERR_OK;
-     }
--    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
-+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
- }
- 
- static void ipa_subdomains_handler_master_done(struct tevent_req *req)
-@@ -1370,7 +1435,7 @@ done:
-     if (ret == EOK) {
-         dp_error = DP_ERR_OK;
-     }
--    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
-+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
- }
- 
- static void ipa_subdom_online_cb(void *pvt);
-@@ -1505,12 +1570,12 @@ void ipa_subdomains_handler(struct be_req *be_req)
- 
-     if (ctx->disabled_until > now) {
-         DEBUG(SSSDBG_TRACE_ALL, "Subdomain provider disabled.\n");
--        be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
-+        ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
-         return;
-     }
- 
-     if (ctx->last_refreshed > now - IPA_SUBDOMAIN_REFRESH_LIMIT) {
--        be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
-+        ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
-         return;
-     }
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0116-PAM-Check-for-trusted-domain-before-sending-the-requ.patch b/SOURCES/0116-PAM-Check-for-trusted-domain-before-sending-the-requ.patch
deleted file mode 100644
index 18ccd03..0000000
--- a/SOURCES/0116-PAM-Check-for-trusted-domain-before-sending-the-requ.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-From 663fb2625181ca8b80d26526a8298674ab6242a1 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 23 Nov 2014 19:43:04 +0100
-Subject: [PATCH 116/117] PAM: Check for trusted domain before sending the
- request to BE
-
-https://fedorahosted.org/sssd/ticket/2501
-
-Moving the checks to one place has the advantage of not duplicating
-security decisions. Previously, the checks were scattered all over the
-responder code, making testing hard.
-
-The disadvantage is that we actually check for the presence of the user,
-which might trigger some back end lookups. But I think the benefits
-overweight the disadvantage.
-
-Also only check the requested domains from a trusted client. An untrusted
-client should simply have no say in what domains he wants to talk to, it
-should ignore the 'domains' option.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/responder/pam/pamsrv_cmd.c | 67 ++++++++++++++++--------------------------
- 1 file changed, 26 insertions(+), 41 deletions(-)
-
-diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
-index dd0e6e4cf54e6d98da807808ad6973dddc013413..b60ccba2d4ff669e7ed0252923a53755410851e3 100644
---- a/src/responder/pam/pamsrv_cmd.c
-+++ b/src/responder/pam/pamsrv_cmd.c
-@@ -898,17 +898,6 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
-             goto done;
-         }
- 
--        /* Untrusted users can access only public domains. */
--        if (!pctx->is_uid_trusted &&
--            !is_domain_public(pd->domain, pctx->public_domains,
--                              pctx->public_domains_count)) {
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "Untrusted user %"PRIu32" cannot access unpublic domain %s.\n",
--                  cctx->client_euid, pd->domain);
--            ret = EPERM;
--            goto done;
--        }
--
-         ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
-                                       preq->domain, pd->user);
-         if (ncret == EEXIST) {
-@@ -916,34 +905,12 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
-             ret = ENOENT;
-             goto done;
-         }
--
--        /* skip this domain if not requested */
--        if (!is_domain_requested(pd, pd->domain)) {
--            ret = ENOENT;
--            goto done;
--        }
-     } else {
-         for (dom = preq->cctx->rctx->domains;
-              dom;
-              dom = get_next_domain(dom, false)) {
-             if (dom->fqnames) continue;
- 
--            /* Untrusted users can access only public domains. */
--            if (!pctx->is_uid_trusted &&
--                !is_domain_public(dom->name, pctx->public_domains,
--                                  pctx->public_domains_count)) {
--                DEBUG(SSSDBG_MINOR_FAILURE,
--                      "Untrusted user %"PRIu32" cannot access unpublic domain %s."
--                      " Trying next domain.\n",
--                      cctx->client_euid, dom->name);
--                continue;
--            }
--
--            /* skip this domain if not requested */
--            if (!is_domain_requested(pd, dom->name)) {
--                continue;
--            }
--
-             ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout,
-                                           dom, pd->user);
-             if (ncret == ENOENT) {
-@@ -959,7 +926,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
-                    "Trying next domain.\n", pd->user, dom->name);
-         }
- 
--        if (!dom || !is_domain_requested(pd, dom->name)) {
-+        if (!dom) {
-             ret = ENOENT;
-             goto done;
-         }
-@@ -1055,14 +1022,9 @@ static int pam_check_user_search(struct pam_auth_req *preq)
- 
-     while (dom) {
-        /* if it is a domainless search, skip domains that require fully
--        * qualified names instead, also untrusted users can access only
--        * public domains */
-+        * qualified names instead */
-         while (dom && !preq->pd->domain && !preq->pd->name_is_upn
--               && (dom->fqnames ||
--                   (!pctx->is_uid_trusted &&
--                    !is_domain_public(dom->name,
--                                      pctx->public_domains,
--                                      pctx->public_domains_count)))) {
-+               && dom->fqnames) {
-             dom = get_next_domain(dom, false);
-         }
- 
-@@ -1334,11 +1296,34 @@ done:
- static void pam_dom_forwarder(struct pam_auth_req *preq)
- {
-     int ret;
-+    struct pam_ctx *pctx =
-+            talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
- 
-     if (!preq->pd->domain) {
-         preq->pd->domain = preq->domain->name;
-     }
- 
-+    /* Untrusted users can access only public domains. */
-+    if (!pctx->is_uid_trusted &&
-+            !is_domain_public(preq->pd->domain, pctx->public_domains,
-+                            pctx->public_domains_count)) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+                "Untrusted user %"PRIu32" cannot access non-public domain %s.\n",
-+                preq->cctx->client_euid, preq->pd->domain);
-+        preq->pd->pam_status = PAM_PERM_DENIED;
-+        pam_reply(preq);
-+        return;
-+    }
-+
-+    /* skip this domain if not requested and the user is trusted
-+     * as untrusted users can't request a domain */
-+    if (pctx->is_uid_trusted &&
-+            !is_domain_requested(preq->pd, preq->pd->domain)) {
-+        preq->pd->pam_status = PAM_USER_UNKNOWN;
-+        pam_reply(preq);
-+        return;
-+    }
-+
-     if (!NEED_CHECK_PROVIDER(preq->domain->provider)) {
-         preq->callback = pam_reply;
-         ret = LOCAL_pam_handler(preq);
--- 
-1.9.3
-
diff --git a/SOURCES/0117-PAM-Move-is_uid_trusted-from-pam_ctx-to-preq.patch b/SOURCES/0117-PAM-Move-is_uid_trusted-from-pam_ctx-to-preq.patch
deleted file mode 100644
index 25b5f5b..0000000
--- a/SOURCES/0117-PAM-Move-is_uid_trusted-from-pam_ctx-to-preq.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From 377741700be52a7f496231ab808a673e3e8ff10e Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Sun, 23 Nov 2014 21:07:58 +0100
-Subject: [PATCH 117/117] PAM: Move is_uid_trusted from pam_ctx to preq
-
-Keeping a per-request flag in a global structure is really dangerous.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/responder/pam/pamsrv.h     |  2 +-
- src/responder/pam/pamsrv_cmd.c | 23 ++++++++++++-----------
- 2 files changed, 13 insertions(+), 12 deletions(-)
-
-diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
-index f92e7f7db0964777c26d69c7c08471a19de8ade3..066f35a428a9af81d665309b4ab5a80cf69561ba 100644
---- a/src/responder/pam/pamsrv.h
-+++ b/src/responder/pam/pamsrv.h
-@@ -39,7 +39,6 @@ struct pam_ctx {
-     hash_table_t *id_table;
-     size_t trusted_uids_count;
-     uid_t *trusted_uids;
--    bool is_uid_trusted;
- 
-     /* List of domains that are accessible even for untrusted users. */
-     char **public_domains;
-@@ -58,6 +57,7 @@ struct pam_auth_req {
- 
-     pam_dp_callback_t *callback;
- 
-+    bool is_uid_trusted;
-     bool check_provider;
-     void *data;
- 
-diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
-index b60ccba2d4ff669e7ed0252923a53755410851e3..02720018b91e1319346a023eca571913b544284a 100644
---- a/src/responder/pam/pamsrv_cmd.c
-+++ b/src/responder/pam/pamsrv_cmd.c
-@@ -849,15 +849,6 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
-             talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx);
-     struct tevent_req *req;
- 
--    pctx->is_uid_trusted = is_uid_trusted(cctx->client_euid,
--                                          pctx->trusted_uids_count,
--                                          pctx->trusted_uids);
--
--    if (!pctx->is_uid_trusted) {
--        DEBUG(SSSDBG_MINOR_FAILURE, "uid %"PRIu32" is not trusted.\n",
--              cctx->client_euid);
--    }
--
-     preq = talloc_zero(cctx, struct pam_auth_req);
-     if (!preq) {
-         return ENOMEM;
-@@ -872,6 +863,16 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
-     }
-     pd = preq->pd;
- 
-+    preq->is_uid_trusted = is_uid_trusted(cctx->client_euid,
-+                                          pctx->trusted_uids_count,
-+                                          pctx->trusted_uids);
-+
-+    if (!preq->is_uid_trusted) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "uid %"PRIu32" is not trusted.\n",
-+              cctx->client_euid);
-+    }
-+
-+
-     pd->cmd = pam_cmd;
-     pd->priv = cctx->priv;
- 
-@@ -1304,7 +1305,7 @@ static void pam_dom_forwarder(struct pam_auth_req *preq)
-     }
- 
-     /* Untrusted users can access only public domains. */
--    if (!pctx->is_uid_trusted &&
-+    if (!preq->is_uid_trusted &&
-             !is_domain_public(preq->pd->domain, pctx->public_domains,
-                             pctx->public_domains_count)) {
-         DEBUG(SSSDBG_MINOR_FAILURE,
-@@ -1317,7 +1318,7 @@ static void pam_dom_forwarder(struct pam_auth_req *preq)
- 
-     /* skip this domain if not requested and the user is trusted
-      * as untrusted users can't request a domain */
--    if (pctx->is_uid_trusted &&
-+    if (preq->is_uid_trusted &&
-             !is_domain_requested(preq->pd, preq->pd->domain)) {
-         preq->pd->pam_status = PAM_USER_UNKNOWN;
-         pam_reply(preq);
--- 
-1.9.3
-
diff --git a/SOURCES/0118-krb5-make-krb5-provider-view-aware.patch b/SOURCES/0118-krb5-make-krb5-provider-view-aware.patch
deleted file mode 100644
index df110b6..0000000
--- a/SOURCES/0118-krb5-make-krb5-provider-view-aware.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-From f2a61159a9d8a73405d5dbc6f74bb176b3ee34c9 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 27 Nov 2014 10:01:40 +0100
-Subject: [PATCH 118/128] krb5: make krb5 provider view aware
-
-https://fedorahosted.org/sssd/ticket/2510
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_subdomains.c | 13 +++++++++++++
- src/providers/krb5/krb5_auth.c     | 18 ++++++++++++------
- 2 files changed, 25 insertions(+), 6 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index 6fdb0befa32f96d01c9b3666a3ef9c8331a83242..d053d46ac4208bd52fcbf524a11243896b849612 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -1174,6 +1174,19 @@ static void ipa_get_view_name_done(struct tevent_req *req)
-                 DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
-             }
-         }
-+
-+        /* TODO: only needed if view changed */
-+        ret = sysdb_master_domain_update(ctx->sd_ctx->be_ctx->domain);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_master_domain_update failed.\n");
-+            goto done;
-+        }
-+
-+        ret = sysdb_update_subdomains(ctx->sd_ctx->be_ctx->domain);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
-+            goto done;
-+        }
-     }
- 
-     ret = ipa_check_master(ctx);
-diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
-index e791aee1c2d83f84ba617db1d5d93948c0e4e2a1..e43b3652786678b79499e30ed546712ef080fe2c 100644
---- a/src/providers/krb5/krb5_auth.c
-+++ b/src/providers/krb5/krb5_auth.c
-@@ -462,8 +462,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-     }
-     kr = state->kr;
- 
--    ret = sysdb_get_user_attr(state, state->domain, state->pd->user, attrs,
--                              &res);
-+    ret = sysdb_get_user_attr_with_views(state, state->domain, state->pd->user,
-+                                         attrs, &res);
-     if (ret) {
-         DEBUG(SSSDBG_FUNC_DATA,
-               "sysdb search for upn of user [%s] failed.\n", pd->user);
-@@ -503,14 +503,18 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-             goto done;
-         }
- 
--        kr->homedir = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_HOMEDIR,
--                                                  NULL);
-+        kr->homedir = sss_view_ldb_msg_find_attr_as_string(state->domain,
-+                                                           res->msgs[0],
-+                                                           SYSDB_HOMEDIR,
-+                                                           NULL);
-         if (kr->homedir == NULL) {
-             DEBUG(SSSDBG_CONF_SETTINGS,
-                   "Home directory for user [%s] not known.\n", pd->user);
-         }
- 
--        kr->uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0);
-+        kr->uid = sss_view_ldb_msg_find_attr_as_uint64(state->domain,
-+                                                       res->msgs[0],
-+                                                       SYSDB_UIDNUM, 0);
-         if (kr->uid == 0) {
-             DEBUG(SSSDBG_CONF_SETTINGS,
-                   "UID for user [%s] not known.\n", pd->user);
-@@ -518,7 +522,9 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-             goto done;
-         }
- 
--        kr->gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
-+        kr->gid = sss_view_ldb_msg_find_attr_as_uint64(state->domain,
-+                                                       res->msgs[0],
-+                                                       SYSDB_GIDNUM, 0);
-         if (kr->gid == 0) {
-             DEBUG(SSSDBG_CONF_SETTINGS,
-                   "GID for user [%s] not known.\n", pd->user);
--- 
-1.9.3
-
diff --git a/SOURCES/0119-IPA-only-update-view-data-if-it-really-changed.patch b/SOURCES/0119-IPA-only-update-view-data-if-it-really-changed.patch
deleted file mode 100644
index 00e13b8..0000000
--- a/SOURCES/0119-IPA-only-update-view-data-if-it-really-changed.patch
+++ /dev/null
@@ -1,167 +0,0 @@
-From 50d00230cbbc4fd960ffd2ebfced826c2e671bc2 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 27 Nov 2014 13:41:37 +0100
-Subject: [PATCH 119/128] IPA: only update view data if it really changed
-
-https://fedorahosted.org/sssd/ticket/2510
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_subdomains.c | 116 +++++++++++++++++++++----------------
- 1 file changed, 66 insertions(+), 50 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index d053d46ac4208bd52fcbf524a11243896b849612..3148389f71135b6c64e62d1cf7f4064dd183f595 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -1110,23 +1110,44 @@ static void ipa_get_view_name_done(struct tevent_req *req)
-               "View name changed, this is not supported at runtime. " \
-               "Please restart SSSD to get the new view applied.\n");
-     } else {
--        ctx->sd_ctx->view_read_at_init = true;
--        /* View name changed */
--        if (ctx->sd_ctx->id_ctx->view_name != NULL) {
--            ret = sysdb_transaction_start(ctx->sd_ctx->be_ctx->domain->sysdb);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
--                goto done;
--            }
-+        if (ctx->sd_ctx->id_ctx->view_name == NULL
-+            || strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0) {
-+            /* View name changed */
- 
--            if (strcmp(ctx->sd_ctx->id_ctx->view_name,
--                       SYSDB_DEFAULT_VIEW_NAME) != 0) {
--                /* Old view was not the default view, delete view tree */
--                ret = sysdb_delete_view_tree(ctx->sd_ctx->be_ctx->domain->sysdb,
-+            if (ctx->sd_ctx->id_ctx->view_name != NULL) {
-+                ret = sysdb_transaction_start(
-+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_transaction_start failed.\n");
-+                    goto done;
-+                }
-+
-+                if (strcmp(ctx->sd_ctx->id_ctx->view_name,
-+                           SYSDB_DEFAULT_VIEW_NAME) != 0) {
-+                    /* Old view was not the default view, delete view tree */
-+                    ret = sysdb_delete_view_tree(
-+                                             ctx->sd_ctx->be_ctx->domain->sysdb,
-                                              ctx->sd_ctx->id_ctx->view_name);
-+                    if (ret != EOK) {
-+                        DEBUG(SSSDBG_OP_FAILURE,
-+                              "sysdb_delete_view_tree failed.\n");
-+                        sret = sysdb_transaction_cancel(
-+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
-+                        if (sret != EOK) {
-+                            DEBUG(SSSDBG_OP_FAILURE,
-+                                  "sysdb_transaction_cancel failed.\n");
-+                            goto done;
-+                        }
-+                        goto done;
-+                    }
-+                }
-+
-+                ret = sysdb_invalidate_overrides(
-+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
-                 if (ret != EOK) {
-                     DEBUG(SSSDBG_OP_FAILURE,
--                          "sysdb_delete_view_tree failed.\n");
-+                          "sysdb_invalidate_overrides failed.\n");
-                     sret = sysdb_transaction_cancel(
-                                             ctx->sd_ctx->be_ctx->domain->sysdb);
-                     if (sret != EOK) {
-@@ -1136,57 +1157,52 @@ static void ipa_get_view_name_done(struct tevent_req *req)
-                     }
-                     goto done;
-                 }
--            }
- 
--            ret = sysdb_invalidate_overrides(
-+                ret = sysdb_transaction_commit(
-                                             ctx->sd_ctx->be_ctx->domain->sysdb);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE,
--                      "sysdb_invalidate_overrides failed.\n");
--                sret = sysdb_transaction_cancel(
--                                            ctx->sd_ctx->be_ctx->domain->sysdb);
--                if (sret != EOK) {
--                    DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed.\n");
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                                          "sysdb_transaction_commit failed.\n");
-                     goto done;
-                 }
--                goto done;
-+
-+                /* TODO: start referesh task */
-             }
- 
--            ret = sysdb_transaction_commit(ctx->sd_ctx->be_ctx->domain->sysdb);
-+            ret = sysdb_update_view_name(ctx->sd_ctx->be_ctx->domain->sysdb,
-+                                         view_name);
-             if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed.\n");
--                goto done;
-+                DEBUG(SSSDBG_CRIT_FAILURE,
-+                      "Cannot add/update view name to sysdb.\n");
-+            } else {
-+                talloc_free(ctx->sd_ctx->id_ctx->view_name);
-+                ctx->sd_ctx->id_ctx->view_name = talloc_strdup(
-+                                                            ctx->sd_ctx->id_ctx,
-+                                                            view_name);
-+                if (ctx->sd_ctx->id_ctx->view_name == NULL) {
-+                    DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
-+                }
-             }
--
--            /* TODO: start referesh task */
-         }
- 
--        ret = sysdb_update_view_name(ctx->sd_ctx->be_ctx->domain->sysdb,
--                                     view_name);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_CRIT_FAILURE,
--                  "Cannot add/update view name to sysdb.\n");
--        } else {
--            talloc_free(ctx->sd_ctx->id_ctx->view_name);
--            ctx->sd_ctx->id_ctx->view_name = talloc_strdup(ctx->sd_ctx->id_ctx,
--                                                           view_name);
--            if (ctx->sd_ctx->id_ctx->view_name == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
-+        if (!ctx->sd_ctx->view_read_at_init) {
-+            /* refresh view data of all domains at startup */
-+            ret = sysdb_master_domain_update(ctx->sd_ctx->be_ctx->domain);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE,
-+                      "sysdb_master_domain_update failed.\n");
-+                goto done;
-+            }
-+
-+            ret = sysdb_update_subdomains(ctx->sd_ctx->be_ctx->domain);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
-+                goto done;
-             }
-         }
- 
--        /* TODO: only needed if view changed */
--        ret = sysdb_master_domain_update(ctx->sd_ctx->be_ctx->domain);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_OP_FAILURE, "sysdb_master_domain_update failed.\n");
--            goto done;
--        }
-+        ctx->sd_ctx->view_read_at_init = true;
- 
--        ret = sysdb_update_subdomains(ctx->sd_ctx->be_ctx->domain);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_subdomains failed.\n");
--            goto done;
--        }
-     }
- 
-     ret = ipa_check_master(ctx);
--- 
-1.9.3
-
diff --git a/SOURCES/0120-krb5-do-not-fail-if-checking-the-old-ccache-failed.patch b/SOURCES/0120-krb5-do-not-fail-if-checking-the-old-ccache-failed.patch
deleted file mode 100644
index 8e91746..0000000
--- a/SOURCES/0120-krb5-do-not-fail-if-checking-the-old-ccache-failed.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From 8aa6f3460bc0b1a5cf29b6958f508735b5e82999 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 27 Nov 2014 13:42:19 +0100
-Subject: [PATCH 120/128] krb5: do not fail if checking the old ccache failed
-
-https://fedorahosted.org/sssd/ticket/2510
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                     | 1 +
- src/providers/krb5/krb5_child.c | 7 +++++--
- 2 files changed, 6 insertions(+), 2 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 56a562c761d39ff5f54bc034ede563c40bf21ef8..130c647e51d3554b2b0f69e83f17b38f1366eb3b 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2505,6 +2505,7 @@ krb5_child_SOURCES = \
-     src/util/signal.c \
-     src/util/strtonum.c \
-     src/util/become_user.c \
-+    src/util/util_errors.c \
-     src/sss_client/common.c \
-     $(NULL)
- krb5_child_CFLAGS = \
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 94cd34e433cf6a197860d233fbf9ca30cd3eb535..d828dd550251d70851edcdc6b1eda6f5c051baf2 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -34,6 +34,7 @@
- #include "util/user_info_msg.h"
- #include "util/child_common.h"
- #include "util/find_uid.h"
-+#include "src/util/util_errors.h"
- #include "providers/dp_backend.h"
- #include "providers/krb5/krb5_auth.h"
- #include "providers/krb5/krb5_utils.h"
-@@ -2039,8 +2040,10 @@ static int k5c_ccache_setup(struct krb5_req *kr, uint32_t offline)
- 
-     ret = k5c_check_old_ccache(kr);
-     if (ret != 0) {
--        DEBUG(SSSDBG_OP_FAILURE, "Cannot check old ccache\n");
--        return ret;
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot check old ccache [%s]: [%d][%s]. " \
-+                                   "Assuming old cache is invalid " \
-+                                   "and not used.\n",
-+                                   kr->old_ccname, ret, sss_strerror(ret));
-     }
- 
-     /* Pre-creating the ccache must be done as root, otherwise we can't mkdir
--- 
-1.9.3
-
diff --git a/SOURCES/0121-test-avoid-leaks-in-leak-tests.patch b/SOURCES/0121-test-avoid-leaks-in-leak-tests.patch
deleted file mode 100644
index c7d226b..0000000
--- a/SOURCES/0121-test-avoid-leaks-in-leak-tests.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 664843123793879049459326127c2686f6361106 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 28 Nov 2014 18:16:33 +0100
-Subject: [PATCH 121/128] test: avoid leaks in leak tests
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/tests/cmocka/test_ifp.c | 5 ++++-
- src/tests/leak_check.c      | 6 +++++-
- 2 files changed, 9 insertions(+), 2 deletions(-)
-
-diff --git a/src/tests/cmocka/test_ifp.c b/src/tests/cmocka/test_ifp.c
-index d6e41706d5f55414c0376bd04d299ec6ad73c11e..5793f91911c1e15c2c241aaa51ffcd4196daea63 100644
---- a/src/tests/cmocka/test_ifp.c
-+++ b/src/tests/cmocka/test_ifp.c
-@@ -209,6 +209,8 @@ void test_el_to_dict(void **state)
-     dbus_message_iter_get_basic(&iter_dict, &attr_val);
-     assert_string_equal(attr_val, "two");
-     assert_false(dbus_message_iter_next(&iter_dict));
-+
-+    talloc_free(sr);
- }
- 
- static void assert_string_list_equal(const char **s1,
-@@ -500,7 +502,8 @@ int main(int argc, const char *argv[])
-         unit_test(ifp_test_req_create),
-         unit_test(ifp_test_req_wrong_uid),
-         unit_test(test_path_prefix),
--        unit_test(test_el_to_dict),
-+        unit_test_setup_teardown(test_el_to_dict,
-+                                 ifp_test_req_setup, ifp_test_req_teardown),
-         unit_test(test_attr_acl),
-         unit_test(test_attr_acl_ex),
-         unit_test(test_attr_allowed),
-diff --git a/src/tests/leak_check.c b/src/tests/leak_check.c
-index bb5698cd80d5b360433d95a6297b740bb5cded87..1eaa2cd097bda54094098a2947bb3834a9bf04f4 100644
---- a/src/tests/leak_check.c
-+++ b/src/tests/leak_check.c
-@@ -130,10 +130,14 @@ leak_check_setup(void)
- bool
- leak_check_teardown(void)
- {
-+    bool res;
-     check_leaks_pop(global_talloc_context);
-     if (snapshot_stack != NULL) {
-         _set_leak_err_msg("Exiting with a non-empty stack");
-         return false;
-     }
--    return check_leaks(global_talloc_context, 0);
-+    res = check_leaks(global_talloc_context, 0);
-+    talloc_disable_null_tracking();
-+    talloc_free(global_talloc_context);
-+    return res;
- }
--- 
-1.9.3
-
diff --git a/SOURCES/0122-krb5-add-copy_ccache_into_memory.patch b/SOURCES/0122-krb5-add-copy_ccache_into_memory.patch
deleted file mode 100644
index 256b98b..0000000
--- a/SOURCES/0122-krb5-add-copy_ccache_into_memory.patch
+++ /dev/null
@@ -1,441 +0,0 @@
-From 3e53a8cd98b9410cd378ad68d8528e2a8d6d4f6a Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 17 Nov 2014 17:39:38 +0100
-Subject: [PATCH 122/128] krb5: add copy_ccache_into_memory()
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                         |  18 +++
- src/providers/krb5/krb5_ccache.c    | 110 +++++++++++++++++
- src/providers/krb5/krb5_ccache.h    |  17 +++
- src/tests/cmocka/test_copy_ccache.c | 238 ++++++++++++++++++++++++++++++++++++
- 4 files changed, 383 insertions(+)
- create mode 100644 src/tests/cmocka/test_copy_ccache.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 130c647e51d3554b2b0f69e83f17b38f1366eb3b..62d900dec654baff59762c934885aef9ae5510b9 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -214,6 +214,7 @@ if HAVE_CMOCKA
-         test_search_bases \
-         sdap-tests \
-         test_sysdb_views \
-+        test_copy_ccache \
-         $(NULL)
- 
- if BUILD_IFP
-@@ -2079,6 +2080,23 @@ test_sysdb_views_LDADD = \
-     libsss_test_common.la \
-     $(NULL)
- 
-+test_copy_ccache_SOURCES = \
-+    src/tests/cmocka/test_copy_ccache.c \
-+    src/providers/krb5/krb5_ccache.c \
-+    src/util/sss_krb5.c \
-+    $(NULL)
-+test_copy_ccache_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(NULL)
-+test_copy_ccache_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(POPT_LIBS) \
-+    $(TALLOC_LIBS) \
-+    $(KRB5_LIBS) \
-+    $(SSSD_INTERNAL_LTLIBS) \
-+    libsss_test_common.la \
-+    $(NULL)
-+
- endif # HAVE_CMOCKA
- 
- noinst_PROGRAMS = pam_test_client
-diff --git a/src/providers/krb5/krb5_ccache.c b/src/providers/krb5/krb5_ccache.c
-index 7aa36b744ddcf7e46edcc26405a5101645b8b546..de6e694a9ba7099e3b05fa8ab3aa9245c280dba5 100644
---- a/src/providers/krb5/krb5_ccache.c
-+++ b/src/providers/krb5/krb5_ccache.c
-@@ -667,3 +667,113 @@ errno_t safe_remove_old_ccache_file(const char *old_ccache,
- 
-     return sss_krb5_cc_destroy(old_ccache, uid, gid);
- }
-+
-+krb5_error_code copy_ccache_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-+                                        const char *ccache_file,
-+                                        char **_mem_name)
-+{
-+    krb5_error_code kerr;
-+    krb5_ccache ccache;
-+    krb5_ccache mem_ccache = NULL;
-+    char *ccache_name = NULL;
-+    krb5_principal princ = NULL;
-+    char *mem_name = NULL;
-+    char *sep;
-+
-+    kerr = krb5_cc_resolve(kctx, ccache_file, &ccache);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error resolving ccache [%s].\n",
-+                                    ccache_file);
-+        return kerr;
-+    }
-+
-+    kerr = krb5_cc_get_full_name(kctx, ccache, &ccache_name);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to read name for ccache [%s].\n",
-+                                    ccache_file);
-+        goto done;
-+    }
-+
-+    sep = strchr(ccache_name, ':');
-+    if (sep == NULL || sep[1] == '\0') {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Ccache name [%s] does not have delimiter[:] .\n", ccache_name);
-+        kerr = KRB5KRB_ERR_GENERIC;
-+        goto done;
-+    }
-+
-+    if (strncmp(ccache_name, "MEMORY:", sizeof("MEMORY:") -1) == 0) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "Ccache [%s] is already memory ccache.\n",
-+                                 ccache_name);
-+        *_mem_name = talloc_strdup(mem_ctx, ccache_name);
-+        if(*_mem_name == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+            kerr = KRB5KRB_ERR_GENERIC;
-+            goto done;
-+        }
-+        kerr = 0;
-+        goto done;
-+    }
-+    if (strncmp(ccache_name, "FILE:", sizeof("FILE:") -1) == 0) {
-+        mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s", sep + 1);
-+        if (mem_name == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
-+            kerr = KRB5KRB_ERR_GENERIC;
-+            goto done;
-+        }
-+    } else {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected ccache type for ccache [%s], " \
-+                                    "currently only FILE is supported.\n",
-+                                    ccache_name);
-+        kerr = KRB5KRB_ERR_GENERIC;
-+        goto done;
-+    }
-+
-+    kerr = krb5_cc_resolve(kctx, mem_name, &mem_ccache);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error resolving ccache [%s].\n", mem_name);
-+        goto done;
-+    }
-+
-+    kerr = krb5_cc_get_principal(kctx, ccache, &princ);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "error reading principal from ccache [%s].\n", ccache_name);
-+        goto done;
-+    }
-+
-+    kerr = krb5_cc_initialize(kctx, mem_ccache, princ);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Failed to initialize ccache [%s].\n", mem_name);
-+        goto done;
-+    }
-+
-+    kerr = krb5_cc_copy_creds(kctx, ccache, mem_ccache);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Failed to copy ccache [%s] to [%s].\n", ccache_name, mem_name);
-+        goto done;
-+    }
-+
-+    *_mem_name = mem_name;
-+    kerr = 0;
-+
-+done:
-+    if (kerr != 0) {
-+        talloc_free(mem_name);
-+    }
-+
-+    free(ccache_name);
-+    krb5_free_principal(kctx, princ);
-+
-+    if (krb5_cc_close(kctx, ccache) != 0) {
-+        DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_close failed.\n");
-+    }
-+
-+    if (krb5_cc_close(kctx, mem_ccache) != 0) {
-+        DEBUG(SSSDBG_OP_FAILURE, "krb5_cc_close failed.\n");
-+    }
-+
-+    return  kerr;
-+}
-diff --git a/src/providers/krb5/krb5_ccache.h b/src/providers/krb5/krb5_ccache.h
-index e47df3665e3f325cc56d34767b416662577cc048..f3928e644d704ed263cbe28bab327bf75b2f5cce 100644
---- a/src/providers/krb5/krb5_ccache.h
-+++ b/src/providers/krb5/krb5_ccache.h
-@@ -53,4 +53,21 @@ errno_t safe_remove_old_ccache_file(const char *old_ccache,
-                                     const char *new_ccache,
-                                     uid_t uid, gid_t gid);
- 
-+/**
-+ * @brief Copy given ccache into a MEMORY ccache
-+ *
-+ * @param[in] mem_ctx Talloc memory context the new ccache name should be
-+ *                    allocated on
-+ * @param[in] kctx Kerberos context
-+ * @param[in] ccache_file Name of existing ccache
-+ * @param[out] _mem_name Name of the new MEMORY ccache
-+ *
-+ * In contrast to MEMORY keytabs MEMORY ccaches can and must be removed
-+ * explicitly with krb5_cc_destroy() from the memory. Just calling
-+ * krb5_cc_close() will keep the MEMORY ccache in memory even if there are no
-+ * open handles for the given MEMORY ccache.
-+ */
-+krb5_error_code copy_ccache_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-+                                        const char *ccache_file,
-+                                        char **_mem_name);
- #endif /* __KRB5_CCACHE_H__ */
-diff --git a/src/tests/cmocka/test_copy_ccache.c b/src/tests/cmocka/test_copy_ccache.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..c7a5573b83b8faeb5c7447b48fa40ec8957e1aaf
---- /dev/null
-+++ b/src/tests/cmocka/test_copy_ccache.c
-@@ -0,0 +1,238 @@
-+/*
-+    Authors:
-+        Sumit Bose <sbose@redhat.com>
-+
-+    Copyright (C) 2014 Red Hat
-+
-+    SSSD tests: Tests ccache utilities
-+
-+    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 <stdio.h>
-+#include <popt.h>
-+
-+#include "util/sss_krb5.h"
-+#include "providers/krb5/krb5_common.h"
-+#include "providers/krb5/krb5_ccache.h"
-+#include "tests/cmocka/common_mock.h"
-+
-+#define CCACHE_TEST_CLIENT_PRINC "test/client@TEST.CCACHE"
-+#define CCACHE_TEST_SERVER_PRINC "test/server@TEST.CCACHE"
-+#define CCACHE_PATH TEST_DIR "/ccache_test.ccache"
-+
-+struct ccache_test_ctx {
-+    krb5_context kctx;
-+    const char *ccache_file_name;
-+    krb5_principal client_principal;
-+    krb5_principal server_principal;
-+};
-+
-+void setup_ccache(void **state)
-+{
-+    struct ccache_test_ctx *test_ctx;
-+    krb5_error_code kerr;
-+    krb5_ccache ccache;
-+    krb5_creds test_creds;
-+    static krb5_address addr;
-+    int add=0x12345;
-+    krb5_authdata *a;
-+
-+    static krb5_address *addrs[] = {
-+        &addr,
-+        NULL,
-+    };
-+
-+    assert_true(leak_check_setup());
-+
-+
-+    test_ctx = talloc_zero(global_talloc_context, struct ccache_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    kerr = krb5_init_context(&test_ctx->kctx);
-+    assert_int_equal(kerr, 0);
-+
-+    addr.magic = KV5M_ADDRESS;
-+    addr.addrtype = ADDRTYPE_INET;
-+    addr.length = 4;
-+    addr.contents = (krb5_octet *) &add;
-+
-+    memset(&test_creds, 0, sizeof(test_creds));
-+    test_creds.magic = KV5M_CREDS;
-+    kerr = krb5_parse_name(test_ctx->kctx, CCACHE_TEST_CLIENT_PRINC,
-+                           &test_ctx->client_principal);
-+    assert_int_equal(kerr, 0);
-+    test_creds.client = test_ctx->client_principal;
-+    kerr = krb5_parse_name(test_ctx->kctx, CCACHE_TEST_SERVER_PRINC,
-+                           &test_ctx->server_principal);
-+    assert_int_equal(kerr, 0);
-+    test_creds.server = test_ctx->server_principal;
-+
-+    test_creds.keyblock.magic = KV5M_KEYBLOCK;
-+    test_creds.keyblock.contents = 0;
-+    test_creds.keyblock.enctype = 1;
-+    test_creds.keyblock.length = 1;
-+    test_creds.keyblock.contents = (unsigned char *) discard_const("1");
-+    test_creds.times.authtime = 1111;
-+    test_creds.times.starttime = 2222;
-+    test_creds.times.endtime = 3333;
-+    test_creds.times.renew_till = 4444;
-+    test_creds.is_skey = 1;
-+    test_creds.ticket_flags = 5555;
-+    test_creds.addresses = addrs;
-+
-+    test_creds.ticket.magic = KV5M_DATA;
-+    test_creds.ticket.length = sizeof("Ticket");
-+    test_creds.ticket.data = discard_const("Ticket");
-+
-+    test_creds.authdata = malloc (2 * sizeof(krb5_authdata *));
-+    assert_non_null(test_creds.authdata);
-+
-+    a = (krb5_authdata *) malloc(sizeof(krb5_authdata));
-+    assert_non_null(a);
-+
-+    a->magic = KV5M_AUTHDATA;
-+    a->ad_type = KRB5_AUTHDATA_IF_RELEVANT;
-+    a->contents = (krb5_octet * ) malloc(1);
-+    assert_non_null(a->contents);
-+    a->contents[0]=5;
-+    a->length = 1;
-+    test_creds.authdata[0] = a;
-+    test_creds.authdata[1] = NULL;
-+
-+
-+    test_ctx->ccache_file_name = "FILE:" CCACHE_PATH;
-+
-+    kerr = krb5_cc_resolve(test_ctx->kctx, test_ctx->ccache_file_name,
-+                               &ccache);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = krb5_cc_initialize(test_ctx->kctx, ccache, test_creds.client);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = krb5_cc_store_cred(test_ctx->kctx, ccache, &test_creds);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = krb5_cc_close(test_ctx->kctx, ccache);
-+    assert_int_equal(kerr, 0);
-+
-+    check_leaks_push(test_ctx);
-+    *state = test_ctx;
-+
-+    krb5_free_authdata(test_ctx->kctx, test_creds.authdata);
-+}
-+
-+void teardown_ccache(void **state)
-+{
-+    int ret;
-+    struct ccache_test_ctx *test_ctx = talloc_get_type(*state,
-+                                                        struct ccache_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    krb5_free_principal(test_ctx->kctx, test_ctx->client_principal);
-+    krb5_free_principal(test_ctx->kctx, test_ctx->server_principal);
-+    krb5_free_context(test_ctx->kctx);
-+
-+    ret = unlink(CCACHE_PATH);
-+    assert_int_equal(ret, 0);
-+
-+    assert_true(check_leaks_pop(test_ctx) == true);
-+    talloc_free(test_ctx);
-+    assert_true(leak_check_teardown());
-+}
-+
-+void test_copy_ccache(void **state)
-+{
-+    krb5_error_code kerr;
-+    char *mem_ccache_name;
-+    krb5_ccache ccache;
-+    krb5_creds mcreds;
-+    krb5_creds creds;
-+    krb5_principal mem_principal;
-+    struct ccache_test_ctx *test_ctx = talloc_get_type(*state,
-+                                                        struct ccache_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    kerr = copy_ccache_into_memory(test_ctx, test_ctx->kctx,
-+                                   test_ctx->ccache_file_name,
-+                                   &mem_ccache_name);
-+    assert_int_equal(kerr, 0);
-+    assert_non_null(mem_ccache_name);
-+
-+    kerr = krb5_cc_resolve(test_ctx->kctx, mem_ccache_name, &ccache);
-+    assert_int_equal(kerr, 0);
-+
-+    talloc_free(mem_ccache_name);
-+
-+    kerr = krb5_cc_get_principal(test_ctx->kctx, ccache, &mem_principal);
-+    assert_int_equal(kerr, 0);
-+    assert_non_null(mem_principal);
-+
-+    assert_true(krb5_principal_compare(test_ctx->kctx, mem_principal,
-+                                       test_ctx->client_principal));
-+    krb5_free_principal(test_ctx->kctx, mem_principal);
-+
-+    memset(&mcreds, 0, sizeof(mcreds));
-+    memset(&creds, 0, sizeof(mcreds));
-+    mcreds.client = test_ctx->client_principal;
-+    mcreds.server = test_ctx->server_principal;
-+    kerr = krb5_cc_retrieve_cred(test_ctx->kctx, ccache, 0, &mcreds, &creds);
-+    assert_int_equal(kerr, 0);
-+    krb5_free_cred_contents(test_ctx->kctx, &creds);
-+
-+    kerr = krb5_cc_destroy(test_ctx->kctx, ccache);
-+    assert_int_equal(kerr, 0);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    poptContext pc;
-+    int opt;
-+    int rv;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test_setup_teardown(test_copy_ccache,
-+                                 setup_ccache, teardown_ccache),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    /* Even though normally the tests should clean up after themselves
-+     * they might not after a failed run. Remove the old db to be sure */
-+    tests_set_cwd();
-+
-+    rv = run_tests(tests);
-+
-+    return rv;
-+}
--- 
-1.9.3
-
diff --git a/SOURCES/0123-krb5-add-copy_keytab_into_memory.patch b/SOURCES/0123-krb5-add-copy_keytab_into_memory.patch
deleted file mode 100644
index 6a9f46f..0000000
--- a/SOURCES/0123-krb5-add-copy_keytab_into_memory.patch
+++ /dev/null
@@ -1,484 +0,0 @@
-From c3dd5cd9ba4020d0db0dd4ae1d9003ba852780c8 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 17 Nov 2014 17:40:26 +0100
-Subject: [PATCH 123/128] krb5: add copy_keytab_into_memory()
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                         |  18 +++
- src/providers/krb5/krb5_common.h    |  31 ++++++
- src/providers/krb5/krb5_keytab.c    | 165 ++++++++++++++++++++++++++++
- src/tests/cmocka/test_copy_keytab.c | 213 ++++++++++++++++++++++++++++++++++++
- 4 files changed, 427 insertions(+)
- create mode 100644 src/providers/krb5/krb5_keytab.c
- create mode 100644 src/tests/cmocka/test_copy_keytab.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 62d900dec654baff59762c934885aef9ae5510b9..065992b84ce491b8b6ce1826cb5e88d7e0295176 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -215,6 +215,7 @@ if HAVE_CMOCKA
-         sdap-tests \
-         test_sysdb_views \
-         test_copy_ccache \
-+        test_copy_keytab \
-         $(NULL)
- 
- if BUILD_IFP
-@@ -2097,6 +2098,23 @@ test_copy_ccache_LDADD = \
-     libsss_test_common.la \
-     $(NULL)
- 
-+test_copy_keytab_SOURCES = \
-+    src/tests/cmocka/test_copy_keytab.c \
-+    src/providers/krb5/krb5_keytab.c \
-+    src/util/sss_krb5.c \
-+    $(NULL)
-+test_copy_keytab_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    $(NULL)
-+test_copy_keytab_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(POPT_LIBS) \
-+    $(TALLOC_LIBS) \
-+    $(KRB5_LIBS) \
-+    $(SSSD_INTERNAL_LTLIBS) \
-+    libsss_test_common.la \
-+    $(NULL)
-+
- endif # HAVE_CMOCKA
- 
- noinst_PROGRAMS = pam_test_client
-diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
-index a5cee6497e4930b16b1102a525d9fa3452845a58..81e64688a6d93a4b3ecf41d75d1bf6166b4619ce 100644
---- a/src/providers/krb5/krb5_common.h
-+++ b/src/providers/krb5/krb5_common.h
-@@ -189,4 +189,35 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
-                         struct bet_ops **ops,
-                         void **pvt_auth_data);
- 
-+/* from krb5_keytab.c */
-+
-+/**
-+ * @brief Copy given keytab into a MEMORY keytab
-+ *
-+ * @param[in] mem_ctx Talloc memory context the new keytab name should be
-+ *                    allocated on
-+ * @param[in] kctx Kerberos context
-+ * @param[in] inp_keytab_file Existing keytab, if set to NULL the default
-+ *                            keytab will be used
-+ * @param[out] _mem_name Name of the new MEMORY keytab
-+ * @param[out] _mem_keytab Krb5 keytab handle for the new MEMORY keytab, NULL
-+ *                         may be passed here if the caller has no use for the
-+ *                         handle
-+ *
-+ * The memory for the MEMORY keytab is handled by libkrb5 internally and
-+ * a reference counter is used. If the reference counter of the specific
-+ * MEMORY keytab reaches 0, i.e. no open ones are left, the memory is free.
-+ * This means we cannot call krb5_kt_close() for the new MEMORY keytab  in
-+ * copy_keytab_into_memory() because this would destroy it immediately. Hence
-+ * we have to return the handle so that the caller can safely remove the
-+ * MEMORY keytab if the is not needed anymore. Since libkrb5 frees the
-+ * internal memory when the library is unloaded short running processes can
-+ * safely pass NULL as the 5th argument because on exit all memory is freed.
-+ * Long running processes which need more control over the memory consumption
-+ * should close the handle for free the memory at runtime.
-+ */
-+krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-+                                        const char *inp_keytab_file,
-+                                        char **_mem_name,
-+                                        krb5_keytab *_mem_keytab);
- #endif /* __KRB5_COMMON_H__ */
-diff --git a/src/providers/krb5/krb5_keytab.c b/src/providers/krb5/krb5_keytab.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..855f69419611b863a7aea79e2788272f819b0736
---- /dev/null
-+++ b/src/providers/krb5/krb5_keytab.c
-@@ -0,0 +1,165 @@
-+/*
-+    SSSD
-+
-+    Kerberos 5 Backend Module -- keytab related utilities
-+
-+    Authors:
-+        Sumit Bose <sbose@redhat.com>
-+
-+    Copyright (C) 2014 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 "util/util.h"
-+#include "util/sss_krb5.h"
-+
-+krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-+                                        char *inp_keytab_file,
-+                                        char **_mem_name,
-+                                        krb5_keytab *_mem_keytab)
-+{
-+    krb5_error_code kerr;
-+    krb5_error_code kt_err;
-+    krb5_keytab keytab = NULL;
-+    krb5_keytab mem_keytab = NULL;
-+    krb5_kt_cursor cursor;
-+    krb5_keytab_entry entry;
-+    char keytab_name[MAX_KEYTAB_NAME_LEN];
-+    char *sep;
-+    char *mem_name = NULL;
-+    char *keytab_file;
-+    char default_keytab_name[MAX_KEYTAB_NAME_LEN];
-+
-+    keytab_file = inp_keytab_file;
-+    if (keytab_file == NULL) {
-+        kerr = krb5_kt_default_name(kctx, default_keytab_name,
-+                                    sizeof(default_keytab_name));
-+        if (kerr != 0) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_default_name failed.\n");
-+            return kerr;
-+        }
-+
-+        keytab_file = default_keytab_name;
-+    }
-+
-+    kerr = krb5_kt_resolve(kctx, keytab_file, &keytab);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n",
-+                                    keytab_file);
-+        return kerr;
-+    }
-+
-+    kerr = krb5_kt_have_content(kctx, keytab);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "keytab [%s] has not entries.\n",
-+                                    keytab_file);
-+        goto done;
-+    }
-+
-+    kerr = krb5_kt_get_name(kctx, keytab, keytab_name, sizeof(keytab_name));
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to read name for keytab [%s].\n",
-+                                    keytab_file);
-+        goto done;
-+    }
-+
-+    sep = strchr(keytab_name, ':');
-+    if (sep == NULL || sep[1] == '\0') {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Keytab name [%s] does not have delimiter[:] .\n", keytab_name);
-+        kerr = KRB5KRB_ERR_GENERIC;
-+        goto done;
-+    }
-+
-+    if (strncmp(keytab_name, "MEMORY:", sizeof("MEMORY:") -1) == 0) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "Keytab [%s] is already memory keytab.\n",
-+                                 keytab_name);
-+        *_mem_name = talloc_strdup(mem_ctx, keytab_name);
-+        if(*_mem_name == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+            kerr = KRB5KRB_ERR_GENERIC;
-+            goto done;
-+        }
-+        kerr = 0;
-+        goto done;
-+    }
-+
-+    mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s", sep + 1);
-+    if (mem_name == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
-+        kerr = KRB5KRB_ERR_GENERIC;
-+        goto done;
-+    }
-+
-+    kerr = krb5_kt_resolve(kctx, mem_name, &mem_keytab);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n",
-+                                    mem_name);
-+        goto done;
-+    }
-+
-+    memset(&cursor, 0, sizeof(cursor));
-+    kerr = krb5_kt_start_seq_get(kctx, keytab, &cursor);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab [%s].\n", keytab_file);
-+        goto done;
-+    }
-+
-+    memset(&entry, 0, sizeof(entry));
-+    while ((kt_err = krb5_kt_next_entry(kctx, keytab, &entry, &cursor)) == 0) {
-+        kerr = krb5_kt_add_entry(kctx, mem_keytab, &entry);
-+        if (kerr != 0) {
-+            DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_add_entry failed.\n");
-+            goto done;
-+        }
-+
-+        kerr = sss_krb5_free_keytab_entry_contents(kctx, &entry);
-+        if (kerr != 0) {
-+            DEBUG(SSSDBG_MINOR_FAILURE, "Failed to free keytab entry.\n");
-+        }
-+        memset(&entry, 0, sizeof(entry));
-+    }
-+
-+    kerr = krb5_kt_end_seq_get(kctx, keytab, &cursor);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n");
-+        goto done;
-+    }
-+
-+    /* check if we got any errors from krb5_kt_next_entry */
-+    if (kt_err != 0 && kt_err != KRB5_KT_END) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab [%s].\n", keytab_file);
-+        kerr = KRB5KRB_ERR_GENERIC;
-+        goto done;
-+    }
-+
-+    *_mem_name = mem_name;
-+    if (_mem_keytab != NULL) {
-+        *_mem_keytab = mem_keytab;
-+    }
-+
-+    kerr = 0;
-+done:
-+
-+    if (kerr != 0) {
-+        talloc_free(mem_name);
-+    }
-+
-+    if (keytab != NULL && krb5_kt_close(kctx, keytab) != 0) {
-+            DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed");
-+    }
-+
-+    return kerr;
-+}
-diff --git a/src/tests/cmocka/test_copy_keytab.c b/src/tests/cmocka/test_copy_keytab.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..9d2b801564f738b4a75445045bd7602b2fd01625
---- /dev/null
-+++ b/src/tests/cmocka/test_copy_keytab.c
-@@ -0,0 +1,213 @@
-+/*
-+    Authors:
-+        Sumit Bose <sbose@redhat.com>
-+
-+    Copyright (C) 2014 Red Hat
-+
-+    SSSD tests: Tests keytab utilities
-+
-+    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 <stdio.h>
-+#include <popt.h>
-+
-+#include "util/sss_krb5.h"
-+#include "providers/krb5/krb5_common.h"
-+#include "tests/cmocka/common_mock.h"
-+
-+#define KEYTAB_TEST_PRINC "test/keytab@TEST.KEYTAB"
-+#define KEYTAB_PATH TEST_DIR "/keytab_test.keytab"
-+
-+struct keytab_test_ctx {
-+    krb5_context kctx;
-+    const char *keytab_file_name;
-+    krb5_principal principal;
-+};
-+
-+void setup_keytab(void **state)
-+{
-+    struct keytab_test_ctx *test_ctx;
-+    krb5_error_code kerr;
-+    krb5_keytab keytab;
-+    krb5_keytab_entry kent;
-+
-+    assert_true(leak_check_setup());
-+
-+    test_ctx = talloc_zero(global_talloc_context, struct keytab_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    kerr = krb5_init_context(&test_ctx->kctx);
-+    assert_int_equal(kerr, 0);
-+
-+    test_ctx->keytab_file_name = "FILE:" KEYTAB_PATH;
-+
-+    kerr = krb5_kt_resolve(test_ctx->kctx, test_ctx->keytab_file_name, &keytab);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = krb5_parse_name(test_ctx->kctx, KEYTAB_TEST_PRINC,
-+                           &test_ctx->principal);
-+    assert_int_equal(kerr, 0);
-+
-+    memset(&kent, 0, sizeof(kent));
-+    kent.magic = KV5M_KEYTAB_ENTRY;
-+    kent.principal = test_ctx->principal;
-+    kent.timestamp = 12345;
-+    kent.vno = 1;
-+    kent.key.magic = KV5M_KEYBLOCK;
-+    kent.key.enctype = 1;
-+    kent.key.length = 2;
-+    kent.key.contents = (krb5_octet *) discard_const("11");
-+
-+    kerr = krb5_kt_add_entry(test_ctx->kctx, keytab, &kent);
-+    assert_int_equal(kerr, 0);
-+
-+    kent.key.enctype = 2;
-+    kent.key.contents = (krb5_octet *) discard_const("12");
-+
-+    kerr = krb5_kt_add_entry(test_ctx->kctx, keytab, &kent);
-+    assert_int_equal(kerr, 0);
-+
-+    kent.vno = 2;
-+    kent.key.enctype = 1;
-+    kent.key.contents = (krb5_octet *) discard_const("21");
-+
-+    kerr = krb5_kt_add_entry(test_ctx->kctx, keytab, &kent);
-+    assert_int_equal(kerr, 0);
-+
-+    kent.key.enctype = 2;
-+    kent.key.contents = (krb5_octet *) discard_const("22");
-+
-+    kerr = krb5_kt_add_entry(test_ctx->kctx, keytab, &kent);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = krb5_kt_close(test_ctx->kctx, keytab);
-+    assert_int_equal(kerr, 0);
-+
-+    check_leaks_push(test_ctx);
-+    *state = test_ctx;
-+}
-+
-+void teardown_keytab(void **state)
-+{
-+    int ret;
-+    struct keytab_test_ctx *test_ctx = talloc_get_type(*state,
-+                                                        struct keytab_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    krb5_free_principal(test_ctx->kctx, test_ctx->principal);
-+    krb5_free_context(test_ctx->kctx);
-+
-+    ret = unlink(KEYTAB_PATH);
-+    assert_int_equal(ret, 0);
-+
-+    assert_true(check_leaks_pop(test_ctx) == true);
-+    talloc_free(test_ctx);
-+    assert_true(leak_check_teardown());
-+}
-+
-+void test_copy_keytab(void **state)
-+{
-+    krb5_error_code kerr;
-+    char *mem_keytab_name;
-+    krb5_keytab mem_keytab;
-+    krb5_keytab keytab;
-+    krb5_keytab_entry kent;
-+    struct keytab_test_ctx *test_ctx = talloc_get_type(*state,
-+                                                        struct keytab_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    kerr = copy_keytab_into_memory(test_ctx, test_ctx->kctx,
-+                                   test_ctx->keytab_file_name,
-+                                   &mem_keytab_name, &mem_keytab);
-+    assert_int_equal(kerr, 0);
-+    assert_non_null(mem_keytab_name);
-+
-+    kerr = krb5_kt_resolve(test_ctx->kctx, mem_keytab_name, &keytab);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = krb5_kt_get_entry(test_ctx->kctx, keytab, test_ctx->principal, 9, 9,
-+                             &kent);
-+    assert_int_not_equal(kerr, 0);
-+
-+    kerr = krb5_kt_get_entry(test_ctx->kctx, keytab, test_ctx->principal, 1, 1,
-+                             &kent);
-+    assert_int_equal(kerr, 0);
-+    krb5_free_keytab_entry_contents(test_ctx->kctx, &kent);
-+
-+    kerr = krb5_kt_get_entry(test_ctx->kctx, keytab, test_ctx->principal, 1, 2,
-+                             &kent);
-+    assert_int_equal(kerr, 0);
-+    krb5_free_keytab_entry_contents(test_ctx->kctx, &kent);
-+
-+    kerr = krb5_kt_get_entry(test_ctx->kctx, keytab, test_ctx->principal, 2, 1,
-+                             &kent);
-+    assert_int_equal(kerr, 0);
-+    krb5_free_keytab_entry_contents(test_ctx->kctx, &kent);
-+
-+    kerr = krb5_kt_get_entry(test_ctx->kctx, keytab, test_ctx->principal, 2, 2,
-+                             &kent);
-+    assert_int_equal(kerr, 0);
-+    krb5_free_keytab_entry_contents(test_ctx->kctx, &kent);
-+
-+    talloc_free(mem_keytab_name);
-+
-+    kerr = krb5_kt_close(test_ctx->kctx, keytab);
-+    assert_int_equal(kerr, 0);
-+
-+    kerr = krb5_kt_close(test_ctx->kctx, mem_keytab);
-+    assert_int_equal(kerr, 0);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    poptContext pc;
-+    int opt;
-+    int rv;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test_setup_teardown(test_copy_keytab,
-+                                 setup_keytab, teardown_keytab),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    /* Even though normally the tests should clean up after themselves
-+     * they might not after a failed run. Remove the old db to be sure */
-+    tests_set_cwd();
-+
-+    rv = run_tests(tests);
-+
-+    return rv;
-+}
--- 
-1.9.3
-
diff --git a/SOURCES/0124-ldap_child-copy-keytab-into-memory-to-drop-privilege.patch b/SOURCES/0124-ldap_child-copy-keytab-into-memory-to-drop-privilege.patch
deleted file mode 100644
index 27ea1c3..0000000
--- a/SOURCES/0124-ldap_child-copy-keytab-into-memory-to-drop-privilege.patch
+++ /dev/null
@@ -1,159 +0,0 @@
-From ebda717383bf29731c3b4d7e809be7c7fae76284 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 1 Dec 2014 17:24:31 +0100
-Subject: [PATCH 124/128] ldap_child: copy keytab into memory to drop
- privileges earlier
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                     |  1 +
- src/providers/ldap/ldap_child.c | 64 +++++++++++++++++++++++++++++------------
- 2 files changed, 46 insertions(+), 19 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 065992b84ce491b8b6ce1826cb5e88d7e0295176..3d16428856d6cb2e9e190b0df8895ab3f45db39c 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2564,6 +2564,7 @@ krb5_child_LDADD = \
- 
- ldap_child_SOURCES = \
-     src/providers/ldap/ldap_child.c \
-+    src/providers/krb5/krb5_keytab.c \
-     src/util/sss_krb5.c \
-     src/util/atomic_io.c \
-     src/util/authtok.c \
-diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
-index a922b181715c5e89301e9f50bdb81723d1ff2a6a..f7f8d1d2eab3f66fe4f7d09e50458b495739c1d2 100644
---- a/src/providers/ldap/ldap_child.c
-+++ b/src/providers/ldap/ldap_child.c
-@@ -33,6 +33,7 @@
- #include "util/sss_krb5.h"
- #include "util/child_common.h"
- #include "providers/dp_backend.h"
-+#include "providers/krb5/krb5_common.h"
- 
- static krb5_context krb5_error_ctx;
- #define LDAP_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error)
-@@ -47,8 +48,9 @@ static const char *__ldap_child_krb5_error_msg;
- struct input_buffer {
-     const char *realm_str;
-     const char *princ_str;
--    const char *keytab_name;
-+    char *keytab_name;
-     krb5_deltat lifetime;
-+    krb5_context context;
-     uid_t uid;
-     gid_t gid;
- };
-@@ -246,12 +248,11 @@ static int lc_verify_keytab_ex(const char *principal,
- }
- 
- static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-+                                               krb5_context context,
-                                                const char *realm_str,
-                                                const char *princ_str,
-                                                const char *keytab_name,
-                                                const krb5_deltat lifetime,
--                                               uid_t uid,
--                                               gid_t gid,
-                                                const char **ccname_out,
-                                                time_t *expire_time_out)
- {
-@@ -262,7 +263,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-     char *full_princ = NULL;
-     char *default_realm = NULL;
-     char *tmp_str = NULL;
--    krb5_context context = NULL;
-     krb5_keytab keytab = NULL;
-     krb5_ccache ccache = NULL;
-     krb5_principal kprinc;
-@@ -278,13 +278,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-     char *ccname_file;
-     mode_t old_umask;
- 
--    krberr = krb5_init_context(&context);
--    if (krberr) {
--        DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n");
--        return krberr;
--    }
--    DEBUG(SSSDBG_TRACE_INTERNAL, "Kerberos context initialized\n");
--
-     tmp_ctx = talloc_new(memctx);
-     if (tmp_ctx == NULL) {
-         krberr = KRB5KRB_ERR_GENERIC;
-@@ -440,12 +433,6 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-     }
-     DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n");
- 
--    krberr = become_user(uid, gid);
--    if (krberr != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
--        goto done;
--    }
--
-     ccname_dummy = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file_dummy);
-     ccname = talloc_asprintf(tmp_ctx, "FILE:%s", ccname_file);
-     if (ccname_dummy == NULL || ccname == NULL) {
-@@ -558,6 +545,30 @@ static int prepare_response(TALLOC_CTX *mem_ctx,
-     return EOK;
- }
- 
-+static krb5_error_code privileged_krb5_setup(struct input_buffer *ibuf)
-+{
-+    krb5_error_code kerr;
-+    char *keytab_name;
-+
-+    kerr = krb5_init_context(&ibuf->context);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to init kerberos context\n");
-+        return kerr;
-+    }
-+    DEBUG(SSSDBG_TRACE_INTERNAL, "Kerberos context initialized\n");
-+
-+    kerr = copy_keytab_into_memory(ibuf, ibuf->context, ibuf->keytab_name,
-+                                   &keytab_name, NULL);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_OP_FAILURE, "copy_keytab_into_memory failed.\n");
-+        return kerr;
-+    }
-+    talloc_free(ibuf->keytab_name);
-+    ibuf->keytab_name = keytab_name;
-+
-+    return 0;
-+}
-+
- int main(int argc, const char *argv[])
- {
-     int ret;
-@@ -662,11 +673,26 @@ int main(int argc, const char *argv[])
-         goto fail;
-     }
- 
-+    kerr = privileged_krb5_setup(ibuf);
-+    if (kerr != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Privileged Krb5 setup failed.\n");
-+        goto fail;
-+    }
-+    DEBUG(SSSDBG_TRACE_INTERNAL, "Kerberos context initialized\n");
-+
-+    kerr = become_user(ibuf->uid, ibuf->gid);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
-+        goto fail;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_INTERNAL,
-+          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
-+
-     DEBUG(SSSDBG_TRACE_INTERNAL, "getting TGT sync\n");
--    kerr = ldap_child_get_tgt_sync(main_ctx,
-+    kerr = ldap_child_get_tgt_sync(main_ctx, ibuf->context,
-                                    ibuf->realm_str, ibuf->princ_str,
-                                    ibuf->keytab_name, ibuf->lifetime,
--                                   ibuf->uid, ibuf->gid,
-                                    &ccname, &expire_time);
-     if (kerr != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "ldap_child_get_tgt_sync failed.\n");
--- 
-1.9.3
-
diff --git a/SOURCES/0125-krb5_child-become-user-earlier.patch b/SOURCES/0125-krb5_child-become-user-earlier.patch
deleted file mode 100644
index 6a5fd92..0000000
--- a/SOURCES/0125-krb5_child-become-user-earlier.patch
+++ /dev/null
@@ -1,249 +0,0 @@
-From 0c7f33bb6b16ef7dd27816489d9ec0b5c758c64f Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 1 Dec 2014 17:36:56 +0100
-Subject: [PATCH 125/128] krb5_child: become user earlier
-
-The host keytab and the FAST credential cache are copied into memory
-early at startup to allow to drop privileges earlier.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- Makefile.am                     |   1 +
- src/providers/krb5/krb5_child.c | 131 ++++++++++++++++++++++++++++------------
- 2 files changed, 94 insertions(+), 38 deletions(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index 3d16428856d6cb2e9e190b0df8895ab3f45db39c..6f6db56f5d6229b530cc6f18f66c42f22140bdeb 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -2531,6 +2531,7 @@ libsss_ad_la_LDFLAGS = \
- krb5_child_SOURCES = \
-     src/providers/krb5/krb5_child.c \
-     src/providers/krb5/krb5_ccache.c \
-+    src/providers/krb5/krb5_keytab.c \
-     src/providers/dp_pam_data_util.c \
-     src/util/user_info_msg.c \
-     src/util/sss_krb5.c \
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index d828dd550251d70851edcdc6b1eda6f5c051baf2..ce8a9235e1d64bccc91d367bc744cca2b32a40da 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -42,6 +42,12 @@
- 
- #define SSSD_KRB5_CHANGEPW_PRINCIPAL "kadmin/changepw"
- 
-+enum k5c_fast_opt {
-+    K5C_FAST_NEVER,
-+    K5C_FAST_TRY,
-+    K5C_FAST_DEMAND,
-+};
-+
- struct krb5_req {
-     krb5_context ctx;
-     krb5_principal princ;
-@@ -67,6 +73,7 @@ struct krb5_req {
-     char *old_ccname;
-     bool old_cc_valid;
-     bool old_cc_active;
-+    enum k5c_fast_opt fast_val;
- };
- 
- static krb5_context krb5_error_ctx;
-@@ -1839,6 +1846,7 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
-     char *fast_principal;
-     krb5_error_code kerr;
-     char *tmp_str;
-+    char *new_ccname;
- 
-     tmp_str = getenv(SSSD_KRB5_FAST_PRINCIPAL);
-     if (tmp_str) {
-@@ -1881,6 +1889,15 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
-         return kerr;
-     }
- 
-+    kerr = copy_ccache_into_memory(kr, kr->ctx, kr->fast_ccname, &new_ccname);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "copy_ccache_into_memory failed.\n");
-+        return kerr;
-+    }
-+
-+    talloc_free(kr->fast_ccname);
-+    kr->fast_ccname = new_ccname;
-+
-     kerr = sss_krb5_get_init_creds_opt_set_fast_ccache_name(kr->ctx,
-                                                             kr->options,
-                                                             kr->fast_ccname);
-@@ -1908,12 +1925,6 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
-     return EOK;
- }
- 
--enum k5c_fast_opt {
--    K5C_FAST_NEVER,
--    K5C_FAST_TRY,
--    K5C_FAST_DEMAND,
--};
--
- static errno_t check_use_fast(enum k5c_fast_opt *_fast_val)
- {
-     char *use_fast_str;
-@@ -2064,19 +2075,8 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
- {
-     krb5_error_code kerr;
-     int parse_flags;
--    enum k5c_fast_opt fast_val;
- 
--    kerr = check_use_fast(&fast_val);
--    if (kerr != EOK) {
--        return kerr;
--    }
--
--    kerr = k5c_ccache_setup(kr, offline);
--    if (kerr != EOK) {
--        return kerr;
--    }
--
--    if (offline || (fast_val == K5C_FAST_NEVER && kr->validate == false)) {
-+    if (offline || (kr->fast_val == K5C_FAST_NEVER && kr->validate == false)) {
-         /* If krb5_child was started as setuid, but we don't need to
-          * perform either validation or FAST, just drop privileges to
-          * the user who is logging in. The same applies to the offline case
-@@ -2097,12 +2097,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-               "Cannot read [%s] from environment.\n", SSSD_KRB5_REALM);
-     }
- 
--    kerr = krb5_init_context(&kr->ctx);
--    if (kerr != 0) {
--        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
--        return kerr;
--    }
--
-     /* Set the global error context */
-     krb5_error_ctx = kr->ctx;
- 
-@@ -2145,12 +2139,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-         return ENOMEM;
-     }
- 
--    kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
--    if (kerr != 0) {
--        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
--        return kerr;
--    }
--
- #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_RESPONDER
-     kerr = krb5_get_init_creds_opt_set_responder(kr->ctx, kr->options,
-                                                  sss_krb5_responder, kr);
-@@ -2175,14 +2163,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
- 
-     if (!offline) {
-         set_canonicalize_option(kr->options);
--
--        if (fast_val != K5C_FAST_NEVER) {
--            kerr = k5c_setup_fast(kr, fast_val == K5C_FAST_DEMAND);
--            if (kerr != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "Cannot set up FAST\n");
--                return kerr;
--            }
--        }
-     }
- 
- /* TODO: set options, e.g.
-@@ -2199,6 +2179,63 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-     return kerr;
- }
- 
-+static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
-+                                             uint32_t offline)
-+{
-+    krb5_error_code kerr;
-+    int ret;
-+    char *mem_keytab;
-+
-+    kerr = krb5_init_context(&kr->ctx);
-+    if (kerr != 0) {
-+        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
-+        return kerr;
-+    }
-+
-+    kerr = sss_krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
-+    if (kerr != 0) {
-+        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
-+        return kerr;
-+    }
-+
-+    ret = check_use_fast(&kr->fast_val);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "check_use_fast failed.\n");
-+        return ret;;
-+    }
-+
-+    /* For ccache types FILE: and DIR: we might need to create some directory
-+     * components as root */
-+    ret = k5c_ccache_setup(kr, offline);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "k5c_ccache_setup failed.\n");
-+        return ret;
-+    }
-+
-+    if (!(offline ||
-+            (kr->fast_val == K5C_FAST_NEVER && kr->validate == false))) {
-+        kerr = copy_keytab_into_memory(kr, kr->ctx, kr->keytab, &mem_keytab,
-+                                       NULL);
-+        if (kerr != 0) {
-+            DEBUG(SSSDBG_OP_FAILURE, "copy_keytab_into_memory failed.\n");
-+            return kerr;
-+        }
-+
-+        talloc_free(kr->keytab);
-+        kr->keytab = mem_keytab;
-+
-+        if (kr->fast_val != K5C_FAST_NEVER) {
-+            kerr = k5c_setup_fast(kr, kr->fast_val == K5C_FAST_DEMAND);
-+            if (kerr != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "Cannot set up FAST\n");
-+                return kerr;
-+            }
-+        }
-+    }
-+
-+    return 0;
-+}
-+
- int main(int argc, const char *argv[])
- {
-     struct krb5_req *kr = NULL;
-@@ -2207,6 +2244,7 @@ int main(int argc, const char *argv[])
-     poptContext pc;
-     int debug_fd = -1;
-     errno_t ret;
-+    krb5_error_code kerr;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-@@ -2274,6 +2312,23 @@ int main(int argc, const char *argv[])
- 
-     close(STDIN_FILENO);
- 
-+    kerr = privileged_krb5_setup(kr, offline);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "privileged_krb5_setup failed.\n");
-+        ret = EFAULT;
-+        goto done;
-+    }
-+
-+    kerr = become_user(kr->uid, kr->gid);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
-+        ret = EFAULT;
-+        goto done;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_INTERNAL,
-+          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
-+
-     ret = k5c_setup(kr, offline);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_child_setup failed.\n");
--- 
-1.9.3
-
diff --git a/SOURCES/0126-TESTS-Basic-child-tests.patch b/SOURCES/0126-TESTS-Basic-child-tests.patch
deleted file mode 100644
index 3abf8a0..0000000
--- a/SOURCES/0126-TESTS-Basic-child-tests.patch
+++ /dev/null
@@ -1,314 +0,0 @@
-From 9d501b05b47a63e29c586c6dd3d40ac615a98886 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 1 Dec 2014 12:04:25 +0100
-Subject: [PATCH 126/128] TESTS: Basic child tests
-
-The child_common.c module had no unit tests, yet we need to amend it.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- Makefile.am                          |  25 ++++++
- src/tests/cmocka/test_child.c        |  83 +++++++++++++++++++
- src/tests/cmocka/test_child_common.c | 150 +++++++++++++++++++++++++++++++++++
- 3 files changed, 258 insertions(+)
- create mode 100644 src/tests/cmocka/test_child.c
- create mode 100644 src/tests/cmocka/test_child_common.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 6f6db56f5d6229b530cc6f18f66c42f22140bdeb..b719c646721835096931819b10be6f1a766ef22e 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -216,6 +216,7 @@ if HAVE_CMOCKA
-         test_sysdb_views \
-         test_copy_ccache \
-         test_copy_keytab \
-+        test_child_common \
-         $(NULL)
- 
- if BUILD_IFP
-@@ -233,6 +234,7 @@ endif   # HAVE_CMOCKA
- check_PROGRAMS = \
-     stress-tests \
-     krb5-child-test \
-+    test-child \
-     $(non_interactive_cmocka_based_tests) \
-     $(non_interactive_check_based_tests)
- 
-@@ -2115,6 +2117,29 @@ test_copy_keytab_LDADD = \
-     libsss_test_common.la \
-     $(NULL)
- 
-+test_child_SOURCES = \
-+    src/tests/cmocka/test_child.c \
-+    $(NULL)
-+test_child_LDADD = \
-+    $(POPT_LIBS) \
-+    $(SSSD_INTERNAL_LTLIBS) \
-+    $(NULL)
-+
-+test_child_common_SOURCES = \
-+    src/tests/cmocka/test_child_common.c \
-+    $(NULL)
-+test_child_common_CFLAGS = \
-+    $(AM_CFLAGS) \
-+    -DCHILD_DIR=\"$(builddir)\" \
-+    $(NULL)
-+test_child_common_LDADD = \
-+    $(CMOCKA_LIBS) \
-+    $(POPT_LIBS) \
-+    $(TALLOC_LIBS) \
-+    $(SSSD_INTERNAL_LTLIBS) \
-+    libsss_test_common.la \
-+    $(NULL)
-+
- endif # HAVE_CMOCKA
- 
- noinst_PROGRAMS = pam_test_client
-diff --git a/src/tests/cmocka/test_child.c b/src/tests/cmocka/test_child.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..a857afce1fe7c4f3949fe77fe4e0a24e15961a4f
---- /dev/null
-+++ b/src/tests/cmocka/test_child.c
-@@ -0,0 +1,83 @@
-+/*
-+    SSSD
-+
-+    Tests -- a simple test process that echoes input back
-+
-+    Authors:
-+        Jakub Hrozek <jhrozek@redhat.com>
-+
-+    Copyright (C) 2014 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 <sys/types.h>
-+#include <unistd.h>
-+#include <stdlib.h>
-+#include <popt.h>
-+
-+#include "util/util.h"
-+#include "util/child_common.h"
-+
-+int main(int argc, const char *argv[])
-+{
-+    int opt;
-+    int debug_fd = -1;
-+    poptContext pc;
-+    const char *action;
-+    ssize_t len = 0;
-+    ssize_t written;
-+    errno_t ret;
-+    uint8_t *buf[IN_BUF_SIZE];
-+    uid_t uid;
-+    gid_t gid;
-+
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0,
-+         _("Debug level"), NULL},
-+        {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0,
-+         _("Add debug timestamps"), NULL},
-+        {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0,
-+         _("Show timestamps with microseconds"), NULL},
-+        {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
-+         _("An open file descriptor for the debug logs"), NULL},
-+        {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &debug_to_stderr, 0, \
-+         _("Send the debug output to stderr directly."), NULL }, \
-+        SSSD_SERVER_OPTS(uid, gid)
-+        POPT_TABLEEND
-+    };
-+
-+    /* 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);
-+            _exit(1);
-+        }
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_FUNC, "test_child completed successfully\n");
-+    _exit(0);
-+
-+fail:
-+    DEBUG(SSSDBG_TRACE_FUNC, "test_child completed successfully\n");
-+    close(STDOUT_FILENO);
-+    _exit(-1);
-+}
-diff --git a/src/tests/cmocka/test_child_common.c b/src/tests/cmocka/test_child_common.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..f2cd8c0081c2e85432db1c9696102780dc990e75
---- /dev/null
-+++ b/src/tests/cmocka/test_child_common.c
-@@ -0,0 +1,150 @@
-+/*
-+    Authors:
-+        Jakub Hrozek <jhrozek@redhat.com>
-+
-+    Copyright (C) 2014 Red Hat
-+
-+    SSSD tests: Child handlers
-+
-+    This program is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU General Public License as published by
-+    the Free Software Foundation; either version 3 of the License, or
-+    (at your option) any later version.
-+
-+    This program is distributed in the hope that it will be useful,
-+    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+    GNU General Public License for more details.
-+
-+    You should have received a copy of the GNU General Public License
-+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-+*/
-+
-+#include <talloc.h>
-+#include <tevent.h>
-+#include <errno.h>
-+#include <popt.h>
-+
-+#include "util/child_common.h"
-+#include "tests/cmocka/common_mock.h"
-+
-+#define TEST_BIN    "test-child"
-+#define ECHO_STR    "Hello child"
-+
-+struct child_test_ctx {
-+    int pipefd_to_child[2];
-+    int pipefd_from_child[2];
-+
-+    struct sss_test_ctx *test_ctx;
-+};
-+
-+void child_test_setup(void **state)
-+{
-+    struct child_test_ctx *child_tctx;
-+    errno_t ret;
-+
-+    check_leaks_push(global_talloc_context);
-+    child_tctx = talloc(global_talloc_context, struct child_test_ctx);
-+    assert_non_null(child_tctx);
-+
-+    child_tctx->test_ctx = create_ev_test_ctx(child_tctx);
-+    assert_non_null(child_tctx->test_ctx);
-+
-+    ret = pipe(child_tctx->pipefd_from_child);
-+    assert_int_not_equal(ret, -1);
-+    DEBUG(SSSDBG_TRACE_LIBS, "from_child: %d:%d\n",
-+                             child_tctx->pipefd_from_child[0],
-+                             child_tctx->pipefd_from_child[1]);
-+
-+    ret = pipe(child_tctx->pipefd_to_child);
-+    assert_int_not_equal(ret, -1);
-+    DEBUG(SSSDBG_TRACE_LIBS, "to_child: %d:%d\n",
-+                             child_tctx->pipefd_to_child[0],
-+                             child_tctx->pipefd_to_child[1]);
-+
-+    *state = child_tctx;
-+}
-+
-+void child_test_teardown(void **state)
-+{
-+    struct child_test_ctx *child_tctx = talloc_get_type(*state,
-+                                                        struct child_test_ctx);
-+
-+    talloc_free(child_tctx);
-+    check_leaks_pop(global_talloc_context);
-+}
-+
-+/* Just make sure the exec works. The child does nothing but exits */
-+void test_exec_child(void **state)
-+{
-+    errno_t ret;
-+    pid_t child_pid;
-+    int status;
-+    struct child_test_ctx *child_tctx = talloc_get_type(*state,
-+                                                        struct child_test_ctx);
-+
-+    child_pid = fork();
-+    assert_int_not_equal(child_pid, -1);
-+    if (child_pid == 0) {
-+        ret = exec_child(child_tctx,
-+                         child_tctx->pipefd_to_child,
-+                         child_tctx->pipefd_from_child,
-+                         CHILD_DIR"/"TEST_BIN, 2);
-+        assert_int_equal(ret, EOK);
-+    } else {
-+            do {
-+                errno = 0;
-+                ret = waitpid(child_pid, &status, 0);
-+            } while (ret == -1 && errno == EINTR);
-+
-+            if (ret > 0) {
-+                ret = EIO;
-+                if (WIFEXITED(status)) {
-+                    ret = WEXITSTATUS(status);
-+                    assert_int_equal(ret, 0);
-+                }
-+            } else {
-+                DEBUG(SSSDBG_FUNC_DATA,
-+                    "Failed to wait for children %d\n", child_pid);
-+                ret = EIO;
-+            }
-+    }
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    int rv;
-+    poptContext pc;
-+    int opt;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test_setup_teardown(test_exec_child,
-+                                 child_test_setup,
-+                                 child_test_teardown),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    rv = run_tests(tests);
-+    return rv;
-+}
--- 
-1.9.3
-
diff --git a/SOURCES/0127-Add-extra_args-to-exec_child.patch b/SOURCES/0127-Add-extra_args-to-exec_child.patch
deleted file mode 100644
index 7ab2f55..0000000
--- a/SOURCES/0127-Add-extra_args-to-exec_child.patch
+++ /dev/null
@@ -1,287 +0,0 @@
-From 6468d9f2bb30147967a724075c504afb3481d465 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 1 Dec 2014 12:25:24 +0100
-Subject: [PATCH 127/128] Add extra_args to exec_child()
-
-Related:
-    https://fedorahosted.org/sssd/ticket/2503
-
-Currently all child processes use the same arguments, the construction
-of argv[] is even hardcoded in exec_child(). Add an extra_args[] array
-that extends the common set of argvs so that we can have child-specific
-arguments. Also adds a unit test.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/ad/ad_gpo.c               |  2 +-
- src/providers/ipa/ipa_selinux.c         |  3 ++-
- src/providers/krb5/krb5_child_handler.c |  3 ++-
- src/providers/ldap/sdap_child_helpers.c |  3 ++-
- src/tests/cmocka/test_child.c           | 31 ++++++++++++----------
- src/tests/cmocka/test_child_common.c    | 47 ++++++++++++++++++++++++++++++++-
- src/util/child_common.c                 | 23 ++++++++++++++--
- src/util/child_common.h                 |  3 ++-
- 8 files changed, 93 insertions(+), 22 deletions(-)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 83edbe4fb5a7e617cab95c0330ceae31392b18b2..62715861c91484fa2a57e7cc13ba403c9096d9a7 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -3960,7 +3960,7 @@ gpo_fork_child(struct tevent_req *req)
-     if (pid == 0) { /* child */
-         err = exec_child(state,
-                          pipefd_to_child, pipefd_from_child,
--                         GPO_CHILD, gpo_child_debug_fd);
-+                         GPO_CHILD, gpo_child_debug_fd, NULL);
-         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec gpo_child: [%d][%s].\n",
-               err, strerror(err));
-         return err;
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index 30ad6f0a7c4622ca5eb9a75ae4f57183543515c6..531258dac5c033b5896598e44e28a373d6cf5e3b 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -1036,7 +1036,8 @@ static errno_t selinux_fork_child(struct selinux_child_state *state)
-     if (pid == 0) { /* child */
-         ret = exec_child(state,
-                          pipefd_to_child, pipefd_from_child,
--                         SELINUX_CHILD, selinux_child_debug_fd);
-+                         SELINUX_CHILD, selinux_child_debug_fd,
-+                         NULL);
-         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec selinux_child: [%d][%s].\n",
-               ret, sss_strerror(ret));
-         return ret;
-diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
-index 93961172c7a3a5d8f2a4fb320370037f188b5909..9bb61f65437694d8aa2109513b5f061dfc9ee21c 100644
---- a/src/providers/krb5/krb5_child_handler.c
-+++ b/src/providers/krb5/krb5_child_handler.c
-@@ -299,7 +299,8 @@ static errno_t fork_child(struct tevent_req *req)
-     if (pid == 0) { /* child */
-         err = exec_child(state,
-                          pipefd_to_child, pipefd_from_child,
--                         KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd);
-+                         KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd,
-+                         NULL);
-         if (err != EOK) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec KRB5 child: [%d][%s].\n",
-                       err, strerror(err));
-diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
-index 40010989021eb7cf77b96876b2d1c4119ed39163..b60891d2b41f9a359856eb22174128d7f07559fb 100644
---- a/src/providers/ldap/sdap_child_helpers.c
-+++ b/src/providers/ldap/sdap_child_helpers.c
-@@ -108,7 +108,8 @@ static errno_t sdap_fork_child(struct tevent_context *ev,
-     if (pid == 0) { /* child */
-         err = exec_child(child,
-                          pipefd_to_child, pipefd_from_child,
--                         LDAP_CHILD, ldap_child_debug_fd);
-+                         LDAP_CHILD, ldap_child_debug_fd,
-+                         NULL);
-         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec LDAP child: [%d][%s].\n",
-                                     err, strerror(err));
-         return err;
-diff --git a/src/tests/cmocka/test_child.c b/src/tests/cmocka/test_child.c
-index a857afce1fe7c4f3949fe77fe4e0a24e15961a4f..0bb50a4e005a26b1fbd332b17558d1284de77ea1 100644
---- a/src/tests/cmocka/test_child.c
-+++ b/src/tests/cmocka/test_child.c
-@@ -35,13 +35,9 @@ int main(int argc, const char *argv[])
-     int opt;
-     int debug_fd = -1;
-     poptContext pc;
--    const char *action;
--    ssize_t len = 0;
--    ssize_t written;
--    errno_t ret;
--    uint8_t *buf[IN_BUF_SIZE];
--    uid_t uid;
--    gid_t gid;
-+    const char *action = NULL;
-+    const char *guitar;
-+    const char *drums;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-@@ -54,8 +50,9 @@ int main(int argc, const char *argv[])
-         {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0,
-          _("An open file descriptor for the debug logs"), NULL},
-         {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, &debug_to_stderr, 0, \
--         _("Send the debug output to stderr directly."), NULL }, \
--        SSSD_SERVER_OPTS(uid, gid)
-+         _("Send the debug output to stderr directly."), NULL },
-+        {"guitar", 0, POPT_ARG_STRING, &guitar, 0, _("Who plays guitar"), NULL },
-+        {"drums", 0, POPT_ARG_STRING, &drums, 0, _("Who plays drums"), NULL },
-         POPT_TABLEEND
-     };
- 
-@@ -73,11 +70,17 @@ int main(int argc, const char *argv[])
-         }
-     }
- 
-+    action = getenv("TEST_CHILD_ACTION");
-+    if (action) {
-+        if (strcasecmp(action, "check_extra_args") == 0) {
-+            if (!(strcmp(guitar, "george") == 0 \
-+                        && strcmp(drums, "ringo") == 0)) {
-+                DEBUG(SSSDBG_CRIT_FAILURE, "This band sounds weird\n");
-+                _exit(1);
-+            }
-+        }
-+    }
-+
-     DEBUG(SSSDBG_TRACE_FUNC, "test_child completed successfully\n");
-     _exit(0);
--
--fail:
--    DEBUG(SSSDBG_TRACE_FUNC, "test_child completed successfully\n");
--    close(STDOUT_FILENO);
--    _exit(-1);
- }
-diff --git a/src/tests/cmocka/test_child_common.c b/src/tests/cmocka/test_child_common.c
-index f2cd8c0081c2e85432db1c9696102780dc990e75..112ed0ad97294bc45eac7c2124155e6b1908ad92 100644
---- a/src/tests/cmocka/test_child_common.c
-+++ b/src/tests/cmocka/test_child_common.c
-@@ -89,7 +89,49 @@ void test_exec_child(void **state)
-         ret = exec_child(child_tctx,
-                          child_tctx->pipefd_to_child,
-                          child_tctx->pipefd_from_child,
--                         CHILD_DIR"/"TEST_BIN, 2);
-+                         CHILD_DIR"/"TEST_BIN, 2, NULL);
-+        assert_int_equal(ret, EOK);
-+    } else {
-+            do {
-+                errno = 0;
-+                ret = waitpid(child_pid, &status, 0);
-+            } while (ret == -1 && errno == EINTR);
-+
-+            if (ret > 0) {
-+                ret = EIO;
-+                if (WIFEXITED(status)) {
-+                    ret = WEXITSTATUS(status);
-+                    assert_int_equal(ret, 0);
-+                }
-+            } else {
-+                DEBUG(SSSDBG_FUNC_DATA,
-+                    "Failed to wait for children %d\n", child_pid);
-+                ret = EIO;
-+            }
-+    }
-+}
-+
-+/* Just make sure the exec works. The child does nothing but exits */
-+void test_exec_child_extra_args(void **state)
-+{
-+    errno_t ret;
-+    pid_t child_pid;
-+    int status;
-+    struct child_test_ctx *child_tctx = talloc_get_type(*state,
-+                                                        struct child_test_ctx);
-+    const char *extra_args[] = { "--guitar=george",
-+                                 "--drums=ringo",
-+                                 NULL };
-+
-+    setenv("TEST_CHILD_ACTION", "check_extra_args", 1);
-+
-+    child_pid = fork();
-+    assert_int_not_equal(child_pid, -1);
-+    if (child_pid == 0) {
-+        ret = exec_child(child_tctx,
-+                         child_tctx->pipefd_to_child,
-+                         child_tctx->pipefd_from_child,
-+                         CHILD_DIR"/"TEST_BIN, 2, extra_args);
-         assert_int_equal(ret, EOK);
-     } else {
-             do {
-@@ -126,6 +168,9 @@ int main(int argc, const char *argv[])
-         unit_test_setup_teardown(test_exec_child,
-                                  child_test_setup,
-                                  child_test_teardown),
-+        unit_test_setup_teardown(test_exec_child_extra_args,
-+                                 child_test_setup,
-+                                 child_test_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-diff --git a/src/util/child_common.c b/src/util/child_common.c
-index cc6a8fa758bfa6efa511c28cd9121e759b590342..9710630f9773ae02258e4f0dd609a3d74978c8f4 100644
---- a/src/util/child_common.c
-+++ b/src/util/child_common.c
-@@ -623,6 +623,7 @@ static void child_invoke_callback(struct tevent_context *ev,
- static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
-                                   int child_debug_fd,
-                                   const char *binary,
-+                                  const char *extra_argv[],
-                                   char ***_argv)
- {
-     /*
-@@ -632,6 +633,7 @@ static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
-     uint_t argc = 5;
-     char ** argv;
-     errno_t ret = EINVAL;
-+    size_t i;
- 
-     /* Save the current state in case an interrupt changes it */
-     bool child_debug_to_file = debug_to_file;
-@@ -642,6 +644,10 @@ static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
-     if (child_debug_to_file) argc++;
-     if (child_debug_stderr) argc++;
- 
-+    if (extra_argv) {
-+        for (i = 0; extra_argv[i]; i++) argc++;
-+    }
-+
-     /*
-      * program name, debug_level, debug_to_file, debug_timestamps,
-      * debug_microseconds and NULL
-@@ -654,6 +660,17 @@ static errno_t prepare_child_argv(TALLOC_CTX *mem_ctx,
- 
-     argv[--argc] = NULL;
- 
-+    /* Add extra_attrs first */
-+    if (extra_argv) {
-+        for (i = 0; extra_argv[i]; i++) {
-+            argv[--argc] = talloc_strdup(argv, extra_argv[i]);
-+            if (argv[argc] == NULL) {
-+                ret = ENOMEM;
-+                goto fail;
-+            }
-+        }
-+    }
-+
-     argv[--argc] = talloc_asprintf(argv, "--debug-level=%#.4x",
-                               debug_level);
-     if (argv[argc] == NULL) {
-@@ -714,7 +731,8 @@ fail:
- 
- errno_t exec_child(TALLOC_CTX *mem_ctx,
-                    int *pipefd_to_child, int *pipefd_from_child,
--                   const char *binary, int debug_fd)
-+                   const char *binary, int debug_fd,
-+                   const char *extra_argv[])
- {
-     int ret;
-     errno_t err;
-@@ -739,7 +757,8 @@ errno_t exec_child(TALLOC_CTX *mem_ctx,
-     }
- 
-     ret = prepare_child_argv(mem_ctx, debug_fd,
--                             binary, &argv);
-+                             binary, extra_argv,
-+                             &argv);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "prepare_child_argv.\n");
-         return ret;
-diff --git a/src/util/child_common.h b/src/util/child_common.h
-index e159719a2fca70a4ea044d79530a0d21cb3577e8..e659388ece3677b7746c159d7de3e86171bb4146 100644
---- a/src/util/child_common.h
-+++ b/src/util/child_common.h
-@@ -114,7 +114,8 @@ void child_sig_handler(struct tevent_context *ev,
- /* Never returns EOK, ether returns an error, or doesn't return on success */
- errno_t exec_child(TALLOC_CTX *mem_ctx,
-                    int *pipefd_to_child, int *pipefd_from_child,
--                   const char *binary, int debug_fd);
-+                   const char *binary, int debug_fd,
-+                   const char *extra_argv[]);
- 
- void child_cleanup(int readfd, int writefd);
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0128-KRB5-Create-the-fast-ccache-in-a-child-process.patch b/SOURCES/0128-KRB5-Create-the-fast-ccache-in-a-child-process.patch
deleted file mode 100644
index 674badb..0000000
--- a/SOURCES/0128-KRB5-Create-the-fast-ccache-in-a-child-process.patch
+++ /dev/null
@@ -1,240 +0,0 @@
-From c32ceaed108c86305d5862430225be636fd7532b Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 28 Nov 2014 13:04:42 +0100
-Subject: [PATCH 128/128] KRB5: Create the fast ccache in a child process
-
-Related:
-    https://fedorahosted.org/sssd/ticket/2503
-
-In order to avoid calling Kerberos library calls as root, the krb5_child
-forks itself and recreates the FAST ccache as the SSSD user.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/krb5/krb5_child.c         | 118 ++++++++++++++++++++++++--------
- src/providers/krb5/krb5_child_handler.c |  10 ++-
- 2 files changed, 100 insertions(+), 28 deletions(-)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index ce8a9235e1d64bccc91d367bc744cca2b32a40da..1ce1220751a338cb2a2e5f204107b376000a4e3e 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -74,6 +74,9 @@ struct krb5_req {
-     bool old_cc_valid;
-     bool old_cc_active;
-     enum k5c_fast_opt fast_val;
-+
-+    uid_t fast_uid;
-+    gid_t fast_gid;
- };
- 
- static krb5_context krb5_error_ctx;
-@@ -1005,17 +1008,6 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
-         DEBUG(SSSDBG_CONF_SETTINGS, "TGT validation is disabled.\n");
-     }
- 
--    if (kr->validate || kr->fast_ccname != NULL) {
--        /* We drop root privileges which were needed to read the keytab file
--         * for the validation of the credentials or for FAST here to run the
--         * ccache I/O operations with user privileges. */
--        kerr = become_user(kr->uid, kr->gid);
--        if (kerr != 0) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
--            return kerr;
--        }
--    }
--
-     /* If kr->ccname is cache collection (DIR:/...), we want to work
-      * directly with file ccache (DIR::/...), but cache collection
-      * should be returned back to back end.
-@@ -1432,17 +1424,6 @@ static errno_t renew_tgt_child(struct krb5_req *kr)
-         DEBUG(SSSDBG_CONF_SETTINGS, "TGT validation is disabled.\n");
-     }
- 
--    if (kr->validate || kr->fast_ccname != NULL) {
--        /* We drop root privileges which were needed to read the keytab file
--         * for the validation of the credentials or for FAST here to run the
--         * ccache I/O operations with user privileges. */
--        kerr = become_user(kr->uid, kr->gid);
--        if (kerr != 0) {
--            DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed.\n");
--            goto done;
--        }
--    }
--
-     kerr = krb5_cc_initialize(kr->ctx, ccache, kr->princ);
-     if (kerr != 0) {
-         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
-@@ -1716,6 +1697,8 @@ done:
- 
- static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
-                                          krb5_context ctx,
-+                                         uid_t fast_uid,
-+                                         gid_t fast_gid,
-                                          const char *primary,
-                                          const char *realm,
-                                          const char *keytab_name,
-@@ -1729,6 +1712,8 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
-     krb5_keytab keytab = NULL;
-     krb5_principal client_princ = NULL;
-     krb5_principal server_princ = NULL;
-+    pid_t fchild_pid;
-+    int status;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -1786,10 +1771,79 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
-         }
-     }
- 
--    kerr = get_and_save_tgt_with_keytab(ctx, client_princ, keytab, ccname);
--    if (kerr != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "get_and_save_tgt_with_keytab failed.\n");
--        goto done;
-+    /* Need to recreate the FAST ccache */
-+    fchild_pid = fork();
-+    switch (fchild_pid) {
-+        case -1:
-+            DEBUG(SSSDBG_CRIT_FAILURE, "fork failed\n");
-+            kerr = EIO;
-+            goto done;
-+        case 0:
-+            /* Child */
-+            debug_prg_name = talloc_asprintf(NULL, "[sssd[krb5_child[%d]]]", getpid());
-+            if (debug_prg_name == NULL) {
-+                debug_prg_name = "[sssd[krb5_child]]";
-+                DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n");
-+                /* Try to carry on */
-+            }
-+
-+            kerr = become_user(fast_uid, fast_gid);
-+            if (kerr != 0) {
-+                DEBUG(SSSDBG_CRIT_FAILURE, "become_user failed: %d\n", kerr);
-+                exit(1);
-+            }
-+            DEBUG(SSSDBG_TRACE_INTERNAL,
-+                  "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
-+
-+            kerr = get_and_save_tgt_with_keytab(ctx, client_princ,
-+                                                keytab, ccname);
-+            if (kerr != 0) {
-+                DEBUG(SSSDBG_CRIT_FAILURE,
-+                      "get_and_save_tgt_with_keytab failed: %d\n", kerr);
-+                exit(2);
-+            }
-+            exit(0);
-+        default:
-+            /* Parent */
-+            do {
-+                errno = 0;
-+                kerr = waitpid(fchild_pid, &status, 0);
-+            } while (kerr == -1 && errno == EINTR);
-+
-+            if (kerr > 0) {
-+                kerr = EIO;
-+                if (WIFEXITED(status)) {
-+                    kerr = WEXITSTATUS(status);
-+                    /* Don't blindly fail if the child fails, but check
-+                     * the ccache again */
-+                    if (kerr != 0) {
-+                        DEBUG(SSSDBG_MINOR_FAILURE,
-+                              "Creating FAST ccache failed, krb5_child will "
-+                              "likely fail!\n");
-+                    }
-+                } else {
-+                    DEBUG(SSSDBG_CRIT_FAILURE,
-+                          "krb5_child subprocess %d terminated unexpectedly\n",
-+                          fchild_pid);
-+                }
-+            } else {
-+                DEBUG(SSSDBG_FUNC_DATA,
-+                    "Failed to wait for children %d\n", fchild_pid);
-+                kerr = EIO;
-+            }
-+    }
-+
-+    /* Check the ccache times again. Should be updated ... */
-+    memset(&tgtt, 0, sizeof(tgtt));
-+    kerr = get_tgt_times(ctx, ccname, server_princ, client_princ, &tgtt);
-+    if (kerr == 0) {
-+        if (tgtt.endtime > time(NULL)) {
-+            DEBUG(SSSDBG_FUNC_DATA, "FAST TGT was successfully recreated!\n");
-+            goto done;
-+        } else {
-+            kerr = ERR_CREDS_EXPIRED;
-+            goto done;
-+        }
-     }
- 
-     kerr = 0;
-@@ -1881,7 +1935,8 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand)
-         fast_principal = NULL;
-     }
- 
--    kerr = check_fast_ccache(kr, kr->ctx, fast_principal, fast_principal_realm,
-+    kerr = check_fast_ccache(kr, kr->ctx, kr->fast_uid, kr->fast_gid,
-+                             fast_principal, fast_principal_realm,
-                              kr->keytab, &kr->fast_ccname);
-     if (kerr != 0) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "check_fast_ccache failed.\n");
-@@ -2245,6 +2300,8 @@ int main(int argc, const char *argv[])
-     int debug_fd = -1;
-     errno_t ret;
-     krb5_error_code kerr;
-+    uid_t fast_uid;
-+    gid_t fast_gid;
- 
-     struct poptOption long_options[] = {
-         POPT_AUTOHELP
-@@ -2259,6 +2316,10 @@ int main(int argc, const char *argv[])
-         {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN,
-          &debug_to_stderr, 0,
-          _("Send the debug output to stderr directly."), NULL },
-+        {"fast-ccache-uid", 0, POPT_ARG_INT, &fast_uid, 0,
-+          _("The user to create FAST ccache as"), NULL},
-+        {"fast-ccache-gid", 0, POPT_ARG_INT, &fast_gid, 0,
-+          _("The group to create FAST ccache as"), NULL},
-         POPT_TABLEEND
-     };
- 
-@@ -2305,6 +2366,9 @@ int main(int argc, const char *argv[])
-     }
-     talloc_steal(kr, debug_prg_name);
- 
-+    kr->fast_uid = fast_uid;
-+    kr->fast_gid = fast_gid;
-+
-     ret = k5c_recv_data(kr, STDIN_FILENO, &offline);
-     if (ret != EOK) {
-         goto done;
-diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
-index 9bb61f65437694d8aa2109513b5f061dfc9ee21c..1454d220fb294abc339df6e862154012a03fdca0 100644
---- a/src/providers/krb5/krb5_child_handler.c
-+++ b/src/providers/krb5/krb5_child_handler.c
-@@ -278,6 +278,14 @@ static errno_t fork_child(struct tevent_req *req)
-     errno_t err;
-     struct handle_child_state *state = tevent_req_data(req,
-                                                      struct handle_child_state);
-+    const char *k5c_extra_args[3];
-+
-+    k5c_extra_args[0] = talloc_asprintf(state, "--fast-ccache-uid=%"SPRIuid, getuid());
-+    k5c_extra_args[1] = talloc_asprintf(state, "--fast-ccache-gid=%"SPRIgid, getgid());
-+    k5c_extra_args[2] = NULL;
-+    if (k5c_extra_args[0] == NULL || k5c_extra_args[1] == NULL) {
-+        return ENOMEM;
-+    }
- 
-     ret = pipe(pipefd_from_child);
-     if (ret == -1) {
-@@ -300,7 +308,7 @@ static errno_t fork_child(struct tevent_req *req)
-         err = exec_child(state,
-                          pipefd_to_child, pipefd_from_child,
-                          KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd,
--                         NULL);
-+                         k5c_extra_args);
-         if (err != EOK) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec KRB5 child: [%d][%s].\n",
-                       err, strerror(err));
--- 
-1.9.3
-
diff --git a/SOURCES/0129-KRB5-Relax-DEBUG-message.patch b/SOURCES/0129-KRB5-Relax-DEBUG-message.patch
deleted file mode 100644
index 27115e4..0000000
--- a/SOURCES/0129-KRB5-Relax-DEBUG-message.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From cf944e48215fa55bbc268e291aff11adb2bba4aa Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 28 Nov 2014 19:56:27 +0100
-Subject: [PATCH 129/130] KRB5: Relax DEBUG message
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/krb5/krb5_child.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 1ce1220751a338cb2a2e5f204107b376000a4e3e..8f23346a67d4d2467a4d1869fd298ec4d6f68e92 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -1672,8 +1672,11 @@ static krb5_error_code get_tgt_times(krb5_context ctx, const char *ccname,
-     mcred.client = client_principal;
- 
-     krberr = krb5_cc_retrieve_cred(ctx, ccache, 0, &mcred, &cred);
--    if (krberr != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_retrieve_cred failed.\n");
-+    if (krberr == KRB5_FCC_NOFILE) {
-+        DEBUG(SSSDBG_TRACE_LIBS, "FAST ccache must be recreated\n");
-+    } else if (krberr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_retrieve_cred failed\n");
-+        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, krberr);
-         krberr = 0;
-         goto done;
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0130-IPA-Do-not-append-domain-name-to-fq-name.patch b/SOURCES/0130-IPA-Do-not-append-domain-name-to-fq-name.patch
deleted file mode 100644
index 3ceebcd..0000000
--- a/SOURCES/0130-IPA-Do-not-append-domain-name-to-fq-name.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From edcaf7122748fb2cd5dcfe055b904127c99f3234 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Mon, 1 Dec 2014 17:29:49 +0100
-Subject: [PATCH 130/130] IPA: Do not append domain name to fq name
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Usernames from AD subdomains are already in fqdn we should not append
-domain name in this case.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2512
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
----
- src/providers/ipa/ipa_selinux.c | 21 +++++++++++++++++----
- 1 file changed, 17 insertions(+), 4 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index 531258dac5c033b5896598e44e28a373d6cf5e3b..c4e70cfcb0748988d91fc1db57cf5a30d5365be4 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -812,6 +812,7 @@ selinux_child_setup(TALLOC_CTX *mem_ctx,
-     char *ptr;
-     char *username;
-     char *username_final;
-+    char *domain_name = NULL;
-     TALLOC_CTX *tmp_ctx;
-     struct selinux_child_input *sci;
- 
-@@ -849,10 +850,22 @@ selinux_child_setup(TALLOC_CTX *mem_ctx,
-     }
- 
-     if (dom->fqnames) {
--        username_final = talloc_asprintf(tmp_ctx, dom->names->fq_fmt,
--                                         username, dom->name);
--        if (username_final == NULL) {
--            ret = ENOMEM;
-+        ret = sss_parse_name(tmp_ctx, dom->names, username, &domain_name,
-+                             NULL);
-+        if (ret == EOK && domain_name != NULL) {
-+            /* username is already a fully qualified name */
-+            username_final = username;
-+        } else if ((ret == EOK && domain_name == NULL)
-+                   || ret == ERR_REGEX_NOMATCH) {
-+            username_final = talloc_asprintf(tmp_ctx, dom->names->fq_fmt,
-+                                             username, dom->name);
-+            if (username_final == NULL) {
-+                ret = ENOMEM;
-+                goto done;
-+            }
-+        } else {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "sss_parse_name failed: [%d] %s", ret, sss_strerror(ret));
-             goto done;
-         }
-     } else {
--- 
-1.9.3
-
diff --git a/SOURCES/0131-TESTS-Build-test_child-even-without-cmocka.patch b/SOURCES/0131-TESTS-Build-test_child-even-without-cmocka.patch
deleted file mode 100644
index 8611b93..0000000
--- a/SOURCES/0131-TESTS-Build-test_child-even-without-cmocka.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From ebf091115b9aaca6a8a78e83b7b4ca7fde95e990 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 3 Dec 2014 17:00:25 +0100
-Subject: [PATCH 131/131] TESTS: Build test_child even without cmocka
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- Makefile.am | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/Makefile.am b/Makefile.am
-index b719c646721835096931819b10be6f1a766ef22e..8202659e0933529ca7911952bbf1476dbb4a76fc 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -234,10 +234,13 @@ endif   # HAVE_CMOCKA
- check_PROGRAMS = \
-     stress-tests \
-     krb5-child-test \
--    test-child \
-     $(non_interactive_cmocka_based_tests) \
-     $(non_interactive_check_based_tests)
- 
-+if HAVE_CMOCKA
-+check_PROGRAMS += test-child
-+endif # HAVE_CMOCKA
-+
- PYTHON_TESTS =
- 
- if BUILD_PYTHON_BINDINGS
--- 
-1.9.3
-
diff --git a/SOURCES/0132-sss_client-Work-around-glibc-bug.patch b/SOURCES/0132-sss_client-Work-around-glibc-bug.patch
deleted file mode 100644
index 7281024..0000000
--- a/SOURCES/0132-sss_client-Work-around-glibc-bug.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From 2e84796d8e23ee6e406c0625288655e056b0d90d Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Tue, 18 Nov 2014 12:02:10 +0100
-Subject: [PATCH 132/132] sss_client: Work around glibc bug
-
-glibc is inconsistent with how it treats and returns NSS_STATUS_UNAVAIL.
-
-The sss nss plugin is present in nsswitch by default on some platforms
-due to glibc caching and problem with long living applications (e.g. GNOME).
-But sssd needn't be configuread and it cause problems in some programs.
-In this situation, the SSSD nss plugin should behave as if it was functioning
-but had no data even thought sssd is not running. The errors have to be passed
-from nss plugin up to the user with minimal moidiffication.
-
-Thanks to Stephen Gallagher for initial patch.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2439
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/conf_macros.m4      | 13 +++++++++++++
- src/sss_client/common.c | 10 ++++++++++
- 2 files changed, 23 insertions(+)
-
-diff --git a/src/conf_macros.m4 b/src/conf_macros.m4
-index df9d1ddf89be38709e56ad4b214e5f7c6cbb0f97..027490e524f321b9d444395e788aa7476dd916e9 100644
---- a/src/conf_macros.m4
-+++ b/src/conf_macros.m4
-@@ -708,6 +708,19 @@ AC_ARG_ENABLE([dbus-tests],
-               [build_dbus_tests=yes])
- AM_CONDITIONAL([BUILD_DBUS_TESTS], [test x$build_dbus_tests = xyes])
- 
-+AC_ARG_ENABLE([sss-default-nss-plugin],
-+              [AS_HELP_STRING([--enable-sss-default-nss-plugin],
-+                              [This option change standard behaviour of sss nss
-+                               plugin. If this option is enabled the sss nss
-+                               plugin will behave as it was not in
-+                               nsswitch.conf when sssd is not running.
-+                               [default=no]])],
-+              [enable_sss_default_nss_plugin=$enableval],
-+              [enable_sss_default_nss_plugin=no])
-+AS_IF([test x$enable_sss_default_nss_plugin = xyes],
-+      AC_DEFINE_UNQUOTED([NONSTANDARD_SSS_NSS_BEHAVIOUR], [1],
-+          [whether to build sssd nss plugin with nonstandard glibc behaviour]))
-+
- AC_DEFUN([WITH_NFS],
-   [ AC_ARG_WITH([nfsv4-idmapd-plugin],
-                 [AC_HELP_STRING([--with-nfsv4-idmapd-plugin],
-diff --git a/src/sss_client/common.c b/src/sss_client/common.c
-index ebe783aba9cfa3dc11a529e7875966f139eea1af..7c4bb7ab8769a72f943158366f358b108bfc3bdc 100644
---- a/src/sss_client/common.c
-+++ b/src/sss_client/common.c
-@@ -724,7 +724,12 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
- 
-     ret = sss_cli_check_socket(errnop, SSS_NSS_SOCKET_NAME);
-     if (ret != SSS_STATUS_SUCCESS) {
-+#ifdef NONSTANDARD_SSS_NSS_BEHAVIOUR
-+        errno = 0;
-+        return NSS_STATUS_NOTFOUND;
-+#else
-         return NSS_STATUS_UNAVAIL;
-+#endif
-     }
- 
-     ret = sss_cli_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
-@@ -735,7 +740,12 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
-         return NSS_STATUS_SUCCESS;
-     case SSS_STATUS_UNAVAIL:
-     default:
-+#ifdef NONSTANDARD_SSS_NSS_BEHAVIOUR
-+        errno = 0;
-+        return NSS_STATUS_NOTFOUND;
-+#else
-         return NSS_STATUS_UNAVAIL;
-+#endif
-     }
- }
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0133-Skip-CHAUTHTOK_PRELIM-when-using-OTPs.patch b/SOURCES/0133-Skip-CHAUTHTOK_PRELIM-when-using-OTPs.patch
deleted file mode 100644
index 6a4159d..0000000
--- a/SOURCES/0133-Skip-CHAUTHTOK_PRELIM-when-using-OTPs.patch
+++ /dev/null
@@ -1,186 +0,0 @@
-From fc4862295d512e464feff60cbc5df8c50bf83644 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 27 Nov 2014 20:29:03 +0100
-Subject: [PATCH 133/138] Skip CHAUTHTOK_PRELIM when using OTPs
-
-https://fedorahosted.org/sssd/ticket/2484
-
-When OTPs are used, we can only used each authtoken at most once. When
-it comes to Kerberos password changes, this was only working previously
-by accident, because the old authtoken was first used to verify the old
-password is valid and not expired and then also to acquire a chpass
-principal.
-
-This patch looks at the user object in LDAP to check if the user has any
-OTPs enabled. If he does, the CHAUTHTOK_PRELIM step is skipped
-completely so that the OTP can be used to acquire the chpass ticket
-later.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/db/sysdb.h                 |  2 ++
- src/providers/ad/ad_opts.h     |  1 +
- src/providers/ipa/ipa_opts.h   |  1 +
- src/providers/krb5/krb5_auth.c | 38 +++++++++++++++++++++++++++++++++++---
- src/providers/ldap/ldap_opts.h |  3 +++
- src/providers/ldap/sdap.h      |  1 +
- 6 files changed, 43 insertions(+), 3 deletions(-)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index 5bd7f90acb685bbaff5c98f433c7dce8175c33ca..4fbbb16718a2fc3d444e4c6dba5fca4c1bb3096a 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -127,6 +127,8 @@
- 
- #define SYSDB_SSH_PUBKEY "sshPublicKey"
- 
-+#define SYSDB_AUTH_TYPE "authType"
-+
- #define SYSDB_SUBDOMAIN_REALM "realmName"
- #define SYSDB_SUBDOMAIN_FLAT "flatName"
- #define SYSDB_SUBDOMAIN_ID "domainID"
-diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
-index c3de3d94b1818665a86bba8a2432c699717b6a34..d9405e5020ca724a0f7caa752ac10fb07d8aa397 100644
---- a/src/providers/ad/ad_opts.h
-+++ b/src/providers/ad/ad_opts.h
-@@ -212,6 +212,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = {
-     { "ldap_user_nds_login_expiration_time", NULL, SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
-     { "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
-     { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL },
-+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
-     SDAP_ATTR_MAP_TERMINATOR
- };
- 
-diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
-index f77ff1d05b9540155db44d04d4fb3aac9d7b5988..66af648583e552d7edd932f6bb5a2c3bef107e51 100644
---- a/src/providers/ipa/ipa_opts.h
-+++ b/src/providers/ipa/ipa_opts.h
-@@ -203,6 +203,7 @@ struct sdap_attr_map ipa_user_map[] = {
-     { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
-     { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
-     { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL },
-+    { "ldap_user_auth_type", "ipaUserAuthType", SYSDB_AUTH_TYPE, NULL },
-     SDAP_ATTR_MAP_TERMINATOR
- };
- 
-diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
-index e43b3652786678b79499e30ed546712ef080fe2c..25caf7b788a3f373f47e9d8aad38a2ea6fc12621 100644
---- a/src/providers/krb5/krb5_auth.c
-+++ b/src/providers/krb5/krb5_auth.c
-@@ -311,6 +311,25 @@ static void krb5_auth_store_creds(struct sss_domain_info *domain,
-     }
- }
- 
-+static bool is_otp_enabled(struct ldb_message *user_msg)
-+{
-+    struct ldb_message_element *el;
-+    size_t i;
-+
-+    el = ldb_msg_find_element(user_msg, SYSDB_AUTH_TYPE);
-+    if (el == NULL) {
-+        return false;
-+    }
-+
-+    for (i = 0; i < el->num_values; i++) {
-+        if (strcmp((const char * )el->values[i].data, "otp") == 0) {
-+            return true;
-+        }
-+    }
-+
-+    return false;
-+}
-+
- /* krb5_auth request */
- 
- struct krb5_auth_state {
-@@ -344,8 +363,9 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-     const char *realm;
-     struct tevent_req *req;
-     struct tevent_req *subreq;
--    int authtok_type;
-+    enum sss_authtok_type authtok_type;
-     int ret;
-+    bool otp;
- 
-     req = tevent_req_create(mem_ctx, &state, struct krb5_auth_state);
-     if (req == NULL) {
-@@ -441,7 +461,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-         goto done;
-     }
- 
--    attrs = talloc_array(state, const char *, 7);
-+    attrs = talloc_array(state, const char *, 8);
-     if (attrs == NULL) {
-         ret = ENOMEM;
-         goto done;
-@@ -453,7 +473,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-     attrs[3] = SYSDB_UIDNUM;
-     attrs[4] = SYSDB_GIDNUM;
-     attrs[5] = SYSDB_CANONICAL_UPN;
--    attrs[6] = NULL;
-+    attrs[6] = SYSDB_AUTH_TYPE;
-+    attrs[7] = NULL;
- 
-     ret = krb5_setup(state, pd, krb5_ctx, &state->kr);
-     if (ret != EOK) {
-@@ -547,6 +568,17 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
-         break;
-     }
- 
-+    otp = is_otp_enabled(res->msgs[0]);
-+    if (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM && otp == true) {
-+        /* To avoid consuming the OTP */
-+        DEBUG(SSSDBG_TRACE_FUNC,
-+              "Skipping password checks for OTP-enabled user\n");
-+        state->pam_status = PAM_SUCCESS;
-+        state->dp_err = DP_ERR_OK;
-+        ret = EOK;
-+        goto done;
-+    }
-+
-     kr->srv = NULL;
-     kr->kpasswd_srv = NULL;
- 
-diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
-index f46381e9fac7b93730ce0767154989f2e3b7ebbf..7c9ed3e01f726f2ba6ecb2a7268867abd3baa37d 100644
---- a/src/providers/ldap/ldap_opts.h
-+++ b/src/providers/ldap/ldap_opts.h
-@@ -179,6 +179,7 @@ struct sdap_attr_map rfc2307_user_map[] = {
-     { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
-     { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
-     { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL },
-+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
-     SDAP_ATTR_MAP_TERMINATOR
- };
- 
-@@ -233,6 +234,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
-     { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
-     { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
-     { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL },
-+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
-     SDAP_ATTR_MAP_TERMINATOR
- };
- 
-@@ -287,6 +289,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = {
-     { "ldap_user_nds_login_expiration_time", NULL, SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
-     { "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
-     { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL },
-+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
-     SDAP_ATTR_MAP_TERMINATOR
- };
- 
-diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
-index aa10623a58d7d667205b09e744dc2b924ca821ed..921051b41a911a2d1117672a8e9c2697b679f24e 100644
---- a/src/providers/ldap/sdap.h
-+++ b/src/providers/ldap/sdap.h
-@@ -280,6 +280,7 @@ enum sdap_user_attrs {
-     SDAP_AT_NDS_LOGIN_EXPIRATION_TIME,
-     SDAP_AT_NDS_LOGIN_ALLOWED_TIME_MAP,
-     SDAP_AT_USER_SSH_PUBLIC_KEY,
-+    SDAP_AT_USER_AUTH_TYPE,
- 
-     SDAP_OPTS_USER /* attrs counter */
- };
--- 
-1.9.3
-
diff --git a/SOURCES/0134-PAM-Domain-names-are-case-insensitive.patch b/SOURCES/0134-PAM-Domain-names-are-case-insensitive.patch
deleted file mode 100644
index bda512e..0000000
--- a/SOURCES/0134-PAM-Domain-names-are-case-insensitive.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From f5ecf965b20acf977ad7e8e2ff97b57dd9c94000 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 10 Dec 2014 11:35:18 +0100
-Subject: [PATCH 134/138] PAM: Domain names are case-insensitive
-
-The pam_public_domains option and matching the domain requested by a
-trusted process was done in a case-sensitive manner which is different
-from how we match domain names in SSSD normally.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/responder/pam/pamsrv_cmd.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
-index 02720018b91e1319346a023eca571913b544284a..29a9810e6f2d86210d9e1303f55a411d81704ddf 100644
---- a/src/responder/pam/pamsrv_cmd.c
-+++ b/src/responder/pam/pamsrv_cmd.c
-@@ -56,7 +56,7 @@ static bool is_domain_requested(struct pam_data *pd, const char *domain_name)
-     }
- 
-     for (i = 0; pd->requested_domains[i]; i++) {
--        if (strcmp(domain_name, pd->requested_domains[i])) {
-+        if (strcasecmp(domain_name, pd->requested_domains[i])) {
-             continue;
-         }
- 
-@@ -831,7 +831,7 @@ static bool is_domain_public(char *name,
-     size_t i;
- 
-     for(i=0; i < public_dom_names_count; i++) {
--        if (strcmp(name, public_dom_names[i]) == 0) {
-+        if (strcasecmp(name, public_dom_names[i]) == 0) {
-             return true;
-         }
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0135-PAM-Missing-argument-to-domains-should-fail-auth.patch b/SOURCES/0135-PAM-Missing-argument-to-domains-should-fail-auth.patch
deleted file mode 100644
index 1217bed..0000000
--- a/SOURCES/0135-PAM-Missing-argument-to-domains-should-fail-auth.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 0620f73a3c4b494112b75eeedfed4933e231382f Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 10 Dec 2014 12:02:47 +0100
-Subject: [PATCH 135/138] PAM: Missing argument to domains= should fail auth
-
-When the administrator sets the domains= list, he usually wants to
-restrict the set of domains. An empty list is an undefined configuration
-and it's safer to fail then.
-
-https://fedorahosted.org/sssd/ticket/2516
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/sss_client/pam_sss.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
-index d64e826daeb80be8998ef3b410047e3a44051b07..fdf6c9e6da75c9f7eaa7c00d9a5792fbdd97eabc 100644
---- a/src/sss_client/pam_sss.c
-+++ b/src/sss_client/pam_sss.c
-@@ -1487,6 +1487,12 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh,
- 
-     eval_argv(pamh, argc, argv, &flags, &retries, &quiet_mode, &domains);
- 
-+    /* Fail all authentication on misconfigured domains= parameter. The admin
-+     * probably wanted to restrict authentication, so it's safer to fail */
-+    if (domains && strcmp(domains, "") == 0) {
-+        return PAM_SYSTEM_ERR;
-+    }
-+
-     pi.requested_domains = domains;
- 
-     ret = get_pam_items(pamh, &pi);
--- 
-1.9.3
-
diff --git a/SOURCES/0136-MAN-Misspelled-username-in-pam_trusted_users-is-not-.patch b/SOURCES/0136-MAN-Misspelled-username-in-pam_trusted_users-is-not-.patch
deleted file mode 100644
index 2b12fba..0000000
--- a/SOURCES/0136-MAN-Misspelled-username-in-pam_trusted_users-is-not-.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From e786e081edecabb8e8506dd3c5e668094827bc52 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 11 Dec 2014 11:19:58 +0100
-Subject: [PATCH 136/138] MAN: Misspelled username in pam_trusted_users is not
- fatal
-
-The man page claimed that failing to resolve an user name results in
-failure to start SSSD, but it's not the case and shouldn't be, because
-marking a user as trusted only elevates privileges, so it's safe to
-ignore that failure.
-
-https://fedorahosted.org/sssd/ticket/2530
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/man/sssd.conf.5.xml | 5 -----
- 1 file changed, 5 deletions(-)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index 3525d78caff28fd05cc18061d023fec3c50d1a47..2002ccc7caf7013ead5b97c463fba46b734090ae 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -907,11 +907,6 @@ fallback_homedir = /home/%u
-                             the PAM responder even in case it is not in the
-                             pam_trusted_users list.
-                         </para>
--                        <para>
--                            Also please note that if there is a user name in
--                            pam_trusted_users list which fails to be resolved
--                            it will cause that SSSD will not be started.
--                        </para>
-                     </listitem>
-                 </varlistentry>
-                 <varlistentry>
--- 
-1.9.3
-
diff --git a/SOURCES/0137-RESPONDER-Log-failures-to-resolve-user-names-in-csv_.patch b/SOURCES/0137-RESPONDER-Log-failures-to-resolve-user-names-in-csv_.patch
deleted file mode 100644
index 807e319..0000000
--- a/SOURCES/0137-RESPONDER-Log-failures-to-resolve-user-names-in-csv_.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 12e075db7ef0e72fba64ca2cd0eb55a6414388c0 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 11 Dec 2014 11:28:57 +0100
-Subject: [PATCH 137/138] RESPONDER: Log failures to resolve user names in
- csv_string_to_uid_array
-
-This patch makes it more discoverable for the admin to find typos in the
-various user lists. Typically, the user lists are used to add access to
-some feature and printing a syslog message would make sure the admin
-sees the mistake.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/responder/common/responder_common.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
-index 6646fa2587a8299de40eaef35830351136b8149a..a5a44478759e0d515e8437c3bb9bcd78dbb1e4f5 100644
---- a/src/responder/common/responder_common.c
-+++ b/src/responder/common/responder_common.c
-@@ -215,6 +215,9 @@ errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
-                 DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is neither a valid "
-                                          "UID nor a user name which could be "
-                                          "resolved by getpwnam().\n", list[c]);
-+                sss_log(SSS_LOG_WARNING, "List item [%s] is neither a valid "
-+                                         "UID nor a user name which could be "
-+                                         "resolved by getpwnam().\n", list[c]);
-                 goto done;
-             }
-         }
--- 
-1.9.3
-
diff --git a/SOURCES/0138-KRB5-Check-FAST-kinit-errors-using-get_tgt_times.patch b/SOURCES/0138-KRB5-Check-FAST-kinit-errors-using-get_tgt_times.patch
deleted file mode 100644
index d1cbfc6..0000000
--- a/SOURCES/0138-KRB5-Check-FAST-kinit-errors-using-get_tgt_times.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From 03afa4cbef2c2ba3c70fbad4f3e1e36c05fafe82 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 8 Dec 2014 13:29:23 +0100
-Subject: [PATCH 138/138] KRB5: Check FAST kinit errors using get_tgt_times()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/krb5/krb5_child.c | 28 +++++++++++++++-------------
- 1 file changed, 15 insertions(+), 13 deletions(-)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 8f23346a67d4d2467a4d1869fd298ec4d6f68e92..3318e0647c0e7d7f0e7305cc4204d9c2db020162 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -1662,6 +1662,7 @@ static krb5_error_code get_tgt_times(krb5_context ctx, const char *ccname,
-     krberr = krb5_cc_resolve(ctx, ccname, &ccache);
-     if (krberr != 0) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "krb5_cc_resolve failed.\n");
-+        KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, krberr);
-         goto done;
-     }
- 
-@@ -1814,7 +1815,6 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
-             } while (kerr == -1 && errno == EINTR);
- 
-             if (kerr > 0) {
--                kerr = EIO;
-                 if (WIFEXITED(status)) {
-                     kerr = WEXITSTATUS(status);
-                     /* Don't blindly fail if the child fails, but check
-@@ -1830,26 +1830,28 @@ static krb5_error_code check_fast_ccache(TALLOC_CTX *mem_ctx,
-                           fchild_pid);
-                 }
-             } else {
--                DEBUG(SSSDBG_FUNC_DATA,
--                    "Failed to wait for children %d\n", fchild_pid);
--                kerr = EIO;
-+                DEBUG(SSSDBG_CRIT_FAILURE,
-+                      "Failed to wait for child %d\n", fchild_pid);
-+                /* Let the code re-check the TGT times and fail if we
-+                 * can't find the updated principal */
-             }
-     }
- 
-     /* Check the ccache times again. Should be updated ... */
-     memset(&tgtt, 0, sizeof(tgtt));
-     kerr = get_tgt_times(ctx, ccname, server_princ, client_princ, &tgtt);
--    if (kerr == 0) {
--        if (tgtt.endtime > time(NULL)) {
--            DEBUG(SSSDBG_FUNC_DATA, "FAST TGT was successfully recreated!\n");
--            goto done;
--        } else {
--            kerr = ERR_CREDS_EXPIRED;
--            goto done;
--        }
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_OP_FAILURE, "get_tgt_times() failed\n");
-+        goto done;
-     }
- 
--    kerr = 0;
-+    if (tgtt.endtime < time(NULL)) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "Valid FAST TGT not found after attempting to renew it\n");
-+        kerr = ERR_CREDS_EXPIRED;
-+        goto done;
-+    }
-+    DEBUG(SSSDBG_FUNC_DATA, "FAST TGT was successfully recreated!\n");
- 
- done:
-     if (client_princ != NULL) {
--- 
-1.9.3
-
diff --git a/SOURCES/0139-MAN-Clarify-ad_gpo_map-options.patch b/SOURCES/0139-MAN-Clarify-ad_gpo_map-options.patch
deleted file mode 100644
index cba3d15..0000000
--- a/SOURCES/0139-MAN-Clarify-ad_gpo_map-options.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 01fa6711add8c52aa1a8474cf34af67d1e555c91 Mon Sep 17 00:00:00 2001
-From: Dan Lavu <side_control@runlevelone.net>
-Date: Mon, 15 Dec 2014 03:20:40 +0100
-Subject: [PATCH 1/2] MAN: Clarify ad_gpo_map* options
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2515
----
- src/man/sssd-ad.5.xml | 11 +++++++++++
- 1 file changed, 11 insertions(+)
-
-diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
-index 4e29d4f75cae5bf17e4bb85fa46c921b25ee8047..b721fb73b20837c9dc3abac25d3300649115c607 100644
---- a/src/man/sssd-ad.5.xml
-+++ b/src/man/sssd-ad.5.xml
-@@ -342,6 +342,11 @@ FOREST:EXAMPLE.COM:(memberOf=cn=admins,ou=groups,dc=example,dc=com)
-                             DenyInteractiveLogonRight policy settings.
-                         </para>
-                         <para>
-+                            Note: Using the Group Policy Management Editor this
-+                            value InteractiveLogonRight  is called "Allow log on
-+                            locally" and "Deny log on locally".
-+                        </para>
-+                        <para>
-                             It is possible to add another PAM service name
-                             to the default set by using <quote>+service_name</quote>
-                             or to explicitly remove a PAM service name from
-@@ -407,6 +412,12 @@ FOREST:EXAMPLE.COM:(memberOf=cn=admins,ou=groups,dc=example,dc=com)
-                             DenyRemoteInteractiveLogonRight policy settings.
-                         </para>
-                         <para>
-+                            Note: Using the Group Policy Management Editor this
-+                            value is called "Allow log on through Remote Desktop
-+                            Services" and "Deny log on through Remote Desktop
-+                            Services".
-+                        </para>
-+                        <para>
-                             It is possible to add another PAM service name
-                             to the default set by using <quote>+service_name</quote>
-                             or to explicitly remove a PAM service name from
--- 
-1.9.3
-
diff --git a/SOURCES/0140-krb5_child-Initialize-REALM-earlier.patch b/SOURCES/0140-krb5_child-Initialize-REALM-earlier.patch
deleted file mode 100644
index c4e5f68..0000000
--- a/SOURCES/0140-krb5_child-Initialize-REALM-earlier.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From a183e279f754afdd571d8b084c7a36b71d5c1701 Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Wed, 17 Dec 2014 09:10:33 +0100
-Subject: [PATCH 2/2] krb5_child: Initialize REALM earlier
-
-Environment variable SSSD_KRB5_REALM was used to late for initialisation
-realm. and therefore default value NULL was used.
-The SSSD_KRB5_REALM (kr->realm) was used as fast_principal_realm for checking
-fast cache: privileged_krb5_setup -> k5c_setup_fast -> check_fast_ccache
-And therefore wrong principal was used when the option krb5_fast_principal is
-empty.
-
-[find_principal_in_keytab] (0x4000): Trying to find principal (null)@(null) in keytab.
-[match_principal] (0x1000): Principal matched to the sample ((null)@(null)).
-[get_tgt_times] (0x1000): FAST ccache must be recreated
-[get_tgt_times] (0x0020): krb5_cc_retrieve_cred failed
-[get_tgt_times] (0x0020): 1688: [-1765328243][Matching credential not found]
-[check_fast_ccache] (0x0040): Valid FAST TGT not found after attempting to renew it
-[k5c_setup_fast] (0x0020): check_fast_ccache failed.
-[k5c_setup_fast] (0x0020): 1956: [1432158213][Unknown code UUz 5]
-[privileged_krb5_setup] (0x0040): Cannot set up FAST
-[main] (0x0020): privileged_krb5_setup failed.
-[main] (0x0020): krb5_child failed!
-
-As a result of this user was not able to authenticate.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2526
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/krb5/krb5_child.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 76a0757f6176d4ad9d049bc8825a64328b19a818..64fe6f0cb19e831ed4b49f627cb3b3a124272943 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -2159,12 +2159,6 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline)
-     DEBUG(SSSDBG_TRACE_INTERNAL,
-           "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
- 
--    kr->realm = getenv(SSSD_KRB5_REALM);
--    if (kr->realm == NULL) {
--        DEBUG(SSSDBG_MINOR_FAILURE,
--              "Cannot read [%s] from environment.\n", SSSD_KRB5_REALM);
--    }
--
-     /* Set the global error context */
-     krb5_error_ctx = kr->ctx;
- 
-@@ -2254,6 +2248,12 @@ static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
-     int ret;
-     char *mem_keytab;
- 
-+    kr->realm = getenv(SSSD_KRB5_REALM);
-+    if (kr->realm == NULL) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Cannot read [%s] from environment.\n", SSSD_KRB5_REALM);
-+    }
-+
-     kerr = krb5_init_context(&kr->ctx);
-     if (kerr != 0) {
-         KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr);
--- 
-1.9.3
-
diff --git a/SOURCES/0141-TESTS-sysdb_delete_by_sid-test-return-value.patch b/SOURCES/0141-TESTS-sysdb_delete_by_sid-test-return-value.patch
deleted file mode 100644
index 07a6408..0000000
--- a/SOURCES/0141-TESTS-sysdb_delete_by_sid-test-return-value.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-From 13c0cf829eca7891ad9d0087e91c72650f990149 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Tue, 9 Dec 2014 09:47:11 +0000
-Subject: [PATCH 2/7] TESTS: sysdb_delete_by_sid() test return value
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Check that return value of sysdb_delete_by_sid() is not changed as
-called SYSDB functions have changed the return value.
-
-Part of patches for:
-https://fedorahosted.org/sssd/ticket/1991
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/tests/sysdb-tests.c | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
-
-diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
-index b55901a30feb94cd8199eab096785a02dfc89b9a..d303982647547eefdce7c37ac5b70e1ffbe869ce 100644
---- a/src/tests/sysdb-tests.c
-+++ b/src/tests/sysdb-tests.c
-@@ -5127,7 +5127,28 @@ START_TEST(test_sysdb_search_object_by_uuid)
-                       "UUIDuser") == 0, "Unexpected object found, " \
-                       "expected [%s], got [%s].", "UUIDuser",
-                       ldb_msg_find_attr_as_string(res->msgs[0],SYSDB_NAME, ""));
-+    talloc_free(test_ctx);
-+}
-+END_TEST
- 
-+START_TEST(test_sysdb_delete_by_sid)
-+{
-+    errno_t ret;
-+    struct sysdb_test_ctx *test_ctx;
-+
-+    /* Setup */
-+    ret = setup_sysdb_tests(&test_ctx);
-+    fail_if(ret != EOK, "Could not set up the test");
-+
-+    check_leaks_push(test_ctx);
-+
-+    /* Delete the group by SID */
-+    ret = sysdb_delete_by_sid(test_ctx->sysdb, test_ctx->domain,
-+                              "S-1-2-3-4-NON_EXISTING_SID");
-+    fail_unless(ret == EOK, "sysdb_delete_by_sid failed with [%d][%s].",
-+                ret, strerror(ret));
-+
-+    fail_unless(check_leaks_pop(test_ctx) == true, "Memory leak");
-     talloc_free(test_ctx);
- }
- END_TEST
-@@ -6175,6 +6196,7 @@ Suite *create_sysdb_suite(void)
-     tcase_add_test(tc_sysdb, test_sysdb_search_custom_update);
-     tcase_add_test(tc_sysdb, test_sysdb_search_custom);
-     tcase_add_test(tc_sysdb, test_sysdb_delete_custom);
-+    tcase_add_test(tc_sysdb, test_sysdb_delete_by_sid);
- 
-     /* test recursive delete */
-     tcase_add_test(tc_sysdb, test_sysdb_delete_recursive);
--- 
-1.9.3
-
diff --git a/SOURCES/0142-NSS-nss_cmd_getbysid_search-return-ENOENT.patch b/SOURCES/0142-NSS-nss_cmd_getbysid_search-return-ENOENT.patch
deleted file mode 100644
index 9267d53..0000000
--- a/SOURCES/0142-NSS-nss_cmd_getbysid_search-return-ENOENT.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From d7b90921c1a404f0d9fb8384a8fd55fd15b86916 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Wed, 17 Dec 2014 14:10:45 +0000
-Subject: [PATCH 3/7] NSS: nss_cmd_getbysid_search return ENOENT
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/responder/nss/nsssrv_cmd.c | 16 ++++++++--------
- 1 file changed, 8 insertions(+), 8 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index ea58920bc3611c84958e8d0aca0e122d90c68e5c..80ac221e288665741d8b1e2bd020ecca568106c1 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4502,16 +4502,16 @@ static errno_t nss_cmd_getbysid_search(struct nss_dom_ctx *dctx)
-         return ENOENT;
-     }
- 
--    if (dctx->res->count == 0 && !dctx->check_provider) {
-+    if (dctx->res->count == 0) {
-         DEBUG(SSSDBG_OP_FAILURE, "No results for getbysid call.\n");
--
--        /* set negative cache only if not result of cache check */
--        ret = sss_ncache_set_sid(nctx->ncache, false, cmdctx->secid);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_MINOR_FAILURE,
--                  "Cannot set negative cache for %s\n", cmdctx->secid);
-+        if (!dctx->check_provider) {
-+            /* set negative cache only if not result of cache check */
-+            ret = sss_ncache_set_sid(nctx->ncache, false, cmdctx->secid);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_MINOR_FAILURE,
-+                      "Cannot set negative cache for %s\n", cmdctx->secid);
-+            }
-         }
--
-         return ENOENT;
-     }
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0143-SYSDB-sysdb_search_object_by_sid-returns-ENOENT.patch b/SOURCES/0143-SYSDB-sysdb_search_object_by_sid-returns-ENOENT.patch
deleted file mode 100644
index 6cd2d4f..0000000
--- a/SOURCES/0143-SYSDB-sysdb_search_object_by_sid-returns-ENOENT.patch
+++ /dev/null
@@ -1,249 +0,0 @@
-From 4bbcc2d6d3f16b015796818746a45134861c93a4 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Tue, 9 Dec 2014 11:01:13 +0000
-Subject: [PATCH 4/7] SYSDB: sysdb_search_object_by_sid returns ENOENT
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-sysdb_search_object_by_sid returns ENOENT if no results are found.
-
-Part od solution for:
-https://fedorahosted.org/sssd/ticket/1991
-
-Fixes:
-https://fedorahosted.org/sssd/ticket/2520
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/db/sysdb.h                 |  2 +-
- src/db/sysdb_ops.c             | 68 ++++++------------------------------------
- src/responder/nss/nsssrv_cmd.c | 25 ++++++++--------
- src/responder/pac/pacsrv_cmd.c | 29 ++++++++++--------
- src/tests/sysdb-tests.c        |  5 +---
- 5 files changed, 39 insertions(+), 90 deletions(-)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index 01900425ac5e8733eb57877bbadef0e8da00475f..b1e057107cc6e3d4ce7b7bb8e821a2414c3424a7 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -1035,7 +1035,7 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
-                                    struct sss_domain_info *domain,
-                                    const char *sid_str,
-                                    const char **attrs,
--                                   struct ldb_result **msg);
-+                                   struct ldb_result **res);
- 
- errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx,
-                                     struct sss_domain_info *domain,
-diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
-index 768f9455329b136b3de9794ad127dd349f1eaa43..b12540b68d1c81c419455416294f3449dd84914e 100644
---- a/src/db/sysdb_ops.c
-+++ b/src/db/sysdb_ops.c
-@@ -2994,7 +2994,14 @@ int sysdb_delete_by_sid(struct sysdb_ctx *sysdb,
-     }
- 
-     ret = sysdb_search_object_by_sid(tmp_ctx, domain, sid_str, NULL, &res);
--    if (ret != EOK) {
-+
-+    if (ret == ENOENT) {
-+        /* No existing entry. Just quit. */
-+        DEBUG(SSSDBG_TRACE_FUNC,
-+              "search by sid did not return any results.\n");
-+        ret = EOK;
-+        goto done;
-+    } else if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "search by sid failed: %d (%s)\n",
-               ret, strerror(ret));
-         goto done;
-@@ -3007,12 +3014,6 @@ int sysdb_delete_by_sid(struct sysdb_ctx *sysdb,
-         goto done;
-     }
- 
--    if (res->count == 0) {
--        /* No existing entry. Just quit. */
--        ret = EOK;
--        goto done;
--    }
--
-     ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, false);
-     if (ret != EOK) {
-         goto done;
-@@ -3564,61 +3565,10 @@ errno_t sysdb_search_object_by_sid(TALLOC_CTX *mem_ctx,
-                                    struct sss_domain_info *domain,
-                                    const char *sid_str,
-                                    const char **attrs,
--                                   struct ldb_result **msg)
-+                                   struct ldb_result **res)
- {
--/* TODO: use
-     return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_SID_FILTER,
-                                            sid_str, attrs, res);
--
--    when verified that all callers can handle ENOENT correctly. */
--
--    TALLOC_CTX *tmp_ctx;
--    const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM,
--                                ORIGINALAD_PREFIX SYSDB_NAME,
--                                SYSDB_OBJECTCLASS, NULL };
--    struct ldb_dn *basedn;
--    int ret;
--    struct ldb_result *res = NULL;
--
--    tmp_ctx = talloc_new(NULL);
--    if (!tmp_ctx) {
--        return ENOMEM;
--    }
--
--    basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, SYSDB_DOM_BASE, domain->name);
--    if (basedn == NULL) {
--        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
--        ret = ENOMEM;
--        goto done;
--    }
--
--    ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res,
--                     basedn, LDB_SCOPE_SUBTREE, attrs?attrs:def_attrs,
--                     SYSDB_SID_FILTER, sid_str);
--    if (ret != EOK) {
--        ret = sysdb_error_to_errno(ret);
--        DEBUG(SSSDBG_OP_FAILURE, "ldb_search failed.\n");
--        goto done;
--    }
--
--    if (res->count > 1) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Search for SID [%s] returned more than " \
--                                    "one object.\n", sid_str);
--        ret = EINVAL;
--        goto done;
--    }
--
--    *msg = talloc_steal(mem_ctx, res);
--
--done:
--    if (ret == ENOENT) {
--        DEBUG(SSSDBG_TRACE_FUNC, "No such entry.\n");
--    } else if (ret) {
--        DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
--    }
--
--    talloc_zfree(tmp_ctx);
--    return ret;
- }
- 
- errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx,
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index 80ac221e288665741d8b1e2bd020ecca568106c1..3c5d450714fb3f7655cd32aeef900b4f5e9782c7 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4491,20 +4491,10 @@ static errno_t nss_cmd_getbysid_search(struct nss_dom_ctx *dctx)
- 
-     ret = sysdb_search_object_by_sid(cmdctx, dom, cmdctx->secid, NULL,
-                                      &dctx->res);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache!\n");
--        return EIO;
--    }
--
--    if (dctx->res->count > 1) {
--        DEBUG(SSSDBG_FATAL_FAILURE, "getbysid call returned more than one " \
--                                     "result !?!\n");
--        return ENOENT;
--    }
--
--    if (dctx->res->count == 0) {
--        DEBUG(SSSDBG_OP_FAILURE, "No results for getbysid call.\n");
-+    if (ret == ENOENT) {
-         if (!dctx->check_provider) {
-+            DEBUG(SSSDBG_OP_FAILURE, "No results for getbysid call.\n");
-+
-             /* set negative cache only if not result of cache check */
-             ret = sss_ncache_set_sid(nctx->ncache, false, cmdctx->secid);
-             if (ret != EOK) {
-@@ -4513,6 +4503,15 @@ static errno_t nss_cmd_getbysid_search(struct nss_dom_ctx *dctx)
-             }
-         }
-         return ENOENT;
-+    } else if (ret != EOK) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache!\n");
-+        return EIO;
-+    }
-+
-+    if (dctx->res->count > 1) {
-+        DEBUG(SSSDBG_FATAL_FAILURE, "getbysid call returned more than one " \
-+                                     "result !?!\n");
-+        return ENOENT;
-     }
- 
-     /* if this is a caching provider (or if we haven't checked the cache
-diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c
-index cc92592893899b1fa269188facc1a8154f80991d..07d2f0cf79b70429dc7cf2784a8e31d651e5095f 100644
---- a/src/responder/pac/pacsrv_cmd.c
-+++ b/src/responder/pac/pacsrv_cmd.c
-@@ -297,17 +297,17 @@ static void pac_lookup_sids_done(struct tevent_req *req)
-             msg = NULL;
-             ret = sysdb_search_object_by_sid(pr_ctx, dom, entries[c].key.str,
-                                              NULL, &msg);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_object_by_sid " \
--                                          "failed.\n");
--                continue;
--            }
--
--            if (msg->count == 0) {
-+            if (ret == ENOENT) {
-                 DEBUG(SSSDBG_OP_FAILURE, "No entry found for SID [%s].\n",
--                                          entries[c].key.str);
-+                      entries[c].key.str);
-                 continue;
--            } else if (msg->count > 1) {
-+            } else if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE,
-+                      "sysdb_search_object_by_sid failed.\n");
-+                continue;
-+            }
-+
-+            if (msg->count > 1) {
-                 DEBUG(SSSDBG_CRIT_FAILURE, "More then one result returned " \
-                                             "for SID [%s].\n",
-                                             entries[c].key.str);
-@@ -911,10 +911,13 @@ pac_store_membership(struct pac_req_ctx *pr_ctx,
- 
-     ret = sysdb_search_object_by_sid(tmp_ctx, grp_dom, grp_sid_str,
-                                      group_attrs, &group);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_TRACE_INTERNAL, "sysdb_search_object_by_sid " \
--                                      "for SID [%s] failed [%d][%s].\n",
--                                      grp_sid_str, ret, strerror(ret));
-+    if (ret == ENOENT) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Unexpected number of groups returned.\n");
-+        goto done;
-+    } else if (ret != EOK) {
-+        DEBUG(SSSDBG_TRACE_INTERNAL,
-+              "sysdb_search_object_by_sid for SID [%s] failed [%d][%s].\n",
-+              grp_sid_str, ret, strerror(ret));
-         goto done;
-     }
- 
-diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
-index d303982647547eefdce7c37ac5b70e1ffbe869ce..92b41e90d08c2d50775289ba8c922f39350ce625 100644
---- a/src/tests/sysdb-tests.c
-+++ b/src/tests/sysdb-tests.c
-@@ -4861,13 +4861,10 @@ START_TEST (test_sysdb_search_return_ENOENT)
-     talloc_zfree(res);
- 
-     /* Search object */
--    /* TODO: Should return ENOENT */
-     ret = sysdb_search_object_by_sid(test_ctx, test_ctx->domain,
-                                      "S-5-4-3-2-1", NULL, &res);
--    fail_unless(ret == EOK, "sysdb_search_object_by_sid_str failed with "
-+    fail_unless(ret == ENOENT, "sysdb_search_object_by_sid_str failed with "
-                              "[%d][%s].", ret, strerror(ret));
--    fail_unless(res->count == 0, "sysdb_search_object_by_sid_str should not "
--                                 "return anything.");
-     talloc_zfree(res);
- 
-     /* Search can return more results */
--- 
-1.9.3
-
diff --git a/SOURCES/0144-handle-KRB5KRB_ERR_GENERIC-as-unspecific-error.patch b/SOURCES/0144-handle-KRB5KRB_ERR_GENERIC-as-unspecific-error.patch
deleted file mode 100644
index 6301175..0000000
--- a/SOURCES/0144-handle-KRB5KRB_ERR_GENERIC-as-unspecific-error.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 956dbefd49ce3cbf27539d8846a6d71462a3a927 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 17 Dec 2014 09:42:57 +0100
-Subject: [PATCH 5/7] krb5: handle KRB5KRB_ERR_GENERIC as unspecific error
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-KRB5KRB_ERR_GENERIC is a generic error and we cannot make any
-assumptions about the cause. If there are cases where
-KRB5KRB_ERR_GENERIC is returned and SSSD should behave differently this
-must be solved by other means.
-
-Resolves https://fedorahosted.org/sssd/ticket/2535
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/krb5/krb5_child.c | 13 ++++++++++++-
- 1 file changed, 12 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 64fe6f0cb19e831ed4b49f627cb3b3a124272943..e5ce50be4bb088df3c45e5f642e8b3f3608c4662 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -1076,7 +1076,6 @@ static errno_t map_krb5_error(krb5_error_code kerr)
-     case KRB5_LIBOS_CANTREADPWD:
-         return ERR_NO_CREDS;
- 
--    case KRB5KRB_ERR_GENERIC:
-     case KRB5KRB_AP_ERR_SKEW:
-     case KRB5_KDC_UNREACH:
-     case KRB5_REALM_CANT_RESOLVE:
-@@ -1099,6 +1098,18 @@ static errno_t map_krb5_error(krb5_error_code kerr)
-     case KRB5KDC_ERR_PREAUTH_FAILED:
-         return ERR_CREDS_INVALID;
- 
-+    /* Please do not remove KRB5KRB_ERR_GENERIC here, it is a _generic_ error
-+     * code and we cannot make any assumptions about the reason for the error.
-+     * As a consequence we cannot return a different error code than a generic
-+     * one which unfortunately might result in a unspecific system error
-+     * message to the user.
-+     *
-+     * If there are cases where libkrb5 calls return KRB5KRB_ERR_GENERIC where
-+     * SSSD should behave differently this has to be detected by different
-+     * means, e.g. by evaluation error messages, and then the error code
-+     * should be changed to a more suitable KRB5* error code or immediately to
-+     * a SSSD ERR_* error code to avoid the default handling here. */
-+    case KRB5KRB_ERR_GENERIC:
-     default:
-         return ERR_INTERNAL;
-     }
--- 
-1.9.3
-
diff --git a/SOURCES/0145-IPA-verify-group-memberships-of-trusted-domain-users.patch b/SOURCES/0145-IPA-verify-group-memberships-of-trusted-domain-users.patch
deleted file mode 100644
index 37f9d78..0000000
--- a/SOURCES/0145-IPA-verify-group-memberships-of-trusted-domain-users.patch
+++ /dev/null
@@ -1,215 +0,0 @@
-From ad463501d3bdea4c24c17d792efc1c3e65c08c19 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 11 Dec 2014 10:49:39 +0100
-Subject: [PATCH 6/7] IPA: verify group memberships of trusted domain users
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Depending on the state of the cache group object a freshly created or
-updates user entry for a trusted domain user might already be a member
-of the group or not. This cache makes sure the requested user is a
-member of all groups returned from the extdom request. Special care has
-to be taken to cover cross-domain group-memberships properly.
-
-Resolves https://fedorahosted.org/sssd/ticket/2529
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 145 ++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 144 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 0eab1afc36e4d2c1d770c596c512a641fd276425..677d1625860186ad02d4d8c7290d45b782bc4c38 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -568,7 +568,7 @@ static errno_t add_v1_user_data(BerElement *ber, struct resp_attrs *attrs)
-          attrs->ngroups++);
- 
-     if (attrs->ngroups > 0) {
--        attrs->groups = talloc_array(attrs, char *, attrs->ngroups);
-+        attrs->groups = talloc_zero_array(attrs, char *, attrs->ngroups + 1);
-         if (attrs->groups == NULL) {
-             DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-             ret = ENOMEM;
-@@ -1528,6 +1528,81 @@ done:
-     return;
- }
- 
-+static errno_t get_groups_dns(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom,
-+                              char **name_list, char ***_dn_list)
-+{
-+    int ret;
-+    TALLOC_CTX *tmp_ctx;
-+    int c;
-+    struct sss_domain_info *root_domain;
-+    char **dn_list;
-+
-+    if (name_list == NULL) {
-+        *_dn_list = NULL;
-+        return EOK;
-+    }
-+
-+    /* To handle cross-domain memberships we have to check the domain for
-+     * each group the member should be added or deleted. Since sub-domains
-+     * use fully-qualified names by default any short name can only belong
-+     * to the root/head domain. find_domain_by_object_name() will return
-+     * the domain given in the first argument if the second argument is a
-+     * a short name hence we always use root_domain as first argument. */
-+    root_domain = get_domains_head(dom);
-+    if (root_domain->fqnames) {
-+        DEBUG(SSSDBG_TRACE_FUNC,
-+              "Root domain uses fully-qualified names, " \
-+              "objects might not be correctly added to groups with " \
-+              "short names.\n");
-+    }
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    for (c = 0; name_list[c] != NULL; c++);
-+
-+    dn_list = talloc_zero_array(tmp_ctx, char *, c + 1);
-+    if (dn_list == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    for (c = 0; name_list[c] != NULL; c++) {
-+        dom = find_domain_by_object_name(root_domain, name_list[c]);
-+        if (dom == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE,
-+                  "Cannot find domain for [%s].\n", name_list[c]);
-+            ret = ENOENT;
-+            goto done;
-+        }
-+
-+        /* This might fail if some unexpected cases are used. But current
-+         * sysdb code which handles group membership constructs DNs this way
-+         * as well, IPA names are lowercased and AD names by default will be
-+         * lowercased as well. If there are really use-cases which cause an
-+         * issue here, sysdb_group_strdn() has to be replaced by a proper
-+         * search. */
-+        dn_list[c] = sysdb_group_strdn(dn_list, dom->name, name_list[c]);
-+        if (dn_list[c] == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_group_strdn failed.\n");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+    }
-+
-+    *_dn_list = talloc_steal(mem_ctx, dn_list);
-+    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,
-@@ -1548,6 +1623,13 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-     const char *tmp_str;
-     struct ldb_result *res;
-     enum sysdb_member_type type;
-+    char **sysdb_grouplist;
-+    char **add_groups;
-+    char **add_groups_dns;
-+    char **del_groups;
-+    char **del_groups_dns;
-+    bool in_transaction = false;
-+    int tret;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -1716,6 +1798,13 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                 gid = attrs->a.user.pw_gid;
-             }
- 
-+            ret = sysdb_transaction_start(dom->sysdb);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
-+                goto done;
-+            }
-+            in_transaction = true;
-+
-             ret = sysdb_store_user(dom, name, NULL,
-                                    attrs->a.user.pw_uid,
-                                    gid, attrs->a.user.pw_gecos,
-@@ -1726,6 +1815,53 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                 DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_user failed.\n");
-                 goto done;
-             }
-+
-+            if (attrs->response_type == RESP_USER_GROUPLIST) {
-+                ret = get_sysdb_grouplist(tmp_ctx, dom->sysdb, dom, name,
-+                                          &sysdb_grouplist);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "get_sysdb_grouplist failed.\n");
-+                    goto done;
-+                }
-+
-+                ret = diff_string_lists(tmp_ctx, attrs->groups, sysdb_grouplist,
-+                                        &add_groups, &del_groups, NULL);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "diff_string_lists failed.\n");
-+                    goto done;
-+                }
-+
-+                ret = get_groups_dns(tmp_ctx, dom, add_groups, &add_groups_dns);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "get_groups_dns failed.\n");
-+                    goto done;
-+                }
-+
-+                ret = get_groups_dns(tmp_ctx, dom, del_groups, &del_groups_dns);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "get_groups_dns failed.\n");
-+                    goto done;
-+                }
-+
-+                DEBUG(SSSDBG_TRACE_INTERNAL, "Updating memberships for %s\n",
-+                                             name);
-+                ret = sysdb_update_members_dn(dom, name, SYSDB_MEMBER_USER,
-+                                          (const char *const *) add_groups_dns,
-+                                          (const char *const *) del_groups_dns);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_CRIT_FAILURE, "Membership update failed [%d]: %s\n",
-+                                               ret, sss_strerror(ret));
-+                    goto done;
-+                }
-+            }
-+
-+            ret = sysdb_transaction_commit(dom->sysdb);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
-+                goto done;
-+            }
-+            in_transaction = false;
-+
-             break;
-         case RESP_GROUP:
-         case RESP_GROUP_MEMBERS:
-@@ -1818,6 +1954,13 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-     }
- 
- done:
-+    if (in_transaction) {
-+        tret = sysdb_transaction_cancel(dom->sysdb);
-+        if (tret != EOK) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
-+        }
-+    }
-+
-     talloc_free(tmp_ctx);
- 
-     return ret;
--- 
-1.9.3
-
diff --git a/SOURCES/0146-IPA-properly-handle-groups-from-different-domains.patch b/SOURCES/0146-IPA-properly-handle-groups-from-different-domains.patch
deleted file mode 100644
index bfc5abf..0000000
--- a/SOURCES/0146-IPA-properly-handle-groups-from-different-domains.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From 8f9d7684a47cd4715dce22c8254ddde205db9afe Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 12 Dec 2014 13:07:55 -0500
-Subject: [PATCH 7/7] IPA: properly handle groups from different domains
-
-When groups are resolved on IPA clients as part of a user lookup not all
-groups have to be from the same domain as the used. This has to be
-checked to store the group object properly in the cache.
-
-Related to https://fedorahosted.org/sssd/ticket/2529
-       and https://fedorahosted.org/sssd/ticket/2524
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 18 ++++++++++++++++--
- 1 file changed, 16 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 677d1625860186ad02d4d8c7290d45b782bc4c38..6d5b45edf20f720f5b97f0ed5c8ec591c580de0d 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1867,10 +1867,24 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-         case RESP_GROUP_MEMBERS:
-             type = SYSDB_MEMBER_GROUP;
- 
-+            if (0 != strcmp(dom->name, attrs->domain_name)) {
-+                dom = find_domain_by_name(get_domains_head(dom),
-+                                          attrs->domain_name, true);
-+                if (dom == NULL) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "Cannot find domain: [%s]\n", attrs->domain_name);
-+                    ret = EINVAL;
-+                    goto done;
-+                }
-+            }
-+
-             if (name == NULL) {
-+                name = attrs->a.group.gr_name;
-+            }
-+
-+            if (IS_SUBDOMAIN(dom)) {
-                 /* we always use the fully qualified name for subdomain users */
--                name = sss_tc_fqname(tmp_ctx, dom->names, dom,
--                                     attrs->a.group.gr_name);
-+                name = sss_tc_fqname(tmp_ctx, dom->names, dom, name);
-                 if (!name) {
-                     DEBUG(SSSDBG_OP_FAILURE, "failed to format user name,\n");
-                     ret = ENOMEM;
--- 
-1.9.3
-
diff --git a/SOURCES/0147-LDAP-retain-external-members.patch b/SOURCES/0147-LDAP-retain-external-members.patch
deleted file mode 100644
index ddb3499..0000000
--- a/SOURCES/0147-LDAP-retain-external-members.patch
+++ /dev/null
@@ -1,261 +0,0 @@
-From 6fac5e5f0c54a0f92872ce1450606cfcb577a920 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Thu, 20 Nov 2014 18:27:04 +0000
-Subject: [PATCH] LDAP: retain external members
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When processing group membership check sysdb for group members from
-extern domain and include them in newly processed group membership as
-extern members are curently found only when initgroups() is called.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2492
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/db/sysdb.h                         |   6 ++
- src/db/sysdb_ops.c                     |  83 ++++++++++++++++++++++++++
- src/providers/ldap/sdap_async_groups.c | 104 +++++++++++++++++++++++++++++++++
- 3 files changed, 193 insertions(+)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index 5bd7f90acb685bbaff5c98f433c7dce8175c33ca..cdcdfd51d6146bee5b212e6acfe98c831b635d33 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -1103,4 +1103,10 @@ errno_t sysdb_gpo_get_gpo_result_setting(TALLOC_CTX *mem_ctx,
-                                          const char *policy_setting_key,
-                                          const char **policy_setting_value);
- 
-+errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
-+                                  struct sss_domain_info *dom,
-+                                  const char *group_name,
-+                                  const char ***_sids,
-+                                  const char ***_dns,
-+                                  size_t *_n);
- #endif /* __SYS_DB_H__ */
-diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
-index 998046a2ca1c746b2032f430e5f9c4a7151e1dbc..768f9455329b136b3de9794ad127dd349f1eaa43 100644
---- a/src/db/sysdb_ops.c
-+++ b/src/db/sysdb_ops.c
-@@ -3630,3 +3630,86 @@ errno_t sysdb_search_object_by_uuid(TALLOC_CTX *mem_ctx,
-     return sysdb_search_object_by_str_attr(mem_ctx, domain, SYSDB_UUID_FILTER,
-                                            uuid_str, attrs, res);
- }
-+
-+errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
-+                                  struct sss_domain_info *dom,
-+                                  const char *group_name,
-+                                  const char ***_sids,
-+                                  const char ***_dns,
-+                                  size_t *_n)
-+{
-+    errno_t ret;
-+    size_t i, m_count;
-+    TALLOC_CTX *tmp_ctx;
-+    struct ldb_message *msg;
-+    struct ldb_message **members;
-+    const char *attrs[] = { SYSDB_SID_STR, NULL };
-+    const char **sids = NULL, **dns = NULL;
-+    size_t n = 0;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    ret = sysdb_search_group_by_name(tmp_ctx, dom, group_name, NULL, &msg);
-+    if (ret != EOK) {
-+        goto done;
-+    }
-+
-+    /* Get sid_str attribute of all elemets pointed to by group members */
-+    ret = sysdb_asq_search(tmp_ctx, dom, msg->dn, NULL, SYSDB_MEMBER, attrs,
-+                           &m_count, &members);
-+    if (ret != EOK) {
-+        goto done;
-+    }
-+
-+    sids = talloc_array(tmp_ctx, const char*, m_count);
-+    if (sids == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    dns = talloc_array(tmp_ctx, const char*, m_count);
-+    if (dns == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    for (i=0; i < m_count; i++) {
-+        const char *sidstr;
-+
-+        sidstr = ldb_msg_find_attr_as_string(members[i], SYSDB_SID_STR, NULL);
-+
-+        if (sidstr != NULL) {
-+            sids[n] = talloc_steal(sids, sidstr);
-+
-+            dns[n] = talloc_steal(dns, ldb_dn_get_linearized(members[i]->dn));
-+            if (dns[n] == NULL) {
-+                ret = ENOMEM;
-+                goto done;
-+            }
-+            n++;
-+        }
-+    }
-+
-+    if (n == 0) {
-+        ret = ENOENT;
-+        goto done;
-+    }
-+
-+    *_n = n;
-+    *_sids = talloc_steal(mem_ctx, sids);
-+    *_dns = talloc_steal(mem_ctx, dns);
-+
-+    ret = EOK;
-+
-+done:
-+    if (ret == ENOENT) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "No such entry\n");
-+    } else if (ret) {
-+        DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
-+    }
-+    talloc_free(tmp_ctx);
-+    return ret;
-+}
-diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
-index 8cf7f7ff1d414049f0694c7d2873556fc9dad741..c86b5c6b59a4de7e945b95cafae9149f681e2e18 100644
---- a/src/providers/ldap/sdap_async_groups.c
-+++ b/src/providers/ldap/sdap_async_groups.c
-@@ -801,6 +801,87 @@ done:
-     return ret;
- }
- 
-+static errno_t
-+are_sids_from_same_dom(const char *sid1, const char *sid2, bool *_result)
-+{
-+    size_t len_prefix_sid1;
-+    size_t len_prefix_sid2;
-+    char *rid1, *rid2;
-+    bool result;
-+
-+    rid1 = strrchr(sid1, '-');
-+    if (rid1 == NULL) {
-+        return EINVAL;
-+    }
-+
-+    rid2 = strrchr(sid2, '-');
-+    if (rid2 == NULL) {
-+        return EINVAL;
-+    }
-+
-+    len_prefix_sid1 = rid1 - sid1;
-+    len_prefix_sid2 = rid2 - sid2;
-+
-+    result = (len_prefix_sid1 == len_prefix_sid2) &&
-+        (strncmp(sid1, sid2, len_prefix_sid1) == 0);
-+
-+    *_result = result;
-+
-+    return EOK;
-+}
-+
-+static errno_t
-+retain_extern_members(TALLOC_CTX *mem_ctx,
-+                      struct sss_domain_info *dom,
-+                      const char *group_name,
-+                      const char *group_sid,
-+                      char ***_userdns,
-+                      size_t *_nuserdns)
-+{
-+    TALLOC_CTX *tmp_ctx;
-+    const char **sids, **dns;
-+    bool same_domain;
-+    errno_t ret;
-+    size_t i, n;
-+    size_t nuserdns = 0;
-+    const char **userdns = NULL;
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    ret = sysdb_get_sids_of_members(tmp_ctx, dom, group_name, &sids, &dns, &n);
-+    if (ret != EOK) {
-+        if (ret != ENOENT) {
-+            DEBUG(SSSDBG_TRACE_ALL,
-+                  "get_sids_of_members failed: %d [%s]\n",
-+                  ret, sss_strerror(ret));
-+        }
-+        goto done;
-+    }
-+
-+    for (i=0; i < n; i++) {
-+        ret = are_sids_from_same_dom(group_sid, sids[i], &same_domain);
-+        if (ret == EOK && !same_domain) {
-+            DEBUG(SSSDBG_TRACE_ALL, "extern member: %s\n", dns[i]);
-+            nuserdns++;
-+            userdns = talloc_realloc(tmp_ctx, userdns, const char*, nuserdns);
-+            if (userdns == NULL) {
-+                ret = ENOMEM;
-+                goto done;
-+            }
-+            userdns[nuserdns-1] = talloc_steal(userdns, dns[i]);
-+        }
-+    }
-+    *_nuserdns = nuserdns;
-+    *_userdns = discard_const(talloc_steal(mem_ctx, userdns));
-+    ret = EOK;
-+
-+done:
-+    talloc_free(tmp_ctx);
-+    return ret;
-+}
- 
- /* ==Save-Group-Memebrs=================================================== */
- 
-@@ -817,6 +898,7 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
- {
-     struct ldb_message_element *el;
-     struct sysdb_attrs *group_attrs = NULL;
-+    const char *group_sid;
-     const char *group_name;
-     char **userdns = NULL;
-     size_t nuserdns = 0;
-@@ -843,6 +925,28 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx,
-         }
-     }
- 
-+    /* This is a temporal solution until the IPA provider is able to
-+     * resolve external group membership.
-+     * https://fedorahosted.org/sssd/ticket/2522
-+     */
-+    if (opts->schema_type == SDAP_SCHEMA_IPA_V1) {
-+        ret = sysdb_attrs_get_string(attrs, SYSDB_SID_STR, &group_sid);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_TRACE_FUNC, "Failed to get group sid\n");
-+            group_sid = NULL;
-+        }
-+
-+        if (group_sid != NULL) {
-+            ret = retain_extern_members(memctx, dom, group_name, group_sid,
-+                                        &userdns, &nuserdns);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_TRACE_INTERNAL,
-+                      "retain_extern_members failed: %d:[%s].\n",
-+                      ret, sss_strerror(ret));
-+            }
-+        }
-+    }
-+
-     ret = sysdb_attrs_get_el(attrs,
-                     opts->group_map[SDAP_AT_GROUP_MEMBER].sys_name, &el);
-     if (ret != EOK) {
--- 
-1.9.3
-
diff --git a/SOURCES/0148-IPA-do-not-try-to-add-override-gid-twice.patch b/SOURCES/0148-IPA-do-not-try-to-add-override-gid-twice.patch
deleted file mode 100644
index fd32d86..0000000
--- a/SOURCES/0148-IPA-do-not-try-to-add-override-gid-twice.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From b52b26176c92f3b06dba5598428c70c0cde13fd1 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 2 Dec 2014 21:10:01 +0100
-Subject: [PATCH 1/2] IPA: do not try to add override gid twice
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-By default user and group overrides use the same attribute name for the
-GID and this cause SSSD machinery to add the same value twice which
-cause an error in ldb_add() or ldm_modify().
-
-Related to https://fedorahosted.org/sssd/ticket/2514
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/db/sysdb_views.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index 8cc279af6c72f3e7ab2917d997f84a33a05e91b9..c735a7bd8588a80743d40438d010db5912f47bb5 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -525,8 +525,14 @@ errno_t sysdb_store_override(struct sss_domain_info *domain,
-             goto done;
-         }
- 
--        /* TODO: add nameAlias for case-insentitive searches */
-         for (c = 0; c < attrs->num; c++) {
-+            /* Set num_values to 1 because by default user and group overrides
-+             * use the same attribute name for the GID and this cause SSSD
-+             * machinery to add the same value twice */
-+            if (attrs->a[c].num_values > 1
-+                    && strcmp(attrs->a[c].name, SYSDB_GIDNUM) == 0) {
-+                attrs->a[c].num_values = 1;
-+            }
-             msg->elements[c] = attrs->a[c];
-             msg->elements[c].flags = LDB_FLAG_MOD_ADD;
-         }
--- 
-1.9.3
-
diff --git a/SOURCES/0149-IPA-handle-GID-overrides-for-MPG-domains-on-clients.patch b/SOURCES/0149-IPA-handle-GID-overrides-for-MPG-domains-on-clients.patch
deleted file mode 100644
index 465ac9e..0000000
--- a/SOURCES/0149-IPA-handle-GID-overrides-for-MPG-domains-on-clients.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 034dcabb40e654a95f3714d871db471ff7bf97f8 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 4 Dec 2014 12:50:03 +0100
-Subject: [PATCH 2/2] IPA: handle GID overrides for MPG domains on clients
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves https://fedorahosted.org/sssd/ticket/2514
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 26 ++++++++++++++++++++++++++
- 1 file changed, 26 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 6d5b45edf20f720f5b97f0ed5c8ec591c580de0d..55450c7029391a99bfc33b8446765f71c4d0928a 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1618,6 +1618,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-     char *realm;
-     char *upn = NULL;
-     gid_t gid;
-+    gid_t orig_gid = 0;
-     TALLOC_CTX *tmp_ctx;
-     const char *sid_str;
-     const char *tmp_str;
-@@ -1796,6 +1797,31 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-             gid = 0;
-             if (dom->mpg == false) {
-                 gid = attrs->a.user.pw_gid;
-+            } else {
-+                /* The extdom plugin always returns the objects with the
-+                 * default view applied. Since the GID is handled specially
-+                 * for MPG domains we have add any overridden GID separately.
-+                 */
-+                ret = sysdb_attrs_get_uint32_t(attrs->sysdb_attrs,
-+                                               ORIGINALAD_PREFIX SYSDB_GIDNUM,
-+                                               &orig_gid);
-+                if (ret == EOK || ret == ENOENT) {
-+                    if ((orig_gid != 0 && orig_gid != attrs->a.user.pw_gid)
-+                            || attrs->a.user.pw_uid != attrs->a.user.pw_gid) {
-+                        ret = sysdb_attrs_add_uint32(attrs->sysdb_attrs,
-+                                                     SYSDB_GIDNUM,
-+                                                     attrs->a.user.pw_gid);
-+                        if (ret != EOK) {
-+                            DEBUG(SSSDBG_OP_FAILURE,
-+                                  "sysdb_attrs_add_uint32 failed.\n");
-+                            goto done;
-+                        }
-+                    }
-+                } else {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_attrs_get_uint32_t failed.\n");
-+                    goto done;
-+                }
-             }
- 
-             ret = sysdb_transaction_start(dom->sysdb);
--- 
-1.9.3
-
diff --git a/SOURCES/0150-simple-access-provider-non-existing-object.patch b/SOURCES/0150-simple-access-provider-non-existing-object.patch
deleted file mode 100644
index 1fffdb9..0000000
--- a/SOURCES/0150-simple-access-provider-non-existing-object.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-From 79f128801d598ca57a6acebade01136525a47e00 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Wed, 4 Jun 2014 17:41:31 +0100
-Subject: [PATCH] simple access provider: non-existing object
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2519
-
-Not existing user/group in simple_allow_users/simple_allow_groups should not
-imply access denied.
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/providers/simple/simple_access_check.c | 35 +++++++++++++++++++++---------
- 1 file changed, 25 insertions(+), 10 deletions(-)
-
-diff --git a/src/providers/simple/simple_access_check.c b/src/providers/simple/simple_access_check.c
-index 13c66d58f71225a6c458c19e7fb9d26fd15c08ea..d6662871948afffa2cd822614a671149d2f3bf1a 100644
---- a/src/providers/simple/simple_access_check.c
-+++ b/src/providers/simple/simple_access_check.c
-@@ -24,6 +24,11 @@
- #include "util/sss_utf8.h"
- #include "db/sysdb.h"
- 
-+#define NON_EXIST_USR_ALLOW "The user %s does not exist. Possible typo in simple_allow_users.\n"
-+#define NON_EXIST_USR_DENY  "The user %s does not exist. Possible typo in simple_deny_users.\n"
-+#define NON_EXIST_GRP_ALLOW "The group %s does not exist. Possible typo in simple_allow_groups.\n"
-+#define NON_EXIST_GRP_DENY  "The group %s does not exist. Possible typo in simple_deny_groups.\n"
-+
- static bool
- is_posix(const struct ldb_message *group)
- {
-@@ -53,9 +58,11 @@ simple_check_users(struct simple_ctx *ctx, const char *username,
-             domain = find_domain_by_object_name(ctx->domain,
-                                                 ctx->allow_users[i]);
-             if (domain == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "Invalid user %s!\n",
--                                            ctx->allow_users[i]);
--                return EINVAL;
-+                DEBUG(SSSDBG_CRIT_FAILURE, NON_EXIST_USR_ALLOW,
-+                      ctx->allow_users[i]);
-+                sss_log(SSS_LOG_CRIT, NON_EXIST_USR_ALLOW,
-+                        ctx->allow_users[i]);
-+                continue;
-             }
- 
-             if (sss_string_equal(domain->case_sensitive, username,
-@@ -86,8 +93,10 @@ simple_check_users(struct simple_ctx *ctx, const char *username,
-             domain = find_domain_by_object_name(ctx->domain,
-                                                 ctx->deny_users[i]);
-             if (domain == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "Invalid user %s!\n",
--                                            ctx->deny_users[i]);
-+                DEBUG(SSSDBG_CRIT_FAILURE, NON_EXIST_USR_DENY,
-+                      ctx->deny_users[i]);
-+                sss_log(SSS_LOG_CRIT, NON_EXIST_USR_DENY,
-+                        ctx->deny_users[i]);
-                 return EINVAL;
-             }
- 
-@@ -125,9 +134,12 @@ simple_check_groups(struct simple_ctx *ctx, const char **group_names,
-             domain = find_domain_by_object_name(ctx->domain,
-                                                 ctx->allow_groups[i]);
-             if (domain == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "Invalid group %s!\n",
--                                            ctx->allow_groups[i]);
--                return EINVAL;
-+                DEBUG(SSSDBG_CRIT_FAILURE, NON_EXIST_GRP_ALLOW,
-+                      ctx->allow_groups[i]);
-+                sss_log(SSS_LOG_CRIT, NON_EXIST_GRP_ALLOW,
-+                        ctx->allow_groups[i]);
-+
-+                continue;
-             }
- 
-             for(j = 0; group_names[j]; j++) {
-@@ -158,8 +170,11 @@ simple_check_groups(struct simple_ctx *ctx, const char **group_names,
-             domain = find_domain_by_object_name(ctx->domain,
-                                                 ctx->deny_groups[i]);
-             if (domain == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "Invalid group %s!\n",
--                                            ctx->deny_groups[i]);
-+                DEBUG(SSSDBG_CRIT_FAILURE, NON_EXIST_GRP_DENY,
-+                      ctx->deny_groups[i]);
-+                sss_log(SSS_LOG_CRIT, NON_EXIST_GRP_DENY,
-+                        ctx->deny_groups[i]);
-+
-                 return EINVAL;
-             }
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0151-libwbclient-initialize-some-return-values.patch b/SOURCES/0151-libwbclient-initialize-some-return-values.patch
deleted file mode 100644
index 6bcb02d..0000000
--- a/SOURCES/0151-libwbclient-initialize-some-return-values.patch
+++ /dev/null
@@ -1,101 +0,0 @@
-From 082e13dba488ebb2b948d6a362095153714b669f Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 19 Dec 2014 11:21:41 +0100
-Subject: [PATCH] libwbclient: initialize some return values
-
-Some callers of libwbclient functions expects the return values are
-initialized even it the functions returns an error. This patch adds some
-initializations to meet this requirement.
-
-Resolves https://fedorahosted.org/sssd/ticket/2537
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/sss_client/libwbclient/wbc_pam_sssd.c | 36 +++++++++++++++++++++++++++++++
- 1 file changed, 36 insertions(+)
-
-diff --git a/src/sss_client/libwbclient/wbc_pam_sssd.c b/src/sss_client/libwbclient/wbc_pam_sssd.c
-index 893a5c16cf0e020e0570ea838d96fa82292373fa..174cf1310fad0243036fe591978cc89700903896 100644
---- a/src/sss_client/libwbclient/wbc_pam_sssd.c
-+++ b/src/sss_client/libwbclient/wbc_pam_sssd.c
-@@ -45,6 +45,10 @@ wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
-                  struct wbcAuthUserInfo **info,
-                  struct wbcAuthErrorInfo **error)
- {
-+    if (error != NULL) {
-+        *error = NULL;
-+    }
-+
-     WBC_SSSD_NOT_IMPLEMENTED;
- }
- 
-@@ -52,6 +56,10 @@ wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
- wbcErr wbcCheckTrustCredentials(const char *domain,
-                 struct wbcAuthErrorInfo **error)
- {
-+    if (error != NULL) {
-+        *error = NULL;
-+    }
-+
-     WBC_SSSD_NOT_IMPLEMENTED;
- }
- 
-@@ -59,6 +67,10 @@ wbcErr wbcCheckTrustCredentials(const char *domain,
- wbcErr wbcChangeTrustCredentials(const char *domain,
-                  struct wbcAuthErrorInfo **error)
- {
-+    if (error != NULL) {
-+        *error = NULL;
-+    }
-+
-     WBC_SSSD_NOT_IMPLEMENTED;
- }
- 
-@@ -102,6 +114,14 @@ wbcErr wbcChangeUserPasswordEx(const struct wbcChangePasswordParams *params,
-                    enum wbcPasswordChangeRejectReason *reject_reason,
-                    struct wbcUserPasswordPolicyInfo **policy)
- {
-+    if (error != NULL) {
-+        *error = NULL;
-+    }
-+
-+    if (policy != NULL) {
-+        *policy = NULL;
-+    }
-+
-     WBC_SSSD_NOT_IMPLEMENTED;
- }
- 
-@@ -129,6 +149,18 @@ wbcErr wbcLogonUser(const struct wbcLogonUserParams *params,
-             struct wbcAuthErrorInfo **error,
-             struct wbcUserPasswordPolicyInfo **policy)
- {
-+    if (info != NULL) {
-+        *info = NULL;
-+    }
-+
-+    if (error != NULL) {
-+        *error = NULL;
-+    }
-+
-+    if (policy != NULL) {
-+        *policy = NULL;
-+    }
-+
-     WBC_SSSD_NOT_IMPLEMENTED;
- }
- 
-@@ -137,6 +169,10 @@ wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
-                           struct wbcCredentialCacheInfo **info,
-                           struct wbcAuthErrorInfo **error)
- {
-+    if (error != NULL) {
-+        *error = NULL;
-+    }
-+
-     WBC_SSSD_NOT_IMPLEMENTED;
- }
- 
--- 
-1.9.3
-
diff --git a/SOURCES/0152-GPO-Ignore-ENOENT-result-from-sysdb_gpo_get_gpo_resu.patch b/SOURCES/0152-GPO-Ignore-ENOENT-result-from-sysdb_gpo_get_gpo_resu.patch
deleted file mode 100644
index f951b5c..0000000
--- a/SOURCES/0152-GPO-Ignore-ENOENT-result-from-sysdb_gpo_get_gpo_resu.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 2f38a6fe31be1619f4725733f388b99e64f9c668 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 6 Jan 2015 13:14:35 +0100
-Subject: [PATCH 152/160] GPO: Ignore ENOENT result from
- sysdb_gpo_get_gpo_result_setting()
-
-https://fedorahosted.org/sssd/ticket/2542
-
-If the GPO result object was missing completely, we would error out with
-a fatal error code. It's more user-friendly to treat the missing object
-as if the requested attribute was missing on the provider level.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit fc2cc91a5b645180e53d46436b0d08011aac8d74)
----
- src/providers/ad/ad_gpo.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 62715861c91484fa2a57e7cc13ba403c9096d9a7..4f8497809bfe962672a99f26de7b61f9f89ac6fa 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -1339,7 +1339,10 @@ parse_policy_setting_value(TALLOC_CTX *mem_ctx,
-     char **sids_list = NULL;
- 
-     ret = sysdb_gpo_get_gpo_result_setting(mem_ctx, domain, key, &value);
--    if (ret != EOK) {
-+    if (ret == ENOENT) {
-+        DEBUG(SSSDBG_TRACE_FUNC, "No previous GPO result\n");
-+        value = NULL;
-+    } else if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE,
-               "Cannot retrieve settings from sysdb for key: '%s' [%d][%s].\n",
-               key, ret, sss_strerror(ret));
--- 
-2.1.0
-
diff --git a/SOURCES/0153-GPO-Set-libsmb-debugging-to-stderr.patch b/SOURCES/0153-GPO-Set-libsmb-debugging-to-stderr.patch
deleted file mode 100644
index 1af59b9..0000000
--- a/SOURCES/0153-GPO-Set-libsmb-debugging-to-stderr.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 0af3ec742fd3d160d8b6ccc81a368e851456d61c Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 6 Jan 2015 16:54:44 +0100
-Subject: [PATCH 153/160] GPO: Set libsmb debugging to stderr
-
-libsmb logs to stdout by default. It's much more reasonable to log to
-stderr by default.
-
-Please also note:
-    https://bugzilla.samba.org/show_bug.cgi?id=11036
-and:
-    https://fedorahosted.org/sssd/ticket/2544
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit bb7ddd2be9847bfb07395341c7623da1b104b8a6)
----
- src/providers/ad/ad_gpo_child.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/providers/ad/ad_gpo_child.c b/src/providers/ad/ad_gpo_child.c
-index 4bb48c0479400ebeeca287acfcb1573c69a76b90..c6eb52f06b1daadb083bd4c9efb299a12031d4d5 100644
---- a/src/providers/ad/ad_gpo_child.c
-+++ b/src/providers/ad/ad_gpo_child.c
-@@ -601,6 +601,7 @@ perform_smb_operations(int cached_gpt_version,
-         goto done;
-     }
- 
-+    smbc_setOptionDebugToStderr(smbc_ctx, 1);
-     smbc_setFunctionAuthData(smbc_ctx, sssd_krb_get_auth_data_fn);
-     smbc_setOptionUseKerberos(smbc_ctx, 1);
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0154-UTIL-Allow-dup-ing-child-pipe-to-a-different-FD.patch b/SOURCES/0154-UTIL-Allow-dup-ing-child-pipe-to-a-different-FD.patch
deleted file mode 100644
index d0888b1..0000000
--- a/SOURCES/0154-UTIL-Allow-dup-ing-child-pipe-to-a-different-FD.patch
+++ /dev/null
@@ -1,193 +0,0 @@
-From df95d21e5253cec8745329567ab8050bfcd52333 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 7 Jan 2015 10:36:12 +0100
-Subject: [PATCH 154/160] UTIL: Allow dup-ing child pipe to a different FD
-
-Related to:
-    https://fedorahosted.org/sssd/ticket/2544
-
-Adds a new function exec_child_ex and moves setting the extra_argv[]
-to exec_child_ex() along with specifying the input and output fds.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 16cb0969f0a9ea71524d852077d6a480740d4f12)
----
- src/providers/ad/ad_gpo.c               |  2 +-
- src/providers/ipa/ipa_selinux.c         |  3 +--
- src/providers/krb5/krb5_child_handler.c |  8 ++++----
- src/providers/ldap/sdap_child_helpers.c |  3 +--
- src/tests/cmocka/test_child_common.c    | 11 ++++++-----
- src/util/child_common.c                 | 22 ++++++++++++++++------
- src/util/child_common.h                 | 12 ++++++++++--
- 7 files changed, 39 insertions(+), 22 deletions(-)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 4f8497809bfe962672a99f26de7b61f9f89ac6fa..1ae62e7c4727702d5338258046e89e4b654904eb 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -3963,7 +3963,7 @@ gpo_fork_child(struct tevent_req *req)
-     if (pid == 0) { /* child */
-         err = exec_child(state,
-                          pipefd_to_child, pipefd_from_child,
--                         GPO_CHILD, gpo_child_debug_fd, NULL);
-+                         GPO_CHILD, gpo_child_debug_fd);
-         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec gpo_child: [%d][%s].\n",
-               err, strerror(err));
-         return err;
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index c4e70cfcb0748988d91fc1db57cf5a30d5365be4..133b679b6d518704ebb2bd901c64ac48170c9a0b 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -1049,8 +1049,7 @@ static errno_t selinux_fork_child(struct selinux_child_state *state)
-     if (pid == 0) { /* child */
-         ret = exec_child(state,
-                          pipefd_to_child, pipefd_from_child,
--                         SELINUX_CHILD, selinux_child_debug_fd,
--                         NULL);
-+                         SELINUX_CHILD, selinux_child_debug_fd);
-         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec selinux_child: [%d][%s].\n",
-               ret, sss_strerror(ret));
-         return ret;
-diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c
-index 1454d220fb294abc339df6e862154012a03fdca0..633cd917737d3f39526b049cc3d930b67f8b5c66 100644
---- a/src/providers/krb5/krb5_child_handler.c
-+++ b/src/providers/krb5/krb5_child_handler.c
-@@ -305,10 +305,10 @@ static errno_t fork_child(struct tevent_req *req)
-     pid = fork();
- 
-     if (pid == 0) { /* child */
--        err = exec_child(state,
--                         pipefd_to_child, pipefd_from_child,
--                         KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd,
--                         k5c_extra_args);
-+        err = exec_child_ex(state,
-+                            pipefd_to_child, pipefd_from_child,
-+                            KRB5_CHILD, state->kr->krb5_ctx->child_debug_fd,
-+                            k5c_extra_args, STDIN_FILENO, STDOUT_FILENO);
-         if (err != EOK) {
-             DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec KRB5 child: [%d][%s].\n",
-                       err, strerror(err));
-diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
-index b60891d2b41f9a359856eb22174128d7f07559fb..40010989021eb7cf77b96876b2d1c4119ed39163 100644
---- a/src/providers/ldap/sdap_child_helpers.c
-+++ b/src/providers/ldap/sdap_child_helpers.c
-@@ -108,8 +108,7 @@ static errno_t sdap_fork_child(struct tevent_context *ev,
-     if (pid == 0) { /* child */
-         err = exec_child(child,
-                          pipefd_to_child, pipefd_from_child,
--                         LDAP_CHILD, ldap_child_debug_fd,
--                         NULL);
-+                         LDAP_CHILD, ldap_child_debug_fd);
-         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec LDAP child: [%d][%s].\n",
-                                     err, strerror(err));
-         return err;
-diff --git a/src/tests/cmocka/test_child_common.c b/src/tests/cmocka/test_child_common.c
-index 112ed0ad97294bc45eac7c2124155e6b1908ad92..348b3e6c354d724fac12939c8bd785bbb993e667 100644
---- a/src/tests/cmocka/test_child_common.c
-+++ b/src/tests/cmocka/test_child_common.c
-@@ -89,7 +89,7 @@ void test_exec_child(void **state)
-         ret = exec_child(child_tctx,
-                          child_tctx->pipefd_to_child,
-                          child_tctx->pipefd_from_child,
--                         CHILD_DIR"/"TEST_BIN, 2, NULL);
-+                         CHILD_DIR"/"TEST_BIN, 2);
-         assert_int_equal(ret, EOK);
-     } else {
-             do {
-@@ -128,10 +128,11 @@ void test_exec_child_extra_args(void **state)
-     child_pid = fork();
-     assert_int_not_equal(child_pid, -1);
-     if (child_pid == 0) {
--        ret = exec_child(child_tctx,
--                         child_tctx->pipefd_to_child,
--                         child_tctx->pipefd_from_child,
--                         CHILD_DIR"/"TEST_BIN, 2, extra_args);
-+        ret = exec_child_ex(child_tctx,
-+                            child_tctx->pipefd_to_child,
-+                            child_tctx->pipefd_from_child,
-+                            CHILD_DIR"/"TEST_BIN, 2, extra_args,
-+                            STDIN_FILENO, STDOUT_FILENO);
-         assert_int_equal(ret, EOK);
-     } else {
-             do {
-diff --git a/src/util/child_common.c b/src/util/child_common.c
-index 9710630f9773ae02258e4f0dd609a3d74978c8f4..7975a839499370a4a29d9fbc59f815d7da1f63dd 100644
---- a/src/util/child_common.c
-+++ b/src/util/child_common.c
-@@ -729,17 +729,18 @@ fail:
-     return ret;
- }
- 
--errno_t exec_child(TALLOC_CTX *mem_ctx,
--                   int *pipefd_to_child, int *pipefd_from_child,
--                   const char *binary, int debug_fd,
--                   const char *extra_argv[])
-+errno_t exec_child_ex(TALLOC_CTX *mem_ctx,
-+                      int *pipefd_to_child, int *pipefd_from_child,
-+                      const char *binary, int debug_fd,
-+                      const char *extra_argv[],
-+                      int child_in_fd, int child_out_fd)
- {
-     int ret;
-     errno_t err;
-     char **argv;
- 
-     close(pipefd_to_child[1]);
--    ret = dup2(pipefd_to_child[0], STDIN_FILENO);
-+    ret = dup2(pipefd_to_child[0], child_in_fd);
-     if (ret == -1) {
-         err = errno;
-         DEBUG(SSSDBG_CRIT_FAILURE,
-@@ -748,7 +749,7 @@ errno_t exec_child(TALLOC_CTX *mem_ctx,
-     }
- 
-     close(pipefd_from_child[0]);
--    ret = dup2(pipefd_from_child[1], STDOUT_FILENO);
-+    ret = dup2(pipefd_from_child[1], child_out_fd);
-     if (ret == -1) {
-         err = errno;
-         DEBUG(SSSDBG_CRIT_FAILURE,
-@@ -770,6 +771,15 @@ errno_t exec_child(TALLOC_CTX *mem_ctx,
-     return err;
- }
- 
-+errno_t exec_child(TALLOC_CTX *mem_ctx,
-+                   int *pipefd_to_child, int *pipefd_from_child,
-+                   const char *binary, int debug_fd)
-+{
-+    return exec_child_ex(mem_ctx, pipefd_to_child, pipefd_from_child,
-+                         binary, debug_fd, NULL,
-+                         STDIN_FILENO, STDOUT_FILENO);
-+}
-+
- void child_cleanup(int readfd, int writefd)
- {
-     int ret;
-diff --git a/src/util/child_common.h b/src/util/child_common.h
-index e659388ece3677b7746c159d7de3e86171bb4146..369de71a13449beb185e5bc682c8871625fe6027 100644
---- a/src/util/child_common.h
-+++ b/src/util/child_common.h
-@@ -112,10 +112,18 @@ void child_sig_handler(struct tevent_context *ev,
-                        int count, void *__siginfo, void *pvt);
- 
- /* Never returns EOK, ether returns an error, or doesn't return on success */
-+errno_t exec_child_ex(TALLOC_CTX *mem_ctx,
-+                      int *pipefd_to_child, int *pipefd_from_child,
-+                      const char *binary, int debug_fd,
-+                      const char *extra_argv[],
-+                      int child_in_fd, int child_out_fd);
-+
-+/* Same as exec_child_ex() except child_in_fd is set to STDIN_FILENO and
-+ * child_out_fd is set to STDOUT_FILENO and extra_argv is always NULL.
-+ */
- errno_t exec_child(TALLOC_CTX *mem_ctx,
-                    int *pipefd_to_child, int *pipefd_from_child,
--                   const char *binary, int debug_fd,
--                   const char *extra_argv[]);
-+                   const char *binary, int debug_fd);
- 
- void child_cleanup(int readfd, int writefd);
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0155-GPO-Don-t-use-stdout-for-output-in-gpo_child.patch b/SOURCES/0155-GPO-Don-t-use-stdout-for-output-in-gpo_child.patch
deleted file mode 100644
index 7eefa07..0000000
--- a/SOURCES/0155-GPO-Don-t-use-stdout-for-output-in-gpo_child.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From 3ec755f9b2db95fa05cd38ca32a0dddb255014f8 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 7 Jan 2015 10:42:09 +0100
-Subject: [PATCH 155/160] GPO: Don't use stdout for output in gpo_child
-
-Resolves:
-    https://fedorahosted.org/sssd/ticket/2544
-
-Use a dedicated fd instead to work around
-https://bugzilla.samba.org/show_bug.cgi?id=11036
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit f00a61b6079d8de81432077a59daf015d85800d2)
----
- src/providers/ad/ad_gpo.c       | 7 ++++---
- src/providers/ad/ad_gpo.h       | 4 ++++
- src/providers/ad/ad_gpo_child.c | 7 ++++---
- 3 files changed, 12 insertions(+), 6 deletions(-)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 1ae62e7c4727702d5338258046e89e4b654904eb..083fc8c2cde36bb15d1a1becd3ddac383a4008fe 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -3961,9 +3961,10 @@ gpo_fork_child(struct tevent_req *req)
-     pid = fork();
- 
-     if (pid == 0) { /* child */
--        err = exec_child(state,
--                         pipefd_to_child, pipefd_from_child,
--                         GPO_CHILD, gpo_child_debug_fd);
-+        err = exec_child_ex(state,
-+                            pipefd_to_child, pipefd_from_child,
-+                            GPO_CHILD, gpo_child_debug_fd, NULL,
-+                            STDIN_FILENO, AD_GPO_CHILD_OUT_FILENO);
-         DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec gpo_child: [%d][%s].\n",
-               err, strerror(err));
-         return err;
-diff --git a/src/providers/ad/ad_gpo.h b/src/providers/ad/ad_gpo.h
-index 77051aadaed7858cce808b5c6c51f0be515d9800..9fd590a2b262b66c1efd493d8736774bdfa61b40 100644
---- a/src/providers/ad/ad_gpo.h
-+++ b/src/providers/ad/ad_gpo.h
-@@ -23,6 +23,10 @@
- #ifndef AD_GPO_H_
- #define AD_GPO_H_
- 
-+#include "providers/ad/ad_access.h"
-+
-+#define AD_GPO_CHILD_OUT_FILENO 3
-+
- /*
-  * This pair of functions provides client-side GPO processing.
-  *
-diff --git a/src/providers/ad/ad_gpo_child.c b/src/providers/ad/ad_gpo_child.c
-index c6eb52f06b1daadb083bd4c9efb299a12031d4d5..27f0db3ec2504e55886094a35cda1f536a7494ee 100644
---- a/src/providers/ad/ad_gpo_child.c
-+++ b/src/providers/ad/ad_gpo_child.c
-@@ -33,6 +33,7 @@
- #include "util/util.h"
- #include "util/child_common.h"
- #include "providers/dp_backend.h"
-+#include "providers/ad/ad_gpo.h"
- #include "sss_cli.h"
- 
- #define SMB_BUFFER_SIZE 65536
-@@ -778,7 +779,7 @@ main(int argc, const char *argv[])
- 
-     errno = 0;
- 
--    written = sss_atomic_write_s(STDOUT_FILENO, resp->buf, resp->size);
-+    written = sss_atomic_write_s(AD_GPO_CHILD_OUT_FILENO, resp->buf, resp->size);
-     if (written == -1) {
-         ret = errno;
-         DEBUG(SSSDBG_CRIT_FAILURE, "write failed [%d][%s].\n", ret,
-@@ -793,13 +794,13 @@ main(int argc, const char *argv[])
-     }
- 
-     DEBUG(SSSDBG_TRACE_FUNC, "gpo_child completed successfully\n");
--    close(STDOUT_FILENO);
-+    close(AD_GPO_CHILD_OUT_FILENO);
-     talloc_free(main_ctx);
-     return EXIT_SUCCESS;
- 
- fail:
-     DEBUG(SSSDBG_CRIT_FAILURE, "gpo_child failed!\n");
--    close(STDOUT_FILENO);
-+    close(AD_GPO_CHILD_OUT_FILENO);
-     talloc_free(main_ctx);
-     return EXIT_FAILURE;
- }
--- 
-2.1.0
-
diff --git a/SOURCES/0156-GPO-Extract-server-hostname-after-connecting.patch b/SOURCES/0156-GPO-Extract-server-hostname-after-connecting.patch
deleted file mode 100644
index 16bdd8f..0000000
--- a/SOURCES/0156-GPO-Extract-server-hostname-after-connecting.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-From f0af52e320e8f1b062701b2eb36b49915a4e8194 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 6 Jan 2015 13:03:34 +0100
-Subject: [PATCH 156/160] GPO: Extract server hostname after connecting
-
-https://fedorahosted.org/sssd/ticket/2543
-
-The LDAP URI is not valid prior to connecting to LDAP. Moreover,
-reconnecting to a different server might invalidate the URI.
-
-Move reading the URI after the connection has been established.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit ccff8e75940963a0f68f86efcddc37133318abfa)
----
- src/providers/ad/ad_gpo.c | 58 +++++++++++++++++++++++------------------------
- 1 file changed, 29 insertions(+), 29 deletions(-)
-
-diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
-index 083fc8c2cde36bb15d1a1becd3ddac383a4008fe..375ef1d8a7df13911831a55fed5d5a425daaa996 100644
---- a/src/providers/ad/ad_gpo.c
-+++ b/src/providers/ad/ad_gpo.c
-@@ -1489,8 +1489,6 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx,
-     struct tevent_req *req;
-     struct tevent_req *subreq;
-     struct ad_gpo_access_state *state;
--    char *server_uri;
--    LDAPURLDesc *lud;
-     errno_t ret;
-     int hret;
-     hash_key_t key;
-@@ -1580,33 +1578,6 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx,
-         goto immediately;
-     }
- 
--    /* extract server_hostname from server_uri */
--    server_uri = state->conn->service->uri;
--    ret = ldap_url_parse(server_uri, &lud);
--    if (ret != LDAP_SUCCESS) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "Failed to parse ldap URI (%s)!\n", server_uri);
--        ret = EINVAL;
--        goto immediately;
--    }
--
--    if (lud->lud_host == NULL) {
--        DEBUG(SSSDBG_CRIT_FAILURE,
--              "The LDAP URI (%s) did not contain a host name\n", server_uri);
--        ldap_free_urldesc(lud);
--        ret = EINVAL;
--        goto immediately;
--    }
--
--    state->server_hostname = talloc_strdup(state, lud->lud_host);
--    ldap_free_urldesc(lud);
--    if (!state->server_hostname) {
--        ret = ENOMEM;
--        goto immediately;
--    }
--    DEBUG(SSSDBG_TRACE_ALL, "server_hostname from uri: %s\n",
--          state->server_hostname);
--
-     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
-     if (subreq == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE,
-@@ -1666,6 +1637,8 @@ ad_gpo_connect_done(struct tevent_req *subreq)
-     char *domain_dn;
-     int dp_error;
-     errno_t ret;
-+    char *server_uri;
-+    LDAPURLDesc *lud;
- 
-     const char *attrs[] = {AD_AT_DN, AD_AT_UAC, NULL};
- 
-@@ -1702,6 +1675,33 @@ ad_gpo_connect_done(struct tevent_req *subreq)
-         }
-     }
- 
-+    /* extract server_hostname from server_uri */
-+    server_uri = state->conn->service->uri;
-+    ret = ldap_url_parse(server_uri, &lud);
-+    if (ret != LDAP_SUCCESS) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "Failed to parse ldap URI (%s)!\n", server_uri);
-+        ret = EINVAL;
-+        goto done;
-+    }
-+
-+    if (lud->lud_host == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE,
-+              "The LDAP URI (%s) did not contain a host name\n", server_uri);
-+        ldap_free_urldesc(lud);
-+        ret = EINVAL;
-+        goto done;
-+    }
-+
-+    state->server_hostname = talloc_strdup(state, lud->lud_host);
-+    ldap_free_urldesc(lud);
-+    if (!state->server_hostname) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+    DEBUG(SSSDBG_TRACE_ALL, "server_hostname from uri: %s\n",
-+          state->server_hostname);
-+
-     sam_account_name = sss_krb5_get_primary(state, "%S$", state->ad_hostname);
-     if (sam_account_name == NULL) {
-         ret = ENOMEM;
--- 
-2.1.0
-
diff --git a/SOURCES/0157-IPA-add-get_be_acct_req_for_user_name.patch b/SOURCES/0157-IPA-add-get_be_acct_req_for_user_name.patch
deleted file mode 100644
index a76ed19..0000000
--- a/SOURCES/0157-IPA-add-get_be_acct_req_for_user_name.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From 6c8052a571a74ab67d371a624e561ecdc50744af Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 10 Dec 2014 15:02:15 +0100
-Subject: [PATCH 157/160] IPA: add get_be_acct_req_for_user_name()
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit d32b165fad7b89462f49c82349e1df5a2343afa2)
----
- src/providers/ipa/ipa_id.h    |  5 +++++
- src/providers/ipa/ipa_views.c | 13 +++++++++++++
- 2 files changed, 18 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
-index 9d219f281847df0ba4ac24061e598eb6915f9c38..2bb5e0d38f42d4bbb04854dfb04804fecf6257e8 100644
---- a/src/providers/ipa/ipa_id.h
-+++ b/src/providers/ipa/ipa_id.h
-@@ -87,6 +87,11 @@ errno_t get_be_acct_req_for_uuid(TALLOC_CTX *mem_ctx, const char *uuid,
-                                  const char *domain_name,
-                                  struct be_acct_req **_ar);
- 
-+errno_t get_be_acct_req_for_user_name(TALLOC_CTX *mem_ctx,
-+                                      const char *user_name,
-+                                      const char *domain_name,
-+                                      struct be_acct_req **_ar);
-+
- struct tevent_req *ipa_get_ad_override_send(TALLOC_CTX *mem_ctx,
-                                             struct tevent_context *ev,
-                                             struct sdap_id_ctx *sdap_id_ctx,
-diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
-index c768186d7cf5e5a997e2ca27a167b62c8dc99b3f..ccaea69563728a5cecc202709da5dab51747c040 100644
---- a/src/providers/ipa/ipa_views.c
-+++ b/src/providers/ipa/ipa_views.c
-@@ -177,6 +177,10 @@ static errno_t get_be_acct_req_for_xyz(TALLOC_CTX *mem_ctx, const char *val,
-         ar->entry_type = BE_REQ_BY_UUID;
-         ar->filter_type = BE_FILTER_UUID;
-         break;
-+    case BE_REQ_USER:
-+        ar->entry_type = BE_REQ_USER;
-+        ar->filter_type = BE_FILTER_NAME;
-+        break;
-     default:
-         DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type [%d].\n", type);
-         talloc_free(ar);
-@@ -213,6 +217,15 @@ errno_t get_be_acct_req_for_uuid(TALLOC_CTX *mem_ctx, const char *uuid,
-                                    _ar);
- }
- 
-+errno_t get_be_acct_req_for_user_name(TALLOC_CTX *mem_ctx,
-+                                      const char *user_name,
-+                                      const char *domain_name,
-+                                      struct be_acct_req **_ar)
-+{
-+    return get_be_acct_req_for_xyz(mem_ctx, user_name, domain_name, BE_REQ_USER,
-+                                   _ar);
-+}
-+
- struct ipa_get_ad_override_state {
-     struct tevent_context *ev;
-     struct sdap_id_ctx *sdap_id_ctx;
--- 
-2.1.0
-
diff --git a/SOURCES/0158-IPA-resolve-ghost-members-if-a-non-default-view-is-a.patch b/SOURCES/0158-IPA-resolve-ghost-members-if-a-non-default-view-is-a.patch
deleted file mode 100644
index 2ef66f7..0000000
--- a/SOURCES/0158-IPA-resolve-ghost-members-if-a-non-default-view-is-a.patch
+++ /dev/null
@@ -1,288 +0,0 @@
-From f20163d0e2076cbdfe48975a8ad38d471d8c5386 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 10 Dec 2014 15:03:18 +0100
-Subject: [PATCH 158/160] IPA: resolve ghost members if a non-default view is
- applied
-
-Related to https://fedorahosted.org/sssd/ticket/2481
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 765d9075bb1e10ae0f09b6c2701bfd50aeb423d4)
----
- src/providers/ipa/ipa_id.c            | 212 ++++++++++++++++++++++++++++++++++
- src/providers/ipa/ipa_subdomains_id.c |   1 +
- 2 files changed, 213 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
-index 5665a1835e8b0ab18325bfc68a8d8b5650730943..4df6ed0e8ee1e9886151703f424b4580db8799a4 100644
---- a/src/providers/ipa/ipa_id.c
-+++ b/src/providers/ipa/ipa_id.c
-@@ -144,6 +144,150 @@ static void ipa_account_info_done(struct tevent_req *req)
-     sdap_handler_done(breq, dp_error, ret, error_text);
- }
- 
-+struct ipa_resolve_user_list_state {
-+    struct tevent_context *ev;
-+    struct sdap_id_ctx *sdap_id_ctx;
-+    struct be_req *be_req;
-+    struct ldb_message_element *users;
-+    const char *domain_name;
-+    size_t user_idx;
-+
-+    int dp_error;
-+};
-+
-+static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req);
-+static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq);
-+
-+static struct tevent_req *
-+ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-+                           struct be_req *be_req,
-+                           struct sdap_id_ctx *sdap_id_ctx,
-+                           const char *domain_name,
-+                           struct ldb_message_element *users)
-+{
-+    int ret;
-+    struct tevent_req *req;
-+    struct ipa_resolve_user_list_state *state;
-+
-+    req = tevent_req_create(memctx, &state,
-+                            struct ipa_resolve_user_list_state);
-+    if (req == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
-+        return NULL;
-+    }
-+
-+    state->ev = ev;
-+    state->sdap_id_ctx = sdap_id_ctx;
-+    state->be_req = be_req;
-+    state->domain_name = domain_name;
-+    state->users = users;
-+    state->user_idx = 0;
-+    state->dp_error = DP_ERR_FATAL;
-+
-+    ret = ipa_resolve_user_list_get_user_step(req);
-+    if (ret == EAGAIN) {
-+        return req;
-+    } else if (ret == EOK) {
-+        state->dp_error = DP_ERR_OK;
-+        tevent_req_done(req);
-+    } else {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "ipa_resolve_user_list_get_user_step failed.\n");
-+        tevent_req_error(req, ret);
-+    }
-+    tevent_req_post(req, ev);
-+    return req;
-+}
-+
-+static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req)
-+{
-+    int ret;
-+    struct tevent_req *subreq;
-+    struct be_acct_req *ar;
-+    struct ipa_resolve_user_list_state *state = tevent_req_data(req,
-+                                            struct ipa_resolve_user_list_state);
-+
-+    if (state->user_idx >= state->users->num_values) {
-+        return EOK;
-+    }
-+
-+    ret = get_be_acct_req_for_user_name(state,
-+                            (char *) state->users->values[state->user_idx].data,
-+                            state->domain_name, &ar);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_user_name failed.\n");
-+        return ret;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_ALL, "Trying to resolve user [%s].\n", ar->filter_value);
-+
-+    subreq = sdap_handle_acct_req_send(state, state->be_req, ar,
-+                                       state->sdap_id_ctx,
-+                                       state->sdap_id_ctx->opts->sdom,
-+                                       state->sdap_id_ctx->conn, true);
-+    if (subreq == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    tevent_req_set_callback(subreq, ipa_resolve_user_list_get_user_done, req);
-+
-+    return EAGAIN;
-+}
-+
-+static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_resolve_user_list_state *state = tevent_req_data(req,
-+                                            struct ipa_resolve_user_list_state);
-+    int ret;
-+
-+    ret = sdap_handle_acct_req_recv(subreq, &state->dp_error, NULL, NULL);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
-+        goto done;
-+    }
-+
-+    state->user_idx++;
-+
-+    ret = ipa_resolve_user_list_get_user_step(req);
-+    if (ret == EAGAIN) {
-+        return;
-+    }
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "ipa_resolve_user_list_get_user_step failed.\n");
-+    }
-+
-+done:
-+    if (ret == EOK) {
-+        state->dp_error = DP_ERR_OK;
-+        tevent_req_done(req);
-+    } else {
-+        if (state->dp_error == DP_ERR_OK) {
-+            state->dp_error = DP_ERR_FATAL;
-+        }
-+        tevent_req_error(req, ret);
-+    }
-+    return;
-+}
-+
-+static int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error)
-+{
-+    struct ipa_resolve_user_list_state *state = tevent_req_data(req,
-+                                            struct ipa_resolve_user_list_state);
-+
-+    if (dp_error) {
-+        *dp_error = state->dp_error;
-+    }
-+
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+
-+    return EOK;
-+}
-+
- struct ipa_id_get_account_info_state {
-     struct tevent_context *ev;
-     struct ipa_id_ctx *ipa_ctx;
-@@ -157,6 +301,7 @@ struct ipa_id_get_account_info_state {
- 
-     struct sysdb_attrs *override_attrs;
-     struct ldb_message *obj_msg;
-+    struct ldb_message_element *ghosts;
-     int dp_error;
- };
- 
-@@ -166,6 +311,7 @@ static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req,
-                                                         struct be_acct_req *ar);
- static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq);
- static void ipa_id_get_account_info_done(struct tevent_req *subreq);
-+static void ipa_id_get_user_list_done(struct tevent_req *subreq);
- 
- static struct tevent_req *
- ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-@@ -405,6 +551,16 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
-         goto fail;
-     }
- 
-+    if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_GROUP
-+            && state->ipa_ctx->view_name != NULL
-+            && strcmp(state->ipa_ctx->view_name,
-+                      SYSDB_DEFAULT_VIEW_NAME) != 0) {
-+        /* check for ghost members because ghost members are not allowed if a
-+         * view other than the default view is applied.*/
-+
-+        state->ghosts = ldb_msg_find_element(state->obj_msg, SYSDB_GHOST);
-+    }
-+
-     if (state->override_attrs == NULL) {
-         uuid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_UUID, NULL);
-         if (uuid == NULL) {
-@@ -457,6 +613,21 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
-         }
-     }
- 
-+    if (state->ghosts != NULL) {
-+        /* Resolve ghost members */
-+        subreq = ipa_resolve_user_list_send(state, state->ev, state->be_req,
-+                                            state->ipa_ctx->sdap_id_ctx,
-+                                            state->domain->name,
-+                                            state->ghosts);
-+        if (subreq == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
-+            ret = ENOMEM;
-+            goto fail;
-+        }
-+        tevent_req_set_callback(subreq, ipa_id_get_user_list_done, req);
-+        return;
-+    }
-+
-     state->dp_error = DP_ERR_OK;
-     tevent_req_done(req);
-     return;
-@@ -508,6 +679,47 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq)
-         goto fail;
-     }
- 
-+    if (state->ghosts != NULL) {
-+        /* Resolve ghost members */
-+        subreq = ipa_resolve_user_list_send(state, state->ev, state->be_req,
-+                                            state->ipa_ctx->sdap_id_ctx,
-+                                            state->domain->name,
-+                                            state->ghosts);
-+        if (subreq == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
-+            ret = ENOMEM;
-+            goto fail;
-+        }
-+        tevent_req_set_callback(subreq, ipa_id_get_user_list_done, req);
-+        return;
-+    }
-+
-+    state->dp_error = DP_ERR_OK;
-+    tevent_req_done(req);
-+    return;
-+
-+fail:
-+    state->dp_error = dp_error;
-+    tevent_req_error(req, ret);
-+    return;
-+}
-+
-+static void ipa_id_get_user_list_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+    int dp_error = DP_ERR_FATAL;
-+    int ret;
-+
-+    ret = ipa_resolve_user_list_recv(subreq, &dp_error);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user list %d\n", ret);
-+        goto fail;
-+    }
-+
-     state->dp_error = DP_ERR_OK;
-     tevent_req_done(req);
-     return;
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index ce5a6d1a1048eda4d8b7017bd92bc7ee76e66ef9..cf0cddf6884295268b30fc8e0209b543c1699297 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -862,6 +862,7 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
-                             SYSDB_SID_STR,
-                             SYSDB_OBJECTCLASS,
-                             SYSDB_UUID,
-+                            SYSDB_GHOST,
-                             NULL };
-     char *name;
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0159-sysdb-fix-group-members-with-overridden-names.patch b/SOURCES/0159-sysdb-fix-group-members-with-overridden-names.patch
deleted file mode 100644
index 1e1b376..0000000
--- a/SOURCES/0159-sysdb-fix-group-members-with-overridden-names.patch
+++ /dev/null
@@ -1,144 +0,0 @@
-From 092b3c062c3568d1a01766d71a25004ee3cfc64e Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 12 Jan 2015 18:36:42 +0100
-Subject: [PATCH 159/160] sysdb: fix group members with overridden names
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit fbcdc08722aa8ed17c4b114e01fbb37c02cfb2fe)
----
- src/db/sysdb.h       |  1 +
- src/db/sysdb_views.c | 73 ++++++++++++++++++++++++++++++++++++++++++++--------
- 2 files changed, 63 insertions(+), 11 deletions(-)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index b1e057107cc6e3d4ce7b7bb8e821a2414c3424a7..9e33fee37a352498ed0c987dc2ae0da3500d63d5 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -210,6 +210,7 @@
- 
- #define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \
-                            SYSDB_MEMBERUID, \
-+                           SYSDB_MEMBER, \
-                            SYSDB_GHOST, \
-                            SYSDB_DEFAULT_ATTRS, \
-                            SYSDB_SID_STR, \
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index c735a7bd8588a80743d40438d010db5912f47bb5..717edf20a447003568060cf4d32bf8d47bd93e63 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -1268,6 +1268,10 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
-     const char *override_dn_str;
-     struct ldb_dn *override_dn;
-     const char *memberuid;
-+    const char *orig_name;
-+    char *orig_domain;
-+    char *val;
-+    struct sss_domain_info *orig_dom;
- 
-     members = ldb_msg_find_element(obj, SYSDB_MEMBER);
-     if (members == NULL || members->num_values == 0) {
-@@ -1306,6 +1310,12 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
-             goto done;
-         }
- 
-+        if (ldb_msg_find_attr_as_uint64(member_obj->msgs[0],
-+                                        SYSDB_UIDNUM, 0) == 0) {
-+            /* Skip non-POSIX-user members i.e. groups and non-POSIX users */
-+            continue;
-+        }
-+
-         override_dn_str = ldb_msg_find_attr_as_string(member_obj->msgs[0],
-                                                       SYSDB_OVERRIDE_DN, NULL);
-         if (override_dn_str == NULL) {
-@@ -1324,6 +1334,16 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
-             goto done;
-         }
- 
-+        orig_name = ldb_msg_find_attr_as_string(member_obj->msgs[0],
-+                                                SYSDB_NAME,
-+                                                NULL);
-+        if (orig_name == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Object [%s] has no name.\n",
-+                  ldb_dn_get_linearized(member_obj->msgs[0]->dn));
-+            ret = EINVAL;
-+            goto done;
-+        }
-+
-         memberuid = NULL;
-         if (ldb_dn_compare(member_obj->msgs[0]->dn, override_dn) != 0) {
-             DEBUG(SSSDBG_TRACE_ALL, "Checking override for object [%s].\n",
-@@ -1347,29 +1367,60 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain,
-             memberuid = ldb_msg_find_attr_as_string(override_obj->msgs[0],
-                                                     SYSDB_NAME,
-                                                     NULL);
-+
-+            if (memberuid != NULL) {
-+                ret = sss_parse_name(tmp_ctx, domain->names, orig_name,
-+                                     &orig_domain, NULL);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                         "sss_parse_name failed to split original name [%s].\n",
-+                         orig_name);
-+                    goto done;
-+                }
-+
-+                if (orig_domain != NULL) {
-+                    orig_dom = find_domain_by_name(get_domains_head(domain),
-+                                                   orig_domain, true);
-+                    if (orig_dom == NULL) {
-+                        DEBUG(SSSDBG_CRIT_FAILURE,
-+                              "Cannot find domain with name [%s].\n",
-+                              orig_domain);
-+                        ret = EINVAL;
-+                        goto done;
-+                    }
-+                    memberuid = sss_get_domain_name(tmp_ctx, memberuid,
-+                                                    orig_dom);
-+                    if (memberuid == NULL) {
-+                        DEBUG(SSSDBG_OP_FAILURE,
-+                              "sss_get_domain_name failed.\n");
-+                        ret = ENOMEM;
-+                        goto done;
-+                    }
-+                }
-+            }
-         }
- 
-         if (memberuid == NULL) {
-             DEBUG(SSSDBG_TRACE_ALL, "No override name available.\n");
- 
--            memberuid = ldb_msg_find_attr_as_string(member_obj->msgs[0],
--                                                    SYSDB_NAME,
--                                                    NULL);
--            if (memberuid == NULL) {
--                DEBUG(SSSDBG_CRIT_FAILURE, "Object [%s] has no name.\n",
--                      ldb_dn_get_linearized(member_obj->msgs[0]->dn));
--                ret = EINVAL;
--                goto done;
--            }
-+            memberuid = orig_name;
-         }
- 
--        ret = ldb_msg_add_string(obj, OVERRIDE_PREFIX SYSDB_MEMBERUID,
--                                 memberuid);
-+        val = talloc_strdup(obj, memberuid);
-+        if (val == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+
-+        ret = ldb_msg_add_string(obj, OVERRIDE_PREFIX SYSDB_MEMBERUID, val);
-         if (ret != LDB_SUCCESS) {
-             DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
-             ret = sysdb_error_to_errno(ret);
-             goto done;
-         }
-+        DEBUG(SSSDBG_TRACE_ALL, "Added [%s] to [%s].\n", memberuid,
-+                                OVERRIDE_PREFIX SYSDB_MEMBERUID);
- 
-         /* Free all temporary data of the current member to avoid memory usage
-          * spikes. All temporary data should be allocated below member_dn. */
--- 
-2.1.0
-
diff --git a/SOURCES/0160-IPA-ipa_resolve_user_list_send-take-care-of-override.patch b/SOURCES/0160-IPA-ipa_resolve_user_list_send-take-care-of-override.patch
deleted file mode 100644
index d025570..0000000
--- a/SOURCES/0160-IPA-ipa_resolve_user_list_send-take-care-of-override.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-From a74c81b88afe4fe592527cc137504cb3d78d4660 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 13 Jan 2015 11:03:37 +0100
-Subject: [PATCH 160/160] IPA: ipa_resolve_user_list_send() take care of
- overrides
-
-Currently ipa_resolve_user_list_send() only looks up the related user
-objects but do not check for overrides. This patch tries to fix this.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit eab17959df71341073f946c533f59fc5e593b35c)
----
- src/providers/ipa/ipa_id.c | 18 ++++++++----------
- 1 file changed, 8 insertions(+), 10 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
-index 4df6ed0e8ee1e9886151703f424b4580db8799a4..3d6861eeb562683518d425616b0e5c413cddba0b 100644
---- a/src/providers/ipa/ipa_id.c
-+++ b/src/providers/ipa/ipa_id.c
-@@ -146,7 +146,7 @@ static void ipa_account_info_done(struct tevent_req *req)
- 
- struct ipa_resolve_user_list_state {
-     struct tevent_context *ev;
--    struct sdap_id_ctx *sdap_id_ctx;
-+    struct ipa_id_ctx *ipa_ctx;
-     struct be_req *be_req;
-     struct ldb_message_element *users;
-     const char *domain_name;
-@@ -161,7 +161,7 @@ static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq);
- static struct tevent_req *
- ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-                            struct be_req *be_req,
--                           struct sdap_id_ctx *sdap_id_ctx,
-+                           struct ipa_id_ctx *ipa_ctx,
-                            const char *domain_name,
-                            struct ldb_message_element *users)
- {
-@@ -177,7 +177,7 @@ ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
-     }
- 
-     state->ev = ev;
--    state->sdap_id_ctx = sdap_id_ctx;
-+    state->ipa_ctx = ipa_ctx;
-     state->be_req = be_req;
-     state->domain_name = domain_name;
-     state->users = users;
-@@ -221,10 +221,8 @@ static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req)
- 
-     DEBUG(SSSDBG_TRACE_ALL, "Trying to resolve user [%s].\n", ar->filter_value);
- 
--    subreq = sdap_handle_acct_req_send(state, state->be_req, ar,
--                                       state->sdap_id_ctx,
--                                       state->sdap_id_ctx->opts->sdom,
--                                       state->sdap_id_ctx->conn, true);
-+    subreq = ipa_id_get_account_info_send(state, state->ev, state->ipa_ctx,
-+                                          state->be_req, ar);
-     if (subreq == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n");
-         return ENOMEM;
-@@ -243,7 +241,7 @@ static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq)
-                                             struct ipa_resolve_user_list_state);
-     int ret;
- 
--    ret = sdap_handle_acct_req_recv(subreq, &state->dp_error, NULL, NULL);
-+    ret = ipa_id_get_account_info_recv(subreq, &state->dp_error);
-     talloc_zfree(subreq);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
-@@ -616,7 +614,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
-     if (state->ghosts != NULL) {
-         /* Resolve ghost members */
-         subreq = ipa_resolve_user_list_send(state, state->ev, state->be_req,
--                                            state->ipa_ctx->sdap_id_ctx,
-+                                            state->ipa_ctx,
-                                             state->domain->name,
-                                             state->ghosts);
-         if (subreq == NULL) {
-@@ -682,7 +680,7 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq)
-     if (state->ghosts != NULL) {
-         /* Resolve ghost members */
-         subreq = ipa_resolve_user_list_send(state, state->ev, state->be_req,
--                                            state->ipa_ctx->sdap_id_ctx,
-+                                            state->ipa_ctx,
-                                             state->domain->name,
-                                             state->ghosts);
-         if (subreq == NULL) {
--- 
-2.1.0
-
diff --git a/SOURCES/0161-IPA-do-not-look-up-overrides-on-client-with-default-.patch b/SOURCES/0161-IPA-do-not-look-up-overrides-on-client-with-default-.patch
deleted file mode 100644
index bd6c53b..0000000
--- a/SOURCES/0161-IPA-do-not-look-up-overrides-on-client-with-default-.patch
+++ /dev/null
@@ -1,154 +0,0 @@
-From 7d4d2a29a210964024f971708e82c441034d49a7 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 4 Dec 2014 13:26:32 +0100
-Subject: [PATCH 161/167] IPA: do not look up overrides on client with default
- view
-
-The IPA extdom plugin returns the data with the default view already
-applied hence it is on needed to look up the override data if the client
-has the default view assigned.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit d8ceb194023a2cdc8bc183acc322e9a7fb6fe2b1)
----
- src/providers/ipa/ipa_s2n_exop.c | 63 +++++++++++++++++++++++++++++++---------
- 1 file changed, 49 insertions(+), 14 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 55450c7029391a99bfc33b8446765f71c4d0928a..1d9a79a383e47fcdd37f30a24327ae76facea5b9 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -888,11 +888,13 @@ struct ipa_s2n_get_groups_state {
-     int exop_timeout;
-     struct resp_attrs *attrs;
-     struct sss_domain_info *obj_domain;
-+    struct sysdb_attrs *override_attrs;
- };
- 
- static errno_t ipa_s2n_get_groups_step(struct tevent_req *req);
- static void ipa_s2n_get_groups_get_override_done(struct tevent_req *subreq);
- static void ipa_s2n_get_groups_next(struct tevent_req *subreq);
-+static errno_t ipa_s2n_get_groups_save_step(struct tevent_req *req);
- 
- static struct tevent_req *ipa_s2n_get_groups_send(TALLOC_CTX *mem_ctx,
-                                                   struct tevent_context *ev,
-@@ -921,6 +923,7 @@ static struct tevent_req *ipa_s2n_get_groups_send(TALLOC_CTX *mem_ctx,
-     state->req_input.inp.name = NULL;
-     state->exop_timeout = exop_timeout;
-     state->attrs = NULL;
-+    state->override_attrs = NULL;
- 
-     ret = ipa_s2n_get_groups_step(req);
-     if (ret != EOK) {
-@@ -1018,6 +1021,18 @@ static void ipa_s2n_get_groups_next(struct tevent_req *subreq)
-         goto fail;
-     }
- 
-+    if (strcmp(state->ipa_ctx->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
-+        ret = ipa_s2n_get_groups_save_step(req);
-+        if (ret == EOK) {
-+            tevent_req_done(req);
-+        } else if (ret != EAGAIN) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_groups_save_step failed.\n");
-+            goto fail;
-+        }
-+
-+        return;
-+    }
-+
-     ret = sysdb_attrs_get_string(state->attrs->sysdb_attrs, SYSDB_SID_STR,
-                                  &sid_str);
-     if (ret != EOK) {
-@@ -1059,39 +1074,55 @@ static void ipa_s2n_get_groups_get_override_done(struct tevent_req *subreq)
-                                                       struct tevent_req);
-     struct ipa_s2n_get_groups_state *state = tevent_req_data(req,
-                                                struct ipa_s2n_get_groups_state);
--    struct sysdb_attrs *override_attrs = NULL;
- 
--    ret = ipa_get_ad_override_recv(subreq, NULL, state, &override_attrs);
-+    ret = ipa_get_ad_override_recv(subreq, NULL, state, &state->override_attrs);
-     talloc_zfree(subreq);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
-         goto fail;
-     }
- 
-+    ret = ipa_s2n_get_groups_save_step(req);
-+    if (ret == EOK) {
-+        tevent_req_done(req);
-+    } else if (ret != EAGAIN) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_groups_save_step failed.\n");
-+        goto fail;
-+    }
-+
-+    return;
-+
-+fail:
-+    tevent_req_error(req,ret);
-+    return;
-+}
-+
-+static errno_t ipa_s2n_get_groups_save_step(struct tevent_req *req)
-+{
-+    int ret;
-+    struct ipa_s2n_get_groups_state *state = tevent_req_data(req,
-+                                               struct ipa_s2n_get_groups_state);
-+
-     ret = ipa_s2n_save_objects(state->dom, &state->req_input, state->attrs,
--                               NULL, state->ipa_ctx->view_name, override_attrs);
-+                               NULL, state->ipa_ctx->view_name,
-+                               state->override_attrs);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
--        goto fail;
-+        return ret;
-     }
- 
-     state->group_idx++;
-     if (state->group_list[state->group_idx] == NULL) {
--        tevent_req_done(req);
--        return;
-+        return EOK;
-     }
- 
-     ret = ipa_s2n_get_groups_step(req);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_groups_step failed.\n");
--        goto fail;
-+        return ret;
-     }
- 
--    return;
--
--fail:
--    tevent_req_error(req,ret);
--    return;
-+    return EAGAIN;
- }
- 
- static int ipa_s2n_get_groups_recv(struct tevent_req *req)
-@@ -1484,7 +1515,9 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
-         ret = ENOENT;
-     }
- 
--    if (ret == ENOENT) {
-+    if (ret == ENOENT
-+            || strcmp(state->ipa_ctx->view_name,
-+                      SYSDB_DEFAULT_VIEW_NAME) == 0) {
-         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
-                                    state->simple_attrs, NULL, NULL);
-         if (ret != EOK) {
-@@ -2046,7 +2079,9 @@ static void ipa_s2n_get_groups_done(struct tevent_req  *subreq)
-         goto fail;
-     }
- 
--    if (state->override_attrs == NULL) {
-+    if (state->override_attrs == NULL
-+            && strcmp(state->ipa_ctx->view_name,
-+                      SYSDB_DEFAULT_VIEW_NAME) != 0) {
-         subreq = ipa_get_ad_override_send(state, state->ev,
-                            state->ipa_ctx->sdap_id_ctx,
-                            state->ipa_ctx->ipa_options,
--- 
-2.1.0
-
diff --git a/SOURCES/0162-IPA-make-version-check-more-precise.patch b/SOURCES/0162-IPA-make-version-check-more-precise.patch
deleted file mode 100644
index 11be584..0000000
--- a/SOURCES/0162-IPA-make-version-check-more-precise.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 8eb022f5a34e86b091c62fb0c9b30834021f1e23 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 5 Dec 2014 11:03:48 +0100
-Subject: [PATCH 162/167] IPA: make version check more precise
-
-The call protected by the check does not only expect the version 1 of
-the extdom plugin is used but a specific response type as well. Since
-version 1 can return older response types as well we want to be on the
-safe side.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 2fc12875f7d51248799016c19c1298b85e06a286)
----
- src/providers/ipa/ipa_s2n_exop.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 1d9a79a383e47fcdd37f30a24327ae76facea5b9..b02387a827b7da27d944db8f7fa326f153e12715 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -759,7 +759,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
-             attrs->a.user.pw_uid = uid;
-             attrs->a.user.pw_gid = gid;
- 
--            if (is_v1) {
-+            if (is_v1 && type == RESP_USER_GROUPLIST) {
-                 ret = add_v1_user_data(ber, attrs);
-                 if (ret != EOK) {
-                     DEBUG(SSSDBG_OP_FAILURE, "add_v1_user_data failed.\n");
-@@ -798,7 +798,7 @@ static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
- 
-             attrs->a.group.gr_gid = gid;
- 
--            if (is_v1) {
-+            if (is_v1 && type == RESP_GROUP_MEMBERS) {
-                 ret = add_v1_group_data(ber, attrs);
-                 if (ret != EOK) {
-                     DEBUG(SSSDBG_OP_FAILURE, "add_v1_group_data failed.\n");
--- 
-2.1.0
-
diff --git a/SOURCES/0163-IPA-add-missing-break.patch b/SOURCES/0163-IPA-add-missing-break.patch
deleted file mode 100644
index 0be9ae7..0000000
--- a/SOURCES/0163-IPA-add-missing-break.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 24a53fe7f04c3d230b090efd76bc43692d4e2d78 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 5 Dec 2014 11:06:26 +0100
-Subject: [PATCH 163/167] IPA: add missing break
-
-The current request already returned the SID, we do not need to request
-it separately.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit e6046d23b3e90102fb3c796737ced03fb5a60fea)
----
- src/providers/ipa/ipa_s2n_exop.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index b02387a827b7da27d944db8f7fa326f153e12715..68f4cb7d8ff778342c5280652f0a62753c7c7b2c 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1451,6 +1451,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
- 
-                 return;
-             }
-+            break;
-         }
- 
-         if (state->req_input->type == REQ_INP_SECID
--- 
-2.1.0
-
diff --git a/SOURCES/0164-IPA-process_members-optionally-return-missing-member.patch b/SOURCES/0164-IPA-process_members-optionally-return-missing-member.patch
deleted file mode 100644
index c121189..0000000
--- a/SOURCES/0164-IPA-process_members-optionally-return-missing-member.patch
+++ /dev/null
@@ -1,154 +0,0 @@
-From c74de0bbed7729b44567ca1cf364ddca94a2acbf Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 5 Dec 2014 11:11:49 +0100
-Subject: [PATCH 164/167] IPA: process_members() optionally return missing
- members list
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 942ebb62c8df766a22271103abd518ddae02ea3a)
----
- src/providers/ipa/ipa_s2n_exop.c | 85 +++++++++++++++++++++++++++++++---------
- 1 file changed, 67 insertions(+), 18 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 68f4cb7d8ff778342c5280652f0a62753c7c7b2c..bc476b469d02ea5f80d7e792693f5d25db889b74 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1222,7 +1222,8 @@ fail:
- 
- static errno_t process_members(struct sss_domain_info *domain,
-                                struct sysdb_attrs *group_attrs,
--                               char **members)
-+                               char **members,
-+                               TALLOC_CTX *mem_ctx, char ***_missing_members)
- {
-     int ret;
-     size_t c;
-@@ -1231,9 +1232,12 @@ static errno_t process_members(struct sss_domain_info *domain,
-     const char *dn_str;
-     struct sss_domain_info *obj_domain;
-     struct sss_domain_info *parent_domain;
-+    char **missing_members = NULL;
-+    size_t miss_count = 0;
- 
-     if (members == NULL) {
-         DEBUG(SSSDBG_TRACE_INTERNAL, "No members\n");
-+        *_missing_members = NULL;
-         return EOK;
-     }
- 
-@@ -1243,6 +1247,17 @@ static errno_t process_members(struct sss_domain_info *domain,
-         return ENOMEM;
-     }
- 
-+    if (_missing_members != NULL && mem_ctx != NULL) {
-+        /* count members */
-+        for (c = 0; members[c] != NULL; c++);
-+        missing_members = talloc_zero_array(tmp_ctx, char *, c + 1);
-+        if (missing_members == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "talloc_array_zero failed.\n");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+    }
-+
-     parent_domain = get_domains_head(domain);
- 
-     for (c = 0; members[c] != NULL; c++) {
-@@ -1256,27 +1271,46 @@ static errno_t process_members(struct sss_domain_info *domain,
-         ret = sysdb_search_user_by_name(tmp_ctx, obj_domain, members[c], NULL,
-                                         &msg);
-         if (ret == EOK) {
--            dn_str = ldb_dn_get_linearized(msg->dn);
--            if (dn_str == NULL) {
--                DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_get_linearized failed.\n");
--                goto done;
--            }
-+            if (group_attrs != NULL) {
-+                dn_str = ldb_dn_get_linearized(msg->dn);
-+                if (dn_str == NULL) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_get_linearized failed.\n");
-+                    goto done;
-+                }
- 
--            DEBUG(SSSDBG_TRACE_ALL, "Adding member [%s][%s]\n",
--                                    members[c], dn_str);
-+                DEBUG(SSSDBG_TRACE_ALL, "Adding member [%s][%s]\n",
-+                                        members[c], dn_str);
- 
--            ret = sysdb_attrs_add_string(group_attrs, SYSDB_MEMBER, dn_str);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
--                goto done;
-+                ret = sysdb_attrs_add_string(group_attrs, SYSDB_MEMBER, dn_str);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_attrs_add_string failed.\n");
-+                    goto done;
-+                }
-             }
-         } else if (ret == ENOENT) {
--            DEBUG(SSSDBG_TRACE_ALL, "Adding ghost member [%s]\n", members[c]);
-+            if (group_attrs != NULL) {
-+                DEBUG(SSSDBG_TRACE_ALL, "Adding ghost member [%s]\n",
-+                                        members[c]);
- 
--            ret = sysdb_attrs_add_string(group_attrs, SYSDB_GHOST, members[c]);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
--                goto done;
-+                ret = sysdb_attrs_add_string(group_attrs, SYSDB_GHOST,
-+                                             members[c]);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_attrs_add_string failed.\n");
-+                    goto done;
-+                }
-+            }
-+
-+            if (missing_members != NULL) {
-+                missing_members[miss_count] = talloc_strdup(missing_members,
-+                                                            members[c]);
-+                if (missing_members[miss_count] == NULL) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+                    ret = ENOMEM;
-+                    goto done;
-+                }
-+                miss_count++;
-             }
-         } else {
-             DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_name failed.\n");
-@@ -1284,6 +1318,21 @@ static errno_t process_members(struct sss_domain_info *domain,
-         }
-     }
- 
-+    if (_missing_members != NULL)  {
-+        if (miss_count == 0) {
-+            *_missing_members = NULL;
-+        } else {
-+            if (mem_ctx != NULL) {
-+                *_missing_members = talloc_steal(mem_ctx, missing_members);
-+            } else {
-+                DEBUG(SSSDBG_CRIT_FAILURE,
-+                      "Missing memory context for missing members list.\n");
-+                ret = EINVAL;
-+                goto done;
-+            }
-+        }
-+    }
-+
-     ret = EOK;
- done:
-     talloc_free(tmp_ctx);
-@@ -1986,7 +2035,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-             }
- 
-             ret = process_members(dom, attrs->sysdb_attrs,
--                                  attrs->a.group.gr_mem);
-+                                  attrs->a.group.gr_mem, NULL, NULL);
-             if (ret != EOK) {
-                 DEBUG(SSSDBG_OP_FAILURE, "process_members failed.\n");
-                 goto done;
--- 
-2.1.0
-
diff --git a/SOURCES/0165-IPA-rename-ipa_s2n_get_groups_send-to-ipa_s2n_get_fq.patch b/SOURCES/0165-IPA-rename-ipa_s2n_get_groups_send-to-ipa_s2n_get_fq.patch
deleted file mode 100644
index c0ac0e6..0000000
--- a/SOURCES/0165-IPA-rename-ipa_s2n_get_groups_send-to-ipa_s2n_get_fq.patch
+++ /dev/null
@@ -1,304 +0,0 @@
-From a1f99b4609c29bf92ad717f7f21a62582fe24e1f Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 9 Dec 2014 17:04:30 +0100
-Subject: [PATCH 165/167] IPA: rename ipa_s2n_get_groups_send() to
- ipa_s2n_get_fqlist_send()
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit f1f22df95996390f63266ebacb624e521d934592)
----
- src/providers/ipa/ipa_s2n_exop.c | 100 +++++++++++++++++++--------------------
- 1 file changed, 50 insertions(+), 50 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index bc476b469d02ea5f80d7e792693f5d25db889b74..505c2325f2a74e26816bb59ad3c7d4810cc64dbf 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -877,38 +877,38 @@ done:
-     return ret;
- }
- 
--struct ipa_s2n_get_groups_state {
-+struct ipa_s2n_get_fqlist_state {
-     struct tevent_context *ev;
-     struct ipa_id_ctx *ipa_ctx;
-     struct sss_domain_info *dom;
-     struct sdap_handle *sh;
-     struct req_input req_input;
--    char **group_list;
--    size_t group_idx;
-+    char **fqname_list;
-+    size_t fqname_idx;
-     int exop_timeout;
-     struct resp_attrs *attrs;
-     struct sss_domain_info *obj_domain;
-     struct sysdb_attrs *override_attrs;
- };
- 
--static errno_t ipa_s2n_get_groups_step(struct tevent_req *req);
--static void ipa_s2n_get_groups_get_override_done(struct tevent_req *subreq);
--static void ipa_s2n_get_groups_next(struct tevent_req *subreq);
--static errno_t ipa_s2n_get_groups_save_step(struct tevent_req *req);
-+static errno_t ipa_s2n_get_fqlist_step(struct tevent_req *req);
-+static void ipa_s2n_get_fqlist_get_override_done(struct tevent_req *subreq);
-+static void ipa_s2n_get_fqlist_next(struct tevent_req *subreq);
-+static errno_t ipa_s2n_get_fqlist_save_step(struct tevent_req *req);
- 
--static struct tevent_req *ipa_s2n_get_groups_send(TALLOC_CTX *mem_ctx,
-+static struct tevent_req *ipa_s2n_get_fqlist_send(TALLOC_CTX *mem_ctx,
-                                                   struct tevent_context *ev,
-                                                   struct ipa_id_ctx *ipa_ctx,
-                                                   struct sss_domain_info *dom,
-                                                   struct sdap_handle *sh,
-                                                   int exop_timeout,
--                                                  char **group_list)
-+                                                  char **fqname_list)
- {
-     int ret;
--    struct ipa_s2n_get_groups_state *state;
-+    struct ipa_s2n_get_fqlist_state *state;
-     struct tevent_req *req;
- 
--    req = tevent_req_create(mem_ctx, &state, struct ipa_s2n_get_groups_state);
-+    req = tevent_req_create(mem_ctx, &state, struct ipa_s2n_get_fqlist_state);
-     if (req == NULL) {
-         return NULL;
-     }
-@@ -917,17 +917,17 @@ static struct tevent_req *ipa_s2n_get_groups_send(TALLOC_CTX *mem_ctx,
-     state->ipa_ctx = ipa_ctx;
-     state->dom = dom;
-     state->sh = sh;
--    state->group_list = group_list;
--    state->group_idx = 0;
-+    state->fqname_list = fqname_list;
-+    state->fqname_idx = 0;
-     state->req_input.type = REQ_INP_NAME;
-     state->req_input.inp.name = NULL;
-     state->exop_timeout = exop_timeout;
-     state->attrs = NULL;
-     state->override_attrs = NULL;
- 
--    ret = ipa_s2n_get_groups_step(req);
-+    ret = ipa_s2n_get_fqlist_step(req);
-     if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_groups_step failed.\n");
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_fqlist_step failed.\n");
-         goto done;
-     }
- 
-@@ -940,25 +940,25 @@ done:
-     return req;
- }
- 
--static errno_t ipa_s2n_get_groups_step(struct tevent_req *req)
-+static errno_t ipa_s2n_get_fqlist_step(struct tevent_req *req)
- {
-     int ret;
--    struct ipa_s2n_get_groups_state *state = tevent_req_data(req,
--                                               struct ipa_s2n_get_groups_state);
-+    struct ipa_s2n_get_fqlist_state *state = tevent_req_data(req,
-+                                               struct ipa_s2n_get_fqlist_state);
-     struct berval *bv_req;
-     struct tevent_req *subreq;
-     struct sss_domain_info *parent_domain;
--    char *group_name = NULL;
-+    char *short_name = NULL;
-     char *domain_name = NULL;
- 
-     parent_domain = get_domains_head(state->dom);
- 
-     ret = sss_parse_name(state, parent_domain->names,
--                         state->group_list[state->group_idx],
--                         &domain_name, &group_name);
-+                         state->fqname_list[state->fqname_idx],
-+                         &domain_name, &short_name);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n",
--                                    state->group_list[state->group_idx],
-+                                    state->fqname_list[state->fqname_idx],
-                                     ret, sss_strerror(ret));
-         return ret;
-     }
-@@ -974,7 +974,7 @@ static errno_t ipa_s2n_get_groups_step(struct tevent_req *req)
-         state->obj_domain = parent_domain;
-     }
- 
--    state->req_input.inp.name = group_name;
-+    state->req_input.inp.name = short_name;
- 
-     ret = s2n_encode_request(state, state->obj_domain->name, BE_REQ_GROUP,
-                              REQ_FULL_WITH_MEMBERS,
-@@ -990,18 +990,18 @@ static errno_t ipa_s2n_get_groups_step(struct tevent_req *req)
-         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_exop_send failed.\n");
-         return ENOMEM;
-     }
--    tevent_req_set_callback(subreq, ipa_s2n_get_groups_next, req);
-+    tevent_req_set_callback(subreq, ipa_s2n_get_fqlist_next, req);
- 
-     return EOK;
- }
- 
--static void ipa_s2n_get_groups_next(struct tevent_req *subreq)
-+static void ipa_s2n_get_fqlist_next(struct tevent_req *subreq)
- {
-     int ret;
-     struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                       struct tevent_req);
--    struct ipa_s2n_get_groups_state *state = tevent_req_data(req,
--                                               struct ipa_s2n_get_groups_state);
-+    struct ipa_s2n_get_fqlist_state *state = tevent_req_data(req,
-+                                               struct ipa_s2n_get_fqlist_state);
-     char *retoid = NULL;
-     struct berval *retdata = NULL;
-     const char *sid_str;
-@@ -1022,11 +1022,11 @@ static void ipa_s2n_get_groups_next(struct tevent_req *subreq)
-     }
- 
-     if (strcmp(state->ipa_ctx->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
--        ret = ipa_s2n_get_groups_save_step(req);
-+        ret = ipa_s2n_get_fqlist_save_step(req);
-         if (ret == EOK) {
-             tevent_req_done(req);
-         } else if (ret != EAGAIN) {
--            DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_groups_save_step failed.\n");
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_fqlist_save_step failed.\n");
-             goto fail;
-         }
- 
-@@ -1058,7 +1058,7 @@ static void ipa_s2n_get_groups_next(struct tevent_req *subreq)
-         ret = ENOMEM;
-         goto fail;
-     }
--    tevent_req_set_callback(subreq, ipa_s2n_get_groups_get_override_done, req);
-+    tevent_req_set_callback(subreq, ipa_s2n_get_fqlist_get_override_done, req);
- 
-     return;
- 
-@@ -1067,13 +1067,13 @@ fail:
-     return;
- }
- 
--static void ipa_s2n_get_groups_get_override_done(struct tevent_req *subreq)
-+static void ipa_s2n_get_fqlist_get_override_done(struct tevent_req *subreq)
- {
-     int ret;
-     struct tevent_req *req = tevent_req_callback_data(subreq,
-                                                       struct tevent_req);
--    struct ipa_s2n_get_groups_state *state = tevent_req_data(req,
--                                               struct ipa_s2n_get_groups_state);
-+    struct ipa_s2n_get_fqlist_state *state = tevent_req_data(req,
-+                                               struct ipa_s2n_get_fqlist_state);
- 
-     ret = ipa_get_ad_override_recv(subreq, NULL, state, &state->override_attrs);
-     talloc_zfree(subreq);
-@@ -1082,11 +1082,11 @@ static void ipa_s2n_get_groups_get_override_done(struct tevent_req *subreq)
-         goto fail;
-     }
- 
--    ret = ipa_s2n_get_groups_save_step(req);
-+    ret = ipa_s2n_get_fqlist_save_step(req);
-     if (ret == EOK) {
-         tevent_req_done(req);
-     } else if (ret != EAGAIN) {
--        DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_groups_save_step failed.\n");
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_fqlist_save_step failed.\n");
-         goto fail;
-     }
- 
-@@ -1097,11 +1097,11 @@ fail:
-     return;
- }
- 
--static errno_t ipa_s2n_get_groups_save_step(struct tevent_req *req)
-+static errno_t ipa_s2n_get_fqlist_save_step(struct tevent_req *req)
- {
-     int ret;
--    struct ipa_s2n_get_groups_state *state = tevent_req_data(req,
--                                               struct ipa_s2n_get_groups_state);
-+    struct ipa_s2n_get_fqlist_state *state = tevent_req_data(req,
-+                                               struct ipa_s2n_get_fqlist_state);
- 
-     ret = ipa_s2n_save_objects(state->dom, &state->req_input, state->attrs,
-                                NULL, state->ipa_ctx->view_name,
-@@ -1111,21 +1111,21 @@ static errno_t ipa_s2n_get_groups_save_step(struct tevent_req *req)
-         return ret;
-     }
- 
--    state->group_idx++;
--    if (state->group_list[state->group_idx] == NULL) {
-+    state->fqname_idx++;
-+    if (state->fqname_list[state->fqname_idx] == NULL) {
-         return EOK;
-     }
- 
--    ret = ipa_s2n_get_groups_step(req);
-+    ret = ipa_s2n_get_fqlist_step(req);
-     if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_groups_step failed.\n");
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_fqlist_step failed.\n");
-         return ret;
-     }
- 
-     return EAGAIN;
- }
- 
--static int ipa_s2n_get_groups_recv(struct tevent_req *req)
-+static int ipa_s2n_get_fqlist_recv(struct tevent_req *req)
- {
-     TEVENT_REQ_RETURN_ON_ERROR(req);
- 
-@@ -1426,7 +1426,7 @@ done:
-     return ret;
- }
- 
--static void ipa_s2n_get_groups_done(struct tevent_req  *subreq);
-+static void ipa_s2n_get_fqlist_done(struct tevent_req  *subreq);
- static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq);
- static void ipa_s2n_get_user_done(struct tevent_req *subreq)
- {
-@@ -1485,17 +1485,17 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
-             }
- 
-             if (missing_groups != NULL) {
--                subreq = ipa_s2n_get_groups_send(state, state->ev,
-+                subreq = ipa_s2n_get_fqlist_send(state, state->ev,
-                                                  state->ipa_ctx, state->dom,
-                                                  state->sh, state->exop_timeout,
-                                                  missing_groups);
-                 if (subreq == NULL) {
-                     DEBUG(SSSDBG_OP_FAILURE,
--                          "ipa_s2n_get_groups_send failed.\n");
-+                          "ipa_s2n_get_fqlist_send failed.\n");
-                     ret = ENOMEM;
-                     goto done;
-                 }
--                tevent_req_set_callback(subreq, ipa_s2n_get_groups_done,
-+                tevent_req_set_callback(subreq, ipa_s2n_get_fqlist_done,
-                                         req);
- 
-                 return;
-@@ -2089,7 +2089,7 @@ done:
-     return ret;
- }
- 
--static void ipa_s2n_get_groups_done(struct tevent_req  *subreq)
-+static void ipa_s2n_get_fqlist_done(struct tevent_req  *subreq)
- {
-     int ret;
-     struct tevent_req *req = tevent_req_callback_data(subreq,
-@@ -2099,10 +2099,10 @@ static void ipa_s2n_get_groups_done(struct tevent_req  *subreq)
-     const char *sid_str;
-     struct be_acct_req *ar;
- 
--    ret = ipa_s2n_get_groups_recv(subreq);
-+    ret = ipa_s2n_get_fqlist_recv(subreq);
-     talloc_zfree(subreq);
-     if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "s2n get_groups request failed.\n");
-+        DEBUG(SSSDBG_OP_FAILURE, "s2n get_fqlist request failed.\n");
-         tevent_req_error(req, ret);
-         return;
-     }
--- 
-2.1.0
-
diff --git a/SOURCES/0166-IPA-resolve-missing-members.patch b/SOURCES/0166-IPA-resolve-missing-members.patch
deleted file mode 100644
index 205d27f..0000000
--- a/SOURCES/0166-IPA-resolve-missing-members.patch
+++ /dev/null
@@ -1,137 +0,0 @@
-From 7dfe969cb2c9e116eaeb1813e2c1adb80195944e Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 5 Dec 2014 11:12:42 +0100
-Subject: [PATCH 166/167] IPA: resolve missing members
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 3cd287313d93e29f9754feb46017dba2a039affd)
----
- src/providers/ipa/ipa_s2n_exop.c | 62 +++++++++++++++++++++++++++++++---------
- 1 file changed, 48 insertions(+), 14 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 505c2325f2a74e26816bb59ad3c7d4810cc64dbf..0aa12f371e8aa0d58311391a27c668aa929a5b80 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -886,6 +886,8 @@ struct ipa_s2n_get_fqlist_state {
-     char **fqname_list;
-     size_t fqname_idx;
-     int exop_timeout;
-+    int entry_type;
-+    enum request_types request_type;
-     struct resp_attrs *attrs;
-     struct sss_domain_info *obj_domain;
-     struct sysdb_attrs *override_attrs;
-@@ -897,12 +899,14 @@ static void ipa_s2n_get_fqlist_next(struct tevent_req *subreq);
- static errno_t ipa_s2n_get_fqlist_save_step(struct tevent_req *req);
- 
- static struct tevent_req *ipa_s2n_get_fqlist_send(TALLOC_CTX *mem_ctx,
--                                                  struct tevent_context *ev,
--                                                  struct ipa_id_ctx *ipa_ctx,
--                                                  struct sss_domain_info *dom,
--                                                  struct sdap_handle *sh,
--                                                  int exop_timeout,
--                                                  char **fqname_list)
-+                                                struct tevent_context *ev,
-+                                                struct ipa_id_ctx *ipa_ctx,
-+                                                struct sss_domain_info *dom,
-+                                                struct sdap_handle *sh,
-+                                                int exop_timeout,
-+                                                int entry_type,
-+                                                enum request_types request_type,
-+                                                char **fqname_list)
- {
-     int ret;
-     struct ipa_s2n_get_fqlist_state *state;
-@@ -922,6 +926,8 @@ static struct tevent_req *ipa_s2n_get_fqlist_send(TALLOC_CTX *mem_ctx,
-     state->req_input.type = REQ_INP_NAME;
-     state->req_input.inp.name = NULL;
-     state->exop_timeout = exop_timeout;
-+    state->entry_type = entry_type;
-+    state->request_type = request_type;
-     state->attrs = NULL;
-     state->override_attrs = NULL;
- 
-@@ -976,8 +982,8 @@ static errno_t ipa_s2n_get_fqlist_step(struct tevent_req *req)
- 
-     state->req_input.inp.name = short_name;
- 
--    ret = s2n_encode_request(state, state->obj_domain->name, BE_REQ_GROUP,
--                             REQ_FULL_WITH_MEMBERS,
-+    ret = s2n_encode_request(state, state->obj_domain->name, state->entry_type,
-+                             state->request_type,
-                              &state->req_input, &bv_req);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "s2n_encode_request failed.\n");
-@@ -1439,7 +1445,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
-     struct berval *retdata = NULL;
-     struct resp_attrs *attrs = NULL;
-     struct berval *bv_req = NULL;
--    char **missing_groups = NULL;
-+    char **missing_list = NULL;
-     struct ldb_dn **group_dn_list = NULL;
-     const char *sid_str;
-     struct be_acct_req *ar;
-@@ -1478,17 +1484,46 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
-         if (attrs->response_type == RESP_USER_GROUPLIST) {
-             ret = get_group_dn_list(state, state->dom,
-                                     attrs->ngroups, attrs->groups,
--                                    &group_dn_list, &missing_groups);
-+                                    &group_dn_list, &missing_list);
-             if (ret != EOK) {
-                 DEBUG(SSSDBG_OP_FAILURE, "get_group_dn_list failed.\n");
-                 goto done;
-             }
- 
--            if (missing_groups != NULL) {
-+            if (missing_list != NULL) {
-                 subreq = ipa_s2n_get_fqlist_send(state, state->ev,
-                                                  state->ipa_ctx, state->dom,
-                                                  state->sh, state->exop_timeout,
--                                                 missing_groups);
-+                                                 BE_REQ_GROUP,
-+                                                 REQ_FULL_WITH_MEMBERS,
-+                                                 missing_list);
-+                if (subreq == NULL) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "ipa_s2n_get_fqlist_send failed.\n");
-+                    ret = ENOMEM;
-+                    goto done;
-+                }
-+                tevent_req_set_callback(subreq, ipa_s2n_get_fqlist_done,
-+                                        req);
-+
-+                return;
-+            }
-+            break;
-+        } else if (attrs->response_type == RESP_GROUP_MEMBERS) {
-+            ret = process_members(state->dom, NULL, attrs->a.group.gr_mem,
-+                                  state, &missing_list);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "process_members failed.\n");
-+                goto done;
-+            }
-+
-+            if (missing_list != NULL) {
-+                subreq = ipa_s2n_get_fqlist_send(state, state->ev,
-+                                                 state->ipa_ctx, state->dom,
-+                                                 state->sh, state->exop_timeout,
-+                                                 BE_REQ_USER,
-+                                                 REQ_FULL_WITH_MEMBERS,
-+                                                 missing_list);
-                 if (subreq == NULL) {
-                     DEBUG(SSSDBG_OP_FAILURE,
-                           "ipa_s2n_get_fqlist_send failed.\n");
-@@ -1503,8 +1538,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
-             break;
-         }
- 
--        if (state->req_input->type == REQ_INP_SECID
--                || attrs->response_type == RESP_GROUP_MEMBERS) {
-+        if (state->req_input->type == REQ_INP_SECID) {
-             /* We already know the SID, we do not have to read it. */
-             break;
-         }
--- 
-2.1.0
-
diff --git a/SOURCES/0167-IPA-set-SYSDB_INITGR_EXPIRE-for-RESP_USER_GROUPLIST.patch b/SOURCES/0167-IPA-set-SYSDB_INITGR_EXPIRE-for-RESP_USER_GROUPLIST.patch
deleted file mode 100644
index a0f093b..0000000
--- a/SOURCES/0167-IPA-set-SYSDB_INITGR_EXPIRE-for-RESP_USER_GROUPLIST.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From d9da43cb6ec9aff5aa1a760e50f3bcbf54307d25 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 9 Dec 2014 17:48:46 +0100
-Subject: [PATCH 167/167] IPA: set SYSDB_INITGR_EXPIRE for RESP_USER_GROUPLIST
-
-Since RESP_USER_GROUPLIST contains all group memberships it is
-effectively an initgroups request hence SYSDB_INITGR_EXPIRE will be set.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 62d919aea98edd1095f6a22241903d4c045b46ed)
----
- src/providers/ipa/ipa_s2n_exop.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 0aa12f371e8aa0d58311391a27c668aa929a5b80..e7c2d9bb97908746eb5ab6cacc6fc58d353dea06 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1911,6 +1911,20 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                 }
-             }
- 
-+            if (attrs->response_type == RESP_USER_GROUPLIST) {
-+                /* Since RESP_USER_GROUPLIST contains all group memberships it
-+                 * is effectively an initgroups request hence
-+                 * SYSDB_INITGR_EXPIRE will be set.*/
-+                ret = sysdb_attrs_add_time_t(attrs->sysdb_attrs,
-+                                             SYSDB_INITGR_EXPIRE,
-+                                             time(NULL) + timeout);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_attrs_add_time_t failed.\n");
-+                    goto done;
-+                }
-+            }
-+
-             gid = 0;
-             if (dom->mpg == false) {
-                 gid = attrs->a.user.pw_gid;
--- 
-2.1.0
-
diff --git a/SOURCES/0168-krb5_child-Return-ERR_NETWORK_IO-on-KRB5_KDCREP_SKEW.patch b/SOURCES/0168-krb5_child-Return-ERR_NETWORK_IO-on-KRB5_KDCREP_SKEW.patch
deleted file mode 100644
index b52cb4d..0000000
--- a/SOURCES/0168-krb5_child-Return-ERR_NETWORK_IO-on-KRB5_KDCREP_SKEW.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From 6bc93a28d5638ea4e76be699f507a76fa3e357ff Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 14 Jan 2015 11:03:14 +0100
-Subject: [PATCH 168/168] krb5_child: Return ERR_NETWORK_IO on KRB5_KDCREP_SKEW
-
-Previously, we were only handling KRB5KRB_AP_ERR_SKEW
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 9b2cd4e5e451c07cb2f04cdbaea2b94ccb5fb2ee)
----
- src/providers/krb5/krb5_child.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 9645f1aefbbaaf7fda511bb9650722109403d9df..39cd62846e3c58d65a87f670768cf699ae191f14 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -1072,6 +1072,7 @@ static errno_t map_krb5_error(krb5_error_code kerr)
-     case KRB5_LIBOS_CANTREADPWD:
-         return ERR_NO_CREDS;
- 
-+    case KRB5_KDCREP_SKEW:
-     case KRB5KRB_AP_ERR_SKEW:
-     case KRB5_KDC_UNREACH:
-     case KRB5_REALM_CANT_RESOLVE:
--- 
-2.1.0
-
diff --git a/SOURCES/0169-krb5-fix-entry-order-in-MEMORY-keytab.patch b/SOURCES/0169-krb5-fix-entry-order-in-MEMORY-keytab.patch
deleted file mode 100644
index 6abefe7..0000000
--- a/SOURCES/0169-krb5-fix-entry-order-in-MEMORY-keytab.patch
+++ /dev/null
@@ -1,203 +0,0 @@
-From 7c20e30182e3b5f7f8ebcd8174bded4dcc2f89a8 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 15 Jan 2015 10:38:33 +0100
-Subject: [PATCH 169/169] krb5: fix entry order in MEMORY keytab
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Since krb5_kt_add_entry() adds new entries at the beginning of a MEMORY
-type keytab and not at the end a simple copy into a MEMORY type keytab
-will revert the order of the keytab entries. Since e.g. the sssd_krb5
-man page give hints about where to add entries into keytab files to help
-SSSD to find a right entry we have to keep the order when coping a
-keytab into a MEMORY type keytab. This patch fixes this by doing a
-second copy to retain the original order.
-
-Resolves https://fedorahosted.org/sssd/ticket/2557
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-
-(cherry picked from commit 24df1487413d13248dcc70d2548a763930da4c65)
----
- src/providers/krb5/krb5_keytab.c | 118 +++++++++++++++++++++++++++++----------
- 1 file changed, 90 insertions(+), 28 deletions(-)
-
-diff --git a/src/providers/krb5/krb5_keytab.c b/src/providers/krb5/krb5_keytab.c
-index 855f69419611b863a7aea79e2788272f819b0736..ec8d6502d89c0d7f75c28b151523d235b6bc131d 100644
---- a/src/providers/krb5/krb5_keytab.c
-+++ b/src/providers/krb5/krb5_keytab.c
-@@ -25,20 +25,78 @@
- #include "util/util.h"
- #include "util/sss_krb5.h"
- 
-+static krb5_error_code do_keytab_copy(krb5_context kctx, krb5_keytab s_keytab,
-+                                      krb5_keytab d_keytab)
-+{
-+    krb5_error_code kerr;
-+    krb5_error_code kt_err;
-+    krb5_kt_cursor cursor;
-+    krb5_keytab_entry entry;
-+
-+    memset(&cursor, 0, sizeof(cursor));
-+    kerr = krb5_kt_start_seq_get(kctx, s_keytab, &cursor);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab.\n");
-+        return kerr;
-+    }
-+
-+    memset(&entry, 0, sizeof(entry));
-+    while ((kt_err = krb5_kt_next_entry(kctx, s_keytab, &entry,
-+                                        &cursor)) == 0) {
-+        kerr = krb5_kt_add_entry(kctx, d_keytab, &entry);
-+        if (kerr != 0) {
-+            DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_add_entry failed.\n");
-+            kt_err = krb5_kt_end_seq_get(kctx, s_keytab, &cursor);
-+            if (kt_err != 0) {
-+                DEBUG(SSSDBG_TRACE_ALL,
-+                      "krb5_kt_end_seq_get failed with [%d], ignored.\n",
-+                      kt_err);
-+            }
-+            return kerr;
-+        }
-+
-+        kerr = sss_krb5_free_keytab_entry_contents(kctx, &entry);
-+        if (kerr != 0) {
-+            DEBUG(SSSDBG_MINOR_FAILURE, "Failed to free keytab entry.\n");
-+            kt_err = krb5_kt_end_seq_get(kctx, s_keytab, &cursor);
-+            if (kt_err != 0) {
-+                DEBUG(SSSDBG_TRACE_ALL,
-+                      "krb5_kt_end_seq_get failed with [%d], ignored.\n",
-+                      kt_err);
-+            }
-+            return kerr;
-+        }
-+        memset(&entry, 0, sizeof(entry));
-+    }
-+
-+    kerr = krb5_kt_end_seq_get(kctx, s_keytab, &cursor);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n");
-+        return kerr;
-+    }
-+
-+    /* check if we got any errors from krb5_kt_next_entry */
-+    if (kt_err != 0 && kt_err != KRB5_KT_END) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab.\n");
-+        return kt_err;
-+    }
-+
-+    return 0;
-+}
-+
- krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-                                         char *inp_keytab_file,
-                                         char **_mem_name,
-                                         krb5_keytab *_mem_keytab)
- {
-     krb5_error_code kerr;
--    krb5_error_code kt_err;
-     krb5_keytab keytab = NULL;
-     krb5_keytab mem_keytab = NULL;
--    krb5_kt_cursor cursor;
--    krb5_keytab_entry entry;
-+    krb5_keytab tmp_mem_keytab = NULL;
-     char keytab_name[MAX_KEYTAB_NAME_LEN];
-     char *sep;
-     char *mem_name = NULL;
-+    char *tmp_mem_name = NULL;
-     char *keytab_file;
-     char default_keytab_name[MAX_KEYTAB_NAME_LEN];
- 
-@@ -103,6 +161,13 @@ krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-         goto done;
-     }
- 
-+    tmp_mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s.tmp", sep + 1);
-+    if (tmp_mem_name == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
-+        kerr = KRB5KRB_ERR_GENERIC;
-+        goto done;
-+    }
-+
-     kerr = krb5_kt_resolve(kctx, mem_name, &mem_keytab);
-     if (kerr != 0) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n",
-@@ -110,38 +175,29 @@ krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-         goto done;
-     }
- 
--    memset(&cursor, 0, sizeof(cursor));
--    kerr = krb5_kt_start_seq_get(kctx, keytab, &cursor);
-+    kerr = krb5_kt_resolve(kctx, tmp_mem_name, &tmp_mem_keytab);
-     if (kerr != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab [%s].\n", keytab_file);
-+        DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n",
-+                                    tmp_mem_name);
-         goto done;
-     }
- 
--    memset(&entry, 0, sizeof(entry));
--    while ((kt_err = krb5_kt_next_entry(kctx, keytab, &entry, &cursor)) == 0) {
--        kerr = krb5_kt_add_entry(kctx, mem_keytab, &entry);
--        if (kerr != 0) {
--            DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_add_entry failed.\n");
--            goto done;
--        }
--
--        kerr = sss_krb5_free_keytab_entry_contents(kctx, &entry);
--        if (kerr != 0) {
--            DEBUG(SSSDBG_MINOR_FAILURE, "Failed to free keytab entry.\n");
--        }
--        memset(&entry, 0, sizeof(entry));
--    }
--
--    kerr = krb5_kt_end_seq_get(kctx, keytab, &cursor);
-+    kerr = do_keytab_copy(kctx, keytab, tmp_mem_keytab);
-     if (kerr != 0) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n");
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy keytab [%s] into [%s].\n",
-+                                    keytab_file, tmp_mem_name);
-         goto done;
-     }
- 
--    /* check if we got any errors from krb5_kt_next_entry */
--    if (kt_err != 0 && kt_err != KRB5_KT_END) {
--        DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab [%s].\n", keytab_file);
--        kerr = KRB5KRB_ERR_GENERIC;
-+    /* krb5_kt_add_entry() adds new entries into MEMORY keytabs at the
-+     * beginning and not at the end as for FILE keytabs. Since we want to keep
-+     * the processing order we have to copy the MEMORY keytab again to retain
-+     * the order from the FILE keytab. */
-+
-+    kerr = do_keytab_copy(kctx, tmp_mem_keytab, mem_keytab);
-+    if (kerr != 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy keytab [%s] into [%s].\n",
-+                                    tmp_mem_name, mem_name);
-         goto done;
-     }
- 
-@@ -153,12 +209,18 @@ krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
-     kerr = 0;
- done:
- 
-+    talloc_free(tmp_mem_name);
-+
-     if (kerr != 0) {
-         talloc_free(mem_name);
-     }
- 
-+    if (tmp_mem_keytab != NULL && krb5_kt_close(kctx, tmp_mem_keytab) != 0) {
-+        DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed.\n");
-+    }
-+
-     if (keytab != NULL && krb5_kt_close(kctx, keytab) != 0) {
--            DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed");
-+        DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed.\n");
-     }
- 
-     return kerr;
--- 
-2.1.0
-
diff --git a/SOURCES/0170-nss-make-fill_orig-multi-value-aware.patch b/SOURCES/0170-nss-make-fill_orig-multi-value-aware.patch
deleted file mode 100644
index e823d9d..0000000
--- a/SOURCES/0170-nss-make-fill_orig-multi-value-aware.patch
+++ /dev/null
@@ -1,301 +0,0 @@
-From 42cd56abee7c8403c585db2d85a0d32f141b05a6 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 20 Jan 2015 12:48:19 +0100
-Subject: [PATCH 170/172] nss: make fill_orig() multi-value aware
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 5f4d896ec8e06476f4282b562b1044de14c48ecf)
----
- src/responder/nss/nsssrv_cmd.c  |  86 ++++++++++++++++++++------
- src/tests/cmocka/test_nss_srv.c | 131 +++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 197 insertions(+), 20 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index c523dafc9455a07f3b0fd1f9db00bee551358a84..b49807e3e349942c0617253fdf45b4ad43ba2ee1 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4612,13 +4612,14 @@ static errno_t fill_orig(struct sss_packet *packet,
- {
-     int ret;
-     TALLOC_CTX *tmp_ctx;
--    const char *tmp_str;
-     uint8_t *body;
-     size_t blen;
-     size_t pctr = 0;
-     size_t c;
-+    size_t d;
-     size_t sum;
-     size_t found;
-+    size_t array_size;
-     size_t extra_attrs_count = 0;
-     const char **extra_attrs_list = NULL;
-     const char *orig_attr_list[] = {SYSDB_SID_STR,
-@@ -4637,6 +4638,8 @@ static errno_t fill_orig(struct sss_packet *packet,
-     struct sized_string *keys;
-     struct sized_string *vals;
-     struct nss_ctx *nctx;
-+    struct ldb_message_element *el;
-+    struct ldb_val *val;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -4652,10 +4655,9 @@ static errno_t fill_orig(struct sss_packet *packet,
-                 extra_attrs_count++);
-     }
- 
--    keys = talloc_array(tmp_ctx, struct sized_string,
--                        sizeof(orig_attr_list) + extra_attrs_count);
--    vals = talloc_array(tmp_ctx, struct sized_string,
--                        sizeof(orig_attr_list) + extra_attrs_count);
-+    array_size = sizeof(orig_attr_list) + extra_attrs_count;
-+    keys = talloc_array(tmp_ctx, struct sized_string, array_size);
-+    vals = talloc_array(tmp_ctx, struct sized_string, array_size);
-     if (keys == NULL || vals == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-         ret = ENOMEM;
-@@ -4665,26 +4667,72 @@ static errno_t fill_orig(struct sss_packet *packet,
-     sum = 0;
-     found = 0;
-     for (c = 0; orig_attr_list[c] != NULL; c++) {
--        tmp_str = ldb_msg_find_attr_as_string(msg, orig_attr_list[c], NULL);
--        if (tmp_str != NULL) {
--            to_sized_string(&keys[found], orig_attr_list[c]);
--            sum += keys[found].len;
--            to_sized_string(&vals[found], tmp_str);
--            sum += vals[found].len;
-+        el = ldb_msg_find_element(msg, orig_attr_list[c]);
-+        if (el != NULL &&  el->num_values > 0) {
-+            if (el->num_values > 1) {
-+                array_size += el->num_values;
-+                keys = talloc_realloc(tmp_ctx, keys, struct sized_string,
-+                                      array_size);
-+                vals = talloc_realloc(tmp_ctx, vals, struct sized_string,
-+                                      array_size);
-+                if (keys == NULL || vals == NULL) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-+                    ret = ENOMEM;
-+                    goto done;
-+                }
-+            }
-+            for (d = 0; d < el->num_values; d++) {
-+                to_sized_string(&keys[found], orig_attr_list[c]);
-+                sum += keys[found].len;
-+                val = &(el->values[d]);
-+                if (val == NULL || val->data == NULL
-+                        || val->data[val->length] != '\0') {
-+                    DEBUG(SSSDBG_CRIT_FAILURE,
-+                          "Unexpected attribute value found for [%s].\n",
-+                          orig_attr_list[c]);
-+                    ret = EINVAL;
-+                    goto done;
-+                }
-+                to_sized_string(&vals[found], (const char *)val->data);
-+                sum += vals[found].len;
- 
--            found++;
-+                found++;
-+            }
-         }
-     }
- 
-     for (c = 0; c < extra_attrs_count; c++) {
--        tmp_str = ldb_msg_find_attr_as_string(msg, extra_attrs_list[c], NULL);
--        if (tmp_str != NULL) {
--            to_sized_string(&keys[found], extra_attrs_list[c]);
--            sum += keys[found].len;
--            to_sized_string(&vals[found], tmp_str);
--            sum += vals[found].len;
-+        el = ldb_msg_find_element(msg, extra_attrs_list[c]);
-+        if (el != NULL &&  el->num_values > 0) {
-+            if (el->num_values > 1) {
-+                array_size += el->num_values;
-+                keys = talloc_realloc(tmp_ctx, keys, struct sized_string,
-+                                      array_size);
-+                vals = talloc_realloc(tmp_ctx, vals, struct sized_string,
-+                                      array_size);
-+                if (keys == NULL || vals == NULL) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-+                    ret = ENOMEM;
-+                    goto done;
-+                }
-+            }
-+            for (d = 0; d < el->num_values; d++) {
-+                to_sized_string(&keys[found], extra_attrs_list[c]);
-+                sum += keys[found].len;
-+                val = &(el->values[d]);
-+                if (val == NULL || val->data == NULL
-+                        || val->data[val->length] != '\0') {
-+                    DEBUG(SSSDBG_CRIT_FAILURE,
-+                          "Unexpected attribute value found for [%s].\n",
-+                          orig_attr_list[c]);
-+                    ret = EINVAL;
-+                    goto done;
-+                }
-+                to_sized_string(&vals[found], (const char *)val->data);
-+                sum += vals[found].len;
- 
--            found++;
-+                found++;
-+            }
-         }
-     }
- 
-diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
-index c318d94be867bbb9991de288cdae45d2ddc29b24..d7825e4384a4cc91407ed4bc66a1e190d558369f 100644
---- a/src/tests/cmocka/test_nss_srv.c
-+++ b/src/tests/cmocka/test_nss_srv.c
-@@ -52,7 +52,8 @@ struct nss_test_ctx {
-     bool ncache_hit;
- };
- 
--const char *global_extra_attrs[] = {"phone", "mobile", NULL};
-+const char *global_extra_attrs[] = {"phone", "mobile", SYSDB_ORIG_MEMBEROF,
-+                                    NULL};
- 
- struct nss_test_ctx *nss_test_ctx;
- 
-@@ -1946,6 +1947,132 @@ void test_nss_getorigbyname_extra_attrs(void **state)
-     assert_int_equal(ret, EOK);
- }
- 
-+
-+static int test_nss_getorigbyname_multi_check(uint32_t status, uint8_t *body,
-+                                              size_t blen)
-+{
-+    const char *s;
-+    enum sss_id_type id_type;
-+    size_t rp = 2 * sizeof(uint32_t);
-+
-+    assert_int_equal(status, EOK);
-+
-+    SAFEALIGN_COPY_UINT32(&id_type, body+rp, &rp);
-+    assert_int_equal(id_type, SSS_ID_TYPE_UID);
-+
-+    /* Sequence of null terminated strings */
-+    s = (char *) body+rp;
-+    assert_string_equal(s, SYSDB_SID_STR);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "S-1-2-3-4");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_NAME);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "orig_name");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_UIDNUM);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "1234");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, SYSDB_ORIG_MEMBEROF);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "cn=abc");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, SYSDB_ORIG_MEMBEROF);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "cn=def");
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, SYSDB_ORIG_MEMBEROF);
-+    rp += strlen(s) + 1;
-+    assert_true(rp < blen);
-+
-+    s = (char *) body+rp;
-+    assert_string_equal(s, "cn=123");
-+    rp += strlen(s) + 1;
-+    assert_int_equal(rp, blen);
-+
-+    return EOK;
-+}
-+void test_nss_getorigbyname_multi_value_attrs(void **state)
-+{
-+    errno_t ret;
-+    struct sysdb_attrs *attrs;
-+
-+    attrs = sysdb_new_attrs(nss_test_ctx);
-+    assert_non_null(attrs);
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, "S-1-2-3-4");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, ORIGINALAD_PREFIX SYSDB_NAME,
-+                                 "orig_name");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_uint32(attrs, ORIGINALAD_PREFIX SYSDB_UIDNUM, 1234);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_MEMBEROF, "cn=abc");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_MEMBEROF, "cn=def");
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_MEMBEROF, "cn=123");
-+    assert_int_equal(ret, EOK);
-+
-+    /* Prime the cache with a valid user */
-+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
-+                         "testuserorigmulti", 3456, 7890,
-+                         "test user orig multi value",
-+                         "/home/testuserorigextra", "/bin/sh", NULL,
-+                         attrs, 300, 0);
-+    assert_int_equal(ret, EOK);
-+
-+    mock_input_user_or_group("testuserorigmulti");
-+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETORIGBYNAME);
-+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
-+
-+    /* Query for that user, call a callback when command finishes */
-+    set_cmd_cb(test_nss_getorigbyname_multi_check);
-+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETORIGBYNAME,
-+                          nss_test_ctx->nss_cmds);
-+    assert_int_equal(ret, EOK);
-+
-+    /* Wait until the test finishes with EOK */
-+    ret = test_ev_loop(nss_test_ctx->tctx);
-+    assert_int_equal(ret, EOK);
-+}
-+
- void nss_test_setup(void **state)
- {
-     struct sss_test_conf_param params[] = {
-@@ -2096,6 +2223,8 @@ int main(int argc, const char *argv[])
-                                  nss_test_setup, nss_test_teardown),
-         unit_test_setup_teardown(test_nss_getorigbyname_extra_attrs,
-                                  nss_test_setup_extra_attr, nss_test_teardown),
-+        unit_test_setup_teardown(test_nss_getorigbyname_multi_value_attrs,
-+                                 nss_test_setup_extra_attr, nss_test_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-2.1.0
-
diff --git a/SOURCES/0171-nss-refactor-fill_orig.patch b/SOURCES/0171-nss-refactor-fill_orig.patch
deleted file mode 100644
index 1b3ecbe..0000000
--- a/SOURCES/0171-nss-refactor-fill_orig.patch
+++ /dev/null
@@ -1,184 +0,0 @@
-From a122ee37841392ceb8332d51728b54f9656225bc Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 20 Jan 2015 13:50:16 +0100
-Subject: [PATCH 171/172] nss: refactor fill_orig()
-
-The two loops in fill_orig were almost identical.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit a4d64002b5ca763622bde240d27797d361ba0388)
----
- src/responder/nss/nsssrv_cmd.c | 133 ++++++++++++++++++++---------------------
- 1 file changed, 66 insertions(+), 67 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index b49807e3e349942c0617253fdf45b4ad43ba2ee1..6b9988548cdb25873e0c59503595e42d69b8d8e1 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4605,6 +4605,61 @@ static errno_t fill_sid(struct sss_packet *packet,
-     return EOK;
- }
- 
-+static errno_t process_attr_list(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
-+                                 const char **attr_list,
-+                                 struct sized_string **_keys,
-+                                 struct sized_string **_vals,
-+                                 size_t *array_size, size_t *sum, size_t *found)
-+{
-+    size_t c;
-+    size_t d;
-+    struct sized_string *keys;
-+    struct sized_string *vals;
-+    struct ldb_val *val;
-+    struct ldb_message_element *el;
-+
-+    keys = *_keys;
-+    vals = *_vals;
-+
-+    for (c = 0; attr_list[c] != NULL; c++) {
-+        el = ldb_msg_find_element(msg, attr_list[c]);
-+        if (el != NULL &&  el->num_values > 0) {
-+            if (el->num_values > 1) {
-+                *array_size += el->num_values;
-+                keys = talloc_realloc(mem_ctx, keys, struct sized_string,
-+                                      *array_size);
-+                vals = talloc_realloc(mem_ctx, vals, struct sized_string,
-+                                      *array_size);
-+                if (keys == NULL || vals == NULL) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-+                    return ENOMEM;
-+                }
-+            }
-+            for (d = 0; d < el->num_values; d++) {
-+                to_sized_string(&keys[*found], attr_list[c]);
-+                *sum += keys[*found].len;
-+                val = &(el->values[d]);
-+                if (val == NULL || val->data == NULL
-+                        || val->data[val->length] != '\0') {
-+                    DEBUG(SSSDBG_CRIT_FAILURE,
-+                          "Unexpected attribute value found for [%s].\n",
-+                          attr_list[c]);
-+                    return EINVAL;
-+                }
-+                to_sized_string(&vals[*found], (const char *)val->data);
-+                *sum += vals[*found].len;
-+
-+                (*found)++;
-+            }
-+        }
-+    }
-+
-+    *_keys = keys;
-+    *_vals = vals;
-+
-+    return EOK;
-+}
-+
- static errno_t fill_orig(struct sss_packet *packet,
-                          struct resp_ctx *rctx,
-                          enum sss_id_type id_type,
-@@ -4616,7 +4671,6 @@ static errno_t fill_orig(struct sss_packet *packet,
-     size_t blen;
-     size_t pctr = 0;
-     size_t c;
--    size_t d;
-     size_t sum;
-     size_t found;
-     size_t array_size;
-@@ -4638,8 +4692,6 @@ static errno_t fill_orig(struct sss_packet *packet,
-     struct sized_string *keys;
-     struct sized_string *vals;
-     struct nss_ctx *nctx;
--    struct ldb_message_element *el;
--    struct ldb_val *val;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -4666,73 +4718,20 @@ static errno_t fill_orig(struct sss_packet *packet,
- 
-     sum = 0;
-     found = 0;
--    for (c = 0; orig_attr_list[c] != NULL; c++) {
--        el = ldb_msg_find_element(msg, orig_attr_list[c]);
--        if (el != NULL &&  el->num_values > 0) {
--            if (el->num_values > 1) {
--                array_size += el->num_values;
--                keys = talloc_realloc(tmp_ctx, keys, struct sized_string,
--                                      array_size);
--                vals = talloc_realloc(tmp_ctx, vals, struct sized_string,
--                                      array_size);
--                if (keys == NULL || vals == NULL) {
--                    DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
--                    ret = ENOMEM;
--                    goto done;
--                }
--            }
--            for (d = 0; d < el->num_values; d++) {
--                to_sized_string(&keys[found], orig_attr_list[c]);
--                sum += keys[found].len;
--                val = &(el->values[d]);
--                if (val == NULL || val->data == NULL
--                        || val->data[val->length] != '\0') {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "Unexpected attribute value found for [%s].\n",
--                          orig_attr_list[c]);
--                    ret = EINVAL;
--                    goto done;
--                }
--                to_sized_string(&vals[found], (const char *)val->data);
--                sum += vals[found].len;
- 
--                found++;
--            }
--        }
-+    ret = process_attr_list(tmp_ctx, msg, orig_attr_list, &keys, &vals,
-+                            &array_size, &sum, &found);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "process_attr_list failed.\n");
-+        goto done;
-     }
- 
--    for (c = 0; c < extra_attrs_count; c++) {
--        el = ldb_msg_find_element(msg, extra_attrs_list[c]);
--        if (el != NULL &&  el->num_values > 0) {
--            if (el->num_values > 1) {
--                array_size += el->num_values;
--                keys = talloc_realloc(tmp_ctx, keys, struct sized_string,
--                                      array_size);
--                vals = talloc_realloc(tmp_ctx, vals, struct sized_string,
--                                      array_size);
--                if (keys == NULL || vals == NULL) {
--                    DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
--                    ret = ENOMEM;
--                    goto done;
--                }
--            }
--            for (d = 0; d < el->num_values; d++) {
--                to_sized_string(&keys[found], extra_attrs_list[c]);
--                sum += keys[found].len;
--                val = &(el->values[d]);
--                if (val == NULL || val->data == NULL
--                        || val->data[val->length] != '\0') {
--                    DEBUG(SSSDBG_CRIT_FAILURE,
--                          "Unexpected attribute value found for [%s].\n",
--                          orig_attr_list[c]);
--                    ret = EINVAL;
--                    goto done;
--                }
--                to_sized_string(&vals[found], (const char *)val->data);
--                sum += vals[found].len;
--
--                found++;
--            }
-+    if (extra_attrs_count != 0) {
-+        ret = process_attr_list(tmp_ctx, msg, extra_attrs_list, &keys, &vals,
-+                                &array_size, &sum, &found);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "process_attr_list failed.\n");
-+            goto done;
-         }
-     }
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0172-nss-Add-original-DN-and-memberOf-to-origbyname-reque.patch b/SOURCES/0172-nss-Add-original-DN-and-memberOf-to-origbyname-reque.patch
deleted file mode 100644
index 0c1ed1c..0000000
--- a/SOURCES/0172-nss-Add-original-DN-and-memberOf-to-origbyname-reque.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From ac9d460c61bf3bdb3aed5d96541d7e5baf8d9648 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 20 Jan 2015 12:51:57 +0100
-Subject: [PATCH 172/172] nss: Add original DN and memberOf to origbyname
- request
-
-IPA HBAC evaluation relies on the original values for DN and memberOf
-attributes.
-
-Resolves https://fedorahosted.org/sssd/ticket/2560
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 7543052f562f157f7b17fdc46a6777d80c0cb3bd)
----
- src/responder/nss/nsssrv_cmd.c  | 4 ++++
- src/tests/cmocka/test_nss_srv.c | 3 +--
- 2 files changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index 6b9988548cdb25873e0c59503595e42d69b8d8e1..324688eeeb90109a31391d01a9e1cd96707da7ed 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4160,6 +4160,8 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
-                                    SYSDB_AD_ACCOUNT_EXPIRES,
-                                    SYSDB_AD_USER_ACCOUNT_CONTROL,
-                                    SYSDB_SSH_PUBKEY,
-+                                   SYSDB_ORIG_DN,
-+                                   SYSDB_ORIG_MEMBEROF,
-                                    SYSDB_DEFAULT_ATTRS, NULL};
-     const char **attrs;
-     bool user_found = false;
-@@ -4688,6 +4690,8 @@ static errno_t fill_orig(struct sss_packet *packet,
-                                     SYSDB_AD_ACCOUNT_EXPIRES,
-                                     SYSDB_AD_USER_ACCOUNT_CONTROL,
-                                     SYSDB_SSH_PUBKEY,
-+                                    SYSDB_ORIG_DN,
-+                                    SYSDB_ORIG_MEMBEROF,
-                                     NULL};
-     struct sized_string *keys;
-     struct sized_string *vals;
-diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
-index d7825e4384a4cc91407ed4bc66a1e190d558369f..ba84fccf718c1a3f4a8ff20a54d8e82c2aa58a1e 100644
---- a/src/tests/cmocka/test_nss_srv.c
-+++ b/src/tests/cmocka/test_nss_srv.c
-@@ -52,8 +52,7 @@ struct nss_test_ctx {
-     bool ncache_hit;
- };
- 
--const char *global_extra_attrs[] = {"phone", "mobile", SYSDB_ORIG_MEMBEROF,
--                                    NULL};
-+const char *global_extra_attrs[] = {"phone", "mobile", NULL};
- 
- struct nss_test_ctx *nss_test_ctx;
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0173-Open-the-PAC-socket-from-krb5_child-before-dropping-.patch b/SOURCES/0173-Open-the-PAC-socket-from-krb5_child-before-dropping-.patch
deleted file mode 100644
index a78837d..0000000
--- a/SOURCES/0173-Open-the-PAC-socket-from-krb5_child-before-dropping-.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From 8e650486102cb0c60f54e43acecacffdf3858ada Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 20 Jan 2015 18:06:49 +0100
-Subject: [PATCH 173/173] Open the PAC socket from krb5_child before dropping
- root
-
-The PAC responder by default allows only connections from the root user.
-This patch opens the socket to the PAC responder before the krb5_child
-drops privileges so the connection seemingly comes from root.
-
-https://fedorahosted.org/sssd/ticket/2559
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 858e750c3d4fe54e50616a1ed1e101469503c070)
----
- src/providers/krb5/krb5_child.c |  8 ++++++++
- src/sss_client/common.c         | 13 +++++++++++++
- src/sss_client/sss_cli.h        |  6 ++++++
- 3 files changed, 27 insertions(+)
-
-diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
-index 39cd62846e3c58d65a87f670768cf699ae191f14..4c2f81fb122baa42e38e6f3d0ec5e2cf80ac5fa6 100644
---- a/src/providers/krb5/krb5_child.c
-+++ b/src/providers/krb5/krb5_child.c
-@@ -2305,6 +2305,14 @@ static krb5_error_code privileged_krb5_setup(struct krb5_req *kr,
-         }
-     }
- 
-+    if (kr->send_pac) {
-+        ret = sss_pac_check_and_open();
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_MINOR_FAILURE, "Cannot open the PAC responder socket\n");
-+            /* Not fatal */
-+        }
-+    }
-+
-     return 0;
- }
- 
-diff --git a/src/sss_client/common.c b/src/sss_client/common.c
-index 7c4bb7ab8769a72f943158366f358b108bfc3bdc..1b0fb1223f3509ef0b5aaf4a53851b868e12d6f0 100644
---- a/src/sss_client/common.c
-+++ b/src/sss_client/common.c
-@@ -749,6 +749,19 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
-     }
- }
- 
-+int sss_pac_check_and_open(void)
-+{
-+    enum sss_status ret;
-+    int errnop;
-+
-+    ret = sss_cli_check_socket(&errnop, SSS_PAC_SOCKET_NAME);
-+    if (ret != SSS_STATUS_SUCCESS) {
-+        return EIO;
-+    }
-+
-+    return EOK;
-+}
-+
- int sss_pac_make_request(enum sss_cli_command cmd,
-                          struct sss_cli_req_data *rd,
-                          uint8_t **repbuf, size_t *replen,
-diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
-index 2d909311cf2fa508a187ee4a29a45eae681dc705..6286077fcf25aead1dfcba5c6483e4ff8ae63b9f 100644
---- a/src/sss_client/sss_cli.h
-+++ b/src/sss_client/sss_cli.h
-@@ -511,6 +511,12 @@ int sss_pam_make_request(enum sss_cli_command cmd,
-                          int *errnop);
- void sss_pam_close_fd(void);
- 
-+/* Checks access to the PAC responder and opens the socket, if available.
-+ * Required for processes like krb5_child that need to open the socket
-+ * before dropping privs.
-+ */
-+int sss_pac_check_and_open(void);
-+
- int sss_pac_make_request(enum sss_cli_command cmd,
-                          struct sss_cli_req_data *rd,
-                          uint8_t **repbuf, size_t *replen,
--- 
-2.1.0
-
diff --git a/SOURCES/0174-views-fix-GID-overrride-for-mpg-domains.patch b/SOURCES/0174-views-fix-GID-overrride-for-mpg-domains.patch
deleted file mode 100644
index 9d5d603..0000000
--- a/SOURCES/0174-views-fix-GID-overrride-for-mpg-domains.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 4663b9a486964533183533046f7093e9a3a9b75b Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 21 Jan 2015 12:35:00 +0100
-Subject: [PATCH 174/176] views: fix GID overrride for mpg domains
-
-When adding a user sysdb internally adds a value to SYSDB_GIDNUM for
-mpg domain which might cause conflicts with the one we added to users
-git GID overrides. With this patch the override GID is added after the
-user is created but in the same transaction
-
-Releted to https://fedorahosted.org/sssd/ticket/2514
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit ba818cc39dfe94c2b8613f4badf7912811f0f737)
----
- src/providers/ipa/ipa_s2n_exop.c | 21 ++++++++++++++++++++-
- 1 file changed, 20 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index e7c2d9bb97908746eb5ab6cacc6fc58d353dea06..a9c2f1ae3955bc3d2707bbcd186609a8d76b6169 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1748,6 +1748,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-     char **del_groups_dns;
-     bool in_transaction = false;
-     int tret;
-+    struct sysdb_attrs *gid_override_attrs = NULL;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -1939,7 +1940,16 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                 if (ret == EOK || ret == ENOENT) {
-                     if ((orig_gid != 0 && orig_gid != attrs->a.user.pw_gid)
-                             || attrs->a.user.pw_uid != attrs->a.user.pw_gid) {
--                        ret = sysdb_attrs_add_uint32(attrs->sysdb_attrs,
-+
-+                        gid_override_attrs = sysdb_new_attrs(tmp_ctx);
-+                        if (gid_override_attrs == NULL) {
-+                            DEBUG(SSSDBG_OP_FAILURE,
-+                                  "sysdb_new_attrs failed.\n");
-+                            ret = ENOMEM;
-+                            goto done;
-+                        }
-+
-+                        ret = sysdb_attrs_add_uint32(gid_override_attrs,
-                                                      SYSDB_GIDNUM,
-                                                      attrs->a.user.pw_gid);
-                         if (ret != EOK) {
-@@ -1973,6 +1983,15 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                 goto done;
-             }
- 
-+            if (gid_override_attrs != NULL) {
-+                ret = sysdb_set_user_attr(dom, name, gid_override_attrs,
-+                                          SYSDB_MOD_REP);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_user_attr failed.\n");
-+                    goto done;
-+                }
-+            }
-+
-             if (attrs->response_type == RESP_USER_GROUPLIST) {
-                 ret = get_sysdb_grouplist(tmp_ctx, dom->sysdb, dom, name,
-                                           &sysdb_grouplist);
--- 
-2.1.0
-
diff --git a/SOURCES/0175-IPA-properly-handle-mixed-case-trusted-domains.patch b/SOURCES/0175-IPA-properly-handle-mixed-case-trusted-domains.patch
deleted file mode 100644
index 08b0a46..0000000
--- a/SOURCES/0175-IPA-properly-handle-mixed-case-trusted-domains.patch
+++ /dev/null
@@ -1,214 +0,0 @@
-From f3ddfba05798b694768316c82d609dec29e31642 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 22 Jan 2015 17:03:00 +0100
-Subject: [PATCH 175/176] IPA: properly handle mixed-case trusted domains
-
-In the SSSD cache domain names are handled case-sensitive. As a result
-fully-qualified names in RDN contain the domain part in the original
-spelling. When IPA client lookup up group-memberships on the IPA server
-via the extdom plugin the names returned are all lower case. To make
-sure new DNs are generated correctly the domain part must adjusted.
-
-Related to https://fedorahosted.org/sssd/ticket/2159
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 16 +++++++--
- src/tests/cmocka/test_utils.c    | 44 ++++++++++++++++++++++++
- src/util/domain_info_utils.c     | 72 ++++++++++++++++++++++++++++++++++++++++
- src/util/util.h                  |  3 ++
- 4 files changed, 133 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index a9c2f1ae3955bc3d2707bbcd186609a8d76b6169..997d0dce8d3225f83bbce506d349e4a8705e1e95 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1749,6 +1749,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-     bool in_transaction = false;
-     int tret;
-     struct sysdb_attrs *gid_override_attrs = NULL;
-+    char ** exop_grouplist;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -2000,8 +2001,19 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                     goto done;
-                 }
- 
--                ret = diff_string_lists(tmp_ctx, attrs->groups, sysdb_grouplist,
--                                        &add_groups, &del_groups, NULL);
-+                /* names returned by extdom exop will be all lower case, since
-+                 * we handle domain names case sensitve in the cache we have
-+                 * to make sure we use the right case. */
-+                ret = fix_domain_in_name_list(tmp_ctx, dom, attrs->groups,
-+                                              &exop_grouplist);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE, "fix_domain_name failed.\n");
-+                    goto done;
-+                }
-+
-+                ret = diff_string_lists(tmp_ctx, exop_grouplist,
-+                                        sysdb_grouplist, &add_groups,
-+                                        &del_groups, NULL);
-                 if (ret != EOK) {
-                     DEBUG(SSSDBG_OP_FAILURE, "diff_string_lists failed.\n");
-                     goto done;
-diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
-index 5dc00c4cc9707776fabda50ad1eab8e582b16c0f..dc6e35dc02204714c5befbf4d67e7e7cbd8f4af1 100644
---- a/src/tests/cmocka/test_utils.c
-+++ b/src/tests/cmocka/test_utils.c
-@@ -1030,6 +1030,48 @@ void test_sss_write_krb5_conf_snippet(void **state)
-     free(path);
- }
- 
-+
-+void test_fix_domain_in_name_list(void **state)
-+{
-+    struct name_init_test_ctx *test_ctx;
-+
-+    int ret;
-+    struct sss_domain_info *sd;
-+    struct sss_domain_info *dom;
-+    const char *in[] = { "abc@test.case.dom", "def@TEST.case.DOM", NULL};
-+    char **out = NULL;
-+
-+    test_ctx = talloc_get_type(*state, struct name_init_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    ret = confdb_get_domains(test_ctx->confdb, &dom);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sss_names_init(dom, test_ctx->confdb, NULL, &dom->names);
-+    assert_int_equal(ret, EOK);
-+
-+    sd = talloc_zero(test_ctx, struct sss_domain_info);
-+    assert_non_null(sd);
-+    sd->name = talloc_strdup(sd, "TesT.CasE.DoM");
-+    assert_non_null(sd->name);
-+    sd->names = dom->names;
-+    DLIST_ADD(dom->subdomains, sd);
-+    sd->parent = dom;
-+
-+    ret = fix_domain_in_name_list(test_ctx, dom, discard_const(in), &out);
-+    assert_int_equal(ret, EOK);
-+    assert_non_null(out);
-+    assert_non_null(out[0]);
-+    assert_string_equal(out[0], "abc@TesT.CasE.DoM");
-+    assert_non_null(out[1]);
-+    assert_string_equal(out[1], "def@TesT.CasE.DoM");
-+    assert_null(out[2]);
-+
-+    talloc_free(out);
-+    talloc_free(sd);
-+    talloc_free(dom);
-+}
-+
- int main(int argc, const char *argv[])
- {
-     poptContext pc;
-@@ -1078,6 +1120,8 @@ int main(int argc, const char *argv[])
-                                  setup_add_strings_lists,
-                                  teardown_add_strings_lists),
-         unit_test(test_sss_write_krb5_conf_snippet),
-+        unit_test_setup_teardown(test_fix_domain_in_name_list,
-+                                 confdb_test_setup, confdb_test_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
-index e04b905768078c503168f27327f974c0f19a6775..e0f1120e3c96757b0ad623b7dd6d43af2e643589 100644
---- a/src/util/domain_info_utils.c
-+++ b/src/util/domain_info_utils.c
-@@ -777,3 +777,75 @@ done:
- 
-     return ret;
- }
-+
-+errno_t fix_domain_in_name_list(TALLOC_CTX *mem_ctx,
-+                                struct sss_domain_info *dom,
-+                                char **in, char ***_out)
-+{
-+    int ret;
-+    size_t c;
-+    TALLOC_CTX *tmp_ctx;
-+    char **out;
-+    struct sss_domain_info *head;
-+    struct sss_domain_info *out_domain;
-+    char *in_name;
-+    char *in_domain;
-+
-+    head = get_domains_head(dom);
-+
-+    tmp_ctx = talloc_new(NULL);
-+    if (tmp_ctx == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-+        return ENOMEM;
-+    }
-+
-+    /* count elements */
-+    for (c = 0; in[c] != NULL; c++);
-+
-+    out = talloc_zero_array(tmp_ctx, char *, c + 1);
-+    if (out == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    for (c = 0; in[c] != NULL; c++) {
-+        ret = sss_parse_name(tmp_ctx, head->names, in[c], &in_domain,
-+                              &in_name);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sss_parse_name failed for [%s].\n",
-+                                      in[c]);
-+            goto done;
-+        }
-+
-+        if (in_domain == NULL) {
-+            out[c] = talloc_strdup(out, in_name);
-+        } else {
-+            out_domain = find_domain_by_name(head, in_domain, true);
-+            if (out_domain == NULL) {
-+                DEBUG(SSSDBG_CRIT_FAILURE,
-+                      "Cannot find domain with name [%s].\n", in_domain);
-+                ret = EINVAL;
-+                goto done;
-+            }
-+
-+            out[c] = sss_tc_fqname(out, head->names, out_domain, in_name);
-+        }
-+
-+        if (out[c] == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "%s failed.\n",
-+                  in_domain == NULL ? "talloc_strdup" : "sss_tc_fqname");
-+            ret = ENOMEM;
-+            goto done;
-+        }
-+    }
-+
-+    *_out = talloc_steal(mem_ctx, out);
-+
-+    ret = EOK;
-+
-+done:
-+    talloc_free(tmp_ctx);
-+
-+    return ret;
-+}
-diff --git a/src/util/util.h b/src/util/util.h
-index 45efd1aef94c2e058a435933e7c41adaecc676e2..23624c8156a053bc6c30bda9796029af3da62d3a 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -589,6 +589,9 @@ errno_t get_dom_names(TALLOC_CTX *mem_ctx,
-                       char ***_dom_names,
-                       int *_dom_names_count);
- 
-+errno_t fix_domain_in_name_list(TALLOC_CTX *mem_ctx,
-+                                struct sss_domain_info *dom,
-+                                char **in, char ***_out);
- /* from util_lock.c */
- errno_t sss_br_lock_file(int fd, size_t start, size_t len,
-                          int num_tries, useconds_t wait);
--- 
-2.1.0
-
diff --git a/SOURCES/0176-nss-fix-SID-lookups.patch b/SOURCES/0176-nss-fix-SID-lookups.patch
deleted file mode 100644
index 28b9dfc..0000000
--- a/SOURCES/0176-nss-fix-SID-lookups.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 660d1493ad63cc39f99e3d2fb981598fab404b82 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 22 Jan 2015 18:30:04 +0100
-Subject: [PATCH 176/176] nss: fix SID lookups
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-https://fedorahosted.org/sssd/ticket/2566
-
-Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
----
- src/responder/nss/nsssrv_cmd.c | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index 324688eeeb90109a31391d01a9e1cd96707da7ed..da24ce1730999518b2e1bc52604940ee979072e3 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4503,8 +4503,16 @@ static errno_t nss_cmd_getbysid_search(struct nss_dom_ctx *dctx)
-                 DEBUG(SSSDBG_MINOR_FAILURE,
-                       "Cannot set negative cache for %s\n", cmdctx->secid);
-             }
-+
-+            return ENOENT;
-         }
--        return ENOENT;
-+
-+        dctx->res = talloc_zero(cmdctx, struct ldb_result);
-+        if (dctx->res == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n");
-+            return ENOMEM;
-+        }
-+        /* Fall through and call the backend */
-     } else if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache!\n");
-         return EIO;
--- 
-2.1.0
-
diff --git a/SOURCES/0177-sysdb-remove-ghosts-in-all-sub-domains-as-well.patch b/SOURCES/0177-sysdb-remove-ghosts-in-all-sub-domains-as-well.patch
deleted file mode 100644
index 2f46254..0000000
--- a/SOURCES/0177-sysdb-remove-ghosts-in-all-sub-domains-as-well.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 8a18e0f42e45a29ca78f5ec2c21987cd8df3474d Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 23 Jan 2015 14:39:07 +0100
-Subject: [PATCH 177/177] sysdb: remove ghosts in all sub-domains as well
-
-If a user is a member is a group in a different sub-domain, e.g with
-universal groups in AD, the ghost attribute might not be properly
-removed from the group object if the user is resolved. The reason is
-that only groups from the domain of the user were search for ghost
-attributes. This patch increases the search-base to all sub-domains of
-the configured SSSD domain.
-
-Resolves https://fedorahosted.org/sssd/ticket/2567
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit fc2146c108e28d50bbf691925cedf9592142dd14)
----
- src/db/sysdb_ops.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
-index b12540b68d1c81c419455416294f3449dd84914e..0c254d8cdad1144c32aad7e470fa2a35cd24b38b 100644
---- a/src/db/sysdb_ops.c
-+++ b/src/db/sysdb_ops.c
-@@ -1219,8 +1219,9 @@ sysdb_remove_ghostattr_from_groups(struct sss_domain_info *domain,
-         ERROR_OUT(ret, EINVAL, done);
-     }
- 
--    tmpdn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
--                            SYSDB_TMPL_GROUP_BASE, domain->name);
-+    /* To cover cross-domain group-membership we must search in all
-+     * sub-domains. */
-+    tmpdn = ldb_dn_new(tmp_ctx, domain->sysdb->ldb, SYSDB_BASE);
-     if (!tmpdn) {
-         ret = ENOMEM;
-         goto done;
--- 
-2.1.0
-
diff --git a/SOURCES/0178-IPA-Rename-user_dom-into-obj_dom.patch b/SOURCES/0178-IPA-Rename-user_dom-into-obj_dom.patch
deleted file mode 100644
index f6032a8..0000000
--- a/SOURCES/0178-IPA-Rename-user_dom-into-obj_dom.patch
+++ /dev/null
@@ -1,113 +0,0 @@
-From 943d1b32aeb8cbddccbe3a499504ec07955937b5 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 30 Oct 2014 17:38:19 +0100
-Subject: [PATCH 178/181] IPA: Rename user_dom into obj_dom
-
-There was a variable in the IPA subdomain code named user_dom, however,
-it was used in code that processes both users and groups, which was
-confusing.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
----
- src/providers/ipa/ipa_subdomains_id.c | 24 ++++++++++++------------
- 1 file changed, 12 insertions(+), 12 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index cf0cddf6884295268b30fc8e0209b543c1699297..79285548d9470b34d66b366367fb69ef57710f83 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -539,7 +539,7 @@ struct ipa_get_ad_acct_state {
-     struct ipa_id_ctx *ipa_ctx;
-     struct be_req *be_req;
-     struct be_acct_req *ar;
--    struct sss_domain_info *user_dom;
-+    struct sss_domain_info *obj_dom;
-     char *object_sid;
-     struct sysdb_attrs *override_attrs;
-     struct ldb_message *obj_msg;
-@@ -581,15 +581,15 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
-     state->override_attrs = override_attrs;
- 
-     /* This can only be a subdomain request, verify subdomain */
--    state->user_dom = find_domain_by_name(ipa_ctx->sdap_id_ctx->be->domain,
--                                          ar->domain, true);
--    if (state->user_dom == NULL) {
-+    state->obj_dom = find_domain_by_name(ipa_ctx->sdap_id_ctx->be->domain,
-+                                         ar->domain, true);
-+    if (state->obj_dom == NULL) {
-         ret = EINVAL;
-         goto fail;
-     }
- 
-     /* Let's see if this subdomain has a ad_id_ctx */
--    ad_id_ctx = ipa_get_ad_id_ctx(ipa_ctx, state->user_dom);
-+    ad_id_ctx = ipa_get_ad_id_ctx(ipa_ctx, state->obj_dom);
-     if (ad_id_ctx == NULL) {
-         ret = EINVAL;
-         goto fail;
-@@ -604,7 +604,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
-     switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
-     case BE_REQ_INITGROUPS:
-     case BE_REQ_GROUP:
--        clist = ad_gc_conn_list(req, ad_id_ctx, state->user_dom);
-+        clist = ad_gc_conn_list(req, ad_id_ctx, state->obj_dom);
-         if (clist == NULL) {
-             ret = ENOMEM;
-             goto fail;
-@@ -621,7 +621,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
-     }
- 
-     /* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */
--    sdom = sdap_domain_get(sdap_id_ctx->opts, state->user_dom);
-+    sdom = sdap_domain_get(sdap_id_ctx->opts, state->obj_dom);
-     if (sdom == NULL) {
-         ret = EIO;
-         goto fail;
-@@ -988,7 +988,7 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
-         return;
-     }
- 
--    ret = get_object_from_cache(state, state->user_dom, state->ar,
-+    ret = get_object_from_cache(state, state->obj_dom, state->ar,
-                                 &state->obj_msg);
-     if (ret == ENOENT) {
-         DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n");
-@@ -999,7 +999,7 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
-         goto fail;
-     }
- 
--    ret = apply_subdomain_homedir(state, state->user_dom,
-+    ret = apply_subdomain_homedir(state, state->obj_dom,
-                                   state->obj_msg);
-     if (ret != EOK && ret != ENOENT) {
-         DEBUG(SSSDBG_OP_FAILURE,
-@@ -1024,7 +1024,7 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq)
-         }
- 
-         ret = get_be_acct_req_for_sid(state, state->object_sid,
--                                      state->user_dom->name, &ar);
-+                                      state->obj_dom->name, &ar);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
-             goto fail;
-@@ -1103,7 +1103,7 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
-     if (state->override_attrs != NULL) {
-         /* We are in ipa-server-mode, so the view is the default view by
-          * definition. */
--        ret = sysdb_apply_default_override(state->user_dom,
-+        ret = sysdb_apply_default_override(state->obj_dom,
-                                            state->override_attrs,
-                                            state->obj_msg->dn);
-         if (ret != EOK) {
-@@ -1121,7 +1121,7 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
-      * users. */
-     subreq = ipa_get_ad_memberships_send(state, state->ev, state->ar,
-                                          state->ipa_ctx->server_mode,
--                                         state->user_dom,
-+                                         state->obj_dom,
-                                          state->ipa_ctx->sdap_id_ctx,
-                                          state->ipa_ctx->server_mode->realm);
-     if (subreq == NULL) {
--- 
-2.1.0
-
diff --git a/SOURCES/0179-IPA-resolve-IPA-group-memberships-for-AD-users.patch b/SOURCES/0179-IPA-resolve-IPA-group-memberships-for-AD-users.patch
deleted file mode 100644
index b5f9b2f..0000000
--- a/SOURCES/0179-IPA-resolve-IPA-group-memberships-for-AD-users.patch
+++ /dev/null
@@ -1,107 +0,0 @@
-From a3fc740fbfbfd5a2771a3872cf03287879c957c3 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 22 Jan 2015 21:20:25 +0100
-Subject: [PATCH 179/181] IPA: resolve IPA group-memberships for AD users
-
-So far only for initgroups requests the IPA group memberships where
-resolved for AD users and due to
-6fac5e5f0c54a0f92872ce1450606cfcb577a920 those memberships are not
-overridden by other request. But it turned out that the originalMemberOf
-attributes related to the IPA group memberships can be overridden by
-user lookups.  Since the originalMemberOf attribute is important in the
-HBAC evaluation this patch makes sure that the originalMemberOf
-attribute is not removed but updated during user lookups.
-
-Related to https://fedorahosted.org/sssd/ticket/2560
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 63748c69a2c6785d949c82f94749704e0408e5a7)
----
- src/providers/ipa/ipa_subdomains_ext_groups.c |  3 +-
- src/providers/ipa/ipa_subdomains_id.c         | 44 +++++++++++++++++++++++++--
- 2 files changed, 44 insertions(+), 3 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c
-index 6feca44de537f4c721bfe4ea5e3fde1b946e4aac..b9690bdb682a9348340d22d4b24f0f284671610d 100644
---- a/src/providers/ipa/ipa_subdomains_ext_groups.c
-+++ b/src/providers/ipa/ipa_subdomains_ext_groups.c
-@@ -452,7 +452,8 @@ struct tevent_req *ipa_get_ad_memberships_send(TALLOC_CTX *mem_ctx,
-     state->domain = domain;
-     state->dp_error = -1;
- 
--    if ((ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS
-+    if (((ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS
-+            && (ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_USER)
-             || ar->filter_type != BE_FILTER_NAME) {
-         DEBUG(SSSDBG_OP_FAILURE, "Unsupported request type.\n");
-         ret = EINVAL;
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index 79285548d9470b34d66b366367fb69ef57710f83..c8714a216daff7506f00248e25c281529d0479c4 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -1099,6 +1099,8 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
-                                                 struct ipa_get_ad_acct_state);
-     errno_t ret;
-     struct tevent_req *subreq;
-+    const char *obj_name;
-+    int entry_type;
- 
-     if (state->override_attrs != NULL) {
-         /* We are in ipa-server-mode, so the view is the default view by
-@@ -1112,13 +1114,51 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
-         }
-     }
- 
--    if ((state->ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS) {
-+    entry_type = (state->ar->entry_type & BE_REQ_TYPE_MASK);
-+    if (entry_type != BE_REQ_INITGROUPS
-+            && entry_type != BE_REQ_USER
-+            && entry_type != BE_REQ_BY_SECID) {
-         tevent_req_done(req);
-         return EOK;
-     }
- 
-+    /* Replace ID with name in search filter */
-+    if ((entry_type == BE_REQ_USER && state->ar->filter_type == BE_FILTER_IDNUM)
-+            || entry_type == BE_REQ_BY_SECID) {
-+        if (state->obj_msg == NULL) {
-+            ret = get_object_from_cache(state, state->obj_dom, state->ar,
-+                                        &state->obj_msg);
-+            if (ret == ENOENT) {
-+                DEBUG(SSSDBG_MINOR_FAILURE,
-+                      "Object not found, ending request\n");
-+                tevent_req_done(req);
-+                return EOK;
-+            } else if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
-+                return ret;
-+            }
-+        }
-+
-+        obj_name = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_NAME,
-+                                               NULL);
-+        if (obj_name == NULL) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "Cached object has no name.\n");
-+            return EINVAL;
-+        }
-+
-+        state->ar->filter_value = talloc_strdup(state->ar, obj_name);
-+        if (state->ar->filter_value == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+            return ENOMEM;
-+        }
-+        state->ar->filter_type = BE_FILTER_NAME;
-+        state->ar->entry_type = BE_REQ_USER;
-+    }
-+
-+
-     /* For initgroups request we have to check IPA group memberships of AD
--     * users. */
-+     * users. This has to be done for other user-request as well to make sure
-+     * IPA related attributes are not overwritten. */
-     subreq = ipa_get_ad_memberships_send(state, state->ev, state->ar,
-                                          state->ipa_ctx->server_mode,
-                                          state->obj_dom,
--- 
-2.1.0
-
diff --git a/SOURCES/0180-IPA-process_members-add-ghosts-only-once.patch b/SOURCES/0180-IPA-process_members-add-ghosts-only-once.patch
deleted file mode 100644
index 6b795c2..0000000
--- a/SOURCES/0180-IPA-process_members-add-ghosts-only-once.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 11277f49cabdf4b7b49dba05dc4db9c2e5ffe53b Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 21 Jan 2015 16:33:59 +0100
-Subject: [PATCH 180/181] IPA: process_members() add ghosts only once
-
-Since ghost entries might not be properly removed on the IPA server
-(https://fedorahosted.org/sssd/ticket/2567) chances are that during
-extdom group lookups a single user is returned multiple time. This patch
-removes the duplicates before trying to write the data to the cache.
-
-Related to https://fedorahosted.org/sssd/ticket/2159
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 60f11e2fa1f63cd40ebace525ad823b0360fac94)
----
- src/providers/ipa/ipa_s2n_exop.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 997d0dce8d3225f83bbce506d349e4a8705e1e95..6f8d5687d66717ba62e83da27dd6b23bc12151fb 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1299,8 +1299,10 @@ static errno_t process_members(struct sss_domain_info *domain,
-                 DEBUG(SSSDBG_TRACE_ALL, "Adding ghost member [%s]\n",
-                                         members[c]);
- 
--                ret = sysdb_attrs_add_string(group_attrs, SYSDB_GHOST,
--                                             members[c]);
-+                /* There were cases where the server returned the same user
-+                 * multiple times */
-+                ret = sysdb_attrs_add_string_safe(group_attrs, SYSDB_GHOST,
-+                                                  members[c]);
-                 if (ret != EOK) {
-                     DEBUG(SSSDBG_OP_FAILURE,
-                           "sysdb_attrs_add_string failed.\n");
--- 
-2.1.0
-
diff --git a/SOURCES/0181-IPA-Use-attr-s-dom-for-users-too.patch b/SOURCES/0181-IPA-Use-attr-s-dom-for-users-too.patch
deleted file mode 100644
index 83f9296..0000000
--- a/SOURCES/0181-IPA-Use-attr-s-dom-for-users-too.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From 8ffc33de4e1ea85159ee72178efafaac060a8c3b Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 26 Jan 2015 20:29:37 +0100
-Subject: [PATCH 181/181] IPA: Use attr's dom for users, too
-
-The 'dom' pointer points to domain of the main object being saved. In
-case of group, dom points to the domain where the group resides. But
-when saving members, each members might be from a different domain, so we
-need to find every member's domain based on the attributes.
-
-Also don't use Yoda style in conditions.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit b2c5e98def89a0c3d16f5cf7e07ce2020338b540)
----
- src/providers/ipa/ipa_s2n_exop.c | 22 +++++++++++-----------
- 1 file changed, 11 insertions(+), 11 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 6f8d5687d66717ba62e83da27dd6b23bc12151fb..35bd303d4aa3651e80c70297507bdc85d05bfbde 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1819,6 +1819,17 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-         }
-     }
- 
-+    if (strcmp(dom->name, attrs->domain_name) != 0) {
-+        dom = find_domain_by_name(get_domains_head(dom),
-+                                  attrs->domain_name, true);
-+        if (dom == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                    "Cannot find domain: [%s]\n", attrs->domain_name);
-+            ret = EINVAL;
-+            goto done;
-+        }
-+    }
-+
-     switch (attrs->response_type) {
-         case RESP_USER:
-         case RESP_USER_GROUPLIST:
-@@ -2057,17 +2068,6 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-         case RESP_GROUP_MEMBERS:
-             type = SYSDB_MEMBER_GROUP;
- 
--            if (0 != strcmp(dom->name, attrs->domain_name)) {
--                dom = find_domain_by_name(get_domains_head(dom),
--                                          attrs->domain_name, true);
--                if (dom == NULL) {
--                    DEBUG(SSSDBG_OP_FAILURE,
--                          "Cannot find domain: [%s]\n", attrs->domain_name);
--                    ret = EINVAL;
--                    goto done;
--                }
--            }
--
-             if (name == NULL) {
-                 name = attrs->a.group.gr_name;
-             }
--- 
-2.1.0
-
diff --git a/SOURCES/0182-SELINUX-Call-setuid-0-setgid-0-to-also-set-the-real-.patch b/SOURCES/0182-SELINUX-Call-setuid-0-setgid-0-to-also-set-the-real-.patch
deleted file mode 100644
index 92e600e..0000000
--- a/SOURCES/0182-SELINUX-Call-setuid-0-setgid-0-to-also-set-the-real-.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From a77f0b5c39b1f6c497b2b5c6c072d2f4f6e7a745 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 26 Jan 2015 15:15:29 +0100
-Subject: [PATCH 182/183] SELINUX: Call setuid(0)/setgid(0) to also set the
- real IDs to root
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-https://fedorahosted.org/sssd/ticket/2564
-
-libselinux uses many access(2) calls and access() uses the real UID,
-not the effective UID for the check. Therefore, the setuid selinux_child,
-which only has effective UID of root would fail the check.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
-(cherry picked from commit 486f0d5227a9b81815aaaf7d9a2c39aafcbfdf6a)
----
- src/providers/ipa/selinux_child.c | 18 +++++++++++++++++-
- 1 file changed, 17 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
-index a38ffcb26f890349f47478063103e603fe6304cf..bda89c847dc160e1d667d333ee515cf7260e7db8 100644
---- a/src/providers/ipa/selinux_child.c
-+++ b/src/providers/ipa/selinux_child.c
-@@ -197,7 +197,23 @@ int main(int argc, const char *argv[])
- 
-     DEBUG(SSSDBG_TRACE_FUNC, "selinux_child started.\n");
-     DEBUG(SSSDBG_TRACE_INTERNAL,
--          "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid());
-+          "Running with effective IDs: [%"SPRIuid"][%"SPRIgid"].\n",
-+          geteuid(), getegid());
-+
-+    /* libsemanage calls access(2) which works with real IDs, not effective.
-+     * We need to switch also the real ID to 0.
-+     */
-+    if (getuid() != 0) {
-+        setuid(0);
-+    }
-+
-+    if (getgid() != 0) {
-+        setgid(0);
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_INTERNAL,
-+          "Running with real IDs [%"SPRIuid"][%"SPRIgid"].\n",
-+          getuid(), getgid());
- 
-     main_ctx = talloc_new(NULL);
-     if (main_ctx == NULL) {
--- 
-2.1.0
-
diff --git a/SOURCES/0183-SELINUX-Set-and-reset-umask-when-caling-set_seuser-f.patch b/SOURCES/0183-SELINUX-Set-and-reset-umask-when-caling-set_seuser-f.patch
deleted file mode 100644
index 2753cc8..0000000
--- a/SOURCES/0183-SELINUX-Set-and-reset-umask-when-caling-set_seuser-f.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From 20dd4c33d226862d124b2f010181550e820df5f8 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 27 Jan 2015 11:12:18 +0100
-Subject: [PATCH 183/183] SELINUX: Set and reset umask when caling set_seuser
- from deamon code
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-https://fedorahosted.org/sssd/ticket/2563
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
-(cherry picked from commit 8f78b6442f3176ee43aa06704a3adb9f4ac625d6)
----
- src/providers/ipa/selinux_child.c | 18 +++++++++++++++++-
- src/util/util.h                   |  4 ++++
- 2 files changed, 21 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
-index bda89c847dc160e1d667d333ee515cf7260e7db8..d4670389667607972dd6f072b5ddfda5973e082b 100644
---- a/src/providers/ipa/selinux_child.c
-+++ b/src/providers/ipa/selinux_child.c
-@@ -135,6 +135,22 @@ static errno_t prepare_response(TALLOC_CTX *mem_ctx,
-     return EOK;
- }
- 
-+static int sc_set_seuser(const char *login_name, const char *seuser_name,
-+                         const char *mls)
-+{
-+    int ret;
-+    mode_t old_mask;
-+
-+    /* This is a workaround for
-+     * https://bugzilla.redhat.com/show_bug.cgi?id=1186422 to make sure
-+     * the directories are created with the expected permissions
-+     */
-+    old_mask = umask(0);
-+    ret = set_seuser(login_name, seuser_name, mls);
-+    umask(old_mask);
-+    return ret;
-+}
-+
- int main(int argc, const char *argv[])
- {
-     int opt;
-@@ -256,7 +272,7 @@ int main(int argc, const char *argv[])
- 
-     DEBUG(SSSDBG_TRACE_FUNC, "performing selinux operations\n");
- 
--    ret = set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
-+    ret = sc_set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set SELinux login context.\n");
-         goto fail;
-diff --git a/src/util/util.h b/src/util/util.h
-index 23624c8156a053bc6c30bda9796029af3da62d3a..bf3a9a057aed77e93949370f8651af2631d91432 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -628,6 +628,10 @@ errno_t switch_creds(TALLOC_CTX *mem_ctx,
- errno_t restore_creds(struct sss_creds *saved_creds);
- 
- /* from sss_semanage.c */
-+/* Please note that libsemange relies on files and directories created with
-+ * certain permissions. Therefore the caller should make sure the umask is
-+ * not too restricted (especially when called from the daemon code).
-+ */
- int set_seuser(const char *login_name, const char *seuser_name,
-                const char *mlsrange);
- int del_seuser(const char *login_name);
--- 
-2.1.0
-
diff --git a/SOURCES/0184-LDAP-Add-UUID-when-saving-incomplete-groups.patch b/SOURCES/0184-LDAP-Add-UUID-when-saving-incomplete-groups.patch
deleted file mode 100644
index 5a0250d..0000000
--- a/SOURCES/0184-LDAP-Add-UUID-when-saving-incomplete-groups.patch
+++ /dev/null
@@ -1,171 +0,0 @@
-From 1c1551628ca2d1f7a6cc0938f0cf79c2b2ce6e8b Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 27 Jan 2015 16:02:33 +0100
-Subject: [PATCH 184/188] LDAP: Add UUID when saving incomplete groups
-
-Related to:
-https://fedorahosted.org/sssd/ticket/2571
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 108db0e3b9e06e530364ef8228634f5e3f6bd3b5)
----
- src/db/sysdb.h                                |  1 +
- src/db/sysdb_ops.c                            |  6 ++++++
- src/providers/ldap/sdap_async_initgroups.c    | 16 +++++++++++++---
- src/providers/ldap/sdap_async_initgroups_ad.c |  2 +-
- src/tests/sysdb-tests.c                       | 16 ++++++++--------
- 5 files changed, 29 insertions(+), 12 deletions(-)
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index 9e33fee37a352498ed0c987dc2ae0da3500d63d5..cf6028acb806d5d4eedf4cf0680cf4ac9fd6368d 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -797,6 +797,7 @@ int sysdb_add_incomplete_group(struct sss_domain_info *domain,
-                                gid_t gid,
-                                const char *original_dn,
-                                const char *sid_str,
-+                               const char *uuid,
-                                bool posix,
-                                time_t now);
- 
-diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
-index 0c254d8cdad1144c32aad7e470fa2a35cd24b38b..6085762dcc5585114dd3049dd3a365856cb6b190 100644
---- a/src/db/sysdb_ops.c
-+++ b/src/db/sysdb_ops.c
-@@ -1610,6 +1610,7 @@ int sysdb_add_incomplete_group(struct sss_domain_info *domain,
-                                gid_t gid,
-                                const char *original_dn,
-                                const char *sid_str,
-+                               const char *uuid,
-                                bool posix,
-                                time_t now)
- {
-@@ -1656,6 +1657,11 @@ int sysdb_add_incomplete_group(struct sss_domain_info *domain,
-         if (ret) goto done;
-     }
- 
-+    if (uuid) {
-+        ret = sysdb_attrs_add_string(attrs, SYSDB_UUID, uuid);
-+        if (ret) goto done;
-+    }
-+
-     ret = sysdb_set_group_attr(domain, name, attrs, SYSDB_MOD_REP);
- 
- done:
-diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
-index d3e080013ec99c18648c6a57e478d50eb3b666f1..6b3179d2d6bb30b3b00aa35b07da42de3cf08a34 100644
---- a/src/providers/ldap/sdap_async_initgroups.c
-+++ b/src/providers/ldap/sdap_async_initgroups.c
-@@ -41,6 +41,7 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-     int i, mi, ai;
-     const char *groupname;
-     const char *original_dn;
-+    const char *uuid = NULL;
-     char **missing;
-     gid_t gid;
-     int ret;
-@@ -191,15 +192,24 @@ static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-                                              &original_dn);
-                 if (ret) {
-                     DEBUG(SSSDBG_FUNC_DATA,
--                          "The group has no name original DN\n");
-+                          "The group has no original DN\n");
-                     original_dn = NULL;
-                 }
- 
-+                ret = sysdb_attrs_get_string(ldap_groups[ai],
-+                                             SYSDB_UUID,
-+                                             &uuid);
-+                if (ret) {
-+                    DEBUG(SSSDBG_FUNC_DATA,
-+                          "The group has no UUID\n");
-+                    uuid = NULL;
-+                }
-+
-                 DEBUG(SSSDBG_TRACE_INTERNAL,
-                       "Adding fake group %s to sysdb\n", groupname);
-                 ret = sysdb_add_incomplete_group(domain, groupname, gid,
--                                                 original_dn, sid_str, posix,
--                                                 now);
-+                                                 original_dn, sid_str,
-+                                                 uuid, posix, now);
-                 if (ret != EOK) {
-                     goto done;
-                 }
-diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
-index a533279f680d5cabc096cb9e64cfdb1057c5c799..1b8c8d981ea14ac0fca0903f16296c8a6701c5dd 100644
---- a/src/providers/ldap/sdap_async_initgroups_ad.c
-+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
-@@ -929,7 +929,7 @@ static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq)
-              * it will replace this temporary entry. */
-             name = sid;
-             ret = sysdb_add_incomplete_group(domain, name, gid,
--                                             NULL, sid, false, now);
-+                                             NULL, sid, NULL, false, now);
-             if (ret != EOK) {
-                 DEBUG(SSSDBG_MINOR_FAILURE, "Could not create incomplete "
-                                              "group: [%s]\n", strerror(ret));
-diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
-index 0c49d0ca7ca89d772f2a7df2ddd4acc20c4e312c..a78cf713fbe165204708bcf787b998acab0b7ca5 100644
---- a/src/tests/sysdb-tests.c
-+++ b/src/tests/sysdb-tests.c
-@@ -266,7 +266,7 @@ static int test_add_incomplete_group(struct test_data *data)
-     int ret;
- 
-     ret = sysdb_add_incomplete_group(data->ctx->domain, data->groupname,
--                                     data->gid, NULL, NULL, true, 0);
-+                                     data->gid, NULL, NULL, NULL, true, 0);
-     return ret;
- }
- 
-@@ -3986,8 +3986,8 @@ START_TEST(test_odd_characters)
-     /* ===== Groups ===== */
- 
-     /* Add */
--    ret = sysdb_add_incomplete_group(test_ctx->domain,
--                                     odd_groupname, 20000, NULL, NULL, true, 0);
-+    ret = sysdb_add_incomplete_group(test_ctx->domain, odd_groupname,
-+                                     20000, NULL, NULL, NULL, true, 0);
-     fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
-                             ret, strerror(ret));
- 
-@@ -4143,8 +4143,8 @@ START_TEST(test_SSS_LDB_SEARCH)
-     fail_if(nonexist_dn == NULL, "sysdb_group_dn failed");
- 
-     /* Add */
--    ret = sysdb_add_incomplete_group(test_ctx->domain,
--                                     groupname, 20000, NULL, NULL, true, 0);
-+    ret = sysdb_add_incomplete_group(test_ctx->domain, groupname,
-+                                     20000, NULL, NULL, NULL, true, 0);
-     fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
-                 ret, strerror(ret));
- 
-@@ -4935,14 +4935,14 @@ START_TEST(test_sysdb_original_dn_case_insensitive)
-     ret = sysdb_add_incomplete_group(test_ctx->domain,
-                                      "case_sensitive_group1", 29000,
-                                      "cn=case_sensitive_group1,cn=example,cn=com",
--                                     NULL, true, 0);
-+                                     NULL, NULL, true, 0);
-     fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
-                             ret, strerror(ret));
- 
-     ret = sysdb_add_incomplete_group(test_ctx->domain,
-                                      "case_sensitive_group2", 29001,
-                                      "cn=CASE_SENSITIVE_GROUP1,cn=EXAMPLE,cn=COM",
--                                     NULL, true, 0);
-+                                     NULL, NULL, true, 0);
-     fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
-                             ret, strerror(ret));
- 
-@@ -4978,7 +4978,7 @@ START_TEST(test_sysdb_search_sid_str)
-     ret = sysdb_add_incomplete_group(test_ctx->domain,
-                                      "group", 29000,
-                                      "cn=group,cn=example,cn=com",
--                                     "S-1-2-3-4", true, 0);
-+                                     "S-1-2-3-4", NULL, true, 0);
-     fail_unless(ret == EOK, "sysdb_add_incomplete_group error [%d][%s]",
-                             ret, strerror(ret));
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0185-IPA-Resolve-IPA-user-groups-overrideDN-in-non-defaul.patch b/SOURCES/0185-IPA-Resolve-IPA-user-groups-overrideDN-in-non-defaul.patch
deleted file mode 100644
index d50be0a..0000000
--- a/SOURCES/0185-IPA-Resolve-IPA-user-groups-overrideDN-in-non-defaul.patch
+++ /dev/null
@@ -1,395 +0,0 @@
-From 85d5f67d94ea38a3dc920b3fe85aba7385930b81 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Mon, 26 Jan 2015 23:25:17 +0100
-Subject: [PATCH 185/188] IPA: Resolve IPA user groups' overrideDN in
- non-default view
-
-When the client is in a non-default view, we need to store the override
-data, in particular the overrideDN as well.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2571
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit b2c3722b9a1eaf265f6b102043958f6d4378788c)
----
- src/providers/ipa/ipa_id.c | 318 ++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 311 insertions(+), 7 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
-index 3d6861eeb562683518d425616b0e5c413cddba0b..cc6abcf8721e3f05526bf62063f0cbdc7c1c257b 100644
---- a/src/providers/ipa/ipa_id.c
-+++ b/src/providers/ipa/ipa_id.c
-@@ -286,6 +286,239 @@ static int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error)
-     return EOK;
- }
- 
-+struct ipa_initgr_get_overrides_state {
-+    struct tevent_context *ev;
-+    struct ipa_id_ctx *ipa_ctx;
-+    struct sss_domain_info *user_dom;
-+    const char *realm;
-+
-+    struct ldb_message **groups;
-+    size_t group_count;
-+    size_t group_idx;
-+    struct be_acct_req *ar;
-+
-+    int dp_error;
-+};
-+
-+static int ipa_initgr_get_overrides_step(struct tevent_req *req);
-+
-+static struct tevent_req *
-+ipa_initgr_get_overrides_send(TALLOC_CTX *memctx,
-+                             struct tevent_context *ev,
-+                             struct ipa_id_ctx *ipa_ctx,
-+                             struct sss_domain_info *user_dom,
-+                             size_t groups_count,
-+                             struct ldb_message **groups)
-+{
-+    int ret;
-+    struct tevent_req *req;
-+    struct ipa_initgr_get_overrides_state *state;
-+
-+    req = tevent_req_create(memctx, &state,
-+                            struct ipa_initgr_get_overrides_state);
-+    if (req == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
-+        return NULL;
-+    }
-+    state->ev = ev;
-+    state->ipa_ctx = ipa_ctx;
-+    state->user_dom = user_dom;
-+    state->groups = groups;
-+    state->group_count = groups_count;
-+    state->group_idx = 0;
-+    state->ar = NULL;
-+    state->realm = dp_opt_get_string(state->ipa_ctx->ipa_options->basic,
-+                                     IPA_KRB5_REALM);
-+    if (state->realm == NULL) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "No Kerberos realm for IPA?\n");
-+        ret = EINVAL;
-+        goto done;
-+    }
-+
-+    ret = ipa_initgr_get_overrides_step(req);
-+done:
-+    if (ret == EOK) {
-+        tevent_req_done(req);
-+        tevent_req_post(req, ev);
-+    } else if (ret != EAGAIN) {
-+        tevent_req_error(req, ret);
-+        tevent_req_post(req, ev);
-+    }
-+
-+    return req;
-+}
-+
-+static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq);
-+
-+static int ipa_initgr_get_overrides_step(struct tevent_req *req)
-+{
-+    int ret;
-+    struct tevent_req *subreq;
-+    const char *ipa_uuid;
-+    struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
-+                                        struct ipa_initgr_get_overrides_state);
-+
-+    DEBUG(SSSDBG_TRACE_LIBS,
-+          "Processing group %zu/%zu\n", state->group_idx, state->group_count);
-+
-+    if (state->group_idx >= state->group_count) {
-+        return EOK;
-+    }
-+
-+    ipa_uuid = ldb_msg_find_attr_as_string(state->groups[state->group_idx],
-+                                            SYSDB_UUID, NULL);
-+    if (ipa_uuid == NULL) {
-+        /* This should never happen, the search filter used to get the list
-+         * of groups includes "uuid=*"
-+         */
-+        DEBUG(SSSDBG_OP_FAILURE, "A group with no UUID, error!\n");
-+        return EINVAL;
-+    }
-+
-+    talloc_free(state->ar); /* Avoid spiking memory with many groups */
-+
-+    ret = get_be_acct_req_for_uuid(state, ipa_uuid,
-+                                   state->user_dom->name, &state->ar);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
-+        return ret;
-+    }
-+
-+    DEBUG(SSSDBG_TRACE_LIBS, "Fetching group %s\n", ipa_uuid);
-+
-+    subreq = ipa_get_ad_override_send(state, state->ev,
-+                                      state->ipa_ctx->sdap_id_ctx,
-+                                      state->ipa_ctx->ipa_options,
-+                                      state->realm,
-+                                      state->ipa_ctx->view_name,
-+                                      state->ar);
-+    if (subreq == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_override_send failed.\n");
-+        return ENOMEM;
-+    }
-+    tevent_req_set_callback(subreq,
-+                            ipa_initgr_get_overrides_override_done, req);
-+    return EAGAIN;
-+}
-+
-+static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
-+                                        struct ipa_initgr_get_overrides_state);
-+    int ret;
-+    struct sysdb_attrs *override_attrs;
-+
-+    ret = ipa_get_ad_override_recv(subreq, &state->dp_error, state,
-+                                   &override_attrs);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    ret = sysdb_store_override(state->user_dom, state->ipa_ctx->view_name,
-+                               SYSDB_MEMBER_GROUP,
-+                               override_attrs,
-+                               state->groups[state->group_idx]->dn);
-+    talloc_free(override_attrs);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    state->group_idx++;
-+
-+    ret = ipa_initgr_get_overrides_step(req);
-+    if (ret == EAGAIN) {
-+        return;
-+    } else if (ret != EOK) {
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    tevent_req_done(req);
-+}
-+
-+static int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error)
-+{
-+    struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
-+                                        struct ipa_initgr_get_overrides_state);
-+
-+    if (dp_error) {
-+        *dp_error = state->dp_error;
-+    }
-+
-+    TEVENT_REQ_RETURN_ON_ERROR(req);
-+    return EOK;
-+}
-+
-+/* Given a user name, retrieve an array of group UUIDs of groups that have
-+ * no overrideDN attribute but do have an UUID attribute.
-+ */
-+static errno_t ipa_id_get_group_uuids(TALLOC_CTX *mem_ctx,
-+                                      struct sysdb_ctx *sysdb,
-+                                      const char *username,
-+                                      size_t *_msgs_count,
-+                                      struct ldb_message ***_msgs)
-+{
-+    const char *filter;
-+    TALLOC_CTX *tmp_ctx;
-+    char **uuid_list = NULL;
-+    errno_t ret;
-+    struct ldb_dn *base_dn;
-+    const char *attrs[] = { SYSDB_UUID, NULL };
-+    size_t msgs_count;
-+    struct ldb_message **msgs;
-+
-+    tmp_ctx = talloc_new(mem_ctx);
-+    if (tmp_ctx == NULL) {
-+        return ENOMEM;
-+    }
-+
-+    filter = talloc_asprintf(tmp_ctx,
-+                             "(&(objectclass=%s)(!(%s=*))(%s=*))",
-+                             SYSDB_GROUP_CLASS, SYSDB_OVERRIDE_DN,
-+                             SYSDB_UUID);
-+    if (filter == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    base_dn = sysdb_base_dn(sysdb, tmp_ctx);
-+    if (base_dn == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-+    ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn,
-+                             LDB_SCOPE_SUBTREE, filter, attrs,
-+                             &msgs_count, &msgs);
-+    if (ret == ENOENT) {
-+        DEBUG(SSSDBG_TRACE_FUNC,
-+              "No groups without %s in sysdb\n", SYSDB_OVERRIDE_DN);
-+        ret = EOK;
-+        goto done;
-+    } else if (ret != EOK) {
-+        goto done;
-+    }
-+
-+    uuid_list = talloc_zero_array(tmp_ctx, char *, msgs_count);
-+    if (uuid_list == NULL) {
-+        goto done;
-+    }
-+
-+    *_msgs_count = msgs_count;
-+    *_msgs = talloc_steal(mem_ctx, msgs);
-+    ret = EOK;
-+done:
-+    talloc_free(tmp_ctx);
-+    return ret;
-+}
-+
- struct ipa_id_get_account_info_state {
-     struct tevent_context *ev;
-     struct ipa_id_ctx *ipa_ctx;
-@@ -300,6 +533,11 @@ struct ipa_id_get_account_info_state {
-     struct sysdb_attrs *override_attrs;
-     struct ldb_message *obj_msg;
-     struct ldb_message_element *ghosts;
-+
-+    struct ldb_message **user_groups;
-+    size_t group_cnt;
-+    size_t group_idx;
-+
-     int dp_error;
- };
- 
-@@ -519,6 +757,8 @@ static errno_t ipa_id_get_account_info_get_original_step(struct tevent_req *req,
-     return EOK;
- }
- 
-+static void ipa_id_get_user_groups_done(struct tevent_req *subreq);
-+
- static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
- {
-     struct tevent_req *req = tevent_req_callback_data(subreq,
-@@ -549,16 +789,28 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
-         goto fail;
-     }
- 
--    if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_GROUP
--            && state->ipa_ctx->view_name != NULL
--            && strcmp(state->ipa_ctx->view_name,
--                      SYSDB_DEFAULT_VIEW_NAME) != 0) {
--        /* check for ghost members because ghost members are not allowed if a
--         * view other than the default view is applied.*/
-+    if (state->ipa_ctx->view_name != NULL &&
-+            strcmp(state->ipa_ctx->view_name, SYSDB_DEFAULT_VIEW_NAME) != 0) {
- 
--        state->ghosts = ldb_msg_find_element(state->obj_msg, SYSDB_GHOST);
-+        if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_GROUP) {
-+            /* check for ghost members because ghost members are not allowed
-+             * if a view other than the default view is applied.*/
-+            state->ghosts = ldb_msg_find_element(state->obj_msg, SYSDB_GHOST);
-+        } else if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == \
-+                        BE_REQ_INITGROUPS) {
-+            /* Get UUID list of groups that have no overrideDN set. */
-+            ret = ipa_id_get_group_uuids(state, state->sysdb,
-+                                         state->ar->filter_value,
-+                                         &state->group_cnt,
-+                                         &state->user_groups);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "Cannot get UUID list: %d\n", ret);
-+                goto fail;
-+            }
-+        }
-     }
- 
-+
-     if (state->override_attrs == NULL) {
-         uuid = ldb_msg_find_attr_as_string(state->obj_msg, SYSDB_UUID, NULL);
-         if (uuid == NULL) {
-@@ -626,6 +878,19 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
-         return;
-     }
- 
-+    if (state->user_groups != NULL) {
-+        subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
-+                                              state->domain, state->group_cnt,
-+                                              state->user_groups);
-+        if (subreq == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
-+            ret = ENOMEM;
-+            goto fail;
-+        }
-+        tevent_req_set_callback(subreq, ipa_id_get_user_groups_done, req);
-+        return;
-+    }
-+
-     state->dp_error = DP_ERR_OK;
-     tevent_req_done(req);
-     return;
-@@ -692,6 +957,19 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq)
-         return;
-     }
- 
-+    if (state->user_groups != NULL) {
-+        subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
-+                                              state->domain, state->group_cnt,
-+                                              state->user_groups);
-+        if (subreq == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
-+            ret = ENOMEM;
-+            goto fail;
-+        }
-+        tevent_req_set_callback(subreq, ipa_id_get_user_groups_done, req);
-+        return;
-+    }
-+
-     state->dp_error = DP_ERR_OK;
-     tevent_req_done(req);
-     return;
-@@ -728,6 +1006,32 @@ fail:
-     return;
- }
- 
-+static void ipa_id_get_user_groups_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    struct ipa_id_get_account_info_state *state = tevent_req_data(req,
-+                                          struct ipa_id_get_account_info_state);
-+    int dp_error = DP_ERR_FATAL;
-+    int ret;
-+
-+    ret = ipa_initgr_get_overrides_recv(subreq, &dp_error);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user groups %d\n", ret);
-+        goto fail;
-+    }
-+
-+    state->dp_error = DP_ERR_OK;
-+    tevent_req_done(req);
-+    return;
-+
-+fail:
-+    state->dp_error = dp_error;
-+    tevent_req_error(req, ret);
-+    return;
-+}
-+
- static int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error)
- {
-     struct ipa_id_get_account_info_state *state = tevent_req_data(req,
--- 
-2.1.0
-
diff --git a/SOURCES/0186-ipa_s2n_save_objects-properly-handle-fully-qualified.patch b/SOURCES/0186-ipa_s2n_save_objects-properly-handle-fully-qualified.patch
deleted file mode 100644
index 9ffeed2..0000000
--- a/SOURCES/0186-ipa_s2n_save_objects-properly-handle-fully-qualified.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From a79ca19a29c08de2ba42b8ce7b48244730896cfc Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 28 Jan 2015 11:44:37 +0100
-Subject: [PATCH 186/188] ipa_s2n_save_objects: properly handle fully-qualified
- group names
-
-Check if the given name is already fully-qualified instead of adding a
-domain name unconditionally.
-
-Related to https://fedorahosted.org/sssd/ticket/2529
-       and https://fedorahosted.org/sssd/ticket/2524
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 9ad346318dc2cc5d5a340d8d981ddfdcc6f632da)
----
- src/providers/ipa/ipa_s2n_exop.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 35bd303d4aa3651e80c70297507bdc85d05bfbde..18f2a867df3ad705008537843ea94e38dab0006e 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -2074,7 +2074,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
- 
-             if (IS_SUBDOMAIN(dom)) {
-                 /* we always use the fully qualified name for subdomain users */
--                name = sss_tc_fqname(tmp_ctx, dom->names, dom, name);
-+                name = sss_get_domain_name(tmp_ctx, name, dom);
-                 if (!name) {
-                     DEBUG(SSSDBG_OP_FAILURE, "failed to format user name,\n");
-                     ret = ENOMEM;
--- 
-2.1.0
-
diff --git a/SOURCES/0187-AD-use-GC-for-SID-requests-as-well.patch b/SOURCES/0187-AD-use-GC-for-SID-requests-as-well.patch
deleted file mode 100644
index 37bedb3..0000000
--- a/SOURCES/0187-AD-use-GC-for-SID-requests-as-well.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-From 4517ac5121054f0f14dbcb977f0844d49817f4b8 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Wed, 28 Jan 2015 14:04:45 +0100
-Subject: [PATCH 187/188] AD: use GC for SID requests as well
-
-If a universal group is looked up by SID the cross-domain members must
-be resolved with the help of the Global Catalog.
-
-Related to https://fedorahosted.org/sssd/ticket/2514
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 561ed2fd03bab04cfdddbc09c4b48563c9d9b87e)
----
- src/providers/ipa/ipa_subdomains_id.c |  1 +
- src/providers/ldap/ldap_id.c          | 38 ++++++++++++++++++++++++++---------
- 2 files changed, 29 insertions(+), 10 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index c8714a216daff7506f00248e25c281529d0479c4..0508e14b690c144f4bace9ed14a326ac724eb910 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -603,6 +603,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
-      */
-     switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
-     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);
-         if (clist == NULL) {
-diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
-index 2e58f4e49eb33a85cbb8b4144c69004c6b5b312b..5ce462d77867f115fe5c0214fcb95b72a4370472 100644
---- a/src/providers/ldap/ldap_id.c
-+++ b/src/providers/ldap/ldap_id.c
-@@ -33,6 +33,7 @@
- #include "providers/ldap/sdap_async.h"
- #include "providers/ldap/sdap_idmap.h"
- #include "providers/ldap/sdap_users.h"
-+#include "providers/ad/ad_common.h"
- 
- /* =Users-Related-Functions-(by-name,by-uid)============================== */
- 
-@@ -1745,6 +1746,8 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq)
-     struct get_user_and_group_state *state = tevent_req_data(req,
-                                                struct get_user_and_group_state);
-     int ret;
-+    struct ad_id_ctx *ad_id_ctx;
-+    struct sdap_id_conn_ctx *user_conn;
- 
-     ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret);
-     talloc_zfree(subreq);
-@@ -1764,8 +1767,22 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq)
- 
-     /* Now the search finished fine but did not find an entry.
-      * Retry with users. */
-+
-+    user_conn = state->conn;
-+    /* Prefer LDAP over GC for users */
-+    if (state->id_ctx->opts->schema_type == SDAP_SCHEMA_AD
-+            && state->sdom->pvt != NULL) {
-+        ad_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx);
-+        if (ad_id_ctx != NULL &&  ad_id_ctx->ldap_ctx != NULL
-+                && state->conn == ad_id_ctx->gc_ctx) {
-+            DEBUG(SSSDBG_TRACE_ALL,
-+                  "Switching to LDAP connection for user lookup.\n");
-+            user_conn = ad_id_ctx->ldap_ctx;
-+        }
-+    }
-+
-     subreq = users_get_send(req, state->ev, state->id_ctx,
--                            state->sdom, state->conn,
-+                            state->sdom, user_conn,
-                             state->filter_val, state->filter_type, NULL,
-                             state->attrs_type, state->noexist_delete);
-     if (subreq == NULL) {
-@@ -1792,16 +1809,17 @@ static void get_user_and_group_users_done(struct tevent_req *subreq)
-         tevent_req_error(req, ret);
-         return;
-     }
--
-     if (state->sdap_ret == ENOENT) {
--        /* The search ran to completion, but nothing was found.
--         * Delete the existing entry, if any. */
--        ret = sysdb_delete_by_sid(state->sysdb, state->domain,
--                                  state->filter_val);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_OP_FAILURE, "Could not delete entry by SID!\n");
--            tevent_req_error(req, ret);
--            return;
-+        if (state->noexist_delete == true) {
-+            /* The search ran to completion, but nothing was found.
-+             * Delete the existing entry, if any. */
-+            ret = sysdb_delete_by_sid(state->sysdb, state->domain,
-+                                      state->filter_val);
-+            if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE, "Could not delete entry by SID!\n");
-+                tevent_req_error(req, ret);
-+                return;
-+            }
-         }
-     } else if (state->sdap_ret != EOK) {
-         tevent_req_error(req, EIO);
--- 
-2.1.0
-
diff --git a/SOURCES/0188-fill_id-fix-LE-BE-issue-with-wrong-data-type.patch b/SOURCES/0188-fill_id-fix-LE-BE-issue-with-wrong-data-type.patch
deleted file mode 100644
index 98ecf55..0000000
--- a/SOURCES/0188-fill_id-fix-LE-BE-issue-with-wrong-data-type.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From d5c7e81dac95073613c8f8b12280ed001d4ed3b1 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 29 Jan 2015 20:31:19 +0100
-Subject: [PATCH 188/188] fill_id() fix LE/BE issue with wrong data type
-
-Related to https://fedorahosted.org/sssd/ticket/1588
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 866ab45027c83fafb7f7f45d34d3e1e7721b77dc)
----
- src/responder/nss/nsssrv_cmd.c | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
-index da24ce1730999518b2e1bc52604940ee979072e3..c03e5db846ec5b889cab5c2c37a40ef2ae229306 100644
---- a/src/responder/nss/nsssrv_cmd.c
-+++ b/src/responder/nss/nsssrv_cmd.c
-@@ -4867,18 +4867,20 @@ static errno_t fill_id(struct sss_packet *packet,
-     uint8_t *body;
-     size_t blen;
-     size_t pctr = 0;
--    uint64_t id;
-+    uint64_t tmp_id;
-+    uint32_t id;
- 
-     if (id_type == SSS_ID_TYPE_GID) {
--        id = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
-+        tmp_id = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
-     } else {
--        id = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
-+        tmp_id = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
-     }
- 
--    if (id == 0 || id >= UINT32_MAX) {
-+    if (tmp_id == 0 || tmp_id >= UINT32_MAX) {
-         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid POSIX ID.\n");
-         return EINVAL;
-     }
-+    id = (uint32_t) tmp_id;
- 
-     ret = sss_packet_grow(packet, 4 * sizeof(uint32_t));
-     if (ret != EOK) {
--- 
-2.1.0
-
diff --git a/SOURCES/0189-LDAP-unlink-ccname_file_dummy-if-there-is-an-error.patch b/SOURCES/0189-LDAP-unlink-ccname_file_dummy-if-there-is-an-error.patch
deleted file mode 100644
index 41b000b..0000000
--- a/SOURCES/0189-LDAP-unlink-ccname_file_dummy-if-there-is-an-error.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From 8d6ecbc445e5b08b1a03c7fab6ea4e4a24e033d8 Mon Sep 17 00:00:00 2001
-From: Daniel Hjorth <dh@dhjorth.com>
-Date: Wed, 25 Feb 2015 13:07:35 -0700
-Subject: [PATCH 189/190] LDAP: unlink ccname_file_dummy if there is an error
-
-https://fedorahosted.org/sssd/ticket/2592
-
-If there is an error after ccname_file_dummy is created but before it is
-renamed then the file isn't removed.  This can cause a lot of files to be
-created and take up inodes in a filesystem.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 2b20ff2e33ad3993a9cad910c4b4b828513613df)
----
- src/providers/ldap/ldap_child.c | 12 +++++++++++-
- 1 file changed, 11 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
-index f7f8d1d2eab3f66fe4f7d09e50458b495739c1d2..bb61a61858abba90530150ba771053fb8abff14a 100644
---- a/src/providers/ldap/ldap_child.c
-+++ b/src/providers/ldap/ldap_child.c
-@@ -491,16 +491,26 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-               "rename failed [%d][%s].\n", ret, strerror(ret));
-         goto done;
-     }
-+    ccname_file_dummy = NULL;
- 
-     krberr = 0;
-     *ccname_out = talloc_steal(memctx, ccname);
-     *expire_time_out = my_creds.times.endtime - kdc_time_offset;
- 
- done:
--    talloc_free(tmp_ctx);
-     if (krberr != 0) KRB5_SYSLOG(krberr);
-     if (keytab) krb5_kt_close(context, keytab);
-     if (context) krb5_free_context(context);
-+    if (ccname_file_dummy) {
-+        DEBUG(SSSDBG_TRACE_INTERNAL, "Unlinking [%s]\n", ccname_file_dummy);
-+        ret = unlink(ccname_file_dummy);
-+        if (ret == -1) {
-+            ret = errno;
-+            DEBUG(SSSDBG_MINOR_FAILURE,
-+                  "Unlink failed [%d][%s].\n", ret, strerror(ret));
-+        }
-+    }
-+    talloc_free(tmp_ctx);
-     return krberr;
- }
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0190-selinux-Delete-existing-user-mapping-on-empty-defaul.patch b/SOURCES/0190-selinux-Delete-existing-user-mapping-on-empty-defaul.patch
deleted file mode 100644
index 9101930..0000000
--- a/SOURCES/0190-selinux-Delete-existing-user-mapping-on-empty-defaul.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From 0f1b17391dce51ce149cafecf5dfe7acc1dc32cb Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 13 Feb 2015 17:57:35 +0100
-Subject: [PATCH 190/190] selinux: Delete existing user mapping on empty
- default
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-https://fedorahosted.org/sssd/ticket/2587
-
-The case of SELinux default user mapping being an empty string is valid,
-it should translate into "pick the default context on the target
-machine".
-
-In case the context is empty, we need to delete the per-user mapping from
-the SELinux database to make sure the default is used.
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit 01f78f755fde63997ccfded71fb8395569b11430)
----
- src/providers/ipa/ipa_selinux.c   | 14 ++++++++------
- src/providers/ipa/selinux_child.c | 10 +++++++++-
- 2 files changed, 17 insertions(+), 7 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index 133b679b6d518704ebb2bd901c64ac48170c9a0b..1172424cb3f6df06e6ecaa8914427f8f945a7251 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -749,7 +749,7 @@ static errno_t choose_best_seuser(TALLOC_CTX *mem_ctx,
- 
-     /* If no maps match, we'll use the default SELinux user from the
-      * config */
--    seuser_mls_str = talloc_strdup(tmp_ctx, default_user);
-+    seuser_mls_str = talloc_strdup(tmp_ctx, default_user ? default_user : "");
-     if (seuser_mls_str == NULL) {
-         ret = ENOMEM;
-         goto done;
-@@ -1373,11 +1373,13 @@ ipa_get_selinux_maps_offline(struct tevent_req *req)
-         return ENOMEM;
-     }
- 
--    ret = sysdb_attrs_add_string(state->defaults,
--                                 IPA_CONFIG_SELINUX_DEFAULT_USER_CTX,
--                                 default_user);
--    if (ret != EOK) {
--        return ret;
-+    if (default_user) {
-+        ret = sysdb_attrs_add_string(state->defaults,
-+                                    IPA_CONFIG_SELINUX_DEFAULT_USER_CTX,
-+                                    default_user);
-+        if (ret != EOK) {
-+            return ret;
-+        }
-     }
- 
-     ret = sysdb_attrs_add_string(state->defaults,
-diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
-index d4670389667607972dd6f072b5ddfda5973e082b..2f79dea109752de09af1105495e1ca8db1e80680 100644
---- a/src/providers/ipa/selinux_child.c
-+++ b/src/providers/ipa/selinux_child.c
-@@ -146,7 +146,15 @@ static int sc_set_seuser(const char *login_name, const char *seuser_name,
-      * the directories are created with the expected permissions
-      */
-     old_mask = umask(0);
--    ret = set_seuser(login_name, seuser_name, mls);
-+    if (strcmp(seuser_name, "") == 0) {
-+        /* An empty SELinux user should cause SSSD to use the system
-+         * default. We need to remove the SELinux user from the DB
-+         * in that case
-+         */
-+        ret = del_seuser(login_name);
-+    } else {
-+        ret = set_seuser(login_name, seuser_name, mls);
-+    }
-     umask(old_mask);
-     return ret;
- }
--- 
-2.1.0
-
diff --git a/SOURCES/0191-ldap_child-initialized-ccname_file_dummy.patch b/SOURCES/0191-ldap_child-initialized-ccname_file_dummy.patch
deleted file mode 100644
index da25e03..0000000
--- a/SOURCES/0191-ldap_child-initialized-ccname_file_dummy.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 77e789f65ab6a5007945edc2a9650a7209358b9c Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Fri, 6 Mar 2015 11:27:36 +0100
-Subject: [PATCH 191/191] ldap_child: initialized ccname_file_dummy
-
-ccname_file_dummy is used in the done-block which is called before
-ccname_file_dummy is set to a value. This patch initializes
-ccname_file_dummy to NULL.
-
-Related to https://fedorahosted.org/sssd/ticket/2592
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit cc0f9a541c5ecdad750a86b2de9baa1f07403e9e)
----
- src/providers/ldap/ldap_child.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
-index bb61a61858abba90530150ba771053fb8abff14a..822eb22b9c841f5c1b863cad087d65d7e63ae4ae 100644
---- a/src/providers/ldap/ldap_child.c
-+++ b/src/providers/ldap/ldap_child.c
-@@ -274,7 +274,7 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
-     int kdc_time_offset_usec;
-     int ret;
-     TALLOC_CTX *tmp_ctx;
--    char *ccname_file_dummy;
-+    char *ccname_file_dummy = NULL;
-     char *ccname_file;
-     mode_t old_umask;
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0192-ipa_selinux-Fix-warning-may-be-used-uninitialized.patch b/SOURCES/0192-ipa_selinux-Fix-warning-may-be-used-uninitialized.patch
deleted file mode 100644
index 4ad7eff..0000000
--- a/SOURCES/0192-ipa_selinux-Fix-warning-may-be-used-uninitialized.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 448d1e38c9e97ba67041692dc03724e14bd3421a Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 13 Mar 2015 12:38:29 +0100
-Subject: [PATCH 192/193] ipa_selinux: Fix warning may be used uninitialized
-
-src/providers/ipa/ipa_selinux.c: In function 'ipa_selinux_handler_done':
-src/providers/ipa/ipa_selinux.c:927:16: error: 'sci' may be used uninitialized in this function [-Werror=maybe-uninitialized]
-     state->sci = sci;
-                ^
-src/providers/ipa/ipa_selinux.c:333:33: note: 'sci' was declared here
-     struct selinux_child_input *sci;
-                                 ^
-cc1: all warnings being treated as errors
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit befd8f4639ecef8185e82092beae801d68fa7eae)
----
- src/providers/ipa/ipa_selinux.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index 1172424cb3f6df06e6ecaa8914427f8f945a7251..0716536cdb3b34d386ed1a31e6a239a09173b25b 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -330,7 +330,7 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
-     struct sysdb_attrs **hbac_rules = 0;
-     struct sysdb_attrs **best_match_maps;
-     struct map_order_ctx *map_order_ctx;
--    struct selinux_child_input *sci;
-+    struct selinux_child_input *sci = NULL;
-     struct tevent_req *child_req;
- 
-     ret = ipa_get_selinux_recv(req, breq, &map_count, &maps,
--- 
-2.1.0
-
diff --git a/SOURCES/0193-selinux-Handle-setup-with-empty-default-and-no-confi.patch b/SOURCES/0193-selinux-Handle-setup-with-empty-default-and-no-confi.patch
deleted file mode 100644
index 4bbf745..0000000
--- a/SOURCES/0193-selinux-Handle-setup-with-empty-default-and-no-confi.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From 1a04637d4c07762c44889963eb25a405d24397cf Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 12 Mar 2015 16:31:13 +0100
-Subject: [PATCH 193/193] selinux: Handle setup with empty default and no
- configured rules
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-SSSD also needs to handle the setup where no rules match the machine and
-the default has no MLS component.
-
-Related to:
-https://fedorahosted.org/sssd/ticket/2587
-
-Reviewed-by: Michal Židek <mzidek@redhat.com>
-(cherry picked from commit 3e6dac8e14f8a3da6d359ee013453dbd8a38dd99)
-(cherry picked from commit 4b6ee69fb1f713aae125b0fc2d345846e7a0d642)
----
- src/providers/ipa/ipa_selinux.c   |  4 ++--
- src/providers/ipa/selinux_child.c | 10 ++++++++--
- 2 files changed, 10 insertions(+), 4 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
-index 0716536cdb3b34d386ed1a31e6a239a09173b25b..899dd07105a98faac9430211404499911434f6d6 100644
---- a/src/providers/ipa/ipa_selinux.c
-+++ b/src/providers/ipa/ipa_selinux.c
-@@ -808,7 +808,7 @@ selinux_child_setup(TALLOC_CTX *mem_ctx,
- {
-     errno_t ret;
-     char *seuser;
--    char *mls_range;
-+    const char *mls_range;
-     char *ptr;
-     char *username;
-     char *username_final;
-@@ -834,7 +834,7 @@ selinux_child_setup(TALLOC_CTX *mem_ctx,
-     }
-     if (*ptr == '\0') {
-         /* No mls_range specified */
--        mls_range = NULL;
-+        mls_range = "";
-     } else {
-         *ptr = '\0'; /* split */
-         mls_range = ptr + 1;
-diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
-index 2f79dea109752de09af1105495e1ca8db1e80680..abcb93b1a76783fd048ddebc976830ac42e1f757 100644
---- a/src/providers/ipa/selinux_child.c
-+++ b/src/providers/ipa/selinux_child.c
-@@ -49,7 +49,9 @@ static errno_t unpack_buffer(uint8_t *buf,
-     SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-     DEBUG(SSSDBG_TRACE_INTERNAL, "seuser length: %d\n", len);
-     if (len == 0) {
--        return EINVAL;
-+        ibuf->seuser = "";
-+        DEBUG(SSSDBG_TRACE_INTERNAL,
-+              "Empty SELinux user, will delete the mapping\n");
-     } else {
-         if ((p + len ) > size) return EINVAL;
-         ibuf->seuser = talloc_strndup(ibuf, (char *)(buf + p), len);
-@@ -62,7 +64,10 @@ static errno_t unpack_buffer(uint8_t *buf,
-     SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-     DEBUG(SSSDBG_TRACE_INTERNAL, "mls_range length: %d\n", len);
-     if (len == 0) {
--        return EINVAL;
-+        if (strcmp(ibuf->seuser, "") != 0) {
-+            DEBUG(SSSDBG_CRIT_FAILURE, "No MLS mapping!\n");
-+            return EINVAL;
-+        }
-     } else {
-         if ((p + len ) > size) return EINVAL;
-         ibuf->mls_range = talloc_strndup(ibuf, (char *)(buf + p), len);
-@@ -75,6 +80,7 @@ static errno_t unpack_buffer(uint8_t *buf,
-     SAFEALIGN_COPY_UINT32_CHECK(&len, buf + p, size, &p);
-     DEBUG(SSSDBG_TRACE_INTERNAL, "username length: %d\n", len);
-     if (len == 0) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "No username set!\n");
-         return EINVAL;
-     } else {
-         if ((p + len ) > size) return EINVAL;
--- 
-2.1.0
-
diff --git a/SOURCES/0194-IPA-idviews-check-if-view-name-is-set.patch b/SOURCES/0194-IPA-idviews-check-if-view-name-is-set.patch
deleted file mode 100644
index 0aa0958..0000000
--- a/SOURCES/0194-IPA-idviews-check-if-view-name-is-set.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 4127df0800a5d4be30fa28ee01df6e68aedc5aa4 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 17 Mar 2015 11:08:05 +0100
-Subject: [PATCH 194/194] IPA idviews: check if view name is set
-
-When working with older FreeIPA releases the view name might not always
-been set. This patch add checks to might sure it is only dereferenced
-when set.
-
-Resolves https://fedorahosted.org/sssd/ticket/2604
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 8be0cf3eea892e13410c13abb030322599ca1b4f)
----
- src/providers/ipa/ipa_s2n_exop.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 18f2a867df3ad705008537843ea94e38dab0006e..f546067fae4ff45f976885f3b650866b292a3b8a 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1027,7 +1027,8 @@ static void ipa_s2n_get_fqlist_next(struct tevent_req *subreq)
-         goto fail;
-     }
- 
--    if (strcmp(state->ipa_ctx->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
-+    if (state->ipa_ctx->view_name == NULL ||
-+            strcmp(state->ipa_ctx->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
-         ret = ipa_s2n_get_fqlist_save_step(req);
-         if (ret == EOK) {
-             tevent_req_done(req);
-@@ -1602,6 +1603,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
-     }
- 
-     if (ret == ENOENT
-+            || state->ipa_ctx->view_name == NULL
-             || strcmp(state->ipa_ctx->view_name,
-                       SYSDB_DEFAULT_VIEW_NAME) == 0) {
-         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
-@@ -2211,6 +2213,7 @@ static void ipa_s2n_get_fqlist_done(struct tevent_req  *subreq)
-     }
- 
-     if (state->override_attrs == NULL
-+            && state->ipa_ctx->view_name != NULL
-             && strcmp(state->ipa_ctx->view_name,
-                       SYSDB_DEFAULT_VIEW_NAME) != 0) {
-         subreq = ipa_get_ad_override_send(state, state->ev,
--- 
-2.1.0
-
diff --git a/SOURCES/0195-IPA-make-sure-output-variable-is-set.patch b/SOURCES/0195-IPA-make-sure-output-variable-is-set.patch
deleted file mode 100644
index d5bba63..0000000
--- a/SOURCES/0195-IPA-make-sure-output-variable-is-set.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 9a12e4166ff96b659bd6bfd606ba7de87a9e95d3 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Thu, 19 Mar 2015 14:26:26 +0100
-Subject: [PATCH 195/196] IPA: make sure output variable is set
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit abb093b4ae10f2a5748bf9f194bf76794002eba0)
----
- src/providers/ipa/ipa_s2n_exop.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index f546067fae4ff45f976885f3b650866b292a3b8a..7e2b70b953075d33df10ea614c55ce5d25f49b9b 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1244,7 +1244,9 @@ static errno_t process_members(struct sss_domain_info *domain,
- 
-     if (members == NULL) {
-         DEBUG(SSSDBG_TRACE_INTERNAL, "No members\n");
--        *_missing_members = NULL;
-+        if (_missing_members != NULL) {
-+            *_missing_members = NULL;
-+        }
-         return EOK;
-     }
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0196-IPA-set-EINVAL-if-dn-can-t-be-linearized.patch b/SOURCES/0196-IPA-set-EINVAL-if-dn-can-t-be-linearized.patch
deleted file mode 100644
index c040fef..0000000
--- a/SOURCES/0196-IPA-set-EINVAL-if-dn-can-t-be-linearized.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 424f26892d1b2587a806694820babf5754b8db66 Mon Sep 17 00:00:00 2001
-From: Pavel Reichl <preichl@redhat.com>
-Date: Thu, 19 Mar 2015 10:21:21 -0400
-Subject: [PATCH 196/196] IPA: set EINVAL if dn can't be linearized
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit 131da4d9f40e0e407d7bcae18ff16507976bc6c7)
----
- src/providers/ipa/ipa_s2n_exop.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 7e2b70b953075d33df10ea614c55ce5d25f49b9b..292f174257fbf6f6ebc8db6d1eb38cb4b5349b81 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1284,6 +1284,7 @@ static errno_t process_members(struct sss_domain_info *domain,
-                 dn_str = ldb_dn_get_linearized(msg->dn);
-                 if (dn_str == NULL) {
-                     DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_get_linearized failed.\n");
-+                    ret = EINVAL;
-                     goto done;
-                 }
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch b/SOURCES/0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch
deleted file mode 100644
index 3c458ee..0000000
--- a/SOURCES/0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch
+++ /dev/null
@@ -1,297 +0,0 @@
-From b8d9eca0d9469c1209161b31a0109d8e4ea2868c Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Mon, 9 Mar 2015 16:36:29 +0100
-Subject: [PATCH] LDAP/AD: do not resolve group members during tokenGroups
- request
-
-During initgroups requests we try to avoid to resolve the complete
-member list of groups if possible, e.g. if there are no nested groups.
-The tokenGroups LDAP lookup return the complete list of memberships for
-a user hence it is not necessary lookup the other group member and
-un-roll nested groups. With this patch only the group entry is looked up
-and saved as incomplete group to the cache.
-
-This is achieved by adding a new boolean parameter no_members to
-groups_get_send() and sdap_get_groups_send(). The difference to config
-options like ldap_group_nesting_level = 0 or ignore_group_members is
-that if no_members is set to true groups which are missing in the cache
-are created a incomplete groups. As a result a request to lookup this
-group will trigger a new LDAP request to resolve the group completely.
-This way no information is ignored but the time needed to read all data
-is better distributed between different requests.
-
-https://fedorahosted.org/sssd/ticket/2601
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1)
----
- src/providers/ipa/ipa_subdomains_ext_groups.c |  2 +-
- src/providers/ldap/ldap_common.h              |  3 ++-
- src/providers/ldap/ldap_id.c                  | 14 +++++++----
- src/providers/ldap/sdap_async.h               |  3 ++-
- src/providers/ldap/sdap_async_enum.c          |  2 +-
- src/providers/ldap/sdap_async_groups.c        | 36 ++++++++++++++++++++++++++-
- src/providers/ldap/sdap_async_initgroups.c    | 14 +++++------
- src/providers/ldap/sdap_async_initgroups_ad.c |  2 +-
- src/providers/ldap/sdap_async_private.h       |  6 +++++
- 9 files changed, 64 insertions(+), 18 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c
-index ad278b248ec2a2a157fed0a455dbe97049e83f9d..976a71cfe3ab42425e3884c5f6d9e096fe61bb34 100644
---- a/src/providers/ipa/ipa_subdomains_ext_groups.c
-+++ b/src/providers/ipa/ipa_subdomains_ext_groups.c
-@@ -872,7 +872,7 @@ static void ipa_add_ad_memberships_get_next(struct tevent_req *req)
-                                  state->sdap_id_ctx->conn,
-                                  (const char *) val->data,
-                                  BE_FILTER_NAME, BE_ATTR_CORE,
--                                 false);
-+                                 false, false);
-     if (subreq == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n");
-         ret = ENOMEM;
-diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
-index bf69489a79e903a98878edb53d372d2242df2b0f..57ad1b8458988d7e108f019c20f67bcde32539d4 100644
---- a/src/providers/ldap/ldap_common.h
-+++ b/src/providers/ldap/ldap_common.h
-@@ -212,7 +212,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
-                                    const char *name,
-                                    int filter_type,
-                                    int attrs_type,
--                                   bool noexist_delete);
-+                                   bool noexist_delete,
-+                                   bool no_members);
- int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret);
- 
- struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx,
-diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
-index 6de5b72a8b66cd95b16d25a2c37dc21a57695de3..55bb3c9fbd6f623e7795d7399c9e5ac4d5192e85 100644
---- a/src/providers/ldap/ldap_id.c
-+++ b/src/providers/ldap/ldap_id.c
-@@ -528,6 +528,7 @@ struct groups_get_state {
-     int dp_error;
-     int sdap_ret;
-     bool noexist_delete;
-+    bool no_members;
- };
- 
- static int groups_get_retry(struct tevent_req *req);
-@@ -544,7 +545,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
-                                    const char *name,
-                                    int filter_type,
-                                    int attrs_type,
--                                   bool noexist_delete)
-+                                   bool noexist_delete,
-+                                   bool no_members)
- {
-     struct tevent_req *req;
-     struct groups_get_state *state;
-@@ -567,6 +569,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
-     state->conn = conn;
-     state->dp_error = DP_ERR_FATAL;
-     state->noexist_delete = noexist_delete;
-+    state->no_members = no_members;
- 
-     state->op = sdap_id_op_create(state, state->conn->conn_cache);
-     if (!state->op) {
-@@ -713,7 +716,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
- 
-     /* TODO: handle attrs_type */
-     ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP,
--                               state->domain->ignore_group_members ?
-+                               (state->domain->ignore_group_members
-+                                    || state->no_members) ?
-                                    (const char **)member_filter : NULL,
-                                &state->attrs, NULL);
- 
-@@ -845,7 +849,7 @@ static void groups_get_search(struct tevent_req *req)
-                                   state->attrs, state->filter,
-                                   dp_opt_get_int(state->ctx->opts->basic,
-                                                  SDAP_SEARCH_TIMEOUT),
--                                  false);
-+                                  false, state->no_members);
-     if (!subreq) {
-         tevent_req_error(req, ENOMEM);
-         return;
-@@ -1383,7 +1387,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
-                                  ar->filter_value,
-                                  ar->filter_type,
-                                  ar->attr_type,
--                                 noexist_delete);
-+                                 noexist_delete, false);
-         break;
- 
-     case BE_REQ_INITGROUPS: /* init groups for user */
-@@ -1718,7 +1722,7 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
-     subreq = groups_get_send(req, state->ev, state->id_ctx,
-                              state->sdom, state->conn,
-                              state->filter_val, state->filter_type,
--                             state->attrs_type, state->noexist_delete);
-+                             state->attrs_type, state->noexist_delete, false);
-     if (subreq == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "users_get_send failed.\n");
-         ret = ENOMEM;
-diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
-index 1239f28c173373aac23c5796d694c7bd5ca24c96..ef9b3bbadba830bcf730b6fa70867c17d51380af 100644
---- a/src/providers/ldap/sdap_async.h
-+++ b/src/providers/ldap/sdap_async.h
-@@ -96,7 +96,8 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx,
-                                        const char **attrs,
-                                        const char *filter,
-                                        int timeout,
--                                       bool enumeration);
-+                                       bool enumeration,
-+                                       bool no_members);
- int sdap_get_groups_recv(struct tevent_req *req,
-                          TALLOC_CTX *mem_ctx, char **timestamp);
- 
-diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c
-index 242b3172f367b0b35738bd2e86ea927a4409d2d6..1cc09abdf1aa14e3d1690ea1abe32604ae4ff1cd 100644
---- a/src/providers/ldap/sdap_async_enum.c
-+++ b/src/providers/ldap/sdap_async_enum.c
-@@ -811,7 +811,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
-                                   state->attrs, state->filter,
-                                   dp_opt_get_int(state->ctx->opts->basic,
-                                                  SDAP_ENUM_SEARCH_TIMEOUT),
--                                  true);
-+                                  true, false);
-     if (!subreq) {
-         ret = ENOMEM;
-         goto fail;
-diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
-index c86b5c6b59a4de7e945b95cafae9149f681e2e18..818f30b95d4a4707c32d16b9866b008d89141e4d 100644
---- a/src/providers/ldap/sdap_async_groups.c
-+++ b/src/providers/ldap/sdap_async_groups.c
-@@ -1750,6 +1750,7 @@ struct sdap_get_groups_state {
-     char *filter;
-     int timeout;
-     bool enumeration;
-+    bool no_members;
- 
-     char *higher_usn;
-     struct sysdb_attrs **groups;
-@@ -1779,7 +1780,8 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx,
-                                        const char **attrs,
-                                        const char *filter,
-                                        int timeout,
--                                       bool enumeration)
-+                                       bool enumeration,
-+                                       bool no_members)
- {
-     errno_t ret;
-     struct tevent_req *req;
-@@ -1802,6 +1804,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx,
-     state->count = 0;
-     state->timeout = timeout;
-     state->enumeration = enumeration;
-+    state->no_members = no_members;
-     state->base_filter = filter;
-     state->base_iter = 0;
-     state->search_bases = sdom->group_search_bases;
-@@ -1926,6 +1929,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
-     bool next_base = false;
-     size_t count;
-     struct sysdb_attrs **groups;
-+    char **groupnamelist;
- 
-     ret = sdap_get_generic_recv(subreq, state,
-                                 &count, &groups);
-@@ -1992,6 +1996,36 @@ static void sdap_get_groups_process(struct tevent_req *subreq)
-         return;
-     }
- 
-+    if (state->no_members) {
-+        ret = sysdb_attrs_primary_name_list(state->sysdb, state,
-+                                state->groups, state->count,
-+                                state->opts->group_map[SDAP_AT_GROUP_NAME].name,
-+                                &groupnamelist);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "sysdb_attrs_primary_name_list failed.\n");
-+            tevent_req_error(req, ret);
-+            return;
-+        }
-+
-+        ret = sdap_add_incomplete_groups(state->sysdb, state->dom, state->opts,
-+                                         groupnamelist, state->groups,
-+                                         state->count);
-+        if (ret == EOK) {
-+            DEBUG(SSSDBG_TRACE_LIBS,
-+                  "Reading only group data without members successful.\n");
-+            tevent_req_done(req);
-+        } else {
-+            DEBUG(SSSDBG_OP_FAILURE, "sdap_add_incomplete_groups failed.\n");
-+            tevent_req_error(req, ret);
-+        }
-+        return;
-+
-+        ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts,
-+                               state->groups, state->count, false,
-+                               NULL, true, NULL);
-+    }
-+
-     /* Check whether we need to do nested searches
-      * for RFC2307bis/FreeIPA/ActiveDirectory
-      * We don't need to do this for enumeration,
-diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
-index 48c16b71637f83399d9a523f64f6d812b91681ef..2fd235f2868b877c0e5d5d9f7b1b76d269eee8ee 100644
---- a/src/providers/ldap/sdap_async_initgroups.c
-+++ b/src/providers/ldap/sdap_async_initgroups.c
-@@ -29,12 +29,12 @@
- #include "providers/ldap/sdap_users.h"
- 
- /* ==Save-fake-group-list=====================================*/
--static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
--                                          struct sss_domain_info *domain,
--                                          struct sdap_options *opts,
--                                          char **groupnames,
--                                          struct sysdb_attrs **ldap_groups,
--                                          int ldap_groups_count)
-+errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-+                                   struct sss_domain_info *domain,
-+                                   struct sdap_options *opts,
-+                                   char **groupnames,
-+                                   struct sysdb_attrs **ldap_groups,
-+                                   int ldap_groups_count)
- {
-     TALLOC_CTX *tmp_ctx;
-     struct ldb_message *msg;
-@@ -3152,7 +3152,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
- 
-     subreq = groups_get_send(req, state->ev, state->id_ctx,
-                              state->id_ctx->opts->sdom, state->conn,
--                             gid, BE_FILTER_IDNUM, BE_ATTR_ALL, NULL);
-+                             gid, BE_FILTER_IDNUM, BE_ATTR_ALL, false, false);
-     if (!subreq) {
-         ret = ENOMEM;
-         goto fail;
-diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
-index 1b8c8d981ea14ac0fca0903f16296c8a6701c5dd..9915f1863f172d5d3f59afe03abbbfb87fdf3409 100644
---- a/src/providers/ldap/sdap_async_initgroups_ad.c
-+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
-@@ -630,7 +630,7 @@ static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req)
- 
-     subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain,
-                              state->conn, state->current_sid,
--                             BE_FILTER_SECID, BE_ATTR_CORE, false);
-+                             BE_FILTER_SECID, BE_ATTR_CORE, false, true);
-     if (subreq == NULL) {
-         return ENOMEM;
-     }
-diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h
-index e689394c5db8a3385c333e6b98372c6f6d34366c..3995a2ac357c52f546696284d71d2127d0302409 100644
---- a/src/providers/ldap/sdap_async_private.h
-+++ b/src/providers/ldap/sdap_async_private.h
-@@ -132,4 +132,10 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx,
-                                unsigned long *_num_groups,
-                                struct sysdb_attrs ***_groups);
- 
-+errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-+                                   struct sss_domain_info *domain,
-+                                   struct sdap_options *opts,
-+                                   char **groupnames,
-+                                   struct sysdb_attrs **ldap_groups,
-+                                   int ldap_groups_count);
- #endif /* _SDAP_ASYNC_PRIVATE_H_ */
--- 
-2.1.0
-
diff --git a/SOURCES/0198-SDAP-Do-not-set-gid-0-twice.patch b/SOURCES/0198-SDAP-Do-not-set-gid-0-twice.patch
deleted file mode 100644
index a6c60ee..0000000
--- a/SOURCES/0198-SDAP-Do-not-set-gid-0-twice.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 63209a5d62f2ef1a184b5d1799a27bab8278f43a Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Fri, 10 Apr 2015 14:33:35 +0200
-Subject: [PATCH 198/200] SDAP: Do not set gid 0 twice
-
-The gid o was added to sysdb attrs directly in sdap_save_group for 1st time
-and for second time in the function sdap_store_group_with_gid,
-which was called every time from function sdap_save_group
-
-[sysdb_set_entry_attr] (0x0080): ldb_modify failed:
-    [Attribute or value exists](20)[attribute 'gidNumber': value #1
-    on 'name=domainlocalgroup1_dom2-493341@sssdad_tree.com,cn=groups,cn=sssdad_tree.com,cn=sysdb' provided more than once]
-[sysdb_set_entry_attr] (0x0040): Error: 17 (File exists)
-[sysdb_store_group] (0x1000): sysdb_set_group_attr failed.
-[sysdb_store_group] (0x0400): Error: 17 (File exists)
-[sdap_store_group_with_gid] (0x0040):
-    Could not store group domainlocalgroup1_dom2-493341@sssdad_tree.com
-[sdap_save_group] (0x0080): Could not store group with GID: [File exists]
-[sdap_save_group] (0x0080):
-    Failed to save group [domainlocalgroup1_dom2-493341@sssdad_tree.com]: [File exists]
-[sdap_save_groups] (0x0040): Failed to store group 0. Ignoring.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 5d864e7a9d0e1e6fb7dd8158c5b8bfb71040b908)
----
- src/providers/ldap/sdap_async_groups.c | 7 -------
- 1 file changed, 7 deletions(-)
-
-diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
-index 818f30b95d4a4707c32d16b9866b008d89141e4d..4be8c502ea77a3913ddac2a24fbacbc522b2ef6b 100644
---- a/src/providers/ldap/sdap_async_groups.c
-+++ b/src/providers/ldap/sdap_async_groups.c
-@@ -608,13 +608,6 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-             gid = 0;
-             DEBUG(SSSDBG_TRACE_FUNC, "Filtering AD group [%s].\n",
-                                       group_name);
--            ret = sysdb_attrs_add_uint32(group_attrs,
--                                         opts->group_map[SDAP_AT_GROUP_GID].sys_name, 0);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_CRIT_FAILURE,
--                      "Failed to add a GID to non-posix group!\n");
--                return ret;
--            }
-             ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, false);
-             if (ret != EOK) {
-                 DEBUG(SSSDBG_OP_FAILURE,
--- 
-2.1.0
-
diff --git a/SOURCES/0199-SDAP-Extract-filtering-AD-group-to-function.patch b/SOURCES/0199-SDAP-Extract-filtering-AD-group-to-function.patch
deleted file mode 100644
index 263918e..0000000
--- a/SOURCES/0199-SDAP-Extract-filtering-AD-group-to-function.patch
+++ /dev/null
@@ -1,240 +0,0 @@
-From 64eb7055b640e9c92701886effc36f74fe9e709f Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Mon, 13 Apr 2015 09:44:35 +0200
-Subject: [PATCH 199/200] SDAP: Extract filtering AD group to function
-
-Patch remove code duplication.
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit bad2fc8133d941e5a6c8d8016c9689e039265c61)
----
- Makefile.am                                   |  2 +
- src/providers/ldap/sdap_ad_groups.c           | 68 +++++++++++++++++++++++++++
- src/providers/ldap/sdap_async_groups.c        | 40 ++++++----------
- src/providers/ldap/sdap_async_nested_groups.c | 31 ++++--------
- src/providers/ldap/sdap_async_private.h       |  7 +++
- 5 files changed, 101 insertions(+), 47 deletions(-)
- create mode 100644 src/providers/ldap/sdap_ad_groups.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 8202659e0933529ca7911952bbf1476dbb4a76fc..f402239af2cfaf77dde1ce6ff261015f5d9bfacc 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -1858,6 +1858,7 @@ nestedgroups_tests_SOURCES = \
-     src/providers/ldap/sdap_idmap.c \
-     src/tests/cmocka/test_nested_groups.c \
-     src/providers/ldap/sdap_async_nested_groups.c \
-+    src/providers/ldap/sdap_ad_groups.c \
-     $(NULL)
- nestedgroups_tests_CFLAGS = \
-     $(AM_CFLAGS) \
-@@ -2307,6 +2308,7 @@ libsss_ldap_common_la_SOURCES = \
-     src/providers/ldap/sdap_async_connection.c \
-     src/providers/ldap/sdap_async_netgroups.c \
-     src/providers/ldap/sdap_async_services.c \
-+    src/providers/ldap/sdap_ad_groups.c \
-     src/providers/ldap/sdap_child_helpers.c \
-     src/providers/ldap/sdap_fd_events.c \
-     src/providers/ldap/sdap_id_op.c \
-diff --git a/src/providers/ldap/sdap_ad_groups.c b/src/providers/ldap/sdap_ad_groups.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..0e36328b9b52643a2ec698b2a41f2a56a8ff69b6
---- /dev/null
-+++ b/src/providers/ldap/sdap_ad_groups.c
-@@ -0,0 +1,68 @@
-+/*
-+    SSSD
-+
-+    AD groups helper routines
-+
-+    Authors:
-+        Lukas Slebodnik <lslebodn@redhat.com>
-+
-+    Copyright (C) 2013 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 "db/sysdb.h"
-+#include "providers/ldap/sdap.h"
-+#include "providers/ldap/sdap_async_private.h"
-+
-+/* ==Group-Parsing Routines=============================================== */
-+
-+errno_t sdap_check_ad_group_type(struct sss_domain_info *dom,
-+                                 struct sdap_options *opts,
-+                                 struct sysdb_attrs *group_attrs,
-+                                 const char *group_name,
-+                                 bool *_need_filter)
-+{
-+    int32_t ad_group_type;
-+    errno_t ret = EOK;
-+    *_need_filter = false;
-+
-+    if (opts->schema_type == SDAP_SCHEMA_AD) {
-+        ret = sysdb_attrs_get_int32_t(group_attrs, SYSDB_GROUP_TYPE,
-+                                      &ad_group_type);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_int32_t failed.\n");
-+            return ret;
-+        }
-+
-+        DEBUG(SSSDBG_TRACE_ALL,
-+              "AD group [%s] has type flags %#x.\n",
-+              group_name, ad_group_type);
-+
-+        /* Only security groups from AD are considered for POSIX groups.
-+         * Additionally only global and universal group are taken to account
-+         * for trusted domains. */
-+        if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY)
-+            || (IS_SUBDOMAIN(dom)
-+                && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL)
-+                      || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) {
-+            DEBUG(SSSDBG_TRACE_FUNC,
-+                  "Filtering AD group [%s].\n", group_name);
-+
-+            *_need_filter = true;
-+        }
-+    }
-+
-+    return ret;
-+}
-diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
-index 4be8c502ea77a3913ddac2a24fbacbc522b2ef6b..00a676372fa042dfc2d57e5799261f9a45ed4a73 100644
---- a/src/providers/ldap/sdap_async_groups.c
-+++ b/src/providers/ldap/sdap_async_groups.c
-@@ -510,10 +510,10 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     TALLOC_CTX *tmpctx = NULL;
-     bool posix_group;
-     bool use_id_mapping;
-+    bool need_filter;
-     char *sid_str;
-     const char *uuid;
-     struct sss_domain_info *subdomain;
--    int32_t ad_group_type;
- 
-     tmpctx = talloc_new(NULL);
-     if (!tmpctx) {
-@@ -588,32 +588,20 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     DEBUG(SSSDBG_TRACE_FUNC, "Processing group %s\n", group_name);
- 
-     posix_group = true;
--    if (opts->schema_type == SDAP_SCHEMA_AD) {
--        ret = sysdb_attrs_get_int32_t(attrs, SYSDB_GROUP_TYPE, &ad_group_type);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_int32_t failed.\n");
--            goto done;
--        }
-+    ret = sdap_check_ad_group_type(dom, opts, attrs, group_name,
-+                                   &need_filter);
-+    if (ret != EOK) {
-+        goto done;
-+    }
-+    if (need_filter) {
-+        posix_group = false;
-+        gid = 0;
- 
--        DEBUG(SSSDBG_TRACE_ALL, "AD group [%s] has type flags %#x.\n",
--                                 group_name, ad_group_type);
--        /* Only security groups from AD are considered for POSIX groups.
--         * Additionally only global and universal group are taken to account
--         * for trusted domains. */
--        if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY)
--                || (IS_SUBDOMAIN(dom)
--                    && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL)
--                        || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) {
--            posix_group = false;
--            gid = 0;
--            DEBUG(SSSDBG_TRACE_FUNC, "Filtering AD group [%s].\n",
--                                      group_name);
--            ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, false);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE,
--                      "Error: Failed to mark group as non-posix!\n");
--                return ret;
--            }
-+        ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, false);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE,
-+                  "Error: Failed to mark group as non-posix!\n");
-+            return ret;
-         }
-     }
- 
-diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c
-index 1eba35ae8ac90acac8a2d46e8cc5f2b57e3a9256..08e199869ad16c3b19d998a2a28eae9a0dd0a371 100644
---- a/src/providers/ldap/sdap_async_nested_groups.c
-+++ b/src/providers/ldap/sdap_async_nested_groups.c
-@@ -240,32 +240,21 @@ sdap_nested_group_hash_group(struct sdap_nested_group_ctx *group_ctx,
- {
-     struct sdap_attr_map *map = group_ctx->opts->group_map;
-     gid_t gid;
--    errno_t ret = ENOENT;
--    int32_t ad_group_type;
-+    errno_t ret;
-     bool posix_group = true;
-     bool use_id_mapping;
-     bool can_find_gid;
-+    bool need_filter;
- 
--    if (group_ctx->opts->schema_type == SDAP_SCHEMA_AD) {
--        ret = sysdb_attrs_get_int32_t(group, SYSDB_GROUP_TYPE, &ad_group_type);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_int32_t failed.\n");
--            return ret;
--        }
-+    ret = sdap_check_ad_group_type(group_ctx->domain, group_ctx->opts,
-+                                   group, "", &need_filter);
-+    if (ret != EOK) {
-+        return ret;
-+    }
- 
--        DEBUG(SSSDBG_TRACE_ALL, "AD group has type flags %#x.\n",
--                                 ad_group_type);
--        /* Only security groups from AD are considered for POSIX groups.
--         * Additionally only global and universal group are taken to account
--         * for trusted domains. */
--        if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY)
--                || (IS_SUBDOMAIN(group_ctx->domain)
--                    && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL)
--                        || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) {
--            posix_group = false;
--            gid = 0;
--            DEBUG(SSSDBG_TRACE_FUNC, "Filtering AD group.\n");
--        }
-+    if (need_filter) {
-+        posix_group = false;
-+        gid = 0;
-     }
- 
-     use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(
-diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h
-index 3995a2ac357c52f546696284d71d2127d0302409..db542eaf869efcd53d0937bef3fc6e99cc78b938 100644
---- a/src/providers/ldap/sdap_async_private.h
-+++ b/src/providers/ldap/sdap_async_private.h
-@@ -138,4 +138,11 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-                                    char **groupnames,
-                                    struct sysdb_attrs **ldap_groups,
-                                    int ldap_groups_count);
-+
-+/* from sdap_async_nested_groups.c */
-+errno_t sdap_check_ad_group_type(struct sss_domain_info *dom,
-+                                 struct sdap_options *opts,
-+                                 struct sysdb_attrs *group_attrs,
-+                                 const char *group_name,
-+                                 bool *_need_filter);
- #endif /* _SDAP_ASYNC_PRIVATE_H_ */
--- 
-2.1.0
-
diff --git a/SOURCES/0200-SDAP-Filter-ad-groups-in-initgroups.patch b/SOURCES/0200-SDAP-Filter-ad-groups-in-initgroups.patch
deleted file mode 100644
index 42b8547..0000000
--- a/SOURCES/0200-SDAP-Filter-ad-groups-in-initgroups.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From bea6b6c6bcf711e0d96a4263f60e0e1b0a64c45f Mon Sep 17 00:00:00 2001
-From: Lukas Slebodnik <lslebodn@redhat.com>
-Date: Mon, 13 Apr 2015 09:50:29 +0200
-Subject: [PATCH 200/200] SDAP: Filter ad groups in initgroups
-
-Function sdap_add_incomplete_groups stored domain local groups
-from subdomain as POSIX group, which should not be done.
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2614
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit b9fbeb75e7a4f50f98d979a70a710f9221892483)
----
- src/providers/ldap/sdap_async_initgroups.c | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
-diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
-index bc6b5e45e6a7f7dc0c482a6bbbf2aa602371a647..43b72fe2051b452c6ea755c8842117cceafa143a 100644
---- a/src/providers/ldap/sdap_async_initgroups.c
-+++ b/src/providers/ldap/sdap_async_initgroups.c
-@@ -51,6 +51,7 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-     time_t now;
-     char *sid_str = NULL;
-     bool use_id_mapping;
-+    bool need_filter;
-     char *tmp_name;
- 
-     /* There are no groups in LDAP but we should add user to groups ?? */
-@@ -205,6 +206,17 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-                     uuid = NULL;
-                 }
- 
-+                ret = sdap_check_ad_group_type(domain, opts, ldap_groups[ai],
-+                                               groupname, &need_filter);
-+                if (ret != EOK) {
-+                    goto done;
-+                }
-+
-+                if (need_filter) {
-+                    posix = false;
-+                    gid = 0;
-+                }
-+
-                 DEBUG(SSSDBG_TRACE_INTERNAL,
-                       "Adding fake group %s to sysdb\n", groupname);
-                 ret = sysdb_add_incomplete_group(domain, groupname, gid,
--- 
-2.1.0
-
diff --git a/SOURCES/0201-sdap-properly-handle-binary-objectGuid-attribute.patch b/SOURCES/0201-sdap-properly-handle-binary-objectGuid-attribute.patch
deleted file mode 100644
index 35ba8ec..0000000
--- a/SOURCES/0201-sdap-properly-handle-binary-objectGuid-attribute.patch
+++ /dev/null
@@ -1,501 +0,0 @@
-From 745cf4cc7f4e8f7cdc6ea74b5c39a70f0201a883 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 17 Feb 2015 04:41:21 +0100
-Subject: [PATCH 201/207] sdap: properly handle binary objectGuid attribute
-
-Although in the initial processing SSSD treats the binary value right at
-some point it mainly assumes that it is a string. Depending on the value
-this might end up with the correct binary value stored in the cache but
-in most cases there will be only a broken entry in the cache.
-
-This patch converts the binary value into a string representation which
-is described in [MS-DTYP] and stores the result in the cache.
-
-Resolves https://fedorahosted.org/sssd/ticket/2588
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
----
- src/db/sysdb.h                             |   6 ++
- src/db/sysdb_ops.c                         |  52 +++++++++++
- src/providers/ldap/sdap_async_groups.c     |  25 ++----
- src/providers/ldap/sdap_async_initgroups.c |   7 +-
- src/providers/ldap/sdap_async_users.c      |  23 ++---
- src/tests/cmocka/test_string_utils.c       |  59 +++++++++++++
- src/tests/cmocka/test_sysdb_utils.c        | 134 +++++++++++++++++++++++++++++
- src/tests/cmocka/test_utils.h              |   1 +
- src/tests/cwrap/Makefile.am                |   2 +
- src/util/string_utils.c                    |  25 ++++++
- src/util/util.h                            |   7 ++
- 11 files changed, 307 insertions(+), 34 deletions(-)
- create mode 100644 src/tests/cmocka/test_sysdb_utils.c
-
-diff --git a/src/db/sysdb.h b/src/db/sysdb.h
-index cf6028acb806d5d4eedf4cf0680cf4ac9fd6368d..ee5757130ec24a4ddfef854af5f59fc3ccc5b8ae 100644
---- a/src/db/sysdb.h
-+++ b/src/db/sysdb.h
-@@ -1113,4 +1113,10 @@ errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx,
-                                   const char ***_sids,
-                                   const char ***_dns,
-                                   size_t *_n);
-+
-+errno_t sysdb_handle_original_uuid(const char *orig_name,
-+                                   struct sysdb_attrs *src_attrs,
-+                                   const char *src_name,
-+                                   struct sysdb_attrs *dest_attrs,
-+                                   const char *dest_name);
- #endif /* __SYS_DB_H__ */
-diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
-index 6085762dcc5585114dd3049dd3a365856cb6b190..7e1c1d9763a04cd33374770f4ea5d51286bcfee2 100644
---- a/src/db/sysdb_ops.c
-+++ b/src/db/sysdb_ops.c
-@@ -3670,3 +3670,55 @@ done:
-     talloc_free(tmp_ctx);
-     return ret;
- }
-+
-+errno_t sysdb_handle_original_uuid(const char *orig_name,
-+                                   struct sysdb_attrs *src_attrs,
-+                                   const char *src_name,
-+                                   struct sysdb_attrs *dest_attrs,
-+                                   const char *dest_name)
-+{
-+    int ret;
-+    struct ldb_message_element *el;
-+    char guid_str_buf[GUID_STR_BUF_SIZE];
-+
-+    if (orig_name == NULL || src_attrs == NULL || src_name == NULL
-+            || dest_attrs == NULL || dest_name == NULL) {
-+        return EINVAL;
-+    }
-+
-+    ret = sysdb_attrs_get_el_ext(src_attrs, src_name, false, &el);
-+    if (ret != EOK) {
-+        if (ret != ENOENT) {
-+            DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el failed.\n");
-+        }
-+        return ret;
-+    }
-+
-+    if (el->num_values != 1) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Found more than one UUID value, using the first.\n");
-+    }
-+
-+    /* Check if we got a binary AD objectGUID */
-+    if (el->values[0].length == GUID_BIN_LENGTH
-+            && strcasecmp(orig_name, "objectGUID") == 0) {
-+        ret = guid_blob_to_string_buf(el->values[0].data, guid_str_buf,
-+                                      GUID_STR_BUF_SIZE);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "guid_blob_to_string_buf failed.\n");
-+            return ret;
-+        }
-+
-+        ret = sysdb_attrs_add_string(dest_attrs, dest_name, guid_str_buf);
-+    } else {
-+        ret = sysdb_attrs_add_string(dest_attrs, dest_name,
-+                                     (const char *)el->values[0].data);
-+    }
-+
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n");
-+        return ret;;
-+    }
-+
-+    return EOK;
-+}
-diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
-index 00a676372fa042dfc2d57e5799261f9a45ed4a73..1714188bee681ff70a03db741cf50058f145abbe 100644
---- a/src/providers/ldap/sdap_async_groups.c
-+++ b/src/providers/ldap/sdap_async_groups.c
-@@ -512,7 +512,6 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     bool use_id_mapping;
-     bool need_filter;
-     char *sid_str;
--    const char *uuid;
-     struct sss_domain_info *subdomain;
- 
-     tmpctx = talloc_new(NULL);
-@@ -549,22 +548,14 @@ static int sdap_save_group(TALLOC_CTX *memctx,
-     }
- 
-     /* Always store UUID if available */
--    ret = sysdb_attrs_get_string(attrs,
--                                 opts->group_map[SDAP_AT_GROUP_UUID].sys_name,
--                                 &uuid);
--    if (ret == EOK) {
--        ret = sysdb_attrs_add_string(group_attrs, SYSDB_UUID, uuid);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n",
--                                         sss_strerror(ret));
--            goto done;
--        }
--    } else if (ret == ENOENT) {
--        DEBUG(SSSDBG_TRACE_ALL, "UUID not available for group [%s].\n",
--                                 group_name);
--    } else {
--        DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n",
--                                     sss_strerror(ret));
-+    ret = sysdb_handle_original_uuid(
-+                                   opts->group_map[SDAP_AT_GROUP_UUID].def_name,
-+                                   attrs,
-+                                   opts->group_map[SDAP_AT_GROUP_UUID].sys_name,
-+                                   group_attrs, SYSDB_UUID);
-+    if (ret != EOK) {
-+        DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE,
-+              "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret));
-     }
- 
-     /* If this object has a SID available, we will determine the correct
-diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
-index 43b72fe2051b452c6ea755c8842117cceafa143a..416d2a9594e456b159f24c224fdd8bf8617377d7 100644
---- a/src/providers/ldap/sdap_async_initgroups.c
-+++ b/src/providers/ldap/sdap_async_initgroups.c
-@@ -197,8 +197,13 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb,
-                     original_dn = NULL;
-                 }
- 
-+                ret = sysdb_handle_original_uuid(
-+                                   opts->group_map[SDAP_AT_GROUP_UUID].def_name,
-+                                   ldap_groups[ai],
-+                                   opts->group_map[SDAP_AT_GROUP_UUID].sys_name,
-+                                   ldap_groups[ai], "uniqueIDstr");
-                 ret = sysdb_attrs_get_string(ldap_groups[ai],
--                                             SYSDB_UUID,
-+                                             "uniqueIDstr",
-                                              &uuid);
-                 if (ret) {
-                     DEBUG(SSSDBG_FUNC_DATA,
-diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c
-index 367e3d795ddd0db5c1c2f8e57d700419f371cd15..82b4df4793f5f0679046f259c251f5897af831cf 100644
---- a/src/providers/ldap/sdap_async_users.c
-+++ b/src/providers/ldap/sdap_async_users.c
-@@ -140,7 +140,6 @@ int sdap_save_user(TALLOC_CTX *memctx,
-     TALLOC_CTX *tmpctx = NULL;
-     bool use_id_mapping;
-     char *sid_str;
--    const char *uuid;
-     char *dom_sid_str = NULL;
-     struct sss_domain_info *subdomain;
- 
-@@ -179,21 +178,13 @@ int sdap_save_user(TALLOC_CTX *memctx,
-     }
- 
-     /* Always store UUID if available */
--    ret = sysdb_attrs_get_string(attrs,
--                                 opts->user_map[SDAP_AT_USER_UUID].sys_name,
--                                 &uuid);
--    if (ret == EOK) {
--        ret = sysdb_attrs_add_string(user_attrs, SYSDB_UUID, uuid);
--        if (ret != EOK) {
--            DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n",
--                                         sss_strerror(ret));
--            goto done;
--        }
--    } else if (ret == ENOENT) {
--        DEBUG(SSSDBG_TRACE_ALL, "UUID not available for user.\n");
--    } else {
--        DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n",
--                                     sss_strerror(ret));
-+    ret = sysdb_handle_original_uuid(opts->user_map[SDAP_AT_USER_UUID].def_name,
-+                                     attrs,
-+                                     opts->user_map[SDAP_AT_USER_UUID].sys_name,
-+                                     user_attrs, SYSDB_UUID);
-+    if (ret != EOK) {
-+        DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE,
-+              "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret));
-     }
- 
-     /* If this object has a SID available, we will determine the correct
-diff --git a/src/tests/cmocka/test_string_utils.c b/src/tests/cmocka/test_string_utils.c
-index e446387d6c429515360b23b428555befa915b49a..5d3fcf4fe454a0be3a4c72b778003481f66910bb 100644
---- a/src/tests/cmocka/test_string_utils.c
-+++ b/src/tests/cmocka/test_string_utils.c
-@@ -133,3 +133,62 @@ void test_reverse_replace_whitespaces(void **state)
-     assert_true(check_leaks_pop(mem_ctx) == true);
-     talloc_free(mem_ctx);
- }
-+
-+void test_guid_blob_to_string_buf(void **state)
-+{
-+    int ret;
-+    char str_buf[GUID_STR_BUF_SIZE];
-+    size_t c;
-+
-+    /* How to get test data:
-+     * The objectGUID attribute contains a 16byte long binary value
-+     * representing the GUID of the object. This data can be converted
-+     * manually to the string representation but it might be easier to use
-+     * LDAP_SERVER_EXTENDED_DN_OID as described in [MS-ADST] section
-+     * 3.1.1.3.4.1.5. This is an LDAP extended control which adds the GUID and
-+     * the SID to the DN of an object. This can be activate with the -E
-+     * ldapsearch option like:
-+     *
-+     *  ldapsearch -E 1.2.840.113556.1.4.529=::MAMCAQE= ....
-+     *
-+     * where 'MAMCAQE=' is the base64 encoded BER sequence with the integer
-+     * value 1 (see [MS-ADTS] for details about possible values).
-+     *
-+     * Btw, if you want to use the string representation of a GUID to search
-+     * for an object in AD you have to use the GUID as the search base in the
-+     * following form:
-+     *
-+     *  ldapsearch b '<GUID=fea80d8d-dbd5-4f84-8574-7db0477f962e>' ...
-+     *
-+     * (please note that the '<' and '>' are really needed).
-+     */
-+    struct test_data {
-+        uint8_t blob[16];
-+        const char *guid_str;
-+    } test_data[] = {
-+        {{0x8d, 0x0d, 0xa8, 0xfe, 0xd5, 0xdb, 0x84, 0x4f,
-+          0x85, 0x74, 0x7d, 0xb0, 0x47, 0x7f, 0x96, 0x2e},
-+        "fea80d8d-dbd5-4f84-8574-7db0477f962e"},
-+        {{0x91, 0x7e, 0x2e, 0xf8, 0x4e, 0x44, 0xfa, 0x4e,
-+         0xb1, 0x13, 0x08, 0x98, 0x63, 0x49, 0x6c, 0xc6},
-+        "f82e7e91-444e-4efa-b113-089863496cc6"},
-+        {{0}, NULL}
-+    };
-+
-+    ret = guid_blob_to_string_buf(NULL, str_buf, GUID_STR_BUF_SIZE);
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = guid_blob_to_string_buf((const uint8_t *) "1234567812345678", NULL,
-+                                  GUID_STR_BUF_SIZE);
-+    assert_int_equal(ret, EINVAL);
-+
-+    ret = guid_blob_to_string_buf((const uint8_t *) "1234567812345678", str_buf, 0);
-+    assert_int_equal(ret, EINVAL);
-+
-+    for (c = 0; test_data[c].guid_str != NULL; c++) {
-+        ret = guid_blob_to_string_buf(test_data[c].blob, str_buf,
-+                                      sizeof(str_buf));
-+        assert_int_equal(ret, EOK);
-+        assert_string_equal(test_data[c].guid_str, str_buf);
-+    }
-+}
-diff --git a/src/tests/cmocka/test_sysdb_utils.c b/src/tests/cmocka/test_sysdb_utils.c
-new file mode 100644
-index 0000000000000000000000000000000000000000..d217314ccb9234f8d0d329d87c5dc9e847acbcf0
---- /dev/null
-+++ b/src/tests/cmocka/test_sysdb_utils.c
-@@ -0,0 +1,134 @@
-+/*
-+    SSSD
-+
-+    sysdb_utils - Tests for various sysdb calls
-+
-+    Authors:
-+        Sumit Bose <sbose@redhat.com>
-+
-+    Copyright (C) 2015 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 <stdarg.h>
-+#include <stddef.h>
-+#include <setjmp.h>
-+#include <cmocka.h>
-+#include <popt.h>
-+
-+#include "tests/cmocka/common_mock.h"
-+
-+#define IPA_UUID "bcae7c40-97eb-11e4-88ca-525400e96a6b"
-+
-+#define AD_GUID_BIN {0x8d, 0x0d, 0xa8, 0xfe, 0xd5, 0xdb, 0x84, 0x4f, \
-+                     0x85, 0x74, 0x7d, 0xb0, 0x47, 0x7f, 0x96, 0x2e};
-+#define AD_GUID "fea80d8d-dbd5-4f84-8574-7db0477f962e"
-+static void test_sysdb_handle_original_uuid(void **state)
-+{
-+    int ret;
-+    struct sysdb_attrs *src_attrs;
-+    struct sysdb_attrs *dest_attrs;
-+    const char *guid;
-+    uint8_t bin_guid[] = AD_GUID_BIN;
-+    struct ldb_val guid_val = {bin_guid, 16};
-+
-+    ret = sysdb_handle_original_uuid(NULL, NULL, NULL, NULL, NULL);
-+    assert_int_equal(ret, EINVAL);
-+
-+    src_attrs = sysdb_new_attrs(NULL);
-+    assert_non_null(src_attrs);
-+
-+    dest_attrs = sysdb_new_attrs(NULL);
-+    assert_non_null(dest_attrs);
-+
-+    ret = sysdb_handle_original_uuid("xyz", src_attrs, "abc", dest_attrs,
-+                                     "def");
-+    assert_int_equal(ret, ENOENT);
-+
-+    ret = sysdb_attrs_add_val(src_attrs, "GUID", &guid_val);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_attrs_add_string(src_attrs, "UUID", IPA_UUID);
-+    assert_int_equal(ret, EOK);
-+
-+    ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID",
-+                                     dest_attrs, "def");
-+    assert_int_equal(ret, EOK);
-+    ret = sysdb_attrs_get_string(dest_attrs, "def", &guid);
-+    assert_int_equal(ret, EOK);
-+    assert_string_equal(guid, AD_GUID);
-+
-+    ret = sysdb_handle_original_uuid("ipaUniqueID", src_attrs, "UUID",
-+                                     dest_attrs, "ghi");
-+    assert_int_equal(ret, EOK);
-+    ret = sysdb_attrs_get_string(dest_attrs, "ghi", &guid);
-+    assert_int_equal(ret, EOK);
-+    assert_string_equal(guid, IPA_UUID);
-+
-+    talloc_free(src_attrs);
-+    src_attrs = sysdb_new_attrs(NULL);
-+    assert_non_null(src_attrs);
-+
-+    /* check objectGUID with length other than 16 */
-+    ret = sysdb_attrs_add_string(src_attrs, "GUID", IPA_UUID);
-+    assert_int_equal(ret, EOK);
-+    ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID",
-+                                     dest_attrs, "jkl");
-+    assert_int_equal(ret, EOK);
-+    ret = sysdb_attrs_get_string(dest_attrs, "jkl", &guid);
-+    assert_int_equal(ret, EOK);
-+    assert_string_equal(guid, IPA_UUID);
-+
-+    talloc_free(src_attrs);
-+    talloc_free(dest_attrs);
-+}
-+
-+int main(int argc, const char *argv[])
-+{
-+    int rv;
-+    poptContext pc;
-+    int opt;
-+    struct poptOption long_options[] = {
-+        POPT_AUTOHELP
-+        SSSD_DEBUG_OPTS
-+        POPT_TABLEEND
-+    };
-+
-+    const UnitTest tests[] = {
-+        unit_test(test_sysdb_handle_original_uuid),
-+    };
-+
-+    /* Set debug level to invalid value so we can deside if -d 0 was used. */
-+    debug_level = SSSDBG_INVALID;
-+
-+    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
-+    while((opt = poptGetNextOpt(pc)) != -1) {
-+        switch(opt) {
-+        default:
-+            fprintf(stderr, "\nInvalid option %s: %s\n\n",
-+                    poptBadOption(pc, 0), poptStrerror(opt));
-+            poptPrintUsage(pc, stderr, 0);
-+            return 1;
-+        }
-+    }
-+    poptFreeContext(pc);
-+
-+    DEBUG_CLI_INIT(debug_level);
-+
-+    tests_set_cwd();
-+    rv = run_tests(tests);
-+
-+    return rv;
-+}
-diff --git a/src/tests/cmocka/test_utils.h b/src/tests/cmocka/test_utils.h
-index f85ac2f2b3c50a60099970752b06adbad38b9fd1..61ef7e43a82649d775d9b932def9e957b0761bed 100644
---- a/src/tests/cmocka/test_utils.h
-+++ b/src/tests/cmocka/test_utils.h
-@@ -29,5 +29,6 @@ void test_textual_public_key(void **state);
- /* from src/tests/cmocka/test_string_utils.c */
- void test_replace_whitespaces(void **state);
- void test_reverse_replace_whitespaces(void **state);
-+void test_guid_blob_to_string_buf(void **state);
- 
- #endif /* __TESTS__CMOCKA__TEST_UTILS_H__ */
-diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
-index 46abab5ae32189b0561d1901407d2bb38a1ec4c0..7e603fda15024da71cf57912acc69bddcc882357 100644
---- a/src/tests/cwrap/Makefile.am
-+++ b/src/tests/cwrap/Makefile.am
-@@ -78,6 +78,7 @@ server_tests_SOURCES = \
-     ../../../src/util/atomic_io.c \
-     ../../../src/util/signal.c \
-     ../../../src/util/util.c \
-+    ../../../src/util/string_utils.c \
-     ../../../src/util/strtonum.c \
-     ../../../src/util/util_errors.c \
-     ../../../src/util/safe-format-string.c \
-@@ -115,6 +116,7 @@ usertools_tests_SOURCES = \
-     ../../../src/util/domain_info_utils.c \
-     ../../../src/util/safe-format-string.c \
-     ../../../src/util/usertools.c \
-+    ../../../src/util/string_utils.c \
-     ../../../src/util/strtonum.c \
-     ../../../src/util/backup_file.c \
-     ../../../src/util/atomic_io.c \
-diff --git a/src/util/string_utils.c b/src/util/string_utils.c
-index a39b950e852de7ed43d6e8a32de3e7fb08a0dc56..71b2a092018076fd9c20ef9ac39a11964876cfc3 100644
---- a/src/util/string_utils.c
-+++ b/src/util/string_utils.c
-@@ -83,3 +83,28 @@ char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx,
- 
-     return replace_char(mem_ctx, orig_name, subst, ' ');
- }
-+
-+errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf,
-+                                size_t buf_size)
-+{
-+    int ret;
-+
-+    if (blob == NULL || str_buf == NULL || buf_size < GUID_STR_BUF_SIZE) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Buffer too small.\n");
-+        return EINVAL;
-+    }
-+
-+    ret = snprintf(str_buf, buf_size,
-+         "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-+         blob[3], blob[2], blob[1], blob[0],
-+         blob[5], blob[4],
-+         blob[7], blob[6],
-+         blob[8], blob[9],
-+         blob[10], blob[11],blob[12], blob[13],blob[14], blob[15]);;
-+    if (ret != (GUID_STR_BUF_SIZE -1)) {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "snprintf failed.\n");
-+        return EIO;
-+    }
-+
-+    return EOK;
-+}
-diff --git a/src/util/util.h b/src/util/util.h
-index bf3a9a057aed77e93949370f8651af2631d91432..1530b550bb85c121cbc33c8c6353b7ecae9edaae 100644
---- a/src/util/util.h
-+++ b/src/util/util.h
-@@ -618,6 +618,13 @@ char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx,
-                                  const char *orig_name,
-                                  const char replace_char);
- 
-+#define GUID_BIN_LENGTH 16
-+/* 16 2-digit hex values + 4 dashes + terminating 0 */
-+#define GUID_STR_BUF_SIZE (2 * GUID_BIN_LENGTH + 4 + 1)
-+
-+errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf,
-+                                size_t buf_size);
-+
- /* from become_user.c */
- errno_t become_user(uid_t uid, gid_t gid);
- struct sss_creds;
--- 
-2.1.0
-
diff --git a/SOURCES/0202-Download-complete-groups-if-ignore_group_members-is-.patch b/SOURCES/0202-Download-complete-groups-if-ignore_group_members-is-.patch
deleted file mode 100644
index 59b00f7..0000000
--- a/SOURCES/0202-Download-complete-groups-if-ignore_group_members-is-.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From 591ee6dee11c4509e8e748ce83414913143e751d Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 22 May 2015 15:19:31 +0200
-Subject: [PATCH 202/207] Download complete groups if ignore_group_members is
- set with tokengroups
-
-Resolves:
-    https://fedorahosted.org/sssd/ticket/2644
-
-When tokenGroups are enabled, we save groups using their SID as the RDN
-attribute during initgroups() and later, if the groups is requested and saved
-again with the full name, remove the original and save the new group entry.
-
-Saving the new group entry would break if ignore_group_members is also
-set, because the new group entry would lack the "member" attribute, so the
-member/memberof links between the new group and the user entry wouldn't
-be established again.
-
-This patch changes the initgroups processing so that the full group
-object is fetched when initgroups is enabled but together with
-ignore_group_members. This solution imposes some performance impact,
-because instead of one search for tokenGroups we also need to resolve the
-groups. The more systematic solution would be to get rid of removing the
-group entry as described in https://fedorahosted.org/sssd/ticket/2656
-
-To reproduce the bug, set: ignore_group_members = True with a
-backend that uses:
-    id_provider = ad
-Then run:
-    $ id aduser@ad_domain.com
-    $ id aduser@ad_domain.com
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
-(cherry picked from commit ee44aac95e42c3cb634876286a2aa4960ac69a2b)
----
- src/providers/ldap/sdap_async_initgroups_ad.c | 17 +++++++++++++++--
- 1 file changed, 15 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
-index 9915f18..463d850 100644
---- a/src/providers/ldap/sdap_async_initgroups_ad.c
-+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
-@@ -1445,7 +1445,18 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx,
-     state->use_id_mapping = use_id_mapping;
-     state->domain = domain;
- 
--    if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) {
-+    /* We can compute the the gidNumber attribute from SIDs obtained from
-+     * the tokenGroups lookup in case ID mapping is used for a user from the
-+     * parent domain. For trusted domains, we need to know the group type
-+     * to be able to filter out domain-local groups. Additionally, as a
-+     * temporary workaround until https://fedorahosted.org/sssd/ticket/2656
-+     * is fixed, we also fetch the group object if group members are ignored
-+     * to avoid having to transfer and retain members when the fake
-+     * tokengroups object without name is replaced by the full group object
-+     */
-+    if (state->use_id_mapping
-+            && !IS_SUBDOMAIN(state->domain)
-+            && state->domain->ignore_group_members == false) {
-         subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts,
-                                                          sysdb, domain, sh,
-                                                          name, orig_dn,
-@@ -1485,7 +1496,9 @@ static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq)
-     req = tevent_req_callback_data(subreq, struct tevent_req);
-     state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state);
- 
--    if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) {
-+    if (state->use_id_mapping
-+            && !IS_SUBDOMAIN(state->domain)
-+            && state->domain->ignore_group_members == false) {
-         ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq);
-     } else {
-         ret = sdap_ad_tokengroups_initgr_posix_recv(subreq);
--- 
-2.1.0
-
diff --git a/SOURCES/0203-confdb-Add-new-option-subdomain_inherit.patch b/SOURCES/0203-confdb-Add-new-option-subdomain_inherit.patch
deleted file mode 100644
index 8659f29..0000000
--- a/SOURCES/0203-confdb-Add-new-option-subdomain_inherit.patch
+++ /dev/null
@@ -1,152 +0,0 @@
-From a4dcc9a1290cfb82fde44bb8f4a4ab8d4668cd5b Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 29 Apr 2015 19:41:14 +0200
-Subject: [PATCH 203/207] confdb: Add new option subdomain_inherit
-
-Adds a new option subdomain_inherit that would allow administrators to pick
-and choose which option to pass to subdomains.
-
-This option is required for:
-    https://fedorahosted.org/sssd/ticket/2644
-as a short-term fix.
-
-The proper solution is described in:
-    https://fedorahosted.org/sssd/ticket/2599
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit 1711cbfd2e36d44af1ae50e3a2beeec3a1f0b5e8)
----
- src/confdb/confdb.c                  | 13 +++++++++++++
- src/confdb/confdb.h                  |  2 ++
- src/config/SSSDConfig/__init__.py.in |  1 +
- src/config/SSSDConfigTest.py         |  6 ++++--
- src/config/etc/sssd.api.conf         |  1 +
- src/man/sssd.conf.5.xml              | 20 +++++++++++++++++++-
- 6 files changed, 40 insertions(+), 3 deletions(-)
-
-diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
-index c55a945..6b2ce73 100644
---- a/src/confdb/confdb.c
-+++ b/src/confdb/confdb.c
-@@ -1212,6 +1212,19 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
-         }
-     }
- 
-+    tmp = ldb_msg_find_attr_as_string(res->msgs[0],
-+                                      CONFDB_DOMAIN_SUBDOMAIN_INHERIT,
-+                                      NULL);
-+    if (tmp != NULL) {
-+        ret = split_on_separator(domain, tmp, ',', true, true,
-+                                 &domain->sd_inherit, NULL);
-+        if (ret != 0) {
-+            DEBUG(SSSDBG_FATAL_FAILURE,
-+                  "Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE);
-+            goto done;
-+        }
-+    }
-+
-     ret = get_entry_as_uint32(res->msgs[0], &domain->subdomain_refresh_interval,
-                               CONFDB_DOMAIN_SUBDOMAIN_REFRESH, 14400);
-     if (ret != EOK || domain->subdomain_refresh_interval == 0) {
-diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
-index 159aa9f..468c757 100644
---- a/src/confdb/confdb.h
-+++ b/src/confdb/confdb.h
-@@ -183,6 +183,7 @@
- #define CONFDB_DOMAIN_PWD_EXPIRATION_WARNING "pwd_expiration_warning"
- #define CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL "refresh_expired_interval"
- #define CONFDB_DOMAIN_OFFLINE_TIMEOUT "offline_timeout"
-+#define CONFDB_DOMAIN_SUBDOMAIN_INHERIT "subdomain_inherit"
- 
- /* Local Provider */
- #define CONFDB_LOCAL_DEFAULT_SHELL   "default_shell"
-@@ -263,6 +264,7 @@ struct sss_domain_info {
-     struct sss_domain_info *next;
- 
-     bool disabled;
-+    char **sd_inherit;
- };
- 
- /**
-diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
-index 500bd71..8b9ab5a 100644
---- a/src/config/SSSDConfig/__init__.py.in
-+++ b/src/config/SSSDConfig/__init__.py.in
-@@ -144,6 +144,7 @@ option_strings = {
-     'dyndns_auth' : _("What kind of authentication should be used to perform the DNS update"),
-     'subdomain_enumerate' : _('Control enumeration of trusted domains'),
-     'subdomain_refresh_interval' : _('How often should subdomains list be refreshed'),
-+    'subdomain_inherit' : _('List of options that should be inherited into a subdomain'),
- 
-     # [provider/ipa]
-     'ipa_domain' : _('IPA domain'),
-diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
-index 78e22f6..6719132 100755
---- a/src/config/SSSDConfigTest.py
-+++ b/src/config/SSSDConfigTest.py
-@@ -538,7 +538,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
-             'hostid_provider',
-             'subdomains_provider',
-             'realmd_tags',
--            'subdomain_refresh_interval']
-+            'subdomain_refresh_interval',
-+            'subdomain_inherit']
- 
-         self.assertTrue(type(options) == dict,
-                         "Options should be a dictionary")
-@@ -897,7 +898,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
-             'hostid_provider',
-             'subdomains_provider',
-             'realmd_tags',
--            'subdomain_refresh_interval']
-+            'subdomain_refresh_interval',
-+            'subdomain_inherit']
- 
-         self.assertTrue(type(options) == dict,
-                         "Options should be a dictionary")
-diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
-index c16769a..8b3dee6 100644
---- a/src/config/etc/sssd.api.conf
-+++ b/src/config/etc/sssd.api.conf
-@@ -129,6 +129,7 @@ default_shell = str, None, false
- description = str, None, false
- realmd_tags = str, None, false
- subdomain_refresh_interval = int, None, false
-+subdomain_inherit = str, None, false
- 
- #Entry cache timeouts
- entry_cache_user_timeout = int, None, false
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index 2002ccc..f7d688a 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -476,7 +476,25 @@
-                         </para>
-                     </listitem>
-                 </varlistentry>
--
-+                <varlistentry>
-+                    <term>subdomain_inherit (string)</term>
-+                    <listitem>
-+                        <para>
-+                            Specifies a list of configuration parameters that
-+                            should be inherited by a subdomain. Please note
-+                            that only selected parameters can be inherited.
-+                        </para>
-+                        <para>
-+                            Example:
-+                            <programlisting>
-+subdomain_inherit = ldap_purge_cache_timeout
-+                            </programlisting>
-+                        </para>
-+                        <para>
-+                            Default: none
-+                        </para>
-+                    </listitem>
-+                </varlistentry>
-             </variablelist>
-         </refsect2>
- 
--- 
-2.1.0
-
diff --git a/SOURCES/0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch b/SOURCES/0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch
deleted file mode 100644
index a2f16fe..0000000
--- a/SOURCES/0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch
+++ /dev/null
@@ -1,308 +0,0 @@
-From 092c9d35a4cc85c9910669bb3a8169f000ebc69c Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Wed, 6 May 2015 08:06:53 +0200
-Subject: [PATCH 204/207] DP: Add a function to inherit DP options, if set
-
-Related to:
-    https://fedorahosted.org/sssd/ticket/2644
-
-Adds a utility function that checks if a DP option is present in
-the subdomain_inherit list. If it is, then the option is set from source
-to destination dp_option array.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit b3d110fbc424a03674a6e50e489a7cbab9702f0b)
-
-Conflicts:
-	src/tests/cmocka/test_dp_opts.c
----
- src/providers/data_provider.h      |   5 ++
- src/providers/data_provider_opts.c |  57 +++++++++++++++++
- src/tests/cmocka/test_dp_opts.c    | 127 ++++++++++++++++++++++++++++++++++---
- 3 files changed, 181 insertions(+), 8 deletions(-)
-
-diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
-index 5df493e..657d2b7 100644
---- a/src/providers/data_provider.h
-+++ b/src/providers/data_provider.h
-@@ -277,6 +277,11 @@ struct dp_option {
- 
- #define DP_OPTION_TERMINATOR { NULL, 0, NULL_STRING, NULL_STRING }
- 
-+void dp_option_inherit(char **inherit_opt_list,
-+                       int option,
-+                       struct dp_option *parent_opts,
-+                       struct dp_option *subdom_opts);
-+
- int dp_get_options(TALLOC_CTX *memctx,
-                    struct confdb_ctx *cdb,
-                    const char *conf_path,
-diff --git a/src/providers/data_provider_opts.c b/src/providers/data_provider_opts.c
-index 8ad8456..9db43fc 100644
---- a/src/providers/data_provider_opts.c
-+++ b/src/providers/data_provider_opts.c
-@@ -21,6 +21,63 @@
- 
- #include "data_provider.h"
- 
-+/* =Copy-Option-From-Subdomain-If-Allowed================================= */
-+void dp_option_inherit(char **inherit_opt_list,
-+                       int option,
-+                       struct dp_option *parent_opts,
-+                       struct dp_option *subdom_opts)
-+{
-+    errno_t ret;
-+    bool inherit_option;
-+
-+    inherit_option = string_in_list(parent_opts[option].opt_name,
-+                                    inherit_opt_list, false);
-+    if (inherit_option == false) {
-+        DEBUG(SSSDBG_CONF_SETTINGS,
-+              "Option %s is not set up to be inherited\n",
-+              parent_opts[option].opt_name);
-+        return;
-+    }
-+
-+    DEBUG(SSSDBG_CONF_SETTINGS,
-+          "Will inherit option %s\n", parent_opts[option].opt_name);
-+    switch (parent_opts[option].type) {
-+    case DP_OPT_NUMBER:
-+        ret = dp_opt_set_int(subdom_opts,
-+                             option,
-+                             dp_opt_get_int(parent_opts,
-+                                            option));
-+        break;
-+    case DP_OPT_STRING:
-+        ret = dp_opt_set_string(subdom_opts,
-+                                option,
-+                                dp_opt_get_string(parent_opts,
-+                                                  option));
-+        break;
-+    case DP_OPT_BLOB:
-+        ret = dp_opt_set_blob(subdom_opts,
-+                              option,
-+                              dp_opt_get_blob(parent_opts,
-+                                              option));
-+        break;
-+    case DP_OPT_BOOL:
-+        ret = dp_opt_set_bool(subdom_opts,
-+                              option,
-+                              dp_opt_get_bool(parent_opts,
-+                                              option));
-+        break;
-+    default:
-+        ret = EINVAL;
-+        break;
-+    }
-+
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_MINOR_FAILURE,
-+              "Failed to inherit option %s\n", parent_opts[option].opt_name);
-+        /* Not fatal */
-+    }
-+}
-+
- /* =Retrieve-Options====================================================== */
- 
- int dp_get_options(TALLOC_CTX *memctx,
-diff --git a/src/tests/cmocka/test_dp_opts.c b/src/tests/cmocka/test_dp_opts.c
-index 0f3052a..60267ab 100644
---- a/src/tests/cmocka/test_dp_opts.c
-+++ b/src/tests/cmocka/test_dp_opts.c
-@@ -284,37 +284,63 @@ void opt_test_getset_teardown(void **state)
-     talloc_free(opts);
- }
- 
--void opt_test_getset_string(void **state)
-+static void assert_nondefault_string_empty(struct dp_option *opts)
- {
--    struct dp_option *opts = talloc_get_type(*state, struct dp_option);
--    int ret;
-     char *s;
- 
-     s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT);
-     assert_null(s);
-+}
-+
-+static void set_nondefault_string(struct dp_option *opts)
-+{
-+    int ret;
- 
-     ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1");
-     assert_int_equal(ret, EOK);
-+}
-+
-+static void check_nondefault_string(struct dp_option *opts)
-+{
-+    char *s;
- 
-     s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT);
-     assert_non_null(s);
-     assert_string_equal(s, "str1");
- }
- 
--void opt_test_getset_blob(void **state)
-+void opt_test_getset_string(void **state)
- {
-     struct dp_option *opts = talloc_get_type(*state, struct dp_option);
--    int ret;
-+
-+    assert_nondefault_string_empty(opts);
-+    set_nondefault_string(opts);
-+    check_nondefault_string(opts);
-+}
-+
-+static void assert_nondefault_blob_empty(struct dp_option *opts)
-+{
-     struct dp_opt_blob b;
- 
-     b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT);
-     assert_null(b.data);
-     assert_int_equal(b.length, 0);
-+}
-+
-+static void set_nondefault_blob(struct dp_option *opts)
-+{
-+    struct dp_opt_blob b;
-+    int ret;
- 
-     b.data = discard_const_p(uint8_t, "blob2");
-     b.length = strlen("blob2");
-     ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b);
-     assert_int_equal(ret, EOK);
-+}
-+
-+static void check_nondefault_blob(struct dp_option *opts)
-+{
-+    struct dp_opt_blob b;
- 
-     b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT);
-     assert_non_null(b.data);
-@@ -322,22 +348,45 @@ void opt_test_getset_blob(void **state)
-     assert_memory_equal(b.data, "blob2", strlen("blob2"));
- }
- 
--void opt_test_getset_int(void **state)
-+void opt_test_getset_blob(void **state)
- {
-     struct dp_option *opts = talloc_get_type(*state, struct dp_option);
--    int ret;
--    int i;
- 
-+    assert_nondefault_blob_empty(opts);
-+    set_nondefault_blob(opts);
-+    check_nondefault_blob(opts);
-+}
-+
-+static void assert_nondefault_int_notset(struct dp_option *opts)
-+{
-+    int i;
-     i = dp_opt_get_int(opts, OPT_INT_NODEFAULT);
-     assert_int_equal(i, 0);
-+}
- 
-+static void set_nondefault_int(struct dp_option *opts)
-+{
-+    int ret;
-     ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456);
-     assert_int_equal(ret, EOK);
-+}
- 
-+static void assert_nondefault_int_set(struct dp_option *opts)
-+{
-+    int i;
-     i = dp_opt_get_int(opts, OPT_INT_NODEFAULT);
-     assert_int_equal(i, 456);
- }
- 
-+void opt_test_getset_int(void **state)
-+{
-+    struct dp_option *opts = talloc_get_type(*state, struct dp_option);
-+
-+    assert_nondefault_int_notset(opts);
-+    set_nondefault_int(opts);
-+    assert_nondefault_int_set(opts);
-+}
-+
- void opt_test_getset_bool(void **state)
- {
-     struct dp_option *opts = talloc_get_type(*state, struct dp_option);
-@@ -354,6 +403,65 @@ void opt_test_getset_bool(void **state)
-     assert_false(b == true);
- }
- 
-+void opt_test_inherit(void **state)
-+{
-+    struct dp_option *opts = talloc_get_type(*state, struct dp_option);
-+    int ret;
-+    struct dp_option *opts_copy;
-+    const char *s;
-+    const char *sd_inherit_match[] = { "string_nodefault",
-+                                       "blob_nodefault",
-+                                       "int_nodefault",
-+                                       "bool_true",
-+                                       NULL };
-+
-+    ret = dp_copy_defaults(opts, test_def_opts,
-+                           OPT_NUM_OPTS, &opts_copy);
-+    assert_int_equal(ret, EOK);
-+    assert_defaults(opts);
-+
-+    dp_option_inherit(NULL, OPT_STRING_NODEFAULT,
-+                      opts, opts_copy);
-+    s = dp_opt_get_string(opts_copy, OPT_STRING_NODEFAULT);
-+    assert_null(s);
-+
-+    /* string */
-+    assert_nondefault_string_empty(opts_copy);
-+    set_nondefault_string(opts);
-+    dp_option_inherit(discard_const(sd_inherit_match),
-+                      OPT_STRING_NODEFAULT,
-+                      opts, opts_copy);
-+    check_nondefault_string(opts_copy);
-+
-+    /* blob */
-+    assert_nondefault_blob_empty(opts_copy);
-+    set_nondefault_blob(opts);
-+    dp_option_inherit(discard_const(sd_inherit_match),
-+                      OPT_BLOB_NODEFAULT,
-+                      opts, opts_copy);
-+    check_nondefault_blob(opts_copy);
-+
-+    /* number */
-+    assert_nondefault_int_notset(opts_copy);
-+    set_nondefault_int(opts);
-+    dp_option_inherit(discard_const(sd_inherit_match),
-+                      OPT_INT_NODEFAULT,
-+                      opts, opts_copy);
-+    assert_nondefault_int_set(opts_copy);
-+
-+    /* bool */
-+    assert_true(dp_opt_get_bool(opts_copy, OPT_BOOL_TRUE));
-+
-+    ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false);
-+    assert_int_equal(ret, EOK);
-+
-+    dp_option_inherit(discard_const(sd_inherit_match),
-+                      OPT_BOOL_TRUE,
-+                      opts, opts_copy);
-+
-+    assert_false(dp_opt_get_bool(opts_copy, OPT_BOOL_TRUE));
-+}
-+
- int main(int argc, const char *argv[])
- {
-     int no_cleanup = 0;
-@@ -380,6 +488,9 @@ int main(int argc, const char *argv[])
-         unit_test_setup_teardown(opt_test_getset_blob,
-                                  opt_test_getset_setup,
-                                  opt_test_getset_teardown),
-+        unit_test_setup_teardown(opt_test_inherit,
-+                                 opt_test_getset_setup,
-+                                 opt_test_getset_teardown),
-         unit_test(opt_test_copy_default),
-         unit_test(opt_test_copy_options),
-         unit_test(opt_test_get)
--- 
-2.1.0
-
diff --git a/SOURCES/0205-SDAP-Add-sdap_copy_map_entry.patch b/SOURCES/0205-SDAP-Add-sdap_copy_map_entry.patch
deleted file mode 100644
index f3f7307..0000000
--- a/SOURCES/0205-SDAP-Add-sdap_copy_map_entry.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-From 62416ef0d547018872da915d0fe863780926d7be Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Fri, 22 May 2015 18:31:42 +0200
-Subject: [PATCH 205/207] SDAP: Add sdap_copy_map_entry
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit 12089241f6a6eabf4f0c95669e5fc2bb3b503c06)
-
-Conflicts:
-	src/tests/cmocka/test_sdap.c
----
- src/providers/ldap/sdap.c    | 17 +++++++++
- src/providers/ldap/sdap.h    |  4 +++
- src/tests/cmocka/test_sdap.c | 82 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 103 insertions(+)
-
-diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
-index e428d5f..bc9f8b3 100644
---- a/src/providers/ldap/sdap.c
-+++ b/src/providers/ldap/sdap.c
-@@ -28,6 +28,23 @@
- 
- /* =Retrieve-Options====================================================== */
- 
-+errno_t sdap_copy_map_entry(const struct sdap_attr_map *src_map,
-+                            struct sdap_attr_map *dst_map,
-+                            int entry_index)
-+{
-+    if (src_map[entry_index].name != NULL) {
-+        dst_map[entry_index].name = talloc_strdup(dst_map,
-+                                                  src_map[entry_index].name);
-+        if (dst_map[entry_index].name == NULL) {
-+            return ENOMEM;
-+        }
-+    } else {
-+        dst_map->name = NULL;
-+    }
-+
-+    return EOK;
-+}
-+
- int sdap_copy_map(TALLOC_CTX *memctx,
-                  struct sdap_attr_map *src_map,
-                  int num_entries,
-diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
-index 921051b..c0e9ff9 100644
---- a/src/providers/ldap/sdap.h
-+++ b/src/providers/ldap/sdap.h
-@@ -467,6 +467,10 @@ struct sdap_deref_attrs {
-     struct sysdb_attrs *attrs;
- };
- 
-+errno_t sdap_copy_map_entry(const struct sdap_attr_map *src_map,
-+                            struct sdap_attr_map *dst_map,
-+                            int entry_index);
-+
- int sdap_copy_map(TALLOC_CTX *memctx,
-                  struct sdap_attr_map *src_map,
-                  int num_entries,
-diff --git a/src/tests/cmocka/test_sdap.c b/src/tests/cmocka/test_sdap.c
-index 404e100..d1e6959 100644
---- a/src/tests/cmocka/test_sdap.c
-+++ b/src/tests/cmocka/test_sdap.c
-@@ -718,6 +718,80 @@ void test_parse_no_dn(void **state)
-     talloc_free(map);
- }
- 
-+struct copy_map_entry_test_ctx {
-+    struct sdap_attr_map *src_map;
-+    struct sdap_attr_map *dst_map;
-+};
-+
-+static void copy_map_entry_test_setup(void **state)
-+{
-+    int ret;
-+    struct copy_map_entry_test_ctx *test_ctx;
-+
-+    assert_true(leak_check_setup());
-+
-+    test_ctx = talloc_zero(global_talloc_context,
-+                           struct copy_map_entry_test_ctx);
-+    assert_non_null(test_ctx);
-+
-+    ret = sdap_copy_map(test_ctx, rfc2307_user_map,
-+                        SDAP_OPTS_USER, &test_ctx->src_map);
-+    assert_int_equal(ret, ERR_OK);
-+
-+    ret = sdap_copy_map(test_ctx, rfc2307_user_map,
-+                        SDAP_OPTS_USER, &test_ctx->dst_map);
-+    assert_int_equal(ret, ERR_OK);
-+
-+    check_leaks_push(test_ctx);
-+    *state = test_ctx;
-+}
-+
-+static void copy_map_entry_test_teardown(void **state)
-+{
-+    struct copy_map_entry_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                               struct copy_map_entry_test_ctx);
-+    assert_true(check_leaks_pop(test_ctx) == true);
-+    talloc_free(test_ctx);
-+    assert_true(leak_check_teardown());
-+    return 0;
-+}
-+
-+static const char *copy_uuid(struct copy_map_entry_test_ctx *test_ctx)
-+{
-+    errno_t ret;
-+
-+    assert_null(test_ctx->dst_map[SDAP_AT_USER_UUID].name);
-+    ret = sdap_copy_map_entry(test_ctx->src_map, test_ctx->dst_map,
-+                              SDAP_AT_USER_UUID);
-+    assert_int_equal(ret, EOK);
-+    return test_ctx->dst_map[SDAP_AT_USER_UUID].name;
-+}
-+
-+static void test_sdap_copy_map_entry(void **state)
-+{
-+    struct copy_map_entry_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                               struct copy_map_entry_test_ctx);
-+    const char *uuid_set_val = "test_uuid_val";
-+    const char *uuid_val = NULL;
-+
-+    test_ctx->src_map[SDAP_AT_USER_UUID].name = discard_const(uuid_set_val);
-+
-+    uuid_val = copy_uuid(test_ctx);
-+    assert_non_null(uuid_val);
-+    assert_string_equal(uuid_val, uuid_set_val);
-+    talloc_free(test_ctx->dst_map[SDAP_AT_USER_UUID].name);
-+}
-+
-+static void test_sdap_copy_map_entry_null_name(void **state)
-+{
-+    struct copy_map_entry_test_ctx *test_ctx = talloc_get_type_abort(*state,
-+                                               struct copy_map_entry_test_ctx);
-+    const char *uuid_val = NULL;
-+
-+    uuid_val = copy_uuid(test_ctx);
-+    assert_null(uuid_val);
-+}
-+
- int main(int argc, const char *argv[])
- {
-     poptContext pc;
-@@ -763,6 +837,14 @@ int main(int argc, const char *argv[])
-         unit_test_setup_teardown(test_parse_deref_map_mismatch,
-                                  parse_entry_test_setup,
-                                  parse_entry_test_teardown),
-+
-+        /* Map option tests */
-+        unit_test_setup_teardown(test_sdap_copy_map_entry,
-+                                 copy_map_entry_test_setup,
-+                                 copy_map_entry_test_teardown),
-+        unit_test_setup_teardown(test_sdap_copy_map_entry_null_name,
-+                                 copy_map_entry_test_setup,
-+                                 copy_map_entry_test_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-2.1.0
-
diff --git a/SOURCES/0206-UTIL-Inherit-ignore_group_members.patch b/SOURCES/0206-UTIL-Inherit-ignore_group_members.patch
deleted file mode 100644
index 1e26b84..0000000
--- a/SOURCES/0206-UTIL-Inherit-ignore_group_members.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 71565f0969738171e04f35e9aba93e63e4e83a8e Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 28 Apr 2015 17:04:51 +0200
-Subject: [PATCH 206/207] UTIL: Inherit ignore_group_members
-
-Resolves:
-    https://fedorahosted.org/sssd/ticket/2644
-
-Allows the administrators to extend ignore_group_members to subdomains
-as well by setting:
-    subdomain_inherit = ignore_group_members
-in the domain section.
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit 01c049ceef55c7bbfca1e47cecb2a0a2cf0a5d44)
----
- src/man/sssd.conf.5.xml      | 4 ++++
- src/util/domain_info_utils.c | 9 +++++++++
- 2 files changed, 13 insertions(+)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index f7d688a..19995be 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -483,6 +483,10 @@
-                             Specifies a list of configuration parameters that
-                             should be inherited by a subdomain. Please note
-                             that only selected parameters can be inherited.
-+                            Currently the following options can be inherited:
-+                        </para>
-+                        <para>
-+                            ignore_group_members
-                         </para>
-                         <para>
-                             Example:
-diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
-index e0f1120..75eca8a 100644
---- a/src/util/domain_info_utils.c
-+++ b/src/util/domain_info_utils.c
-@@ -206,6 +206,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
-                                       const char *forest)
- {
-     struct sss_domain_info *dom;
-+    bool inherit_option;
- 
-     DEBUG(SSSDBG_TRACE_FUNC,
-           "Creating [%s] as subdomain of [%s]!\n", name, parent->name);
-@@ -281,6 +282,14 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
-     dom->enumerate = enumerate;
-     dom->fqnames = true;
-     dom->mpg = mpg;
-+    /* If the parent domain filters out group members, the subdomain should
-+     * as well if configured */
-+    inherit_option = string_in_list(CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS,
-+                                    parent->sd_inherit, false);
-+    if (inherit_option) {
-+        dom->ignore_group_members = parent->ignore_group_members;
-+    }
-+
-     /* If the parent domain explicitly limits ID ranges, the subdomain
-      * should honour the limits as well.
-      */
--- 
-2.1.0
-
diff --git a/SOURCES/0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch b/SOURCES/0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch
deleted file mode 100644
index b888870..0000000
--- a/SOURCES/0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch
+++ /dev/null
@@ -1,340 +0,0 @@
-From 8e382375715232130f7b96d3098a7c7a0d6cef7d Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 28 Apr 2015 13:48:42 +0200
-Subject: [PATCH 207/207] subdomains: Inherit cleanup period and tokengroup
- settings from parent domain
-
-Allows the administrator to extend the functionality of
-ldap_purge_cache_timeout, ldap_user_principal and ldap_use_tokengroups to
-the subdomains.
-
-This is a less intrusive way of achieving:
-    https://fedorahosted.org/sssd/ticket/2627
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit 9b162bf39ef75629f54ffa1d0bd5f9c13119b650)
-
-Conflicts:
-	src/tests/cmocka/test_sdap.c
----
- src/man/sssd.conf.5.xml            |   9 +++
- src/providers/ad/ad_subdomains.c   |   4 +
- src/providers/ipa/ipa_subdomains.c |   4 +
- src/providers/ldap/sdap.c          |  58 ++++++++++++++
- src/providers/ldap/sdap.h          |   4 +
- src/tests/cmocka/test_sdap.c       | 158 +++++++++++++++++++++++++++++++++++++
- 6 files changed, 237 insertions(+)
-
-diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
-index 19995be..ef82dcd 100644
---- a/src/man/sssd.conf.5.xml
-+++ b/src/man/sssd.conf.5.xml
-@@ -489,6 +489,15 @@
-                             ignore_group_members
-                         </para>
-                         <para>
-+                            ldap_purge_cache_timeout
-+                        </para>
-+                        <para>
-+                            ldap_use_tokengroups
-+                        </para>
-+                        <para>
-+                            ldap_user_principal
-+                        </para>
-+                        <para>
-                             Example:
-                             <programlisting>
- subdomain_inherit = ldap_purge_cache_timeout
-diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
-index 3c61d13..554da69 100644
---- a/src/providers/ad/ad_subdomains.c
-+++ b/src/providers/ad/ad_subdomains.c
-@@ -180,6 +180,10 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
-         return EFAULT;
-     }
- 
-+    sdap_inherit_options(subdom->parent->sd_inherit,
-+                         id_ctx->sdap_id_ctx->opts,
-+                         ad_id_ctx->sdap_id_ctx->opts);
-+
-     /* Set up the ID mapping object */
-     ad_id_ctx->sdap_id_ctx->opts->idmap_ctx =
-         id_ctx->sdap_id_ctx->opts->idmap_ctx;
-diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
-index 3148389..e529454 100644
---- a/src/providers/ipa/ipa_subdomains.c
-+++ b/src/providers/ipa/ipa_subdomains.c
-@@ -228,6 +228,10 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
-         return EFAULT;
-     }
- 
-+    sdap_inherit_options(subdom->parent->sd_inherit,
-+                         id_ctx->sdap_id_ctx->opts,
-+                         ad_id_ctx->sdap_id_ctx->opts);
-+
-     ret = sdap_id_setup_tasks(be_ctx,
-                               ad_id_ctx->sdap_id_ctx,
-                               sdom,
-diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
-index bc9f8b3..9b65940 100644
---- a/src/providers/ldap/sdap.c
-+++ b/src/providers/ldap/sdap.c
-@@ -243,6 +243,64 @@ int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx,
-     return EOK;
- }
- 
-+static void sdap_inherit_basic_options(char **inherit_opt_list,
-+                                       struct dp_option *parent_opts,
-+                                       struct dp_option *subdom_opts)
-+{
-+    int inherit_options[] = {
-+        SDAP_CACHE_PURGE_TIMEOUT,
-+        SDAP_AD_USE_TOKENGROUPS,
-+        SDAP_OPTS_BASIC     /* sentinel */
-+    };
-+    int i;
-+
-+    for (i = 0; inherit_options[i] != SDAP_OPTS_BASIC; i++) {
-+        dp_option_inherit(inherit_opt_list,
-+                          inherit_options[i],
-+                          parent_opts,
-+                          subdom_opts);
-+    }
-+}
-+
-+static void sdap_inherit_user_options(char **inherit_opt_list,
-+                                      struct sdap_attr_map *parent_user_map,
-+                                      struct sdap_attr_map *child_user_map)
-+{
-+    int inherit_options[] = {
-+        SDAP_AT_USER_PRINC,
-+        SDAP_OPTS_USER          /* sentinel */
-+    };
-+    int i;
-+    int opt_index;
-+    bool inherit_option;
-+
-+    for (i = 0; inherit_options[i] != SDAP_OPTS_USER; i++) {
-+        opt_index = inherit_options[i];
-+
-+        inherit_option = string_in_list(parent_user_map[opt_index].opt_name,
-+                                        inherit_opt_list,
-+                                        false);
-+        if (inherit_option == false) {
-+            continue;
-+        }
-+
-+        sdap_copy_map_entry(parent_user_map, child_user_map, opt_index);
-+    }
-+}
-+
-+void sdap_inherit_options(char **inherit_opt_list,
-+                          struct sdap_options *parent_sdap_opts,
-+                          struct sdap_options *child_sdap_opts)
-+{
-+    sdap_inherit_basic_options(inherit_opt_list,
-+                               parent_sdap_opts->basic,
-+                               child_sdap_opts->basic);
-+
-+    sdap_inherit_user_options(inherit_opt_list,
-+                              parent_sdap_opts->user_map,
-+                              child_sdap_opts->user_map);
-+}
-+
- int sdap_get_map(TALLOC_CTX *memctx,
-                  struct confdb_ctx *cdb,
-                  const char *conf_path,
-diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
-index c0e9ff9..19fc039 100644
---- a/src/providers/ldap/sdap.h
-+++ b/src/providers/ldap/sdap.h
-@@ -491,6 +491,10 @@ int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx,
-                               struct sdap_attr_map **_map,
-                               size_t *_new_size);
- 
-+void sdap_inherit_options(char **inherit_opt_list,
-+                          struct sdap_options *parent_sdap_opts,
-+                          struct sdap_options *child_sdap_opts);
-+
- int sdap_get_map(TALLOC_CTX *memctx,
-                  struct confdb_ctx *cdb,
-                  const char *conf_path,
-diff --git a/src/tests/cmocka/test_sdap.c b/src/tests/cmocka/test_sdap.c
-index d1e6959..5488694 100644
---- a/src/tests/cmocka/test_sdap.c
-+++ b/src/tests/cmocka/test_sdap.c
-@@ -792,6 +792,150 @@ static void test_sdap_copy_map_entry_null_name(void **state)
-     assert_null(uuid_val);
- }
- 
-+struct test_sdap_inherit_ctx {
-+    struct sdap_options *parent_sdap_opts;
-+    struct sdap_options *child_sdap_opts;
-+};
-+
-+struct sdap_options *mock_sdap_opts(TALLOC_CTX *mem_ctx)
-+{
-+    int ret;
-+    struct sdap_options *opts;
-+
-+    opts = talloc_zero(mem_ctx, struct sdap_options);
-+    assert_non_null(opts);
-+
-+    ret = sdap_copy_map(opts, rfc2307_user_map,
-+                        SDAP_OPTS_USER, &opts->user_map);
-+    assert_int_equal(ret, ERR_OK);
-+
-+    ret = dp_copy_defaults(opts, default_basic_opts,
-+                           SDAP_OPTS_BASIC, &opts->basic);
-+    assert_int_equal(ret, ERR_OK);
-+
-+    return opts;
-+}
-+
-+static void test_sdap_inherit_option_setup(void **state)
-+{
-+    int ret;
-+    struct test_sdap_inherit_ctx *test_ctx;
-+
-+    assert_true(leak_check_setup());
-+
-+    test_ctx = talloc_zero(global_talloc_context,
-+                           struct test_sdap_inherit_ctx);
-+    assert_non_null(test_ctx);
-+
-+    test_ctx->child_sdap_opts = talloc_zero(test_ctx, struct sdap_options);
-+
-+    test_ctx->parent_sdap_opts = mock_sdap_opts(test_ctx);
-+    assert_non_null(test_ctx->parent_sdap_opts);
-+    test_ctx->child_sdap_opts = mock_sdap_opts(test_ctx);
-+    assert_non_null(test_ctx->child_sdap_opts);
-+
-+    test_ctx->parent_sdap_opts->user_map[SDAP_AT_USER_PRINC].name = \
-+                                                  discard_const("test_princ");
-+
-+    ret = dp_opt_set_int(test_ctx->parent_sdap_opts->basic,
-+                         SDAP_CACHE_PURGE_TIMEOUT, 123);
-+    assert_int_equal(ret, EOK);
-+
-+    *state = test_ctx;
-+}
-+
-+static void test_sdap_inherit_option_teardown(void **state)
-+{
-+    struct test_sdap_inherit_ctx *test_ctx = \
-+                talloc_get_type_abort(*state, struct test_sdap_inherit_ctx);
-+
-+    talloc_free(test_ctx);
-+    assert_true(leak_check_teardown());
-+}
-+
-+static void test_sdap_inherit_option_null(void **state)
-+{
-+    struct test_sdap_inherit_ctx *test_ctx = \
-+                talloc_get_type_abort(*state, struct test_sdap_inherit_ctx);
-+    int val;
-+
-+    val = dp_opt_get_int(test_ctx->child_sdap_opts->basic,
-+                         SDAP_CACHE_PURGE_TIMEOUT);
-+    assert_int_equal(val, 10800);
-+
-+    sdap_inherit_options(NULL,
-+                         test_ctx->parent_sdap_opts,
-+                         test_ctx->child_sdap_opts);
-+
-+    val = dp_opt_get_int(test_ctx->child_sdap_opts->basic,
-+                         SDAP_CACHE_PURGE_TIMEOUT);
-+    assert_int_equal(val, 10800);
-+}
-+
-+static void test_sdap_inherit_option_notset(void **state)
-+{
-+    struct test_sdap_inherit_ctx *test_ctx = \
-+                talloc_get_type_abort(*state, struct test_sdap_inherit_ctx);
-+    int val;
-+    const char *inherit_options[] = { "ldap_use_tokengroups", NULL };
-+
-+    val = dp_opt_get_int(test_ctx->child_sdap_opts->basic,
-+                         SDAP_CACHE_PURGE_TIMEOUT);
-+    assert_int_equal(val, 10800);
-+
-+    /* parent has nondefault, but it's not supposed to be inherited */
-+    sdap_inherit_options(discard_const(inherit_options),
-+                         test_ctx->parent_sdap_opts,
-+                         test_ctx->child_sdap_opts);
-+
-+    val = dp_opt_get_int(test_ctx->child_sdap_opts->basic,
-+                         SDAP_CACHE_PURGE_TIMEOUT);
-+    assert_int_equal(val, 10800);
-+}
-+
-+static void test_sdap_inherit_option_basic(void **state)
-+{
-+    struct test_sdap_inherit_ctx *test_ctx = \
-+                talloc_get_type_abort(*state, struct test_sdap_inherit_ctx);
-+    int val;
-+    const char *inherit_options[] = { "ldap_purge_cache_timeout", NULL };
-+
-+    val = dp_opt_get_int(test_ctx->child_sdap_opts->basic,
-+                         SDAP_CACHE_PURGE_TIMEOUT);
-+    assert_int_equal(val, 10800);
-+
-+    /* parent has nondefault, but it's not supposed to be inherited */
-+    sdap_inherit_options(discard_const(inherit_options),
-+                         test_ctx->parent_sdap_opts,
-+                         test_ctx->child_sdap_opts);
-+
-+    val = dp_opt_get_int(test_ctx->child_sdap_opts->basic,
-+                         SDAP_CACHE_PURGE_TIMEOUT);
-+    assert_int_equal(val, 123);
-+}
-+
-+static void test_sdap_inherit_option_user(void **state)
-+{
-+    struct test_sdap_inherit_ctx *test_ctx = \
-+                talloc_get_type_abort(*state, struct test_sdap_inherit_ctx);
-+    const char *inherit_options[] = { "ldap_user_principal", NULL };
-+
-+    assert_string_equal(
-+            test_ctx->child_sdap_opts->user_map[SDAP_AT_USER_PRINC].name,
-+            "krbPrincipalName");
-+
-+    /* parent has nondefault, but it's not supposed to be inherited */
-+    sdap_inherit_options(discard_const(inherit_options),
-+                         test_ctx->parent_sdap_opts,
-+                         test_ctx->child_sdap_opts);
-+
-+    assert_string_equal(
-+            test_ctx->child_sdap_opts->user_map[SDAP_AT_USER_PRINC].name,
-+            "test_princ");
-+
-+    talloc_free(test_ctx->child_sdap_opts->user_map[SDAP_AT_USER_PRINC].name);
-+}
-+
- int main(int argc, const char *argv[])
- {
-     poptContext pc;
-@@ -845,6 +989,20 @@ int main(int argc, const char *argv[])
-         unit_test_setup_teardown(test_sdap_copy_map_entry_null_name,
-                                  copy_map_entry_test_setup,
-                                  copy_map_entry_test_teardown),
-+
-+        /* Option inherit tests */
-+        unit_test_setup_teardown(test_sdap_inherit_option_null,
-+                                 test_sdap_inherit_option_setup,
-+                                 test_sdap_inherit_option_teardown),
-+        unit_test_setup_teardown(test_sdap_inherit_option_notset,
-+                                 test_sdap_inherit_option_setup,
-+                                 test_sdap_inherit_option_teardown),
-+        unit_test_setup_teardown(test_sdap_inherit_option_basic,
-+                                 test_sdap_inherit_option_setup,
-+                                 test_sdap_inherit_option_teardown),
-+        unit_test_setup_teardown(test_sdap_inherit_option_user,
-+                                 test_sdap_inherit_option_setup,
-+                                 test_sdap_inherit_option_teardown),
-     };
- 
-     /* Set debug level to invalid value so we can deside if -d 0 was used. */
--- 
-2.1.0
-
diff --git a/SOURCES/0208-sudo-sanitize-filter-values.patch b/SOURCES/0208-sudo-sanitize-filter-values.patch
deleted file mode 100644
index 89e3f39..0000000
--- a/SOURCES/0208-sudo-sanitize-filter-values.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From ea10cbf8ec9669f4041c1df511b5f1b48aecce21 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
-Date: Thu, 9 Apr 2015 13:03:08 +0200
-Subject: [PATCH 208/208] sudo: sanitize filter values
-
-Resolves:
-https://fedorahosted.org/sssd/ticket/2613
-
-Reviewed-by: Pavel Reichl <preichl@redhat.com>
-(cherry picked from commit c526cd124515cc2d44a413dcbfd4a74ddb490150)
-(cherry picked from commit 2fb2a267d0d15cce84b0ccea7e088a4b580e42fb)
----
- src/db/sysdb_sudo.c | 15 +++++++++++++--
- 1 file changed, 13 insertions(+), 2 deletions(-)
-
-diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c
-index 261ed82d672cd95f0c0f429a177dae39d3b9c204..cd072dd2900757c69f7fd7f559559e310ceccda7 100644
---- a/src/db/sysdb_sudo.c
-+++ b/src/db/sysdb_sudo.c
-@@ -221,6 +221,7 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
-     TALLOC_CTX *tmp_ctx = NULL;
-     char *filter = NULL;
-     char *specific_filter = NULL;
-+    char *sanitized = NULL;
-     time_t now;
-     errno_t ret;
-     int i;
-@@ -246,9 +247,14 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
-     }
- 
-     if ((flags & SYSDB_SUDO_FILTER_USERNAME) && (username != NULL)) {
-+        ret = sss_filter_sanitize(tmp_ctx, username, &sanitized);
-+        if (ret != EOK) {
-+            goto done;
-+        }
-+
-         specific_filter = talloc_asprintf_append(specific_filter, "(%s=%s)",
-                                                  SYSDB_SUDO_CACHE_AT_USER,
--                                                 username);
-+                                                 sanitized);
-         NULL_CHECK(specific_filter, ret, done);
-     }
- 
-@@ -261,9 +267,14 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
- 
-     if ((flags & SYSDB_SUDO_FILTER_GROUPS) && (groupnames != NULL)) {
-         for (i=0; groupnames[i] != NULL; i++) {
-+            ret = sss_filter_sanitize(tmp_ctx, groupnames[i], &sanitized);
-+            if (ret != EOK) {
-+                goto done;
-+            }
-+
-             specific_filter = talloc_asprintf_append(specific_filter, "(%s=%%%s)",
-                                                      SYSDB_SUDO_CACHE_AT_USER,
--                                                     groupnames[i]);
-+                                                     sanitized);
-             NULL_CHECK(specific_filter, ret, done);
-         }
-     }
--- 
-2.4.3
-
diff --git a/SOURCES/0209-SYSDB-Index-the-objectSIDString-attribute.patch b/SOURCES/0209-SYSDB-Index-the-objectSIDString-attribute.patch
deleted file mode 100644
index aea17b0..0000000
--- a/SOURCES/0209-SYSDB-Index-the-objectSIDString-attribute.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-From 36f2fe9d7e5bd3af72b306da7b07df3cfd557810 Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Thu, 25 Jun 2015 17:33:47 +0200
-Subject: [PATCH 209/210] SYSDB: Index the objectSIDString attribute
-
-(cherry picked from commit 2302b7f53869db17fe6f733f52cce94d9714eeb4)
----
- src/db/sysdb.c         |  7 +++++++
- src/db/sysdb_private.h |  5 ++++-
- src/db/sysdb_upgrade.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 62 insertions(+), 1 deletion(-)
-
-diff --git a/src/db/sysdb.c b/src/db/sysdb.c
-index 1f02585e747dda6aadde772f76f30d3d69c4cfc0..5be5da3ae70bf13313be85a59a85552d4bcce7f0 100644
---- a/src/db/sysdb.c
-+++ b/src/db/sysdb.c
-@@ -1250,6 +1250,13 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
-             }
-         }
- 
-+        if (strcmp(version, SYSDB_VERSION_0_16) == 0) {
-+            ret = sysdb_upgrade_16(sysdb, &version);
-+            if (ret != EOK) {
-+                goto done;
-+            }
-+        }
-+
-         /* The version should now match SYSDB_VERSION.
-          * If not, it means we didn't match any of the
-          * known older versions. The DB might be
-diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h
-index 8a5b8be8cbcf0513fa4c471ac41f803a4e2a5b24..9788206a1ee125b6a838031edb57b243a42bbb60 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_17 "0.17"
- #define SYSDB_VERSION_0_16 "0.16"
- #define SYSDB_VERSION_0_15 "0.15"
- #define SYSDB_VERSION_0_14 "0.14"
-@@ -40,7 +41,7 @@
- #define SYSDB_VERSION_0_2 "0.2"
- #define SYSDB_VERSION_0_1 "0.1"
- 
--#define SYSDB_VERSION SYSDB_VERSION_0_16
-+#define SYSDB_VERSION SYSDB_VERSION_0_17
- 
- #define SYSDB_BASE_LDIF \
-      "dn: @ATTRIBUTES\n" \
-@@ -68,6 +69,7 @@
-      "@IDXATTR: serviceProtocol\n" \
-      "@IDXATTR: sudoUser\n" \
-      "@IDXATTR: sshKnownHostsExpire\n" \
-+     "@IDXATTR: objectSIDString\n" \
-      "@IDXONE: 1\n" \
-      "\n" \
-      "dn: @MODULES\n" \
-@@ -120,6 +122,7 @@ int sysdb_upgrade_12(struct sysdb_ctx *sysdb, const char **ver);
- int sysdb_upgrade_13(struct sysdb_ctx *sysdb, const char **ver);
- int sysdb_upgrade_14(struct sysdb_ctx *sysdb, const char **ver);
- int sysdb_upgrade_15(struct sysdb_ctx *sysdb, const char **ver);
-+int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver);
- 
- int add_string(struct ldb_message *msg, int flags,
-                const char *attr, const char *value);
-diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c
-index 558b4f5205c333e7a2b60d0a8e11589f122c385a..816b1eff83a644e6571165ed79a1a9bf420ef847 100644
---- a/src/db/sysdb_upgrade.c
-+++ b/src/db/sysdb_upgrade.c
-@@ -1587,6 +1587,57 @@ done:
-     return ret;
- }
- 
-+int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver)
-+{
-+    struct ldb_message *msg;
-+    struct upgrade_ctx *ctx;
-+    errno_t ret;
-+
-+    ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_17, &ctx);
-+    if (ret) {
-+        return ret;
-+    }
-+
-+    /* add new indexes */
-+    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;
-+    }
-+
-+    /* add index for cached */
-+    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", "objectSIDString");
-+    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;
-+    }
-+
-+    /* conversion done, update version number */
-+    ret = update_version(ctx);
-+
-+done:
-+    ret = finish_upgrade(ret, &ctx, ver);
-+    return ret;
-+}
-+
- /*
-  * Example template for future upgrades.
-  * Copy and change version numbers as appropriate.
--- 
-2.4.3
-
diff --git a/SOURCES/0210-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch b/SOURCES/0210-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch
deleted file mode 100644
index ae6d246..0000000
--- a/SOURCES/0210-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-From 09bf564bfe4f6f8407056e3261bfc7948d45bdbf Mon Sep 17 00:00:00 2001
-From: Jakub Hrozek <jhrozek@redhat.com>
-Date: Tue, 21 Jul 2015 11:44:03 +0200
-Subject: [PATCH 210/210] IPA: Remove MPG groups if getgrgid was called before
- getpw()
-
-https://fedorahosted.org/sssd/ticket/2724
-
-This bug only affects IPA clients that are connected to IPA servers with
-AD trust and ID mapping in effect.
-
-If an IPA client calls getgrgid() for an ID that matches a user, the
-user's private group would be returned and stored as a group entry.
-
-Subsequent queries for that user would fail, because MPG domains impose
-uniqueness restriction for both the ID and name space across groups and
-users.
-
-To work around that, we remove the UPG groups in MPG domains during a
-group lookup.
-
-Reviewed-by: Sumit Bose <sbose@redhat.com>
----
- src/providers/ipa/ipa_s2n_exop.c | 41 ++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 39 insertions(+), 2 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 292f174257fbf6f6ebc8db6d1eb38cb4b5349b81..8de46136d0bc9d1c26b44c532d7bd405880aca50 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -1757,6 +1757,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-     int tret;
-     struct sysdb_attrs *gid_override_attrs = NULL;
-     char ** exop_grouplist;
-+    struct ldb_message *msg;
- 
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-@@ -1997,8 +1998,44 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                                    attrs->a.user.pw_dir, attrs->a.user.pw_shell,
-                                    NULL, attrs->sysdb_attrs, NULL,
-                                    timeout, now);
--            if (ret != EOK) {
--                DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_user failed.\n");
-+            if (ret == EEXIST && dom->mpg == true) {
-+                /* This handles the case where getgrgid() was called for
-+                 * this user, so a group was created in the cache
-+                 */
-+                ret = sysdb_search_group_by_name(tmp_ctx, dom, name, NULL, &msg);
-+                if (ret != EOK) {
-+                    /* Fail even on ENOENT, the group must be around */
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "Could not delete MPG group [%d]: %s\n",
-+                          ret, sss_strerror(ret));
-+                    goto done;
-+                }
-+
-+                ret = sysdb_delete_group(dom, NULL, attrs->a.user.pw_uid);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_delete_group failed for MPG group [%d]: %s\n",
-+                          ret, sss_strerror(ret));
-+                    goto done;
-+                }
-+
-+                ret = sysdb_store_user(dom, name, NULL,
-+                                       attrs->a.user.pw_uid,
-+                                       gid, attrs->a.user.pw_gecos,
-+                                       attrs->a.user.pw_dir,
-+                                       attrs->a.user.pw_shell,
-+                                       NULL, attrs->sysdb_attrs, NULL,
-+                                       timeout, now);
-+                if (ret != EOK) {
-+                    DEBUG(SSSDBG_OP_FAILURE,
-+                          "sysdb_store_user failed for MPG user [%d]: %s\n",
-+                          ret, sss_strerror(ret));
-+                    goto done;
-+                }
-+            } else if (ret != EOK) {
-+                DEBUG(SSSDBG_OP_FAILURE,
-+                      "sysdb_store_user failed [%d]: %s\n",
-+                      ret, sss_strerror(ret));
-                 goto done;
-             }
- 
--- 
-2.4.3
-
diff --git a/SOURCES/0211-IPA-do-initgroups-if-extdom-exop-supports-it.patch b/SOURCES/0211-IPA-do-initgroups-if-extdom-exop-supports-it.patch
deleted file mode 100644
index 6a61fb4..0000000
--- a/SOURCES/0211-IPA-do-initgroups-if-extdom-exop-supports-it.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From 215f988b07610ae55dfcb67f355bc864ddcbf72d Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 28 Apr 2015 17:18:48 +0200
-Subject: [PATCH 211/214] IPA: do initgroups if extdom exop supports it
-
-Newer versions of the extdom plugin return the full list of
-group-memberships during a user lookup request. With these version there
-is no need to reject a initgroups request for sub/trusted-domain users
-anymore. This is e.g. useful for callers which call getgrouplist()
-directly without calling getpwnam() before. Additionally it helps if for
-some reasons the lifetime of the user entry and the lifetime of the
-initgroups data is different.
-
-Related to https://fedorahosted.org/sssd/ticket/2633
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit e87badc0f6fb20a443cf12bde9582ecbc2aef727)
-(cherry picked from commit 24905d4ecbf210687e385449448f5a5ec97d2833)
----
- src/providers/ipa/ipa_s2n_exop.c      |  3 ---
- src/providers/ipa/ipa_subdomains.h    |  4 ++++
- src/providers/ipa/ipa_subdomains_id.c | 24 +++++++++++++++++-------
- 3 files changed, 21 insertions(+), 10 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 8de46136d0bc9d1c26b44c532d7bd405880aca50..03264fcd7f6f42dfa68db4f331184da32529818f 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -50,9 +50,6 @@ enum response_types {
- };
- 
- /* ==Sid2Name Extended Operation============================================= */
--#define EXOP_SID2NAME_OID "2.16.840.1.113730.3.8.10.4"
--#define EXOP_SID2NAME_V1_OID "2.16.840.1.113730.3.8.10.4.1"
--
- struct ipa_s2n_exop_state {
-     struct sdap_handle *sh;
- 
-diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h
-index ceb862226b504bca6c9c596554fb88e6df1d51c3..9b179792dcab7ea935fa7159ca879d12b561a55f 100644
---- a/src/providers/ipa/ipa_subdomains.h
-+++ b/src/providers/ipa/ipa_subdomains.h
-@@ -28,6 +28,10 @@
- #include "providers/dp_backend.h"
- #include "providers/ipa/ipa_common.h"
- 
-+/* ==Sid2Name Extended Operation============================================= */
-+#define EXOP_SID2NAME_OID "2.16.840.1.113730.3.8.10.4"
-+#define EXOP_SID2NAME_V1_OID "2.16.840.1.113730.3.8.10.4.1"
-+
- struct be_ctx *ipa_get_subdomains_be_ctx(struct be_ctx *be_ctx);
- 
- const char *get_flat_name_from_subdomain_name(struct be_ctx *be_ctx,
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index 0508e14b690c144f4bace9ed14a326ac724eb910..1020c8a0b9209fc7404c32963ad5622fc6958d6b 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -375,15 +375,9 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
-         case BE_REQ_GROUP:
-         case BE_REQ_BY_SECID:
-         case BE_REQ_USER_AND_GROUP:
-+        case BE_REQ_INITGROUPS:
-             ret = EOK;
-             break;
--        case BE_REQ_INITGROUPS:
--            ret = ENOTSUP;
--            DEBUG(SSSDBG_TRACE_FUNC, "Initgroups requests are not handled " \
--                                      "by the IPA provider but are resolved " \
--                                      "by the responder directly from the " \
--                                      "cache.\n");
--            break;
-         default:
-             ret = EINVAL;
-             DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain request type.\n");
-@@ -423,6 +417,22 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq)
-         return;
-     }
- 
-+    if (state->entry_type == BE_REQ_INITGROUPS) {
-+        /* With V1 of the extdom plugin a user lookup will resolve the full
-+         * group membership of the user. */
-+        if (sdap_is_extension_supported(sdap_id_op_handle(state->op),
-+                                        EXOP_SID2NAME_V1_OID)) {
-+            state->entry_type = BE_REQ_USER;
-+        } else {
-+            DEBUG(SSSDBG_TRACE_FUNC, "Initgroups requests are not handled " \
-+                                      "by the IPA provider but are resolved " \
-+                                      "by the responder directly from the " \
-+                                      "cache.\n");
-+            tevent_req_error(req, ENOTSUP);
-+            return;
-+        }
-+    }
-+
-     req_input = talloc(state, struct req_input);
-     if (req_input == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "talloc failed.\n");
--- 
-2.4.3
-
diff --git a/SOURCES/0212-IPA-update-initgr-expire-timestamp-conditionally.patch b/SOURCES/0212-IPA-update-initgr-expire-timestamp-conditionally.patch
deleted file mode 100644
index 62b7581..0000000
--- a/SOURCES/0212-IPA-update-initgr-expire-timestamp-conditionally.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-From ab9cc3894af6fc0e768c631da23446287cd6e8e2 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 28 Apr 2015 17:20:05 +0200
-Subject: [PATCH 212/214] IPA: update initgr expire timestamp conditionally
-
-Newer versions of the extdom plugin return the full list of
-group-memberships during user lookups. As a result the lifetime of the
-group-membership data is updates in those cases. But if the user is not
-looked up directly but is resolved as a group member during a group
-lookup SSSD does not resolve all group-membership of the user to avoid
-deep recursion and eventually a complete enumeration of the user and
-group base. In this case the lifetime of the group-memberships should
-not be updated because it might be incomplete.
-
-Related to https://fedorahosted.org/sssd/ticket/2633
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit cffe3135f29c737f2598f3c1384bfba1694fb843)
-(cherry picked from commit f643fadbd072a9d3725f5f750340d5b13628ce6a)
----
- src/providers/ipa/ipa_s2n_exop.c | 19 +++++++++++--------
- 1 file changed, 11 insertions(+), 8 deletions(-)
-
-diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
-index 03264fcd7f6f42dfa68db4f331184da32529818f..2f1974d2c250ad2f8283659de4ddc319500ac6a5 100644
---- a/src/providers/ipa/ipa_s2n_exop.c
-+++ b/src/providers/ipa/ipa_s2n_exop.c
-@@ -676,7 +676,8 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                                     struct resp_attrs *attrs,
-                                     struct resp_attrs *simple_attrs,
-                                     const char *view_name,
--                                    struct sysdb_attrs *override_attrs);
-+                                    struct sysdb_attrs *override_attrs,
-+                                    bool update_initgr_timeout);
- 
- static errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
-                                      char *retoid,
-@@ -1109,7 +1110,7 @@ static errno_t ipa_s2n_get_fqlist_save_step(struct tevent_req *req)
- 
-     ret = ipa_s2n_save_objects(state->dom, &state->req_input, state->attrs,
-                                NULL, state->ipa_ctx->view_name,
--                               state->override_attrs);
-+                               state->override_attrs, false);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
-         return ret;
-@@ -1607,7 +1608,7 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq)
-             || strcmp(state->ipa_ctx->view_name,
-                       SYSDB_DEFAULT_VIEW_NAME) == 0) {
-         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
--                                   state->simple_attrs, NULL, NULL);
-+                                   state->simple_attrs, NULL, NULL, true);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
-             goto done;
-@@ -1729,7 +1730,8 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                                     struct resp_attrs *attrs,
-                                     struct resp_attrs *simple_attrs,
-                                     const char *view_name,
--                                    struct sysdb_attrs *override_attrs)
-+                                    struct sysdb_attrs *override_attrs,
-+                                    bool update_initgr_timeout)
- {
-     int ret;
-     time_t now;
-@@ -1929,7 +1931,8 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom,
-                 }
-             }
- 
--            if (attrs->response_type == RESP_USER_GROUPLIST) {
-+            if (attrs->response_type == RESP_USER_GROUPLIST
-+                    && update_initgr_timeout) {
-                 /* Since RESP_USER_GROUPLIST contains all group memberships it
-                  * is effectively an initgroups request hence
-                  * SYSDB_INITGR_EXPIRE will be set.*/
-@@ -2231,7 +2234,7 @@ static void ipa_s2n_get_fqlist_done(struct tevent_req  *subreq)
-                                  &sid_str);
-     if (ret == ENOENT) {
-         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
--                                   state->simple_attrs, NULL, NULL);
-+                                   state->simple_attrs, NULL, NULL, true);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
-             goto fail;
-@@ -2271,7 +2274,7 @@ static void ipa_s2n_get_fqlist_done(struct tevent_req  *subreq)
-         ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
-                                    state->simple_attrs,
-                                    state->ipa_ctx->view_name,
--                                   state->override_attrs);
-+                                   state->override_attrs, true);
-         if (ret != EOK) {
-             DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
-             tevent_req_error(req, ret);
-@@ -2307,7 +2310,7 @@ static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq)
- 
-     ret = ipa_s2n_save_objects(state->dom, state->req_input, state->attrs,
-                                state->simple_attrs, state->ipa_ctx->view_name,
--                               override_attrs);
-+                               override_attrs, true);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_save_objects failed.\n");
-         tevent_req_error(req, ret);
--- 
-2.4.3
-
diff --git a/SOURCES/0213-IPA-enhance-ipa_initgr_get_overrides_send.patch b/SOURCES/0213-IPA-enhance-ipa_initgr_get_overrides_send.patch
deleted file mode 100644
index 49524dc..0000000
--- a/SOURCES/0213-IPA-enhance-ipa_initgr_get_overrides_send.patch
+++ /dev/null
@@ -1,199 +0,0 @@
-From 3d9560303f7c96abf36ff93abd85b2319808d3f6 Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 28 Apr 2015 20:58:15 +0200
-Subject: [PATCH 213/214] IPA: enhance ipa_initgr_get_overrides_send()
-
-This patch makes ipa_initgr_get_overrides_send() public and add support
-to search overrides by UUID or by SID.
-
-Related to https://fedorahosted.org/sssd/ticket/2633
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 145578006684481434ced78461ab8d1c3570f478)
-(cherry picked from commit 58a19d50888b1a7da0ee78b49e7d3dcbebc8614d)
----
- src/db/sysdb_views.c       |  5 ++++
- src/providers/ipa/ipa_id.c | 63 +++++++++++++++++++++++++++++++++-------------
- src/providers/ipa/ipa_id.h | 10 ++++++++
- 3 files changed, 61 insertions(+), 17 deletions(-)
-
-diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
-index 717edf20a447003568060cf4d32bf8d47bd93e63..58cad5426109f0fb37ef16fd1304b50a702cf44a 100644
---- a/src/db/sysdb_views.c
-+++ b/src/db/sysdb_views.c
-@@ -733,6 +733,11 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
-                                     NULL };
-     bool override_attrs_found = false;
- 
-+    if (override_attrs == NULL) {
-+        /* nothing to do */
-+        return EOK;
-+    }
-+
-     tmp_ctx = talloc_new(NULL);
-     if (tmp_ctx == NULL) {
-         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
-diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
-index cc6abcf8721e3f05526bf62063f0cbdc7c1c257b..02b59ab77a7408012efdd9a1538287e08de0af1e 100644
---- a/src/providers/ipa/ipa_id.c
-+++ b/src/providers/ipa/ipa_id.c
-@@ -294,6 +294,7 @@ struct ipa_initgr_get_overrides_state {
- 
-     struct ldb_message **groups;
-     size_t group_count;
-+    const char *groups_id_attr;
-     size_t group_idx;
-     struct be_acct_req *ar;
- 
-@@ -302,13 +303,14 @@ struct ipa_initgr_get_overrides_state {
- 
- static int ipa_initgr_get_overrides_step(struct tevent_req *req);
- 
--static struct tevent_req *
-+struct tevent_req *
- ipa_initgr_get_overrides_send(TALLOC_CTX *memctx,
-                              struct tevent_context *ev,
-                              struct ipa_id_ctx *ipa_ctx,
-                              struct sss_domain_info *user_dom,
-                              size_t groups_count,
--                             struct ldb_message **groups)
-+                             struct ldb_message **groups,
-+                             const char *groups_id_attr)
- {
-     int ret;
-     struct tevent_req *req;
-@@ -334,6 +336,12 @@ ipa_initgr_get_overrides_send(TALLOC_CTX *memctx,
-         ret = EINVAL;
-         goto done;
-     }
-+    state->groups_id_attr = talloc_strdup(state, groups_id_attr);
-+    if (state->groups_id_attr == NULL) {
-+        DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
-+        ret = ENOMEM;
-+        goto done;
-+    }
- 
-     ret = ipa_initgr_get_overrides_step(req);
- done:
-@@ -366,7 +374,7 @@ static int ipa_initgr_get_overrides_step(struct tevent_req *req)
-     }
- 
-     ipa_uuid = ldb_msg_find_attr_as_string(state->groups[state->group_idx],
--                                            SYSDB_UUID, NULL);
-+                                           state->groups_id_attr, NULL);
-     if (ipa_uuid == NULL) {
-         /* This should never happen, the search filter used to get the list
-          * of groups includes "uuid=*"
-@@ -377,11 +385,24 @@ static int ipa_initgr_get_overrides_step(struct tevent_req *req)
- 
-     talloc_free(state->ar); /* Avoid spiking memory with many groups */
- 
--    ret = get_be_acct_req_for_uuid(state, ipa_uuid,
--                                   state->user_dom->name, &state->ar);
--    if (ret != EOK) {
--        DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
--        return ret;
-+    if (strcmp(state->groups_id_attr, SYSDB_UUID) == 0) {
-+        ret = get_be_acct_req_for_uuid(state, ipa_uuid,
-+                                       state->user_dom->name, &state->ar);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
-+            return ret;
-+        }
-+    } else if (strcmp(state->groups_id_attr, SYSDB_SID_STR) == 0) {
-+        ret = get_be_acct_req_for_sid(state, ipa_uuid,
-+                                      state->user_dom->name, &state->ar);
-+        if (ret != EOK) {
-+            DEBUG(SSSDBG_OP_FAILURE, "get_be_acct_req_for_sid failed.\n");
-+            return ret;
-+        }
-+    } else {
-+        DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported groups ID type [%s].\n",
-+                                   state->groups_id_attr);
-+        return EINVAL;
-     }
- 
-     DEBUG(SSSDBG_TRACE_LIBS, "Fetching group %s\n", ipa_uuid);
-@@ -408,7 +429,7 @@ static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
-     struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
-                                         struct ipa_initgr_get_overrides_state);
-     int ret;
--    struct sysdb_attrs *override_attrs;
-+    struct sysdb_attrs *override_attrs = NULL;
- 
-     ret = ipa_get_ad_override_recv(subreq, &state->dp_error, state,
-                                    &override_attrs);
-@@ -419,10 +440,16 @@ static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
-         return;
-     }
- 
--    ret = sysdb_store_override(state->user_dom, state->ipa_ctx->view_name,
--                               SYSDB_MEMBER_GROUP,
--                               override_attrs,
--                               state->groups[state->group_idx]->dn);
-+    if (strcmp(state->ipa_ctx->view_name, SYSDB_DEFAULT_VIEW_NAME) == 0) {
-+        ret = sysdb_apply_default_override(state->user_dom, override_attrs,
-+                                       state->groups[state->group_idx]->dn);
-+    } else {
-+        ret = sysdb_store_override(state->user_dom,
-+                                   state->ipa_ctx->view_name,
-+                                   SYSDB_MEMBER_GROUP,
-+                                   override_attrs,
-+                                   state->groups[state->group_idx]->dn);
-+    }
-     talloc_free(override_attrs);
-     if (ret != EOK) {
-         DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_override failed.\n");
-@@ -443,7 +470,7 @@ static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
-     tevent_req_done(req);
- }
- 
--static int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error)
-+int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error)
- {
-     struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
-                                         struct ipa_initgr_get_overrides_state);
-@@ -881,7 +908,8 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
-     if (state->user_groups != NULL) {
-         subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
-                                               state->domain, state->group_cnt,
--                                              state->user_groups);
-+                                              state->user_groups,
-+                                              SYSDB_UUID);
-         if (subreq == NULL) {
-             DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
-             ret = ENOMEM;
-@@ -959,8 +987,9 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq)
- 
-     if (state->user_groups != NULL) {
-         subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
--                                              state->domain, state->group_cnt,
--                                              state->user_groups);
-+                                               state->domain, state->group_cnt,
-+                                               state->user_groups,
-+                                               SYSDB_UUID);
-         if (subreq == NULL) {
-             DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n");
-             ret = ENOMEM;
-diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
-index 2bb5e0d38f42d4bbb04854dfb04804fecf6257e8..c03ca037a2850478a8f4933bac4fcf8bd70ada04 100644
---- a/src/providers/ipa/ipa_id.h
-+++ b/src/providers/ipa/ipa_id.h
-@@ -119,4 +119,14 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
-                               struct sss_domain_info *dom,
-                               struct be_acct_req *ar,
-                               struct ldb_message **_msg);
-+
-+struct tevent_req *
-+ipa_initgr_get_overrides_send(TALLOC_CTX *memctx,
-+                             struct tevent_context *ev,
-+                             struct ipa_id_ctx *ipa_ctx,
-+                             struct sss_domain_info *user_dom,
-+                             size_t groups_count,
-+                             struct ldb_message **groups,
-+                             const char *groups_id_attr);
-+int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error);
- #endif
--- 
-2.4.3
-
diff --git a/SOURCES/0214-IPA-search-for-overrides-during-initgroups-in-sever-.patch b/SOURCES/0214-IPA-search-for-overrides-during-initgroups-in-sever-.patch
deleted file mode 100644
index c7ceb75..0000000
--- a/SOURCES/0214-IPA-search-for-overrides-during-initgroups-in-sever-.patch
+++ /dev/null
@@ -1,116 +0,0 @@
-From 61964561654d86e1ba2179fc0afd7f93cafbc6ab Mon Sep 17 00:00:00 2001
-From: Sumit Bose <sbose@redhat.com>
-Date: Tue, 28 Apr 2015 20:59:43 +0200
-Subject: [PATCH 214/214] IPA: search for overrides during initgroups in sever
- mode
-
-After the group memberships of a user from a trusted domain are read it
-must be checked if there are overrides for the discovered groups to be
-able to return the right gid or name to the caller.
-
-Related to https://fedorahosted.org/sssd/ticket/2633
-
-Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-(cherry picked from commit 2263c6dd1242c92253240f4998c86a04b6a0ca3a)
-(cherry picked from commit eaf656843831d579f30f94154d88aba2201c1712)
----
- src/providers/ipa/ipa_subdomains_id.c | 69 +++++++++++++++++++++++++++++++++++
- 1 file changed, 69 insertions(+)
-
-diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
-index 1020c8a0b9209fc7404c32963ad5622fc6958d6b..ffe2b18e8dda2137d2ebbfdb780c908eabcd4708 100644
---- a/src/providers/ipa/ipa_subdomains_id.c
-+++ b/src/providers/ipa/ipa_subdomains_id.c
-@@ -558,6 +558,8 @@ struct ipa_get_ad_acct_state {
- static void ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq);
- static void ipa_get_ad_override_done(struct tevent_req *subreq);
- 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);
-@@ -1112,6 +1114,9 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
-     struct tevent_req *subreq;
-     const char *obj_name;
-     int entry_type;
-+    size_t groups_count = 0;
-+    struct ldb_message **groups = NULL;
-+    const char *attrs[] = SYSDB_INITGR_ATTRS;
- 
-     if (state->override_attrs != NULL) {
-         /* We are in ipa-server-mode, so the view is the default view by
-@@ -1166,6 +1171,70 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req)
-         state->ar->entry_type = BE_REQ_USER;
-     }
- 
-+    /* Lookup all groups the user is a member of which do not have ORIGINALAD
-+     * attributes set, i.e. where overrides might not have been applied. */
-+    ret = sysdb_asq_search(state, state->obj_dom, state->obj_msg->dn,
-+                          "(&("SYSDB_GC")("SYSDB_GIDNUM"=*)" \
-+                            "(!("ORIGINALAD_PREFIX SYSDB_GIDNUM"=*))" \
-+                            "(!("ORIGINALAD_PREFIX SYSDB_NAME"=*)))",
-+                          SYSDB_INITGR_ATTR,
-+                          attrs, &groups_count, &groups);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_groups_without_orig failed.\n");
-+        return ret;
-+    }
-+
-+    if (groups != NULL) {
-+        subreq = ipa_initgr_get_overrides_send(state, state->ev, state->ipa_ctx,
-+                                               state->obj_dom, groups_count,
-+                                               groups, SYSDB_SID_STR);
-+        if (subreq == NULL) {
-+            DEBUG(SSSDBG_OP_FAILURE, "ipa_initgr_get_overrides_send failed.\n");
-+            return ENOMEM;
-+        }
-+        tevent_req_set_callback(subreq, ipa_id_get_groups_overrides_done, req);
-+        return EOK;
-+    }
-+
-+    ret = ipa_get_ad_ipa_membership_step(req);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_ipa_membership_step failed.\n");
-+        return ret;
-+    }
-+
-+    return EOK;
-+}
-+
-+static void ipa_id_get_groups_overrides_done(struct tevent_req *subreq)
-+{
-+    struct tevent_req *req = tevent_req_callback_data(subreq,
-+                                                struct tevent_req);
-+    errno_t ret;
-+
-+    ret = ipa_initgr_get_overrides_recv(subreq, NULL);
-+    talloc_zfree(subreq);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE,
-+              "IPA resolve user groups overrides failed [%d].\n", ret);
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    ret = ipa_get_ad_ipa_membership_step(req);
-+    if (ret != EOK) {
-+        DEBUG(SSSDBG_OP_FAILURE, "ipa_get_ad_ipa_membership_step failed.\n");
-+        tevent_req_error(req, ret);
-+        return;
-+    }
-+
-+    return;
-+}
-+
-+static errno_t ipa_get_ad_ipa_membership_step(struct tevent_req *req)
-+{
-+    struct ipa_get_ad_acct_state *state = tevent_req_data(req,
-+                                                struct ipa_get_ad_acct_state);
-+    struct tevent_req *subreq;
- 
-     /* For initgroups request we have to check IPA group memberships of AD
-      * users. This has to be done for other user-request as well to make sure
--- 
-2.4.3
-
diff --git a/SOURCES/0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec b/SOURCES/0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec
new file mode 100644
index 0000000..f24afe3
--- /dev/null
+++ b/SOURCES/0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec
@@ -0,0 +1,26 @@
+From 8d38a4b28ab7af15406b244910f369ba1aff02db Mon Sep 17 00:00:00 2001
+From: Jakub Hrozek <jhrozek@redhat.com>
+Date: Thu, 30 Oct 2014 15:59:17 +0100
+Subject: [PATCH 93/93] NOUPSTREAM: Default to root if sssd user is not
+ specified
+
+---
+ src/monitor/monitor.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
+index 0dea327213a1ad04b6f69c0ffb0fb87254420796..20b4aef4ee94fd42de1585d7d7c2e01ea01845ac 100644
+--- a/src/monitor/monitor.c
++++ b/src/monitor/monitor.c
+@@ -925,7 +925,7 @@ static int get_service_user(struct mt_ctx *ctx)
+ 
+     ret = confdb_get_string(ctx->cdb, ctx, CONFDB_MONITOR_CONF_ENTRY,
+                             CONFDB_MONITOR_USER_RUNAS,
+-                            SSSD_USER, &user_str);
++                            "root", &user_str);
+     if (ret != EOK) {
+         DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get the user to run as\n");
+         return ret;
+-- 
+1.9.3
+
diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec
index 25a1229..76d90cb 100644
--- a/SPECS/sssd.spec
+++ b/SPECS/sssd.spec
@@ -22,230 +22,125 @@
 %endif
 
 Name: sssd
-Version: 1.12.2
-Release: 58%{?dist}.18
+Version: 1.13.0
+Release: 40%{?dist}
 Group: Applications/System
 Summary: System Security Services Daemon
 License: GPLv3+
 URL: http://fedorahosted.org/sssd/
 Source0: https://fedorahosted.org/released/sssd/%{name}-%{version}.tar.gz
+Source1: cert9.db
+Source2: key4.db
 BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
 ### Patches ###
-Patch0001:  0001-util-Move-semanage-related-functions-to-src-util.patch
-Patch0002:  0002-sss_semanage-Add-mlsrange-parameter-to-set_seuser.patch
-Patch0003:  0003-IPA-Use-set_seuser-instead-of-writing-selinux-login-.patch
-Patch0004:  0004-SSSD-Add-the-options-to-specify-a-UID-and-GID-to-run.patch
-Patch0005:  0005-SSSD-Chown-the-log-files.patch
-Patch0006:  0006-UTIL-Use-a-custom-PID_PATH-and-DB_PATH-when-unit-tes.patch
-Patch0007:  0007-TESTS-Unit-tests-can-use-confdb-without-using-sysdb.patch
-Patch0008:  0008-TESTS-Add-std-gnu99-to-cwrap-tests-CFLAGS.patch
-Patch0009:  0009-TESTS-Unit-tests-for-server_setup.patch
-Patch0010:  0010-RPM-Package-the-libsss_semanage.so-library.patch
-Patch0011:  0011-ipa-fix-issues-with-older-servers-not-supporting-vie.patch
-Patch0012:  0012-ipa-improve-error-reporting-for-extdom-LDAP-exop.patch
-Patch0013:  0013-BUILD-Fix-automake-warning.patch
-Patch0014:  0014-test_server-Fix-waiting-for-background-process.patch
-Patch0015:  0015-ipa_subdomains_handler_master_done-initialize-reply_.patch
-Patch0016:  0016-Fix-debug-messages-trailing.patch
-Patch0017:  0017-IPA-Handle-NULL-members-in-process_members.patch
-Patch0018:  0018-SPEC-Print-testsuite-log-for-failed-test.patch
-Patch0019:  0019-MAN-PAGE-modified-sssd-ldap.5.xml-for-sssd-ticket-24.patch
-Patch0020:  0020-NSS-Possibility-to-use-any-shells-in-allowed_shells.patch
-Patch0021:  0021-GPO-Terminate-request-on-error.patch
-Patch0022:  0022-pyhbac-pysss-fix-reference-leaks.patch
-Patch0023:  0023-UTIL-Add-a-function-to-convert-id_t-from-a-number-or.patch
-Patch0024:  0024-BUILD-Add-a-config-option-for-sssd-user-own-private-.patch
-Patch0025:  0025-RPM-Change-file-ownership-to-sssd.sssd.patch
-Patch0026:  0026-SSSD-Load-a-user-to-run-a-service-as-from-configurat.patch
-Patch0027:  0027-SBUS-Chown-the-sbus-socket-if-needed.patch
-Patch0028:  0028-SBUS-Allow-connections-from-other-UIDs.patch
-Patch0029:  0029-BE-Own-the-sbus-socket-as-the-SSSD-user.patch
-Patch0030:  0030-MONITOR-Allow-confdb-to-be-accessed-by-nonroot-user.patch
-Patch0031:  0031-SYSDB-Allow-calling-chown-on-the-sysdb-file-from-mon.patch
-Patch0032:  0032-NSS-Run-as-a-user-specified-by-monitor.patch
-Patch0033:  0033-responder_common-Create-fd-for-pipe-in-helper.patch
-Patch0034:  0034-TEST-Unit-test-for-create_pipe_fd.patch
-Patch0035:  0035-responders-Do-not-initialize-pipe-fd-if-already-pres.patch
-Patch0036:  0036-PAM-Create-pipe-file-descriptors-before-privileges-a.patch
-Patch0037:  0037-PAM-Run-pam-responder-as-nonroot.patch
-Patch0038:  0038-AUTOFS-Run-the-autofs-responder-as-the-SSSD-user.patch
-Patch0039:  0039-PAC-Run-the-pac-responder-as-the-SSSD-user.patch
-Patch0040:  0040-SUDO-Run-the-sudo-responder-as-the-SSSD-user.patch
-Patch0041:  0041-SSH-Run-the-ssh-responder-as-the-SSSD-user.patch
-Patch0042:  0042-SBUS-Fix-error-handling-after-closing-container.patch
-Patch0043:  0043-TESTS-Add-tests-for-the-views-related-option-maps.patch
-Patch0044:  0044-RESPONDERS-refactor-create_pipe_fd.patch
-Patch0045:  0045-RESPONDERS-Don-t-hard-code-umask-value-in-utility-fu.patch
-Patch0046:  0046-RESPONDERS-Set-default-value-for-umask.patch
-Patch0047:  0047-nss-group-enumeration-fix.patch
-Patch0048:  0048-nss-preserve-service-name-in-getsrv-call.patch
-Patch0049:  0049-sdap_print_server-use-getpeername-to-get-server-addr.patch
-Patch0050:  0050-IPA-Don-t-fail-the-request-when-BE-doesn-t-find-the-.patch
-Patch0051:  0051-memberof-check-for-empty-arrays-to-avoid-segfaults.patch
-Patch0052:  0052-CONFDB-Detect-fix-misconf-opt-refresh_expired_interv.patch
-Patch0053:  0053-NSS-disable-midpoint-refresh-for-netgroups.patch
-Patch0054:  0054-IPA-use-ipaUserGroup-object-class-for-groups.patch
-Patch0055:  0055-Add-add_strings_lists-utility-function.patch
-Patch0056:  0056-IPA-inherit-ldap_user_extra_attrs-to-AD-subdomains.patch
-Patch0057:  0057-Add-parse_attr_list_ex-helper-function.patch
-Patch0058:  0058-nss-parse-user_attributes-option.patch
-Patch0059:  0059-nss-return-user_attributes-in-origbyname-request.patch
-Patch0060:  0060-sysdb_get_user_attr_with_views-add-mandatory-overrid.patch
-Patch0061:  0061-sysdb_add_overrides_to_object-add-new-parameter-and-.patch
-Patch0062:  0062-Views-apply-user-SSH-public-key-override.patch
-Patch0063:  0063-Add-test-for-sysdb_add_overrides_to_object.patch
-Patch0064:  0064-Add-ssh-pubkey-to-origbyname-request.patch
-Patch0065:  0065-BUILD-Install-ldap_child-and-as-setuid-if-running-un.patch
-Patch0066:  0066-LDAP-Move-sss_krb5_verify_keytab_ex-to-ldap_child.patch
-Patch0067:  0067-LDAP-read-the-correct-data-type-from-ldap_child-s-in.patch
-Patch0068:  0068-LDAP-Drop-privileges-after-kinit-in-ldap_child.patch
-Patch0069:  0069-UTIL-Remove-code-duplication-of-struct-io.patch
-Patch0070:  0070-UTIL-Remove-more-code-duplication-setting-up-child-p.patch
-Patch0071:  0071-IPA-Move-setting-the-SELinux-context-to-a-child-proc.patch
-Patch0072:  0072-test_sysdb_views-Use-unique-directory-for-cache.patch
-Patch0073:  0073-selinux_child-Do-not-ignore-return-values.patch
-Patch0074:  0074-IPA-Store-right-username-to-selinux-child-context.patch
-Patch0075:  0075-PAM-Remove-authtok-from-PAM-stack-with-OTP.patch
-Patch0076:  0076-Revert-LDAP-Remove-unused-option-ldap_user_uuid.patch
-Patch0077:  0077-Revert-LDAP-Remove-unused-option-ldap_group_uuid.patch
-Patch0078:  0078-Fix-uuid-defaults.patch
-Patch0079:  0079-Revert-LDAP-Change-defaults-for-ldap_user-group_obje.patch
-Patch0080:  0080-LDAP-Disable-token-groups-by-default.patch
-Patch0081:  0081-proxy-Do-not-try-to-store-same-alias-twice.patch
-Patch0082:  0082-PROXY-Preserve-service-name-in-proxy-provider.patch
-Patch0083:  0083-BUILD-Install-krb5_child-as-suid-if-running-under-no.patch
-Patch0084:  0084-KRB5-Drop-privileges-in-the-child-not-the-back-end.patch
-Patch0085:  0085-KRB5-Move-ccache-related-functions-to-krb5_ccache.c.patch
-Patch0086:  0086-KRB5-Move-checking-for-illegal-RE-to-krb5_utils.c.patch
-Patch0087:  0087-KRB5-Move-all-ccache-operations-to-krb5_child.c.patch
-Patch0088:  0088-KRB5-Do-not-switch_creds-if-already-the-specified-us.patch
-Patch0089:  0089-BUILD-Use-separate-chown-to-make-changing-ownership-.patch
-Patch0090:  0090-BUILD-Make-chown-of-files-to-sssd-user-non-fatal.patch
-Patch0091:  0091-BUILD-Touch-files-in-DESTDIR.patch
-Patch0092:  0092-BE-Become-a-regular-user-after-initialization.patch
-Patch0093:  0093-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-speci.patch
-Patch0094:  0094-MAN-page-edit-for-ldap_use_tokengroups.patch
-Patch0095:  0095-sysdb-add-sysdb_search_object_by_uuid.patch
-Patch0096:  0096-ipa-add-split_ipa_anchor.patch
-Patch0097:  0097-LDAP-add-support-for-lookups-by-UUID.patch
-Patch0098:  0098-LDAP-always-store-UUID-if-available.patch
-Patch0099:  0099-ipa-add-get_be_acct_req_for_uuid.patch
-Patch0100:  0100-IPA-make-get_object_from_cache-public.patch
-Patch0101:  0101-IPA-check-overrrides-for-IPA-users-as-well.patch
-Patch0102:  0102-Enable-views-for-all-domains.patch
-Patch0103:  0103-MAN-Update-case_sensitive-Preserving-in-man-pages.patch
-Patch0104:  0104-Man-debug_timestamps-and-debug_microseconds.patch
-Patch0105:  0105-sss_client-Extract-destroying-of-mmap-cache-to-funct.patch
-Patch0106:  0106-sss_client-Fix-race-condition-in-memory-cache.patch
-Patch0107:  0107-IPA-Handle-IPA-groups-returned-from-extop-plugin.patch
-Patch0108:  0108-Fix-KRB5_CONF_PATH.patch
-Patch0109:  0109-AD-IPA-add-krb5_confd_path-configuration-option.patch
-Patch0110:  0110-test-Wrong-parameter-type-in-sss_parse_name_check.patch
-Patch0111:  0111-util-Special-case-PCRE_ERROR_NOMATCH-in-sss_parse_na.patch
-Patch0112:  0112-util-sss_get_domain_name-regex-mismatch-not-fatal.patch
-Patch0113:  0113-sysdb-add-sysdb_delete_view_tree.patch
-Patch0114:  0114-sysdb-add-sysdb_invalidate_overrides.patch
-Patch0115:  0115-views-allow-view-name-change-at-startup.patch
-Patch0116:  0116-PAM-Check-for-trusted-domain-before-sending-the-requ.patch
-Patch0117:  0117-PAM-Move-is_uid_trusted-from-pam_ctx-to-preq.patch
-Patch0118:  0118-krb5-make-krb5-provider-view-aware.patch
-Patch0119:  0119-IPA-only-update-view-data-if-it-really-changed.patch
-Patch0120:  0120-krb5-do-not-fail-if-checking-the-old-ccache-failed.patch
-Patch0121:  0121-test-avoid-leaks-in-leak-tests.patch
-Patch0122:  0122-krb5-add-copy_ccache_into_memory.patch
-Patch0123:  0123-krb5-add-copy_keytab_into_memory.patch
-Patch0124:  0124-ldap_child-copy-keytab-into-memory-to-drop-privilege.patch
-Patch0125:  0125-krb5_child-become-user-earlier.patch
-Patch0126:  0126-TESTS-Basic-child-tests.patch
-Patch0127:  0127-Add-extra_args-to-exec_child.patch
-Patch0128:  0128-KRB5-Create-the-fast-ccache-in-a-child-process.patch
-Patch0129:  0129-KRB5-Relax-DEBUG-message.patch
-Patch0130:  0130-IPA-Do-not-append-domain-name-to-fq-name.patch
-Patch0131:  0131-TESTS-Build-test_child-even-without-cmocka.patch
-Patch0132:  0132-sss_client-Work-around-glibc-bug.patch
-Patch0133:  0133-Skip-CHAUTHTOK_PRELIM-when-using-OTPs.patch
-Patch0134:  0134-PAM-Domain-names-are-case-insensitive.patch
-Patch0135:  0135-PAM-Missing-argument-to-domains-should-fail-auth.patch
-Patch0136:  0136-MAN-Misspelled-username-in-pam_trusted_users-is-not-.patch
-Patch0137:  0137-RESPONDER-Log-failures-to-resolve-user-names-in-csv_.patch
-Patch0138:  0138-KRB5-Check-FAST-kinit-errors-using-get_tgt_times.patch
-Patch0139:  0139-MAN-Clarify-ad_gpo_map-options.patch
-Patch0140:  0140-krb5_child-Initialize-REALM-earlier.patch
-Patch0141:  0141-TESTS-sysdb_delete_by_sid-test-return-value.patch
-Patch0142:  0142-NSS-nss_cmd_getbysid_search-return-ENOENT.patch
-Patch0143:  0143-SYSDB-sysdb_search_object_by_sid-returns-ENOENT.patch
-Patch0144:  0144-handle-KRB5KRB_ERR_GENERIC-as-unspecific-error.patch
-Patch0145:  0145-IPA-verify-group-memberships-of-trusted-domain-users.patch
-Patch0146:  0146-IPA-properly-handle-groups-from-different-domains.patch
-Patch0147:  0147-LDAP-retain-external-members.patch
-Patch0148:  0148-IPA-do-not-try-to-add-override-gid-twice.patch
-Patch0149:  0149-IPA-handle-GID-overrides-for-MPG-domains-on-clients.patch
-Patch0150:  0150-simple-access-provider-non-existing-object.patch
-Patch0151:  0151-libwbclient-initialize-some-return-values.patch
-Patch0152:  0152-GPO-Ignore-ENOENT-result-from-sysdb_gpo_get_gpo_resu.patch
-Patch0153:  0153-GPO-Set-libsmb-debugging-to-stderr.patch
-Patch0154:  0154-UTIL-Allow-dup-ing-child-pipe-to-a-different-FD.patch
-Patch0155:  0155-GPO-Don-t-use-stdout-for-output-in-gpo_child.patch
-Patch0156:  0156-GPO-Extract-server-hostname-after-connecting.patch
-Patch0157:  0157-IPA-add-get_be_acct_req_for_user_name.patch
-Patch0158:  0158-IPA-resolve-ghost-members-if-a-non-default-view-is-a.patch
-Patch0159:  0159-sysdb-fix-group-members-with-overridden-names.patch
-Patch0160:  0160-IPA-ipa_resolve_user_list_send-take-care-of-override.patch
-Patch0161:  0161-IPA-do-not-look-up-overrides-on-client-with-default-.patch
-Patch0162:  0162-IPA-make-version-check-more-precise.patch
-Patch0163:  0163-IPA-add-missing-break.patch
-Patch0164:  0164-IPA-process_members-optionally-return-missing-member.patch
-Patch0165:  0165-IPA-rename-ipa_s2n_get_groups_send-to-ipa_s2n_get_fq.patch
-Patch0166:  0166-IPA-resolve-missing-members.patch
-Patch0167:  0167-IPA-set-SYSDB_INITGR_EXPIRE-for-RESP_USER_GROUPLIST.patch
-Patch0168:  0168-krb5_child-Return-ERR_NETWORK_IO-on-KRB5_KDCREP_SKEW.patch
-Patch0169:  0169-krb5-fix-entry-order-in-MEMORY-keytab.patch
-Patch0170:  0170-nss-make-fill_orig-multi-value-aware.patch
-Patch0171:  0171-nss-refactor-fill_orig.patch
-Patch0172:  0172-nss-Add-original-DN-and-memberOf-to-origbyname-reque.patch
-Patch0173:  0173-Open-the-PAC-socket-from-krb5_child-before-dropping-.patch
-Patch0174:  0174-views-fix-GID-overrride-for-mpg-domains.patch
-Patch0175:  0175-IPA-properly-handle-mixed-case-trusted-domains.patch
-Patch0176:  0176-nss-fix-SID-lookups.patch
-Patch0177:  0177-sysdb-remove-ghosts-in-all-sub-domains-as-well.patch
-Patch0178:  0178-IPA-Rename-user_dom-into-obj_dom.patch
-Patch0179:  0179-IPA-resolve-IPA-group-memberships-for-AD-users.patch
-Patch0180:  0180-IPA-process_members-add-ghosts-only-once.patch
-Patch0181:  0181-IPA-Use-attr-s-dom-for-users-too.patch
-Patch0182:  0182-SELINUX-Call-setuid-0-setgid-0-to-also-set-the-real-.patch
-Patch0183:  0183-SELINUX-Set-and-reset-umask-when-caling-set_seuser-f.patch
-Patch0184:  0184-LDAP-Add-UUID-when-saving-incomplete-groups.patch
-Patch0185:  0185-IPA-Resolve-IPA-user-groups-overrideDN-in-non-defaul.patch
-Patch0186:  0186-ipa_s2n_save_objects-properly-handle-fully-qualified.patch
-Patch0187:  0187-AD-use-GC-for-SID-requests-as-well.patch
-Patch0188:  0188-fill_id-fix-LE-BE-issue-with-wrong-data-type.patch
-Patch0189:  0189-LDAP-unlink-ccname_file_dummy-if-there-is-an-error.patch
-Patch0190:  0190-selinux-Delete-existing-user-mapping-on-empty-defaul.patch
-Patch0191:  0191-ldap_child-initialized-ccname_file_dummy.patch
-Patch0192:  0192-ipa_selinux-Fix-warning-may-be-used-uninitialized.patch
-Patch0193:  0193-selinux-Handle-setup-with-empty-default-and-no-confi.patch
-Patch0194:  0194-IPA-idviews-check-if-view-name-is-set.patch
-Patch0195:  0195-IPA-make-sure-output-variable-is-set.patch
-Patch0196:  0196-IPA-set-EINVAL-if-dn-can-t-be-linearized.patch
-Patch0197:  0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch
-Patch0198:  0198-SDAP-Do-not-set-gid-0-twice.patch
-Patch0199:  0199-SDAP-Extract-filtering-AD-group-to-function.patch
-Patch0200:  0200-SDAP-Filter-ad-groups-in-initgroups.patch
-Patch0201:  0201-sdap-properly-handle-binary-objectGuid-attribute.patch
-Patch0202:  0202-Download-complete-groups-if-ignore_group_members-is-.patch
-Patch0203:  0203-confdb-Add-new-option-subdomain_inherit.patch
-Patch0204:  0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch
-Patch0205:  0205-SDAP-Add-sdap_copy_map_entry.patch
-Patch0206:  0206-UTIL-Inherit-ignore_group_members.patch
-Patch0207:  0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch
-Patch0208:  0208-sudo-sanitize-filter-values.patch
-Patch0209:  0209-SYSDB-Index-the-objectSIDString-attribute.patch
-Patch0210:  0210-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch
-Patch0211:  0211-IPA-do-initgroups-if-extdom-exop-supports-it.patch
-Patch0212:  0212-IPA-update-initgr-expire-timestamp-conditionally.patch
-Patch0213:  0213-IPA-enhance-ipa_initgr_get_overrides_send.patch
-Patch0214:  0214-IPA-search-for-overrides-during-initgroups-in-sever-.patch
+Patch0001:  0001-test-common-sss_dp_get_account_recv-fix-assignment.patch
+Patch0002:  0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch
+Patch0003:  0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch
+Patch0004:  0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch
+Patch0005:  0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch
+Patch0006:  0006-UTIL-Add-sss_filter_sanitize_ex.patch
+Patch0007:  0007-LDAP-Fetch-users-and-groups-using-wildcards.patch
+Patch0008:  0008-LDAP-Add-sdap_get_and_parse_generic_send.patch
+Patch0009:  0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch
+Patch0010:  0010-LDAP-Add-sdap_lookup_type-enum.patch
+Patch0011:  0011-LDAP-Add-the-wildcard_limit-option.patch
+Patch0012:  0012-IFP-Add-wildcard-requests.patch
+Patch0013:  0013-KRB5-Return-right-data-provider-error-code.patch
+Patch0014:  0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch
+Patch0015:  0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch
+Patch0016:  0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch
+Patch0017:  0017-DYNDNS-special-value-for-dyndns_iface-option.patch
+Patch0018:  0018-TESTS-dyndns-tests-support-AAAA-addresses.patch
+Patch0019:  0019-DYNDNS-support-for-dualstack.patch
+Patch0020:  0020-VIEWS-TEST-add-null-check.patch
+Patch0021:  0021-SYSDB-prepare-for-LOCAL-view.patch
+Patch0022:  0022-TOOLS-add-common-command-framework.patch
+Patch0023:  0023-TOOLS-add-sss_override-for-local-overrides.patch
+Patch0024:  0024-IPA-Better-debugging.patch
+Patch0025:  0025-UTIL-Lower-debug-level-in-perform_checks.patch
+Patch0026:  0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch
+Patch0027:  0027-TESTS-fix-compiler-warnings.patch
+Patch0028:  0028-intg-Invalidate-memory-cache-before-removing-files.patch
+Patch0029:  0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch
+Patch0030:  0030-utils-add-NSS-version-of-cert-utils.patch
+Patch0031:  0031-Add-NSS-version-of-p11_child.patch
+Patch0032:  0032-pack_message_v3-allow-empty-name.patch
+Patch0033:  0033-authok-add-support-for-Smart-Card-related-authtokens.patch
+Patch0034:  0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch
+Patch0035:  0035-pam_sss-add-sc-support.patch
+Patch0036:  0036-ssh-generate-public-keys-from-certificate.patch
+Patch0037:  0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch
+Patch0038:  0038-mmap_cache-Rename-variables.patch
+Patch0039:  0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch
+Patch0040:  0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch
+Patch0041:  0041-sss_client-Update-integrity-check-of-records-in-mmap.patch
+Patch0042:  0042-intg_test-Add-module-for-simulation-of-utility-id.patch
+Patch0043:  0043-intg_test-Add-integration-test-for-memory-cache.patch
+Patch0044:  0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch
+Patch0045:  0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch
+Patch0046:  0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch
+Patch0047:  0047-test_memory_cache-Test-invalidation-with-sss_cache.patch
+Patch0048:  0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch
+Patch0049:  0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch
+Patch0050:  0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch
+Patch0051:  0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch
+Patch0052:  0052-IFP-use-default-limit-if-provided-is-0.patch
+Patch0053:  0053-sudo-use-higher-value-wins-when-ordering-rules.patch
+Patch0054:  0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch
+Patch0055:  0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch
+Patch0056:  0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch
+Patch0057:  0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch
+Patch0058:  0058-p11child-set-restrictive-umask-and-clear-environment.patch
+Patch0059:  0059-pam-Incerease-p11-child-timeout.patch
+Patch0060:  0060-SYSDB-Index-the-objectSIDString-attribute.patch
+Patch0061:  0061-sss_override-print-input-name-if-unable-to-parse-it.patch
+Patch0062:  0062-sss_override-support-domains-that-require-fqname.patch
+Patch0063:  0063-TOOLS-add-sss_colondb-API.patch
+Patch0064:  0064-sss_override-decompose-code-better.patch
+Patch0065:  0065-sss_override-support-import-and-export.patch
+Patch0066:  0066-NSS-Fix-use-after-free.patch
+Patch0067:  0067-sss_override-document-debug-options.patch
+Patch0068:  0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch
+Patch0069:  0069-GPO-fix-memory-leak.patch
+Patch0070:  0070-sss_override-support-fqn-in-override-name.patch
+Patch0071:  0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch
+Patch0072:  0072-views-fix-two-typos-in-debug-messages.patch
+Patch0073:  0073-views-allow-ghost-members-for-LOCAL-view.patch
+Patch0074:  0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch
+Patch0075:  0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch
+Patch0076:  0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch
+Patch0077:  0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch
+Patch0078:  0078-KRB5-Offline-operation-with-disabled-domain.patch
+Patch0079:  0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch
+Patch0080:  0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch
+Patch0081:  0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch
+Patch0082:  0082-sss_override-remove-d-from-manpage.patch
+Patch0083:  0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch
+Patch0084:  0084-DYNDNS-Add-a-new-option-dyndns_server.patch
+Patch0085:  0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch
+Patch0086:  0086-DYNDNS-remove-redundant-talloc_steal.patch
+Patch0087:  0087-DYNDNS-remove-zone-command.patch
+Patch0088:  0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch
+Patch0089:  0089-DYNDNS-remove-code-duplication.patch
+Patch0090:  0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch
+Patch0091:  0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch
+Patch0092:  0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch
+Patch0093:  0093-DEBUG-Add-new-debug-category-for-fail-over.patch
+Patch0094:  0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch
+Patch0095:  0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch
+Patch0096:  0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch
+Patch0097:  0097-AD-inicialize-root_domain_attrs-field.patch
+Patch0098:  0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch
+Patch0099:  0099-Fix-memory-leak-in-sssdpac_verify.patch
+Patch0100:  0100-AD-Provide-common-connection-list-construction-funct.patch
+Patch0101:  0101-AD-Consolidate-connection-list-construction-on-ad_co.patch
+Patch0102:  0102-nss-send-original-name-and-id-with-local-views-if-po.patch
+Patch0103:  0103-sudo-search-with-view-even-if-user-is-found.patch
+Patch0104:  0104-sudo-send-original-name-and-id-with-local-views-if-p.patch
+
+#This patch should not be removed in RHEL-7
+Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec
 
 ### Dependencies ###
 Requires: sssd-common = %{version}-%{release}
@@ -260,6 +155,7 @@ Requires: python-sssdconfig = %{version}-%{release}
 %global servicename sssd
 %global sssdstatedir %{_localstatedir}/lib/sss
 %global dbpath %{sssdstatedir}/db
+%global keytabdir %{sssdstatedir}/keytabs
 %global pipepath %{sssdstatedir}/pipes
 %global mcpath %{sssdstatedir}/mc
 %global pubconfpath %{sssdstatedir}/pubconf
@@ -286,6 +182,7 @@ BuildRequires: dbus-libs
 BuildRequires: openldap-devel
 BuildRequires: pam-devel
 BuildRequires: nss-devel
+BuildRequires: openssl-devel
 BuildRequires: nspr-devel
 BuildRequires: pcre-devel
 BuildRequires: libxslt
@@ -384,6 +281,8 @@ Summary: Userspace tools for use with the SSSD
 Group: Applications/System
 License: GPLv3+
 Requires: sssd-common = %{version}-%{release}
+Requires: python-sss = %{version}-%{release}
+Requires: python-sssdconfig = %{version}-%{release}
 
 %description tools
 Provides userspace tools for manipulating users, groups, and nested groups in
@@ -403,6 +302,28 @@ BuildArch: noarch
 %description -n python-sssdconfig
 Provides python files for manipulation SSSD and IPA configuration files.
 
+%package -n python-sss
+Summary: Python2 bindings for sssd
+Group: Development/Libraries
+License: LGPLv3+
+Requires: sssd-common = %{version}-%{release}
+
+%description -n python-sss
+Provides python2 module for manipulating users, groups, and nested groups in
+SSSD when using id_provider = local in /etc/sssd/sssd.conf.
+
+Also provides several other useful python2 bindings:
+    * function for retrieving list of groups user belongs to.
+    * class for obfuscation of passwords
+
+%package -n python-sss-murmur
+Summary: Python2 bindings for murmur hash function
+Group: Development/Libraries
+License: LGPLv3+
+
+%description -n python-sss-murmur
+Provides python2 module for calculating the murmur hash version 3
+
 %package ldap
 Summary: The LDAP back end of the SSSD
 Group: Applications/System
@@ -480,7 +401,7 @@ Requires: bind-utils
 Requires: sssd-common-pac = %{version}-%{release}
 # In order for libwbclient to be upgraded before sssd-ad and sets up the
 # alternatives symlink
-Requires: libwbclient
+Requires: libwbclient >= 4.2.3-1
 
 %description ad
 Provides the Active Directory back end that the SSSD can utilize to fetch
@@ -535,14 +456,16 @@ Requires: libipa_hbac = %{version}-%{release}
 %description -n libipa_hbac-devel
 Utility library to validate FreeIPA HBAC rules for authorization requests
 
-%package -n libipa_hbac-python
+%package -n python-libipa_hbac
 Summary: Python bindings for the FreeIPA HBAC Evaluator library
 Group: Development/Libraries
 License: LGPLv3+
 Requires: libipa_hbac = %{version}-%{release}
+Provides: libipa_hbac-python = %{version}-%{release}
+Obsoletes: libipa_hbac-python < 1.12.90
 
-%description -n libipa_hbac-python
-The libipa_hbac-python contains the bindings so that libipa_hbac can be
+%description -n python-libipa_hbac
+The python-libipa_hbac contains the bindings so that libipa_hbac can be
 used by Python applications.
 
 %package -n libsss_nss_idmap
@@ -564,14 +487,16 @@ Requires: libsss_nss_idmap = %{version}-%{release}
 %description -n libsss_nss_idmap-devel
 Utility library for SID based lookups
 
-%package -n libsss_nss_idmap-python
+%package -n python-libsss_nss_idmap
 Summary: Python bindings for libsss_nss_idmap
 Group: Development/Libraries
 License: LGPLv3+
 Requires: libsss_nss_idmap = %{version}-%{release}
+Provides: libsss_nss_idmap-python = %{version}-%{release}
+Obsoletes: libsss_nss_idmap-python < 1.12.90
 
-%description -n libsss_nss_idmap-python
-The libsss_nss_idmap-python contains the bindings so that libsss_nss_idmap can
+%description -n python-libsss_nss_idmap
+The python-libsss_nss_idmap contains the bindings so that libsss_nss_idmap can
 be used by Python applications.
 
 %package dbus
@@ -590,6 +515,7 @@ Summary: The SSSD D-Bus responder helper library
 Group: Development/Libraries
 License: GPLv3+
 Requires: dbus-libs
+Requires: sssd-dbus = %{version}-%{release}
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
 
@@ -647,6 +573,12 @@ for p in %patches ; do
     UpdateTimestamps -p1 $p
 done
 
+# patch(1) doesn't handle binary files we need for tests. Package them
+# as additional sources and add to the source tree
+mkdir src/tests/cmocka/p11_nssdb/
+cp %{SOURCE1} src/tests/cmocka/p11_nssdb/
+cp %{SOURCE2} src/tests/cmocka/p11_nssdb/
+
 %build
 autoreconf -ivf
 %configure \
@@ -668,7 +600,9 @@ autoreconf -ivf
     --with-syslog=journald \
     --with-test-dir=/dev/shm \
     --enable-sss-default-nss-plugin \
-    %{?with_cifs_utils_plugin_option}
+    %{?with_cifs_utils_plugin_option} \
+    --without-python3-bindings \
+    --with-ad-gpo-default=permissive
 
 make %{?_smp_mflags} all docs
 
@@ -797,6 +731,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_libexecdir}/%{servicename}/sssd_autofs
 %{_libexecdir}/%{servicename}/sssd_ssh
 %{_libexecdir}/%{servicename}/sssd_sudo
+%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/p11_child
 
 %dir %{_libdir}/%{name}
 %{_libdir}/%{name}/libsss_simple.so
@@ -804,7 +739,9 @@ rm -rf $RPM_BUILD_ROOT
 #Internal shared libraries
 %{_libdir}/%{name}/libsss_child.so
 %{_libdir}/%{name}/libsss_crypt.so
+%{_libdir}/%{name}/libsss_cert.so
 %{_libdir}/%{name}/libsss_debug.so
+%{_libdir}/%{name}/libsss_krb5_common.so
 %{_libdir}/%{name}/libsss_ldap_common.so
 %{_libdir}/%{name}/libsss_util.so
 %{_libdir}/%{name}/libsss_semanage.so
@@ -826,6 +763,7 @@ rm -rf $RPM_BUILD_ROOT
 %attr(755,sssd,sssd) %dir %{mcpath}
 %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/passwd
 %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/group
+%ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/initgroups
 %attr(755,sssd,sssd) %dir %{pipepath}
 %attr(755,sssd,sssd) %dir %{pubconfpath}
 %attr(755,sssd,sssd) %dir %{gpocachepath}
@@ -848,8 +786,6 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man5/sss_rpcidmapd.5*
 %{_mandir}/man8/sssd.8*
 %{_mandir}/man8/sss_cache.8*
-%{python_sitearch}/pysss.so
-%{python_sitearch}/pysss_murmur.so
 
 %files ldap -f sssd_ldap.lang
 %defattr(-,root,root,-)
@@ -860,7 +796,6 @@ rm -rf $RPM_BUILD_ROOT
 %files krb5-common
 %defattr(-,root,root,-)
 %doc COPYING
-%{_libdir}/%{name}/libsss_krb5_common.so
 %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/ldap_child
 %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/krb5_child
 
@@ -879,6 +814,7 @@ rm -rf $RPM_BUILD_ROOT
 %defattr(-,root,root,-)
 %doc COPYING
 %attr(755,root,root) %dir %{pubconfpath}/krb5.include.d
+%attr(700,sssd,sssd) %dir %{keytabdir}
 %{_libdir}/%{name}/libsss_ipa.so
 %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/selinux_child
 %{_mandir}/man5/sssd-ipa.5*
@@ -894,7 +830,7 @@ rm -rf $RPM_BUILD_ROOT
 %files proxy
 %defattr(-,root,root,-)
 %doc COPYING
-%{_libexecdir}/%{servicename}/proxy_child
+%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/proxy_child
 %{_libdir}/%{name}/libsss_proxy.so
 
 %files dbus
@@ -952,6 +888,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_sbindir}/sss_groupmod
 %{_sbindir}/sss_groupshow
 %{_sbindir}/sss_obfuscate
+%{_sbindir}/sss_override
 %{_sbindir}/sss_debuglevel
 %{_sbindir}/sss_seed
 %{_mandir}/man8/sss_groupadd.8*
@@ -962,6 +899,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_mandir}/man8/sss_userdel.8*
 %{_mandir}/man8/sss_usermod.8*
 %{_mandir}/man8/sss_obfuscate.8*
+%{_mandir}/man8/sss_override.8*
 %{_mandir}/man8/sss_debuglevel.8*
 %{_mandir}/man8/sss_seed.8*
 
@@ -970,6 +908,16 @@ rm -rf $RPM_BUILD_ROOT
 %dir %{python_sitelib}/SSSDConfig
 %{python_sitelib}/SSSDConfig/*.py*
 
+%files -n python-sss
+%defattr(-,root,root,-)
+%{python_sitearch}/pysss.so
+%{python_sitearch}/_py2sss.so
+
+%files -n python-sss-murmur
+%defattr(-,root,root,-)
+%{python_sitearch}/pysss_murmur.so
+%{python_sitearch}/_py2sss_murmur.so
+
 %files -n libsss_idmap
 %defattr(-,root,root,-)
 %doc src/sss_client/COPYING src/sss_client/COPYING.LESSER
@@ -994,9 +942,10 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/libipa_hbac.so
 %{_libdir}/pkgconfig/ipa_hbac.pc
 
-%files -n libipa_hbac-python
+%files -n python-libipa_hbac
 %defattr(-,root,root,-)
 %{python_sitearch}/pyhbac.so
+%{python_sitearch}/_py2hbac.so
 
 %files -n libsss_nss_idmap
 %defattr(-,root,root,-)
@@ -1010,9 +959,10 @@ rm -rf $RPM_BUILD_ROOT
 %{_libdir}/libsss_nss_idmap.so
 %{_libdir}/pkgconfig/sss_nss_idmap.pc
 
-%files -n libsss_nss_idmap-python
+%files -n python-libsss_nss_idmap
 %defattr(-,root,root,-)
 %{python_sitearch}/pysss_nss_idmap.so
+%{python_sitearch}/_py2sss_nss_idmap.so
 
 %files libwbclient
 %defattr(-,root,root,-)
@@ -1044,7 +994,7 @@ if [ $1 -ge 1 ] ; then
 fi
 
 %preun common
-if [ $1 -eq 0 ]; then
+if [ $1 -eq 0 ] ; then
      # Package removal, not upgrade
     /bin/systemctl --no-reload disable sssd.service > /dev/null 2>&1 || :
     /bin/systemctl stop sssd.service > /dev/null 2>&1 || :
@@ -1056,7 +1006,7 @@ fi
 /usr/sbin/alternatives --install /etc/cifs-utils/idmap-plugin cifs-idmap-plugin %{_libdir}/cifs-utils/cifs_idmap_sss.so 20
 
 %preun client
-if [ $1 -eq 0 ]; then
+if [ $1 -eq 0 ] ; then
         /usr/sbin/alternatives --remove cifs-idmap-plugin %{_libdir}/cifs-utils/cifs_idmap_sss.so
 fi
 %else
@@ -1073,6 +1023,10 @@ fi
 
 %postun -n libsss_idmap -p /sbin/ldconfig
 
+%post -n libsss_nss_idmap -p /sbin/ldconfig
+
+%postun -n libsss_nss_idmap -p /sbin/ldconfig
+
 %post libwbclient
 %{_sbindir}/update-alternatives --install %{_libdir}/libwbclient.so.0.11 \
                                 libwbclient.so.0.11%{libwbc_alternatives_suffix} \
@@ -1109,60 +1063,271 @@ fi
 /usr/bin/rm -f /var/tmp/sssd.upgrade || :
 
 %changelog
-* Fri Oct  2 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.18
-- Resolves: rhbz#1268205 - SSSD intermittently fails to resolve external
-                           IPA group membership.
+* Wed Oct 14 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-40
+- Resolves: rhbz#1270827 - local overrides: don't contact server with
+                           overridden name/id
 
-* Thu Sep  3 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.17
-- Actually apply the patch for rhbz#1255442
-- Resolves: rhbz#1255442 - getgrgid for user's UID on a trust client
-                           prevents getpw*
+* Wed Oct  7 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-39
+- Resolves: rhbz#1267837 - sssd_be crashed in ipa_srv_ad_acct_lookup_step
+
+* Wed Oct  7 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-38
+- Resolves: rhbz#1267176 - Memory leak / possible DoS with krb auth.
+
+* Wed Oct  7 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-37
+- Resolves: rhbz#1267836 - PAM responder crashed if user was not set
+
+* Wed Sep 30 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-36
+- Resolves: rhbz#1266107 - AD: Conditional jump or move depends on
+                           uninitialised value
+
+* Wed Sep 23 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-35
+- Resolves: rhbz#1250135 - Detect re-established trusts in the IPA
+                           subdomain code
+
+* Tue Sep 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-34
+- Fix a Coverity warning in dyndns code
+- Resolves: rhbz#1261155 - nsupdate exits on first GSSAPI error instead
+                           of processing other commands
+* Tue Sep 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-33
+- Resolves: rhbz#1261155 - nsupdate exits on first GSSAPI error instead
+                           of processing other commands
+
+* Tue Sep 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-32
+- Resolves: rhbz#1263735 - Could not resolve AD user from root domain
+
+* Tue Sep 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-31
+- Remove -d from sss_override manpage
+- Related: rhbz#1259512 - sss_override : The local override user is not found
+
+* Tue Sep 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-30
+- Patches required for better handling of failover with one-way trusts
+- Related: rhbz#1250135 - Detect re-established trusts in the IPA subdomain
+                          code
+
+* Fri Sep 18 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-29
+- Resolves: rhbz#1263587 - sss_override --name doesn't work with RFC2307
+                           and ghost users
+
+* Fri Sep 18 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-28
+- Resolves: rhbz#1259512 - sss_override : The local override user is not found
+
+* Fri Sep 18 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-27
+- Resolves: rhbz#1260027 - sssd_be memory leak with sssd-ad in GPO code
+
+* Tue Sep  1 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-26
+- Resolves: rhbz#1256398 - sssd cannot resolve user names containing
+                           backslash with ldap provider
 
-* Thu Aug 20 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.16
-- Resolves: rhbz#1255443 - Add index for 'objectSIDString' and maybe to
+* Tue Aug 25 2015 Martin Kosek <mkosek@redhat.com> - 1.13.0-25
+- Resolves: rhbz#1254189 - sss_override contains an extra parameter --debug
+                           but is not listed in the man page or in
+                           the arguments help
+
+* Thu Aug 20 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-24
+- Resolves: rhbz#1254518 - Fix crash in nss responder
+
+* Thu Aug 20 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-23
+- Support import/export for local overrides
+- Support FQDNs for local overrides
+- Resolves: rhbz#1254184 - sss_override does not work correctly when
+                           'use_fully_qualified_names = True'
+
+* Tue Aug 18 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-22
+- Resolves: rhbz#1244950 - Add index for 'objectSIDString' and maybe to
                            other cache attributes
 
-* Thu Aug 20 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.15
-- Resolves: rhbz#1255442 - getgrgid for user's UID on a trust client
-                           prevents getpw*
+* Mon Aug 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-21
+- Resolves: rhbz#1250415 - sssd: p11_child hardening
+
+* Mon Aug 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-20
+- Related: rhbz#1250135 - Detect re-established trusts in the IPA
+                          subdomain code
+
+* Mon Aug 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-19
+- Resolves: rhbz#1202724 - [RFE] Add a way to lookup users based on CAC
+                           identity certificates
+
+* Mon Aug 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-18
+- Resolves: rhbz#1232950 - [IPA/IdM] sudoOrder not honored as expected
 
-* Mon Jul 20 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.14
-- Resolves: rhbz#1244761 - Relax the libldb requirements to unblock
-                           RH Storage
+* Mon Aug 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-17
+- Fix wildcard_limit=0
+- Resolves: rhbz#1206571 - [RFE] Expose D-BUS interface
 
-* Thu Jun 18 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.13
-- Resolves: rhbz#1232130 - sysdb sudo search doesn't escape special characters
+* Mon Aug 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-16
+- Fix race condition in invalidating the memory cache
+- Related: rhbz#1206575 - [RFE] The fast memory cache should cache initgroups
 
-* Mon Jun  8 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.12
-- Resolves: rhbz#1226801 - ignore_group_members doesn't work for subdomains
-- Resolves: rhbz#1226180 - Provide a way to disable the cleanup task
+* Mon Aug 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-15
+- Resolves: rhbz#1249015 - KDC proxy not working with SSSD krb5_use_kdcinfo
+                           enabled
 
-* Thu May 28 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.9
-- Resolves: rhbz#1227772 - Properly handle AD's binary objectGUID
+* Thu Aug  6 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-14
+- Bump release number
+- Related: rhbz#1246489 - sss_obfuscate fails with "ImportError: No module
+                          named pysss"
 
-* Wed Apr 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.8
+* Thu Aug  6 2015 Lukas Slebodnik <lslebodn@redhat.com> - 1.13.0-13
+- Fix missing dependency of sssd-tools
+- Resolves: rhbz#1246489 - sss_obfuscate fails with "ImportError: No module
+                           named pysss"
+
+* Wed Aug  5 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-12
+- More memory cache related fixes
+- Related: rhbz#1206575 - [RFE] The fast memory cache should cache initgroups
+
+* Tue Aug  4 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-11
+- Remove binary blob from SC patches as patch(1) can't handle those
+- Related: rhbz#854396 - [RFE] Support for smart cards
+
+* Tue Aug  4 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-10
+- Resolves: rhbz#1244949 - getgrgid for user's UID on a trust client
+                           prevents getpw*
+
+* Tue Aug  4 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-9
+- Fix memory cache integration tests
+- Resolves: rhbz#1206575 - [RFE] The fast memory cache should cache initgroups
+- Resolves: rhbz#854396 - [RFE] Support for smart cards
+
+* Tue Jul 28 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-8
+- Remove OTP from PAM stack correctly
+- Related: rhbz#1200873 - [RFE] Allow smart multi step prompting when
+                          user logs in with password and token code from IPA
+- Handle sssd-owned keytabs when sssd runs as root
+- Related: rhbz#1205144 - RFE: Support one-way trusts for IPA
+
+* Mon Jul 27 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-7
+- Resolves: rhbz#1183747 - [FEAT] UID and GID mapping on individual clients
+
+* Fri Jul 24 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-6
+- Resolves: rhbz#1206565 - [RFE] Add dualstack and multihomed support
+- Resolves: rhbz#1187146 - If v4 address exists, will not create nonexistant
+                           v6 in ipa domain
+
+* Fri Jul 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-5
+- Resolves: rhbz#1242942 - well-known SID check is broken for NetBIOS prefixes
+
+* Fri Jul 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-4
+- Resolves: rhbz#1234722 - sssd ad provider fails to start in rhel7.2
+
+* Thu Jul 16 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-3
+- Add support for InfoPipe wildcard requests
+- Resolves: rhbz#1206571 - [RFE] Expose D-BUS interface
+
+* Mon Jul  6 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-2
+- Also package the initgr memcache
+- Related: rhbz#1205554 - Rebase SSSD to 1.13.x
+
+* Mon Jul  6 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0-1
+- Rebase to 1.13.0 upstream
+- Related: rhbz#1205554 - Rebase SSSD to 1.13.x
+- Resolves: rhbz#910187 - [RFE] authenticate against cache in SSSD
+- Resolves: rhbz#1206575 - [RFE] The fast memory cache should cache initgroups
+
+* Wed Jul  1 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0.3alpha
+- Don't default to SSSD user
+- Related: rhbz#1205554 - Rebase SSSD to 1.13.x
+
+* Tue Jun 23 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0.2alpha
+- Related: rhbz#1205554 - Rebase SSSD to 1.13.x
+- GPO default should be permissve
+
+* Mon Jun 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.13.0.1alpha
+- Resolves: rhbz#1205554 - Rebase SSSD to 1.13.x
+- Relax the libldb requirement
+- Resolves: rhbz#1221992 - sssd_be segfault at 0 ip sp error 6 in
+                           libtevent.so.0.9.21
+- Resolves: rhbz#1221839 - SSSD group enumeration inconsistent due to
+                           binary SIDs
+- Resolves: rhbz#1219285 - Unable to resolve group memberships for AD
+                           users when using sssd-1.12.2-58.el7_1.6.x86_64
+                           client in combination with
+                           ipa-server-3.0.0-42.el6.x86_64 with AD Trust
+- Resolves: rhbz#1217559 - [RFE] Support GPOs from different domain controllers
+- Resolves: rhbz#1217350 - ignore_group_members doesn't work for subdomains
+- Resolves: rhbz#1217127 - Override for IPA users with login does not list
+                           user all groups
+- Resolves: rhbz#1216285 - autofs provider fails when default_domain_suffix
+                           and use_fully_qualified_names set
+- Resolves: rhbz#1214719 - Group resolution is inconsistent with group
+                           overrides
+- Resolves: rhbz#1214718 - Overridde with --login fails trusted adusers
+                           group membership resolution
+- Resolves: rhbz#1214716 - idoverridegroup for ipa group with --group-name
+                           does not work
+- Resolves: rhbz#1214337 - Overrides with --login work in second attempt
+- Resolves: rhbz#1212489 - Disable the cleanup task by default
+- Resolves: rhbz#1211830 - external users do not resolve with
+                           "default_domain_suffix" set in IPA server sssd.conf
+- Resolves: rhbz#1210854 - Only set the selinux context if the context
+                           differs from the local one
+- Resolves: rhbz#1209483 - When using id_provider=proxy with
+                           auth_provider=ldap, it does not work as expected
+- Resolves: rhbz#1209374 - Man sssd-ad(5) lists Group Policy Management
+                           Editor naming for some policies but not for all
+- Resolves: rhbz#1208507 - sysdb sudo search doesn't escape special characters
+- Resolves: rhbz#1206571 - [RFE] Expose D-BUS interface
+- Resolves: rhbz#1206566 - SSSD does not update Dynamic DNS records if
+                           the IPA domain differs from machine hostname's
+                           domain
+- Resolves: rhbz#1206189 - [bug] sssd always appends default_domain_suffix
+                           when checking for host keys
+- Resolves: rhbz#1204203 - sssd crashes intermittently
+- Resolves: rhbz#1203945 - [FJ7.0 Bug]: getgrent returns error because
+                           sss is written in nsswitch.conf as default
+- Resolves: rhbz#1203642 - GPO access control looks for computer object
+                           in user's domain only
+- Resolves: rhbz#1202245 - SSSD's HBAC processing is not permissive enough
+                           with broken replication entries
+- Resolves: rhbz#1201271 - sssd_nss segfaults if initgroups request is by
+                           UPN and doesn't find anything
+- Resolves: rhbz#1200873 - [RFE] Allow smart multi step prompting when
+                           user logs in with password and token code from IPA
+- Resolves: rhbz#1199541 - Read and use the TTL value when resolving a
+                           SRV query
+- Resolves: rhbz#1199533 - [RFE] Implement background refresh for users,
+                           groups or other cache objects
+- Resolves: rhbz#1199445 - Does sssd-ad use the most suitable attribute
+                           for group name?
+- Resolves: rhbz#1198477 - ccname_file_dummy is not unlinked on error
+- Resolves: rhbz#1187103 - [RFE] User's home directories are not taken
+                           from AD when there is an IPA trust with AD
+- Resolves: rhbz#1185536 - In ipa-ad trust, with 'default_domain_suffix' set
+                           to AD domain, IPA user are not able to log unless
+                           use_fully_qualified_names is set
+- Resolves: rhbz#1175760 - [RFE] Have OpenLDAP lock out ssh keys when
+                           account naturally expires
+- Resolves: rhbz#1163806 - [RFE]ad provider dns_discovery_domain option:
+                           kerberos discovery is not using this option
+- Resolves: rhbz#1205160 - Complain loudly if backend doesn't start due
+                           to missing or invalid keytab
+
+* Wed Apr 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-61
+- Resolves: rhbz#1226119 - Properly handle AD's binary objectGUID
+
+* Wed Apr 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-60
 - Filter out domain-local groups during AD initgroups operation
-- Related: rhbz#1214286 - SSSD downloads too much information when fetching
+- Related: rhbz#1201840 - SSSD downloads too much information when fetching
                           information about groups
 
-* Wed Apr 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.7
-- Resolves: rhbz#1214286 - SSSD downloads too much information when fetching
+* Wed Apr 22 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-59
+- Resolves: rhbz#1201840 - SSSD downloads too much information when fetching
                            information about groups
 
 * Thu Mar 19 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.6
 - Initialize variable in the views code in one success and one failure path
-- Resolves: rhbz#1203365 - sssd_be segfault on IPA(when auth with AD
+- Resolves: rhbz#1202170 - sssd_be segfault on IPA(when auth with AD
                            trusted domain) client at
                            src/providers/ipa/ipa_s2n_exop.c:1605
 
 * Tue Mar 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.5
-- Resolves: rhbz#1203365 - sssd_be segfault on IPA(when auth with AD
+- Resolves: rhbz#1202170 - sssd_be segfault on IPA(when auth with AD
                            trusted domain) client at
                            src/providers/ipa/ipa_s2n_exop.c:1605
 
 * Tue Mar 17 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.4
 - Handle case where there is no default and no rules
-- Resolves: rhbz#1199143 - With empty ipaselinuxusermapdefault security
+- Resolves: rhbz#1192314 - With empty ipaselinuxusermapdefault security
                            context on client is staff_u
 
 * Thu Mar  5 2015 Jakub Hrozek <jhrozek@redhat.com> - 1.12.2-58.3