From 905b4de0e68274ed1d28be199df37121524b2919 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mar 05 2015 13:22:13 +0000 Subject: import sssd-1.12.2-58.el7 --- diff --git a/.gitignore b/.gitignore index c3932a8..5032c1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/sssd-1.11.2.tar.gz +SOURCES/sssd-1.12.2.tar.gz diff --git a/.sssd.metadata b/.sssd.metadata index dc0ee00..1ccf4e7 100644 --- a/.sssd.metadata +++ b/.sssd.metadata @@ -1 +1 @@ -c1a747f6b8cb5fd37bec8e759eb5ef033b067973 SOURCES/sssd-1.11.2.tar.gz +c7969eeb880fdd79cead88504c313fa042ca524a SOURCES/sssd-1.12.2.tar.gz diff --git a/SOURCES/0001-SYSDB-Skip-malformed-netgroup-attribute.patch b/SOURCES/0001-SYSDB-Skip-malformed-netgroup-attribute.patch deleted file mode 100644 index a240448..0000000 --- a/SOURCES/0001-SYSDB-Skip-malformed-netgroup-attribute.patch +++ /dev/null @@ -1,36 +0,0 @@ -From d0eeff900d721a0e147b3513d075dbb64b002dc1 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 12 Nov 2013 14:39:27 +0100 -Subject: [PATCH 1/6] SYSDB: Skip malformed netgroup attribute. - -It was not easy find out why netgroup could not be covert into result entries. -Problem was that nisNetgroupTriple contained unexpected string "(,user01)" -This patch will ignore only malformed attribute and processing of netgroup -will not fail. - -Resolves: -https://fedorahosted.org/sssd/ticket/2137 ---- - src/db/sysdb_search.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c -index 8dfaf1f2ada22db5e70ebe18bee1ee299e4767dd..d15fc73ce2272bff53650ae9dd0dbdad99a849e6 100644 ---- a/src/db/sysdb_search.c -+++ b/src/db/sysdb_search.c -@@ -728,7 +728,11 @@ errno_t sysdb_netgr_to_entries(TALLOC_CTX *mem_ctx, - &tmp_entry[c]->value.triple.username, - &tmp_entry[c]->value.triple.domainname); - if (ret != EOK) { -- goto done; -+ DEBUG(SSSDBG_IMPORTANT_INFO, -+ ("Cannot split netgroup triple [%s], " -+ "this attribute will be skipped \n", -+ triple_str)); -+ continue; - } - - c++; --- -1.8.4.2 - 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 new file mode 100644 index 0000000..f87ee45 --- /dev/null +++ b/SOURCES/0001-util-Move-semanage-related-functions-to-src-util.patch @@ -0,0 +1,590 @@ +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-monitor-Specific-error-message-for-missing-sssd.conf.patch b/SOURCES/0002-monitor-Specific-error-message-for-missing-sssd.conf.patch deleted file mode 100644 index ea4a22b..0000000 --- a/SOURCES/0002-monitor-Specific-error-message-for-missing-sssd.conf.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 08134dde5a6c8b23cf40ec8f0020cd553af2667e Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Tue, 19 Nov 2013 11:24:31 +0000 -Subject: [PATCH 2/6] monitor: Specific error message for missing sssd.conf - -Specific error message is logged for missing sssd.conf file. New sssd specific -error value is introduced for this case. - -Resolves: -https://fedorahosted.org/sssd/ticket/2156 ---- - src/confdb/confdb_setup.c | 9 +++++++-- - src/monitor/monitor.c | 8 +++++++- - src/util/util_errors.c | 1 + - src/util/util_errors.h | 1 + - 4 files changed, 16 insertions(+), 3 deletions(-) - -diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c -index b13553eaa560bb83ecf7a53b32ab116f38f7f480..2a34e4f7a3e5f9aa37760036520f5274e9289b70 100644 ---- a/src/confdb/confdb_setup.c -+++ b/src/confdb/confdb_setup.c -@@ -155,8 +155,13 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb) - /* Open config file */ - ret = sss_ini_config_file_open(init_data, config_file); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to open configuration file.\n")); -- ret = EIO; -+ DEBUG(SSSDBG_TRACE_FUNC, -+ ("sss_ini_config_file_open failed: %s [%d]\n", strerror(ret), -+ ret)); -+ if (ret == ENOENT) { -+ /* sss specific error denoting missing configuration file */ -+ ret = ERR_MISSING_CONF; -+ } - goto done; - } - -diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c -index 3d8ba26285b6a8fc60ccb695f8b10ae1714ac918..09f530d2643b45fc31fb4dbe3cb69f2abc5510af 100644 ---- a/src/monitor/monitor.c -+++ b/src/monitor/monitor.c -@@ -1614,7 +1614,7 @@ static errno_t load_configuration(TALLOC_CTX *mem_ctx, - ret = confdb_init_db(config_file, ctx->cdb); - if (ret != EOK) { - DEBUG(0, ("ConfDB initialization has failed [%s]\n", -- strerror(ret))); -+ sss_strerror(ret))); - goto done; - } - -@@ -2789,6 +2789,12 @@ int main(int argc, const char *argv[]) - ret = load_configuration(tmp_ctx, config_file, &monitor); - if (ret != EOK) { - switch (ret) { -+ case ERR_MISSING_CONF: -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Configuration file: %s does not exist.\n", config_file)); -+ sss_log(SSS_LOG_ALERT, -+ "Configuration file: %s does not exist.\n", config_file); -+ break; - case EPERM: - case EACCES: - DEBUG(SSSDBG_CRIT_FAILURE, -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index b3d10f97b0567ca21ca08a3f2d326ea401c28aff..114c8b04fd354b166d14e526a3bab6a6c0c05951 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -50,6 +50,7 @@ struct err_string error_to_str[] = { - { "Dynamic DNS update not possible while offline" }, /* ERR_DYNDNS_OFFLINE */ - { "Entry not found" }, /* ERR_NOT_FOUND */ - { "Domain not found" }, /* ERR_DOMAIN_NOT_FOUND */ -+ { "Missing configuration file" }, /* ERR_MISSING_CONF */ - }; - - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 685607c5bb1b4e7c37152c876518a2b1c69c18d6..bca45f392b0357c3f1c848768358cb1d47514715 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -72,6 +72,7 @@ enum sssd_errors { - ERR_DYNDNS_OFFLINE, - ERR_NOT_FOUND, - ERR_DOMAIN_NOT_FOUND, -+ ERR_MISSING_CONF, - ERR_LAST /* ALWAYS LAST */ - }; - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..c6f920d --- /dev/null +++ b/SOURCES/0002-sss_semanage-Add-mlsrange-parameter-to-set_seuser.patch @@ -0,0 +1,153 @@ +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/0003-AD-Fix-a-typo-in-the-man-page.patch b/SOURCES/0003-AD-Fix-a-typo-in-the-man-page.patch deleted file mode 100644 index 9baeeb9..0000000 --- a/SOURCES/0003-AD-Fix-a-typo-in-the-man-page.patch +++ /dev/null @@ -1,26 +0,0 @@ -From ebb9c8acfb2423a2474cbbc52794d41975478dcf Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 18 Nov 2013 11:05:04 +0100 -Subject: [PATCH 3/6] AD: Fix a typo in the man page - -https://fedorahosted.org/sssd/ticket/2154 ---- - src/man/sssd-ad.5.xml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index 3dcf2c7390e89cacec202f49c559eccf03800450..e31f87a96a14907c64166e53da443ad735c6e85e 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -175,7 +175,7 @@ ldap_id_mapping = False - This option specifies LDAP access control - filter that the user must match in order - to be allowed access. Please note that the -- access_filter option must be -+ access_provider option must be - explicitly set to ad in order - for this option to have an effect. - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..83341fe --- /dev/null +++ b/SOURCES/0003-IPA-Use-set_seuser-instead-of-writing-selinux-login-.patch @@ -0,0 +1,277 @@ +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/0004-LDAP-Initialize-user-count-for-AD-matching-rule.patch b/SOURCES/0004-LDAP-Initialize-user-count-for-AD-matching-rule.patch deleted file mode 100644 index 10ffd1a..0000000 --- a/SOURCES/0004-LDAP-Initialize-user-count-for-AD-matching-rule.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 44d60762a2ffe45b2dadf05634eefb2af2e3ce14 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 18 Nov 2013 16:38:34 +0100 -Subject: [PATCH 4/6] LDAP: Initialize user count for AD matching rule - -https://fedorahosted.org/sssd/ticket/2157 - -If AD matching rule was selected, but the group was empty, the SSSD -accessed random data. Initializing count to zero prevents that. ---- - src/providers/ldap/sdap_async_groups.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 7a8f3e2a5c83c5b320497a76c363a90620315dcf..9f7e3e55d0234e9aa7b9e59456044587bcad88ef 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -1828,7 +1828,7 @@ static void sdap_ad_match_rule_members_process(struct tevent_req *subreq) - struct sysdb_attrs *group = state->groups[0]; - struct ldb_message_element *member_el; - struct ldb_message_element *orig_dn_el; -- size_t count; -+ size_t count = 0; - size_t i; - hash_table_t *ghosts; - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..31302d7 --- /dev/null +++ b/SOURCES/0004-SSSD-Add-the-options-to-specify-a-UID-and-GID-to-run.patch @@ -0,0 +1,366 @@ +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 new file mode 100644 index 0000000..f1f2b37 --- /dev/null +++ b/SOURCES/0005-SSSD-Chown-the-log-files.patch @@ -0,0 +1,93 @@ +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-SSSD-Improved-domain-detection.patch b/SOURCES/0005-SSSD-Improved-domain-detection.patch deleted file mode 100644 index 7ae4898..0000000 --- a/SOURCES/0005-SSSD-Improved-domain-detection.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 3cf1217a277d1103a8956e33fc0a8464227e2dd2 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 14 Nov 2013 21:34:51 +0000 -Subject: [PATCH 5/6] SSSD: Improved domain detection - -A bit more elegant way of detection of what domain the group member belongs to - -Resolves: -https://fedorahosted.org/sssd/ticket/2132 ---- - src/providers/ldap/ldap_common.c | 39 ++++++++++++++++++++++++++++----------- - src/util/sss_ldap.c | 28 +++++++++++++++++++++++----- - src/util/sss_ldap.h | 6 ++++++ - 3 files changed, 57 insertions(+), 16 deletions(-) - -diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c -index facf102edc792c75a563a276f3ea9f3acc3052b4..35ea81360b4ec61eca6b952cd86fc93a6eda17dc 100644 ---- a/src/providers/ldap/ldap_common.c -+++ b/src/providers/ldap/ldap_common.c -@@ -68,23 +68,40 @@ sdap_domain_get_by_dn(struct sdap_options *opts, - const char *dn) - { - struct sdap_domain *sditer = NULL; -- char *dc = NULL; -+ struct sdap_domain *sdmatch = NULL; -+ TALLOC_CTX *tmp_ctx = NULL; -+ int match_len; -+ int best_match_len = 0; - -- dc = strstr(dn, "dc="); -- if (dc == NULL) { -- dc = strstr(dn, "DC="); -- if (dc == NULL) { -- return NULL; -- } -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return NULL; - } - - DLIST_FOR_EACH(sditer, opts->sdom) { -- if (strcasecmp(sditer->basedn, dc) == 0) { -- return sditer; -+ if (sss_ldap_dn_in_search_bases_len(tmp_ctx, dn, sditer->search_bases, -+ NULL, &match_len) -+ || sss_ldap_dn_in_search_bases_len(tmp_ctx, dn, -+ sditer->user_search_bases, NULL, &match_len) -+ || sss_ldap_dn_in_search_bases_len(tmp_ctx, dn, -+ sditer->group_search_bases, NULL, &match_len) -+ || sss_ldap_dn_in_search_bases_len(tmp_ctx, dn, -+ sditer->netgroup_search_bases, NULL, &match_len) -+ || sss_ldap_dn_in_search_bases_len(tmp_ctx, dn, -+ sditer->sudo_search_bases, NULL, &match_len) -+ || sss_ldap_dn_in_search_bases_len(tmp_ctx, dn, -+ sditer->service_search_bases, NULL, &match_len) -+ || sss_ldap_dn_in_search_bases_len(tmp_ctx, dn, -+ sditer->autofs_search_bases, NULL, &match_len)) { -+ if (best_match_len < match_len) { -+ /*this is a longer match*/ -+ best_match_len = match_len; -+ sdmatch = sditer; -+ } - } - } -- -- return NULL; -+ talloc_free(tmp_ctx); -+ return sdmatch; - } - - errno_t -diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c -index 6d7b0907ca2fa48d9cff5257ab6bbba0ae7dd5c6..e1a05e8f60afb692ac95c99a443febac72a31187 100644 ---- a/src/util/sss_ldap.c -+++ b/src/util/sss_ldap.c -@@ -470,10 +470,13 @@ int sss_ldap_init_recv(struct tevent_req *req, LDAP **ldap, int *sd) - * _filter will contain combined filters from all possible search bases - * or NULL if it should be empty - */ --bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx, -- const char *dn, -- struct sdap_search_base **search_bases, -- char **_filter) -+ -+ -+bool sss_ldap_dn_in_search_bases_len(TALLOC_CTX *mem_ctx, -+ const char *dn, -+ struct sdap_search_base **search_bases, -+ char **_filter, -+ int *_match_len) - { - struct sdap_search_base *base; - int basedn_len, dn_len; -@@ -484,6 +487,7 @@ bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx, - bool backslash_found = false; - char *filter = NULL; - bool ret = false; -+ int match_len; - - if (dn == NULL) { - DEBUG(SSSDBG_FUNC_DATA, ("dn is NULL\n")); -@@ -511,6 +515,7 @@ bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx, - if (!base_confirmed) { - continue; - } -+ match_len = basedn_len; - - switch (base->scope) { - case LDAP_SCOPE_BASE: -@@ -558,6 +563,9 @@ bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx, - * Append filter otherwise. - */ - ret = true; -+ if (_match_len) { -+ *_match_len = match_len; -+ } - - if (base->filter == NULL || _filter == NULL) { - goto done; -@@ -575,7 +583,8 @@ bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx, - if (filter != NULL) { - *_filter = talloc_asprintf(mem_ctx, "(|%s)", filter); - if (*_filter == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf_append() failed\n")); -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("talloc_asprintf_append() failed\n")); - ret = false; - goto done; - } -@@ -589,6 +598,15 @@ done: - return ret; - } - -+bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx, -+ const char *dn, -+ struct sdap_search_base **search_bases, -+ char **_filter) -+{ -+ return sss_ldap_dn_in_search_bases_len(mem_ctx, dn, search_bases, _filter, -+ NULL); -+} -+ - char *sss_ldap_encode_ndr_uint32(TALLOC_CTX *mem_ctx, uint32_t flags) - { - char hex[9]; /* 4 bytes in hex + terminating zero */ -diff --git a/src/util/sss_ldap.h b/src/util/sss_ldap.h -index e5c30eb2115d422ef5a52cc5cd75c85be8fbe2d7..f298b2fbb30cf1532f8e94504ffb83ef73880b81 100644 ---- a/src/util/sss_ldap.h -+++ b/src/util/sss_ldap.h -@@ -74,6 +74,12 @@ bool sss_ldap_dn_in_search_bases(TALLOC_CTX *mem_ctx, - struct sdap_search_base **search_bases, - char **_filter); - -+bool sss_ldap_dn_in_search_bases_len(TALLOC_CTX *mem_ctx, -+ const char *dn, -+ struct sdap_search_base **search_bases, -+ char **_filter, -+ int *_match_len); -+ - char *sss_ldap_encode_ndr_uint32(TALLOC_CTX *mem_ctx, uint32_t flags); - - #endif /* __SSS_LDAP_H__ */ --- -1.8.4.2 - diff --git a/SOURCES/0006-SSSD-Unit-test-sss_ldap_dn_in_search_bases.patch b/SOURCES/0006-SSSD-Unit-test-sss_ldap_dn_in_search_bases.patch deleted file mode 100644 index e0555b3..0000000 --- a/SOURCES/0006-SSSD-Unit-test-sss_ldap_dn_in_search_bases.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 94c85df2d7ded82f2939d8fe29821e4c78ff000d Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 14 Nov 2013 21:52:26 +0000 -Subject: [PATCH 6/6] SSSD: Unit test - sss_ldap_dn_in_search_bases - -Unit test testing detection of the right domain when processing group with members from several domains - -Resolves: -https://fedorahosted.org/sssd/ticket/2132 ---- - Makefile.am | 27 ++++- - src/tests/cmocka/test_search_bases.c | 191 +++++++++++++++++++++++++++++++++++ - 2 files changed, 217 insertions(+), 1 deletion(-) - create mode 100644 src/tests/cmocka/test_search_bases.c - -diff --git a/Makefile.am b/Makefile.am -index 2ba1ec0fd94e3292f05de0139d607b3626b5c6f7..583ccdb499306268640bfb894f673c42945e19ff 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -151,7 +151,8 @@ if HAVE_CMOCKA - fqnames-tests \ - test_sss_idmap \ - test_utils \ -- ad_access_filter_tests -+ ad_access_filter_tests \ -+ test_search_bases - endif - - check_PROGRAMS = \ -@@ -1367,6 +1368,30 @@ test_utils_LDADD = \ - $(SSSD_INTERNAL_LTLIBS) \ - libsss_test_common.la - -+test_search_bases_SOURCES = \ -+ $(sssd_be_SOURCES) \ -+ src/util/sss_ldap.c \ -+ src/util/sss_krb5.c \ -+ src/util/find_uid.c \ -+ src/util/user_info_msg.c \ -+ src/tests/cmocka/test_search_bases.c -+test_search_bases_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ -DUNIT_TESTING -+test_search_bases_LDADD = \ -+ $(PAM_LIBS) \ -+ $(CMOCKA_LIBS) \ -+ $(POPT_LIBS) \ -+ $(SSSD_LIBS) \ -+ $(CARES_LIBS) \ -+ $(KRB5_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ $(SYSTEMD_LOGIN_LIBS) \ -+ libsss_ldap_common.la \ -+ libsss_idmap.la \ -+ libsss_krb5_common.la \ -+ libsss_test_common.la -+ - ad_access_filter_tests_SOURCES = \ - $(sssd_be_SOURCES) \ - src/util/sss_ldap.c \ -diff --git a/src/tests/cmocka/test_search_bases.c b/src/tests/cmocka/test_search_bases.c -new file mode 100644 -index 0000000000000000000000000000000000000000..e03ef3662685d92335bce4a7023e1ac7e64432c8 ---- /dev/null -+++ b/src/tests/cmocka/test_search_bases.c -@@ -0,0 +1,191 @@ -+/* -+ Authors: -+ Pavel Reichl -+ -+ Copyright (C) 2013 Red Hat -+ -+ SSSD tests - Search bases -+ -+ 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 -+#include -+#include -+ -+#include "util/find_uid.h" -+#include "util/sss_ldap.h" -+#include "tests/common.h" -+#include "providers/ldap/ldap_common.h" -+#include "providers/ldap/sdap.h" -+#include "dhash.h" -+#include "tests/common_check.h" -+ -+enum sss_test_get_by_dn { -+ DN_NOT_IN_DOMS, /* dn is not in any domain */ -+ DN_IN_DOM1, /* dn is in the domain based on dns */ -+ DN_IN_DOM2, /* dn is in the domain based on dns2 */ -+}; -+ -+static struct sdap_search_base** generate_bases(TALLOC_CTX *mem_ctx, -+ const char** dns, size_t n) -+{ -+ struct sdap_search_base **search_bases; -+ errno_t err; -+ int i; -+ -+ search_bases = talloc_array(mem_ctx, struct sdap_search_base *, n + 1); -+ assert_non_null(search_bases); -+ -+ for (i=0; i < n; ++i) { -+ err = sdap_create_search_base(mem_ctx, dns[i], LDAP_SCOPE_SUBTREE, -+ NULL, &search_bases[i]); -+ if (err != EOK) { -+ fprintf(stderr, "Failed to create search base\n"); -+ } -+ assert_int_equal(err, EOK); -+ } -+ search_bases[n] = NULL; -+ return search_bases; -+} -+ -+static bool do_test_search_bases(const char* dn, const char** dns, size_t n) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct sdap_search_base **search_bases; -+ bool ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ assert_non_null(tmp_ctx); -+ -+ search_bases = generate_bases(tmp_ctx, dns, n); -+ check_leaks_push(tmp_ctx); -+ ret = sss_ldap_dn_in_search_bases(tmp_ctx, dn, search_bases, NULL); -+ assert_true(check_leaks_pop(tmp_ctx) == true); -+ -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+void test_search_bases_fail(void **state) -+{ -+ const char *dn = "cn=user, dc=sub, dc=ad, dc=pb"; -+ const char *dns[] = {"dc=example, dc=com", "dc=subdom, dc=ad, dc=pb"}; -+ bool ret; -+ -+ ret = do_test_search_bases(dn, dns, 2); -+ assert_false(ret); -+} -+ -+void test_search_bases_success(void **state) -+{ -+ const char *dn = "cn=user, dc=sub, dc=ad, dc=pb"; -+ const char *dns[] = {"", "dc=ad, dc=pb", "dc=sub, dc=ad, dc=pb"}; -+ bool ret; -+ -+ ret = do_test_search_bases(dn, dns, 3); -+ assert_true(ret); -+} -+ -+static void do_test_get_by_dn(const char *dn, const char **dns, size_t n, -+ const char **dns2, size_t n2, int expected_result) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct sdap_options *opts; -+ struct sdap_domain *sdom; -+ struct sdap_domain *sdom2; -+ struct sdap_domain *res_sdom; -+ struct sdap_search_base **search_bases; -+ struct sdap_search_base **search_bases2; -+ tmp_ctx = talloc_new(NULL); -+ assert_non_null(tmp_ctx); -+ -+ search_bases = generate_bases(tmp_ctx, dns, n); -+ search_bases2 = generate_bases(tmp_ctx, dns2, n2); -+ sdom = talloc_zero(tmp_ctx, struct sdap_domain); -+ assert_non_null(sdom); -+ sdom2 = talloc_zero(tmp_ctx, struct sdap_domain); -+ assert_non_null(sdom2); -+ -+ sdom->search_bases = search_bases; -+ sdom->next = sdom2; -+ sdom->prev = NULL; -+ sdom2->search_bases = search_bases2; -+ sdom2->next = NULL; -+ sdom2->prev = sdom; -+ -+ opts = talloc(tmp_ctx, struct sdap_options); -+ assert_non_null(opts); -+ opts->sdom = sdom; -+ res_sdom = sdap_domain_get_by_dn(opts, dn); -+ -+ switch (expected_result) { -+ case DN_NOT_IN_DOMS: -+ assert_null(res_sdom); -+ break; -+ case DN_IN_DOM1: -+ assert_true(res_sdom == sdom); -+ break; -+ case DN_IN_DOM2: -+ assert_true(res_sdom == sdom2); -+ break; -+ } -+ -+ talloc_free(tmp_ctx); -+} -+ -+void test_get_by_dn(void **state) -+{ -+ const char *dn = "cn=user, dc=sub, dc=ad, dc=pb"; -+ const char *dns[] = {"dc=ad, dc=pb"}; -+ const char *dns2[] = {"dc=sub, dc=ad, dc=pb"}; -+ -+ do_test_get_by_dn(dn, dns, 1, dns2, 1, DN_IN_DOM2); -+} -+ -+void test_get_by_dn2(void **state) -+{ -+ const char *dn = "cn=user, dc=ad, dc=com"; -+ const char *dns[] = {"dc=ad, dc=com"}; -+ const char *dns2[] = {"dc=sub, dc=ad, dc=pb"}; -+ -+ do_test_get_by_dn(dn, dns, 1, dns2, 1, DN_IN_DOM1); -+} -+ -+void test_get_by_dn_fail(void **state) -+{ -+ const char *dn = "cn=user, dc=sub, dc=example, dc=com"; -+ const char *dns[] = {"dc=ad, dc=pb"}; -+ const char *dns2[] = {"dc=sub, dc=ad, dc=pb"}; -+ -+ do_test_get_by_dn(dn, dns, 1, dns2, 1, DN_NOT_IN_DOMS); -+} -+ -+int main(void) -+{ -+ const UnitTest tests[] = { -+ unit_test(test_search_bases_fail), -+ unit_test(test_search_bases_success), -+ unit_test(test_get_by_dn_fail), -+ unit_test(test_get_by_dn), -+ unit_test(test_get_by_dn2) -+ }; -+ -+ return run_tests(tests); -+} --- -1.8.4.2 - 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 new file mode 100644 index 0000000..23fb933 --- /dev/null +++ b/SOURCES/0006-UTIL-Use-a-custom-PID_PATH-and-DB_PATH-when-unit-tes.patch @@ -0,0 +1,80 @@ +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-TESTS-Unit-tests-can-use-confdb-without-using-sysdb.patch b/SOURCES/0007-TESTS-Unit-tests-can-use-confdb-without-using-sysdb.patch new file mode 100644 index 0000000..baf9afa --- /dev/null +++ b/SOURCES/0007-TESTS-Unit-tests-can-use-confdb-without-using-sysdb.patch @@ -0,0 +1,85 @@ +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/0007-do-not-use-default_domain_suffix-with-autofs.patch b/SOURCES/0007-do-not-use-default_domain_suffix-with-autofs.patch deleted file mode 100644 index d10d47d..0000000 --- a/SOURCES/0007-do-not-use-default_domain_suffix-with-autofs.patch +++ /dev/null @@ -1,25 +0,0 @@ -From b7c339c616e88c0e8db5c5a653dacdedf19a147a Mon Sep 17 00:00:00 2001 -From: Aron Parsons -Date: Wed, 6 Nov 2013 15:18:54 +0000 -Subject: [PATCH 7/7] do not use default_domain_suffix with autofs - ---- - src/responder/autofs/autofssrv_cmd.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/responder/autofs/autofssrv_cmd.c b/src/responder/autofs/autofssrv_cmd.c -index e9168ea8f85cbaf9e934b44838d17360024a2bc1..4c5bda01d4abd967e8cd8260904f34546b898d99 100644 ---- a/src/responder/autofs/autofssrv_cmd.c -+++ b/src/responder/autofs/autofssrv_cmd.c -@@ -435,7 +435,7 @@ setautomntent_send(TALLOC_CTX *mem_ctx, - state->dctx = dctx; - - ret = sss_parse_name_for_domains(state, client->rctx->domains, -- client->rctx->default_domain, rawname, -+ NULL, rawname, - &domname, &state->mapname); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, --- -1.8.4.2 - diff --git a/SOURCES/0008-SYSDB-Sanitize-filter-before-sysdb_search_groups.patch b/SOURCES/0008-SYSDB-Sanitize-filter-before-sysdb_search_groups.patch deleted file mode 100644 index c51c590..0000000 --- a/SOURCES/0008-SYSDB-Sanitize-filter-before-sysdb_search_groups.patch +++ /dev/null @@ -1,63 +0,0 @@ -From bd24c6f485ac1421053167eabd6e5e963829403b Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 25 Nov 2013 13:43:30 +0100 -Subject: [PATCH 8/9] SYSDB: Sanitize filter before sysdb_search_groups - -sysdb_delete_user fails with EIO if user does not exist and contains -backslashes. -ldb could not parse filter (&(objectclass=group)(ghost=usr\\\\001)), -because ghost value was not sanitized - -Resolves: -https://fedorahosted.org/sssd/ticket/2163 ---- - src/db/sysdb_ops.c | 9 ++++++++- - src/tests/sysdb-tests.c | 5 +++++ - 2 files changed, 13 insertions(+), 1 deletion(-) - -diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c -index 094c27b7f478e0a53a3b6666c727e86eb36a249e..eb88cd256d0c2e45e1528e8a867e42354215cc7f 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -2539,6 +2539,7 @@ int sysdb_delete_user(struct sysdb_ctx *sysdb, - struct ldb_message *msg; - int ret; - int i; -+ char *sanitized_name; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { -@@ -2578,7 +2579,13 @@ int sysdb_delete_user(struct sysdb_ctx *sysdb, - } - } else if (ret == ENOENT && name != NULL) { - /* Perhaps a ghost user? */ -- filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_GHOST, name); -+ ret = sss_filter_sanitize(tmp_ctx, name, &sanitized_name); -+ if (ret != EOK) { -+ goto fail; -+ } -+ -+ filter = talloc_asprintf(tmp_ctx, "(%s=%s)", -+ SYSDB_GHOST, sanitized_name); - if (filter == NULL) { - ret = ENOMEM; - goto fail; -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index 1c28526e06df012b8749e1540e70a27948c17ab2..bf964fd76d33bbceac6c1846db7a5011db1375f5 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -3998,6 +3998,11 @@ START_TEST(test_odd_characters) - fail_unless(ret == EOK, "sysdb_delete_user error [%d][%s]", - ret, strerror(ret)); - -+ /* Delete non existing User */ -+ ret = sysdb_delete_user(test_ctx->sysdb, test_ctx->domain, -+ odd_username, 10000); -+ fail_unless(ret == ENOENT, "sysdb_delete_user error [%d][%s]", -+ ret, strerror(ret)); - - /* Delete Group */ - ret = sysdb_delete_group(test_ctx->sysdb, test_ctx->domain, --- -1.8.4.2 - 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 new file mode 100644 index 0000000..f3bf0c4 --- /dev/null +++ b/SOURCES/0008-TESTS-Add-std-gnu99-to-cwrap-tests-CFLAGS.patch @@ -0,0 +1,33 @@ +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-SYSDB-Sanitize-filter-before-removing-ghost-attrs.patch b/SOURCES/0009-SYSDB-Sanitize-filter-before-removing-ghost-attrs.patch deleted file mode 100644 index ac80bac..0000000 --- a/SOURCES/0009-SYSDB-Sanitize-filter-before-removing-ghost-attrs.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 0a509d518dd5d17e32e3a4c34b319a38210ba17b Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 25 Nov 2013 16:01:59 +0100 -Subject: [PATCH 9/9] SYSDB: Sanitize filter before removing ghost attrs - -sysdb_add_user fails with EIO if enumeration is disabled and user contains -backslashes. -We try to remove ghost attributes from groups with disabled enumeration, -but unsanitized filter is used to find ghost attributes -"(|(ghost=usr\\\\002)" and ldb cannot parse this filter. - -Resolves: -https://fedorahosted.org/sssd/ticket/2163 ---- - src/db/sysdb_ops.c | 9 ++++++++- - src/tests/sysdb-tests.c | 19 +++++++++++++++++++ - 2 files changed, 27 insertions(+), 1 deletion(-) - -diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c -index eb88cd256d0c2e45e1528e8a867e42354215cc7f..890bf1eb3cc5fc0b6eb6f7a145aee6d87945cd8d 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -1091,6 +1091,7 @@ sysdb_remove_ghostattr_from_groups(struct sysdb_ctx *sysdb, - struct ldb_dn *tmpdn; - const char *group_attrs[] = {SYSDB_NAME, SYSDB_GHOST, SYSDB_ORIG_MEMBER, NULL}; - const char *userdn; -+ char *sanitized_name; - char *filter; - errno_t ret = EOK; - size_t group_count = 0; -@@ -1101,7 +1102,13 @@ sysdb_remove_ghostattr_from_groups(struct sysdb_ctx *sysdb, - return ENOENT; - } - -- filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)", SYSDB_GHOST, name); -+ ret = sss_filter_sanitize(tmp_ctx, name, &sanitized_name); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)", -+ SYSDB_GHOST, sanitized_name); - if (!filter) { - ret = ENOMEM; - goto done; -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index bf964fd76d33bbceac6c1846db7a5011db1375f5..ddbf6f28fd5024945fedcb3c6e2122948c4f1459 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -3900,6 +3900,8 @@ START_TEST(test_odd_characters) - struct ldb_message *msg; - const struct ldb_val *val; - const char odd_username[] = "*(odd)\\user,name"; -+ const char odd_username_orig_dn[] = -+ "\\2a\\28odd\\29\\5cuser,name,cn=users,dc=example,dc=com"; - const char odd_groupname[] = "*(odd\\*)\\group,name"; - const char odd_netgroupname[] = "*(odd\\*)\\netgroup,name"; - const char *received_user; -@@ -4010,6 +4012,23 @@ START_TEST(test_odd_characters) - fail_unless(ret == EOK, "sysdb_delete_group error [%d][%s]", - ret, strerror(ret)); - -+ /* Add */ -+ ret = sysdb_add_user(test_ctx->sysdb, -+ test_ctx->domain, -+ odd_username, -+ 10000, 0, -+ "","","", -+ odd_username_orig_dn, -+ NULL, 5400, 0); -+ fail_unless(ret == EOK, "sysdb_add_user error [%d][%s]", -+ ret, strerror(ret)); -+ -+ /* Delete User */ -+ ret = sysdb_delete_user(test_ctx->sysdb, test_ctx->domain, -+ odd_username, 10000); -+ fail_unless(ret == EOK, "sysdb_delete_user error [%d][%s]", -+ ret, strerror(ret)); -+ - /* ===== Netgroups ===== */ - /* Add */ - ret = sysdb_add_netgroup(test_ctx->sysdb, test_ctx->domain, --- -1.8.4.2 - diff --git a/SOURCES/0009-TESTS-Unit-tests-for-server_setup.patch b/SOURCES/0009-TESTS-Unit-tests-for-server_setup.patch new file mode 100644 index 0000000..384197a --- /dev/null +++ b/SOURCES/0009-TESTS-Unit-tests-for-server_setup.patch @@ -0,0 +1,322 @@ +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-Split-out-a-request-to-search-for-a-user-w-o-sa.patch b/SOURCES/0010-LDAP-Split-out-a-request-to-search-for-a-user-w-o-sa.patch deleted file mode 100644 index 3d4f47b..0000000 --- a/SOURCES/0010-LDAP-Split-out-a-request-to-search-for-a-user-w-o-sa.patch +++ /dev/null @@ -1,301 +0,0 @@ -From 26f41ed62ab74d628764702a1522cedd22b55599 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 1 Oct 2013 17:44:07 +0200 -Subject: [PATCH 10/11] LDAP: Split out a request to search for a user w/o - saving - -Related: -https://fedorahosted.org/sssd/ticket/2077 - -Certain situations require that a user entry is downloaded for further -inpection, but not saved to the sysdb right away. This patch splits the -previously monolithic request into one that just downloads the data and -one that uses the new one to download and save the user. ---- - src/providers/ldap/sdap_async.h | 16 ++++ - src/providers/ldap/sdap_async_users.c | 162 +++++++++++++++++++++++++++------- - 2 files changed, 146 insertions(+), 32 deletions(-) - -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index c8031c9a9d527a6d808f1ddce096de23850ebfd6..dbf572cdc82b100ba9c26b4853f05db1ba5fa4ed 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -58,6 +58,22 @@ errno_t sdap_connect_host_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - struct sdap_handle **_sh); - -+/* Search users in LDAP, return them as attrs */ -+struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sss_domain_info *dom, -+ struct sdap_options *opts, -+ struct sdap_search_base **search_bases, -+ struct sdap_handle *sh, -+ const char **attrs, -+ const char *filter, -+ int timeout, -+ bool enumeration); -+int sdap_search_user_recv(TALLOC_CTX *memctx, struct tevent_req *req, -+ char **higher_usn, struct sysdb_attrs ***users, -+ size_t *count); -+ -+/* Search users in LDAP using the request above, save them to cache */ - struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index 9cfe217482580d4a11ad4ace2f688f42ca55d7b3..7f0b2eea0b5ee909bcf148236c7fc43863fe8c13 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -579,15 +579,15 @@ done: - - /* ==Search-Users-with-filter============================================= */ - --struct sdap_get_users_state { -+struct sdap_search_user_state { - struct tevent_context *ev; - struct sdap_options *opts; - struct sdap_handle *sh; - struct sss_domain_info *dom; -- struct sysdb_ctx *sysdb; -+ - const char **attrs; - const char *base_filter; -- char *filter; -+ const char *filter; - int timeout; - bool enumeration; - -@@ -599,33 +599,31 @@ struct sdap_get_users_state { - struct sdap_search_base **search_bases; - }; - --static errno_t sdap_get_users_next_base(struct tevent_req *req); --static void sdap_get_users_process(struct tevent_req *subreq); -+static errno_t sdap_search_user_next_base(struct tevent_req *req); -+static void sdap_search_user_process(struct tevent_req *subreq); - --struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, -- struct tevent_context *ev, -- struct sss_domain_info *dom, -- struct sysdb_ctx *sysdb, -- struct sdap_options *opts, -- struct sdap_search_base **search_bases, -- struct sdap_handle *sh, -- const char **attrs, -- const char *filter, -- int timeout, -- bool enumeration) -+struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sss_domain_info *dom, -+ struct sdap_options *opts, -+ struct sdap_search_base **search_bases, -+ struct sdap_handle *sh, -+ const char **attrs, -+ const char *filter, -+ int timeout, -+ bool enumeration) - { - errno_t ret; - struct tevent_req *req; -- struct sdap_get_users_state *state; -+ struct sdap_search_user_state *state; - -- req = tevent_req_create(memctx, &state, struct sdap_get_users_state); -- if (!req) return NULL; -+ req = tevent_req_create(memctx, &state, struct sdap_search_user_state); -+ if (req == NULL) return NULL; - - state->ev = ev; - state->opts = opts; - state->dom = dom; - state->sh = sh; -- state->sysdb = sysdb; - state->attrs = attrs; - state->higher_usn = NULL; - state->users = NULL; -@@ -643,7 +641,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - goto done; - } - -- ret = sdap_get_users_next_base(req); -+ ret = sdap_search_user_next_base(req); - - done: - if (ret != EOK) { -@@ -654,18 +652,18 @@ done: - return req; - } - --static errno_t sdap_get_users_next_base(struct tevent_req *req) -+static errno_t sdap_search_user_next_base(struct tevent_req *req) - { - struct tevent_req *subreq; -- struct sdap_get_users_state *state; -+ struct sdap_search_user_state *state; - -- state = tevent_req_data(req, struct sdap_get_users_state); -+ state = tevent_req_data(req, struct sdap_search_user_state); - - talloc_zfree(state->filter); - state->filter = sdap_get_id_specific_filter(state, - state->base_filter, - state->search_bases[state->base_iter]->filter); -- if (!state->filter) { -+ if (state->filter == NULL) { - return ENOMEM; - } - -@@ -681,20 +679,20 @@ static errno_t sdap_get_users_next_base(struct tevent_req *req) - state->opts->user_map, SDAP_OPTS_USER, - state->timeout, - state->enumeration); /* If we're enumerating, we need paging */ -- if (!subreq) { -+ if (subreq == NULL) { - return ENOMEM; - } -- tevent_req_set_callback(subreq, sdap_get_users_process, req); -+ tevent_req_set_callback(subreq, sdap_search_user_process, req); - - return EOK; - } - --static void sdap_get_users_process(struct tevent_req *subreq) -+static void sdap_search_user_process(struct tevent_req *subreq) - { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); -- struct sdap_get_users_state *state = tevent_req_data(req, -- struct sdap_get_users_state); -+ struct sdap_search_user_state *state = tevent_req_data(req, -+ struct sdap_search_user_state); - int ret; - size_t count, i; - struct sysdb_attrs **users; -@@ -744,7 +742,7 @@ static void sdap_get_users_process(struct tevent_req *subreq) - state->base_iter++; - if (state->search_bases[state->base_iter]) { - /* There are more search bases to try */ -- ret = sdap_get_users_next_base(req); -+ ret = sdap_search_user_next_base(req); - if (ret != EOK) { - tevent_req_error(req, ret); - } -@@ -760,12 +758,112 @@ static void sdap_get_users_process(struct tevent_req *subreq) - return; - } - -+ DEBUG(SSSDBG_TRACE_ALL, ("Retrieved total %zu users\n", state->count)); -+ tevent_req_done(req); -+} -+ -+ -+int sdap_search_user_recv(TALLOC_CTX *memctx, struct tevent_req *req, -+ char **higher_usn, struct sysdb_attrs ***users, -+ size_t *count) -+{ -+ struct sdap_search_user_state *state = tevent_req_data(req, -+ struct sdap_search_user_state); -+ -+ if (higher_usn) { -+ *higher_usn = talloc_steal(memctx, state->higher_usn); -+ } -+ -+ if (users) { -+ *users = talloc_steal(memctx, state->users); -+ } -+ -+ if (count) { -+ *count = state->count; -+ } -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -+ -+/* ==Search-And-Save-Users-with-filter============================================= */ -+struct sdap_get_users_state { -+ struct sysdb_ctx *sysdb; -+ struct sdap_options *opts; -+ struct sss_domain_info *dom; -+ -+ char *higher_usn; -+ struct sysdb_attrs **users; -+ size_t count; -+}; -+ -+static void sdap_get_users_done(struct tevent_req *subreq); -+ -+struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sss_domain_info *dom, -+ struct sysdb_ctx *sysdb, -+ struct sdap_options *opts, -+ struct sdap_search_base **search_bases, -+ struct sdap_handle *sh, -+ const char **attrs, -+ const char *filter, -+ int timeout, -+ bool enumeration) -+{ -+ errno_t ret; -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct sdap_get_users_state *state; -+ -+ req = tevent_req_create(memctx, &state, struct sdap_get_users_state); -+ if (!req) return NULL; -+ -+ state->sysdb = sysdb; -+ state->opts = opts; -+ state->dom = dom; -+ -+ subreq = sdap_search_user_send(state, ev, dom, opts, search_bases, -+ sh, attrs, filter, timeout, enumeration); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ tevent_req_set_callback(subreq, sdap_get_users_done, req); -+ -+ ret = EOK; -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ } -+ -+ return req; -+} -+ -+static void sdap_get_users_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_get_users_state *state = tevent_req_data(req, -+ struct sdap_get_users_state); -+ int ret; -+ -+ ret = sdap_search_user_recv(state, subreq, &state->higher_usn, -+ &state->users, &state->count); -+ if (ret) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to retrieve users\n")); -+ tevent_req_error(req, ret); -+ return; -+ } -+ - ret = sdap_save_users(state, state->sysdb, - state->dom, state->opts, - state->users, state->count, - &state->higher_usn); - if (ret) { -- DEBUG(2, ("Failed to store users.\n")); -+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to store users.\n")); - tevent_req_error(req, ret); - return; - } --- -1.8.4.2 - diff --git a/SOURCES/0010-RPM-Package-the-libsss_semanage.so-library.patch b/SOURCES/0010-RPM-Package-the-libsss_semanage.so-library.patch new file mode 100644 index 0000000..1e8e2b6 --- /dev/null +++ b/SOURCES/0010-RPM-Package-the-libsss_semanage.so-library.patch @@ -0,0 +1,28 @@ +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-Search-for-original-DN-during-auth-if-it-s-miss.patch b/SOURCES/0011-LDAP-Search-for-original-DN-during-auth-if-it-s-miss.patch deleted file mode 100644 index 11481f6..0000000 --- a/SOURCES/0011-LDAP-Search-for-original-DN-during-auth-if-it-s-miss.patch +++ /dev/null @@ -1,269 +0,0 @@ -From 8285fdca515e103eed41625a444de6fe72c5daa7 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 1 Oct 2013 17:44:55 +0200 -Subject: [PATCH 11/11] LDAP: Search for original DN during auth if it's - missing - -Resolves: https://fedorahosted.org/sssd/ticket/2077 - -If during the LDAP authentication we find out that the originalDN to -bind as is missing (because the ID module is not LDAP based), we can try -to look up the user from LDAP without saving him just in order to -receive the originalDN. ---- - src/providers/ldap/ldap_auth.c | 210 +++++++++++++++++++++++++++++++++++++---- - 1 file changed, 194 insertions(+), 16 deletions(-) - -diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c -index f9bab4b2b72a061c88fbf18d3f8401b673f79619..ddaeb09c8ae06812855a1daec2fc3399eb4be361 100644 ---- a/src/providers/ldap/ldap_auth.c -+++ b/src/providers/ldap/ldap_auth.c -@@ -343,6 +343,146 @@ shadow_fail: - } - - /* ==Get-User-DN========================================================== */ -+struct get_user_dn_state { -+ const char *username; -+ -+ char *orig_dn; -+}; -+ -+static void get_user_dn_done(struct tevent_req *subreq); -+ -+static struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sss_domain_info *domain, -+ struct sdap_handle *sh, -+ struct sdap_options *opts, -+ const char *username) -+{ -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct get_user_dn_state *state; -+ char *clean_name; -+ char *filter; -+ const char **attrs; -+ errno_t ret; -+ -+ req = tevent_req_create(memctx, &state, struct get_user_dn_state); -+ if (!req) return NULL; -+ -+ state->username = username; -+ -+ ret = sss_filter_sanitize(state, username, &clean_name); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", -+ opts->user_map[SDAP_AT_USER_NAME].name, -+ clean_name, -+ opts->user_map[SDAP_OC_USER].name); -+ talloc_zfree(clean_name); -+ if (filter == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to build the base filter\n")); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* We're mostly interested in the DN anyway */ -+ attrs = talloc_array(state, const char *, 3); -+ if (attrs == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ attrs[0] = "objectclass"; -+ attrs[1] = opts->user_map[SDAP_AT_USER_NAME].name; -+ attrs[2] = NULL; -+ -+ subreq = sdap_search_user_send(state, ev, domain, opts, -+ opts->sdom->user_search_bases, -+ sh, attrs, filter, -+ dp_opt_get_int(opts->basic, -+ SDAP_SEARCH_TIMEOUT), -+ false); -+ if (!subreq) { -+ ret = ENOMEM; -+ goto done; -+ } -+ tevent_req_set_callback(subreq, get_user_dn_done, req); -+ return req; -+ -+done: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void get_user_dn_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct get_user_dn_state *state = tevent_req_data(req, -+ struct get_user_dn_state); -+ struct ldb_message_element *el; -+ struct sysdb_attrs **users; -+ size_t count; -+ -+ ret = sdap_search_user_recv(state, subreq, NULL, &users, &count); -+ talloc_zfree(subreq); -+ if (ret && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to retrieve users\n")); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (count == 0) { -+ DEBUG(SSSDBG_OP_FAILURE, ("No such user\n")); -+ tevent_req_error(req, ENOMEM); -+ return; -+ } else if (count > 1) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Multiple users matched\n")); -+ tevent_req_error(req, EIO); -+ return; -+ } -+ -+ /* exactly one user. Get the originalDN */ -+ ret = sysdb_attrs_get_el_ext(users[0], SYSDB_ORIG_DN, false, &el); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("originalDN is not available for [%s].\n", state->username)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->orig_dn = talloc_strdup(state, (const char *) el->values[0].data); -+ if (state->orig_dn == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Found originalDN [%s] for [%s]\n", -+ state->orig_dn, state->username)); -+ tevent_req_done(req); -+} -+ -+static int get_user_dn_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, -+ char **orig_dn) -+{ -+ struct get_user_dn_state *state = tevent_req_data(req, -+ struct get_user_dn_state); -+ -+ if (orig_dn) { -+ *orig_dn = talloc_move(mem_ctx, &state->orig_dn); -+ } -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} - - static int get_user_dn(TALLOC_CTX *memctx, - struct sysdb_ctx *sysdb, -@@ -391,25 +531,20 @@ static int get_user_dn(TALLOC_CTX *memctx, - - switch (res->count) { - case 0: -- /* FIXME: not in cache, needs a true search */ -- ret = ENOENT; -+ /* No such user entry? Look it up */ -+ ret = EAGAIN; - break; - - case 1: - dn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_ORIG_DN, NULL); -- if (dn) { -- dn = talloc_strdup(tmpctx, dn); -- } else { -- /* TODO: try to search ldap server ? */ -- -- /* FIXME: remove once we store originalDN on every call -- * NOTE: this is wrong, works only with some DITs */ -- dn = talloc_asprintf(tmpctx, "%s=%s,%s", -- opts->user_map[SDAP_AT_USER_NAME].name, -- username, -- dp_opt_get_string(opts->basic, -- SDAP_USER_SEARCH_BASE)); -+ if (dn == NULL) { -+ /* The user entry has no original DN. This is the case when the ID -+ * provider is not LDAP-based (proxy perhaps) */ -+ ret = EAGAIN; -+ break; - } -+ -+ dn = talloc_strdup(tmpctx, dn); - if (!dn) { - ret = ENOMEM; - break; -@@ -466,6 +601,8 @@ struct auth_state { - }; - - static struct tevent_req *auth_get_server(struct tevent_req *req); -+static void auth_get_dn_done(struct tevent_req *subreq); -+static void auth_do_bind(struct tevent_req *req); - static void auth_resolve_done(struct tevent_req *subreq); - static void auth_connect_done(struct tevent_req *subreq); - static void auth_bind_user_done(struct tevent_req *subreq); -@@ -610,11 +747,52 @@ static void auth_connect_done(struct tevent_req *subreq) - ret = get_user_dn(state, state->ctx->be->domain->sysdb, state->ctx->be->domain, - state->ctx->opts, state->username, &state->dn, - &state->pw_expire_type, &state->pw_expire_data); -- if (ret) { -- tevent_req_error(req, ret); -+ if (ret == EOK) { -+ /* All required user data was pre-cached during an identity lookup. -+ * We can proceed with the bind */ -+ auth_do_bind(req); -+ return; -+ } else if (ret == EAGAIN) { -+ /* The cached user entry was missing the bind DN. Need to look -+ * it up based on user name in order to perform the bind */ -+ subreq = get_user_dn_send(req, state->ev, state->ctx->be->domain, -+ state->sh, state->ctx->opts, state->username); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, auth_get_dn_done, req); -+ return; -+ } -+ -+ tevent_req_error(req, ret); -+ return; -+} -+ -+static void auth_get_dn_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct auth_state *state = tevent_req_data(req, struct auth_state); -+ errno_t ret; -+ -+ ret = get_user_dn_recv(state, subreq, &state->dn); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ERR_ACCOUNT_UNKNOWN); - return; - } - -+ /* The DN was found with an LDAP lookup -+ * We can proceed with the bind */ -+ return auth_do_bind(req); -+} -+ -+static void auth_do_bind(struct tevent_req *req) -+{ -+ struct auth_state *state = tevent_req_data(req, struct auth_state); -+ struct tevent_req *subreq; -+ - subreq = sdap_auth_send(state, state->ev, state->sh, - NULL, NULL, state->dn, - state->authtok); --- -1.8.4.2 - 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 new file mode 100644 index 0000000..4e95f7f --- /dev/null +++ b/SOURCES/0011-ipa-fix-issues-with-older-servers-not-supporting-vie.patch @@ -0,0 +1,97 @@ +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-LDAP-Prevent-from-using-uninitialized-sdap_options.patch b/SOURCES/0012-LDAP-Prevent-from-using-uninitialized-sdap_options.patch deleted file mode 100644 index 7c99b36..0000000 --- a/SOURCES/0012-LDAP-Prevent-from-using-uninitialized-sdap_options.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 5eea6f1e7a43bdd63a1530fb9c68ef292f431f4f Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 13 Nov 2013 08:32:23 +0100 -Subject: [PATCH 12/12] LDAP: Prevent from using uninitialized sdap_options - -ldap_get_options can fail in time of ldap back end initialisation -and then sssd try to release uninitialised sdap_options. - -Resolves: -https://fedorahosted.org/sssd/ticket/2147 ---- - src/providers/ldap/ldap_init.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c -index 17874b1325d3e5bf2eded62c6f022364b84a5c2a..15615b2891f2e3104c11e8610c081adcd1d1ee8e 100644 ---- a/src/providers/ldap/ldap_init.c -+++ b/src/providers/ldap/ldap_init.c -@@ -94,7 +94,7 @@ int sssm_ldap_id_init(struct be_ctx *bectx, - const char *dns_service_name; - const char *sasl_mech; - struct sdap_service *sdap_service; -- struct sdap_options *opts; -+ struct sdap_options *opts = NULL; - int ret; - - /* If we're already set up, just return that */ --- -1.8.4.2 - 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 new file mode 100644 index 0000000..8120e60 --- /dev/null +++ b/SOURCES/0012-ipa-improve-error-reporting-for-extdom-LDAP-exop.patch @@ -0,0 +1,48 @@ +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 new file mode 100644 index 0000000..7c93e71 --- /dev/null +++ b/SOURCES/0013-BUILD-Fix-automake-warning.patch @@ -0,0 +1,39 @@ +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-SUBDOMAINS-Reuse-cached-results-if-DP-is-offline.patch b/SOURCES/0013-SUBDOMAINS-Reuse-cached-results-if-DP-is-offline.patch deleted file mode 100644 index bc5a348..0000000 --- a/SOURCES/0013-SUBDOMAINS-Reuse-cached-results-if-DP-is-offline.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 8751aace6de14f3782765a89555b65e991f340a0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 3 Dec 2013 15:25:25 +0100 -Subject: [PATCH 13/15] SUBDOMAINS: Reuse cached results if DP is offline - -If Data Provider was unable to refresh the subdomain list, the -sss_domain_info->subdomains list was NULL. Which meant that no DP -request matched any known domain and hence offline authentication was -not working correctly. - -Resolves: -https://fedorahosted.org/sssd/ticket/2168 ---- - src/providers/ad/ad_subdomains.c | 7 +++++++ - src/providers/ipa/ipa_subdomains.c | 8 ++++++-- - 2 files changed, 13 insertions(+), 2 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 9911dfe0f4fda6749fa6dd3f15b1c04a36964ca4..18414523096ba0e53261415551eea57b4b2758b2 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -650,5 +650,12 @@ int ad_subdom_init(struct be_ctx *be_ctx, - return EFAULT; - } - -+ ret = sysdb_update_subdomains(be_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not load the list of subdomains. " -+ "Users from trusted domains might not be resolved correctly\n")); -+ /* Ignore this error and try to discover the subdomains later */ -+ } -+ - return EOK; - } -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 4f7627eddb9c54d68e45be876157057f3c30b422..416e21913be8e991c9f496ff2b54f238b602f304 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -809,8 +809,6 @@ static void ipa_subdomains_get_conn_done(struct tevent_req *req) - DEBUG(SSSDBG_MINOR_FAILURE, - ("No IPA server is available, cannot get the " - "subdomain list while offline\n")); -- --/* FIXME: return saved results ?? */ - } else { - DEBUG(SSSDBG_OP_FAILURE, - ("Failed to connect to IPA server: [%d](%s)\n", -@@ -1291,6 +1289,12 @@ int ipa_subdom_init(struct be_ctx *be_ctx, - DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add subdom offline callback")); - } - -+ ret = sysdb_update_subdomains(be_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not load the list of subdomains. " -+ "Users from trusted domains might not be resolved correctly\n")); -+ } -+ - return EOK; - } - --- -1.8.4.2 - diff --git a/SOURCES/0014-failover-check-dns_domain-if-primary-servers-lookup-.patch b/SOURCES/0014-failover-check-dns_domain-if-primary-servers-lookup-.patch deleted file mode 100644 index 3da0806..0000000 --- a/SOURCES/0014-failover-check-dns_domain-if-primary-servers-lookup-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0926cec5b98218131ac822e1684f9bce7aa0072c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Thu, 5 Dec 2013 13:19:16 +0100 -Subject: [PATCH 14/15] failover: check dns_domain if primary servers lookup - failed - -If primary servers lookup failed, dns_domain is not set. - -Resolves: -https://fedorahosted.org/sssd/ticket/2173 ---- - src/providers/fail_over_srv.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/src/providers/fail_over_srv.c b/src/providers/fail_over_srv.c -index 543516ef19e288556e39e61b400a628c94e2817b..c27416899e30b3cf8b3c0496adb08089f4b2c11d 100644 ---- a/src/providers/fail_over_srv.c -+++ b/src/providers/fail_over_srv.c -@@ -302,13 +302,17 @@ static void fo_discover_servers_primary_done(struct tevent_req *subreq) - } - - if (state->backup_domain == NULL) { -+ /* if there is no backup domain, we are done */ - DEBUG(SSSDBG_TRACE_FUNC, ("No backup domain specified\n")); - goto done; - } - -- if (strcasecmp(state->dns_domain, state->backup_domain) == 0) { -- /* primary domain was unreachable, we will use servers from backup -- * domain as primary */ -+ if (state->dns_domain != NULL -+ && strcasecmp(state->dns_domain, state->backup_domain) == 0) { -+ /* If there was no error and dns_domain is the same as backup domain, -+ * it means that we were unable to resolve SRV in primary domain, but -+ * SRV from backup domain was resolved and those servers are considered -+ * to be primary. We are done. */ - state->backup_servers = NULL; - state->num_backup_servers = 0; - --- -1.8.4.2 - diff --git a/SOURCES/0014-test_server-Fix-waiting-for-background-process.patch b/SOURCES/0014-test_server-Fix-waiting-for-background-process.patch new file mode 100644 index 0000000..f4b8270 --- /dev/null +++ b/SOURCES/0014-test_server-Fix-waiting-for-background-process.patch @@ -0,0 +1,48 @@ +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-NSS-Set-packet-length-for-initgroups.patch b/SOURCES/0015-NSS-Set-packet-length-for-initgroups.patch deleted file mode 100644 index b122626..0000000 --- a/SOURCES/0015-NSS-Set-packet-length-for-initgroups.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 644f0b89c61b8a912514df550633f179c654240a Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 5 Nov 2013 17:58:36 +0100 -Subject: [PATCH 15/15] NSS: Set packet length for initgroups - -Some groups could be skipped, but packet length was not trimmed. -This is a reason why valgrind reported access to uninitialised bytes. -Actually, it isn't a problem, because the first uint32 in body is number of -sended gids. - -Resolves: -https://fedorahosted.org/sssd/ticket/2138 ---- - src/responder/nss/nsssrv_cmd.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index ada2b64df88d6a03a5c36a76076da447faa573c9..07f31188074bf45664969fb33388edb475e53b96 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -3558,6 +3558,13 @@ static int fill_initgr(struct sss_packet *packet, struct ldb_result *res) - - ((uint32_t *)body)[0] = num-skipped; /* num results */ - ((uint32_t *)body)[1] = 0; /* reserved */ -+ blen = (2 + bindex) * sizeof(uint32_t); -+ ret = sss_packet_set_size(packet, blen); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not set packet size to value:%zu\n", blen)); -+ return ret; -+ } - - return EOK; - } --- -1.8.4.2 - diff --git a/SOURCES/0015-ipa_subdomains_handler_master_done-initialize-reply_.patch b/SOURCES/0015-ipa_subdomains_handler_master_done-initialize-reply_.patch new file mode 100644 index 0000000..5115210 --- /dev/null +++ b/SOURCES/0015-ipa_subdomains_handler_master_done-initialize-reply_.patch @@ -0,0 +1,31 @@ +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-Fix-debug-messages-trailing.patch b/SOURCES/0016-Fix-debug-messages-trailing.patch new file mode 100644 index 0000000..1812d97 --- /dev/null +++ b/SOURCES/0016-Fix-debug-messages-trailing.patch @@ -0,0 +1,37 @@ +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/0016-NSS-Fix-memory-leak-in-sss_setnetgrent.patch b/SOURCES/0016-NSS-Fix-memory-leak-in-sss_setnetgrent.patch deleted file mode 100644 index 698ba3e..0000000 --- a/SOURCES/0016-NSS-Fix-memory-leak-in-sss_setnetgrent.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 81aa563090c33bafbf22f1cde586b77ed526c25f Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 27 Nov 2013 10:22:59 +0100 -Subject: [PATCH 16/17] NSS: Fix memory leak in sss_setnetgrent - -struct nss_cmd_ctx was not released in function nss_cmd_setnetgrent_done -and it wasn't used in the other function, because getnetgrent creates its own -nss_cmd_ctx context. struct nss_cmd_ctx was released after closing client -because it was allocated under client context. Memory leak is apparent with -long living clients. - -Resolves: -https://fedorahosted.org/sssd/ticket/2170 ---- - src/responder/nss/nsssrv_netgroup.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c -index a1c41968db0becbc42a1c501b666d9aec5241b5f..18e8579372fa39a1b3a60076948bc12bc008fb80 100644 ---- a/src/responder/nss/nsssrv_netgroup.c -+++ b/src/responder/nss/nsssrv_netgroup.c -@@ -687,7 +687,7 @@ static void nss_cmd_setnetgrent_done(struct tevent_req *req) - ((uint32_t *)body)[1] = 0; /* reserved */ - } - -- sss_cmd_done(cmdctx->cctx, NULL); -+ sss_cmd_done(cmdctx->cctx, cmdctx); - return; - } - --- -1.8.4.2 - diff --git a/SOURCES/0017-AD-use-LDAP-for-group-lookups.patch b/SOURCES/0017-AD-use-LDAP-for-group-lookups.patch deleted file mode 100644 index be1d3cf..0000000 --- a/SOURCES/0017-AD-use-LDAP-for-group-lookups.patch +++ /dev/null @@ -1,253 +0,0 @@ -From 0324d31d0479e5de0d3aac05bf5fb922d84f84c4 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 9 Dec 2013 11:45:28 +0100 -Subject: [PATCH 17/17] AD: use LDAP for group lookups - -The group memberships cannot be reliable retrieved from the Global -Catalog. By default the memberOf attribute is not replicated to the GC -at all and the member attribute is copied from the local LDAP instance -to the GC running on the same host, but is only replicated to other GC -instances for groups with universal scope. Additionally the tokenGroups -attribute contains invalid SIDs when used with the GC for users from a -different domains than the GC belongs to. - -As a result the requests which tries to resolve group-memberships of a -AD user have to go to a LDAP server from the domain of the user. - -Fixes https://fedorahosted.org/sssd/ticket/2161 and -https://fedorahosted.org/sssd/ticket/2148 as a side-effect. ---- - src/providers/ad/ad_id.c | 20 +++++- - src/providers/ad/ad_subdomains.c | 133 ++++++++++++++++++++++++++++++++++++++- - src/providers/ldap/sdap.h | 2 + - 3 files changed, 152 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 87b69c66892ebfa48a1067c63006f3e3bd2e7444..dadb50da92cac87d3162bddb44395dad7d2abbc4 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -188,6 +188,8 @@ 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; -+ struct sdap_domain *sdom; -+ struct ad_id_ctx *subdom_id_ctx; - - /* LDAP, GC, sentinel */ - clist = talloc_zero_array(breq, struct sdap_id_conn_ctx *, 3); -@@ -197,8 +199,6 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - case BE_REQ_USER: /* user */ - case BE_REQ_BY_SECID: /* by SID */ - case BE_REQ_USER_AND_GROUP: /* get SID */ -- case BE_REQ_GROUP: /* group */ -- case BE_REQ_INITGROUPS: /* init groups for user */ - /* Always try GC first */ - clist[0] = ad_ctx->gc_ctx; - if (IS_SUBDOMAIN(dom) == true) { -@@ -216,6 +216,22 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - clist[1] = ad_ctx->ldap_ctx; - break; - -+ case BE_REQ_GROUP: /* group */ -+ case BE_REQ_INITGROUPS: /* init groups for user */ -+ if (IS_SUBDOMAIN(dom)) { -+ sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom); -+ if (sdom == NULL || sdom->pvt == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", -+ dom->name)); -+ return NULL; -+ } -+ subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); -+ clist[0] = subdom_id_ctx->ldap_ctx; -+ } else { -+ clist[0] = ad_ctx->ldap_ctx; -+ } -+ break; -+ - default: - clist[0] = ad_ctx->ldap_ctx; - break; -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 18414523096ba0e53261415551eea57b4b2758b2..28c5eafb395b70e8f3630a43b67c61810683fe7c 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -25,6 +25,7 @@ - #include "providers/ldap/sdap_async.h" - #include "providers/ad/ad_subdomains.h" - #include "providers/ad/ad_domain_info.h" -+#include "providers/ad/ad_srv.h" - #include "providers/ldap/sdap_idmap.h" - #include "util/util_sss_idmap.h" - #include -@@ -68,6 +69,7 @@ struct ad_subdomains_ctx { - - time_t last_refreshed; - struct tevent_timer *timer_event; -+ struct ad_id_ctx *ad_id_ctx; - }; - - struct ad_subdomains_req_ctx { -@@ -86,10 +88,138 @@ struct ad_subdomains_req_ctx { - }; - - static errno_t -+ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, -+ struct ad_id_ctx *id_ctx, -+ struct sss_domain_info *subdom, -+ struct ad_id_ctx **_subdom_id_ctx) -+{ -+ struct ad_options *ad_options; -+ struct ad_id_ctx *ad_id_ctx; -+ const char *gc_service_name; -+ struct ad_srv_plugin_ctx *srv_ctx; -+ char *ad_domain; -+ struct sdap_domain *sdom; -+ errno_t ret; -+ const char *realm; -+ const char *hostname; -+ -+ realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM); -+ hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME); -+ if (realm == NULL || hostname == NULL) { -+ DEBUG(SSSDBG_CONF_SETTINGS, ("Missing realm or hostname.\n")); -+ return EINVAL; -+ } -+ -+ ad_options = ad_create_default_options(id_ctx, realm, hostname); -+ if (ad_options == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD options\n")); -+ talloc_free(ad_options); -+ return ENOMEM; -+ } -+ -+ ad_domain = subdom->name; -+ -+ ret = dp_opt_set_string(ad_options->basic, AD_DOMAIN, ad_domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot set AD domain\n")); -+ talloc_free(ad_options); -+ return ret; -+ } -+ -+ gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name); -+ if (gc_service_name == NULL) { -+ talloc_free(ad_options); -+ return ENOMEM; -+ } -+ -+ ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, realm, -+ subdom->name, gc_service_name, -+ subdom->name, &ad_options->service); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize AD failover\n")); -+ talloc_free(ad_options); -+ return ret; -+ } -+ -+ ad_id_ctx = ad_id_ctx_init(ad_options, be_ctx); -+ if (ad_id_ctx == NULL) { -+ talloc_free(ad_options); -+ return ENOMEM; -+ } -+ ad_id_ctx->sdap_id_ctx->opts = ad_options->id; -+ ad_options->id_ctx = ad_id_ctx; -+ -+ /* use AD plugin */ -+ srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx->be_res, -+ default_host_dbs, -+ ad_id_ctx->ad_options->id, -+ hostname, -+ ad_domain); -+ if (srv_ctx == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory?\n")); -+ return ENOMEM; -+ } -+ be_fo_set_srv_lookup_plugin(be_ctx, ad_srv_plugin_send, -+ ad_srv_plugin_recv, srv_ctx, "AD"); -+ -+ ret = sdap_domain_subdom_add(ad_id_ctx->sdap_id_ctx, -+ ad_id_ctx->sdap_id_ctx->opts->sdom, -+ subdom->parent); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize sdap domain\n")); -+ talloc_free(ad_options); -+ return ret; -+ } -+ -+ sdom = sdap_domain_get(ad_id_ctx->sdap_id_ctx->opts, subdom); -+ if (sdom == NULL) { -+ return EFAULT; -+ } -+ -+ ret = sdap_id_setup_tasks(ad_id_ctx->sdap_id_ctx, -+ ad_id_ctx->ldap_ctx, sdom, -+ ldap_enumeration_send, -+ ldap_enumeration_recv); -+ if (ret != EOK) { -+ talloc_free(ad_options); -+ return ret; -+ } -+ -+ /* Set up the ID mapping object */ -+ ad_id_ctx->sdap_id_ctx->opts->idmap_ctx = -+ id_ctx->sdap_id_ctx->opts->idmap_ctx; -+ -+ *_subdom_id_ctx = ad_id_ctx; -+ return EOK; -+} -+ -+static errno_t - ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx, - struct sss_domain_info *parent) - { -- return sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent); -+ int ret; -+ struct sdap_domain *sditer; -+ struct ad_id_ctx *subdom_id_ctx; -+ -+ ret = sdap_domain_subdom_add(ctx->sdap_id_ctx, ctx->sdom, parent); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_domain_subdom_add failed.\n")); -+ return ret; -+ } -+ -+ DLIST_FOR_EACH(sditer, ctx->sdom) { -+ if (IS_SUBDOMAIN(sditer->dom) && sditer->pvt == NULL) { -+ ret = ad_subdom_ad_ctx_new(ctx->be_ctx, ctx->ad_id_ctx, -+ sditer->dom, &subdom_id_ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("ad_subdom_ad_ctx_new failed.\n")); -+ } else { -+ sditer->pvt = subdom_id_ctx; -+ } -+ } -+ } -+ -+ return EOK; - } - - static errno_t -@@ -630,6 +760,7 @@ int ad_subdom_init(struct be_ctx *be_ctx, - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - return ENOMEM; - } -+ ctx->ad_id_ctx = id_ctx; - *ops = &ad_subdomains_ops; - *pvt_data = ctx; - -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index c53471b9bd6d9b18f37a8bf4089c8700d4a1163d..fa641730bb78b6a96c0b9640af7612b876f56533 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -394,6 +394,8 @@ struct sdap_domain { - struct timeval last_enum; - /* cleanup loop timer */ - struct timeval last_purge; -+ -+ void *pvt; - }; - - struct sdap_options { --- -1.8.4.2 - diff --git a/SOURCES/0017-IPA-Handle-NULL-members-in-process_members.patch b/SOURCES/0017-IPA-Handle-NULL-members-in-process_members.patch new file mode 100644 index 0000000..1cdf793 --- /dev/null +++ b/SOURCES/0017-IPA-Handle-NULL-members-in-process_members.patch @@ -0,0 +1,40 @@ +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 new file mode 100644 index 0000000..47f2cdc --- /dev/null +++ b/SOURCES/0018-SPEC-Print-testsuite-log-for-failed-test.patch @@ -0,0 +1,32 @@ +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-idmap-add-API-to-free-allocated-SIDs.patch b/SOURCES/0018-idmap-add-API-to-free-allocated-SIDs.patch deleted file mode 100644 index 02df2e8..0000000 --- a/SOURCES/0018-idmap-add-API-to-free-allocated-SIDs.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 16c8b0e7a0ac40b078f98c9f8025d39a59dca9bb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 1 Nov 2013 12:23:23 +0100 -Subject: [PATCH 18/31] idmap: add API to free allocated SIDs - ---- - src/lib/idmap/sss_idmap.c | 36 +++++++++++++++++++++++++++++++++++ - src/lib/idmap/sss_idmap.h | 48 +++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 84 insertions(+) - -diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c -index 9278e10d2bee37b741a87cd84d666d8a5b7bb671..3f1e7a58f390a3c10999251e2155ef513ba69bd7 100644 ---- a/src/lib/idmap/sss_idmap.c -+++ b/src/lib/idmap/sss_idmap.c -@@ -246,6 +246,42 @@ enum idmap_error_code sss_idmap_free(struct sss_idmap_ctx *ctx) - return IDMAP_SUCCESS; - } - -+static enum idmap_error_code sss_idmap_free_ptr(struct sss_idmap_ctx *ctx, -+ void *ptr) -+{ -+ CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); -+ -+ if (ptr != NULL) { -+ ctx->free_func(ptr, ctx->alloc_pvt); -+ } -+ -+ return IDMAP_SUCCESS; -+} -+ -+enum idmap_error_code sss_idmap_free_sid(struct sss_idmap_ctx *ctx, -+ char *sid) -+{ -+ return sss_idmap_free_ptr(ctx, sid); -+} -+ -+enum idmap_error_code sss_idmap_free_dom_sid(struct sss_idmap_ctx *ctx, -+ struct sss_dom_sid *dom_sid) -+{ -+ return sss_idmap_free_ptr(ctx, dom_sid); -+} -+ -+enum idmap_error_code sss_idmap_free_smb_sid(struct sss_idmap_ctx *ctx, -+ struct dom_sid *smb_sid) -+{ -+ return sss_idmap_free_ptr(ctx, smb_sid); -+} -+ -+enum idmap_error_code sss_idmap_free_bin_sid(struct sss_idmap_ctx *ctx, -+ uint8_t *bin_sid) -+{ -+ return sss_idmap_free_ptr(ctx, bin_sid); -+} -+ - enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, - const char *dom_sid, - id_t *slice_num, -diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h -index 4101fb9a5e0982c6ba0560decd299a0ed9e722b6..1e1c9a5cfe490301d0e633db808589f1bc0ef857 100644 ---- a/src/lib/idmap/sss_idmap.h -+++ b/src/lib/idmap/sss_idmap.h -@@ -504,6 +504,54 @@ enum idmap_error_code sss_idmap_unix_to_bin_sid(struct sss_idmap_ctx *ctx, - enum idmap_error_code sss_idmap_free(struct sss_idmap_ctx *ctx); - - /** -+ * @brief Free mapped SID. -+ * -+ * @param[in] ctx Idmap context -+ * @param[in] sid SID to be freed. -+ * -+ * @return -+ * - #IDMAP_CONTEXT_INVALID: Provided context is invalid -+ */ -+enum idmap_error_code sss_idmap_free_sid(struct sss_idmap_ctx *ctx, -+ char *sid); -+ -+/** -+ * @brief Free mapped domain SID. -+ * -+ * @param[in] ctx Idmap context -+ * @param[in] dom_sid Domain SID to be freed. -+ * -+ * @return -+ * - #IDMAP_CONTEXT_INVALID: Provided context is invalid -+ */ -+enum idmap_error_code sss_idmap_free_dom_sid(struct sss_idmap_ctx *ctx, -+ struct sss_dom_sid *dom_sid); -+ -+/** -+ * @brief Free mapped Samba SID. -+ * -+ * @param[in] ctx Idmap context -+ * @param[in] smb_sid Samba SID to be freed. -+ * -+ * @return -+ * - #IDMAP_CONTEXT_INVALID: Provided context is invalid -+ */ -+enum idmap_error_code sss_idmap_free_smb_sid(struct sss_idmap_ctx *ctx, -+ struct dom_sid *smb_sid); -+ -+/** -+ * @brief Free mapped binary SID. -+ * -+ * @param[in] ctx Idmap context -+ * @param[in] smb_sid Binary SID to be freed. -+ * -+ * @return -+ * - #IDMAP_CONTEXT_INVALID: Provided context is invalid -+ */ -+enum idmap_error_code sss_idmap_free_bin_sid(struct sss_idmap_ctx *ctx, -+ uint8_t *bin_sid); -+ -+/** - * @brief Translate error code to a string - * - * @param[in] err Idmap error code --- -1.8.4.2 - 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 new file mode 100644 index 0000000..c611e9b --- /dev/null +++ b/SOURCES/0019-MAN-PAGE-modified-sssd-ldap.5.xml-for-sssd-ticket-24.patch @@ -0,0 +1,72 @@ +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/0019-free-idmapped-SIDs-correctly.patch b/SOURCES/0019-free-idmapped-SIDs-correctly.patch deleted file mode 100644 index 241ae14..0000000 --- a/SOURCES/0019-free-idmapped-SIDs-correctly.patch +++ /dev/null @@ -1,205 +0,0 @@ -From 9fad27b40eff82bcdffa61cafcc54e2d7750faee Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 1 Nov 2013 12:27:59 +0100 -Subject: [PATCH 19/31] free idmapped SIDs correctly - -Resolves: -https://fedorahosted.org/sssd/ticket/2133 ---- - src/providers/ad/ad_id.c | 3 +-- - src/providers/ad/ad_subdomains.c | 2 ++ - src/providers/ldap/ldap_id.c | 4 ++-- - src/providers/ldap/sdap_async_initgroups_ad.c | 2 ++ - src/responder/pac/pacsrv_cmd.c | 2 ++ - src/responder/pac/pacsrv_utils.c | 4 ++-- - src/tests/cmocka/test_sss_idmap.c | 2 ++ - src/tests/sss_idmap-tests.c | 14 +++++++------- - 8 files changed, 20 insertions(+), 13 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index dadb50da92cac87d3162bddb44395dad7d2abbc4..19bc65825be21c6419db1e92db642be0a14b97a8 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -307,8 +307,7 @@ static errno_t ad_account_can_shortcut(struct be_ctx *be_ctx, - - done: - if (sid != NULL) { -- /* FIXME: use library function when #2133 is fixed */ -- talloc_free(sid); -+ sss_idmap_free_sid(idmap_ctx->map, sid); - } - - if (ret == EOK) { -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 28c5eafb395b70e8f3630a43b67c61810683fe7c..dd692fb699ddf14bcf8f9926383e82da77c494e0 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -302,7 +302,9 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx, - - ret = EOK; - done: -+ sss_idmap_free_sid(ctx->sdap_id_ctx->opts->idmap_ctx->map, sid_str); - talloc_free(tmp_ctx); -+ - return ret; - } - -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index fad1585331b7f0240770d2dc5a2e89788d2ad4da..793bc99ebcec883be7db3fc9dd56fa511d8ba3bb 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -139,7 +139,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - - attr_name = ctx->opts->user_map[SDAP_AT_USER_OBJECTSID].name; - ret = sss_filter_sanitize(state, sid, &clean_name); -- talloc_zfree(sid); -+ sss_idmap_free_sid(ctx->opts->idmap_ctx->map, sid); - if (ret != EOK) { - goto fail; - } -@@ -509,7 +509,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - - attr_name = ctx->opts->group_map[SDAP_AT_GROUP_OBJECTSID].name; - ret = sss_filter_sanitize(state, sid, &clean_name); -- talloc_zfree(sid); -+ sss_idmap_free_sid(ctx->opts->idmap_ctx->map, sid); - if (ret != EOK) { - goto fail; - } -diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c -index a0841a799bdbb1ad4de856d1715c88588b3b4da9..aa72c8876ba93eefc6230537801c50ab04e591ce 100644 ---- a/src/providers/ldap/sdap_async_initgroups_ad.c -+++ b/src/providers/ldap/sdap_async_initgroups_ad.c -@@ -594,6 +594,8 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq) - in_transaction = false; - - done: -+ sss_idmap_free_sid(state->opts->idmap_ctx->map, sid_str); -+ - if (in_transaction) { - sret = sysdb_transaction_cancel(state->sysdb); - DEBUG(SSSDBG_FATAL_FAILURE, -diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c -index f6e8abaf580a43417f3ea09929feccf19e5b0f29..144f5f5847e7ead490d59bae0e2fe49722eb9b69 100644 ---- a/src/responder/pac/pacsrv_cmd.c -+++ b/src/responder/pac/pacsrv_cmd.c -@@ -161,6 +161,8 @@ static errno_t pac_add_pac_user(struct cli_ctx *cctx) - goto done; - } - -+ talloc_steal(pr_ctx, pr_ctx->user_dom_sid_str); -+ - ret = responder_get_domain_by_id(cctx->rctx, pr_ctx->user_dom_sid_str, - &pr_ctx->dom); - if (ret == EAGAIN || ret == ENOENT) { -diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c -index 05b53edee2ada79abf8bd04a6032314b68541d8e..30055a1345b7d943e6adf822438263c92e53b51a 100644 ---- a/src/responder/pac/pacsrv_utils.c -+++ b/src/responder/pac/pacsrv_utils.c -@@ -264,14 +264,14 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - goto done; - } - -- talloc_zfree(sid_str); -+ sss_idmap_free_sid(pac_ctx->idmap_ctx, sid_str); - } - - ret = EOK; - - done: - talloc_free(sid_str); -- talloc_free(user_dom_sid_str); -+ sss_idmap_free_sid(pac_ctx->idmap_ctx, user_dom_sid_str); - - if (ret == EOK) { - *_sid_table = sid_table; -diff --git a/src/tests/cmocka/test_sss_idmap.c b/src/tests/cmocka/test_sss_idmap.c -index 53ed35a97863f8f52b82bec64d6dfb192891b0fe..019b4618ef0e14e87cb86d64989e8f5ca9dfdfd8 100644 ---- a/src/tests/cmocka/test_sss_idmap.c -+++ b/src/tests/cmocka/test_sss_idmap.c -@@ -251,6 +251,7 @@ void test_map_id(void **state) - err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, id, &sid); - assert_int_equal(err, IDMAP_SUCCESS); - assert_string_equal(sid, TEST_DOM_SID"-0"); -+ sss_idmap_free_sid(test_ctx->idmap_ctx, sid); - - err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, - TEST_DOM_SID"-"TEST_OFFSET_STR, &id); -@@ -260,6 +261,7 @@ void test_map_id(void **state) - err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, id, &sid); - assert_int_equal(err, IDMAP_SUCCESS); - assert_string_equal(sid, TEST_DOM_SID"-"TEST_OFFSET_STR); -+ sss_idmap_free_sid(test_ctx->idmap_ctx, sid); - } - - void test_map_id_external(void **state) -diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c -index 65e61351ddcf52deffe9c8abf38497cd9183c448..b2de0e70f794414587080587af1fd4a06d5ae854 100644 ---- a/src/tests/sss_idmap-tests.c -+++ b/src/tests/sss_idmap-tests.c -@@ -280,7 +280,7 @@ START_TEST(idmap_test_uid2sid) - "sss_idmap_unix_to_sid returned wrong SID, " - "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); - -- talloc_free(sid); -+ sss_idmap_free_sid(idmap_ctx, sid); - } - END_TEST - -@@ -304,7 +304,7 @@ START_TEST(idmap_test_uid2dom_sid) - "sss_idmap_unix_to_dom_sid returned wrong SID, " - "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); - -- talloc_free(sid); -+ sss_idmap_free_sid(idmap_ctx, sid); - talloc_free(dom_sid); - } - END_TEST -@@ -330,7 +330,7 @@ START_TEST(idmap_test_uid2bin_sid) - "sss_idmap_unix_to_bin_sid returned wrong SID, " - "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); - -- talloc_free(sid); -+ sss_idmap_free_sid(idmap_ctx, sid); - talloc_free(bin_sid); - } - END_TEST -@@ -385,7 +385,7 @@ START_TEST(idmap_test_sid2dom_sid) - "SID strings do not match."); - - talloc_free(dom_sid); -- talloc_free(new_sid); -+ sss_idmap_free_sid(idmap_ctx, new_sid); - } - END_TEST - -@@ -418,7 +418,7 @@ START_TEST(idmap_test_large_and_too_large_sid) - "did not return IDMAP_SID_INVALID"); - - talloc_free(dom_sid); -- talloc_free(new_sid); -+ sss_idmap_free_sid(idmap_ctx, new_sid); - } - END_TEST - -@@ -454,7 +454,7 @@ START_TEST(idmap_test_bin_sid2sid) - "expected [%s], get [%s]", - test_sid, sid); - -- talloc_free(sid); -+ sss_idmap_free_sid(idmap_ctx, sid); - } - END_TEST - -@@ -528,7 +528,7 @@ START_TEST(idmap_test_smb_sid2sid) - "expected [%s], get [%s]", - test_sid, sid); - -- talloc_free(sid); -+ sss_idmap_free_sid(idmap_ctx, sid); - } - END_TEST - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..9007059 --- /dev/null +++ b/SOURCES/0020-NSS-Possibility-to-use-any-shells-in-allowed_shells.patch @@ -0,0 +1,71 @@ +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-free-idmapped-dom-SIDs-correctly.patch b/SOURCES/0020-free-idmapped-dom-SIDs-correctly.patch deleted file mode 100644 index 8632643..0000000 --- a/SOURCES/0020-free-idmapped-dom-SIDs-correctly.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 8894f5214c20e530c15a7481ed0b84e533cef519 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 1 Nov 2013 13:17:17 +0100 -Subject: [PATCH 20/31] free idmapped dom SIDs correctly - -Resolves: -https://fedorahosted.org/sssd/ticket/2133 ---- - src/tests/sss_idmap-tests.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c -index b2de0e70f794414587080587af1fd4a06d5ae854..c43e326b1f49ac74c387c76e58f2f32efdce40ff 100644 ---- a/src/tests/sss_idmap-tests.c -+++ b/src/tests/sss_idmap-tests.c -@@ -261,7 +261,7 @@ START_TEST(idmap_test_dom_sid2uid) - "sss_idmap_dom_sid_to_unix returned wrong id, " - "got [%d], expected [%d].", id, 1000 + IDMAP_RANGE_MIN); - -- talloc_free(dom_sid); -+ sss_idmap_free_dom_sid(idmap_ctx, dom_sid); - } - END_TEST - -@@ -305,7 +305,7 @@ START_TEST(idmap_test_uid2dom_sid) - "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); - - sss_idmap_free_sid(idmap_ctx, sid); -- talloc_free(dom_sid); -+ sss_idmap_free_dom_sid(idmap_ctx, dom_sid); - } - END_TEST - -@@ -358,7 +358,7 @@ START_TEST(idmap_test_bin_sid2dom_sid) - fail_unless(memcmp(test_bin_sid, new_bin_sid, test_bin_sid_length) == 0, - "Binary SIDs do not match."); - -- talloc_free(dom_sid); -+ sss_idmap_free_dom_sid(idmap_ctx, dom_sid); - talloc_free(new_bin_sid); - } - END_TEST -@@ -384,7 +384,7 @@ START_TEST(idmap_test_sid2dom_sid) - fail_unless(strcmp("S-1-5-21-1-2-3-1000", new_sid) == 0, - "SID strings do not match."); - -- talloc_free(dom_sid); -+ sss_idmap_free_dom_sid(idmap_ctx, dom_sid); - sss_idmap_free_sid(idmap_ctx, new_sid); - } - END_TEST -@@ -417,7 +417,7 @@ START_TEST(idmap_test_large_and_too_large_sid) - "Trying to convert a SID with a too large component " - "did not return IDMAP_SID_INVALID"); - -- talloc_free(dom_sid); -+ sss_idmap_free_dom_sid(idmap_ctx, dom_sid); - sss_idmap_free_sid(idmap_ctx, new_sid); - } - END_TEST -@@ -475,7 +475,7 @@ START_TEST(idmap_test_smb_sid2dom_sid) - fail_unless(memcmp(&test_smb_sid, new_smb_sid, sizeof(struct dom_sid)) == 0, - "Samba dom_sid-s do not match."); - -- talloc_free(dom_sid); -+ sss_idmap_free_dom_sid(idmap_ctx, dom_sid); - talloc_free(new_smb_sid); - } - END_TEST --- -1.8.4.2 - diff --git a/SOURCES/0021-GPO-Terminate-request-on-error.patch b/SOURCES/0021-GPO-Terminate-request-on-error.patch new file mode 100644 index 0000000..c087e3e --- /dev/null +++ b/SOURCES/0021-GPO-Terminate-request-on-error.patch @@ -0,0 +1,31 @@ +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-free-idmapped-smb-SIDs-correctly.patch b/SOURCES/0021-free-idmapped-smb-SIDs-correctly.patch deleted file mode 100644 index 5566418..0000000 --- a/SOURCES/0021-free-idmapped-smb-SIDs-correctly.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 6b44bc4465b954183f8a52fbb05da6b63b17f0d1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 4 Nov 2013 11:59:28 +0100 -Subject: [PATCH 21/31] free idmapped smb SIDs correctly - -Resolves: -https://fedorahosted.org/sssd/ticket/2133 ---- - src/tests/sss_idmap-tests.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c -index c43e326b1f49ac74c387c76e58f2f32efdce40ff..888be82248045058093d6943ef73742d8812eac3 100644 ---- a/src/tests/sss_idmap-tests.c -+++ b/src/tests/sss_idmap-tests.c -@@ -476,7 +476,7 @@ START_TEST(idmap_test_smb_sid2dom_sid) - "Samba dom_sid-s do not match."); - - sss_idmap_free_dom_sid(idmap_ctx, dom_sid); -- talloc_free(new_smb_sid); -+ sss_idmap_free_smb_sid(idmap_ctx, new_smb_sid); - } - END_TEST - -@@ -512,7 +512,7 @@ START_TEST(idmap_test_bin_sid2smb_sid) - fail_unless(memcmp(&test_smb_sid, smb_sid, sizeof(struct dom_sid)) == 0, - "Samba dom_sid structs do not match."); - -- talloc_free(smb_sid); -+ sss_idmap_free_smb_sid(idmap_ctx, smb_sid); - } - END_TEST - -@@ -543,7 +543,7 @@ START_TEST(idmap_test_sid2smb_sid) - fail_unless(memcmp(&test_smb_sid, smb_sid, sizeof(struct dom_sid)) == 0, - "Samba dom_sid structs do not match."); - -- talloc_free(smb_sid); -+ sss_idmap_free_smb_sid(idmap_ctx, smb_sid); - } - END_TEST - --- -1.8.4.2 - diff --git a/SOURCES/0022-free-idmapped-binary-SIDs-correctly.patch b/SOURCES/0022-free-idmapped-binary-SIDs-correctly.patch deleted file mode 100644 index 6ad0fd2..0000000 --- a/SOURCES/0022-free-idmapped-binary-SIDs-correctly.patch +++ /dev/null @@ -1,77 +0,0 @@ -From ccb2fe6ee1397b3c3d413d6c546cb88701958de3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Thu, 7 Nov 2013 11:09:48 +0100 -Subject: [PATCH 22/31] free idmapped binary SIDs correctly - -Resolves: -https://fedorahosted.org/sssd/ticket/2133 ---- - src/responder/nss/nsssrv_cmd.c | 2 +- - src/tests/sss_idmap-tests.c | 10 +++++----- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index 07f31188074bf45664969fb33388edb475e53b96..550017c0e4385a7147ed5ef83da2c37cb97c8092 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -4341,7 +4341,7 @@ static int nss_cmd_getbysid(enum sss_cli_command cmd, struct cli_ctx *cctx) - /* If the body isn't a SID, fail */ - err = sss_idmap_sid_to_bin_sid(nctx->idmap_ctx, sid_str, - &bin_sid, &bin_sid_length); -- talloc_free(bin_sid); -+ sss_idmap_free_bin_sid(nctx->idmap_ctx, bin_sid); - if (err != IDMAP_SUCCESS) { - DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_bin_sid failed for [%s].\n", - body)); -diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c -index 888be82248045058093d6943ef73742d8812eac3..f5ec68383679bfc685467bd625c86b8d6f474d48 100644 ---- a/src/tests/sss_idmap-tests.c -+++ b/src/tests/sss_idmap-tests.c -@@ -242,7 +242,7 @@ START_TEST(idmap_test_bin_sid2uid) - "sss_idmap_bin_sid_to_unix returned wrong id, " - "got [%d], expected [%d].", id, 1000 + IDMAP_RANGE_MIN); - -- talloc_free(bin_sid); -+ sss_idmap_free_bin_sid(idmap_ctx, bin_sid); - } - END_TEST - -@@ -331,7 +331,7 @@ START_TEST(idmap_test_uid2bin_sid) - "expected [%s], got [%s].", "S-1-5-21-1-2-3-1000", sid); - - sss_idmap_free_sid(idmap_ctx, sid); -- talloc_free(bin_sid); -+ sss_idmap_free_bin_sid(idmap_ctx, bin_sid); - } - END_TEST - -@@ -359,7 +359,7 @@ START_TEST(idmap_test_bin_sid2dom_sid) - "Binary SIDs do not match."); - - sss_idmap_free_dom_sid(idmap_ctx, dom_sid); -- talloc_free(new_bin_sid); -+ sss_idmap_free_bin_sid(idmap_ctx, new_bin_sid); - } - END_TEST - -@@ -437,7 +437,7 @@ START_TEST(idmap_test_sid2bin_sid) - fail_unless(memcmp(bin_sid, test_bin_sid, test_bin_sid_length) == 0, - "Binary SIDs do not match"); - -- talloc_free(bin_sid); -+ sss_idmap_free_bin_sid(idmap_ctx, bin_sid); - } - END_TEST - -@@ -496,7 +496,7 @@ START_TEST(idmap_test_smb_sid2bin_sid) - fail_unless(memcmp(bin_sid, test_bin_sid, test_bin_sid_length) == 0, - "Binary SIDs do not match."); - -- talloc_free(bin_sid); -+ sss_idmap_free_bin_sid(idmap_ctx, bin_sid); - } - END_TEST - --- -1.8.4.2 - diff --git a/SOURCES/0022-pyhbac-pysss-fix-reference-leaks.patch b/SOURCES/0022-pyhbac-pysss-fix-reference-leaks.patch new file mode 100644 index 0000000..180d730 --- /dev/null +++ b/SOURCES/0022-pyhbac-pysss-fix-reference-leaks.patch @@ -0,0 +1,122 @@ +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-Initialize-sid_str-to-NULL-to-avoid-freeing-random-d.patch b/SOURCES/0023-Initialize-sid_str-to-NULL-to-avoid-freeing-random-d.patch deleted file mode 100644 index 4839823..0000000 --- a/SOURCES/0023-Initialize-sid_str-to-NULL-to-avoid-freeing-random-d.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 456d952eecf2f068feafd2fff8bec8df84eba8ca Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 7 Nov 2013 12:00:43 +0100 -Subject: [PATCH 23/31] Initialize sid_str to NULL to avoid freeing random data - -If any function before failed, sss_idmap_free_sid() might have been -called with random data. ---- - src/providers/ad/ad_subdomains.c | 2 +- - src/providers/ldap/sdap_async_initgroups_ad.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index dd692fb699ddf14bcf8f9926383e82da77c494e0..100fb13e99f7bf4b3946b1f5c5f9c626674bfb46 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -234,7 +234,7 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx, - errno_t ret; - enum idmap_error_code err; - struct ldb_message_element *el; -- char *sid_str; -+ char *sid_str = NULL; - uint32_t trust_type; - bool mpg; - -diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c -index aa72c8876ba93eefc6230537801c50ab04e591ce..e58d93fb2da36febd6074381882192ba9e204e86 100644 ---- a/src/providers/ldap/sdap_async_initgroups_ad.c -+++ b/src/providers/ldap/sdap_async_initgroups_ad.c -@@ -361,7 +361,7 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq) - size_t user_count, group_count, i; - TALLOC_CTX *tmp_ctx; - bool in_transaction = false; -- char *sid_str; -+ char *sid_str = NULL; - gid_t gid; - time_t now; - struct sss_domain_info *group_domain; --- -1.8.4.2 - 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 new file mode 100644 index 0000000..5bdce3c --- /dev/null +++ b/SOURCES/0023-UTIL-Add-a-function-to-convert-id_t-from-a-number-or.patch @@ -0,0 +1,518 @@ +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 new file mode 100644 index 0000000..b75f699 --- /dev/null +++ b/SOURCES/0024-BUILD-Add-a-config-option-for-sssd-user-own-private-.patch @@ -0,0 +1,116 @@ +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-ad-refactor-tokengroups-initgroups.patch b/SOURCES/0024-ad-refactor-tokengroups-initgroups.patch deleted file mode 100644 index cd4ad74..0000000 --- a/SOURCES/0024-ad-refactor-tokengroups-initgroups.patch +++ /dev/null @@ -1,749 +0,0 @@ -From 8b581624e18d6f232d3174ed112d032bb6deffba Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 12 Nov 2013 13:52:40 +0100 -Subject: [PATCH 24/31] ad: refactor tokengroups initgroups - -sdap_get_ad_tokengroups_initgroups is split into more parts so -it can be reused later. ---- - src/providers/ldap/sdap_async.h | 20 +- - src/providers/ldap/sdap_async_initgroups.c | 16 +- - src/providers/ldap/sdap_async_initgroups_ad.c | 552 ++++++++++++++++---------- - 3 files changed, 357 insertions(+), 231 deletions(-) - -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index dbf572cdc82b100ba9c26b4853f05db1ba5fa4ed..67623454e675f648259c089acca59258f386ecdb 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -294,17 +294,17 @@ sdap_get_ad_match_rule_initgroups_recv(struct tevent_req *req); - - - struct tevent_req * --sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct sdap_options *opts, -- struct sysdb_ctx *sysdb, -- struct sss_domain_info *domain, -- struct sdap_handle *sh, -- const char *name, -- const char *orig_dn, -- int timeout); -+sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sdap_options *opts, -+ struct sysdb_ctx *sysdb, -+ struct sss_domain_info *domain, -+ struct sdap_handle *sh, -+ const char *name, -+ const char *orig_dn, -+ int timeout); - - errno_t --sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req); -+sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req); - - #endif /* _SDAP_ASYNC_H_ */ -diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c -index c16d484950e06c8474cc38db45b978b624473056..7d5cd2e7cbd86e2eb9774dfee1b8e31edec57b88 100644 ---- a/src/providers/ldap/sdap_async_initgroups.c -+++ b/src/providers/ldap/sdap_async_initgroups.c -@@ -2857,13 +2857,13 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) - /* Take advantage of AD's tokenGroups mechanism to look up all - * parent groups in a single request. - */ -- subreq = sdap_get_ad_tokengroups_initgroups_send(state, state->ev, -- state->opts, -- state->sysdb, -- state->dom, -- state->sh, -- cname, orig_dn, -- state->timeout); -+ subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev, -+ state->opts, -+ state->sysdb, -+ state->dom, -+ state->sh, -+ cname, orig_dn, -+ state->timeout); - } else if (state->opts->support_matching_rule - && dp_opt_get_bool(state->opts->basic, - SDAP_AD_MATCHING_RULE_INITGROUPS)) { -@@ -2952,7 +2952,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) - case SDAP_SCHEMA_AD: - if (state->use_id_mapping - && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) { -- ret = sdap_get_ad_tokengroups_initgroups_recv(subreq); -+ ret = sdap_ad_tokengroups_initgroups_recv(subreq); - } - else if (state->opts->support_matching_rule - && dp_opt_get_bool(state->opts->basic, -diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c -index e58d93fb2da36febd6074381882192ba9e204e86..7ba155338a358681c1bd201bee1c75f67afb4650 100644 ---- a/src/providers/ldap/sdap_async_initgroups_ad.c -+++ b/src/providers/ldap/sdap_async_initgroups_ad.c -@@ -298,96 +298,87 @@ sdap_get_ad_match_rule_initgroups_recv(struct tevent_req *req) - return EOK; - } - --struct sdap_ad_tokengroups_initgr_state { -+struct sdap_get_ad_tokengroups_state { - struct tevent_context *ev; -- struct sdap_options *opts; -- struct sysdb_ctx *sysdb; -- struct sss_domain_info *domain; -- struct sdap_handle *sh; -+ struct sss_idmap_ctx *idmap_ctx; - const char *username; -+ -+ char **sids; -+ size_t num_sids; - }; - --static void --sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *req); -+static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq); - --struct tevent_req * --sdap_get_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct sdap_options *opts, -- struct sysdb_ctx *sysdb, -- struct sss_domain_info *domain, -- struct sdap_handle *sh, -- const char *name, -- const char *orig_dn, -- int timeout) -+static struct tevent_req * -+sdap_get_ad_tokengroups_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sdap_options *opts, -+ struct sdap_handle *sh, -+ const char *name, -+ const char *orig_dn, -+ int timeout) - { -- struct tevent_req *req; -- struct tevent_req *subreq; -- struct sdap_ad_tokengroups_initgr_state *state; -+ struct sdap_get_ad_tokengroups_state *state = NULL; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; - const char *attrs[] = {AD_TOKENGROUPS_ATTR, NULL}; -+ errno_t ret; - - req = tevent_req_create(mem_ctx, &state, -- struct sdap_ad_tokengroups_initgr_state); -- if (!req) return NULL; -+ struct sdap_get_ad_tokengroups_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); -+ return NULL; -+ } - -+ state->idmap_ctx = opts->idmap_ctx->map; - state->ev = ev; -- state->opts = opts; -- state->sysdb = sysdb; -- state->domain = domain; -- state->sh = sh; -- state->username = name; -+ state->username = talloc_strdup(state, name); -+ if (state->username == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ subreq = sdap_get_generic_send(state, state->ev, opts, sh, orig_dn, -+ LDAP_SCOPE_BASE, NULL, attrs, -+ NULL, 0, timeout, false); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ tevent_req_set_callback(subreq, sdap_get_ad_tokengroups_done, req); -+ -+ return req; - -- subreq = sdap_get_generic_send( -- state, state->ev, state->opts, state->sh, -- orig_dn, LDAP_SCOPE_BASE, NULL, attrs, -- NULL, 0, timeout, false); -- if (!subreq) { -- tevent_req_error(req, ENOMEM); -- tevent_req_post(req, ev); -- return req; -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); - } -+ tevent_req_post(req, ev); - -- tevent_req_set_callback(subreq, -- sdap_get_ad_tokengroups_initgroups_lookup_done, -- req); - return req; - } - --static void --sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq) -+static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq) - { -- errno_t ret, sret; -+ TALLOC_CTX *tmp_ctx = NULL; -+ struct sdap_get_ad_tokengroups_state *state = NULL; -+ struct tevent_req *req = NULL; -+ struct sysdb_attrs **users = NULL; -+ struct ldb_message_element *el = NULL; - enum idmap_error_code err; -- size_t user_count, group_count, i; -- TALLOC_CTX *tmp_ctx; -- bool in_transaction = false; - char *sid_str = NULL; -- gid_t gid; -- time_t now; -- struct sss_domain_info *group_domain; -- struct sysdb_attrs **users; -- struct ldb_message_element *el; -- struct ldb_message *msg; -- struct ldb_dn *group_ldb_dn; -- const char *group_str_dn; -- char **ldap_grouplist; -- char **sysdb_grouplist; -- char **add_groups; -- char **del_groups; -- const char *attrs[] = { SYSDB_NAME, NULL }; -- const char *group_name; -- struct tevent_req *req = -- tevent_req_callback_data(subreq, struct tevent_req); -- struct sdap_ad_tokengroups_initgr_state *state = -- tevent_req_data(req, struct sdap_ad_tokengroups_initgr_state); -+ size_t num_users; -+ size_t i; -+ errno_t ret; - -- tmp_ctx = talloc_new(NULL); -- if (!tmp_ctx) { -- ret = ENOMEM; -- goto done; -- } -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state); - -- ret = sdap_get_generic_recv(subreq, tmp_ctx, &user_count, &users); -+ ret = sdap_get_generic_recv(subreq, tmp_ctx, &num_users, &users); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, -@@ -395,226 +386,361 @@ sdap_get_ad_tokengroups_initgroups_lookup_done(struct tevent_req *subreq) - goto done; - } - -- if (user_count != 1) { -+ if (num_users != 1) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("More than one result on a base search!\n")); - ret = EINVAL; - goto done; - } - -- /* Get the list of group SIDs */ -- ret = sysdb_attrs_get_el_ext(users[0], AD_TOKENGROUPS_ATTR, -- false, &el); -- if (ret != EOK) { -- if (ret == ENOENT) { -- DEBUG(SSSDBG_TRACE_LIBS, -- ("No tokenGroups entries for [%s]\n", -- state->username)); -- /* No groups in LDAP. We need to ensure that the -- * sysdb matches. -- */ -- el = talloc_zero(tmp_ctx, struct ldb_message_element); -- if (!el) { -- ret = ENOMEM; -- goto done; -- } -- el->num_values = 0; -+ /* get the list of sids from tokengroups */ -+ ret = sysdb_attrs_get_el_ext(users[0], AD_TOKENGROUPS_ATTR, false, &el); -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_TRACE_LIBS, ("No tokenGroups entries for [%s]\n", -+ state->username)); - -- /* This will skip the group-processing loop below -- * and proceed to removing any sysdb groups. -- */ -- } else { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Could not read tokenGroups attribute: [%s]\n", -- strerror(ret))); -- goto done; -- } -+ state->sids = NULL; -+ state->num_sids = 0; -+ ret = EOK; -+ goto done; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not read tokenGroups attribute: " -+ "[%s]\n", strerror(ret))); -+ goto done; - } - -- /* Process the groups */ -- now = time(NULL); -- -- ret = sysdb_transaction_start(state->sysdb); -- if (ret != EOK) goto done; -- in_transaction = true; -- -- ldap_grouplist = talloc_array(tmp_ctx, char *, el->num_values + 1); -- if (!ldap_grouplist) { -+ state->num_sids = 0; -+ state->sids = talloc_zero_array(state, char*, el->num_values); -+ if (state->sids == NULL) { - ret = ENOMEM; - goto done; - } -- group_count = 0; - -+ /* convert binary sid to string */ - for (i = 0; i < el->num_values; i++) { -- /* Get the SID and convert it to a GID */ -- -- err = sss_idmap_bin_sid_to_sid(state->opts->idmap_ctx->map, -- el->values[i].data, -- el->values[i].length, -- &sid_str); -+ err = sss_idmap_bin_sid_to_sid(state->idmap_ctx, el->values[i].data, -+ el->values[i].length, &sid_str); - if (err != IDMAP_SUCCESS) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Could not convert binary SID to string: [%s]. Skipping\n", - idmap_error_string(err))); - continue; - } -- DEBUG(SSSDBG_TRACE_LIBS, -- ("Processing membership SID [%s]\n", -- sid_str)); -- ret = sdap_idmap_sid_to_unix(state->opts->idmap_ctx, sid_str, -- &gid); -+ -+ state->sids[i] = talloc_move(state->sids, &sid_str); -+ state->num_sids++; -+ } -+ -+ /* shrink array to final number of elements */ -+ state->sids = talloc_realloc(state, state->sids, char*, state->num_sids); -+ if (state->sids == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t sdap_get_ad_tokengroups_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ size_t *_num_sids, -+ char ***_sids) -+{ -+ struct sdap_get_ad_tokengroups_state *state = NULL; -+ state = tevent_req_data(req, struct sdap_get_ad_tokengroups_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ if (_num_sids != NULL) { -+ *_num_sids = state->num_sids; -+ } -+ -+ if (_sids != NULL) { -+ *_sids = talloc_steal(mem_ctx, state->sids); -+ } -+ -+ return EOK; -+} -+ -+static errno_t -+sdap_ad_tokengroups_update_members(TALLOC_CTX *mem_ctx, -+ const char *username, -+ struct sysdb_ctx *sysdb, -+ struct sss_domain_info *domain, -+ char **ldap_groups) -+{ -+ TALLOC_CTX *tmp_ctx = NULL; -+ char **sysdb_groups = NULL; -+ char **add_groups = NULL; -+ char **del_groups = NULL; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n")); -+ return ENOMEM; -+ } -+ -+ /* Get the current sysdb group list for this user so we can update it. */ -+ ret = get_sysdb_grouplist_dn(tmp_ctx, sysdb, domain, -+ username, &sysdb_groups); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not get the list of groups for " -+ "[%s] in the sysdb: [%s]\n", username, strerror(ret))); -+ goto done; -+ } -+ -+ /* Find the differences between the sysdb and LDAP lists. -+ * Groups in the sysdb only must be removed. */ -+ ret = diff_string_lists(tmp_ctx, ldap_groups, sysdb_groups, -+ &add_groups, &del_groups, NULL); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, ("Updating memberships for [%s]\n", username)); -+ -+ ret = sysdb_update_members_dn(domain->sysdb, domain, username, -+ SYSDB_MEMBER_USER, -+ (const char *const *) add_groups, -+ (const char *const *) del_groups); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Membership update failed [%d]: %s\n", -+ ret, strerror(ret))); -+ goto done; -+ } -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+struct sdap_ad_tokengroups_initgroups_state { -+ struct sdap_idmap_ctx *idmap_ctx; -+ struct sysdb_ctx *sysdb; -+ struct sss_domain_info *domain; -+ const char *username; -+}; -+ -+static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq); -+ -+struct tevent_req * -+sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sdap_options *opts, -+ struct sysdb_ctx *sysdb, -+ struct sss_domain_info *domain, -+ struct sdap_handle *sh, -+ const char *name, -+ const char *orig_dn, -+ int timeout) -+{ -+ struct sdap_ad_tokengroups_initgroups_state *state = NULL; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct sdap_ad_tokengroups_initgroups_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); -+ return NULL; -+ } -+ -+ state->idmap_ctx = opts->idmap_ctx; -+ state->sysdb = sysdb; -+ state->domain = domain; -+ state->username = talloc_strdup(state, name); -+ if (state->username == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ subreq = sdap_get_ad_tokengroups_send(state, ev, opts, sh, name, orig_dn, -+ timeout); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgroups_done, req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq) -+{ -+ TALLOC_CTX *tmp_ctx = NULL; -+ struct sdap_ad_tokengroups_initgroups_state *state = NULL; -+ struct tevent_req *req = NULL; -+ struct sss_domain_info *domain = NULL; -+ struct ldb_message *msg = NULL; -+ const char *attrs[] = {SYSDB_NAME, NULL}; -+ const char *name = NULL; -+ const char *sid = NULL; -+ char **sids = NULL; -+ size_t num_sids; -+ size_t i; -+ time_t now; -+ gid_t gid; -+ char **groups = NULL; -+ size_t num_groups; -+ errno_t ret, sret; -+ bool in_transaction; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n")); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state); -+ -+ ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to acquire tokengroups [%d]: %s\n", -+ ret, strerror(ret))); -+ goto done; -+ } -+ -+ num_groups = 0; -+ groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1); -+ if (groups == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ now = time(NULL); -+ ret = sysdb_transaction_start(state->sysdb); -+ if (ret != EOK) { -+ goto done; -+ } -+ in_transaction = true; -+ -+ for (i = 0; i < num_sids; i++) { -+ sid = sids[i]; -+ DEBUG(SSSDBG_TRACE_LIBS, ("Processing membership SID [%s]\n", sid)); -+ -+ ret = sdap_idmap_sid_to_unix(state->idmap_ctx, sid, &gid); - if (ret == ENOTSUP) { - DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n")); - ret = EOK; - continue; - } else if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Could not convert SID to GID: [%s]. Skipping\n", -- strerror(ret))); -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not convert SID to GID: [%s]. " -+ "Skipping\n", strerror(ret))); - continue; - } - -- group_domain = find_subdomain_by_sid(get_domains_head(state->domain), -- sid_str); -- if (group_domain == NULL) { -- DEBUG(SSSDBG_MINOR_FAILURE, ("Domain not found for SID %s\n", -- sid_str)); -+ domain = find_subdomain_by_sid(get_domains_head(state->domain), sid); -+ if (domain == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Domain not found for SID %s\n", sid)); - continue; - } - -- DEBUG(SSSDBG_TRACE_LIBS, -- ("Processing membership GID [%"SPRIgid"]\n", gid)); -+ DEBUG(SSSDBG_TRACE_LIBS, ("SID [%s] maps to GID [%"SPRIgid"]\n", -+ sid, gid)); - - /* Check whether this GID already exists in the sysdb */ -- ret = sysdb_search_group_by_gid(tmp_ctx, group_domain->sysdb, -- group_domain, gid, attrs, &msg); -+ ret = sysdb_search_group_by_gid(tmp_ctx, domain->sysdb, domain, -+ gid, attrs, &msg); - if (ret == EOK) { -- group_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -- if (!group_name) { -+ name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -+ if (name == NULL) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Could not retrieve group name from sysdb\n")); - ret = EINVAL; - goto done; - } - } else if (ret == ENOENT) { -- /* This is a new group. For now, we will store it -- * under the name of its SID. When a direct lookup of -- * the group or its GID occurs, it will replace this -- * temporary entry. -- */ -- -- group_name = sid_str; -- ret = sysdb_add_incomplete_group(group_domain->sysdb, -- group_domain, -- group_name, gid, -- NULL, sid_str, false, now); -+ /* This is a new group. For now, we will store it under the name -+ * of its SID. When a direct lookup of the group or its GID occurs, -+ * it will replace this temporary entry. */ -+ name = sid; -+ ret = sysdb_add_incomplete_group(domain->sysdb, domain, name, gid, -+ NULL, sid, false, now); - if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Could not create incomplete group: [%s]\n", -- strerror(ret))); -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not create incomplete " -+ "group: [%s]\n", strerror(ret))); - goto done; - } - } else { - /* Unexpected error */ -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Could not look up group in sysdb: [%s]\n", -- strerror(ret))); -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not look up group in sysdb: " -+ "[%s]\n", strerror(ret))); - goto done; - } - -- group_ldb_dn = sysdb_group_dn(group_domain->sysdb, tmp_ctx, -- group_domain, group_name); -- if (group_ldb_dn == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("sysdb_group_dn() failed\n")); -+ groups[num_groups] = sysdb_group_strdn(tmp_ctx, domain->name, name); -+ if (groups[num_groups] == NULL) { - ret = ENOMEM; - goto done; - } -- -- group_str_dn = ldb_dn_get_linearized(group_ldb_dn); -- if (group_str_dn == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("ldb_dn_get_linearized() failed\n")); -- ret = EINVAL; -- goto done; -- } -- -- ldap_grouplist[group_count] = -- talloc_strdup(ldap_grouplist, group_str_dn); -- if (!ldap_grouplist[group_count]) { -- ret = ENOMEM; -- goto done; -- } -- -- talloc_zfree(group_ldb_dn); /* also frees group_str_dn */ -- group_str_dn = NULL; -- -- group_count++; -- } -- ldap_grouplist[group_count] = NULL; -- -- /* Get the current sysdb group list for this user -- * so we can update it. -- */ -- ret = get_sysdb_grouplist_dn(state, state->sysdb, state->domain, -- state->username, &sysdb_grouplist); -- if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Could not get the list of groups for [%s] in the sysdb: " -- "[%s]\n", -- state->username, strerror(ret))); -- goto done; -+ num_groups++; - } - -- /* Find the differences between the sysdb and LDAP lists -- * Groups in the sysdb only must be removed. -- */ -- ret = diff_string_lists(tmp_ctx, ldap_grouplist, sysdb_grouplist, -- &add_groups, &del_groups, NULL); -- if (ret != EOK) goto done; -+ groups[num_groups] = NULL; - -- DEBUG(SSSDBG_TRACE_LIBS, -- ("Updating memberships for [%s]\n", state->username)); -- ret = sysdb_update_members_dn(state->sysdb, state->domain, -- state->username, SYSDB_MEMBER_USER, -- (const char *const *) add_groups, -- (const char *const *) del_groups); -+ ret = sdap_ad_tokengroups_update_members(state, state->username, -+ state->sysdb, state->domain, -+ groups); - if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Membership update failed [%d]: %s\n", -- ret, strerror(ret))); -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Membership update failed [%d]: %s\n", -+ ret, strerror(ret))); - goto done; - } - - ret = sysdb_transaction_commit(state->sysdb); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- ("Could not commit transaction! [%s]\n", -- strerror(ret))); -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not commit transaction! [%s]\n", -+ strerror(ret))); - goto done; - } - in_transaction = false; - - done: -- sss_idmap_free_sid(state->opts->idmap_ctx->map, sid_str); -+ talloc_free(tmp_ctx); - - if (in_transaction) { - sret = sysdb_transaction_cancel(state->sysdb); -- DEBUG(SSSDBG_FATAL_FAILURE, -- ("Could not cancel transaction! [%s]\n", -- strerror(sret))); -+ DEBUG(SSSDBG_FATAL_FAILURE, ("Could not cancel transaction! [%s]\n", -+ strerror(sret))); - } - -- if (ret == EOK) { -- tevent_req_done(req); -- } else { -+ if (ret != EOK) { - tevent_req_error(req, ret); -+ return; - } -- talloc_free(tmp_ctx); -- return; -+ -+ tevent_req_done(req); - } - --errno_t --sdap_get_ad_tokengroups_initgroups_recv(struct tevent_req *req) -+errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req) - { - TEVENT_REQ_RETURN_ON_ERROR(req); -+ - return EOK; - } --- -1.8.4.2 - diff --git a/SOURCES/0025-RPM-Change-file-ownership-to-sssd.sssd.patch b/SOURCES/0025-RPM-Change-file-ownership-to-sssd.sssd.patch new file mode 100644 index 0000000..ff8be93 --- /dev/null +++ b/SOURCES/0025-RPM-Change-file-ownership-to-sssd.sssd.patch @@ -0,0 +1,67 @@ +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-ad-use-tokengroups-even-when-id-mapping-is-disabled.patch b/SOURCES/0025-ad-use-tokengroups-even-when-id-mapping-is-disabled.patch deleted file mode 100644 index 50f54c9..0000000 --- a/SOURCES/0025-ad-use-tokengroups-even-when-id-mapping-is-disabled.patch +++ /dev/null @@ -1,677 +0,0 @@ -From 6385798f807d370fe6685653e337f65bf59f21bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 12 Nov 2013 13:51:34 +0100 -Subject: [PATCH 25/31] ad: use tokengroups even when id mapping is disabled - -https://fedorahosted.org/sssd/ticket/1568 ---- - src/providers/ldap/sdap_async.h | 4 +- - src/providers/ldap/sdap_async_initgroups.c | 10 +- - src/providers/ldap/sdap_async_initgroups_ad.c | 537 +++++++++++++++++++++++++- - 3 files changed, 525 insertions(+), 26 deletions(-) - -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index 67623454e675f648259c089acca59258f386ecdb..f47437553a2d35dac90d86209848e840a237c3fb 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -296,13 +296,15 @@ sdap_get_ad_match_rule_initgroups_recv(struct tevent_req *req); - struct tevent_req * - sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, -+ struct sdap_id_ctx *id_ctx, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - struct sdap_handle *sh, - const char *name, - const char *orig_dn, -- int timeout); -+ int timeout, -+ bool use_id_mapping); - - errno_t - sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req); -diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c -index 7d5cd2e7cbd86e2eb9774dfee1b8e31edec57b88..1b865af0a113222b3c9c11e9401718abad577fd7 100644 ---- a/src/providers/ldap/sdap_async_initgroups.c -+++ b/src/providers/ldap/sdap_async_initgroups.c -@@ -2852,18 +2852,19 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) - return; - } - -- if (state->use_id_mapping -- && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) { -+ if (state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) { - /* Take advantage of AD's tokenGroups mechanism to look up all - * parent groups in a single request. - */ - subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev, -+ state->id_ctx, - state->opts, - state->sysdb, - state->dom, - state->sh, - cname, orig_dn, -- state->timeout); -+ state->timeout, -+ state->use_id_mapping); - } else if (state->opts->support_matching_rule - && dp_opt_get_bool(state->opts->basic, - SDAP_AD_MATCHING_RULE_INITGROUPS)) { -@@ -2950,8 +2951,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) - - case SDAP_SCHEMA_RFC2307BIS: - case SDAP_SCHEMA_AD: -- if (state->use_id_mapping -- && state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) { -+ if (state->opts->dc_functional_level >= DS_BEHAVIOR_WIN2008) { - ret = sdap_ad_tokengroups_initgroups_recv(subreq); - } - else if (state->opts->support_matching_rule -diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c -index 7ba155338a358681c1bd201bee1c75f67afb4650..8e0506831cb189415b62efaa378d3dc7ec350cde 100644 ---- a/src/providers/ldap/sdap_async_initgroups_ad.c -+++ b/src/providers/ldap/sdap_async_initgroups_ad.c -@@ -525,33 +525,180 @@ done: - return ret; - } - --struct sdap_ad_tokengroups_initgroups_state { -+struct sdap_ad_resolve_sids_state { -+ struct tevent_context *ev; -+ struct sdap_id_ctx *id_ctx; -+ struct sdap_options *opts; -+ struct sss_domain_info *domain; -+ char **sids; -+ -+ const char *current_sid; -+ int index; -+}; -+ -+static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req); -+static void sdap_ad_resolve_sids_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *id_ctx, -+ struct sdap_options *opts, -+ struct sss_domain_info *domain, -+ char **sids) -+{ -+ struct sdap_ad_resolve_sids_state *state = NULL; -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct sdap_ad_resolve_sids_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); -+ return NULL; -+ } -+ -+ state->ev = ev; -+ state->id_ctx = id_ctx; -+ state->opts = opts; -+ state->domain = get_domains_head(domain); -+ state->sids = sids; -+ state->index = 0; -+ -+ if (state->sids == NULL) { -+ ret = EOK; -+ goto immediately; -+ } -+ -+ ret = sdap_ad_resolve_sids_step(req); -+ if (ret != EAGAIN) { -+ goto immediately; -+ } -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req) -+{ -+ struct sdap_ad_resolve_sids_state *state = NULL; -+ struct tevent_req *subreq = NULL; -+ struct sdap_domain *sdap_domain = NULL; -+ struct sss_domain_info *domain = NULL; -+ -+ state = tevent_req_data(req, struct sdap_ad_resolve_sids_state); -+ -+ do { -+ state->current_sid = state->sids[state->index]; -+ if (state->current_sid == NULL) { -+ return EOK; -+ } -+ state->index++; -+ -+ domain = find_subdomain_by_sid(state->domain, state->current_sid); -+ if (domain == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("SID %s does not belong to any known " -+ "domain\n", state->current_sid)); -+ } -+ } while (domain == NULL); -+ -+ sdap_domain = sdap_domain_get(state->opts, domain); -+ if (sdap_domain == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("SDAP domain does not exist?\n")); -+ return ERR_INTERNAL; -+ } -+ -+ subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain, -+ state->id_ctx->conn, state->current_sid, -+ BE_FILTER_SECID, BE_ATTR_CORE, false); -+ if (subreq == NULL) { -+ return ENOMEM; -+ } -+ -+ tevent_req_set_callback(subreq, sdap_ad_resolve_sids_done, req); -+ -+ return EAGAIN; -+} -+ -+static void sdap_ad_resolve_sids_done(struct tevent_req *subreq) -+{ -+ struct sdap_ad_resolve_sids_state *state = NULL; -+ struct tevent_req *req = NULL; -+ int dp_error; -+ int sdap_error; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct sdap_ad_resolve_sids_state); -+ -+ ret = groups_get_recv(subreq, &dp_error, &sdap_error); -+ talloc_zfree(subreq); -+ if (ret != EOK || sdap_error != EOK || dp_error != DP_ERR_OK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to resolve SID %s [dp_error: %d, " -+ "sdap_error: %d, ret: %d]: %s\n", state->current_sid, dp_error, -+ sdap_error, ret, strerror(ret))); -+ goto done; -+ } -+ -+ ret = sdap_ad_resolve_sids_step(req); -+ if (ret == EAGAIN) { -+ /* continue with next SID */ -+ return; -+ } -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t sdap_ad_resolve_sids_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -+ -+ -+struct sdap_ad_tokengroups_initgr_mapping_state { - struct sdap_idmap_ctx *idmap_ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; - const char *username; - }; - --static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq); -+static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq); - --struct tevent_req * --sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct sdap_options *opts, -- struct sysdb_ctx *sysdb, -- struct sss_domain_info *domain, -- struct sdap_handle *sh, -- const char *name, -- const char *orig_dn, -- int timeout) -+static struct tevent_req * -+sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sdap_options *opts, -+ struct sysdb_ctx *sysdb, -+ struct sss_domain_info *domain, -+ struct sdap_handle *sh, -+ const char *name, -+ const char *orig_dn, -+ int timeout) - { -- struct sdap_ad_tokengroups_initgroups_state *state = NULL; -+ struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; - struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; - errno_t ret; - - req = tevent_req_create(mem_ctx, &state, -- struct sdap_ad_tokengroups_initgroups_state); -+ struct sdap_ad_tokengroups_initgr_mapping_state); - if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); - return NULL; -@@ -573,7 +720,8 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, - goto immediately; - } - -- tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgroups_done, req); -+ tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_mapping_done, -+ req); - - return req; - -@@ -588,10 +736,10 @@ immediately: - return req; - } - --static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq) -+static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq) - { - TALLOC_CTX *tmp_ctx = NULL; -- struct sdap_ad_tokengroups_initgroups_state *state = NULL; -+ struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; - struct tevent_req *req = NULL; - struct sss_domain_info *domain = NULL; - struct ldb_message *msg = NULL; -@@ -599,14 +747,14 @@ static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq) - const char *name = NULL; - const char *sid = NULL; - char **sids = NULL; -- size_t num_sids; -+ size_t num_sids = 0; - size_t i; - time_t now; - gid_t gid; - char **groups = NULL; - size_t num_groups; - errno_t ret, sret; -- bool in_transaction; -+ bool in_transaction = false; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { -@@ -616,7 +764,7 @@ 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); -+ state = tevent_req_data(req, struct sdap_ad_tokengroups_initgr_mapping_state); - - ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids); - talloc_zfree(subreq); -@@ -738,6 +886,355 @@ done: - tevent_req_done(req); - } - -+static int sdap_ad_tokengroups_initgr_mapping_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -+ -+struct sdap_ad_tokengroups_initgr_posix_state { -+ struct tevent_context *ev; -+ struct sdap_id_ctx *id_ctx; -+ struct sdap_options *opts; -+ struct sysdb_ctx *sysdb; -+ struct sss_domain_info *domain; -+ const char *username; -+}; -+ -+static void -+sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq); -+ -+static void -+sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *id_ctx, -+ struct sdap_options *opts, -+ struct sysdb_ctx *sysdb, -+ struct sss_domain_info *domain, -+ struct sdap_handle *sh, -+ const char *name, -+ const char *orig_dn, -+ int timeout) -+{ -+ struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct sdap_ad_tokengroups_initgr_posix_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); -+ return NULL; -+ } -+ -+ state->ev = ev; -+ state->id_ctx = id_ctx; -+ state->opts = opts; -+ state->sysdb = sysdb; -+ state->domain = domain; -+ state->username = talloc_strdup(state, name); -+ if (state->username == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ subreq = sdap_get_ad_tokengroups_send(state, ev, opts, sh, name, orig_dn, -+ timeout); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_tg_done, -+ req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void -+sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq) -+{ -+ TALLOC_CTX *tmp_ctx = NULL; -+ struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; -+ struct tevent_req *req = NULL; -+ struct sss_domain_info *domain = NULL; -+ struct ldb_message *msg = NULL; -+ const char *attrs[] = {SYSDB_NAME, SYSDB_POSIX, NULL}; -+ const char *is_posix = NULL; -+ const char *name = NULL; -+ char *sid = NULL; -+ char **sids = NULL; -+ size_t num_sids = 0; -+ char **valid_groups = NULL; -+ size_t num_valid_groups; -+ char **missing_sids = NULL; -+ size_t num_missing_sids; -+ size_t i; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n")); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, -+ struct sdap_ad_tokengroups_initgr_posix_state); -+ -+ ret = sdap_get_ad_tokengroups_recv(state, subreq, &num_sids, &sids); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to acquire tokengroups [%d]: %s\n", -+ ret, strerror(ret))); -+ goto done; -+ } -+ -+ num_valid_groups = 0; -+ valid_groups = talloc_zero_array(tmp_ctx, char*, num_sids + 1); -+ if (valid_groups == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ num_missing_sids = 0; -+ missing_sids = talloc_zero_array(tmp_ctx, char*, num_sids + 1); -+ if (missing_sids == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* For each SID check if it is already present in the cache. If yes, we -+ * will get name of the group and update the membership. Otherwise we need -+ * to remember the SID and download missing groups one by one. */ -+ for (i = 0; i < num_sids; i++) { -+ sid = sids[i]; -+ DEBUG(SSSDBG_TRACE_LIBS, ("Processing membership SID [%s]\n", sid)); -+ -+ domain = find_subdomain_by_sid(get_domains_head(state->domain), sid); -+ if (domain == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Domain not found for SID %s\n", sid)); -+ continue; -+ } -+ -+ ret = sysdb_search_group_by_sid_str(tmp_ctx, domain->sysdb, domain, -+ sid, attrs, &msg); -+ if (ret == EOK) { -+ is_posix = ldb_msg_find_attr_as_string(msg, SYSDB_POSIX, NULL); -+ if (is_posix != NULL && strcmp(is_posix, "FALSE") == 0) { -+ /* skip non-posix group */ -+ continue; -+ } -+ -+ /* we will update membership of this group */ -+ name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -+ if (name == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("Could not retrieve group name from sysdb\n")); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ valid_groups[num_valid_groups] = sysdb_group_strdn(tmp_ctx, -+ domain->name, -+ name); -+ if (valid_groups[num_valid_groups] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ num_valid_groups++; -+ } else if (ret == ENOENT) { -+ /* we need to download this group */ -+ missing_sids[num_missing_sids] = talloc_steal(missing_sids, sid); -+ num_missing_sids++; -+ -+ DEBUG(SSSDBG_TRACE_FUNC, ("Missing SID %s will be downloaded\n", -+ sid)); -+ } else { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not look up group in sysdb: " -+ "[%s]\n", strerror(ret))); -+ goto done; -+ } -+ } -+ -+ valid_groups[num_valid_groups] = NULL; -+ missing_sids[num_missing_sids] = NULL; -+ -+ /* update membership of existing groups */ -+ ret = sdap_ad_tokengroups_update_members(state, state->username, -+ state->sysdb, state->domain, -+ valid_groups); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Membership update failed [%d]: %s\n", -+ ret, strerror(ret))); -+ goto done; -+ } -+ -+ /* download missing SIDs */ -+ missing_sids = talloc_steal(state, missing_sids); -+ subreq = sdap_ad_resolve_sids_send(state, state->ev, state->id_ctx, -+ state->opts, state->domain, -+ missing_sids); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_sids_done, -+ req); -+ -+ return; -+ -+done: -+ talloc_free(tmp_ctx); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static void -+sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ -+ ret = sdap_ad_resolve_sids_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to resolve missing SIDs " -+ "[%d]: %s\n", ret, strerror(ret))); -+ goto done; -+ } -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -+ -+struct sdap_ad_tokengroups_initgroups_state { -+ bool use_id_mapping; -+}; -+ -+static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq); -+ -+struct tevent_req * -+sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *id_ctx, -+ struct sdap_options *opts, -+ struct sysdb_ctx *sysdb, -+ struct sss_domain_info *domain, -+ struct sdap_handle *sh, -+ const char *name, -+ const char *orig_dn, -+ int timeout, -+ bool use_id_mapping) -+{ -+ struct sdap_ad_tokengroups_initgroups_state *state = NULL; -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct sdap_ad_tokengroups_initgroups_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n")); -+ return NULL; -+ } -+ -+ state->use_id_mapping = use_id_mapping; -+ -+ if (state->use_id_mapping) { -+ subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts, -+ sysdb, domain, sh, -+ name, orig_dn, -+ timeout); -+ } else { -+ subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, opts, -+ sysdb, domain, sh, -+ name, orig_dn, -+ timeout); -+ } -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgroups_done, req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq) -+{ -+ struct sdap_ad_tokengroups_initgroups_state *state = NULL; -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ 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) { -+ ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq); -+ } else { -+ ret = sdap_ad_tokengroups_initgr_posix_recv(subreq); -+ } -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ - errno_t sdap_ad_tokengroups_initgroups_recv(struct tevent_req *req) - { - TEVENT_REQ_RETURN_ON_ERROR(req); --- -1.8.4.2 - diff --git a/SOURCES/0026-AD-filter-domain-local-groups-for-trusted-sub-domain.patch b/SOURCES/0026-AD-filter-domain-local-groups-for-trusted-sub-domain.patch deleted file mode 100644 index a0be4bd..0000000 --- a/SOURCES/0026-AD-filter-domain-local-groups-for-trusted-sub-domain.patch +++ /dev/null @@ -1,309 +0,0 @@ -From 8d55e0fffd29184d44cb49eaab2ca3a4226e0123 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 10 Dec 2013 10:14:28 +0100 -Subject: [PATCH 26/31] AD: filter domain local groups for trusted/sub domains - -In Active Directory groups with a domain local scope should only be used -inside of the specific domain. Since SSSD read the group memberships -from LDAP server of the user's domain the domain local groups are -included in the LDAP result. Those groups should be filtered out if the -domain is a sub/trusted domain, i.e. is not the domain the client -running SSSD is joined to. - -The groups will still be in the cache but marked as non-POSIX groups and -no GID will be assigned. - -Fixes https://fedorahosted.org/sssd/ticket/2178 ---- - src/providers/ldap/sdap.h | 8 ++ - src/providers/ldap/sdap_async_groups.c | 160 ++++++++++++++++---------- - src/providers/ldap/sdap_async_initgroups_ad.c | 6 +- - src/providers/ldap/sdap_async_nested_groups.c | 28 ++++- - 4 files changed, 138 insertions(+), 64 deletions(-) - -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index fa641730bb78b6a96c0b9640af7612b876f56533..a7ea94eb810a96b61862bd8cc6fcd800c3e8e0cb 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -137,6 +137,14 @@ struct sdap_ppolicy_data { - #define SDAP_AD_USN "uSNChanged" - #define SDAP_AD_LAST_USN "highestCommittedUSN" - -+#define SDAP_AD_GROUP_TYPE_BUILTIN 0x00000001 -+#define SDAP_AD_GROUP_TYPE_GLOBAL 0x00000002 -+#define SDAP_AD_GROUP_TYPE_DOMAIN_LOCAL 0x00000004 -+#define SDAP_AD_GROUP_TYPE_UNIVERSAL 0x00000008 -+#define SDAP_AD_GROUP_TYPE_APP_BASIC 0x00000010 -+#define SDAP_AD_GROUP_TYPE_APP_QUERY 0x00000020 -+#define SDAP_AD_GROUP_TYPE_SECURITY 0x80000000 -+ - enum sdap_basic_opt { - SDAP_URI = 0, - SDAP_BACKUP_URI, -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 9f7e3e55d0234e9aa7b9e59456044587bcad88ef..33648c5da367c908d085a71a9a9017cb294bb300 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -451,6 +451,7 @@ static int sdap_save_group(TALLOC_CTX *memctx, - bool posix_group; - bool use_id_mapping; - char *sid_str; -+ int32_t ad_group_type; - - tmpctx = talloc_new(NULL); - if (!tmpctx) { -@@ -503,74 +504,113 @@ static int sdap_save_group(TALLOC_CTX *memctx, - } - DEBUG(SSSDBG_TRACE_FUNC, ("Processing group %s\n", group_name)); - -- use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx, -- dom->name, -- sid_str); -- if (use_id_mapping) { -- posix_group = true; -- -- if (sid_str == NULL) { -- DEBUG(SSSDBG_MINOR_FAILURE, ("SID not available, cannot map a " \ -- "unix ID to group [%s].\n", group_name)); -- ret = ENOENT; -+ 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; - } - -- DEBUG(SSSDBG_TRACE_LIBS, -- ("Mapping group [%s] objectSID [%s] to unix ID\n", -- group_name, sid_str)); -- -- /* Convert the SID into a UNIX group ID */ -- ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &gid); -- if (ret == ENOTSUP) { -- /* ENOTSUP is returned if built-in SID was provided -- * => do not store the group, but return EOK */ -- DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n")); -- ret = EOK; -- goto done; -- } else if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Could not convert SID string: [%s]\n", -- strerror(ret))); -- goto done; -+ DEBUG(SSSDBG_TRACE_ALL, ("AD group [%s] has type flags %#x.", -+ 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_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, -+ ("Error: Failed to mark group as non-posix!\n")); -+ return ret; -+ } - } -+ } - -- /* Store the GID in the ldap_attrs so it doesn't get -- * treated as a missing attribute from LDAP and removed. -- */ -- ret = sdap_replace_id(attrs, SYSDB_GIDNUM, gid); -- if (ret) { -- DEBUG(SSSDBG_OP_FAILURE, ("Cannot set the id-mapped GID\n")); -- goto done; -- } -- } else { -- ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix_group); -- if (ret == ENOENT) { -+ if (posix_group) { -+ use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping(opts->idmap_ctx, -+ dom->name, -+ sid_str); -+ if (use_id_mapping) { - posix_group = true; -- } else if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Error reading posix attribute: [%s]\n", -- strerror(ret))); -- goto done; -- } - -- DEBUG(8, ("This is%s a posix group\n", (posix_group)?"":" not")); -- ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, posix_group); -- if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Error setting posix attribute: [%s]\n", -- strerror(ret))); -- goto done; -- } -+ if (sid_str == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("SID not available, cannot map a " \ -+ "unix ID to group [%s].\n", group_name)); -+ ret = ENOENT; -+ goto done; -+ } - -- ret = sysdb_attrs_get_uint32_t(attrs, -- opts->group_map[SDAP_AT_GROUP_GID].sys_name, -- &gid); -- if (ret != EOK) { -- DEBUG(1, ("no gid provided for [%s] in domain [%s].\n", -- group_name, dom->name)); -- ret = EINVAL; -- goto done; -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("Mapping group [%s] objectSID [%s] to unix ID\n", -+ group_name, sid_str)); -+ -+ /* Convert the SID into a UNIX group ID */ -+ ret = sdap_idmap_sid_to_unix(opts->idmap_ctx, sid_str, &gid); -+ if (ret == ENOTSUP) { -+ /* ENOTSUP is returned if built-in SID was provided -+ * => do not store the group, but return EOK */ -+ DEBUG(SSSDBG_TRACE_FUNC, ("Skipping built-in object.\n")); -+ ret = EOK; -+ goto done; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("Could not convert SID string: [%s]\n", -+ strerror(ret))); -+ goto done; -+ } -+ -+ /* Store the GID in the ldap_attrs so it doesn't get -+ * treated as a missing attribute from LDAP and removed. -+ */ -+ ret = sdap_replace_id(attrs, SYSDB_GIDNUM, gid); -+ if (ret) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot set the id-mapped GID\n")); -+ goto done; -+ } -+ } else { -+ ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix_group); -+ if (ret == ENOENT) { -+ posix_group = true; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("Error reading posix attribute: [%s]\n", -+ strerror(ret))); -+ goto done; -+ } -+ -+ DEBUG(8, ("This is%s a posix group\n", (posix_group)?"":" not")); -+ ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, posix_group); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("Error setting posix attribute: [%s]\n", -+ strerror(ret))); -+ goto done; -+ } -+ -+ ret = sysdb_attrs_get_uint32_t(attrs, -+ opts->group_map[SDAP_AT_GROUP_GID].sys_name, -+ &gid); -+ if (ret != EOK) { -+ DEBUG(1, ("no gid provided for [%s] in domain [%s].\n", -+ group_name, dom->name)); -+ ret = EINVAL; -+ goto done; -+ } - } - } - -diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c -index 8e0506831cb189415b62efaa378d3dc7ec350cde..f1bf77e8614c30b214118140e380c23c40c1195b 100644 ---- a/src/providers/ldap/sdap_async_initgroups_ad.c -+++ b/src/providers/ldap/sdap_async_initgroups_ad.c -@@ -1145,6 +1145,7 @@ static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req) - - struct sdap_ad_tokengroups_initgroups_state { - bool use_id_mapping; -+ struct sss_domain_info *domain; - }; - - static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq); -@@ -1175,8 +1176,9 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, - } - - state->use_id_mapping = use_id_mapping; -+ state->domain = domain; - -- if (state->use_id_mapping) { -+ if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) { - subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts, - sysdb, domain, sh, - name, orig_dn, -@@ -1216,7 +1218,7 @@ 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) { -+ if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) { - ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq); - } else { - ret = sdap_ad_tokengroups_initgr_posix_recv(subreq); -diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c -index c107b700b84b8c178051fd4505f3947be8373de2..f58564aec0628c827672950f767401ee32051b59 100644 ---- a/src/providers/ldap/sdap_async_nested_groups.c -+++ b/src/providers/ldap/sdap_async_nested_groups.c -@@ -239,15 +239,39 @@ 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; -+ int32_t ad_group_type; -+ bool posix_group = true; -+ -+ 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; -+ } -+ -+ 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")); -+ } -+ } - - ret = sysdb_attrs_get_uint32_t(group, map[SDAP_AT_GROUP_GID].sys_name, - &gid); -- if (ret == ENOENT || (ret == EOK && gid == 0)) { -+ if (ret == ENOENT || (ret == EOK && gid == 0) || !posix_group) { - DEBUG(SSSDBG_TRACE_ALL, - ("The group's gid was %s\n", ret == ENOENT ? "missing" : "zero")); - DEBUG(SSSDBG_TRACE_INTERNAL, - ("Marking group as non-posix and setting GID=0!\n")); -- if (ret == ENOENT) { -+ if (ret == ENOENT || !posix_group) { - ret = sysdb_attrs_add_uint32(group, - map[SDAP_AT_GROUP_GID].sys_name, 0); - if (ret != EOK) { --- -1.8.4.2 - 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 new file mode 100644 index 0000000..646f2f7 --- /dev/null +++ b/SOURCES/0026-SSSD-Load-a-user-to-run-a-service-as-from-configurat.patch @@ -0,0 +1,216 @@ +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-AD-cross-domain-membership-fix.patch b/SOURCES/0027-AD-cross-domain-membership-fix.patch deleted file mode 100644 index 5f273b4..0000000 --- a/SOURCES/0027-AD-cross-domain-membership-fix.patch +++ /dev/null @@ -1,639 +0,0 @@ -From 402af69c0bb7ea8b84e36f3567de6086042cb152 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 18 Dec 2013 13:47:31 +0100 -Subject: [PATCH 27/31] AD: cross-domain membership fix - -A recent patch directed all call related to group membership lookups to -the AD LDAP port to fix an issue related to missing group memberships in -the Global Catalog. As a side-effect it broke cross-domain -group-memberships because those cannot be resolved by the connection to -the LDAP port. - -The patch tires to fix this by restoring the original behaviour in the -top-level lookup calls in the AD provider and switching to the LDAP port -only for the LDAP request which is expected to return the full group -membership. - -Additionally this patch contains a related fix for the tokenGroups with -Posix attributes patch. The original connection, typically a Global -Catalog connection in the AD case is passed down the stack so that the -group lookup after the tokenGroups request can run over the same -connection. ---- - src/providers/ad/ad_id.c | 19 +-- - src/providers/ad/ad_init.c | 2 + - src/providers/ldap/sdap_async.h | 1 + - src/providers/ldap/sdap_async_groups.c | 62 +++++++- - src/providers/ldap/sdap_async_initgroups.c | 50 ++++++- - src/providers/ldap/sdap_async_initgroups_ad.c | 197 ++++++++++++++++++++++---- - 6 files changed, 281 insertions(+), 50 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 19bc65825be21c6419db1e92db642be0a14b97a8..cf71b172dd7c241a9280a7ea72ef2518f66a7435 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -199,6 +199,8 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - case BE_REQ_USER: /* user */ - case BE_REQ_BY_SECID: /* by SID */ - case BE_REQ_USER_AND_GROUP: /* get SID */ -+ case BE_REQ_GROUP: /* group */ -+ case BE_REQ_INITGROUPS: /* init groups for user */ - /* Always try GC first */ - clist[0] = ad_ctx->gc_ctx; - if (IS_SUBDOMAIN(dom) == true) { -@@ -215,23 +217,6 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - */ - clist[1] = ad_ctx->ldap_ctx; - break; -- -- case BE_REQ_GROUP: /* group */ -- case BE_REQ_INITGROUPS: /* init groups for user */ -- if (IS_SUBDOMAIN(dom)) { -- sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom); -- if (sdom == NULL || sdom->pvt == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", -- dom->name)); -- return NULL; -- } -- subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); -- clist[0] = subdom_id_ctx->ldap_ctx; -- } else { -- clist[0] = ad_ctx->ldap_ctx; -- } -- break; -- - default: - clist[0] = ad_ctx->ldap_ctx; - break; -diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c -index d06efbd082bd6bba74fb6616c7dd722c99244988..332bfda3801db3824ce1896d37e65e2c3a6b8b8b 100644 ---- a/src/providers/ad/ad_init.c -+++ b/src/providers/ad/ad_init.c -@@ -214,6 +214,8 @@ sssm_ad_id_init(struct be_ctx *bectx, - goto done; - } - -+ ad_ctx->sdap_id_ctx->opts->sdom->pvt = ad_ctx; -+ - /* Set up the ID mapping object */ - ret = sdap_idmap_init(ad_ctx->sdap_id_ctx, ad_ctx->sdap_id_ctx, - &ad_ctx->sdap_id_ctx->opts->idmap_ctx); -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index f47437553a2d35dac90d86209848e840a237c3fb..33e8708ab7e80ab4280df300fdc300d4ecd18305 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -297,6 +297,7 @@ struct tevent_req * - sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_ctx *id_ctx, -+ struct sdap_id_conn_ctx *conn, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 33648c5da367c908d085a71a9a9017cb294bb300..9eece9a6e4baaf302a28b57a63dae45a0741136c 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -26,6 +26,7 @@ - #include "providers/ldap/sdap_async_private.h" - #include "providers/ldap/ldap_common.h" - #include "providers/ldap/sdap_idmap.h" -+#include "providers/ad/ad_common.h" - - /* ==Group-Parsing Routines=============================================== */ - -@@ -1540,9 +1541,13 @@ struct sdap_get_groups_state { - - size_t base_iter; - struct sdap_search_base **search_bases; -+ -+ struct sdap_handle *ldap_sh; -+ struct sdap_id_op *op; - }; - - static errno_t sdap_get_groups_next_base(struct tevent_req *req); -+static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq); - static void sdap_get_groups_process(struct tevent_req *subreq); - static void sdap_get_groups_done(struct tevent_req *subreq); - -@@ -1558,7 +1563,9 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, - { - errno_t ret; - struct tevent_req *req; -+ struct tevent_req *subreq; - struct sdap_get_groups_state *state; -+ struct ad_id_ctx *subdom_id_ctx; - - req = tevent_req_create(memctx, &state, struct sdap_get_groups_state); - if (!req) return NULL; -@@ -1586,6 +1593,30 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, - goto done; - } - -+ /* With AD by default the Global Catalog is used for lookup. But the GC -+ * group object might not have full group membership data. To make sure we -+ * connect to an LDAP server of the group's domain. */ -+ if (state->opts->schema_type == SDAP_SCHEMA_AD && sdom->pvt != NULL) { -+ subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); -+ state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); -+ if (!state->op) { -+ DEBUG(2, ("sdap_id_op_create failed\n")); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ subreq = sdap_id_op_connect_send(state->op, state, &ret); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ tevent_req_set_callback(subreq, -+ sdap_get_groups_ldap_connect_done, -+ req); -+ return req; -+ } -+ - ret = sdap_get_groups_next_base(req); - - done: -@@ -1597,6 +1628,34 @@ done: - return req; - } - -+static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req; -+ struct sdap_get_groups_state *state; -+ int ret; -+ int dp_error; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct sdap_get_groups_state); -+ -+ ret = sdap_id_op_connect_recv(subreq, &dp_error); -+ talloc_zfree(subreq); -+ -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->ldap_sh = sdap_id_op_handle(state->op); -+ -+ ret = sdap_get_groups_next_base(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } -+ -+ return; -+} -+ - static errno_t sdap_get_groups_next_base(struct tevent_req *req) - { - struct tevent_req *subreq; -@@ -1617,7 +1676,8 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - state->search_bases[state->base_iter]->basedn)); - - subreq = sdap_get_generic_send( -- state, state->ev, state->opts, state->sh, -+ 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, -diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c -index 1b865af0a113222b3c9c11e9401718abad577fd7..aba7ba42dade8923ae91f5bc8962e03d038c15a1 100644 ---- a/src/providers/ldap/sdap_async_initgroups.c -+++ b/src/providers/ldap/sdap_async_initgroups.c -@@ -2749,6 +2749,10 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) - const char *orig_dn; - const char *cname; - bool in_transaction = false; -+ char *expected_basedn; -+ size_t expected_basedn_len; -+ size_t dn_len; -+ size_t c = 0; - - DEBUG(9, ("Receiving info for the user\n")); - -@@ -2788,11 +2792,50 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) - } else if (count != 1) { - DEBUG(SSSDBG_OP_FAILURE, - ("Expected one user entry and got %zu\n", count)); -- tevent_req_error(req, EINVAL); -- return; -+ -+ ret = domain_to_basedn(state, state->dom->name, &expected_basedn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("domain_to_basedn failed.\n")); -+ tevent_req_error(req, ret); -+ return; -+ } -+ expected_basedn = talloc_asprintf(state, "%s%s", -+ "cn=users,", expected_basedn); -+ if (expected_basedn == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_append failed.\n")); -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_ALL, ("Expected BaseDN is [%s].\n", expected_basedn)); -+ expected_basedn_len = strlen(expected_basedn); -+ -+ for (c = 0; c < count; c++) { -+ ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); -+ tevent_req_error(req, ret); -+ return; -+ } -+ dn_len = strlen(orig_dn); -+ -+ if (dn_len > expected_basedn_len -+ && strcasecmp(orig_dn + (dn_len - expected_basedn_len), -+ expected_basedn) == 0) { -+ DEBUG(SSSDBG_TRACE_ALL, -+ ("Found matching dn [%s].\n", orig_dn)); -+ break; -+ } -+ } -+ -+ if (c == count) { -+ DEBUG(SSSDBG_OP_FAILURE, ("No matching DN found.\n")); -+ tevent_req_error(req, EINVAL); -+ return; -+ } - } - -- state->orig_user = usr_attrs[0]; -+ state->orig_user = usr_attrs[c]; - - ret = sysdb_transaction_start(state->sysdb); - if (ret) { -@@ -2858,6 +2901,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) - */ - subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev, - state->id_ctx, -+ state->conn, - state->opts, - state->sysdb, - state->dom, -diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c -index f1bf77e8614c30b214118140e380c23c40c1195b..8f8f0a4cc635818dcc7f75f9da603ce2f55c820f 100644 ---- a/src/providers/ldap/sdap_async_initgroups_ad.c -+++ b/src/providers/ldap/sdap_async_initgroups_ad.c -@@ -25,6 +25,7 @@ - #include "providers/ldap/ldap_common.h" - #include "providers/ldap/sdap_async_private.h" - #include "providers/ldap/sdap_idmap.h" -+#include "providers/ad/ad_common.h" - #include "lib/idmap/sss_idmap.h" - - struct sdap_ad_match_rule_initgr_state { -@@ -528,6 +529,7 @@ done: - struct sdap_ad_resolve_sids_state { - struct tevent_context *ev; - struct sdap_id_ctx *id_ctx; -+ struct sdap_id_conn_ctx *conn; - struct sdap_options *opts; - struct sss_domain_info *domain; - char **sids; -@@ -543,6 +545,7 @@ static struct tevent_req * - sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_ctx *id_ctx, -+ struct sdap_id_conn_ctx *conn, - struct sdap_options *opts, - struct sss_domain_info *domain, - char **sids) -@@ -560,6 +563,7 @@ sdap_ad_resolve_sids_send(TALLOC_CTX *mem_ctx, - - state->ev = ev; - state->id_ctx = id_ctx; -+ state->conn = conn; - state->opts = opts; - state->domain = get_domains_head(domain); - state->sids = sids; -@@ -618,7 +622,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->id_ctx->conn, state->current_sid, -+ state->conn, state->current_sid, - BE_FILTER_SECID, BE_ATTR_CORE, false); - if (subreq == NULL) { - return ENOMEM; -@@ -673,12 +677,21 @@ static errno_t sdap_ad_resolve_sids_recv(struct tevent_req *req) - - - struct sdap_ad_tokengroups_initgr_mapping_state { -+ struct tevent_context *ev; -+ struct sdap_options *opts; -+ struct sdap_handle *sh; - struct sdap_idmap_ctx *idmap_ctx; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; -+ const char *orig_dn; -+ int timeout; - const char *username; -+ -+ struct sdap_id_op *op; - }; - -+static void -+sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq); - static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq); - - static struct tevent_req * -@@ -695,6 +708,8 @@ sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, - struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; - struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; -+ struct sdap_domain *sdom; -+ struct ad_id_ctx *subdom_id_ctx; - errno_t ret; - - req = tevent_req_create(mem_ctx, &state, -@@ -704,36 +719,92 @@ sdap_ad_tokengroups_initgr_mapping_send(TALLOC_CTX *mem_ctx, - return NULL; - } - -+ state->ev = ev; -+ state->opts = opts; -+ state->sh = sh; - state->idmap_ctx = opts->idmap_ctx; - state->sysdb = sysdb; - state->domain = domain; -+ state->timeout = timeout; -+ state->orig_dn = orig_dn; - state->username = talloc_strdup(state, name); - if (state->username == NULL) { - ret = ENOMEM; - goto immediately; - } - -- subreq = sdap_get_ad_tokengroups_send(state, ev, opts, sh, name, orig_dn, -- timeout); -+ sdom = sdap_domain_get(opts, domain); -+ if (sdom == NULL || sdom->pvt == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", -+ domain->name)); -+ ret = EINVAL; -+ goto immediately; -+ } -+ subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); -+ state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); -+ if (!state->op) { -+ DEBUG(2, ("sdap_id_op_create failed\n")); -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - ret = ENOMEM; - goto immediately; - } - -+ tevent_req_set_callback(subreq, -+ sdap_ad_tokengroups_initgr_mapping_connect_done, -+ req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void -+sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq) -+{ -+ struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL; -+ struct tevent_req *req = NULL; -+ int ret; -+ int dp_error = DP_ERR_FATAL; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, -+ struct sdap_ad_tokengroups_initgr_mapping_state); -+ -+ -+ ret = sdap_id_op_connect_recv(subreq, &dp_error); -+ talloc_zfree(subreq); -+ -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts, -+ sdap_id_op_handle(state->op), -+ state->username, -+ state->orig_dn, state->timeout); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ - tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_mapping_done, - req); - -- return req; -- --immediately: -- if (ret == EOK) { -- tevent_req_done(req); -- } else { -- tevent_req_error(req, ret); -- } -- tevent_req_post(req, ev); -- -- return req; -+ return; - } - - static void sdap_ad_tokengroups_initgr_mapping_done(struct tevent_req *subreq) -@@ -896,22 +967,31 @@ static int sdap_ad_tokengroups_initgr_mapping_recv(struct tevent_req *req) - struct sdap_ad_tokengroups_initgr_posix_state { - struct tevent_context *ev; - struct sdap_id_ctx *id_ctx; -+ struct sdap_id_conn_ctx *conn; - struct sdap_options *opts; -+ struct sdap_handle *sh; - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; -+ const char *orig_dn; -+ int timeout; - const char *username; -+ -+ struct sdap_id_op *op; - }; - - static void - sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq); - - static void -+sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq); -+static void - sdap_ad_tokengroups_initgr_posix_sids_done(struct tevent_req *subreq); - - static struct tevent_req * - sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_ctx *id_ctx, -+ struct sdap_id_conn_ctx *conn, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, -@@ -923,6 +1003,8 @@ sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, - struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; - struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; -+ struct sdap_domain *sdom; -+ struct ad_id_ctx *subdom_id_ctx; - errno_t ret; - - req = tevent_req_create(mem_ctx, &state, -@@ -934,36 +1016,91 @@ sdap_ad_tokengroups_initgr_posix_send(TALLOC_CTX *mem_ctx, - - state->ev = ev; - state->id_ctx = id_ctx; -+ state->conn = conn; - state->opts = opts; -+ state->sh = sh; - state->sysdb = sysdb; - state->domain = domain; -+ state->orig_dn = orig_dn; -+ state->timeout = timeout; - state->username = talloc_strdup(state, name); - if (state->username == NULL) { - ret = ENOMEM; - goto immediately; - } - -- subreq = sdap_get_ad_tokengroups_send(state, ev, opts, sh, name, orig_dn, -- timeout); -+ sdom = sdap_domain_get(opts, domain); -+ if (sdom == NULL || sdom->pvt == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", -+ domain->name)); -+ ret = EINVAL; -+ goto immediately; -+ } -+ subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); -+ state->op = sdap_id_op_create(state, subdom_id_ctx->ldap_ctx->conn_cache); -+ if (!state->op) { -+ DEBUG(2, ("sdap_id_op_create failed\n")); -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ subreq = sdap_id_op_connect_send(state->op, state, &ret); - if (subreq == NULL) { - ret = ENOMEM; - goto immediately; - } - -+ tevent_req_set_callback(subreq, -+ sdap_ad_tokengroups_initgr_posix_sids_connect_done, -+ req); -+ -+ return req; -+ -+immediately: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ -+ return req; -+} -+ -+static void -+sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq) -+{ -+ struct sdap_ad_tokengroups_initgr_posix_state *state = NULL; -+ struct tevent_req *req = NULL; -+ int ret; -+ int dp_error = DP_ERR_FATAL; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, -+ struct sdap_ad_tokengroups_initgr_posix_state); -+ -+ -+ ret = sdap_id_op_connect_recv(subreq, &dp_error); -+ talloc_zfree(subreq); -+ -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ subreq = sdap_get_ad_tokengroups_send(state, state->ev, state->opts, -+ sdap_id_op_handle(state->op), -+ state->username, state->orig_dn, -+ state->timeout); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ - tevent_req_set_callback(subreq, sdap_ad_tokengroups_initgr_posix_tg_done, - req); - -- return req; -- --immediately: -- if (ret == EOK) { -- tevent_req_done(req); -- } else { -- tevent_req_error(req, ret); -- } -- tevent_req_post(req, ev); -- -- return req; -+ return; - } - - static void -@@ -1089,6 +1226,7 @@ sdap_ad_tokengroups_initgr_posix_tg_done(struct tevent_req *subreq) - /* download missing SIDs */ - missing_sids = talloc_steal(state, missing_sids); - subreq = sdap_ad_resolve_sids_send(state, state->ev, state->id_ctx, -+ state->conn, - state->opts, state->domain, - missing_sids); - if (subreq == NULL) { -@@ -1154,6 +1292,7 @@ struct tevent_req * - sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_ctx *id_ctx, -+ struct sdap_id_conn_ctx *conn, - struct sdap_options *opts, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, -@@ -1184,8 +1323,8 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, - name, orig_dn, - timeout); - } else { -- subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, opts, -- sysdb, domain, sh, -+ subreq = sdap_ad_tokengroups_initgr_posix_send(state, ev, id_ctx, conn, -+ opts, sysdb, domain, sh, - name, orig_dn, - timeout); - } --- -1.8.4.2 - diff --git a/SOURCES/0027-SBUS-Chown-the-sbus-socket-if-needed.patch b/SOURCES/0027-SBUS-Chown-the-sbus-socket-if-needed.patch new file mode 100644 index 0000000..0398ee0 --- /dev/null +++ b/SOURCES/0027-SBUS-Chown-the-sbus-socket-if-needed.patch @@ -0,0 +1,165 @@ +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/0028-AD-Add-a-utility-function-to-create-list-of-connecti.patch b/SOURCES/0028-AD-Add-a-utility-function-to-create-list-of-connecti.patch deleted file mode 100644 index 3083367..0000000 --- a/SOURCES/0028-AD-Add-a-utility-function-to-create-list-of-connecti.patch +++ /dev/null @@ -1,497 +0,0 @@ -From 1dced7370e55be16154bbb649606f928765819d0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 3 Dec 2013 20:45:44 +0100 -Subject: [PATCH 28/31] AD: Add a utility function to create list of - connections - -ad_id.c and ad_access.c used the same block of code. With the upcoming -option to disable GC lookups, we should unify the code in a function to -avoid breaking one of the code paths. - -The same applies for the LDAP connection to the trusted AD DC. - -Includes a unit test. ---- - Makefile.am | 28 +++++ - src/providers/ad/ad_access.c | 16 +-- - src/providers/ad/ad_access.h | 4 +- - src/providers/ad/ad_common.c | 52 +++++++++ - src/providers/ad/ad_common.h | 7 ++ - src/providers/ad/ad_id.c | 29 ++--- - src/providers/ad/ad_init.c | 3 +- - src/tests/cmocka/test_ad_common.c | 221 ++++++++++++++++++++++++++++++++++++++ - 8 files changed, 319 insertions(+), 41 deletions(-) - create mode 100644 src/tests/cmocka/test_ad_common.c - -diff --git a/Makefile.am b/Makefile.am -index 583ccdb499306268640bfb894f673c42945e19ff..da407038089f3c010dea139735db9e0e2f000943 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -152,6 +152,7 @@ if HAVE_CMOCKA - test_sss_idmap \ - test_utils \ - ad_access_filter_tests \ -+ ad_common_tests \ - test_search_bases - endif - -@@ -1398,6 +1399,7 @@ ad_access_filter_tests_SOURCES = \ - src/util/sss_krb5.c \ - src/util/find_uid.c \ - src/util/user_info_msg.c \ -+ src/providers/ad/ad_common.c \ - src/tests/cmocka/test_ad_access_filter.c - ad_access_filter_tests_CFLAGS = \ - $(AM_CFLAGS) \ -@@ -1416,6 +1418,32 @@ ad_access_filter_tests_LDADD = \ - libsss_krb5_common.la \ - libsss_test_common.la - -+ad_common_tests_SOURCES = \ -+ $(sssd_be_SOURCES) \ -+ src/util/sss_ldap.c \ -+ src/util/sss_krb5.c \ -+ src/util/find_uid.c \ -+ src/util/user_info_msg.c \ -+ src/tests/cmocka/test_ad_common.c -+ad_common_tests_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(SYSTEMD_LOGIN_CFLAGS) \ -+ -DUNIT_TESTING -+ad_common_tests_LDFLAGS = \ -+ -Wl,-wrap,sdap_set_sasl_options -+ad_common_tests_LDADD = \ -+ $(PAM_LIBS) \ -+ $(CMOCKA_LIBS) \ -+ $(SSSD_LIBS) \ -+ $(CARES_LIBS) \ -+ $(KRB5_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ $(SYSTEMD_LOGIN_LIBS) \ -+ libsss_ldap_common.la \ -+ libsss_idmap.la \ -+ libsss_krb5_common.la \ -+ libsss_test_common.la -+ - endif - - noinst_PROGRAMS = pam_test_client -diff --git a/src/providers/ad/ad_access.c b/src/providers/ad/ad_access.c -index 6995172db304810899e538b37572e4ba953db3e7..68a292abc88daa2f10f6797db50cc75335e80483 100644 ---- a/src/providers/ad/ad_access.c -+++ b/src/providers/ad/ad_access.c -@@ -274,26 +274,12 @@ ad_access_send(TALLOC_CTX *mem_ctx, - goto done; - } - -- state->clist = talloc_zero_array(state, struct sdap_id_conn_ctx *, 3); -+ state->clist = ad_gc_conn_list(state, ctx->ad_id_ctx, domain); - if (state->clist == NULL) { - ret = ENOMEM; - goto done; - } - -- /* Always try GC first */ -- ctx->gc_ctx->ignore_mark_offline = false; -- state->clist[0] = ctx->gc_ctx; -- if (IS_SUBDOMAIN(domain) == false) { -- /* fall back to ldap if gc is not available */ -- state->clist[0]->ignore_mark_offline = true; -- -- /* With root domain users we have the option to -- * fall back to LDAP in case ie POSIX attributes -- * are used but not replicated to GC -- */ -- state->clist[1] = ctx->ldap_ctx; -- } -- - ret = ad_access_step(req, state->clist[state->cindex]); - if (ret != EOK) { - goto done; -diff --git a/src/providers/ad/ad_access.h b/src/providers/ad/ad_access.h -index ca5e69729c574be53b7da04df0ff89446da04c58..3bd19ccc508b43f7103c7041dcc8573a00235097 100644 ---- a/src/providers/ad/ad_access.h -+++ b/src/providers/ad/ad_access.h -@@ -26,9 +26,7 @@ - struct ad_access_ctx { - struct dp_option *ad_options; - struct sdap_access_ctx *sdap_access_ctx; -- -- struct sdap_id_conn_ctx *ldap_ctx; -- struct sdap_id_conn_ctx *gc_ctx; -+ struct ad_id_ctx *ad_id_ctx; - }; - - void -diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c -index f679c11ad18078b454b778ef30e40cca716412cb..af0ec839964233c7642205f4489e5b6462509848 100644 ---- a/src/providers/ad/ad_common.c -+++ b/src/providers/ad/ad_common.c -@@ -1096,3 +1096,55 @@ ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx) - - return ad_ctx; - } -+ -+struct sdap_id_conn_ctx * -+ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom) -+{ -+ struct sdap_id_conn_ctx *conn; -+ struct sdap_domain *sdom; -+ struct ad_id_ctx *subdom_id_ctx; -+ -+ if (IS_SUBDOMAIN(dom)) { -+ sdom = sdap_domain_get(ad_ctx->sdap_id_ctx->opts, dom); -+ if (sdom == NULL || sdom->pvt == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("No ID ctx available for [%s].\n", -+ dom->name)); -+ return NULL; -+ } -+ subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); -+ conn = subdom_id_ctx->ldap_ctx; -+ } else { -+ conn = ad_ctx->ldap_ctx; -+ } -+ -+ return conn; -+} -+ -+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 **clist; -+ -+ clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 3); -+ if (clist == NULL) return NULL; -+ -+ /* Always try GC first */ -+ clist[0] = ad_ctx->gc_ctx; -+ if (IS_SUBDOMAIN(dom) == true) { -+ clist[0]->ignore_mark_offline = false; -+ /* Subdomain users are only present in GC. */ -+ return clist; -+ } -+ -+ /* fall back to ldap if gc is not available */ -+ clist[0]->ignore_mark_offline = true; -+ -+ /* With root domain users we have the option to -+ * fall back to LDAP in case ie POSIX attributes -+ * are used but not replicated to GC -+ */ -+ clist[1] = ad_ctx->ldap_ctx; -+ -+ return clist; -+} -diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h -index b8b73c042b8a5433f720c89c04447c07cd3eac43..ed5b8584dc5327a24e60985486c6155604271fd2 100644 ---- a/src/providers/ad/ad_common.h -+++ b/src/providers/ad/ad_common.h -@@ -115,6 +115,13 @@ ad_get_dyndns_options(struct be_ctx *be_ctx, - struct ad_id_ctx * - ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx); - -+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_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom); -+ - /* AD dynamic DNS updates */ - errno_t ad_dyndns_init(struct be_ctx *be_ctx, - struct ad_options *ctx); -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index cf71b172dd7c241a9280a7ea72ef2518f66a7435..e47c41863a14eed695907548d64f4559fbae629d 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -188,12 +188,6 @@ 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; -- struct sdap_domain *sdom; -- struct ad_id_ctx *subdom_id_ctx; -- -- /* LDAP, GC, sentinel */ -- clist = talloc_zero_array(breq, struct sdap_id_conn_ctx *, 3); -- if (clist == NULL) return NULL; - - switch (ar->entry_type & BE_REQ_TYPE_MASK) { - case BE_REQ_USER: /* user */ -@@ -201,24 +195,17 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - case BE_REQ_USER_AND_GROUP: /* get SID */ - case BE_REQ_GROUP: /* group */ - case BE_REQ_INITGROUPS: /* init groups for user */ -- /* Always try GC first */ -- clist[0] = ad_ctx->gc_ctx; -- if (IS_SUBDOMAIN(dom) == true) { -- clist[0]->ignore_mark_offline = false; -- /* Subdomain users are only present in GC. */ -- break; -- } -- /* fall back to ldap if gc is not available */ -- clist[0]->ignore_mark_offline = true; -- -- /* With root domain users we have the option to -- * fall back to LDAP in case ie POSIX attributes -- * are used but not replicated to GC -- */ -- clist[1] = ad_ctx->ldap_ctx; -+ 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; - break; - } - -diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c -index 332bfda3801db3824ce1896d37e65e2c3a6b8b8b..ed69a7d9889bac1281b5ff7c7b0f290ab09173fb 100644 ---- a/src/providers/ad/ad_init.c -+++ b/src/providers/ad/ad_init.c -@@ -377,8 +377,7 @@ sssm_ad_access_init(struct be_ctx *bectx, - if (ret != EOK) { - goto fail; - } -- access_ctx->ldap_ctx = ad_id_ctx->ldap_ctx; -- access_ctx->gc_ctx = ad_id_ctx->gc_ctx; -+ access_ctx->ad_id_ctx = ad_id_ctx; - - ret = dp_copy_options(access_ctx, ad_options->basic, AD_OPTS_BASIC, - &access_ctx->ad_options); -diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c -new file mode 100644 -index 0000000000000000000000000000000000000000..648b68f2dc05947b1fbb4c680ec63d3c2c6275b3 ---- /dev/null -+++ b/src/tests/cmocka/test_ad_common.c -@@ -0,0 +1,221 @@ -+/* -+ Authors: -+ Jakub Hrozek -+ -+ Copyright (C) 2013 Red Hat -+ -+ SSSD tests: AD access control filter tests -+ -+ 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 -+#include -+#include -+ -+/* In order to access opaque types */ -+#include "providers/ad/ad_common.c" -+ -+#include "tests/cmocka/common_mock.h" -+ -+#define DOMNAME "domname" -+#define SUBDOMNAME "sub."DOMNAME -+#define REALMNAME DOMNAME -+#define HOST_NAME "ad."REALMNAME -+ -+struct ad_common_test_ctx { -+ struct ad_id_ctx *ad_ctx; -+ struct ad_id_ctx *subdom_ad_ctx; -+ -+ struct sss_domain_info *dom; -+ struct sss_domain_info *subdom; -+}; -+ -+static void -+ad_common_test_setup(void **state) -+{ -+ struct ad_common_test_ctx *test_ctx; -+ errno_t ret; -+ struct sdap_domain *sdom; -+ struct ad_id_ctx *ad_ctx; -+ struct ad_id_ctx *subdom_ad_ctx; -+ struct sdap_id_conn_ctx *subdom_ldap_ctx; -+ -+ assert_true(leak_check_setup()); -+ check_leaks_push(global_talloc_context); -+ -+ test_ctx = talloc_zero(global_talloc_context, struct ad_common_test_ctx); -+ assert_non_null(test_ctx); -+ -+ test_ctx->dom = talloc_zero(test_ctx, struct sss_domain_info); -+ assert_non_null(test_ctx->dom); -+ test_ctx->dom->name = discard_const(DOMNAME); -+ -+ test_ctx->subdom = talloc_zero(test_ctx, struct sss_domain_info); -+ assert_non_null(test_ctx->subdom); -+ test_ctx->subdom->name = discard_const(SUBDOMNAME); -+ test_ctx->subdom->parent = test_ctx->dom; -+ -+ ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx); -+ assert_non_null(ad_ctx); -+ -+ ad_ctx->ad_options = ad_create_default_options(ad_ctx, -+ REALMNAME, HOST_NAME); -+ assert_non_null(ad_ctx->ad_options); -+ -+ ad_ctx->gc_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx); -+ assert_non_null(ad_ctx->gc_ctx); -+ -+ ad_ctx->ldap_ctx = talloc_zero(ad_ctx, struct sdap_id_conn_ctx); -+ assert_non_null(ad_ctx->ldap_ctx); -+ -+ ad_ctx->sdap_id_ctx = talloc_zero(ad_ctx, struct sdap_id_ctx); -+ assert_non_null(ad_ctx->sdap_id_ctx); -+ -+ ad_ctx->sdap_id_ctx->opts = talloc_zero(ad_ctx->sdap_id_ctx, -+ struct sdap_options); -+ assert_non_null(ad_ctx->sdap_id_ctx->opts); -+ -+ ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->dom, &sdom); -+ assert_int_equal(ret, EOK); -+ -+ subdom_ad_ctx = talloc_zero(test_ctx, struct ad_id_ctx); -+ assert_non_null(subdom_ad_ctx); -+ -+ subdom_ldap_ctx = talloc_zero(subdom_ad_ctx, struct sdap_id_conn_ctx); -+ assert_non_null(subdom_ldap_ctx); -+ subdom_ad_ctx->ldap_ctx = subdom_ldap_ctx; -+ -+ ret = sdap_domain_add(ad_ctx->sdap_id_ctx->opts, test_ctx->subdom, &sdom); -+ assert_int_equal(ret, EOK); -+ sdom->pvt = subdom_ad_ctx; -+ -+ test_ctx->ad_ctx = ad_ctx; -+ test_ctx->subdom_ad_ctx = subdom_ad_ctx; -+ -+ check_leaks_push(test_ctx); -+ *state = test_ctx; -+} -+ -+static void -+ad_common_test_teardown(void **state) -+{ -+ struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, -+ struct ad_common_test_ctx); -+ assert_non_null(test_ctx); -+ -+ assert_true(check_leaks_pop(test_ctx) == true); -+ talloc_free(test_ctx); -+ assert_true(check_leaks_pop(global_talloc_context) == true); -+ assert_true(leak_check_teardown()); -+} -+ -+errno_t -+__wrap_sdap_set_sasl_options(struct sdap_options *id_opts, -+ char *default_primary, -+ char *default_realm, -+ const char *keytab_path) -+{ -+ /* Pretend SASL is fine */ -+ return EOK; -+} -+ -+void test_ldap_conn_list(void **state) -+{ -+ struct sdap_id_conn_ctx *conn; -+ -+ struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, -+ struct ad_common_test_ctx); -+ assert_non_null(test_ctx); -+ -+ conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->dom); -+ assert_true(conn == test_ctx->ad_ctx->ldap_ctx); -+ -+ conn = ad_get_dom_ldap_conn(test_ctx->ad_ctx, test_ctx->subdom); -+ assert_true(conn == test_ctx->subdom_ad_ctx->ldap_ctx); -+} -+ -+void test_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_gc_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->gc_ctx); -+ /* If there is a fallback, we should ignore the offline mode */ -+ assert_true(conn_list[0]->ignore_mark_offline); -+ assert_true(conn_list[1] == test_ctx->ad_ctx->ldap_ctx); -+ assert_false(conn_list[1]->ignore_mark_offline); -+ assert_null(conn_list[2]); -+ talloc_free(conn_list); -+ -+ conn_list = ad_gc_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_false(conn_list[0]->ignore_mark_offline); -+ assert_null(conn_list[1]); -+ talloc_free(conn_list); -+} -+ -+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_setup_teardown(test_ldap_conn_list, -+ ad_common_test_setup, -+ ad_common_test_teardown), -+ unit_test_setup_teardown(test_conn_list, -+ ad_common_test_setup, -+ ad_common_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_INIT(debug_level); -+ -+ tests_set_cwd(); -+ -+ return run_tests(tests); -+} --- -1.8.4.2 - diff --git a/SOURCES/0028-SBUS-Allow-connections-from-other-UIDs.patch b/SOURCES/0028-SBUS-Allow-connections-from-other-UIDs.patch new file mode 100644 index 0000000..e410782 --- /dev/null +++ b/SOURCES/0028-SBUS-Allow-connections-from-other-UIDs.patch @@ -0,0 +1,78 @@ +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/0029-AD-Add-a-new-option-to-turn-off-GC-lookups.patch b/SOURCES/0029-AD-Add-a-new-option-to-turn-off-GC-lookups.patch deleted file mode 100644 index 03ff29d..0000000 --- a/SOURCES/0029-AD-Add-a-new-option-to-turn-off-GC-lookups.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 168396cd93b3f0e42b4842f520f2bcece91274c6 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 29 Nov 2013 11:39:09 +0100 -Subject: [PATCH 29/31] AD: Add a new option to turn off GC lookups - -SSSD now defaults to using GC by default. For some environments, for -instance those that don't or can't replicate the POSIX attributes to -Global Catalog, this might not be desirable. - -This patch introduces a new option ad_enable_gc, that is enabled by -default. Setting this option to false makes the SSSD contact only the -LDAP port of AD DCs. ---- - src/config/etc/sssd.api.d/sssd-ad.conf | 1 + - src/man/sssd-ad.5.xml | 17 +++++++++++++++++ - src/providers/ad/ad_common.c | 31 ++++++++++++++++++------------- - src/providers/ad/ad_common.h | 1 + - src/providers/ad/ad_opts.h | 1 + - src/tests/cmocka/test_ad_common.c | 20 ++++++++++++++++++++ - 6 files changed, 58 insertions(+), 13 deletions(-) - -diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf -index 9f606f6c4da65d4bfb20a97ee27801dac9307868..00e8968d2b6dab33a39005f11a497cb3e2185302 100644 ---- a/src/config/etc/sssd.api.d/sssd-ad.conf -+++ b/src/config/etc/sssd.api.d/sssd-ad.conf -@@ -5,6 +5,7 @@ ad_backup_server = str, None, false - ad_hostname = str, None, false - ad_enable_dns_sites = bool, None, false - ad_access_filter = str, None, false -+ad_enable_gc = bool, None, false - ldap_uri = str, None, false - ldap_backup_uri = str, None, false - ldap_search_base = str, None, false -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index e31f87a96a14907c64166e53da443ad735c6e85e..38cc31278cf87c98ca9e53cf91fda7b141bff78d 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -228,6 +228,23 @@ FOREST:EXAMPLE.COM:(memberOf=cn=admins,ou=groups,dc=example,dc=com) - - - -+ ad_enable_gc (boolean) -+ -+ -+ By default, the SSSD connects to the Global -+ Catalog first to retrieve users and uses the -+ LDAP port to retrieve group memberships or -+ as a fallback. Disabling this option makes -+ the SSSD only connect to the LDAP port of the -+ current AD server. -+ -+ -+ Default: true -+ -+ -+ -+ -+ - dyndns_update (boolean) - - -diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c -index af0ec839964233c7642205f4489e5b6462509848..a5ea4f587f30575a5903d8ae1a459f53512c011f 100644 ---- a/src/providers/ad/ad_common.c -+++ b/src/providers/ad/ad_common.c -@@ -1125,26 +1125,31 @@ ad_gc_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(mem_ctx, struct sdap_id_conn_ctx *, 3); - if (clist == NULL) return NULL; - - /* Always try GC first */ -- clist[0] = ad_ctx->gc_ctx; -- if (IS_SUBDOMAIN(dom) == true) { -- clist[0]->ignore_mark_offline = false; -- /* Subdomain users are only present in GC. */ -- return clist; -+ if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) { -+ clist[cindex] = ad_ctx->gc_ctx; -+ if (IS_SUBDOMAIN(dom) == true) { -+ clist[cindex]->ignore_mark_offline = false; -+ /* Subdomain users are only present in GC. */ -+ return clist; -+ } -+ /* fall back to ldap if gc is not available */ -+ clist[cindex]->ignore_mark_offline = true; -+ cindex++; - } - -- /* fall back to ldap if gc is not available */ -- clist[0]->ignore_mark_offline = true; -- -- /* With root domain users we have the option to -- * fall back to LDAP in case ie POSIX attributes -- * are used but not replicated to GC -- */ -- clist[1] = ad_ctx->ldap_ctx; -+ if (IS_SUBDOMAIN(dom) == false) { -+ /* With root domain users we have the option to -+ * fall back to LDAP in case ie POSIX attributes -+ * are used but not replicated to GC -+ */ -+ clist[cindex] = ad_ctx->ldap_ctx; -+ } - - return clist; - } -diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h -index ed5b8584dc5327a24e60985486c6155604271fd2..d370cef69124c127f41d7c4cbaa25713363e7752 100644 ---- a/src/providers/ad/ad_common.h -+++ b/src/providers/ad/ad_common.h -@@ -42,6 +42,7 @@ enum ad_basic_opt { - AD_KRB5_REALM, - AD_ENABLE_DNS_SITES, - AD_ACCESS_FILTER, -+ AD_ENABLE_GC, - - AD_OPTS_BASIC /* opts counter */ - }; -diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h -index 8022a16274a04389b7a64b491ec28a0c3c55aaef..5b7b1c89f5f45d7cc744a955e6378390948a99fd 100644 ---- a/src/providers/ad/ad_opts.h -+++ b/src/providers/ad/ad_opts.h -@@ -36,6 +36,7 @@ struct dp_option ad_basic_opts[] = { - { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING}, - { "ad_enable_dns_sites", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, - { "ad_access_filter", DP_OPT_STRING, NULL_STRING, NULL_STRING}, -+ { "ad_enable_gc", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, - DP_OPTION_TERMINATOR - }; - -diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c -index 648b68f2dc05947b1fbb4c680ec63d3c2c6275b3..07502b82d43d730562c60125b639d8e7d1034458 100644 ---- a/src/tests/cmocka/test_ad_common.c -+++ b/src/tests/cmocka/test_ad_common.c -@@ -159,6 +159,8 @@ void test_conn_list(void **state) - struct ad_common_test_ctx); - assert_non_null(test_ctx); - -+ assert_true(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic, -+ AD_ENABLE_GC)); - conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->dom); - assert_non_null(conn_list); - -@@ -177,6 +179,24 @@ void test_conn_list(void **state) - assert_false(conn_list[0]->ignore_mark_offline); - assert_null(conn_list[1]); - talloc_free(conn_list); -+ -+ dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false); -+ assert_false(dp_opt_get_bool(test_ctx->ad_ctx->ad_options->basic, -+ AD_ENABLE_GC)); -+ -+ conn_list = ad_gc_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_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom); -+ assert_non_null(conn_list); -+ -+ assert_null(conn_list[0]); -+ talloc_free(conn_list); - } - - int main(int argc, const char *argv[]) --- -1.8.4.2 - 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 new file mode 100644 index 0000000..18c8342 --- /dev/null +++ b/SOURCES/0029-BE-Own-the-sbus-socket-as-the-SSSD-user.patch @@ -0,0 +1,115 @@ +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/0030-AD-Enable-fallback-to-LDAP-of-trusted-domain.patch b/SOURCES/0030-AD-Enable-fallback-to-LDAP-of-trusted-domain.patch deleted file mode 100644 index 7190d1f..0000000 --- a/SOURCES/0030-AD-Enable-fallback-to-LDAP-of-trusted-domain.patch +++ /dev/null @@ -1,69 +0,0 @@ -From dfebe8a952561e51fe1d603886ba4e979b29d889 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 13 Dec 2013 20:11:11 +0100 -Subject: [PATCH 30/31] AD: Enable fallback to LDAP of trusted domain - -Since we have the LDAP port of a trusted AD GC always available now, we -can always perform a fallback. ---- - src/providers/ad/ad_common.c | 14 +------------- - src/tests/cmocka/test_ad_common.c | 7 ++++--- - 2 files changed, 5 insertions(+), 16 deletions(-) - -diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c -index a5ea4f587f30575a5903d8ae1a459f53512c011f..99fa4c07af2a79bb3ca195214ddb0dbd60c61620 100644 ---- a/src/providers/ad/ad_common.c -+++ b/src/providers/ad/ad_common.c -@@ -1133,23 +1133,11 @@ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, - /* Always try GC first */ - if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC)) { - clist[cindex] = ad_ctx->gc_ctx; -- if (IS_SUBDOMAIN(dom) == true) { -- clist[cindex]->ignore_mark_offline = false; -- /* Subdomain users are only present in GC. */ -- return clist; -- } -- /* fall back to ldap if gc is not available */ - clist[cindex]->ignore_mark_offline = true; - cindex++; - } - -- if (IS_SUBDOMAIN(dom) == false) { -- /* With root domain users we have the option to -- * fall back to LDAP in case ie POSIX attributes -- * are used but not replicated to GC -- */ -- clist[cindex] = ad_ctx->ldap_ctx; -- } -+ clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom); - - return clist; - } -diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c -index 07502b82d43d730562c60125b639d8e7d1034458..bbd56b1b9b78cb78cb24726522822ad2f7ae9980 100644 ---- a/src/tests/cmocka/test_ad_common.c -+++ b/src/tests/cmocka/test_ad_common.c -@@ -176,8 +176,9 @@ void test_conn_list(void **state) - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx); -- assert_false(conn_list[0]->ignore_mark_offline); -- assert_null(conn_list[1]); -+ 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); - talloc_free(conn_list); - - dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false); -@@ -195,7 +196,7 @@ void test_conn_list(void **state) - conn_list = ad_gc_conn_list(test_ctx, test_ctx->ad_ctx, test_ctx->subdom); - assert_non_null(conn_list); - -- assert_null(conn_list[0]); -+ assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx); - talloc_free(conn_list); - } - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..b111c2d --- /dev/null +++ b/SOURCES/0030-MONITOR-Allow-confdb-to-be-accessed-by-nonroot-user.patch @@ -0,0 +1,51 @@ +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/0031-Bump-sss_idmap-version-to-3-0-3.patch b/SOURCES/0031-Bump-sss_idmap-version-to-3-0-3.patch deleted file mode 100644 index 57a1353..0000000 --- a/SOURCES/0031-Bump-sss_idmap-version-to-3-0-3.patch +++ /dev/null @@ -1,26 +0,0 @@ -From eb03d9c884e6d69af31d079a3bcb572de1a5838b Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 4 Nov 2013 11:59:49 +0100 -Subject: [PATCH 31/31] Bump sss_idmap version to 3:0:3 - -New functions were added. ---- - Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Makefile.am b/Makefile.am -index da407038089f3c010dea139735db9e0e2f000943..16648f9aa2275b60ec84a95ff8a26b1225b97918 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -612,7 +612,7 @@ libsss_idmap_la_SOURCES = \ - src/lib/idmap/sss_idmap_conv.c \ - src/util/murmurhash3.c - libsss_idmap_la_LDFLAGS = \ -- -version-info 2:0:2 -+ -version-info 3:0:3 - - dist_pkgconfig_DATA += src/sss_client/idmap/sss_nss_idmap.pc - libsss_nss_idmap_la_SOURCES = \ --- -1.8.4.2 - 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 new file mode 100644 index 0000000..5d69f05 --- /dev/null +++ b/SOURCES/0031-SYSDB-Allow-calling-chown-on-the-sysdb-file-from-mon.patch @@ -0,0 +1,94 @@ +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-AD-Refresh-subdomain-data-structures-on-startup.patch b/SOURCES/0032-AD-Refresh-subdomain-data-structures-on-startup.patch deleted file mode 100644 index ff6078a..0000000 --- a/SOURCES/0032-AD-Refresh-subdomain-data-structures-on-startup.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 1213f1a45e222b3c1b304262c51900d8ab2a886a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 13 Dec 2013 19:11:47 +0100 -Subject: [PATCH 32/34] AD: Refresh subdomain data structures on startup - -Previously, if no changes were done to the list of subdomains, the SSSD -didn't update its list of sdap_domain mappings for the new subdomain. -This resulted in errors as no id_ctx was present for the subdomain -during lookup. - -This patch moves the block of code performed during update to a function -of its own and calls it during provider initialization as well. ---- - src/providers/ad/ad_subdomains.c | 49 ++++++++++++++++++++++++++-------------- - 1 file changed, 32 insertions(+), 17 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 100fb13e99f7bf4b3946b1f5c5f9c626674bfb46..e438a688c364084a3f2bbca338a39d61aa86b5d6 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -414,6 +414,31 @@ done: - return ret; - } - -+static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *ctx) -+{ -+ errno_t ret; -+ -+ ret = sysdb_update_subdomains(ctx->be_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_update_subdomains failed.\n")); -+ return ret; -+ } -+ -+ ret = sss_write_domain_mappings(ctx->be_ctx->domain, false); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("sss_krb5_write_mappings failed.\n")); -+ /* Just continue */ -+ } -+ -+ ret = ads_store_sdap_subdom(ctx, ctx->be_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("ads_store_sdap_subdom failed.\n")); -+ return ret; -+ } -+ -+ return EOK; -+} -+ - static void ad_subdomains_get_conn_done(struct tevent_req *req); - static void ad_subdomains_master_dom_done(struct tevent_req *req); - static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx); -@@ -619,25 +644,15 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req) - goto done; - } - -+ DEBUG(SSSDBG_TRACE_LIBS, ("There are %schanges\n", -+ refresh_has_changes ? "" : "no ")); -+ - if (refresh_has_changes) { -- ret = sysdb_update_subdomains(ctx->sd_ctx->be_ctx->domain); -+ ret = ad_subdom_reinit(ctx->sd_ctx); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_update_subdomains failed.\n")); -+ DEBUG(SSSDBG_OP_FAILURE, ("Could not reinitialize subdomains\n")); - goto done; - } -- -- ret = ads_store_sdap_subdom(ctx->sd_ctx, ctx->sd_ctx->be_ctx->domain); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("ads_store_sdap_subdom failed.\n")); -- goto done; -- } -- -- ret = sss_write_domain_mappings(ctx->sd_ctx->be_ctx->domain, false); -- if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("sss_krb5_write_mappings failed.\n")); -- /* Just continue */ -- } - } - - ret = EOK; -@@ -783,9 +798,9 @@ int ad_subdom_init(struct be_ctx *be_ctx, - return EFAULT; - } - -- ret = sysdb_update_subdomains(be_ctx->domain); -+ ret = ad_subdom_reinit(ctx); - if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, ("Could not load the list of subdomains. " -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not reinitialize subdomains. " - "Users from trusted domains might not be resolved correctly\n")); - /* Ignore this error and try to discover the subdomains later */ - } --- -1.8.4.2 - 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 new file mode 100644 index 0000000..4ac28ba --- /dev/null +++ b/SOURCES/0032-NSS-Run-as-a-user-specified-by-monitor.patch @@ -0,0 +1,48 @@ +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/0033-IPA-Refresh-subdomain-data-structures-on-startup.patch b/SOURCES/0033-IPA-Refresh-subdomain-data-structures-on-startup.patch deleted file mode 100644 index 2d070bf..0000000 --- a/SOURCES/0033-IPA-Refresh-subdomain-data-structures-on-startup.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 3a1056929310cf304449baf3feed94bc8fe46383 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 17 Dec 2013 17:22:45 +0100 -Subject: [PATCH 33/34] IPA: Refresh subdomain data structures on startup - -Write domain-mappings at startup and initialize internal data structures -on provider startup, not only during updates. ---- - src/providers/ipa/ipa_subdomains.c | 51 ++++++++++++++++++++++++-------------- - 1 file changed, 32 insertions(+), 19 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 416e21913be8e991c9f496ff2b54f238b602f304..56fd4f99654aa07f822c49d6d39526765785f0de 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -267,6 +267,35 @@ ipa_ad_subdom_refresh(struct be_ctx *be_ctx, - return EOK; - } - -+static errno_t -+ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx) -+{ -+ errno_t ret; -+ -+ ret = sysdb_update_subdomains(ctx->be_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_update_subdomains failed.\n")); -+ return ret; -+ } -+ -+ ret = ipa_ad_subdom_refresh(ctx->be_ctx, ctx->id_ctx, ctx->be_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("ipa_ad_subdom_refresh failed.\n")); -+ return ret; -+ } -+ -+ ret = sss_write_domain_mappings(ctx->be_ctx->domain, -+ dp_opt_get_bool(ctx->id_ctx->ipa_options->basic, -+ IPA_SERVER_MODE)); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("sss_krb5_write_mappings failed.\n")); -+ /* Just continue */ -+ } -+ -+ return EOK; -+} -+ - static void - ipa_ad_subdom_remove(struct ipa_subdomains_ctx *ctx, - struct sss_domain_info *subdom) -@@ -921,27 +950,11 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) - } - - if (refresh_has_changes) { -- ret = sysdb_update_subdomains(domain); -+ ret = ipa_subdom_reinit(ctx->sd_ctx); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_update_subdomains failed.\n")); -+ DEBUG(SSSDBG_OP_FAILURE, ("Could not reinitialize subdomains\n")); - goto done; - } -- -- ret = ipa_ad_subdom_refresh(ctx->sd_ctx->be_ctx, ctx->sd_ctx->id_ctx, -- domain); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("ipa_ad_subdom_refresh failed.\n")); -- goto done; -- } -- -- ret = sss_write_domain_mappings(domain, -- dp_opt_get_bool(ctx->sd_ctx->id_ctx->ipa_options->basic, -- IPA_SERVER_MODE)); -- if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("sss_krb5_write_mappings failed.\n")); -- /* Just continue */ -- } - } - - ret = sysdb_master_domain_update(domain); -@@ -1289,7 +1302,7 @@ int ipa_subdom_init(struct be_ctx *be_ctx, - DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add subdom offline callback")); - } - -- ret = sysdb_update_subdomains(be_ctx->domain); -+ ret = ipa_subdom_reinit(ctx); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, ("Could not load the list of subdomains. " - "Users from trusted domains might not be resolved correctly\n")); --- -1.8.4.2 - 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 new file mode 100644 index 0000000..06adf5c --- /dev/null +++ b/SOURCES/0033-responder_common-Create-fd-for-pipe-in-helper.patch @@ -0,0 +1,212 @@ +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-IPA-Call-ipa_ad_subdom_refresh-when-server-mode-is-i.patch b/SOURCES/0034-IPA-Call-ipa_ad_subdom_refresh-when-server-mode-is-i.patch deleted file mode 100644 index d3f683f..0000000 --- a/SOURCES/0034-IPA-Call-ipa_ad_subdom_refresh-when-server-mode-is-i.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 414d36bc08bf3ddb8c742f4548711cc0b448bb85 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 18 Dec 2013 18:14:46 +0100 -Subject: [PATCH 34/34] IPA: Call ipa_ad_subdom_refresh when server mode is - initialized - -ipa_ad_subdom_refresh was called before IPA server context was -initialized. On IPA server, this caused the code to dereference a NULL -pointer and crash. ---- - src/providers/ipa/ipa_subdomains.c | 20 ++++++++++++++------ - 1 file changed, 14 insertions(+), 6 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 56fd4f99654aa07f822c49d6d39526765785f0de..2d28d7cd0538b204eb2818e71e029dec19456a1c 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -278,12 +278,6 @@ ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx) - return ret; - } - -- ret = ipa_ad_subdom_refresh(ctx->be_ctx, ctx->id_ctx, ctx->be_ctx->domain); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("ipa_ad_subdom_refresh failed.\n")); -- return ret; -- } -- - ret = sss_write_domain_mappings(ctx->be_ctx->domain, - dp_opt_get_bool(ctx->id_ctx->ipa_options->basic, - IPA_SERVER_MODE)); -@@ -955,6 +949,13 @@ static void ipa_subdomains_handler_done(struct tevent_req *req) - DEBUG(SSSDBG_OP_FAILURE, ("Could not reinitialize subdomains\n")); - goto done; - } -+ -+ ret = ipa_ad_subdom_refresh(ctx->sd_ctx->be_ctx, ctx->sd_ctx->id_ctx, -+ domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("ipa_ad_subdom_refresh failed.\n")); -+ goto done; -+ } - } - - ret = sysdb_master_domain_update(domain); -@@ -1316,6 +1317,7 @@ int ipa_ad_subdom_init(struct be_ctx *be_ctx, - { - char *realm; - char *hostname; -+ errno_t ret; - - if (dp_opt_get_bool(id_ctx->ipa_options->basic, - IPA_SERVER_MODE) == false) { -@@ -1360,5 +1362,11 @@ int ipa_ad_subdom_init(struct be_ctx *be_ctx, - id_ctx->server_mode->trusts = NULL; - id_ctx->server_mode->ext_groups = NULL; - -+ ret = ipa_ad_subdom_refresh(be_ctx, id_ctx, be_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("ipa_ad_subdom_refresh failed.\n")); -+ return ret; -+ } -+ - return EOK; - } --- -1.8.4.2 - diff --git a/SOURCES/0034-TEST-Unit-test-for-create_pipe_fd.patch b/SOURCES/0034-TEST-Unit-test-for-create_pipe_fd.patch new file mode 100644 index 0000000..dd2c9a4 --- /dev/null +++ b/SOURCES/0034-TEST-Unit-test-for-create_pipe_fd.patch @@ -0,0 +1,131 @@ +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-responders-Do-not-initialize-pipe-fd-if-already-pres.patch b/SOURCES/0035-responders-Do-not-initialize-pipe-fd-if-already-pres.patch new file mode 100644 index 0000000..db698b6 --- /dev/null +++ b/SOURCES/0035-responders-Do-not-initialize-pipe-fd-if-already-pres.patch @@ -0,0 +1,187 @@ +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/0035-sss_cache-initialize-names-member-of-sss_domain_info.patch b/SOURCES/0035-sss_cache-initialize-names-member-of-sss_domain_info.patch deleted file mode 100644 index 825f38f..0000000 --- a/SOURCES/0035-sss_cache-initialize-names-member-of-sss_domain_info.patch +++ /dev/null @@ -1,80 +0,0 @@ -From ca3dda947538ca1c16386d4c3f86f97eee7d0abc Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 25 Nov 2013 17:54:06 +0100 -Subject: [PATCH 35/41] sss_cache: initialize names member of sss_domain_info - -sss_tc_fqname() called by sss_get_domain_name() requires that the names -member of the sss_domain_info struct is set to work properly. If the -names struct is properly initialized in sss_domain_info the separate one -in the tool context is not needed anymore. - -Related to https://fedorahosted.org/sssd/ticket/1741 ---- - src/tools/sss_cache.c | 23 ++++++++++------------- - 1 file changed, 10 insertions(+), 13 deletions(-) - -diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c -index fa2e29de8bf8a035dd725aa3190af1c2a2091e05..3b6e62393f6cf0f6ccc94aea8cf19bf3aedc444f 100644 ---- a/src/tools/sss_cache.c -+++ b/src/tools/sss_cache.c -@@ -63,7 +63,6 @@ static errno_t search_autofsmaps(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, - struct cache_tool_ctx { - struct confdb_ctx *confdb; - struct sss_domain_info *domains; -- struct sss_names_ctx *nctx; - - char *user_filter; - char *group_filter; -@@ -209,7 +208,7 @@ static errno_t update_filter(struct cache_tool_ctx *tctx, - return ENOMEM; - } - -- ret = sss_parse_name(tmp_ctx, tctx->nctx, name, -+ ret = sss_parse_name(tmp_ctx, dinfo->names, name, - &parsed_domain, &parsed_name); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, ("sss_parse_name failed\n")); -@@ -280,17 +279,6 @@ static errno_t update_all_filters(struct cache_tool_ctx *tctx, - { - errno_t ret; - -- if (IS_SUBDOMAIN(dinfo)) { -- ret = sss_names_init(tctx, tctx->confdb, dinfo->parent->name, -- &tctx->nctx); -- } else { -- ret = sss_names_init(tctx, tctx->confdb, dinfo->name, &tctx->nctx); -- } -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("sss_names_init() failed\n")); -- return ret; -- } -- - /* Update user filter */ - ret = update_filter(tctx, dinfo, tctx->user_name, - tctx->update_user_filter, "(%s=%s)", false, -@@ -467,6 +455,7 @@ errno_t init_domains(struct cache_tool_ctx *ctx, const char *domain) - { - char *confdb_path; - int ret; -+ struct sss_domain_info *dinfo; - - confdb_path = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE); - if (confdb_path == NULL) { -@@ -505,6 +494,14 @@ errno_t init_domains(struct cache_tool_ctx *ctx, const char *domain) - } - } - -+ for (dinfo = ctx->domains; dinfo; dinfo = get_next_domain(dinfo, false)) { -+ ret = sss_names_init(ctx, ctx->confdb, dinfo->name, &dinfo->names); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("sss_names_init() failed\n")); -+ return ret; -+ } -+ } -+ - return EOK; - } - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..bbf32df --- /dev/null +++ b/SOURCES/0036-PAM-Create-pipe-file-descriptors-before-privileges-a.patch @@ -0,0 +1,85 @@ +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-sss_cache-fix-case-sensitivity-issue.patch b/SOURCES/0036-sss_cache-fix-case-sensitivity-issue.patch deleted file mode 100644 index b9ca7c5..0000000 --- a/SOURCES/0036-sss_cache-fix-case-sensitivity-issue.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 2db8726f09800d64231f403198742d22a04a8d8b Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 26 Nov 2013 10:27:50 +0100 -Subject: [PATCH 36/41] sss_cache: fix case-sensitivity issue - -For case-insensitive domains the lower-case name for case-insensitive -searches is stored in SYSDB_NAME_ALIAS. - -Related to https://fedorahosted.org/sssd/ticket/1741 ---- - src/tools/sss_cache.c | 63 +++++++++++++++++++++++++++++---------------------- - 1 file changed, 36 insertions(+), 27 deletions(-) - -diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c -index 3b6e62393f6cf0f6ccc94aea8cf19bf3aedc444f..56dc47afdcb92b71dc1ef71d7f26fdf276a1c45f 100644 ---- a/src/tools/sss_cache.c -+++ b/src/tools/sss_cache.c -@@ -196,6 +196,8 @@ static errno_t update_filter(struct cache_tool_ctx *tctx, - TALLOC_CTX *tmp_ctx = NULL; - char *use_name = NULL; - char *filter; -+ char *sanitized; -+ char *lc_sanitized; - - if (!name || !update) { - /* Nothing to do */ -@@ -215,6 +217,14 @@ static errno_t update_filter(struct cache_tool_ctx *tctx, - goto done; - } - -+ if (parsed_domain != NULL && strcasecmp(dinfo->name, parsed_domain) != 0) { -+ /* We were able to parse the domain from given fqdn, but it -+ * does not match with currently processed domain. */ -+ filter = NULL; -+ ret = EOK; -+ goto done; -+ } -+ - if (!dinfo->case_sensitive && !force_case_sensitivity) { - use_name = sss_tc_utf8_str_tolower(tmp_ctx, parsed_name); - if (!use_name) { -@@ -232,41 +242,40 @@ static errno_t update_filter(struct cache_tool_ctx *tctx, - ret = ENOMEM; - goto done; - } -+ } - -- if (!strcasecmp(dinfo->name, parsed_domain)) { -- if (fmt) { -- filter = talloc_asprintf(tmp_ctx, fmt, -- SYSDB_NAME, use_name); -- } else { -- filter = talloc_strdup(tmp_ctx, use_name); -- } -- if (filter == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n")); -- ret = ENOMEM; -- goto done; -- } -+ ret = sss_filter_sanitize_for_dom(tmp_ctx, use_name, dinfo, -+ &sanitized, &lc_sanitized); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to sanitize the given name.\n")); -+ goto done; -+ } -+ -+ if (fmt) { -+ if (!dinfo->case_sensitive && !force_case_sensitivity) { -+ filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)(%s=%s))", -+ SYSDB_NAME_ALIAS, lc_sanitized, -+ SYSDB_NAME_ALIAS, sanitized); - } else { -- /* We were able to parse the domain from given fqdn, but it -- * does not match with currently processed domain. */ -- filter = NULL; -+ filter = talloc_asprintf(tmp_ctx, fmt, SYSDB_NAME, sanitized); - } - } else { -- if (fmt) { -- filter = talloc_asprintf(tmp_ctx, fmt, SYSDB_NAME, name); -- } else { -- filter = talloc_strdup(tmp_ctx, name); -- } -- if (filter == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n")); -- ret = ENOMEM; -- goto done; -- } -+ filter = talloc_strdup(tmp_ctx, sanitized); -+ } -+ if (filter == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n")); -+ ret = ENOMEM; -+ goto done; - } - -- talloc_free(*_filter); -- *_filter = talloc_steal(tctx, filter); - ret = EOK; -+ - done: -+ if (ret == EOK) { -+ talloc_free(*_filter); -+ *_filter = talloc_steal(tctx, filter); -+ } -+ - talloc_free(tmp_ctx); - return ret; - --- -1.8.4.2 - diff --git a/SOURCES/0037-Add-sysdb_attrs_add_lc_name_alias.patch b/SOURCES/0037-Add-sysdb_attrs_add_lc_name_alias.patch deleted file mode 100644 index 96db4f3..0000000 --- a/SOURCES/0037-Add-sysdb_attrs_add_lc_name_alias.patch +++ /dev/null @@ -1,107 +0,0 @@ -From b1f74ee745aa84f53fe330d55fafb9810012f875 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 28 Nov 2013 11:28:39 +0100 -Subject: [PATCH 37/41] Add sysdb_attrs_add_lc_name_alias - ---- - src/db/sysdb.c | 22 ++++++++++++++++++++++ - src/db/sysdb.h | 2 ++ - src/tests/sysdb-tests.c | 29 +++++++++++++++++++++++++++++ - 3 files changed, 53 insertions(+) - -diff --git a/src/db/sysdb.c b/src/db/sysdb.c -index da5dbe84c2415025a188544f4b4c944888f07888..2a4be58008fc1164765db26aaba3886071448d30 100644 ---- a/src/db/sysdb.c -+++ b/src/db/sysdb.c -@@ -618,6 +618,28 @@ int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, - return ret; - } - -+int sysdb_attrs_add_lc_name_alias(struct sysdb_attrs *attrs, -+ const char *value) -+{ -+ char *lc_str; -+ int ret; -+ -+ if (attrs == NULL || value == NULL) { -+ return EINVAL; -+ } -+ -+ lc_str = sss_tc_utf8_str_tolower(attrs, value); -+ if (lc_str == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot convert name to lowercase\n")); -+ return ENOMEM; -+ } -+ -+ ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lc_str); -+ talloc_free(lc_str); -+ -+ return ret; -+} -+ - int sysdb_attrs_copy_values(struct sysdb_attrs *src, - struct sysdb_attrs *dst, - const char *name) -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 4d5ef0b4794a85aa7fbc8f261d42eddd1043284e..f3358d642efd1c13203061c43e455a5c26c72740 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -274,6 +274,8 @@ int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs, - const char *name, uint32_t value); - int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, - const char *name, time_t value); -+int sysdb_attrs_add_lc_name_alias(struct sysdb_attrs *attrs, -+ const char *value); - int sysdb_attrs_copy_values(struct sysdb_attrs *src, - struct sysdb_attrs *dst, - const char *name); -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index ddbf6f28fd5024945fedcb3c6e2122948c4f1459..63ffac82e15849e5f6534462ce7c58b183412acc 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -4422,6 +4422,33 @@ START_TEST(test_sysdb_svc_remove_alias) - } - END_TEST - -+#define LC_NAME_ALIAS_TEST_VAL "TeSt VaLuE" -+#define LC_NAME_ALIAS_CHECK_VAL "test value" -+START_TEST(test_sysdb_attrs_add_lc_name_alias) -+{ -+ int ret; -+ struct sysdb_attrs *attrs; -+ const char *str; -+ -+ ret = sysdb_attrs_add_lc_name_alias(NULL, NULL); -+ fail_unless(ret == EINVAL, "EINVAL not returned for NULL input"); -+ -+ attrs = sysdb_new_attrs(NULL); -+ fail_unless(attrs != NULL, "sysdb_new_attrs failed"); -+ -+ ret = sysdb_attrs_add_lc_name_alias(attrs, LC_NAME_ALIAS_TEST_VAL); -+ fail_unless(ret == EOK, "sysdb_attrs_add_lc_name_alias failed"); -+ -+ ret = sysdb_attrs_get_string(attrs, SYSDB_NAME_ALIAS, &str); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string failed"); -+ fail_unless(strcmp(str, LC_NAME_ALIAS_CHECK_VAL) == 0, -+ "Unexpected value, expected [%s], got [%s]", -+ LC_NAME_ALIAS_CHECK_VAL, str); -+ -+ talloc_free(attrs); -+} -+END_TEST -+ - START_TEST(test_sysdb_has_enumerated) - { - errno_t ret; -@@ -5188,6 +5215,8 @@ Suite *create_sysdb_suite(void) - tcase_add_test(tc_sysdb, test_sysdb_store_services); - tcase_add_test(tc_sysdb, test_sysdb_svc_remove_alias); - -+ tcase_add_test(tc_sysdb, test_sysdb_attrs_add_lc_name_alias); -+ - /* Add all test cases to the test suite */ - suite_add_tcase(s, tc_sysdb); - --- -1.8.4.2 - diff --git a/SOURCES/0037-PAM-Run-pam-responder-as-nonroot.patch b/SOURCES/0037-PAM-Run-pam-responder-as-nonroot.patch new file mode 100644 index 0000000..78d50f8 --- /dev/null +++ b/SOURCES/0037-PAM-Run-pam-responder-as-nonroot.patch @@ -0,0 +1,43 @@ +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 new file mode 100644 index 0000000..87f2823 --- /dev/null +++ b/SOURCES/0038-AUTOFS-Run-the-autofs-responder-as-the-SSSD-user.patch @@ -0,0 +1,43 @@ +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-Use-sysdb_attrs_add_lc_name_alias-to-add-case-insens.patch b/SOURCES/0038-Use-sysdb_attrs_add_lc_name_alias-to-add-case-insens.patch deleted file mode 100644 index 0679bf7..0000000 --- a/SOURCES/0038-Use-sysdb_attrs_add_lc_name_alias-to-add-case-insens.patch +++ /dev/null @@ -1,195 +0,0 @@ -From e90d014c1ce95a30f4be2383a4b4f47ad21c5601 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 28 Nov 2013 12:31:24 +0100 -Subject: [PATCH 38/41] Use sysdb_attrs_add_lc_name_alias to add - case-insensitive alias - ---- - src/providers/ipa/ipa_s2n_exop.c | 27 ++++++--------------------- - src/providers/ldap/sdap_async.c | 21 ++++++++++++++++----- - src/providers/proxy/proxy_id.c | 20 ++------------------ - src/providers/proxy/proxy_netgroup.c | 10 +--------- - src/responder/pac/pacsrv_utils.c | 4 ++-- - 5 files changed, 27 insertions(+), 55 deletions(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index d8506aaae2582f496033212e5abeef753244c21a..8bad16d42facac3a585a4fdf579c3d2bb913dd71 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -651,7 +651,6 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - struct sysdb_attrs *user_attrs = NULL; - struct sysdb_attrs *group_attrs = NULL; - char *name; -- char *lc_name; - char *realm; - char *upn; - struct berval *bv_req = NULL; -@@ -767,16 +766,10 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - goto done; - } - -- lc_name = sss_tc_utf8_str_tolower(user_attrs, name); -- if (lc_name == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n")); -- ret = ENOMEM; -- goto done; -- } -- -- ret = sysdb_attrs_add_string(user_attrs, SYSDB_NAME_ALIAS, lc_name); -+ ret = sysdb_attrs_add_lc_name_alias(user_attrs, name); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n")); -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("sysdb_attrs_add_lc_name_alias failed.\n")); - goto done; - } - -@@ -852,18 +845,10 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) - goto done; - } - -- lc_name = sss_tc_utf8_str_tolower(group_attrs, name); -- if (lc_name == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- ("Cannot convert name to lowercase\n")); -- ret = ENOMEM; -- goto done; -- } -- -- ret = sysdb_attrs_add_string(group_attrs, SYSDB_NAME_ALIAS, -- lc_name); -+ ret = sysdb_attrs_add_lc_name_alias(group_attrs, name); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n")); -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("sysdb_attrs_add_lc_name_alias failed.\n")); - goto done; - } - -diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c -index f5cc962b34c8ef5e8c8dc9cf90b77d782b389032..e905d2dd6d539baadcd29aa0869ca04e845947e2 100644 ---- a/src/providers/ldap/sdap_async.c -+++ b/src/providers/ldap/sdap_async.c -@@ -2318,12 +2318,23 @@ sdap_save_all_names(const char *name, - goto done; - } - -- ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, domname); -- if (ret) { -- DEBUG(SSSDBG_OP_FAILURE, ("Failed to add alias [%s] into the " -- "attribute list\n", aliases[i])); -- goto done; -+ if (lowercase) { -+ ret = sysdb_attrs_add_lc_name_alias(attrs, domname); -+ if (ret) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to add lower-cased version " -+ "of alias [%s] into the " -+ "attribute list\n", aliases[i])); -+ goto done; -+ } -+ } else { -+ ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, domname); -+ if (ret) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to add alias [%s] into the " -+ "attribute list\n", aliases[i])); -+ goto done; -+ } - } -+ - } - - ret = EOK; -diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c -index 963aad2d0676a665d69be2ea2996ad49cb2bacc6..2c01aad5ae86e11d22383d6b618073ef8e9d6dbb 100644 ---- a/src/providers/proxy/proxy_id.c -+++ b/src/providers/proxy/proxy_id.c -@@ -223,7 +223,6 @@ static int save_user(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, - { - const char *shell; - const char *gecos; -- char *lower; - struct sysdb_attrs *attrs = NULL; - errno_t ret; - const char *cased_alias; -@@ -249,14 +248,7 @@ static int save_user(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, - } - - if (lowercase) { -- lower = sss_tc_utf8_str_tolower(attrs, pwd->pw_name); -- if (!lower) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n")); -- talloc_zfree(attrs); -- return ENOMEM; -- } -- -- ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower); -+ ret = sysdb_attrs_add_lc_name_alias(attrs, pwd->pw_name); - if (ret) { - DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n")); - talloc_zfree(attrs); -@@ -540,7 +532,6 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, - { - errno_t ret, sret; - struct sysdb_attrs *attrs = NULL; -- char *lower; - const char *cased_alias; - TALLOC_CTX *tmp_ctx; - time_t now = time(NULL); -@@ -595,14 +586,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, - } - - if (dom->case_sensitive == false) { -- lower = sss_tc_utf8_str_tolower(attrs, grp->gr_name); -- if (!lower) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n")); -- ret = ENOMEM; -- goto done; -- } -- -- ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower); -+ 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; -diff --git a/src/providers/proxy/proxy_netgroup.c b/src/providers/proxy/proxy_netgroup.c -index 04a0b18d7079aa15d04562ee5c785caed4456fb5..bb0bc171b8c3688a92c14f711669f752653a39f0 100644 ---- a/src/providers/proxy/proxy_netgroup.c -+++ b/src/providers/proxy/proxy_netgroup.c -@@ -74,17 +74,9 @@ static errno_t save_netgroup(struct sysdb_ctx *sysdb, - uint64_t cache_timeout) - { - errno_t ret; -- char *lower; - - if (lowercase) { -- lower = sss_tc_utf8_str_tolower(NULL, name); -- if (!lower) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n")); -- return ENOMEM; -- } -- -- ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower); -- talloc_free(lower); -+ ret = sysdb_attrs_add_lc_name_alias(attrs, name); - if (ret) { - DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n")); - return ret; -diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c -index 30055a1345b7d943e6adf822438263c92e53b51a..6a6ea2e357483c68533c501b93c16383ee644048 100644 ---- a/src/responder/pac/pacsrv_utils.c -+++ b/src/responder/pac/pacsrv_utils.c -@@ -483,9 +483,9 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, pwd->pw_name); -+ ret = sysdb_attrs_add_lc_name_alias(attrs, pwd->pw_name); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n")); -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_lc_name_alias failed.\n")); - goto done; - } - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..d57f2b7 --- /dev/null +++ b/SOURCES/0039-PAC-Run-the-pac-responder-as-the-SSSD-user.patch @@ -0,0 +1,44 @@ +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-Use-lower-case-name-for-case-insensitive-searches.patch b/SOURCES/0039-Use-lower-case-name-for-case-insensitive-searches.patch deleted file mode 100644 index ac7d540..0000000 --- a/SOURCES/0039-Use-lower-case-name-for-case-insensitive-searches.patch +++ /dev/null @@ -1,356 +0,0 @@ -From b0af402f8201d28922892b18792474f4ec546f36 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 13 Dec 2013 11:44:59 +0100 -Subject: [PATCH 39/41] Use lower-case name for case-insensitive searches - -The patch makes sure that a completely lower-cased version of a fully -qualified name is used for case insensitive searches. Currently there -are code paths where the domain name was used as configured and was not -lower-cased. - -To make sure this patch does not break with old entries in the cache or -case sensitive domains a third template was added to the related filters -templates which is either filled with a completely lower-cased version or -with the old version. The other two template values are unchanged. ---- - src/db/sysdb.h | 10 +++++----- - src/db/sysdb_ops.c | 8 +++++--- - src/db/sysdb_search.c | 30 ++++++++++++++++++++-------- - src/responder/pam/pam_LOCAL_domain.c | 4 ++-- - src/tests/cmocka/test_utils.c | 38 ++++++++++++++++++++++++++++++++++++ - src/util/sss_tc_utf8.c | 30 ++++++++++++++++++++++++++++ - src/util/util.h | 6 ++++++ - 7 files changed, 108 insertions(+), 18 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index f3358d642efd1c13203061c43e455a5c26c72740..f1ed8158ccff70f85940d63f247e23451c22c30f 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -144,23 +144,23 @@ - #define SYSDB_NC "objectclass="SYSDB_NETGROUP_CLASS - #define SYSDB_MPGC "|("SYSDB_UC")("SYSDB_GC")" - --#define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" -+#define SYSDB_PWNAM_FILTER "(&("SYSDB_UC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" - #define SYSDB_PWUID_FILTER "(&("SYSDB_UC")("SYSDB_UIDNUM"=%lu))" - #define SYSDB_PWSID_FILTER "(&("SYSDB_UC")("SYSDB_SID_STR"=%s))" - #define SYSDB_PWENT_FILTER "("SYSDB_UC")" - --#define SYSDB_GRNAM_FILTER "(&("SYSDB_GC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" -+#define SYSDB_GRNAM_FILTER "(&("SYSDB_GC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" - #define SYSDB_GRGID_FILTER "(&("SYSDB_GC")("SYSDB_GIDNUM"=%lu))" - #define SYSDB_GRSID_FILTER "(&("SYSDB_GC")("SYSDB_SID_STR"=%s))" - #define SYSDB_GRENT_FILTER "("SYSDB_GC")" --#define SYSDB_GRNAM_MPG_FILTER "(&("SYSDB_MPGC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" -+#define SYSDB_GRNAM_MPG_FILTER "(&("SYSDB_MPGC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" - #define SYSDB_GRGID_MPG_FILTER "(&("SYSDB_MPGC")("SYSDB_GIDNUM"=%lu))" - #define SYSDB_GRENT_MPG_FILTER "("SYSDB_MPGC")" - - #define SYSDB_INITGR_FILTER "(&("SYSDB_GC")("SYSDB_GIDNUM"=*))" - --#define SYSDB_NETGR_FILTER "(&("SYSDB_NC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" --#define SYSDB_NETGR_TRIPLES_FILTER "(|("SYSDB_NAME"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_MEMBEROF"=%s))" -+#define SYSDB_NETGR_FILTER "(&("SYSDB_NC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" -+#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))" - -diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c -index 890bf1eb3cc5fc0b6eb6f7a145aee6d87945cd8d..a5dfd443c84b87609881f9042b3e82958c3b0e5f 100644 ---- a/src/db/sysdb_ops.c -+++ b/src/db/sysdb_ops.c -@@ -305,6 +305,7 @@ int sysdb_search_user_by_name(TALLOC_CTX *mem_ctx, - struct ldb_dn *basedn; - size_t msgs_count = 0; - char *sanitized_name; -+ char *lc_sanitized_name; - char *filter; - int ret; - -@@ -320,13 +321,14 @@ int sysdb_search_user_by_name(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sss_filter_sanitize(tmp_ctx, name, &sanitized_name); -+ ret = sss_filter_sanitize_for_dom(tmp_ctx, name, domain, &sanitized_name, -+ &lc_sanitized_name); - if (ret != EOK) { - goto done; - } - -- filter = talloc_asprintf(tmp_ctx, SYSDB_PWNAM_FILTER, sanitized_name, -- sanitized_name); -+ filter = talloc_asprintf(tmp_ctx, SYSDB_PWNAM_FILTER, lc_sanitized_name, -+ sanitized_name, sanitized_name); - if (!filter) { - ret = ENOMEM; - goto done; -diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c -index d15fc73ce2272bff53650ae9dd0dbdad99a849e6..308710a2c780b9a709930b7d8a16a0c07471aff7 100644 ---- a/src/db/sysdb_search.c -+++ b/src/db/sysdb_search.c -@@ -38,6 +38,7 @@ int sysdb_getpwnam(TALLOC_CTX *mem_ctx, - struct ldb_dn *base_dn; - struct ldb_result *res; - char *sanitized_name; -+ char *lc_sanitized_name; - const char *src_name; - int ret; - -@@ -61,13 +62,15 @@ int sysdb_getpwnam(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sss_filter_sanitize(tmp_ctx, src_name, &sanitized_name); -+ ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain, -+ &sanitized_name, &lc_sanitized_name); - if (ret != EOK) { - goto done; - } - - ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, - LDB_SCOPE_SUBTREE, attrs, SYSDB_PWNAM_FILTER, -+ lc_sanitized_name, - sanitized_name, sanitized_name); - if (ret) { - ret = sysdb_error_to_errno(ret); -@@ -214,6 +217,7 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx, - struct ldb_dn *base_dn; - struct ldb_result *res; - const char *src_name; -+ char *lc_sanitized_name; - int ret; - - tmp_ctx = talloc_new(NULL); -@@ -243,14 +247,15 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sss_filter_sanitize(tmp_ctx, src_name, &sanitized_name); -+ ret = sss_filter_sanitize_for_dom(tmp_ctx, src_name, domain, -+ &sanitized_name, &lc_sanitized_name); - if (ret != EOK) { - goto done; - } - - ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, - LDB_SCOPE_SUBTREE, attrs, fmt_filter, -- sanitized_name, sanitized_name); -+ lc_sanitized_name, sanitized_name, sanitized_name); - if (ret) { - ret = sysdb_error_to_errno(ret); - goto done; -@@ -481,6 +486,7 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx, - struct ldb_dn *base_dn; - struct ldb_result *res; - char *sanitized_name; -+ char *lc_sanitized_name; - int ret; - - tmp_ctx = talloc_new(NULL); -@@ -495,14 +501,15 @@ int sysdb_get_user_attr(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sss_filter_sanitize(tmp_ctx, name, &sanitized_name); -+ ret = sss_filter_sanitize_for_dom(tmp_ctx, name, domain, &sanitized_name, -+ &lc_sanitized_name); - if (ret != EOK) { - goto done; - } - - ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, - LDB_SCOPE_SUBTREE, attributes, -- SYSDB_PWNAM_FILTER, sanitized_name, -+ SYSDB_PWNAM_FILTER, lc_sanitized_name, sanitized_name, - sanitized_name); - if (ret) { - ret = sysdb_error_to_errno(ret); -@@ -785,6 +792,7 @@ errno_t sysdb_getnetgr(TALLOC_CTX *mem_ctx, - struct ldb_dn *base_dn; - struct ldb_result *result; - char *sanitized_netgroup; -+ char *lc_sanitized_netgroup; - char *netgroup_dn; - int lret; - errno_t ret; -@@ -802,7 +810,9 @@ errno_t sysdb_getnetgr(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sss_filter_sanitize(tmp_ctx, netgroup, &sanitized_netgroup); -+ ret = sss_filter_sanitize_for_dom(tmp_ctx, netgroup, domain, -+ &sanitized_netgroup, -+ &lc_sanitized_netgroup); - if (ret != EOK) { - goto done; - } -@@ -816,7 +826,7 @@ errno_t sysdb_getnetgr(TALLOC_CTX *mem_ctx, - - lret = ldb_search(sysdb->ldb, tmp_ctx, &result, base_dn, - LDB_SCOPE_SUBTREE, attrs, -- SYSDB_NETGR_TRIPLES_FILTER, -+ SYSDB_NETGR_TRIPLES_FILTER, lc_sanitized_netgroup, - sanitized_netgroup, sanitized_netgroup, - netgroup_dn); - ret = sysdb_error_to_errno(lret); -@@ -843,6 +853,7 @@ int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx, - struct ldb_dn *base_dn; - struct ldb_result *result; - char *sanitized_netgroup; -+ char *lc_sanitized_netgroup; - int ret; - - tmp_ctx = talloc_new(NULL); -@@ -857,7 +868,9 @@ int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sss_filter_sanitize(tmp_ctx, netgrname, &sanitized_netgroup); -+ ret = sss_filter_sanitize_for_dom(tmp_ctx, netgrname, domain, -+ &sanitized_netgroup, -+ &lc_sanitized_netgroup); - if (ret != EOK) { - goto done; - } -@@ -865,6 +878,7 @@ int sysdb_get_netgroup_attr(TALLOC_CTX *mem_ctx, - ret = ldb_search(sysdb->ldb, tmp_ctx, &result, base_dn, - LDB_SCOPE_SUBTREE, attributes, - SYSDB_NETGR_FILTER, -+ lc_sanitized_netgroup, - sanitized_netgroup, - sanitized_netgroup); - if (ret) { -diff --git a/src/responder/pam/pam_LOCAL_domain.c b/src/responder/pam/pam_LOCAL_domain.c -index e7776cba3b74a86ef63dad30f08b4436a59a89be..49ddbcda39468e6a4f2065d97df309ce881b6aa4 100644 ---- a/src/responder/pam/pam_LOCAL_domain.c -+++ b/src/responder/pam/pam_LOCAL_domain.c -@@ -258,12 +258,12 @@ int LOCAL_pam_handler(struct pam_auth_req *preq) - - if (res->count < 1) { - DEBUG(4, ("No user found with filter ["SYSDB_PWNAM_FILTER"]\n", -- pd->user, pd->user)); -+ pd->user, pd->user, pd->user)); - pd->pam_status = PAM_USER_UNKNOWN; - goto done; - } else if (res->count > 1) { - DEBUG(4, ("More than one object found with filter ["SYSDB_PWNAM_FILTER"]\n", -- pd->user, pd->user)); -+ pd->user, pd->user, pd->user)); - lreq->error = EFAULT; - goto done; - } -diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c -index 1be59ab69cfa632010c5e1700dc79f59b6f48fde..61e8e9f07ca2f6772b12fe602acb3d2872b39c10 100644 ---- a/src/tests/cmocka/test_utils.c -+++ b/src/tests/cmocka/test_utils.c -@@ -177,6 +177,41 @@ void test_find_subdomain_by_sid_missing_sid(void **state) - } - } - -+#define TEST_SANITIZE_INPUT "TestUser@Test.Domain" -+#define TEST_SANITIZE_LC_INPUT "testuser@test.domain" -+ -+void test_sss_filter_sanitize_for_dom(void **state) -+{ -+ struct dom_list_test_ctx *test_ctx; -+ int ret; -+ char *sanitized; -+ char *lc_sanitized; -+ struct sss_domain_info *dom; -+ -+ test_ctx = talloc_get_type(*state, struct dom_list_test_ctx); -+ dom = test_ctx->dom_list; -+ -+ dom->case_sensitive = true; -+ -+ ret = sss_filter_sanitize_for_dom(test_ctx, TEST_SANITIZE_INPUT, dom, -+ &sanitized, &lc_sanitized); -+ assert_int_equal(ret, EOK); -+ assert_string_equal(sanitized, TEST_SANITIZE_INPUT); -+ assert_string_equal(lc_sanitized, TEST_SANITIZE_INPUT); -+ talloc_free(sanitized); -+ talloc_free(lc_sanitized); -+ -+ dom->case_sensitive = false; -+ -+ ret = sss_filter_sanitize_for_dom(test_ctx, TEST_SANITIZE_INPUT, dom, -+ &sanitized, &lc_sanitized); -+ assert_int_equal(ret, EOK); -+ assert_string_equal(sanitized, TEST_SANITIZE_INPUT); -+ assert_string_equal(lc_sanitized, TEST_SANITIZE_LC_INPUT); -+ talloc_free(sanitized); -+ talloc_free(lc_sanitized); -+} -+ - int main(int argc, const char *argv[]) - { - poptContext pc; -@@ -194,6 +229,9 @@ int main(int argc, const char *argv[]) - setup_dom_list, teardown_dom_list), - unit_test_setup_teardown(test_find_subdomain_by_sid_missing_sid, - setup_dom_list, teardown_dom_list), -+ -+ unit_test_setup_teardown(test_sss_filter_sanitize_for_dom, -+ setup_dom_list, teardown_dom_list), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ -diff --git a/src/util/sss_tc_utf8.c b/src/util/sss_tc_utf8.c -index 6a976211f7b77d329ba3261577c43466406f3da9..e1426a44f3518783dca4f22cd6016cdde92d0f56 100644 ---- a/src/util/sss_tc_utf8.c -+++ b/src/util/sss_tc_utf8.c -@@ -55,3 +55,33 @@ sss_tc_utf8_tolower(TALLOC_CTX *mem_ctx, const uint8_t *s, size_t len, size_t *_ - return ret; - } - -+errno_t sss_filter_sanitize_for_dom(TALLOC_CTX *mem_ctx, -+ const char *input, -+ struct sss_domain_info *dom, -+ char **sanitized, -+ char **lc_sanitized) -+{ -+ int ret; -+ -+ ret = sss_filter_sanitize(mem_ctx, input, sanitized); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sss_filter_sanitize failed.\n")); -+ return ret; -+ } -+ -+ if (dom->case_sensitive) { -+ *lc_sanitized = talloc_strdup(mem_ctx, *sanitized); -+ } else { -+ *lc_sanitized = sss_tc_utf8_str_tolower(mem_ctx, *sanitized); -+ } -+ -+ if (*lc_sanitized == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("%s failed.\n", -+ dom->case_sensitive ? -+ "talloc_strdup" : -+ "sss_tc_utf8_str_tolower")); -+ return ENOMEM; -+ } -+ -+ return EOK; -+} -diff --git a/src/util/util.h b/src/util/util.h -index 058c1c27986f9749a18dd4c92ddb9428349a1dac..3334476ab83a137d957765fe2c9afba4ad0d014c 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -484,6 +484,12 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, - const char *input, - char **sanitized); - -+errno_t sss_filter_sanitize_for_dom(TALLOC_CTX *mem_ctx, -+ const char *input, -+ struct sss_domain_info *dom, -+ char **sanitized, -+ char **lc_sanitized); -+ - char * - sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr); - --- -1.8.4.2 - diff --git a/SOURCES/0040-Add-new-option-ldap_group_type.patch b/SOURCES/0040-Add-new-option-ldap_group_type.patch deleted file mode 100644 index 0f0f27f..0000000 --- a/SOURCES/0040-Add-new-option-ldap_group_type.patch +++ /dev/null @@ -1,177 +0,0 @@ -From fd56e9302454869c636c2e40322eec52391b4c4f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 9 Dec 2013 12:17:43 +0100 -Subject: [PATCH 40/41] Add new option ldap_group_type - ---- - 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/db/sysdb.h | 1 + - src/man/sssd-ldap.5.xml | 21 +++++++++++++++++++++ - src/providers/ad/ad_opts.h | 1 + - src/providers/ipa/ipa_opts.h | 1 + - src/providers/ldap/ldap_opts.h | 3 +++ - src/providers/ldap/sdap.h | 1 + - 10 files changed, 32 insertions(+) - -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index af5903c65e05411d5773f1f9b1f742fdb832433c..8563a91e7afe680edfa0b9dd951ac7ab5a0fd3b0 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -284,6 +284,7 @@ option_strings = { - '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'), - #replaced by ldap_entry_usn# 'ldap_group_entry_usn' : _('entryUSN attribute'), - 'ldap_group_nesting_level' : _('Maximum nesting level SSSd will follow'), - -diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf -index 00e8968d2b6dab33a39005f11a497cb3e2185302..6b136f2ec88614092cf1ceb4e2cea79db064d468 100644 ---- a/src/config/etc/sssd.api.d/sssd-ad.conf -+++ b/src/config/etc/sssd.api.d/sssd-ad.conf -@@ -91,6 +91,7 @@ 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 -+ldap_group_type = int, None, false - ldap_force_upper_case_realm = bool, None, false - ldap_group_nesting_level = int, None, false - ldap_netgroup_search_base = 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 bc14fbe3d4153bd7a7ca4ffe0351edf0b8c02ee4..a94b5f09b073c050bff597d66c8164e4f38a9bfe 100644 ---- a/src/config/etc/sssd.api.d/sssd-ipa.conf -+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf -@@ -98,6 +98,7 @@ 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 -+ldap_group_type = int, None, false - ldap_force_upper_case_realm = bool, None, false - ldap_group_nesting_level = int, None, false - ldap_netgroup_search_base = 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 eb239664c49e9d516468c184dfeac190ecf8ddd8..4f5a06800d4ba4dacea08285b9db3abdc44df8f3 100644 ---- a/src/config/etc/sssd.api.d/sssd-ldap.conf -+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf -@@ -93,6 +93,7 @@ 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 -+ldap_group_type = int, None, false - ldap_group_nesting_level = int, None, false - ldap_force_upper_case_realm = bool, None, false - ldap_netgroup_search_base = str, None, false -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index f1ed8158ccff70f85940d63f247e23451c22c30f..9bcd7be0960fcfa390fb9150594ea84880a14eea 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -76,6 +76,7 @@ - #define SYSDB_POSIX "isPosix" - #define SYSDB_USER_CATEGORY "userCategory" - #define SYSDB_HOST_CATEGORY "hostCategory" -+#define SYSDB_GROUP_TYPE "groupType" - - #define SYSDB_GECOS "gecos" - #define SYSDB_LAST_LOGIN "lastLogin" -diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml -index efe22c9d22adccb244fe99603a74eb93dbddea7f..cc58544c38e8ffa779f0a1b22a69caaf3f193ce1 100644 ---- a/src/man/sssd-ldap.5.xml -+++ b/src/man/sssd-ldap.5.xml -@@ -849,6 +849,27 @@ - - - -+ ldap_group_type (integer) -+ -+ -+ The LDAP attribute that contains an integer value -+ indicating the type of the group and maybe other -+ flags. -+ -+ -+ This attribute is currently only used by the AD -+ provider to determine if a group is a domain local -+ groups and has to be filtered out for trusted -+ domains. -+ -+ -+ Default: groupType in the AD provider, othewise not -+ set -+ -+ -+ -+ -+ - ldap_group_nesting_level (integer) - - -diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h -index 5b7b1c89f5f45d7cc744a955e6378390948a99fd..0deeec99a9c1944301b80d1f25713b5d0504e88c 100644 ---- a/src/providers/ad/ad_opts.h -+++ b/src/providers/ad/ad_opts.h -@@ -209,6 +209,7 @@ struct sdap_attr_map ad_2008r2_group_map[] = { - { "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 }, -+ { "ldap_group_type", "groupType", SYSDB_GROUP_TYPE, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h -index 5ec36c550b166e07a9ed2f2c31474c55d0ecdaee..27dc3e2f977383836c18cb824abceb03c9e9056c 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -209,6 +209,7 @@ struct sdap_attr_map ipa_group_map[] = { - { "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 }, -+ { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h -index a6c821f3ac3ad951a3b45168b298b96fefb96b60..9593dfd30a81db60b7358c66975871507340aa4b 100644 ---- a/src/providers/ldap/ldap_opts.h -+++ b/src/providers/ldap/ldap_opts.h -@@ -187,6 +187,7 @@ struct sdap_attr_map rfc2307_group_map[] = { - { "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 }, - SDAP_ATTR_MAP_TERMINATOR - }; - -@@ -241,6 +242,7 @@ struct sdap_attr_map rfc2307bis_group_map[] = { - { "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 }, - SDAP_ATTR_MAP_TERMINATOR - }; - -@@ -293,6 +295,7 @@ struct sdap_attr_map gen_ad2008r2_group_map[] = { - { "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 }, -+ { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index a7ea94eb810a96b61862bd8cc6fcd800c3e8e0cb..d408be0a65cdd840d8379b7af4c0ab1e67ed3f5c 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -296,6 +296,7 @@ enum sdap_group_attrs { - SDAP_AT_GROUP_OBJECTSID, - SDAP_AT_GROUP_MODSTAMP, - SDAP_AT_GROUP_USN, -+ SDAP_AT_GROUP_TYPE, - - SDAP_OPTS_GROUP /* attrs counter */ - }; --- -1.8.4.2 - 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 new file mode 100644 index 0000000..2fc6840 --- /dev/null +++ b/SOURCES/0040-SUDO-Run-the-sudo-responder-as-the-SSSD-user.patch @@ -0,0 +1,43 @@ +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/0041-Add-sysdb_attrs_get_int32_t.patch b/SOURCES/0041-Add-sysdb_attrs_get_int32_t.patch deleted file mode 100644 index 04d3a63..0000000 --- a/SOURCES/0041-Add-sysdb_attrs_get_int32_t.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 91c41b25f3d2e5a6074d1dd73c3355f9159d2cae Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 10 Dec 2013 10:14:02 +0100 -Subject: [PATCH 41/41] Add sysdb_attrs_get_int32_t - ---- - src/db/sysdb.c | 26 ++++++++++++++++++++++++++ - src/db/sysdb.h | 2 ++ - 2 files changed, 28 insertions(+) - -diff --git a/src/db/sysdb.c b/src/db/sysdb.c -index 2a4be58008fc1164765db26aaba3886071448d30..0e07ed60858298a1ac85d06146ccb98c5899a705 100644 ---- a/src/db/sysdb.c -+++ b/src/db/sysdb.c -@@ -366,6 +366,32 @@ int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name, - return EOK; - } - -+int sysdb_attrs_get_int32_t(struct sysdb_attrs *attrs, const char *name, -+ int32_t *value) -+{ -+ struct ldb_message_element *el; -+ int ret; -+ char *endptr; -+ int32_t val; -+ -+ ret = sysdb_attrs_get_el_ext(attrs, name, false, &el); -+ if (ret) { -+ return ret; -+ } -+ -+ if (el->num_values != 1) { -+ return ERANGE; -+ } -+ -+ errno = 0; -+ val = strtoint32((const char *) el->values[0].data, &endptr, 10); -+ if (errno != 0) return errno; -+ if (*endptr) return EINVAL; -+ -+ *value = val; -+ return EOK; -+} -+ - int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name, - uint32_t *value) - { -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 9bcd7be0960fcfa390fb9150594ea84880a14eea..255a135f0cad788e4c952b86fe24ca10f5e63732 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -294,6 +294,8 @@ errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name, - bool *value); - int sysdb_attrs_get_uint16_t(struct sysdb_attrs *attrs, const char *name, - uint16_t *value); -+int sysdb_attrs_get_int32_t(struct sysdb_attrs *attrs, const char *name, -+ int32_t *value); - int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name, - uint32_t *value); - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..86d2d0b --- /dev/null +++ b/SOURCES/0041-SSH-Run-the-ssh-responder-as-the-SSSD-user.patch @@ -0,0 +1,44 @@ +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/0042-IPA-fix-for-recent-AD-group-membership-changes.patch b/SOURCES/0042-IPA-fix-for-recent-AD-group-membership-changes.patch deleted file mode 100644 index fa294ce..0000000 --- a/SOURCES/0042-IPA-fix-for-recent-AD-group-membership-changes.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 32388a70e254021473cca2caf8fcc77fdf7e7635 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 7 Jan 2014 13:04:58 +0100 -Subject: [PATCH 42/43] IPA: fix for recent AD group membership changes - ---- - src/providers/ipa/ipa_subdomains.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 2d28d7cd0538b204eb2818e71e029dec19456a1c..9efbd725f1102d34af2107801286bca1c6412c19 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -192,6 +192,8 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, - return ret; - } - -+ sdom->pvt = ad_id_ctx; -+ - /* Set up the ID mapping object */ - ad_id_ctx->sdap_id_ctx->opts->idmap_ctx = - id_ctx->sdap_id_ctx->opts->idmap_ctx; --- -1.8.4.2 diff --git a/SOURCES/0042-SBUS-Fix-error-handling-after-closing-container.patch b/SOURCES/0042-SBUS-Fix-error-handling-after-closing-container.patch new file mode 100644 index 0000000..b7ed294 --- /dev/null +++ b/SOURCES/0042-SBUS-Fix-error-handling-after-closing-container.patch @@ -0,0 +1,38 @@ +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/0043-LDAP-Fix-typo-and-use-the-right-attribute-map.patch b/SOURCES/0043-LDAP-Fix-typo-and-use-the-right-attribute-map.patch deleted file mode 100644 index 1f5f205..0000000 --- a/SOURCES/0043-LDAP-Fix-typo-and-use-the-right-attribute-map.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 147af349a5642f85689cbfe68136f0e01706330e Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 8 Jan 2014 08:11:46 +0100 -Subject: [PATCH 43/43] LDAP: Fix typo and use the right attribute map - -https://fedorahosted.org/sssd/ticket/2191 - -There was a copy-n-paste bug in the code that resulted in using a wrong -attribute map. This could lead to the primary name not being selected -correctly. ---- - src/providers/ldap/sdap.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c -index 078326ad3614ed2cd41659ea279642a46a0e24e1..ddcf199b61311b69fde54c3ee25f2338ceb05576 100644 ---- a/src/providers/ldap/sdap.c -+++ b/src/providers/ldap/sdap.c -@@ -1246,7 +1246,7 @@ errno_t sdap_get_user_primary_name(TALLOC_CTX *memctx, - const char **_user_name) - { - return sdap_get_primary_name(memctx, -- opts->group_map[SDAP_AT_USER_NAME].name, -+ opts->user_map[SDAP_AT_USER_NAME].name, - attrs, dom, _user_name); - } - --- -1.8.4.2 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 new file mode 100644 index 0000000..5ea2aa3 --- /dev/null +++ b/SOURCES/0043-TESTS-Add-tests-for-the-views-related-option-maps.patch @@ -0,0 +1,33 @@ +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/0044-RESPONDERS-refactor-create_pipe_fd.patch b/SOURCES/0044-RESPONDERS-refactor-create_pipe_fd.patch new file mode 100644 index 0000000..28f0ad7 --- /dev/null +++ b/SOURCES/0044-RESPONDERS-refactor-create_pipe_fd.patch @@ -0,0 +1,95 @@ +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/0044-pac-fix-double-free.patch b/SOURCES/0044-pac-fix-double-free.patch deleted file mode 100644 index afc6cf0..0000000 --- a/SOURCES/0044-pac-fix-double-free.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 47bc6c387ab1d3f835167c528bb57f688080af1a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 11 Nov 2013 12:47:53 +0100 -Subject: [PATCH 44/47] pac: fix double free - ---- - src/responder/pac/pacsrv_utils.c | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - -diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c -index 6a6ea2e357483c68533c501b93c16383ee644048..a82320fcae3b0494e7b6b322428e3a17ed729b4a 100644 ---- a/src/responder/pac/pacsrv_utils.c -+++ b/src/responder/pac/pacsrv_utils.c -@@ -74,6 +74,7 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - struct sss_domain_info *user_dom; - struct sss_domain_info *group_dom; - char *sid_str = NULL; -+ char *msid_str = NULL; - char *user_dom_sid_str = NULL; - size_t user_dom_sid_str_len; - enum idmap_error_code err; -@@ -231,24 +232,22 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - - } - -- talloc_zfree(sid_str); -- - for(s = 0; s < info3->sidcount; s++) { - err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, info3->sids[s].sid, -- &sid_str); -+ &msid_str); - if (err != IDMAP_SUCCESS) { - DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n")); - ret = EFAULT; - goto done; - } - -- key.str = sid_str; -+ key.str = msid_str; - value.ul = 0; - -- ret = responder_get_domain_by_id(pac_ctx->rctx, sid_str, &group_dom); -+ ret = responder_get_domain_by_id(pac_ctx->rctx, msid_str, &group_dom); - if (ret == EOK) { - ret = sysdb_search_object_by_sid(mem_ctx, group_dom->sysdb, -- group_dom, sid_str, NULL, &msg); -+ group_dom, msid_str, NULL, &msg); - if (ret == EOK && msg->count == 1 ) { - value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], - SYSDB_GIDNUM, 0); -@@ -257,14 +256,13 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - } - - ret = hash_enter(sid_table, &key, &value); -+ sss_idmap_free_sid(pac_ctx->idmap_ctx, msid_str); - if (ret != HASH_SUCCESS) { - DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n", - ret, hash_error_string(ret))); - ret = EIO; - goto done; - } -- -- sss_idmap_free_sid(pac_ctx->idmap_ctx, sid_str); - } - - ret = EOK; --- -1.8.4.2 - 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 new file mode 100644 index 0000000..706c165 --- /dev/null +++ b/SOURCES/0045-RESPONDERS-Don-t-hard-code-umask-value-in-utility-fu.patch @@ -0,0 +1,51 @@ +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-pac-fix-potential-memory-leaks.patch b/SOURCES/0045-pac-fix-potential-memory-leaks.patch deleted file mode 100644 index 3658ae5..0000000 --- a/SOURCES/0045-pac-fix-potential-memory-leaks.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 7e60e5991e97443044ae9c097131c84e9538cc42 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 12 Nov 2013 13:41:49 +0100 -Subject: [PATCH 45/47] pac: fix potential memory leaks - ---- - src/responder/pac/pacsrv_utils.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c -index a82320fcae3b0494e7b6b322428e3a17ed729b4a..53edcc286119aa4a315285827da96e5d157afec9 100644 ---- a/src/responder/pac/pacsrv_utils.c -+++ b/src/responder/pac/pacsrv_utils.c -@@ -82,7 +82,7 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - hash_key_t key; - hash_value_t value; - char *rid_start; -- struct ldb_result *msg; -+ struct ldb_result *msg = NULL; - char *user_sid_str = NULL; - char *primary_group_sid_str = NULL; - -@@ -154,8 +154,8 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - sid_str, NULL, &msg); - if (ret == EOK && msg->count == 1) { - value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], SYSDB_UIDNUM, 0); -- talloc_free(msg); - } -+ talloc_zfree(msg); - - ret = hash_enter(sid_table, &key, &value); - if (ret != HASH_SUCCESS) { -@@ -189,8 +189,8 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - sid_str, NULL, &msg); - if (ret == EOK && msg->count == 1) { - value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], SYSDB_GIDNUM, 0); -- talloc_free(msg); - } -+ talloc_zfree(msg); - - ret = hash_enter(sid_table, &key, &value); - if (ret != HASH_SUCCESS) { -@@ -219,8 +219,8 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - if (ret == EOK && msg->count == 1) { - value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], - SYSDB_GIDNUM, 0); -- talloc_free(msg); - } -+ talloc_zfree(msg); - - ret = hash_enter(sid_table, &key, &value); - if (ret != HASH_SUCCESS) { -@@ -251,8 +251,8 @@ errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx, - if (ret == EOK && msg->count == 1 ) { - value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], - SYSDB_GIDNUM, 0); -- talloc_free(msg); - } -+ talloc_zfree(msg); - } - - ret = hash_enter(sid_table, &key, &value); --- -1.8.4.2 - diff --git a/SOURCES/0046-RESPONDERS-Set-default-value-for-umask.patch b/SOURCES/0046-RESPONDERS-Set-default-value-for-umask.patch new file mode 100644 index 0000000..fdb94a3 --- /dev/null +++ b/SOURCES/0046-RESPONDERS-Set-default-value-for-umask.patch @@ -0,0 +1,129 @@ +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-responder-Set-forest-attribute-in-AD-domains.patch b/SOURCES/0046-responder-Set-forest-attribute-in-AD-domains.patch deleted file mode 100644 index 54068b1..0000000 --- a/SOURCES/0046-responder-Set-forest-attribute-in-AD-domains.patch +++ /dev/null @@ -1,321 +0,0 @@ -From 6ac0feca0cdc66fc8d8a612e25d37a49d27c0233 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Tue, 17 Dec 2013 17:32:04 +0000 -Subject: [PATCH 46/47] responder: Set forest attribute in AD domains - -Resolves: -https://fedorahosted.org/sssd/ticket/2160 ---- - src/db/sysdb.h | 3 ++- - src/db/sysdb_subdomains.c | 35 ++++++++++++++++++++++++++++- - src/providers/ad/ad_domain_info.c | 46 +++++++++++++++++++++++++++++++------- - src/providers/ad/ad_domain_info.h | 3 ++- - src/providers/ad/ad_id.c | 5 +++-- - src/providers/ad/ad_subdomains.c | 9 +++++--- - src/providers/ipa/ipa_subdomains.c | 2 +- - src/providers/ldap/sdap_access.c | 2 +- - 8 files changed, 87 insertions(+), 18 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 255a135f0cad788e4c952b86fe24ca10f5e63732..9677294b22e47f5169d7631673beec2dbc6117ad 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -388,7 +388,8 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain); - errno_t sysdb_master_domain_update(struct sss_domain_info *domain); - - errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, -- const char *flat, const char *id); -+ const char *flat, const char *id, -+ const char* forest); - - errno_t sysdb_subdomain_delete(struct sysdb_ctx *sysdb, const char *name); - -diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c -index 43c75799cdc2856916b2dc95c3a544ef99b56081..9c2926c00b0cc08cb8e317ae838e26c82506ee37 100644 ---- a/src/db/sysdb_subdomains.c -+++ b/src/db/sysdb_subdomains.c -@@ -208,6 +208,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain) - SYSDB_SUBDOMAIN_REALM, - SYSDB_SUBDOMAIN_FLAT, - SYSDB_SUBDOMAIN_ID, -+ SYSDB_SUBDOMAIN_FOREST, - NULL}; - - tmp_ctx = talloc_new(NULL); -@@ -278,13 +279,27 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain) - } - } - -+ tmp_str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SUBDOMAIN_FOREST, -+ NULL); -+ if (tmp_str != NULL && -+ (domain->forest == NULL || -+ strcasecmp(tmp_str, domain->forest) != 0)) { -+ talloc_free(domain->forest); -+ domain->forest = talloc_strdup(domain, tmp_str); -+ if (domain->forest == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ - done: - talloc_free(tmp_ctx); - return ret; - } - - errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, -- const char *flat, const char *id) -+ const char *flat, const char *id, -+ const char* forest) - { - TALLOC_CTX *tmp_ctx; - struct ldb_message *msg; -@@ -345,6 +360,24 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, - do_update = true; - } - -+ if (forest != NULL && (domain->forest == NULL || -+ strcmp(domain->forest, forest) != 0)) { -+ ret = ldb_msg_add_empty(msg, SYSDB_SUBDOMAIN_FOREST, -+ LDB_FLAG_MOD_REPLACE, NULL); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_FOREST, forest); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ do_update = true; -+ } -+ - if (do_update == false) { - ret = EOK; - goto done; -diff --git a/src/providers/ad/ad_domain_info.c b/src/providers/ad/ad_domain_info.c -index eff2034d12261510ed7535dee7098a6e68f1f2c2..5475c5bc7ec74e81080566c6fbd6919c54a60f40 100644 ---- a/src/providers/ad/ad_domain_info.c -+++ b/src/providers/ad/ad_domain_info.c -@@ -41,9 +41,9 @@ - #define MASTER_DOMAIN_SID_FILTER "objectclass=domain" - - static errno_t --netlogon_get_flat_name(TALLOC_CTX *mem_ctx, -- struct sysdb_attrs *reply, -- char **_flat_name) -+netlogon_get_domain_info(TALLOC_CTX *mem_ctx, -+ struct sysdb_attrs *reply, -+ char **_flat_name, char **_forest) - { - errno_t ret; - struct ldb_message_element *el; -@@ -52,6 +52,7 @@ netlogon_get_flat_name(TALLOC_CTX *mem_ctx, - enum ndr_err_code ndr_err; - struct netlogon_samlogon_response response; - const char *flat_name; -+ const char *forest; - - ret = sysdb_attrs_get_el(reply, AD_AT_NETLOGON, &el); - if (ret != EOK) { -@@ -92,11 +93,13 @@ netlogon_get_flat_name(TALLOC_CTX *mem_ctx, - goto done; - } - -+ /* get flat name */ - if (response.data.nt5_ex.domain_name != NULL && - *response.data.nt5_ex.domain_name != '\0') { - flat_name = response.data.nt5_ex.domain_name; - } else { -- DEBUG(SSSDBG_MINOR_FAILURE, ("No netlogon data available\n")); -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("No netlogon domain name data available\n")); - ret = ENOENT; - goto done; - } -@@ -107,6 +110,24 @@ netlogon_get_flat_name(TALLOC_CTX *mem_ctx, - ret = ENOMEM; - goto done; - } -+ -+ /* get forest */ -+ if (response.data.nt5_ex.forest != NULL && -+ *response.data.nt5_ex.forest != '\0') { -+ forest = response.data.nt5_ex.forest; -+ } else { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("No netlogon forest data available\n")); -+ ret = ENOENT; -+ goto done; -+ } -+ -+ *_forest = talloc_strdup(mem_ctx, forest); -+ if (*_forest == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); -+ ret = ENOMEM; -+ goto done; -+ } -+ - ret = EOK; - done: - talloc_free(ndr_pull); -@@ -124,6 +145,7 @@ struct ad_master_domain_state { - int base_iter; - - char *flat; -+ char *forest; - char *sid; - }; - -@@ -338,14 +360,17 @@ ad_master_domain_netlogon_done(struct tevent_req *subreq) - - /* Exactly one flat name. Carry on */ - -- ret = netlogon_get_flat_name(state, reply[0], &state->flat); -+ ret = netlogon_get_domain_info(state, reply[0], &state->flat, -+ &state->forest); - if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, ("Could not get the flat name\n")); -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("Could not get the flat name or forest\n")); - /* Not fatal. Just quit. */ - goto done; - } -- - DEBUG(SSSDBG_TRACE_FUNC, ("Found flat name [%s].\n", state->flat)); -+ DEBUG(SSSDBG_TRACE_FUNC, ("Found forest [%s].\n", state->forest)); -+ - done: - tevent_req_done(req); - return; -@@ -355,7 +380,8 @@ errno_t - ad_master_domain_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - char **_flat, -- char **_id) -+ char **_id, -+ char **_forest) - { - struct ad_master_domain_state *state = tevent_req_data(req, - struct ad_master_domain_state); -@@ -366,6 +392,10 @@ ad_master_domain_recv(struct tevent_req *req, - *_flat = talloc_steal(mem_ctx, state->flat); - } - -+ if (_forest) { -+ *_forest = talloc_steal(mem_ctx, state->forest); -+ } -+ - if (_id) { - *_id = talloc_steal(mem_ctx, state->sid); - } -diff --git a/src/providers/ad/ad_domain_info.h b/src/providers/ad/ad_domain_info.h -index d21706396034509a498391e666e03a8e2eda8e08..d3a6416cebd07b524aceedcb63a18c4467e3dc4e 100644 ---- a/src/providers/ad/ad_domain_info.h -+++ b/src/providers/ad/ad_domain_info.h -@@ -36,6 +36,7 @@ errno_t - ad_master_domain_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - char **_flat, -- char **_id); -+ char **_id, -+ char **_forest); - - #endif /* _AD_MASTER_DOMAIN_H_ */ -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index e47c41863a14eed695907548d64f4559fbae629d..44bfa00986b6c0ebfa65dd7b83dd45eb64b87946 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -519,9 +519,10 @@ ad_enumeration_master_done(struct tevent_req *subreq) - struct ad_enumeration_state); - char *flat_name; - char *master_sid; -+ char *forest; - - ret = ad_master_domain_recv(subreq, state, -- &flat_name, &master_sid); -+ &flat_name, &master_sid, &forest); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve master domain info\n")); -@@ -530,7 +531,7 @@ ad_enumeration_master_done(struct tevent_req *subreq) - } - - ret = sysdb_master_domain_add_info(state->sdom->dom, -- flat_name, master_sid); -+ flat_name, master_sid, forest); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Cannot save master domain info\n")); - tevent_req_error(req, ret); -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index e438a688c364084a3f2bbca338a39d61aa86b5d6..62c3e16d0d3323a32848b4fbf54d2a151c16f64c 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -85,6 +85,7 @@ struct ad_subdomains_req_ctx { - - char *master_sid; - char *flat_name; -+ char *forest; - }; - - static errno_t -@@ -294,7 +295,7 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx, - - /* AD subdomains are currently all mpg and do not enumerate */ - ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str, -- mpg, false, NULL); -+ mpg, false, domain->forest); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n")); - goto done; -@@ -539,7 +540,8 @@ static void ad_subdomains_master_dom_done(struct tevent_req *req) - ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx); - - ret = ad_master_domain_recv(req, ctx, -- &ctx->flat_name, &ctx->master_sid); -+ &ctx->flat_name, &ctx->master_sid, -+ &ctx->forest); - talloc_zfree(req); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve master domain info\n")); -@@ -547,7 +549,8 @@ static void ad_subdomains_master_dom_done(struct tevent_req *req) - } - - ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain, -- ctx->flat_name, ctx->master_sid); -+ ctx->flat_name, ctx->master_sid, -+ ctx->forest); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Cannot save master domain info\n")); - goto done; -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 9efbd725f1102d34af2107801286bca1c6412c19..d9c204451f1b734ee98ce4c48f3f139731e47dec 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -1076,7 +1076,7 @@ static void ipa_subdomains_handler_master_done(struct tevent_req *req) - } - - ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain, -- flat, id); -+ flat, id, NULL); - } else { - ctx->search_base_iter++; - ret = ipa_subdomains_handler_get(ctx, IPA_SUBDOMAINS_MASTER); -diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c -index 6b387271a229668ddfa5d67143a585e667a16ddd..f0df24e7f3a855304b0cfd9d075ac67334f9bb1a 100644 ---- a/src/providers/ldap/sdap_access.c -+++ b/src/providers/ldap/sdap_access.c -@@ -214,7 +214,7 @@ static void sdap_access_filter_done(struct tevent_req *subreq) - ret = sdap_access_filter_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { -- DEBUG(1, ("Error retrieving access check result.\n")); -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Error retrieving access check result.\n")); - tevent_req_error(req, ret); - return; - } --- -1.8.4.2 - diff --git a/SOURCES/0047-LDAP-Add-a-new-error-code-for-malformed-access-contr.patch b/SOURCES/0047-LDAP-Add-a-new-error-code-for-malformed-access-contr.patch deleted file mode 100644 index 706968d..0000000 --- a/SOURCES/0047-LDAP-Add-a-new-error-code-for-malformed-access-contr.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 91ab35daf713e146dfae53a67f6b86b424c897d5 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 8 Jan 2014 17:12:17 +0100 -Subject: [PATCH 47/47] LDAP: Add a new error code for malformed access control - filter - -https://fedorahosted.org/sssd/ticket/2164 - -The patch adds a new error code and special cases the new code so that -access is denied and a nicer log message is shown. ---- - src/providers/ldap/sdap_access.c | 8 +++++++- - src/providers/ldap/sdap_async.c | 12 ++++++------ - src/providers/ldap/sdap_async_groups_ad.c | 2 +- - src/providers/ldap/sdap_async_initgroups_ad.c | 4 ++-- - src/util/util_errors.c | 1 + - src/util/util_errors.h | 1 + - 6 files changed, 18 insertions(+), 10 deletions(-) - -diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c -index f0df24e7f3a855304b0cfd9d075ac67334f9bb1a..29e83eb43cf78107e2075e1aa95211abac6d2df1 100644 ---- a/src/providers/ldap/sdap_access.c -+++ b/src/providers/ldap/sdap_access.c -@@ -855,9 +855,15 @@ static void sdap_access_filter_get_access_done(struct tevent_req *subreq) - } - } else if (dp_error == DP_ERR_OFFLINE) { - ret = sdap_access_filter_decide_offline(req); -+ } else if (ret == ERR_INVALID_FILTER) { -+ sss_log(SSS_LOG_ERR, -+ "Malformed access control filter [%s]\n", state->filter); -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Malformed access control filter [%s]\n", state->filter)); -+ ret = ERR_ACCESS_DENIED; - } else { - DEBUG(1, ("sdap_get_generic_send() returned error [%d][%s]\n", -- ret, strerror(ret))); -+ ret, sss_strerror(ret))); - } - - goto done; -diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c -index e905d2dd6d539baadcd29aa0869ca04e845947e2..367007bde0011ed4de283b2a50b22538830a5275 100644 ---- a/src/providers/ldap/sdap_async.c -+++ b/src/providers/ldap/sdap_async.c -@@ -1306,9 +1306,9 @@ static errno_t sdap_get_generic_ext_step(struct tevent_req *req) - sss_log(SSS_LOG_ERR, "LDAP connection error, %s", - sss_ldap_err2string(lret)); - } -- } -- -- else { -+ } else if (lret == LDAP_FILTER_ERROR) { -+ ret = ERR_INVALID_FILTER; -+ } else { - ret = EIO; - } - goto done; -@@ -1570,7 +1570,7 @@ static void sdap_get_generic_done(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret) { - DEBUG(4, ("sdap_get_generic_ext_recv failed [%d]: %s\n", -- ret, strerror(ret))); -+ ret, sss_strerror(ret))); - tevent_req_error(req, ret); - return; - } -@@ -1790,7 +1790,7 @@ static void sdap_x_deref_search_done(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret) { - DEBUG(4, ("sdap_get_generic_ext_recv failed [%d]: %s\n", -- ret, strerror(ret))); -+ ret, sss_strerror(ret))); - tevent_req_error(req, ret); - return; - } -@@ -2049,7 +2049,7 @@ static void sdap_asq_search_done(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret) { - DEBUG(4, ("sdap_get_generic_ext_recv failed [%d]: %s\n", -- ret, strerror(ret))); -+ ret, sss_strerror(ret))); - tevent_req_error(req, ret); - return; - } -diff --git a/src/providers/ldap/sdap_async_groups_ad.c b/src/providers/ldap/sdap_async_groups_ad.c -index 9b61c697d5789c3ec3467ec52a7171f6a640ce9e..6a8a4fd139657040ff83cad10ba35a0dde4a0122 100644 ---- a/src/providers/ldap/sdap_async_groups_ad.c -+++ b/src/providers/ldap/sdap_async_groups_ad.c -@@ -183,7 +183,7 @@ sdap_get_ad_match_rule_members_step(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, -- ("LDAP search failed: [%s]\n", strerror(ret))); -+ ("LDAP search failed: [%s]\n", sss_strerror(ret))); - tevent_req_error(req, ret); - return; - } -diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c -index 8f8f0a4cc635818dcc7f75f9da603ce2f55c820f..724f308da68daf05e2dc4cc6c64cac347ab8a0ca 100644 ---- a/src/providers/ldap/sdap_async_initgroups_ad.c -+++ b/src/providers/ldap/sdap_async_initgroups_ad.c -@@ -208,7 +208,7 @@ sdap_get_ad_match_rule_initgroups_step(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, -- ("LDAP search failed: [%s]\n", strerror(ret))); -+ ("LDAP search failed: [%s]\n", sss_strerror(ret))); - goto error; - } - -@@ -383,7 +383,7 @@ static void sdap_get_ad_tokengroups_done(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, -- ("LDAP search failed: [%s]\n", strerror(ret))); -+ ("LDAP search failed: [%s]\n", sss_strerror(ret))); - goto done; - } - -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 114c8b04fd354b166d14e526a3bab6a6c0c05951..633257e8da0ef039e555a07ad8b51125114ca01c 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -51,6 +51,7 @@ struct err_string error_to_str[] = { - { "Entry not found" }, /* ERR_NOT_FOUND */ - { "Domain not found" }, /* ERR_DOMAIN_NOT_FOUND */ - { "Missing configuration file" }, /* ERR_MISSING_CONF */ -+ { "Malformed search filter" }, /* ERR_INVALID_FILTER, */ - }; - - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index bca45f392b0357c3f1c848768358cb1d47514715..1332085031dbe6935cbdc94543fa14b09fe81028 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -73,6 +73,7 @@ enum sssd_errors { - ERR_NOT_FOUND, - ERR_DOMAIN_NOT_FOUND, - ERR_MISSING_CONF, -+ ERR_INVALID_FILTER, - ERR_LAST /* ALWAYS LAST */ - }; - --- -1.8.4.2 - diff --git a/SOURCES/0047-nss-group-enumeration-fix.patch b/SOURCES/0047-nss-group-enumeration-fix.patch new file mode 100644 index 0000000..ce1f157 --- /dev/null +++ b/SOURCES/0047-nss-group-enumeration-fix.patch @@ -0,0 +1,37 @@ +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/0048-FAST-when-parsing-krb5_child-response-make-sure-to-n.patch b/SOURCES/0048-FAST-when-parsing-krb5_child-response-make-sure-to-n.patch deleted file mode 100644 index 0b1fb22..0000000 --- a/SOURCES/0048-FAST-when-parsing-krb5_child-response-make-sure-to-n.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 103f7efda7b84e7c791af2ebc2255e61e826fd75 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 24 Dec 2013 13:01:46 +0200 -Subject: [PATCH 48/48] FAST: when parsing krb5_child response, make sure to - not miss OTP message if it was last one - -The last message in the stream might be with empty payload which means we get -only message type and message length (0) returned, i.e. 8 bytes left remaining -in the stream after processing preceding message. This makes our calculation at -the end of a message processing loop incorrect -- p+2*sizeof(int32_t) can be -equal to len, after all. - -Fixes FAST processing for FreeIPA native OTP case: -https://fedorahosted.org/sssd/ticket/2186 ---- - src/providers/krb5/krb5_child_handler.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c -index 92dec0d2afb1627b61c3dd1037e91546a7ee08d6..d6c1dc1f9707444a82e433a375839cadf73f1259 100644 ---- a/src/providers/krb5/krb5_child_handler.c -+++ b/src/providers/krb5/krb5_child_handler.c -@@ -548,8 +548,9 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len, - * CCACHE_ENV_NAME"=". pref_len also counts the trailing '=' because - * sizeof() counts the trailing '\0' of a string. */ - pref_len = sizeof(CCACHE_ENV_NAME); -- if (msg_len > pref_len && -- strncmp((const char *) &buf[p], CCACHE_ENV_NAME"=", pref_len) == 0) { -+ if ((msg_type == SSS_PAM_ENV_ITEM) && -+ (msg_len > pref_len) && -+ (strncmp((const char *) &buf[p], CCACHE_ENV_NAME"=", pref_len) == 0)) { - ccname = (char *) &buf[p+pref_len]; - ccname_len = msg_len-pref_len; - } -@@ -600,7 +601,7 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len, - - p += msg_len; - -- if ((p < len) && (p + 2*sizeof(int32_t) >= len)) { -+ if ((p < len) && (p + 2*sizeof(int32_t) > len)) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("The remainder of the message is too short.\n")); - return EINVAL; --- -1.8.4.2 - diff --git a/SOURCES/0048-nss-preserve-service-name-in-getsrv-call.patch b/SOURCES/0048-nss-preserve-service-name-in-getsrv-call.patch new file mode 100644 index 0000000..4c0b651 --- /dev/null +++ b/SOURCES/0048-nss-preserve-service-name-in-getsrv-call.patch @@ -0,0 +1,58 @@ +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-UTIL-Inherit-parent-domain-s-default_shell.patch b/SOURCES/0049-UTIL-Inherit-parent-domain-s-default_shell.patch deleted file mode 100644 index 5d3c101..0000000 --- a/SOURCES/0049-UTIL-Inherit-parent-domain-s-default_shell.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 14bafb02c396396e04412a4981b98ae75534294a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 14 Jan 2014 10:55:39 +0100 -Subject: [PATCH 49/53] UTIL: Inherit parent domain's default_shell - -Some override parameters were not inherited when creating subdomains. -Especially with AD trusts, this gave strange results. ---- - src/util/domain_info_utils.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c -index 61efc0b40dcd8969b635781549feab3eee79299e..98678f97b95d271a0d2e18daadae7f3f9a79f89e 100644 ---- a/src/util/domain_info_utils.c -+++ b/src/util/domain_info_utils.c -@@ -271,10 +271,13 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, - dom->group_timeout = parent->group_timeout; - dom->netgroup_timeout = parent->netgroup_timeout; - dom->service_timeout = parent->service_timeout; -- dom->override_homedir = parent->override_homedir; - dom->names = parent->names; - -+ dom->override_homedir = parent->override_homedir; -+ dom->fallback_homedir = parent->fallback_homedir; - dom->subdomain_homedir = parent->subdomain_homedir; -+ dom->override_shell = parent->override_shell; -+ dom->default_shell = parent->default_shell; - - if (parent->sysdb == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("Missing sysdb context in parent domain.\n")); --- -1.8.4.2 - 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 new file mode 100644 index 0000000..3b644fa --- /dev/null +++ b/SOURCES/0049-sdap_print_server-use-getpeername-to-get-server-addr.patch @@ -0,0 +1,27 @@ +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 new file mode 100644 index 0000000..0cd0508 --- /dev/null +++ b/SOURCES/0050-IPA-Don-t-fail-the-request-when-BE-doesn-t-find-the-.patch @@ -0,0 +1,53 @@ +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-NSS-Use-plain-user-name-when-expanding-homedir.patch b/SOURCES/0050-NSS-Use-plain-user-name-when-expanding-homedir.patch deleted file mode 100644 index 7fddcbd..0000000 --- a/SOURCES/0050-NSS-Use-plain-user-name-when-expanding-homedir.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 90e871a816440af34f095d3b1003476a0978a348 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 14 Jan 2014 11:10:25 +0100 -Subject: [PATCH 50/53] NSS: Use plain user name when expanding homedir - ---- - src/responder/nss/nsssrv_cmd.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index 550017c0e4385a7147ed5ef83da2c37cb97c8092..c59078b545842561a7e5f62e9a99da6057b23660 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -172,13 +172,24 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx, - struct ldb_message *msg, - struct nss_ctx *nctx, - struct sss_domain_info *dom, -- const char *name, -+ const char *orig_name, - uint32_t uid) - { - const char *homedir; -+ char *name; -+ char *domname; -+ errno_t ret; - - homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL); - -+ /* Subdomain users store FQDN in their name attribute */ -+ ret = sss_parse_name(mem_ctx, dom->names, orig_name, &domname, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not parse [%s] into " -+ "name-value components.\n", orig_name)); -+ return NULL; -+ } -+ - /* Check whether we are unconditionally overriding the server - * for home directory locations. - */ --- -1.8.4.2 - 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 new file mode 100644 index 0000000..a7eb747 --- /dev/null +++ b/SOURCES/0051-memberof-check-for-empty-arrays-to-avoid-segfaults.patch @@ -0,0 +1,41 @@ +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-simple-access-match-objects-using-flat-name.patch b/SOURCES/0051-simple-access-match-objects-using-flat-name.patch deleted file mode 100644 index cf15b3e..0000000 --- a/SOURCES/0051-simple-access-match-objects-using-flat-name.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 9df26b2f56d249ce69f7fd7d5c40b55dfe119e93 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 8 Jan 2014 15:46:57 +0000 -Subject: [PATCH 51/53] simple access: match objects using flat name - -Use flat name to recognise users and groups belonging to main sssd domain. - -Resolves: -https://fedorahosted.org/sssd/ticket/2189 ---- - src/providers/simple/simple_access.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c -index 46b045e531dfc5fcdff4fc4f5370734aca1e377c..f2bfe755039fd7a370749fd3ce94a47c62c216bc 100644 ---- a/src/providers/simple/simple_access.c -+++ b/src/providers/simple/simple_access.c -@@ -140,7 +140,9 @@ static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx, - goto done; - } - -- if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0) { -+ if (domain == NULL || strcasecmp(domain, be_ctx->domain->name) == 0 || -+ (be_ctx->domain->flat_name != NULL && -+ strcasecmp(domain, be_ctx->domain->flat_name) == 0)) { - /* This object belongs to main SSSD domain. Those users and groups - * are stored without domain part, so we will strip it off. - * */ --- -1.8.4.2 - 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 new file mode 100644 index 0000000..bcbefd1 --- /dev/null +++ b/SOURCES/0052-CONFDB-Detect-fix-misconf-opt-refresh_expired_interv.patch @@ -0,0 +1,45 @@ +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-simple-access-refresh-master-domain-info.patch b/SOURCES/0052-simple-access-refresh-master-domain-info.patch deleted file mode 100644 index 4069e20..0000000 --- a/SOURCES/0052-simple-access-refresh-master-domain-info.patch +++ /dev/null @@ -1,219 +0,0 @@ -From b6c53b49cde8188bf2f8b493b275118472c4482e Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 8 Jan 2014 16:03:08 +0000 -Subject: [PATCH 52/53] simple access: refresh master domain info - -To correctly decide if an object is a member of the main sssd domain, a flat name -is needed. However, the information may not be available when the module is -inited so it may be necessary to refresh this data later while processing a -request. - -Resolves: -https://fedorahosted.org/sssd/ticket/2189 ---- - src/providers/simple/simple_access.c | 135 +++++++++++++++++++++++------------ - src/providers/simple/simple_access.h | 2 + - 2 files changed, 92 insertions(+), 45 deletions(-) - -diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c -index f2bfe755039fd7a370749fd3ce94a47c62c216bc..eab62a826b4749aa5e5dab4a8e491fc2263be4fb 100644 ---- a/src/providers/simple/simple_access.c -+++ b/src/providers/simple/simple_access.c -@@ -32,7 +32,76 @@ - #define CONFDB_SIMPLE_ALLOW_GROUPS "simple_allow_groups" - #define CONFDB_SIMPLE_DENY_GROUPS "simple_deny_groups" - -+#define TIMEOUT_OF_REFRESH_FILTER_LISTS 5 -+ - static void simple_access_check(struct tevent_req *req); -+static errno_t simple_access_parse_names(TALLOC_CTX *mem_ctx, -+ struct be_ctx *be_ctx, -+ char **list, -+ char ***_out); -+ -+static int simple_access_obtain_filter_lists(struct simple_ctx *ctx) -+{ -+ struct be_ctx *bectx = ctx->be_ctx; -+ int ret; -+ int i; -+ struct { -+ const char *name; -+ const char *option; -+ char **orig_list; -+ char ***ctx_list; -+ } lists[] = {{"Allow users", CONFDB_SIMPLE_ALLOW_USERS, NULL, NULL}, -+ {"Deny users", CONFDB_SIMPLE_DENY_USERS, NULL, NULL}, -+ {"Allow groups", CONFDB_SIMPLE_ALLOW_GROUPS, NULL, NULL}, -+ {"Deny groups", CONFDB_SIMPLE_DENY_GROUPS, NULL, NULL}, -+ {NULL, NULL, NULL, NULL}}; -+ -+ lists[0].ctx_list = &ctx->allow_users; -+ lists[1].ctx_list = &ctx->deny_users; -+ lists[2].ctx_list = &ctx->allow_groups; -+ lists[3].ctx_list = &ctx->deny_groups; -+ -+ ret = sysdb_master_domain_update(bectx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FUNC_DATA, ("Update of master domain failed [%d]: %s.\n", -+ ret, sss_strerror(ret))); -+ goto failed; -+ } -+ -+ for (i = 0; lists[i].name != NULL; i++) { -+ ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path, -+ lists[i].option, &lists[i].orig_list); -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_FUNC_DATA, ("%s list is empty.\n", lists[i].name)); -+ *lists[i].ctx_list = NULL; -+ continue; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("confdb_get_string_as_list failed.\n")); -+ goto failed; -+ } -+ -+ ret = simple_access_parse_names(ctx, bectx, lists[i].orig_list, -+ lists[i].ctx_list); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to parse %s list [%d]: %s\n", -+ lists[i].name, ret, sss_strerror(ret))); -+ goto failed; -+ } -+ } -+ -+ if (!ctx->allow_users && -+ !ctx->allow_groups && -+ !ctx->deny_users && -+ !ctx->deny_groups) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("No rules supplied for simple access provider. " -+ "Access will be granted for all users.\n")); -+ } -+ return EOK; -+ -+failed: -+ return ret; -+} - - void simple_access_handler(struct be_req *be_req) - { -@@ -40,13 +109,16 @@ void simple_access_handler(struct be_req *be_req) - struct pam_data *pd; - struct tevent_req *req; - struct simple_ctx *ctx; -+ int ret; -+ time_t now; - - pd = talloc_get_type(be_req_get_data(be_req), struct pam_data); - - pd->pam_status = PAM_SYSTEM_ERR; - - if (pd->cmd != SSS_PAM_ACCT_MGMT) { -- DEBUG(4, ("simple access does not handles pam task %d.\n", pd->cmd)); -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ ("simple access does not handle pam task %d.\n", pd->cmd)); - pd->pam_status = PAM_MODULE_UNKNOWN; - goto done; - } -@@ -54,6 +126,18 @@ void simple_access_handler(struct be_req *be_req) - ctx = talloc_get_type(be_ctx->bet_info[BET_ACCESS].pvt_bet_data, - struct simple_ctx); - -+ -+ now = time(NULL); -+ if ((now - ctx->last_refresh_of_filter_lists) -+ > TIMEOUT_OF_REFRESH_FILTER_LISTS) { -+ -+ ret = simple_access_obtain_filter_lists(ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to refresh filter lists\n")); -+ } -+ ctx->last_refresh_of_filter_lists = now; -+ } -+ - req = simple_access_check_send(be_req, be_ctx->ev, ctx, pd->user); - if (!req) { - pd->pam_status = PAM_SYSTEM_ERR; -@@ -176,18 +260,6 @@ int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops, - { - int ret = EINVAL; - struct simple_ctx *ctx; -- int i; -- struct { -- const char *name; -- const char *option; -- char **orig_list; -- char ***ctx_list; -- } lists[] = {{"Allow users", CONFDB_SIMPLE_ALLOW_USERS, NULL, NULL}, -- {"Deny users", CONFDB_SIMPLE_DENY_USERS, NULL, NULL}, -- {"Allow groups", CONFDB_SIMPLE_ALLOW_GROUPS, NULL, NULL}, -- {"Deny groups", CONFDB_SIMPLE_DENY_GROUPS, NULL, NULL}, -- {NULL, NULL, NULL, NULL}}; -- - ctx = talloc_zero(bectx, struct simple_ctx); - if (ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n")); -@@ -196,39 +268,11 @@ int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops, - - ctx->domain = bectx->domain; - ctx->be_ctx = bectx; -+ ctx->last_refresh_of_filter_lists = 0; - -- lists[0].ctx_list = &ctx->allow_users; -- lists[1].ctx_list = &ctx->deny_users; -- lists[2].ctx_list = &ctx->allow_groups; -- lists[3].ctx_list = &ctx->deny_groups; -- -- for (i = 0; lists[i].name != NULL; i++) { -- ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path, -- lists[i].option, &lists[i].orig_list); -- if (ret == ENOENT) { -- DEBUG(SSSDBG_FUNC_DATA, ("%s list is empty.\n", lists[i].name)); -- *lists[i].ctx_list = NULL; -- continue; -- } else if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("confdb_get_string_as_list failed.\n")); -- goto failed; -- } -- -- ret = simple_access_parse_names(ctx, bectx, lists[i].orig_list, -- lists[i].ctx_list); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to parse %s list [%d]: %s\n", -- lists[i].name, ret, sss_strerror(ret))); -- goto failed; -- } -- } -- -- if (!ctx->allow_users && -- !ctx->allow_groups && -- !ctx->deny_users && -- !ctx->deny_groups) { -- DEBUG(SSSDBG_OP_FAILURE, ("No rules supplied for simple access provider. " -- "Access will be granted for all users.\n")); -+ ret = simple_access_obtain_filter_lists(ctx); -+ if (ret != EOK) { -+ goto failed; - } - - *ops = &simple_access_ops; -@@ -240,3 +284,4 @@ failed: - talloc_free(ctx); - return ret; - } -+ -diff --git a/src/providers/simple/simple_access.h b/src/providers/simple/simple_access.h -index 15dfaceb2d9a6670d3559e4a945c2c7a633fad44..a618b2e2ec16a2f32bad7ceb1f5adb7523199316 100644 ---- a/src/providers/simple/simple_access.h -+++ b/src/providers/simple/simple_access.h -@@ -32,6 +32,8 @@ struct simple_ctx { - char **deny_users; - char **allow_groups; - char **deny_groups; -+ -+ time_t last_refresh_of_filter_lists; - }; - - struct tevent_req *simple_access_check_send(TALLOC_CTX *mem_ctx, --- -1.8.4.2 - diff --git a/SOURCES/0053-NSS-add-support-for-subdomain_homedir.patch b/SOURCES/0053-NSS-add-support-for-subdomain_homedir.patch deleted file mode 100644 index c5b5068..0000000 --- a/SOURCES/0053-NSS-add-support-for-subdomain_homedir.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 7bc2cfa445142254276d712a0ff6622eaf670253 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 15 Jan 2014 15:52:35 +0000 -Subject: [PATCH 53/53] NSS: add support for subdomain_homedir - -Resolves: -https://fedorahosted.org/sssd/ticket/2169 ---- - src/responder/nss/nsssrv_cmd.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index c59078b545842561a7e5f62e9a99da6057b23660..9ac3680de4d6ff12fe0c77a3963f84934e385276 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -201,6 +201,14 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx, - name, uid, homedir, dom->name, NULL); - } - -+ /* Override home directory location for subdomains. -+ * This option can be overriden by override_homedir. -+ */ -+ if (IS_SUBDOMAIN(dom) && dom->subdomain_homedir) { -+ return expand_homedir_template(mem_ctx, dom->subdomain_homedir, -+ name, uid, homedir, dom->name, NULL); -+ } -+ - if (!homedir || *homedir == '\0') { - /* In the case of a NULL or empty homedir, check to see if - * we have a fallback homedir to use. --- -1.8.4.2 - diff --git a/SOURCES/0053-NSS-disable-midpoint-refresh-for-netgroups.patch b/SOURCES/0053-NSS-disable-midpoint-refresh-for-netgroups.patch new file mode 100644 index 0000000..21fc8ca --- /dev/null +++ b/SOURCES/0053-NSS-disable-midpoint-refresh-for-netgroups.patch @@ -0,0 +1,102 @@ +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/0054-AD-Return-right-error-code-from-netlogon_get_flat_na.patch b/SOURCES/0054-AD-Return-right-error-code-from-netlogon_get_flat_na.patch deleted file mode 100644 index afca73b..0000000 --- a/SOURCES/0054-AD-Return-right-error-code-from-netlogon_get_flat_na.patch +++ /dev/null @@ -1,29 +0,0 @@ -From e47d40005610c3f6e14d4a656fda2e8cadde4844 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 16 Jan 2014 16:42:50 +0100 -Subject: [PATCH 54/57] AD: Return right error code from netlogon_get_flat_name - -EOK was returned in done section of netlogon_get_flat_name, -even if error code was set in variable ret. - -This patch fixes also warnings from scan-build. ---- - src/providers/ad/ad_domain_info.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ad/ad_domain_info.c b/src/providers/ad/ad_domain_info.c -index 5475c5bc7ec74e81080566c6fbd6919c54a60f40..28d24b1613040ab1e85cd1504c5469aa60bc08c5 100644 ---- a/src/providers/ad/ad_domain_info.c -+++ b/src/providers/ad/ad_domain_info.c -@@ -131,7 +131,7 @@ netlogon_get_domain_info(TALLOC_CTX *mem_ctx, - ret = EOK; - done: - talloc_free(ndr_pull); -- return EOK; -+ return ret; - } - - struct ad_master_domain_state { --- -1.8.4.2 - diff --git a/SOURCES/0054-IPA-use-ipaUserGroup-object-class-for-groups.patch b/SOURCES/0054-IPA-use-ipaUserGroup-object-class-for-groups.patch new file mode 100644 index 0000000..a6d6b35 --- /dev/null +++ b/SOURCES/0054-IPA-use-ipaUserGroup-object-class-for-groups.patch @@ -0,0 +1,35 @@ +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/0055-AD-Don-t-fail-the-request-if-ad_account_can_shortcut.patch b/SOURCES/0055-AD-Don-t-fail-the-request-if-ad_account_can_shortcut.patch deleted file mode 100644 index 31bc56b..0000000 --- a/SOURCES/0055-AD-Don-t-fail-the-request-if-ad_account_can_shortcut.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 380c18bfccd25961cf56c9f61b1ac8641a2022b1 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 16 Jan 2014 20:49:15 +0100 -Subject: [PATCH 55/57] AD: Don't fail the request if ad_account_can_shortcut - fails - ---- - src/providers/ad/ad_id.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 44bfa00986b6c0ebfa65dd7b83dd45eb64b87946..ada47753fb337641df582a5a59affe8124fc2035 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -320,7 +320,9 @@ ad_account_info_handler(struct be_req *be_req) - ar->filter_type, ar->filter_value, - ar->domain, &shortcut); - if (ret != EOK) { -- goto fail; -+ DEBUG(SSSDBG_TRACE_FUNC, -+ ("Cannot determine the right domain: %s\n", sss_strerror(ret))); -+ shortcut = false; - } - - if (shortcut) { --- -1.8.4.2 - diff --git a/SOURCES/0055-Add-add_strings_lists-utility-function.patch b/SOURCES/0055-Add-add_strings_lists-utility-function.patch new file mode 100644 index 0000000..981804b --- /dev/null +++ b/SOURCES/0055-Add-add_strings_lists-utility-function.patch @@ -0,0 +1,246 @@ +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/0056-IPA-inherit-ldap_user_extra_attrs-to-AD-subdomains.patch b/SOURCES/0056-IPA-inherit-ldap_user_extra_attrs-to-AD-subdomains.patch new file mode 100644 index 0000000..585391e --- /dev/null +++ b/SOURCES/0056-IPA-inherit-ldap_user_extra_attrs-to-AD-subdomains.patch @@ -0,0 +1,72 @@ +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-MAN-Fix-a-typo.patch b/SOURCES/0056-MAN-Fix-a-typo.patch deleted file mode 100644 index 4d8b827..0000000 --- a/SOURCES/0056-MAN-Fix-a-typo.patch +++ /dev/null @@ -1,25 +0,0 @@ -From c5b312ebf55befc4d37f9a279340b55e65475cd3 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 20 Jan 2014 17:04:28 +0100 -Subject: [PATCH 56/57] MAN: Fix a typo - ---- - src/man/sssd.conf.5.xml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 43c06955d0182afe5a3c7d703f7c08b7cd09f503..b879bdf63c40e80efa21644bd9ba9d2d3477af06 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -489,7 +489,7 @@ - - example: - --override_homedir = /home/%u -+fallback_homedir = /home/%u - - - --- -1.8.4.2 - diff --git a/SOURCES/0057-Add-parse_attr_list_ex-helper-function.patch b/SOURCES/0057-Add-parse_attr_list_ex-helper-function.patch new file mode 100644 index 0000000..56a75c9 --- /dev/null +++ b/SOURCES/0057-Add-parse_attr_list_ex-helper-function.patch @@ -0,0 +1,432 @@ +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-LDAP-Fix-error-check.patch b/SOURCES/0057-LDAP-Fix-error-check.patch deleted file mode 100644 index fd1664f..0000000 --- a/SOURCES/0057-LDAP-Fix-error-check.patch +++ /dev/null @@ -1,28 +0,0 @@ -From fe7f5b1a3a965d1667ba1552a2b1165788f3bd2e Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 17 Jan 2014 10:49:27 +0100 -Subject: [PATCH 57/57] LDAP: Fix error check - -https://fedorahosted.org/sssd/ticket/2199 ---- - src/providers/ldap/ldap_common.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c -index 35ea81360b4ec61eca6b952cd86fc93a6eda17dc..4c94937aad9e25bd1cd0b6d573da2982b0f1be05 100644 ---- a/src/providers/ldap/ldap_common.c -+++ b/src/providers/ldap/ldap_common.c -@@ -831,8 +831,8 @@ errno_t common_parse_search_base(TALLOC_CTX *mem_ctx, - ret = sdap_create_search_base(search_bases, unparsed_base, - LDAP_SCOPE_SUBTREE, old_filter, - &search_bases[0]); -- if (!search_bases[0]) { -- ret = ENOMEM; -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot create new sdap search base\n")); - goto done; - } - --- -1.8.4.2 - diff --git a/SOURCES/0058-LDAP-Don-t-fail-if-subdomain-cannot-be-found-by-sid.patch b/SOURCES/0058-LDAP-Don-t-fail-if-subdomain-cannot-be-found-by-sid.patch deleted file mode 100644 index c0ab7e0..0000000 --- a/SOURCES/0058-LDAP-Don-t-fail-if-subdomain-cannot-be-found-by-sid.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 8509e1fe368b62225b7cf39eb1eec6cac7bf38b3 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 13 Dec 2013 18:20:08 +0100 -Subject: [PATCH 58/60] LDAP: Don't fail if subdomain cannot be found by sid - -Domain needn't contain sid if id_provider is ldap. -With enabled id mapping, user couldn't be stored, because domain -couldn't be found by sid. - -Resolves: -https://fedorahosted.org/sssd/ticket/2172 ---- - src/providers/ldap/sdap_async_users.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index 7f0b2eea0b5ee909bcf148236c7fc43863fe8c13..65c456c8fffb57cbf9e977a49388dbe250d1412a 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -124,6 +124,7 @@ int sdap_save_user(TALLOC_CTX *memctx, - bool use_id_mapping; - char *sid_str; - char *dom_sid_str = NULL; -+ struct sss_domain_info *subdomain; - - DEBUG(SSSDBG_TRACE_FUNC, ("Save user\n")); - -@@ -163,11 +164,12 @@ int sdap_save_user(TALLOC_CTX *memctx, - /* If this object has a SID available, we will determine the correct - * domain by its SID. */ - if (sid_str != NULL) { -- dom = find_subdomain_by_sid(get_domains_head(dom), sid_str); -- if (dom == NULL) { -- DEBUG(SSSDBG_OP_FAILURE, ("SID %s does not belong to any known " -+ subdomain = find_subdomain_by_sid(get_domains_head(dom), sid_str); -+ if (subdomain) { -+ dom = subdomain; -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, ("SID %s does not belong to any known " - "domain\n", sid_str)); -- return ERR_DOMAIN_NOT_FOUND; - } - } - --- -1.8.4.2 - diff --git a/SOURCES/0058-nss-parse-user_attributes-option.patch b/SOURCES/0058-nss-parse-user_attributes-option.patch new file mode 100644 index 0000000..c332b66 --- /dev/null +++ b/SOURCES/0058-nss-parse-user_attributes-option.patch @@ -0,0 +1,103 @@ +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/0059-LDAP-update-id-mapping-detection-for-ldap-provider.patch b/SOURCES/0059-LDAP-update-id-mapping-detection-for-ldap-provider.patch deleted file mode 100644 index f1573d8..0000000 --- a/SOURCES/0059-LDAP-update-id-mapping-detection-for-ldap-provider.patch +++ /dev/null @@ -1,33 +0,0 @@ -From adff1d0ac15ef7fd58cf2bc79af60f38c807126c Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 15 Jan 2014 14:55:10 +0100 -Subject: [PATCH 59/60] LDAP: update id mapping detection for ldap provider - -For id_provider ldap, it is only necessary to enable option ldap_id_mapping. -It is an regression introduced in the commit d3e1d88ce7de3216a862b - -Resolves: -https://fedorahosted.org/sssd/ticket/2172 ---- - src/providers/ldap/sdap_idmap.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c -index 249201def04131e01722479026b851e47e2283b5..b6455b81fbdedffc92bbaf8bdfbc12c1615a22f5 100644 ---- a/src/providers/ldap/sdap_idmap.c -+++ b/src/providers/ldap/sdap_idmap.c -@@ -522,6 +522,11 @@ bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx, - int ret; - TALLOC_CTX *tmp_ctx = NULL; - -+ if (dp_opt_get_bool(ctx->id_ctx->opts->basic, SDAP_ID_MAPPING) -+ && 0 == strcmp("ldap", ctx->id_ctx->be->bet_info[BET_ID].mod_name)) { -+ return true; -+ } -+ - err = sss_idmap_domain_has_algorithmic_mapping(ctx->map, dom_sid, - &has_algorithmic_mapping); - if (err == IDMAP_SUCCESS) { --- -1.8.4.2 - diff --git a/SOURCES/0059-nss-return-user_attributes-in-origbyname-request.patch b/SOURCES/0059-nss-return-user_attributes-in-origbyname-request.patch new file mode 100644 index 0000000..81ce0c0 --- /dev/null +++ b/SOURCES/0059-nss-return-user_attributes-in-origbyname-request.patch @@ -0,0 +1,383 @@ +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/0060-sdap_idamp-Fall-back-to-another-method-if-sid-is-wro.patch b/SOURCES/0060-sdap_idamp-Fall-back-to-another-method-if-sid-is-wro.patch deleted file mode 100644 index ccfa04f..0000000 --- a/SOURCES/0060-sdap_idamp-Fall-back-to-another-method-if-sid-is-wro.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 993aaa15cf4b128951fc9bd4a574e7ac5895d942 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 13 Dec 2013 15:33:23 +0100 -Subject: [PATCH 60/60] sdap_idamp: Fall back to another method if sid is wrong - -sss_idmap_domain_has_algorithmic_mapping can return also -IDMAP_SID_INVALID, but it does not mean that idmaping is -unavailable. We should fall back to another method of detection -(sss_idmap_domain_by_name_has_algorithmic_mapping) -and do not return false immediately. - -Resolves: -https://fedorahosted.org/sssd/ticket/2172 ---- - src/providers/ldap/sdap_idmap.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c -index b6455b81fbdedffc92bbaf8bdfbc12c1615a22f5..57c448fffa1b13699bd8042d33ac729bddb02ca8 100644 ---- a/src/providers/ldap/sdap_idmap.c -+++ b/src/providers/ldap/sdap_idmap.c -@@ -529,9 +529,15 @@ bool sdap_idmap_domain_has_algorithmic_mapping(struct sdap_idmap_ctx *ctx, - - err = sss_idmap_domain_has_algorithmic_mapping(ctx->map, dom_sid, - &has_algorithmic_mapping); -- if (err == IDMAP_SUCCESS) { -+ switch (err){ -+ case IDMAP_SUCCESS: - return has_algorithmic_mapping; -- } else if (err != IDMAP_SID_UNKNOWN && err != IDMAP_NO_DOMAIN) { -+ case IDMAP_SID_INVALID: /* FALLTHROUGH */ -+ case IDMAP_SID_UNKNOWN: /* FALLTHROUGH */ -+ case IDMAP_NO_DOMAIN: /* FALLTHROUGH */ -+ /* continue with idmap_domain_by_name */ -+ break; -+ default: - return false; - } - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..2be9d08 --- /dev/null +++ b/SOURCES/0060-sysdb_get_user_attr_with_views-add-mandatory-overrid.patch @@ -0,0 +1,100 @@ +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-krb5-hint-to-increase-krb5_auth_timeout.patch b/SOURCES/0061-krb5-hint-to-increase-krb5_auth_timeout.patch deleted file mode 100644 index 14fbea6..0000000 --- a/SOURCES/0061-krb5-hint-to-increase-krb5_auth_timeout.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 4777e706ed485ea61ebb0006c00a3d85440ffe70 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Tue, 21 Jan 2014 12:14:01 +0000 -Subject: [PATCH 61/62] krb5: hint to increase krb5_auth_timeout - -Resolves: -https://fedorahosted.org/sssd/ticket/2202 ---- - src/providers/krb5/krb5_child_handler.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c -index d6c1dc1f9707444a82e433a375839cadf73f1259..a0e8f610bbb27a25afa6171763a128dc7b8ea04d 100644 ---- a/src/providers/krb5/krb5_child_handler.c -+++ b/src/providers/krb5/krb5_child_handler.c -@@ -254,7 +254,10 @@ static void krb5_child_timeout(struct tevent_context *ev, - return; - } - -- DEBUG(9, ("timeout for child [%d] reached.\n", state->child_pid)); -+ DEBUG(SSSDBG_IMPORTANT_INFO, -+ ("Timeout for child [%d] reached. In case KDC is distant or network " -+ "is slow you may consider increasing value of krb5_auth_timeout.\n", -+ state->child_pid)); - - ret = kill(state->child_pid, SIGKILL); - if (ret == -1) { --- -1.8.4.2 - 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 new file mode 100644 index 0000000..378f73f --- /dev/null +++ b/SOURCES/0061-sysdb_add_overrides_to_object-add-new-parameter-and-.patch @@ -0,0 +1,214 @@ +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-LDAP-Don-t-abort-request-if-no-id-mapping-domain-mat.patch b/SOURCES/0062-LDAP-Don-t-abort-request-if-no-id-mapping-domain-mat.patch deleted file mode 100644 index 1957040..0000000 --- a/SOURCES/0062-LDAP-Don-t-abort-request-if-no-id-mapping-domain-mat.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 2ea997d55fb7b18bbf153d5fa625b688285dfdb9 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 24 Jan 2014 10:02:23 +0100 -Subject: [PATCH 62/62] LDAP: Don't abort request if no id mapping domain - matches - -If an ID was requested from the back end, but no ID mapping domain -matched, the request ended with a scary error message. It's better to -treat the request as if no such ID was found in the domain - -Related: -https://fedorahosted.org/sssd/ticket/2200 ---- - src/providers/ad/ad_id.c | 2 +- - src/providers/ldap/ldap_id.c | 44 +++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 40 insertions(+), 6 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index ada47753fb337641df582a5a59affe8124fc2035..e74653b734010712ff0562ce1bcbad2b03aba27e 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -386,7 +386,7 @@ ad_account_info_complete(struct tevent_req *req) - error_text = NULL; - } else { - DEBUG(SSSDBG_FATAL_FAILURE, -- ("Bug: dp_error is OK on failed request")); -+ ("Bug: dp_error is OK on failed request\n")); - dp_error = DP_ERR_FATAL; - error_text = req_error_text; - } -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index 793bc99ebcec883be7db3fc9dd56fa511d8ba3bb..e36c1f697c18e865a47d991dad103fc440456118 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -129,7 +129,20 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - /* Convert the UID to its objectSID */ - err = sss_idmap_unix_to_sid(ctx->opts->idmap_ctx->map, - uid, &sid); -- if (err != IDMAP_SUCCESS) { -+ if (err == IDMAP_NO_DOMAIN) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("[%s] did not match any configured ID mapping domain\n", -+ name)); -+ -+ ret = sysdb_delete_user(state->sysdb, -+ state->domain, NULL, uid); -+ if (ret == ENOENT) { -+ /* Ignore errors to remove users that were not cached previously */ -+ ret = EOK; -+ } -+ -+ goto fail; -+ } else if (err != IDMAP_SUCCESS) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Mapping ID [%s] to SID failed: [%s]\n", - name, idmap_error_string(err))); -@@ -213,7 +226,11 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - return req; - - fail: -- tevent_req_error(req, ret); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } else { -+ tevent_req_done(req); -+ } - tevent_req_post(req, ev); - return req; - } -@@ -496,10 +513,23 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - goto fail; - } - -- /* Convert the UID to its objectSID */ -+ /* Convert the GID to its objectSID */ - err = sss_idmap_unix_to_sid(ctx->opts->idmap_ctx->map, - gid, &sid); -- if (err != IDMAP_SUCCESS) { -+ if (err == IDMAP_NO_DOMAIN) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("[%s] did not match any configured ID mapping domain\n", -+ name)); -+ -+ ret = sysdb_delete_group(state->sysdb, -+ state->domain, NULL, gid); -+ if (ret == ENOENT) { -+ /* Ignore errors to remove users that were not cached previously */ -+ ret = EOK; -+ } -+ -+ goto fail; -+ } else if (err != IDMAP_SUCCESS) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Mapping ID [%s] to SID failed: [%s]\n", - name, idmap_error_string(err))); -@@ -587,7 +617,11 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - return req; - - fail: -- tevent_req_error(req, ret); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } else { -+ tevent_req_done(req); -+ } - tevent_req_post(req, ev); - return req; - } --- -1.8.4.2 - diff --git a/SOURCES/0062-Views-apply-user-SSH-public-key-override.patch b/SOURCES/0062-Views-apply-user-SSH-public-key-override.patch new file mode 100644 index 0000000..d61f8f8 --- /dev/null +++ b/SOURCES/0062-Views-apply-user-SSH-public-key-override.patch @@ -0,0 +1,317 @@ +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/0063-Add-test-for-sysdb_add_overrides_to_object.patch b/SOURCES/0063-Add-test-for-sysdb_add_overrides_to_object.patch new file mode 100644 index 0000000..0d8d7d3 --- /dev/null +++ b/SOURCES/0063-Add-test-for-sysdb_add_overrides_to_object.patch @@ -0,0 +1,290 @@ +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-sudo-memset-tm-when-converting-time-attributes.patch b/SOURCES/0063-sudo-memset-tm-when-converting-time-attributes.patch deleted file mode 100644 index f53462a..0000000 --- a/SOURCES/0063-sudo-memset-tm-when-converting-time-attributes.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 89eca8339610956f8d95d701dc02d3f8256e2770 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 29 Jan 2014 12:56:08 +0100 -Subject: [PATCH 63/71] sudo: memset tm when converting time attributes - -strptime() which is used to parse LDAP time value does not initialize -all fields of tm structure (especially tm_isdst). This results in -random behavior - when the tm is converted into timestamp via mktime(), -the result depends on current value of tm_isdst. - -Resolves: -https://fedorahosted.org/sssd/ticket/2213 - -b ---- - src/db/sysdb_sudo.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c -index 4e98b5b35f3968a1db68c32812eac71670578b60..ceaecbd2666cfb84422bd72b3109da9c4aa0f0f3 100644 ---- a/src/db/sysdb_sudo.c -+++ b/src/db/sysdb_sudo.c -@@ -56,6 +56,8 @@ static errno_t sysdb_sudo_convert_time(const char *str, time_t *unix_time) - NULL}; - - for (format = formats; *format != NULL; format++) { -+ /* strptime() may leave some fields uninitialized */ -+ memset(&tm, 0, sizeof(struct tm)); - tret = strptime(str, *format, &tm); - if (tret != NULL && *tret == '\0') { - *unix_time = mktime(&tm); --- -1.8.4.2 - diff --git a/SOURCES/0064-AD-Don-t-mark-domain-as-enumerated-twice.patch b/SOURCES/0064-AD-Don-t-mark-domain-as-enumerated-twice.patch deleted file mode 100644 index 0e318c1..0000000 --- a/SOURCES/0064-AD-Don-t-mark-domain-as-enumerated-twice.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 392058122b5993a195436c2d5d9833e5e1dd0198 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 16 Dec 2013 03:36:19 +0100 -Subject: [PATCH 64/71] AD: Don't mark domain as enumerated twice - -The domain was already marked as enumerated using sysdb_set_enumerated -in the enumeration request itself. ---- - src/providers/ad/ad_id.c | 13 ------------- - 1 file changed, 13 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index e74653b734010712ff0562ce1bcbad2b03aba27e..85edcf6d604f705f5645f77689c2b4c7471b5edd 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -571,19 +571,6 @@ ad_enumeration_done(struct tevent_req *subreq) - return; - } - -- /* Ok, we've completed an enumeration. Save this to the -- * sysdb so we can postpone starting up the enumeration -- * process on the next SSSD service restart (to avoid -- * slowing down system boot-up -- */ -- ret = sysdb_set_enumerated(state->sdom->dom->sysdb, -- state->sdom->dom, true); -- if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Could not mark domain as having enumerated.\n")); -- /* This error is non-fatal, so continue */ -- } -- - tevent_req_done(req); - } - --- -1.8.4.2 - diff --git a/SOURCES/0064-Add-ssh-pubkey-to-origbyname-request.patch b/SOURCES/0064-Add-ssh-pubkey-to-origbyname-request.patch new file mode 100644 index 0000000..c9cd2be --- /dev/null +++ b/SOURCES/0064-Add-ssh-pubkey-to-origbyname-request.patch @@ -0,0 +1,38 @@ +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/0065-AD-Store-info-on-whether-a-subdomain-is-set-to-enume.patch b/SOURCES/0065-AD-Store-info-on-whether-a-subdomain-is-set-to-enume.patch deleted file mode 100644 index 284d0d1..0000000 --- a/SOURCES/0065-AD-Store-info-on-whether-a-subdomain-is-set-to-enume.patch +++ /dev/null @@ -1,97 +0,0 @@ -From c6808be838567870a251d79baad1080910f6ec4c Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 10 Dec 2013 17:33:35 +0100 -Subject: [PATCH 65/71] AD: Store info on whether a subdomain is set to - enumerate - -Depending on the state of the subdomain_enumerate variable, the newly -created subdomain object is created with the right value of "enumerate" -attribute in the sysdb. ---- - src/providers/ad/ad_subdomains.c | 38 +++++++++++++++++++++++++++++++++----- - 1 file changed, 33 insertions(+), 5 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 62c3e16d0d3323a32848b4fbf54d2a151c16f64c..348561a85524c203293c713d3f31552a99d74a43 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -223,10 +223,28 @@ ads_store_sdap_subdom(struct ad_subdomains_ctx *ctx, - return EOK; - } - -+static errno_t ad_subdom_enumerates(struct sss_domain_info *parent, -+ struct sysdb_attrs *attrs, -+ bool *_enumerates) -+{ -+ errno_t ret; -+ const char *name; -+ -+ ret = sysdb_attrs_get_string(attrs, AD_AT_TRUST_PARTNER, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); -+ return ret; -+ } -+ -+ *_enumerates = subdomain_enumerates(parent, name); -+ return EOK; -+} -+ - static errno_t - ad_subdom_store(struct ad_subdomains_ctx *ctx, - struct sss_domain_info *domain, -- struct sysdb_attrs *subdom_attrs) -+ struct sysdb_attrs *subdom_attrs, -+ bool enumerate) - { - TALLOC_CTX *tmp_ctx; - const char *name; -@@ -293,9 +311,8 @@ ad_subdom_store(struct ad_subdomains_ctx *ctx, - name, - sid_str); - -- /* AD subdomains are currently all mpg and do not enumerate */ - ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str, -- mpg, false, domain->forest); -+ mpg, enumerate, domain->forest); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_subdomain_store failed.\n")); - goto done; -@@ -319,6 +336,7 @@ static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx, - const char *value; - int c, h; - int ret; -+ bool enumerate; - - domain = ctx->be_ctx->domain; - memset(handled, 0, sizeof(bool) * count); -@@ -367,7 +385,12 @@ static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx, - talloc_zfree(sdom); - } else { - /* ok let's try to update it */ -- ret = ad_subdom_store(ctx, domain, reply[c]); -+ ret = ad_subdom_enumerates(domain, reply[c], &enumerate); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = ad_subdom_store(ctx, domain, reply[c], enumerate); - if (ret) { - /* Nothing we can do about the error. Let's at least try - * to reuse the existing domains -@@ -396,7 +419,12 @@ static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx, - /* Nothing we can do about the error. Let's at least try - * to reuse the existing domains. - */ -- ret = ad_subdom_store(ctx, domain, reply[c]); -+ ret = ad_subdom_enumerates(domain, reply[c], &enumerate); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = ad_subdom_store(ctx, domain, reply[c], enumerate); - if (ret) { - DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to parse subdom data, " - "will try to use cached subdomain\n")); --- -1.8.4.2 - 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 new file mode 100644 index 0000000..a15d69a --- /dev/null +++ b/SOURCES/0065-BUILD-Install-ldap_child-and-as-setuid-if-running-un.patch @@ -0,0 +1,51 @@ +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/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 new file mode 100644 index 0000000..f11e54f --- /dev/null +++ b/SOURCES/0066-LDAP-Move-sss_krb5_verify_keytab_ex-to-ldap_child.patch @@ -0,0 +1,220 @@ +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-LDAP-Pass-a-private-context-to-enumeration-ptask-ins.patch b/SOURCES/0066-LDAP-Pass-a-private-context-to-enumeration-ptask-ins.patch deleted file mode 100644 index bba823a..0000000 --- a/SOURCES/0066-LDAP-Pass-a-private-context-to-enumeration-ptask-ins.patch +++ /dev/null @@ -1,284 +0,0 @@ -From 1a5d7f670d94cb5c2b4a727e1e4cb3f1debadaa7 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 10 Dec 2013 21:49:45 +0100 -Subject: [PATCH 66/71] LDAP: Pass a private context to enumeration ptask - instead of hardcoded connection - -Previously, the sdap-domain enumeration request used a single connection context to -download all the data. Now we'd like to use different connections to -download different objects, so the ID context is passed in and the -request itself decides which connection to use for the sdap-domain -enumeration. ---- - src/providers/ad/ad_id.c | 12 ++++++++---- - src/providers/ad/ad_init.c | 7 ++++--- - src/providers/ad/ad_subdomains.c | 8 +++++--- - src/providers/ipa/ipa_subdomains.c | 8 +++++--- - src/providers/ldap/ldap_common.c | 15 +++++++++------ - src/providers/ldap/ldap_common.h | 17 +++++++++-------- - src/providers/ldap/ldap_id_enum.c | 21 ++++++++++++--------- - 7 files changed, 52 insertions(+), 36 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 85edcf6d604f705f5645f77689c2b4c7471b5edd..99383c13bdadfe9eb2af9f9323ca19a9759d4620 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -414,6 +414,7 @@ ad_check_online(struct be_req *be_req) - } - - struct ad_enumeration_state { -+ struct ad_id_ctx *id_ctx; - struct ldap_enum_ctx *ectx; - struct sdap_id_op *sdap_op; - struct tevent_context *ev; -@@ -443,6 +444,7 @@ ad_enumeration_send(TALLOC_CTX *mem_ctx, - - ectx = talloc_get_type(pvt, struct ldap_enum_ctx); - if (ectx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve ldap_enum_ctx!\n")); - ret = EFAULT; - goto fail; - } -@@ -450,8 +452,10 @@ ad_enumeration_send(TALLOC_CTX *mem_ctx, - state->ectx = ectx; - state->ev = ev; - state->sdom = ectx->sdom; -+ state->id_ctx = talloc_get_type(ectx->pvt, struct ad_id_ctx); - -- state->sdap_op = sdap_id_op_create(state, ectx->conn->conn_cache); -+ state->sdap_op = sdap_id_op_create(state, -+ state->id_ctx->ldap_ctx->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed.\n")); - ret = ENOMEM; -@@ -500,7 +504,7 @@ ad_enumeration_conn_done(struct tevent_req *subreq) - } - - subreq = ad_master_domain_send(state, state->ev, -- state->ectx->conn, -+ state->id_ctx->ldap_ctx, - state->sdap_op, - state->sdom->dom->name); - if (subreq == NULL) { -@@ -540,8 +544,8 @@ ad_enumeration_master_done(struct tevent_req *subreq) - return; - } - -- subreq = sdap_dom_enum_send(state, state->ev, state->ectx->ctx, -- state->sdom, state->ectx->conn); -+ subreq = sdap_dom_enum_send(state, state->ev, state->id_ctx->sdap_id_ctx, -+ state->sdom, state->id_ctx->ldap_ctx); - if (subreq == NULL) { - /* The ptask API will reschedule the enumeration on its own on - * failure */ -diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c -index ed69a7d9889bac1281b5ff7c7b0f290ab09173fb..eff6d990d131e3aba124d252d001dd39e78b45cf 100644 ---- a/src/providers/ad/ad_init.c -+++ b/src/providers/ad/ad_init.c -@@ -205,11 +205,12 @@ sssm_ad_id_init(struct be_ctx *bectx, - goto done; - } - -- ret = sdap_id_setup_tasks(ad_ctx->sdap_id_ctx, -- ad_ctx->sdap_id_ctx->conn, -+ ret = sdap_id_setup_tasks(bectx, -+ ad_ctx->sdap_id_ctx, - ad_ctx->sdap_id_ctx->opts->sdom, - ad_enumeration_send, -- ad_enumeration_recv); -+ ad_enumeration_recv, -+ ad_ctx); - if (ret != EOK) { - goto done; - } -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 348561a85524c203293c713d3f31552a99d74a43..e7871cc32407893948fe1b2803258d68c70889c1 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -177,10 +177,12 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, - return EFAULT; - } - -- ret = sdap_id_setup_tasks(ad_id_ctx->sdap_id_ctx, -- ad_id_ctx->ldap_ctx, sdom, -+ ret = sdap_id_setup_tasks(be_ctx, -+ ad_id_ctx->sdap_id_ctx, -+ sdom, - ldap_enumeration_send, -- ldap_enumeration_recv); -+ ldap_enumeration_recv, -+ ad_id_ctx->sdap_id_ctx); - if (ret != EOK) { - talloc_free(ad_options); - return ret; -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index d9c204451f1b734ee98ce4c48f3f139731e47dec..88b6ba52538be83417e98c9a5dd033bea87ebe4b 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -183,10 +183,12 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, - return EFAULT; - } - -- ret = sdap_id_setup_tasks(ad_id_ctx->sdap_id_ctx, -- ad_id_ctx->ldap_ctx, sdom, -+ ret = sdap_id_setup_tasks(be_ctx, -+ ad_id_ctx->sdap_id_ctx, -+ sdom, - ldap_enumeration_send, -- ldap_enumeration_recv); -+ ldap_enumeration_recv, -+ ad_id_ctx->sdap_id_ctx); - if (ret != EOK) { - talloc_free(ad_options); - return ret; -diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c -index 4c94937aad9e25bd1cd0b6d573da2982b0f1be05..e799c783c118309409faca0294eadc4736d15108 100644 ---- a/src/providers/ldap/ldap_common.c -+++ b/src/providers/ldap/ldap_common.c -@@ -974,16 +974,18 @@ void sdap_mark_offline(struct sdap_id_ctx *ctx) - - int ldap_id_setup_tasks(struct sdap_id_ctx *ctx) - { -- return sdap_id_setup_tasks(ctx, ctx->conn, ctx->opts->sdom, -+ return sdap_id_setup_tasks(ctx->be, ctx, ctx->opts->sdom, - ldap_enumeration_send, -- ldap_enumeration_recv); -+ ldap_enumeration_recv, -+ ctx); - } - --int sdap_id_setup_tasks(struct sdap_id_ctx *ctx, -- struct sdap_id_conn_ctx *conn, -+int sdap_id_setup_tasks(struct be_ctx *be_ctx, -+ struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - be_ptask_send_t send_fn, -- be_ptask_recv_t recv_fn) -+ be_ptask_recv_t recv_fn, -+ void *pvt) - { - int ret; - -@@ -991,7 +993,8 @@ int sdap_id_setup_tasks(struct sdap_id_ctx *ctx, - if (sdom->dom->enumerate) { - DEBUG(SSSDBG_TRACE_FUNC, ("Setting up enumeration for %s\n", - sdom->dom->name)); -- ret = ldap_setup_enumeration(ctx, conn, sdom, send_fn, recv_fn); -+ ret = ldap_setup_enumeration(be_ctx, ctx->opts, sdom, -+ send_fn, recv_fn, pvt); - } else { - /* the enumeration task, runs the cleanup process by itself, - * but if enumeration is not running we need to schedule it */ -diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h -index b3bd950e1dca6df0f5668397d5e5a0796e519862..889d5b118861e4ea3f51ab8a8ea5c5947e2560b9 100644 ---- a/src/providers/ldap/ldap_common.h -+++ b/src/providers/ldap/ldap_common.h -@@ -95,11 +95,12 @@ void sdap_handle_account_info(struct be_req *breq, struct sdap_id_ctx *ctx, - - /* Set up enumeration and/or cleanup */ - int ldap_id_setup_tasks(struct sdap_id_ctx *ctx); --int sdap_id_setup_tasks(struct sdap_id_ctx *ctx, -- struct sdap_id_conn_ctx *conn, -+int sdap_id_setup_tasks(struct be_ctx *be_ctx, -+ struct sdap_id_ctx *ctx, - struct sdap_domain *sdom, - be_ptask_send_t send_fn, -- be_ptask_recv_t recv_fn); -+ be_ptask_recv_t recv_fn, -+ void *pvt); - - struct tevent_req * - sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, -@@ -177,16 +178,16 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx, - * structure that contains the request data - */ - struct ldap_enum_ctx { -- struct sdap_id_ctx *ctx; - struct sdap_domain *sdom; -- struct sdap_id_conn_ctx *conn; -+ void *pvt; - }; - --errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, -- struct sdap_id_conn_ctx *conn, -+errno_t ldap_setup_enumeration(struct be_ctx *be_ctx, -+ struct sdap_options *opts, - struct sdap_domain *sdom, - be_ptask_send_t send_fn, -- be_ptask_recv_t recv_fn); -+ be_ptask_recv_t recv_fn, -+ void *pvt); - struct tevent_req * - ldap_enumeration_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, -diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c -index 8cccaa916a24beb10fe692d9a0e09f5f47ceb6f7..c791496a6143b23118bf17a58f738fb0bfb5f95a 100644 ---- a/src/providers/ldap/ldap_id_enum.c -+++ b/src/providers/ldap/ldap_id_enum.c -@@ -27,11 +27,12 @@ - #include "providers/ldap/ldap_common.h" - #include "providers/ldap/sdap_async_enum.h" - --errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, -- struct sdap_id_conn_ctx *conn, -+errno_t ldap_setup_enumeration(struct be_ctx *be_ctx, -+ struct sdap_options *opts, - struct sdap_domain *sdom, - be_ptask_send_t send_fn, -- be_ptask_recv_t recv_fn) -+ be_ptask_recv_t recv_fn, -+ void *pvt) - { - errno_t ret; - time_t first_delay; -@@ -60,17 +61,16 @@ errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, - first_delay = 0; - } - -- period = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); -+ period = dp_opt_get_int(opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); - - ectx = talloc(sdom, struct ldap_enum_ctx); - if (ectx == NULL) { - return ENOMEM; - } -- ectx->ctx = ctx; - ectx->sdom = sdom; -- ectx->conn = conn; -+ ectx->pvt = pvt; - -- ret = be_ptask_create(sdom, ctx->be, -+ ret = be_ptask_create(sdom, be_ctx, - period, /* period */ - first_delay, /* first_delay */ - 5, /* enabled delay */ -@@ -91,6 +91,7 @@ errno_t ldap_setup_enumeration(struct sdap_id_ctx *ctx, - - struct ldap_enumeration_state { - struct ldap_enum_ctx *ectx; -+ struct sdap_id_ctx *id_ctx; - struct sss_domain_info *dom; - }; - -@@ -118,14 +119,16 @@ ldap_enumeration_send(TALLOC_CTX *mem_ctx, - - ectx = talloc_get_type(pvt, struct ldap_enum_ctx); - if (ectx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve ldap_enum_ctx!\n")); - ret = EFAULT; - goto fail; - } - state->ectx = ectx; - state->dom = ectx->sdom->dom; -+ state->id_ctx = talloc_get_type_abort(ectx->pvt, struct sdap_id_ctx); - -- subreq = sdap_dom_enum_send(ectx, ev, ectx->ctx, ectx->sdom, -- ectx->conn); -+ subreq = sdap_dom_enum_send(ectx, ev, state->id_ctx, ectx->sdom, -+ state->id_ctx->conn); - if (subreq == NULL) { - /* The ptask API will reschedule the enumeration on its own on - * failure */ --- -1.8.4.2 - diff --git a/SOURCES/0067-LDAP-Add-enum-request-with-custom-connection.patch b/SOURCES/0067-LDAP-Add-enum-request-with-custom-connection.patch deleted file mode 100644 index 04b5e24..0000000 --- a/SOURCES/0067-LDAP-Add-enum-request-with-custom-connection.patch +++ /dev/null @@ -1,482 +0,0 @@ -From 431198674303beea2a6a25af6d3fa4e852995b26 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 16 Dec 2013 02:41:53 +0100 -Subject: [PATCH 67/71] LDAP: Add enum request with custom connection - -This commit changes the enumerate-sdap-domain request to accept a -connection context per object that can be enumerated. Internally in the -request, an sdap_id_op is also created per enumerated object type. - -This change will allow i.e. users to be enumerated using GC connection, -while keeping the LDAP connection for groups and services. ---- - src/providers/ldap/sdap_async_enum.c | 309 +++++++++++++++++++++-------------- - src/providers/ldap/sdap_async_enum.h | 11 ++ - 2 files changed, 193 insertions(+), 127 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c -index 8487f9a13b279bc71f633590bbab163945fc8f7c..cbc56be20526e6c2323f9fd1b49038dd4bf13fe5 100644 ---- a/src/providers/ldap/sdap_async_enum.c -+++ b/src/providers/ldap/sdap_async_enum.c -@@ -47,49 +47,56 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - bool purge); - static errno_t enum_groups_recv(struct tevent_req *req); - --/* ==Enumeration-Request==================================================== */ --struct sdap_dom_enum_state { -+/* ==Enumeration-Request-with-connections=================================== */ -+struct sdap_dom_enum_ex_state { - struct tevent_context *ev; - struct sdap_id_ctx *ctx; - struct sdap_domain *sdom; -- struct sdap_id_conn_ctx *conn; -- struct sdap_id_op *op; -+ -+ struct sdap_id_conn_ctx *user_conn; -+ struct sdap_id_conn_ctx *group_conn; -+ struct sdap_id_conn_ctx *svc_conn; -+ struct sdap_id_op *user_op; -+ struct sdap_id_op *group_op; -+ struct sdap_id_op *svc_op; - - bool purge; - }; - --static errno_t sdap_dom_enum_retry(struct tevent_req *req); --static void sdap_dom_enum_conn_done(struct tevent_req *subreq); --static void sdap_dom_enum_users_done(struct tevent_req *subreq); --static void sdap_dom_enum_groups_done(struct tevent_req *subreq); --static void sdap_dom_enum_services_done(struct tevent_req *subreq); -+static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req, -+ struct sdap_id_op *op, -+ tevent_req_fn tcb); -+static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq); -+static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq); -+static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq); -+static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq); -+static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq); -+static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq); -+static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq); - - struct tevent_req * --sdap_dom_enum_send(TALLOC_CTX *memctx, -- struct tevent_context *ev, -- struct sdap_id_ctx *ctx, -- struct sdap_domain *sdom, -- struct sdap_id_conn_ctx *conn) -+sdap_dom_enum_ex_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *ctx, -+ struct sdap_domain *sdom, -+ struct sdap_id_conn_ctx *user_conn, -+ struct sdap_id_conn_ctx *group_conn, -+ struct sdap_id_conn_ctx *svc_conn) - { - struct tevent_req *req; -- struct sdap_dom_enum_state *state; -+ struct sdap_dom_enum_ex_state *state; - int t; - errno_t ret; - -- req = tevent_req_create(ctx, &state, struct sdap_dom_enum_state); -- if (!req) return NULL; -+ req = tevent_req_create(ctx, &state, struct sdap_dom_enum_ex_state); -+ if (req == NULL) return NULL; - - state->ev = ev; - state->ctx = ctx; - state->sdom = sdom; -- state->conn = conn; -- state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); -- if (!state->op) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create failed\n")); -- ret = EIO; -- goto fail; -- } -- -+ state->user_conn = user_conn; -+ state->group_conn = group_conn; -+ state->svc_conn = svc_conn; - sdom->last_enum = tevent_timeval_current(); - - t = dp_opt_get_int(ctx->opts->basic, SDAP_CACHE_PURGE_TIMEOUT); -@@ -97,9 +104,17 @@ sdap_dom_enum_send(TALLOC_CTX *memctx, - state->purge = true; - } - -- ret = sdap_dom_enum_retry(req); -+ state->user_op = sdap_id_op_create(state, user_conn->conn_cache); -+ if (state->user_op == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create failed for users\n")); -+ ret = EIO; -+ goto fail; -+ } -+ -+ ret = sdap_dom_enum_ex_retry(req, state->user_op, -+ sdap_dom_enum_ex_get_users); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("ldap_id_enumerate_retry failed\n")); -+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_dom_enum_ex_retry failed\n")); - goto fail; - } - -@@ -111,31 +126,32 @@ fail: - return req; - } - --static errno_t sdap_dom_enum_retry(struct tevent_req *req) -+static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req, -+ struct sdap_id_op *op, -+ tevent_req_fn tcb) - { -- struct sdap_dom_enum_state *state = tevent_req_data(req, -- struct sdap_dom_enum_state); -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); - struct tevent_req *subreq; - errno_t ret; - -- subreq = sdap_id_op_connect_send(state->op, state, &ret); -+ subreq = sdap_id_op_connect_send(op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, - ("sdap_id_op_connect_send failed: %d\n", ret)); - return ret; - } - -- tevent_req_set_callback(subreq, sdap_dom_enum_conn_done, req); -+ tevent_req_set_callback(subreq, tcb, req); - return EOK; - } - --static void sdap_dom_enum_conn_done(struct tevent_req *subreq) -+static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq) - { -+ errno_t ret; -+ int dp_error; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); -- struct sdap_dom_enum_state *state = tevent_req_data(req, -- struct sdap_dom_enum_state); -- int ret, dp_error; - - ret = sdap_id_op_connect_recv(subreq, &dp_error); - talloc_zfree(subreq); -@@ -150,150 +166,173 @@ static void sdap_dom_enum_conn_done(struct tevent_req *subreq) - "LDAP server: (%d)[%s]\n", ret, strerror(ret))); - tevent_req_error(req, ret); - } -+ return false; -+ } -+ -+ return true; -+} -+ -+static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ -+ if (sdap_dom_enum_ex_connected(subreq) == false) { - return; - } - - subreq = enum_users_send(state, state->ev, - state->ctx, state->sdom, -- state->op, state->purge); -+ state->user_op, state->purge); - if (subreq == NULL) { - tevent_req_error(req, ENOMEM); - return; - } -- tevent_req_set_callback(subreq, sdap_dom_enum_users_done, req); -+ tevent_req_set_callback(subreq, sdap_dom_enum_ex_users_done, req); - } - --static void sdap_dom_enum_users_done(struct tevent_req *subreq) -+static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq) - { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); -- struct sdap_dom_enum_state *state = tevent_req_data(req, -- struct sdap_dom_enum_state); -- uint64_t err = 0; -- int ret, dp_error = DP_ERR_FATAL; -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ errno_t ret; -+ int dp_error; - -- err = enum_users_recv(subreq); -+ ret = enum_users_recv(subreq); - talloc_zfree(subreq); -- if (err != EOK && err != ENOENT) { -- /* We call sdap_id_op_done only on error -- * as the connection is reused by groups enumeration */ -- ret = sdap_id_op_done(state->op, (int)err, &dp_error); -- if (dp_error == DP_ERR_OK) { -- /* retry */ -- ret = sdap_dom_enum_retry(req); -- if (ret == EOK) { -- return; -- } -- -- dp_error = DP_ERR_FATAL; -- } -- -- if (dp_error == DP_ERR_OFFLINE) { -- tevent_req_done(req); -- } else { -- DEBUG(SSSDBG_OP_FAILURE, -- ("User enumeration failed with: (%d)[%s]\n", -- ret, strerror(ret))); -+ ret = sdap_id_op_done(state->user_op, ret, &dp_error); -+ if (dp_error == DP_ERR_OK && ret != EOK) { -+ /* retry */ -+ ret = sdap_dom_enum_ex_retry(req, state->user_op, -+ sdap_dom_enum_ex_get_users); -+ if (ret != EOK) { - tevent_req_error(req, ret); -+ return; - } - return; - } - -+ state->group_op = sdap_id_op_create(state, state->group_conn->conn_cache); -+ if (state->group_op == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create failed for groups\n")); -+ tevent_req_error(req, EIO); -+ return; -+ } -+ -+ ret = sdap_dom_enum_ex_retry(req, state->group_op, -+ sdap_dom_enum_ex_get_groups); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Continues to sdap_dom_enum_ex_get_groups */ -+} -+ -+static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ -+ if (sdap_dom_enum_ex_connected(subreq) == false) { -+ return; -+ } -+ - subreq = enum_groups_send(state, state->ev, state->ctx, - state->sdom, -- state->op, state->purge); -+ state->group_op, state->purge); - if (subreq == NULL) { - tevent_req_error(req, ENOMEM); - return; - } -- tevent_req_set_callback(subreq, sdap_dom_enum_groups_done, req); -+ tevent_req_set_callback(subreq, sdap_dom_enum_ex_groups_done, req); - } - --static void sdap_dom_enum_groups_done(struct tevent_req *subreq) -+static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq) - { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); -- struct sdap_dom_enum_state *state = tevent_req_data(req, -- struct sdap_dom_enum_state); -- uint64_t err = 0; -- int ret, dp_error = DP_ERR_FATAL; -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ int ret; -+ int dp_error; - -- err = enum_groups_recv(subreq); -+ ret = enum_groups_recv(subreq); - talloc_zfree(subreq); -- if (err != EOK && err != ENOENT) { -- /* We call sdap_id_op_done only on error -- * as the connection is reused by services enumeration */ -- ret = sdap_id_op_done(state->op, (int)err, &dp_error); -- if (dp_error == DP_ERR_OK && ret != EOK) { -- /* retry */ -- ret = sdap_dom_enum_retry(req); -- if (ret == EOK) { -- return; -- } -- -- dp_error = DP_ERR_FATAL; -- } -- -+ ret = sdap_id_op_done(state->group_op, ret, &dp_error); -+ if (dp_error == DP_ERR_OK && ret != EOK) { -+ /* retry */ -+ ret = sdap_dom_enum_ex_retry(req, state->group_op, -+ sdap_dom_enum_ex_get_groups); - if (ret != EOK) { -- if (dp_error == DP_ERR_OFFLINE) { -- tevent_req_done(req); -- } else { -- DEBUG(SSSDBG_OP_FAILURE, -- ("Group enumeration failed with: (%d)[%s]\n", -- ret, strerror(ret))); -- tevent_req_error(req, ret); -- } -- -+ tevent_req_error(req, ret); - return; - } -+ return; -+ } -+ -+ -+ state->svc_op = sdap_id_op_create(state, state->svc_conn->conn_cache); -+ if (state->svc_op == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create failed for svcs\n")); -+ tevent_req_error(req, EIO); -+ return; -+ } -+ -+ ret = sdap_dom_enum_ex_retry(req, state->svc_op, -+ sdap_dom_enum_ex_get_svcs); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+} -+ -+static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ -+ if (sdap_dom_enum_ex_connected(subreq) == false) { -+ return; - } - - subreq = enum_services_send(state, state->ev, state->ctx, -- state->op, state->purge); -+ state->svc_op, state->purge); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } -- tevent_req_set_callback(subreq, sdap_dom_enum_services_done, req); -+ tevent_req_set_callback(subreq, sdap_dom_enum_ex_svcs_done, req); - } - --static void sdap_dom_enum_services_done(struct tevent_req *subreq) -+static void sdap_dom_enum_ex_svcs_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 sdap_dom_enum_state *state = tevent_req_data(req, -- struct sdap_dom_enum_state); -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ int ret; -+ int dp_error; - - ret = enum_services_recv(subreq); - talloc_zfree(subreq); -- if (ret == ENOENT) ret = EOK; -- -- /* All enumerations are complete, so conclude the -- * id_op -- */ -- ret = sdap_id_op_done(state->op, ret, &dp_error); -+ ret = sdap_id_op_done(state->svc_op, ret, &dp_error); - if (dp_error == DP_ERR_OK && ret != EOK) { - /* retry */ -- ret = sdap_dom_enum_retry(req); -- if (ret == EOK) { -- return; -- } -- -- dp_error = DP_ERR_FATAL; -- } -- -- if (ret != EOK) { -- if (dp_error == DP_ERR_OFFLINE) { -- tevent_req_done(req); -- } else { -- DEBUG(SSSDBG_MINOR_FAILURE, -- ("Service enumeration failed with: (%d)[%s]\n", -- ret, strerror(ret))); -+ ret = sdap_dom_enum_ex_retry(req, state->user_op, -+ sdap_dom_enum_ex_get_svcs); -+ if (ret != EOK) { - tevent_req_error(req, ret); -+ return; - } -- - return; - } - -@@ -323,11 +362,27 @@ static void sdap_dom_enum_services_done(struct tevent_req *subreq) - tevent_req_done(req); - } - -+errno_t sdap_dom_enum_ex_recv(struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -+ -+/* ==Enumeration-Request==================================================== */ -+struct tevent_req * -+sdap_dom_enum_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *ctx, -+ struct sdap_domain *sdom, -+ struct sdap_id_conn_ctx *conn) -+{ -+ return sdap_dom_enum_ex_send(memctx, ev, ctx, sdom, conn, conn, conn); -+} -+ - errno_t sdap_dom_enum_recv(struct tevent_req *req) - { -- TEVENT_REQ_RETURN_ON_ERROR(req); -- -- return EOK; -+ return sdap_dom_enum_ex_recv(req); - } - - /* ==User-Enumeration===================================================== */ -diff --git a/src/providers/ldap/sdap_async_enum.h b/src/providers/ldap/sdap_async_enum.h -index 04ec8c6dcbec4bcce0de67b9e10acc857c9e9416..2da38f988913fa0d6f252697925e50e05eb794a6 100644 ---- a/src/providers/ldap/sdap_async_enum.h -+++ b/src/providers/ldap/sdap_async_enum.h -@@ -27,6 +27,17 @@ - #define _SDAP_ASYNC_ENUM_H_ - - struct tevent_req * -+sdap_dom_enum_ex_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sdap_id_ctx *ctx, -+ struct sdap_domain *sdom, -+ struct sdap_id_conn_ctx *user_conn, -+ struct sdap_id_conn_ctx *group_conn, -+ struct sdap_id_conn_ctx *svc_conn); -+ -+errno_t sdap_dom_enum_ex_recv(struct tevent_req *req); -+ -+struct tevent_req * - sdap_dom_enum_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_id_ctx *ctx, --- -1.8.4.2 - 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 new file mode 100644 index 0000000..4b66c75 --- /dev/null +++ b/SOURCES/0067-LDAP-read-the-correct-data-type-from-ldap_child-s-in.patch @@ -0,0 +1,34 @@ +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/0068-AD-Enumerate-users-from-GC-other-entities-from-LDAP.patch b/SOURCES/0068-AD-Enumerate-users-from-GC-other-entities-from-LDAP.patch deleted file mode 100644 index b8b61b9..0000000 --- a/SOURCES/0068-AD-Enumerate-users-from-GC-other-entities-from-LDAP.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 1a077f0af935497b972a763a7027924a65476b01 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 28 Jan 2014 13:59:44 +0100 -Subject: [PATCH 68/71] AD: Enumerate users from GC, other entities from LDAP - ---- - src/providers/ad/ad_id.c | 20 +++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 99383c13bdadfe9eb2af9f9323ca19a9759d4620..a47aa4f75ab348b0f4597fea264d770b5abe3184 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -526,6 +526,7 @@ ad_enumeration_master_done(struct tevent_req *subreq) - char *flat_name; - char *master_sid; - char *forest; -+ struct sdap_id_conn_ctx *user_conn; - - ret = ad_master_domain_recv(subreq, state, - &flat_name, &master_sid, &forest); -@@ -544,8 +545,21 @@ ad_enumeration_master_done(struct tevent_req *subreq) - return; - } - -- subreq = sdap_dom_enum_send(state, state->ev, state->id_ctx->sdap_id_ctx, -- state->sdom, state->id_ctx->ldap_ctx); -+ if (dp_opt_get_bool(state->id_ctx->ad_options->basic, AD_ENABLE_GC)) { -+ user_conn = state->id_ctx->gc_ctx; -+ } else { -+ user_conn = state->id_ctx->ldap_ctx; -+ } -+ -+ /* Groups are searched for in LDAP, users in GC. Services (if present, -+ * which is unlikely in AD) from LDAP as well -+ */ -+ subreq = sdap_dom_enum_ex_send(state, state->ev, -+ state->id_ctx->sdap_id_ctx, -+ state->sdom, -+ user_conn, /* Users */ -+ state->id_ctx->ldap_ctx, /* Groups */ -+ state->id_ctx->ldap_ctx); /* Services */ - if (subreq == NULL) { - /* The ptask API will reschedule the enumeration on its own on - * failure */ -@@ -566,7 +580,7 @@ ad_enumeration_done(struct tevent_req *subreq) - struct ad_enumeration_state *state = tevent_req_data(req, - struct ad_enumeration_state); - -- ret = sdap_dom_enum_recv(subreq); -+ ret = sdap_dom_enum_ex_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, --- -1.8.4.2 - 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 new file mode 100644 index 0000000..fef3059 --- /dev/null +++ b/SOURCES/0068-LDAP-Drop-privileges-after-kinit-in-ldap_child.patch @@ -0,0 +1,214 @@ +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/0069-LDAP-Don-t-clobber-original_member-during-enumeratio.patch b/SOURCES/0069-LDAP-Don-t-clobber-original_member-during-enumeratio.patch deleted file mode 100644 index 7523a4a..0000000 --- a/SOURCES/0069-LDAP-Don-t-clobber-original_member-during-enumeratio.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 37722379349e257e2e77583e515ceafa3eee804c Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 21 Jan 2014 23:40:17 +0100 -Subject: [PATCH 69/71] LDAP: Don't clobber original_member during enumeration - ---- - src/providers/ldap/sdap_async_groups.c | 17 +++++++++++------ - 1 file changed, 11 insertions(+), 6 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 9eece9a6e4baaf302a28b57a63dae45a0741136c..4ed7d4ab9c0c932da49b244f061329a334719159 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -807,6 +807,7 @@ static int sdap_save_groups(TALLOC_CTX *memctx, - int num_groups, - bool populate_members, - hash_table_t *ghosts, -+ bool save_orig_member, - char **_usn_value) - { - TALLOC_CTX *tmpctx; -@@ -864,9 +865,9 @@ static int sdap_save_groups(TALLOC_CTX *memctx, - usn_value = NULL; - - /* if 2 pass savemembers = false */ -- ret = sdap_save_group(tmpctx, sysdb, -- opts, dom, groups[i], -- populate_members, has_nesting, -+ ret = sdap_save_group(tmpctx, sysdb, opts, dom, groups[i], -+ populate_members, -+ has_nesting && save_orig_member, - ghosts, &usn_value, now); - - /* Do not fail completely on errors. -@@ -1835,7 +1836,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - "to allow unrolling of nested groups.\n")); - ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts, - state->groups, state->count, false, -- NULL, NULL); -+ NULL, true, NULL); - if (ret) { - DEBUG(2, ("Failed to store groups.\n")); - tevent_req_error(req, ret); -@@ -1887,10 +1888,14 @@ static void sdap_get_groups_done(struct tevent_req *subreq) - - /* If ignore_group_members is set for the domain, don't update - * group memberships in the cache. -+ * -+ * If enumeration is on, don't overwrite orig_members as they've been -+ * saved earlier. - */ - ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts, - state->groups, state->count, - !state->dom->ignore_group_members, NULL, -+ !state->enumeration, - &state->higher_usn); - if (ret) { - DEBUG(2, ("Failed to store groups.\n")); -@@ -2014,7 +2019,7 @@ static void sdap_ad_match_rule_members_process(struct tevent_req *subreq) - /* Now save the group, users and ghosts to the cache */ - ret = sdap_save_groups(tmp_ctx, state->sysdb, state->dom, - state->opts, state->groups, 1, -- false, ghosts, NULL); -+ false, ghosts, true, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - ("Could not save group to the cache: [%s]\n", -@@ -2090,7 +2095,7 @@ static void sdap_nested_done(struct tevent_req *subreq) - } - - ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts, -- groups, group_count, false, ghosts, -+ groups, group_count, false, ghosts, true, - &state->higher_usn); - if (ret != EOK) { - goto fail; --- -1.8.4.2 - diff --git a/SOURCES/0069-UTIL-Remove-code-duplication-of-struct-io.patch b/SOURCES/0069-UTIL-Remove-code-duplication-of-struct-io.patch new file mode 100644 index 0000000..6f7d29d --- /dev/null +++ b/SOURCES/0069-UTIL-Remove-code-duplication-of-struct-io.patch @@ -0,0 +1,218 @@ +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-DB-Add-sss_ldb_el_to_string_list.patch b/SOURCES/0070-DB-Add-sss_ldb_el_to_string_list.patch deleted file mode 100644 index 8b9b419..0000000 --- a/SOURCES/0070-DB-Add-sss_ldb_el_to_string_list.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 329165182d0decee35f3837c1d2ad899f99e9950 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 28 Jan 2014 14:51:58 +0100 -Subject: [PATCH 70/71] DB: Add sss_ldb_el_to_string_list - ---- - src/db/sysdb.c | 41 ++++++++++++++++++++++++++--------------- - src/db/sysdb.h | 2 ++ - src/tests/sysdb-tests.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 77 insertions(+), 15 deletions(-) - -diff --git a/src/db/sysdb.c b/src/db/sysdb.c -index 0e07ed60858298a1ac85d06146ccb98c5899a705..592cadc1a322ee8504c407a508e34e7eb9465a15 100644 ---- a/src/db/sysdb.c -+++ b/src/db/sysdb.c -@@ -466,35 +466,46 @@ errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name, - return EOK; - } - --int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name, -- TALLOC_CTX *mem_ctx, const char ***string) -+const char **sss_ldb_el_to_string_list(TALLOC_CTX *mem_ctx, -+ struct ldb_message_element *el) - { -- struct ldb_message_element *el; -- int ret; - unsigned int u; - const char **a; - -- ret = sysdb_attrs_get_el_ext(attrs, name, false, &el); -- if (ret) { -- return ret; -- } -- -- a = talloc_array(mem_ctx, const char *, el->num_values + 1); -+ a = talloc_zero_array(mem_ctx, const char *, el->num_values + 1); - if (a == NULL) { -- return ENOMEM; -+ return NULL; - } - -- memset(a, 0, sizeof(const char *) * (el->num_values + 1)); -- -- for(u = 0; u < el->num_values; u++) { -+ for (u = 0; u < el->num_values; u++) { - a[u] = talloc_strndup(a, (const char *)el->values[u].data, - el->values[u].length); - if (a[u] == NULL) { - talloc_free(a); -- return ENOMEM; -+ return NULL; - } - } - -+ return a; -+} -+ -+int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name, -+ TALLOC_CTX *mem_ctx, const char ***string) -+{ -+ struct ldb_message_element *el; -+ int ret; -+ const char **a; -+ -+ ret = sysdb_attrs_get_el_ext(attrs, name, false, &el); -+ if (ret) { -+ return ret; -+ } -+ -+ a = sss_ldb_el_to_string_list(mem_ctx, el); -+ if (a == NULL) { -+ return ENOMEM; -+ } -+ - *string = a; - return EOK; - } -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 9677294b22e47f5169d7631673beec2dbc6117ad..5bd2c50ebff1ca1f4bb11d12e40512d8f460acbb 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -288,6 +288,8 @@ int sysdb_attrs_steal_string(struct sysdb_attrs *attrs, - const char *name, char *str); - int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name, - const char **string); -+const char **sss_ldb_el_to_string_list(TALLOC_CTX *mem_ctx, -+ struct ldb_message_element *el); - int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name, - TALLOC_CTX *mem_ctx, const char ***string); - errno_t sysdb_attrs_get_bool(struct sysdb_attrs *attrs, const char *name, -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index 63ffac82e15849e5f6534462ce7c58b183412acc..69b09c7d4580595854330062e0f549eab1f8cf22 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -4449,6 +4449,52 @@ START_TEST(test_sysdb_attrs_add_lc_name_alias) - } - END_TEST - -+START_TEST(test_sysdb_attrs_get_string_array) -+{ -+ int ret; -+ struct sysdb_attrs *attrs; -+ const char **list; -+ const char *attrname = "test_attr"; -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_message_element *el = NULL; -+ -+ tmp_ctx = talloc_new(NULL); -+ fail_unless(tmp_ctx != NULL, "talloc_new failed"); -+ -+ attrs = sysdb_new_attrs(NULL); -+ fail_unless(attrs != NULL, "sysdb_new_attrs failed"); -+ -+ ret = sysdb_attrs_add_string(attrs, attrname, "val1"); -+ fail_unless(ret == EOK, "sysdb_attrs_add_string failed"); -+ ret = sysdb_attrs_add_string(attrs, attrname, "val2"); -+ fail_unless(ret == EOK, "sysdb_attrs_add_string failed"); -+ -+ ret = sysdb_attrs_get_el_ext(attrs, attrname, false, &el); -+ fail_unless(ret == EOK, "sysdb_attrs_get_el_ext failed"); -+ -+ list = sss_ldb_el_to_string_list(tmp_ctx, el); -+ fail_if(list == NULL, ("sss_ldb_el_to_string_list failed\n")); -+ -+ ck_assert_str_eq(list[0], "val1"); -+ ck_assert_str_eq(list[1], "val2"); -+ fail_unless(list[2] == NULL, "Expected terminated list"); -+ -+ talloc_free(list); -+ -+ ret = sysdb_attrs_get_string_array(attrs, attrname, tmp_ctx, &list); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string_array failed"); -+ -+ /* This test relies on values keeping the same order. It is the case -+ * with LDB, but if we ever switch from LDB, we need to amend the test -+ */ -+ ck_assert_str_eq(list[0], "val1"); -+ ck_assert_str_eq(list[1], "val2"); -+ fail_unless(list[2] == NULL, "Expected terminated list"); -+ -+ talloc_free(tmp_ctx); -+} -+END_TEST -+ - START_TEST(test_sysdb_has_enumerated) - { - errno_t ret; -@@ -5217,6 +5263,9 @@ Suite *create_sysdb_suite(void) - - tcase_add_test(tc_sysdb, test_sysdb_attrs_add_lc_name_alias); - -+/* ===== UTIL TESTS ===== */ -+ tcase_add_test(tc_sysdb, test_sysdb_attrs_get_string_array); -+ - /* Add all test cases to the test suite */ - suite_add_tcase(s, tc_sysdb); - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..c12d4ca --- /dev/null +++ b/SOURCES/0070-UTIL-Remove-more-code-duplication-setting-up-child-p.patch @@ -0,0 +1,184 @@ +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/0071-AD-Establish-cross-domain-memberships-after-enumerat.patch b/SOURCES/0071-AD-Establish-cross-domain-memberships-after-enumerat.patch deleted file mode 100644 index fc32870..0000000 --- a/SOURCES/0071-AD-Establish-cross-domain-memberships-after-enumerat.patch +++ /dev/null @@ -1,508 +0,0 @@ -From 8c714cbf1d0ce2cbddc4222ade51e1f93f36dbe8 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Jan 2014 15:21:24 +0100 -Subject: [PATCH 71/71] AD: Establish cross-domain memberships after - enumeration finishes - -Because domain enumeration currently works for each domain separately, -the code has to establish cross-domain memberships after all domains are -enumerated. The code works as follows: - - 1) check if any *sub*domains were enumerated. If not, do nothing - 2) if any of the groups saved had more original members than - sysdb members, check if members of these groups can be linked now - that all users and groups are saved using the orig_member - attribute of the group matched against originalDN member of the - user. - -Related: -https://fedorahosted.org/sssd/ticket/2142 ---- - src/providers/ad/ad_id.c | 390 +++++++++++++++++++++++++++++++++++++-- - src/providers/ad/ad_subdomains.c | 11 -- - 2 files changed, 379 insertions(+), 22 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index a47aa4f75ab348b0f4597fea264d770b5abe3184..e3302c15774ab1c24b16cefc274313e447b31e5c 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -420,10 +420,13 @@ struct ad_enumeration_state { - struct tevent_context *ev; - - struct sdap_domain *sdom; -+ struct sdap_domain *sditer; - }; - - static void ad_enumeration_conn_done(struct tevent_req *subreq); - static void ad_enumeration_master_done(struct tevent_req *subreq); -+static errno_t ad_enum_sdom(struct tevent_req *req, struct sdap_domain *sd, -+ struct ad_id_ctx *id_ctx); - static void ad_enumeration_done(struct tevent_req *subreq); - - struct tevent_req * -@@ -452,6 +455,7 @@ ad_enumeration_send(TALLOC_CTX *mem_ctx, - state->ectx = ectx; - state->ev = ev; - state->sdom = ectx->sdom; -+ state->sditer = state->sdom; - state->id_ctx = talloc_get_type(ectx->pvt, struct ad_id_ctx); - - state->sdap_op = sdap_id_op_create(state, -@@ -526,7 +530,6 @@ ad_enumeration_master_done(struct tevent_req *subreq) - char *flat_name; - char *master_sid; - char *forest; -- struct sdap_id_conn_ctx *user_conn; - - ret = ad_master_domain_recv(subreq, state, - &flat_name, &master_sid, &forest); -@@ -545,32 +548,57 @@ ad_enumeration_master_done(struct tevent_req *subreq) - return; - } - -- if (dp_opt_get_bool(state->id_ctx->ad_options->basic, AD_ENABLE_GC)) { -- user_conn = state->id_ctx->gc_ctx; -+ ret = ad_enum_sdom(req, state->sdom, state->id_ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not enumerate domain %s\n", state->sdom->dom->name)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Execution will resume in ad_enumeration_done */ -+} -+ -+static errno_t -+ad_enum_sdom(struct tevent_req *req, -+ struct sdap_domain *sd, -+ struct ad_id_ctx *id_ctx) -+{ -+ struct sdap_id_conn_ctx *user_conn; -+ struct tevent_req *subreq; -+ struct ad_enumeration_state *state = tevent_req_data(req, -+ struct ad_enumeration_state); -+ -+ if (dp_opt_get_bool(id_ctx->ad_options->basic, AD_ENABLE_GC)) { -+ user_conn = id_ctx->gc_ctx; - } else { -- user_conn = state->id_ctx->ldap_ctx; -+ user_conn = id_ctx->ldap_ctx; - } - - /* Groups are searched for in LDAP, users in GC. Services (if present, - * which is unlikely in AD) from LDAP as well - */ - subreq = sdap_dom_enum_ex_send(state, state->ev, -- state->id_ctx->sdap_id_ctx, -- state->sdom, -- user_conn, /* Users */ -- state->id_ctx->ldap_ctx, /* Groups */ -- state->id_ctx->ldap_ctx); /* Services */ -+ id_ctx->sdap_id_ctx, -+ sd, -+ user_conn, /* Users */ -+ id_ctx->ldap_ctx, /* Groups */ -+ id_ctx->ldap_ctx); /* Services */ - if (subreq == NULL) { - /* The ptask API will reschedule the enumeration on its own on - * failure */ - DEBUG(SSSDBG_OP_FAILURE, - ("Failed to schedule enumeration, retrying later!\n")); -- tevent_req_error(req, ENOMEM); -- return; -+ return ENOMEM; - } - tevent_req_set_callback(subreq, ad_enumeration_done, req); -+ -+ return EOK; - } - -+static errno_t ad_enum_cross_dom_members(struct sdap_options *opts, -+ struct sss_domain_info *dom); -+ - static void - ad_enumeration_done(struct tevent_req *subreq) - { -@@ -579,6 +607,7 @@ ad_enumeration_done(struct tevent_req *subreq) - struct tevent_req); - struct ad_enumeration_state *state = tevent_req_data(req, - struct ad_enumeration_state); -+ struct ad_id_ctx *subdom_id_ctx; - - ret = sdap_dom_enum_ex_recv(subreq); - talloc_zfree(subreq); -@@ -589,9 +618,348 @@ ad_enumeration_done(struct tevent_req *subreq) - return; - } - -+ state->sditer = state->sditer->next; -+ if (state->sditer != NULL) { -+ subdom_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx); -+ if (subdom_id_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve subdomain ad_id_ctx!\n")); -+ tevent_req_error(req, EFAULT); -+ return; -+ } -+ -+ ret = ad_enum_sdom(req, state->sditer, state->sditer->pvt); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Could not enumerate domain %s\n", -+ state->sditer->dom->name)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Execution will resume in ad_enumeration_done */ -+ return; -+ } -+ -+ /* No more subdomains to enumerate. Check if we need to fixup -+ * cross-domain membership -+ */ -+ if (state->sditer != state->sdom) { -+ /* We did enumerate at least one subdomain. Walk the subdomains -+ * and fixup members for each of them -+ */ -+ for (state->sditer = state->sdom; -+ state->sditer; -+ state->sditer = state->sditer->next) { -+ ret = ad_enum_cross_dom_members(state->id_ctx->ad_options->id, -+ state->sditer->dom); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Could not check cross-domain " -+ "memberships for %s, group memberships might be " -+ "incomplete!\n", state->sdom->dom->name)); -+ continue; -+ } -+ } -+ } -+ - tevent_req_done(req); - } - -+static errno_t ad_group_extra_members(TALLOC_CTX *mem_ctx, -+ const struct ldb_message *group, -+ struct sss_domain_info *dom, -+ char ***_group_only); -+static errno_t ad_group_add_member(struct sdap_options *opts, -+ struct sss_domain_info *group_domain, -+ struct ldb_dn *group_dn, -+ const char *member); -+ -+static errno_t -+ad_enum_cross_dom_members(struct sdap_options *opts, -+ struct sss_domain_info *dom) -+{ -+ errno_t ret; -+ errno_t sret; -+ char *filter; -+ TALLOC_CTX *tmp_ctx; -+ const char *attrs[] = { -+ SYSDB_NAME, -+ SYSDB_MEMBER, -+ SYSDB_ORIG_MEMBER, -+ NULL -+ }; -+ size_t count, i, mi; -+ struct ldb_message **msgs; -+ bool in_transaction = false; -+ char **group_only; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) return ENOMEM; -+ -+ ret = sysdb_transaction_start(dom->sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); -+ goto done; -+ } -+ in_transaction = true; -+ -+ filter = talloc_asprintf(tmp_ctx, "(%s=*)", SYSDB_NAME); -+ if (filter == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_search_groups(tmp_ctx, dom->sysdb, dom, -+ filter, attrs, &count, &msgs); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ for (i = 0; i < count; i++) { -+ ret = ad_group_extra_members(tmp_ctx, msgs[i], dom, &group_only); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to check extra members\n")); -+ } else if (group_only == NULL) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("No extra members\n")); -+ continue; -+ } -+ -+ /* Group has extra members */ -+ for (mi = 0; group_only[mi]; mi++) { -+ ret = ad_group_add_member(opts, dom, msgs[i]->dn, group_only[mi]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add [%s]: %s\n", -+ group_only[mi], strerror(ret))); -+ continue; -+ } -+ } -+ -+ talloc_zfree(group_only); -+ } -+ -+ ret = sysdb_transaction_commit(dom->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(dom->sysdb); -+ if (sret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n")); -+ } -+ } -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t -+ad_group_stored_orig_members(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, -+ struct ldb_dn *dn, char ***_odn_list); -+ -+static errno_t -+ad_group_extra_members(TALLOC_CTX *mem_ctx, const struct ldb_message *group, -+ struct sss_domain_info *dom, char ***_group_only) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_message_element *m, *om; -+ const char *name; -+ errno_t ret; -+ char **sysdb_odn_list; -+ const char **group_odn_list; -+ char **group_only = NULL; -+ -+ if (_group_only == NULL) return EINVAL; -+ *_group_only = NULL; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) return ENOMEM; -+ -+ om = ldb_msg_find_element(group, SYSDB_ORIG_MEMBER); -+ m = ldb_msg_find_element(group, SYSDB_MEMBER); -+ name = ldb_msg_find_attr_as_string(group, SYSDB_NAME, NULL); -+ if (name == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("A group with no name!\n")); -+ ret = EFAULT; -+ goto done; -+ } -+ -+ if (om == NULL || om->num_values == 0) { -+ DEBUG(SSSDBG_TRACE_FUNC, ("Group %s has no original members\n", name)); -+ ret = EOK; -+ goto done; -+ } -+ -+ if (m == NULL || (m->num_values < om->num_values)) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ ("Group %s has %d members but %d original members\n", -+ name, m ? m->num_values : 0, om->num_values)); -+ -+ /* Get the list of originalDN attributes that are already -+ * linked to the group -+ */ -+ ret = ad_group_stored_orig_members(tmp_ctx, dom, group->dn, -+ &sysdb_odn_list); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not retrieve list of original members for %s\n", -+ name)); -+ goto done; -+ } -+ -+ /* Get the list of original DN attributes the group had in AD */ -+ group_odn_list = sss_ldb_el_to_string_list(tmp_ctx, om); -+ if (group_odn_list == NULL) { -+ ret = EFAULT; -+ goto done; -+ } -+ -+ /* Compare the two lists */ -+ ret = diff_string_lists(tmp_ctx, discard_const(group_odn_list), -+ sysdb_odn_list, &group_only, NULL, NULL); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not compare lists of members for %s\n", name)); -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+ *_group_only = talloc_steal(mem_ctx, group_only); -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t -+ad_group_stored_orig_members(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, -+ struct ldb_dn *dn, char ***_odn_list) -+{ -+ errno_t ret; -+ TALLOC_CTX *tmp_ctx; -+ size_t m_count, i; -+ struct ldb_message **members; -+ const char *attrs[] = { -+ SYSDB_NAME, -+ SYSDB_ORIG_DN, -+ NULL -+ }; -+ char **odn_list; -+ const char *odn; -+ size_t oi; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) return ENOMEM; -+ -+ /* Get all entries member element points to */ -+ ret = sysdb_asq_search(tmp_ctx, dom->sysdb, dn, NULL, SYSDB_MEMBER, -+ attrs, &m_count, &members); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ odn_list = talloc_zero_array(tmp_ctx, char *, m_count + 1); -+ if (odn_list == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* Get a list of their original DNs */ -+ oi = 0; -+ for (i = 0; i < m_count; i++) { -+ odn = ldb_msg_find_attr_as_string(members[i], SYSDB_ORIG_DN, NULL); -+ if (odn == NULL) { -+ continue; -+ } -+ -+ odn_list[oi] = talloc_strdup(odn_list, odn); -+ if (odn_list[oi] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ oi++; -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Member %s already in sysdb\n", odn)); -+ } -+ -+ ret = EOK; -+ *_odn_list = talloc_steal(mem_ctx, odn_list); -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t -+ad_group_add_member(struct sdap_options *opts, -+ struct sss_domain_info *group_domain, -+ struct ldb_dn *group_dn, -+ const char *member) -+{ -+ struct sdap_domain *sd; -+ struct ldb_dn *base_dn; -+ TALLOC_CTX *tmp_ctx; -+ errno_t ret; -+ const char *mem_filter; -+ size_t msgs_count; -+ struct ldb_message **msgs; -+ -+ /* This member would be from a different domain */ -+ sd = sdap_domain_get_by_dn(opts, member); -+ if (sd == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("No matching domain for %s\n", member)); -+ return ENOENT; -+ } -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) return ENOMEM; -+ -+ mem_filter = talloc_asprintf(tmp_ctx, "(%s=%s)", -+ SYSDB_ORIG_DN, member); -+ if (mem_filter == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ base_dn = sysdb_domain_dn(sd->dom->sysdb, tmp_ctx, sd->dom); -+ if (base_dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_search_entry(tmp_ctx, sd->dom->sysdb, base_dn, -+ LDB_SCOPE_SUBTREE, mem_filter, NULL, -+ &msgs_count, &msgs); -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_TRACE_FUNC, ("No member [%s] in sysdb\n", member)); -+ ret = EOK; -+ goto done; -+ } else if (ret != EOK) { -+ goto done; -+ } -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("[%s] found in sysdb\n", member)); -+ -+ if (msgs_count != 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Search by orig DN returned %zd results!\n", msgs_count)); -+ ret = EFAULT; -+ goto done; -+ } -+ -+ ret = sysdb_mod_group_member(group_domain->sysdb, msgs[0]->dn, -+ group_dn, SYSDB_MOD_ADD); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Could not add [%s] as a member of [%s]\n", -+ ldb_dn_get_linearized(msgs[0]->dn), -+ ldb_dn_get_linearized(group_dn))); -+ goto done; -+ } -+ -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ - errno_t - ad_enumeration_recv(struct tevent_req *req) - { -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index e7871cc32407893948fe1b2803258d68c70889c1..0d9652b5c615add47958cfdc61eba862a332ae4d 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -177,17 +177,6 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, - return EFAULT; - } - -- ret = sdap_id_setup_tasks(be_ctx, -- ad_id_ctx->sdap_id_ctx, -- sdom, -- ldap_enumeration_send, -- ldap_enumeration_recv, -- ad_id_ctx->sdap_id_ctx); -- if (ret != EOK) { -- talloc_free(ad_options); -- return ret; -- } -- - /* Set up the ID mapping object */ - ad_id_ctx->sdap_id_ctx->opts->idmap_ctx = - id_ctx->sdap_id_ctx->opts->idmap_ctx; --- -1.8.4.2 - 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 new file mode 100644 index 0000000..f19dd79 --- /dev/null +++ b/SOURCES/0071-IPA-Move-setting-the-SELinux-context-to-a-child-proc.patch @@ -0,0 +1,927 @@ +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/0072-AD-SRV-use-right-domain-name-for-CLDAP-ping.patch b/SOURCES/0072-AD-SRV-use-right-domain-name-for-CLDAP-ping.patch deleted file mode 100644 index b3f1d9c..0000000 --- a/SOURCES/0072-AD-SRV-use-right-domain-name-for-CLDAP-ping.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 9118f124fad5fe15c5beb910db08794d9b3d2685 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 24 Jan 2014 16:52:22 +0100 -Subject: [PATCH 72/73] AD SRV: use right domain name for CLDAP ping - -Currently always the name of the configured domain was passed to the -CLDAP request. This will fail if the CLDAP request is send to a DC form -a different domain. ---- - src/providers/ad/ad_srv.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ad/ad_srv.c b/src/providers/ad/ad_srv.c -index a238c192e495c3ff6330123d8e53d7d480e88e1b..99502e431e7b8b053e6ec58780abfd10859937be 100644 ---- a/src/providers/ad/ad_srv.c -+++ b/src/providers/ad/ad_srv.c -@@ -723,7 +723,7 @@ static void ad_srv_plugin_dcs_done(struct tevent_req *subreq) - state->ctx->be_res, - state->ctx->host_dbs, - state->ctx->opts, -- state->ctx->ad_domain, -+ state->discovery_domain, - dcs, num_dcs); - if (subreq == NULL) { - ret = ENOMEM; --- -1.8.4.2 - 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 new file mode 100644 index 0000000..904977c --- /dev/null +++ b/SOURCES/0072-test_sysdb_views-Use-unique-directory-for-cache.patch @@ -0,0 +1,48 @@ +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/0073-MAN-clarify-which-shell-option-takes-precedence.patch b/SOURCES/0073-MAN-clarify-which-shell-option-takes-precedence.patch deleted file mode 100644 index e6fd18e..0000000 --- a/SOURCES/0073-MAN-clarify-which-shell-option-takes-precedence.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 045b0cbf342d50ce07fc768fbce63b9bd0309215 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 29 Jan 2014 13:24:15 +0100 -Subject: [PATCH 73/73] MAN: clarify which shell option takes precedence - ---- - src/man/sssd.conf.5.xml | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index b879bdf63c40e80efa21644bd9ba9d2d3477af06..84770f6b28876278a0ddd6d8a8a8f9a8e0d3146f 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -503,8 +503,9 @@ fallback_homedir = /home/%u - - - Override the login shell for all users. This -- option can be specified globally in the [nss] -- section or per-domain. -+ option supersedes any other shell options if -+ it takes effect and can be set either in the -+ [nss] section or per-domain. - - - Default: not set (SSSD will use the value -@@ -568,10 +569,10 @@ fallback_homedir = /home/%u - default_shell - - -- The default shell to use if the provider does not -- return one during lookup. This option supersedes -- any other shell options if it takes effect and can -- be set either in the [nss] section or per-domain. -+ The default shell to use if the provider does -+ not return one during lookup. This option can -+ be specified globally in the [nss] section -+ or per-domain. - - - Default: not set (Return NULL if no shell is --- -1.8.4.2 - diff --git a/SOURCES/0073-selinux_child-Do-not-ignore-return-values.patch b/SOURCES/0073-selinux_child-Do-not-ignore-return-values.patch new file mode 100644 index 0000000..fcc0efb --- /dev/null +++ b/SOURCES/0073-selinux_child-Do-not-ignore-return-values.patch @@ -0,0 +1,37 @@ +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/0074-IPA-Store-right-username-to-selinux-child-context.patch b/SOURCES/0074-IPA-Store-right-username-to-selinux-child-context.patch new file mode 100644 index 0000000..968b699 --- /dev/null +++ b/SOURCES/0074-IPA-Store-right-username-to-selinux-child-context.patch @@ -0,0 +1,31 @@ +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-LDAP-store-group-if-subdomain-cannot-be-found-by-sid.patch b/SOURCES/0074-LDAP-store-group-if-subdomain-cannot-be-found-by-sid.patch deleted file mode 100644 index 1caa79e..0000000 --- a/SOURCES/0074-LDAP-store-group-if-subdomain-cannot-be-found-by-sid.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 53554c55a75477b0ea719b845ff1660ac1a2ec82 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 24 Jan 2014 17:03:27 +0100 -Subject: [PATCH 74/75] LDAP: store group if subdomain cannot be found by sid - -Domain needn't contain sid if id_provider is ldap. -With enabled id mapping, group couldn't be stored, because domain -couldn't be found by sid. - -Resolves: -https://fedorahosted.org/sssd/ticket/2172 ---- - src/providers/ldap/sdap_async_groups.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 4ed7d4ab9c0c932da49b244f061329a334719159..ab3691f80aaecca988dcbf0877491a37af3ae49b 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -452,6 +452,7 @@ static int sdap_save_group(TALLOC_CTX *memctx, - bool posix_group; - bool use_id_mapping; - char *sid_str; -+ struct sss_domain_info *subdomain; - int32_t ad_group_type; - - tmpctx = talloc_new(NULL); -@@ -490,11 +491,12 @@ static int sdap_save_group(TALLOC_CTX *memctx, - /* If this object has a SID available, we will determine the correct - * domain by its SID. */ - if (sid_str != NULL) { -- dom = find_subdomain_by_sid(get_domains_head(dom), sid_str); -- if (dom == NULL) { -- DEBUG(SSSDBG_OP_FAILURE, ("SID %s does not belong to any known " -+ subdomain = find_subdomain_by_sid(get_domains_head(dom), sid_str); -+ if (subdomain) { -+ dom = subdomain; -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, ("SID %s does not belong to any known " - "domain\n", sid_str)); -- return ERR_DOMAIN_NOT_FOUND; - } - } - --- -1.8.4.2 - diff --git a/SOURCES/0075-LDAP-require-attribute-groupType-for-AD-groups.patch b/SOURCES/0075-LDAP-require-attribute-groupType-for-AD-groups.patch deleted file mode 100644 index ea1b78c..0000000 --- a/SOURCES/0075-LDAP-require-attribute-groupType-for-AD-groups.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 42817081e7afe5b67d4151c5ac87b0a48da31a1b Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 29 Jan 2014 14:58:53 +0100 -Subject: [PATCH 75/75] LDAP: require attribute groupType for AD groups - -Commit 8280c5213094 introduced filtering local groups for trusted/sub domains, -but attribute groupType was not available with configuration id_provide ldap -and ldap_schema ad. - -Resolves: -https://fedorahosted.org/sssd/ticket/2172 ---- - src/providers/ldap/ldap_opts.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h -index 9593dfd30a81db60b7358c66975871507340aa4b..d07051c51aef860943ee8bd4953e8f3d0660a656 100644 ---- a/src/providers/ldap/ldap_opts.h -+++ b/src/providers/ldap/ldap_opts.h -@@ -295,7 +295,7 @@ struct sdap_attr_map gen_ad2008r2_group_map[] = { - { "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 }, -- { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL }, -+ { "ldap_group_type", "groupType", SYSDB_GROUP_TYPE, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - --- -1.8.4.2 - 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 new file mode 100644 index 0000000..a8c6200 --- /dev/null +++ b/SOURCES/0075-PAM-Remove-authtok-from-PAM-stack-with-OTP.patch @@ -0,0 +1,87 @@ +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-MONITOR-Incorrect-permissions-on-sssd.conf.patch b/SOURCES/0076-MONITOR-Incorrect-permissions-on-sssd.conf.patch deleted file mode 100644 index 381c18e..0000000 --- a/SOURCES/0076-MONITOR-Incorrect-permissions-on-sssd.conf.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 3af4a383964cf391e0277bd8a272156a1805e357 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 5 Feb 2014 17:32:20 +0000 -Subject: [PATCH 76/80] MONITOR: Incorrect permissions on sssd.conf - -Print user friendly warning when permissions on sssd.conf are incorrect and -provide hint. - -Resolves: -https://fedorahosted.org/sssd/ticket/2208 - -Reviewed-by: Stephen Gallagher -(cherry picked from commit b3cc9b98966fa2d90172348c334b3b70c5261ab3) ---- - src/monitor/monitor.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c -index 09f530d2643b45fc31fb4dbe3cb69f2abc5510af..72a8b7c4a376dd9b68349b959cb869b9da059d38 100644 ---- a/src/monitor/monitor.c -+++ b/src/monitor/monitor.c -@@ -84,6 +84,11 @@ - */ - #define KRB5_RCACHE_DIR_DISABLE "__LIBKRB5_DEFAULTS__" - -+/* Warning messages */ -+#define CONF_FILE_PERM_ERROR_MSG "Cannot read config file %s. Please check "\ -+ "if permissions are 0600 and the file is "\ -+ "owned by root.root." -+ - int cmdline_debug_level; - int cmdline_debug_timestamps; - int cmdline_debug_microseconds; -@@ -2798,7 +2803,8 @@ int main(int argc, const char *argv[]) - case EPERM: - case EACCES: - DEBUG(SSSDBG_CRIT_FAILURE, -- ("Insufficient permissions to read configuration file.\n")); -+ (CONF_FILE_PERM_ERROR_MSG, config_file)); -+ sss_log(SSS_LOG_ALERT, CONF_FILE_PERM_ERROR_MSG, config_file); - break; - default: - DEBUG(SSSDBG_CRIT_FAILURE, --- -1.8.5.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 new file mode 100644 index 0000000..8ef2540 --- /dev/null +++ b/SOURCES/0076-Revert-LDAP-Remove-unused-option-ldap_user_uuid.patch @@ -0,0 +1,176 @@ +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/0077-Revert-LDAP-Remove-unused-option-ldap_group_uuid.patch b/SOURCES/0077-Revert-LDAP-Remove-unused-option-ldap_group_uuid.patch new file mode 100644 index 0000000..ff902cb --- /dev/null +++ b/SOURCES/0077-Revert-LDAP-Remove-unused-option-ldap_group_uuid.patch @@ -0,0 +1,176 @@ +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/0077-Revert-NSS-add-support-for-subdomain_homedir.patch b/SOURCES/0077-Revert-NSS-add-support-for-subdomain_homedir.patch deleted file mode 100644 index 3f14be6..0000000 --- a/SOURCES/0077-Revert-NSS-add-support-for-subdomain_homedir.patch +++ /dev/null @@ -1,34 +0,0 @@ -From e7987aced2a2052d3cbff185f6e53708b552995b Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Tue, 21 Jan 2014 15:06:37 +0000 -Subject: [PATCH 77/80] Revert "NSS: add support for subdomain_homedir" - -This reverts commit 1dc7694a1cbc62b0d7e23cc1369579e5ce0071e8. - -Reviewed-by: Jakub Hrozek ---- - src/responder/nss/nsssrv_cmd.c | 8 -------- - 1 file changed, 8 deletions(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index 9ac3680de4d6ff12fe0c77a3963f84934e385276..c59078b545842561a7e5f62e9a99da6057b23660 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -201,14 +201,6 @@ static const char *get_homedir_override(TALLOC_CTX *mem_ctx, - name, uid, homedir, dom->name, NULL); - } - -- /* Override home directory location for subdomains. -- * This option can be overriden by override_homedir. -- */ -- if (IS_SUBDOMAIN(dom) && dom->subdomain_homedir) { -- return expand_homedir_template(mem_ctx, dom->subdomain_homedir, -- name, uid, homedir, dom->name, NULL); -- } -- - if (!homedir || *homedir == '\0') { - /* In the case of a NULL or empty homedir, check to see if - * we have a fallback homedir to use. --- -1.8.5.3 - diff --git a/SOURCES/0078-AD-support-for-subdomain_homedir.patch b/SOURCES/0078-AD-support-for-subdomain_homedir.patch deleted file mode 100644 index ac57314..0000000 --- a/SOURCES/0078-AD-support-for-subdomain_homedir.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 0b813ab764fd0b255e342765b79533e1869cd06e Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 22 Jan 2014 16:47:22 +0000 -Subject: [PATCH 78/80] AD: support for subdomain_homedir - -Homedir is defaultly set accordingly to subdomain_homedir for users from AD. - -Resolves: -https://fedorahosted.org/sssd/ticket/2169 - -Reviewed-by: Jakub Hrozek ---- - src/providers/ipa/ipa_subdomains_id.c | 190 ++++++++++++++++++++++++++++++++++ - 1 file changed, 190 insertions(+) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index c29a2a3047af105966b636422105abd15e8a3992..fb1ad896885866dd9c34f9db960e09d92763f86d 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -25,6 +25,7 @@ - #include - - #include "util/util.h" -+#include "util/sss_nss.h" - #include "util/strtonum.h" - #include "db/sysdb.h" - #include "providers/ldap/ldap_common.h" -@@ -350,6 +351,185 @@ ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx, - return (iter) ? iter->ad_id_ctx : NULL; - } - -+static errno_t -+get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, -+ const char *fqname, uint32_t uid, -+ const char **_homedir) -+{ -+ errno_t ret; -+ char *name; -+ const char *homedir; -+ TALLOC_CTX *tmp_ctx; -+ -+ tmp_ctx = talloc_new(mem_ctx); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sss_parse_name(tmp_ctx, dom->names, fqname, NULL, &name); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ homedir = expand_homedir_template(tmp_ctx, dom->subdomain_homedir, name, -+ uid, NULL, dom->name, dom->flat_name); -+ -+ if (homedir == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("expand_homedir_template failed\n")); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ if (_homedir == NULL) { -+ ret = EINVAL; -+ goto done; -+ } -+ *_homedir = talloc_steal(mem_ctx, homedir); -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t -+store_homedir_of_user(struct sss_domain_info *domain, -+ const char *fqname, const char *homedir) -+{ -+ errno_t ret; -+ errno_t sret; -+ TALLOC_CTX *tmp_ctx; -+ bool in_transaction = false; -+ struct sysdb_attrs *attrs; -+ struct sysdb_ctx *sysdb = domain->sysdb; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ attrs = sysdb_new_attrs(tmp_ctx); -+ if (attrs == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, homedir); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Error setting homedir: [%s]\n", -+ strerror(ret))); -+ goto done; -+ } -+ -+ ret = sysdb_transaction_start(sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); -+ goto done; -+ } -+ -+ in_transaction = true; -+ -+ ret = sysdb_set_user_attr(sysdb, domain, fqname, attrs, SYSDB_MOD_REP); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Failed to update homedir information!\n")); -+ goto done; -+ } -+ -+ ret = sysdb_transaction_commit(sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Cannot commit sysdb transaction [%d]: %s.\n", -+ ret, strerror(ret))); -+ goto done; -+ } -+ -+ in_transaction = false; -+ -+done: -+ if (in_transaction) { -+ sret = sysdb_transaction_cancel(sysdb); -+ if (sret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction.\n")); -+ } -+ } -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t -+apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, -+ int filter_type, const char *filter_value) -+{ -+ errno_t ret; -+ uint32_t uid; -+ const char *fqname; -+ const char *homedir = NULL; -+ struct ldb_result *res; -+ -+ if (filter_type == BE_FILTER_NAME) { -+ ret = sysdb_getpwnam(mem_ctx, dom->sysdb, dom, filter_value, &res); -+ } else if (filter_type == BE_FILTER_IDNUM) { -+ errno = 0; -+ uid = strtouint32(filter_value, NULL, 10); -+ if (errno != 0) { -+ ret = errno; -+ goto done; -+ } -+ ret = sysdb_getpwuid(mem_ctx, dom->sysdb, dom, uid, &res); -+ } else { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Unsupported filter type: [%d].\n", filter_type)); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Failed to make request to our cache: [%d]: [%s]\n", -+ ret, sss_strerror(ret))); -+ goto done; -+ } -+ -+ if (res->count == 0) { -+ ret = ENOENT; -+ goto done; -+ } -+ -+ /* -+ * Homedir is always overriden by subdomain_homedir even if it was -+ * explicitly set by user. -+ */ -+ fqname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL); -+ uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0); -+ if (uid == 0) { -+ DEBUG(SSSDBG_OP_FAILURE, ("UID for user [%s] is not known.\n", -+ filter_value)); -+ ret = ENOENT; -+ goto done; -+ } -+ -+ ret = get_subdomain_homedir_of_user(mem_ctx, dom, fqname, uid, &homedir); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("get_subdomain_homedir_of_user failed: [%d]: [%s]\n", -+ ret, sss_strerror(ret))); -+ goto done; -+ } -+ -+ ret = store_homedir_of_user(dom, fqname, homedir); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("store_homedir_of_user failed: [%d]: [%s]\n", -+ ret, sss_strerror(ret))); -+ goto done; -+ } -+ -+done: -+ return ret; -+} -+ - static void - ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) - { -@@ -367,6 +547,16 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) - return; - } - -+ ret = apply_subdomain_homedir(state, state->user_dom, -+ state->ar->filter_type, -+ state->ar->filter_value); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("apply_subdomain_homedir failed: [%d]: [%s].\n", -+ ret, sss_strerror(ret))); -+ goto fail; -+ } -+ - if ((state->ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS) { - tevent_req_done(req); - return; --- -1.8.5.3 - diff --git a/SOURCES/0078-Fix-uuid-defaults.patch b/SOURCES/0078-Fix-uuid-defaults.patch new file mode 100644 index 0000000..dd94248 --- /dev/null +++ b/SOURCES/0078-Fix-uuid-defaults.patch @@ -0,0 +1,102 @@ +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/0079-MAN-update-of-subdomain_homedir-usage.patch b/SOURCES/0079-MAN-update-of-subdomain_homedir-usage.patch deleted file mode 100644 index d14bd16..0000000 --- a/SOURCES/0079-MAN-update-of-subdomain_homedir-usage.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 75b31af85b662912d9deb0c6a8f14728f20e5d2d Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 29 Jan 2014 16:55:30 +0000 -Subject: [PATCH 79/80] MAN: update of subdomain_homedir usage - -Resolves: -https://fedorahosted.org/sssd/ticket/2169 - -Reviewed-by: Jakub Hrozek ---- - src/man/sssd.conf.5.xml | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 84770f6b28876278a0ddd6d8a8a8f9a8e0d3146f..5d861c73cfeb41920619d95e5c1e5c1975dcc45b 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -1771,7 +1771,8 @@ fallback_homedir = /home/%u - - - Use this homedir as default value for all subdomains -- within this domain. See override_homedir -+ within this domain in IPA AD trust. -+ See override_homedir - for info about possible values. In addition to those, the - expansion below can only be used with - subdomain_homedir. --- -1.8.5.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 new file mode 100644 index 0000000..fca592e --- /dev/null +++ b/SOURCES/0079-Revert-LDAP-Change-defaults-for-ldap_user-group_obje.patch @@ -0,0 +1,88 @@ +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-LDAP-Disable-token-groups-by-default.patch b/SOURCES/0080-LDAP-Disable-token-groups-by-default.patch new file mode 100644 index 0000000..dd0bbcb --- /dev/null +++ b/SOURCES/0080-LDAP-Disable-token-groups-by-default.patch @@ -0,0 +1,55 @@ +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/0080-utils-handling-NULL-params-in-sss_parse_name.patch b/SOURCES/0080-utils-handling-NULL-params-in-sss_parse_name.patch deleted file mode 100644 index b8ff0cd..0000000 --- a/SOURCES/0080-utils-handling-NULL-params-in-sss_parse_name.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 6ab5595ec7360bd4cc4c0494a1e0afedda701961 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Sun, 26 Jan 2014 12:39:43 +0000 -Subject: [PATCH 80/80] utils: handling NULL params in sss_parse_name - -Reviewed-by: Jakub Hrozek ---- - src/util/usertools.c | 50 +++++++++++++++++++++++++++----------------------- - src/util/util.h | 2 +- - 2 files changed, 28 insertions(+), 24 deletions(-) - -diff --git a/src/util/usertools.c b/src/util/usertools.c -index 9edae41e0f216f9f0d1660e473f3aa1bf7160b06..fab0a261e82b8c4d8071ced1dac99b8e3b987b00 100644 ---- a/src/util/usertools.c -+++ b/src/util/usertools.c -@@ -322,7 +322,7 @@ done: - - int sss_parse_name(TALLOC_CTX *memctx, - struct sss_names_ctx *snctx, -- const char *orig, char **domain, char **name) -+ const char *orig, char **_domain, char **_name) - { - pcre *re = snctx->re; - const char *result; -@@ -346,31 +346,35 @@ int sss_parse_name(TALLOC_CTX *memctx, - - strnum = ret; - -- result = NULL; -- ret = pcre_get_named_substring(re, orig, ovec, strnum, "name", &result); -- if (ret < 0 || !result) { -- DEBUG(2, ("Name not found!\n")); -- return EINVAL; -+ if (_name != NULL) { -+ result = NULL; -+ ret = pcre_get_named_substring(re, orig, ovec, strnum, "name", &result); -+ if (ret < 0 || !result) { -+ DEBUG(2, ("Name not found!\n")); -+ return EINVAL; -+ } -+ *_name = talloc_strdup(memctx, result); -+ pcre_free_substring(result); -+ if (!*_name) return ENOMEM; - } -- *name = talloc_strdup(memctx, result); -- pcre_free_substring(result); -- if (!*name) return ENOMEM; - -- -- result = NULL; -- ret = pcre_get_named_substring(re, orig, ovec, strnum, "domain", &result); -- if (ret < 0 || !result) { -- DEBUG(4, ("Domain not provided!\n")); -- *domain = NULL; -- } else { -- /* ignore "" string */ -- if (*result) { -- *domain = talloc_strdup(memctx, result); -- pcre_free_substring(result); -- if (!*domain) return ENOMEM; -+ if (_domain != NULL) { -+ result = NULL; -+ ret = pcre_get_named_substring(re, orig, ovec, strnum, "domain", -+ &result); -+ if (ret < 0 || !result) { -+ DEBUG(4, ("Domain not provided!\n")); -+ *_domain = NULL; - } else { -- pcre_free_substring(result); -- *domain = NULL; -+ /* ignore "" string */ -+ if (*result) { -+ *_domain = talloc_strdup(memctx, result); -+ pcre_free_substring(result); -+ if (!*_domain) return ENOMEM; -+ } else { -+ pcre_free_substring(result); -+ *_domain = NULL; -+ } - } - } - -diff --git a/src/util/util.h b/src/util/util.h -index 3334476ab83a137d957765fe2c9afba4ad0d014c..7b185bcb4287a4afc5bf67b40164cf69b9beeb19 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -349,7 +349,7 @@ int sss_names_init(TALLOC_CTX *mem_ctx, - - int sss_parse_name(TALLOC_CTX *memctx, - struct sss_names_ctx *snctx, -- const char *orig, char **domain, char **name); -+ const char *orig, char **_domain, char **_name); - - char * - sss_get_cased_name(TALLOC_CTX *mem_ctx, const char *orig_name, --- -1.8.5.3 - diff --git a/SOURCES/0081-LDAP-Detect-the-presence-of-POSIX-attributes.patch b/SOURCES/0081-LDAP-Detect-the-presence-of-POSIX-attributes.patch deleted file mode 100644 index 6c4671b..0000000 --- a/SOURCES/0081-LDAP-Detect-the-presence-of-POSIX-attributes.patch +++ /dev/null @@ -1,834 +0,0 @@ -From 3b0d429051648a1545de528ec760c4823088a1d9 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 16 Dec 2013 18:36:12 +0100 -Subject: [PATCH 81/84] LDAP: Detect the presence of POSIX attributes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When the schema is set to AD and ID mapping is not used, there is a one-time -check ran when searching for users to detect the presence of POSIX -attributes in LDAP. If this check fails, the search fails as if no entry -was found and returns a special error code. - -The sdap_server_opts structure is filled every time a client connects to -a server so the posix check boolean is reset to false again on connecting -to the server. - -It might be better to move the check to where the rootDSE is retrieved, -but the check depends on several features that are not known to the code -that retrieves the rootDSE (or the connection code for example) such as what -the attribute mappings are or the authentication method that should be used. - -Reviewed-by: Sumit Bose -Reviewed-by: Pavel Březina -(cherry picked from commit e81deec535d11912b87954c81a1edd768c1386c9) ---- - src/providers/ad/ad_id.c | 50 ++++++++- - src/providers/ad/ad_id.h | 1 + - src/providers/ipa/ipa_subdomains_id.c | 2 +- - src/providers/ldap/ldap_id.c | 158 +++++++++++++++++++++++++-- - src/providers/ldap/sdap.h | 1 + - src/providers/ldap/sdap_async.c | 200 ++++++++++++++++++++++++++++++++++ - src/providers/ldap/sdap_async.h | 9 ++ - src/providers/ldap/sdap_async_enum.c | 96 +++++++++++++++- - src/util/util_errors.c | 1 + - src/util/util_errors.h | 1 + - 10 files changed, 504 insertions(+), 15 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index e3302c15774ab1c24b16cefc274313e447b31e5c..bfae86284355b6c13547aac55b7273133bde851d 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -27,6 +27,28 @@ - #include "providers/ldap/sdap_async_enum.h" - #include "providers/ldap/sdap_idmap.h" - -+static void -+disable_gc(struct ad_options *ad_options) -+{ -+ errno_t ret; -+ -+ if (dp_opt_get_bool(ad_options->basic, AD_ENABLE_GC) == false) { -+ return; -+ } -+ -+ DEBUG(SSSDBG_IMPORTANT_INFO, ("POSIX attributes were requested " -+ "but are not present on the server side. Global Catalog " -+ "lookups will be disabled\n")); -+ -+ ret = dp_opt_set_bool(ad_options->basic, -+ AD_ENABLE_GC, false); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("Could not turn off GC support\n")); -+ /* Not fatal */ -+ } -+} -+ - struct ad_handle_acct_info_state { - struct be_req *breq; - struct be_acct_req *ar; -@@ -34,6 +56,7 @@ struct ad_handle_acct_info_state { - struct sdap_id_conn_ctx **conn; - struct sdap_domain *sdom; - size_t cindex; -+ struct ad_options *ad_options; - - int dp_error; - const char *err; -@@ -47,6 +70,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, - struct be_req *breq, - struct be_acct_req *ar, - struct sdap_id_ctx *ctx, -+ struct ad_options *ad_options, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx **conn) - { -@@ -64,6 +88,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, - state->ctx = ctx; - state->sdom = sdom; - state->conn = conn; -+ state->ad_options = ad_options; - state->cindex = 0; - - ret = ad_handle_acct_info_step(req); -@@ -137,12 +162,14 @@ ad_handle_acct_info_done(struct tevent_req *subreq) - if (sdap_err == EOK) { - tevent_req_done(req); - return; -+ } else if (sdap_err == ERR_NO_POSIX) { -+ disable_gc(state->ad_options); - } else if (sdap_err != ENOENT) { - tevent_req_error(req, EIO); - return; - } - -- /* Ret is only ENOENT now. Try the next connection */ -+ /* Ret is only ENOENT or ERR_NO_POSIX now. Try the next connection */ - state->cindex++; - ret = ad_handle_acct_info_step(req); - if (ret != EAGAIN) { -@@ -356,7 +383,7 @@ ad_account_info_handler(struct be_req *be_req) - } - - req = ad_handle_acct_info_send(be_req, be_req, ar, sdap_id_ctx, -- sdom, clist); -+ ad_ctx->ad_options, sdom, clist); - if (req == NULL) { - ret = ENOMEM; - goto fail; -@@ -611,9 +638,24 @@ ad_enumeration_done(struct tevent_req *subreq) - - ret = sdap_dom_enum_ex_recv(subreq); - talloc_zfree(subreq); -- if (ret != EOK) { -+ if (ret == ERR_NO_POSIX) { -+ /* Retry enumerating the same domain again, this time w/o -+ * connecting to GC -+ */ -+ disable_gc(state->id_ctx->ad_options); -+ ret = ad_enum_sdom(req, state->sditer, state->id_ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not retry domain %s\n", state->sditer->dom->name)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Execution will resume in ad_enumeration_done */ -+ return; -+ } else if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, -- ("Could not enumerate domain %s\n", state->sdom->dom->name)); -+ ("Could not enumerate domain %s\n", state->sditer->dom->name)); - tevent_req_error(req, ret); - return; - } -diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h -index 74b85645c2d6458617a4064fe3fb3f99696c3741..9eb0ac3754be2fd687ed2257b91854f5fceb82a2 100644 ---- a/src/providers/ad/ad_id.h -+++ b/src/providers/ad/ad_id.h -@@ -31,6 +31,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, - struct be_req *breq, - struct be_acct_req *ar, - struct sdap_id_ctx *ctx, -+ struct ad_options *ad_options, - struct sdap_domain *sdom, - struct sdap_id_conn_ctx **conn); - errno_t -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index fb1ad896885866dd9c34f9db960e09d92763f86d..b61c6a5f4d7605f0cdfa182bbc933d35c4613a79 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -323,7 +323,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, - } - - subreq = ad_handle_acct_info_send(req, be_req, ar, sdap_id_ctx, -- sdom, clist); -+ ad_id_ctx->ad_options, sdom, clist); - if (subreq == NULL) { - ret = ENOMEM; - goto fail; -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index e36c1f697c18e865a47d991dad103fc440456118..b948ba9f358af994bdbbb99a468f7dbe66e65c1d 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -50,6 +50,7 @@ struct users_get_state { - - char *filter; - const char **attrs; -+ bool use_id_mapping; - - int dp_error; - int sdap_ret; -@@ -58,6 +59,8 @@ struct users_get_state { - - static int users_get_retry(struct tevent_req *req); - static void users_get_connect_done(struct tevent_req *subreq); -+static void users_get_posix_check_done(struct tevent_req *subreq); -+static void users_get_search(struct tevent_req *req); - static void users_get_done(struct tevent_req *subreq); - - struct tevent_req *users_get_send(TALLOC_CTX *memctx, -@@ -79,7 +82,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - uid_t uid; - enum idmap_error_code err; - char *sid; -- bool use_id_mapping; - - req = tevent_req_create(memctx, &state, struct users_get_state); - if (!req) return NULL; -@@ -103,7 +105,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - state->name = name; - state->filter_type = filter_type; - -- use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( -+ state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->name, - sdom->dom->domain_id); -@@ -116,7 +118,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - } - break; - case BE_FILTER_IDNUM: -- if (use_id_mapping) { -+ if (state->use_id_mapping) { - /* If we're ID-mapping, we need to use the objectSID - * in the search filter. - */ -@@ -184,7 +186,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - goto fail; - } - -- if (use_id_mapping || filter_type == BE_FILTER_SECID) { -+ if (state->use_id_mapping || filter_type == BE_FILTER_SECID) { - /* When mapping IDs or looking for SIDs, we don't want to limit - * ourselves to users with a UID value. But there must be a SID to map - * from. -@@ -269,6 +271,75 @@ static void users_get_connect_done(struct tevent_req *subreq) - return; - } - -+ /* If POSIX attributes have been requested with an AD server and we -+ * have no idea about POSIX attributes support, run a one-time check -+ */ -+ if (state->use_id_mapping == false && -+ state->ctx->opts->schema_type == SDAP_SCHEMA_AD && -+ state->ctx->srv_opts && -+ state->ctx->srv_opts->posix_checked == false) { -+ subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts, -+ sdap_id_op_handle(state->op), -+ state->sdom->user_search_bases, -+ dp_opt_get_int(state->ctx->opts->basic, -+ SDAP_SEARCH_TIMEOUT)); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, users_get_posix_check_done, req); -+ return; -+ } -+ -+ users_get_search(req); -+} -+ -+static void users_get_posix_check_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ bool has_posix; -+ int dp_error; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct users_get_state *state = tevent_req_data(req, -+ struct users_get_state); -+ -+ ret = sdap_posix_check_recv(subreq, &has_posix); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ /* We can only finish the id_op on error as the connection -+ * is re-used by the user search -+ */ -+ ret = sdap_id_op_done(state->op, ret, &dp_error); -+ if (dp_error == DP_ERR_OK && ret != EOK) { -+ /* retry */ -+ ret = users_get_retry(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } -+ return; -+ } -+ } -+ -+ state->ctx->srv_opts->posix_checked = true; -+ -+ /* If the check ran to completion, we know for certain about the attributes -+ */ -+ if (has_posix == false) { -+ state->sdap_ret = ERR_NO_POSIX; -+ tevent_req_done(req); -+ return; -+ } -+ -+ users_get_search(req); -+} -+ -+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; -+ - subreq = sdap_get_users_send(state, state->ev, - state->domain, state->sysdb, - state->ctx->opts, -@@ -434,6 +505,7 @@ struct groups_get_state { - - char *filter; - const char **attrs; -+ bool use_id_mapping; - - int dp_error; - int sdap_ret; -@@ -442,6 +514,8 @@ struct groups_get_state { - - static int groups_get_retry(struct tevent_req *req); - static void groups_get_connect_done(struct tevent_req *subreq); -+static void groups_get_posix_check_done(struct tevent_req *subreq); -+static void groups_get_search(struct tevent_req *req); - static void groups_get_done(struct tevent_req *subreq); - - struct tevent_req *groups_get_send(TALLOC_CTX *memctx, -@@ -463,7 +537,6 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - gid_t gid; - enum idmap_error_code err; - char *sid; -- bool use_id_mapping; - const char *member_filter[2]; - - req = tevent_req_create(memctx, &state, struct groups_get_state); -@@ -488,7 +561,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - state->name = name; - state->filter_type = filter_type; - -- use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( -+ state->use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( - ctx->opts->idmap_ctx, - sdom->dom->name, - sdom->dom->domain_id); -@@ -503,7 +576,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - } - break; - case BE_FILTER_IDNUM: -- if (use_id_mapping) { -+ if (state->use_id_mapping) { - /* If we're ID-mapping, we need to use the objectSID - * in the search filter. - */ -@@ -571,7 +644,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - goto fail; - } - -- if (use_id_mapping || filter_type == BE_FILTER_SECID) { -+ if (state->use_id_mapping || filter_type == BE_FILTER_SECID) { - /* When mapping IDs or looking for SIDs, we don't want to limit - * ourselves to groups with a GID value - */ -@@ -660,6 +733,75 @@ static void groups_get_connect_done(struct tevent_req *subreq) - return; - } - -+ /* If POSIX attributes have been requested with an AD server and we -+ * have no idea about POSIX attributes support, run a one-time check -+ */ -+ if (state->use_id_mapping == false && -+ state->ctx->opts->schema_type == SDAP_SCHEMA_AD && -+ state->ctx->srv_opts && -+ state->ctx->srv_opts->posix_checked == false) { -+ subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts, -+ sdap_id_op_handle(state->op), -+ state->sdom->user_search_bases, -+ dp_opt_get_int(state->ctx->opts->basic, -+ SDAP_SEARCH_TIMEOUT)); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, groups_get_posix_check_done, req); -+ return; -+ } -+ -+ groups_get_search(req); -+} -+ -+static void groups_get_posix_check_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ bool has_posix; -+ int dp_error; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct groups_get_state *state = tevent_req_data(req, -+ struct groups_get_state); -+ -+ ret = sdap_posix_check_recv(subreq, &has_posix); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ /* We can only finish the id_op on error as the connection -+ * is re-used by the group search -+ */ -+ ret = sdap_id_op_done(state->op, ret, &dp_error); -+ if (dp_error == DP_ERR_OK && ret != EOK) { -+ /* retry */ -+ ret = groups_get_retry(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } -+ return; -+ } -+ } -+ -+ state->ctx->srv_opts->posix_checked = true; -+ -+ /* If the check ran to completion, we know for certain about the attributes -+ */ -+ if (has_posix == false) { -+ state->sdap_ret = ERR_NO_POSIX; -+ tevent_req_done(req); -+ return; -+ } -+ -+ groups_get_search(req); -+} -+ -+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; -+ - subreq = sdap_get_groups_send(state, state->ev, - state->sdom, - state->ctx->opts, -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index d408be0a65cdd840d8379b7af4c0ab1e67ed3f5c..f3f13e9c72b368af0c14e2d830a89a41e8cf77e4 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -446,6 +446,7 @@ struct sdap_server_opts { - char *max_group_value; - char *max_service_value; - char *max_sudo_value; -+ bool posix_checked; - }; - - struct sdap_id_ctx; -diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c -index 367007bde0011ed4de283b2a50b22538830a5275..1022a093f06ec7e9a50b13160fc9a4660a255e92 100644 ---- a/src/providers/ldap/sdap_async.c -+++ b/src/providers/ldap/sdap_async.c -@@ -21,6 +21,7 @@ - - #include - #include "util/util.h" -+#include "util/strtonum.h" - #include "providers/ldap/sdap_async_private.h" - - #define REALM_SEPARATOR '@' -@@ -2083,6 +2084,205 @@ int sdap_asq_search_recv(struct tevent_req *req, - return EOK; - } - -+/* ==Posix attribute presence test================================= */ -+static errno_t sdap_posix_check_next(struct tevent_req *req); -+static void sdap_posix_check_done(struct tevent_req *subreq); -+static errno_t sdap_posix_check_parse(struct sdap_handle *sh, -+ struct sdap_msg *msg, -+ void *pvt); -+ -+struct sdap_posix_check_state { -+ struct tevent_context *ev; -+ struct sdap_options *opts; -+ struct sdap_handle *sh; -+ struct sdap_search_base **search_bases; -+ int timeout; -+ -+ const char **attrs; -+ const char *filter; -+ size_t base_iter; -+ -+ bool has_posix; -+}; -+ -+struct tevent_req * -+sdap_posix_check_send(TALLOC_CTX *memctx, struct tevent_context *ev, -+ struct sdap_options *opts, struct sdap_handle *sh, -+ struct sdap_search_base **search_bases, -+ int timeout) -+{ -+ struct tevent_req *req = NULL; -+ struct sdap_posix_check_state *state; -+ errno_t ret; -+ -+ req = tevent_req_create(memctx, &state, struct sdap_posix_check_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ev = ev; -+ state->sh = sh; -+ state->opts = opts; -+ state->search_bases = search_bases; -+ state->timeout = timeout; -+ -+ state->attrs = talloc_array(state, const char *, 4); -+ if (state->attrs == NULL) { -+ ret = ENOMEM; -+ goto fail; -+ } -+ state->attrs[0] = "objectclass"; -+ state->attrs[1] = opts->user_map[SDAP_AT_USER_UID].name; -+ state->attrs[2] = opts->group_map[SDAP_AT_GROUP_GID].name; -+ state->attrs[3] = NULL; -+ -+ state->filter = talloc_asprintf(state, "(|(%s=*)(%s=*))", -+ opts->user_map[SDAP_AT_USER_UID].name, -+ opts->group_map[SDAP_AT_GROUP_GID].name); -+ if (state->filter == NULL) { -+ ret = ENOMEM; -+ goto fail; -+ } -+ -+ ret = sdap_posix_check_next(req); -+ if (ret != EOK) { -+ goto fail; -+ } -+ -+ return req; -+ -+fail: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t sdap_posix_check_next(struct tevent_req *req) -+{ -+ struct tevent_req *subreq = NULL; -+ struct sdap_posix_check_state *state = -+ tevent_req_data(req, struct sdap_posix_check_state); -+ -+ DEBUG(SSSDBG_TRACE_FUNC, -+ ("Searching for POSIX attributes with base [%s]\n", -+ state->search_bases[state->base_iter]->basedn)); -+ -+ subreq = sdap_get_generic_ext_send(state, state->ev, state->opts, -+ state->sh, -+ state->search_bases[state->base_iter]->basedn, -+ LDAP_SCOPE_SUBTREE, state->filter, -+ state->attrs, false, -+ NULL, NULL, 1, state->timeout, -+ false, sdap_posix_check_parse, -+ state); -+ if (subreq == NULL) { -+ return ENOMEM; -+ } -+ tevent_req_set_callback(subreq, sdap_posix_check_done, req); -+ -+ return EOK; -+} -+ -+static errno_t sdap_posix_check_parse(struct sdap_handle *sh, -+ struct sdap_msg *msg, -+ void *pvt) -+{ -+ struct berval **vals = NULL; -+ struct sdap_posix_check_state *state = -+ talloc_get_type(pvt, struct sdap_posix_check_state); -+ char *dn; -+ char *endptr; -+ -+ dn = ldap_get_dn(sh->ldap, msg->msg); -+ if (dn == NULL) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("Search did not find any entry with POSIX attributes\n")); -+ goto done; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, ("Found [%s] with POSIX attributes\n", dn)); -+ ldap_memfree(dn); -+ -+ vals = ldap_get_values_len(sh->ldap, msg->msg, -+ state->opts->user_map[SDAP_AT_USER_UID].name); -+ if (vals == NULL) { -+ vals = ldap_get_values_len(sh->ldap, msg->msg, -+ state->opts->group_map[SDAP_AT_GROUP_GID].name); -+ if (vals == NULL) { -+ DEBUG(SSSDBG_TRACE_LIBS, ("Entry does not have POSIX attrs?\n")); -+ goto done; -+ } -+ } -+ -+ if (vals[0] == NULL) { -+ DEBUG(SSSDBG_TRACE_LIBS, ("No value for POSIX attr\n")); -+ goto done; -+ } -+ -+ errno = 0; -+ strtouint32(vals[0]->bv_val, &endptr, 10); -+ if (errno || *endptr || (vals[0]->bv_val == endptr)) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("POSIX attribute is not a number: %s\n", vals[0]->bv_val)); -+ goto done; -+ } -+ -+ state->has_posix = true; -+done: -+ ldap_value_free_len(vals); -+ return EOK; -+} -+ -+static void sdap_posix_check_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_posix_check_state *state = -+ tevent_req_data(req, struct sdap_posix_check_state); -+ errno_t ret; -+ -+ ret = sdap_get_generic_ext_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("sdap_get_generic_ext_recv failed [%d]: %s\n", -+ ret, strerror(ret))); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Positive hit is definitve, no need to search other bases */ -+ if (state->has_posix == true) { -+ DEBUG(SSSDBG_FUNC_DATA, ("Server has POSIX attributes\n")); -+ tevent_req_done(req); -+ return; -+ } -+ -+ state->base_iter++; -+ if (state->search_bases[state->base_iter]) { -+ /* There are more search bases to try */ -+ ret = sdap_posix_check_next(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } -+ return; -+ } -+ -+ /* All bases done! */ -+ DEBUG(SSSDBG_TRACE_LIBS, ("Cycled through all bases\n")); -+ tevent_req_done(req); -+} -+ -+int sdap_posix_check_recv(struct tevent_req *req, -+ bool *_has_posix) -+{ -+ struct sdap_posix_check_state *state = tevent_req_data(req, -+ struct sdap_posix_check_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ *_has_posix = state->has_posix; -+ return EOK; -+} -+ - /* ==Generic Deref Search============================================ */ - enum sdap_deref_type { - SDAP_DEREF_OPENLDAP, -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index 33e8708ab7e80ab4280df300fdc300d4ecd18305..593404af3c460f8d956b0832b8f7e398b331729b 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -210,6 +210,15 @@ int sdap_deref_search_recv(struct tevent_req *req, - size_t *reply_count, - struct sdap_deref_attrs ***reply); - -+struct tevent_req * -+sdap_posix_check_send(TALLOC_CTX *memctx, struct tevent_context *ev, -+ struct sdap_options *opts, struct sdap_handle *sh, -+ struct sdap_search_base **search_bases, -+ int timeout); -+ -+int sdap_posix_check_recv(struct tevent_req *req, -+ bool *_has_posix); -+ - errno_t - sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs, - const char *attr_name, -diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c -index cbc56be20526e6c2323f9fd1b49038dd4bf13fe5..0c20afa9d7a1b0198bb71cffdafcb14763c1dafb 100644 ---- a/src/providers/ldap/sdap_async_enum.c -+++ b/src/providers/ldap/sdap_async_enum.c -@@ -68,6 +68,8 @@ static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req, - tevent_req_fn tcb); - static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq); - static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq); -+static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq); -+static errno_t sdap_dom_enum_search_users(struct tevent_req *req); - static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq); - static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq); - static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq); -@@ -178,19 +180,109 @@ static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq) - struct tevent_req); - struct sdap_dom_enum_ex_state *state = tevent_req_data(req, - struct sdap_dom_enum_ex_state); -+ bool use_id_mapping; -+ errno_t ret; - - if (sdap_dom_enum_ex_connected(subreq) == false) { - return; - } - -+ use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( -+ state->ctx->opts->idmap_ctx, -+ state->sdom->dom->name, -+ state->sdom->dom->domain_id); -+ -+ /* If POSIX attributes have been requested with an AD server and we -+ * have no idea about POSIX attributes support, run a one-time check -+ */ -+ if (use_id_mapping == false && -+ state->ctx->opts->schema_type == SDAP_SCHEMA_AD && -+ state->ctx->srv_opts && -+ state->ctx->srv_opts->posix_checked == false) { -+ subreq = sdap_posix_check_send(state, state->ev, state->ctx->opts, -+ sdap_id_op_handle(state->user_op), -+ state->sdom->user_search_bases, -+ dp_opt_get_int(state->ctx->opts->basic, -+ SDAP_SEARCH_TIMEOUT)); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, -+ sdap_dom_enum_ex_posix_check_done, req); -+ return; -+ } -+ -+ -+ ret = sdap_dom_enum_search_users(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ /* Execution resumes in sdap_dom_enum_ex_users_done */ -+} -+ -+static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ bool has_posix; -+ int dp_error; -+ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ -+ ret = sdap_posix_check_recv(subreq, &has_posix); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ /* We can only finish the id_op on error as the connection -+ * is re-used by the user search -+ */ -+ ret = sdap_id_op_done(state->user_op, ret, &dp_error); -+ if (dp_error == DP_ERR_OK && ret != EOK) { -+ /* retry */ -+ ret = sdap_dom_enum_ex_retry(req, state->user_op, -+ sdap_dom_enum_ex_get_users); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } -+ return; -+ } -+ } -+ -+ state->ctx->srv_opts->posix_checked = true; -+ -+ /* If the check ran to completion, we know for certain about the attributes -+ */ -+ if (has_posix == false) { -+ tevent_req_error(req, ERR_NO_POSIX); -+ return; -+ } -+ -+ -+ ret = sdap_dom_enum_search_users(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ /* Execution resumes in sdap_dom_enum_ex_users_done */ -+} -+ -+static errno_t sdap_dom_enum_search_users(struct tevent_req *req) -+{ -+ struct sdap_dom_enum_ex_state *state = tevent_req_data(req, -+ struct sdap_dom_enum_ex_state); -+ struct tevent_req *subreq; -+ - subreq = enum_users_send(state, state->ev, - state->ctx, state->sdom, - state->user_op, state->purge); - if (subreq == NULL) { -- tevent_req_error(req, ENOMEM); -- return; -+ return ENOMEM; - } - tevent_req_set_callback(subreq, sdap_dom_enum_ex_users_done, req); -+ return EOK; - } - - static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq) -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 633257e8da0ef039e555a07ad8b51125114ca01c..c9b507557da07555c719bb0dd18145e6799a53eb 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -52,6 +52,7 @@ struct err_string error_to_str[] = { - { "Domain not found" }, /* ERR_DOMAIN_NOT_FOUND */ - { "Missing configuration file" }, /* ERR_MISSING_CONF */ - { "Malformed search filter" }, /* ERR_INVALID_FILTER, */ -+ { "No POSIX attributes detected" }, /* ERR_NO_POSIX */ - }; - - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 1332085031dbe6935cbdc94543fa14b09fe81028..3dd94af1f304d65e22515c859c6f69a021fa7e92 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -74,6 +74,7 @@ enum sssd_errors { - ERR_DOMAIN_NOT_FOUND, - ERR_MISSING_CONF, - ERR_INVALID_FILTER, -+ ERR_NO_POSIX, - ERR_LAST /* ALWAYS LAST */ - }; - --- -1.8.5.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 new file mode 100644 index 0000000..bd7330c --- /dev/null +++ b/SOURCES/0081-proxy-Do-not-try-to-store-same-alias-twice.patch @@ -0,0 +1,161 @@ +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-AD-Only-download-domains-that-are-set-to-enumerate.patch b/SOURCES/0082-AD-Only-download-domains-that-are-set-to-enumerate.patch deleted file mode 100644 index b9b8cc0..0000000 --- a/SOURCES/0082-AD-Only-download-domains-that-are-set-to-enumerate.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 94f1e5966733e1b327a9eba37781379c5d90f8a3 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 5 Feb 2014 16:39:47 +0100 -Subject: [PATCH 82/84] AD: Only download domains that are set to enumerate -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit 957c55df7a7086166fb3c14cead6a0dab8f574c1) ---- - src/providers/ad/ad_id.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index bfae86284355b6c13547aac55b7273133bde851d..2d3c11bb838f1418c006f9d79d8552cec1443e66 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -660,7 +660,11 @@ ad_enumeration_done(struct tevent_req *subreq) - return; - } - -- state->sditer = state->sditer->next; -+ do { -+ state->sditer = state->sditer->next; -+ } while (state->sditer && -+ state->sditer->dom->enumerate == false); -+ - if (state->sditer != NULL) { - subdom_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx); - if (subdom_id_ctx == NULL) { --- -1.8.5.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 new file mode 100644 index 0000000..cb209dc --- /dev/null +++ b/SOURCES/0082-PROXY-Preserve-service-name-in-proxy-provider.patch @@ -0,0 +1,62 @@ +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/0083-AD-Remove-dead-code.patch b/SOURCES/0083-AD-Remove-dead-code.patch deleted file mode 100644 index 178d308..0000000 --- a/SOURCES/0083-AD-Remove-dead-code.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 7f9da1ed660e45e276778187260ddbbf411c761e Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 5 Feb 2014 16:40:41 +0100 -Subject: [PATCH 83/84] AD: Remove dead code -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit d3436880c0ec1a7776698c739d4a3edc9a6ac57c) ---- - src/providers/ad/ad_id.c | 8 -------- - 1 file changed, 8 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 2d3c11bb838f1418c006f9d79d8552cec1443e66..87af656b364344a8ef27a444e5dfcf8848939110 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -634,7 +634,6 @@ ad_enumeration_done(struct tevent_req *subreq) - struct tevent_req); - struct ad_enumeration_state *state = tevent_req_data(req, - struct ad_enumeration_state); -- struct ad_id_ctx *subdom_id_ctx; - - ret = sdap_dom_enum_ex_recv(subreq); - talloc_zfree(subreq); -@@ -666,13 +665,6 @@ ad_enumeration_done(struct tevent_req *subreq) - state->sditer->dom->enumerate == false); - - if (state->sditer != NULL) { -- subdom_id_ctx = talloc_get_type(state->sdom->pvt, struct ad_id_ctx); -- if (subdom_id_ctx == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot retrieve subdomain ad_id_ctx!\n")); -- tevent_req_error(req, EFAULT); -- return; -- } -- - ret = ad_enum_sdom(req, state->sditer, state->sditer->pvt); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Could not enumerate domain %s\n", --- -1.8.5.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 new file mode 100644 index 0000000..26f66d8 --- /dev/null +++ b/SOURCES/0083-BUILD-Install-krb5_child-as-suid-if-running-under-no.patch @@ -0,0 +1,51 @@ +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/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 new file mode 100644 index 0000000..9168a2d --- /dev/null +++ b/SOURCES/0084-KRB5-Drop-privileges-in-the-child-not-the-back-end.patch @@ -0,0 +1,142 @@ +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/0084-LDAP-Handle-errors-from-sdap_id_op-properly-in-enum-.patch b/SOURCES/0084-LDAP-Handle-errors-from-sdap_id_op-properly-in-enum-.patch deleted file mode 100644 index 88049e5..0000000 --- a/SOURCES/0084-LDAP-Handle-errors-from-sdap_id_op-properly-in-enum-.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 97616c8e1ab41c72c509a31626fafcfb07241a46 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 11 Feb 2014 12:23:51 +0100 -Subject: [PATCH 84/84] LDAP: Handle errors from sdap_id_op properly in enum - code -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit 93dabb2fe0a798f22bb802b9c6521ab9e6a4ac36) ---- - src/providers/ldap/sdap_async_enum.c | 42 +++++++++++++++++++++++++++++++++++- - 1 file changed, 41 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c -index 0c20afa9d7a1b0198bb71cffdafcb14763c1dafb..0431d03c38098080847035d522ab5f1f494b8bfe 100644 ---- a/src/providers/ldap/sdap_async_enum.c -+++ b/src/providers/ldap/sdap_async_enum.c -@@ -235,7 +235,7 @@ static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq) - - ret = sdap_posix_check_recv(subreq, &has_posix); - talloc_zfree(subreq); -- if (ret != EOK) { -+ if (ret != EOK && ret != ERR_NO_POSIX) { - /* We can only finish the id_op on error as the connection - * is re-used by the user search - */ -@@ -248,6 +248,16 @@ static void sdap_dom_enum_ex_posix_check_done(struct tevent_req *subreq) - tevent_req_error(req, ret); - } - return; -+ } else if (dp_error == DP_ERR_OFFLINE) { -+ DEBUG(SSSDBG_TRACE_FUNC, ("Backend is offline, retrying later\n")); -+ tevent_req_done(req); -+ return; -+ } else { -+ /* Non-recoverable error */ -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("POSIX check failed: %d: %s\n", ret, sss_strerror(ret))); -+ tevent_req_error(req, ret); -+ return; - } - } - -@@ -306,6 +316,16 @@ static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq) - return; - } - return; -+ } else if (dp_error == DP_ERR_OFFLINE) { -+ DEBUG(SSSDBG_TRACE_FUNC, ("Backend is offline, retrying later\n")); -+ tevent_req_done(req); -+ return; -+ } else if (ret != EOK && ret != ENOENT) { -+ /* Non-recoverable error */ -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("User enumeration failed: %d: %s\n", ret, sss_strerror(ret))); -+ tevent_req_error(req, ret); -+ return; - } - - state->group_op = sdap_id_op_create(state, state->group_conn->conn_cache); -@@ -367,6 +387,16 @@ static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq) - return; - } - return; -+ } else if (dp_error == DP_ERR_OFFLINE) { -+ DEBUG(SSSDBG_TRACE_FUNC, ("Backend is offline, retrying later\n")); -+ tevent_req_done(req); -+ return; -+ } else if (ret != EOK && ret != ENOENT) { -+ /* Non-recoverable error */ -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Group enumeration failed: %d: %s\n", ret, sss_strerror(ret))); -+ tevent_req_error(req, ret); -+ return; - } - - -@@ -426,6 +456,16 @@ static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq) - return; - } - return; -+ } else if (dp_error == DP_ERR_OFFLINE) { -+ DEBUG(SSSDBG_TRACE_FUNC, ("Backend is offline, retrying later\n")); -+ tevent_req_done(req); -+ return; -+ } else if (ret != EOK && ret != ENOENT) { -+ /* Non-recoverable error */ -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Service enumeration failed: %d: %s\n", ret, sss_strerror(ret))); -+ tevent_req_error(req, ret); -+ return; - } - - /* Ok, we've completed an enumeration. Save this to the --- -1.8.5.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 new file mode 100644 index 0000000..73c0db0 --- /dev/null +++ b/SOURCES/0085-KRB5-Move-ccache-related-functions-to-krb5_ccache.c.patch @@ -0,0 +1,1794 @@ +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/0085-SSS_CACHE-Reset-the-initgroups-attribute-when-resett.patch b/SOURCES/0085-SSS_CACHE-Reset-the-initgroups-attribute-when-resett.patch deleted file mode 100644 index 684c1e6..0000000 --- a/SOURCES/0085-SSS_CACHE-Reset-the-initgroups-attribute-when-resett.patch +++ /dev/null @@ -1,35 +0,0 @@ -From a5910c05a1013c9a050f6df3d4c6884e894bf2d9 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 11 Feb 2014 22:51:48 +0100 -Subject: [PATCH 85/88] SSS_CACHE: Reset the initgroups attribute when - resetting users -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -(cherry picked from commit 30ee051025753b63ceb19d3b83c44019a19554a1) -Reviewed-by: Lukáš Slebodník ---- - src/tools/sss_cache.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/tools/sss_cache.c b/src/tools/sss_cache.c -index 56dc47afdcb92b71dc1ef71d7f26fdf276a1c45f..59b36db3e25333f4ca5da241b607edda226b929f 100644 ---- a/src/tools/sss_cache.c -+++ b/src/tools/sss_cache.c -@@ -424,6 +424,12 @@ static errno_t invalidate_entry(TALLOC_CTX *ctx, struct sysdb_ctx *sysdb, - if (ret == EOK) { - switch (entry_type) { - case TYPE_USER: -+ /* For users, we also need to reset the initgroups -+ * cache expiry */ -+ ret = sysdb_attrs_add_time_t(sys_attrs, -+ SYSDB_INITGR_EXPIRE, 1); -+ if (ret != EOK) return ret; -+ - ret = sysdb_set_user_attr(sysdb, domain, name, sys_attrs, - SYSDB_MOD_REP); - break; --- -1.8.5.3 - diff --git a/SOURCES/0086-IPA-Default-to-krb5_use_fast-try.patch b/SOURCES/0086-IPA-Default-to-krb5_use_fast-try.patch deleted file mode 100644 index 724e723..0000000 --- a/SOURCES/0086-IPA-Default-to-krb5_use_fast-try.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 529c7ade2f7f633fdb80e2f5b2055afd5a017d2f Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 11 Feb 2014 15:36:04 +0100 -Subject: [PATCH 86/88] IPA: Default to krb5_use_fast=try -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -Reviewed-by: Nathaniel McCallum -Reviewed-by: Alexander Bokovoy ---- - src/providers/ipa/ipa_common.c | 27 +++++++++++++++++++++++++++ - src/providers/ipa/ipa_opts.h | 2 +- - 2 files changed, 28 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c -index 671374098afa1f2e00fc9cf1788ba4383b600a1b..e0abd169302406a555728589185b67e0fbbcfe94 100644 ---- a/src/providers/ipa/ipa_common.c -+++ b/src/providers/ipa/ipa_common.c -@@ -664,6 +664,33 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts, - dp_opt_get_string(ipa_opts->auth, KRB5_REALM))); - } - -+ /* If krb5_fast_principal was not set explicitly, default to -+ * host/$client_hostname -+ */ -+ value = dp_opt_get_string(ipa_opts->auth, KRB5_FAST_PRINCIPAL); -+ if (value == NULL) { -+ value = talloc_asprintf(ipa_opts->auth, "host/%s", -+ dp_opt_get_string(ipa_opts->basic, -+ IPA_HOSTNAME)); -+ if (value == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot set %s!\n", -+ ipa_opts->auth[KRB5_FAST_PRINCIPAL].opt_name)); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = dp_opt_set_string(ipa_opts->auth, KRB5_FAST_PRINCIPAL, -+ value); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot set %s!\n", -+ ipa_opts->auth[KRB5_FAST_PRINCIPAL].opt_name)); -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_CONF_SETTINGS, ("Option %s set to %s\n", -+ ipa_opts->auth[KRB5_FAST_PRINCIPAL].opt_name, value)); -+ } -+ - /* Set flag that controls whether we want to write the - * kdcinfo files at all - */ -diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h -index 27dc3e2f977383836c18cb824abceb03c9e9056c..c46d421ad0bfb9272cbdadbfeea5ebcf65a7deb1 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -274,7 +274,7 @@ struct dp_option ipa_def_krb5_opts[] = { - { "krb5_renewable_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "krb5_lifetime", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "krb5_renew_interval", DP_OPT_STRING, NULL_STRING, NULL_STRING }, -- { "krb5_use_fast", DP_OPT_STRING, NULL_STRING, NULL_STRING }, -+ { "krb5_use_fast", DP_OPT_STRING, { "try" }, NULL_STRING }, - { "krb5_fast_principal", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "krb5_canonicalize", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, - { "krb5_use_enterprise_principal", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, --- -1.8.5.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 new file mode 100644 index 0000000..f8e95e4 --- /dev/null +++ b/SOURCES/0086-KRB5-Move-checking-for-illegal-RE-to-krb5_utils.c.patch @@ -0,0 +1,487 @@ +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-IPA-default-krb5_fast_principal-to-host-client-realm.patch b/SOURCES/0087-IPA-default-krb5_fast_principal-to-host-client-realm.patch deleted file mode 100644 index ca8a886..0000000 --- a/SOURCES/0087-IPA-default-krb5_fast_principal-to-host-client-realm.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 920e81404bc37e57f2d7613ca9031e2337c1edd0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 14 Feb 2014 11:45:50 +0100 -Subject: [PATCH 87/88] IPA: default krb5_fast_principal to host/$client@$realm - -If krb5_fast_principal is not set in sssd.conf it was set to host/$client, -KRB5 default realm was used which doesn't have to be the same as realm -used for IPA, thus authentication failed when using FAST. - -Reviewed-by: Alexander Bokovoy -(cherry picked from commit e325cabe762fad7d696e014a7fdbb47a5cb8174a) ---- - src/providers/ipa/ipa_common.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c -index e0abd169302406a555728589185b67e0fbbcfe94..d4db1549b3657268381d0e425615c1b389fed23e 100644 ---- a/src/providers/ipa/ipa_common.c -+++ b/src/providers/ipa/ipa_common.c -@@ -665,13 +665,15 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts, - } - - /* If krb5_fast_principal was not set explicitly, default to -- * host/$client_hostname -+ * host/$client_hostname@REALM - */ - value = dp_opt_get_string(ipa_opts->auth, KRB5_FAST_PRINCIPAL); - if (value == NULL) { -- value = talloc_asprintf(ipa_opts->auth, "host/%s", -+ value = talloc_asprintf(ipa_opts->auth, "host/%s@%s", - dp_opt_get_string(ipa_opts->basic, -- IPA_HOSTNAME)); -+ IPA_HOSTNAME), -+ dp_opt_get_string(ipa_opts->auth, -+ KRB5_REALM)); - if (value == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot set %s!\n", - ipa_opts->auth[KRB5_FAST_PRINCIPAL].opt_name)); --- -1.8.5.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 new file mode 100644 index 0000000..da6bae6 --- /dev/null +++ b/SOURCES/0087-KRB5-Move-all-ccache-operations-to-krb5_child.c.patch @@ -0,0 +1,889 @@ +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-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 new file mode 100644 index 0000000..8f3e925 --- /dev/null +++ b/SOURCES/0088-KRB5-Do-not-switch_creds-if-already-the-specified-us.patch @@ -0,0 +1,124 @@ +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/0088-MAN-Clarify-the-new-krb5_use_fast-IPA-default.patch b/SOURCES/0088-MAN-Clarify-the-new-krb5_use_fast-IPA-default.patch deleted file mode 100644 index a985a8c..0000000 --- a/SOURCES/0088-MAN-Clarify-the-new-krb5_use_fast-IPA-default.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 4d5cbad45245016747aa34f2271f2fe5214cf34a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 17 Feb 2014 17:30:52 +0100 -Subject: [PATCH 88/88] MAN: Clarify the new krb5_use_fast IPA default - ---- - src/man/sssd-ipa.5.xml | 34 ++++++++++++++++++++++++++++++++++ - src/man/sssd-krb5.5.xml | 2 +- - 2 files changed, 35 insertions(+), 1 deletion(-) - -diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml -index 28ac252abbeb508d62ca1a94f2440afc6b5b5c88..7ab59dc20cc43c7ed86c0e1a988a30813b9fe673 100644 ---- a/src/man/sssd-ipa.5.xml -+++ b/src/man/sssd-ipa.5.xml -@@ -399,6 +399,40 @@ - - - -+ krb5_use_fast (string) -+ -+ -+ Enables flexible authentication secure tunneling -+ (FAST) for Kerberos pre-authentication. The -+ following options are supported: -+ -+ -+ never use FAST. -+ -+ -+ try to use FAST. If the server -+ does not support FAST, continue the -+ authentication without it. This is -+ equivalent to not setting this option at all. -+ -+ -+ demand to use FAST. The -+ authentication fails if the server does not -+ require fast. -+ -+ -+ Default: try -+ -+ -+ NOTE: SSSD supports FAST only with -+ MIT Kerberos version 1.8 and later. If SSSD is used -+ with an older version of MIT Kerberos, using this -+ option is a configuration error. -+ -+ -+ -+ -+ - ipa_hbac_refresh (integer) - - -diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml -index 384d506616408c3f45f5b85621a8101ef4faa3e8..602c07e9c2e2b9c231c596d50be94b7d220c3257 100644 ---- a/src/man/sssd-krb5.5.xml -+++ b/src/man/sssd-krb5.5.xml -@@ -502,7 +502,7 @@ - - - -- Default: false (AD provide: true) -+ Default: false (AD provider: true) - - - --- -1.8.5.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 new file mode 100644 index 0000000..bdda2a6 --- /dev/null +++ b/SOURCES/0089-BUILD-Use-separate-chown-to-make-changing-ownership-.patch @@ -0,0 +1,88 @@ +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-IPA-Don-t-call-tevent_req_post-outside-_send.patch b/SOURCES/0089-IPA-Don-t-call-tevent_req_post-outside-_send.patch deleted file mode 100644 index ac3ca2d..0000000 --- a/SOURCES/0089-IPA-Don-t-call-tevent_req_post-outside-_send.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 4b1c7fee8fd597660e77436fd205802e353b2e97 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 19 Feb 2014 15:00:15 +0100 -Subject: [PATCH 89/90] IPA: Don't call tevent_req_post outside _send -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit 6d4574a8dd1a9cafbb15631e7d01bdf6e67f821b) ---- - src/providers/ipa/ipa_subdomains_id.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index b61c6a5f4d7605f0cdfa182bbc933d35c4613a79..c15bdaa703835ab07a9b3b21d1304220a01eac10 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -580,7 +580,6 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) - fail: - state->dp_error = DP_ERR_FATAL; - tevent_req_error(req, ret); -- tevent_req_post(req, state->ev); - return; - } - --- -1.8.5.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 new file mode 100644 index 0000000..d6262bb --- /dev/null +++ b/SOURCES/0090-BUILD-Make-chown-of-files-to-sssd-user-non-fatal.patch @@ -0,0 +1,44 @@ +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-IPA-Don-t-fail-if-apply_subdomain_homedir-returns-EN.patch b/SOURCES/0090-IPA-Don-t-fail-if-apply_subdomain_homedir-returns-EN.patch deleted file mode 100644 index c09b52e..0000000 --- a/SOURCES/0090-IPA-Don-t-fail-if-apply_subdomain_homedir-returns-EN.patch +++ /dev/null @@ -1,28 +0,0 @@ -From da729f6765e11fec980fbb9ec1291e2a7ef533fe Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 19 Feb 2014 15:34:34 +0100 -Subject: [PATCH 90/90] IPA: Don't fail if apply_subdomain_homedir returns - ENOENT - -Reviewed-by: Pavel Reichl -(cherry picked from commit 26786da26706aeedbda4caea0383c143ed4e59dc) ---- - src/providers/ipa/ipa_subdomains_id.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index c15bdaa703835ab07a9b3b21d1304220a01eac10..637dd61f9f272eb4ac4ecb8368d2210801bb0373 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -550,7 +550,7 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) - ret = apply_subdomain_homedir(state, state->user_dom, - state->ar->filter_type, - state->ar->filter_value); -- if (ret != EOK) { -+ if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, - ("apply_subdomain_homedir failed: [%d]: [%s].\n", - ret, sss_strerror(ret))); --- -1.8.5.3 - diff --git a/SOURCES/0091-BUILD-Touch-files-in-DESTDIR.patch b/SOURCES/0091-BUILD-Touch-files-in-DESTDIR.patch new file mode 100644 index 0000000..0fb4940 --- /dev/null +++ b/SOURCES/0091-BUILD-Touch-files-in-DESTDIR.patch @@ -0,0 +1,43 @@ +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-LDAP-Setup-periodic-task-only-once.patch b/SOURCES/0091-LDAP-Setup-periodic-task-only-once.patch deleted file mode 100644 index 00b4633..0000000 --- a/SOURCES/0091-LDAP-Setup-periodic-task-only-once.patch +++ /dev/null @@ -1,132 +0,0 @@ -From f7a7a583c475eb22a6d762e74c67ffcfa7ba32d0 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 12 Feb 2014 14:33:49 +0100 -Subject: [PATCH 91/92] LDAP: Setup periodic task only once. - -If id provider is {ipa, ad} periodic task will be stared in sssm_{ipa,ad}_init -If you enable enumeration and use different providers for id and sudo(autofs) -then another periodic task will be scheduled. -This can cause weird behaviour (e.g. missing members of group) - -Perodic tasks will be started only by id_provider. - -Resolves: -https://fedorahosted.org/sssd/ticket/2153 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 057cb583f02bf47678c393cb8f1f74861c2b960b) ---- - src/providers/ldap/ldap_init.c | 54 ++++++++++++++++++++++++++++++++---------- - 1 file changed, 41 insertions(+), 13 deletions(-) - -diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c -index 15615b2891f2e3104c11e8610c081adcd1d1ee8e..cf4ab5598e2b6eb00c188edabb61e22605e7dc82 100644 ---- a/src/providers/ldap/ldap_init.c -+++ b/src/providers/ldap/ldap_init.c -@@ -84,9 +84,9 @@ errno_t check_order_list_for_duplicates(char **list, - return EOK; - } - --int sssm_ldap_id_init(struct be_ctx *bectx, -- struct bet_ops **ops, -- void **pvt_data) -+static int ldap_id_init_internal(struct be_ctx *bectx, -+ struct bet_ops **ops, -+ void **pvt_data) - { - struct sdap_id_ctx *ctx = NULL; - const char *urls; -@@ -160,11 +160,6 @@ int sssm_ldap_id_init(struct be_ctx *bectx, - ret = sdap_idmap_init(ctx, ctx, &ctx->opts->idmap_ctx); - if (ret != EOK) goto done; - -- ret = ldap_id_setup_tasks(ctx); -- if (ret != EOK) { -- goto done; -- } -- - ret = sdap_setup_child(); - if (ret != EOK) { - DEBUG(1, ("setup_child failed [%d][%s].\n", -@@ -202,6 +197,39 @@ done: - return ret; - } - -+int sssm_ldap_id_init(struct be_ctx *bectx, -+ struct bet_ops **ops, -+ void **pvt_data) -+{ -+ int ret; -+ struct sdap_id_ctx *ctx = NULL; -+ -+ ret = ldap_id_init_internal(bectx, ops, (void **) &ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("ldap_id_init_internal failed [%d][%s].\n", -+ ret, strerror(ret))); -+ goto done; -+ } -+ -+ ret = ldap_id_setup_tasks(ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("sdap_id_setup_tasks failed [%d][%s].\n", -+ ret, strerror(ret))); -+ goto done; -+ } -+ -+ *pvt_data = ctx; -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(ctx); -+ } -+ return ret; -+} -+ - int sssm_ldap_auth_init(struct be_ctx *bectx, - struct bet_ops **ops, - void **pvt_data) -@@ -211,7 +239,7 @@ int sssm_ldap_auth_init(struct be_ctx *bectx, - struct sdap_auth_ctx *ctx; - int ret; - -- ret = sssm_ldap_id_init(bectx, ops, &data); -+ ret = ldap_id_init_internal(bectx, ops, &data); - if (ret == EOK) { - id_ctx = talloc_get_type(data, struct sdap_id_ctx); - -@@ -302,9 +330,9 @@ int sssm_ldap_access_init(struct be_ctx *bectx, - goto done; - } - -- ret = sssm_ldap_id_init(bectx, ops, (void **)&access_ctx->id_ctx); -+ ret = ldap_id_init_internal(bectx, ops, (void **)&access_ctx->id_ctx); - if (ret != EOK) { -- DEBUG(1, ("sssm_ldap_id_init failed.\n")); -+ DEBUG(SSSDBG_CRIT_FAILURE, ("ldap_id_init_internal failed.\n")); - goto done; - } - -@@ -417,7 +445,7 @@ int sssm_ldap_sudo_init(struct be_ctx *be_ctx, - void *data; - int ret; - -- ret = sssm_ldap_id_init(be_ctx, ops, &data); -+ ret = ldap_id_init_internal(be_ctx, ops, &data); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot init LDAP ID provider [%d]: %s\n", - ret, strerror(ret))); -@@ -447,7 +475,7 @@ int sssm_ldap_autofs_init(struct be_ctx *be_ctx, - void *data; - int ret; - -- ret = sssm_ldap_id_init(be_ctx, ops, &data); -+ ret = ldap_id_init_internal(be_ctx, ops, &data); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot init LDAP ID provider [%d]: %s\n", - ret, strerror(ret))); --- -1.8.5.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 new file mode 100644 index 0000000..c6df42f --- /dev/null +++ b/SOURCES/0092-BE-Become-a-regular-user-after-initialization.patch @@ -0,0 +1,44 @@ +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-UTIL-Sanitize-whitespaces.patch b/SOURCES/0092-UTIL-Sanitize-whitespaces.patch deleted file mode 100644 index 09cdfa0..0000000 --- a/SOURCES/0092-UTIL-Sanitize-whitespaces.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 1c4109bf7f16016cf0b53cd73e7b80e0d87be660 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 24 Feb 2014 11:37:52 +0100 -Subject: [PATCH 92/92] UTIL: Sanitize whitespaces. - -Original patches submitted by: mpesari(Thanks!!) - -It can cause problems if user will hit spaces before entering username. -(e.g in gdm). Spaces are ignored by LDAP; it's better to escape them. - -Resolves: -https://fedorahosted.org/sssd/ticket/1955 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 2b8208b45feb2aab64d560d3e12e01e7b6d00d39) ---- - src/util/util.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/src/util/util.c b/src/util/util.c -index fb3bed146e2c634375a1133ef512673dee16718a..1ec5c2a9474b0cd2d19a50b495e218d1da7da6c8 100644 ---- a/src/util/util.c -+++ b/src/util/util.c -@@ -537,6 +537,16 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, - - while (input[i]) { - switch(input[i]) { -+ case '\t': -+ output[j++] = '\\'; -+ output[j++] = '0'; -+ output[j++] = '9'; -+ break; -+ case ' ': -+ output[j++] = '\\'; -+ output[j++] = '2'; -+ output[j++] = '0'; -+ break; - case '*': - output[j++] = '\\'; - output[j++] = '2'; --- -1.8.5.3 - diff --git a/SOURCES/0093-IDMAP-add-sss_idmap_check_collision-_ex.patch b/SOURCES/0093-IDMAP-add-sss_idmap_check_collision-_ex.patch deleted file mode 100644 index fe6caa9..0000000 --- a/SOURCES/0093-IDMAP-add-sss_idmap_check_collision-_ex.patch +++ /dev/null @@ -1,362 +0,0 @@ -From 4206e5dbe37277a4002010e85438fe376b5b1812 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 3 Feb 2014 13:30:35 +0100 -Subject: [PATCH 93/97] IDMAP: add sss_idmap_check_collision(_ex) - ---- - src/lib/idmap/sss_idmap.c | 129 ++++++++++++++++++++++++++------------ - src/lib/idmap/sss_idmap.h | 65 +++++++++++++++++++ - src/tests/cmocka/test_sss_idmap.c | 93 +++++++++++++++++++++++++++ - 3 files changed, 247 insertions(+), 40 deletions(-) - -diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c -index 3f1e7a58f390a3c10999251e2155ef513ba69bd7..4c453120539a549807e9b6bb4db2dc396c1b3152 100644 ---- a/src/lib/idmap/sss_idmap.c -+++ b/src/lib/idmap/sss_idmap.c -@@ -380,55 +380,104 @@ enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, - return IDMAP_SUCCESS; - } - -+enum idmap_error_code sss_idmap_check_collision_ex(const char *o_name, -+ const char *o_sid, -+ struct sss_idmap_range *o_range, -+ uint32_t o_first_rid, -+ const char *o_range_id, -+ bool o_external_mapping, -+ const char *n_name, -+ const char *n_sid, -+ struct sss_idmap_range *n_range, -+ uint32_t n_first_rid, -+ const char *n_range_id, -+ bool n_external_mapping) -+{ -+ bool names_equal; -+ bool sids_equal; -+ -+ /* TODO: if both ranges have the same ID check if an update is -+ * needed. */ -+ -+ /* Check if ID ranges overlap. -+ * ID ranges with external mapping may overlap. */ -+ if ((!n_external_mapping && !o_external_mapping) -+ && ((n_range->min >= o_range->min -+ && n_range->min <= o_range->max) -+ || (n_range->max >= o_range->min -+ && n_range->max <= o_range->max))) { -+ return IDMAP_COLLISION; -+ } -+ -+ names_equal = (strcasecmp(n_name, o_name) == 0); -+ sids_equal = ((n_sid == NULL && o_sid == NULL) -+ || (n_sid != NULL && o_sid != NULL -+ && strcasecmp(n_sid, o_sid) == 0)); -+ -+ /* check if domain name and SID are consistent */ -+ if ((names_equal && !sids_equal) || (!names_equal && sids_equal)) { -+ return IDMAP_COLLISION; -+ } -+ -+ /* check if external_mapping is consistent */ -+ if (names_equal && sids_equal -+ && n_external_mapping != o_external_mapping) { -+ return IDMAP_COLLISION; -+ } -+ -+ /* check if RID ranges overlap */ -+ if (names_equal && sids_equal -+ && n_external_mapping == false -+ && n_first_rid >= o_first_rid -+ && n_first_rid <= o_first_rid + (o_range->max - o_range->min)) { -+ return IDMAP_COLLISION; -+ } -+ -+ return IDMAP_SUCCESS; -+} -+ -+enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx, -+ char *n_name, char *n_sid, -+ struct sss_idmap_range *n_range, -+ uint32_t n_first_rid, -+ char *n_range_id, -+ bool n_external_mapping) -+{ -+ struct idmap_domain_info *dom; -+ enum idmap_error_code err; -+ -+ for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { -+ err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range, -+ dom->first_rid, dom->range_id, -+ dom->external_mapping, -+ n_name, n_sid, n_range, n_first_rid, -+ n_range_id, n_external_mapping); -+ if (err != IDMAP_SUCCESS) { -+ return err; -+ } -+ } -+ return IDMAP_SUCCESS; -+} -+ - static enum idmap_error_code dom_check_collision( - struct idmap_domain_info *dom_list, - struct idmap_domain_info *new_dom) - { - struct idmap_domain_info *dom; -- bool names_equal; -- bool sids_equal; -+ enum idmap_error_code err; - - for (dom = dom_list; dom != NULL; dom = dom->next) { -- -- /* TODO: if both ranges have the same ID check if an update is -- * needed. */ -- -- /* Check if ID ranges overlap. -- * ID ranges with external mapping may overlap. */ -- if ((!new_dom->external_mapping && !dom->external_mapping) -- && ((new_dom->range->min >= dom->range->min -- && new_dom->range->min <= dom->range->max) -- || (new_dom->range->max >= dom->range->min -- && new_dom->range->max <= dom->range->max))) { -- return IDMAP_COLLISION; -- } -- -- names_equal = (strcasecmp(new_dom->name, dom->name) == 0); -- sids_equal = ((new_dom->sid == NULL && dom->sid == NULL) -- || (new_dom->sid != NULL && dom->sid != NULL -- && strcasecmp(new_dom->sid, dom->sid) == 0)); -- -- /* check if domain name and SID are consistent */ -- if ((names_equal && !sids_equal) || (!names_equal && sids_equal)) { -- return IDMAP_COLLISION; -- } -- -- /* check if external_mapping is consistent */ -- if (names_equal && sids_equal -- && new_dom->external_mapping != dom->external_mapping) { -- return IDMAP_COLLISION; -- } -- -- /* check if RID ranges overlap */ -- if (names_equal && sids_equal -- && new_dom->external_mapping == false -- && new_dom->first_rid >= dom->first_rid -- && new_dom->first_rid <= -- dom->first_rid + (dom->range->max - dom->range->min)) { -- return IDMAP_COLLISION; -+ err = sss_idmap_check_collision_ex(dom->name, dom->sid, dom->range, -+ dom->first_rid, dom->range_id, -+ dom->external_mapping, -+ new_dom->name, new_dom->sid, -+ new_dom->range, new_dom->first_rid, -+ new_dom->range_id, -+ new_dom->external_mapping); -+ if (err != IDMAP_SUCCESS) { -+ return err; - } - } -- - return IDMAP_SUCCESS; - } - -diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h -index 1e1c9a5cfe490301d0e633db808589f1bc0ef857..ccc63f7f760b877cdb17696325731f8e540b2736 100644 ---- a/src/lib/idmap/sss_idmap.h -+++ b/src/lib/idmap/sss_idmap.h -@@ -289,6 +289,71 @@ enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx, - const char *range_id, - uint32_t rid, - bool external_mapping); -+ -+/** -+ * @brief Check if a new range would collide with any existing one -+ * -+ * @param[in] ctx Idmap context -+ * @param[in] n_name Zero-terminated string with the domain name the new -+ * range should belong to -+ * @param[in] n_sid Zero-terminated string representation of the domain -+ * SID (S-1-15-.....) the new range sould belong to -+ * @param[in] n_range The new id range -+ * @param[in] n_range_id unique identifier of the new range, it is needed -+ * to allow updates at runtime, may be NULL -+ * @param[in] n_first_rid The RID that should be mapped to the first ID of the -+ * new range. -+ * @param[in] n_external_mapping Mapping type of the new range -+ * -+ * @return -+ * - #IDMAP_COLLISION: New range collides with existing one -+ */ -+enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx, -+ char *n_name, char *n_sid, -+ struct sss_idmap_range *n_range, -+ uint32_t n_first_rid, -+ char *n_range_id, -+ bool n_external_mapping); -+ -+/** -+ * @brief Check if two ranges would collide -+ * -+ * @param[in] o_name Zero-terminated string with the domain name the -+ * first range should belong to -+ * @param[in] o_sid Zero-terminated string representation of the domain -+ * SID (S-1-15-.....) the first range sould belong to -+ * @param[in] o_range The first id range -+ * @param[in] o_range_id unique identifier of the first range, it is needed -+ * to allow updates at runtime, may be NULL -+ * @param[in] o_first_rid The RID that should be mapped to the first ID of the -+ * first range. -+ * @param[in] o_external_mapping Mapping type of the first range -+ * @param[in] n_name Zero-terminated string with the domain name the -+ * second range should belong to -+ * @param[in] n_sid Zero-terminated string representation of the domain -+ * SID (S-1-15-.....) the second range sould belong to -+ * @param[in] n_range The second id range -+ * @param[in] n_range_id unique identifier of the second range, it is needed -+ * to allow updates at runtime, may be NULL -+ * @param[in] n_first_rid The RID that should be mapped to the first ID of the -+ * second range. -+ * @param[in] n_external_mapping Mapping type of the second range -+ * -+ * @return -+ * - #IDMAP_COLLISION: New range collides with existing one -+ */ -+enum idmap_error_code sss_idmap_check_collision_ex(const char *o_name, -+ const char *o_sid, -+ struct sss_idmap_range *o_range, -+ uint32_t o_first_rid, -+ const char *o_range_id, -+ bool o_external_mapping, -+ const char *n_name, -+ const char *n_sid, -+ struct sss_idmap_range *n_range, -+ uint32_t n_first_rid, -+ const char *n_range_id, -+ bool n_external_mapping); - /** - * @brief Translate SID to a unix UID or GID - * -diff --git a/src/tests/cmocka/test_sss_idmap.c b/src/tests/cmocka/test_sss_idmap.c -index 019b4618ef0e14e87cb86d64989e8f5ca9dfdfd8..ff933216416b61618bf764d8c2554b273706c787 100644 ---- a/src/tests/cmocka/test_sss_idmap.c -+++ b/src/tests/cmocka/test_sss_idmap.c -@@ -30,11 +30,15 @@ - #define TEST_RANGE_MAX 399999 - #define TEST_DOM_NAME "test.dom" - #define TEST_DOM_SID "S-1-5-21-123-456-789" -+#define TEST_FIRST_RID 0 -+#define TEST_EXT_MAPPING true - - #define TEST_2_RANGE_MIN 600000 - #define TEST_2_RANGE_MAX 799999 - #define TEST_2_DOM_NAME "test2.dom" - #define TEST_2_DOM_SID "S-1-5-21-987-654-321" -+#define TEST_2_FIRST_RID 1000000 -+#define TEST_2_EXT_MAPPING true - - #define TEST_OFFSET 1000000 - #define TEST_OFFSET_STR "1000000" -@@ -408,6 +412,94 @@ void test_has_algorithmic_by_name(void **state) - assert_false(use_id_mapping); - } - -+void test_sss_idmap_check_collision_ex(void **state) -+{ -+ enum idmap_error_code err; -+ struct sss_idmap_range r1 = {TEST_RANGE_MIN, TEST_RANGE_MAX}; -+ struct sss_idmap_range r2 = {TEST_2_RANGE_MIN, TEST_2_RANGE_MAX}; -+ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ TEST_EXT_MAPPING, -+ TEST_2_DOM_NAME, TEST_2_DOM_SID, &r2, -+ TEST_2_FIRST_RID, NULL, -+ TEST_2_EXT_MAPPING); -+ assert_int_equal(err, IDMAP_SUCCESS); -+ -+ /* Same name, different SID */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ TEST_EXT_MAPPING, -+ TEST_DOM_NAME, TEST_2_DOM_SID, &r2, -+ TEST_2_FIRST_RID, NULL, -+ TEST_2_EXT_MAPPING); -+ assert_int_equal(err, IDMAP_COLLISION); -+ -+ /* Same SID, different name */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ TEST_EXT_MAPPING, -+ TEST_2_DOM_NAME, TEST_DOM_SID, &r2, -+ TEST_2_FIRST_RID, NULL, -+ TEST_2_EXT_MAPPING); -+ assert_int_equal(err, IDMAP_COLLISION); -+ -+ /* Same SID and name, no overlaps */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ TEST_EXT_MAPPING, -+ TEST_DOM_NAME, TEST_DOM_SID, &r2, -+ TEST_2_FIRST_RID, NULL, -+ TEST_2_EXT_MAPPING); -+ assert_int_equal(err, IDMAP_SUCCESS); -+ -+ /* Same SID and name, different mappings */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ TEST_EXT_MAPPING, -+ TEST_DOM_NAME, TEST_DOM_SID, &r2, -+ TEST_2_FIRST_RID, NULL, -+ !TEST_EXT_MAPPING); -+ assert_int_equal(err, IDMAP_COLLISION); -+ -+ /* Same SID and name, Overlapping RID range */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ false, -+ TEST_DOM_NAME, TEST_DOM_SID, &r2, -+ TEST_FIRST_RID, NULL, -+ false); -+ assert_int_equal(err, IDMAP_COLLISION); -+ -+ /* Different SID and name, Overlapping RID range */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ false, -+ TEST_2_DOM_NAME, TEST_2_DOM_SID, &r2, -+ TEST_FIRST_RID, NULL, -+ false); -+ assert_int_equal(err, IDMAP_SUCCESS); -+ -+ -+ /* Overlapping ranges with no external mapping */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ false, -+ TEST_2_DOM_NAME, TEST_2_DOM_SID, &r1, -+ TEST_2_FIRST_RID, NULL, -+ false); -+ assert_int_equal(err, IDMAP_COLLISION); -+ -+ /* Overlapping ranges with external mapping */ -+ err = sss_idmap_check_collision_ex(TEST_DOM_NAME, TEST_DOM_SID, &r1, -+ TEST_FIRST_RID, NULL, -+ true, -+ TEST_2_DOM_NAME, TEST_2_DOM_SID, &r1, -+ TEST_2_FIRST_RID, NULL, -+ true); -+ assert_int_equal(err, IDMAP_SUCCESS); -+} -+ - int main(int argc, const char *argv[]) - { - poptContext pc; -@@ -439,6 +531,7 @@ int main(int argc, const char *argv[]) - unit_test_setup_teardown(test_has_algorithmic_by_name, - test_sss_idmap_setup_with_both, - test_sss_idmap_teardown), -+ unit_test(test_sss_idmap_check_collision_ex), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -1.8.5.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 new file mode 100644 index 0000000..f24afe3 --- /dev/null +++ b/SOURCES/0093-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-speci.patch @@ -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/SOURCES/0094-IPA-refactor-idmap-code-and-add-test.patch b/SOURCES/0094-IPA-refactor-idmap-code-and-add-test.patch deleted file mode 100644 index c648a76..0000000 --- a/SOURCES/0094-IPA-refactor-idmap-code-and-add-test.patch +++ /dev/null @@ -1,630 +0,0 @@ -From 5ec1d31f32583761c05691c951576b6213037393 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 7 Feb 2014 15:54:30 +0100 -Subject: [PATCH 94/97] IPA: refactor idmap code and add test - ---- - Makefile.am | 15 +++ - src/providers/ipa/ipa_common.h | 10 ++ - src/providers/ipa/ipa_idmap.c | 248 +++++++++++++++---------------------- - src/tests/cmocka/test_ipa_idmap.c | 249 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 374 insertions(+), 148 deletions(-) - create mode 100644 src/tests/cmocka/test_ipa_idmap.c - -diff --git a/Makefile.am b/Makefile.am -index 16648f9aa2275b60ec84a95ff8a26b1225b97918..2e1a1e6bacfb79e4ef7068a22a64c21d23858cb9 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -150,6 +150,7 @@ if HAVE_CMOCKA - dyndns-tests \ - fqnames-tests \ - test_sss_idmap \ -+ test_ipa_idmap \ - test_utils \ - ad_access_filter_tests \ - ad_common_tests \ -@@ -1359,6 +1360,20 @@ test_sss_idmap_LDADD = \ - $(SSSD_INTERNAL_LTLIBS) \ - libsss_test_common.la - -+test_ipa_idmap_SOURCES = \ -+ src/tests/cmocka/test_ipa_idmap.c \ -+ src/providers/ipa/ipa_idmap.c -+test_ipa_idmap_CFLAGS = \ -+ $(AM_CFLAGS) -+test_ipa_idmap_LDFLAGS = \ -+ -Wl,-wrap,sysdb_get_ranges -+test_ipa_idmap_LDADD = \ -+ $(CMOCKA_LIBS) \ -+ $(POPT_LIBS) \ -+ libsss_idmap.la \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_test_common.la -+ - test_utils_SOURCES = \ - src/tests/cmocka/test_utils.c - test_utils_CFLAGS = \ -diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h -index 02f0baf55f0d226eeb8956076b9bbcce285d4a94..0b8a17c532b7b0081dc749dcef1e6c0e684a7ed2 100644 ---- a/src/providers/ipa/ipa_common.h -+++ b/src/providers/ipa/ipa_common.h -@@ -195,6 +195,16 @@ int ipa_sudo_init(struct be_ctx *be_ctx, - struct bet_ops **ops, - void **pvt_data); - -+errno_t get_idmap_data_from_range(struct range_info *r, char *domain_name, -+ char **_name, char **_sid, uint32_t *_rid, -+ struct sss_idmap_range *_range, -+ bool *_external_mapping); -+ -+errno_t ipa_idmap_get_ranges_from_sysdb(struct sdap_idmap_ctx *idmap_ctx, -+ const char *dom_name, -+ const char *dom_sid_str, -+ bool allow_collisions); -+ - errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx, - struct sdap_idmap_ctx **_idmap_ctx); -diff --git a/src/providers/ipa/ipa_idmap.c b/src/providers/ipa/ipa_idmap.c -index eaca0ed3c3ce2622fbf80dff13d22e2e521f54fe..a65086af4cb4bec7ab85774f3ca1a3555056cee0 100644 ---- a/src/providers/ipa/ipa_idmap.c -+++ b/src/providers/ipa/ipa_idmap.c -@@ -156,9 +156,68 @@ done: - return ret; - } - --errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx, -- const char *dom_name, -- const char *dom_sid_str) -+errno_t get_idmap_data_from_range(struct range_info *r, char *domain_name, -+ char **_name, char **_sid, uint32_t *_rid, -+ struct sss_idmap_range *_range, -+ bool *_external_mapping) -+{ -+ if (r->range_type == NULL) { -+ /* Older IPA servers might not have the range_type attribute, but -+ * only support local ranges and trusts with algorithmic mapping. */ -+ -+ if (r->trusted_dom_sid == NULL && r->secondary_base_rid != 0) { -+ /* local IPA domain */ -+ *_rid = 0; -+ *_external_mapping = true; -+ *_name = domain_name; -+ *_sid = NULL; -+ } else if (r->trusted_dom_sid != NULL -+ && r->secondary_base_rid == 0) { -+ /* trusted domain */ -+ *_rid = r->base_rid; -+ *_external_mapping = false; -+ *_name = r->trusted_dom_sid; -+ *_sid = r->trusted_dom_sid; -+ } else { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Cannot determine range type, " \ -+ "for id range [%s].\n", -+ r->name)); -+ return EINVAL; -+ } -+ } else { -+ if (strcmp(r->range_type, IPA_RANGE_LOCAL) == 0) { -+ *_rid = 0; -+ *_external_mapping = true; -+ *_name = domain_name; -+ *_sid = NULL; -+ } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) == 0) { -+ *_rid = 0; -+ *_external_mapping = true; -+ *_name = r->trusted_dom_sid; -+ *_sid = r->trusted_dom_sid; -+ } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST) == 0) { -+ *_rid = r->base_rid; -+ *_external_mapping = false; -+ *_name = r->trusted_dom_sid; -+ *_sid = r->trusted_dom_sid; -+ } else { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Range type [%s] of id range " \ -+ "[%s] not supported.\n", \ -+ r->range_type, r->name)); -+ return EINVAL; -+ } -+ } -+ -+ _range->min = r->base_id; -+ _range->max = r->base_id + r->id_range_size -1; -+ -+ return EOK; -+} -+ -+errno_t ipa_idmap_get_ranges_from_sysdb(struct sdap_idmap_ctx *idmap_ctx, -+ const char *dom_name, -+ const char *dom_sid_str, -+ bool allow_collisions) - { - int ret; - size_t range_count; -@@ -166,7 +225,6 @@ errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx, - TALLOC_CTX *tmp_ctx; - size_t c; - enum idmap_error_code err; -- struct range_info *r; - struct sss_idmap_range range; - uint32_t rid; - bool external_mapping; -@@ -187,74 +245,39 @@ errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx, - } - - for (c = 0; c < range_count; c++) { -- r = range_list[c]; -- -- if (r->range_type == NULL) { -- /* Older IPA servers might not have the range_type attribute, but -- * only support local ranges and trusts with algorithmic mapping. */ -- -- if (r->trusted_dom_sid == NULL && r->secondary_base_rid != 0) { -- /* local IPA domain */ -- rid = 0; -- external_mapping = true; -- name = idmap_ctx->id_ctx->be->domain->name; -- sid = NULL; -- } else if (r->trusted_dom_sid != NULL -- && r->secondary_base_rid == 0) { -- /* trusted domain */ -- rid = r->base_rid; -- external_mapping = false; -- name = r->trusted_dom_sid; -- sid = r->trusted_dom_sid; -- } else { -- DEBUG(SSSDBG_MINOR_FAILURE, ("Cannot determine range type, " \ -- "skipping id ange [%s].\n", -- r->name)); -- continue; -- } -- } else { -- if (strcmp(r->range_type, IPA_RANGE_LOCAL) == 0) { -- rid = 0; -- external_mapping = true; -- name = idmap_ctx->id_ctx->be->domain->name; -- sid = NULL; -- } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) == 0) { -- rid = 0; -- external_mapping = true; -- name = r->trusted_dom_sid; -- sid = r->trusted_dom_sid; -- } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST) == 0) { -- rid = r->base_rid; -- external_mapping = false; -- name = r->trusted_dom_sid; -- sid = r->trusted_dom_sid; -- } else { -- DEBUG(SSSDBG_MINOR_FAILURE, ("Range type [%s] not supported, " \ -- "skipping id range [%s].\n", -- r->range_type, r->name)); -- continue; -- } -+ ret = get_idmap_data_from_range(range_list[c], -+ idmap_ctx->id_ctx->be->domain->name, -+ &name, &sid, &rid, &range, -+ &external_mapping); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("get_idmap_data_from_range failed for " \ -+ "id range [%s], skipping.\n", -+ range_list[c]->name)); -+ continue; - } - -- range.min = r->base_id; -- range.max = r->base_id + r->id_range_size -1; - err = sss_idmap_add_domain_ex(idmap_ctx->map, name, sid, &range, -- r->name, rid, external_mapping); -- if (err != IDMAP_SUCCESS && err != IDMAP_COLLISION) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Could not add range [%s] to ID map\n", -- r->name)); -- ret = EIO; -+ range_list[c]->name, rid, -+ external_mapping); -+ if (err != IDMAP_SUCCESS) { -+ if (!allow_collisions || err != IDMAP_COLLISION) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Could not add range [%s] to ID map\n", -+ range_list[c]->name)); -+ ret = EIO; -+ goto done; -+ } -+ } -+ } -+ -+ if (dom_name != NULL || dom_sid_str != NULL) { -+ ret = ipa_idmap_check_posix_child(idmap_ctx, dom_name, dom_sid_str, -+ range_count, range_list); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("ipa_idmap_check_posix_child failed.\n")); - goto done; - } - } - -- ret = ipa_idmap_check_posix_child(idmap_ctx, dom_name, dom_sid_str, -- range_count, range_list); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("ipa_idmap_check_posix_child failed.\n")); -- goto done; -- } -- - ret = EOK; - - done: -@@ -263,6 +286,14 @@ done: - return ret; - } - -+errno_t ipa_idmap_find_new_domain(struct sdap_idmap_ctx *idmap_ctx, -+ const char *dom_name, -+ const char *dom_sid_str) -+{ -+ return ipa_idmap_get_ranges_from_sysdb(idmap_ctx, dom_name, dom_sid_str, -+ true); -+} -+ - errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx, - struct sdap_id_ctx *id_ctx, - struct sdap_idmap_ctx **_idmap_ctx) -@@ -270,17 +301,7 @@ errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx, - errno_t ret; - TALLOC_CTX *tmp_ctx; - enum idmap_error_code err; -- size_t c; - struct sdap_idmap_ctx *idmap_ctx = NULL; -- struct sysdb_ctx *sysdb = id_ctx->be->domain->sysdb; -- size_t range_count; -- struct range_info **range_list; -- struct range_info *r; -- struct sss_idmap_range range; -- uint32_t rid; -- bool external_mapping; -- char *name; -- char *sid; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) return ENOMEM; -@@ -309,82 +330,13 @@ errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx, - goto done; - } - -- -- /* Read in any existing mappings from the cache */ -- ret = sysdb_get_ranges(tmp_ctx, sysdb, &range_count, &range_list); -- if (ret != EOK && ret != ENOENT) { -- DEBUG(SSSDBG_FATAL_FAILURE, -- ("Could not read ranges from the cache: [%s]\n", -- strerror(ret))); -+ ret = ipa_idmap_get_ranges_from_sysdb(idmap_ctx, NULL, NULL, false); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("ipa_idmap_get_ranges_from_sysdb failed.\n")); - goto done; - } - -- DEBUG(SSSDBG_CONF_SETTINGS, -- ("Initializing [%zu] domains for ID-mapping\n", range_count)); -- -- for (c = 0; c < range_count; c++) { -- -- r = range_list[c]; -- -- if (r->range_type == NULL) { -- /* Older IPA servers might not have the range_type attribute, but -- * only support local ranges and trusts with algorithmic mapping. */ -- -- if (r->trusted_dom_sid == NULL && r->secondary_base_rid != 0) { -- /* local IPA domain */ -- rid = 0; -- external_mapping = true; -- sid = NULL; -- name = id_ctx->be->domain->name; -- } else if (r->trusted_dom_sid != NULL -- && r->secondary_base_rid == 0) { -- /* trusted domain */ -- rid = r->base_rid; -- external_mapping = false; -- sid = r->trusted_dom_sid; -- name = sid; -- } else { -- DEBUG(SSSDBG_MINOR_FAILURE, ("Cannot determine range type, " \ -- "skipping id ange [%s].\n", -- r->name)); -- continue; -- } -- } else { -- if (strcmp(r->range_type, IPA_RANGE_LOCAL) == 0) { -- rid = 0; -- external_mapping = true; -- sid = NULL; -- name = id_ctx->be->domain->name; -- } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST_POSIX) == 0) { -- rid = 0; -- external_mapping = true; -- sid = r->trusted_dom_sid; -- name = sid; -- } else if (strcmp(r->range_type, IPA_RANGE_AD_TRUST) == 0) { -- rid = r->base_rid; -- external_mapping = false; -- sid = r->trusted_dom_sid; -- name = sid; -- } else { -- DEBUG(SSSDBG_MINOR_FAILURE, ("Range type [%s] not supported, " \ -- "skipping id range [%s].\n", -- r->range_type, r->name)); -- continue; -- } -- } -- -- range.min = r->base_id; -- range.max = r->base_id + r->id_range_size -1; -- err = sss_idmap_add_domain_ex(idmap_ctx->map, name, sid, &range, -- r->name, rid, external_mapping); -- if (err != IDMAP_SUCCESS) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Could not add range [%s] to ID map\n", -- r->name)); -- ret = EIO; -- goto done; -- } -- } -- - *_idmap_ctx = talloc_steal(mem_ctx, idmap_ctx); - ret = EOK; - -diff --git a/src/tests/cmocka/test_ipa_idmap.c b/src/tests/cmocka/test_ipa_idmap.c -new file mode 100644 -index 0000000000000000000000000000000000000000..2fb2cde2f9a7f1172fb69b268d19b559ff9d2f32 ---- /dev/null -+++ b/src/tests/cmocka/test_ipa_idmap.c -@@ -0,0 +1,249 @@ -+/* -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2014 Red Hat -+ -+ SSSD tests: Unit tests for id-mapping in the IPA provider -+ -+ 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 "tests/cmocka/common_mock.h" -+#include "lib/idmap/sss_idmap.h" -+#include "providers/ipa/ipa_common.h" -+#include "providers/ldap/sdap_idmap.h" -+ -+#define RANGE_NAME discard_const("range1") -+#define DOMAIN_SID discard_const("S-1-5-21-2-3-4") -+#define DOMAIN_NAME discard_const("dom.test") -+#define BASE_RID 111 -+#define SECONDARY_BASE_RID 11223344 -+#define BASE_ID 123456 -+#define RANGE_SIZE 222222 -+#define RANGE_MAX (BASE_ID + RANGE_SIZE - 1) -+ -+void test_get_idmap_data_from_range(void **state) -+{ -+ char *dom_name; -+ char *sid; -+ uint32_t rid; -+ struct sss_idmap_range range; -+ bool external_mapping; -+ size_t c; -+ errno_t ret; -+ -+ struct test_data { -+ struct range_info r; -+ errno_t exp_ret; -+ char *exp_dom_name; -+ char *exp_sid; -+ uint32_t exp_rid; -+ struct sss_idmap_range exp_range; -+ bool exp_external_mapping; -+ } d[] = { -+ /* working IPA_RANGE_LOCAL range */ -+ {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, SECONDARY_BASE_RID, -+ NULL, discard_const(IPA_RANGE_LOCAL)}, -+ EOK, DOMAIN_NAME, NULL, 0, {BASE_ID, RANGE_MAX}, true}, -+ /* working old-style IPA_RANGE_LOCAL range without range type */ -+ {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, SECONDARY_BASE_RID, -+ NULL, NULL}, -+ EOK, DOMAIN_NAME, NULL, 0, {BASE_ID, RANGE_MAX}, true}, -+ /* old-style IPA_RANGE_LOCAL without SID and secondary base rid */ -+ {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, NULL, NULL}, -+ EINVAL, NULL, NULL, 0, {0, 0}, false}, -+ /* old-style range with SID and secondary base rid */ -+ {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, SECONDARY_BASE_RID, -+ DOMAIN_SID, NULL}, -+ EINVAL, NULL, NULL, 0, {0, 0}, false}, -+ /* working IPA_RANGE_AD_TRUST range */ -+ {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID, -+ discard_const(IPA_RANGE_AD_TRUST)}, -+ EOK, DOMAIN_SID, DOMAIN_SID, BASE_RID, {BASE_ID, RANGE_MAX}, false}, -+ /* working old-style IPA_RANGE_AD_TRUST range without range type */ -+ {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID, NULL}, -+ EOK, DOMAIN_SID, DOMAIN_SID, BASE_RID, {BASE_ID, RANGE_MAX}, false}, -+ /* working IPA_RANGE_AD_TRUST_POSIX range */ -+ {{RANGE_NAME, BASE_ID, RANGE_SIZE, BASE_RID, 0, DOMAIN_SID, -+ discard_const(IPA_RANGE_AD_TRUST_POSIX)}, -+ EOK, DOMAIN_SID, DOMAIN_SID, 0, {BASE_ID, RANGE_MAX}, true}, -+ {{0}, 0, NULL, NULL, 0, {0, 0}, false} -+ }; -+ -+ for (c = 0; d[c].exp_dom_name != NULL; c++) { -+ ret = get_idmap_data_from_range(&d[c].r, DOMAIN_NAME, &dom_name, &sid, -+ &rid, &range, &external_mapping); -+ assert_int_equal(ret, d[c].exp_ret); -+ assert_string_equal(dom_name, d[c].exp_dom_name); -+ if (d[c].exp_sid == NULL) { -+ assert_null(sid); -+ } else { -+ assert_string_equal(sid, d[c].exp_sid); -+ } -+ assert_int_equal(rid, d[c].exp_rid); -+ assert_int_equal(range.min, d[c].exp_range.min); -+ assert_int_equal(range.max, d[c].exp_range.max); -+ assert_true(external_mapping == d[c].exp_external_mapping); -+ } -+} -+ -+errno_t __wrap_sysdb_get_ranges(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, -+ size_t *range_count, -+ struct range_info ***range_list) -+{ -+ -+ *range_count = sss_mock_type(size_t); -+ *range_list = talloc_steal(mem_ctx, -+ sss_mock_ptr_type(struct range_info **)); -+ return EOK; -+} -+ -+struct test_ctx { -+ struct sdap_idmap_ctx *idmap_ctx; -+ struct sdap_id_ctx *sdap_id_ctx; -+}; -+ -+static struct range_info **get_range_list(TALLOC_CTX *mem_ctx) -+{ -+ struct range_info **range_list; -+ -+ range_list = talloc_array(mem_ctx, struct range_info *, 2); -+ assert_non_null(range_list); -+ -+ range_list[0] = talloc_zero(range_list, struct range_info); -+ assert_non_null(range_list[0]); -+ -+ range_list[0]->name = talloc_strdup(range_list[0], RANGE_NAME); -+ assert_non_null( range_list[0]->name); -+ range_list[0]->base_id = BASE_ID; -+ range_list[0]->id_range_size = RANGE_SIZE; -+ range_list[0]->base_rid = BASE_RID; -+ range_list[0]->secondary_base_rid = 0; -+ range_list[0]->trusted_dom_sid = talloc_strdup(range_list[0], DOMAIN_SID); -+ assert_non_null(range_list[0]->trusted_dom_sid); -+ range_list[0]->range_type = talloc_strdup(range_list[0], -+ IPA_RANGE_AD_TRUST); -+ assert_non_null(range_list[0]->range_type); -+ -+ return range_list; -+} -+ -+void setup_idmap_ctx(void **state) -+{ -+ int ret; -+ struct test_ctx *test_ctx; -+ -+ assert_true(leak_check_setup()); -+ -+ test_ctx = talloc_zero(global_talloc_context, struct test_ctx); -+ assert_non_null(test_ctx); -+ -+ test_ctx->sdap_id_ctx = talloc_zero(test_ctx, -+ struct sdap_id_ctx); -+ assert_non_null(test_ctx->sdap_id_ctx); -+ -+ test_ctx->sdap_id_ctx->be = talloc_zero(test_ctx->sdap_id_ctx, -+ struct be_ctx); -+ assert_non_null(test_ctx->sdap_id_ctx->be); -+ -+ test_ctx->sdap_id_ctx->be->domain = talloc_zero(test_ctx->sdap_id_ctx->be, -+ struct sss_domain_info); -+ assert_non_null(test_ctx->sdap_id_ctx->be->domain); -+ -+ test_ctx->sdap_id_ctx->be->domain->name = -+ talloc_strdup(test_ctx->sdap_id_ctx->be->domain, DOMAIN_NAME); -+ assert_non_null(test_ctx->sdap_id_ctx->be->domain->name); -+ -+ will_return(__wrap_sysdb_get_ranges, 1); -+ will_return(__wrap_sysdb_get_ranges, get_range_list(global_talloc_context)); -+ -+ ret = ipa_idmap_init(test_ctx, test_ctx->sdap_id_ctx, -+ &test_ctx->idmap_ctx); -+ assert_int_equal(ret, EOK); -+ -+ check_leaks_push(test_ctx); -+ *state = test_ctx; -+} -+ -+void teardown_idmap_ctx(void **state) -+{ -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ -+ assert_non_null(test_ctx); -+ -+ assert_true(check_leaks_pop(test_ctx) == true); -+ -+ talloc_free(test_ctx); -+ assert_true(leak_check_teardown()); -+} -+ -+void test_ipa_idmap_get_ranges_from_sysdb(void **state) -+{ -+ int ret; -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ assert_non_null(test_ctx); -+ -+ will_return(__wrap_sysdb_get_ranges, 1); -+ will_return(__wrap_sysdb_get_ranges, get_range_list(test_ctx->idmap_ctx)); -+ ret = ipa_idmap_get_ranges_from_sysdb(test_ctx->idmap_ctx, -+ DOMAIN_NAME, DOMAIN_SID, true); -+ assert_int_equal(ret, EOK); -+ -+ will_return(__wrap_sysdb_get_ranges, 1); -+ will_return(__wrap_sysdb_get_ranges, get_range_list(global_talloc_context)); -+ ret = ipa_idmap_get_ranges_from_sysdb(test_ctx->idmap_ctx, -+ DOMAIN_NAME, DOMAIN_SID, false); -+ assert_int_equal(ret, EIO); -+} -+ -+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_idmap_data_from_range), -+ unit_test_setup_teardown(test_ipa_idmap_get_ranges_from_sysdb, -+ setup_idmap_ctx, teardown_idmap_ctx), -+ }; -+ -+ /* 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_INIT(debug_level); -+ -+ tests_set_cwd(); -+ -+ return run_tests(tests); -+} --- -1.8.5.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 new file mode 100644 index 0000000..1900f08 --- /dev/null +++ b/SOURCES/0094-MAN-page-edit-for-ldap_use_tokengroups.patch @@ -0,0 +1,44 @@ +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-IPA-check-ranges-for-collisions-before-saving-them.patch b/SOURCES/0095-IPA-check-ranges-for-collisions-before-saving-them.patch deleted file mode 100644 index b083bfd..0000000 --- a/SOURCES/0095-IPA-check-ranges-for-collisions-before-saving-them.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 841fef45aef0a1424d4afbf3ea2bb40566155af9 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 7 Feb 2014 18:17:09 +0100 -Subject: [PATCH 95/97] IPA: check ranges for collisions before saving them - -Fixes https://fedorahosted.org/sssd/ticket/2253 ---- - src/providers/ipa/ipa_subdomains.c | 83 +++++++++++++++++++++++++++++--------- - 1 file changed, 63 insertions(+), 20 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index 88b6ba52538be83417e98c9a5dd033bea87ebe4b..07ae03b6ab0325b011a26f36f4fdc9a5766b8445 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -351,14 +351,28 @@ const char *get_flat_name_from_subdomain_name(struct be_ctx *be_ctx, - } - - static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, -+ char *domain_name, - size_t count, - struct sysdb_attrs **reply, - struct range_info ***_range_list) - { - struct range_info **range_list = NULL; -+ struct range_info *r; - const char *value; - size_t c; -+ size_t d; - int ret; -+ enum idmap_error_code err; -+ char *name1; -+ char *name2; -+ char *sid1; -+ char *sid2; -+ uint32_t rid1; -+ uint32_t rid2; -+ struct sss_idmap_range range1; -+ struct sss_idmap_range range2; -+ bool mapping1; -+ bool mapping2; - - range_list = talloc_array(mem_ctx, struct range_info *, count + 1); - if (range_list == NULL) { -@@ -367,8 +381,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - } - - for (c = 0; c < count; c++) { -- range_list[c] = talloc_zero(range_list, struct range_info); -- if (range_list[c] == NULL) { -+ r = talloc_zero(range_list, struct range_info); -+ if (r == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n")); - ret = ENOMEM; - goto done; -@@ -379,8 +393,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); - goto done; - } -- range_list[c]->name = talloc_strdup(range_list[c], value); -- if (range_list[c]->name == NULL) { -+ r->name = talloc_strdup(r, value); -+ if (r->name == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; -@@ -388,9 +402,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - - ret = sysdb_attrs_get_string(reply[c], IPA_TRUSTED_DOMAIN_SID, &value); - if (ret == EOK) { -- range_list[c]->trusted_dom_sid = talloc_strdup(range_list[c], -- value); -- if (range_list[c]->trusted_dom_sid == NULL) { -+ r->trusted_dom_sid = talloc_strdup(r, value); -+ if (r->trusted_dom_sid == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; -@@ -401,28 +414,28 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - } - - ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_ID, -- &range_list[c]->base_id); -+ &r->base_id); - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); - goto done; - } - - ret = sysdb_attrs_get_uint32_t(reply[c], IPA_ID_RANGE_SIZE, -- &range_list[c]->id_range_size); -+ &r->id_range_size); - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); - goto done; - } - - ret = sysdb_attrs_get_uint32_t(reply[c], IPA_BASE_RID, -- &range_list[c]->base_rid); -+ &r->base_rid); - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); - goto done; - } - - ret = sysdb_attrs_get_uint32_t(reply[c], IPA_SECONDARY_BASE_RID, -- &range_list[c]->secondary_base_rid); -+ &r->secondary_base_rid); - if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); - goto done; -@@ -430,8 +443,8 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - - ret = sysdb_attrs_get_string(reply[c], IPA_RANGE_TYPE, &value); - if (ret == EOK) { -- range_list[c]->range_type = talloc_strdup(range_list[c], value); -- if (range_list[c]->range_type == NULL) { -+ r->range_type = talloc_strdup(r, value); -+ if (r->range_type == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; -@@ -439,23 +452,52 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - } else if (ret == ENOENT) { - /* Older IPA servers might not have the range_type attribute, but - * only support local ranges and trusts with algorithmic mapping. */ -- if (range_list[c]->trusted_dom_sid == NULL) { -- range_list[c]->range_type = talloc_strdup(range_list[c], -- IPA_RANGE_LOCAL); -+ if (r->trusted_dom_sid == NULL) { -+ r->range_type = talloc_strdup(r, IPA_RANGE_LOCAL); - } else { -- range_list[c]->range_type = talloc_strdup(range_list[c], -- IPA_RANGE_AD_TRUST); -+ r->range_type = talloc_strdup(r, IPA_RANGE_AD_TRUST); - } - } else { - DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); - goto done; - } -- if (range_list[c]->range_type == NULL) { -+ if (r->range_type == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); - ret = ENOMEM; - goto done; - } -+ -+ 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")); -+ goto done; -+ } -+ for (d = 0; d < c; d++) { -+ ret = get_idmap_data_from_range(range_list[d], domain_name, &name2, -+ &sid2, &rid2, &range2, &mapping2); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("get_idmap_data_from_range failed.\n")); -+ goto done; -+ } -+ -+ err = sss_idmap_check_collision_ex(name1, sid1, &range1, rid1, -+ r->name, mapping1, -+ name2, sid2, &range2, rid2, -+ range_list[d]->name, mapping2); -+ if (err != IDMAP_SUCCESS) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Collision of ranges [%s] and [%s] detected.\n", -+ r->name, range_list[d]->name)); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ range_list[c] = r; - } -+ - range_list[c] = NULL; - - *_range_list = range_list; -@@ -1013,7 +1055,8 @@ static void ipa_subdomains_handler_ranges_done(struct tevent_req *req) - goto done; - } - -- ret = ipa_ranges_parse_results(ctx, reply_count, reply, &range_list); -+ ret = ipa_ranges_parse_results(ctx, domain->name, -+ reply_count, reply, &range_list); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - ("ipa_ranges_parse_results request failed.\n")); --- -1.8.5.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 new file mode 100644 index 0000000..01d0903 --- /dev/null +++ b/SOURCES/0095-sysdb-add-sysdb_search_object_by_uuid.patch @@ -0,0 +1,209 @@ +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-OPTS-Allow-using-defaults-for-blobs.patch b/SOURCES/0096-OPTS-Allow-using-defaults-for-blobs.patch deleted file mode 100644 index ac6b578..0000000 --- a/SOURCES/0096-OPTS-Allow-using-defaults-for-blobs.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 2f08218f0eb6e069c94401ac439d5d7f5b032564 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 24 Feb 2014 15:42:15 +0100 -Subject: [PATCH 96/97] OPTS: Allow using defaults for blobs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit ddd21d5dc3c89712d9286d1f66f4b2af73651cf2) ---- - src/providers/data_provider_opts.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/providers/data_provider_opts.c b/src/providers/data_provider_opts.c -index 0edadecc12d2e354c590df9d3ed011cb4e44eee0..5a2e3b74da7d4af4326a56a9cd47b7826e4b78e3 100644 ---- a/src/providers/data_provider_opts.c -+++ b/src/providers/data_provider_opts.c -@@ -78,6 +78,9 @@ int dp_get_options(TALLOC_CTX *memctx, - if (tmp) { - opts[i].val.blob.data = (uint8_t *)tmp; - opts[i].val.blob.length = strlen(tmp); -+ } else if (opts[i].def_val.blob.data != NULL) { -+ opts[i].val.blob.data = opts[i].def_val.blob.data; -+ opts[i].val.blob.length = opts[i].def_val.blob.length; - } else { - opts[i].val.blob.data = NULL; - opts[i].val.blob.length = 0; --- -1.8.5.3 - diff --git a/SOURCES/0096-ipa-add-split_ipa_anchor.patch b/SOURCES/0096-ipa-add-split_ipa_anchor.patch new file mode 100644 index 0000000..fd7df7e --- /dev/null +++ b/SOURCES/0096-ipa-add-split_ipa_anchor.patch @@ -0,0 +1,179 @@ +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-DP-Provide-separate-dp_copy_defaults-function.patch b/SOURCES/0097-DP-Provide-separate-dp_copy_defaults-function.patch deleted file mode 100644 index 4ef2599..0000000 --- a/SOURCES/0097-DP-Provide-separate-dp_copy_defaults-function.patch +++ /dev/null @@ -1,637 +0,0 @@ -From cb5090d6da0e0b378b095b151af70fa21cd62e9e Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 24 Feb 2014 15:42:51 +0100 -Subject: [PATCH 97/97] DP: Provide separate dp_copy_defaults function -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2257 - -Reviewed-by: Pavel Březina -(cherry picked from commit 90afedb00608547ae1f32aa7aafd552c4b306909) ---- - Makefile.am | 12 ++ - src/providers/ad/ad_common.c | 16 +- - src/providers/data_provider.h | 5 + - src/providers/data_provider_opts.c | 42 ++-- - src/tests/cmocka/test_dp_opts.c | 421 +++++++++++++++++++++++++++++++++++++ - src/tests/ipa_ldap_opt-tests.c | 2 +- - 6 files changed, 476 insertions(+), 22 deletions(-) - create mode 100644 src/tests/cmocka/test_dp_opts.c - -diff --git a/Makefile.am b/Makefile.am -index 2e1a1e6bacfb79e4ef7068a22a64c21d23858cb9..9025ec6a5bfa16408278506fdd573666b4b6dbe5 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -154,6 +154,7 @@ if HAVE_CMOCKA - test_utils \ - ad_access_filter_tests \ - ad_common_tests \ -+ dp_opt_tests \ - test_search_bases - endif - -@@ -1459,6 +1460,17 @@ ad_common_tests_LDADD = \ - libsss_krb5_common.la \ - libsss_test_common.la - -+dp_opt_tests_SOURCES = \ -+ src/providers/data_provider_opts.c \ -+ src/tests/cmocka/test_dp_opts.c -+dp_opt_tests_CFLAGS = \ -+ $(AM_CFLAGS) -+dp_opt_tests_LDADD = \ -+ $(CMOCKA_LIBS) \ -+ $(TALLOC_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_test_common.la -+ - endif - - noinst_PROGRAMS = pam_test_client -diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c -index 99fa4c07af2a79bb3ca195214ddb0dbd60c61620..605de49f7f7ae910cbc78e38f888600ba78a0c4f 100644 ---- a/src/providers/ad/ad_common.c -+++ b/src/providers/ad/ad_common.c -@@ -44,10 +44,10 @@ ad_create_default_sdap_options(TALLOC_CTX *mem_ctx) - return NULL; - } - -- ret = dp_copy_options(id_opts, -- ad_def_ldap_opts, -- SDAP_OPTS_BASIC, -- &id_opts->basic); -+ ret = dp_copy_defaults(id_opts, -+ ad_def_ldap_opts, -+ SDAP_OPTS_BASIC, -+ &id_opts->basic); - if (ret != EOK) { - goto fail; - } -@@ -117,10 +117,10 @@ ad_create_default_options(TALLOC_CTX *mem_ctx, - ad_options = talloc_zero(mem_ctx, struct ad_options); - if (ad_options == NULL) return NULL; - -- ret = dp_copy_options(ad_options, -- ad_basic_opts, -- AD_OPTS_BASIC, -- &ad_options->basic); -+ ret = dp_copy_defaults(ad_options, -+ ad_basic_opts, -+ AD_OPTS_BASIC, -+ &ad_options->basic); - if (ret != EOK) { - talloc_free(ad_options); - return NULL; -diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h -index d086d5d2f368578c6a44a2c3b33738c894feba95..d86ff58e65c7ae35f7269fdd10ed78f529ed8d8c 100644 ---- a/src/providers/data_provider.h -+++ b/src/providers/data_provider.h -@@ -295,6 +295,11 @@ int dp_copy_options(TALLOC_CTX *memctx, - int num_opts, - struct dp_option **_opts); - -+int dp_copy_defaults(TALLOC_CTX *memctx, -+ struct dp_option *src_opts, -+ int num_opts, -+ struct dp_option **_opts); -+ - const char *_dp_opt_get_cstring(struct dp_option *opts, - int id, const char *location); - char *_dp_opt_get_string(struct dp_option *opts, -diff --git a/src/providers/data_provider_opts.c b/src/providers/data_provider_opts.c -index 5a2e3b74da7d4af4326a56a9cd47b7826e4b78e3..0cc48e46e8bbba487aea15b4ad1044e8ddc0482a 100644 ---- a/src/providers/data_provider_opts.c -+++ b/src/providers/data_provider_opts.c -@@ -131,11 +131,11 @@ done: - } - - /* =Basic-Option-Helpers================================================== */ -- --int dp_copy_options(TALLOC_CTX *memctx, -- struct dp_option *src_opts, -- int num_opts, -- struct dp_option **_opts) -+static int dp_copy_options_ex(TALLOC_CTX *memctx, -+ bool copy_values, -+ struct dp_option *src_opts, -+ int num_opts, -+ struct dp_option **_opts) - { - struct dp_option *opts; - int i, ret = EOK; -@@ -151,9 +151,9 @@ int dp_copy_options(TALLOC_CTX *memctx, - - switch (src_opts[i].type) { - case DP_OPT_STRING: -- if (src_opts[i].val.string) { -+ if (copy_values) { - ret = dp_opt_set_string(opts, i, src_opts[i].val.string); -- } else if (src_opts[i].def_val.string) { -+ } else { - ret = dp_opt_set_string(opts, i, src_opts[i].def_val.string); - } - if (ret != EOK) { -@@ -169,9 +169,9 @@ int dp_copy_options(TALLOC_CTX *memctx, - break; - - case DP_OPT_BLOB: -- if (src_opts[i].val.blob.data) { -+ if (copy_values) { - ret = dp_opt_set_blob(opts, i, src_opts[i].val.blob); -- } else if (src_opts[i].def_val.blob.data) { -+ } else { - ret = dp_opt_set_blob(opts, i, src_opts[i].def_val.blob); - } - if (ret != EOK) { -@@ -185,9 +185,9 @@ int dp_copy_options(TALLOC_CTX *memctx, - break; - - case DP_OPT_NUMBER: -- if (src_opts[i].val.number) { -+ if (copy_values) { - ret = dp_opt_set_int(opts, i, src_opts[i].val.number); -- } else if (src_opts[i].def_val.number) { -+ } else { - ret = dp_opt_set_int(opts, i, src_opts[i].def_val.number); - } - if (ret != EOK) { -@@ -201,9 +201,9 @@ int dp_copy_options(TALLOC_CTX *memctx, - break; - - case DP_OPT_BOOL: -- if (src_opts[i].val.boolean) { -+ if (copy_values) { - ret = dp_opt_set_bool(opts, i, src_opts[i].val.boolean); -- } else if (src_opts[i].def_val.boolean) { -+ } else { - ret = dp_opt_set_bool(opts, i, src_opts[i].def_val.boolean); - } - if (ret != EOK) { -@@ -225,6 +225,22 @@ done: - return ret; - } - -+int dp_copy_options(TALLOC_CTX *memctx, -+ struct dp_option *src_opts, -+ int num_opts, -+ struct dp_option **_opts) -+{ -+ return dp_copy_options_ex(memctx, true, src_opts, num_opts, _opts); -+} -+ -+int dp_copy_defaults(TALLOC_CTX *memctx, -+ struct dp_option *src_opts, -+ int num_opts, -+ struct dp_option **_opts) -+{ -+ return dp_copy_options_ex(memctx, false, src_opts, num_opts, _opts); -+} -+ - static const char *dp_opt_type_to_string(enum dp_opt_type type) - { - switch (type) { -diff --git a/src/tests/cmocka/test_dp_opts.c b/src/tests/cmocka/test_dp_opts.c -new file mode 100644 -index 0000000000000000000000000000000000000000..07998b4034fb33195c99340e5544596925ecf145 ---- /dev/null -+++ b/src/tests/cmocka/test_dp_opts.c -@@ -0,0 +1,421 @@ -+/* -+ Authors: -+ Jakub Hrozek -+ -+ Copyright (C) 2014 Red Hat -+ -+ SSSD tests: Data Provider Option Tests -+ -+ 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 "providers/data_provider.h" -+ -+#include "tests/cmocka/common_mock.h" -+ -+#define STRING_DEFAULT "stringval" -+#define BLOB_DEFAULT "blobval" -+#define INT_DEFAULT 123 -+ -+#define TESTS_PATH "tests_opts" -+#define TEST_CONF_DB "test_opt_conf.ldb" -+#define TEST_SYSDB_FILE "cache_opt_test.ldb" -+#define TEST_DOM_NAME "opt_test" -+#define TEST_ID_PROVIDER "ldap" -+ -+enum test_opts { -+ OPT_STRING_NODEFAULT, -+ OPT_STRING_DEFAULT, -+ OPT_BLOB_NODEFAULT, -+ OPT_BLOB_DEFAULT, -+ OPT_INT_NODEFAULT, -+ OPT_INT_DEFAULT, -+ OPT_BOOL_TRUE, -+ OPT_BOOL_FALSE, -+ -+ OPT_NUM_OPTS -+}; -+ -+struct dp_option test_def_opts[] = { -+ { "string_nodefault", DP_OPT_STRING, NULL_STRING, NULL_STRING }, -+ { "string_default", DP_OPT_STRING, { STRING_DEFAULT }, NULL_STRING}, -+ { "blob_nodefault", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB }, -+ { "blob_default", DP_OPT_BLOB, -+ { .blob = { discard_const(BLOB_DEFAULT), -+ sizeof(BLOB_DEFAULT) - 1 } }, -+ NULL_BLOB }, -+ { "int_nodefault", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER }, -+ { "int_default", DP_OPT_NUMBER, { .number = INT_DEFAULT }, NULL_NUMBER }, -+ { "bool_true", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, -+ { "bool_false", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, -+ DP_OPTION_TERMINATOR -+}; -+ -+static void assert_defaults(struct dp_option *opts) -+{ -+ char *s; -+ struct dp_opt_blob b; -+ int i; -+ bool bo; -+ -+ s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); -+ assert_null(s); -+ -+ s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); -+ assert_non_null(s); -+ assert_string_equal(s, STRING_DEFAULT); -+ -+ b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); -+ assert_null(b.data); -+ assert_int_equal(b.length, 0); -+ -+ b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); -+ assert_non_null(b.data); -+ assert_int_equal(b.length, strlen(BLOB_DEFAULT)); -+ assert_memory_equal(b.data, BLOB_DEFAULT, strlen(BLOB_DEFAULT)); -+ -+ i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); -+ assert_int_equal(i, 0); -+ -+ i = dp_opt_get_int(opts, OPT_INT_DEFAULT); -+ assert_int_equal(i, INT_DEFAULT); -+ -+ bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); -+ assert_true(bo == true); -+ -+ bo = dp_opt_get_bool(opts, OPT_BOOL_FALSE); -+ assert_true(bo == false); -+} -+ -+void opt_test_copy_default(void **state) -+{ -+ int ret; -+ TALLOC_CTX *mem_ctx; -+ struct dp_option *opts; -+ struct dp_opt_blob b; -+ -+ mem_ctx = talloc_new(global_talloc_context); -+ assert_non_null(mem_ctx); -+ -+ ret = dp_copy_defaults(mem_ctx, test_def_opts, OPT_NUM_OPTS, &opts); -+ assert_int_equal(ret, EOK); -+ assert_defaults(opts); -+ -+ /* Test that copy_defaults would still copy defaults even if we -+ * change the values -+ */ -+ ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); -+ assert_int_equal(ret, EOK); -+ ret = dp_opt_set_string(opts, OPT_STRING_DEFAULT, "str2"); -+ assert_int_equal(ret, EOK); -+ -+ b.data = discard_const_p(uint8_t, "blob1"); -+ b.length = strlen("blob1"); -+ ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b); -+ assert_int_equal(ret, EOK); -+ -+ ret = dp_opt_set_blob(opts, OPT_BLOB_DEFAULT, b); -+ b.data = discard_const_p(uint8_t, "blob2"); -+ b.length = strlen("blob2"); -+ assert_int_equal(ret, EOK); -+ -+ ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); -+ assert_int_equal(ret, EOK); -+ ret = dp_opt_set_int(opts, OPT_INT_DEFAULT, 789); -+ assert_int_equal(ret, EOK); -+ -+ ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); -+ assert_int_equal(ret, EOK); -+ ret = dp_opt_set_bool(opts, OPT_BOOL_FALSE, true); -+ assert_int_equal(ret, EOK); -+ -+ talloc_free(opts); -+ ret = dp_copy_defaults(mem_ctx, test_def_opts, OPT_NUM_OPTS, &opts); -+ assert_int_equal(ret, EOK); -+ assert_defaults(opts); -+} -+ -+void opt_test_copy_options(void **state) -+{ -+ int ret; -+ TALLOC_CTX *mem_ctx; -+ struct dp_option *opts; -+ char *s; -+ struct dp_opt_blob b; -+ int i; -+ bool bo; -+ -+ mem_ctx = talloc_new(global_talloc_context); -+ assert_non_null(mem_ctx); -+ -+ ret = dp_copy_options(mem_ctx, test_def_opts, OPT_NUM_OPTS, &opts); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(ret, EOK); -+ -+ ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); -+ assert_int_equal(ret, EOK); -+ -+ b.data = discard_const_p(uint8_t, "blob1"); -+ b.length = strlen("blob1"); -+ ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b); -+ assert_int_equal(ret, EOK); -+ -+ ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); -+ assert_int_equal(ret, EOK); -+ -+ ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); -+ assert_int_equal(ret, EOK); -+ -+ /* Test that options set to an explicit value retain -+ * the value and even options with default value -+ * do not return the default unless explicitly set -+ */ -+ s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); -+ assert_string_equal(s, "str1"); -+ s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); -+ assert_null(s); -+ -+ b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); -+ assert_non_null(b.data); -+ assert_int_equal(b.length, strlen("blob1")); -+ assert_memory_equal(b.data, "blob1", strlen("blob1")); -+ b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); -+ assert_null(b.data); -+ assert_int_equal(b.length, 0); -+ -+ i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); -+ assert_int_equal(i, 456); -+ i = dp_opt_get_int(opts, OPT_INT_DEFAULT); -+ assert_int_equal(i, 0); -+ -+ bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); -+ assert_false(bo == true); -+} -+ -+void opt_test_get(void **state) -+{ -+ int ret; -+ struct sss_test_ctx *tctx; -+ struct dp_option *opts; -+ char *dompath; -+ struct sss_test_conf_param params[] = { -+ { "string_nodefault", "stringval2" }, -+ { "blob_nodefault", "blobval2" }, -+ { "int_nodefault", "456" }, -+ { "bool_true", "false" }, -+ { NULL, NULL }, /* Sentinel */ -+ }; -+ char *s; -+ struct dp_opt_blob b; -+ int i; -+ bool bo; -+ -+ tctx = create_dom_test_ctx(global_talloc_context, TESTS_PATH, TEST_CONF_DB, -+ TEST_SYSDB_FILE, TEST_DOM_NAME, -+ TEST_ID_PROVIDER, params); -+ assert_non_null(tctx); -+ -+ dompath = talloc_asprintf(tctx, "config/domain/%s", TEST_DOM_NAME); -+ assert_non_null(dompath); -+ -+ ret = dp_get_options(global_talloc_context, tctx->confdb, dompath, -+ test_def_opts, OPT_NUM_OPTS, &opts); -+ assert_int_equal(ret, EOK); -+ -+ /* Options that were not specified explicitly should only have the default -+ * value, those that have been specified explicitly should carry that -+ * value -+ */ -+ s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); -+ assert_non_null(s); -+ assert_string_equal(s, "stringval2"); -+ -+ s = dp_opt_get_string(opts, OPT_STRING_DEFAULT); -+ assert_non_null(s); -+ assert_string_equal(s, STRING_DEFAULT); -+ -+ b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); -+ assert_non_null(b.data); -+ assert_int_equal(b.length, strlen("blobval2")); -+ assert_memory_equal(b.data, "blobval2", strlen("blobval2")); -+ -+ b = dp_opt_get_blob(opts, OPT_BLOB_DEFAULT); -+ assert_non_null(b.data); -+ assert_int_equal(b.length, strlen(BLOB_DEFAULT)); -+ assert_memory_equal(b.data, BLOB_DEFAULT, strlen(BLOB_DEFAULT)); -+ -+ i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); -+ assert_int_equal(i, 456); -+ -+ i = dp_opt_get_int(opts, OPT_INT_DEFAULT); -+ assert_int_equal(i, INT_DEFAULT); -+ -+ bo = dp_opt_get_bool(opts, OPT_BOOL_TRUE); -+ assert_true(bo == false); -+ -+ bo = dp_opt_get_bool(opts, OPT_BOOL_FALSE); -+ assert_true(bo == false); -+} -+ -+void opt_test_getset_setup(void **state) -+{ -+ int ret; -+ struct dp_option *opts; -+ -+ ret = dp_copy_defaults(global_talloc_context, -+ test_def_opts, OPT_NUM_OPTS, &opts); -+ assert_int_equal(ret, EOK); -+ assert_defaults(opts); -+ -+ *state = opts; -+} -+ -+void opt_test_getset_teardown(void **state) -+{ -+ struct dp_option *opts = talloc_get_type(*state, struct dp_option); -+ talloc_free(opts); -+} -+ -+void opt_test_getset_string(void **state) -+{ -+ 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); -+ -+ ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); -+ assert_int_equal(ret, EOK); -+ -+ 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) -+{ -+ struct dp_option *opts = talloc_get_type(*state, struct dp_option); -+ int ret; -+ struct dp_opt_blob b; -+ -+ b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); -+ assert_null(b.data); -+ assert_int_equal(b.length, 0); -+ -+ 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); -+ -+ b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); -+ assert_non_null(b.data); -+ assert_int_equal(b.length, strlen("blob2")); -+ assert_memory_equal(b.data, "blob2", strlen("blob2")); -+} -+ -+void opt_test_getset_int(void **state) -+{ -+ struct dp_option *opts = talloc_get_type(*state, struct dp_option); -+ int ret; -+ int i; -+ -+ i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); -+ assert_int_equal(i, 0); -+ -+ ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); -+ assert_int_equal(ret, EOK); -+ -+ i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); -+ assert_int_equal(i, 456); -+} -+ -+void opt_test_getset_bool(void **state) -+{ -+ struct dp_option *opts = talloc_get_type(*state, struct dp_option); -+ int ret; -+ bool b; -+ -+ b = dp_opt_get_bool(opts, OPT_BOOL_TRUE); -+ assert_true(b == true); -+ -+ ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); -+ assert_int_equal(ret, EOK); -+ -+ b = dp_opt_get_bool(opts, OPT_BOOL_TRUE); -+ assert_false(b == true); -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ int no_cleanup = 0; -+ poptContext pc; -+ int opt; -+ int ret; -+ 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(opt_test_getset_string, -+ opt_test_getset_setup, -+ opt_test_getset_teardown), -+ unit_test_setup_teardown(opt_test_getset_int, -+ opt_test_getset_setup, -+ opt_test_getset_teardown), -+ unit_test_setup_teardown(opt_test_getset_bool, -+ opt_test_getset_setup, -+ opt_test_getset_teardown), -+ unit_test_setup_teardown(opt_test_getset_blob, -+ 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) -+ }; -+ -+ /* 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_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_SYSDB_FILE); -+ test_dom_suite_setup(TESTS_PATH); -+ -+ ret = run_tests(tests); -+ if (ret == 0 && !no_cleanup) { -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_SYSDB_FILE); -+ } -+ return ret; -+} -diff --git a/src/tests/ipa_ldap_opt-tests.c b/src/tests/ipa_ldap_opt-tests.c -index 40afa5cba87d89bc6fa7345302991fe766b43314..25a094082dc369092f10ad823d98909027dd9a7e 100644 ---- a/src/tests/ipa_ldap_opt-tests.c -+++ b/src/tests/ipa_ldap_opt-tests.c -@@ -170,7 +170,7 @@ START_TEST(test_copy_opts) - tmp_ctx = talloc_new(NULL); - fail_unless(tmp_ctx != NULL, "talloc_new failed"); - -- ret = dp_copy_options(tmp_ctx, ad_def_ldap_opts, SDAP_OPTS_BASIC, &opts); -+ ret = dp_copy_defaults(tmp_ctx, ad_def_ldap_opts, SDAP_OPTS_BASIC, &opts); - fail_unless(ret == EOK, "[%s]", strerror(ret)); - - for (int i=0; i < SDAP_OPTS_BASIC; i++) { --- -1.8.5.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 new file mode 100644 index 0000000..f731fb0 --- /dev/null +++ b/SOURCES/0097-LDAP-add-support-for-lookups-by-UUID.patch @@ -0,0 +1,147 @@ +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 new file mode 100644 index 0000000..21921b4 --- /dev/null +++ b/SOURCES/0098-LDAP-always-store-UUID-if-available.patch @@ -0,0 +1,200 @@ +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-MAN-Clarify-the-ldap_access_filter-option-further.patch b/SOURCES/0098-MAN-Clarify-the-ldap_access_filter-option-further.patch deleted file mode 100644 index d98e726..0000000 --- a/SOURCES/0098-MAN-Clarify-the-ldap_access_filter-option-further.patch +++ /dev/null @@ -1,49 +0,0 @@ -From af16267fc9d681fc4230fa82a9fe86de9491c8fd Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 24 Feb 2014 19:42:23 +0100 -Subject: [PATCH 98/99] MAN: Clarify the ldap_access_filter option further - -https://fedorahosted.org/sssd/ticket/2235 - -The memberof example was misleading and was making aministrators think -that the ldap_access_filter can resolve nested group memberships. - -Reviewed-by: Sumit Bose -Reviewed-by: Stephen Gallagher -(cherry picked from commit 604d46e028ab62f83060fb88bdd3319a31aca2d1) ---- - src/man/sssd-ldap.5.xml | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml -index cc58544c38e8ffa779f0a1b22a69caaf3f193ce1..b271a2b7fa8b19ac3e4475bd8ca634b0414f5ea4 100644 ---- a/src/man/sssd-ldap.5.xml -+++ b/src/man/sssd-ldap.5.xml -@@ -1775,19 +1775,20 @@ - and this option is not set, it will result in all - users being denied access. - Use access_provider = permit to change this default -- behavior. -+ behavior. Please note that this filter is applied on -+ the LDAP user entry only. - - - Example: - - - access_provider = ldap --ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com -+ldap_access_filter = (employeeType=admin) - - - This example means that access to this host is -- restricted to members of the "allowedusers" group -- in ldap. -+ restricted to users whose employeeType -+ attribute is set to "admin". - - - Offline caching for this feature is limited to --- -1.8.5.3 - diff --git a/SOURCES/0099-MAN-Clarify-that-changing-ID-mapping-options-might-r.patch b/SOURCES/0099-MAN-Clarify-that-changing-ID-mapping-options-might-r.patch deleted file mode 100644 index d560ead..0000000 --- a/SOURCES/0099-MAN-Clarify-that-changing-ID-mapping-options-might-r.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 59995f35b7dd6ec552be1081b0120f2344e3ded3 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 25 Feb 2014 17:09:00 +0100 -Subject: [PATCH 99/99] MAN: Clarify that changing ID mapping options might - require purging the cache - -https://fedorahosted.org/sssd/ticket/2252 - -Currently SSSD chokes when IDs of users change, we don't support ID -changes yet. Because some users were confused about the failures, this -patch adds additional clarification. - -Reviewed-by: Sumit Bose -Reviewed-by: Stephen Gallagher -(cherry picked from commit 3dfa09a826e5f63b4948462c2452937fc329834d) ---- - src/man/include/ldap_id_mapping.xml | 42 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 42 insertions(+) - -diff --git a/src/man/include/ldap_id_mapping.xml b/src/man/include/ldap_id_mapping.xml -index 71ff248f1f24242b911f615fd6afeb0382dfa5a1..7f5dbd30be67745b26dbced341762705d6e09f14 100644 ---- a/src/man/include/ldap_id_mapping.xml -+++ b/src/man/include/ldap_id_mapping.xml -@@ -12,6 +12,48 @@ - need to use manually-assigned values, ALL values must be - manually-assigned. - -+ -+ Please note that changing the ID mapping related configuration -+ options will cause user and group IDs to change. At the moment, -+ SSSD does not support changing IDs, so the SSSD database must -+ be removed. Because cached passwords are also stored in the -+ database, removing the database should only be performed while -+ the authentication servers are reachable, otherwise users might -+ get locked out. In order to cache the password, an authentication -+ must be performed. It is not sufficient to use -+ -+ sss_cache -+ 8 -+ -+ to remove the database, rather the process -+ consists of: -+ -+ -+ -+ Making sure the remote servers are reachable -+ -+ -+ -+ -+ Stopping the SSSD service -+ -+ -+ -+ -+ Removing the database -+ -+ -+ -+ -+ Starting the SSSD service -+ -+ -+ -+ Moreover, as the change of IDs might necessitate the adjustment -+ of other system properties such as file and directory ownership, -+ it's advisable to plan ahead and test the ID mapping configuration -+ thoroughly. -+ - - - Mapping Algorithm --- -1.8.5.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 new file mode 100644 index 0000000..503f95d --- /dev/null +++ b/SOURCES/0099-ipa-add-get_be_acct_req_for_uuid.patch @@ -0,0 +1,102 @@ +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-DOC-Fix-names-of-arguments-in-doxygen-comments.patch b/SOURCES/0100-DOC-Fix-names-of-arguments-in-doxygen-comments.patch deleted file mode 100644 index 5138aea..0000000 --- a/SOURCES/0100-DOC-Fix-names-of-arguments-in-doxygen-comments.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 02e3c4dad405464c2f0cec97203a98e5fb251273 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 13 Feb 2014 17:46:29 +0100 -Subject: [PATCH 100/101] DOC: Fix names of arguments in doxygen comments -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit 3b35ff47651e4893ce537a273466766b962362da) ---- - src/lib/idmap/sss_idmap.h | 2 +- - src/sss_client/idmap/sss_nss_idmap.h | 6 +++--- - src/util/util.h | 2 +- - 3 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/lib/idmap/sss_idmap.h b/src/lib/idmap/sss_idmap.h -index ccc63f7f760b877cdb17696325731f8e540b2736..0797083293f7e010962828ddcd72709b290859b9 100644 ---- a/src/lib/idmap/sss_idmap.h -+++ b/src/lib/idmap/sss_idmap.h -@@ -608,7 +608,7 @@ enum idmap_error_code sss_idmap_free_smb_sid(struct sss_idmap_ctx *ctx, - * @brief Free mapped binary SID. - * - * @param[in] ctx Idmap context -- * @param[in] smb_sid Binary SID to be freed. -+ * @param[in] bin_sid Binary SID to be freed. - * - * @return - * - #IDMAP_CONTEXT_INVALID: Provided context is invalid -diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h -index be5c506e27f0e418022cff78b48ca3a37aacd5af..79dacfbdb1708569507742fbd8579cf7aaa06d9b 100644 ---- a/src/sss_client/idmap/sss_nss_idmap.h -+++ b/src/sss_client/idmap/sss_nss_idmap.h -@@ -43,7 +43,7 @@ enum sss_id_type { - * @param[in] fq_name Fully qualified name of a user or a group - * @param[out] sid String representation of the SID of the requested user - * or group, must be freed by the caller -- * @param[out] id_type Type of the object related to the given name -+ * @param[out] type Type of the object related to the given name - * - * @return - * - 0 (EOK): success, sid contains the requested SID -@@ -63,7 +63,7 @@ int sss_nss_getsidbyname(const char *fq_name, char **sid, - * @param[in] id POSIX UID or GID - * @param[out] sid String representation of the SID of the requested user - * or group, must be freed by the caller -- * @param[out] id_type Type of the object related to the given ID -+ * @param[out] type Type of the object related to the given ID - * - * @return - * - see #sss_nss_getsidbyname -@@ -76,7 +76,7 @@ int sss_nss_getsidbyid(uint32_t id, char **sid, enum sss_id_type *type); - * @param[in] sid String representation of the SID - * @param[out] fq_name Fully qualified name of a user or a group, - * must be freed by the caller -- * @param[out] id_type Type of the object related to the SID -+ * @param[out] type Type of the object related to the SID - * - * @return - * - see #sss_nss_getsidbyname -diff --git a/src/util/util.h b/src/util/util.h -index 7b185bcb4287a4afc5bf67b40164cf69b9beeb19..89684e84a5be6c26fe08e5d3ab3d20d3a0e199b1 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -513,7 +513,7 @@ bool string_in_list(const char *string, char **list, bool case_sensitive); - * prevents the compiler from optimizing out - * - * @param data The address of buffer to wipe -- * @param s Size of the buffer -+ * @param size Size of the buffer - */ - void safezero(void *data, size_t size); - --- -1.8.5.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 new file mode 100644 index 0000000..371eb07 --- /dev/null +++ b/SOURCES/0100-IPA-make-get_object_from_cache-public.patch @@ -0,0 +1,57 @@ +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-IPA-check-overrrides-for-IPA-users-as-well.patch b/SOURCES/0101-IPA-check-overrrides-for-IPA-users-as-well.patch new file mode 100644 index 0000000..f1432a8 --- /dev/null +++ b/SOURCES/0101-IPA-check-overrrides-for-IPA-users-as-well.patch @@ -0,0 +1,517 @@ +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/0101-libsss_idmap-bump-version-info.patch b/SOURCES/0101-libsss_idmap-bump-version-info.patch deleted file mode 100644 index d40eb17..0000000 --- a/SOURCES/0101-libsss_idmap-bump-version-info.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e5792a6be9c3c75c7ec47af873309668f1943ae2 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 26 Feb 2014 20:50:19 +0100 -Subject: [PATCH 101/101] libsss_idmap: bump version-info -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník -(cherry picked from commit 034ffb3c69cd04f03b36b89766c47a7c9bd9b831) ---- - Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Makefile.am b/Makefile.am -index 9025ec6a5bfa16408278506fdd573666b4b6dbe5..879054c2fb96f937fbd58ca0757d703cdea218d8 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -614,7 +614,7 @@ libsss_idmap_la_SOURCES = \ - src/lib/idmap/sss_idmap_conv.c \ - src/util/murmurhash3.c - libsss_idmap_la_LDFLAGS = \ -- -version-info 3:0:3 -+ -version-info 4:0:4 - - dist_pkgconfig_DATA += src/sss_client/idmap/sss_nss_idmap.pc - libsss_nss_idmap_la_SOURCES = \ --- -1.8.5.3 - diff --git a/SOURCES/0102-Enable-views-for-all-domains.patch b/SOURCES/0102-Enable-views-for-all-domains.patch new file mode 100644 index 0000000..877c138 --- /dev/null +++ b/SOURCES/0102-Enable-views-for-all-domains.patch @@ -0,0 +1,32 @@ +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-config-API-add-missing-subdomain-target-to-AD-provid.patch b/SOURCES/0102-config-API-add-missing-subdomain-target-to-AD-provid.patch deleted file mode 100644 index 3c91933..0000000 --- a/SOURCES/0102-config-API-add-missing-subdomain-target-to-AD-provid.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 565ae8c3bec0dd3f1cb618b3766a907b820625ca Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 28 Feb 2014 10:04:08 +0100 -Subject: [PATCH 102/104] config API: add missing subdomain target to AD - provider test -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník -Reviewed-by: Pavel Březina -(cherry picked from commit b564424a77c7c3b361c944e0623023d0cfea2c9f) ---- - src/config/SSSDConfigTest.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py -index b6c1d74aa42917fde1222f90f99cb343c80d921a..e6cf663ec86396a3d50dcbc14d4cf4d1157b0d5d 100755 ---- a/src/config/SSSDConfigTest.py -+++ b/src/config/SSSDConfigTest.py -@@ -730,7 +730,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): - control_provider_dict = { - 'ipa': ['id', 'auth', 'access', 'chpass', 'sudo', 'autofs', - 'session', 'hostid', 'subdomains'], -- 'ad': ['id', 'auth', 'access', 'chpass'], -+ 'ad': ['id', 'auth', 'access', 'chpass', 'subdomains'], - 'local': ['id', 'auth', 'chpass'], - 'ldap': ['id', 'auth', 'access', 'chpass', 'sudo', 'autofs'], - 'krb5': ['auth', 'access', 'chpass'], --- -1.8.5.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 new file mode 100644 index 0000000..e91c003 --- /dev/null +++ b/SOURCES/0103-MAN-Update-case_sensitive-Preserving-in-man-pages.patch @@ -0,0 +1,31 @@ +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-AD-provider.patch b/SOURCES/0103-SUDO-AD-provider.patch deleted file mode 100644 index a456185..0000000 --- a/SOURCES/0103-SUDO-AD-provider.patch +++ /dev/null @@ -1,244 +0,0 @@ -From a15ab6146ebba795e3b58d5f32cf7a1d8653c082 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 28 Feb 2014 10:05:34 +0100 -Subject: [PATCH 103/104] SUDO: AD provider -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch adds the sudo target to the AD provider. The main reason is -to cover different default settings in the LDAP and AD provider. E.g. -the default for ldap_id_mapping is True in the AD provider and False -in the LDAP provider. If ldap_id_mapping was not set explicitly in the -config file both components worked with different setting. - -Fixes https://fedorahosted.org/sssd/ticket/2256 - -Reviewed-by: Jakub Hrozek -Reviewed-by: Lukáš Slebodník -Reviewed-by: Pavel Březina -(cherry picked from commit 61804568ce5ede3b1a699cda17c033dd6c23f0e3) ---- - Makefile.am | 5 ++++ - src/config/SSSDConfigTest.py | 2 +- - src/config/etc/sssd.api.d/sssd-ad.conf | 21 ++++++++++++++ - src/man/sssd-ad.5.xml | 6 ++-- - src/man/sssd.conf.5.xml | 15 ++++++++-- - src/providers/ad/ad_common.h | 4 +++ - src/providers/ad/ad_init.c | 25 +++++++++++++++++ - src/providers/ad/ad_sudo.c | 51 ++++++++++++++++++++++++++++++++++ - 8 files changed, 122 insertions(+), 7 deletions(-) - create mode 100644 src/providers/ad/ad_sudo.c - -diff --git a/Makefile.am b/Makefile.am -index 879054c2fb96f937fbd58ca0757d703cdea218d8..b37c04067d34569ad357327b7d463cc5b052f065 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1803,6 +1803,11 @@ libsss_ad_la_SOURCES = \ - src/util/sss_krb5.c \ - src/util/sss_ldap.c - -+if BUILD_SUDO -+libsss_ad_la_SOURCES += \ -+ src/providers/ad/ad_sudo.c -+endif -+ - libsss_ad_la_CFLAGS = \ - $(AM_CFLAGS) \ - $(LDAP_CFLAGS) \ -diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py -index e6cf663ec86396a3d50dcbc14d4cf4d1157b0d5d..98b2fee63d519201047b0c576295863d59b0a37a 100755 ---- a/src/config/SSSDConfigTest.py -+++ b/src/config/SSSDConfigTest.py -@@ -730,7 +730,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): - control_provider_dict = { - 'ipa': ['id', 'auth', 'access', 'chpass', 'sudo', 'autofs', - 'session', 'hostid', 'subdomains'], -- 'ad': ['id', 'auth', 'access', 'chpass', 'subdomains'], -+ 'ad': ['id', 'auth', 'access', 'chpass', 'sudo', 'subdomains'], - 'local': ['id', 'auth', 'chpass'], - 'ldap': ['id', 'auth', 'access', 'chpass', 'sudo', 'autofs'], - 'krb5': ['auth', 'access', 'chpass'], -diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf -index 6b136f2ec88614092cf1ceb4e2cea79db064d468..aa20ca0bb5b70818525d61a1480a6b56bd8c4e48 100644 ---- a/src/config/etc/sssd.api.d/sssd-ad.conf -+++ b/src/config/etc/sssd.api.d/sssd-ad.conf -@@ -132,3 +132,24 @@ krb5_kpasswd = str, None, false - krb5_backup_kpasswd = str, None, false - - [provider/ad/subdomains] -+ -+[provider/ad/sudo] -+ldap_sudo_search_base = str, None, false -+ldap_sudo_full_refresh_interval = int, None, false -+ldap_sudo_smart_refresh_interval = int, None, false -+ldap_sudo_use_host_filter = bool, None, false -+ldap_sudo_hostnames = str, None, false -+ldap_sudo_ip = str, None, false -+ldap_sudo_include_netgroups = bool, None, false -+ldap_sudo_include_regexp = bool, None, false -+ldap_sudorule_object_class = str, None, false -+ldap_sudorule_name = str, None, false -+ldap_sudorule_command = str, None, false -+ldap_sudorule_host = str, None, false -+ldap_sudorule_user = str, None, false -+ldap_sudorule_option = str, None, false -+ldap_sudorule_runasuser = str, None, false -+ldap_sudorule_runasgroup = str, None, false -+ldap_sudorule_notbefore = str, None, false -+ldap_sudorule_notafter = str, None, false -+ldap_sudorule_order = str, None, false -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index 38cc31278cf87c98ca9e53cf91fda7b141bff78d..8cd94d4aeaf553ecb54e0e4c866be5fb7a44fa8e 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -60,9 +60,9 @@ - - - However, it is neither necessary nor recommended to set these -- options. The AD provider can also be used as an access and chpass -- provider. No configuration of the access provider is required on -- the client side. -+ options. The AD provider can also be used as an access, chpass and -+ sudo provider. No configuration of the access provider is required -+ on the client side. - - - By default, the AD provider will map UID and GID values from the -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 5d861c73cfeb41920619d95e5c1e5c1975dcc45b..29b08d53d2568f2fce47b37ea0b88c9dc233c12e 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -1450,14 +1450,23 @@ fallback_homedir = /home/%u - - sssd-ldap - 5 -- for more information on configuring LDAP. -+ for more information on configuring -+ LDAP. -+ -+ -+ ipa the same as ldap -+ but with IPA default settings. -+ -+ -+ ad the same as ldap -+ but with AD default settings. - - - none disables SUDO explicitly. - - -- Default: The value of id_provider is used if it -- is set. -+ Default: The value of id_provider is -+ used if it is set. - - - -diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h -index d370cef69124c127f41d7c4cbaa25713363e7752..bc11e54b0c4903c876f23bfea3ef573f06ba8c69 100644 ---- a/src/providers/ad/ad_common.h -+++ b/src/providers/ad/ad_common.h -@@ -128,4 +128,8 @@ errno_t ad_dyndns_init(struct be_ctx *be_ctx, - struct ad_options *ctx); - void ad_dyndns_timer(void *pvt); - -+int ad_sudo_init(struct be_ctx *be_ctx, -+ struct ad_id_ctx *id_ctx, -+ struct bet_ops **ops, -+ void **pvt_data); - #endif /* AD_COMMON_H_ */ -diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c -index eff6d990d131e3aba124d252d001dd39e78b45cf..500d807e9c44e92089d31c81f3b22c9606c476e5 100644 ---- a/src/providers/ad/ad_init.c -+++ b/src/providers/ad/ad_init.c -@@ -467,3 +467,28 @@ int sssm_ad_subdomains_init(struct be_ctx *bectx, - - return EOK; - } -+ -+ -+int sssm_ad_sudo_init(struct be_ctx *bectx, -+ struct bet_ops **ops, -+ void **pvt_data) -+{ -+#ifdef BUILD_SUDO -+ struct ad_id_ctx *id_ctx; -+ int ret; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Initializing AD sudo handler\n")); -+ -+ ret = sssm_ad_id_init(bectx, ops, (void **) &id_ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("sssm_ad_id_init failed.\n")); -+ return ret; -+ } -+ -+ return ad_sudo_init(bectx, id_ctx, ops, pvt_data); -+#else -+ DEBUG(SSSDBG_MINOR_FAILURE, ("Sudo init handler called but SSSD is " -+ "built without sudo support, ignoring\n")); -+ return EOK; -+#endif -+} -diff --git a/src/providers/ad/ad_sudo.c b/src/providers/ad/ad_sudo.c -new file mode 100644 -index 0000000000000000000000000000000000000000..b85c95c5c2f44e116a75bc24e073c067806621dd ---- /dev/null -+++ b/src/providers/ad/ad_sudo.c -@@ -0,0 +1,51 @@ -+/* -+ SSSD -+ -+ AD SUDO Provider Initialization 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 "providers/ad/ad_common.h" -+#include "providers/ldap/sdap_sudo.h" -+ -+int ad_sudo_init(struct be_ctx *be_ctx, -+ struct ad_id_ctx *id_ctx, -+ struct bet_ops **ops, -+ void **pvt_data) -+{ -+ int ret; -+ struct ad_options *ad_options; -+ struct sdap_options *ldap_options; -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Initializing sudo AD back end\n")); -+ -+ ret = sdap_sudo_init(be_ctx, id_ctx->sdap_id_ctx, ops, pvt_data); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot initialize LDAP SUDO [%d]: %s\n", -+ ret, strerror(ret))); -+ return ret; -+ } -+ -+ ad_options = id_ctx->ad_options; -+ ldap_options = id_ctx->sdap_id_ctx->opts; -+ -+ ad_options->id->sudorule_map = ldap_options->sudorule_map; -+ return EOK; -+} --- -1.8.5.3 - diff --git a/SOURCES/0104-Man-debug_timestamps-and-debug_microseconds.patch b/SOURCES/0104-Man-debug_timestamps-and-debug_microseconds.patch new file mode 100644 index 0000000..f8d95aa --- /dev/null +++ b/SOURCES/0104-Man-debug_timestamps-and-debug_microseconds.patch @@ -0,0 +1,44 @@ +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-ipa-server-mode-use-lower-case-user-name-for-home-di.patch b/SOURCES/0104-ipa-server-mode-use-lower-case-user-name-for-home-di.patch deleted file mode 100644 index 4071e9b..0000000 --- a/SOURCES/0104-ipa-server-mode-use-lower-case-user-name-for-home-di.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 3b8640e8ef5cbcf934cdd6f42e9f6d956ca47395 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 3 Mar 2014 12:40:43 +0100 -Subject: [PATCH 104/104] ipa-server-mode: use lower-case user name for home - dir - -In older IPA server versions where the AD users where looked up by -winbind the user name component of the home directory path was always -lower case. This still holds for IPA clients as well. To avoid -regression this patch makes the user name component lower case as well. - -Fixes https://fedorahosted.org/sssd/ticket/2263 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 48b1db73639135dd4a15ee153f958c912836c621) ---- - src/providers/ipa/ipa_subdomains_id.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 637dd61f9f272eb4ac4ecb8368d2210801bb0373..00993c496c1d100b37a780828c81492c2fac6157 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -358,6 +358,7 @@ get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - { - errno_t ret; - char *name; -+ char *lc_name; - const char *homedir; - TALLOC_CTX *tmp_ctx; - -@@ -372,7 +373,15 @@ get_subdomain_homedir_of_user(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - goto done; - } - -- homedir = expand_homedir_template(tmp_ctx, dom->subdomain_homedir, name, -+ /* To be compatible with the old winbind based user lookups and IPA -+ * clients the user name in the home directory path will be lower-case. */ -+ lc_name = sss_tc_utf8_str_tolower(tmp_ctx, name); -+ if (lc_name == NULL) { -+ ret =ENOMEM; -+ goto done; -+ } -+ -+ homedir = expand_homedir_template(tmp_ctx, dom->subdomain_homedir, lc_name, - uid, NULL, dom->name, dom->flat_name); - - if (homedir == NULL) { --- -1.8.5.3 - diff --git a/SOURCES/0105-IPA-Do-not-save-intermediate-data-to-sysdb.patch b/SOURCES/0105-IPA-Do-not-save-intermediate-data-to-sysdb.patch deleted file mode 100644 index ba7de59..0000000 --- a/SOURCES/0105-IPA-Do-not-save-intermediate-data-to-sysdb.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 4fc9c7b11aa64a151d19b908ca07d8b16b6657ff Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 4 Mar 2014 13:48:36 +0100 -Subject: [PATCH 105/105] IPA: Do not save intermediate data to sysdb - -https://fedorahosted.org/sssd/ticket/2264 - -Reviewed-by: Sumit Bose ---- - src/providers/ipa/ipa_selinux.c | 68 ++++++++++++++++++++--------------------- - 1 file changed, 34 insertions(+), 34 deletions(-) - -diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c -index c227db937a84228c0f3945dbe11ba904c7ad9744..2209ca188654d8c79ee402ba71beeadab2904093 100644 ---- a/src/providers/ipa/ipa_selinux.c -+++ b/src/providers/ipa/ipa_selinux.c -@@ -251,6 +251,40 @@ static void ipa_selinux_handler_done(struct tevent_req *req) - goto fail; - } - -+ ret = sysdb_transaction_start(sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); -+ goto fail; -+ } -+ in_transaction = true; -+ -+ ret = sysdb_delete_usermaps(op_ctx->domain->sysdb, op_ctx->domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Cannot delete existing maps from sysdb\n")); -+ goto fail; -+ } -+ -+ ret = sysdb_store_selinux_config(sysdb, op_ctx->domain, -+ default_user, map_order); -+ if (ret != EOK) { -+ goto fail; -+ } -+ -+ if (map_count > 0 && maps != NULL) { -+ ret = ipa_save_user_maps(sysdb, op_ctx->domain, map_count, maps); -+ if (ret != EOK) { -+ goto fail; -+ } -+ } -+ -+ ret = sysdb_transaction_commit(sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Could not commit transaction\n")); -+ goto fail; -+ } -+ in_transaction = false; -+ - /* Process the maps and return list of best matches (maps with - * highest priority). The input maps are also parent memory - * context for the output list of best matches. The best match -@@ -279,40 +313,6 @@ static void ipa_selinux_handler_done(struct tevent_req *req) - goto fail; - } - -- ret = sysdb_transaction_start(sysdb); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n")); -- goto fail; -- } -- in_transaction = true; -- -- ret = sysdb_delete_usermaps(op_ctx->domain->sysdb, op_ctx->domain); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- ("Cannot delete existing maps from sysdb\n")); -- goto fail; -- } -- -- ret = sysdb_store_selinux_config(sysdb, op_ctx->domain, -- default_user, map_order); -- if (ret != EOK) { -- goto fail; -- } -- -- if (map_count > 0 && maps != NULL) { -- ret = ipa_save_user_maps(sysdb, op_ctx->domain, map_count, maps); -- if (ret != EOK) { -- goto fail; -- } -- } -- -- ret = sysdb_transaction_commit(sysdb); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("Could not commit transaction\n")); -- goto fail; -- } -- in_transaction = false; -- - /* 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); --- -1.8.5.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 new file mode 100644 index 0000000..dd197e2 --- /dev/null +++ b/SOURCES/0105-sss_client-Extract-destroying-of-mmap-cache-to-funct.patch @@ -0,0 +1,72 @@ +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-Fix-krb5-changepw-when-FAST-only-preauth-methods-are.patch b/SOURCES/0106-Fix-krb5-changepw-when-FAST-only-preauth-methods-are.patch deleted file mode 100644 index 5c7b4a8..0000000 --- a/SOURCES/0106-Fix-krb5-changepw-when-FAST-only-preauth-methods-are.patch +++ /dev/null @@ -1,127 +0,0 @@ -From bbe47ea8ebe6373d0b05181eb27bb65432a9cc97 Mon Sep 17 00:00:00 2001 -From: Nathaniel McCallum -Date: Fri, 7 Mar 2014 12:21:11 -0500 -Subject: [PATCH 106/107] Fix krb5 changepw when FAST-only preauth methods are - used (like OTP) - -Before this patch, a different set of options was used when calling -krb5_get_init_creds_password() for the changepw principal. Because -this set of options did not contain the same FAST settings as the -options for normal requests, all authentication would fail when the -password of a FAST-only account would expire. - -The two sets approach was cargo-cult from kinit where multiple -requests could be issued using the same options set. However, in the -case of krb5_child, only one request (or occasionally a well-defined -second request) will be issued. Two option sets are therefore not -required. - -To fix this problem we removed the second option set used for changepw -requests. All requests now use a single option set which is modified, -if needed, for well-defined subsequent requests. - -Reviewed-by: Jakub Hrozek -Reviewed-by: Sumit Bose ---- - src/providers/krb5/krb5_child.c | 40 ++++++---------------------------------- - 1 file changed, 6 insertions(+), 34 deletions(-) - -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index aa29de0cb4e14ea4804ba660b4b8e9b64e9e340e..461a27464f4fea09d4ca430b53aff072b29de141 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -65,27 +65,14 @@ struct krb5_req { - static krb5_context krb5_error_ctx; - #define KRB5_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error) - --static krb5_error_code get_changepw_options(krb5_context ctx, -- krb5_get_init_creds_opt **_options) -+static void set_changepw_options(krb5_context ctx, -+ krb5_get_init_creds_opt *options) - { -- krb5_get_init_creds_opt *options; -- krb5_error_code kerr; -- -- kerr = sss_krb5_get_init_creds_opt_alloc(ctx, &options); -- if (kerr != 0) { -- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); -- return kerr; -- } -- - sss_krb5_get_init_creds_opt_set_canonicalize(options, 0); - krb5_get_init_creds_opt_set_forwardable(options, 0); - krb5_get_init_creds_opt_set_proxiable(options, 0); - krb5_get_init_creds_opt_set_renew_life(options, 0); - krb5_get_init_creds_opt_set_tkt_life(options, 5*60); -- -- *_options = options; -- -- return 0; - } - - static errno_t sss_send_pac(krb5_authdata **pac_authdata) -@@ -1023,7 +1010,6 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) - krb5_prompter_fct prompter = NULL; - const char *realm_name; - int realm_length; -- krb5_get_init_creds_opt *chagepw_options; - size_t msg_len; - uint8_t *msg; - -@@ -1041,12 +1027,7 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) - prompter = sss_krb5_prompter; - } - -- kerr = get_changepw_options(kr->ctx, &chagepw_options); -- if (kerr != 0) { -- DEBUG(SSSDBG_OP_FAILURE, ("get_changepw_options failed.\n")); -- return kerr; -- } -- -+ set_changepw_options(kr->ctx, kr->options); - sss_krb5_princ_realm(kr->ctx, kr->princ, &realm_name, &realm_length); - - DEBUG(SSSDBG_TRACE_FUNC, -@@ -1055,8 +1036,7 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) - discard_const(password), - prompter, kr, 0, - SSSD_KRB5_CHANGEPW_PRINCIPAL, -- chagepw_options); -- sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options); -+ kr->options); - if (kerr != 0) { - ret = pack_user_info_chpass_error(kr->pd, "Old password not accepted.", - &msg_len, &msg); -@@ -1164,7 +1144,6 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) - - static errno_t tgt_req_child(struct krb5_req *kr) - { -- krb5_get_init_creds_opt *chagepw_options; - const char *password = NULL; - krb5_error_code kerr; - int ret; -@@ -1210,19 +1189,12 @@ static errno_t tgt_req_child(struct krb5_req *kr) - DEBUG(1, ("Failed to unset expire callback, continue ...\n")); - } - -- kerr = get_changepw_options(kr->ctx, &chagepw_options); -- if (kerr != 0) { -- DEBUG(SSSDBG_OP_FAILURE, ("get_changepw_options failed.\n")); -- return kerr; -- } -- -+ set_changepw_options(kr->ctx, kr->options); - kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ, - discard_const(password), - sss_krb5_prompter, kr, 0, - SSSD_KRB5_CHANGEPW_PRINCIPAL, -- chagepw_options); -- -- sss_krb5_get_init_creds_opt_free(kr->ctx, chagepw_options); -+ kr->options); - - krb5_free_cred_contents(kr->ctx, kr->creds); - if (kerr == 0) { --- -1.8.5.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 new file mode 100644 index 0000000..40d08e9 --- /dev/null +++ b/SOURCES/0106-sss_client-Fix-race-condition-in-memory-cache.patch @@ -0,0 +1,243 @@ +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 new file mode 100644 index 0000000..fc3b5c3 --- /dev/null +++ b/SOURCES/0107-IPA-Handle-IPA-groups-returned-from-extop-plugin.patch @@ -0,0 +1,37 @@ +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/0107-IPA-Use-GC-for-AD-initgroup-requests.patch b/SOURCES/0107-IPA-Use-GC-for-AD-initgroup-requests.patch deleted file mode 100644 index f795e50..0000000 --- a/SOURCES/0107-IPA-Use-GC-for-AD-initgroup-requests.patch +++ /dev/null @@ -1,46 +0,0 @@ -From d34211137c7e70563b073b83d773ae18688efbbc Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 6 Mar 2014 15:37:57 +0100 -Subject: [PATCH 107/107] IPA: Use GC for AD initgroup requests - -Reviewed-by: Jakub Hrozek ---- - src/providers/ipa/ipa_subdomains_id.c | 21 +++++++++++++++------ - 1 file changed, 15 insertions(+), 6 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 00993c496c1d100b37a780828c81492c2fac6157..978ccc261d7525662e835b867044b6a5238a29df 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -307,13 +307,22 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, - /* Currently only LDAP port for AD is used because POSIX - * attributes are not replicated to GC by default - */ -- clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2); -- if (clist == NULL) { -- ret = ENOMEM; -- goto fail; -+ -+ if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_INITGROUPS) { -+ clist = ad_gc_conn_list(req, ad_id_ctx, state->user_dom); -+ if (clist == NULL) { -+ ret = ENOMEM; -+ goto fail; -+ } -+ } else { -+ 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[1] = NULL; - } -- clist[0] = ad_id_ctx->ldap_ctx; -- clist[1] = NULL; - - /* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */ - sdom = sdap_domain_get(sdap_id_ctx->opts, state->user_dom); --- -1.8.5.3 - diff --git a/SOURCES/0108-AD-Only-connect-to-GC-for-subdomain-users.patch b/SOURCES/0108-AD-Only-connect-to-GC-for-subdomain-users.patch deleted file mode 100644 index 26f9aea..0000000 --- a/SOURCES/0108-AD-Only-connect-to-GC-for-subdomain-users.patch +++ /dev/null @@ -1,57 +0,0 @@ -From e62c422753537d8e2b98e979553626850b7b7600 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 5 Mar 2014 11:50:54 +0100 -Subject: [PATCH 108/110] AD: Only connect to GC for subdomain users -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2251 - -By connecting to GC for users from both trusted domains and parent -domain, we lose the ability to download the shell and homedir if these -are used with ID mapping. - -This patch changes the user lookups only. Changing the logic for all -lookups would break cross-domain group memberships, for example. - -Reviewed-by: Pavel Březina -(cherry picked from commit bb8a08118db0916bf8252a9481c16271ec20acd3) ---- - src/providers/ad/ad_id.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 87af656b364344a8ef27a444e5dfcf8848939110..a35823b4b77d42fc583a61653a175f0ee4d22ac4 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -215,9 +215,26 @@ 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); -+ break; - case BE_REQ_BY_SECID: /* by SID */ - case BE_REQ_USER_AND_GROUP: /* get SID */ - case BE_REQ_GROUP: /* group */ --- -1.8.5.3 - diff --git a/SOURCES/0108-Fix-KRB5_CONF_PATH.patch b/SOURCES/0108-Fix-KRB5_CONF_PATH.patch new file mode 100644 index 0000000..92e907b --- /dev/null +++ b/SOURCES/0108-Fix-KRB5_CONF_PATH.patch @@ -0,0 +1,57 @@ +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 new file mode 100644 index 0000000..e37de2c --- /dev/null +++ b/SOURCES/0109-AD-IPA-add-krb5_confd_path-configuration-option.patch @@ -0,0 +1,464 @@ +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/0109-MAN-Clarify-the-GC-support-a-bit.patch b/SOURCES/0109-MAN-Clarify-the-GC-support-a-bit.patch deleted file mode 100644 index 8269e74..0000000 --- a/SOURCES/0109-MAN-Clarify-the-GC-support-a-bit.patch +++ /dev/null @@ -1,51 +0,0 @@ -From b9336c0c96d409ecd7371a55fbfcf5691814efec Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 5 Mar 2014 12:13:48 +0100 -Subject: [PATCH 109/110] MAN: Clarify the GC support a bit -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It should be noted that disabling GC does *not* disable lookups from -trusted domains. Disabling GC might be a a good way for admins who wish -to use POSIX attributes in trusted domains and the man page should hint -this option. - -Reviewed-by: Pavel Březina -(cherry picked from commit fdaaf2525e333af04ee9b48429b6766b5fd6cab6) ---- - src/man/sssd-ad.5.xml | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index 8cd94d4aeaf553ecb54e0e4c866be5fb7a44fa8e..0554317f533f2309d9fad60dfe5543f8546a6bbc 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -232,11 +232,19 @@ FOREST:EXAMPLE.COM:(memberOf=cn=admins,ou=groups,dc=example,dc=com) - - - By default, the SSSD connects to the Global -- Catalog first to retrieve users and uses the -- LDAP port to retrieve group memberships or -- as a fallback. Disabling this option makes -- the SSSD only connect to the LDAP port of the -- current AD server. -+ Catalog first to retrieve users from trusted -+ domains and uses the LDAP port to retrieve -+ group memberships or as a fallback. Disabling -+ this option makes the SSSD only connect to -+ the LDAP port of the current AD server. -+ -+ -+ Please note that disabling Global Catalog support -+ does not disable retrieving users from trusted -+ domains. The SSSD would connect to the LDAP port -+ of trusted domains instead. However, Global -+ Catalog must be used in order to resolve -+ cross-domain group memberships. - - - Default: true --- -1.8.5.3 - diff --git a/SOURCES/0110-IPA-Use-the-correct-domain-when-processing-SELinux-r.patch b/SOURCES/0110-IPA-Use-the-correct-domain-when-processing-SELinux-r.patch deleted file mode 100644 index a5644b8..0000000 --- a/SOURCES/0110-IPA-Use-the-correct-domain-when-processing-SELinux-r.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 83eedf41e97e3fae59d92c0331cb3d1dc62a9010 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 5 Mar 2014 16:35:00 +0100 -Subject: [PATCH 110/110] IPA: Use the correct domain when processing SELinux - rules -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We blindly used the user's domain for everything. That wrong in case the -user comes from a subdomain. We should use the IPA domain for accessing -the SELinux rules and host data and the user domain only for the user. - -https://fedorahosted.org/sssd/ticket/2270 - -Reviewed-by: Pavel Březina -(cherry picked from commit 36f606d6743e77721bedeed0907f1be7a19fa4f4) ---- - src/providers/ipa/ipa_selinux.c | 26 ++++++++++++++++---------- - 1 file changed, 16 insertions(+), 10 deletions(-) - -diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c -index 2209ca188654d8c79ee402ba71beeadab2904093..4ec5a64159de139f9ba5b30bf1f1a56baf32a52f 100644 ---- a/src/providers/ipa/ipa_selinux.c -+++ b/src/providers/ipa/ipa_selinux.c -@@ -57,7 +57,8 @@ static errno_t ipa_get_selinux_recv(struct tevent_req *req, - - static struct ipa_selinux_op_ctx * - ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, -- struct sss_domain_info *domain, -+ struct sss_domain_info *ipa_domain, -+ struct sss_domain_info *user_domain, - struct be_req *be_req, const char *username, - const char *hostname, - struct ipa_selinux_ctx *selinux_ctx); -@@ -80,7 +81,8 @@ static errno_t ipa_selinux_process_maps(TALLOC_CTX *mem_ctx, - - struct ipa_selinux_op_ctx { - struct be_req *be_req; -- struct sss_domain_info *domain; -+ struct sss_domain_info *user_domain; -+ struct sss_domain_info *ipa_domain; - struct ipa_selinux_ctx *selinux_ctx; - - struct sysdb_attrs *user; -@@ -131,6 +133,7 @@ void ipa_selinux_handler(struct be_req *be_req) - } - - op_ctx = ipa_selinux_create_op_ctx(be_req, user_domain->sysdb, -+ be_ctx->domain, - user_domain, - be_req, pd->user, hostname, - selinux_ctx); -@@ -155,7 +158,8 @@ fail: - - static struct ipa_selinux_op_ctx * - ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, -- struct sss_domain_info *domain, -+ struct sss_domain_info *ipa_domain, -+ struct sss_domain_info *user_domain, - struct be_req *be_req, const char *username, - const char *hostname, - struct ipa_selinux_ctx *selinux_ctx) -@@ -175,15 +179,16 @@ ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, - return NULL; - } - op_ctx->be_req = be_req; -- op_ctx->domain = domain; -+ op_ctx->ipa_domain = ipa_domain; -+ op_ctx->user_domain = user_domain; - op_ctx->selinux_ctx = selinux_ctx; - -- ret = sss_selinux_extract_user(op_ctx, sysdb, domain, username, &op_ctx->user); -+ ret = sss_selinux_extract_user(op_ctx, sysdb, user_domain, username, &op_ctx->user); - if (ret != EOK) { - goto fail; - } - -- host_dn = sysdb_custom_dn(sysdb, op_ctx, domain, hostname, HBAC_HOSTS_SUBDIR); -+ host_dn = sysdb_custom_dn(sysdb, op_ctx, ipa_domain, hostname, HBAC_HOSTS_SUBDIR); - if (host_dn == NULL) { - goto fail; - } -@@ -229,7 +234,7 @@ static void ipa_selinux_handler_done(struct tevent_req *req) - struct ipa_selinux_op_ctx *op_ctx = tevent_req_callback_data(req, struct ipa_selinux_op_ctx); - struct be_req *breq = op_ctx->be_req; - struct be_ctx *be_ctx = be_req_get_be_ctx(breq); -- struct sysdb_ctx *sysdb = op_ctx->domain->sysdb; -+ struct sysdb_ctx *sysdb = op_ctx->ipa_domain->sysdb; - errno_t ret, sret; - size_t map_count = 0; - struct sysdb_attrs **maps = NULL; -@@ -258,21 +263,22 @@ static void ipa_selinux_handler_done(struct tevent_req *req) - } - in_transaction = true; - -- ret = sysdb_delete_usermaps(op_ctx->domain->sysdb, op_ctx->domain); -+ ret = sysdb_delete_usermaps(op_ctx->ipa_domain->sysdb, op_ctx->ipa_domain); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Cannot delete existing maps from sysdb\n")); - goto fail; - } - -- ret = sysdb_store_selinux_config(sysdb, op_ctx->domain, -+ ret = sysdb_store_selinux_config(op_ctx->ipa_domain->sysdb, -+ op_ctx->ipa_domain, - default_user, map_order); - if (ret != EOK) { - goto fail; - } - - if (map_count > 0 && maps != NULL) { -- ret = ipa_save_user_maps(sysdb, op_ctx->domain, map_count, maps); -+ ret = ipa_save_user_maps(sysdb, op_ctx->ipa_domain, map_count, maps); - if (ret != EOK) { - goto fail; - } --- -1.8.5.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 new file mode 100644 index 0000000..5ac4004 --- /dev/null +++ b/SOURCES/0110-test-Wrong-parameter-type-in-sss_parse_name_check.patch @@ -0,0 +1,32 @@ +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-IPA-KRB5-handle-KRB5_PROG_ETYPE_NOSUPP-during-IPA-pa.patch b/SOURCES/0111-IPA-KRB5-handle-KRB5_PROG_ETYPE_NOSUPP-during-IPA-pa.patch deleted file mode 100644 index edef6ea..0000000 --- a/SOURCES/0111-IPA-KRB5-handle-KRB5_PROG_ETYPE_NOSUPP-during-IPA-pa.patch +++ /dev/null @@ -1,32 +0,0 @@ -From f8a49b3bff8d3969824fc7ba4e90d229f0c4edea Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 11 Mar 2014 13:16:14 +0100 -Subject: [PATCH 111/111] IPA/KRB5: handle KRB5_PROG_ETYPE_NOSUPP during IPA - password migration - -Fixes https://fedorahosted.org/sssd/ticket/2279 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 63bf0b7697d5a51b5338070d0e2652d49a4728ce) ---- - src/providers/krb5/krb5_child.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index 461a27464f4fea09d4ca430b53aff072b29de141..af303e6c8c507c7cef108027c49cc4adb74162e7 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -986,6 +986,10 @@ static errno_t map_krb5_error(krb5_error_code kerr) - case KRB5KRB_AP_ERR_BAD_INTEGRITY: - return ERR_AUTH_FAILED; - -+ /* ERR_CREDS_INVALID is used to indicate to the IPA provider that trying -+ * password migration would make sense. All Kerberos error codes which can -+ * be seen while migrating LDAP users to IPA should be added here. */ -+ case KRB5_PROG_ETYPE_NOSUPP: - case KRB5_PREAUTH_FAILED: - case KRB5KDC_ERR_PREAUTH_FAILED: - return ERR_CREDS_INVALID; --- -1.8.5.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 new file mode 100644 index 0000000..0de6c3c --- /dev/null +++ b/SOURCES/0111-util-Special-case-PCRE_ERROR_NOMATCH-in-sss_parse_na.patch @@ -0,0 +1,85 @@ +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-AD-Continue-if-sssd-failes-to-check-extra-members.patch b/SOURCES/0112-AD-Continue-if-sssd-failes-to-check-extra-members.patch deleted file mode 100644 index 25f4e5c..0000000 --- a/SOURCES/0112-AD-Continue-if-sssd-failes-to-check-extra-members.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 2ac5fed1ea4e9f56a18d0cc3b445855cdc6757c2 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 12 Mar 2014 17:38:22 +0100 -Subject: [PATCH 112/113] AD: Continue if sssd failes to check extra members - -Reported by scan-build - - for (mi = 0; group_only[mi]; mi++) { - ^~~~~~~~~~ -warning: Array access (from variable 'group_only') results in a null pointer -dereference - -It can happend if function ad_group_extra_members fails (ret != EOK) - -Reviewed-by: Simo Sorce -(cherry picked from commit bad65473c4c28ecbf2b6bd374a7ae2d634d57d8d) ---- - 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 a35823b4b77d42fc583a61653a175f0ee4d22ac4..01d18d7ae4bee82d8b75c7103c0f07635c6e08cc 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -772,6 +772,7 @@ ad_enum_cross_dom_members(struct sdap_options *opts, - ret = ad_group_extra_members(tmp_ctx, msgs[i], dom, &group_only); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Failed to check extra members\n")); -+ continue; - } else if (group_only == NULL) { - DEBUG(SSSDBG_TRACE_INTERNAL, ("No extra members\n")); - continue; --- -1.8.5.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 new file mode 100644 index 0000000..e4a8d6a --- /dev/null +++ b/SOURCES/0112-util-sss_get_domain_name-regex-mismatch-not-fatal.patch @@ -0,0 +1,41 @@ +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-IPA-Write-SELinux-usernames-in-the-right-case.patch b/SOURCES/0113-IPA-Write-SELinux-usernames-in-the-right-case.patch deleted file mode 100644 index c09551c..0000000 --- a/SOURCES/0113-IPA-Write-SELinux-usernames-in-the-right-case.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 12fa74c860993f154d1eb1585b4a735ca3684565 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 12 Mar 2014 15:19:02 +0100 -Subject: [PATCH 113/113] IPA: Write SELinux usernames in the right case -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2282 - -Reviewed-by: Michal Židek ---- - src/providers/ipa/ipa_selinux.c | 26 +++++++++++++++++++++----- - 1 file changed, 21 insertions(+), 5 deletions(-) - -diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c -index 4ec5a64159de139f9ba5b30bf1f1a56baf32a52f..7f59161918a04ff8c994a0ce0fe55924ff09eda7 100644 ---- a/src/providers/ipa/ipa_selinux.c -+++ b/src/providers/ipa/ipa_selinux.c -@@ -225,6 +225,7 @@ static errno_t create_order_array(TALLOC_CTX *mem_ctx, const char *map_order, - char ***_order_array, size_t *_order_count); - static errno_t choose_best_seuser(struct sysdb_attrs **usermaps, - struct pam_data *pd, -+ struct sss_domain_info *user_domain, - char **order_array, int order_count, - const char *default_user); - -@@ -311,8 +312,8 @@ static void ipa_selinux_handler_done(struct tevent_req *req) - goto fail; - } - -- ret = choose_best_seuser(best_match_maps, pd, order_array, order_count, -- default_user); -+ ret = choose_best_seuser(best_match_maps, pd, op_ctx->user_domain, -+ order_array, order_count, default_user); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Failed to evaluate ordered SELinux users array.\n")); -@@ -601,13 +602,16 @@ done: - return ret; - } - --static errno_t write_selinux_login_file(const char *username, char *string); -+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); - - /* 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, - struct pam_data *pd, -+ struct sss_domain_info *user_domain, - char **order_array, int order_count, - const char *default_user) - { -@@ -662,7 +666,7 @@ static errno_t choose_best_seuser(struct sysdb_attrs **usermaps, - } - } - -- ret = write_selinux_login_file(pd->user, file_content); -+ ret = write_selinux_login_file(pd->user, user_domain, file_content); - done: - if (!file_content) { - err = remove_selinux_login_file(pd->user); -@@ -673,7 +677,9 @@ done: - return ret; - } - --static errno_t write_selinux_login_file(const char *username, char *string) -+static errno_t write_selinux_login_file(const char *orig_name, -+ struct sss_domain_info *dom, -+ char *string) - { - char *path = NULL; - char *tmp_path = NULL; -@@ -685,6 +691,7 @@ static errno_t write_selinux_login_file(const char *username, char *string) - char *full_string = NULL; - int enforce; - errno_t ret = EOK; -+ const char *username; - - len = strlen(string); - if (len == 0) { -@@ -697,6 +704,15 @@ static errno_t write_selinux_login_file(const char *username, char *string) - return ENOMEM; - } - -+ /* pam_selinux needs the username in the same format getpwnam() would -+ * return it -+ */ -+ username = sss_get_cased_name(tmp_ctx, orig_name, dom->case_sensitive); -+ if (username == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ - path = selogin_path(tmp_ctx, username); - if (path == NULL) { - ret = ENOMEM; --- -1.8.5.3 - diff --git a/SOURCES/0113-sysdb-add-sysdb_delete_view_tree.patch b/SOURCES/0113-sysdb-add-sysdb_delete_view_tree.patch new file mode 100644 index 0000000..8173280 --- /dev/null +++ b/SOURCES/0113-sysdb-add-sysdb_delete_view_tree.patch @@ -0,0 +1,175 @@ +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-krb5_child-remove-unused-option-lifetime_str-from-k5.patch b/SOURCES/0114-krb5_child-remove-unused-option-lifetime_str-from-k5.patch deleted file mode 100644 index 4aeb7a6..0000000 --- a/SOURCES/0114-krb5_child-remove-unused-option-lifetime_str-from-k5.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 4069c662c32836f8ebba7f091c44f9db2a1ef62e Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 20 Mar 2014 18:39:48 +0100 -Subject: [PATCH 114/117] krb5_child: remove unused option lifetime_str from - k5c_setup_fast() - -Reviewed-by: Jakub Hrozek ---- - src/providers/krb5/krb5_child.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index af303e6c8c507c7cef108027c49cc4adb74162e7..7f07efc161d0242e64bd67e13dec9a3faa9f2e30 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -1666,7 +1666,7 @@ static errno_t k5c_recv_data(struct krb5_req *kr, int fd, uint32_t *offline) - return ret; - } - --static int k5c_setup_fast(struct krb5_req *kr, char *lifetime_str, bool demand) -+static int k5c_setup_fast(struct krb5_req *kr, bool demand) - { - krb5_principal fast_princ_struct; - krb5_data *realm_data; -@@ -1675,9 +1675,6 @@ static int k5c_setup_fast(struct krb5_req *kr, char *lifetime_str, bool demand) - krb5_error_code kerr; - char *tmp_str; - -- DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n", -- SSSD_KRB5_LIFETIME, lifetime_str)); -- - tmp_str = getenv(SSSD_KRB5_FAST_PRINCIPAL); - if (tmp_str) { - DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n", -@@ -1869,9 +1866,9 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline) - 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, lifetime_str, false); -+ kerr = k5c_setup_fast(kr, false); - } else if (strcasecmp(use_fast_str, "demand") == 0) { -- kerr = k5c_setup_fast(kr, lifetime_str, true); -+ kerr = k5c_setup_fast(kr, true); - } else { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Unsupported value [%s] for krb5_use_fast.\n", --- -1.8.5.3 - diff --git a/SOURCES/0114-sysdb-add-sysdb_invalidate_overrides.patch b/SOURCES/0114-sysdb-add-sysdb_invalidate_overrides.patch new file mode 100644 index 0000000..8dadcc4 --- /dev/null +++ b/SOURCES/0114-sysdb-add-sysdb_invalidate_overrides.patch @@ -0,0 +1,248 @@ +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-krb5-child-extract-lifetime-settings-into-set_lifeti.patch b/SOURCES/0115-krb5-child-extract-lifetime-settings-into-set_lifeti.patch deleted file mode 100644 index c9502fa..0000000 --- a/SOURCES/0115-krb5-child-extract-lifetime-settings-into-set_lifeti.patch +++ /dev/null @@ -1,133 +0,0 @@ -From b86041a3760faa9273f1df879e8bfa38fbbb84aa Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 21 Mar 2014 12:14:11 +0100 -Subject: [PATCH 115/117] krb5-child: extract lifetime settings into - set_lifetime_options() - -Additionally the lifetime option flags are unset if there are no -explicit settings to make sure the defaults from krb5.conf are used even -if other values were set manually in between. - -Reviewed-by: Jakub Hrozek ---- - src/providers/krb5/krb5_child.c | 89 +++++++++++++++++++++++++---------------- - 1 file changed, 55 insertions(+), 34 deletions(-) - -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index 7f07efc161d0242e64bd67e13dec9a3faa9f2e30..7ea111e108e189c6839feec0f1108175c0291605 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -65,6 +65,57 @@ struct krb5_req { - static krb5_context krb5_error_ctx; - #define KRB5_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error) - -+static krb5_error_code set_lifetime_options(krb5_get_init_creds_opt *options) -+{ -+ char *lifetime_str; -+ krb5_error_code kerr; -+ krb5_deltat lifetime; -+ -+ lifetime_str = getenv(SSSD_KRB5_RENEWABLE_LIFETIME); -+ if (lifetime_str == NULL) { -+ DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n", -+ SSSD_KRB5_RENEWABLE_LIFETIME)); -+ -+ /* Unset option flag to make sure defaults from krb5.conf are used. */ -+ options->flags &= ~(KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE); -+ } else { -+ kerr = krb5_string_to_deltat(lifetime_str, &lifetime); -+ if (kerr != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("krb5_string_to_deltat failed for [%s].\n", -+ lifetime_str)); -+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); -+ return kerr; -+ } -+ DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n", -+ SSSD_KRB5_RENEWABLE_LIFETIME, lifetime_str)); -+ krb5_get_init_creds_opt_set_renew_life(options, lifetime); -+ } -+ -+ lifetime_str = getenv(SSSD_KRB5_LIFETIME); -+ if (lifetime_str == NULL) { -+ DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n", -+ SSSD_KRB5_LIFETIME)); -+ -+ /* Unset option flag to make sure defaults from krb5.conf are used. */ -+ options->flags &= ~(KRB5_GET_INIT_CREDS_OPT_TKT_LIFE); -+ } else { -+ kerr = krb5_string_to_deltat(lifetime_str, &lifetime); -+ if (kerr != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("krb5_string_to_deltat failed for [%s].\n", -+ lifetime_str)); -+ KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); -+ return kerr; -+ } -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ ("%s is set to [%s]\n", SSSD_KRB5_LIFETIME, lifetime_str)); -+ krb5_get_init_creds_opt_set_tkt_life(options, lifetime); -+ } -+ -+ return 0; -+} -+ - static void set_changepw_options(krb5_context ctx, - krb5_get_init_creds_opt *options) - { -@@ -1744,9 +1795,7 @@ static int k5c_setup_fast(struct krb5_req *kr, bool demand) - static int k5c_setup(struct krb5_req *kr, uint32_t offline) - { - krb5_error_code kerr; -- char *lifetime_str; - char *use_fast_str; -- krb5_deltat lifetime; - int parse_flags; - - kr->realm = getenv(SSSD_KRB5_REALM); -@@ -1825,38 +1874,10 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline) - krb5_get_init_creds_opt_set_change_password_prompt(kr->options, 0); - #endif - -- lifetime_str = getenv(SSSD_KRB5_RENEWABLE_LIFETIME); -- if (lifetime_str == NULL) { -- DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n", -- SSSD_KRB5_RENEWABLE_LIFETIME)); -- } else { -- kerr = krb5_string_to_deltat(lifetime_str, &lifetime); -- if (kerr != 0) { -- DEBUG(1, ("krb5_string_to_deltat failed for [%s].\n", -- lifetime_str)); -- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); -- return kerr; -- } -- DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n", -- SSSD_KRB5_RENEWABLE_LIFETIME, lifetime_str)); -- krb5_get_init_creds_opt_set_renew_life(kr->options, lifetime); -- } -- -- lifetime_str = getenv(SSSD_KRB5_LIFETIME); -- if (lifetime_str == NULL) { -- DEBUG(SSSDBG_CONF_SETTINGS, ("Cannot read [%s] from environment.\n", -- SSSD_KRB5_LIFETIME)); -- } else { -- kerr = krb5_string_to_deltat(lifetime_str, &lifetime); -- if (kerr != 0) { -- DEBUG(1, ("krb5_string_to_deltat failed for [%s].\n", -- lifetime_str)); -- KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); -- return kerr; -- } -- DEBUG(SSSDBG_CONF_SETTINGS, -- ("%s is set to [%s]\n", SSSD_KRB5_LIFETIME, lifetime_str)); -- krb5_get_init_creds_opt_set_tkt_life(kr->options, lifetime); -+ kerr = set_lifetime_options(kr->options); -+ if (kerr != 0) { -+ DEBUG(SSSDBG_OP_FAILURE, ("set_lifetime_options failed.\n")); -+ return kerr; - } - - if (!offline) { --- -1.8.5.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 new file mode 100644 index 0000000..71678f0 --- /dev/null +++ b/SOURCES/0115-views-allow-view-name-change-at-startup.patch @@ -0,0 +1,231 @@ +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 new file mode 100644 index 0000000..18ccd03 --- /dev/null +++ b/SOURCES/0116-PAM-Check-for-trusted-domain-before-sending-the-requ.patch @@ -0,0 +1,146 @@ +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/0116-krb5_client-rename-krb5_set_canonicalize-to-set_cano.patch b/SOURCES/0116-krb5_client-rename-krb5_set_canonicalize-to-set_cano.patch deleted file mode 100644 index 96a23b3..0000000 --- a/SOURCES/0116-krb5_client-rename-krb5_set_canonicalize-to-set_cano.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 7dbdbb87a5660128b0bbac011c3684e13380f162 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 21 Mar 2014 16:15:39 +0100 -Subject: [PATCH 116/117] krb5_client: rename krb5_set_canonicalize() to - set_canonicalize_option() - -Reviewed-by: Jakub Hrozek ---- - src/providers/krb5/krb5_child.c | 32 ++++++++++++++++---------------- - 1 file changed, 16 insertions(+), 16 deletions(-) - -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index 7ea111e108e189c6839feec0f1108175c0291605..674dad7387c6874209ee5e491cefc18eba4a6da5 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -116,6 +116,20 @@ static krb5_error_code set_lifetime_options(krb5_get_init_creds_opt *options) - return 0; - } - -+static void set_canonicalize_option(krb5_get_init_creds_opt *opts) -+{ -+ int canonicalize = 0; -+ char *tmp_str; -+ -+ tmp_str = getenv(SSSD_KRB5_CANONICALIZE); -+ if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) { -+ canonicalize = 1; -+ } -+ DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n", -+ SSSD_KRB5_CANONICALIZE, tmp_str ? tmp_str : "not set")); -+ sss_krb5_get_init_creds_opt_set_canonicalize(opts, canonicalize); -+} -+ - static void set_changepw_options(krb5_context ctx, - krb5_get_init_creds_opt *options) - { -@@ -875,20 +889,6 @@ done: - - } - --static void krb5_set_canonicalize(krb5_get_init_creds_opt *opts) --{ -- int canonicalize = 0; -- char *tmp_str; -- -- tmp_str = getenv(SSSD_KRB5_CANONICALIZE); -- if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) { -- canonicalize = 1; -- } -- DEBUG(SSSDBG_CONF_SETTINGS, ("%s is set to [%s]\n", -- SSSD_KRB5_CANONICALIZE, tmp_str ? tmp_str : "not set")); -- sss_krb5_get_init_creds_opt_set_canonicalize(opts, canonicalize); --} -- - static krb5_error_code get_and_save_tgt_with_keytab(krb5_context ctx, - krb5_principal princ, - krb5_keytab keytab, -@@ -904,7 +904,7 @@ static krb5_error_code get_and_save_tgt_with_keytab(krb5_context ctx, - krb5_get_init_creds_opt_set_address_list(&options, NULL); - krb5_get_init_creds_opt_set_forwardable(&options, 0); - krb5_get_init_creds_opt_set_proxiable(&options, 0); -- krb5_set_canonicalize(&options); -+ set_canonicalize_option(&options); - - kerr = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL, - &options); -@@ -1881,7 +1881,7 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline) - } - - if (!offline) { -- krb5_set_canonicalize(kr->options); -+ set_canonicalize_option(kr->options); - - use_fast_str = getenv(SSSD_KRB5_USE_FAST); - if (use_fast_str == NULL || strcasecmp(use_fast_str, "never") == 0) { --- -1.8.5.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 new file mode 100644 index 0000000..25b5f5b --- /dev/null +++ b/SOURCES/0117-PAM-Move-is_uid_trusted-from-pam_ctx-to-preq.patch @@ -0,0 +1,91 @@ +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/0117-krb5-child-add-revert_changepw_options.patch b/SOURCES/0117-krb5-child-add-revert_changepw_options.patch deleted file mode 100644 index 10478f3..0000000 --- a/SOURCES/0117-krb5-child-add-revert_changepw_options.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 62b3828dae4445e30d948cf858e0ecbe120eaf36 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 21 Mar 2014 16:16:23 +0100 -Subject: [PATCH 117/117] krb5-child: add revert_changepw_options() - -After changing the Kerberos password krb5-child will try to get a fresh -TGT with the new password. This patch tries to make sure the right gic -options are used. - -Resolves: https://fedorahosted.org/sssd/ticket/2289 - -Reviewed-by: Jakub Hrozek ---- - src/providers/krb5/krb5_child.c | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) - -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index 674dad7387c6874209ee5e491cefc18eba4a6da5..97c5a590ad78080613325b5a397ac965905932fd 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -140,6 +140,24 @@ static void set_changepw_options(krb5_context ctx, - krb5_get_init_creds_opt_set_tkt_life(options, 5*60); - } - -+static void revert_changepw_options(krb5_get_init_creds_opt *options) -+{ -+ krb5_error_code kerr; -+ -+ set_canonicalize_option(options); -+ -+ /* Currently we do not set forwardable and proxiable explicitly, the flags -+ * must be removed so that libkrb5 can take the defaults from krb5.conf */ -+ options->flags &= ~(KRB5_GET_INIT_CREDS_OPT_FORWARDABLE); -+ options->flags &= ~(KRB5_GET_INIT_CREDS_OPT_PROXIABLE); -+ -+ kerr = set_lifetime_options(options); -+ if (kerr != 0) { -+ DEBUG(SSSDBG_OP_FAILURE, ("set_lifetime_options failed.\n")); -+ } -+} -+ -+ - static errno_t sss_send_pac(krb5_authdata **pac_authdata) - { - struct sss_cli_req_data sss_data; -@@ -1187,6 +1205,10 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) - - krb5_free_cred_contents(kr->ctx, kr->creds); - -+ /* We changed some of the gic options for the password change, now we have -+ * to change them back to get a fresh TGT. */ -+ revert_changepw_options(kr->options); -+ - kerr = get_and_save_tgt(kr, newpassword); - - sss_authtok_set_empty(kr->pd->newauthtok); --- -1.8.5.3 - diff --git a/SOURCES/0118-KRB5-Do-not-attempt-to-get-a-TGT-after-a-password-ch.patch b/SOURCES/0118-KRB5-Do-not-attempt-to-get-a-TGT-after-a-password-ch.patch deleted file mode 100644 index 700c581..0000000 --- a/SOURCES/0118-KRB5-Do-not-attempt-to-get-a-TGT-after-a-password-ch.patch +++ /dev/null @@ -1,164 +0,0 @@ -From a9278ff6f7b387c529c3b57251974403c5990d44 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 18 Mar 2014 16:48:11 +0100 -Subject: [PATCH] KRB5: Do not attempt to get a TGT after a password change - using OTP - -https://fedorahosted.org/sssd/ticket/2271 - -The current krb5_child code attempts to get a TGT for the convenience of -the user using the new password after a password change operation. -However, an OTP should never be used twice, which means we can't perform -the kinit operation after chpass is finished. Instead, we only print a -PAM information instructing the user to log out and back in manually. ---- - src/providers/krb5/krb5_auth.c | 21 ++++++++++++++++++--- - src/providers/krb5/krb5_child.c | 12 ++++++++++++ - src/sss_client/pam_sss.c | 19 +++++++++++++++++++ - src/sss_client/sss_cli.h | 3 +++ - 4 files changed, 52 insertions(+), 3 deletions(-) - -diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c -index ce461f5adefc6e42fdc69726ff71d23526375c0c..48c0746efc3d136a1f13e8982384d503d8d20723 100644 ---- a/src/providers/krb5/krb5_auth.c -+++ b/src/providers/krb5/krb5_auth.c -@@ -815,6 +815,7 @@ 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); -@@ -1062,9 +1063,23 @@ static void krb5_auth_done(struct tevent_req *subreq) - - ret = sss_krb5_check_ccache_princ(kr->uid, kr->gid, kr->ccname, kr->upn); - if (ret) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- ("No ccache for %s in %s?\n", kr->upn, kr->ccname)); -- goto done; -+ 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) { -diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c -index d000d70167936b09bbaa39ec7a665089572d9aaa..3ee49e4678078d15dab98eeddf56d36f87955dcf 100644 ---- a/src/providers/krb5/krb5_child.c -+++ b/src/providers/krb5/krb5_child.c -@@ -45,6 +45,7 @@ struct krb5_req { - krb5_principal princ; - char* name; - krb5_creds *creds; -+ bool otp; - krb5_get_init_creds_opt *options; - - struct pam_data *pd; -@@ -370,6 +371,8 @@ static krb5_error_code answer_otp(krb5_context ctx, - goto done; - } - -+ kr->otp = true; -+ - /* Validate our assumptions about the contents of authtok. */ - ret = sss_authtok_get_password(kr->pd->authtok, &pwd, &len); - if (ret != EOK) -@@ -694,6 +697,8 @@ static errno_t k5c_send_data(struct krb5_req *kr, int fd, errno_t error) - size_t len; - int ret; - -+ DEBUG(SSSDBG_FUNC_DATA, ("Received error code %d\n", error)); -+ - ret = pack_response_packet(kr, error, kr->pd->resp_list, &buf, &len); - if (ret != EOK) { - DEBUG(1, ("pack_response_packet failed.\n")); -@@ -1110,6 +1115,8 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) - prompter, kr, 0, - SSSD_KRB5_CHANGEPW_PRINCIPAL, - kr->options); -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ ("chpass is%s using OTP\n", kr->otp ? "" : " not")); - if (kerr != 0) { - ret = pack_user_info_chpass_error(kr->pd, "Old password not accepted.", - &msg_len, &msg); -@@ -1205,6 +1212,11 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) - - krb5_free_cred_contents(kr->ctx, kr->creds); - -+ if (kr->otp == true) { -+ sss_authtok_set_empty(kr->pd->newauthtok); -+ return map_krb5_error(kerr); -+ } -+ - /* We changed some of the gic options for the password change, now we have - * to change them back to get a fresh TGT. */ - revert_changepw_options(kr->options); -diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c -index 4ff38f299bec75a49c8aace06eecab5735ca9443..e629fc19bd705ac35c2fa1ea4946f40c5eb49079 100644 ---- a/src/sss_client/pam_sss.c -+++ b/src/sss_client/pam_sss.c -@@ -771,6 +771,22 @@ static int user_info_offline_chpass(pam_handle_t *pamh) - return PAM_SUCCESS; - } - -+static int user_info_otp_chpass(pam_handle_t *pamh) -+{ -+ int ret; -+ -+ ret = do_pam_conversation(pamh, PAM_TEXT_INFO, -+ _("After changing the OTP password, you need to " -+ "log out and back in order to acquire a ticket"), -+ NULL, NULL); -+ if (ret != PAM_SUCCESS) { -+ D(("do_pam_conversation failed.")); -+ return PAM_SYSTEM_ERR; -+ } -+ -+ return PAM_SUCCESS; -+} -+ - static int user_info_chpass_error(pam_handle_t *pamh, size_t buflen, - uint8_t *buf) - { -@@ -856,6 +872,9 @@ static int eval_user_info_response(pam_handle_t *pamh, size_t buflen, - case SSS_PAM_USER_INFO_OFFLINE_CHPASS: - ret = user_info_offline_chpass(pamh); - break; -+ case SSS_PAM_USER_INFO_OTP_CHPASS: -+ ret = user_info_otp_chpass(pamh); -+ break; - case SSS_PAM_USER_INFO_CHPASS_ERROR: - ret = user_info_chpass_error(pamh, buflen, buf); - break; -diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h -index 285a2979addb0c0677527b76b3b6755f2f173815..16a08e1869bb81ede2c1db87f1fb6d0a51087847 100644 ---- a/src/sss_client/sss_cli.h -+++ b/src/sss_client/sss_cli.h -@@ -451,6 +451,9 @@ enum user_info_type { - * possible to change the password while - * the system is offline. This message - * is generated by the PAM responder. */ -+ SSS_PAM_USER_INFO_OTP_CHPASS, /**< Tell the user that he needs to kinit -+ * or login and logout to get a TGT after -+ * an OTP password change */ - SSS_PAM_USER_INFO_CHPASS_ERROR, /**< Tell the user that a password change - * failed and optionally give a reason. - * @param Size of the message as unsigned --- -1.8.5.3 - diff --git a/SOURCES/0118-krb5-make-krb5-provider-view-aware.patch b/SOURCES/0118-krb5-make-krb5-provider-view-aware.patch new file mode 100644 index 0000000..df110b6 --- /dev/null +++ b/SOURCES/0118-krb5-make-krb5-provider-view-aware.patch @@ -0,0 +1,88 @@ +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-Use-function-sysdb_attrs_get_el-in-safe-way.patch b/SOURCES/0119-IPA-Use-function-sysdb_attrs_get_el-in-safe-way.patch deleted file mode 100644 index 2aa64b7..0000000 --- a/SOURCES/0119-IPA-Use-function-sysdb_attrs_get_el-in-safe-way.patch +++ /dev/null @@ -1,76 +0,0 @@ -From a9385ea99d15976c5e7585059945f6964f85339c Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 25 Mar 2014 17:57:32 +0100 -Subject: [PATCH] IPA: Use function sysdb_attrs_get_el in safe way - -Function sysdb_attrs_get_el can enlarge array of ldb_message_element in "struct -sysdb_attrs" if attribute is not among available attributes. Array will be -enlarged with function talloc_realloc but realloc can move array to another -place in memory therefore ldb_message_element should not be used after next -call of function sysdb_attrs_get_el - - sysdb_attrs_get_el(netgroup, SYSDB_ORIG_MEMBER_USER, &user_found); - sysdb_attrs_get_el(netgroup, SYSDB_ORIG_MEMBER_HOST, &host_found); -With netgroups, it is common to omit user or host from netgroup triple. -There is very high probability that realloc will be called. it is possible -pointer user_found can refer to the old area after the second call of function -sysdb_attrs_get_el. - -Resolves: -https://fedorahosted.org/sssd/ticket/2284 ---- - src/providers/ipa/ipa_netgroups.c | 17 +++++++---------- - 1 file changed, 7 insertions(+), 10 deletions(-) - -diff --git a/src/providers/ipa/ipa_netgroups.c b/src/providers/ipa/ipa_netgroups.c -index 49a4ba9ab60a05b31241916cf0a7669c785764d4..9cc374bc17eb53accaf607736a19555e17ebf4e1 100644 ---- a/src/providers/ipa/ipa_netgroups.c -+++ b/src/providers/ipa/ipa_netgroups.c -@@ -297,9 +297,7 @@ static void ipa_get_netgroups_process(struct tevent_req *subreq) - struct ipa_get_netgroups_state *state = tevent_req_data(req, - struct ipa_get_netgroups_state); - int i, ret; -- struct ldb_message_element *ng_found; -- struct ldb_message_element *host_found; -- struct ldb_message_element *user_found; -+ struct ldb_message_element *el; - struct sdap_search_base **netgr_bases; - struct sysdb_attrs **netgroups; - size_t netgroups_count; -@@ -345,16 +343,19 @@ static void ipa_get_netgroups_process(struct tevent_req *subreq) - - for (i = 0; i < netgroups_count; i++) { - ret = sysdb_attrs_get_el(netgroups[i], SYSDB_ORIG_NETGROUP_MEMBER, -- &ng_found); -+ &el); - if (ret != EOK) goto done; -+ if (el->num_values) state->entities_found |= ENTITY_NG; - - ret = sysdb_attrs_get_el(netgroups[i], SYSDB_ORIG_MEMBER_USER, -- &user_found); -+ &el); - if (ret != EOK) goto done; -+ if (el->num_values) state->entities_found |= ENTITY_USER; - - ret = sysdb_attrs_get_el(netgroups[i], SYSDB_ORIG_MEMBER_HOST, -- &host_found); -+ &el); - if (ret != EOK) goto done; -+ if (el->num_values) state->entities_found |= ENTITY_HOST; - - ret = sysdb_attrs_get_string(netgroups[i], SYSDB_ORIG_DN, &orig_dn); - if (ret != EOK) { -@@ -371,10 +372,6 @@ static void ipa_get_netgroups_process(struct tevent_req *subreq) - goto done; - } - -- if (ng_found->num_values) state->entities_found |= ENTITY_NG; -- if (user_found->num_values) state->entities_found |= ENTITY_USER; -- if (host_found->num_values) state->entities_found |= ENTITY_HOST; -- - if (state->entities_found == 0) { - continue; - } --- -1.8.5.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 new file mode 100644 index 0000000..00e13b8 --- /dev/null +++ b/SOURCES/0119-IPA-only-update-view-data-if-it-really-changed.patch @@ -0,0 +1,167 @@ +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-AD-connect-to-forest-root-when-downloading-the-list-.patch b/SOURCES/0120-AD-connect-to-forest-root-when-downloading-the-list-.patch deleted file mode 100644 index de10d29..0000000 --- a/SOURCES/0120-AD-connect-to-forest-root-when-downloading-the-list-.patch +++ /dev/null @@ -1,478 +0,0 @@ -From d97ff9abd276e9216e5868be37c3762d208b36c0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 1 Apr 2014 13:51:49 -0400 -Subject: [PATCH 120/120] AD: connect to forest root when downloading the list - of subdomains - -https://fedorahosted.org/sssd/ticket/2285 - -Only the forest root has the knowledge about all the domains in the forest, -the forest leaves only see themselves and the forest root. - -This patch switches to connecting to the forest root for downloading the -trusted domains instead of the server we are connected to. ---- - src/providers/ad/ad_subdomains.c | 372 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 363 insertions(+), 9 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 0d9652b5c615add47958cfdc61eba862a332ae4d..3c841788d5d88069d79a9438b72f57c8c2e0ffda 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -54,7 +54,9 @@ - * the same forest. See http://msdn.microsoft.com/en-us/library/cc223786.aspx - * for more information. - */ --#define SLAVE_DOMAIN_FILTER "(&(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*)))" -+#define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))" -+#define SLAVE_DOMAIN_FILTER "(&"SLAVE_DOMAIN_FILTER_BASE")" -+#define FOREST_ROOT_FILTER_FMT "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))" - - /* do not refresh more often than every 5 seconds for now */ - #define AD_SUBDOMAIN_REFRESH_LIMIT 5 -@@ -80,6 +82,11 @@ struct ad_subdomains_req_ctx { - char *current_filter; - size_t base_iter; - -+ struct ad_id_ctx *root_id_ctx; -+ struct sdap_id_op *root_op; -+ size_t root_base_iter; -+ struct sysdb_attrs *root_domain; -+ - size_t reply_count; - struct sysdb_attrs **reply; - -@@ -461,6 +468,7 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *ctx) - - static void ad_subdomains_get_conn_done(struct tevent_req *req); - static void ad_subdomains_master_dom_done(struct tevent_req *req); -+static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx); - static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx); - - static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx, -@@ -481,6 +489,10 @@ static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx, - req_ctx->sd_ctx = ctx; - req_ctx->current_filter = NULL; - req_ctx->base_iter = 0; -+ req_ctx->root_base_iter = 0; -+ req_ctx->root_id_ctx = NULL; -+ req_ctx->root_op = NULL; -+ req_ctx->root_domain = NULL; - req_ctx->reply_count = 0; - req_ctx->reply = NULL; - -@@ -575,7 +587,20 @@ static void ad_subdomains_master_dom_done(struct tevent_req *req) - goto done; - } - -- ret = ad_subdomains_get_slave(ctx); -+ if (strcasecmp(ctx->sd_ctx->be_ctx->domain->name, ctx->forest) != 0) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ ("SSSD needs to look up the forest root domain\n")); -+ ret = ad_subdomains_get_root(ctx); -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ ("Connected to forest root, looking up child domains..\n")); -+ -+ ctx->root_op = ctx->sdap_op; -+ ctx->root_id_ctx = ctx->sd_ctx->ad_id_ctx; -+ -+ ret = ad_subdomains_get_slave(ctx); -+ } -+ - if (ret == EAGAIN) { - return; - } else if (ret != EOK) { -@@ -586,6 +611,244 @@ done: - be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL); - } - -+static void ad_subdomains_get_root_domain_done(struct tevent_req *req); -+ -+static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx) -+{ -+ struct tevent_req *req; -+ struct sdap_search_base *base; -+ struct sdap_id_ctx *sdap_id_ctx; -+ char *filter; -+ const char *forest_root_attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER, -+ AD_AT_SID, AD_AT_TRUST_TYPE, -+ AD_AT_TRUST_ATTRS, NULL }; -+ -+ sdap_id_ctx = ctx->sd_ctx->sdap_id_ctx; -+ base = sdap_id_ctx->opts->sdom->search_bases[ctx->root_base_iter]; -+ if (base == NULL) { -+ return EOK; -+ } -+ -+ filter = talloc_asprintf(ctx, FOREST_ROOT_FILTER_FMT, ctx->forest); -+ if (filter == NULL) { -+ return ENOMEM; -+ } -+ -+ req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev, -+ sdap_id_ctx->opts, -+ sdap_id_op_handle(ctx->sdap_op), -+ base->basedn, LDAP_SCOPE_SUBTREE, -+ filter, forest_root_attrs, -+ NULL, 0, -+ dp_opt_get_int(sdap_id_ctx->opts->basic, -+ SDAP_SEARCH_TIMEOUT), -+ false); -+ -+ if (req == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n")); -+ return ENOMEM; -+ } -+ -+ tevent_req_set_callback(req, ad_subdomains_get_root_domain_done, ctx); -+ return EAGAIN; -+} -+ -+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); -+ -+static void ad_subdomains_get_root_domain_done(struct tevent_req *req) -+{ -+ int ret; -+ size_t reply_count; -+ struct sysdb_attrs **reply = NULL; -+ struct ad_subdomains_req_ctx *ctx; -+ int dp_error = DP_ERR_FATAL; -+ bool has_changes; -+ -+ ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx); -+ -+ ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply); -+ talloc_zfree(req); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n")); -+ goto fail; -+ } -+ -+ if (reply_count == 0) { -+ /* If no root domain was found in the default search base, try the -+ * next one, if available -+ */ -+ ctx->root_base_iter++; -+ ret = ad_subdomains_get_root(ctx); -+ if (ret == EAGAIN) { -+ return; -+ } -+ -+ goto fail; -+ } else if (reply_count > 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ ("Multiple results for root domain search, " -+ "domain list might be incomplete!\n")); -+ -+ ctx->root_op = ctx->sdap_op; -+ ctx->root_id_ctx = ctx->sd_ctx->ad_id_ctx; -+ -+ ret = ad_subdomains_get_slave(ctx); -+ if (ret == EAGAIN) { -+ return; -+ } -+ -+ goto fail; -+ } -+ /* Exactly one result, good. */ -+ -+ /* We won't use the operation to the local LDAP anymore, but -+ * read from the forest root -+ */ -+ ret = sdap_id_op_done(ctx->sdap_op, ret, &dp_error); -+ if (ret != EOK) { -+ 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 search the AD server: [%d](%s)\n", -+ ret, strerror(ret))); -+ } -+ goto fail; -+ } -+ -+ ret = ad_subdomains_refresh(ctx->sd_ctx, 1, reply, &has_changes); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("ad_subdomains_refresh failed.\n")); -+ goto fail; -+ } -+ -+ if (has_changes) { -+ ret = ad_subdom_reinit(ctx->sd_ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Could not reinitialize subdomains\n")); -+ goto fail; -+ } -+ } -+ -+ ctx->root_domain = reply[0]; -+ 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")); -+ ret = EFAULT; -+ goto fail; -+ } -+ -+ ctx->root_op = sdap_id_op_create(ctx, -+ ctx->root_id_ctx->ldap_ctx->conn_cache); -+ if (ctx->root_op == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed.\n")); -+ ret = ENOMEM; -+ goto fail; -+ } -+ -+ req = sdap_id_op_connect_send(ctx->root_op, ctx, &ret); -+ if (req == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_connect_send failed: %d(%s).\n", -+ ret, strerror(ret))); -+ goto fail; -+ } -+ -+ tevent_req_set_callback(req, ad_subdomains_root_conn_done, ctx); -+ return; -+ -+fail: -+ if (ret == EOK) { -+ ctx->sd_ctx->last_refreshed = time(NULL); -+ dp_error = DP_ERR_OK; -+ } -+ 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) -+{ -+ 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); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); -+ return NULL; -+ } -+ -+ /* With a subsequent run, the root should already be known */ -+ root = find_subdomain_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); -+ if (sdom == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Cannot get the sdom for %s!\n", root->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, -+ &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; -+ } -+ -+ return root_id_ctx; -+} -+ -+static void ad_subdomains_root_conn_done(struct tevent_req *req) -+{ -+ int ret; -+ int dp_error = DP_ERR_FATAL; -+ struct ad_subdomains_req_ctx *ctx; -+ -+ ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx); -+ -+ 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))); -+ } -+ -+ goto fail; -+ } -+ -+ ret = ad_subdomains_get_slave(ctx); -+ if (ret == EAGAIN) { -+ return; -+ } else if (ret != EOK) { -+ goto fail; -+ } -+ -+fail: -+ be_req_terminate(ctx->be_req, dp_error, ret, NULL); -+} -+ - static void ad_subdomains_get_slave_domain_done(struct tevent_req *req); - - static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx) -@@ -596,18 +859,18 @@ static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx) - AD_AT_SID, AD_AT_TRUST_TYPE, - AD_AT_TRUST_ATTRS, NULL }; - -- base = ctx->sd_ctx->sdap_id_ctx->opts->sdom->search_bases[ctx->base_iter]; -+ base = ctx->root_id_ctx->sdap_id_ctx->opts->sdom->search_bases[ctx->base_iter]; - if (base == NULL) { - return EOK; - } - - req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev, -- ctx->sd_ctx->sdap_id_ctx->opts, -- sdap_id_op_handle(ctx->sdap_op), -+ ctx->root_id_ctx->sdap_id_ctx->opts, -+ sdap_id_op_handle(ctx->root_op), - base->basedn, LDAP_SCOPE_SUBTREE, - SLAVE_DOMAIN_FILTER, slave_dom_attrs, - NULL, 0, -- dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic, -+ dp_opt_get_int(ctx->root_id_ctx->sdap_id_ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), - false); - -@@ -620,6 +883,68 @@ static errno_t ad_subdomains_get_slave(struct ad_subdomains_req_ctx *ctx) - return EAGAIN; - } - -+static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ size_t nsd, struct sysdb_attrs **sd, -+ struct sysdb_attrs *root, -+ size_t *_nsd_out, -+ struct sysdb_attrs ***_sd_out) -+{ -+ size_t i, sdi; -+ struct sysdb_attrs **sd_out; -+ const char *sd_name; -+ errno_t ret; -+ -+ if (root == NULL) { -+ /* We are connected directly to the root domain. The 'sd' -+ * list is complete and we can just use it -+ */ -+ *_nsd_out = nsd; -+ *_sd_out = sd; -+ return EOK; -+ } -+ -+ /* If we searched for root separately, we must: -+ * a) treat the root domain as a subdomain -+ * b) filter the subdomain we are connected to from the subdomain -+ * list, from our point of view, it's the master domain -+ */ -+ sd_out = talloc_zero_array(mem_ctx, struct sysdb_attrs *, nsd+1); -+ if (sd_out == NULL) { -+ return ENOMEM; -+ } -+ -+ sdi = 0; -+ for (i = 0; i < nsd; i++) { -+ ret = sysdb_attrs_get_string(sd[i], AD_AT_TRUST_PARTNER, &sd_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); -+ goto fail; -+ } -+ -+ if (strcasecmp(sd_name, domain->name) == 0) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ ("Not including primary domain %s in the subdomain list\n", -+ domain->name)); -+ continue; -+ } -+ -+ sd_out[sdi] = talloc_steal(sd_out, sd[i]); -+ sdi++; -+ } -+ -+ /* Now include the root */ -+ sd_out[sdi] = talloc_steal(sd_out, root); -+ -+ *_nsd_out = sdi+1; -+ *_sd_out = sd_out; -+ return EOK; -+ -+fail: -+ talloc_free(sd_out); -+ return ret; -+} -+ - static void ad_subdomains_get_slave_domain_done(struct tevent_req *req) - { - int ret; -@@ -628,6 +953,8 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req) - struct ad_subdomains_req_ctx *ctx; - int dp_error = DP_ERR_FATAL; - bool refresh_has_changes = false; -+ size_t nsubdoms; -+ struct sysdb_attrs **subdoms; - - ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx); - -@@ -653,13 +980,40 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req) - ctx->base_iter++; - ret = ad_subdomains_get_slave(ctx); - if (ret == EAGAIN) { -+ /* Search in progress */ -+ return; -+ } -+ -+ ret = sdap_id_op_done(ctx->root_op, ret, &dp_error); -+ if (ret != EOK) { -+ 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 search the AD server: [%d](%s)\n", -+ ret, strerror(ret))); -+ } -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Based on whether we are connected to the forest root or not, we might -+ * need to exclude the subdomain we are connected to from the list of -+ * subdomains -+ */ -+ ret = ad_subdomains_process(ctx, ctx->sd_ctx->be_ctx->domain, -+ ctx->reply_count, ctx->reply, -+ ctx->root_domain, &nsubdoms, &subdoms); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot process subdomain list\n")); -+ tevent_req_error(req, ret); - return; -- } else if (ret != EOK) { -- goto done; - } - - /* Got all the subdomains, let's process them */ -- ret = ad_subdomains_refresh(ctx->sd_ctx, ctx->reply_count, ctx->reply, -+ ret = ad_subdomains_refresh(ctx->sd_ctx, nsubdoms, subdoms, - &refresh_has_changes); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Failed to refresh subdomains.\n")); --- -1.9.0 - 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 new file mode 100644 index 0000000..8e91746 --- /dev/null +++ b/SOURCES/0120-krb5-do-not-fail-if-checking-the-old-ccache-failed.patch @@ -0,0 +1,53 @@ +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-IPA-Fix-SELinux-mapping-order-memory-hierarchy.patch b/SOURCES/0121-IPA-Fix-SELinux-mapping-order-memory-hierarchy.patch deleted file mode 100644 index e48bd0e..0000000 --- a/SOURCES/0121-IPA-Fix-SELinux-mapping-order-memory-hierarchy.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 1a088724c4d70edfbecab4252c1644100374f0f0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 2 Apr 2014 22:11:59 +0200 -Subject: [PATCH 121/121] IPA: Fix SELinux mapping order memory hierarchy - -https://fedorahosted.org/sssd/ticket/2300 - -The list of SELinux mapping orders was allocated on tmp_ctx and parsed -into an array. The array itself was correctly allocated on mem_ctx but -its contents remained on tmp_ctx, leading to a use-after-free error. -This patch fixes the memory hierarchy so that both the array and its -contents are allocated on mem_ctx. - -(cherry picked from commit 355b8a655cfcc4e783077d12f76b55da1d23fb87) - -Reviewed-by: Sumit Bose ---- - src/providers/ipa/ipa_selinux.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c -index 7f59161918a04ff8c994a0ce0fe55924ff09eda7..b7cbe445f1ecbfffaa84bb049aaf45ba4ecb1a35 100644 ---- a/src/providers/ipa/ipa_selinux.c -+++ b/src/providers/ipa/ipa_selinux.c -@@ -557,21 +557,15 @@ static errno_t create_order_array(TALLOC_CTX *mem_ctx, const char *map_order, - goto done; - } - -- order = talloc_strdup(tmp_ctx, map_order); -- if (order == NULL) { -- ret = ENOMEM; -- goto done; -- } -- len = strlen(order); -- - /* The "order" string contains one or more SELinux user records - * separated by $. Now we need to create an array of string from - * this one string. First find out how many elements in the array - * will be. This way only one alloc will be necessary for the array - */ - order_count = 1; -+ len = strlen(map_order); - for (i = 0; i < len; i++) { -- if (order[i] == '$') order_count++; -+ if (map_order[i] == '$') order_count++; - } - - order_array = talloc_array(tmp_ctx, char *, order_count); -@@ -580,6 +574,12 @@ static errno_t create_order_array(TALLOC_CTX *mem_ctx, const char *map_order, - goto done; - } - -+ order = talloc_strdup(order_array, map_order); -+ if (order == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ - /* Now fill the array with pointers to the original string. Also - * use binary zeros to make multiple string out of the one. - */ --- -1.9.0 - diff --git a/SOURCES/0121-test-avoid-leaks-in-leak-tests.patch b/SOURCES/0121-test-avoid-leaks-in-leak-tests.patch new file mode 100644 index 0000000..c7d226b --- /dev/null +++ b/SOURCES/0121-test-avoid-leaks-in-leak-tests.patch @@ -0,0 +1,57 @@ +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-AD-Do-not-remove-non-root-domains-when-looking-up-ro.patch b/SOURCES/0122-AD-Do-not-remove-non-root-domains-when-looking-up-ro.patch deleted file mode 100644 index 9247fdd..0000000 --- a/SOURCES/0122-AD-Do-not-remove-non-root-domains-when-looking-up-ro.patch +++ /dev/null @@ -1,89 +0,0 @@ -From a3877f8eb322be17f7d08d74ad3cf655b96219b5 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 13 May 2014 15:18:07 +0200 -Subject: [PATCH 122/124] AD: Do not remove non-root domains when looking up - root domain - -https://fedorahosted.org/sssd/ticket/2322 - -When the AD subdomains code looked up the root domain subsequently -(after the domain list was already populated), the non-root domains -might have been removed along with their respective tasks, because the -root domain lookup only ever matched a single root domain. - -This could cause havoc especially during login when different lookups -for different domains might be going on during user group refresh. ---- - src/providers/ad/ad_subdomains.c | 25 ++++++++++++++++++++++--- - 1 file changed, 22 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 3c841788d5d88069d79a9438b72f57c8c2e0ffda..ee04cbbe048e55666db22c48cf22c4c0241a0e3c 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -325,13 +325,15 @@ done: - } - - static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx, -- int count, struct sysdb_attrs **reply, -+ int count, bool root_domain, -+ struct sysdb_attrs **reply, - bool *changes) - { - struct sdap_domain *sdom; - struct sss_domain_info *domain, *dom; - bool handled[count]; - const char *value; -+ const char *root_name = NULL; - int c, h; - int ret; - bool enumerate; -@@ -340,10 +342,27 @@ static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx, - memset(handled, 0, sizeof(bool) * count); - h = 0; - -+ if (root_domain) { -+ ret = sysdb_attrs_get_string(reply[0], AD_AT_TRUST_PARTNER, -+ &root_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_string failed.\n")); -+ goto done; -+ } -+ } -+ - /* check existing subdomains */ - for (dom = get_next_domain(domain, true); - dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ - dom = get_next_domain(dom, false)) { -+ -+ /* If we are handling root domain, skip all the other domains. We don't -+ * want to accidentally remove non-root domains -+ */ -+ if (root_name && strcmp(root_name, dom->name) != 0) { -+ continue; -+ } -+ - for (c = 0; c < count; c++) { - if (handled[c]) { - continue; -@@ -719,7 +738,7 @@ static void ad_subdomains_get_root_domain_done(struct tevent_req *req) - goto fail; - } - -- ret = ad_subdomains_refresh(ctx->sd_ctx, 1, reply, &has_changes); -+ ret = ad_subdomains_refresh(ctx->sd_ctx, 1, true, reply, &has_changes); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("ad_subdomains_refresh failed.\n")); - goto fail; -@@ -1013,7 +1032,7 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req) - } - - /* Got all the subdomains, let's process them */ -- ret = ad_subdomains_refresh(ctx->sd_ctx, nsubdoms, subdoms, -+ ret = ad_subdomains_refresh(ctx->sd_ctx, nsubdoms, false, subdoms, - &refresh_has_changes); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Failed to refresh subdomains.\n")); --- -1.9.0 - diff --git a/SOURCES/0122-krb5-add-copy_ccache_into_memory.patch b/SOURCES/0122-krb5-add-copy_ccache_into_memory.patch new file mode 100644 index 0000000..256b98b --- /dev/null +++ b/SOURCES/0122-krb5-add-copy_ccache_into_memory.patch @@ -0,0 +1,441 @@ +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-AD-Provider-bug-fix-uninitialized-variable.patch b/SOURCES/0123-AD-Provider-bug-fix-uninitialized-variable.patch deleted file mode 100644 index 0649862..0000000 --- a/SOURCES/0123-AD-Provider-bug-fix-uninitialized-variable.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 400c06ebd99bfa447d0f88228320224291c862e0 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Fri, 25 Apr 2014 13:26:19 +0100 -Subject: [PATCH 123/124] AD Provider: bug-fix uninitialized variable - -ad_subdomains_refresh() always set value to output parameter 'changes' if EOK is returned. - -Reviewed-by: Sumit Bose -(cherry picked from commit cef2384a3a6fc1a1637c6a55e2bced93d28e8fca) ---- - 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 ee04cbbe048e55666db22c48cf22c4c0241a0e3c..ef3bb50e83fc8e39b91922d6fc9646dfe6da58a3 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -423,6 +423,7 @@ static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx, - if (count == h) { - /* all domains were already accounted for and have been updated */ - ret = EOK; -+ *changes = false; - goto done; - } - -@@ -682,7 +683,7 @@ static void ad_subdomains_get_root_domain_done(struct tevent_req *req) - struct sysdb_attrs **reply = NULL; - struct ad_subdomains_req_ctx *ctx; - int dp_error = DP_ERR_FATAL; -- bool has_changes; -+ bool has_changes = false; - - ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx); - --- -1.9.0 - diff --git a/SOURCES/0123-krb5-add-copy_keytab_into_memory.patch b/SOURCES/0123-krb5-add-copy_keytab_into_memory.patch new file mode 100644 index 0000000..6a9f46f --- /dev/null +++ b/SOURCES/0123-krb5-add-copy_keytab_into_memory.patch @@ -0,0 +1,484 @@ +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-AD-Provider-bugfix-use-after-free.patch b/SOURCES/0124-AD-Provider-bugfix-use-after-free.patch deleted file mode 100644 index e10c4b9..0000000 --- a/SOURCES/0124-AD-Provider-bugfix-use-after-free.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 25193cfe110b328b428cde9641400f7dc999416e Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Fri, 25 Apr 2014 14:42:39 +0100 -Subject: [PATCH 124/124] AD Provider: bugfix use-after-free - -Resolves: -https://fedorahosted.org/sssd/ticket/2322 - -Reviewed-by: Sumit Bose -(cherry picked from commit ed61bfc5184d9c7a46d17681a22a1abb64423708) ---- - src/providers/data_provider_be.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c -index 37b687f25810447c08c6e0c6e8da4f64c99a5f5f..f85c63065252b24d4eeec0d2671ab0a1a16d4b9a 100644 ---- a/src/providers/data_provider_be.c -+++ b/src/providers/data_provider_be.c -@@ -210,7 +210,8 @@ void be_req_terminate(struct be_req *be_req, - void be_terminate_domain_requests(struct be_ctx *be_ctx, - const char *domain) - { -- struct be_req *be_req = NULL; -+ struct be_req *be_req; -+ struct be_req *next_be_req; - - DEBUG(SSSDBG_TRACE_FUNC, ("Terminating requests for domain [%s]\n", - domain)); -@@ -220,11 +221,15 @@ void be_terminate_domain_requests(struct be_ctx *be_ctx, - return; - } - -- DLIST_FOR_EACH(be_req, be_ctx->active_requests) { -+ be_req = be_ctx->active_requests; -+ while (be_req) { -+ /* save pointer to next request in case be_req will be freed */ -+ next_be_req = be_req->next; - if (strcmp(domain, be_req->domain->name) == 0) { - be_req_terminate(be_req, DP_ERR_FATAL, ERR_DOMAIN_NOT_FOUND, - sss_strerror(ERR_DOMAIN_NOT_FOUND)); - } -+ be_req = next_be_req; - } - } - --- -1.9.0 - 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 new file mode 100644 index 0000000..27ea1c3 --- /dev/null +++ b/SOURCES/0124-ldap_child-copy-keytab-into-memory-to-drop-privilege.patch @@ -0,0 +1,159 @@ +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-ipa-subdomains-provider-make-sure-search-by-SID-work.patch b/SOURCES/0125-ipa-subdomains-provider-make-sure-search-by-SID-work.patch deleted file mode 100644 index 80cd52c..0000000 --- a/SOURCES/0125-ipa-subdomains-provider-make-sure-search-by-SID-work.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 503e1ebb9c36ecb978a28a5cefd94d24945ee39b Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 13 May 2014 11:22:29 +0300 -Subject: [PATCH 125/126] ipa subdomains provider: make sure search by SID - works for homedir - -Reviewed-by: Jakub Hrozek ---- - src/providers/ipa/ipa_subdomains_id.c | 20 +++++++++++++++----- - 1 file changed, 15 insertions(+), 5 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 978ccc261d7525662e835b867044b6a5238a29df..d8922a461fc1cbbec4bb65b8cd6e6cf25f2dc605 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -484,7 +484,11 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - uint32_t uid; - const char *fqname; - const char *homedir = NULL; -- struct ldb_result *res; -+ struct ldb_result *res = NULL; -+ struct ldb_message *msg = NULL; -+ const char *attrs[] = { SYSDB_NAME, -+ SYSDB_UIDNUM, -+ NULL }; - - if (filter_type == BE_FILTER_NAME) { - ret = sysdb_getpwnam(mem_ctx, dom->sysdb, dom, filter_value, &res); -@@ -496,6 +500,9 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - goto done; - } - ret = sysdb_getpwuid(mem_ctx, dom->sysdb, dom, uid, &res); -+ } else if (filter_type == BE_FILTER_SECID) { -+ ret = sysdb_search_user_by_sid_str(mem_ctx, dom->sysdb, dom, -+ filter_value, attrs, &msg); - } else { - DEBUG(SSSDBG_OP_FAILURE, - ("Unsupported filter type: [%d].\n", filter_type)); -@@ -503,24 +510,27 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - 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))); - goto done; - } - -- if (res->count == 0) { -+ if ((res && res->count == 0) || (msg && msg->num_elements == 0)) { - ret = ENOENT; - goto done; - } - -+ if (res != NULL) { -+ msg = res->msgs[0]; -+ } - /* - * Homedir is always overriden by subdomain_homedir even if it was - * explicitly set by user. - */ -- fqname = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL); -- uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0); -+ fqname = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -+ uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0); - if (uid == 0) { - DEBUG(SSSDBG_OP_FAILURE, ("UID for user [%s] is not known.\n", - filter_value)); --- -1.9.0 - diff --git a/SOURCES/0125-krb5_child-become-user-earlier.patch b/SOURCES/0125-krb5_child-become-user-earlier.patch new file mode 100644 index 0000000..6a5fd92 --- /dev/null +++ b/SOURCES/0125-krb5_child-become-user-earlier.patch @@ -0,0 +1,249 @@ +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 new file mode 100644 index 0000000..3abf8a0 --- /dev/null +++ b/SOURCES/0126-TESTS-Basic-child-tests.patch @@ -0,0 +1,314 @@ +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/0126-tests-Remove-tests-that-check-creating-public-direct.patch b/SOURCES/0126-tests-Remove-tests-that-check-creating-public-direct.patch deleted file mode 100644 index e75778e..0000000 --- a/SOURCES/0126-tests-Remove-tests-that-check-creating-public-direct.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 43dc5617a037f60e4560cb33c050815e03ccdff0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 7 Jan 2014 10:43:55 +0100 -Subject: [PATCH 126/126] tests: Remove tests that check creating public - directories - -The functionality was removed, but we forgot to remove the corresponding -tests, mostly because these tests were only ever ran as root. ---- - src/tests/krb5_utils-tests.c | 121 ------------------------------------------- - 1 file changed, 121 deletions(-) - -diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c -index 3e0c607a58b9ff0840a93867c1ad61cc5a2ae665..11fe1d749dccb5d367e3840ebc0a396b992bce2a 100644 ---- a/src/tests/krb5_utils-tests.c -+++ b/src/tests/krb5_utils-tests.c -@@ -91,124 +91,6 @@ static void check_dir(const char *dirname, uid_t uid, gid_t gid, mode_t mode) - mode, (stat_buf.st_mode & ~S_IFMT)); - } - --START_TEST(test_pub_ccache_dir) --{ -- int ret; -- char *cwd; -- char *testpath; -- char *dirname; -- char *subdirname; -- char *filename; -- -- fail_unless(getuid() == 0, "This test must be run as root."); -- -- cwd = getcwd(NULL, 0); -- fail_unless(cwd != NULL, "getcwd failed."); -- -- testpath = talloc_asprintf(tmp_ctx, "%s/%s", cwd, TESTS_PATH); -- free(cwd); -- fail_unless(testpath != NULL, "talloc_asprintf failed."); -- dirname = talloc_asprintf(tmp_ctx, "%s/pub_ccdir", testpath); -- fail_unless(dirname != NULL, "talloc_asprintf failed."); -- subdirname = talloc_asprintf(tmp_ctx, "%s/subdir", dirname); -- fail_unless(subdirname != NULL, "talloc_asprintf failed."); -- filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname); -- fail_unless(filename != NULL, "talloc_asprintf failed."); -- -- ret = chmod(testpath, 0754); -- fail_unless(ret == EOK, "chmod failed."); -- ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345); -- fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL " -- "while x-bit is missing."); -- -- ret = chmod(testpath, 0755); -- fail_unless(ret == EOK, "chmod failed."); -- ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345); -- fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed."); -- -- check_dir(subdirname, 0, 0, 01777); -- RMDIR(subdirname); -- check_dir(dirname, 0, 0, 0755); -- RMDIR(dirname); --} --END_TEST -- --START_TEST(test_pub_ccache_dir_in_user_dir) --{ -- int ret; -- char *cwd; -- char *dirname; -- char *subdirname; -- char *filename; -- -- fail_unless(getuid() == 0, "This test must be run as root."); -- -- cwd = getcwd(NULL, 0); -- fail_unless(cwd != NULL, "getcwd failed."); -- -- dirname = talloc_asprintf(tmp_ctx, "%s/%s/pub_ccdir", cwd, TESTS_PATH); -- free(cwd); -- fail_unless(dirname != NULL, "talloc_asprintf failed."); -- ret = mkdir(dirname, 0700); -- fail_unless(ret == EOK, "mkdir failed.\n"); -- ret = chown(dirname, 12345, 12345); -- fail_unless(ret == EOK, "chown failed.\n"); -- subdirname = talloc_asprintf(tmp_ctx, "%s/subdir", dirname); -- fail_unless(subdirname != NULL, "talloc_asprintf failed."); -- filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdirname); -- fail_unless(filename != NULL, "talloc_asprintf failed."); -- -- ret = sss_krb5_precreate_ccache(filename, NULL, 12345, 12345); -- fail_unless(ret == EINVAL, "Creating public ccache dir in user dir " -- "does not failed with EINVAL."); -- -- RMDIR(dirname); --} --END_TEST -- --START_TEST(test_priv_ccache_dir) --{ -- int ret; -- char *cwd; -- char *testpath; -- char *dirname; -- char *subdir; -- char *filename; -- uid_t uid = 12345; -- gid_t gid = 12345; -- -- fail_unless(getuid() == 0, "This test must be run as root."); -- -- cwd = getcwd(NULL, 0); -- fail_unless(cwd != NULL, "getcwd failed."); -- -- testpath = talloc_asprintf(tmp_ctx, "%s/%s", cwd, TESTS_PATH); -- free(cwd); -- fail_unless(testpath != NULL, "talloc_asprintf failed."); -- dirname = talloc_asprintf(tmp_ctx, "%s/base", testpath); -- subdir = talloc_asprintf(tmp_ctx, "%s/priv_ccdir", dirname); -- fail_unless(subdir != NULL, "talloc_asprintf failed."); -- filename = talloc_asprintf(tmp_ctx, "%s/ccfile", subdir); -- fail_unless(filename != NULL, "talloc_asprintf failed."); -- -- ret = chmod(testpath, 0754); -- fail_unless(ret == EOK, "chmod failed."); -- ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid); -- fail_unless(ret == EINVAL, "sss_krb5_precreate_ccache does not return EINVAL " -- "while x-bit is missing."); -- -- ret = chmod(testpath, 0755); -- fail_unless(ret == EOK, "chmod failed."); -- ret = sss_krb5_precreate_ccache(filename, NULL, uid, gid); -- fail_unless(ret == EOK, "sss_krb5_precreate_ccache failed."); -- -- check_dir(subdir, uid, gid, 0700); -- RMDIR(subdir); -- check_dir(dirname, 0, 0, 0755); -- RMDIR(dirname); --} --END_TEST -- - START_TEST(test_private_ccache_dir_in_user_dir) - { - int ret; -@@ -736,10 +618,7 @@ Suite *krb5_utils_suite (void) - tcase_add_test (tc_create_dir, test_illegal_patterns); - tcase_add_test (tc_create_dir, test_cc_dir_create); - if (getuid() == 0) { -- tcase_add_test (tc_create_dir, test_priv_ccache_dir); - tcase_add_test (tc_create_dir, test_private_ccache_dir_in_user_dir); -- tcase_add_test (tc_create_dir, test_pub_ccache_dir); -- tcase_add_test (tc_create_dir, test_pub_ccache_dir_in_user_dir); - tcase_add_test (tc_create_dir, test_private_ccache_dir_in_wrong_user_dir); - } else { - printf("Run as root to enable more tests.\n"); --- -1.9.0 - diff --git a/SOURCES/0127-Add-extra_args-to-exec_child.patch b/SOURCES/0127-Add-extra_args-to-exec_child.patch new file mode 100644 index 0000000..7ab2f55 --- /dev/null +++ b/SOURCES/0127-Add-extra_args-to-exec_child.patch @@ -0,0 +1,287 @@ +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/0127-IPA-handle-searches-by-SID-in-apply_subdomain_homedi.patch b/SOURCES/0127-IPA-handle-searches-by-SID-in-apply_subdomain_homedi.patch deleted file mode 100644 index de65245..0000000 --- a/SOURCES/0127-IPA-handle-searches-by-SID-in-apply_subdomain_homedi.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 5ecab6dc08ac35a400e067af09b49e7fcb0f17c0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 12 Aug 2014 10:32:33 +0200 -Subject: [PATCH 127/130] IPA: handle searches by SID in - apply_subdomain_homedir -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2391 - -apply_subdomain_homedir() didn't handle the situation where an entity -that doesn't match was requested from the cache. For user and group -lookups this wasn't a problem because the negative match was caught -sooner. - -But SID lookups can match either user or group. When a group SID was -requested, the preceding LDAP request matched the SID and stored the -group in the cache. Then apply_subdomain_homedir() only tried to search -user by SID, didn't find the entry and accessed a NULL pointer. - -A simple reproducer is: -$ python ->>> import pysss_nss_idmap ->>> pysss_nss_idmap.getnamebysid(group_sid) - -The group_sid can be anything, including Domain Users (XXX-513) - -Reviewed-by: Michal Židek -(cherry picked from commit 82347f452febe3cbffc36b0a3308ffb462515442) ---- - src/providers/ipa/ipa_subdomains_id.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index d8922a461fc1cbbec4bb65b8cd6e6cf25f2dc605..5517602a6e9c7d56406e42aa3afbd2527e2df7ea 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -492,6 +492,9 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - - if (filter_type == BE_FILTER_NAME) { - ret = sysdb_getpwnam(mem_ctx, dom->sysdb, dom, filter_value, &res); -+ if (res && res->count == 0) { -+ ret = ENOENT; -+ } - } else if (filter_type == BE_FILTER_IDNUM) { - errno = 0; - uid = strtouint32(filter_value, NULL, 10); -@@ -500,6 +503,9 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - goto done; - } - ret = sysdb_getpwuid(mem_ctx, dom->sysdb, dom, uid, &res); -+ if (res && res->count == 0) { -+ ret = ENOENT; -+ } - } else if (filter_type == BE_FILTER_SECID) { - ret = sysdb_search_user_by_sid_str(mem_ctx, dom->sysdb, dom, - filter_value, attrs, &msg); -@@ -515,10 +521,9 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, - ("Failed to make request to our cache: [%d]: [%s]\n", - ret, sss_strerror(ret))); - goto done; -- } -- -- if ((res && res->count == 0) || (msg && msg->num_elements == 0)) { -- ret = ENOENT; -+ } else if (ret == ENOENT) { -+ DEBUG(SSSDBG_TRACE_FUNC, ("Cannot find [%s] with search type [%d]\n", -+ filter_value, filter_type)); - goto done; - } - --- -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 new file mode 100644 index 0000000..674badb --- /dev/null +++ b/SOURCES/0128-KRB5-Create-the-fast-ccache-in-a-child-process.patch @@ -0,0 +1,240 @@ +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/0128-LDAP-Ignore-returned-referrals-if-referral-support-i.patch b/SOURCES/0128-LDAP-Ignore-returned-referrals-if-referral-support-i.patch deleted file mode 100644 index 3069a3b..0000000 --- a/SOURCES/0128-LDAP-Ignore-returned-referrals-if-referral-support-i.patch +++ /dev/null @@ -1,82 +0,0 @@ -From b224c49b8f0a9cdf343a443fdf2190dc6f047508 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 20 Aug 2014 14:00:38 +0200 -Subject: [PATCH 128/130] LDAP: Ignore returned referrals if referral support - is disabled - -Reviewed-by: Pavel Reichl -(cherry picked from commit a2ea3f5d9ef9f17efbb61e942c2bc6cff7d1ebf2) ---- - src/providers/ldap/sdap_async.c | 18 +++++++++++++++--- - src/util/util_errors.c | 1 + - src/util/util_errors.h | 2 ++ - 3 files changed, 18 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c -index 1022a093f06ec7e9a50b13160fc9a4660a255e92..7db01d979ee81a3707126a4c3eb1f36006e8b392 100644 ---- a/src/providers/ldap/sdap_async.c -+++ b/src/providers/ldap/sdap_async.c -@@ -1404,6 +1404,10 @@ static void sdap_get_generic_ext_done(struct sdap_op *op, - ldap_memfree(errmsg); - tevent_req_error(req, ENOTSUP); - return; -+ } else if (result == LDAP_REFERRAL) { -+ ldap_memfree(errmsg); -+ tevent_req_error(req, ERR_REFERRAL); -+ return; - } else if (result != LDAP_SUCCESS && result != LDAP_NO_SUCH_OBJECT) { - DEBUG(SSSDBG_OP_FAILURE, - ("Unexpected result from ldap: %s(%d), %s\n", -@@ -1565,13 +1569,21 @@ 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); - int ret; - - ret = sdap_get_generic_ext_recv(subreq); - talloc_zfree(subreq); -- if (ret) { -- DEBUG(4, ("sdap_get_generic_ext_recv failed [%d]: %s\n", -- ret, sss_strerror(ret))); -+ if (ret == ERR_REFERRAL) { -+ if (dp_opt_get_bool(state->opts->basic, SDAP_REFERRALS)) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ } else if (ret) { -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ ("sdap_get_generic_ext_recv failed [%d]: %s\n", -+ ret, sss_strerror(ret))); - tevent_req_error(req, ret); - return; - } -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index c9b507557da07555c719bb0dd18145e6799a53eb..eb7b1aec7b388e2509471cce8322cf38f9388151 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -53,6 +53,7 @@ struct err_string error_to_str[] = { - { "Missing configuration file" }, /* ERR_MISSING_CONF */ - { "Malformed search filter" }, /* ERR_INVALID_FILTER, */ - { "No POSIX attributes detected" }, /* ERR_NO_POSIX */ -+ { "LDAP search returned a referral" }, /* ERR_REFERRAL */ - }; - - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index 3dd94af1f304d65e22515c859c6f69a021fa7e92..2858311dec90ae0ea57dbcd7b6de4beb9fb19c50 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -75,6 +75,8 @@ enum sssd_errors { - ERR_MISSING_CONF, - ERR_INVALID_FILTER, - ERR_NO_POSIX, -+ ERR_NO_SYSBUS, -+ ERR_REFERRAL, - ERR_LAST /* ALWAYS LAST */ - }; - --- -1.9.3 - diff --git a/SOURCES/0129-Ignore-referrals-in-deref-and-ASQ-too.patch b/SOURCES/0129-Ignore-referrals-in-deref-and-ASQ-too.patch deleted file mode 100644 index c2da9d5..0000000 --- a/SOURCES/0129-Ignore-referrals-in-deref-and-ASQ-too.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 5b5cb000d63c3edad40ebb420776df2a18950fcb Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 10 Sep 2014 11:55:24 +0200 -Subject: [PATCH 129/130] Ignore referrals in deref and ASQ, too -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek ---- - src/providers/ldap/sdap_async.c | 20 ++++++++++++++++++-- - 1 file changed, 18 insertions(+), 2 deletions(-) - -diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c -index 7db01d979ee81a3707126a4c3eb1f36006e8b392..b06d94bfd9d1a60f587de5c807389c74f908af5e 100644 ---- a/src/providers/ldap/sdap_async.c -+++ b/src/providers/ldap/sdap_async.c -@@ -1622,6 +1622,7 @@ static errno_t sdap_x_deref_parse_entry(struct sdap_handle *sh, - struct sdap_x_deref_search_state { - struct sdap_handle *sh; - struct sdap_op *op; -+ struct sdap_options *opts; - struct sdap_attr_map_info *maps; - LDAPControl **ctrls; - -@@ -1647,6 +1648,7 @@ sdap_x_deref_search_send(TALLOC_CTX *memctx, struct tevent_context *ev, - state->sh = sh; - state->maps = maps; - state->op = NULL; -+ state->opts = opts; - state->num_maps = num_maps; - state->ctrls = talloc_zero_array(state, LDAPControl *, 2); - if (state->ctrls == NULL) { -@@ -1797,11 +1799,18 @@ static void sdap_x_deref_search_done(struct tevent_req *subreq) - { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); -+ struct sdap_x_deref_search_state *state = tevent_req_data(req, -+ struct sdap_x_deref_search_state); - int ret; - - ret = sdap_get_generic_ext_recv(subreq); - talloc_zfree(subreq); -- if (ret) { -+ if (ret == ERR_REFERRAL) { -+ if (dp_opt_get_bool(state->opts->basic, SDAP_REFERRALS)) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ } else if (ret) { - DEBUG(4, ("sdap_get_generic_ext_recv failed [%d]: %s\n", - ret, sss_strerror(ret))); - tevent_req_error(req, ret); -@@ -2056,11 +2065,18 @@ static void sdap_asq_search_done(struct tevent_req *subreq) - { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); -+ struct sdap_asq_search_state *state = -+ tevent_req_data(req, struct sdap_asq_search_state); - int ret; - - ret = sdap_get_generic_ext_recv(subreq); - talloc_zfree(subreq); -- if (ret) { -+ if (ret == ERR_REFERRAL) { -+ if (dp_opt_get_bool(state->opts->basic, SDAP_REFERRALS)) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ } else if (ret) { - DEBUG(4, ("sdap_get_generic_ext_recv failed [%d]: %s\n", - ret, sss_strerror(ret))); - tevent_req_error(req, ret); --- -1.9.3 - diff --git a/SOURCES/0129-KRB5-Relax-DEBUG-message.patch b/SOURCES/0129-KRB5-Relax-DEBUG-message.patch new file mode 100644 index 0000000..27115e4 --- /dev/null +++ b/SOURCES/0129-KRB5-Relax-DEBUG-message.patch @@ -0,0 +1,31 @@ +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 new file mode 100644 index 0000000..3ceebcd --- /dev/null +++ b/SOURCES/0130-IPA-Do-not-append-domain-name-to-fq-name.patch @@ -0,0 +1,61 @@ +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/0130-IPA-Use-GC-for-group-lookups-in-server-mode.patch b/SOURCES/0130-IPA-Use-GC-for-group-lookups-in-server-mode.patch deleted file mode 100644 index b42b8e4..0000000 --- a/SOURCES/0130-IPA-Use-GC-for-group-lookups-in-server-mode.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 756a944b898e55a83c212999b31ba6550af4b1ce Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 9 Sep 2014 22:13:52 +0200 -Subject: [PATCH 130/130] IPA: Use GC for group lookups in server mode - -https://fedorahosted.org/sssd/ticket/2412 - -Even though AD trusts often work with POSIX attributes which are -normally not replicated to GC, our group lookups are smart since commit -008e1ee835602023891ac45408483d87f41e4d5c and look up the group itself using -the LDAP connection and only use the GC connection to look up the members. - -Reviewed-by: Pavel Reichl -(cherry picked from commit a20ce8cd43d72c89e2ea1d65aefe24ba270f040f) ---- - src/providers/ipa/ipa_subdomains_id.c | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 5517602a6e9c7d56406e42aa3afbd2527e2df7ea..9a90bc2d68561ce518bd31d74ec010c697036352 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -304,17 +304,21 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, - } - sdap_id_ctx = ad_id_ctx->sdap_id_ctx; - -- /* Currently only LDAP port for AD is used because POSIX -- * attributes are not replicated to GC by default -+ /* We read users and groups from GC. From groups, we may switch to -+ * using LDAP connection in the group request itself, but in order -+ * to resolve Universal group memberships, we also need the GC -+ * connection - */ -- -- if ((state->ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_INITGROUPS) { -+ 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); - if (clist == NULL) { - ret = ENOMEM; - goto fail; - } -- } else { -+ break; -+ default: - clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2); - if (clist == NULL) { - ret = ENOMEM; --- -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 new file mode 100644 index 0000000..8611b93 --- /dev/null +++ b/SOURCES/0131-TESTS-Build-test_child-even-without-cmocka.patch @@ -0,0 +1,35 @@ +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 new file mode 100644 index 0000000..7281024 --- /dev/null +++ b/SOURCES/0132-sss_client-Work-around-glibc-bug.patch @@ -0,0 +1,82 @@ +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 new file mode 100644 index 0000000..6a4159d --- /dev/null +++ b/SOURCES/0133-Skip-CHAUTHTOK_PRELIM-when-using-OTPs.patch @@ -0,0 +1,186 @@ +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 new file mode 100644 index 0000000..bda512e --- /dev/null +++ b/SOURCES/0134-PAM-Domain-names-are-case-insensitive.patch @@ -0,0 +1,39 @@ +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 new file mode 100644 index 0000000..1217bed --- /dev/null +++ b/SOURCES/0135-PAM-Missing-argument-to-domains-should-fail-auth.patch @@ -0,0 +1,36 @@ +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 new file mode 100644 index 0000000..2b12fba --- /dev/null +++ b/SOURCES/0136-MAN-Misspelled-username-in-pam_trusted_users-is-not-.patch @@ -0,0 +1,37 @@ +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 new file mode 100644 index 0000000..807e319 --- /dev/null +++ b/SOURCES/0137-RESPONDER-Log-failures-to-resolve-user-names-in-csv_.patch @@ -0,0 +1,33 @@ +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 new file mode 100644 index 0000000..d1cbfc6 --- /dev/null +++ b/SOURCES/0138-KRB5-Check-FAST-kinit-errors-using-get_tgt_times.patch @@ -0,0 +1,77 @@ +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 new file mode 100644 index 0000000..cba3d15 --- /dev/null +++ b/SOURCES/0139-MAN-Clarify-ad_gpo_map-options.patch @@ -0,0 +1,43 @@ +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 new file mode 100644 index 0000000..c4e5f68 --- /dev/null +++ b/SOURCES/0140-krb5_child-Initialize-REALM-earlier.patch @@ -0,0 +1,67 @@ +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 new file mode 100644 index 0000000..07a6408 --- /dev/null +++ b/SOURCES/0141-TESTS-sysdb_delete_by_sid-test-return-value.patch @@ -0,0 +1,63 @@ +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 new file mode 100644 index 0000000..9267d53 --- /dev/null +++ b/SOURCES/0142-NSS-nss_cmd_getbysid_search-return-ENOENT.patch @@ -0,0 +1,45 @@ +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 new file mode 100644 index 0000000..6cd2d4f --- /dev/null +++ b/SOURCES/0143-SYSDB-sysdb_search_object_by_sid-returns-ENOENT.patch @@ -0,0 +1,249 @@ +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 new file mode 100644 index 0000000..6301175 --- /dev/null +++ b/SOURCES/0144-handle-KRB5KRB_ERR_GENERIC-as-unspecific-error.patch @@ -0,0 +1,54 @@ +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 new file mode 100644 index 0000000..37f9d78 --- /dev/null +++ b/SOURCES/0145-IPA-verify-group-memberships-of-trusted-domain-users.patch @@ -0,0 +1,215 @@ +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 new file mode 100644 index 0000000..bfc5abf --- /dev/null +++ b/SOURCES/0146-IPA-properly-handle-groups-from-different-domains.patch @@ -0,0 +1,51 @@ +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 new file mode 100644 index 0000000..ddb3499 --- /dev/null +++ b/SOURCES/0147-LDAP-retain-external-members.patch @@ -0,0 +1,261 @@ +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 new file mode 100644 index 0000000..fd32d86 --- /dev/null +++ b/SOURCES/0148-IPA-do-not-try-to-add-override-gid-twice.patch @@ -0,0 +1,42 @@ +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 new file mode 100644 index 0000000..465ac9e --- /dev/null +++ b/SOURCES/0149-IPA-handle-GID-overrides-for-MPG-domains-on-clients.patch @@ -0,0 +1,62 @@ +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 new file mode 100644 index 0000000..1fffdb9 --- /dev/null +++ b/SOURCES/0150-simple-access-provider-non-existing-object.patch @@ -0,0 +1,96 @@ +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 new file mode 100644 index 0000000..6bcb02d --- /dev/null +++ b/SOURCES/0151-libwbclient-initialize-some-return-values.patch @@ -0,0 +1,101 @@ +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 new file mode 100644 index 0000000..f951b5c --- /dev/null +++ b/SOURCES/0152-GPO-Ignore-ENOENT-result-from-sysdb_gpo_get_gpo_resu.patch @@ -0,0 +1,37 @@ +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 new file mode 100644 index 0000000..1af59b9 --- /dev/null +++ b/SOURCES/0153-GPO-Set-libsmb-debugging-to-stderr.patch @@ -0,0 +1,34 @@ +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 new file mode 100644 index 0000000..d0888b1 --- /dev/null +++ b/SOURCES/0154-UTIL-Allow-dup-ing-child-pipe-to-a-different-FD.patch @@ -0,0 +1,193 @@ +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 new file mode 100644 index 0000000..7eefa07 --- /dev/null +++ b/SOURCES/0155-GPO-Don-t-use-stdout-for-output-in-gpo_child.patch @@ -0,0 +1,92 @@ +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 new file mode 100644 index 0000000..16bdd8f --- /dev/null +++ b/SOURCES/0156-GPO-Extract-server-hostname-after-connecting.patch @@ -0,0 +1,111 @@ +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 new file mode 100644 index 0000000..a76ed19 --- /dev/null +++ b/SOURCES/0157-IPA-add-get_be_acct_req_for_user_name.patch @@ -0,0 +1,64 @@ +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 new file mode 100644 index 0000000..2ef66f7 --- /dev/null +++ b/SOURCES/0158-IPA-resolve-ghost-members-if-a-non-default-view-is-a.patch @@ -0,0 +1,288 @@ +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 new file mode 100644 index 0000000..1e1b376 --- /dev/null +++ b/SOURCES/0159-sysdb-fix-group-members-with-overridden-names.patch @@ -0,0 +1,144 @@ +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 new file mode 100644 index 0000000..d025570 --- /dev/null +++ b/SOURCES/0160-IPA-ipa_resolve_user_list_send-take-care-of-override.patch @@ -0,0 +1,89 @@ +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 new file mode 100644 index 0000000..bd6c53b --- /dev/null +++ b/SOURCES/0161-IPA-do-not-look-up-overrides-on-client-with-default-.patch @@ -0,0 +1,154 @@ +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 new file mode 100644 index 0000000..11be584 --- /dev/null +++ b/SOURCES/0162-IPA-make-version-check-more-precise.patch @@ -0,0 +1,41 @@ +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 new file mode 100644 index 0000000..0be9ae7 --- /dev/null +++ b/SOURCES/0163-IPA-add-missing-break.patch @@ -0,0 +1,29 @@ +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 new file mode 100644 index 0000000..c121189 --- /dev/null +++ b/SOURCES/0164-IPA-process_members-optionally-return-missing-member.patch @@ -0,0 +1,154 @@ +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 new file mode 100644 index 0000000..c0ac0e6 --- /dev/null +++ b/SOURCES/0165-IPA-rename-ipa_s2n_get_groups_send-to-ipa_s2n_get_fq.patch @@ -0,0 +1,304 @@ +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 new file mode 100644 index 0000000..205d27f --- /dev/null +++ b/SOURCES/0166-IPA-resolve-missing-members.patch @@ -0,0 +1,137 @@ +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 new file mode 100644 index 0000000..a0f093b --- /dev/null +++ b/SOURCES/0167-IPA-set-SYSDB_INITGR_EXPIRE-for-RESP_USER_GROUPLIST.patch @@ -0,0 +1,42 @@ +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 new file mode 100644 index 0000000..b52cb4d --- /dev/null +++ b/SOURCES/0168-krb5_child-Return-ERR_NETWORK_IO-on-KRB5_KDCREP_SKEW.patch @@ -0,0 +1,28 @@ +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 new file mode 100644 index 0000000..6abefe7 --- /dev/null +++ b/SOURCES/0169-krb5-fix-entry-order-in-MEMORY-keytab.patch @@ -0,0 +1,203 @@ +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 new file mode 100644 index 0000000..e823d9d --- /dev/null +++ b/SOURCES/0170-nss-make-fill_orig-multi-value-aware.patch @@ -0,0 +1,301 @@ +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 new file mode 100644 index 0000000..1b3ecbe --- /dev/null +++ b/SOURCES/0171-nss-refactor-fill_orig.patch @@ -0,0 +1,184 @@ +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 new file mode 100644 index 0000000..0c1ed1c --- /dev/null +++ b/SOURCES/0172-nss-Add-original-DN-and-memberOf-to-origbyname-reque.patch @@ -0,0 +1,57 @@ +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 new file mode 100644 index 0000000..a78837d --- /dev/null +++ b/SOURCES/0173-Open-the-PAC-socket-from-krb5_child-before-dropping-.patch @@ -0,0 +1,83 @@ +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 new file mode 100644 index 0000000..9d5d603 --- /dev/null +++ b/SOURCES/0174-views-fix-GID-overrride-for-mpg-domains.patch @@ -0,0 +1,67 @@ +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 new file mode 100644 index 0000000..08b0a46 --- /dev/null +++ b/SOURCES/0175-IPA-properly-handle-mixed-case-trusted-domains.patch @@ -0,0 +1,214 @@ +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 new file mode 100644 index 0000000..28b9dfc --- /dev/null +++ b/SOURCES/0176-nss-fix-SID-lookups.patch @@ -0,0 +1,40 @@ +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 new file mode 100644 index 0000000..2f46254 --- /dev/null +++ b/SOURCES/0177-sysdb-remove-ghosts-in-all-sub-domains-as-well.patch @@ -0,0 +1,39 @@ +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 new file mode 100644 index 0000000..f6032a8 --- /dev/null +++ b/SOURCES/0178-IPA-Rename-user_dom-into-obj_dom.patch @@ -0,0 +1,113 @@ +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 new file mode 100644 index 0000000..b5f9b2f --- /dev/null +++ b/SOURCES/0179-IPA-resolve-IPA-group-memberships-for-AD-users.patch @@ -0,0 +1,107 @@ +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 new file mode 100644 index 0000000..6b795c2 --- /dev/null +++ b/SOURCES/0180-IPA-process_members-add-ghosts-only-once.patch @@ -0,0 +1,38 @@ +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 new file mode 100644 index 0000000..83f9296 --- /dev/null +++ b/SOURCES/0181-IPA-Use-attr-s-dom-for-users-too.patch @@ -0,0 +1,61 @@ +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 new file mode 100644 index 0000000..92e600e --- /dev/null +++ b/SOURCES/0182-SELINUX-Call-setuid-0-setgid-0-to-also-set-the-real-.patch @@ -0,0 +1,53 @@ +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 new file mode 100644 index 0000000..2753cc8 --- /dev/null +++ b/SOURCES/0183-SELINUX-Set-and-reset-umask-when-caling-set_seuser-f.patch @@ -0,0 +1,72 @@ +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 new file mode 100644 index 0000000..5a0250d --- /dev/null +++ b/SOURCES/0184-LDAP-Add-UUID-when-saving-incomplete-groups.patch @@ -0,0 +1,171 @@ +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 new file mode 100644 index 0000000..d50be0a --- /dev/null +++ b/SOURCES/0185-IPA-Resolve-IPA-user-groups-overrideDN-in-non-defaul.patch @@ -0,0 +1,395 @@ +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 new file mode 100644 index 0000000..9ffeed2 --- /dev/null +++ b/SOURCES/0186-ipa_s2n_save_objects-properly-handle-fully-qualified.patch @@ -0,0 +1,34 @@ +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 new file mode 100644 index 0000000..37bedb3 --- /dev/null +++ b/SOURCES/0187-AD-use-GC-for-SID-requests-as-well.patch @@ -0,0 +1,104 @@ +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 new file mode 100644 index 0000000..98ecf55 --- /dev/null +++ b/SOURCES/0188-fill_id-fix-LE-BE-issue-with-wrong-data-type.patch @@ -0,0 +1,45 @@ +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/SPECS/sssd.spec b/SPECS/sssd.spec index 82408f1..72599fc 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -1,14 +1,29 @@ +%global rhel7_minor %(%{__grep} -o "7.[0-9]*" /etc/redhat-release |%{__sed} -s 's/7.//') + # we don't want to provide private python extension libs -%define __provides_exclude_from %{python_sitearch}/.*\.so$ +%define __provides_exclude_from %{python_sitearch}/.*\.so$|%{_libdir}/%{name}/modules/libwbclient.so.*$ %define _hardened_build 1 +%if (0%{?fedora} >= 17 || 0%{?rhel} >= 7) + %global with_cifs_utils_plugin 1 +%else + %global with_cifs_utils_plugin_option --disable-cifs-idmap-plugin +%endif + # Determine the location of the LDB modules directory %global ldb_modulesdir %(pkg-config --variable=modulesdir ldb) -%global ldb_version 1.1.16 +%global ldb_version 1.1.17 + +%global with_krb5_localauth_plugin 1 + +%global libwbc_alternatives_suffix %nil +%if 0%{?__isa_bits} == 64 +%global libwbc_alternatives_suffix -64 +%endif Name: sssd -Version: 1.11.2 -Release: 68%{?dist}.6 +Version: 1.12.2 +Release: 58%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -17,136 +32,194 @@ Source0: https://fedorahosted.org/released/sssd/%{name}-%{version}.tar.gz BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) ### Patches ### -Patch0001: 0001-SYSDB-Skip-malformed-netgroup-attribute.patch -Patch0002: 0002-monitor-Specific-error-message-for-missing-sssd.conf.patch -Patch0003: 0003-AD-Fix-a-typo-in-the-man-page.patch -Patch0004: 0004-LDAP-Initialize-user-count-for-AD-matching-rule.patch -Patch0005: 0005-SSSD-Improved-domain-detection.patch -Patch0006: 0006-SSSD-Unit-test-sss_ldap_dn_in_search_bases.patch -Patch0007: 0007-do-not-use-default_domain_suffix-with-autofs.patch -Patch0008: 0008-SYSDB-Sanitize-filter-before-sysdb_search_groups.patch -Patch0009: 0009-SYSDB-Sanitize-filter-before-removing-ghost-attrs.patch -Patch0010: 0010-LDAP-Split-out-a-request-to-search-for-a-user-w-o-sa.patch -Patch0011: 0011-LDAP-Search-for-original-DN-during-auth-if-it-s-miss.patch -Patch0012: 0012-LDAP-Prevent-from-using-uninitialized-sdap_options.patch -Patch0013: 0013-SUBDOMAINS-Reuse-cached-results-if-DP-is-offline.patch -Patch0014: 0014-failover-check-dns_domain-if-primary-servers-lookup-.patch -Patch0015: 0015-NSS-Set-packet-length-for-initgroups.patch -Patch0016: 0016-NSS-Fix-memory-leak-in-sss_setnetgrent.patch -Patch0017: 0017-AD-use-LDAP-for-group-lookups.patch -Patch0018: 0018-idmap-add-API-to-free-allocated-SIDs.patch -Patch0019: 0019-free-idmapped-SIDs-correctly.patch -Patch0020: 0020-free-idmapped-dom-SIDs-correctly.patch -Patch0021: 0021-free-idmapped-smb-SIDs-correctly.patch -Patch0022: 0022-free-idmapped-binary-SIDs-correctly.patch -Patch0023: 0023-Initialize-sid_str-to-NULL-to-avoid-freeing-random-d.patch -Patch0024: 0024-ad-refactor-tokengroups-initgroups.patch -Patch0025: 0025-ad-use-tokengroups-even-when-id-mapping-is-disabled.patch -Patch0026: 0026-AD-filter-domain-local-groups-for-trusted-sub-domain.patch -Patch0027: 0027-AD-cross-domain-membership-fix.patch -Patch0028: 0028-AD-Add-a-utility-function-to-create-list-of-connecti.patch -Patch0029: 0029-AD-Add-a-new-option-to-turn-off-GC-lookups.patch -Patch0030: 0030-AD-Enable-fallback-to-LDAP-of-trusted-domain.patch -Patch0031: 0031-Bump-sss_idmap-version-to-3-0-3.patch -Patch0032: 0032-AD-Refresh-subdomain-data-structures-on-startup.patch -Patch0033: 0033-IPA-Refresh-subdomain-data-structures-on-startup.patch -Patch0034: 0034-IPA-Call-ipa_ad_subdom_refresh-when-server-mode-is-i.patch -Patch0035: 0035-sss_cache-initialize-names-member-of-sss_domain_info.patch -Patch0036: 0036-sss_cache-fix-case-sensitivity-issue.patch -Patch0037: 0037-Add-sysdb_attrs_add_lc_name_alias.patch -Patch0038: 0038-Use-sysdb_attrs_add_lc_name_alias-to-add-case-insens.patch -Patch0039: 0039-Use-lower-case-name-for-case-insensitive-searches.patch -Patch0040: 0040-Add-new-option-ldap_group_type.patch -Patch0041: 0041-Add-sysdb_attrs_get_int32_t.patch -Patch0042: 0042-IPA-fix-for-recent-AD-group-membership-changes.patch -Patch0043: 0043-LDAP-Fix-typo-and-use-the-right-attribute-map.patch -Patch0044: 0044-pac-fix-double-free.patch -Patch0045: 0045-pac-fix-potential-memory-leaks.patch -Patch0046: 0046-responder-Set-forest-attribute-in-AD-domains.patch -Patch0047: 0047-LDAP-Add-a-new-error-code-for-malformed-access-contr.patch -Patch0048: 0048-FAST-when-parsing-krb5_child-response-make-sure-to-n.patch -Patch0049: 0049-UTIL-Inherit-parent-domain-s-default_shell.patch -Patch0050: 0050-NSS-Use-plain-user-name-when-expanding-homedir.patch -Patch0051: 0051-simple-access-match-objects-using-flat-name.patch -Patch0052: 0052-simple-access-refresh-master-domain-info.patch -Patch0053: 0053-NSS-add-support-for-subdomain_homedir.patch -Patch0054: 0054-AD-Return-right-error-code-from-netlogon_get_flat_na.patch -Patch0055: 0055-AD-Don-t-fail-the-request-if-ad_account_can_shortcut.patch -Patch0056: 0056-MAN-Fix-a-typo.patch -Patch0057: 0057-LDAP-Fix-error-check.patch -Patch0058: 0058-LDAP-Don-t-fail-if-subdomain-cannot-be-found-by-sid.patch -Patch0059: 0059-LDAP-update-id-mapping-detection-for-ldap-provider.patch -Patch0060: 0060-sdap_idamp-Fall-back-to-another-method-if-sid-is-wro.patch -Patch0061: 0061-krb5-hint-to-increase-krb5_auth_timeout.patch -Patch0062: 0062-LDAP-Don-t-abort-request-if-no-id-mapping-domain-mat.patch -Patch0063: 0063-sudo-memset-tm-when-converting-time-attributes.patch -Patch0064: 0064-AD-Don-t-mark-domain-as-enumerated-twice.patch -Patch0065: 0065-AD-Store-info-on-whether-a-subdomain-is-set-to-enume.patch -Patch0066: 0066-LDAP-Pass-a-private-context-to-enumeration-ptask-ins.patch -Patch0067: 0067-LDAP-Add-enum-request-with-custom-connection.patch -Patch0068: 0068-AD-Enumerate-users-from-GC-other-entities-from-LDAP.patch -Patch0069: 0069-LDAP-Don-t-clobber-original_member-during-enumeratio.patch -Patch0070: 0070-DB-Add-sss_ldb_el_to_string_list.patch -Patch0071: 0071-AD-Establish-cross-domain-memberships-after-enumerat.patch -Patch0072: 0072-AD-SRV-use-right-domain-name-for-CLDAP-ping.patch -Patch0073: 0073-MAN-clarify-which-shell-option-takes-precedence.patch -Patch0074: 0074-LDAP-store-group-if-subdomain-cannot-be-found-by-sid.patch -Patch0075: 0075-LDAP-require-attribute-groupType-for-AD-groups.patch -Patch0076: 0076-MONITOR-Incorrect-permissions-on-sssd.conf.patch -Patch0077: 0077-Revert-NSS-add-support-for-subdomain_homedir.patch -Patch0078: 0078-AD-support-for-subdomain_homedir.patch -Patch0079: 0079-MAN-update-of-subdomain_homedir-usage.patch -Patch0080: 0080-utils-handling-NULL-params-in-sss_parse_name.patch -Patch0081: 0081-LDAP-Detect-the-presence-of-POSIX-attributes.patch -Patch0082: 0082-AD-Only-download-domains-that-are-set-to-enumerate.patch -Patch0083: 0083-AD-Remove-dead-code.patch -Patch0084: 0084-LDAP-Handle-errors-from-sdap_id_op-properly-in-enum-.patch -Patch0085: 0085-SSS_CACHE-Reset-the-initgroups-attribute-when-resett.patch -Patch0086: 0086-IPA-Default-to-krb5_use_fast-try.patch -Patch0087: 0087-IPA-default-krb5_fast_principal-to-host-client-realm.patch -Patch0088: 0088-MAN-Clarify-the-new-krb5_use_fast-IPA-default.patch -Patch0089: 0089-IPA-Don-t-call-tevent_req_post-outside-_send.patch -Patch0090: 0090-IPA-Don-t-fail-if-apply_subdomain_homedir-returns-EN.patch -Patch0091: 0091-LDAP-Setup-periodic-task-only-once.patch -Patch0092: 0092-UTIL-Sanitize-whitespaces.patch -Patch0093: 0093-IDMAP-add-sss_idmap_check_collision-_ex.patch -Patch0094: 0094-IPA-refactor-idmap-code-and-add-test.patch -Patch0095: 0095-IPA-check-ranges-for-collisions-before-saving-them.patch -Patch0096: 0096-OPTS-Allow-using-defaults-for-blobs.patch -Patch0097: 0097-DP-Provide-separate-dp_copy_defaults-function.patch -Patch0098: 0098-MAN-Clarify-the-ldap_access_filter-option-further.patch -Patch0099: 0099-MAN-Clarify-that-changing-ID-mapping-options-might-r.patch -Patch0100: 0100-DOC-Fix-names-of-arguments-in-doxygen-comments.patch -Patch0101: 0101-libsss_idmap-bump-version-info.patch -Patch0102: 0102-config-API-add-missing-subdomain-target-to-AD-provid.patch -Patch0103: 0103-SUDO-AD-provider.patch -Patch0104: 0104-ipa-server-mode-use-lower-case-user-name-for-home-di.patch -Patch0105: 0105-IPA-Do-not-save-intermediate-data-to-sysdb.patch -Patch0106: 0106-Fix-krb5-changepw-when-FAST-only-preauth-methods-are.patch -Patch0107: 0107-IPA-Use-GC-for-AD-initgroup-requests.patch -Patch0108: 0108-AD-Only-connect-to-GC-for-subdomain-users.patch -Patch0109: 0109-MAN-Clarify-the-GC-support-a-bit.patch -Patch0110: 0110-IPA-Use-the-correct-domain-when-processing-SELinux-r.patch -Patch0111: 0111-IPA-KRB5-handle-KRB5_PROG_ETYPE_NOSUPP-during-IPA-pa.patch -Patch0112: 0112-AD-Continue-if-sssd-failes-to-check-extra-members.patch -Patch0113: 0113-IPA-Write-SELinux-usernames-in-the-right-case.patch -Patch0114: 0114-krb5_child-remove-unused-option-lifetime_str-from-k5.patch -Patch0115: 0115-krb5-child-extract-lifetime-settings-into-set_lifeti.patch -Patch0116: 0116-krb5_client-rename-krb5_set_canonicalize-to-set_cano.patch -Patch0117: 0117-krb5-child-add-revert_changepw_options.patch -Patch0118: 0118-KRB5-Do-not-attempt-to-get-a-TGT-after-a-password-ch.patch -Patch0119: 0119-IPA-Use-function-sysdb_attrs_get_el-in-safe-way.patch -Patch0120: 0120-AD-connect-to-forest-root-when-downloading-the-list-.patch -Patch0121: 0121-IPA-Fix-SELinux-mapping-order-memory-hierarchy.patch -Patch0122: 0122-AD-Do-not-remove-non-root-domains-when-looking-up-ro.patch -Patch0123: 0123-AD-Provider-bug-fix-uninitialized-variable.patch -Patch0124: 0124-AD-Provider-bugfix-use-after-free.patch -Patch0125: 0125-ipa-subdomains-provider-make-sure-search-by-SID-work.patch -Patch0126: 0126-tests-Remove-tests-that-check-creating-public-direct.patch -Patch0127: 0127-IPA-handle-searches-by-SID-in-apply_subdomain_homedi.patch -Patch0128: 0128-LDAP-Ignore-returned-referrals-if-referral-support-i.patch -Patch0129: 0129-Ignore-referrals-in-deref-and-ASQ-too.patch -Patch0130: 0130-IPA-Use-GC-for-group-lookups-in-server-mode.patch +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 ### Dependencies ### @@ -165,6 +238,7 @@ Requires: python-sssdconfig = %{version}-%{release} %global pipepath %{sssdstatedir}/pipes %global mcpath %{sssdstatedir}/mc %global pubconfpath %{sssdstatedir}/pubconf +%global gpocachepath %{sssdstatedir}/gpo_cache ### Build Dependencies ### @@ -176,10 +250,12 @@ BuildRequires: popt-devel BuildRequires: libtalloc-devel BuildRequires: libtevent-devel BuildRequires: libtdb-devel + +# LDB needs a strict version match to build BuildRequires: libldb-devel = %{ldb_version} BuildRequires: libdhash-devel >= 0.4.2 BuildRequires: libcollection-devel -BuildRequires: libini_config-devel >= 1.0.0.1 +BuildRequires: libini_config-devel >= 1.1.0-24 BuildRequires: dbus-devel BuildRequires: dbus-libs BuildRequires: openldap-devel @@ -190,7 +266,11 @@ BuildRequires: pcre-devel BuildRequires: libxslt BuildRequires: libxml2 BuildRequires: docbook-style-xsl -BuildRequires: krb5-devel >= 1.10 +%if (0%{?with_krb5_localauth_plugin} == 1) +BuildRequires: krb5-devel >= 1.12 +%else +BuildRequires: krb5-devel +%endif BuildRequires: c-ares-devel BuildRequires: python-devel BuildRequires: check-devel @@ -207,6 +287,12 @@ BuildRequires: diffstat BuildRequires: findutils BuildRequires: samba4-devel >= 4.0.0-59beta2 BuildRequires: selinux-policy-targeted +BuildRequires: systemd-devel +BuildRequires: libsmbclient-devel +%if (0%{?with_cifs_utils_plugin} == 1) +BuildRequires: cifs-utils-devel +%endif +BuildRequires: libnfsidmap-devel %description Provides a set of daemons to manage access to remote directories and @@ -226,14 +312,20 @@ License: GPLv3+ Conflicts: selinux-policy < 3.10.0-46 Conflicts: sssd < 1.10.0-8%{?dist}.beta2 # Requires + +# LDB needs a strict version match to run +# This protects against +# "sssd[XXX]: ldb: module version mismatch in src/ldb_modules/memberof.c" Requires: libldb%{?_isa} = %{ldb_version} + Requires: libtdb%{?_isa} >= 1.1.3 Requires: sssd-client%{?_isa} = %{version}-%{release} Requires: libsss_idmap%{?_isa} = %{version}-%{release} -Requires: libini_config >= 1.0.0.1 +Requires: libini_config >= 1.1.0-24 Requires(post): systemd-units chkconfig Requires(preun): systemd-units chkconfig Requires(postun): systemd-units chkconfig +Requires(pre): shadow-utils ### Provides ### @@ -255,6 +347,8 @@ Group: Applications/System License: LGPLv3+ Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig +Requires(post): /usr/sbin/alternatives +Requires(preun): /usr/sbin/alternatives %description client Provides the libraries needed by the PAM and NSS stacks to connect to the SSSD @@ -303,6 +397,7 @@ License: GPLv3+ Conflicts: sssd < 1.10.0-8.beta2 Requires: cyrus-sasl-gssapi%{?_isa} Requires: sssd-common = %{version}-%{release} +Requires(pre): shadow-utils %description krb5-common Provides helper processes that the LDAP and Kerberos back ends can use for @@ -342,10 +437,8 @@ Requires: sssd-common = %{version}-%{release} Requires: sssd-krb5-common = %{version}-%{release} Requires: libipa_hbac%{?_isa} = %{version}-%{release} Requires: bind-utils -# RHEL 5 is too old to support the PAC responder -%if !0%{?is_rhel5} Requires: sssd-common-pac = %{version}-%{release} -%endif +Requires(pre): shadow-utils %description ipa Provides the IPA back end that the SSSD can utilize to fetch identity data @@ -359,10 +452,10 @@ Conflicts: sssd < 1.10.0-8.beta2 Requires: sssd-common = %{version}-%{release} Requires: sssd-krb5-common = %{version}-%{release} Requires: bind-utils -# RHEL 5 is too old to support the PAC responder -%if !0%{?is_rhel5} Requires: sssd-common-pac = %{version}-%{release} -%endif +# In order for libwbclient to be upgraded before sssd-ad and sets up the +# alternatives symlink +Requires: libwbclient %description ad Provides the Active Directory back end that the SSSD can utilize to fetch @@ -456,6 +549,56 @@ Requires: libsss_nss_idmap = %{version}-%{release} The libsss_nss_idmap-python contains the bindings so that libsss_nss_idmap can be used by Python applications. +%package dbus +Summary: The D-Bus responder of the SSSD +Group: Applications/System +License: GPLv3+ +BuildRequires: augeas-devel +Requires: sssd-common = %{version}-%{release} + +%description dbus +Provides the D-Bus responder of the SSSD, called the InfoPipe, that allows +the information from the SSSD to be transmitted over the system bus. + +%package -n libsss_simpleifp +Summary: The SSSD D-Bus responder helper library +Group: Development/Libraries +License: GPLv3+ +Requires: dbus-libs +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description -n libsss_simpleifp +Provides library that simplifies D-Bus API for the SSSD InfoPipe responder. + +%package -n libsss_simpleifp-devel +Summary: The SSSD D-Bus responder helper library +Group: Development/Libraries +License: GPLv3+ +Requires: dbus-devel +Requires: libsss_simpleifp = %{version}-%{release} + +%description -n libsss_simpleifp-devel +Provides library that simplifies D-Bus API for the SSSD InfoPipe responder. + +%package libwbclient +Summary: The SSSD libwbclient implementation +Group: Applications/System +License: GPLv3+ and LGPLv3+ +Conflicts: libwbclient < 4.1.12 + +%description libwbclient +The SSSD libwbclient implementation. + +%package libwbclient-devel +Summary: Development libraries for the SSSD libwbclient implementation +Group: Development/Libraries +License: GPLv3+ and LGPLv3+ +Conflicts: libwbclient-devel < 4.1.12 + +%description libwbclient-devel +Development libraries for the SSSD libwbclient implementation. + %prep # Update timestamps on the files touched by a patch, to avoid non-equal # .pyc/.pyo files across the multilib peers within a build, where "Level" @@ -486,20 +629,28 @@ autoreconf -ivf --with-pipe-path=%{pipepath} \ --with-pubconf-path=%{pubconfpath} \ --with-mcache-path=%{mcpath} \ + --with-gpo-cache-path=%{gpocachepath} \ --with-init-dir=%{_initrddir} \ --with-krb5-rcache-dir=%{_localstatedir}/cache/krb5rcache \ --enable-nsslibdir=%{_libdir} \ --enable-pammoddir=%{_libdir}/security \ --enable-ldb-version-check \ + --enable-nfsidmaplibdir=%{_libdir}/libnfsidmap \ --disable-static \ --disable-rpath \ - --with-test-dir=/dev/shm + --with-sssd-user=sssd \ + --with-test-dir=/dev/shm \ + --with-initscript=systemd \ + --with-syslog=journald \ + --with-test-dir=/dev/shm \ + --enable-sss-default-nss-plugin \ + %{?with_cifs_utils_plugin_option} make %{?_smp_mflags} all docs %check export CK_TIMEOUT_MULTIPLIER=10 -make %{?_smp_mflags} check +make %{?_smp_mflags} check VERBOSE=yes unset CK_TIMEOUT_MULTIPLIER %install @@ -632,28 +783,34 @@ 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 %{_libdir}/libsss_sudo.so +%{_libdir}/libnfsidmap/sss.so %{ldb_modulesdir}/memberof.so %{_bindir}/sss_ssh_authorizedkeys %{_bindir}/sss_ssh_knownhostsproxy %{_sbindir}/sss_cache +%{_libexecdir}/%{servicename}/sss_signal %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(700,root,root) %dir %{pipepath}/private -%attr(750,root,root) %dir %{_var}/log/%{name} -%attr(700,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 +%attr(755,root,root) %dir %{_sysconfdir}/systemd/system/sssd.service.d +%config(noreplace) %{_sysconfdir}/systemd/system/sssd.service.d/journal.conf %config(noreplace) %{_sysconfdir}/logrotate.d/sssd %config(noreplace) %{_sysconfdir}/rwtab.d/sssd %dir %{_datadir}/sssd @@ -664,6 +821,7 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man5/sssd.conf.5* %{_mandir}/man5/sssd-simple.5* %{_mandir}/man5/sssd-sudo.5* +%{_mandir}/man5/sss_rpcidmapd.5* %{_mandir}/man8/sssd.8* %{_mandir}/man8/sss_cache.8* %{python_sitearch}/pysss.so @@ -679,8 +837,8 @@ rm -rf $RPM_BUILD_ROOT %defattr(-,root,root,-) %doc COPYING %{_libdir}/%{name}/libsss_krb5_common.so -%{_libexecdir}/%{servicename}/ldap_child -%{_libexecdir}/%{servicename}/krb5_child +%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/ldap_child +%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/krb5_child %files krb5 -f sssd_krb5.lang %defattr(-,root,root,-) @@ -688,25 +846,25 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/%{name}/libsss_krb5.so %{_mandir}/man5/sssd-krb5.5* -# RHEL 5 is too old to support the PAC responder -%if !0%{?is_rhel5} %files common-pac %defattr(-,root,root,-) %doc COPYING %{_libexecdir}/%{servicename}/sssd_pac -%endif %files ipa -f sssd_ipa.lang %defattr(-,root,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 %defattr(-,root,root,-) %doc COPYING %{_libdir}/%{name}/libsss_ad.so +%{_libdir}/%{name}/libsss_ad_common.so +%{_libexecdir}/%{servicename}/gpo_child %{_mandir}/man5/sssd-ad.5* %files proxy @@ -715,6 +873,33 @@ rm -rf $RPM_BUILD_ROOT %{_libexecdir}/%{servicename}/proxy_child %{_libdir}/%{name}/libsss_proxy.so +%files dbus +%defattr(-,root,root,-) +%doc COPYING +%{_libexecdir}/%{servicename}/sssd_ifp +%{_mandir}/man5/sssd-ifp.5* +# InfoPipe DBus plumbing +%{_sysconfdir}/dbus-1/system.d/org.freedesktop.sssd.infopipe.conf +%{_datadir}/dbus-1/system-services/org.freedesktop.sssd.infopipe.service +%{_libdir}/%{name}/libsss_config.so + +%files -n libsss_simpleifp +%defattr(-,root,root,-) +%{_libdir}/libsss_simpleifp.so.* + +%files -n libsss_simpleifp-devel +%defattr(-,root,root,-) +%if 0%{?fedora} +%doc sss_simpleifp_doc/html +%endif +%if 0%{?rhel} >= 6 +%doc sss_simpleifp_doc/html +%endif +%{_includedir}/sss_sifp.h +%{_includedir}/sss_sifp_dbus.h +%{_libdir}/libsss_simpleifp.so +%{_libdir}/pkgconfig/sss_simpleifp.pc + %files client -f sssd_client.lang %defattr(-,root,root,-) %doc src/sss_client/COPYING src/sss_client/COPYING.LESSER @@ -722,6 +907,13 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/security/pam_sss.so %{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so %{_libdir}/krb5/plugins/authdata/sssd_pac_plugin.so +%if (0%{?with_cifs_utils_plugin} == 1) +%{_libdir}/cifs-utils/cifs_idmap_sss.so +%ghost %{_sysconfdir}/cifs-utils/idmap-plugin +%endif +%if (0%{?with_krb5_localauth_plugin} == 1) +%{_libdir}/%{name}/modules/sssd_krb5_localauth_plugin.so +%endif %{_mandir}/man8/pam_sss.8* %{_mandir}/man8/sssd_krb5_locator_plugin.8* @@ -798,6 +990,29 @@ rm -rf $RPM_BUILD_ROOT %defattr(-,root,root,-) %{python_sitearch}/pysss_nss_idmap.so +%files libwbclient +%defattr(-,root,root,-) +%{_libdir}/%{name}/modules/libwbclient.so.* + +%files libwbclient-devel +%defattr(-,root,root,-) +%{_includedir}/wbclient_sssd.h +%{_libdir}/%{name}/modules/libwbclient.so +%{_libdir}/pkgconfig/wbclient_sssd.pc + +%pre ipa +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 + +%pre krb5-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 + +%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 +/bin/systemctl status sssd.service >/dev/null 2>&1 && touch /var/tmp/sssd.upgrade || : + %post common if [ $1 -ge 1 ] ; then # Initial installation @@ -811,13 +1026,18 @@ if [ $1 -eq 0 ]; then /bin/systemctl stop sssd.service > /dev/null 2>&1 || : fi -%postun common -/bin/systemctl daemon-reload >/dev/null 2>&1 || : -if [ $1 -ge 1 ] ; then - /bin/systemctl try-restart sssd.service >/dev/null 2>&1 || : -fi +%if (0%{?with_cifs_utils_plugin} == 1) +%post client +/sbin/ldconfig +/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 + /usr/sbin/alternatives --remove cifs-idmap-plugin %{_libdir}/cifs-utils/cifs_idmap_sss.so +fi +%else %post client -p /sbin/ldconfig +%endif %postun client -p /sbin/ldconfig @@ -829,43 +1049,346 @@ fi %postun -n libsss_idmap -p /sbin/ldconfig -%changelog -* Tue Oct 14 2014 Jakub Hrozek - 1.11.2-68.6 -- Resolves: rhbz#1152200 - Error processing universal groups with - cross-domain membership in SSSD server mode - -* Wed May 21 2014 Jakub Hrozek - 1.11.2-68.5 -- Rebuild for a proper dist tag, yet again, now using the correct build - options -- Related: rhbz#1098608 - Expanding home directory fails when the request - comes from the PAC responder +%post libwbclient +%{_sbindir}/update-alternatives --install %{_libdir}/libwbclient.so.0.11 \ + libwbclient.so.0.11%{libwbc_alternatives_suffix} \ + %{_libdir}/%{name}/modules/libwbclient.so.0.11.0 20 +/sbin/ldconfig -* Wed May 21 2014 Jakub Hrozek - 1.11.2-68.4 -- Rebuild for a proper dist tag -- Related: rhbz#1098608 - Expanding home directory fails when the request - comes from the PAC responder +%preun libwbclient +if [ $1 -eq 0 ]; then + %{_sbindir}/update-alternatives --remove \ + libwbclient.so.0.11%{libwbc_alternatives_suffix} \ + %{_libdir}/%{name}/modules/libwbclient.so.0.11.0 +fi +/sbin/ldconfig -* Wed May 21 2014 Jakub Hrozek - 1.11.2-68.3 +%post libwbclient-devel +%{_sbindir}/update-alternatives --install %{_libdir}/libwbclient.so \ + libwbclient.so%{libwbc_alternatives_suffix} \ + %{_libdir}/%{name}/modules/libwbclient.so 20 + +%preun libwbclient-devel +if [ $1 -eq 0 ]; then + %{_sbindir}/update-alternatives --remove \ + libwbclient.so%{libwbc_alternatives_suffix} \ + %{_libdir}/%{name}/modules/libwbclient.so +fi + +%posttrans common +/bin/systemctl daemon-reload >/dev/null 2>&1 || : +if [ -f /var/tmp/sssd.upgrade ]; then + /bin/systemctl restart sssd.service >/dev/null 2>&1 || : +else + /bin/systemctl try-restart sssd.service >/dev/null 2>&1 || : +fi +/usr/bin/rm -f /var/tmp/sssd.upgrade || : + +%changelog +* Tue Feb 3 2015 Jakub Hrozek - 1.12.2-57 +- Run the restart in sssd-common posttrans +- Explicitly require libwbclient +- Resolves: rhbz#1187113 - sssd deamon was not running after RHEL 7.1 upgrade + +* Fri Jan 30 2015 Jakub Hrozek - 1.12.2-56 +- Resolves: rhbz#1187113 - sssd deamon was not running after RHEL 7.1 upgrade + +* Fri Jan 30 2015 Jakub Hrozek - 1.12.2-55 +- Fix endianess bug in fill_id() +- Related: rhbz#1109331 - [RFE] Allow SSSD to be used with smbd shares + +* Fri Jan 30 2015 Jakub Hrozek - 1.12.2-54 +- Resolves: rhbz#1168904 - gid is overridden by uid in default trust view + +* Fri Jan 30 2015 Jakub Hrozek - 1.12.2-53 +- Resolves: rhbz#1187192 - IPA initgroups don't work correctly in + non-default view + +* Tue Jan 27 2015 Jakub Hrozek - 1.12.2-52 +- Resolves: rhbz#1184982 - Need to set different umask in selinux_child + +* Tue Jan 27 2015 Jakub Hrozek - 1.12.2-51 +- Bump the release number +- Related: rhbz#1184140 - Users saved throug extop don't have the + originalMemberOf attribute + +* Tue Jan 27 2015 Jakub Hrozek - 1.12.2-50 +- Add a patch dependency +- Related: rhbz#1184140 - Users saved throug extop don't have the + originalMemberOf attribute + +* Tue Jan 27 2015 Jakub Hrozek - 1.12.2-49 +- Process ghost members only once +- Fix processing of universal groups with members from different domains +- Related: rhbz#1168904 - gid is overridden by uid in default trust view + +* Tue Jan 27 2015 Jakub Hrozek - 1.12.2-48 +- Related: rhbz#1184140 - Users saved throug extop don't have the + originalMemberOf attribute + +* Fri Jan 23 2015 Jakub Hrozek - 1.12.2-47 +- Resolves: rhbz#1185188 - Uncached SIDs cannot be resolved + +* Fri Jan 23 2015 Jakub Hrozek - 1.12.2-46 +- Handle GID override in MPG domains +- Handle views with mixed-case domains +- Related: rhbz#1168904 - gid is overridden by uid in default trust view + +* Wed Jan 21 2015 Jakub Hrozek - 1.12.2-45 +- Open socket to the PAC responder in krb5_child before dropping root +- Related: rhbz#1184140 - Users saved throug extop don't have the + originalMemberOf attribute + +* Tue Jan 20 2015 Jakub Hrozek - 1.12.2-44 +- Resolves: rhbz#1184140 - Users saved throug extop don't have the + originalMemberOf attribute + +* Mon Jan 19 2015 Jakub Hrozek - 1.12.2-43 +- Resolves: rhbz#1182183 - pam_sss(sshd:auth): authentication failure with + user from AD + +* Wed Jan 14 2015 Jakub Hrozek - 1.12.2-42 +- Resolves: rhbz#889206 - On clock skew sssd returns system error + +* Wed Jan 14 2015 Jakub Hrozek - 1.12.2-41 +- Related: rhbz#1168904 - gid is overridden by uid in default trust view + +* Tue Jan 13 2015 Jakub Hrozek - 1.12.2-40 +- Resolves: rhbz#1177140 - gpo_child fails if "log level" is enabled in smb.conf +- Related: rhbz#1168904 - gid is overridden by uid in default trust view + +* Fri Dec 19 2014 Sumit Bose - 1.12.2-39 +- Resolves: rhbz#1175408 - SSSD should not fail authentication when only allow + rules are used +- Resolves: rhbz#1175705 - sssd-libwbclient conflicts with Samba's and causes + crash in wbinfo + - in addition to the patch libwbclient.so is + filtered out of the Provides list of the package + +* Wed Dec 17 2014 Sumit Bose - 1.12.2-38 +- Resolves: rhbz#1171215 - Crash in function get_object_from_cache +- Resolves: rhbz#1171383 - getent fails for posix group with AD users after + login +- Resolves: rhbz#1171382 - getent of AD universal group fails after group users + login +- Resolves: rhbz#1170300 - Access is not rejected for disabled domain +- Resolves: rhbz#1162486 - Error processing external groups with + getgrnam/getgrgid in the server mode +- Resolves: rhbz#1168904 - gid is overridden by uid in default trust view + +* Wed Dec 17 2014 Sumit Bose - 1.12.2-37 +- Resolves: rhbz#1169459 - sssd-ad: The man page description to enable GPO HBAC + Policies are unclear +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Mon Dec 15 2014 Jakub Hrozek - 1.12.2-35 +- Rebuild to add several forgotten Patch entries +- Resolves: rhbz#1173482 - MAN: Document that only user names are checked + for pam_trusted_users +- Resolves: rhbz#1167324 - pam_sss domains option: User auth should fail + when domains= + +* Sun Dec 14 2014 Jakub Hrozek - 1.12.2-35 +- Remove Coverity warnings in krb5_child code +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Sat Dec 13 2014 Jakub Hrozek - 1.12.2-34 +- Resolves: rhbz#1173482 - MAN: Document that only user names are checked + for pam_trusted_users +- Resolves: rhbz#1167324 - pam_sss domains option: User auth should fail + when domains= + +* Sat Dec 13 2014 Jakub Hrozek - 1.12.2-33 +- Don't error out on chpass with OTPs +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Mon Dec 8 2014 Jakub Hrozek - 1.12.2-32 +- Resolves: rhbz#1124320 - [FJ7.0 Bug]: getgrent returns error because sss + is written in nsswitch.conf as default. + +* Mon Dec 8 2014 Jakub Hrozek - 1.12.2-31 +- Resolves: rhbz#1169739 - selinuxusermap rule does not apply to trusted + AD users +- Enable running unit tests without cmocka +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Wed Dec 3 2014 Jakub Hrozek - 1.12.2-30 +- krb5_child and ldap_child do not call Kerberos calls as root +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Wed Dec 3 2014 Jakub Hrozek - 1.12.2-29 +- Resolves: rhbz#1168735 - The Kerberos provider is not properly views-aware + +* Wed Nov 26 2014 Jakub Hrozek - 1.12.2-28 +- Fix typo in libwbclient-devel alternatives invocation +- Related: rhbz#1109331 - [RFE] Allow SSSD to be used with smbd shares + +* Wed Nov 26 2014 Jakub Hrozek - 1.12.2-27 +- Resolves: rhbz#1166727 - pam_sss domains option: Untrusted users from + the same domain are allowed to auth. + +* Tue Nov 25 2014 Jakub Hrozek - 1.12.2-26 +- Handle migrating clients between views +- Related: rhbz#891984 - [RFE] ID Views: Support migration from the sync + solution to the trust solution + +* Tue Nov 25 2014 Jakub Hrozek - 1.12.2-25 +- Use alternatives for libwbclient +- Related: rhbz#1109331 - [RFE] Allow SSSD to be used with smbd shares + +* Tue Nov 25 2014 Jakub Hrozek - 1.12.2-24 +- Resolves: rhbz#1165794 - sssd does not work with custom value of option + re_expression + +* Tue Nov 25 2014 Jakub Hrozek - 1.12.2-23 +- Add an option that describes where to put generated krb5 files to +- Related: rhbz#1135043 - [RFE] Implement localauth plugin for MIT krb5 1.12 + +* Tue Nov 25 2014 Jakub Hrozek - 1.12.2-22 +- Handle IPA group names returned from the extop plugin +- Related: rhbz#891984 - [RFE] ID Views: Support migration from the sync + solution to the trust solution + +* Tue Nov 25 2014 Jakub Hrozek - 1.12.2-21 +- Resolves: rhbz#1165792 - automount segfaults in sss_nss_check_header + +* Thu Nov 20 2014 Jakub Hrozek - 1.12.2-20 +- Resolves: rhbz#1163742 - "debug_timestamps = false" and "debug_microseconds + = true" do not work after enabling journald + with sssd. + +* Thu Nov 20 2014 Jakub Hrozek - 1.12.2-19 +- Resolves: rhbz#1153593 - Manpage description of case_sensitive=preserving + is incomplete + +* Thu Nov 20 2014 Jakub Hrozek - 1.12.2-18 +- Support views for IPA users +- Related: rhbz#891984 - [RFE] ID Views: Support migration from the sync + solution to the trust solution + +* Thu Nov 20 2014 Jakub Hrozek - 1.12.2-17 +- Update man page to clarify TGs should be disabled with a custom search base +- Related: rhbz#1161741 - TokenGroups for LDAP provider breaks in corner cases + +* Wed Nov 19 2014 Jakub Hrozek - 1.12.2-16 +- Use upstreamed patches for the rootless sssd +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Wed Nov 19 2014 Jakub Hrozek - 1.12.2-15 +- Resolves: rhbz#1153603 - Proxy Provider: Fails to lookup case sensitive + users and groups with case_sensitive=preserving + +* Wed Nov 19 2014 Jakub Hrozek - 1.12.2-14 +- Resolves: rhbz#1161741 - TokenGroups for LDAP provider breaks in corner cases + +* Wed Nov 19 2014 Jakub Hrozek - 1.12.2-13 +- Resolves: rhbz#1162480 - dereferencing failure against openldap server + +* Wed Nov 12 2014 Jakub Hrozek - 1.12.2-12 +- Move adding the user from pretrans to pre, copy adding the user to + sssd-krb5-common and sssd-ipa as well in order to work around yum + ordering issue +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Tue Nov 11 2014 Jakub Hrozek - 1.12.2-11 +- Resolves: rhbz#1113783 - sssd should run under unprivileged user + +* Fri Nov 7 2014 Jakub Hrozek - 1.12.2-10 +- Fix two regressions in the new selinux_child process +- Related: rhbz#1113783 - sssd should run under unprivileged user +- Resolves: rhbz#1132365 - Remove password from the PAM stack if OTP is used + +* Wed Nov 5 2014 Jakub Hrozek - 1.12.2-9 +- Include the ldap_child and selinux_child patches for rootless sssd +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Wed Nov 5 2014 Jakub Hrozek - 1.12.2-8 +- Support overriding SSH public keys with views +- Support extended attributes via the extop plugin +- Related: rhbz#1109756 - Rebase SSSD to 1.12 +- Resolves: rhbz#1137010 - disable midpoint refresh for netgroups if ptask + refresh is enabled + +* Thu Oct 30 2014 Jakub Hrozek - 1.12.2-7 +- Resolves: rhbz#1153518 - service lookups returned in lowercase with + case_sensitive=preserving +- Resolves: rhbz#1158809 - Enumeration shows only a single group multiple + times + +* Wed Oct 22 2014 Jakub Hrozek - 1.12.2-6 +- Include the responder and packaging patches for rootless sssd +- Related: rhbz#1113783 - sssd should run under unprivileged user + +* Wed Oct 22 2014 Jakub Hrozek - 1.12.2-5 +- Amend the sssd-ldap man page with info about lockout setup +- Related: rhbz#1109756 - Rebase SSSD to 1.12 +- Resolves: rhbz#1137014 - Shell fallback mechanism in SSSD +- Resolves: rhbz#790854 - 4 functions with reference leaks within sssd (src/python/pyhbac.c) + +* Wed Oct 22 2014 Jakub Hrozek - 1.12.2-4 +- Fix regressions caused by views patches when SSSD is connected to a + pre-4.0 IPA server +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Wed Oct 22 2014 Jakub Hrozek - 1.12.2-3 +- Add the low-level server changes for running as unprivileged user +- Package the libsss_semange library needed for SELinux label changes +- Related: rhbz#1113783 - sssd should run under unprivileged user +- Resolves: rhbz#1113784 - sssd should audit selinux user map changes + +* Wed Oct 22 2014 Jakub Hrozek - 1.12.2-2 +- Use libsemanage for SELinux label changes +- Resolves: rhbz#1113784 - sssd should audit selinux user map changes + +* Mon Oct 20 2014 Jakub Hrozek - 1.12.2-1 +- Rebase SSSD to 1.12.2 +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Thu Oct 09 2014 Jakub Hrozek - 1.12.1-2 +- Sync with upstream +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Thu Sep 11 2014 Jakub Hrozek - 1.12.1-1 +- Rebuild against ding-libs with fixed SONAME +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Tue Sep 9 2014 Jakub Hrozek - 1.12.1-1 +- Rebase SSSD to 1.12.1 +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Fri Sep 05 2014 Jakub Hrozek - 1.12.0-3 +- Require ldb 2.1.17 +- Related: rhbz#1133914 - Rebase libldb to version 1.1.17 or newer + +* Fri Aug 08 2014 Jakub Hrozek - 1.12.0-2 +- Fix fully qualified IFP lookups +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Thu Jul 24 2014 Jakub Hrozek - 1.12.0-1 +- Rebase SSSD to 1.12.0 +- Related: rhbz#1109756 - Rebase SSSD to 1.12 + +* Wed May 21 2014 Jakub Hrozek - 1.11.2-70 - Squash in upstream review comments about the PAC patch -- Related: rhbz#1098608 - Expanding home directory fails when the request +- Related: rhbz#1097286 - Expanding home directory fails when the request comes from the PAC responder -* Tue May 13 2014 Jakub Hrozek - 1.11.2-68.2 +* Tue May 13 2014 Jakub Hrozek - 1.11.2-69 - Backport a patch to allow krb5-utils-test to run as root -- Related: rhbz#1098608 - Expanding home directory fails when the request +- Related: rhbz#1097286 - Expanding home directory fails when the request comes from the PAC responder -* Tue May 13 2014 Jakub Hrozek - 1.11.2-68.1 -- Resolves: rhbz#1098608 - Expanding home directory fails when the request +* Tue May 13 2014 Jakub Hrozek - 1.11.2-68 +- Resolves: rhbz#1097286 - Expanding home directory fails when the request comes from the PAC responder * Tue May 13 2014 Jakub Hrozek - 1.11.2-67 - Fix a DEBUG message, backport two related fixes -- Related: rhbz#1097323 - segfault in sssd_be when second domain tree +- Related: rhbz#1090653 - segfault in sssd_be when second domain tree users are queried while joined to child domain * Tue May 13 2014 Jakub Hrozek - 1.11.2-66 -- Resolves: rhbz#1097323 - segfault in sssd_be when second domain tree +- Resolves: rhbz#1090653 - segfault in sssd_be when second domain tree users are queried while joined to child domain * Wed Apr 02 2014 Jakub Hrozek - 1.11.2-65