diff --git a/0001-SDAP-Remove-user-from-cache-for-missing-user-in-LDAP.patch b/0001-SDAP-Remove-user-from-cache-for-missing-user-in-LDAP.patch index 9132e8d..2b11454 100644 --- a/0001-SDAP-Remove-user-from-cache-for-missing-user-in-LDAP.patch +++ b/0001-SDAP-Remove-user-from-cache-for-missing-user-in-LDAP.patch @@ -1,7 +1,7 @@ -From 2fd87aeb39f001b840d1be274a459f04b9a6c6f2 Mon Sep 17 00:00:00 2001 +From 4cb5ab77926503943a9dc7bd1d47bcfb6ed6da68 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Wed, 17 Jun 2015 21:35:22 +0200 -Subject: [PATCH] SDAP: Remove user from cache for missing user in LDAP +Subject: [PATCH 01/21] SDAP: Remove user from cache for missing user in LDAP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -21,7 +21,7 @@ Reviewed-by: Michal Židek 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index a53a7d7b1207aa037984c709daed5c577f1ed8bc..4ebcd516bda020a393725d740bf59aadba8a851e 100644 +index a53a7d7..4ebcd51 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -1142,32 +1142,37 @@ static void groups_by_user_done(struct tevent_req *subreq) @@ -32,6 +32,15 @@ index a53a7d7b1207aa037984c709daed5c577f1ed8bc..4ebcd516bda020a393725d740bf59aad - state->dp_error = dp_error; - tevent_req_error(req, ret); - return; +- } +- +- /* state->name is still the name used for the original request. The cached +- * object might have a different name, e.g. a fully-qualified name. */ +- ret = sysdb_get_real_name(state, state->domain, state->name, &cname); +- if (ret != EOK) { +- cname = state->name; +- DEBUG(SSSDBG_OP_FAILURE, "Failed to canonicalize name, using [%s].\n", +- cname); + if (ret == EOK || ret == ENOENT) { + /* state->name is still the name used for the original req. The cached + * object might have a different name, e.g. a fully-qualified name. */ @@ -43,15 +52,6 @@ index a53a7d7b1207aa037984c709daed5c577f1ed8bc..4ebcd516bda020a393725d740bf59aad + } } -- /* state->name is still the name used for the original request. The cached -- * object might have a different name, e.g. a fully-qualified name. */ -- ret = sysdb_get_real_name(state, state->domain, state->name, &cname); -- if (ret != EOK) { -- cname = state->name; -- DEBUG(SSSDBG_OP_FAILURE, "Failed to canonicalize name, using [%s].\n", -- cname); -- } -- - if (ret == ENOENT && state->noexist_delete == true) { - ret = sysdb_delete_user(state->domain, cname, 0); - if (ret != EOK && ret != ENOENT) { @@ -84,5 +84,5 @@ index a53a7d7b1207aa037984c709daed5c577f1ed8bc..4ebcd516bda020a393725d740bf59aad return; } -- -2.4.3 +2.5.0 diff --git a/0002-sss_client-Update-integrity-check-of-records-in-mmap.patch b/0002-sss_client-Update-integrity-check-of-records-in-mmap.patch new file mode 100644 index 0000000..cc76947 --- /dev/null +++ b/0002-sss_client-Update-integrity-check-of-records-in-mmap.patch @@ -0,0 +1,161 @@ +From 0cd0887dc253527f51ed9b2eabe6229e9eb64705 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Thu, 30 Jul 2015 10:50:47 +0200 +Subject: [PATCH 02/21] sss_client: Update integrity check of records in mmap + cache +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The function sss_nss_mc_get_record return copy of record from memory +cache in last argument. Because we should not access data directly +to avoid problems with consistency of record. +The function sss_nss_mc_get_record also check whether length of record +is within data area (with macro MC_CHECK_RECORD_LENGTH) + +However we also tried to do the same check in functions sss_nss_mc_get{gr, pw}* +Pointer to end of strings in record was compared to pointer to the end +of data table. But these two pointers are not within the same allocated area +and does not make sense to compare them. Sometimes record can be allocated +before mmaped area and sometime after. Sometimes it will return cached data +and other time will fall back to responder. + +Resolves: +https://fedorahosted.org/sssd/ticket/2743 + +Reviewed-by: Michal Židek +--- + src/sss_client/nss_mc_group.c | 19 ++++++++++--------- + src/sss_client/nss_mc_passwd.c | 20 ++++++++++---------- + 2 files changed, 20 insertions(+), 19 deletions(-) + +diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c +index e0fdb97..aacf59d 100644 +--- a/src/sss_client/nss_mc_group.c ++++ b/src/sss_client/nss_mc_group.c +@@ -112,16 +112,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, + uint32_t hash; + uint32_t slot; + int ret; +- size_t strs_offset; +- uint8_t *max_addr; ++ const size_t strs_offset = offsetof(struct sss_mc_grp_data, strs); ++ size_t data_size; + + ret = sss_nss_mc_get_ctx("group", &gr_mc_ctx); + if (ret) { + return ret; + } + +- /* Get max address of data table. */ +- max_addr = gr_mc_ctx.data_table + gr_mc_ctx.dt_size; ++ /* Get max size of data table. */ ++ data_size = gr_mc_ctx.dt_size; + + /* hashes are calculated including the NULL terminator */ + hash = sss_nss_mc_hash(&gr_mc_ctx, name, name_len + 1); +@@ -130,7 +130,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, + /* If slot is not within the bounds of mmaped region and + * it's value is not MC_INVALID_VAL, then the cache is + * probbably corrupted. */ +- while (MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) { ++ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { + /* free record from previous iteration */ + free(rec); + rec = NULL; +@@ -147,15 +147,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, + continue; + } + +- strs_offset = offsetof(struct sss_mc_grp_data, strs); + data = (struct sss_mc_grp_data *)rec->data; + /* Integrity check + * - name_len cannot be longer than all strings + * - data->name cannot point outside strings +- * - all strings must be within data_table */ ++ * - all strings must be within copy of record ++ * - size of record must be lower that data table size */ + if (name_len > data->strs_len + || (data->name + name_len) > (strs_offset + data->strs_len) +- || (uint8_t *)data->strs + data->strs_len > max_addr) { ++ || data->strs_len > rec->len ++ || rec->len > data_size) { + ret = ENOENT; + goto done; + } +@@ -168,7 +169,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, + slot = sss_nss_mc_next_slot_with_hash(rec, hash); + } + +- if (!MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) { ++ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { + ret = ENOENT; + goto done; + } +diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c +index 10e43e2..0da7ad0 100644 +--- a/src/sss_client/nss_mc_passwd.c ++++ b/src/sss_client/nss_mc_passwd.c +@@ -105,16 +105,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, + uint32_t hash; + uint32_t slot; + int ret; +- size_t strs_offset; +- uint8_t *max_addr; ++ const size_t strs_offset = offsetof(struct sss_mc_pwd_data, strs); ++ size_t data_size; + + ret = sss_nss_mc_get_ctx("passwd", &pw_mc_ctx); + if (ret) { + return ret; + } + +- /* Get max address of data table. */ +- max_addr = pw_mc_ctx.data_table + pw_mc_ctx.dt_size; ++ /* Get max size of data table. */ ++ data_size = pw_mc_ctx.dt_size; + + /* hashes are calculated including the NULL terminator */ + hash = sss_nss_mc_hash(&pw_mc_ctx, name, name_len + 1); +@@ -123,7 +123,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, + /* If slot is not within the bounds of mmaped region and + * it's value is not MC_INVALID_VAL, then the cache is + * probbably corrupted. */ +- while (MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) { ++ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { + /* free record from previous iteration */ + free(rec); + rec = NULL; +@@ -140,16 +140,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, + continue; + } + +- strs_offset = offsetof(struct sss_mc_pwd_data, strs); +- + data = (struct sss_mc_pwd_data *)rec->data; + /* Integrity check + * - name_len cannot be longer than all strings + * - data->name cannot point outside strings +- * - all strings must be within data_table */ ++ * - all strings must be within copy of record ++ * - size of record must be lower that data table size */ + if (name_len > data->strs_len + || (data->name + name_len) > (strs_offset + data->strs_len) +- || (uint8_t *)data->strs + data->strs_len > max_addr) { ++ || data->strs_len > rec->len ++ || rec->len > data_size) { + ret = ENOENT; + goto done; + } +@@ -162,7 +162,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, + slot = sss_nss_mc_next_slot_with_hash(rec, hash); + } + +- if (!MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) { ++ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { + ret = ENOENT; + goto done; + } +-- +2.5.0 + diff --git a/0003-BUILD-Repair-dependecies-on-deprecated-libraries.patch b/0003-BUILD-Repair-dependecies-on-deprecated-libraries.patch new file mode 100644 index 0000000..6c72afc --- /dev/null +++ b/0003-BUILD-Repair-dependecies-on-deprecated-libraries.patch @@ -0,0 +1,95 @@ +From 51a1e04122fda73847dc368b11b4e8b78335cc78 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Mon, 27 Jul 2015 12:52:49 -0400 +Subject: [PATCH 03/21] BUILD: Repair dependecies on deprecated libraries +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Modules libsystemd-journal and libsystemd-login are +deprecated and "libsystemd" should be used instead +of them. + +Resolves: +https://fedorahosted.org/sssd/ticket/2733 + +Reviewed-by: Lukáš Slebodník +--- + contrib/ci/deps.sh | 2 +- + src/external/systemd.m4 | 40 ++++++++++++++++++++++++++++------------ + 2 files changed, 29 insertions(+), 13 deletions(-) + +diff --git a/contrib/ci/deps.sh b/contrib/ci/deps.sh +index 0cdb996..50e4f44 100644 +--- a/contrib/ci/deps.sh ++++ b/contrib/ci/deps.sh +@@ -84,7 +84,7 @@ if [[ "$DISTRO_BRANCH" == -debian-* ]]; then + libselinux1-dev + libsemanage1-dev + libsmbclient-dev +- libsystemd-journal-dev ++ libsystemd-dev + libtalloc-dev + libtdb-dev + libtevent-dev +diff --git a/src/external/systemd.m4 b/src/external/systemd.m4 +index dbced0d..4c28445 100644 +--- a/src/external/systemd.m4 ++++ b/src/external/systemd.m4 +@@ -1,25 +1,41 @@ ++dnl There are no module libsystemd-journal and libsystem-login ++dnl up systemd version 209 ++PKG_CHECK_EXISTS([libsystemd], ++ [HAVE_LIBSYSTEMD=yes], ++ [HAVE_LIBSYSTEMD=no]) ++ + dnl A macro to check presence of systemd on the system + AC_DEFUN([AM_CHECK_SYSTEMD], + [ + PKG_CHECK_EXISTS(systemd, + [ HAVE_SYSTEMD=1, AC_SUBST(HAVE_SYSTEMD) ], +- [AC_MSG_ERROR([Could not detect systemd presence])] +- ) ++ [AC_MSG_ERROR([Could not detect systemd presence])]) + ]) + ++AS_IF([test x$HAVE_LIBSYSTEMD = xyes], ++ [login_lib_name=libsystemd], ++ [login_lib_name=libsystemd-login]) ++ + AM_COND_IF([HAVE_SYSTEMD], +- [PKG_CHECK_MODULES([SYSTEMD_LOGIN], [libsystemd-login], +- [AC_DEFINE_UNQUOTED(HAVE_SYSTEMD_LOGIN, 1, [Build with libsystemdlogin support])], +- [AC_MSG_NOTICE([Build without libsystemd-login support])])]) ++ [PKG_CHECK_MODULES([SYSTEMD_LOGIN], ++ [$login_lib_name], ++ [AC_DEFINE_UNQUOTED([HAVE_SYSTEMD_LOGIN], 1, ++ [Build with libsystemdlogin support]) ++ ], ++ [AC_MSG_NOTICE([Build without libsystemd-login support])])]) + + dnl A macro to check presence of journald on the system + AC_DEFUN([AM_CHECK_JOURNALD], + [ +- PKG_CHECK_MODULES(JOURNALD, +- libsystemd-journal, +- [AC_DEFINE_UNQUOTED([WITH_JOURNALD], 1, [journald is available])]) +- dnl Some older versions of pkg-config might not set these automatically +- dnl while setting CFLAGS and LIBS manually twice doesn't hurt. +- AC_SUBST([JOURNALD_CFLAGS]) +- AC_SUBST([JOURNALD_LIBS]) ++ AS_IF([test x$HAVE_LIBSYSTEMD = xyes], ++ [journal_lib_name=libsystemd], ++ [journal_lib_name=libsystemd-journal]) ++ ++ PKG_CHECK_MODULES(JOURNALD, [$journal_lib_name], ++ [AC_DEFINE_UNQUOTED([WITH_JOURNALD], 1, ++ [journald is available])]) ++ dnl Some older versions of pkg-config might not set these automatically ++ dnl while setting CFLAGS and LIBS manually twice doesn't hurt. ++ AC_SUBST([JOURNALD_CFLAGS]) ++ AC_SUBST([JOURNALD_LIBS]) + ]) +-- +2.5.0 + diff --git a/0004-SPEC-Workaround-for-build-with-rpm-4.13.patch b/0004-SPEC-Workaround-for-build-with-rpm-4.13.patch new file mode 100644 index 0000000..4aee307 --- /dev/null +++ b/0004-SPEC-Workaround-for-build-with-rpm-4.13.patch @@ -0,0 +1,36 @@ +From 5ad471f3523acc995f54a1058f4e99c8fc3cb8fa Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 31 Jul 2015 14:09:25 +0200 +Subject: [PATCH 04/21] SPEC: Workaround for build with rpm 4.13 + +If the tarball is generated with minimal dependencies extracted from spec file +then translated manual pages are not generated due to missing script po4a. +This step is not necessary for regular nightly/developer builds. +The tarball is created faster without such step. However rpm >= 4.13 +will fail due to empty manifest file. + +Resolves: +https://fedorahosted.org/sssd/ticket/2738 + +Reviewed-by: Jakub Hrozek +--- + contrib/sssd.spec.in | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in +index 2600438..0828bb8 100644 +--- a/contrib/sssd.spec.in ++++ b/contrib/sssd.spec.in +@@ -4,6 +4,9 @@ + # we don't want to provide private python extension libs + %define __provides_exclude_from %{python_sitearch}/.*\.so$ + ++# workaround for rpm 4.13 ++%define _empty_manifest_terminate_build 0 ++ + %if (0%{?fedora} || 0%{?rhel} >= 7) + %global use_systemd 1 + %endif +-- +2.5.0 + diff --git a/0005-CONFDB-Assume-config-file-version-2-if-missing.patch b/0005-CONFDB-Assume-config-file-version-2-if-missing.patch new file mode 100644 index 0000000..5d2ae74 --- /dev/null +++ b/0005-CONFDB-Assume-config-file-version-2-if-missing.patch @@ -0,0 +1,163 @@ +From 5249f1273a52040d30e3c7725a2ea84fdd158a4b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Tue, 7 Jul 2015 15:15:32 +0200 +Subject: [PATCH 05/21] CONFDB: Assume config file version 2 if missing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Default to config file version 2 if the version +is not specified explicitly. + +Ticket: +https://fedorahosted.org/sssd/ticket/2688 + +Reviewed-by: Lukáš Slebodník +--- + src/confdb/confdb.h | 1 + + src/confdb/confdb_setup.c | 48 ++++++++++++++-------------- + src/config/SSSDConfig/__init__.py.in | 5 --- + src/config/SSSDConfig/sssd_upgrade_config.py | 3 +- + src/config/SSSDConfigTest.py | 11 ++----- + 5 files changed, 29 insertions(+), 39 deletions(-) + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index e97c46b..68009fa 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -38,6 +38,7 @@ + * @{ + */ + ++#define CONFDB_DEFAULT_CFG_FILE_VER 2 + #define CONFDB_FILE "config.ldb" + #define CONFDB_DEFAULT_CONFIG_FILE SSSD_CONF_DIR"/sssd.conf" + #define SSSD_MIN_ID 1 +diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c +index 93a1a1b..694a7f0 100644 +--- a/src/confdb/confdb_setup.c ++++ b/src/confdb/confdb_setup.c +@@ -224,30 +224,30 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb) + + ret = sss_ini_check_config_obj(init_data); + if (ret != EOK) { +- /* No known version. Assumed to be version 1 */ +- DEBUG(SSSDBG_FATAL_FAILURE, +- "Config file is an old version. " +- "Please run configuration upgrade script.\n"); +- ret = EINVAL; +- goto done; +- } +- +- version = sss_ini_get_int_config_value(init_data, 1, -1, &ret); +- if (ret != EOK) { +- DEBUG(SSSDBG_FATAL_FAILURE, +- "Config file version could not be determined\n"); +- goto done; +- } else if (version < CONFDB_VERSION_INT) { +- DEBUG(SSSDBG_FATAL_FAILURE, +- "Config file is an old version. " +- "Please run configuration upgrade script.\n"); +- ret = EINVAL; +- goto done; +- } else if (version > CONFDB_VERSION_INT) { +- DEBUG(SSSDBG_FATAL_FAILURE, +- "Config file version is newer than confdb\n"); +- ret = EINVAL; +- goto done; ++ /* No known version. Use default. */ ++ DEBUG(SSSDBG_CONF_SETTINGS, ++ "Value of config_file_version option not found. " ++ "Assumed to be version %d.\n", CONFDB_DEFAULT_CFG_FILE_VER); ++ } else { ++ version = sss_ini_get_int_config_value(init_data, ++ CONFDB_DEFAULT_CFG_FILE_VER, ++ -1, &ret); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Config file version could not be determined\n"); ++ goto done; ++ } else if (version < CONFDB_VERSION_INT) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Config file is an old version. " ++ "Please run configuration upgrade script.\n"); ++ ret = EINVAL; ++ goto done; ++ } else if (version > CONFDB_VERSION_INT) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Config file version is newer than confdb\n"); ++ ret = EINVAL; ++ goto done; ++ } + } + + /* Set up a transaction to replace the configuration */ +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index d72b892..fc87a2b 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -731,11 +731,6 @@ class SSSDService(SSSDConfigObject): + # Set up default options for this service + self.options.update(self.schema.get_defaults(self.name)) + +- # For the [sssd] service, force the config file version +- if servicename == 'sssd': +- self.options['config_file_version'] = 2 +- self.hidden_options.append('config_file_version') +- + def list_options_with_mandatory(self): + """ + List options for the service, including the mandatory flag. +diff --git a/src/config/SSSDConfig/sssd_upgrade_config.py b/src/config/SSSDConfig/sssd_upgrade_config.py +index 282d6c4..767d06d 100644 +--- a/src/config/SSSDConfig/sssd_upgrade_config.py ++++ b/src/config/SSSDConfig/sssd_upgrade_config.py +@@ -47,7 +47,8 @@ class SSSDConfigFile(SSSDChangeConf): + def get_version(self): + ver = self.get_option_index('sssd', 'config_file_version')[1] + if not ver: +- return 1 ++ # config_file_version not found -> default to version 2 ++ return 2 + try: + return int(ver['value']) + except ValueError: +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index aed76e5..868d1a5 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -396,9 +396,6 @@ class SSSDConfigTestSSSDService(unittest.TestCase): + def testGetOption(self): + service = SSSDConfig.SSSDService('sssd', self.schema) + +- # Positive test - Single-valued +- self.assertEqual(service.get_option('config_file_version'), 2) +- + # Positive test - List of values + self.assertEqual(service.get_option('services'), ['nss', 'pam']) + +@@ -410,9 +407,7 @@ class SSSDConfigTestSSSDService(unittest.TestCase): + + #Positive test + options = service.get_all_options() +- control_list = [ +- 'config_file_version', +- 'services'] ++ control_list = ['services'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +@@ -1253,9 +1248,7 @@ class SSSDConfigTestSSSDConfig(unittest.TestCase): + for section in sssdconfig.sections(): + self.assertTrue(section['name'] in control_list) + +- control_list = [ +- 'config_file_version', +- 'services'] ++ control_list = ['services'] + for option in control_list: + self.assertTrue(sssdconfig.has_option('sssd', option), + "Option [%s] missing from [sssd]" % +-- +2.5.0 + diff --git a/0006-SYSDB-Index-the-objectSIDString-attribute.patch b/0006-SYSDB-Index-the-objectSIDString-attribute.patch new file mode 100644 index 0000000..7019ec3 --- /dev/null +++ b/0006-SYSDB-Index-the-objectSIDString-attribute.patch @@ -0,0 +1,134 @@ +From dab2f25c94a0f7509c10b42cfb98700c449e709c Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Thu, 25 Jun 2015 17:33:47 +0200 +Subject: [PATCH 06/21] SYSDB: Index the objectSIDString attribute +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Michal Židek +--- + src/db/sysdb.c | 7 +++++++ + src/db/sysdb_private.h | 5 ++++- + src/db/sysdb_upgrade.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 61 insertions(+), 1 deletion(-) + +diff --git a/src/db/sysdb.c b/src/db/sysdb.c +index 9da6557..07a83a8 100644 +--- a/src/db/sysdb.c ++++ b/src/db/sysdb.c +@@ -1265,6 +1265,13 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, + } + } + ++ if (strcmp(version, SYSDB_VERSION_0_16) == 0) { ++ ret = sysdb_upgrade_16(sysdb, &version); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ + /* The version should now match SYSDB_VERSION. + * If not, it means we didn't match any of the + * known older versions. The DB might be +diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h +index 8a5b8be..9788206 100644 +--- a/src/db/sysdb_private.h ++++ b/src/db/sysdb_private.h +@@ -23,6 +23,7 @@ + #ifndef __INT_SYS_DB_H__ + #define __INT_SYS_DB_H__ + ++#define SYSDB_VERSION_0_17 "0.17" + #define SYSDB_VERSION_0_16 "0.16" + #define SYSDB_VERSION_0_15 "0.15" + #define SYSDB_VERSION_0_14 "0.14" +@@ -40,7 +41,7 @@ + #define SYSDB_VERSION_0_2 "0.2" + #define SYSDB_VERSION_0_1 "0.1" + +-#define SYSDB_VERSION SYSDB_VERSION_0_16 ++#define SYSDB_VERSION SYSDB_VERSION_0_17 + + #define SYSDB_BASE_LDIF \ + "dn: @ATTRIBUTES\n" \ +@@ -68,6 +69,7 @@ + "@IDXATTR: serviceProtocol\n" \ + "@IDXATTR: sudoUser\n" \ + "@IDXATTR: sshKnownHostsExpire\n" \ ++ "@IDXATTR: objectSIDString\n" \ + "@IDXONE: 1\n" \ + "\n" \ + "dn: @MODULES\n" \ +@@ -120,6 +122,7 @@ int sysdb_upgrade_12(struct sysdb_ctx *sysdb, const char **ver); + int sysdb_upgrade_13(struct sysdb_ctx *sysdb, const char **ver); + int sysdb_upgrade_14(struct sysdb_ctx *sysdb, const char **ver); + int sysdb_upgrade_15(struct sysdb_ctx *sysdb, const char **ver); ++int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver); + + int add_string(struct ldb_message *msg, int flags, + const char *attr, const char *value); +diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c +index 558b4f5..1c90e7a 100644 +--- a/src/db/sysdb_upgrade.c ++++ b/src/db/sysdb_upgrade.c +@@ -1587,6 +1587,56 @@ done: + return ret; + } + ++int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver) ++{ ++ struct ldb_message *msg; ++ struct upgrade_ctx *ctx; ++ errno_t ret; ++ ++ ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_17, &ctx); ++ if (ret) { ++ return ret; ++ } ++ ++ msg = ldb_msg_new(ctx); ++ if (msg == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST"); ++ if (msg->dn == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ /* add index for objectSIDString */ ++ ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); ++ if (ret != LDB_SUCCESS) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = ldb_msg_add_string(msg, "@IDXATTR", "objectSIDString"); ++ if (ret != LDB_SUCCESS) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = ldb_modify(sysdb->ldb, msg); ++ if (ret != LDB_SUCCESS) { ++ ret = sysdb_error_to_errno(ret); ++ goto done; ++ } ++ ++ /* conversion done, update version number */ ++ ret = update_version(ctx); ++ ++done: ++ ret = finish_upgrade(ret, &ctx, ver); ++ return ret; ++} ++ + /* + * Example template for future upgrades. + * Copy and change version numbers as appropriate. +-- +2.5.0 + diff --git a/0007-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch b/0007-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch new file mode 100644 index 0000000..01224b5 --- /dev/null +++ b/0007-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch @@ -0,0 +1,89 @@ +From b93b4ac9b0d9f7900ffffe67765613e2057ac63a Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 21 Jul 2015 11:44:03 +0200 +Subject: [PATCH 07/21] IPA: Remove MPG groups if getgrgid was called before + getpw() + +https://fedorahosted.org/sssd/ticket/2724 + +This bug only affects IPA clients that are connected to IPA servers with +AD trust and ID mapping in effect. + +If an IPA client calls getgrgid() for an ID that matches a user, the +user's private group would be returned and stored as a group entry. + +Subsequent queries for that user would fail, because MPG domains impose +uniqueness restriction for both the ID and name space across groups and +users. + +To work around that, we remove the UPG groups in MPG domains during a +group lookup. + +Reviewed-by: Sumit Bose +(cherry picked from commit 6fe057efb981ee4b45dcadf131c03f8501fce28d) +--- + src/providers/ipa/ipa_s2n_exop.c | 41 ++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 39 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c +index fa00691..08d8263 100644 +--- a/src/providers/ipa/ipa_s2n_exop.c ++++ b/src/providers/ipa/ipa_s2n_exop.c +@@ -1768,6 +1768,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, + int tret; + struct sysdb_attrs *gid_override_attrs = NULL; + char ** exop_grouplist; ++ struct ldb_message *msg; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { +@@ -2009,8 +2010,44 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, + attrs->a.user.pw_dir, attrs->a.user.pw_shell, + NULL, attrs->sysdb_attrs, NULL, + timeout, now); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_user failed.\n"); ++ if (ret == EEXIST && dom->mpg == true) { ++ /* This handles the case where getgrgid() was called for ++ * this user, so a group was created in the cache ++ */ ++ ret = sysdb_search_group_by_name(tmp_ctx, dom, name, NULL, &msg); ++ if (ret != EOK) { ++ /* Fail even on ENOENT, the group must be around */ ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Could not delete MPG group [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ ret = sysdb_delete_group(dom, NULL, attrs->a.user.pw_uid); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_delete_group failed for MPG group [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ ret = sysdb_store_user(dom, name, NULL, ++ attrs->a.user.pw_uid, ++ gid, attrs->a.user.pw_gecos, ++ attrs->a.user.pw_dir, ++ attrs->a.user.pw_shell, ++ NULL, attrs->sysdb_attrs, NULL, ++ timeout, now); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_store_user failed for MPG user [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ } else if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_store_user failed [%d]: %s\n", ++ ret, sss_strerror(ret)); + goto done; + } + +-- +2.5.0 + diff --git a/0008-SPEC-Update-spec-file-for-krb5_local_auth_plugin.patch b/0008-SPEC-Update-spec-file-for-krb5_local_auth_plugin.patch new file mode 100644 index 0000000..9b0ab01 --- /dev/null +++ b/0008-SPEC-Update-spec-file-for-krb5_local_auth_plugin.patch @@ -0,0 +1,56 @@ +From ec0696be5f28804fefe61f8cfaf5d82e8d72f8a6 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 24 Jul 2015 09:24:31 +0200 +Subject: [PATCH 08/21] SPEC: Update spec file for krb5_local_auth_plugin + +krb5_localauth_plugin could be build only with MIT kerberos >= 1.12. +However, this feature was backported in downstream to older version +of kerberos. So there were packaging failures + +error: Installed (but unpackaged) file(s) found: + /usr/lib/sssd/modules/sssd_krb5_localauth_plugin.so +RPM build errors: + Installed (but unpackaged) file(s) found: + /usr/lib/sssd/modules/sssd_krb5_localauth_plugin.so +Child returncode was: 1 +EXCEPTION: Command failed. See logs for output. + +Reviewed-by: Petr Cech +(cherry picked from commit b0ee27fd94f1d20d9c220754ae008a3189752287) +--- + contrib/sssd.spec.in | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in +index 0828bb8..bad078a 100644 +--- a/contrib/sssd.spec.in ++++ b/contrib/sssd.spec.in +@@ -1,3 +1,4 @@ ++%global rhel6_minor %(%{__grep} -o "6.[0-9]*" /etc/redhat-release |%{__sed} -s 's/6.//') + %global rhel7_minor %(%{__grep} -o "7.[0-9]*" /etc/redhat-release |%{__sed} -s 's/7.//') + + # Fedora and RHEL 6+ +@@ -37,7 +38,7 @@ + %global with_cifs_utils_plugin_option --disable-cifs-idmap-plugin + %endif + +-%if (0%{?fedora} >= 21 || (0%{?rhel} == 7 && 0%{?rhel7_minor} >= 1)) ++%if (0%{?fedora} || (0%{?rhel} == 7 && 0%{?rhel7_minor} >= 1) || (0%{?rhel} == 6 && 0%{?rhel6_minor} >= 7)) + %global with_krb5_localauth_plugin 1 + %endif + +@@ -96,11 +97,7 @@ BuildRequires: pcre-devel + BuildRequires: libxslt + BuildRequires: libxml2 + BuildRequires: docbook-style-xsl +-%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 +-- +2.5.0 + diff --git a/0009-LDAP-Sanitize-group-dn-before-using-in-filter.patch b/0009-LDAP-Sanitize-group-dn-before-using-in-filter.patch new file mode 100644 index 0000000..7e200c9 --- /dev/null +++ b/0009-LDAP-Sanitize-group-dn-before-using-in-filter.patch @@ -0,0 +1,69 @@ +From 4cbf713b41ae368bc03c1b469e2bb0f568545c82 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Tue, 1 Sep 2015 06:58:50 +0200 +Subject: [PATCH 09/21] LDAP: Sanitize group dn before using in filter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Each string should be sanitized(rfc4515) before using ldbsearch. +A group dn was not sanitized in the function cleanup_groups. + +Resolves: +https://fedorahosted.org/sssd/ticket/2744 + +Reviewed-by: Pavel Březina +(cherry picked from commit 6cb5bad3c8e2f35ca9dce1800a506d626f90c079) +--- + src/providers/ldap/ldap_id_cleanup.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ldap/ldap_id_cleanup.c b/src/providers/ldap/ldap_id_cleanup.c +index 171c9b0..73e5e6f 100644 +--- a/src/providers/ldap/ldap_id_cleanup.c ++++ b/src/providers/ldap/ldap_id_cleanup.c +@@ -359,6 +359,8 @@ static int cleanup_groups(TALLOC_CTX *memctx, + } + + for (i = 0; i < count; i++) { ++ char *sanitized_dn; ++ + dn = ldb_dn_get_linearized(msgs[i]->dn); + if (!dn) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot linearize DN!\n"); +@@ -366,6 +368,15 @@ static int cleanup_groups(TALLOC_CTX *memctx, + goto done; + } + ++ /* sanitize dn */ ++ ret = sss_filter_sanitize(tmpctx, dn, &sanitized_dn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "sss_filter_sanitize failed: %s:[%d]\n", ++ sss_strerror(ret), ret); ++ goto done; ++ } ++ + posix = ldb_msg_find_attr_as_string(msgs[i], SYSDB_POSIX, NULL); + if (!posix || strcmp(posix, "TRUE") == 0) { + /* Search for users that are members of this group, or +@@ -375,11 +386,14 @@ static int cleanup_groups(TALLOC_CTX *memctx, + gid = (gid_t) ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0); + subfilter = talloc_asprintf(tmpctx, "(&(%s=%s)(|(%s=%s)(%s=%lu)))", + SYSDB_OBJECTCLASS, SYSDB_USER_CLASS, +- SYSDB_MEMBEROF, dn, ++ SYSDB_MEMBEROF, sanitized_dn, + SYSDB_GIDNUM, (long unsigned) gid); + } else { +- subfilter = talloc_asprintf(tmpctx, "(%s=%s)", SYSDB_MEMBEROF, dn); ++ subfilter = talloc_asprintf(tmpctx, "(%s=%s)", SYSDB_MEMBEROF, ++ sanitized_dn); + } ++ talloc_zfree(sanitized_dn); ++ + if (!subfilter) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to build filter\n"); + ret = ENOMEM; +-- +2.5.0 + diff --git a/0010-tests-check-special-characters-in-cleanup_groups.patch b/0010-tests-check-special-characters-in-cleanup_groups.patch new file mode 100644 index 0000000..b224640 --- /dev/null +++ b/0010-tests-check-special-characters-in-cleanup_groups.patch @@ -0,0 +1,380 @@ +From 562ee3c30bcb7d1997889c38f15eb2ef889ba7b1 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Tue, 4 Aug 2015 09:25:08 -0400 +Subject: [PATCH 10/21] tests: check special characters in cleanup_groups + +Based on commits: +e2e334b2f51118cb14c7391c4e4e44ff247ef638 +f02b62138466c876f6e8d6382769105f2e920d96 +e0f2a783439fb7d3b85469f34ad6d672abf7e1fa +2cec08a3174bff951c048c57b4b0e4517ad6b7b1 +--- + Makefile.am | 22 +++ + src/tests/cmocka/test_ldap_id_cleanup.c | 315 ++++++++++++++++++++++++++++++++ + 2 files changed, 337 insertions(+) + create mode 100644 src/tests/cmocka/test_ldap_id_cleanup.c + +diff --git a/Makefile.am b/Makefile.am +index ac6a358..91ad413 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -212,6 +212,7 @@ if HAVE_CMOCKA + sbus-internal-tests \ + sss_sifp-tests \ + test_search_bases \ ++ test_ldap_id_cleanup \ + sdap-tests \ + test_sysdb_views \ + test_sysdb_utils \ +@@ -1969,6 +1970,27 @@ test_search_bases_LDADD = \ + libsss_krb5_common.la \ + libsss_test_common.la + ++test_ldap_id_cleanup_SOURCES = \ ++ $(sssd_be_SOURCES) \ ++ src/tests/cmocka/test_ldap_id_cleanup.c \ ++ src/providers/ldap/ldap_id_cleanup.c \ ++ $(NULL) ++test_ldap_id_cleanup_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ -DUNIT_TESTING ++ $(NULL) ++test_ldap_id_cleanup_LDADD = \ ++ $(PAM_LIBS) \ ++ $(CMOCKA_LIBS) \ ++ $(POPT_LIBS) \ ++ $(SSSD_LIBS) \ ++ $(CARES_LIBS) \ ++ $(KRB5_LIBS) \ ++ $(SSSD_INTERNAL_LTLIBS) \ ++ libsss_ldap_common.la \ ++ libsss_test_common.la \ ++ $(NULL) ++ + ad_access_filter_tests_SOURCES = \ + $(sssd_be_SOURCES) \ + src/providers/ad/ad_common.c \ +diff --git a/src/tests/cmocka/test_ldap_id_cleanup.c b/src/tests/cmocka/test_ldap_id_cleanup.c +new file mode 100644 +index 0000000..9578bb7 +--- /dev/null ++++ b/src/tests/cmocka/test_ldap_id_cleanup.c +@@ -0,0 +1,315 @@ ++/* ++ Authors: ++ Pavel Reichl ++ ++ Copyright (C) 2015 Red Hat ++ ++ SSSD tests - id cleanup ++ ++ 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 "tests/cmocka/common_mock.h" ++#include "providers/ldap/ldap_auth.h" ++#include "providers/ldap/ldap_common.h" ++#include "providers/ldap/ldap_opts.h" ++#include "providers/ipa/ipa_opts.h" ++ ++#define TESTS_PATH "tests_ldap_id_cleanup" ++#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; ++ struct sdap_options *opts; ++}; ++ ++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->domain->has_views = true; ++ test_ctx->sysdb = test_ctx->domain->sysdb; ++ ++ *ctx = test_ctx; ++ return EOK; ++} ++ ++#define setup_sysdb_tests(ctx) _setup_sysdb_tests((ctx), false) ++ ++static int 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); ++ ++ test_ctx->domain->mpg = false; ++ ++ /* set options */ ++ test_ctx->opts = talloc_zero(test_ctx, struct sdap_options); ++ assert_non_null(test_ctx->opts); ++ ++ ret = sdap_copy_map(test_ctx->opts, rfc2307_user_map, ++ SDAP_OPTS_USER, &test_ctx->opts->user_map); ++ assert_int_equal(ret, ERR_OK); ++ ++ ret = dp_copy_defaults(test_ctx->opts, default_basic_opts, ++ SDAP_OPTS_BASIC, &test_ctx->opts->basic); ++ assert_int_equal(ret, ERR_OK); ++ ++ dp_opt_set_int(test_ctx->opts->basic, SDAP_ACCOUNT_CACHE_EXPIRATION, 1); ++ ++ *state = (void *) test_ctx; ++ return 0; ++} ++ ++static int 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()); ++ return 0; ++} ++ ++static errno_t invalidate_group(TALLOC_CTX *ctx, ++ struct sss_domain_info *domain, ++ const char *name) ++{ ++ struct sysdb_attrs *sys_attrs = NULL; ++ errno_t ret; ++ ++ sys_attrs = sysdb_new_attrs(ctx); ++ if (sys_attrs) { ++ ret = sysdb_attrs_add_time_t(sys_attrs, ++ SYSDB_CACHE_EXPIRE, 1); ++ if (ret == EOK) { ++ ret = sysdb_set_group_attr(domain, name, sys_attrs, ++ SYSDB_MOD_REP); ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Could not add expiration time to attributes\n"); ++ } ++ talloc_zfree(sys_attrs); ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, "Could not create sysdb attributes\n"); ++ ret = ENOMEM; ++ } ++ return ret; ++} ++ ++static void test_id_cleanup_exp_group(void **state) ++{ ++ errno_t ret; ++ struct ldb_message *msg; ++ struct sdap_domain sdom; ++ const char *special_grp = "special_gr*o/u\\p(2016)"; ++ const char *empty_special_grp = "empty_gr*o/u\\p(2016)"; ++ const char *empty_grp = "empty_grp"; ++ const char *grp = "grp"; ++ /* This timeout can be bigger because we will call invalidate_group ++ * to expire entries without waiting. */ ++ const uint64_t CACHE_TIMEOUT = 30; ++ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, ++ struct sysdb_test_ctx); ++ ++ ret = sysdb_store_group(test_ctx->domain, special_grp, ++ 10002, NULL, CACHE_TIMEOUT, 0); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_store_group(test_ctx->domain, empty_special_grp, ++ 10003, NULL, CACHE_TIMEOUT, 0); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_store_group(test_ctx->domain, grp, ++ 10004, NULL, CACHE_TIMEOUT, 0); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_store_group(test_ctx->domain, empty_grp, ++ 10005, NULL, CACHE_TIMEOUT, 0); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_store_user(test_ctx->domain, "test_user", NULL, ++ 10001, 10002, "Test user", ++ NULL, NULL, NULL, NULL, NULL, ++ 0, 0); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_store_user(test_ctx->domain, "test_user2", NULL, ++ 10002, 10004, "Test user", ++ NULL, NULL, NULL, NULL, NULL, ++ 0, 0); ++ assert_int_equal(ret, EOK); ++ ++ sdom.dom = test_ctx->domain; ++ ++ /* not expired */ ++ ret = ldap_id_cleanup(test_ctx->opts, &sdom); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ special_grp, NULL, &msg); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ empty_special_grp, NULL, &msg); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ grp, NULL, &msg); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ empty_grp, NULL, &msg); ++ assert_int_equal(ret, EOK); ++ ++ /* let records to expire */ ++ invalidate_group(test_ctx, test_ctx->domain, special_grp); ++ invalidate_group(test_ctx, test_ctx->domain, empty_special_grp); ++ invalidate_group(test_ctx, test_ctx->domain, grp); ++ invalidate_group(test_ctx, test_ctx->domain, empty_grp); ++ ++ ret = ldap_id_cleanup(test_ctx->opts, &sdom); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ special_grp, NULL, &msg); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ empty_special_grp, NULL, &msg); ++ assert_int_equal(ret, ENOENT); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ grp, NULL, &msg); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_search_group_by_name(test_ctx, test_ctx->domain, ++ empty_grp, NULL, &msg); ++ assert_int_equal(ret, ENOENT); ++} ++ ++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 struct CMUnitTest tests[] = { ++ cmocka_unit_test_setup_teardown(test_id_cleanup_exp_group, ++ 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(); ++ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_FILE, LOCAL_SYSDB_FILE); ++ test_dom_suite_setup(TESTS_PATH); ++ rv = cmocka_run_group_tests(tests, NULL, NULL); ++ ++ if (rv == 0 && no_cleanup == 0) { ++ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_FILE, LOCAL_SYSDB_FILE); ++ } ++ return rv; ++} +-- +2.5.0 + diff --git a/0002-Fix-memory-leak-in-sssdpac_verify.patch b/0011-Fix-memory-leak-in-sssdpac_verify.patch similarity index 76% rename from 0002-Fix-memory-leak-in-sssdpac_verify.patch rename to 0011-Fix-memory-leak-in-sssdpac_verify.patch index 1d0da91..796ffcd 100644 --- a/0002-Fix-memory-leak-in-sssdpac_verify.patch +++ b/0011-Fix-memory-leak-in-sssdpac_verify.patch @@ -1,19 +1,18 @@ -From 8812a6f98573247653ab5e4a2bab2ea3cac60e99 Mon Sep 17 00:00:00 2001 +From 41a77e02689b48d0a3627b3fae97741ff49fa06f Mon Sep 17 00:00:00 2001 From: Thomas Oulevey Date: Wed, 23 Sep 2015 10:55:59 +0200 -Subject: [PATCH 2/3] Fix memory leak in sssdpac_verify() +Subject: [PATCH 11/21] Fix memory leak in sssdpac_verify() Resolves https://fedorahosted.org/sssd/ticket/2803 Reviewed-by: Sumit Bose (cherry picked from commit b4c44ebb8997d3debb33607c123ccfd9926e0cba) -(cherry picked from commit d6073c978b0aac897aee648670fa6b69503ae676) --- src/sss_client/sssd_pac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sss_client/sssd_pac.c b/src/sss_client/sssd_pac.c -index d1790df50465772e1f310f84e7e6b0e364192720..8b5bb3295f18c33bc22dbb65df3ef4cebbc6aaea 100644 +index d1790df..8b5bb32 100644 --- a/src/sss_client/sssd_pac.c +++ b/src/sss_client/sssd_pac.c @@ -150,6 +150,9 @@ static krb5_error_code sssdpac_verify(krb5_context kcontext, diff --git a/0012-SDAP-Relax-POSIX-check.patch b/0012-SDAP-Relax-POSIX-check.patch new file mode 100644 index 0000000..761b780 --- /dev/null +++ b/0012-SDAP-Relax-POSIX-check.patch @@ -0,0 +1,57 @@ +From b87a8ad335503759f1542d3e1466476860c85a19 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Tue, 22 Sep 2015 04:41:18 -0400 +Subject: [PATCH 12/21] SDAP: Relax POSIX check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Relax the check on UID or GID just to check if at least one of them is +present but do not require them to be positive numbers. + +Add requirement on objectclass attributes to be user or group to make +check more reliable. + +Resolves: +https://fedorahosted.org/sssd/ticket/2800 +(cherry picked from commit 6735c0451d4e80d7cd4b480a8c1f7dafb2b536ea) + +Reviewed-by: Pavel Březina +(cherry picked from commit cc04876ec64b338f61ca275386f70baf91ce700f) +--- + src/providers/ldap/sdap_async.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c +index c30a457..006aa49 100644 +--- a/src/providers/ldap/sdap_async.c ++++ b/src/providers/ldap/sdap_async.c +@@ -2373,9 +2373,12 @@ sdap_posix_check_send(TALLOC_CTX *memctx, struct tevent_context *ev, + state->attrs[2] = opts->group_map[SDAP_AT_GROUP_GID].name; + state->attrs[3] = NULL; + +- state->filter = talloc_asprintf(state, "(|(%s=*)(%s=*))", ++ state->filter = talloc_asprintf(state, ++ "(|(&(%s=*)(objectclass=%s))(&(%s=*)(objectclass=%s)))", + opts->user_map[SDAP_AT_USER_UID].name, +- opts->group_map[SDAP_AT_GROUP_GID].name); ++ opts->user_map[SDAP_OC_USER].name, ++ opts->group_map[SDAP_AT_GROUP_GID].name, ++ opts->group_map[SDAP_OC_GROUP].name); + if (state->filter == NULL) { + ret = ENOMEM; + goto fail; +@@ -2458,9 +2461,8 @@ static errno_t sdap_posix_check_parse(struct sdap_handle *sh, + errno = 0; + strtouint32(vals[0]->bv_val, &endptr, 10); + if (errno || *endptr || (vals[0]->bv_val == endptr)) { +- DEBUG(SSSDBG_OP_FAILURE, ++ DEBUG(SSSDBG_MINOR_FAILURE, + "POSIX attribute is not a number: %s\n", vals[0]->bv_val); +- goto done; + } + + state->has_posix = true; +-- +2.5.0 + diff --git a/0003-GPO-fix-memory-leak.patch b/0013-GPO-fix-memory-leak.patch similarity index 83% rename from 0003-GPO-fix-memory-leak.patch rename to 0013-GPO-fix-memory-leak.patch index d064f54..b3b0683 100644 --- a/0003-GPO-fix-memory-leak.patch +++ b/0013-GPO-fix-memory-leak.patch @@ -1,7 +1,7 @@ -From 93dfb8c8968b871ff453c59356d0f77d4f910ca9 Mon Sep 17 00:00:00 2001 +From 6765f6226d293c30aa798ecb64c5d4826d7dfb2f Mon Sep 17 00:00:00 2001 From: Pavel Reichl Date: Thu, 3 Sep 2015 04:46:50 -0400 -Subject: [PATCH 3/3] GPO: fix memory leak +Subject: [PATCH 13/21] GPO: fix memory leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -11,13 +11,12 @@ https://fedorahosted.org/sssd/ticket/2777 Reviewed-by: Michal Židek (cherry picked from commit 5dbdcc2c7210a0e3eb60ad1e85ba33f27d7faeda) -(cherry picked from commit 4a89c2ebbe2a98e790536165486ecf2d14836e69) --- src/providers/ad/ad_gpo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c -index af864dfbe021438feceffd610cc0ad2b69ca670a..bde810a38b42afc77fd350a999c6500bed1b269f 100644 +index af864df..bde810a 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -557,14 +557,14 @@ ad_gpo_get_sids(TALLOC_CTX *mem_ctx, diff --git a/0014-nss-fix-UPN-lookups-for-sub-domain-users.patch b/0014-nss-fix-UPN-lookups-for-sub-domain-users.patch new file mode 100644 index 0000000..8dd4367 --- /dev/null +++ b/0014-nss-fix-UPN-lookups-for-sub-domain-users.patch @@ -0,0 +1,63 @@ +From 72315a4706e32001b9034b95ab7359a5ae92bc70 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 7 Oct 2015 15:22:34 +0200 +Subject: [PATCH 14/21] nss: fix UPN lookups for sub-domain users +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves https://fedorahosted.org/sssd/ticket/2827 + +Reviewed-by: Pavel Březina +--- + src/db/sysdb_ops.c | 3 +-- + src/responder/nss/nsssrv_cmd.c | 12 ++++++++++-- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index ea786d5..34f1832 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -494,8 +494,7 @@ int sysdb_search_user_by_upn(TALLOC_CTX *mem_ctx, + return ENOMEM; + } + +- basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, +- SYSDB_TMPL_USER_BASE, domain->name); ++ basedn = sysdb_base_dn(domain->sysdb, tmp_ctx); + if (basedn == NULL) { + ret = ENOMEM; + goto done; +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index 12134ce..4285473 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -849,7 +849,11 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + name, dom->name); + /* if a multidomain search, try with next */ + if (cmdctx->check_next) { +- dom = get_next_domain(dom, false); ++ if (cmdctx->name_is_upn) { ++ dom = get_next_domain(dom, true); ++ } else { ++ dom = get_next_domain(dom, false); ++ } + continue; + } + /* There are no further domains or this was a +@@ -924,7 +928,11 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + + /* if a multidomain search, try with next */ + if (cmdctx->check_next) { +- dom = get_next_domain(dom, false); ++ if (cmdctx->name_is_upn) { ++ dom = get_next_domain(dom, true); ++ } else { ++ dom = get_next_domain(dom, false); ++ } + if (dom) continue; + } + +-- +2.5.0 + diff --git a/0015-SSSDConfig-Do-not-raise-exception-if-config_file_ver.patch b/0015-SSSDConfig-Do-not-raise-exception-if-config_file_ver.patch new file mode 100644 index 0000000..50f72c2 --- /dev/null +++ b/0015-SSSDConfig-Do-not-raise-exception-if-config_file_ver.patch @@ -0,0 +1,58 @@ +From d1047cceb993b1e4c0ae3901f709ac17819423cf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Thu, 15 Oct 2015 18:53:37 +0200 +Subject: [PATCH 15/21] SSSDConfig: Do not raise exception if + config_file_version is missing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ticket: +https://fedorahosted.org/sssd/ticket/2837 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 6a044fa43d53638c1d0b874d43f58c0428820362) +(cherry picked from commit a2363aa5984a707b8834816ea8538fe7de250a63) +--- + src/config/SSSDConfig/__init__.py.in | 8 ++++---- + src/config/SSSDConfigTest.py | 5 ----- + 2 files changed, 4 insertions(+), 9 deletions(-) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index fc87a2b..626d0c7 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -1397,10 +1397,10 @@ class SSSDConfig(SSSDChangeConf): + try: + if int(self.get('sssd', 'config_file_version')) != self.API_VERSION: + raise ParsingError("Wrong config_file_version") +- except: +- # Either the 'sssd' section or the 'config_file_version' was not +- # present in the config file +- raise ParsingError("File contains no config_file_version") ++ except TypeError: ++ # This happens when config_file_version is missing. We ++ # can assume it is the default version and continue. ++ pass + + def new_config(self): + """ +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 868d1a5..d303312 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -1213,11 +1213,6 @@ class SSSDConfigTestSSSDConfig(unittest.TestCase): + srcdir + "/etc/sssd.api.d") + self.assertRaises(SSSDConfig.ParsingError, sssdconfig.import_config, srcdir + "/testconfigs/sssd-badversion.conf") + +- # Negative Test - No config file version +- sssdconfig = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", +- srcdir + "/etc/sssd.api.d") +- self.assertRaises(SSSDConfig.ParsingError, sssdconfig.import_config, srcdir + "/testconfigs/sssd-noversion.conf") +- + # Negative Test - Already initialized + sssdconfig = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", + srcdir + "/etc/sssd.api.d") +-- +2.5.0 + diff --git a/0016-SSSDConfigTest-Try-load-saved-config.patch b/0016-SSSDConfigTest-Try-load-saved-config.patch new file mode 100644 index 0000000..8325f9b --- /dev/null +++ b/0016-SSSDConfigTest-Try-load-saved-config.patch @@ -0,0 +1,60 @@ +From 4e0a4a355c4f158f9e7b8e7cbac2f7d0378650a4 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Thu, 15 Oct 2015 10:32:09 +0200 +Subject: [PATCH 16/21] SSSDConfigTest: Try load saved config +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Python module SSSDConfig should be able to save configuration file +and later load the same configuration file without problem. + +Unit test for: +https://fedorahosted.org/sssd/ticket/2837 + +Reviewed-by: Michal Židek +(cherry picked from commit 87ef67286b64af98d32a3a5abcd28a9c2886f751) +(cherry picked from commit 69612bc5d0a9219ecccf3e8c6410059322aeecc6) +--- + src/config/SSSDConfigTest.py | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index d303312..7bad874 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -150,10 +150,14 @@ class SSSDConfigTestValid(unittest.TestCase): + #non-owners, and should not be executable by anyone + self.assertFalse(S_IMODE(mode) & 0o177) + ++ # try to import saved configuration file ++ config = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", ++ srcdir + "/etc/sssd.api.d") ++ config.import_config(configfile=of) ++ + #Remove the output file + os.unlink(of) + +- + def testCreateNewLDAPConfig(self): + sssdconfig = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", + srcdir + "/etc/sssd.api.d") +@@ -184,9 +188,15 @@ class SSSDConfigTestValid(unittest.TestCase): + #non-owners, and should not be executable by anyone + self.assertFalse(S_IMODE(mode) & 0o177) + ++ # try to import saved configuration file ++ config = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", ++ srcdir + "/etc/sssd.api.d") ++ config.import_config(configfile=of) ++ + #Remove the output file + os.unlink(of) + ++ + def testModifyExistingConfig(self): + sssdconfig = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", + srcdir + "/etc/sssd.api.d") +-- +2.5.0 + diff --git a/0017-SSSDConfigTest-Test-real-config-without-config_file_.patch b/0017-SSSDConfigTest-Test-real-config-without-config_file_.patch new file mode 100644 index 0000000..01080c3 --- /dev/null +++ b/0017-SSSDConfigTest-Test-real-config-without-config_file_.patch @@ -0,0 +1,151 @@ +From 523ed0ff50c2832e046fc87789561149e701e262 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Thu, 15 Oct 2015 11:04:06 +0200 +Subject: [PATCH 17/21] SSSDConfigTest: Test real config without + config_file_version +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +src/config/testconfigs/sssd-valid.conf explicitly contains +config_file_version. Recently we changed the default value to 2 +and therefore it needn't be listed in configuration file. +This patch test real sssd.conf without config_file_version. + +Reviewed-by: Michal Židek +(cherry picked from commit 7388fc91bd6c22705e60632346ec815f4a4963f1) +(cherry picked from commit b1c6767617c082de2521976175bc2f499ec295e9) +--- + src/config/SSSDConfigTest.py | 85 ++++++++++++++++++++++++++++++ + src/config/testconfigs/sssd-noversion.conf | 22 ++++++++ + 2 files changed, 107 insertions(+) + +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 7bad874..98101f6 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -1230,6 +1230,91 @@ class SSSDConfigTestSSSDConfig(unittest.TestCase): + self.assertRaises(SSSDConfig.AlreadyInitializedError, + sssdconfig.import_config, srcdir + "/testconfigs/sssd-valid.conf") + ++ def testImportConfigNoVersion(self): ++ # Positive Test ++ sssdconfig = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", ++ srcdir + "/etc/sssd.api.d") ++ sssdconfig.import_config( ++ srcdir + "/testconfigs/sssd-noversion.conf" ++ ) ++ ++ # Validate services ++ services = sssdconfig.list_services() ++ self.assertTrue('sssd' in services) ++ self.assertTrue('nss' in services) ++ self.assertTrue('pam' in services) ++ self.assertTrue('dp' in services) ++ ++ #Verify service attributes ++ sssd_service = sssdconfig.get_service('sssd') ++ service_opts = sssd_service.list_options() ++ ++ self.assertTrue('services' in service_opts.keys()) ++ service_list = sssd_service.get_option('services') ++ self.assertTrue('nss' in service_list) ++ self.assertTrue('pam' in service_list) ++ self.assertTrue('reconnection_retries' in service_opts) ++ ++ #Validate domain list ++ domains = sssdconfig.list_domains() ++ self.assertTrue('LOCAL' in domains) ++ self.assertTrue('LDAP' in domains) ++ self.assertTrue('PROXY' in domains) ++ self.assertTrue('IPA' in domains) ++ ++ # Verify domain attributes ++ ipa_domain = sssdconfig.get_domain('IPA') ++ domain_opts = ipa_domain.list_options() ++ self.assertTrue('debug_level' in domain_opts.keys()) ++ self.assertTrue('id_provider' in domain_opts.keys()) ++ self.assertTrue('auth_provider' in domain_opts.keys()) ++ ++ # Verify domain attributes ++ proxy_domain = sssdconfig.get_domain('PROXY') ++ domain_opts = proxy_domain.list_options() ++ self.assertTrue('debug_level' in domain_opts.keys()) ++ self.assertTrue('id_provider' in domain_opts.keys()) ++ self.assertTrue('auth_provider' in domain_opts.keys()) ++ ++ # Verify domain attributes ++ local_domain = sssdconfig.get_domain('LOCAL') ++ domain_opts = local_domain.list_options() ++ self.assertTrue('debug_level' in domain_opts.keys()) ++ self.assertTrue('id_provider' in domain_opts.keys()) ++ self.assertTrue('auth_provider' in domain_opts.keys()) ++ ++ # Verify domain attributes ++ ldap_domain = sssdconfig.get_domain('LDAP') ++ domain_opts = ldap_domain.list_options() ++ self.assertTrue('debug_level' in domain_opts.keys()) ++ self.assertTrue('id_provider' in domain_opts.keys()) ++ self.assertTrue('auth_provider' in domain_opts.keys()) ++ ++ domain_control_list = [ ++ 'cache_credentials', ++ 'id_provider', ++ 'auth_provider', ++ 'access_provider', ++ 'default_shell', ++ 'fallback_homedir', ++ 'cache_credentials', ++ 'use_fully_qualified_names', ++ ] ++ ++ ad_domain = sssdconfig.get_domain("ad.example.com") ++ ++ for option in ad_domain.get_all_options(): ++ self.assertTrue(option in domain_control_list) ++ ++ negative_domain_control_list = [ ++ 'ad_server', ++ 'ldap_id_mapping', ++ 'ldap_sasl_authid', ++ ] ++ ++ for option in ad_domain.get_all_options(): ++ self.assertFalse(option in negative_domain_control_list) ++ + def testNewConfig(self): + # Positive Test + sssdconfig = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", +diff --git a/src/config/testconfigs/sssd-noversion.conf b/src/config/testconfigs/sssd-noversion.conf +index 71af85c..d5f524d 100644 +--- a/src/config/testconfigs/sssd-noversion.conf ++++ b/src/config/testconfigs/sssd-noversion.conf +@@ -39,3 +39,25 @@ debug_level = 0 + [dp] + debug_level = 0 + ++[domain/ad.example.com] ++cache_credentials = true ++ ++id_provider = ad ++auth_provider = ad ++access_provider = ad ++ ++# Uncomment if service discovery is not working ++# ad_server = server.ad.example.com ++ ++# Uncomment if you want to use POSIX UIDs and GIDs set on the AD side ++# ldap_id_mapping = False ++ ++# Comment out if the users have the shell and home dir set on the AD side ++default_shell = /bin/bash ++fallback_homedir = /home/%d/%u ++ ++# Uncomment and adjust if the default principal SHORTNAME$@REALM is not available ++# ldap_sasl_authid = host/client.ad.example.com@AD.EXAMPLE.COM ++ ++# Comment out if you prefer to user shortnames. ++use_fully_qualified_names = True +-- +2.5.0 + diff --git a/0018-BUILD-Accept-krb5-1.14-for-building-the-PAC-plugin.patch b/0018-BUILD-Accept-krb5-1.14-for-building-the-PAC-plugin.patch new file mode 100644 index 0000000..d362fe6 --- /dev/null +++ b/0018-BUILD-Accept-krb5-1.14-for-building-the-PAC-plugin.patch @@ -0,0 +1,29 @@ +From 16e6d7ffedb52030f0301590f8c63beef44d7e96 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 26 Oct 2015 07:00:50 +0100 +Subject: [PATCH 18/21] BUILD: Accept krb5 1.14 for building the PAC plugin + +Reviewed-by: Sumit Bose +(cherry picked from commit 8fe87c3d35bf301cbb6ed7d441b588327d831924) +(cherry picked from commit 3dd118ee870d4370e8bfff8bd71d7e9954ccac06) +--- + src/external/pac_responder.m4 | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/external/pac_responder.m4 b/src/external/pac_responder.m4 +index b57305c..5c4239a 100644 +--- a/src/external/pac_responder.m4 ++++ b/src/external/pac_responder.m4 +@@ -22,7 +22,8 @@ then + Kerberos\ 5\ release\ 1.10* | \ + Kerberos\ 5\ release\ 1.11* | \ + Kerberos\ 5\ release\ 1.12* | \ +- Kerberos\ 5\ release\ 1.13*) ++ Kerberos\ 5\ release\ 1.13* | \ ++ Kerberos\ 5\ release\ 1.14*) + krb5_version_ok=yes + AC_MSG_RESULT([yes]) + ;; +-- +2.5.0 + diff --git a/0019-LDAP-Fix-leak-of-file-descriptors.patch b/0019-LDAP-Fix-leak-of-file-descriptors.patch new file mode 100644 index 0000000..afbecfe --- /dev/null +++ b/0019-LDAP-Fix-leak-of-file-descriptors.patch @@ -0,0 +1,112 @@ +From d453aacfbc937ceb87b9fd73c72d0bfe6699c005 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Thu, 22 Oct 2015 10:30:12 +0200 +Subject: [PATCH 19/21] LDAP: Fix leak of file descriptors + +The state "struct sss_ldap_init_state" contains socket +created in function sss_ldap_init_send. We register callback +sdap_async_sys_connect_timeout for handling issue with connection + +The tevent request "sss_ldap_init_send" is usually (nested) subrequest +of "struct resolve_service_state" related request created in fucntion +fo_resolve_service_send. Function fo_resolve_service_send also register +timeout callback fo_resolve_service_timeout to state "struct +resolve_service_state". + +It might happen that fo_resolve_service_timeout will be called before +sss_ldap_init_send timeout and we could not handle tiemout error +for state "struct sss_ldap_init_state" and therefore created socket +was not closed. + +We tried to release resources in function sdap_handle_release. +But the structure "struct sdap_handle" had not been initialized yet +with LDAP handle and therefore associated file descriptor could not be closed. + +[fo_resolve_service_timeout] (0x0080): Service resolving timeout reached +[fo_resolve_service_recv] (0x0020): TEVENT_REQ_RETURN_ON_ERROR ret[110] +[sdap_handle_release] (0x2000): Trace: sh[0x7f6713410270], connected[0], ops[(nil)], ldap[(nil)], destructor_lock[0], release_memory +[be_resolve_server_done] (0x1000): Server resolution failed: 14 +[be_resolve_server_recv] (0x0020): TEVENT_REQ_RETURN_ON_ERROR ret[14] +[check_online_callback] (0x0100): Backend returned: (1, 0, ) [Provider is Offline (Success)] + +Resolves: +https://fedorahosted.org/sssd/ticket/2792 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit a10f67d4c64f3b1243de5d86a996475361adf0ac) +(cherry picked from commit db2fdba6f3cecd0612439988e61be60d5d8576bf) +--- + src/util/sss_ldap.c | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c +index dd63b4b..f42f940 100644 +--- a/src/util/sss_ldap.c ++++ b/src/util/sss_ldap.c +@@ -304,6 +304,22 @@ struct sss_ldap_init_state { + #endif + }; + ++static int sss_ldap_init_state_destructor(void *data) ++{ ++ struct sss_ldap_init_state *state = (struct sss_ldap_init_state *)data; ++ ++ if (state->ldap) { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "calling ldap_unbind_ext for ldap:[%p] sd:[%d]\n", ++ state->ldap, state->sd); ++ ldap_unbind_ext(state->ldap, NULL, NULL); ++ } else if (state->sd != -1) { ++ DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd); ++ close(state->sd); ++ } ++ ++ return 0; ++} + + struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, +@@ -321,6 +337,8 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx, + return NULL; + } + ++ talloc_set_destructor((TALLOC_CTX *)state, sss_ldap_init_state_destructor); ++ + state->ldap = NULL; + state->uri = uri; + +@@ -370,9 +388,6 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx, + return req; + + fail: +- if(state->sd >= 0) { +- close(state->sd); +- } + tevent_req_error(req, ret); + #else + DEBUG(SSSDBG_MINOR_FAILURE, "ldap_init_fd not available, " +@@ -455,11 +470,6 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) + return; + + fail: +- if (state->ldap) { +- ldap_unbind_ext(state->ldap, NULL, NULL); +- } else { +- close(state->sd); +- } + tevent_req_error(req, ret); + } + #endif +@@ -470,6 +480,9 @@ int sss_ldap_init_recv(struct tevent_req *req, LDAP **ldap, int *sd) + struct sss_ldap_init_state); + TEVENT_REQ_RETURN_ON_ERROR(req); + ++ /* Everything went well therefore we do not want to release resources */ ++ talloc_set_destructor(state, NULL); ++ + *ldap = state->ldap; + *sd = state->sd; + +-- +2.5.0 + diff --git a/0020-sss_client-Fix-underflow-of-active_threads.patch b/0020-sss_client-Fix-underflow-of-active_threads.patch new file mode 100644 index 0000000..5724ae2 --- /dev/null +++ b/0020-sss_client-Fix-underflow-of-active_threads.patch @@ -0,0 +1,57 @@ +From 11b7c82c2283993cc3fef0abeb598ee9f48eb310 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 6 Nov 2015 08:48:05 +0100 +Subject: [PATCH 20/21] sss_client: Fix underflow of active_threads +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the memory cache was not initialized and there was a failure in +initialisation of memory cache context (e.g. memory cache file +does not exist) then mc_context had to be destroyed to release +resources. + +However the count of active threads in sss_cli_mc_ctx is already higher +than zero because current thread is working wih the mc_context. +But this counter was zero-ed with memset in sss_nss_mc_destroy_ctx +due to issue with initialisation of memory cache. +Then we have to decrease counter of active thread in function +sss_nss_mc_get_ctx because initialisation of mc failed. +And the result of this decrement is underflow of counter. + +Related to: +https://fedorahosted.org/sssd/ticket/2726 + +Reviewed-by: Michal Židek +(cherry picked from commit d4ff84434265dc959098ccfd4e8cd5d61d9052c9) +(cherry picked from commit 01c888be345ed8e77d97a83ed0bf4f57b3e5c740) +--- + src/sss_client/nss_mc_common.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c +index 89ff6b4..182cc6d 100644 +--- a/src/sss_client/nss_mc_common.c ++++ b/src/sss_client/nss_mc_common.c +@@ -104,6 +104,8 @@ errno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx) + + static void sss_nss_mc_destroy_ctx(struct sss_cli_mc_ctx *ctx) + { ++ uint32_t active_threads = ctx->active_threads; ++ + if ((ctx->mmap_base != NULL) && (ctx->mmap_size != 0)) { + munmap(ctx->mmap_base, ctx->mmap_size); + } +@@ -112,6 +114,9 @@ static void sss_nss_mc_destroy_ctx(struct sss_cli_mc_ctx *ctx) + } + memset(ctx, 0, sizeof(struct sss_cli_mc_ctx)); + ctx->fd = -1; ++ ++ /* restore count of active threads */ ++ ctx->active_threads = active_threads; + } + + static errno_t sss_nss_mc_init_ctx(const char *name, +-- +2.5.0 + diff --git a/0021-sssd_client-Do-not-use-removed-memory-cache.patch b/0021-sssd_client-Do-not-use-removed-memory-cache.patch new file mode 100644 index 0000000..93e2210 --- /dev/null +++ b/0021-sssd_client-Do-not-use-removed-memory-cache.patch @@ -0,0 +1,51 @@ +From 356f7e9ad047f66af55c7a1d783b98118fddbb92 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 6 Nov 2015 09:39:05 +0100 +Subject: [PATCH 21/21] sssd_client: Do not use removed memory cache +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/2726 + +Reviewed-by: Michal Židek +(cherry picked from commit c269ca2669706bddb25c5938b50277b0c0a94ea4) +(cherry picked from commit e360fa6e91ee3500435e85b9c51c4932d2b99f33) +--- + src/sss_client/nss_mc_common.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c +index 182cc6d..b56ab8f 100644 +--- a/src/sss_client/nss_mc_common.c ++++ b/src/sss_client/nss_mc_common.c +@@ -60,6 +60,8 @@ errno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx) + struct sss_mc_header h; + bool copy_ok; + int count; ++ int ret; ++ struct stat fdstat; + + /* retry barrier protected reading max 5 times then give up */ + for (count = 5; count > 0; count--) { +@@ -99,6 +101,16 @@ errno_t sss_nss_check_header(struct sss_cli_mc_ctx *ctx) + } + } + ++ ret = fstat(ctx->fd, &fdstat); ++ if (ret == -1) { ++ return EIO; ++ } ++ ++ if (fdstat.st_nlink == 0) { ++ /* memory cache was removed; we need to reinitialize it. */ ++ return EINVAL; ++ } ++ + return 0; + } + +-- +2.5.0 + diff --git a/sssd.spec b/sssd.spec index f0aa6ba..4cea72b 100644 --- a/sssd.spec +++ b/sssd.spec @@ -29,7 +29,7 @@ Name: sssd Version: 1.12.5 -Release: 4%{?dist} +Release: 5%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -39,8 +39,26 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) ### Patches ### Patch0001: 0001-SDAP-Remove-user-from-cache-for-missing-user-in-LDAP.patch -Patch0002: 0002-Fix-memory-leak-in-sssdpac_verify.patch -Patch0003: 0003-GPO-fix-memory-leak.patch +Patch0002: 0002-sss_client-Update-integrity-check-of-records-in-mmap.patch +Patch0003: 0003-BUILD-Repair-dependecies-on-deprecated-libraries.patch +Patch0004: 0004-SPEC-Workaround-for-build-with-rpm-4.13.patch +Patch0005: 0005-CONFDB-Assume-config-file-version-2-if-missing.patch +Patch0006: 0006-SYSDB-Index-the-objectSIDString-attribute.patch +Patch0007: 0007-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch +Patch0008: 0008-SPEC-Update-spec-file-for-krb5_local_auth_plugin.patch +Patch0009: 0009-LDAP-Sanitize-group-dn-before-using-in-filter.patch +Patch0010: 0010-tests-check-special-characters-in-cleanup_groups.patch +Patch0011: 0011-Fix-memory-leak-in-sssdpac_verify.patch +Patch0012: 0012-SDAP-Relax-POSIX-check.patch +Patch0013: 0013-GPO-fix-memory-leak.patch +Patch0014: 0014-nss-fix-UPN-lookups-for-sub-domain-users.patch +Patch0015: 0015-SSSDConfig-Do-not-raise-exception-if-config_file_ver.patch +Patch0016: 0016-SSSDConfigTest-Try-load-saved-config.patch +Patch0017: 0017-SSSDConfigTest-Test-real-config-without-config_file_.patch +Patch0018: 0018-BUILD-Accept-krb5-1.14-for-building-the-PAC-plugin.patch +Patch0019: 0019-LDAP-Fix-leak-of-file-descriptors.patch +Patch0020: 0020-sss_client-Fix-underflow-of-active_threads.patch +Patch0021: 0021-sssd_client-Do-not-use-removed-memory-cache.patch ### Dependencies ### Requires: sssd-common = %{version}-%{release} @@ -909,6 +927,9 @@ fi %{_libdir}/%{name}/modules/libwbclient.so %changelog +* Fri Nov 20 2015 Lukas Slebodnik - 1.12.5-5 +- Backport fixes from upstream 1.12 + * Wed Oct 07 2015 Lukas Slebodnik - 1.12.5-4 - Fix memory leaks (GPO; PAC client) - Resolves: rhbz#1268807 (CVE-2015-5292)