From 6cf099e23f0d52471d4c0199a7e8bbd588dac686 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 19 2015 15:43:04 +0000 Subject: import sssd-1.13.0-40.el7 --- 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 +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 +--- + 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 -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 ---- - 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 - #endif - --#ifdef HAVE_SEMANAGE --#include --#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 2010 - -@@ -23,73 +23,16 @@ - - #include - --#ifdef HAVE_SELINUX --#include --#endif -- - #ifdef HAVE_SEMANAGE - #include - #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 -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 ---- - 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 -- - #ifdef HAVE_SEMANAGE - #include - #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 +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 +--- + 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 -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 ---- - 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 +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 +--- + 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 +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 +--- + 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 -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 ---- - 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 -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 ---- - 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 +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 +--- + 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 +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 +--- + 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 -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 ---- - 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 +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 +--- + 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 -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 ---- - 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 +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 +--- + 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 -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 ---- - 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 +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 +--- + 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 -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 ---- - 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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+#include -+ -+#include -+#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 +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 +--- + 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 -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 ---- - 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 +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 +--- + 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) + + + ++ ++ wildcart_limit (integer) ++ ++ ++ Specifies an upper limit on the number of entries ++ that are downloaded during a wildcard lookup. ++ ++ ++ At the moment, only the InfoPipe responder supports ++ wildcard lookups. ++ ++ ++ Default: 1000 (often the size of one page) ++ ++ ++ ++ + + + +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 -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 ---- - 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 +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 +--- + 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 + + + ++ ++ ++ wildcart_limit (integer) ++ ++ ++ Specifies an upper limit on the number of entries ++ that are downloaded during a wildcard lookup that ++ overrides caller-supplied limit. ++ ++ ++ Default: 0 (let the caller set an upper limit) ++ ++ ++ ++ + + + +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 + + #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 . + */ + ++#include ++ + #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 -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 ---- - 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 -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 ---- - 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 +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 +--- + 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 +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 +--- + 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[^@]+)@?(?P[^@]*$)"); ++ 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 -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 ---- - 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 +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 -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 ---- - 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 +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 + + + Optional. Applicable only when dyndns_update +- is true. Choose the interface whose IP address +- should be used for dynamic DNS updates. +- +- +- 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. + + + Default: Use the IP address of the AD LDAP connection + ++ ++ Example: dyndns_iface = em1, vnet1, vnet2 ++ + + + +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 @@ + + + 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. + + +- NOTE: This option currently supports only one interface. ++ NOTE: This option currently supports multiple interfaces. + + + NOTE: While it is still possible to use the old +@@ -181,6 +182,9 @@ + + Default: Use the IP address of the IPA LDAP connection + ++ ++ Example: dyndns_iface = em1, vnet1, vnet2 ++ + + + +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 -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 ---- - 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 +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 * implies that ++ IPs from all interfaces should be used. + + +- 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 + + + 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. +- +- +- NOTE: This option currently supports multiple interfaces. ++ updates. Special value * implies that ++ IPs from all interfaces should be used. + + + NOTE: While it is still possible to use the old +@@ -180,7 +178,8 @@ + in their config file. + + +- 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 + + + 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 -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 ---- - 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 -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 ---- - 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 +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 +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 -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 ---- - 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 @@ - - - Specifies acceptable cipher suites. Typically this -- is a colon sperated list. See -+ is a colon sperated list. See - ldap.conf - 5 for format. - -@@ -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. - - - expire: use -@@ -2491,6 +2494,27 @@ ldap_access_filter = (employeeType=admin) - - - -+ -+ LDAP ACCESS FILTER EXAMPLE -+ -+ The following example assumes that SSSD is correctly -+ configured and to use the ldap_access_order=lockout. -+ -+ -+ -+ [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 -+ -+ -+ - - - NOTES --- -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 -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 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Pavel Reichl ---- - 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. - - -+ The wildcard (*) can be used to allow any shell. -+ -+ -+ The (*) is useful if you want to use -+ shell_fallback in case that user's shell is not -+ in /etc/shells and maintaining list -+ of all allowed shells in allowed_shells would be -+ to much overhead. -+ -+ - An empty string for shell is passed as-is to libc. - - -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?= +Date: Mon, 27 Jul 2015 17:24:45 +0200 +Subject: [PATCH 20/23] VIEWS TEST: add null-check + +Reviewed-by: Jakub Hrozek +--- + 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 -Date: Tue, 21 Oct 2014 16:18:02 +0200 -Subject: [PATCH 21/22] GPO: Terminate request on error - -Reviewed-by: Pavel Reichl ---- - 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?= +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 +--- + 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?= +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 +--- + 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 ++ ++ 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 . ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#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 ++ ++ 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 . ++*/ ++ ++#ifndef _SSS_TOOLS_H_ ++#define _SSS_TOOLS_H_ ++ ++#include ++#include ++ ++#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 -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 ---- - 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?= +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 +--- + 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 @@ ++ ++ ++ ++SSSD Manual pages ++ ++ ++ ++ ++ sss_override ++ 8 ++ ++ ++ ++ sss_override ++ create local overrides of user and group attributes ++ ++ ++ ++ ++ sss_override ++ COMMAND ++ ++ options ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ sss_override 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. ++ ++ ++ Overrides data are stored in SSSD cache. If the cache is deleted ++ all local overrides are lost. ++ ++ ++ ++ ++ AVAILABLE COMMANDS ++ ++ Argument NAME is the name of original object ++ in all commands. It is not possible to override ++ uid or gid to 0. ++ ++ ++ ++ ++ ++ NAME ++ NAME ++ UID ++ GID ++ HOME ++ SHELL ++ GECOS ++ ++ ++ ++ Override attributes of an user. ++ ++ ++ ++ ++ ++ ++ NAME ++ ++ ++ ++ Remove user overrides. ++ ++ ++ ++ ++ ++ ++ NAME ++ NAME ++ GID ++ ++ ++ ++ Override attributes of a group. ++ ++ ++ ++ ++ ++ ++ NAME ++ ++ ++ ++ Remove group overrides. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +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 ++ ++ 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 . ++*/ ++ ++#include ++ ++#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 -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 -Reviewed-by: Simo Sorce -(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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+#include -+ -+#include -+#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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+#include -+ -+#include -+#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 - #include - #include -+#include -+#include - - #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 - #include - #include -+#include - #include - #include - #include -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 -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 -Reviewed-by: Simo Sorce -(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 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 +Date: Wed, 22 Jul 2015 15:17:57 +0200 +Subject: [PATCH 24/27] IPA: Better debugging + +Reviewed-by: Alexander Bokovoy +--- + 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 -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 -Reviewed-by: Simo Sorce -(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 +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 +--- + 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 +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 +--- + 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 -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 -Reviewed-by: Simo Sorce -(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 @@ - - - -+ user (string) -+ -+ -+ The user to drop the privileges to where -+ appropriate to avoid running as the -+ root user. -+ -+ -+ Default: not set, process will run as root -+ -+ -+ -+ - default_domain_suffix (string) - - -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 -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 -Reviewed-by: Simo Sorce -(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 +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 +--- + 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 -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 -Reviewed-by: Simo Sorce -(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 +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 +--- + 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 -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 -Reviewed-by: Simo Sorce -(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 +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 +--- + 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 -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 -Reviewed-by: Simo Sorce -(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 +Date: Mon, 22 Jun 2015 16:36:36 +0200 +Subject: [PATCH 30/37] utils: add NSS version of cert utils + +Reviewed-by: Jakub Hrozek +--- + 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 ++#ifdef HAVE_LIBCRYPTO + #include ++#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 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 . ++*/ ++ ++#include "util/util.h" ++ ++#include ++#include ++ ++#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 +Date: Fri, 10 Jul 2015 12:10:53 +0200 +Subject: [PATCH 31/37] Add NSS version of p11_child + +Reviewed-by: Jakub Hrozek +--- + 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 ++ ++ 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 . ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "util/util.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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, ¶meters, 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 -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 -Reviewed-by: Simo Sorce -(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 -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 -Reviewed-by: Simo Sorce -(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 +Date: Fri, 26 Jun 2015 14:45:21 +0200 +Subject: [PATCH 32/37] pack_message_v3: allow empty name + +Reviewed-by: Jakub Hrozek +--- + 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 +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 +--- + 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 -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 -Reviewed-by: Simo Sorce -(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 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 . ++*/ ++ ++#include ++ ++#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 -Date: Fri, 17 Oct 2014 16:44:05 +0200 -Subject: [PATCH 34/46] TEST: Unit test for create_pipe_fd - -Reviewed-by: Pavel Reichl -Reviewed-by: Simo Sorce -(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 - #include - #include -+#include - - #include - #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 +Date: Fri, 3 Jul 2015 14:05:11 +0200 +Subject: [PATCH 35/37] pam_sss: add sc support + +Reviewed-by: Jakub Hrozek +--- + 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 -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 -Reviewed-by: Simo Sorce -(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 -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 -Reviewed-by: Simo Sorce -(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 +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 +--- + 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. + + + ++ ++ ca_db (string) ++ ++ ++ Path to a storage of trusted CA certificates. The ++ option is used to validate user certificates before ++ deriving public ssh keys from them. ++ ++ ++ Default: /etc/pki/nssdb ++ ++ ++ + + + +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 . + */ ++#include "config.h" + + #include + #ifdef HAVE_LIBCRYPTO + #include ++#include + #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 + #include + #include ++#include ++#include + ++#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, ¶meters, ++ 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 +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 +--- + 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 -Date: Thu, 9 Oct 2014 17:25:34 +0200 -Subject: [PATCH 37/46] PAM: Run pam responder as nonroot - -Reviewed-by: Pavel Reichl -Reviewed-by: Simo Sorce -(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 -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 -Reviewed-by: Simo Sorce -(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 +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 +(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 -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 -Reviewed-by: Simo Sorce -(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 +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 +(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 -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 -Reviewed-by: Simo Sorce -(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 +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 +(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 -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 -Reviewed-by: Simo Sorce -(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 +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 +(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 -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 -(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 +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 +(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 ++# ++# 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 . ++# ++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 -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 -(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 +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 +(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 ++# ++# 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 . ++# ++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 +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 +(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 -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 -(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 -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 -(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 +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 +(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 -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 -(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 +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 +--- + 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 -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 -(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 +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 +--- + 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 +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 +Reviewed-by: Jakub Hrozek +--- + 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 + #include + #include ++#include + + #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 -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 -(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 +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 +Reviewed-by: Jakub Hrozek +--- + 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 -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 ---- - 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 -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 ---- - 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 +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 +Reviewed-by: Jakub Hrozek +--- + 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 -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 ---- - 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 +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 +--- + 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 + #include ++#include + + #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 -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 ---- - 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?= +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 +--- + 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 -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 ---- - 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?= +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 +--- + 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?= -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 ---- - 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 +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 +--- + 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 -Date: Mon, 27 Oct 2014 16:53:44 +0100 -Subject: [PATCH 55/64] Add add_strings_lists() utility function - -Reviewed-by: Jakub Hrozek ---- - 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 +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 +--- + 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. + + +- Default: no set in the general case, userCertificate ++ Default: no set in the general case, userCertificate;binary + for IPA + + +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 -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 ---- - 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 +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 +--- + 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 -Date: Tue, 28 Oct 2014 19:40:02 +0100 -Subject: [PATCH 57/64] Add parse_attr_list_ex() helper function - -Reviewed-by: Jakub Hrozek ---- - 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 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 . -+*/ -+ -+#include -+ -+#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 +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 +--- + 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 -Date: Tue, 28 Oct 2014 19:42:47 +0100 -Subject: [PATCH 58/64] nss: parse user_attributes option - -Reviewed-by: Jakub Hrozek ---- - 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 - - - -+ -+ user_attributes (string) -+ -+ -+ 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 user_attributes option of -+ the InfoPipe responder (see -+ -+ sssd-ifp -+ 5 -+ -+ for details) but with no default values. -+ -+ -+ To make configuration more easy the NSS responder -+ will check the InfoPipe option if it is not set for -+ the NSS responder. -+ -+ -+ Default: not set, fallback to InfoPipe option -+ -+ -+ - - - -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 +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 +--- + 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 -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 ---- - 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?= +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 +--- + 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 +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 -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 ---- - 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?= +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 +--- + 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 -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 ---- - 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 -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 ---- - 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 @@ - - ldap_user_shell - -+ -+ ldap_user_ssh_public_key -+ - - - -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?= +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 +--- + 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 -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 ---- - 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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#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?= +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 +--- + 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 ++ ++ 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 . ++*/ ++ ++#include ++ ++#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 ++ ++ 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 . ++*/ ++ ++#ifndef _SSS_COLONDB_H_ ++#define _SSS_COLONDB_H_ ++ ++#include ++#include ++#include ++#include ++ ++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 -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 ---- - 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?= +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 +--- + 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 -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 ---- - 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?= +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 +--- + 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 @@ + + + ++ ++ FILE ++ ++ ++ ++ Import user overrides from FILE. ++ Data format is similar to standard passwd file. ++ The format is: ++ ++ ++ original_name:name:uid:gid:gecos:home:shell ++ ++ ++ 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. ++ ++ ++ Examples: ++ ++ ++ ckent:superman:::::: ++ ++ ++ ckent@krypton.com::501:501:Superman:/home/earth:/bin/bash ++ ++ ++ ++ ++ ++ ++ FILE ++ ++ ++ ++ Export all overridden attributes and store them in ++ FILE. See ++ user-import for data format. ++ ++ ++ ++ ++ + + NAME + NAME +@@ -99,6 +143,50 @@ + + + ++ ++ ++ ++ FILE ++ ++ ++ ++ Import group overrides from FILE. ++ Data format is similar to standard group file. ++ The format is: ++ ++ ++ original_name:name:gid ++ ++ ++ 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. ++ ++ ++ Examples: ++ ++ ++ admins:administrators: ++ ++ ++ Domain Users:Users:501 ++ ++ ++ ++ ++ ++ ++ FILE ++ ++ ++ ++ Export all overridden attributes and store them in ++ FILE. See ++ group-import for data format. ++ ++ ++ + + + +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 -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 ---- - 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 +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 +--- + 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 -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 ---- - 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?= +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 +--- + 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 @@ + + + ++ ++ COMMON OPTIONS ++ ++ Those options are available with all commands. ++ ++ ++ ++ ++ , ++ LEVEL ++ ++ ++ ++ ++ ++ + + + +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 -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 ---- - 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 +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 +--- + 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[^@]+)@?(?P[^@]*$)"); + 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 +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 +--- + 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 -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 ---- - 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 -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 ---- - 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?= +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 +--- + 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 -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 ---- - 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 - - #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 - -+/* 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 -+ -+ 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 . -+*/ -+ -+ -+#include -+#include -+#include -+#include -+ -+#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?= +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 +--- + 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 -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 ---- - 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?= +Date: Thu, 17 Sep 2015 11:35:56 +0200 +Subject: [PATCH 72/73] views: fix two typos in debug messages + +Reviewed-by: Sumit Bose +--- + 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 -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 ---- - 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?= +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 +--- + 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 -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 ---- - 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 +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 +--- + 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 +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 +--- + 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 . ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 -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 ---- - 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 -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 ---- - 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 @@ - - - -+ ldap_user_uuid (string) -+ -+ -+ The LDAP attribute that contains the UUID/GUID of -+ an LDAP user object. -+ -+ -+ Default: nsUniqueId -+ -+ -+ -+ -+ - ldap_user_objectsid (string) - - -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 +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 +(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 +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 +(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 -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 ---- - 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 @@ - - - -+ ldap_group_uuid (string) -+ -+ -+ The LDAP attribute that contains the UUID/GUID of -+ an LDAP group object. -+ -+ -+ Default: nsUniqueId -+ -+ -+ -+ -+ - ldap_group_objectsid (string) - - -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 -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 ---- - 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. - - -- Default: nsUniqueId -+ Default: not set in the general case, objectGUID for -+ AD and ipaUniqueID for IPA - - - -@@ -866,7 +867,8 @@ - an LDAP group object. - - -- Default: nsUniqueId -+ Default: not set in the general case, objectGUID for -+ AD and ipaUniqueID for IPA - - - -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 +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 +(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 +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 +(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 -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 ---- - 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. - - -- Default: ipaNTSecurityIdentifier for IPA, objectSID -+ Default: objectSid for ActiveDirectory, not set - for other servers. - - -@@ -882,7 +882,7 @@ - necessary for ActiveDirectory servers. - - -- Default: ipaNTSecurityIdentifier for IPA, objectSID -+ Default: objectSid for ActiveDirectory, not set - for other servers. - - -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 +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 +(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 -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 ---- - 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. - - -- Default: True -+ Default: True for AD and IPA otherwise False. - - - -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 +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 +(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 -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 -Reviewed-by: Jakub Hrozek ---- - 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 -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 -Reviewed-by: Jakub Hrozek ---- - 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?= +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 +(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 @@ + + + +- , ++ + LEVEL + + +-- +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 -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 -Reviewed-by: Lukáš Slebodník ---- - 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 +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 +(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 +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 +(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 + + + ++ ++ dyndns_server (string) ++ ++ ++ The DNS server to use when performing a DNS ++ update. In most setups, it's recommended to leave ++ this option unset. ++ ++ ++ Setting this option makes sense for environments ++ where the DNS server is different from the identity ++ server. ++ ++ ++ Default: None (let nsupdate choose the server) ++ ++ ++ ++ ++ + + + +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 @@ + + + ++ dyndns_server (string) ++ ++ ++ The DNS server to use when performing a DNS ++ update. In most setups, it's recommended to leave ++ this option unset. ++ ++ ++ Setting this option makes sense for environments ++ where the DNS server is different from the identity ++ server. ++ ++ ++ Default: None (let nsupdate choose the server) ++ ++ ++ ++ ++ + ipa_hbac_search_base (string) + + +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 -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 -Reviewed-by: Lukáš Slebodník ---- - 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 +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 +(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. + + ++ Please note that this option will be only used in ++ fallback attempt when previous attempt using ++ autodetected settings failed. ++ ++ + Default: None (let nsupdate choose the server) + + + + +- + + + +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. + + ++ Please note that this option will be only used in ++ fallback attempt when previous attempt using ++ autodetected settings failed. ++ ++ + Default: None (let nsupdate choose the server) + + +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 -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 -Reviewed-by: Lukáš Slebodník ---- - 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 -+ Jakub Hrozek - -- 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 . - */ --#include --#include --#include - --#include "providers/krb5/krb5_utils.h" --#include "providers/krb5/krb5_auth.h" --#include "src/util/find_uid.h" -+#ifdef HAVE_KRB5_KRB5_H -+#include -+#else -+#include -+#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 -+ Jakub Hrozek - -- 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 . - */ - --#ifndef __KRB5_UTILS_H__ --#define __KRB5_UTILS_H__ -+#ifndef __KRB5_CCACHE_H__ -+#define __KRB5_CCACHE_H__ - --#include --#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 - - #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 - - #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 +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 +(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 -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 -Reviewed-by: Lukáš Slebodník ---- - 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 +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 +(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 -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 -Reviewed-by: Lukáš Slebodník ---- - 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 +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 +(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 -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 -Reviewed-by: Lukáš Slebodník ---- - 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 -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 ---- - 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 +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 +(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 -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 ---- - 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 +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 +(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 -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 ---- - 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 +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 +(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 -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 ---- - 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 +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 +(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?= +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 +(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 -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 +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 +(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 -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 -Reviewed-by: Lukáš Slebodník ---- - 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) - ldap_group_search_base (string) - - -- -+ -+ -+ -+ -+ If the option ldap_use_tokengroups 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. -+ -+ - - ldap_sudo_search_base (string) - --- -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 +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 +(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 -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 ---- - 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 +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 +(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 -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 ---- - 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 -+ -+ 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 . -+*/ -+ -+#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 - - #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 +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 +(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 -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 ---- - 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 -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 ---- - 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 +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 +(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 +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 +(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 -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 ---- - 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 +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 +(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 -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 ---- - 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 +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 +(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 -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 ---- - 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 -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 ---- - 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?= +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 +Reviewed-by: Jakub Hrozek +(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 -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 - - - 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. - - - --- -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?= +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 +Reviewed-by: Jakub Hrozek +(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 -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 ---- - 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 @@ - debug_timestamps (bool) - - -- 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. - - - Default: true -@@ -84,7 +86,9 @@ - debug_microseconds (bool) - - -- 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. - - - 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?= +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 +Reviewed-by: Jakub Hrozek +(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 -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 ---- - 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 -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 ---- - 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 - #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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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) - - - -+ -+ -+ krb5_confd_path (string) -+ -+ -+ Absolute path of a directory where SSSD should place -+ Kerberos configuration snippets. -+ -+ -+ To disable the creation of the configuration -+ snippets set the parameter to 'none'. -+ -+ -+ Default: not set (krb5.include.d subdirectory of -+ SSSD's pubconf directory) -+ -+ -+ - - - -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 @@ - - - -+ krb5_confd_path (string) -+ -+ -+ Absolute path of a directory where SSSD should place -+ Kerberos configuration snippets. -+ -+ -+ To disable the creation of the configuration -+ snippets set the parameter to 'none'. -+ -+ -+ Default: not set (krb5.include.d subdirectory of -+ SSSD's pubconf directory) -+ -+ -+ -+ -+ - ipa_hbac_refresh (integer) - - -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 . - */ - -+#define _GNU_SOURCE -+#include - #include - - #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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 -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 -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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -Date: Fri, 28 Nov 2014 18:16:33 +0100 -Subject: [PATCH 121/128] test: avoid leaks in leak tests - -Reviewed-by: Jakub Hrozek ---- - 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 -Date: Mon, 17 Nov 2014 17:39:38 +0100 -Subject: [PATCH 122/128] krb5: add copy_ccache_into_memory() - -Reviewed-by: Jakub Hrozek ---- - 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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+ -+#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 -Date: Mon, 17 Nov 2014 17:40:26 +0100 -Subject: [PATCH 123/128] krb5: add copy_keytab_into_memory() - -Reviewed-by: Jakub Hrozek ---- - 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 -+ -+ 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 . -+*/ -+ -+#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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+ -+#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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+#include -+#include -+ -+#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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+#include -+#include -+ -+#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 -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 ---- - 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 -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 ---- - 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 -Date: Fri, 28 Nov 2014 19:56:27 +0100 -Subject: [PATCH 129/130] KRB5: Relax DEBUG message - -Reviewed-by: Sumit Bose ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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. - -- -- 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. -- - - - --- -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 -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 ---- - 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 -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 ---- - 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 -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. - - -+ Note: Using the Group Policy Management Editor this -+ value InteractiveLogonRight is called "Allow log on -+ locally" and "Deny log on locally". -+ -+ - It is possible to add another PAM service name - to the default set by using +service_name - 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. - - -+ 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". -+ -+ - It is possible to add another PAM service name - to the default set by using +service_name - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 -Reviewed-by: Sumit Bose ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 ---- - 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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -Date: Mon, 12 Jan 2015 18:36:42 +0100 -Subject: [PATCH 159/160] sysdb: fix group members with overridden names - -Reviewed-by: Jakub Hrozek -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -Date: Fri, 5 Dec 2014 11:12:42 +0100 -Subject: [PATCH 166/167] IPA: resolve missing members - -Reviewed-by: Jakub Hrozek -(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 -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 -(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 -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 -(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 -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 -Reviewed-by: Jakub Hrozek - -(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 -Date: Tue, 20 Jan 2015 12:48:19 +0100 -Subject: [PATCH 170/172] nss: make fill_orig() multi-value aware - -Reviewed-by: Jakub Hrozek -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 ---- - 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 -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 ---- - 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 -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 -(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 -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 ---- - 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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -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 -Reviewed-by: Sumit Bose -(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 -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 -Reviewed-by: Pavel Reichl -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -Date: Thu, 19 Mar 2015 14:26:26 +0100 -Subject: [PATCH 195/196] IPA: make sure output variable is set - -Reviewed-by: Pavel Reichl -(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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 -+ -+ 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 . -+*/ -+ -+#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 -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 -(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 -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 ---- - 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 '' ... -+ * -+ * (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 -+ -+ 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 . -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#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 -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 -(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 -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 -(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 @@ - - - -- -+ -+ subdomain_inherit (string) -+ -+ -+ Specifies a list of configuration parameters that -+ should be inherited by a subdomain. Please note -+ that only selected parameters can be inherited. -+ -+ -+ Example: -+ -+subdomain_inherit = ldap_purge_cache_timeout -+ -+ -+ -+ Default: none -+ -+ -+ - - - --- -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 -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 -(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 -Date: Fri, 22 May 2015 18:31:42 +0200 -Subject: [PATCH 205/207] SDAP: Add sdap_copy_map_entry - -Reviewed-by: Pavel Reichl -(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 -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 -(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: -+ -+ -+ ignore_group_members - - - 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 -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 -(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 - - -+ ldap_purge_cache_timeout -+ -+ -+ ldap_use_tokengroups -+ -+ -+ ldap_user_principal -+ -+ - Example: - - 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?= -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 -(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 -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 -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 ---- - 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 -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 -(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 -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 -(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 -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 -(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 -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 -(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 +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 - 1.12.2-58.18 -- Resolves: rhbz#1268205 - SSSD intermittently fails to resolve external - IPA group membership. +* Wed Oct 14 2015 Jakub Hrozek - 1.13.0-40 +- Resolves: rhbz#1270827 - local overrides: don't contact server with + overridden name/id -* Thu Sep 3 2015 Jakub Hrozek - 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 - 1.13.0-39 +- Resolves: rhbz#1267837 - sssd_be crashed in ipa_srv_ad_acct_lookup_step + +* Wed Oct 7 2015 Jakub Hrozek - 1.13.0-38 +- Resolves: rhbz#1267176 - Memory leak / possible DoS with krb auth. + +* Wed Oct 7 2015 Jakub Hrozek - 1.13.0-37 +- Resolves: rhbz#1267836 - PAM responder crashed if user was not set + +* Wed Sep 30 2015 Jakub Hrozek - 1.13.0-36 +- Resolves: rhbz#1266107 - AD: Conditional jump or move depends on + uninitialised value + +* Wed Sep 23 2015 Jakub Hrozek - 1.13.0-35 +- Resolves: rhbz#1250135 - Detect re-established trusts in the IPA + subdomain code + +* Tue Sep 22 2015 Jakub Hrozek - 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 - 1.13.0-33 +- Resolves: rhbz#1261155 - nsupdate exits on first GSSAPI error instead + of processing other commands + +* Tue Sep 22 2015 Jakub Hrozek - 1.13.0-32 +- Resolves: rhbz#1263735 - Could not resolve AD user from root domain + +* Tue Sep 22 2015 Jakub Hrozek - 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 - 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 - 1.13.0-29 +- Resolves: rhbz#1263587 - sss_override --name doesn't work with RFC2307 + and ghost users + +* Fri Sep 18 2015 Jakub Hrozek - 1.13.0-28 +- Resolves: rhbz#1259512 - sss_override : The local override user is not found + +* Fri Sep 18 2015 Jakub Hrozek - 1.13.0-27 +- Resolves: rhbz#1260027 - sssd_be memory leak with sssd-ad in GPO code + +* Tue Sep 1 2015 Jakub Hrozek - 1.13.0-26 +- Resolves: rhbz#1256398 - sssd cannot resolve user names containing + backslash with ldap provider -* Thu Aug 20 2015 Jakub Hrozek - 1.12.2-58.16 -- Resolves: rhbz#1255443 - Add index for 'objectSIDString' and maybe to +* Tue Aug 25 2015 Martin Kosek - 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 - 1.13.0-24 +- Resolves: rhbz#1254518 - Fix crash in nss responder + +* Thu Aug 20 2015 Jakub Hrozek - 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 - 1.13.0-22 +- Resolves: rhbz#1244950 - Add index for 'objectSIDString' and maybe to other cache attributes -* Thu Aug 20 2015 Jakub Hrozek - 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 - 1.13.0-21 +- Resolves: rhbz#1250415 - sssd: p11_child hardening + +* Mon Aug 17 2015 Jakub Hrozek - 1.13.0-20 +- Related: rhbz#1250135 - Detect re-established trusts in the IPA + subdomain code + +* Mon Aug 17 2015 Jakub Hrozek - 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 - 1.13.0-18 +- Resolves: rhbz#1232950 - [IPA/IdM] sudoOrder not honored as expected -* Mon Jul 20 2015 Jakub Hrozek - 1.12.2-58.14 -- Resolves: rhbz#1244761 - Relax the libldb requirements to unblock - RH Storage +* Mon Aug 17 2015 Jakub Hrozek - 1.13.0-17 +- Fix wildcard_limit=0 +- Resolves: rhbz#1206571 - [RFE] Expose D-BUS interface -* Thu Jun 18 2015 Jakub Hrozek - 1.12.2-58.13 -- Resolves: rhbz#1232130 - sysdb sudo search doesn't escape special characters +* Mon Aug 17 2015 Jakub Hrozek - 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 - 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 - 1.13.0-15 +- Resolves: rhbz#1249015 - KDC proxy not working with SSSD krb5_use_kdcinfo + enabled -* Thu May 28 2015 Jakub Hrozek - 1.12.2-58.9 -- Resolves: rhbz#1227772 - Properly handle AD's binary objectGUID +* Thu Aug 6 2015 Jakub Hrozek - 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 - 1.12.2-58.8 +* Thu Aug 6 2015 Lukas Slebodnik - 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 - 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 - 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 - 1.13.0-10 +- Resolves: rhbz#1244949 - getgrgid for user's UID on a trust client + prevents getpw* + +* Tue Aug 4 2015 Jakub Hrozek - 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 - 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 - 1.13.0-7 +- Resolves: rhbz#1183747 - [FEAT] UID and GID mapping on individual clients + +* Fri Jul 24 2015 Jakub Hrozek - 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 - 1.13.0-5 +- Resolves: rhbz#1242942 - well-known SID check is broken for NetBIOS prefixes + +* Fri Jul 17 2015 Jakub Hrozek - 1.13.0-4 +- Resolves: rhbz#1234722 - sssd ad provider fails to start in rhel7.2 + +* Thu Jul 16 2015 Jakub Hrozek - 1.13.0-3 +- Add support for InfoPipe wildcard requests +- Resolves: rhbz#1206571 - [RFE] Expose D-BUS interface + +* Mon Jul 6 2015 Jakub Hrozek - 1.13.0-2 +- Also package the initgr memcache +- Related: rhbz#1205554 - Rebase SSSD to 1.13.x + +* Mon Jul 6 2015 Jakub Hrozek - 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 - 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 - 1.13.0.2alpha +- Related: rhbz#1205554 - Rebase SSSD to 1.13.x +- GPO default should be permissve + +* Mon Jun 22 2015 Jakub Hrozek - 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 - 1.12.2-61 +- Resolves: rhbz#1226119 - Properly handle AD's binary objectGUID + +* Wed Apr 22 2015 Jakub Hrozek - 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 - 1.12.2-58.7 -- Resolves: rhbz#1214286 - SSSD downloads too much information when fetching +* Wed Apr 22 2015 Jakub Hrozek - 1.12.2-59 +- Resolves: rhbz#1201840 - SSSD downloads too much information when fetching information about groups * Thu Mar 19 2015 Jakub Hrozek - 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 - 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 - 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 - 1.12.2-58.3