From b2d4308a8adc2267c8080d4de4152b068f20ec5f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 06:13:15 +0000 Subject: import sssd-1.14.0-43.el7 --- diff --git a/.gitignore b/.gitignore index 27ea61f..f71df95 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ -SOURCES/cert9.db -SOURCES/key4.db -SOURCES/sssd-1.13.0.tar.gz +SOURCES/sssd-1.14.0.tar.gz diff --git a/.sssd.metadata b/.sssd.metadata index 7e1423b..26fd024 100644 --- a/.sssd.metadata +++ b/.sssd.metadata @@ -1,3 +1 @@ -7f7d2513294f425b8a393a7e3f37b36634dd55de SOURCES/cert9.db -6048e03ea386ac40bd801d41d77ece9545592ad3 SOURCES/key4.db -f9c57cfb91d8e0e35d565a1d5b165e8f669989d2 SOURCES/sssd-1.13.0.tar.gz +4ddb4403b07125f413181c43d8d2208c3128924d SOURCES/sssd-1.14.0.tar.gz diff --git a/SOURCES/0001-SYSDB-Fixing-DB-update.patch b/SOURCES/0001-SYSDB-Fixing-DB-update.patch new file mode 100644 index 0000000..f4df02a --- /dev/null +++ b/SOURCES/0001-SYSDB-Fixing-DB-update.patch @@ -0,0 +1,71 @@ +From dc8e4131f73d62f23a4be7148e24315adbc550e4 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Mon, 20 Jun 2016 09:19:03 -0300 +Subject: [PATCH 01/18] SYSDB: Fixing DB update +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Functions sysdb_user_base_dn() and sysdb_group_base_dn() expect +that struct sss_domain_info contains pointer to struct sysdb_ctx. +This is not true in case of sysdb_upgrade functions. +This patch fixes the situation and revert code to the state before +12a000c8c7c07259e438fb1e992134bdd07d9a30 commit. + +Resolves: +https://fedorahosted.org/sssd/ticket/3023 + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Sumit Bose +(cherry picked from commit 311836214245600566f881ff6253594e0999008e) +--- + src/db/sysdb_upgrade.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c +index 1d2978caee4512856fb64c4798a4b031bf6a3af1..4ca8433f9d5430b038f90563c34cede02393b0b0 100644 +--- a/src/db/sysdb_upgrade.c ++++ b/src/db/sysdb_upgrade.c +@@ -443,12 +443,23 @@ int sysdb_check_upgrade_02(struct sss_domain_info *domains, + goto done; + } + +- users_dn = sysdb_user_base_dn(tmp_ctx, dom); ++ /* ++ * dom->sysdb->ldb is not initialized, ++ * so ldb_dn_new_fmt() shouldn't be changed to sysdb_*_base_dn() ++ */ ++ users_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, ++ SYSDB_TMPL_USER_BASE, dom->name); + if (!users_dn) { + ret = ENOMEM; + goto done; + } +- groups_dn = sysdb_group_base_dn(tmp_ctx, dom); ++ ++ /* ++ * dom->sysdb->ldb is not initialized, ++ * so ldb_dn_new_fmt() shouldn't be changed to sysdb_*_base_dn() ++ */ ++ groups_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, ++ SYSDB_TMPL_GROUP_BASE, dom->name); + if (!groups_dn) { + ret = ENOMEM; + goto done; +@@ -1045,7 +1056,12 @@ int sysdb_upgrade_10(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, + return ret; + } + +- basedn = sysdb_user_base_dn(tmp_ctx, domain); ++ /* ++ * dom->sysdb->ldb is not initialized, ++ * so ldb_dn_new_fmt() shouldn't be changed to sysdb_*_base_dn() ++ */ ++ basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, ++ SYSDB_TMPL_USER_BASE, domain->name); + if (basedn == NULL) { + ret = EIO; + goto done; +-- +2.4.11 + diff --git a/SOURCES/0001-test-common-sss_dp_get_account_recv-fix-assignment.patch b/SOURCES/0001-test-common-sss_dp_get_account_recv-fix-assignment.patch deleted file mode 100644 index 4733a5c..0000000 --- a/SOURCES/0001-test-common-sss_dp_get_account_recv-fix-assignment.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 1b20d057dd7d4284d4c88319a12eee5845b14d8f Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 10 Jul 2015 12:37:43 +0200 -Subject: [PATCH 01/13] test common: sss_dp_get_account_recv() fix assignment - -Reviewed-by: Jakub Hrozek ---- - src/tests/cmocka/common_mock_resp_dp.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/tests/cmocka/common_mock_resp_dp.c b/src/tests/cmocka/common_mock_resp_dp.c -index 08d74179d8e2dc0561ea3e2d1e9b5580762ee633..a67ceee4a43184d9894c19a5c11161aca4e1caff 100644 ---- a/src/tests/cmocka/common_mock_resp_dp.c -+++ b/src/tests/cmocka/common_mock_resp_dp.c -@@ -51,7 +51,7 @@ sss_dp_get_account_recv(TALLOC_CTX *mem_ctx, - - *dp_err = sss_mock_type(dbus_uint16_t); - *dp_ret = sss_mock_type(dbus_uint32_t); -- *dp_ret = sss_mock_type(dbus_uint32_t); -+ *err_msg = sss_mock_ptr_type(char *); - - cb = sss_mock_ptr_type(acct_cb_t); - if (cb) { --- -2.4.3 - diff --git a/SOURCES/0002-sssctl-Fix-error-handling-after-memory-allocation-fa.patch b/SOURCES/0002-sssctl-Fix-error-handling-after-memory-allocation-fa.patch new file mode 100644 index 0000000..4590e63 --- /dev/null +++ b/SOURCES/0002-sssctl-Fix-error-handling-after-memory-allocation-fa.patch @@ -0,0 +1,33 @@ +From 36adb8fdc1e0ec14d394a2c51be16c90f4fa1acd Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 8 Jul 2016 12:16:47 +0200 +Subject: [PATCH 02/18] sssctl: Fix error handling after memory allocation + failure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Pavel Březina +(cherry picked from commit 4b18d0c25471150940c1a552bc2504ff9debb703) +--- + src/tools/sssctl/sssctl_cache.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/tools/sssctl/sssctl_cache.c b/src/tools/sssctl/sssctl_cache.c +index 9f626d983a4672cf00fba6b3171b822e8f6e02bd..28de6c139d844f98f9b06844492c935696e19643 100644 +--- a/src/tools/sssctl/sssctl_cache.c ++++ b/src/tools/sssctl/sssctl_cache.c +@@ -364,8 +364,9 @@ static errno_t sssctl_find_object(TALLOC_CTX *mem_ctx, + filter = talloc_asprintf(tmp_ctx, "(&(objectClass=%s)(%s=%s))", + class, attr_name, filter_value); + talloc_free(filter_value); +- if (filter_value == NULL) { ++ if (filter == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); ++ ret = ENOMEM; + goto done; + } + +-- +2.4.11 + diff --git a/SOURCES/0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch b/SOURCES/0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch deleted file mode 100644 index bc0e246..0000000 --- a/SOURCES/0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch +++ /dev/null @@ -1,76 +0,0 @@ -From fd554736d9b0e909acfcdf1aa5358423beefbe91 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 25 Mar 2015 10:03:43 +0100 -Subject: [PATCH 02/13] tests: Move N_ELEMENTS definition to tests/common.h -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Avoids code duplication - -Reviewed-by: Pavel Březina ---- - src/tests/cmocka/test_nested_groups.c | 3 --- - src/tests/cmocka/test_nss_srv.c | 3 --- - src/tests/common.h | 2 ++ - src/tests/sbus_codegen_tests.c | 3 --- - 4 files changed, 2 insertions(+), 9 deletions(-) - -diff --git a/src/tests/cmocka/test_nested_groups.c b/src/tests/cmocka/test_nested_groups.c -index eef9df2dc25c231cb81243f48b759e2fced1a85d..8081ff26102e53b2e453838c3a18e4560ac5317e 100644 ---- a/src/tests/cmocka/test_nested_groups.c -+++ b/src/tests/cmocka/test_nested_groups.c -@@ -48,9 +48,6 @@ - #define GROUP_BASE_DN "cn=groups," OBJECT_BASE_DN - #define USER_BASE_DN "cn=users," OBJECT_BASE_DN - --#define N_ELEMENTS(arr) \ -- (sizeof(arr) / sizeof(arr[0])) -- - struct nested_groups_test_ctx { - struct sss_test_ctx *tctx; - -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index d1a4c16851427a36b123f04cecee5fe5ae2d333d..3ab8d39c44a8bb8cacae20f534dcbeb6ca7dec08 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -41,9 +41,6 @@ - #define TEST_ID_PROVIDER "ldap" - #define TEST_DOM_SID "S-1-5-21-444379608-1639770488-2995963434" - --#define N_ELEMENTS(arr) \ -- (sizeof(arr) / sizeof(arr[0])) -- - struct nss_test_ctx { - struct sss_test_ctx *tctx; - struct sss_domain_info *subdom; -diff --git a/src/tests/common.h b/src/tests/common.h -index 0b351f5d647a8f72bdbc399c6fe02579d4b4e1be..1c6de2c3d6eb924ba7306bd350f8546d61f30751 100644 ---- a/src/tests/common.h -+++ b/src/tests/common.h -@@ -30,6 +30,8 @@ - #include "providers/data_provider.h" - #include "providers/ldap/sdap.h" - -+#define N_ELEMENTS(arr) (sizeof(arr) / sizeof(arr[0])) -+ - extern TALLOC_CTX *global_talloc_context; - - #define check_leaks(ctx, bytes) _check_leaks((ctx), (bytes), __location__) -diff --git a/src/tests/sbus_codegen_tests.c b/src/tests/sbus_codegen_tests.c -index 9e9be52e84672eb3ee3afa4e13d5f60047150e98..4637b92b84459041806bb5950e969e988716bec8 100644 ---- a/src/tests/sbus_codegen_tests.c -+++ b/src/tests/sbus_codegen_tests.c -@@ -33,9 +33,6 @@ - #include "tests/sbus_codegen_tests_generated.h" - #include "util/util_errors.h" - --#define N_ELEMENTS(arr) \ -- (sizeof(arr) / sizeof(arr[0])) -- - /* The following 2 macros were taken from check's project source files (0.9.10) - * http://check.sourceforge.net/ - */ --- -2.4.3 - diff --git a/SOURCES/0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch b/SOURCES/0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch deleted file mode 100644 index 5b07384..0000000 --- a/SOURCES/0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch +++ /dev/null @@ -1,925 +0,0 @@ -From 1d245226d88537123827dcda3fd0bd093275019d Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 24 Mar 2015 23:24:22 +0100 -Subject: [PATCH 03/13] SYSDB: Add functions to look up multiple entries - including name and custom filter -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -Adds new sysdb function: - - sysdb_enumpwent_filter - - sysdb_enumpwent_filter_with_views - - sysdb_enumgrent_filter - - sysdb_enumgrent_filter_with_views - -These are similar to enumeration functions, but optionally allow to -specify a filter to be applied on user/group names. Also an additional -custom filter can be applied. - -Reviewed-by: Pavel Březina ---- - src/db/sysdb.h | 24 ++ - src/db/sysdb_search.c | 252 ++++++++++++------ - src/tests/cmocka/test_sysdb_views.c | 494 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 691 insertions(+), 79 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 48dd26dd294333b265b69b28cd3b5d37f1293b43..0f745ccb1a646d77ba4ad3d714d5f4dce0a51211 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -601,10 +601,22 @@ int sysdb_enumpwent(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_result **res); - -+int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **res); -+ - int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_result **res); - -+int sysdb_enumpwent_filter_with_views(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **res); -+ - int sysdb_getgrnam(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - const char *name, -@@ -619,10 +631,22 @@ int sysdb_enumgrent(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_result **res); - -+int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **res); -+ - int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_result **res); - -+int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **res); -+ - struct sysdb_netgroup_ctx { - enum {SYSDB_NETGROUP_TRIPLE_VAL, SYSDB_NETGROUP_GROUP_VAL} type; - union { -diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c -index a8dcc9f8d6617be8e8fb82a1c6360c6df9726a37..4f617b841bf3b3760d9cb05a06f4b46ea0c58ff5 100644 ---- a/src/db/sysdb_search.c -+++ b/src/db/sysdb_search.c -@@ -255,44 +255,104 @@ done: - return ret; - } - -+static char *enum_filter(TALLOC_CTX *mem_ctx, -+ const char *base_filter, -+ const char *name_filter, -+ const char *addtl_filter) -+{ -+ char *filter; -+ TALLOC_CTX *tmp_ctx = NULL; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return NULL; -+ } -+ -+ if (name_filter == NULL && addtl_filter == NULL) { -+ filter = talloc_strdup(tmp_ctx, base_filter); -+ } else { -+ filter = talloc_asprintf(tmp_ctx, "(&%s", base_filter); -+ -+ if (filter != NULL && name_filter != NULL) { -+ filter = talloc_asprintf_append(filter, "(%s=%s)", -+ SYSDB_NAME, name_filter); -+ } -+ -+ if (filter != NULL && addtl_filter != NULL) { -+ filter = talloc_asprintf_append(filter, "%s", addtl_filter); -+ } -+ -+ if (filter != NULL) { -+ filter = talloc_asprintf_append(filter, ")"); -+ } -+ } -+ -+ if (filter) { -+ talloc_steal(mem_ctx, filter); -+ } -+ -+ talloc_free(tmp_ctx); -+ return filter; -+} -+ -+int sysdb_enumpwent_filter(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **_res) -+{ -+ TALLOC_CTX *tmp_ctx; -+ static const char *attrs[] = SYSDB_PW_ATTRS; -+ char *filter = NULL; -+ struct ldb_dn *base_dn; -+ struct ldb_result *res; -+ int ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (!tmp_ctx) { -+ return ENOMEM; -+ } -+ -+ base_dn = sysdb_user_base_dn(tmp_ctx, domain); -+ if (!base_dn) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ filter = enum_filter(tmp_ctx, SYSDB_PWENT_FILTER, -+ name_filter, addtl_filter); -+ if (filter == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Searching cache with [%s]\n", filter); -+ -+ ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn, -+ LDB_SCOPE_SUBTREE, attrs, "%s", filter); -+ if (ret) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ *_res = talloc_steal(mem_ctx, res); -+ -+done: -+ talloc_zfree(tmp_ctx); -+ return ret; -+} -+ - int sysdb_enumpwent(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_result **_res) - { -- TALLOC_CTX *tmp_ctx; -- static const char *attrs[] = SYSDB_PW_ATTRS; -- struct ldb_dn *base_dn; -- struct ldb_result *res; -- int ret; -- -- tmp_ctx = talloc_new(NULL); -- if (!tmp_ctx) { -- return ENOMEM; -- } -- -- base_dn = sysdb_user_base_dn(tmp_ctx, domain); -- if (!base_dn) { -- ret = ENOMEM; -- goto done; -- } -- -- ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn, -- LDB_SCOPE_SUBTREE, attrs, SYSDB_PWENT_FILTER); -- if (ret) { -- ret = sysdb_error_to_errno(ret); -- goto done; -- } -- -- *_res = talloc_steal(mem_ctx, res); -- --done: -- talloc_zfree(tmp_ctx); -- return ret; -+ return sysdb_enumpwent_filter(mem_ctx, domain, NULL, 0, _res); - } - --int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx, -- struct sss_domain_info *domain, -- struct ldb_result **_res) -+int sysdb_enumpwent_filter_with_views(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **_res) - { - TALLOC_CTX *tmp_ctx; - struct ldb_result *res; -@@ -305,7 +365,7 @@ int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx, - return ENOMEM; - } - -- ret = sysdb_enumpwent(tmp_ctx, domain, &res); -+ ret = sysdb_enumpwent_filter(tmp_ctx, domain, name_filter, addtl_filter, &res); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumpwent failed.\n"); - goto done; -@@ -331,6 +391,13 @@ done: - return ret; - } - -+int sysdb_enumpwent_with_views(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ struct ldb_result **_res) -+{ -+ return sysdb_enumpwent_filter_with_views(mem_ctx, domain, NULL, NULL, _res); -+} -+ - /* groups */ - - static int mpg_convert(struct ldb_message *msg) -@@ -662,57 +729,77 @@ done: - return ret; - } - -+int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **_res) -+{ -+ TALLOC_CTX *tmp_ctx; -+ static const char *attrs[] = SYSDB_GRSRC_ATTRS; -+ const char *filter = NULL; -+ const char *base_filter; -+ struct ldb_dn *base_dn; -+ struct ldb_result *res; -+ int ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (!tmp_ctx) { -+ return ENOMEM; -+ } -+ -+ if (domain->mpg) { -+ base_filter = SYSDB_GRENT_MPG_FILTER; -+ base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, -+ SYSDB_DOM_BASE, domain->name); -+ } else { -+ base_filter = SYSDB_GRENT_FILTER; -+ base_dn = sysdb_group_base_dn(tmp_ctx, domain); -+ } -+ if (!base_dn) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ filter = enum_filter(tmp_ctx, base_filter, -+ name_filter, addtl_filter); -+ if (filter == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ DEBUG(SSSDBG_TRACE_LIBS, "Searching cache with [%s]\n", filter); -+ -+ ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn, -+ LDB_SCOPE_SUBTREE, attrs, "%s", filter); -+ if (ret) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ ret = mpg_res_convert(res); -+ if (ret) { -+ goto done; -+ } -+ -+ *_res = talloc_steal(mem_ctx, res); -+ -+done: -+ talloc_zfree(tmp_ctx); -+ return ret; -+} -+ - int sysdb_enumgrent(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct ldb_result **_res) - { -- TALLOC_CTX *tmp_ctx; -- static const char *attrs[] = SYSDB_GRSRC_ATTRS; -- const char *fmt_filter; -- struct ldb_dn *base_dn; -- struct ldb_result *res; -- int ret; -- -- tmp_ctx = talloc_new(NULL); -- if (!tmp_ctx) { -- return ENOMEM; -- } -- -- if (domain->mpg) { -- fmt_filter = SYSDB_GRENT_MPG_FILTER; -- base_dn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb, -- SYSDB_DOM_BASE, domain->name); -- } else { -- fmt_filter = SYSDB_GRENT_FILTER; -- base_dn = sysdb_group_base_dn(tmp_ctx, domain); -- } -- if (!base_dn) { -- ret = ENOMEM; -- goto done; -- } -- -- ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, base_dn, -- LDB_SCOPE_SUBTREE, attrs, "%s", fmt_filter); -- if (ret) { -- ret = sysdb_error_to_errno(ret); -- goto done; -- } -- -- ret = mpg_res_convert(res); -- if (ret) { -- goto done; -- } -- -- *_res = talloc_steal(mem_ctx, res); -- --done: -- talloc_zfree(tmp_ctx); -- return ret; -+ return sysdb_enumgrent_filter(mem_ctx, domain, NULL, 0, _res); - } - --int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx, -- struct sss_domain_info *domain, -- struct ldb_result **_res) -+int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ const char *addtl_filter, -+ struct ldb_result **_res) - { - TALLOC_CTX *tmp_ctx; - struct ldb_result *res; -@@ -725,7 +812,7 @@ int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx, - return ENOMEM; - } - -- ret = sysdb_enumgrent(tmp_ctx, domain,&res); -+ ret = sysdb_enumgrent_filter(tmp_ctx, domain, name_filter, addtl_filter, &res); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_enumgrent failed.\n"); - goto done; -@@ -759,6 +846,13 @@ done: - return ret; - } - -+int sysdb_enumgrent_with_views(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ struct ldb_result **_res) -+{ -+ return sysdb_enumgrent_filter_with_views(mem_ctx, domain, NULL, NULL, _res); -+} -+ - int sysdb_initgroups(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - const char *name, -diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c -index 69118cd87a172696f8220e1446df7a856e368cb6..1fb598219e9ee581e465ddbb32ba9f2544600c26 100644 ---- a/src/tests/cmocka/test_sysdb_views.c -+++ b/src/tests/cmocka/test_sysdb_views.c -@@ -45,6 +45,7 @@ - #define TEST_USER_HOMEDIR "/home/home" - #define TEST_USER_SHELL "/bin/shell" - #define TEST_USER_SID "S-1-2-3-4" -+#define TEST_GID_OVERRIDE_BASE 100 - - struct sysdb_test_ctx { - struct sysdb_ctx *sysdb; -@@ -108,6 +109,7 @@ static int _setup_sysdb_tests(struct sysdb_test_ctx **ctx, bool enumerate) - TESTS_PATH, &test_ctx->domain); - assert_int_equal(ret, EOK); - -+ test_ctx->domain->has_views = true; - test_ctx->sysdb = test_ctx->domain->sysdb; - - *ctx = test_ctx; -@@ -115,6 +117,7 @@ static int _setup_sysdb_tests(struct sysdb_test_ctx **ctx, bool enumerate) - } - - #define setup_sysdb_tests(ctx) _setup_sysdb_tests((ctx), false) -+#define setup_sysdb_enum_tests(ctx) _setup_sysdb_tests((ctx), true) - - static int test_sysdb_setup(void **state) - { -@@ -426,6 +429,473 @@ void test_sysdb_invalidate_overrides(void **state) - assert_int_equal(ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0), - 1); - assert_null(ldb_msg_find_attr_as_string(msg, SYSDB_OVERRIDE_DN, NULL)); -+ -+ ret = sysdb_delete_user(test_ctx->domain, TEST_USER_NAME, 0); -+ assert_int_equal(ret, EOK); -+} -+ -+static const char *users[] = { "alice", "bob", "barney", NULL }; -+ -+static void enum_test_user_override(struct sysdb_test_ctx *test_ctx, -+ const char *name) -+{ -+ int ret; -+ struct sysdb_attrs *attrs; -+ struct ldb_dn *dn; -+ TALLOC_CTX *tmp_ctx; -+ const char *anchor; -+ const char *override_gecos; -+ -+ tmp_ctx = talloc_new(test_ctx); -+ assert_non_null(tmp_ctx); -+ -+ attrs = sysdb_new_attrs(tmp_ctx); -+ assert_non_null(attrs); -+ -+ dn = sysdb_user_dn(tmp_ctx, test_ctx->domain, name); -+ assert_non_null(dn); -+ -+ anchor = talloc_asprintf(tmp_ctx, "%s%s", TEST_ANCHOR_PREFIX, name); -+ ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, anchor); -+ assert_int_equal(ret, EOK); -+ -+ override_gecos = talloc_asprintf(attrs, "%s_GECOS_OVERRIDE", name); -+ ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, override_gecos); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME, -+ SYSDB_MEMBER_USER, attrs, dn); -+ assert_int_equal(ret, EOK); -+ -+ talloc_free(tmp_ctx); -+} -+ -+static void enum_test_add_users(struct sysdb_test_ctx *test_ctx, -+ const char *usernames[]) -+{ -+ int i; -+ int ret; -+ struct sysdb_attrs *attrs; -+ -+ for (i = 0; usernames[i] != NULL; i++) { -+ attrs = talloc(test_ctx, struct sysdb_attrs); -+ assert_non_null(attrs); -+ -+ ret = sysdb_store_user(test_ctx->domain, usernames[i], -+ NULL, 0, 0, usernames[i], "/", "/bin/sh", -+ NULL, NULL, NULL, 1, 1234 + i); -+ assert_int_equal(ret, EOK); -+ -+ enum_test_user_override(test_ctx, usernames[i]); -+ -+ talloc_free(attrs); -+ } -+} -+ -+static void enum_test_del_users(struct sss_domain_info *dom, -+ const char *usernames[]) -+{ -+ int i; -+ int ret; -+ -+ for (i = 0; usernames[i] != NULL; i++) { -+ ret = sysdb_delete_user(dom, usernames[i], 0); -+ if (ret != EOK && ret != ENOENT) { -+ fail(); -+ } -+ } -+} -+ -+static int test_enum_users_setup(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx; -+ -+ assert_true(leak_check_setup()); -+ -+ ret = setup_sysdb_enum_tests(&test_ctx); -+ assert_int_equal(ret, EOK); -+ -+ enum_test_add_users(test_ctx, users); -+ -+ *state = (void *) test_ctx; -+ return 0; -+} -+ -+static void assert_user_attrs(struct ldb_message *msg, -+ const char *name, -+ bool has_views) -+{ -+ const char *str; -+ -+ str = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -+ assert_string_equal(str, name); -+ str = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL); -+ assert_string_equal(str, name); -+ -+ str = ldb_msg_find_attr_as_string(msg, OVERRIDE_PREFIX SYSDB_GECOS, NULL); -+ if (has_views) { -+ char *override; -+ -+ assert_non_null(str); -+ override = talloc_asprintf(msg, "%s_GECOS_OVERRIDE", name); -+ assert_non_null(override); -+ -+ assert_string_equal(str, override); -+ talloc_free(override); -+ } else { -+ assert_null(str); -+ } -+} -+ -+static int test_enum_users_teardown(void **state) -+{ -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ -+ enum_test_del_users(test_ctx->domain, users); -+ return test_sysdb_teardown(state); -+} -+ -+static void check_enumpwent(int ret, struct ldb_result *res, bool views) -+{ -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, N_ELEMENTS(users)-1); -+ assert_user_attrs(res->msgs[0], "barney", views); -+ assert_user_attrs(res->msgs[1], "alice", views); -+ assert_user_attrs(res->msgs[2], "bob", views); -+} -+ -+static void test_sysdb_enumpwent(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ -+ ret = sysdb_enumpwent(test_ctx, test_ctx->domain, &res); -+ check_enumpwent(ret, res, false); -+} -+ -+static void test_sysdb_enumpwent_views(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ -+ ret = sysdb_enumpwent_with_views(test_ctx, test_ctx->domain, &res); -+ check_enumpwent(ret, res, true); -+} -+ -+static void test_sysdb_enumpwent_filter(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ char *addtl_filter; -+ -+ ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "a*", 0, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_user_attrs(res->msgs[0], "alice", false); -+ -+ ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "b*", 0, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 2); -+ assert_user_attrs(res->msgs[0], "barney", false); -+ assert_user_attrs(res->msgs[1], "bob", false); -+ -+ ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "c*", 0, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 0); -+ -+ ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "*", 0, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, N_ELEMENTS(users)-1); -+ -+ /* Test searching based on time as well */ -+ addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)", -+ SYSDB_LAST_UPDATE, 1233); -+ ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "a*", addtl_filter, &res); -+ talloc_free(addtl_filter); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 0); -+ -+ addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)", -+ SYSDB_LAST_UPDATE, 1234); -+ ret = sysdb_enumpwent_filter(test_ctx, test_ctx->domain, "a*", addtl_filter, &res); -+ talloc_free(addtl_filter); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_user_attrs(res->msgs[0], "alice", false); -+} -+ -+static void test_sysdb_enumpwent_filter_views(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ char *addtl_filter; -+ -+ ret = sysdb_enumpwent_filter_with_views(test_ctx, test_ctx->domain, -+ "a*", NULL, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_user_attrs(res->msgs[0], "alice", true); -+ -+ ret = sysdb_enumpwent_filter_with_views(test_ctx, test_ctx->domain, -+ "b*", NULL, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 2); -+ assert_user_attrs(res->msgs[0], "barney", true); -+ assert_user_attrs(res->msgs[1], "bob", true); -+ -+ addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)", -+ SYSDB_LAST_UPDATE, 1235); -+ ret = sysdb_enumpwent_filter_with_views(test_ctx, test_ctx->domain, -+ "b*", addtl_filter, &res); -+ talloc_free(addtl_filter); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_user_attrs(res->msgs[0], "bob", true); -+ -+ ret = sysdb_enumpwent_filter_with_views(test_ctx, -+ test_ctx->domain, "c*", NULL, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 0); -+ -+ ret = sysdb_enumpwent_filter_with_views(test_ctx, -+ test_ctx->domain, "*", NULL, &res); -+ check_enumpwent(ret, res, true); -+} -+ -+static const char *groups[] = { "one", "two", "three", NULL }; -+ -+static void enum_test_group_override(struct sysdb_test_ctx *test_ctx, -+ const char *name, -+ unsigned override_gid) -+{ -+ int ret; -+ struct sysdb_attrs *attrs; -+ struct ldb_dn *dn; -+ TALLOC_CTX *tmp_ctx; -+ const char *anchor; -+ -+ tmp_ctx = talloc_new(test_ctx); -+ assert_non_null(tmp_ctx); -+ -+ attrs = sysdb_new_attrs(tmp_ctx); -+ assert_non_null(attrs); -+ -+ dn = sysdb_group_dn(tmp_ctx, test_ctx->domain, name); -+ assert_non_null(dn); -+ -+ anchor = talloc_asprintf(tmp_ctx, "%s%s", TEST_ANCHOR_PREFIX, name); -+ ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, anchor); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, override_gid); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME, -+ SYSDB_MEMBER_GROUP, attrs, dn); -+ assert_int_equal(ret, EOK); -+ -+ talloc_free(tmp_ctx); -+} -+ -+static void enum_test_add_groups(struct sysdb_test_ctx *test_ctx, -+ const char *groupnames[]) -+{ -+ int i; -+ int ret; -+ struct sysdb_attrs *attrs; -+ -+ for (i = 0; groupnames[i] != NULL; i++) { -+ attrs = talloc(test_ctx, struct sysdb_attrs); -+ assert_non_null(attrs); -+ -+ ret = sysdb_store_group(test_ctx->domain, groupnames[i], -+ 0, NULL, 1, 1234 + i); -+ assert_int_equal(ret, EOK); -+ -+ enum_test_group_override(test_ctx, groupnames[i], -+ TEST_GID_OVERRIDE_BASE + i); -+ talloc_free(attrs); -+ } -+} -+ -+static void enum_test_del_groups(struct sss_domain_info *dom, -+ const char *groupnames[]) -+{ -+ int i; -+ int ret; -+ -+ for (i = 0; groupnames[i] != NULL; i++) { -+ ret = sysdb_delete_group(dom, groupnames[i], 0); -+ if (ret != EOK && ret != ENOENT) { -+ fail(); -+ } -+ } -+} -+ -+static int test_enum_groups_setup(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx; -+ -+ assert_true(leak_check_setup()); -+ -+ ret = setup_sysdb_enum_tests(&test_ctx); -+ assert_int_equal(ret, EOK); -+ -+ enum_test_add_groups(test_ctx, groups); -+ -+ *state = (void *) test_ctx; -+ return 0; -+} -+ -+static int test_enum_groups_teardown(void **state) -+{ -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ -+ enum_test_del_groups(test_ctx->domain, groups); -+ return test_sysdb_teardown(state); -+} -+ -+static void assert_group_attrs(struct ldb_message *msg, -+ const char *name, -+ unsigned expected_override_gid) -+{ -+ const char *str; -+ unsigned gid; -+ -+ str = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -+ assert_string_equal(str, name); -+ -+ if (expected_override_gid) { -+ gid = ldb_msg_find_attr_as_uint64(msg, -+ OVERRIDE_PREFIX SYSDB_GIDNUM, 0); -+ assert_int_equal(gid, expected_override_gid); -+ } -+} -+ -+static void check_enumgrent(int ret, struct ldb_result *res, bool views) -+{ -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, N_ELEMENTS(groups)-1); -+ assert_group_attrs(res->msgs[0], "three", views ? TEST_GID_OVERRIDE_BASE + 2 : 0); -+ assert_group_attrs(res->msgs[1], "one", views ? TEST_GID_OVERRIDE_BASE : 0); -+ assert_group_attrs(res->msgs[2], "two", views ? TEST_GID_OVERRIDE_BASE + 1 : 0); -+} -+ -+static void test_sysdb_enumgrent(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ -+ ret = sysdb_enumgrent(test_ctx, test_ctx->domain, &res); -+ check_enumgrent(ret, res, false); -+} -+ -+static void test_sysdb_enumgrent_views(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ -+ ret = sysdb_enumgrent_with_views(test_ctx, test_ctx->domain, &res); -+ check_enumgrent(ret, res, true); -+} -+ -+static void test_sysdb_enumgrent_filter(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ char *addtl_filter; -+ -+ ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "o*", 0, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_group_attrs(res->msgs[0], "one", 0); -+ -+ ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "t*", 0, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 2); -+ assert_group_attrs(res->msgs[0], "three", 0); -+ assert_group_attrs(res->msgs[1], "two", 0); -+ -+ ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "x*", 0, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 0); -+ -+ ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "*", 0, &res); -+ check_enumgrent(ret, res, false); -+ -+ addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)", -+ SYSDB_LAST_UPDATE, 1233); -+ ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "o*", addtl_filter, &res); -+ talloc_free(addtl_filter); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 0); -+ -+ addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)", -+ SYSDB_LAST_UPDATE, 1234); -+ ret = sysdb_enumgrent_filter(test_ctx, test_ctx->domain, "o*", addtl_filter, &res); -+ talloc_free(addtl_filter); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_group_attrs(res->msgs[0], "one", 0); -+ -+} -+ -+static void test_sysdb_enumgrent_filter_views(void **state) -+{ -+ int ret; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ struct ldb_result *res; -+ char *addtl_filter; -+ -+ ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain, -+ "o*", NULL, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_group_attrs(res->msgs[0], "one", TEST_GID_OVERRIDE_BASE); -+ -+ ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain, -+ "t*", NULL, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 2); -+ assert_group_attrs(res->msgs[0], "three", TEST_GID_OVERRIDE_BASE + 2); -+ assert_group_attrs(res->msgs[1], "two", TEST_GID_OVERRIDE_BASE + 1); -+ -+ addtl_filter = talloc_asprintf(test_ctx, "(%s<=%d)", -+ SYSDB_LAST_UPDATE, 1235); -+ ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain, -+ "t*", addtl_filter, &res); -+ talloc_free(addtl_filter); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 1); -+ assert_group_attrs(res->msgs[0], "two", TEST_GID_OVERRIDE_BASE + 1); -+ -+ ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain, -+ "x*", NULL, &res); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(res->count, 0); -+ -+ ret = sysdb_enumgrent_filter_with_views(test_ctx, test_ctx->domain, -+ "*", NULL, &res); -+ check_enumgrent(ret, res, true); - } - - int main(int argc, const char *argv[]) -@@ -453,6 +923,30 @@ int main(int argc, const char *argv[]) - test_sysdb_setup, test_sysdb_teardown), - cmocka_unit_test_setup_teardown(test_sysdb_invalidate_overrides, - test_sysdb_setup, test_sysdb_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumpwent, -+ test_enum_users_setup, -+ test_enum_users_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumpwent_views, -+ test_enum_users_setup, -+ test_enum_users_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumpwent_filter, -+ test_enum_users_setup, -+ test_enum_users_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumpwent_filter_views, -+ test_enum_users_setup, -+ test_enum_users_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumgrent, -+ test_enum_groups_setup, -+ test_enum_groups_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumgrent_views, -+ test_enum_groups_setup, -+ test_enum_groups_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumgrent_filter, -+ test_enum_groups_setup, -+ test_enum_groups_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_enumgrent_filter_views, -+ test_enum_groups_setup, -+ test_enum_groups_teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.4.3 - diff --git a/SOURCES/0003-sssctl-config-check-access-check-report.patch b/SOURCES/0003-sssctl-config-check-access-check-report.patch new file mode 100644 index 0000000..3a564f8 --- /dev/null +++ b/SOURCES/0003-sssctl-config-check-access-check-report.patch @@ -0,0 +1,34 @@ +From 0df858e26420bc6fb49819572694fced6791d414 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Thu, 7 Jul 2016 15:43:11 +0200 +Subject: [PATCH 03/18] sssctl: config-check access check report +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Improve output when access check error +is detected by sssctl config-check command. + +Reviewed-by: Pavel Březina +(cherry picked from commit 9dc66cb6b96a885f7272a3c4aa6a44d60cdce82c) +--- + src/tools/sssctl/sssctl_config.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/tools/sssctl/sssctl_config.c b/src/tools/sssctl/sssctl_config.c +index fc13582accd63f58c9d8bce59c4d6e898a96b170..4f6dbcdd7d04183c65b6613efbe5ab95df19e2c7 100644 +--- a/src/tools/sssctl/sssctl_config.c ++++ b/src/tools/sssctl/sssctl_config.c +@@ -68,7 +68,8 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline, + /* Check the file permissions */ + ret = sss_ini_config_access_check(init_data); + if (ret != EOK) { +- printf(_("Access check on sssd.conf file failed.\n")); ++ printf(_("File ownership and permissions check failed. " ++ "Expected root:root and 0600.\n")); + ret = EPERM; + goto done; + } +-- +2.4.11 + diff --git a/SOURCES/0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch b/SOURCES/0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch deleted file mode 100644 index 1d308d5..0000000 --- a/SOURCES/0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 15dcdcf23bce2423f05c03f7c0aa61f23383d488 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 4 May 2015 12:34:32 +0200 -Subject: [PATCH 04/13] DP: Add DP_WILDCARD and - SSS_DP_WILDCARD_USER/SSS_DP_WILDCARD_GROUP -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -Extends the Data Provider interface and the responder<->Data provider -interface with wildcard lookups. - -The patch uses a new "wildcard" prefix rather than reusing the existing -user/group prefixes. - -Reviewed-by: Pavel Březina ---- - src/providers/data_provider.h | 4 ++++ - src/providers/data_provider_be.c | 5 +++++ - src/responder/common/responder.h | 4 +++- - src/responder/common/responder_dp.c | 11 +++++++++++ - 4 files changed, 23 insertions(+), 1 deletion(-) - -diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h -index 13a700308e9c9d1a80c0310dbb1c17de33607498..510c63ce41c99314ec8fcf11fffb2e66082e8951 100644 ---- a/src/providers/data_provider.h -+++ b/src/providers/data_provider.h -@@ -129,6 +129,7 @@ - #define BE_FILTER_SECID 4 - #define BE_FILTER_UUID 5 - #define BE_FILTER_CERT 6 -+#define BE_FILTER_WILDCARD 7 - - #define BE_REQ_USER 0x0001 - #define BE_REQ_GROUP 0x0002 -@@ -153,6 +154,9 @@ - #define DP_SEC_ID_LEN (sizeof(DP_SEC_ID) - 1) - #define DP_CERT_LEN (sizeof(DP_CERT) - 1) - -+#define DP_WILDCARD "wildcard" -+#define DP_WILDCARD_LEN (sizeof(DP_WILDCARD) - 1) -+ - #define EXTRA_NAME_IS_UPN "U" - #define EXTRA_INPUT_MAYBE_WITH_VIEW "V" - -diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c -index f5bdfb676011975defa4c5a734d420c8694f3bdd..d147630248f0a24f5a632760b55b9284a6928e40 100644 ---- a/src/providers/data_provider_be.c -+++ b/src/providers/data_provider_be.c -@@ -1204,6 +1204,11 @@ static int be_get_account_info(struct sbus_request *dbus_req, void *user_data) - ret = split_name_extended(req, &filter[DP_CERT_LEN + 1], - &req->filter_value, - &req->extra_value); -+ } else if (strncmp(filter, DP_WILDCARD"=", DP_WILDCARD_LEN + 1) == 0) { -+ req->filter_type = BE_FILTER_WILDCARD; -+ ret = split_name_extended(req, &filter[DP_WILDCARD_LEN + 1], -+ &req->filter_value, -+ &req->extra_value); - } else if (strcmp(filter, ENUM_INDICATOR) == 0) { - req->filter_type = BE_FILTER_ENUM; - req->filter_value = NULL; -diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h -index bd0250d52aae1efdac3bc0847f692542c6cfb6d2..4d927cfe321bf3ad240b7c175568081ea73ab652 100644 ---- a/src/responder/common/responder.h -+++ b/src/responder/common/responder.h -@@ -282,7 +282,9 @@ enum sss_dp_acct_type { - SSS_DP_SERVICES, - SSS_DP_SECID, - SSS_DP_USER_AND_GROUP, -- SSS_DP_CERT -+ SSS_DP_CERT, -+ SSS_DP_WILDCARD_USER, -+ SSS_DP_WILDCARD_GROUP, - }; - - struct tevent_req * -diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c -index f752c94c37fd0efa0d072ef8c567bd875a08e6f7..f7f8df04e80439d2d02df3e4d2aa4f3576997f36 100644 ---- a/src/responder/common/responder_dp.c -+++ b/src/responder/common/responder_dp.c -@@ -528,9 +528,11 @@ sss_dp_get_account_msg(void *pvt) - - switch (info->type) { - case SSS_DP_USER: -+ case SSS_DP_WILDCARD_USER: - be_type = BE_REQ_USER; - break; - case SSS_DP_GROUP: -+ case SSS_DP_WILDCARD_GROUP: - be_type = BE_REQ_GROUP; - break; - case SSS_DP_INITGROUPS: -@@ -574,6 +576,15 @@ sss_dp_get_account_msg(void *pvt) - filter = talloc_asprintf(info, "%s=%s", DP_CERT, - info->opt_name); - } -+ } else if (info->type == SSS_DP_WILDCARD_USER || -+ info->type == SSS_DP_WILDCARD_GROUP) { -+ if (info->extra) { -+ filter = talloc_asprintf(info, "%s=%s:%s", DP_WILDCARD, -+ info->opt_name, info->extra); -+ } else { -+ filter = talloc_asprintf(info, "%s=%s", DP_WILDCARD, -+ info->opt_name); -+ } - } else { - if (info->extra) { - filter = talloc_asprintf(info, "name=%s:%s", --- -2.4.3 - diff --git a/SOURCES/0004-FO-Set-port-to-NOT_WORKING-when-trying-a-next-server.patch b/SOURCES/0004-FO-Set-port-to-NOT_WORKING-when-trying-a-next-server.patch new file mode 100644 index 0000000..e7bf9c3 --- /dev/null +++ b/SOURCES/0004-FO-Set-port-to-NOT_WORKING-when-trying-a-next-server.patch @@ -0,0 +1,32 @@ +From 95939e9831fb3d9a8f464ecff3377dd6027e0321 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 10 May 2016 14:11:36 +0200 +Subject: [PATCH 04/18] FO: Set port to NOT_WORKING when trying a next server +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://fedorahosted.org/sssd/ticket/3009 + +Reviewed-by: Pavel Březina +(cherry picked from commit c420ce830ac0b0b288a2a887ec2cfce5c748018c) +--- + src/providers/fail_over.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c +index e945c9924597c7addeeb11090e1c1aee5596cb71..1d88d2aa54bfdebd4b648e2b13fa8d03e2be3973 100644 +--- a/src/providers/fail_over.c ++++ b/src/providers/fail_over.c +@@ -1546,7 +1546,7 @@ void fo_try_next_server(struct fo_service *service) + service->active_server = 0; + + if (server->port_status == PORT_WORKING) { +- server->port_status = PORT_NEUTRAL; ++ server->port_status = PORT_NOT_WORKING; + } + } + +-- +2.4.11 + diff --git a/SOURCES/0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch b/SOURCES/0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch deleted file mode 100644 index 40a41fb..0000000 --- a/SOURCES/0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch +++ /dev/null @@ -1,800 +0,0 @@ -From e069e53495d77bc737abd80fb2e7799fa6245e0f Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 24 Mar 2015 23:24:50 +0100 -Subject: [PATCH 05/13] cache_req: Extend cache_req with wildcard lookups -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -Adds two new functions to the cache_req API: - - cache_req_user_by_filter_send - - cache_req_group_by_filter_send - -These functions can be used to retrieve users or groups that match a -specified filter. - -Also renames a variable to avoid constant confusion -- the variable is -only used for debug output. - -Reviewed-by: Pavel Březina ---- - src/responder/common/responder_cache_req.c | 156 ++++++++++- - src/responder/common/responder_cache_req.h | 24 +- - src/tests/cmocka/test_responder_cache_req.c | 414 +++++++++++++++++++++++++++- - 3 files changed, 579 insertions(+), 15 deletions(-) - -diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c -index dd81abadf71c5e10e7bc2ea2490429a49bdc0270..e7099f171d7ef39af7b146a524dadc38a9165e22 100644 ---- a/src/responder/common/responder_cache_req.c -+++ b/src/responder/common/responder_cache_req.c -@@ -28,6 +28,44 @@ - #include "responder/common/responder_cache_req.h" - #include "providers/data_provider.h" - -+static errno_t updated_users_by_filter(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ time_t since, -+ struct ldb_result **_res) -+{ -+ int ret; -+ char *recent_filter; -+ -+ recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)", -+ SYSDB_LAST_UPDATE, since); -+ ret = sysdb_enumpwent_filter_with_views(mem_ctx, domain, -+ name_filter, recent_filter, -+ _res); -+ talloc_free(recent_filter); -+ -+ return ret; -+} -+ -+static errno_t updated_groups_by_filter(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name_filter, -+ time_t since, -+ struct ldb_result **_res) -+{ -+ int ret; -+ char *recent_filter; -+ -+ recent_filter = talloc_asprintf(mem_ctx, "(%s>=%lu)", -+ SYSDB_LAST_UPDATE, since); -+ ret = sysdb_enumgrent_filter_with_views(mem_ctx, domain, -+ name_filter, recent_filter, -+ _res); -+ talloc_free(recent_filter); -+ -+ return ret; -+} -+ - struct cache_req_input { - enum cache_req_type type; - -@@ -51,6 +89,8 @@ struct cache_req_input { - - /* Fully qualified object name used in debug messages. */ - const char *debug_fqn; -+ /* Time when the request started. Useful for by-filter lookups */ -+ time_t req_start; - }; - - struct cache_req_input * -@@ -68,11 +108,14 @@ cache_req_input_create(TALLOC_CTX *mem_ctx, - } - - input->type = type; -+ input->req_start = time(NULL); - - /* Check that input parameters match selected type. */ - switch (input->type) { - case CACHE_REQ_USER_BY_NAME: - case CACHE_REQ_GROUP_BY_NAME: -+ case CACHE_REQ_USER_BY_FILTER: -+ case CACHE_REQ_GROUP_BY_FILTER: - case CACHE_REQ_INITGROUPS: - if (name == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL!\n"); -@@ -121,9 +164,18 @@ cache_req_input_create(TALLOC_CTX *mem_ctx, - case CACHE_REQ_INITGROUPS: - input->dp_type = SSS_DP_INITGROUPS; - break; -+ - case CACHE_REQ_USER_BY_CERT: - input->dp_type = SSS_DP_CERT; - break; -+ -+ case CACHE_REQ_USER_BY_FILTER: -+ input->dp_type = SSS_DP_WILDCARD_USER; -+ break; -+ -+ case CACHE_REQ_GROUP_BY_FILTER: -+ input->dp_type = SSS_DP_WILDCARD_GROUP; -+ break; - } - - return input; -@@ -157,7 +209,7 @@ cache_req_input_set_domain(struct cache_req_input *input, - { - TALLOC_CTX *tmp_ctx = NULL; - const char *name = NULL; -- const char *fqn = NULL; -+ const char *debug_fqn = NULL; - errno_t ret; - - tmp_ctx = talloc_new(NULL); -@@ -171,6 +223,8 @@ cache_req_input_set_domain(struct cache_req_input *input, - switch (input->type) { - case CACHE_REQ_USER_BY_NAME: - case CACHE_REQ_GROUP_BY_NAME: -+ case CACHE_REQ_USER_BY_FILTER: -+ case CACHE_REQ_GROUP_BY_FILTER: - case CACHE_REQ_INITGROUPS: - name = sss_get_cased_name(tmp_ctx, input->orig_name, - domain->case_sensitive); -@@ -185,8 +239,8 @@ cache_req_input_set_domain(struct cache_req_input *input, - goto done; - } - -- fqn = talloc_asprintf(tmp_ctx, "%s@%s", name, domain->name); -- if (fqn == NULL) { -+ debug_fqn = talloc_asprintf(tmp_ctx, "%s@%s", name, domain->name); -+ if (debug_fqn == NULL) { - ret = ENOMEM; - goto done; - } -@@ -194,16 +248,16 @@ cache_req_input_set_domain(struct cache_req_input *input, - break; - - case CACHE_REQ_USER_BY_ID: -- fqn = talloc_asprintf(tmp_ctx, "UID:%d@%s", input->id, domain->name); -- if (fqn == NULL) { -+ debug_fqn = talloc_asprintf(tmp_ctx, "UID:%d@%s", input->id, domain->name); -+ if (debug_fqn == NULL) { - ret = ENOMEM; - goto done; - } - break; - - case CACHE_REQ_GROUP_BY_ID: -- fqn = talloc_asprintf(tmp_ctx, "GID:%d@%s", input->id, domain->name); -- if (fqn == NULL) { -+ debug_fqn = talloc_asprintf(tmp_ctx, "GID:%d@%s", input->id, domain->name); -+ if (debug_fqn == NULL) { - ret = ENOMEM; - goto done; - } -@@ -211,10 +265,10 @@ cache_req_input_set_domain(struct cache_req_input *input, - case CACHE_REQ_USER_BY_CERT: - /* certificates might be quite long, only use the last 10 charcters - * for logging */ -- fqn = talloc_asprintf(tmp_ctx, "CERT:%s@%s", -- get_last_x_chars(input->cert, 10), -- domain->name); -- if (fqn == NULL) { -+ debug_fqn = talloc_asprintf(tmp_ctx, "CERT:%s@%s", -+ get_last_x_chars(input->cert, 10), -+ domain->name); -+ if (debug_fqn == NULL) { - ret = ENOMEM; - goto done; - } -@@ -223,7 +277,7 @@ cache_req_input_set_domain(struct cache_req_input *input, - - input->domain = domain; - input->dom_objname = talloc_steal(input, name); -- input->debug_fqn = talloc_steal(input, fqn); -+ input->debug_fqn = talloc_steal(input, debug_fqn); - - ret = EOK; - -@@ -257,6 +311,10 @@ static errno_t cache_req_check_ncache(struct cache_req_input *input, - case CACHE_REQ_USER_BY_CERT: - ret = sss_ncache_check_cert(ncache, neg_timeout, input->cert); - break; -+ case CACHE_REQ_USER_BY_FILTER: -+ case CACHE_REQ_GROUP_BY_FILTER: -+ ret = EOK; -+ break; - } - - if (ret == EEXIST) { -@@ -282,6 +340,10 @@ static void cache_req_add_to_ncache(struct cache_req_input *input, - ret = sss_ncache_set_group(ncache, false, input->domain, - input->dom_objname); - break; -+ case CACHE_REQ_USER_BY_FILTER: -+ case CACHE_REQ_GROUP_BY_FILTER: -+ /* Nothing to do, adding a wildcard request to ncache doesn't -+ * make sense */ - case CACHE_REQ_USER_BY_ID: - case CACHE_REQ_GROUP_BY_ID: - case CACHE_REQ_USER_BY_CERT: -@@ -308,6 +370,10 @@ static void cache_req_add_to_ncache_global(struct cache_req_input *input, - errno_t ret = ERR_INTERNAL; - - switch (input->type) { -+ case CACHE_REQ_USER_BY_FILTER: -+ case CACHE_REQ_GROUP_BY_FILTER: -+ /* Nothing to do, adding a wildcard request to ncache doesn't -+ * make sense */ - case CACHE_REQ_USER_BY_NAME: - case CACHE_REQ_GROUP_BY_NAME: - case CACHE_REQ_INITGROUPS: -@@ -377,6 +443,18 @@ static errno_t cache_req_get_object(TALLOC_CTX *mem_ctx, - ret = sysdb_search_user_by_cert(mem_ctx, input->domain, - input->cert, &result); - break; -+ case CACHE_REQ_USER_BY_FILTER: -+ one_item_only = false; -+ ret = updated_users_by_filter(mem_ctx, input->domain, -+ input->dom_objname, input->req_start, -+ &result); -+ break; -+ case CACHE_REQ_GROUP_BY_FILTER: -+ one_item_only = false; -+ ret = updated_groups_by_filter(mem_ctx, input->domain, -+ input->dom_objname, input->req_start, -+ &result); -+ break; - } - - if (ret != EOK) { -@@ -397,6 +475,19 @@ done: - return ret; - } - -+/* Return true if the request bypasses cache or false if the cache_req -+ * code can leverage sysdb for this request. -+ */ -+static bool cache_req_bypass_cache(struct cache_req_input *input) -+{ -+ if (input->type == CACHE_REQ_USER_BY_FILTER || -+ input->type == CACHE_REQ_GROUP_BY_FILTER) { -+ return true; -+ } -+ -+ return false; -+} -+ - struct cache_req_cache_state { - /* input data */ - struct tevent_context *ev; -@@ -504,7 +595,8 @@ static errno_t cache_req_cache_check(struct tevent_req *req) - - state = tevent_req_data(req, struct cache_req_cache_state); - -- if (state->result == NULL || state->result->count == 0) { -+ if (state->result == NULL || state->result->count == 0 || -+ cache_req_bypass_cache(state->input) == true) { - ret = ENOENT; - } else { - if (state->input->type == CACHE_REQ_INITGROUPS) { -@@ -1059,3 +1151,41 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx, - neg_timeout, cache_refresh_percent, - domain, input); - } -+ -+struct tevent_req * -+cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct resp_ctx *rctx, -+ const char *domain, -+ const char *filter) -+{ -+ struct cache_req_input *input; -+ -+ input = cache_req_input_create(mem_ctx, CACHE_REQ_USER_BY_FILTER, -+ filter, 0, NULL); -+ if (input == NULL) { -+ return NULL; -+ } -+ -+ return cache_req_steal_input_and_send(mem_ctx, ev, rctx, NULL, -+ 0, 0, domain, input); -+} -+ -+struct tevent_req * -+cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct resp_ctx *rctx, -+ const char *domain, -+ const char *filter) -+{ -+ struct cache_req_input *input; -+ -+ input = cache_req_input_create(mem_ctx, CACHE_REQ_GROUP_BY_FILTER, -+ filter, 0, NULL); -+ if (input == NULL) { -+ return NULL; -+ } -+ -+ return cache_req_steal_input_and_send(mem_ctx, ev, rctx, NULL, -+ 0, 0, domain, input); -+} -diff --git a/src/responder/common/responder_cache_req.h b/src/responder/common/responder_cache_req.h -index 84a9dde7d9df066e44b1352e0a4557f02d08cc15..9e3f88a1427f3dcbde9f81df2ec647821b7aa931 100644 ---- a/src/responder/common/responder_cache_req.h -+++ b/src/responder/common/responder_cache_req.h -@@ -33,7 +33,9 @@ enum cache_req_type { - CACHE_REQ_GROUP_BY_NAME, - CACHE_REQ_GROUP_BY_ID, - CACHE_REQ_INITGROUPS, -- CACHE_REQ_USER_BY_CERT -+ CACHE_REQ_USER_BY_CERT, -+ CACHE_REQ_USER_BY_FILTER, -+ CACHE_REQ_GROUP_BY_FILTER, - }; - - struct cache_req_input; -@@ -143,4 +145,24 @@ cache_req_initgr_by_name_send(TALLOC_CTX *mem_ctx, - #define cache_req_initgr_by_name_recv(mem_ctx, req, _result, _domain, _name) \ - cache_req_recv(mem_ctx, req, _result, _domain, _name) - -+struct tevent_req * -+cache_req_user_by_filter_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct resp_ctx *rctx, -+ const char *domain, -+ const char *filter); -+ -+#define cache_req_user_by_filter_recv(mem_ctx, req, _result, _domain) \ -+ cache_req_recv(mem_ctx, req, _result, _domain, NULL) -+ -+struct tevent_req * -+cache_req_group_by_filter_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct resp_ctx *rctx, -+ const char *domain, -+ const char *filter); -+ -+#define cache_req_group_by_filter_recv(mem_ctx, req, _result, _domain) \ -+ cache_req_recv(mem_ctx, req, _result, _domain, NULL) -+ - #endif /* RESPONDER_CACHE_H_ */ -diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c -index e30deed1c6bc4023a4f2154db21fe1339e9bb3c5..31b6694668607815652f45bc93210554fd2ac918 100644 ---- a/src/tests/cmocka/test_responder_cache_req.c -+++ b/src/tests/cmocka/test_responder_cache_req.c -@@ -38,6 +38,9 @@ - #define TEST_GROUP_NAME "test-group" - #define TEST_GROUP_ID 1000 - -+#define TEST_USER_NAME2 "test-user2" -+#define TEST_GROUP_NAME2 "test-group2" -+ - #define new_single_domain_test(test) \ - cmocka_unit_test_setup_teardown(test_ ## test, \ - test_single_domain_setup, \ -@@ -1694,6 +1697,405 @@ void test_group_by_id_missing_notfound(void **state) - assert_true(test_ctx->dp_called); - } - -+static void cache_req_user_by_filter_test_done(struct tevent_req *req) -+{ -+ struct cache_req_test_ctx *ctx = NULL; -+ -+ ctx = tevent_req_callback_data(req, struct cache_req_test_ctx); -+ -+ ctx->tctx->error = cache_req_user_by_filter_recv(ctx, req, -+ &ctx->result, -+ &ctx->domain); -+ talloc_zfree(req); -+ ctx->tctx->done = true; -+} -+ -+void test_users_by_filter_valid(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ const char *ldbname = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ test_ctx->create_user = true; -+ -+ ret = sysdb_store_user(test_ctx->tctx->dom, TEST_USER_NAME2, "pwd", 1001, 1001, -+ NULL, NULL, NULL, "cn="TEST_USER_NAME2",dc=test", NULL, -+ NULL, 1000, time(NULL)); -+ assert_int_equal(ret, EOK); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ test_ctx->tctx->dom->name, -+ "test*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ERR_OK); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+ -+ assert_non_null(test_ctx->result); -+ assert_int_equal(test_ctx->result->count, 2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_USER_NAME2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_USER_NAME); -+} -+ -+void test_users_by_filter_filter_old(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ const char *ldbname = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ test_ctx->create_user = true; -+ -+ /* This user was updated in distant past, so it wont't be reported by -+ * the filter search */ -+ ret = sysdb_store_user(test_ctx->tctx->dom, TEST_USER_NAME2, "pwd", 1001, 1001, -+ NULL, NULL, NULL, "cn="TEST_USER_NAME2",dc=test", NULL, -+ NULL, 1000, 1); -+ assert_int_equal(ret, EOK); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ test_ctx->tctx->dom->name, -+ "test*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ERR_OK); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+ -+ assert_non_null(test_ctx->result); -+ assert_int_equal(test_ctx->result->count, 1); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_USER_NAME); -+} -+ -+void test_users_by_filter_notfound(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ test_ctx->tctx->dom->name, -+ "nosuchuser*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ENOENT); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+} -+ -+static void test_users_by_filter_multiple_domains_valid(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ struct sss_domain_info *domain = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ const char *ldbname = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ -+ domain = find_domain_by_name(test_ctx->tctx->dom, -+ "responder_cache_req_test_d", true); -+ assert_non_null(domain); -+ -+ ret = sysdb_store_user(domain, TEST_USER_NAME, "pwd", 1000, 1000, -+ NULL, NULL, NULL, "cn="TEST_USER_NAME",dc=test", NULL, -+ NULL, 1000, time(NULL)); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_store_user(domain, TEST_USER_NAME2, "pwd", 1001, 1001, -+ NULL, NULL, NULL, "cn="TEST_USER_NAME2",dc=test", NULL, -+ NULL, 1000, time(NULL)); -+ assert_int_equal(ret, EOK); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ domain->name, -+ "test*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ERR_OK); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+ -+ assert_non_null(test_ctx->result); -+ assert_int_equal(test_ctx->result->count, 2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_USER_NAME2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_USER_NAME); -+} -+ -+static void test_users_by_filter_multiple_domains_notfound(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ struct sss_domain_info *domain = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ -+ domain = find_domain_by_name(test_ctx->tctx->dom, -+ "responder_cache_req_test_d", true); -+ assert_non_null(domain); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_user_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ domain->name, -+ "nosuchuser*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_user_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ENOENT); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+} -+ -+static void cache_req_group_by_filter_test_done(struct tevent_req *req) -+{ -+ struct cache_req_test_ctx *ctx = NULL; -+ -+ ctx = tevent_req_callback_data(req, struct cache_req_test_ctx); -+ -+ ctx->tctx->error = cache_req_group_by_filter_recv(ctx, req, -+ &ctx->result, -+ &ctx->domain); -+ talloc_zfree(req); -+ ctx->tctx->done = true; -+} -+ -+void test_groups_by_filter_valid(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ const char *ldbname = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ test_ctx->create_group = true; -+ -+ ret = sysdb_store_group(test_ctx->tctx->dom, TEST_GROUP_NAME2, -+ 1001, NULL, 1001, time(NULL)); -+ assert_int_equal(ret, EOK); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ test_ctx->tctx->dom->name, -+ "test*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ERR_OK); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+ -+ assert_non_null(test_ctx->result); -+ assert_int_equal(test_ctx->result->count, 2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_GROUP_NAME2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_GROUP_NAME); -+} -+ -+void test_groups_by_filter_notfound(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ test_ctx->tctx->dom->name, -+ "nosuchgroup*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ENOENT); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+} -+ -+void test_groups_by_filter_multiple_domains_valid(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ struct sss_domain_info *domain = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ const char *ldbname = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ -+ domain = find_domain_by_name(test_ctx->tctx->dom, -+ "responder_cache_req_test_d", true); -+ assert_non_null(domain); -+ -+ ret = sysdb_store_group(domain, TEST_GROUP_NAME, -+ 1000, NULL, 1000, time(NULL)); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_store_group(domain, TEST_GROUP_NAME2, -+ 1001, NULL, 1001, time(NULL)); -+ assert_int_equal(ret, EOK); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ domain->name, -+ "test*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ERR_OK); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+ -+ assert_non_null(test_ctx->result); -+ assert_int_equal(test_ctx->result->count, 2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[0], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_GROUP_NAME2); -+ -+ ldbname = ldb_msg_find_attr_as_string(test_ctx->result->msgs[1], -+ SYSDB_NAME, NULL); -+ assert_non_null(ldbname); -+ assert_string_equal(ldbname, TEST_GROUP_NAME); -+} -+ -+void test_groups_by_filter_multiple_domains_notfound(void **state) -+{ -+ struct cache_req_test_ctx *test_ctx = NULL; -+ struct sss_domain_info *domain = NULL; -+ TALLOC_CTX *req_mem_ctx = NULL; -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); -+ domain = find_domain_by_name(test_ctx->tctx->dom, -+ "responder_cache_req_test_d", true); -+ assert_non_null(domain); -+ -+ req_mem_ctx = talloc_new(global_talloc_context); -+ check_leaks_push(req_mem_ctx); -+ -+ /* Filters always go to DP */ -+ will_return(__wrap_sss_dp_get_account_send, test_ctx); -+ mock_account_recv_simple(); -+ -+ req = cache_req_group_by_filter_send(req_mem_ctx, test_ctx->tctx->ev, -+ test_ctx->rctx, -+ domain->name, -+ "nosuchgroup*"); -+ assert_non_null(req); -+ tevent_req_set_callback(req, cache_req_group_by_filter_test_done, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ENOENT); -+ assert_true(check_leaks_pop(req_mem_ctx)); -+} -+ - int main(int argc, const char *argv[]) - { - poptContext pc; -@@ -1741,7 +2143,17 @@ int main(int argc, const char *argv[]) - new_single_domain_test(group_by_id_missing_found), - new_single_domain_test(group_by_id_missing_notfound), - new_multi_domain_test(group_by_id_multiple_domains_found), -- new_multi_domain_test(group_by_id_multiple_domains_notfound) -+ new_multi_domain_test(group_by_id_multiple_domains_notfound), -+ -+ new_single_domain_test(users_by_filter_valid), -+ new_single_domain_test(users_by_filter_filter_old), -+ new_single_domain_test(users_by_filter_notfound), -+ new_multi_domain_test(users_by_filter_multiple_domains_valid), -+ new_multi_domain_test(users_by_filter_multiple_domains_notfound), -+ new_single_domain_test(groups_by_filter_valid), -+ new_single_domain_test(groups_by_filter_notfound), -+ new_multi_domain_test(groups_by_filter_multiple_domains_valid), -+ new_multi_domain_test(groups_by_filter_multiple_domains_notfound), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.4.3 - diff --git a/SOURCES/0005-sssctl-Fix-format-string-for-size_t.patch b/SOURCES/0005-sssctl-Fix-format-string-for-size_t.patch new file mode 100644 index 0000000..b2037a5 --- /dev/null +++ b/SOURCES/0005-sssctl-Fix-format-string-for-size_t.patch @@ -0,0 +1,37 @@ +From 8d82518980eae15d4644ce55058ed852f7f657f5 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 8 Jul 2016 13:04:10 +0200 +Subject: [PATCH 05/18] sssctl: Fix format string for size_t + +src/tools/sssctl/sssctl_config.c: In function 'sssctl_config_check': +src/tools/sssctl/sssctl_config.c:93:14: warning: format '%lu' expects + argument of type 'long unsigned int', but argument 2 has type + 'size_t {aka unsigned int}' [-Wformat=] + printf(_("Issues identified by validators: %lu\n"), num_errors); + ^ +src/tools/sssctl/sssctl_config.c:93:12: note: in expansion of macro '_' + printf(_("Issues identified by validators: %lu\n"), num_errors); + ^ +Reviewed-by: Jakub Hrozek + +(cherry picked from commit cca5695e6cab64def52c009afc8f055a85f1fde4) +--- + src/tools/sssctl/sssctl_config.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tools/sssctl/sssctl_config.c b/src/tools/sssctl/sssctl_config.c +index 4f6dbcdd7d04183c65b6613efbe5ab95df19e2c7..a66d7749c4aee9bd00c0ad2d296292658ffdb9b2 100644 +--- a/src/tools/sssctl/sssctl_config.c ++++ b/src/tools/sssctl/sssctl_config.c +@@ -91,7 +91,7 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline, + } + + /* Output from validators */ +- printf(_("Issues identified by validators: %lu\n"), num_errors); ++ printf(_("Issues identified by validators: %zu\n"), num_errors); + for (i = 0; i < num_errors; i++) { + printf("%s\n", strs[i]); + } +-- +2.4.11 + diff --git a/SOURCES/0006-UTIL-Add-sss_filter_sanitize_ex.patch b/SOURCES/0006-UTIL-Add-sss_filter_sanitize_ex.patch deleted file mode 100644 index 2c48cf8..0000000 --- a/SOURCES/0006-UTIL-Add-sss_filter_sanitize_ex.patch +++ /dev/null @@ -1,118 +0,0 @@ -From f736b14f1e308d67e091d3ee56ef0384d618130e Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 4 May 2015 13:10:01 +0200 -Subject: [PATCH 06/13] UTIL: Add sss_filter_sanitize_ex -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -In order to support wildcard request, we need to introduce an optionally -relaxed version of sss_filter_sanitize that allows to select which -characters are exempt from sanitizing. - -Reviewed-by: Pavel Březina ---- - src/tests/util-tests.c | 9 +++++++++ - src/util/util.c | 28 +++++++++++++++++++++++++--- - src/util/util.h | 5 +++++ - 3 files changed, 39 insertions(+), 3 deletions(-) - -diff --git a/src/tests/util-tests.c b/src/tests/util-tests.c -index 3d42f0193a677200d5cb4a46805892bed978305c..bfdf078027250b8ff0ce0da2d37fbb20f391d06b 100644 ---- a/src/tests/util-tests.c -+++ b/src/tests/util-tests.c -@@ -406,6 +406,15 @@ START_TEST(test_sss_filter_sanitize) - "Expected [%s], got [%s]", - has_all_expected, sanitized); - -+ /* Input is reused from previous test - "\\(user)*name" */ -+ const char has_all_allow_asterisk_expected[] = "\\5c\\28user\\29*name"; -+ ret = sss_filter_sanitize_ex(test_ctx, has_all, &sanitized, "*"); -+ fail_unless(ret == EOK, "has_all error [%d][%s]", -+ ret, strerror(ret)); -+ fail_unless(strcmp(has_all_allow_asterisk_expected, sanitized)==0, -+ "Expected [%s], got [%s]", -+ has_all_expected, sanitized); -+ - talloc_free(test_ctx); - } - END_TEST -diff --git a/src/util/util.c b/src/util/util.c -index cfd26a58b31048996e9669163b821282b219b2de..782cd026b7928e607a8980fb5f333c794feb5b1a 100644 ---- a/src/util/util.c -+++ b/src/util/util.c -@@ -525,13 +525,15 @@ errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count, - return sss_hash_create_ex(mem_ctx, count, tbl, 0, 0, 0, 0, NULL, NULL); - } - --errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, -- const char *input, -- char **sanitized) -+errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx, -+ const char *input, -+ char **sanitized, -+ const char *ignore) - { - char *output; - size_t i = 0; - size_t j = 0; -+ char *allowed; - - /* Assume the worst-case. We'll resize it later, once */ - output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1); -@@ -540,6 +542,19 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, - } - - while (input[i]) { -+ /* Even though this character might have a special meaning, if it's -+ * expliticly allowed, just copy it and move on -+ */ -+ if (ignore == NULL) { -+ allowed = NULL; -+ } else { -+ allowed = strchr(ignore, input[i]); -+ } -+ if (allowed) { -+ output[j++] = input[i++]; -+ continue; -+ } -+ - switch(input[i]) { - case '\t': - output[j++] = '\\'; -@@ -587,6 +602,13 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, - return EOK; - } - -+errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, -+ const char *input, -+ char **sanitized) -+{ -+ return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL); -+} -+ - char * - sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr) - { -diff --git a/src/util/util.h b/src/util/util.h -index 3d90cf0d1024b93016987a4d3e8a515359fd974d..94a3ddea839f0998cb7796f1d2fe13f743de3aaf 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -485,6 +485,11 @@ errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx, - const char *input, - char **sanitized); - -+errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx, -+ const char *input, -+ char **sanitized, -+ const char *ignore); -+ - errno_t sss_filter_sanitize_for_dom(TALLOC_CTX *mem_ctx, - const char *input, - struct sss_domain_info *dom, --- -2.4.3 - diff --git a/SOURCES/0006-doxygen-Fix-path-to-header-file-ipa_hbac.h.patch b/SOURCES/0006-doxygen-Fix-path-to-header-file-ipa_hbac.h.patch new file mode 100644 index 0000000..b3e1f55 --- /dev/null +++ b/SOURCES/0006-doxygen-Fix-path-to-header-file-ipa_hbac.h.patch @@ -0,0 +1,31 @@ +From fda4c78ca651ce478fe744f7de87c2064e80a05d Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 8 Jul 2016 13:27:47 +0200 +Subject: [PATCH 06/18] doxygen: Fix path to header file ipa_hbac.h + +Warning: tag INPUT: input source `src/providers/ipa/ipa_hbac.h' does not exist +warning: source src/providers/ipa/ipa_hbac.h is not + a readable file or directory... skipping. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit b9b2c0836f64f375babb75d92b924f3780f20521) +--- + src/lib/ipa_hbac/ipa_hbac.doxy.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lib/ipa_hbac/ipa_hbac.doxy.in b/src/lib/ipa_hbac/ipa_hbac.doxy.in +index 6d4a92659f1974fa96b8fcfbcca0d4107e3a7dae..d1e9f995ddeffd92dad03b5d1fd18077b6aeb645 100644 +--- a/src/lib/ipa_hbac/ipa_hbac.doxy.in ++++ b/src/lib/ipa_hbac/ipa_hbac.doxy.in +@@ -678,7 +678,7 @@ WARN_LOGFILE = + # directories like "/usr/src/myproject". Separate the files or directories + # with spaces. + +-INPUT = @abs_top_srcdir@/src/providers/ipa/ipa_hbac.h ++INPUT = @abs_top_srcdir@/src/lib/ipa_hbac/ipa_hbac.h + + # This tag can be used to specify the character encoding of the source files + # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +-- +2.4.11 + diff --git a/SOURCES/0007-LDAP-Fetch-users-and-groups-using-wildcards.patch b/SOURCES/0007-LDAP-Fetch-users-and-groups-using-wildcards.patch deleted file mode 100644 index d02553f..0000000 --- a/SOURCES/0007-LDAP-Fetch-users-and-groups-using-wildcards.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 9604ff1731ab7bd067bef62a0df6000eca091856 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 4 May 2015 15:16:44 +0200 -Subject: [PATCH 07/13] LDAP: Fetch users and groups using wildcards -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -Adds handler for the BE_FILTER_WILDCARD in the LDAP provider. So far -it's the same code as if enumeration was used, so there are no limits. - -Reviewed-by: Pavel Březina ---- - src/providers/ldap/ldap_common.h | 3 +++ - src/providers/ldap/ldap_id.c | 50 ++++++++++++++++++++++++++++++++++++++-- - 2 files changed, 51 insertions(+), 2 deletions(-) - -diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h -index 424eacb1da0a6934b132ccb2a5bb175233fa1a80..8294d1db23bdca8d94a098533d93405c4d55226b 100644 ---- a/src/providers/ldap/ldap_common.h -+++ b/src/providers/ldap/ldap_common.h -@@ -39,6 +39,9 @@ - #define LDAP_SSL_URI "ldaps://" - #define LDAP_LDAPI_URI "ldapi://" - -+/* Only the asterisk is allowed in wildcard requests */ -+#define LDAP_ALLOWED_WILDCARDS "*" -+ - /* a fd the child process would log into */ - extern int ldap_child_debug_fd; - -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index 3245e1b12a69483f961f01210d13654b1c7c5345..61f09fc41d3210af5044f5338dd90db67e0123a7 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -114,6 +114,14 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, - sdom->dom->name, - sdom->dom->domain_id); - switch (filter_type) { -+ case BE_FILTER_WILDCARD: -+ attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name; -+ ret = sss_filter_sanitize_ex(state, name, &clean_name, -+ LDAP_ALLOWED_WILDCARDS); -+ if (ret != EOK) { -+ goto done; -+ } -+ break; - case BE_FILTER_NAME: - if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) { - attr_name = ctx->opts->user_map[SDAP_AT_USER_PRINC].name; -@@ -388,6 +396,13 @@ static void users_get_search(struct tevent_req *req) - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - struct tevent_req *subreq; -+ bool multiple_results; -+ -+ if (state->filter_type == BE_FILTER_WILDCARD) { -+ multiple_results = true; -+ } else { -+ multiple_results = false; -+ } - - subreq = sdap_get_users_send(state, state->ev, - state->domain, state->sysdb, -@@ -397,7 +412,7 @@ static void users_get_search(struct tevent_req *req) - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), -- false); -+ multiple_results); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; -@@ -508,6 +523,13 @@ static void users_get_done(struct tevent_req *subreq) - * group we have nothing to do here. */ - break; - -+ case BE_FILTER_WILDCARD: -+ /* We can't know if all users are up-to-date, especially in a large -+ * environment. Do not delete any records, let the responder fetch -+ * the entries they are requested in -+ */ -+ break; -+ - default: - tevent_req_error(req, EINVAL); - return; -@@ -619,6 +641,14 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, - sdom->dom->domain_id); - - switch(filter_type) { -+ case BE_FILTER_WILDCARD: -+ attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name; -+ ret = sss_filter_sanitize_ex(state, name, &clean_name, -+ LDAP_ALLOWED_WILDCARDS); -+ if (ret != EOK) { -+ goto done; -+ } -+ break; - case BE_FILTER_NAME: - attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name; - -@@ -871,6 +901,13 @@ static void groups_get_search(struct tevent_req *req) - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - struct tevent_req *subreq; -+ bool multiple_results; -+ -+ if (state->filter_type == BE_FILTER_WILDCARD) { -+ multiple_results = true; -+ } else { -+ multiple_results = false; -+ } - - subreq = sdap_get_groups_send(state, state->ev, - state->sdom, -@@ -879,7 +916,8 @@ static void groups_get_search(struct tevent_req *req) - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), -- false, state->no_members); -+ multiple_results, -+ state->no_members); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; -@@ -953,6 +991,14 @@ static void groups_get_done(struct tevent_req *subreq) - * group we have nothing to do here. */ - break; - -+ case BE_FILTER_WILDCARD: -+ /* We can't know if all groups are up-to-date, especially in -+ * a large environment. Do not delete any records, let the -+ * responder fetch the entries they are requested in. -+ */ -+ break; -+ -+ - default: - tevent_req_error(req, EINVAL); - return; --- -2.4.3 - diff --git a/SOURCES/0007-ipa_hbac-Fix-documentation-for-hbac_enable_debug.patch b/SOURCES/0007-ipa_hbac-Fix-documentation-for-hbac_enable_debug.patch new file mode 100644 index 0000000..0308ac2 --- /dev/null +++ b/SOURCES/0007-ipa_hbac-Fix-documentation-for-hbac_enable_debug.patch @@ -0,0 +1,31 @@ +From 3743b49557f63d0ca541103fe0929e432cde3678 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 8 Jul 2016 14:39:43 +0200 +Subject: [PATCH 07/18] ipa_hbac: Fix documentation for hbac_enable_debug + +src/lib/ipa_hbac/ipa_hbac.h:68: warning: expected whitespace after [ command + +Reviewed-by: Jakub Hrozek +(cherry picked from commit f3db22862d22821be2d566435cb0c59387343fc2) +--- + src/lib/ipa_hbac/ipa_hbac.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/lib/ipa_hbac/ipa_hbac.h b/src/lib/ipa_hbac/ipa_hbac.h +index 8801c20c492caf53a089c2724c2ed4a96805904c..f9d339c058f109acdea95fa185182f08d1e8af9e 100644 +--- a/src/lib/ipa_hbac/ipa_hbac.h ++++ b/src/lib/ipa_hbac/ipa_hbac.h +@@ -65,8 +65,8 @@ typedef void (*hbac_debug_fn_t)(const char *file, int line, + ...) HBAC_ATTRIBUTE_PRINTF(5, 6); + + /** +- * HBAC uses external_debug_fn for logging messages. +- * @param[in|out] external_debug_void Pointer to external logging function. ++ * HBAC uses external_debug_fn for logging messages. ++ * @param[in] external_debug_fn Pointer to external logging function. + */ + void hbac_enable_debug(hbac_debug_fn_t external_debug_fn); + +-- +2.4.11 + diff --git a/SOURCES/0008-LDAP-Add-sdap_get_and_parse_generic_send.patch b/SOURCES/0008-LDAP-Add-sdap_get_and_parse_generic_send.patch deleted file mode 100644 index b2a8e01..0000000 --- a/SOURCES/0008-LDAP-Add-sdap_get_and_parse_generic_send.patch +++ /dev/null @@ -1,298 +0,0 @@ -From fceab48ac589473216067e40d8577e19a02d3b45 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 4 May 2015 16:27:06 +0200 -Subject: [PATCH 08/13] LDAP: Add sdap_get_and_parse_generic_send -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -So far we had a simple sdap_get_generic_send() request that uses the -right defaults around the low-level sdap_get_generic_ext_send() request -and calls the parser. - -This patch adds also sdap_get_and_parse_generic_send() that exposes all -options that sdap_get_generic_ext_send() offers but also calls the -parser. - -In this patch the function is not used at all. - -Reviewed-by: Pavel Březina ---- - src/providers/ldap/sdap_async.c | 185 ++++++++++++++++++++++++++++------------ - src/providers/ldap/sdap_async.h | 22 +++++ - 2 files changed, 154 insertions(+), 53 deletions(-) - -diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c -index 5263c250b8a15a98e685ca81e636def27ea05894..c5be8561a197c96f62bb2582a4d30c28de71f580 100644 ---- a/src/providers/ldap/sdap_async.c -+++ b/src/providers/ldap/sdap_async.c -@@ -1656,9 +1656,8 @@ static void generic_ext_search_handler(struct tevent_req *subreq, - tevent_req_done(req); - } - -- --/* ==Generic Search============================================ */ --struct sdap_get_generic_state { -+/* ==Generic Search exposing all options======================= */ -+struct sdap_get_and_parse_generic_state { - struct sdap_attr_map *map; - int map_num_attrs; - -@@ -1666,10 +1665,119 @@ struct sdap_get_generic_state { - struct sdap_options *opts; - }; - -+static void sdap_get_and_parse_generic_done(struct tevent_req *subreq); -+static errno_t sdap_get_and_parse_generic_parse_entry(struct sdap_handle *sh, -+ struct sdap_msg *msg, -+ void *pvt); -+ -+struct tevent_req *sdap_get_and_parse_generic_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sdap_options *opts, -+ struct sdap_handle *sh, -+ const char *search_base, -+ int scope, -+ const char *filter, -+ const char **attrs, -+ struct sdap_attr_map *map, -+ int map_num_attrs, -+ int attrsonly, -+ LDAPControl **serverctrls, -+ LDAPControl **clientctrls, -+ int sizelimit, -+ int timeout, -+ bool allow_paging) -+{ -+ struct tevent_req *req = NULL; -+ struct tevent_req *subreq = NULL; -+ struct sdap_get_and_parse_generic_state *state = NULL; -+ -+ req = tevent_req_create(memctx, &state, -+ struct sdap_get_and_parse_generic_state); -+ if (!req) return NULL; -+ -+ state->map = map; -+ state->map_num_attrs = map_num_attrs; -+ state->opts = opts; -+ -+ subreq = sdap_get_generic_ext_send(state, ev, opts, sh, search_base, -+ scope, filter, attrs, false, NULL, -+ NULL, sizelimit, timeout, allow_paging, -+ sdap_get_and_parse_generic_parse_entry, state); -+ if (!subreq) { -+ talloc_zfree(req); -+ return NULL; -+ } -+ tevent_req_set_callback(subreq, sdap_get_and_parse_generic_done, req); -+ -+ return req; -+} -+ -+static errno_t sdap_get_and_parse_generic_parse_entry(struct sdap_handle *sh, -+ struct sdap_msg *msg, -+ void *pvt) -+{ -+ errno_t ret; -+ struct sysdb_attrs *attrs; -+ struct sdap_get_and_parse_generic_state *state = -+ talloc_get_type(pvt, struct sdap_get_and_parse_generic_state); -+ -+ bool disable_range_rtrvl = dp_opt_get_bool(state->opts->basic, -+ SDAP_DISABLE_RANGE_RETRIEVAL); -+ -+ ret = sdap_parse_entry(state, sh, msg, -+ state->map, state->map_num_attrs, -+ &attrs, disable_range_rtrvl); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "sdap_parse_entry failed [%d]: %s\n", ret, strerror(ret)); -+ return ret; -+ } -+ -+ ret = add_to_reply(state, &state->sreply, attrs); -+ if (ret != EOK) { -+ talloc_free(attrs); -+ DEBUG(SSSDBG_CRIT_FAILURE, "add_to_reply failed.\n"); -+ return ret; -+ } -+ -+ /* add_to_reply steals attrs, no need to free them here */ -+ return EOK; -+} -+ -+static void sdap_get_and_parse_generic_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_get_and_parse_generic_state *state = -+ tevent_req_data(req, struct sdap_get_and_parse_generic_state); -+ -+ return generic_ext_search_handler(subreq, state->opts); -+} -+ -+int sdap_get_and_parse_generic_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ size_t *reply_count, -+ struct sysdb_attrs ***reply) -+{ -+ struct sdap_get_and_parse_generic_state *state = tevent_req_data(req, -+ struct sdap_get_and_parse_generic_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ *reply_count = state->sreply.reply_count; -+ *reply = talloc_steal(mem_ctx, state->sreply.reply); -+ -+ return EOK; -+} -+ -+ -+/* ==Simple generic search============================================== */ -+struct sdap_get_generic_state { -+ size_t reply_count; -+ struct sysdb_attrs **reply; -+}; -+ - static void sdap_get_generic_done(struct tevent_req *subreq); --static errno_t sdap_get_generic_parse_entry(struct sdap_handle *sh, -- struct sdap_msg *msg, -- void *pvt); - - struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx, - struct tevent_context *ev, -@@ -1691,16 +1799,12 @@ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx, - req = tevent_req_create(memctx, &state, struct sdap_get_generic_state); - if (!req) return NULL; - -- state->map = map; -- state->map_num_attrs = map_num_attrs; -- state->opts = opts; -- -- subreq = sdap_get_generic_ext_send(state, ev, opts, sh, search_base, -- scope, filter, attrs, false, NULL, -- NULL, 0, timeout, allow_paging, -- sdap_get_generic_parse_entry, state); -- if (!subreq) { -- talloc_zfree(req); -+ subreq = sdap_get_and_parse_generic_send(memctx, ev, opts, sh, search_base, -+ scope, filter, attrs, -+ map, map_num_attrs, -+ false, NULL, NULL, 0, timeout, -+ allow_paging); -+ if (subreq == NULL) { - return NULL; - } - tevent_req_set_callback(subreq, sdap_get_generic_done, req); -@@ -1708,46 +1812,21 @@ struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx, - return req; - } - --static errno_t sdap_get_generic_parse_entry(struct sdap_handle *sh, -- struct sdap_msg *msg, -- void *pvt) --{ -- errno_t ret; -- struct sysdb_attrs *attrs; -- struct sdap_get_generic_state *state = -- talloc_get_type(pvt, struct sdap_get_generic_state); -- -- bool disable_range_rtrvl = dp_opt_get_bool(state->opts->basic, -- SDAP_DISABLE_RANGE_RETRIEVAL); -- -- ret = sdap_parse_entry(state, sh, msg, -- state->map, state->map_num_attrs, -- &attrs, disable_range_rtrvl); -- if (ret != EOK) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- "sdap_parse_entry failed [%d]: %s\n", ret, strerror(ret)); -- return ret; -- } -- -- ret = add_to_reply(state, &state->sreply, attrs); -- if (ret != EOK) { -- talloc_free(attrs); -- DEBUG(SSSDBG_CRIT_FAILURE, "add_to_reply failed.\n"); -- return ret; -- } -- -- /* add_to_reply steals attrs, no need to free them here */ -- return EOK; --} -- - static void sdap_get_generic_done(struct tevent_req *subreq) - { - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_generic_state *state = - tevent_req_data(req, struct sdap_get_generic_state); -+ errno_t ret; - -- return generic_ext_search_handler(subreq, state->opts); -+ ret = sdap_get_and_parse_generic_recv(subreq, state, -+ &state->reply_count, &state->reply); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ tevent_req_done(req); - } - - int sdap_get_generic_recv(struct tevent_req *req, -@@ -1755,13 +1834,13 @@ int sdap_get_generic_recv(struct tevent_req *req, - size_t *reply_count, - struct sysdb_attrs ***reply) - { -- struct sdap_get_generic_state *state = tevent_req_data(req, -- struct sdap_get_generic_state); -+ struct sdap_get_generic_state *state = -+ tevent_req_data(req, struct sdap_get_generic_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - -- *reply_count = state->sreply.reply_count; -- *reply = talloc_steal(mem_ctx, state->sreply.reply); -+ *reply_count = state->reply_count; -+ *reply = talloc_steal(mem_ctx, state->reply); - - return EOK; - } -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index b5db64d7fa3c852fba60e07db19e823e818d29f3..b23dfc313905d01caedd1eace6bcb525481b9ebe 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -181,6 +181,28 @@ int sdap_cli_connect_recv(struct tevent_req *req, - struct sdap_handle **gsh, - struct sdap_server_opts **srv_opts); - -+/* Exposes all options of generic send while allowing to parse by map */ -+struct tevent_req *sdap_get_and_parse_generic_send(TALLOC_CTX *memctx, -+ struct tevent_context *ev, -+ struct sdap_options *opts, -+ struct sdap_handle *sh, -+ const char *search_base, -+ int scope, -+ const char *filter, -+ const char **attrs, -+ struct sdap_attr_map *map, -+ int map_num_attrs, -+ int attrsonly, -+ LDAPControl **serverctrls, -+ LDAPControl **clientctrls, -+ int sizelimit, -+ int timeout, -+ bool allow_paging); -+int sdap_get_and_parse_generic_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ size_t *reply_count, -+ struct sysdb_attrs ***reply); -+ - struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sdap_options *opts, --- -2.4.3 - diff --git a/SOURCES/0008-sssctl-Fix-warning-maybe-uninitialized.patch b/SOURCES/0008-sssctl-Fix-warning-maybe-uninitialized.patch new file mode 100644 index 0000000..77fde17 --- /dev/null +++ b/SOURCES/0008-sssctl-Fix-warning-maybe-uninitialized.patch @@ -0,0 +1,63 @@ +From e64aac5e33523f8473471b945403f0d9ba74c8cf Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 8 Jul 2016 15:27:23 +0200 +Subject: [PATCH 08/18] sssctl: Fix warning maybe-uninitialized +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It looks like some special gcc optimalisation and special case +may cause to have unitialized output argument _dom when return +code is EOK + +src/tools/sssctl/sssctl_cache.c: In function ‘sssctl_print_object’: +src/tools/sssctl/sssctl_cache.c:491:8: error: ‘dom’ may be used + uninitialized in this function [-Werror=maybe-uninitialized] + if (dom == NULL) { + ^ +src/tools/sssctl/sssctl_cache.c:447:15: error: ‘entry’ may be used + uninitialized in this function [-Werror=maybe-uninitialized] + *_entry = talloc_steal(mem_ctx, entry); + ^~~~~~~~~~~~ +src/tools/sssctl/sssctl_cache.c:412:25: note: ‘entry’ was declared here + struct sysdb_attrs *entry; + ^~~~~ + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 64d664c201916d8678b5f4bd7e1559c7ece9217d) +--- + src/tools/sssctl/sssctl_cache.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/src/tools/sssctl/sssctl_cache.c b/src/tools/sssctl/sssctl_cache.c +index 28de6c139d844f98f9b06844492c935696e19643..e23bb89db95217e66a441b7e4d6d32e668486cc8 100644 +--- a/src/tools/sssctl/sssctl_cache.c ++++ b/src/tools/sssctl/sssctl_cache.c +@@ -372,15 +372,19 @@ static errno_t sssctl_find_object(TALLOC_CTX *mem_ctx, + + ret = sssctl_query_cache(tmp_ctx, dom->sysdb, base_dn, filter, + attrs, &entry); +- if (ret == EOK) { ++ switch(ret) { ++ case EOK: + /* Entry was found. */ + *_entry = talloc_steal(mem_ctx, entry); + *_dom = dom; + goto done; +- } else if (ret == ENOENT && fqn_provided) { +- /* Not found but a domain was provided in input. We're done. */ +- goto done; +- } else if (ret != ENOENT) { ++ case ENOENT: ++ if (fqn_provided) { ++ /* Not found but a domain was provided in input. We're done. */ ++ goto done; ++ } ++ break; ++ default: + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to query cache [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; +-- +2.4.11 + diff --git a/SOURCES/0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch b/SOURCES/0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch deleted file mode 100644 index 293d522..0000000 --- a/SOURCES/0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 02813c46feb5484a2e171514c7ba9dd9b1b34006 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 4 May 2015 16:33:37 +0200 -Subject: [PATCH 09/13] LDAP: Use sdap_get_and_parse_generic_/_recv -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -Using the new request sdap_get_and_parse_generic_send is a separate -commit so that we can audit where the function is used during a code -review. - -Reviewed-by: Pavel Březina ---- - src/providers/ldap/sdap_async_groups.c | 8 ++++---- - src/providers/ldap/sdap_async_users.c | 8 ++++---- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 73caa9b5bd662477cd29b5220f6b437991831578..e785307e60d0df5be96a5b2de2c07baabaf1e371 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -1870,14 +1870,14 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - "Searching for groups with base [%s]\n", - state->search_bases[state->base_iter]->basedn); - -- subreq = sdap_get_generic_send( -+ subreq = sdap_get_and_parse_generic_send( - state, state->ev, state->opts, - state->ldap_sh != NULL ? state->ldap_sh : state->sh, - state->search_bases[state->base_iter]->basedn, - state->search_bases[state->base_iter]->scope, - state->filter, state->attrs, - state->opts->group_map, SDAP_OPTS_GROUP, -- state->timeout, -+ 0, NULL, NULL, 0, state->timeout, - state->enumeration); /* If we're enumerating, we need paging */ - if (!subreq) { - return ENOMEM; -@@ -1903,8 +1903,8 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - struct sysdb_attrs **groups; - char **groupnamelist; - -- ret = sdap_get_generic_recv(subreq, state, -- &count, &groups); -+ ret = sdap_get_and_parse_generic_recv(subreq, state, -+ &count, &groups); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index 416bedda8491fae5385e6b6a074b4cf05ae86b65..216b49477bf21481265444c5c03df0aac7ee84e4 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -688,13 +688,13 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - "Searching for users with base [%s]\n", - state->search_bases[state->base_iter]->basedn); - -- subreq = sdap_get_generic_send( -+ subreq = sdap_get_and_parse_generic_send( - state, state->ev, state->opts, state->sh, - state->search_bases[state->base_iter]->basedn, - state->search_bases[state->base_iter]->scope, - state->filter, state->attrs, - state->opts->user_map, state->opts->user_map_cnt, -- state->timeout, -+ 0, NULL, NULL, 0, state->timeout, - state->enumeration); /* If we're enumerating, we need paging */ - if (subreq == NULL) { - return ENOMEM; -@@ -715,8 +715,8 @@ static void sdap_search_user_process(struct tevent_req *subreq) - struct sysdb_attrs **users; - bool next_base = false; - -- ret = sdap_get_generic_recv(subreq, state, -- &count, &users); -+ ret = sdap_get_and_parse_generic_recv(subreq, state, -+ &count, &users); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); --- -2.4.3 - diff --git a/SOURCES/0009-NOUPSTREAM-Bundle-http-parser.patch b/SOURCES/0009-NOUPSTREAM-Bundle-http-parser.patch new file mode 100644 index 0000000..a17b34c --- /dev/null +++ b/SOURCES/0009-NOUPSTREAM-Bundle-http-parser.patch @@ -0,0 +1,2922 @@ +From bd5daccde22322d216d450f40a50c1a3d7c5a32c Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 12 Jul 2016 13:36:32 +0200 +Subject: [PATCH 09/18] NOUPSTREAM: Bundle http-parser + +--- + Makefile.am | 15 + + src/external/libhttp_parser.m4 | 7 +- + src/responder/secrets/http_parser.c | 2469 ++++++++++++++++++++++++++++++++ + src/responder/secrets/http_parser.h | 362 +++++ + src/responder/secrets/secsrv_private.h | 2 +- + 5 files changed, 2850 insertions(+), 5 deletions(-) + create mode 100644 src/responder/secrets/http_parser.c + create mode 100644 src/responder/secrets/http_parser.h + +diff --git a/Makefile.am b/Makefile.am +index 706b60d6a065e0a983f5a1cfbc26a78331c67d58..d05919705910fa565ff954224ce40feb5d7ff39f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1370,6 +1370,9 @@ sssd_secrets_SOURCES = \ + $(SSSD_RESPONDER_OBJ) \ + $(SSSD_RESOLV_OBJ) \ + $(NULL) ++sssd_secrets_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ $(NULL) + sssd_secrets_LDADD = \ + $(HTTP_PARSER_LIBS) \ + $(JANSSON_LIBS) \ +@@ -1379,6 +1382,18 @@ sssd_secrets_LDADD = \ + $(CARES_LIBS) \ + $(SSSD_INTERNAL_LTLIBS) \ + $(NULL) ++ ++if BUNDLE_HTTP_PARSER ++sssd_secrets_CFLAGS += \ ++ -DHTTP_PARSER_STRICT=1 \ ++ $(NULL) ++ ++sssd_secrets_SOURCES += \ ++ src/responder/secrets/http_parser.c \ ++ src/responder/secrets/http_parser.h \ ++ $(NULL) ++endif ++ + endif + + sssd_be_SOURCES = \ +diff --git a/src/external/libhttp_parser.m4 b/src/external/libhttp_parser.m4 +index 504bdf0f66c95b3d224c677a205a46e6f8b44726..c4c5b0dad29da281295529be047d30e502f5de70 100644 +--- a/src/external/libhttp_parser.m4 ++++ b/src/external/libhttp_parser.m4 +@@ -16,7 +16,6 @@ AS_IF([test x"$found_http_parser" != xyes], + [-L$sss_extra_libdir -lhttp_parser]) + ], + [-L$sss_extra_libdir -lhttp_parser_strict])], +- [AC_MSG_ERROR([ +-You must have the header file http_parse.h installed to build sssd +-with secrets responder. If you want to build sssd without secret responder +-then specify --without-secrets when running configure.])])]) ++ [AC_MSG_WARN([Will use bundled http-parser])])]) ++ ++AM_CONDITIONAL([BUNDLE_HTTP_PARSER], [test x"$HTTP_PARSER_LIBS" = x]) +diff --git a/src/responder/secrets/http_parser.c b/src/responder/secrets/http_parser.c +new file mode 100644 +index 0000000000000000000000000000000000000000..3c896ffadcc0dbf13942457d32c77d15bfec33e7 +--- /dev/null ++++ b/src/responder/secrets/http_parser.c +@@ -0,0 +1,2469 @@ ++/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev ++ * ++ * Additional changes are licensed under the same terms as NGINX and ++ * copyright Joyent, Inc. and other Node contributors. All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++#include "http_parser.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef ULLONG_MAX ++# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ ++#endif ++ ++#ifndef MIN ++# define MIN(a,b) ((a) < (b) ? (a) : (b)) ++#endif ++ ++#ifndef ARRAY_SIZE ++# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) ++#endif ++ ++#ifndef BIT_AT ++# define BIT_AT(a, i) \ ++ (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ ++ (1 << ((unsigned int) (i) & 7)))) ++#endif ++ ++#ifndef ELEM_AT ++# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) ++#endif ++ ++#define SET_ERRNO(e) \ ++do { \ ++ parser->http_errno = (e); \ ++} while(0) ++ ++#define CURRENT_STATE() p_state ++#define UPDATE_STATE(V) p_state = (enum state) (V); ++#define RETURN(V) \ ++do { \ ++ parser->state = CURRENT_STATE(); \ ++ return (V); \ ++} while (0); ++#define REEXECUTE() \ ++ goto reexecute; \ ++ ++ ++#ifdef __GNUC__ ++# define LIKELY(X) __builtin_expect(!!(X), 1) ++# define UNLIKELY(X) __builtin_expect(!!(X), 0) ++#else ++# define LIKELY(X) (X) ++# define UNLIKELY(X) (X) ++#endif ++ ++ ++/* Run the notify callback FOR, returning ER if it fails */ ++#define CALLBACK_NOTIFY_(FOR, ER) \ ++do { \ ++ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ ++ \ ++ if (LIKELY(settings->on_##FOR)) { \ ++ parser->state = CURRENT_STATE(); \ ++ if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ ++ SET_ERRNO(HPE_CB_##FOR); \ ++ } \ ++ UPDATE_STATE(parser->state); \ ++ \ ++ /* We either errored above or got paused; get out */ \ ++ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ ++ return (ER); \ ++ } \ ++ } \ ++} while (0) ++ ++/* Run the notify callback FOR and consume the current byte */ ++#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) ++ ++/* Run the notify callback FOR and don't consume the current byte */ ++#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) ++ ++/* Run data callback FOR with LEN bytes, returning ER if it fails */ ++#define CALLBACK_DATA_(FOR, LEN, ER) \ ++do { \ ++ assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ ++ \ ++ if (FOR##_mark) { \ ++ if (LIKELY(settings->on_##FOR)) { \ ++ parser->state = CURRENT_STATE(); \ ++ if (UNLIKELY(0 != \ ++ settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ ++ SET_ERRNO(HPE_CB_##FOR); \ ++ } \ ++ UPDATE_STATE(parser->state); \ ++ \ ++ /* We either errored above or got paused; get out */ \ ++ if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ ++ return (ER); \ ++ } \ ++ } \ ++ FOR##_mark = NULL; \ ++ } \ ++} while (0) ++ ++/* Run the data callback FOR and consume the current byte */ ++#define CALLBACK_DATA(FOR) \ ++ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) ++ ++/* Run the data callback FOR and don't consume the current byte */ ++#define CALLBACK_DATA_NOADVANCE(FOR) \ ++ CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) ++ ++/* Set the mark FOR; non-destructive if mark is already set */ ++#define MARK(FOR) \ ++do { \ ++ if (!FOR##_mark) { \ ++ FOR##_mark = p; \ ++ } \ ++} while (0) ++ ++/* Don't allow the total size of the HTTP headers (including the status ++ * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect ++ * embedders against denial-of-service attacks where the attacker feeds ++ * us a never-ending header that the embedder keeps buffering. ++ * ++ * This check is arguably the responsibility of embedders but we're doing ++ * it on the embedder's behalf because most won't bother and this way we ++ * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger ++ * than any reasonable request or response so this should never affect ++ * day-to-day operation. ++ */ ++#define COUNT_HEADER_SIZE(V) \ ++do { \ ++ parser->nread += (V); \ ++ if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ ++ SET_ERRNO(HPE_HEADER_OVERFLOW); \ ++ goto error; \ ++ } \ ++} while (0) ++ ++ ++#define PROXY_CONNECTION "proxy-connection" ++#define CONNECTION "connection" ++#define CONTENT_LENGTH "content-length" ++#define TRANSFER_ENCODING "transfer-encoding" ++#define UPGRADE "upgrade" ++#define CHUNKED "chunked" ++#define KEEP_ALIVE "keep-alive" ++#define CLOSE "close" ++ ++ ++static const char *method_strings[] = ++ { ++#define XX(num, name, string) #string, ++ HTTP_METHOD_MAP(XX) ++#undef XX ++ }; ++ ++ ++/* Tokens as defined by rfc 2616. Also lowercases them. ++ * token = 1* ++ * separators = "(" | ")" | "<" | ">" | "@" ++ * | "," | ";" | ":" | "\" | <"> ++ * | "/" | "[" | "]" | "?" | "=" ++ * | "{" | "}" | SP | HT ++ */ ++static const char tokens[256] = { ++/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ ++ 0, '!', 0, '#', '$', '%', '&', '\'', ++/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ ++ 0, 0, '*', '+', 0, '-', '.', 0, ++/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ ++ '0', '1', '2', '3', '4', '5', '6', '7', ++/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ ++ '8', '9', 0, 0, 0, 0, 0, 0, ++/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ ++ 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', ++/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ ++ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', ++/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ ++ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', ++/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ ++ 'x', 'y', 'z', 0, 0, 0, '^', '_', ++/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ ++ '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', ++/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ ++ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', ++/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ ++ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', ++/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ ++ 'x', 'y', 'z', 0, '|', 0, '~', 0 }; ++ ++ ++static const int8_t unhex[256] = ++ {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ++ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ++ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ++ , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 ++ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 ++ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ++ ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 ++ ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ++ }; ++ ++ ++#if HTTP_PARSER_STRICT ++# define T(v) 0 ++#else ++# define T(v) v ++#endif ++ ++ ++static const uint8_t normal_url_char[32] = { ++/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ ++ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, ++/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ ++ 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, ++/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ ++ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, ++/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ ++ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, ++/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ ++ 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, ++/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, ++/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, ++/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ ++ 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; ++ ++#undef T ++ ++enum state ++ { s_dead = 1 /* important that this is > 0 */ ++ ++ , s_start_req_or_res ++ , s_res_or_resp_H ++ , s_start_res ++ , s_res_H ++ , s_res_HT ++ , s_res_HTT ++ , s_res_HTTP ++ , s_res_first_http_major ++ , s_res_http_major ++ , s_res_first_http_minor ++ , s_res_http_minor ++ , s_res_first_status_code ++ , s_res_status_code ++ , s_res_status_start ++ , s_res_status ++ , s_res_line_almost_done ++ ++ , s_start_req ++ ++ , s_req_method ++ , s_req_spaces_before_url ++ , s_req_schema ++ , s_req_schema_slash ++ , s_req_schema_slash_slash ++ , s_req_server_start ++ , s_req_server ++ , s_req_server_with_at ++ , s_req_path ++ , s_req_query_string_start ++ , s_req_query_string ++ , s_req_fragment_start ++ , s_req_fragment ++ , s_req_http_start ++ , s_req_http_H ++ , s_req_http_HT ++ , s_req_http_HTT ++ , s_req_http_HTTP ++ , s_req_first_http_major ++ , s_req_http_major ++ , s_req_first_http_minor ++ , s_req_http_minor ++ , s_req_line_almost_done ++ ++ , s_header_field_start ++ , s_header_field ++ , s_header_value_discard_ws ++ , s_header_value_discard_ws_almost_done ++ , s_header_value_discard_lws ++ , s_header_value_start ++ , s_header_value ++ , s_header_value_lws ++ ++ , s_header_almost_done ++ ++ , s_chunk_size_start ++ , s_chunk_size ++ , s_chunk_parameters ++ , s_chunk_size_almost_done ++ ++ , s_headers_almost_done ++ , s_headers_done ++ ++ /* Important: 's_headers_done' must be the last 'header' state. All ++ * states beyond this must be 'body' states. It is used for overflow ++ * checking. See the PARSING_HEADER() macro. ++ */ ++ ++ , s_chunk_data ++ , s_chunk_data_almost_done ++ , s_chunk_data_done ++ ++ , s_body_identity ++ , s_body_identity_eof ++ ++ , s_message_done ++ }; ++ ++ ++#define PARSING_HEADER(state) (state <= s_headers_done) ++ ++ ++enum header_states ++ { h_general = 0 ++ , h_C ++ , h_CO ++ , h_CON ++ ++ , h_matching_connection ++ , h_matching_proxy_connection ++ , h_matching_content_length ++ , h_matching_transfer_encoding ++ , h_matching_upgrade ++ ++ , h_connection ++ , h_content_length ++ , h_transfer_encoding ++ , h_upgrade ++ ++ , h_matching_transfer_encoding_chunked ++ , h_matching_connection_token_start ++ , h_matching_connection_keep_alive ++ , h_matching_connection_close ++ , h_matching_connection_upgrade ++ , h_matching_connection_token ++ ++ , h_transfer_encoding_chunked ++ , h_connection_keep_alive ++ , h_connection_close ++ , h_connection_upgrade ++ }; ++ ++enum http_host_state ++ { ++ s_http_host_dead = 1 ++ , s_http_userinfo_start ++ , s_http_userinfo ++ , s_http_host_start ++ , s_http_host_v6_start ++ , s_http_host ++ , s_http_host_v6 ++ , s_http_host_v6_end ++ , s_http_host_v6_zone_start ++ , s_http_host_v6_zone ++ , s_http_host_port_start ++ , s_http_host_port ++}; ++ ++/* Macros for character classes; depends on strict-mode */ ++#define CR '\r' ++#define LF '\n' ++#define LOWER(c) (unsigned char)(c | 0x20) ++#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') ++#define IS_NUM(c) ((c) >= '0' && (c) <= '9') ++#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) ++#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) ++#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ ++ (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ ++ (c) == ')') ++#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ ++ (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ ++ (c) == '$' || (c) == ',') ++ ++#define STRICT_TOKEN(c) (tokens[(unsigned char)c]) ++ ++#if HTTP_PARSER_STRICT ++#define TOKEN(c) (tokens[(unsigned char)c]) ++#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) ++#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') ++#else ++#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) ++#define IS_URL_CHAR(c) \ ++ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) ++#define IS_HOST_CHAR(c) \ ++ (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') ++#endif ++ ++/** ++ * Verify that a char is a valid visible (printable) US-ASCII ++ * character or %x80-FF ++ **/ ++#define IS_HEADER_CHAR(ch) \ ++ (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) ++ ++#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) ++ ++ ++#if HTTP_PARSER_STRICT ++# define STRICT_CHECK(cond) \ ++do { \ ++ if (cond) { \ ++ SET_ERRNO(HPE_STRICT); \ ++ goto error; \ ++ } \ ++} while (0) ++# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) ++#else ++# define STRICT_CHECK(cond) ++# define NEW_MESSAGE() start_state ++#endif ++ ++ ++/* Map errno values to strings for human-readable output */ ++#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, ++static struct { ++ const char *name; ++ const char *description; ++} http_strerror_tab[] = { ++ HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) ++}; ++#undef HTTP_STRERROR_GEN ++ ++int http_message_needs_eof(const http_parser *parser); ++ ++/* Our URL parser. ++ * ++ * This is designed to be shared by http_parser_execute() for URL validation, ++ * hence it has a state transition + byte-for-byte interface. In addition, it ++ * is meant to be embedded in http_parser_parse_url(), which does the dirty ++ * work of turning state transitions URL components for its API. ++ * ++ * This function should only be invoked with non-space characters. It is ++ * assumed that the caller cares about (and can detect) the transition between ++ * URL and non-URL states by looking for these. ++ */ ++static enum state ++parse_url_char(enum state s, const char ch) ++{ ++ if (ch == ' ' || ch == '\r' || ch == '\n') { ++ return s_dead; ++ } ++ ++#if HTTP_PARSER_STRICT ++ if (ch == '\t' || ch == '\f') { ++ return s_dead; ++ } ++#endif ++ ++ switch (s) { ++ case s_req_spaces_before_url: ++ /* Proxied requests are followed by scheme of an absolute URI (alpha). ++ * All methods except CONNECT are followed by '/' or '*'. ++ */ ++ ++ if (ch == '/' || ch == '*') { ++ return s_req_path; ++ } ++ ++ if (IS_ALPHA(ch)) { ++ return s_req_schema; ++ } ++ ++ break; ++ ++ case s_req_schema: ++ if (IS_ALPHA(ch)) { ++ return s; ++ } ++ ++ if (ch == ':') { ++ return s_req_schema_slash; ++ } ++ ++ break; ++ ++ case s_req_schema_slash: ++ if (ch == '/') { ++ return s_req_schema_slash_slash; ++ } ++ ++ break; ++ ++ case s_req_schema_slash_slash: ++ if (ch == '/') { ++ return s_req_server_start; ++ } ++ ++ break; ++ ++ case s_req_server_with_at: ++ if (ch == '@') { ++ return s_dead; ++ } ++ ++ /* FALLTHROUGH */ ++ case s_req_server_start: ++ case s_req_server: ++ if (ch == '/') { ++ return s_req_path; ++ } ++ ++ if (ch == '?') { ++ return s_req_query_string_start; ++ } ++ ++ if (ch == '@') { ++ return s_req_server_with_at; ++ } ++ ++ if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { ++ return s_req_server; ++ } ++ ++ break; ++ ++ case s_req_path: ++ if (IS_URL_CHAR(ch)) { ++ return s; ++ } ++ ++ switch (ch) { ++ case '?': ++ return s_req_query_string_start; ++ ++ case '#': ++ return s_req_fragment_start; ++ } ++ ++ break; ++ ++ case s_req_query_string_start: ++ case s_req_query_string: ++ if (IS_URL_CHAR(ch)) { ++ return s_req_query_string; ++ } ++ ++ switch (ch) { ++ case '?': ++ /* allow extra '?' in query string */ ++ return s_req_query_string; ++ ++ case '#': ++ return s_req_fragment_start; ++ } ++ ++ break; ++ ++ case s_req_fragment_start: ++ if (IS_URL_CHAR(ch)) { ++ return s_req_fragment; ++ } ++ ++ switch (ch) { ++ case '?': ++ return s_req_fragment; ++ ++ case '#': ++ return s; ++ } ++ ++ break; ++ ++ case s_req_fragment: ++ if (IS_URL_CHAR(ch)) { ++ return s; ++ } ++ ++ switch (ch) { ++ case '?': ++ case '#': ++ return s; ++ } ++ ++ break; ++ ++ default: ++ break; ++ } ++ ++ /* We should never fall out of the switch above unless there's an error */ ++ return s_dead; ++} ++ ++size_t http_parser_execute (http_parser *parser, ++ const http_parser_settings *settings, ++ const char *data, ++ size_t len) ++{ ++ char c, ch; ++ int8_t unhex_val; ++ const char *p = data; ++ const char *header_field_mark = 0; ++ const char *header_value_mark = 0; ++ const char *url_mark = 0; ++ const char *body_mark = 0; ++ const char *status_mark = 0; ++ enum state p_state = (enum state) parser->state; ++ const unsigned int lenient = parser->lenient_http_headers; ++ ++ /* We're in an error state. Don't bother doing anything. */ ++ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { ++ return 0; ++ } ++ ++ if (len == 0) { ++ switch (CURRENT_STATE()) { ++ case s_body_identity_eof: ++ /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if ++ * we got paused. ++ */ ++ CALLBACK_NOTIFY_NOADVANCE(message_complete); ++ return 0; ++ ++ case s_dead: ++ case s_start_req_or_res: ++ case s_start_res: ++ case s_start_req: ++ return 0; ++ ++ default: ++ SET_ERRNO(HPE_INVALID_EOF_STATE); ++ return 1; ++ } ++ } ++ ++ ++ if (CURRENT_STATE() == s_header_field) ++ header_field_mark = data; ++ if (CURRENT_STATE() == s_header_value) ++ header_value_mark = data; ++ switch (CURRENT_STATE()) { ++ case s_req_path: ++ case s_req_schema: ++ case s_req_schema_slash: ++ case s_req_schema_slash_slash: ++ case s_req_server_start: ++ case s_req_server: ++ case s_req_server_with_at: ++ case s_req_query_string_start: ++ case s_req_query_string: ++ case s_req_fragment_start: ++ case s_req_fragment: ++ url_mark = data; ++ break; ++ case s_res_status: ++ status_mark = data; ++ break; ++ default: ++ break; ++ } ++ ++ for (p=data; p != data + len; p++) { ++ ch = *p; ++ ++ if (PARSING_HEADER(CURRENT_STATE())) ++ COUNT_HEADER_SIZE(1); ++ ++reexecute: ++ switch (CURRENT_STATE()) { ++ ++ case s_dead: ++ /* this state is used after a 'Connection: close' message ++ * the parser will error out if it reads another message ++ */ ++ if (LIKELY(ch == CR || ch == LF)) ++ break; ++ ++ SET_ERRNO(HPE_CLOSED_CONNECTION); ++ goto error; ++ ++ case s_start_req_or_res: ++ { ++ if (ch == CR || ch == LF) ++ break; ++ parser->flags = 0; ++ parser->content_length = ULLONG_MAX; ++ ++ if (ch == 'H') { ++ UPDATE_STATE(s_res_or_resp_H); ++ ++ CALLBACK_NOTIFY(message_begin); ++ } else { ++ parser->type = HTTP_REQUEST; ++ UPDATE_STATE(s_start_req); ++ REEXECUTE(); ++ } ++ ++ break; ++ } ++ ++ case s_res_or_resp_H: ++ if (ch == 'T') { ++ parser->type = HTTP_RESPONSE; ++ UPDATE_STATE(s_res_HT); ++ } else { ++ if (UNLIKELY(ch != 'E')) { ++ SET_ERRNO(HPE_INVALID_CONSTANT); ++ goto error; ++ } ++ ++ parser->type = HTTP_REQUEST; ++ parser->method = HTTP_HEAD; ++ parser->index = 2; ++ UPDATE_STATE(s_req_method); ++ } ++ break; ++ ++ case s_start_res: ++ { ++ parser->flags = 0; ++ parser->content_length = ULLONG_MAX; ++ ++ switch (ch) { ++ case 'H': ++ UPDATE_STATE(s_res_H); ++ break; ++ ++ case CR: ++ case LF: ++ break; ++ ++ default: ++ SET_ERRNO(HPE_INVALID_CONSTANT); ++ goto error; ++ } ++ ++ CALLBACK_NOTIFY(message_begin); ++ break; ++ } ++ ++ case s_res_H: ++ STRICT_CHECK(ch != 'T'); ++ UPDATE_STATE(s_res_HT); ++ break; ++ ++ case s_res_HT: ++ STRICT_CHECK(ch != 'T'); ++ UPDATE_STATE(s_res_HTT); ++ break; ++ ++ case s_res_HTT: ++ STRICT_CHECK(ch != 'P'); ++ UPDATE_STATE(s_res_HTTP); ++ break; ++ ++ case s_res_HTTP: ++ STRICT_CHECK(ch != '/'); ++ UPDATE_STATE(s_res_first_http_major); ++ break; ++ ++ case s_res_first_http_major: ++ if (UNLIKELY(ch < '0' || ch > '9')) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_major = ch - '0'; ++ UPDATE_STATE(s_res_http_major); ++ break; ++ ++ /* major HTTP version or dot */ ++ case s_res_http_major: ++ { ++ if (ch == '.') { ++ UPDATE_STATE(s_res_first_http_minor); ++ break; ++ } ++ ++ if (!IS_NUM(ch)) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_major *= 10; ++ parser->http_major += ch - '0'; ++ ++ if (UNLIKELY(parser->http_major > 999)) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ break; ++ } ++ ++ /* first digit of minor HTTP version */ ++ case s_res_first_http_minor: ++ if (UNLIKELY(!IS_NUM(ch))) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_minor = ch - '0'; ++ UPDATE_STATE(s_res_http_minor); ++ break; ++ ++ /* minor HTTP version or end of request line */ ++ case s_res_http_minor: ++ { ++ if (ch == ' ') { ++ UPDATE_STATE(s_res_first_status_code); ++ break; ++ } ++ ++ if (UNLIKELY(!IS_NUM(ch))) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_minor *= 10; ++ parser->http_minor += ch - '0'; ++ ++ if (UNLIKELY(parser->http_minor > 999)) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ break; ++ } ++ ++ case s_res_first_status_code: ++ { ++ if (!IS_NUM(ch)) { ++ if (ch == ' ') { ++ break; ++ } ++ ++ SET_ERRNO(HPE_INVALID_STATUS); ++ goto error; ++ } ++ parser->status_code = ch - '0'; ++ UPDATE_STATE(s_res_status_code); ++ break; ++ } ++ ++ case s_res_status_code: ++ { ++ if (!IS_NUM(ch)) { ++ switch (ch) { ++ case ' ': ++ UPDATE_STATE(s_res_status_start); ++ break; ++ case CR: ++ UPDATE_STATE(s_res_line_almost_done); ++ break; ++ case LF: ++ UPDATE_STATE(s_header_field_start); ++ break; ++ default: ++ SET_ERRNO(HPE_INVALID_STATUS); ++ goto error; ++ } ++ break; ++ } ++ ++ parser->status_code *= 10; ++ parser->status_code += ch - '0'; ++ ++ if (UNLIKELY(parser->status_code > 999)) { ++ SET_ERRNO(HPE_INVALID_STATUS); ++ goto error; ++ } ++ ++ break; ++ } ++ ++ case s_res_status_start: ++ { ++ if (ch == CR) { ++ UPDATE_STATE(s_res_line_almost_done); ++ break; ++ } ++ ++ if (ch == LF) { ++ UPDATE_STATE(s_header_field_start); ++ break; ++ } ++ ++ MARK(status); ++ UPDATE_STATE(s_res_status); ++ parser->index = 0; ++ break; ++ } ++ ++ case s_res_status: ++ if (ch == CR) { ++ UPDATE_STATE(s_res_line_almost_done); ++ CALLBACK_DATA(status); ++ break; ++ } ++ ++ if (ch == LF) { ++ UPDATE_STATE(s_header_field_start); ++ CALLBACK_DATA(status); ++ break; ++ } ++ ++ break; ++ ++ case s_res_line_almost_done: ++ STRICT_CHECK(ch != LF); ++ UPDATE_STATE(s_header_field_start); ++ break; ++ ++ case s_start_req: ++ { ++ if (ch == CR || ch == LF) ++ break; ++ parser->flags = 0; ++ parser->content_length = ULLONG_MAX; ++ ++ if (UNLIKELY(!IS_ALPHA(ch))) { ++ SET_ERRNO(HPE_INVALID_METHOD); ++ goto error; ++ } ++ ++ parser->method = (enum http_method) 0; ++ parser->index = 1; ++ switch (ch) { ++ case 'A': parser->method = HTTP_ACL; break; ++ case 'B': parser->method = HTTP_BIND; break; ++ case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; ++ case 'D': parser->method = HTTP_DELETE; break; ++ case 'G': parser->method = HTTP_GET; break; ++ case 'H': parser->method = HTTP_HEAD; break; ++ case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; ++ case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; ++ case 'N': parser->method = HTTP_NOTIFY; break; ++ case 'O': parser->method = HTTP_OPTIONS; break; ++ case 'P': parser->method = HTTP_POST; ++ /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ ++ break; ++ case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; ++ case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break; ++ case 'T': parser->method = HTTP_TRACE; break; ++ case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; ++ default: ++ SET_ERRNO(HPE_INVALID_METHOD); ++ goto error; ++ } ++ UPDATE_STATE(s_req_method); ++ ++ CALLBACK_NOTIFY(message_begin); ++ ++ break; ++ } ++ ++ case s_req_method: ++ { ++ const char *matcher; ++ if (UNLIKELY(ch == '\0')) { ++ SET_ERRNO(HPE_INVALID_METHOD); ++ goto error; ++ } ++ ++ matcher = method_strings[parser->method]; ++ if (ch == ' ' && matcher[parser->index] == '\0') { ++ UPDATE_STATE(s_req_spaces_before_url); ++ } else if (ch == matcher[parser->index]) { ++ ; /* nada */ ++ } else if (IS_ALPHA(ch)) { ++ ++ switch (parser->method << 16 | parser->index << 8 | ch) { ++#define XX(meth, pos, ch, new_meth) \ ++ case (HTTP_##meth << 16 | pos << 8 | ch): \ ++ parser->method = HTTP_##new_meth; break; ++ ++ XX(POST, 1, 'U', PUT) ++ XX(POST, 1, 'A', PATCH) ++ XX(CONNECT, 1, 'H', CHECKOUT) ++ XX(CONNECT, 2, 'P', COPY) ++ XX(MKCOL, 1, 'O', MOVE) ++ XX(MKCOL, 1, 'E', MERGE) ++ XX(MKCOL, 2, 'A', MKACTIVITY) ++ XX(MKCOL, 3, 'A', MKCALENDAR) ++ XX(SUBSCRIBE, 1, 'E', SEARCH) ++ XX(REPORT, 2, 'B', REBIND) ++ XX(POST, 1, 'R', PROPFIND) ++ XX(PROPFIND, 4, 'P', PROPPATCH) ++ XX(PUT, 2, 'R', PURGE) ++ XX(LOCK, 1, 'I', LINK) ++ XX(UNLOCK, 2, 'S', UNSUBSCRIBE) ++ XX(UNLOCK, 2, 'B', UNBIND) ++ XX(UNLOCK, 3, 'I', UNLINK) ++#undef XX ++ ++ default: ++ SET_ERRNO(HPE_INVALID_METHOD); ++ goto error; ++ } ++ } else if (ch == '-' && ++ parser->index == 1 && ++ parser->method == HTTP_MKCOL) { ++ parser->method = HTTP_MSEARCH; ++ } else { ++ SET_ERRNO(HPE_INVALID_METHOD); ++ goto error; ++ } ++ ++ ++parser->index; ++ break; ++ } ++ ++ case s_req_spaces_before_url: ++ { ++ if (ch == ' ') break; ++ ++ MARK(url); ++ if (parser->method == HTTP_CONNECT) { ++ UPDATE_STATE(s_req_server_start); ++ } ++ ++ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); ++ if (UNLIKELY(CURRENT_STATE() == s_dead)) { ++ SET_ERRNO(HPE_INVALID_URL); ++ goto error; ++ } ++ ++ break; ++ } ++ ++ case s_req_schema: ++ case s_req_schema_slash: ++ case s_req_schema_slash_slash: ++ case s_req_server_start: ++ { ++ switch (ch) { ++ /* No whitespace allowed here */ ++ case ' ': ++ case CR: ++ case LF: ++ SET_ERRNO(HPE_INVALID_URL); ++ goto error; ++ default: ++ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); ++ if (UNLIKELY(CURRENT_STATE() == s_dead)) { ++ SET_ERRNO(HPE_INVALID_URL); ++ goto error; ++ } ++ } ++ ++ break; ++ } ++ ++ case s_req_server: ++ case s_req_server_with_at: ++ case s_req_path: ++ case s_req_query_string_start: ++ case s_req_query_string: ++ case s_req_fragment_start: ++ case s_req_fragment: ++ { ++ switch (ch) { ++ case ' ': ++ UPDATE_STATE(s_req_http_start); ++ CALLBACK_DATA(url); ++ break; ++ case CR: ++ case LF: ++ parser->http_major = 0; ++ parser->http_minor = 9; ++ UPDATE_STATE((ch == CR) ? ++ s_req_line_almost_done : ++ s_header_field_start); ++ CALLBACK_DATA(url); ++ break; ++ default: ++ UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); ++ if (UNLIKELY(CURRENT_STATE() == s_dead)) { ++ SET_ERRNO(HPE_INVALID_URL); ++ goto error; ++ } ++ } ++ break; ++ } ++ ++ case s_req_http_start: ++ switch (ch) { ++ case 'H': ++ UPDATE_STATE(s_req_http_H); ++ break; ++ case ' ': ++ break; ++ default: ++ SET_ERRNO(HPE_INVALID_CONSTANT); ++ goto error; ++ } ++ break; ++ ++ case s_req_http_H: ++ STRICT_CHECK(ch != 'T'); ++ UPDATE_STATE(s_req_http_HT); ++ break; ++ ++ case s_req_http_HT: ++ STRICT_CHECK(ch != 'T'); ++ UPDATE_STATE(s_req_http_HTT); ++ break; ++ ++ case s_req_http_HTT: ++ STRICT_CHECK(ch != 'P'); ++ UPDATE_STATE(s_req_http_HTTP); ++ break; ++ ++ case s_req_http_HTTP: ++ STRICT_CHECK(ch != '/'); ++ UPDATE_STATE(s_req_first_http_major); ++ break; ++ ++ /* first digit of major HTTP version */ ++ case s_req_first_http_major: ++ if (UNLIKELY(ch < '1' || ch > '9')) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_major = ch - '0'; ++ UPDATE_STATE(s_req_http_major); ++ break; ++ ++ /* major HTTP version or dot */ ++ case s_req_http_major: ++ { ++ if (ch == '.') { ++ UPDATE_STATE(s_req_first_http_minor); ++ break; ++ } ++ ++ if (UNLIKELY(!IS_NUM(ch))) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_major *= 10; ++ parser->http_major += ch - '0'; ++ ++ if (UNLIKELY(parser->http_major > 999)) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ break; ++ } ++ ++ /* first digit of minor HTTP version */ ++ case s_req_first_http_minor: ++ if (UNLIKELY(!IS_NUM(ch))) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_minor = ch - '0'; ++ UPDATE_STATE(s_req_http_minor); ++ break; ++ ++ /* minor HTTP version or end of request line */ ++ case s_req_http_minor: ++ { ++ if (ch == CR) { ++ UPDATE_STATE(s_req_line_almost_done); ++ break; ++ } ++ ++ if (ch == LF) { ++ UPDATE_STATE(s_header_field_start); ++ break; ++ } ++ ++ /* XXX allow spaces after digit? */ ++ ++ if (UNLIKELY(!IS_NUM(ch))) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ parser->http_minor *= 10; ++ parser->http_minor += ch - '0'; ++ ++ if (UNLIKELY(parser->http_minor > 999)) { ++ SET_ERRNO(HPE_INVALID_VERSION); ++ goto error; ++ } ++ ++ break; ++ } ++ ++ /* end of request line */ ++ case s_req_line_almost_done: ++ { ++ if (UNLIKELY(ch != LF)) { ++ SET_ERRNO(HPE_LF_EXPECTED); ++ goto error; ++ } ++ ++ UPDATE_STATE(s_header_field_start); ++ break; ++ } ++ ++ case s_header_field_start: ++ { ++ if (ch == CR) { ++ UPDATE_STATE(s_headers_almost_done); ++ break; ++ } ++ ++ if (ch == LF) { ++ /* they might be just sending \n instead of \r\n so this would be ++ * the second \n to denote the end of headers*/ ++ UPDATE_STATE(s_headers_almost_done); ++ REEXECUTE(); ++ } ++ ++ c = TOKEN(ch); ++ ++ if (UNLIKELY(!c)) { ++ SET_ERRNO(HPE_INVALID_HEADER_TOKEN); ++ goto error; ++ } ++ ++ MARK(header_field); ++ ++ parser->index = 0; ++ UPDATE_STATE(s_header_field); ++ ++ switch (c) { ++ case 'c': ++ parser->header_state = h_C; ++ break; ++ ++ case 'p': ++ parser->header_state = h_matching_proxy_connection; ++ break; ++ ++ case 't': ++ parser->header_state = h_matching_transfer_encoding; ++ break; ++ ++ case 'u': ++ parser->header_state = h_matching_upgrade; ++ break; ++ ++ default: ++ parser->header_state = h_general; ++ break; ++ } ++ break; ++ } ++ ++ case s_header_field: ++ { ++ const char* start = p; ++ for (; p != data + len; p++) { ++ ch = *p; ++ c = TOKEN(ch); ++ ++ if (!c) ++ break; ++ ++ switch (parser->header_state) { ++ case h_general: ++ break; ++ ++ case h_C: ++ parser->index++; ++ parser->header_state = (c == 'o' ? h_CO : h_general); ++ break; ++ ++ case h_CO: ++ parser->index++; ++ parser->header_state = (c == 'n' ? h_CON : h_general); ++ break; ++ ++ case h_CON: ++ parser->index++; ++ switch (c) { ++ case 'n': ++ parser->header_state = h_matching_connection; ++ break; ++ case 't': ++ parser->header_state = h_matching_content_length; ++ break; ++ default: ++ parser->header_state = h_general; ++ break; ++ } ++ break; ++ ++ /* connection */ ++ ++ case h_matching_connection: ++ parser->index++; ++ if (parser->index > sizeof(CONNECTION)-1 ++ || c != CONNECTION[parser->index]) { ++ parser->header_state = h_general; ++ } else if (parser->index == sizeof(CONNECTION)-2) { ++ parser->header_state = h_connection; ++ } ++ break; ++ ++ /* proxy-connection */ ++ ++ case h_matching_proxy_connection: ++ parser->index++; ++ if (parser->index > sizeof(PROXY_CONNECTION)-1 ++ || c != PROXY_CONNECTION[parser->index]) { ++ parser->header_state = h_general; ++ } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { ++ parser->header_state = h_connection; ++ } ++ break; ++ ++ /* content-length */ ++ ++ case h_matching_content_length: ++ parser->index++; ++ if (parser->index > sizeof(CONTENT_LENGTH)-1 ++ || c != CONTENT_LENGTH[parser->index]) { ++ parser->header_state = h_general; ++ } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { ++ if (parser->flags & F_CONTENTLENGTH) { ++ SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); ++ goto error; ++ } ++ parser->header_state = h_content_length; ++ parser->flags |= F_CONTENTLENGTH; ++ } ++ break; ++ ++ /* transfer-encoding */ ++ ++ case h_matching_transfer_encoding: ++ parser->index++; ++ if (parser->index > sizeof(TRANSFER_ENCODING)-1 ++ || c != TRANSFER_ENCODING[parser->index]) { ++ parser->header_state = h_general; ++ } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { ++ parser->header_state = h_transfer_encoding; ++ } ++ break; ++ ++ /* upgrade */ ++ ++ case h_matching_upgrade: ++ parser->index++; ++ if (parser->index > sizeof(UPGRADE)-1 ++ || c != UPGRADE[parser->index]) { ++ parser->header_state = h_general; ++ } else if (parser->index == sizeof(UPGRADE)-2) { ++ parser->header_state = h_upgrade; ++ } ++ break; ++ ++ case h_connection: ++ case h_content_length: ++ case h_transfer_encoding: ++ case h_upgrade: ++ if (ch != ' ') parser->header_state = h_general; ++ break; ++ ++ default: ++ assert(0 && "Unknown header_state"); ++ break; ++ } ++ } ++ ++ COUNT_HEADER_SIZE(p - start); ++ ++ if (p == data + len) { ++ --p; ++ break; ++ } ++ ++ if (ch == ':') { ++ UPDATE_STATE(s_header_value_discard_ws); ++ CALLBACK_DATA(header_field); ++ break; ++ } ++ ++ SET_ERRNO(HPE_INVALID_HEADER_TOKEN); ++ goto error; ++ } ++ ++ case s_header_value_discard_ws: ++ if (ch == ' ' || ch == '\t') break; ++ ++ if (ch == CR) { ++ UPDATE_STATE(s_header_value_discard_ws_almost_done); ++ break; ++ } ++ ++ if (ch == LF) { ++ UPDATE_STATE(s_header_value_discard_lws); ++ break; ++ } ++ ++ /* FALLTHROUGH */ ++ ++ case s_header_value_start: ++ { ++ MARK(header_value); ++ ++ UPDATE_STATE(s_header_value); ++ parser->index = 0; ++ ++ c = LOWER(ch); ++ ++ switch (parser->header_state) { ++ case h_upgrade: ++ parser->flags |= F_UPGRADE; ++ parser->header_state = h_general; ++ break; ++ ++ case h_transfer_encoding: ++ /* looking for 'Transfer-Encoding: chunked' */ ++ if ('c' == c) { ++ parser->header_state = h_matching_transfer_encoding_chunked; ++ } else { ++ parser->header_state = h_general; ++ } ++ break; ++ ++ case h_content_length: ++ if (UNLIKELY(!IS_NUM(ch))) { ++ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); ++ goto error; ++ } ++ ++ parser->content_length = ch - '0'; ++ break; ++ ++ case h_connection: ++ /* looking for 'Connection: keep-alive' */ ++ if (c == 'k') { ++ parser->header_state = h_matching_connection_keep_alive; ++ /* looking for 'Connection: close' */ ++ } else if (c == 'c') { ++ parser->header_state = h_matching_connection_close; ++ } else if (c == 'u') { ++ parser->header_state = h_matching_connection_upgrade; ++ } else { ++ parser->header_state = h_matching_connection_token; ++ } ++ break; ++ ++ /* Multi-value `Connection` header */ ++ case h_matching_connection_token_start: ++ break; ++ ++ default: ++ parser->header_state = h_general; ++ break; ++ } ++ break; ++ } ++ ++ case s_header_value: ++ { ++ const char* start = p; ++ enum header_states h_state = (enum header_states) parser->header_state; ++ for (; p != data + len; p++) { ++ ch = *p; ++ if (ch == CR) { ++ UPDATE_STATE(s_header_almost_done); ++ parser->header_state = h_state; ++ CALLBACK_DATA(header_value); ++ break; ++ } ++ ++ if (ch == LF) { ++ UPDATE_STATE(s_header_almost_done); ++ COUNT_HEADER_SIZE(p - start); ++ parser->header_state = h_state; ++ CALLBACK_DATA_NOADVANCE(header_value); ++ REEXECUTE(); ++ } ++ ++ if (!lenient && !IS_HEADER_CHAR(ch)) { ++ SET_ERRNO(HPE_INVALID_HEADER_TOKEN); ++ goto error; ++ } ++ ++ c = LOWER(ch); ++ ++ switch (h_state) { ++ case h_general: ++ { ++ const char* p_cr; ++ const char* p_lf; ++ size_t limit = data + len - p; ++ ++ limit = MIN(limit, HTTP_MAX_HEADER_SIZE); ++ ++ p_cr = (const char*) memchr(p, CR, limit); ++ p_lf = (const char*) memchr(p, LF, limit); ++ if (p_cr != NULL) { ++ if (p_lf != NULL && p_cr >= p_lf) ++ p = p_lf; ++ else ++ p = p_cr; ++ } else if (UNLIKELY(p_lf != NULL)) { ++ p = p_lf; ++ } else { ++ p = data + len; ++ } ++ --p; ++ ++ break; ++ } ++ ++ case h_connection: ++ case h_transfer_encoding: ++ assert(0 && "Shouldn't get here."); ++ break; ++ ++ case h_content_length: ++ { ++ uint64_t t; ++ ++ if (ch == ' ') break; ++ ++ if (UNLIKELY(!IS_NUM(ch))) { ++ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); ++ parser->header_state = h_state; ++ goto error; ++ } ++ ++ t = parser->content_length; ++ t *= 10; ++ t += ch - '0'; ++ ++ /* Overflow? Test against a conservative limit for simplicity. */ ++ if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { ++ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); ++ parser->header_state = h_state; ++ goto error; ++ } ++ ++ parser->content_length = t; ++ break; ++ } ++ ++ /* Transfer-Encoding: chunked */ ++ case h_matching_transfer_encoding_chunked: ++ parser->index++; ++ if (parser->index > sizeof(CHUNKED)-1 ++ || c != CHUNKED[parser->index]) { ++ h_state = h_general; ++ } else if (parser->index == sizeof(CHUNKED)-2) { ++ h_state = h_transfer_encoding_chunked; ++ } ++ break; ++ ++ case h_matching_connection_token_start: ++ /* looking for 'Connection: keep-alive' */ ++ if (c == 'k') { ++ h_state = h_matching_connection_keep_alive; ++ /* looking for 'Connection: close' */ ++ } else if (c == 'c') { ++ h_state = h_matching_connection_close; ++ } else if (c == 'u') { ++ h_state = h_matching_connection_upgrade; ++ } else if (STRICT_TOKEN(c)) { ++ h_state = h_matching_connection_token; ++ } else if (c == ' ' || c == '\t') { ++ /* Skip lws */ ++ } else { ++ h_state = h_general; ++ } ++ break; ++ ++ /* looking for 'Connection: keep-alive' */ ++ case h_matching_connection_keep_alive: ++ parser->index++; ++ if (parser->index > sizeof(KEEP_ALIVE)-1 ++ || c != KEEP_ALIVE[parser->index]) { ++ h_state = h_matching_connection_token; ++ } else if (parser->index == sizeof(KEEP_ALIVE)-2) { ++ h_state = h_connection_keep_alive; ++ } ++ break; ++ ++ /* looking for 'Connection: close' */ ++ case h_matching_connection_close: ++ parser->index++; ++ if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { ++ h_state = h_matching_connection_token; ++ } else if (parser->index == sizeof(CLOSE)-2) { ++ h_state = h_connection_close; ++ } ++ break; ++ ++ /* looking for 'Connection: upgrade' */ ++ case h_matching_connection_upgrade: ++ parser->index++; ++ if (parser->index > sizeof(UPGRADE) - 1 || ++ c != UPGRADE[parser->index]) { ++ h_state = h_matching_connection_token; ++ } else if (parser->index == sizeof(UPGRADE)-2) { ++ h_state = h_connection_upgrade; ++ } ++ break; ++ ++ case h_matching_connection_token: ++ if (ch == ',') { ++ h_state = h_matching_connection_token_start; ++ parser->index = 0; ++ } ++ break; ++ ++ case h_transfer_encoding_chunked: ++ if (ch != ' ') h_state = h_general; ++ break; ++ ++ case h_connection_keep_alive: ++ case h_connection_close: ++ case h_connection_upgrade: ++ if (ch == ',') { ++ if (h_state == h_connection_keep_alive) { ++ parser->flags |= F_CONNECTION_KEEP_ALIVE; ++ } else if (h_state == h_connection_close) { ++ parser->flags |= F_CONNECTION_CLOSE; ++ } else if (h_state == h_connection_upgrade) { ++ parser->flags |= F_CONNECTION_UPGRADE; ++ } ++ h_state = h_matching_connection_token_start; ++ parser->index = 0; ++ } else if (ch != ' ') { ++ h_state = h_matching_connection_token; ++ } ++ break; ++ ++ default: ++ UPDATE_STATE(s_header_value); ++ h_state = h_general; ++ break; ++ } ++ } ++ parser->header_state = h_state; ++ ++ COUNT_HEADER_SIZE(p - start); ++ ++ if (p == data + len) ++ --p; ++ break; ++ } ++ ++ case s_header_almost_done: ++ { ++ if (UNLIKELY(ch != LF)) { ++ SET_ERRNO(HPE_LF_EXPECTED); ++ goto error; ++ } ++ ++ UPDATE_STATE(s_header_value_lws); ++ break; ++ } ++ ++ case s_header_value_lws: ++ { ++ if (ch == ' ' || ch == '\t') { ++ UPDATE_STATE(s_header_value_start); ++ REEXECUTE(); ++ } ++ ++ /* finished the header */ ++ switch (parser->header_state) { ++ case h_connection_keep_alive: ++ parser->flags |= F_CONNECTION_KEEP_ALIVE; ++ break; ++ case h_connection_close: ++ parser->flags |= F_CONNECTION_CLOSE; ++ break; ++ case h_transfer_encoding_chunked: ++ parser->flags |= F_CHUNKED; ++ break; ++ case h_connection_upgrade: ++ parser->flags |= F_CONNECTION_UPGRADE; ++ break; ++ default: ++ break; ++ } ++ ++ UPDATE_STATE(s_header_field_start); ++ REEXECUTE(); ++ } ++ ++ case s_header_value_discard_ws_almost_done: ++ { ++ STRICT_CHECK(ch != LF); ++ UPDATE_STATE(s_header_value_discard_lws); ++ break; ++ } ++ ++ case s_header_value_discard_lws: ++ { ++ if (ch == ' ' || ch == '\t') { ++ UPDATE_STATE(s_header_value_discard_ws); ++ break; ++ } else { ++ switch (parser->header_state) { ++ case h_connection_keep_alive: ++ parser->flags |= F_CONNECTION_KEEP_ALIVE; ++ break; ++ case h_connection_close: ++ parser->flags |= F_CONNECTION_CLOSE; ++ break; ++ case h_connection_upgrade: ++ parser->flags |= F_CONNECTION_UPGRADE; ++ break; ++ case h_transfer_encoding_chunked: ++ parser->flags |= F_CHUNKED; ++ break; ++ default: ++ break; ++ } ++ ++ /* header value was empty */ ++ MARK(header_value); ++ UPDATE_STATE(s_header_field_start); ++ CALLBACK_DATA_NOADVANCE(header_value); ++ REEXECUTE(); ++ } ++ } ++ ++ case s_headers_almost_done: ++ { ++ STRICT_CHECK(ch != LF); ++ ++ if (parser->flags & F_TRAILING) { ++ /* End of a chunked request */ ++ UPDATE_STATE(s_message_done); ++ CALLBACK_NOTIFY_NOADVANCE(chunk_complete); ++ REEXECUTE(); ++ } ++ ++ /* Cannot use chunked encoding and a content-length header together ++ per the HTTP specification. */ ++ if ((parser->flags & F_CHUNKED) && ++ (parser->flags & F_CONTENTLENGTH)) { ++ SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); ++ goto error; ++ } ++ ++ UPDATE_STATE(s_headers_done); ++ ++ /* Set this here so that on_headers_complete() callbacks can see it */ ++ parser->upgrade = ++ ((parser->flags & (F_UPGRADE | F_CONNECTION_UPGRADE)) == ++ (F_UPGRADE | F_CONNECTION_UPGRADE) || ++ parser->method == HTTP_CONNECT); ++ ++ /* Here we call the headers_complete callback. This is somewhat ++ * different than other callbacks because if the user returns 1, we ++ * will interpret that as saying that this message has no body. This ++ * is needed for the annoying case of recieving a response to a HEAD ++ * request. ++ * ++ * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so ++ * we have to simulate it by handling a change in errno below. ++ */ ++ if (settings->on_headers_complete) { ++ switch (settings->on_headers_complete(parser)) { ++ case 0: ++ break; ++ ++ case 2: ++ parser->upgrade = 1; ++ ++ case 1: ++ parser->flags |= F_SKIPBODY; ++ break; ++ ++ default: ++ SET_ERRNO(HPE_CB_headers_complete); ++ RETURN(p - data); /* Error */ ++ } ++ } ++ ++ if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { ++ RETURN(p - data); ++ } ++ ++ REEXECUTE(); ++ } ++ ++ case s_headers_done: ++ { ++ int hasBody; ++ STRICT_CHECK(ch != LF); ++ ++ parser->nread = 0; ++ ++ hasBody = parser->flags & F_CHUNKED || ++ (parser->content_length > 0 && parser->content_length != ULLONG_MAX); ++ if (parser->upgrade && (parser->method == HTTP_CONNECT || ++ (parser->flags & F_SKIPBODY) || !hasBody)) { ++ /* Exit, the rest of the message is in a different protocol. */ ++ UPDATE_STATE(NEW_MESSAGE()); ++ CALLBACK_NOTIFY(message_complete); ++ RETURN((p - data) + 1); ++ } ++ ++ if (parser->flags & F_SKIPBODY) { ++ UPDATE_STATE(NEW_MESSAGE()); ++ CALLBACK_NOTIFY(message_complete); ++ } else if (parser->flags & F_CHUNKED) { ++ /* chunked encoding - ignore Content-Length header */ ++ UPDATE_STATE(s_chunk_size_start); ++ } else { ++ if (parser->content_length == 0) { ++ /* Content-Length header given but zero: Content-Length: 0\r\n */ ++ UPDATE_STATE(NEW_MESSAGE()); ++ CALLBACK_NOTIFY(message_complete); ++ } else if (parser->content_length != ULLONG_MAX) { ++ /* Content-Length header given and non-zero */ ++ UPDATE_STATE(s_body_identity); ++ } else { ++ if (!http_message_needs_eof(parser)) { ++ /* Assume content-length 0 - read the next */ ++ UPDATE_STATE(NEW_MESSAGE()); ++ CALLBACK_NOTIFY(message_complete); ++ } else { ++ /* Read body until EOF */ ++ UPDATE_STATE(s_body_identity_eof); ++ } ++ } ++ } ++ ++ break; ++ } ++ ++ case s_body_identity: ++ { ++ uint64_t to_read = MIN(parser->content_length, ++ (uint64_t) ((data + len) - p)); ++ ++ assert(parser->content_length != 0 ++ && parser->content_length != ULLONG_MAX); ++ ++ /* The difference between advancing content_length and p is because ++ * the latter will automaticaly advance on the next loop iteration. ++ * Further, if content_length ends up at 0, we want to see the last ++ * byte again for our message complete callback. ++ */ ++ MARK(body); ++ parser->content_length -= to_read; ++ p += to_read - 1; ++ ++ if (parser->content_length == 0) { ++ UPDATE_STATE(s_message_done); ++ ++ /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. ++ * ++ * The alternative to doing this is to wait for the next byte to ++ * trigger the data callback, just as in every other case. The ++ * problem with this is that this makes it difficult for the test ++ * harness to distinguish between complete-on-EOF and ++ * complete-on-length. It's not clear that this distinction is ++ * important for applications, but let's keep it for now. ++ */ ++ CALLBACK_DATA_(body, p - body_mark + 1, p - data); ++ REEXECUTE(); ++ } ++ ++ break; ++ } ++ ++ /* read until EOF */ ++ case s_body_identity_eof: ++ MARK(body); ++ p = data + len - 1; ++ ++ break; ++ ++ case s_message_done: ++ UPDATE_STATE(NEW_MESSAGE()); ++ CALLBACK_NOTIFY(message_complete); ++ if (parser->upgrade) { ++ /* Exit, the rest of the message is in a different protocol. */ ++ RETURN((p - data) + 1); ++ } ++ break; ++ ++ case s_chunk_size_start: ++ { ++ assert(parser->nread == 1); ++ assert(parser->flags & F_CHUNKED); ++ ++ unhex_val = unhex[(unsigned char)ch]; ++ if (UNLIKELY(unhex_val == -1)) { ++ SET_ERRNO(HPE_INVALID_CHUNK_SIZE); ++ goto error; ++ } ++ ++ parser->content_length = unhex_val; ++ UPDATE_STATE(s_chunk_size); ++ break; ++ } ++ ++ case s_chunk_size: ++ { ++ uint64_t t; ++ ++ assert(parser->flags & F_CHUNKED); ++ ++ if (ch == CR) { ++ UPDATE_STATE(s_chunk_size_almost_done); ++ break; ++ } ++ ++ unhex_val = unhex[(unsigned char)ch]; ++ ++ if (unhex_val == -1) { ++ if (ch == ';' || ch == ' ') { ++ UPDATE_STATE(s_chunk_parameters); ++ break; ++ } ++ ++ SET_ERRNO(HPE_INVALID_CHUNK_SIZE); ++ goto error; ++ } ++ ++ t = parser->content_length; ++ t *= 16; ++ t += unhex_val; ++ ++ /* Overflow? Test against a conservative limit for simplicity. */ ++ if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { ++ SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); ++ goto error; ++ } ++ ++ parser->content_length = t; ++ break; ++ } ++ ++ case s_chunk_parameters: ++ { ++ assert(parser->flags & F_CHUNKED); ++ /* just ignore this shit. TODO check for overflow */ ++ if (ch == CR) { ++ UPDATE_STATE(s_chunk_size_almost_done); ++ break; ++ } ++ break; ++ } ++ ++ case s_chunk_size_almost_done: ++ { ++ assert(parser->flags & F_CHUNKED); ++ STRICT_CHECK(ch != LF); ++ ++ parser->nread = 0; ++ ++ if (parser->content_length == 0) { ++ parser->flags |= F_TRAILING; ++ UPDATE_STATE(s_header_field_start); ++ } else { ++ UPDATE_STATE(s_chunk_data); ++ } ++ CALLBACK_NOTIFY(chunk_header); ++ break; ++ } ++ ++ case s_chunk_data: ++ { ++ uint64_t to_read = MIN(parser->content_length, ++ (uint64_t) ((data + len) - p)); ++ ++ assert(parser->flags & F_CHUNKED); ++ assert(parser->content_length != 0 ++ && parser->content_length != ULLONG_MAX); ++ ++ /* See the explanation in s_body_identity for why the content ++ * length and data pointers are managed this way. ++ */ ++ MARK(body); ++ parser->content_length -= to_read; ++ p += to_read - 1; ++ ++ if (parser->content_length == 0) { ++ UPDATE_STATE(s_chunk_data_almost_done); ++ } ++ ++ break; ++ } ++ ++ case s_chunk_data_almost_done: ++ assert(parser->flags & F_CHUNKED); ++ assert(parser->content_length == 0); ++ STRICT_CHECK(ch != CR); ++ UPDATE_STATE(s_chunk_data_done); ++ CALLBACK_DATA(body); ++ break; ++ ++ case s_chunk_data_done: ++ assert(parser->flags & F_CHUNKED); ++ STRICT_CHECK(ch != LF); ++ parser->nread = 0; ++ UPDATE_STATE(s_chunk_size_start); ++ CALLBACK_NOTIFY(chunk_complete); ++ break; ++ ++ default: ++ assert(0 && "unhandled state"); ++ SET_ERRNO(HPE_INVALID_INTERNAL_STATE); ++ goto error; ++ } ++ } ++ ++ /* Run callbacks for any marks that we have leftover after we ran our of ++ * bytes. There should be at most one of these set, so it's OK to invoke ++ * them in series (unset marks will not result in callbacks). ++ * ++ * We use the NOADVANCE() variety of callbacks here because 'p' has already ++ * overflowed 'data' and this allows us to correct for the off-by-one that ++ * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' ++ * value that's in-bounds). ++ */ ++ ++ assert(((header_field_mark ? 1 : 0) + ++ (header_value_mark ? 1 : 0) + ++ (url_mark ? 1 : 0) + ++ (body_mark ? 1 : 0) + ++ (status_mark ? 1 : 0)) <= 1); ++ ++ CALLBACK_DATA_NOADVANCE(header_field); ++ CALLBACK_DATA_NOADVANCE(header_value); ++ CALLBACK_DATA_NOADVANCE(url); ++ CALLBACK_DATA_NOADVANCE(body); ++ CALLBACK_DATA_NOADVANCE(status); ++ ++ RETURN(len); ++ ++error: ++ if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { ++ SET_ERRNO(HPE_UNKNOWN); ++ } ++ ++ RETURN(p - data); ++} ++ ++ ++/* Does the parser need to see an EOF to find the end of the message? */ ++int ++http_message_needs_eof (const http_parser *parser) ++{ ++ if (parser->type == HTTP_REQUEST) { ++ return 0; ++ } ++ ++ /* See RFC 2616 section 4.4 */ ++ if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ ++ parser->status_code == 204 || /* No Content */ ++ parser->status_code == 304 || /* Not Modified */ ++ parser->flags & F_SKIPBODY) { /* response to a HEAD request */ ++ return 0; ++ } ++ ++ if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++ ++int ++http_should_keep_alive (const http_parser *parser) ++{ ++ if (parser->http_major > 0 && parser->http_minor > 0) { ++ /* HTTP/1.1 */ ++ if (parser->flags & F_CONNECTION_CLOSE) { ++ return 0; ++ } ++ } else { ++ /* HTTP/1.0 or earlier */ ++ if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { ++ return 0; ++ } ++ } ++ ++ return !http_message_needs_eof(parser); ++} ++ ++ ++const char * ++http_method_str (enum http_method m) ++{ ++ return ELEM_AT(method_strings, m, ""); ++} ++ ++ ++void ++http_parser_init (http_parser *parser, enum http_parser_type t) ++{ ++ void *data = parser->data; /* preserve application data */ ++ memset(parser, 0, sizeof(*parser)); ++ parser->data = data; ++ parser->type = t; ++ parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); ++ parser->http_errno = HPE_OK; ++} ++ ++void ++http_parser_settings_init(http_parser_settings *settings) ++{ ++ memset(settings, 0, sizeof(*settings)); ++} ++ ++const char * ++http_errno_name(enum http_errno err) { ++ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); ++ return http_strerror_tab[err].name; ++} ++ ++const char * ++http_errno_description(enum http_errno err) { ++ assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); ++ return http_strerror_tab[err].description; ++} ++ ++static enum http_host_state ++http_parse_host_char(enum http_host_state s, const char ch) { ++ switch(s) { ++ case s_http_userinfo: ++ case s_http_userinfo_start: ++ if (ch == '@') { ++ return s_http_host_start; ++ } ++ ++ if (IS_USERINFO_CHAR(ch)) { ++ return s_http_userinfo; ++ } ++ break; ++ ++ case s_http_host_start: ++ if (ch == '[') { ++ return s_http_host_v6_start; ++ } ++ ++ if (IS_HOST_CHAR(ch)) { ++ return s_http_host; ++ } ++ ++ break; ++ ++ case s_http_host: ++ if (IS_HOST_CHAR(ch)) { ++ return s_http_host; ++ } ++ ++ /* FALLTHROUGH */ ++ case s_http_host_v6_end: ++ if (ch == ':') { ++ return s_http_host_port_start; ++ } ++ ++ break; ++ ++ case s_http_host_v6: ++ if (ch == ']') { ++ return s_http_host_v6_end; ++ } ++ ++ /* FALLTHROUGH */ ++ case s_http_host_v6_start: ++ if (IS_HEX(ch) || ch == ':' || ch == '.') { ++ return s_http_host_v6; ++ } ++ ++ if (s == s_http_host_v6 && ch == '%') { ++ return s_http_host_v6_zone_start; ++ } ++ break; ++ ++ case s_http_host_v6_zone: ++ if (ch == ']') { ++ return s_http_host_v6_end; ++ } ++ ++ /* FALLTHROUGH */ ++ case s_http_host_v6_zone_start: ++ /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ ++ if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || ++ ch == '~') { ++ return s_http_host_v6_zone; ++ } ++ break; ++ ++ case s_http_host_port: ++ case s_http_host_port_start: ++ if (IS_NUM(ch)) { ++ return s_http_host_port; ++ } ++ ++ break; ++ ++ default: ++ break; ++ } ++ return s_http_host_dead; ++} ++ ++static int ++http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { ++ enum http_host_state s; ++ ++ const char *p; ++ size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; ++ ++ assert(u->field_set & (1 << UF_HOST)); ++ ++ u->field_data[UF_HOST].len = 0; ++ ++ s = found_at ? s_http_userinfo_start : s_http_host_start; ++ ++ for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { ++ enum http_host_state new_s = http_parse_host_char(s, *p); ++ ++ if (new_s == s_http_host_dead) { ++ return 1; ++ } ++ ++ switch(new_s) { ++ case s_http_host: ++ if (s != s_http_host) { ++ u->field_data[UF_HOST].off = p - buf; ++ } ++ u->field_data[UF_HOST].len++; ++ break; ++ ++ case s_http_host_v6: ++ if (s != s_http_host_v6) { ++ u->field_data[UF_HOST].off = p - buf; ++ } ++ u->field_data[UF_HOST].len++; ++ break; ++ ++ case s_http_host_v6_zone_start: ++ case s_http_host_v6_zone: ++ u->field_data[UF_HOST].len++; ++ break; ++ ++ case s_http_host_port: ++ if (s != s_http_host_port) { ++ u->field_data[UF_PORT].off = p - buf; ++ u->field_data[UF_PORT].len = 0; ++ u->field_set |= (1 << UF_PORT); ++ } ++ u->field_data[UF_PORT].len++; ++ break; ++ ++ case s_http_userinfo: ++ if (s != s_http_userinfo) { ++ u->field_data[UF_USERINFO].off = p - buf ; ++ u->field_data[UF_USERINFO].len = 0; ++ u->field_set |= (1 << UF_USERINFO); ++ } ++ u->field_data[UF_USERINFO].len++; ++ break; ++ ++ default: ++ break; ++ } ++ s = new_s; ++ } ++ ++ /* Make sure we don't end somewhere unexpected */ ++ switch (s) { ++ case s_http_host_start: ++ case s_http_host_v6_start: ++ case s_http_host_v6: ++ case s_http_host_v6_zone_start: ++ case s_http_host_v6_zone: ++ case s_http_host_port_start: ++ case s_http_userinfo: ++ case s_http_userinfo_start: ++ return 1; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++void ++http_parser_url_init(struct http_parser_url *u) { ++ memset(u, 0, sizeof(*u)); ++} ++ ++int ++http_parser_parse_url(const char *buf, size_t buflen, int is_connect, ++ struct http_parser_url *u) ++{ ++ enum state s; ++ const char *p; ++ enum http_parser_url_fields uf, old_uf; ++ int found_at = 0; ++ ++ u->port = u->field_set = 0; ++ s = is_connect ? s_req_server_start : s_req_spaces_before_url; ++ old_uf = UF_MAX; ++ ++ for (p = buf; p < buf + buflen; p++) { ++ s = parse_url_char(s, *p); ++ ++ /* Figure out the next field that we're operating on */ ++ switch (s) { ++ case s_dead: ++ return 1; ++ ++ /* Skip delimeters */ ++ case s_req_schema_slash: ++ case s_req_schema_slash_slash: ++ case s_req_server_start: ++ case s_req_query_string_start: ++ case s_req_fragment_start: ++ continue; ++ ++ case s_req_schema: ++ uf = UF_SCHEMA; ++ break; ++ ++ case s_req_server_with_at: ++ found_at = 1; ++ ++ /* FALLTROUGH */ ++ case s_req_server: ++ uf = UF_HOST; ++ break; ++ ++ case s_req_path: ++ uf = UF_PATH; ++ break; ++ ++ case s_req_query_string: ++ uf = UF_QUERY; ++ break; ++ ++ case s_req_fragment: ++ uf = UF_FRAGMENT; ++ break; ++ ++ default: ++ assert(!"Unexpected state"); ++ return 1; ++ } ++ ++ /* Nothing's changed; soldier on */ ++ if (uf == old_uf) { ++ u->field_data[uf].len++; ++ continue; ++ } ++ ++ u->field_data[uf].off = p - buf; ++ u->field_data[uf].len = 1; ++ ++ u->field_set |= (1 << uf); ++ old_uf = uf; ++ } ++ ++ /* host must be present if there is a schema */ ++ /* parsing http:///toto will fail */ ++ if ((u->field_set & (1 << UF_SCHEMA)) && ++ (u->field_set & (1 << UF_HOST)) == 0) { ++ return 1; ++ } ++ ++ if (u->field_set & (1 << UF_HOST)) { ++ if (http_parse_host(buf, u, found_at) != 0) { ++ return 1; ++ } ++ } ++ ++ /* CONNECT requests can only contain "hostname:port" */ ++ if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { ++ return 1; ++ } ++ ++ if (u->field_set & (1 << UF_PORT)) { ++ /* Don't bother with endp; we've already validated the string */ ++ unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10); ++ ++ /* Ports have a max value of 2^16 */ ++ if (v > 0xffff) { ++ return 1; ++ } ++ ++ u->port = (uint16_t) v; ++ } ++ ++ return 0; ++} ++ ++void ++http_parser_pause(http_parser *parser, int paused) { ++ /* Users should only be pausing/unpausing a parser that is not in an error ++ * state. In non-debug builds, there's not much that we can do about this ++ * other than ignore it. ++ */ ++ if (HTTP_PARSER_ERRNO(parser) == HPE_OK || ++ HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { ++ SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); ++ } else { ++ assert(0 && "Attempting to pause parser in error state"); ++ } ++} ++ ++int ++http_body_is_final(const struct http_parser *parser) { ++ return parser->state == s_message_done; ++} ++ ++unsigned long ++http_parser_version(void) { ++ return HTTP_PARSER_VERSION_MAJOR * 0x10000 | ++ HTTP_PARSER_VERSION_MINOR * 0x00100 | ++ HTTP_PARSER_VERSION_PATCH * 0x00001; ++} +diff --git a/src/responder/secrets/http_parser.h b/src/responder/secrets/http_parser.h +new file mode 100644 +index 0000000000000000000000000000000000000000..105ae510a8ab57509de2c68bbe1504e39ffb165e +--- /dev/null ++++ b/src/responder/secrets/http_parser.h +@@ -0,0 +1,362 @@ ++/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++#ifndef http_parser_h ++#define http_parser_h ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Also update SONAME in the Makefile whenever you change these. */ ++#define HTTP_PARSER_VERSION_MAJOR 2 ++#define HTTP_PARSER_VERSION_MINOR 7 ++#define HTTP_PARSER_VERSION_PATCH 0 ++ ++#include ++#if defined(_WIN32) && !defined(__MINGW32__) && \ ++ (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) ++#include ++#include ++typedef __int8 int8_t; ++typedef unsigned __int8 uint8_t; ++typedef __int16 int16_t; ++typedef unsigned __int16 uint16_t; ++typedef __int32 int32_t; ++typedef unsigned __int32 uint32_t; ++typedef __int64 int64_t; ++typedef unsigned __int64 uint64_t; ++#else ++#include ++#endif ++ ++/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run ++ * faster ++ */ ++#ifndef HTTP_PARSER_STRICT ++# define HTTP_PARSER_STRICT 1 ++#endif ++ ++/* Maximium header size allowed. If the macro is not defined ++ * before including this header then the default is used. To ++ * change the maximum header size, define the macro in the build ++ * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove ++ * the effective limit on the size of the header, define the macro ++ * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) ++ */ ++#ifndef HTTP_MAX_HEADER_SIZE ++# define HTTP_MAX_HEADER_SIZE (80*1024) ++#endif ++ ++typedef struct http_parser http_parser; ++typedef struct http_parser_settings http_parser_settings; ++ ++ ++/* Callbacks should return non-zero to indicate an error. The parser will ++ * then halt execution. ++ * ++ * The one exception is on_headers_complete. In a HTTP_RESPONSE parser ++ * returning '1' from on_headers_complete will tell the parser that it ++ * should not expect a body. This is used when receiving a response to a ++ * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: ++ * chunked' headers that indicate the presence of a body. ++ * ++ * Returning `2` from on_headers_complete will tell parser that it should not ++ * expect neither a body nor any futher responses on this connection. This is ++ * useful for handling responses to a CONNECT request which may not contain ++ * `Upgrade` or `Connection: upgrade` headers. ++ * ++ * http_data_cb does not return data chunks. It will be called arbitrarily ++ * many times for each string. E.G. you might get 10 callbacks for "on_url" ++ * each providing just a few characters more data. ++ */ ++typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); ++typedef int (*http_cb) (http_parser*); ++ ++ ++/* Request Methods */ ++#define HTTP_METHOD_MAP(XX) \ ++ XX(0, DELETE, DELETE) \ ++ XX(1, GET, GET) \ ++ XX(2, HEAD, HEAD) \ ++ XX(3, POST, POST) \ ++ XX(4, PUT, PUT) \ ++ /* pathological */ \ ++ XX(5, CONNECT, CONNECT) \ ++ XX(6, OPTIONS, OPTIONS) \ ++ XX(7, TRACE, TRACE) \ ++ /* WebDAV */ \ ++ XX(8, COPY, COPY) \ ++ XX(9, LOCK, LOCK) \ ++ XX(10, MKCOL, MKCOL) \ ++ XX(11, MOVE, MOVE) \ ++ XX(12, PROPFIND, PROPFIND) \ ++ XX(13, PROPPATCH, PROPPATCH) \ ++ XX(14, SEARCH, SEARCH) \ ++ XX(15, UNLOCK, UNLOCK) \ ++ XX(16, BIND, BIND) \ ++ XX(17, REBIND, REBIND) \ ++ XX(18, UNBIND, UNBIND) \ ++ XX(19, ACL, ACL) \ ++ /* subversion */ \ ++ XX(20, REPORT, REPORT) \ ++ XX(21, MKACTIVITY, MKACTIVITY) \ ++ XX(22, CHECKOUT, CHECKOUT) \ ++ XX(23, MERGE, MERGE) \ ++ /* upnp */ \ ++ XX(24, MSEARCH, M-SEARCH) \ ++ XX(25, NOTIFY, NOTIFY) \ ++ XX(26, SUBSCRIBE, SUBSCRIBE) \ ++ XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ ++ /* RFC-5789 */ \ ++ XX(28, PATCH, PATCH) \ ++ XX(29, PURGE, PURGE) \ ++ /* CalDAV */ \ ++ XX(30, MKCALENDAR, MKCALENDAR) \ ++ /* RFC-2068, section 19.6.1.2 */ \ ++ XX(31, LINK, LINK) \ ++ XX(32, UNLINK, UNLINK) \ ++ ++enum http_method ++ { ++#define XX(num, name, string) HTTP_##name = num, ++ HTTP_METHOD_MAP(XX) ++#undef XX ++ }; ++ ++ ++enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; ++ ++ ++/* Flag values for http_parser.flags field */ ++enum flags ++ { F_CHUNKED = 1 << 0 ++ , F_CONNECTION_KEEP_ALIVE = 1 << 1 ++ , F_CONNECTION_CLOSE = 1 << 2 ++ , F_CONNECTION_UPGRADE = 1 << 3 ++ , F_TRAILING = 1 << 4 ++ , F_UPGRADE = 1 << 5 ++ , F_SKIPBODY = 1 << 6 ++ , F_CONTENTLENGTH = 1 << 7 ++ }; ++ ++ ++/* Map for errno-related constants ++ * ++ * The provided argument should be a macro that takes 2 arguments. ++ */ ++#define HTTP_ERRNO_MAP(XX) \ ++ /* No error */ \ ++ XX(OK, "success") \ ++ \ ++ /* Callback-related errors */ \ ++ XX(CB_message_begin, "the on_message_begin callback failed") \ ++ XX(CB_url, "the on_url callback failed") \ ++ XX(CB_header_field, "the on_header_field callback failed") \ ++ XX(CB_header_value, "the on_header_value callback failed") \ ++ XX(CB_headers_complete, "the on_headers_complete callback failed") \ ++ XX(CB_body, "the on_body callback failed") \ ++ XX(CB_message_complete, "the on_message_complete callback failed") \ ++ XX(CB_status, "the on_status callback failed") \ ++ XX(CB_chunk_header, "the on_chunk_header callback failed") \ ++ XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ ++ \ ++ /* Parsing-related errors */ \ ++ XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ ++ XX(HEADER_OVERFLOW, \ ++ "too many header bytes seen; overflow detected") \ ++ XX(CLOSED_CONNECTION, \ ++ "data received after completed connection: close message") \ ++ XX(INVALID_VERSION, "invalid HTTP version") \ ++ XX(INVALID_STATUS, "invalid HTTP status code") \ ++ XX(INVALID_METHOD, "invalid HTTP method") \ ++ XX(INVALID_URL, "invalid URL") \ ++ XX(INVALID_HOST, "invalid host") \ ++ XX(INVALID_PORT, "invalid port") \ ++ XX(INVALID_PATH, "invalid path") \ ++ XX(INVALID_QUERY_STRING, "invalid query string") \ ++ XX(INVALID_FRAGMENT, "invalid fragment") \ ++ XX(LF_EXPECTED, "LF character expected") \ ++ XX(INVALID_HEADER_TOKEN, "invalid character in header") \ ++ XX(INVALID_CONTENT_LENGTH, \ ++ "invalid character in content-length header") \ ++ XX(UNEXPECTED_CONTENT_LENGTH, \ ++ "unexpected content-length header") \ ++ XX(INVALID_CHUNK_SIZE, \ ++ "invalid character in chunk size header") \ ++ XX(INVALID_CONSTANT, "invalid constant string") \ ++ XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ ++ XX(STRICT, "strict mode assertion failed") \ ++ XX(PAUSED, "parser is paused") \ ++ XX(UNKNOWN, "an unknown error occurred") ++ ++ ++/* Define HPE_* values for each errno value above */ ++#define HTTP_ERRNO_GEN(n, s) HPE_##n, ++enum http_errno { ++ HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) ++}; ++#undef HTTP_ERRNO_GEN ++ ++ ++/* Get an http_errno value from an http_parser */ ++#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) ++ ++ ++struct http_parser { ++ /** PRIVATE **/ ++ unsigned int type : 2; /* enum http_parser_type */ ++ unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ ++ unsigned int state : 7; /* enum state from http_parser.c */ ++ unsigned int header_state : 7; /* enum header_state from http_parser.c */ ++ unsigned int index : 7; /* index into current matcher */ ++ unsigned int lenient_http_headers : 1; ++ ++ uint32_t nread; /* # bytes read in various scenarios */ ++ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ ++ ++ /** READ-ONLY **/ ++ unsigned short http_major; ++ unsigned short http_minor; ++ unsigned int status_code : 16; /* responses only */ ++ unsigned int method : 8; /* requests only */ ++ unsigned int http_errno : 7; ++ ++ /* 1 = Upgrade header was present and the parser has exited because of that. ++ * 0 = No upgrade header present. ++ * Should be checked when http_parser_execute() returns in addition to ++ * error checking. ++ */ ++ unsigned int upgrade : 1; ++ ++ /** PUBLIC **/ ++ void *data; /* A pointer to get hook to the "connection" or "socket" object */ ++}; ++ ++ ++struct http_parser_settings { ++ http_cb on_message_begin; ++ http_data_cb on_url; ++ http_data_cb on_status; ++ http_data_cb on_header_field; ++ http_data_cb on_header_value; ++ http_cb on_headers_complete; ++ http_data_cb on_body; ++ http_cb on_message_complete; ++ /* When on_chunk_header is called, the current chunk length is stored ++ * in parser->content_length. ++ */ ++ http_cb on_chunk_header; ++ http_cb on_chunk_complete; ++}; ++ ++ ++enum http_parser_url_fields ++ { UF_SCHEMA = 0 ++ , UF_HOST = 1 ++ , UF_PORT = 2 ++ , UF_PATH = 3 ++ , UF_QUERY = 4 ++ , UF_FRAGMENT = 5 ++ , UF_USERINFO = 6 ++ , UF_MAX = 7 ++ }; ++ ++ ++/* Result structure for http_parser_parse_url(). ++ * ++ * Callers should index into field_data[] with UF_* values iff field_set ++ * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and ++ * because we probably have padding left over), we convert any port to ++ * a uint16_t. ++ */ ++struct http_parser_url { ++ uint16_t field_set; /* Bitmask of (1 << UF_*) values */ ++ uint16_t port; /* Converted UF_PORT string */ ++ ++ struct { ++ uint16_t off; /* Offset into buffer in which field starts */ ++ uint16_t len; /* Length of run in buffer */ ++ } field_data[UF_MAX]; ++}; ++ ++ ++/* Returns the library version. Bits 16-23 contain the major version number, ++ * bits 8-15 the minor version number and bits 0-7 the patch level. ++ * Usage example: ++ * ++ * unsigned long version = http_parser_version(); ++ * unsigned major = (version >> 16) & 255; ++ * unsigned minor = (version >> 8) & 255; ++ * unsigned patch = version & 255; ++ * printf("http_parser v%u.%u.%u\n", major, minor, patch); ++ */ ++unsigned long http_parser_version(void); ++ ++void http_parser_init(http_parser *parser, enum http_parser_type type); ++ ++ ++/* Initialize http_parser_settings members to 0 ++ */ ++void http_parser_settings_init(http_parser_settings *settings); ++ ++ ++/* Executes the parser. Returns number of parsed bytes. Sets ++ * `parser->http_errno` on error. */ ++size_t http_parser_execute(http_parser *parser, ++ const http_parser_settings *settings, ++ const char *data, ++ size_t len); ++ ++ ++/* If http_should_keep_alive() in the on_headers_complete or ++ * on_message_complete callback returns 0, then this should be ++ * the last message on the connection. ++ * If you are the server, respond with the "Connection: close" header. ++ * If you are the client, close the connection. ++ */ ++int http_should_keep_alive(const http_parser *parser); ++ ++/* Returns a string version of the HTTP method. */ ++const char *http_method_str(enum http_method m); ++ ++/* Return a string name of the given error */ ++const char *http_errno_name(enum http_errno err); ++ ++/* Return a string description of the given error */ ++const char *http_errno_description(enum http_errno err); ++ ++/* Initialize all http_parser_url members to 0 */ ++void http_parser_url_init(struct http_parser_url *u); ++ ++/* Parse a URL; return nonzero on failure */ ++int http_parser_parse_url(const char *buf, size_t buflen, ++ int is_connect, ++ struct http_parser_url *u); ++ ++/* Pause or un-pause the parser; a nonzero value pauses */ ++void http_parser_pause(http_parser *parser, int paused); ++ ++/* Checks if this is the final chunk of the body. */ ++int http_body_is_final(const http_parser *parser); ++ ++#ifdef __cplusplus ++} ++#endif ++#endif +diff --git a/src/responder/secrets/secsrv_private.h b/src/responder/secrets/secsrv_private.h +index c3b663996e138bbb14f1ab74db75398ffd0bd5c7..47ed7642cf8da5ecfc8f995199746596a12b3e1d 100644 +--- a/src/responder/secrets/secsrv_private.h ++++ b/src/responder/secrets/secsrv_private.h +@@ -25,7 +25,7 @@ + #include "config.h" + #include "responder/common/responder.h" + #include "responder/secrets/secsrv.h" +-#include ++#include "http_parser.h" + + struct sec_kvp { + char *name; +-- +2.4.11 + diff --git a/SOURCES/0010-LDAP-Add-sdap_lookup_type-enum.patch b/SOURCES/0010-LDAP-Add-sdap_lookup_type-enum.patch deleted file mode 100644 index 9481f75..0000000 --- a/SOURCES/0010-LDAP-Add-sdap_lookup_type-enum.patch +++ /dev/null @@ -1,395 +0,0 @@ -From 179ac94a4910150b846ff1c959e766c5a31274cf Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 8 May 2015 14:49:09 +0200 -Subject: [PATCH 10/13] LDAP: Add sdap_lookup_type enum -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -Change the boolan parameter of sdap_get_users_send and sdap_get_groups_send -to a tri-state that controls whether we expect only a single entry -(ie don't use the paging control), multiple entries with a search limit -(wildcard request) or multiple entries with no limit (enumeration). - -Reviewed-by: Pavel Březina ---- - src/providers/ldap/ldap_auth.c | 2 +- - src/providers/ldap/ldap_id.c | 16 +++++++------- - src/providers/ldap/sdap_async.h | 12 +++++++--- - src/providers/ldap/sdap_async_enum.c | 4 ++-- - src/providers/ldap/sdap_async_groups.c | 40 ++++++++++++++++++++++++---------- - src/providers/ldap/sdap_async_users.c | 32 ++++++++++++++++++++------- - 6 files changed, 73 insertions(+), 33 deletions(-) - -diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c -index 81717942613b4a91ebab668ba2ecfe13caab38be..217e80fd07abc41f2594d19397783683d44600cd 100644 ---- a/src/providers/ldap/ldap_auth.c -+++ b/src/providers/ldap/ldap_auth.c -@@ -418,7 +418,7 @@ static struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx, - sh, attrs, filter, - dp_opt_get_int(opts->basic, - SDAP_SEARCH_TIMEOUT), -- false); -+ SDAP_LOOKUP_SINGLE); - if (!subreq) { - ret = ENOMEM; - goto done; -diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c -index 61f09fc41d3210af5044f5338dd90db67e0123a7..73840d2885ed15a7a9dae2e9175d8361c8fdfe7d 100644 ---- a/src/providers/ldap/ldap_id.c -+++ b/src/providers/ldap/ldap_id.c -@@ -396,12 +396,12 @@ static void users_get_search(struct tevent_req *req) - struct users_get_state *state = tevent_req_data(req, - struct users_get_state); - struct tevent_req *subreq; -- bool multiple_results; -+ enum sdap_entry_lookup_type lookup_type; - - if (state->filter_type == BE_FILTER_WILDCARD) { -- multiple_results = true; -+ lookup_type = SDAP_LOOKUP_WILDCARD; - } else { -- multiple_results = false; -+ lookup_type = SDAP_LOOKUP_SINGLE; - } - - subreq = sdap_get_users_send(state, state->ev, -@@ -412,7 +412,7 @@ static void users_get_search(struct tevent_req *req) - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), -- multiple_results); -+ lookup_type); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; -@@ -901,12 +901,12 @@ static void groups_get_search(struct tevent_req *req) - struct groups_get_state *state = tevent_req_data(req, - struct groups_get_state); - struct tevent_req *subreq; -- bool multiple_results; -+ enum sdap_entry_lookup_type lookup_type; - - if (state->filter_type == BE_FILTER_WILDCARD) { -- multiple_results = true; -+ lookup_type = SDAP_LOOKUP_WILDCARD; - } else { -- multiple_results = false; -+ lookup_type = SDAP_LOOKUP_SINGLE; - } - - subreq = sdap_get_groups_send(state, state->ev, -@@ -916,7 +916,7 @@ static void groups_get_search(struct tevent_req *req) - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_SEARCH_TIMEOUT), -- multiple_results, -+ lookup_type, - state->no_members); - if (!subreq) { - tevent_req_error(req, ENOMEM); -diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h -index b23dfc313905d01caedd1eace6bcb525481b9ebe..09bc0d65407253f93514b30877850cc38009c625 100644 ---- a/src/providers/ldap/sdap_async.h -+++ b/src/providers/ldap/sdap_async.h -@@ -59,6 +59,12 @@ errno_t sdap_connect_host_recv(TALLOC_CTX *mem_ctx, - struct sdap_handle **_sh); - - /* Search users in LDAP, return them as attrs */ -+enum sdap_entry_lookup_type { -+ SDAP_LOOKUP_SINGLE, /* Direct single-user/group lookup */ -+ SDAP_LOOKUP_WILDCARD, /* Multiple entries with a limit */ -+ SDAP_LOOKUP_ENUMERATE, /* Fetch all entries from the server */ -+}; -+ - struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx, - struct tevent_context *ev, - struct sss_domain_info *dom, -@@ -68,7 +74,7 @@ struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- bool enumeration); -+ enum sdap_entry_lookup_type lookup_type); - int sdap_search_user_recv(TALLOC_CTX *memctx, struct tevent_req *req, - char **higher_usn, struct sysdb_attrs ***users, - size_t *count); -@@ -84,7 +90,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- bool enumeration); -+ enum sdap_entry_lookup_type lookup_type); - int sdap_get_users_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp); - -@@ -96,7 +102,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- bool enumeration, -+ enum sdap_entry_lookup_type lookup_type, - bool no_members); - int sdap_get_groups_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, char **timestamp); -diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c -index 35afc55f809669a44aa2beda7d87dfe62d6ec10b..f22276c3ce6f839b765bbc1602fafb010cc37d89 100644 ---- a/src/providers/ldap/sdap_async_enum.c -+++ b/src/providers/ldap/sdap_async_enum.c -@@ -635,7 +635,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx, - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT), -- true); -+ SDAP_LOOKUP_ENUMERATE); - if (!subreq) { - ret = ENOMEM; - goto fail; -@@ -811,7 +811,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, - state->attrs, state->filter, - dp_opt_get_int(state->ctx->opts->basic, - SDAP_ENUM_SEARCH_TIMEOUT), -- true, false); -+ SDAP_LOOKUP_ENUMERATE, false); - if (!subreq) { - ret = ENOMEM; - goto fail; -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index e785307e60d0df5be96a5b2de2c07baabaf1e371..ad0354df1fce9011c68cabb6049e7feee92a44c0 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -1721,7 +1721,7 @@ struct sdap_get_groups_state { - const char *base_filter; - char *filter; - int timeout; -- bool enumeration; -+ enum sdap_entry_lookup_type lookup_type; - bool no_members; - - char *higher_usn; -@@ -1752,7 +1752,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- bool enumeration, -+ enum sdap_entry_lookup_type lookup_type, - bool no_members) - { - errno_t ret; -@@ -1775,7 +1775,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, - state->groups = NULL; - state->count = 0; - state->timeout = timeout; -- state->enumeration = enumeration; -+ state->lookup_type = lookup_type; - state->no_members = no_members; - state->base_filter = filter; - state->base_iter = 0; -@@ -1855,6 +1855,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - { - struct tevent_req *subreq; - struct sdap_get_groups_state *state; -+ bool need_paging = false; - - state = tevent_req_data(req, struct sdap_get_groups_state); - -@@ -1870,6 +1871,19 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - "Searching for groups with base [%s]\n", - state->search_bases[state->base_iter]->basedn); - -+ switch (state->lookup_type) { -+ case SDAP_LOOKUP_SINGLE: -+ need_paging = false; -+ break; -+ /* Only requests that can return multiple entries should require -+ * the paging control -+ */ -+ case SDAP_LOOKUP_WILDCARD: -+ case SDAP_LOOKUP_ENUMERATE: -+ need_paging = true; -+ break; -+ } -+ - subreq = sdap_get_and_parse_generic_send( - state, state->ev, state->opts, - state->ldap_sh != NULL ? state->ldap_sh : state->sh, -@@ -1878,7 +1892,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - state->filter, state->attrs, - state->opts->group_map, SDAP_OPTS_GROUP, - 0, NULL, NULL, 0, state->timeout, -- state->enumeration); /* If we're enumerating, we need paging */ -+ need_paging); - if (!subreq) { - return ENOMEM; - } -@@ -1914,14 +1928,17 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - DEBUG(SSSDBG_TRACE_FUNC, - "Search for groups, returned %zu results.\n", count); - -- if (!state->enumeration && count > 1) { -+ if (state->lookup_type == SDAP_LOOKUP_SINGLE && count > 1) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Individual group search returned multiple results\n"); - tevent_req_error(req, EINVAL); - return; - } - -- if (state->enumeration || count == 0) { -+ if (state->lookup_type == SDAP_LOOKUP_WILDCARD || \ -+ state->lookup_type == SDAP_LOOKUP_ENUMERATE || \ -+ count == 0) { -+ /* No users found in this search or looking up multiple entries */ - next_base = true; - } - -@@ -2003,7 +2020,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - * LDAP_MATCHING_RULE_IN_CHAIN available in - * AD 2008 and later - */ -- if (!state->enumeration) { -+ if (state->lookup_type == SDAP_LOOKUP_SINGLE) { - if ((state->opts->schema_type != SDAP_SCHEMA_RFC2307) - && (dp_opt_get_int(state->opts->basic, SDAP_NESTING_LEVEL) != 0) - && !dp_opt_get_bool(state->opts->basic, SDAP_AD_MATCHING_RULE_GROUPS)) { -@@ -2026,7 +2043,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - /* If we're using LDAP_MATCHING_RULE_IN_CHAIN, start a subreq to - * retrieve the members so we can save them in a single step. - */ -- if (!state->enumeration -+ if (state->lookup_type == SDAP_LOOKUP_SINGLE - && (state->opts->schema_type != SDAP_SCHEMA_RFC2307) - && state->opts->support_matching_rule - && dp_opt_get_bool(state->opts->basic, SDAP_AD_MATCHING_RULE_GROUPS)) { -@@ -2050,7 +2067,8 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - return; - } - -- if (state->enumeration -+ if ((state->lookup_type == SDAP_LOOKUP_ENUMERATE -+ || state->lookup_type == SDAP_LOOKUP_WILDCARD) - && state->opts->schema_type != SDAP_SCHEMA_RFC2307 - && dp_opt_get_int(state->opts->basic, SDAP_NESTING_LEVEL) != 0) { - DEBUG(SSSDBG_TRACE_ALL, "Saving groups without members first " -@@ -2069,7 +2087,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - subreq = sdap_process_group_send(state, state->ev, state->dom, - state->sysdb, state->opts, - state->sh, state->groups[i], -- state->enumeration); -+ state->lookup_type == SDAP_LOOKUP_ENUMERATE); - - if (!subreq) { - tevent_req_error(req, ENOMEM); -@@ -2116,7 +2134,7 @@ static void sdap_get_groups_done(struct tevent_req *subreq) - ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts, - state->groups, state->count, - !state->dom->ignore_group_members, NULL, -- !state->enumeration, -+ state->lookup_type == SDAP_LOOKUP_SINGLE, - &state->higher_usn); - if (ret) { - DEBUG(SSSDBG_OP_FAILURE, "Failed to store groups.\n"); -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index 216b49477bf21481265444c5c03df0aac7ee84e4..f66ae2604c867d4a5e8d223081ece9f1e474cf73 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -606,7 +606,7 @@ struct sdap_search_user_state { - const char *base_filter; - const char *filter; - int timeout; -- bool enumeration; -+ enum sdap_entry_lookup_type lookup_type; - - char *higher_usn; - struct sysdb_attrs **users; -@@ -628,7 +628,7 @@ struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- bool enumeration) -+ enum sdap_entry_lookup_type lookup_type) - { - errno_t ret; - struct tevent_req *req; -@@ -649,7 +649,7 @@ struct tevent_req *sdap_search_user_send(TALLOC_CTX *memctx, - state->base_filter = filter; - state->base_iter = 0; - state->search_bases = search_bases; -- state->enumeration = enumeration; -+ state->lookup_type = lookup_type; - - if (!state->search_bases) { - DEBUG(SSSDBG_CRIT_FAILURE, -@@ -673,6 +673,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - { - struct tevent_req *subreq; - struct sdap_search_user_state *state; -+ bool need_paging = false; - - state = tevent_req_data(req, struct sdap_search_user_state); - -@@ -688,6 +689,19 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - "Searching for users with base [%s]\n", - state->search_bases[state->base_iter]->basedn); - -+ switch (state->lookup_type) { -+ case SDAP_LOOKUP_SINGLE: -+ need_paging = false; -+ break; -+ /* Only requests that can return multiple entries should require -+ * the paging control -+ */ -+ case SDAP_LOOKUP_WILDCARD: -+ case SDAP_LOOKUP_ENUMERATE: -+ need_paging = true; -+ break; -+ } -+ - subreq = sdap_get_and_parse_generic_send( - state, state->ev, state->opts, state->sh, - state->search_bases[state->base_iter]->basedn, -@@ -695,7 +709,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - state->filter, state->attrs, - state->opts->user_map, state->opts->user_map_cnt, - 0, NULL, NULL, 0, state->timeout, -- state->enumeration); /* If we're enumerating, we need paging */ -+ need_paging); - if (subreq == NULL) { - return ENOMEM; - } -@@ -726,8 +740,10 @@ static void sdap_search_user_process(struct tevent_req *subreq) - DEBUG(SSSDBG_TRACE_FUNC, - "Search for users, returned %zu results.\n", count); - -- if (state->enumeration || count == 0) { -- /* No users found in this search or enumerating */ -+ if (state->lookup_type == SDAP_LOOKUP_WILDCARD || \ -+ state->lookup_type == SDAP_LOOKUP_ENUMERATE || \ -+ count == 0) { -+ /* No users found in this search or looking up multiple entries */ - next_base = true; - } - -@@ -827,7 +843,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - const char **attrs, - const char *filter, - int timeout, -- bool enumeration) -+ enum sdap_entry_lookup_type lookup_type) - { - errno_t ret; - struct tevent_req *req; -@@ -842,7 +858,7 @@ struct tevent_req *sdap_get_users_send(TALLOC_CTX *memctx, - state->dom = dom; - - subreq = sdap_search_user_send(state, ev, dom, opts, search_bases, -- sh, attrs, filter, timeout, enumeration); -+ sh, attrs, filter, timeout, lookup_type); - if (subreq == NULL) { - ret = ENOMEM; - goto done; --- -2.4.3 - diff --git a/SOURCES/0010-MAN-Update-description-of-sssctl.patch b/SOURCES/0010-MAN-Update-description-of-sssctl.patch new file mode 100644 index 0000000..4e5482c --- /dev/null +++ b/SOURCES/0010-MAN-Update-description-of-sssctl.patch @@ -0,0 +1,48 @@ +From 41a8e0f463188dd6a78d44908a8601c7c7576b59 Mon Sep 17 00:00:00 2001 +From: Dan Lavu +Date: Mon, 11 Jul 2016 12:27:34 +0200 +Subject: [PATCH 10/14] MAN: Update description of sssctl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Pavel Březina +(cherry picked from commit 8ad1883c79fc1e356bbd2d3e4badd4af9955b9fc) +--- + src/man/sssctl.8.xml | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/src/man/sssctl.8.xml b/src/man/sssctl.8.xml +index 721d0a2f7558b105c22135388757f92270265c4a..cbb632b68b145680ab94523b90180c5f76d69eb9 100644 +--- a/src/man/sssctl.8.xml ++++ b/src/man/sssctl.8.xml +@@ -29,12 +29,11 @@ + + DESCRIPTION + +- sssctl provides simple and unified way to obtain +- information about SSSD status such as active server or list of +- auto-discovered servers and domains or information about cached +- objects. It also provides tools to manage SSSD data files during +- troubleshooting such as a safe way to remove cache files or fetching +- all SSSD log files and more. ++ sssctl provides a simple and unified way ++ to obtain information about SSSD status, such as active server, ++ auto-discovered servers, domains and cached objects. In addition, ++ it can manage SSSD data files for troubleshooting in such a way ++ that is safe to manipulate while SSSD is running. + + + +@@ -42,7 +41,7 @@ + AVAILABLE COMMANDS + + To list all available commands run sssctl +- without any parameter. To print help for selected command ++ without any parameters. To print help for selected command + run sssctl COMMAND --help. + + +-- +2.4.11 + diff --git a/SOURCES/0011-LDAP-Add-the-wildcard_limit-option.patch b/SOURCES/0011-LDAP-Add-the-wildcard_limit-option.patch deleted file mode 100644 index c9145af..0000000 --- a/SOURCES/0011-LDAP-Add-the-wildcard_limit-option.patch +++ /dev/null @@ -1,237 +0,0 @@ -From 4e795d8ff3a1d1f5cd5a7dddaf364909c60d9191 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 17 Jun 2015 16:13:51 +0200 -Subject: [PATCH 11/13] LDAP: Add the wildcard_limit option -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Related: - https://fedorahosted.org/sssd/ticket/2553 - -Adds a new wildcard_limit option that is set by default to 1000 (one -page). This option limits the number of entries that can by default be -returned by a wildcard search. - -Reviewed-by: Pavel Březina ---- - src/config/SSSDConfig/__init__.py.in | 1 + - src/config/etc/sssd.api.d/sssd-ad.conf | 1 + - src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + - src/config/etc/sssd.api.d/sssd-ldap.conf | 1 + - src/man/sssd-ldap.5.xml | 17 +++++++++++++++++ - src/providers/ad/ad_opts.h | 1 + - src/providers/ipa/ipa_opts.h | 1 + - src/providers/ldap/ldap_opts.h | 1 + - src/providers/ldap/sdap.h | 1 + - src/providers/ldap/sdap_async_groups.c | 8 +++++++- - src/providers/ldap/sdap_async_users.c | 8 +++++++- - 11 files changed, 39 insertions(+), 2 deletions(-) - -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 4d45e42af4fa32717caa69cc621834cdffc27431..4b519eddd04cde83c209f5a1940832cc7f41c736 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -355,6 +355,7 @@ option_strings = { - 'ldap_min_id' : _('Set lower boundary for allowed IDs from the LDAP server'), - 'ldap_max_id' : _('Set upper boundary for allowed IDs from the LDAP server'), - 'ldap_pwdlockout_dn' : _('DN for ppolicy queries'), -+ 'wildcard_limit' : _('How many maximum entries to fetch during a wildcard request'), - - # [provider/ldap/auth] - 'ldap_pwd_policy' : _('Policy to evaluate the password expiration'), -diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf -index faab3a51e54d6d498392021a8945501120870f70..b636d93108ef0a3831970d7827895c14b0f3571c 100644 ---- a/src/config/etc/sssd.api.d/sssd-ad.conf -+++ b/src/config/etc/sssd.api.d/sssd-ad.conf -@@ -56,6 +56,7 @@ ldap_deref_threshold = int, None, false - ldap_connection_expire_timeout = int, None, false - ldap_disable_paging = bool, None, false - krb5_confd_path = str, None, false -+wildcard_limit = int, None, false - - [provider/ad/id] - ldap_search_timeout = int, None, false -diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf -index cfcc00f6f7ca768df861e8cf7face065f90e9e83..ab712fe55cdac6d247a085aeca5cc82d65966623 100644 ---- a/src/config/etc/sssd.api.d/sssd-ipa.conf -+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf -@@ -52,6 +52,7 @@ ldap_deref_threshold = int, None, false - ldap_connection_expire_timeout = int, None, false - ldap_disable_paging = bool, None, false - krb5_confd_path = str, None, false -+wildcard_limit = int, None, false - - [provider/ipa/id] - ldap_search_timeout = int, None, false -diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf -index c10290217b1b133792b893d9b80e2599969838a6..8fd45fd4093714f458161eb352157c845d926f06 100644 ---- a/src/config/etc/sssd.api.d/sssd-ldap.conf -+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf -@@ -37,6 +37,7 @@ ldap_sasl_minssf = int, None, false - ldap_connection_expire_timeout = int, None, false - ldap_disable_paging = bool, None, false - ldap_disable_range_retrieval = bool, None, false -+wildcard_limit = int, None, false - - [provider/ldap/id] - ldap_search_timeout = int, None, false -diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml -index f14090843fd32141ad4f491b69868aa7b2412301..9ac175f8d4a8aa01ca2434b800ebae1be88575f5 100644 ---- a/src/man/sssd-ldap.5.xml -+++ b/src/man/sssd-ldap.5.xml -@@ -2135,6 +2135,23 @@ ldap_access_filter = (employeeType=admin) - - - -+ -+ wildcart_limit (integer) -+ -+ -+ Specifies an upper limit on the number of entries -+ that are downloaded during a wildcard lookup. -+ -+ -+ At the moment, only the InfoPipe responder supports -+ wildcard lookups. -+ -+ -+ Default: 1000 (often the size of one page) -+ -+ -+ -+ - - - -diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h -index cb4c05d846d9abe5eedb28013ad13fff6476d431..d685edcb44c771b0afc7a232a82c21fc9d1c89f9 100644 ---- a/src/providers/ad/ad_opts.h -+++ b/src/providers/ad/ad_opts.h -@@ -146,6 +146,7 @@ struct dp_option ad_def_ldap_opts[] = { - { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER}, - { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER}, - { "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING }, -+ { "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER}, - DP_OPTION_TERMINATOR - }; - -diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h -index 253c0715355536cc181c57beed5326a77e87e464..9576228d1bf3424c8867bda058b59c3ca6b2216b 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -157,6 +157,7 @@ struct dp_option ipa_def_ldap_opts[] = { - { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER}, - { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER}, - { "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING }, -+ { "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER}, - DP_OPTION_TERMINATOR - }; - -diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h -index c1b9bf688ef0a92046195c13a11d2c17b2419d67..9f58db5bd9eef1391e97c1890cbff94c2a5406d6 100644 ---- a/src/providers/ldap/ldap_opts.h -+++ b/src/providers/ldap/ldap_opts.h -@@ -122,6 +122,7 @@ struct dp_option default_basic_opts[] = { - { "ldap_min_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER}, - { "ldap_max_id", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER}, - { "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING }, -+ { "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER}, - DP_OPTION_TERMINATOR - }; - -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index d9b2d18637bdb3e7823af9d1de2c042c8134780f..444502bf7159edcf4cebe530cce8b216c737ec30 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -231,6 +231,7 @@ enum sdap_basic_opt { - SDAP_MIN_ID, - SDAP_MAX_ID, - SDAP_PWDLOCKOUT_DN, -+ SDAP_WILDCARD_LIMIT, - - SDAP_OPTS_BASIC /* opts counter */ - }; -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index ad0354df1fce9011c68cabb6049e7feee92a44c0..525c6fa09553d8c0232ce2317751184f83632d86 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -1856,6 +1856,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - struct tevent_req *subreq; - struct sdap_get_groups_state *state; - bool need_paging = false; -+ int sizelimit = 0; - - state = tevent_req_data(req, struct sdap_get_groups_state); - -@@ -1873,13 +1874,18 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - - switch (state->lookup_type) { - case SDAP_LOOKUP_SINGLE: -+ sizelimit = 1; - need_paging = false; - break; - /* Only requests that can return multiple entries should require - * the paging control - */ - case SDAP_LOOKUP_WILDCARD: -+ sizelimit = dp_opt_get_int(state->opts->basic, SDAP_WILDCARD_LIMIT); -+ need_paging = true; -+ break; - case SDAP_LOOKUP_ENUMERATE: -+ sizelimit = 0; /* unlimited */ - need_paging = true; - break; - } -@@ -1891,7 +1897,7 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - state->search_bases[state->base_iter]->scope, - state->filter, state->attrs, - state->opts->group_map, SDAP_OPTS_GROUP, -- 0, NULL, NULL, 0, state->timeout, -+ 0, NULL, NULL, sizelimit, state->timeout, - need_paging); - if (!subreq) { - return ENOMEM; -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index f66ae2604c867d4a5e8d223081ece9f1e474cf73..a864a8b2187de7972aa963b355856e97f7c692a9 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -674,6 +674,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - struct tevent_req *subreq; - struct sdap_search_user_state *state; - bool need_paging = false; -+ int sizelimit = 0; - - state = tevent_req_data(req, struct sdap_search_user_state); - -@@ -691,13 +692,18 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - - switch (state->lookup_type) { - case SDAP_LOOKUP_SINGLE: -+ sizelimit = 1; - need_paging = false; - break; - /* Only requests that can return multiple entries should require - * the paging control - */ - case SDAP_LOOKUP_WILDCARD: -+ sizelimit = dp_opt_get_int(state->opts->basic, SDAP_WILDCARD_LIMIT); -+ need_paging = true; -+ break; - case SDAP_LOOKUP_ENUMERATE: -+ sizelimit = 0; /* unlimited */ - need_paging = true; - break; - } -@@ -708,7 +714,7 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - state->search_bases[state->base_iter]->scope, - state->filter, state->attrs, - state->opts->user_map, state->opts->user_map_cnt, -- 0, NULL, NULL, 0, state->timeout, -+ 0, NULL, NULL, sizelimit, state->timeout, - need_paging); - if (subreq == NULL) { - return ENOMEM; --- -2.4.3 - diff --git a/SOURCES/0011-nss-srv-tests-Fix-prototype-of-wrapped-ncache-functi.patch b/SOURCES/0011-nss-srv-tests-Fix-prototype-of-wrapped-ncache-functi.patch new file mode 100644 index 0000000..eafe318 --- /dev/null +++ b/SOURCES/0011-nss-srv-tests-Fix-prototype-of-wrapped-ncache-functi.patch @@ -0,0 +1,101 @@ +From 721f83fa5661c861674c17edbb309bb9ade15892 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 4 Jul 2016 14:08:46 +0200 +Subject: [PATCH 11/14] nss-srv-tests: Fix prototype of wrapped ncache + functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The argument ttl was recently removed from negative cache functions +(sss_ncache_check_user, sss_ncache_check_uid, sss_ncache_check_sid, +sss_ncache_check_cert) but it was not removed from wrapped versions +in nss-srv-tests. It caused a crash on machine with big endian +and when configure wih --coverage. + +Reviewed-by: Pavel Březina +(cherry picked from commit 35567de112cd5d82acb582cbdb44c8652bbdfda1) +--- + src/tests/cmocka/test_nss_srv.c | 28 ++++++++++++---------------- + 1 file changed, 12 insertions(+), 16 deletions(-) + +diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c +index 5e0398f20b9906df39371826e50a9c78675dfa74..4137e9151be561a57a8f2e674f385ecb37119255 100644 +--- a/src/tests/cmocka/test_nss_srv.c ++++ b/src/tests/cmocka/test_nss_srv.c +@@ -151,60 +151,56 @@ int __wrap_sss_cmd_send_empty(struct cli_ctx *cctx, TALLOC_CTX *freectx) + } + + /* Intercept negative cache lookups */ +-int __real_sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl, ++int __real_sss_ncache_check_user(struct sss_nc_ctx *ctx, + struct sss_domain_info *dom, const char *name); + +-int __wrap_sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl, ++int __wrap_sss_ncache_check_user(struct sss_nc_ctx *ctx, + struct sss_domain_info *dom, const char *name) + { + int ret; + +- ret = __real_sss_ncache_check_user(ctx, ttl, dom, name); ++ ret = __real_sss_ncache_check_user(ctx, dom, name); + if (ret == EEXIST) { + nss_test_ctx->ncache_hits++; + } + return ret; + } + +-int __real_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, ++int __real_sss_ncache_check_uid(struct sss_nc_ctx *ctx, + struct sss_domain_info *dom, uid_t uid); + +-int __wrap_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, ++int __wrap_sss_ncache_check_uid(struct sss_nc_ctx *ctx, + struct sss_domain_info *dom, uid_t uid) + { + int ret; + +- ret = __real_sss_ncache_check_uid(ctx, ttl, dom, uid); ++ ret = __real_sss_ncache_check_uid(ctx, dom, uid); + if (ret == EEXIST) { + nss_test_ctx->ncache_hits++; + } + return ret; + } + +-int __real_sss_ncache_check_sid(struct sss_nc_ctx *ctx, +- int ttl, const char *sid); ++int __real_sss_ncache_check_sid(struct sss_nc_ctx *ctx, const char *sid); + +-int __wrap_sss_ncache_check_sid(struct sss_nc_ctx *ctx, +- int ttl, const char *sid) ++int __wrap_sss_ncache_check_sid(struct sss_nc_ctx *ctx, const char *sid) + { + int ret; + +- ret = __real_sss_ncache_check_sid(ctx, ttl, sid); ++ ret = __real_sss_ncache_check_sid(ctx, sid); + if (ret == EEXIST) { + nss_test_ctx->ncache_hits++; + } + return ret; + } + +-int __real_sss_ncache_check_cert(struct sss_nc_ctx *ctx, +- int ttl, const char *cert); ++int __real_sss_ncache_check_cert(struct sss_nc_ctx *ctx, const char *cert); + +-int __wrap_sss_ncache_check_cert(struct sss_nc_ctx *ctx, +- int ttl, const char *cert) ++int __wrap_sss_ncache_check_cert(struct sss_nc_ctx *ctx, const char *cert) + { + int ret; + +- ret = __real_sss_ncache_check_cert(ctx, ttl, cert); ++ ret = __real_sss_ncache_check_cert(ctx, cert); + if (ret == EEXIST) { + nss_test_ctx->ncache_hits++; + } +-- +2.4.11 + diff --git a/SOURCES/0012-IFP-Add-wildcard-requests.patch b/SOURCES/0012-IFP-Add-wildcard-requests.patch deleted file mode 100644 index d44b2a8..0000000 --- a/SOURCES/0012-IFP-Add-wildcard-requests.patch +++ /dev/null @@ -1,663 +0,0 @@ -From fe9a0097970d12ff261b7417f9e57db95957ab24 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 17 Jun 2015 13:39:43 +0200 -Subject: [PATCH 12/13] IFP: Add wildcard requests -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves: - https://fedorahosted.org/sssd/ticket/2553 - -Can be used as: - -dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \ - /org/freedesktop/sssd/infopipe/Users \ - org.freedesktop.sssd.infopipe.Users.ListByName \ - string:r\* uint32:10 - -dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \ - /org/freedesktop/sssd/infopipe/Groups \ - org.freedesktop.sssd.infopipe.Groups.ListByName \ - string:r\* uint32:10 - -dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \ - /org/freedesktop/sssd/infopipe/Users \ - org.freedesktop.sssd.infopipe.Users.ListByDomainAndName \ - string:ipaldap string:r\* uint32:10 - -dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe \ - /org/freedesktop/sssd/infopipe/Groups \ - org.freedesktop.sssd.infopipe.Groups.ListByDomainAndName \ - string:ipaldap string:r\* uint32:10 - -By default the wildcard_limit is unset, that is, the request will return -all cached entries that match. - -Reviewed-by: Pavel Březina ---- - src/confdb/confdb.h | 1 + - src/man/sssd-ifp.5.xml | 15 ++++ - src/responder/ifp/ifp_groups.c | 175 ++++++++++++++++++++++++++++++++++++++ - src/responder/ifp/ifp_private.h | 22 +++++ - src/responder/ifp/ifp_users.c | 184 ++++++++++++++++++++++++++++++++++++++++ - src/responder/ifp/ifpsrv.c | 23 +++++ - src/responder/ifp/ifpsrv_util.c | 52 ++++++++++++ - 7 files changed, 472 insertions(+) - -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index b2ec2e0b98a9be2d50009df524a1072e9b1c15c7..36df6aea268cc5c82696f20b1a65963350d5e100 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -140,6 +140,7 @@ - /* InfoPipe */ - #define CONFDB_IFP_CONF_ENTRY "config/ifp" - #define CONFDB_IFP_USER_ATTR_LIST "user_attributes" -+#define CONFDB_IFP_WILDCARD_LIMIT "wildcard_limit" - - /* Domains */ - #define CONFDB_DOMAIN_PATH_TMPL "config/domain/%s" -diff --git a/src/man/sssd-ifp.5.xml b/src/man/sssd-ifp.5.xml -index 867c117edccc3c000f7d9e8456298b72ebcdf693..da247f89dd2d9d08e0b1591d4c89f52197b278df 100644 ---- a/src/man/sssd-ifp.5.xml -+++ b/src/man/sssd-ifp.5.xml -@@ -131,6 +131,21 @@ user_attributes = +telephoneNumber, -loginShell - - - -+ -+ -+ wildcart_limit (integer) -+ -+ -+ Specifies an upper limit on the number of entries -+ that are downloaded during a wildcard lookup that -+ overrides caller-supplied limit. -+ -+ -+ Default: 0 (let the caller set an upper limit) -+ -+ -+ -+ - - - -diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c -index 1b581b568f14362a47b4a80eb55d2de8eb936ae3..3060035924026641cc245f2a1970db9e2646e11c 100644 ---- a/src/responder/ifp/ifp_groups.c -+++ b/src/responder/ifp/ifp_groups.c -@@ -81,6 +81,27 @@ done: - return ret; - } - -+static int ifp_groups_list_copy(struct ifp_list_ctx *list_ctx, -+ struct ldb_result *result) -+{ -+ size_t copy_count, i; -+ -+ copy_count = ifp_list_ctx_remaining_capacity(list_ctx, result->count); -+ -+ for (i = 0; i < copy_count; i++) { -+ list_ctx->paths[list_ctx->path_count + i] = \ -+ ifp_groups_build_path_from_msg(list_ctx->paths, -+ list_ctx->dom, -+ result->msgs[i]); -+ if (list_ctx->paths[list_ctx->path_count + i] == NULL) { -+ return ENOMEM; -+ } -+ } -+ -+ list_ctx->path_count += copy_count; -+ return EOK; -+} -+ - static void ifp_groups_find_by_name_done(struct tevent_req *req); - - int ifp_groups_find_by_name(struct sbus_request *sbus_req, -@@ -221,23 +242,177 @@ done: - return; - } - -+static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx); -+static void ifp_groups_list_by_name_done(struct tevent_req *req); -+static void ifp_groups_list_by_name_reply(struct ifp_list_ctx *list_ctx); -+ - int ifp_groups_list_by_name(struct sbus_request *sbus_req, - void *data, - const char *filter, - uint32_t limit) - { -+ struct ifp_ctx *ctx; -+ struct ifp_list_ctx *list_ctx; -+ -+ ctx = talloc_get_type(data, struct ifp_ctx); -+ if (ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); -+ return ERR_INTERNAL; -+ } -+ -+ list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit); -+ if (list_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ return ifp_groups_list_by_name_step(list_ctx); -+} -+ -+static int ifp_groups_list_by_name_step(struct ifp_list_ctx *list_ctx) -+{ -+ struct tevent_req *req; -+ -+ req = cache_req_group_by_filter_send(list_ctx, -+ list_ctx->ctx->rctx->ev, -+ list_ctx->ctx->rctx, -+ list_ctx->dom->name, -+ list_ctx->filter); -+ if (req == NULL) { -+ return ENOMEM; -+ } -+ tevent_req_set_callback(req, -+ ifp_groups_list_by_name_done, list_ctx); -+ - return EOK; - } - -+static void ifp_groups_list_by_name_done(struct tevent_req *req) -+{ -+ DBusError *error; -+ struct ifp_list_ctx *list_ctx; -+ struct sbus_request *sbus_req; -+ struct ldb_result *result; -+ struct sss_domain_info *domain; -+ errno_t ret; -+ -+ list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx); -+ sbus_req = list_ctx->sbus_req; -+ -+ ret = cache_req_group_by_name_recv(sbus_req, req, &result, &domain, NULL); -+ talloc_zfree(req); -+ if (ret != EOK && ret != ENOENT) { -+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " -+ "groups by filter [%d]: %s\n", ret, sss_strerror(ret)); -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+ -+ ret = ifp_groups_list_copy(list_ctx, result); -+ if (ret != EOK) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -+ "Failed to copy domain result"); -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+ -+ list_ctx->dom = get_next_domain(list_ctx->dom, true); -+ if (list_ctx->dom == NULL) { -+ return ifp_groups_list_by_name_reply(list_ctx); -+ } -+ -+ ret = ifp_groups_list_by_name_step(list_ctx); -+ if (ret != EOK) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -+ "Failed to start next-domain search"); -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+} -+ -+static void ifp_groups_list_by_name_reply(struct ifp_list_ctx *list_ctx) -+{ -+ iface_ifp_groups_ListByDomainAndName_finish(list_ctx->sbus_req, -+ list_ctx->paths, -+ list_ctx->path_count); -+} -+ -+static void ifp_groups_list_by_domain_and_name_done(struct tevent_req *req); -+ - int ifp_groups_list_by_domain_and_name(struct sbus_request *sbus_req, - void *data, - const char *domain, - const char *filter, - uint32_t limit) - { -+ struct tevent_req *req; -+ struct ifp_ctx *ctx; -+ struct ifp_list_ctx *list_ctx; -+ -+ ctx = talloc_get_type(data, struct ifp_ctx); -+ if (ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); -+ return ERR_INTERNAL; -+ } -+ -+ list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit); -+ if (list_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ req = cache_req_group_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx, -+ domain, filter); -+ if (req == NULL) { -+ return ENOMEM; -+ } -+ tevent_req_set_callback(req, -+ ifp_groups_list_by_domain_and_name_done, list_ctx); -+ - return EOK; - } - -+static void ifp_groups_list_by_domain_and_name_done(struct tevent_req *req) -+{ -+ DBusError *error; -+ struct ifp_list_ctx *list_ctx; -+ struct sbus_request *sbus_req; -+ struct ldb_result *result; -+ struct sss_domain_info *domain; -+ errno_t ret; -+ -+ list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx); -+ sbus_req = list_ctx->sbus_req; -+ -+ ret = cache_req_user_by_name_recv(sbus_req, req, &result, &domain, NULL); -+ talloc_zfree(req); -+ if (ret == ENOENT) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND, -+ "User not found by filter"); -+ goto done; -+ } else if (ret != EOK) { -+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " -+ "groups by filter [%d]: %s\n", ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = ifp_groups_list_copy(list_ctx, result); -+ if (ret != EOK) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -+ "Failed to copy domain result"); -+ goto done; -+ } -+ -+done: -+ if (ret != EOK) { -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+ -+ iface_ifp_groups_ListByDomainAndName_finish(sbus_req, -+ list_ctx->paths, -+ list_ctx->path_count); -+ return; -+} -+ - static errno_t - ifp_groups_group_get(struct sbus_request *sbus_req, - void *data, -diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h -index 304e4dc535aac4215cf318a0bea845c161c5f079..43519de6fef3033f1e47cecb787d6b02dc9c6e56 100644 ---- a/src/responder/ifp/ifp_private.h -+++ b/src/responder/ifp/ifp_private.h -@@ -44,6 +44,7 @@ struct ifp_ctx { - - struct sysbus_ctx *sysbus; - const char **user_whitelist; -+ uint32_t wildcard_limit; - }; - - errno_t ifp_register_sbus_interface(struct sbus_connection *conn, -@@ -84,4 +85,25 @@ ifp_get_user_extra_attributes(TALLOC_CTX *mem_ctx, struct ifp_ctx *ifp_ctx); - bool ifp_attr_allowed(const char *whitelist[], const char *attr); - bool ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr); - -+/* Used for list calls */ -+struct ifp_list_ctx { -+ struct sbus_request *sbus_req; -+ const char *filter; -+ uint32_t limit; -+ -+ struct sss_domain_info *dom; -+ struct ifp_ctx *ctx; -+ -+ const char **paths; -+ size_t path_count; -+}; -+ -+struct ifp_list_ctx *ifp_list_ctx_new(struct sbus_request *sbus_req, -+ struct ifp_ctx *ctx, -+ const char *filter, -+ uint32_t limit); -+ -+size_t ifp_list_ctx_remaining_capacity(struct ifp_list_ctx *list_ctx, -+ size_t entries); -+ - #endif /* _IFPSRV_PRIVATE_H_ */ -diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c -index 2ec74c30b348ac5f2b84cdc8e2dd406fd44a7da3..effefdc0435d794206dbe7358c61d2ea47760361 100644 ---- a/src/responder/ifp/ifp_users.c -+++ b/src/responder/ifp/ifp_users.c -@@ -309,23 +309,207 @@ done: - return; - } - -+static int ifp_users_list_copy(struct ifp_list_ctx *list_ctx, -+ struct ldb_result *result) -+{ -+ size_t copy_count, i; -+ -+ copy_count = ifp_list_ctx_remaining_capacity(list_ctx, result->count); -+ -+ for (i = 0; i < copy_count; i++) { -+ list_ctx->paths[list_ctx->path_count + i] = \ -+ ifp_users_build_path_from_msg(list_ctx->paths, -+ list_ctx->dom, -+ result->msgs[i]); -+ if (list_ctx->paths[list_ctx->path_count + i] == NULL) { -+ return ENOMEM; -+ } -+ } -+ -+ list_ctx->path_count += copy_count; -+ return EOK; -+} -+ -+static int ifp_users_list_by_name_step(struct ifp_list_ctx *list_ctx); -+static void ifp_users_list_by_name_done(struct tevent_req *req); -+static void ifp_users_list_by_name_reply(struct ifp_list_ctx *list_ctx); -+ - int ifp_users_list_by_name(struct sbus_request *sbus_req, - void *data, - const char *filter, - uint32_t limit) - { -+ struct ifp_ctx *ctx; -+ struct ifp_list_ctx *list_ctx; -+ -+ ctx = talloc_get_type(data, struct ifp_ctx); -+ if (ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); -+ return ERR_INTERNAL; -+ } -+ -+ list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit); -+ if (list_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ return ifp_users_list_by_name_step(list_ctx); -+} -+ -+static int ifp_users_list_by_name_step(struct ifp_list_ctx *list_ctx) -+{ -+ struct tevent_req *req; -+ -+ req = cache_req_user_by_filter_send(list_ctx, -+ list_ctx->ctx->rctx->ev, -+ list_ctx->ctx->rctx, -+ list_ctx->dom->name, -+ list_ctx->filter); -+ if (req == NULL) { -+ return ENOMEM; -+ } -+ tevent_req_set_callback(req, -+ ifp_users_list_by_name_done, list_ctx); -+ - return EOK; - } - -+static void ifp_users_list_by_name_done(struct tevent_req *req) -+{ -+ DBusError *error; -+ struct ifp_list_ctx *list_ctx; -+ struct sbus_request *sbus_req; -+ struct ldb_result *result; -+ struct sss_domain_info *domain; -+ errno_t ret; -+ -+ list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx); -+ sbus_req = list_ctx->sbus_req; -+ -+ ret = cache_req_user_by_name_recv(sbus_req, req, &result, &domain, NULL); -+ talloc_zfree(req); -+ if (ret != EOK && ret != ENOENT) { -+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " -+ "users by filter [%d]: %s\n", ret, sss_strerror(ret)); -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+ -+ ret = ifp_users_list_copy(list_ctx, result); -+ if (ret != EOK) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -+ "Failed to copy domain result"); -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+ -+ list_ctx->dom = get_next_domain(list_ctx->dom, true); -+ if (list_ctx->dom == NULL) { -+ return ifp_users_list_by_name_reply(list_ctx); -+ } -+ -+ ret = ifp_users_list_by_name_step(list_ctx); -+ if (ret != EOK) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -+ "Failed to start next-domain search"); -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+} -+ -+static void ifp_users_list_by_name_reply(struct ifp_list_ctx *list_ctx) -+{ -+ iface_ifp_users_ListByName_finish(list_ctx->sbus_req, -+ list_ctx->paths, -+ list_ctx->path_count); -+} -+ -+static void ifp_users_list_by_domain_and_name_done(struct tevent_req *req); -+ - int ifp_users_list_by_domain_and_name(struct sbus_request *sbus_req, - void *data, - const char *domain, - const char *filter, - uint32_t limit) - { -+ struct tevent_req *req; -+ struct ifp_ctx *ctx; -+ struct ifp_list_ctx *list_ctx; -+ -+ ctx = talloc_get_type(data, struct ifp_ctx); -+ if (ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); -+ return ERR_INTERNAL; -+ } -+ -+ list_ctx = ifp_list_ctx_new(sbus_req, ctx, filter, limit); -+ if (list_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ req = cache_req_user_by_filter_send(list_ctx, ctx->rctx->ev, ctx->rctx, -+ domain, filter); -+ if (req == NULL) { -+ return ENOMEM; -+ } -+ tevent_req_set_callback(req, -+ ifp_users_list_by_domain_and_name_done, list_ctx); -+ - return EOK; - } - -+static void ifp_users_list_by_domain_and_name_done(struct tevent_req *req) -+{ -+ DBusError *error; -+ struct ifp_list_ctx *list_ctx; -+ struct sbus_request *sbus_req; -+ struct ldb_result *result; -+ struct sss_domain_info *domain; -+ errno_t ret; -+ size_t copy_count, i; -+ -+ list_ctx = tevent_req_callback_data(req, struct ifp_list_ctx); -+ sbus_req = list_ctx->sbus_req; -+ -+ ret = cache_req_user_by_name_recv(sbus_req, req, &result, &domain, NULL); -+ talloc_zfree(req); -+ if (ret == ENOENT) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND, -+ "User not found by filter"); -+ goto done; -+ } else if (ret != EOK) { -+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " -+ "users by filter [%d]: %s\n", ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ copy_count = ifp_list_ctx_remaining_capacity(list_ctx, result->count); -+ -+ for (i = 0; i < copy_count; i++) { -+ list_ctx->paths[i] = ifp_users_build_path_from_msg(list_ctx->paths, -+ list_ctx->dom, -+ result->msgs[i]); -+ if (list_ctx->paths[i] == NULL) { -+ error = sbus_error_new(sbus_req, SBUS_ERROR_INTERNAL, -+ "Failed to compose object path"); -+ goto done; -+ } -+ } -+ -+ list_ctx->path_count += copy_count; -+ -+done: -+ if (ret != EOK) { -+ sbus_request_fail_and_finish(sbus_req, error); -+ return; -+ } -+ -+ iface_ifp_users_ListByDomainAndName_finish(sbus_req, -+ list_ctx->paths, -+ list_ctx->path_count); -+ return; -+} -+ - static errno_t - ifp_users_user_get(struct sbus_request *sbus_req, - struct ifp_ctx *ifp_ctx, -diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c -index 631bcd266d7e06154dbf1f37f9f439119b2b8944..cdc411faa330dc2c063e52abe63cd68dbe16a5d9 100644 ---- a/src/responder/ifp/ifpsrv.c -+++ b/src/responder/ifp/ifpsrv.c -@@ -34,6 +34,7 @@ - #include - - #include "util/util.h" -+#include "util/strtonum.h" - #include "sbus/sssd_dbus.h" - #include "monitor/monitor_interfaces.h" - #include "confdb/confdb.h" -@@ -228,6 +229,7 @@ int ifp_process_init(TALLOC_CTX *mem_ctx, - int max_retries; - char *uid_str; - char *attr_list_str; -+ char *wildcard_limit_str; - - ifp_cmds = get_ifp_cmds(); - ret = sss_process_init(mem_ctx, ev, cdb, -@@ -321,6 +323,27 @@ int ifp_process_init(TALLOC_CTX *mem_ctx, - goto fail; - } - -+ /* A bit convoluted way until we have a confdb_get_uint32 */ -+ ret = confdb_get_string(ifp_ctx->rctx->cdb, -+ ifp_ctx->rctx, -+ CONFDB_IFP_CONF_ENTRY, -+ CONFDB_IFP_WILDCARD_LIMIT, -+ NULL, /* no limit by default */ -+ &wildcard_limit_str); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Failed to retrieve limit for a wildcard search\n"); -+ goto fail; -+ } -+ -+ if (wildcard_limit_str) { -+ ifp_ctx->wildcard_limit = strtouint32(wildcard_limit_str, NULL, 10); -+ if (errno != 0) { -+ ret = errno; -+ goto fail; -+ } -+ } -+ - for (iter = ifp_ctx->rctx->be_conns; iter; iter = iter->next) { - sbus_reconnect_init(iter->conn, max_retries, - ifp_dp_reconnect_init, iter); -diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c -index 674165ee4901115c9e17458a75fdb3536b6468c2..3b02fd06f5227e4ffc3d40ffb20fed981c5028a7 100644 ---- a/src/responder/ifp/ifpsrv_util.c -+++ b/src/responder/ifp/ifpsrv_util.c -@@ -21,6 +21,8 @@ - along with this program. If not, see . - */ - -+#include -+ - #include "db/sysdb.h" - #include "responder/ifp/ifp_private.h" - -@@ -269,3 +271,53 @@ ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr) - { - return ifp_attr_allowed(ifp_ctx->user_whitelist, attr); - } -+ -+static uint32_t ifp_list_limit(struct ifp_ctx *ctx, uint32_t limit) -+{ -+ if (ctx->wildcard_limit) { -+ return MIN(ctx->wildcard_limit, limit); -+ } else { -+ return limit; -+ } -+} -+ -+struct ifp_list_ctx *ifp_list_ctx_new(struct sbus_request *sbus_req, -+ struct ifp_ctx *ctx, -+ const char *filter, -+ uint32_t limit) -+{ -+ struct ifp_list_ctx *list_ctx; -+ -+ list_ctx = talloc_zero(sbus_req, struct ifp_list_ctx); -+ if (list_ctx == NULL) { -+ return NULL; -+ } -+ -+ list_ctx->sbus_req = sbus_req; -+ list_ctx->limit = ifp_list_limit(ctx, limit); -+ list_ctx->ctx = ctx; -+ list_ctx->dom = ctx->rctx->domains; -+ list_ctx->filter = filter; -+ list_ctx->paths = talloc_zero_array(list_ctx, const char *, limit); -+ if (list_ctx->paths == NULL) { -+ talloc_free(list_ctx); -+ return NULL; -+ } -+ -+ return list_ctx; -+} -+ -+size_t ifp_list_ctx_remaining_capacity(struct ifp_list_ctx *list_ctx, -+ size_t entries) -+{ -+ size_t capacity = list_ctx->limit - list_ctx->path_count; -+ -+ if (capacity < entries) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "IFP list request has limit of %"PRIu32" entries but back end " -+ "returned %zu entries\n", list_ctx->limit, entries); -+ return capacity; -+ } else { -+ return entries; -+ } -+} --- -2.4.3 - diff --git a/SOURCES/0012-TOOLS-Prevent-dereference-of-null-pointer.patch b/SOURCES/0012-TOOLS-Prevent-dereference-of-null-pointer.patch new file mode 100644 index 0000000..8ff9bfb --- /dev/null +++ b/SOURCES/0012-TOOLS-Prevent-dereference-of-null-pointer.patch @@ -0,0 +1,139 @@ +From be811502403246414b99f3a8834355c53f6f0511 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 6 Jun 2016 18:15:44 +0200 +Subject: [PATCH 12/14] TOOLS: Prevent dereference of null pointer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +VAR_CHECK is called with (var, EOK, ...) +EOK would be returned in case of "var != EOK" +and output argument _attrs would not be initialized. +Therefore there could be dereference of null pointer +after calling function usermod_build_attrs. + +Reviewed-by: Pavel Březina +(cherry picked from commit f9d3aec54d19a771a6eafe09ba6d445cc094bfae) +--- + src/tools/sss_sync_ops.c | 63 +++++++++++++++++++++--------------------------- + 1 file changed, 28 insertions(+), 35 deletions(-) + +diff --git a/src/tools/sss_sync_ops.c b/src/tools/sss_sync_ops.c +index 7f2e3ea85d5874e3c40f53f327b400e38e430228..a23a0b8c30366d2fb68554bfed184b8fce675e2b 100644 +--- a/src/tools/sss_sync_ops.c ++++ b/src/tools/sss_sync_ops.c +@@ -37,13 +37,6 @@ + #define ATTR_NAME_SEP '=' + #define ATTR_VAL_SEP ',' + +-#define VAR_CHECK(var, val, attr, msg) do { \ +- if (var != (val)) { \ +- DEBUG(SSSDBG_CRIT_FAILURE, msg" attribute: %s\n", attr); \ +- return val; \ +- } \ +-} while(0) +- + static int attr_name_val_split(TALLOC_CTX *mem_ctx, const char *nameval, + char **_name, char ***_values, int *_nvals) + { +@@ -200,8 +193,9 @@ static int usermod_build_attrs(TALLOC_CTX *mem_ctx, + int lock, + struct sysdb_attrs **_attrs) + { +- int ret; ++ int ret = EOK; + struct sysdb_attrs *attrs; ++ const char *attr_name = NULL; + + attrs = sysdb_new_attrs(mem_ctx); + if (attrs == NULL) { +@@ -209,60 +203,59 @@ static int usermod_build_attrs(TALLOC_CTX *mem_ctx, + } + + if (shell) { ++ attr_name = SYSDB_SHELL; + ret = sysdb_attrs_add_string(attrs, +- SYSDB_SHELL, ++ attr_name, + shell); +- VAR_CHECK(ret, EOK, SYSDB_SHELL, +- "Could not add attribute to changeset\n"); + } + +- if (home) { ++ if (ret == EOK && home) { ++ attr_name = SYSDB_HOMEDIR; + ret = sysdb_attrs_add_string(attrs, +- SYSDB_HOMEDIR, ++ attr_name, + home); +- VAR_CHECK(ret, EOK, SYSDB_HOMEDIR, +- "Could not add attribute to changeset\n"); + } + +- if (gecos) { ++ if (ret == EOK && gecos) { ++ attr_name = SYSDB_GECOS; + ret = sysdb_attrs_add_string(attrs, +- SYSDB_GECOS, ++ attr_name, + gecos); +- VAR_CHECK(ret, EOK, SYSDB_GECOS, +- "Could not add attribute to changeset\n"); + } + +- if (uid) { ++ if (ret == EOK && uid) { ++ attr_name = SYSDB_UIDNUM; + ret = sysdb_attrs_add_long(attrs, +- SYSDB_UIDNUM, ++ attr_name, + uid); +- VAR_CHECK(ret, EOK, SYSDB_UIDNUM, +- "Could not add attribute to changeset\n"); + } + +- if (gid) { ++ if (ret == EOK && gid) { ++ attr_name = SYSDB_GIDNUM; + ret = sysdb_attrs_add_long(attrs, +- SYSDB_GIDNUM, ++ attr_name, + gid); +- VAR_CHECK(ret, EOK, SYSDB_GIDNUM, +- "Could not add attribute to changeset\n"); + } + +- if (lock == DO_LOCK) { ++ if (ret == EOK && lock == DO_LOCK) { ++ attr_name = SYSDB_DISABLED; + ret = sysdb_attrs_add_string(attrs, +- SYSDB_DISABLED, ++ attr_name, + "true"); +- VAR_CHECK(ret, EOK, SYSDB_DISABLED, +- "Could not add attribute to changeset\n"); + } + +- if (lock == DO_UNLOCK) { ++ if (ret == EOK && lock == DO_UNLOCK) { ++ attr_name = SYSDB_DISABLED; + /* PAM code checks for 'false' value in SYSDB_DISABLED attribute */ + ret = sysdb_attrs_add_string(attrs, +- SYSDB_DISABLED, ++ attr_name, + "false"); +- VAR_CHECK(ret, EOK, SYSDB_DISABLED, +- "Could not add attribute to changeset\n"); ++ } ++ ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Could not add attribute [%s] to changeset.\n", attr_name); ++ return ret; + } + + *_attrs = attrs; +-- +2.4.11 + diff --git a/SOURCES/0013-KRB5-Return-right-data-provider-error-code.patch b/SOURCES/0013-KRB5-Return-right-data-provider-error-code.patch deleted file mode 100644 index 4d2aebf..0000000 --- a/SOURCES/0013-KRB5-Return-right-data-provider-error-code.patch +++ /dev/null @@ -1,32 +0,0 @@ -From aac1c3031aadce0682c4e3873634e405cdd41e69 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 14 Jul 2015 12:48:47 +0200 -Subject: [PATCH 13/13] KRB5: Return right data provider error code -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves: -https://fedorahosted.org/sssd/ticket/2719 - -Reviewed-by: Michal Židek ---- - src/providers/krb5/krb5_wait_queue.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/krb5/krb5_wait_queue.c b/src/providers/krb5/krb5_wait_queue.c -index 126209620dcd22889cf7bcb1cbec1890b8891b41..b4d3f903a94c9fdfffc975f1dfd10a27ab653a8d 100644 ---- a/src/providers/krb5/krb5_wait_queue.c -+++ b/src/providers/krb5/krb5_wait_queue.c -@@ -366,7 +366,7 @@ int krb5_auth_queue_recv(struct tevent_req *req, - } - - if (_dp_err) { -- *_dp_err = state->pam_status; -+ *_dp_err = state->dp_err; - } - - TEVENT_REQ_RETURN_ON_ERROR(req); --- -2.4.3 - diff --git a/SOURCES/0013-config-override_space-is-monitor-s-option.patch b/SOURCES/0013-config-override_space-is-monitor-s-option.patch new file mode 100644 index 0000000..f9d2ccd --- /dev/null +++ b/SOURCES/0013-config-override_space-is-monitor-s-option.patch @@ -0,0 +1,100 @@ +From 3904a70f86d793954822abc543783d57fb36c8ea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 11 Jul 2016 13:11:41 +0200 +Subject: [PATCH 13/14] config: override_space is monitor's option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We read override_space from [sssd] not +[nss] section. + +Resolves: +https://fedorahosted.org/sssd/ticket/3068 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit fc04d11c2fdde0bfe280c6030df2b1d6bf15ce63) +--- + src/config/SSSDConfig/__init__.py.in | 2 +- + src/config/SSSDConfigTest.py | 3 ++- + src/config/cfg_rules.ini | 2 +- + src/config/etc/sssd.api.conf | 2 +- + 4 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index 52af1386c7b6fc858b27d6f1d9197a7906519fc1..ebdd049e4df7ac2349293d6ce3802e7349098273 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -63,6 +63,7 @@ option_strings = { + 'default_domain_suffix' : _('Domain to add to names without a domain component.'), + 'user' : _('The user to drop privileges to'), + 'certificate_verification' : _('Tune certificate verification'), ++ 'override_space': _('All spaces in group or user names will be replaced with this character'), + + # [nss] + 'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'), +@@ -81,7 +82,6 @@ option_strings = { + 'shell_fallback' : _('If a shell stored in central directory is allowed but not available, use this fallback'), + 'default_shell': _('Shell to use if the provider does not list one'), + 'memcache_timeout': _('How long will be in-memory cache records valid'), +- 'override_space': _('All spaces in group or user names will be replaced with this character'), + + # [pam] + 'offline_credentials_expiration' : _('How long to allow cached logins between online logins (days)'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 6ec30234e24b7b48ccab6a98e1f9396990509190..5fa9bce8e6502c0ebf42671058c5e3d5de00ea0d 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -310,7 +310,8 @@ class SSSDConfigTestSSSDService(unittest.TestCase): + 'client_idle_timeout', + 'diag_cmd', + 'description', +- 'certificate_verification'] ++ 'certificate_verification', ++ 'override_space'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index d738ddf5ac5c220dbf2c3c99782368c684072e3f..ae4a9af2cdfd622e1234e26ae7285ff4e47889dc 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -38,6 +38,7 @@ option = krb5_rcache_dir + option = user + option = default_domain_suffix + option = certificate_verification ++option = override_space + + [rule/allowed_nss_options] + validator = ini_allowed_options +@@ -75,7 +76,6 @@ option = shell_fallback + option = default_shell + option = get_domains_timeout + option = memcache_timeout +-option = override_space + + [rule/allowed_pam_options] + validator = ini_allowed_options +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index 91146593d7fcda2930ff85e8ee3e889cc12af962..df6bdeb392b33a1437d790027054ee5e7b33e724 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -28,6 +28,7 @@ krb5_rcache_dir = str, None, false + user = str, None, false + default_domain_suffix = str, None, false + certificate_verification = str, None, false ++override_space = str, None, false + + [nss] + # Name service +@@ -49,7 +50,6 @@ shell_fallback = str, None, false + default_shell = str, None, false + get_domains_timeout = int, None, false + memcache_timeout = int, None, false +-override_space = str, None, false + + [pam] + # Authentication service +-- +2.4.11 + diff --git a/SOURCES/0014-config-Fix-user_attributes.patch b/SOURCES/0014-config-Fix-user_attributes.patch new file mode 100644 index 0000000..df2c8e3 --- /dev/null +++ b/SOURCES/0014-config-Fix-user_attributes.patch @@ -0,0 +1,77 @@ +From 08f1019768f6fa569eccf4892e3b5b57372b971d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 11 Jul 2016 13:23:40 +0200 +Subject: [PATCH 14/14] config: Fix user_attributes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes: +https://fedorahosted.org/sssd/ticket/3068 + +Option user_attributes is also available in +NSS responder, but not in PAC responder. + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 0a172552ec16f3b84d127399551cad786da8fd9d) +--- + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/cfg_rules.ini | 2 +- + src/config/etc/sssd.api.conf | 2 +- + 3 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index ebdd049e4df7ac2349293d6ce3802e7349098273..b5e078d0118a15c10b43fbe050176943ec90e0ee 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -82,6 +82,7 @@ option_strings = { + 'shell_fallback' : _('If a shell stored in central directory is allowed but not available, use this fallback'), + 'default_shell': _('Shell to use if the provider does not list one'), + 'memcache_timeout': _('How long will be in-memory cache records valid'), ++ 'user_attributes': _('List of user attributes the NSS responder is allowed to publish'), + + # [pam] + 'offline_credentials_expiration' : _('How long to allow cached logins between online logins (days)'), +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index ae4a9af2cdfd622e1234e26ae7285ff4e47889dc..85a15be3493cf4b8c5a612b0f66ae4c86d39b1ab 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -58,6 +58,7 @@ option = description + option = diag_cmd + + # Name service ++option = user_attributes + option = enum_cache_timeout + option = entry_cache_nowait_percentage + option = entry_negative_timeout +@@ -192,7 +193,6 @@ option = diag_cmd + + # PAC responder + option = allowed_uids +-option = user_attributes + option = pac_lifetime + + [rule/allowed_ifp_options] +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index df6bdeb392b33a1437d790027054ee5e7b33e724..2d7c5049f5e5bf9df6e5445ee6e5c62211bf1c45 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -50,6 +50,7 @@ shell_fallback = str, None, false + default_shell = str, None, false + get_domains_timeout = int, None, false + memcache_timeout = int, None, false ++user_attributes = str, None, false + + [pam] + # Authentication service +@@ -86,7 +87,6 @@ ca_db = str, None, false + [pac] + # PAC responder + allowed_uids = str, None, false +-user_attributes = str, None, false + pac_lifetime = int, None, false + + [ifp] +-- +2.4.11 + diff --git a/SOURCES/0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch b/SOURCES/0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch deleted file mode 100644 index 936f1f5..0000000 --- a/SOURCES/0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch +++ /dev/null @@ -1,183 +0,0 @@ -From f9f227bb5a7fe6e5af83debbbd892bdb4e13894d Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 14 Jul 2015 14:41:34 +0200 -Subject: [PATCH 14/14] nss_check_name_of_well_known_sid() improve name - splitting -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Currently in the default configuration -nss_check_name_of_well_known_sid() can only split fully-qualified names -in the user@domain.name style. DOM\user style names will cause an error -and terminate the whole request. - -With this patch both styles can be handled by default, additionally if -the name could not be split nss_check_name_of_well_known_sid() returns -ENOENT which can be handled more gracefully by the caller. - -Resolves https://fedorahosted.org/sssd/ticket/2717 - -Reviewed-by: Lukáš Slebodník ---- - src/responder/nss/nsssrv_cmd.c | 8 ++++ - src/tests/cmocka/test_nss_srv.c | 90 ++++++++++++++++++++++++----------------- - src/util/usertools.c | 3 +- - 3 files changed, 61 insertions(+), 40 deletions(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index 0129467302f16af318bbbb0a5be47ff2e235da65..b3998015fa621cad8e06a126a674f94d26158dda 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -1255,6 +1255,14 @@ static int nss_check_name_of_well_known_sid(struct nss_cmd_ctx *cmdctx, - return ret; - } - -+ if (wk_dom_name == NULL || wk_name == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Unable to split [%s] in name and domain part. " \ -+ "Skipping check for well-known name.\n", full_name); -+ -+ return ENOENT; -+ } -+ - ret = name_to_well_known_sid(wk_dom_name, wk_name, &wk_sid); - talloc_free(wk_dom_name); - talloc_free(wk_name); -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index 3ab8d39c44a8bb8cacae20f534dcbeb6ca7dec08..84d3413be70bc0af433b7fd23cf7d78b4b9298f1 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -1734,63 +1734,77 @@ void test_nss_well_known_getidbysid_failure(void **state) - void test_nss_well_known_getsidbyname(void **state) - { - errno_t ret; -+ const char *names[] = { "Cryptographic Operators@BUILTIN", -+ "BUILTIN\\Cryptographic Operators", NULL}; -+ size_t c; - -- will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER); -- will_return(__wrap_sss_packet_get_body, "Cryptographic Operators@BUILTIN"); -- will_return(__wrap_sss_packet_get_body, 0); -- will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); -- will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -- will_return(test_nss_well_known_sid_check, "S-1-5-32-569"); -+ for (c = 0; names[c] != NULL; c++) { -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER); -+ will_return(__wrap_sss_packet_get_body, names[c]); -+ will_return(__wrap_sss_packet_get_body, 0); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ will_return(test_nss_well_known_sid_check, "S-1-5-32-569"); - -- set_cmd_cb(test_nss_well_known_sid_check); -- ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, -- nss_test_ctx->nss_cmds); -- assert_int_equal(ret, EOK); -+ set_cmd_cb(test_nss_well_known_sid_check); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); - -- /* Wait until the test finishes with EOK */ -- ret = test_ev_loop(nss_test_ctx->tctx); -- assert_int_equal(ret, EOK); -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+ } - } - - void test_nss_well_known_getsidbyname_nonexisting(void **state) - { - errno_t ret; -+ const char *names[] = { "Abc@BUILTIN", "BUILTIN\\Abc", NULL }; -+ size_t c; - -- will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER); -- will_return(__wrap_sss_packet_get_body, "Abc@BUILTIN"); -- will_return(__wrap_sss_packet_get_body, 0); -- will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); -- will_return(test_nss_well_known_sid_check, NULL); -+ for (c = 0; names[c] != NULL; c++) { -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER); -+ will_return(__wrap_sss_packet_get_body, names[c]); -+ will_return(__wrap_sss_packet_get_body, 0); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); -+ will_return(test_nss_well_known_sid_check, NULL); - -- set_cmd_cb(test_nss_well_known_sid_check); -- ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, -- nss_test_ctx->nss_cmds); -- assert_int_equal(ret, EOK); -+ set_cmd_cb(test_nss_well_known_sid_check); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); - -- /* Wait until the test finishes with EOK */ -- ret = test_ev_loop(nss_test_ctx->tctx); -- assert_int_equal(ret, EOK); -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+ } - } - - void test_nss_well_known_getsidbyname_special(void **state) - { - errno_t ret; -+ const char *names[] = { "CREATOR OWNER@CREATOR AUTHORITY", -+ "CREATOR AUTHORITY\\CREATOR OWNER", NULL }; -+ size_t c; - -- will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER); -- will_return(__wrap_sss_packet_get_body, "CREATOR OWNER@CREATOR AUTHORITY"); -- will_return(__wrap_sss_packet_get_body, 0); -- will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); -- will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -- will_return(test_nss_well_known_sid_check, "S-1-3-0"); -+ for (c = 0; names[c] != NULL; c++) { -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER); -+ will_return(__wrap_sss_packet_get_body, names[c]); -+ will_return(__wrap_sss_packet_get_body, 0); -+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ will_return(test_nss_well_known_sid_check, "S-1-3-0"); - -- set_cmd_cb(test_nss_well_known_sid_check); -- ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, -- nss_test_ctx->nss_cmds); -- assert_int_equal(ret, EOK); -+ set_cmd_cb(test_nss_well_known_sid_check); -+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, -+ nss_test_ctx->nss_cmds); -+ assert_int_equal(ret, EOK); - -- /* Wait until the test finishes with EOK */ -- ret = test_ev_loop(nss_test_ctx->tctx); -- assert_int_equal(ret, EOK); -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(nss_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+ } - } - - static int test_nss_getorigbyname_check(uint32_t status, uint8_t *body, -diff --git a/src/util/usertools.c b/src/util/usertools.c -index c43d420e31c6c690628ef6179d932eaf99826fee..87a8d7411312c3a80c32374a1fd93bbf0e767a91 100644 ---- a/src/util/usertools.c -+++ b/src/util/usertools.c -@@ -249,8 +249,7 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, - } - - if (!re_pattern) { -- re_pattern = talloc_strdup(tmpctx, -- "(?P[^@]+)@?(?P[^@]*$)"); -+ re_pattern = talloc_strdup(tmpctx, IPA_AD_DEFAULT_RE); - if (!re_pattern) { - ret = ENOMEM; - goto done; --- -2.4.3 - diff --git a/SOURCES/0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch b/SOURCES/0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch deleted file mode 100644 index 21b708e..0000000 --- a/SOURCES/0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch +++ /dev/null @@ -1,98 +0,0 @@ -From c7c762dc50c48cfa43551a3936dd46405e9d33ce Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 8 Jul 2015 09:01:24 -0400 -Subject: [PATCH 15/19] DYNDNS: sss_iface_addr_list_get return ENOENT - -If none of eligible interfaces matches ifname then ENOENT is returned. - -Resolves: -https://fedorahosted.org/sssd/ticket/2549 ---- - src/providers/dp_dyndns.c | 13 +++++++++++-- - src/providers/ldap/sdap_dyndns.c | 6 +++++- - src/tests/cmocka/test_dyndns.c | 20 ++++++++++++++++++++ - 3 files changed, 36 insertions(+), 3 deletions(-) - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 1cac3d0fae2454cea823ed640a4325f27580353f..2ac43a108ff6197d9e2662198a6da976ca348e76 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -222,8 +222,17 @@ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname, - } - } - -- ret = EOK; -- *_addrlist = addrlist; -+ if (addrlist != NULL) { -+ /* OK, some result was found */ -+ ret = EOK; -+ *_addrlist = addrlist; -+ } else { -+ /* No result was found */ -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "No IPs usable for DNS was found for interface: %s.\n", ifname); -+ ret = ENOENT; -+ } -+ - done: - freeifaddrs(ifaces); - return ret; -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index 0d9c9205792062378aa25aad6ac706058001433a..e99a4f6687035928f6775c38b9df6b2a06d38f38 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -502,8 +502,12 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx, - if (iface) { - ret = sss_iface_addr_list_get(state, iface, &state->addresses); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -+ DEBUG(ret == ENOENT ? SSSDBG_MINOR_FAILURE : SSSDBG_OP_FAILURE, - "Cannot get list of addresses from interface %s\n", iface); -+ /* non critical failure */ -+ if (ret == ENOENT) { -+ ret = EOK; -+ } - } - /* We're done. Just fake an async request completion */ - goto done; -diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c -index 689e333d4e68c4a2582894d06b8b7b20c76b9be8..3214e90c063ea9a4cf6f6bc6507bf4e37b7d23a4 100644 ---- a/src/tests/cmocka/test_dyndns.c -+++ b/src/tests/cmocka/test_dyndns.c -@@ -247,6 +247,23 @@ void dyndns_test_get_multi_ifaddr(void **state) - assert_true(check_leaks_pop(dyndns_test_ctx) == true); - } - -+void dyndns_test_get_ifaddr_enoent(void **state) -+{ -+ errno_t ret; -+ struct sss_iface_addr *addrlist = NULL; -+ -+ check_leaks_push(dyndns_test_ctx); -+ will_return_getifaddrs("eth0", "192.168.0.1"); -+ will_return_getifaddrs("eth1", "192.168.0.2"); -+ will_return_getifaddrs(NULL, NULL); /* sentinel */ -+ ret = sss_iface_addr_list_get(dyndns_test_ctx, "non_existing_interface", -+ &addrlist); -+ assert_int_equal(ret, ENOENT); -+ talloc_free(addrlist); -+ -+ assert_true(check_leaks_pop(dyndns_test_ctx) == true); -+} -+ - void dyndns_test_ok(void **state) - { - struct tevent_req *req; -@@ -460,6 +477,9 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(dyndns_test_get_multi_ifaddr, - dyndns_test_simple_setup, - dyndns_test_teardown), -+ cmocka_unit_test_setup_teardown(dyndns_test_get_ifaddr_enoent, -+ dyndns_test_simple_setup, -+ dyndns_test_teardown), - - /* Dynamic DNS update unit tests*/ - cmocka_unit_test_setup_teardown(dyndns_test_ok, --- -2.4.3 - diff --git a/SOURCES/0015-sysdb-tests-Fix-cast-from-pointer-to-integer.patch b/SOURCES/0015-sysdb-tests-Fix-cast-from-pointer-to-integer.patch new file mode 100644 index 0000000..47af5b0 --- /dev/null +++ b/SOURCES/0015-sysdb-tests-Fix-cast-from-pointer-to-integer.patch @@ -0,0 +1,42 @@ +From 7b8c9b01882788d5112b0a529bf74163805889d3 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 8 Jul 2016 13:37:10 +0200 +Subject: [PATCH 15/18] sysdb-tests: Fix cast from pointer to integer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +src/tests/sysdb-tests.c: In function 'test_sysdb_memberof_close_loop': +src/tests/sysdb-tests.c:2740:5: warning: passing argument + 1 of '_ck_assert_msg' makes integer from pointer without a cast + [enabled by default] + fail_unless(data->attrlist[0], "talloc_array failed."); + ^ +In file included from src/tests/sysdb-tests.c:23:0: +/usr/include/check.h:237:16: note: expected 'int' but argument + is of type 'const char *' + void CK_EXPORT _ck_assert_msg (int result, const char *file, + ^ +Reviewed-by: Pavel Březina + +(cherry picked from commit 2bb9e88328ef44eddd935c250ae12337442c5900) +--- + src/tests/sysdb-tests.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c +index 429aa39538901fe387e41eebb27662d7b958142c..bac8a8788b4fde0d6039121efead6fc20fa046f9 100644 +--- a/src/tests/sysdb-tests.c ++++ b/src/tests/sysdb-tests.c +@@ -2737,7 +2737,7 @@ START_TEST (test_sysdb_memberof_close_loop) + fail_unless(data->attrlist != NULL, "talloc_array failed."); + data->attrlist[0] = test_asprintf_fqname(data, test_ctx->domain, + "testgroup%d", data->gid + 9); +- fail_unless(data->attrlist[0], "talloc_array failed."); ++ fail_unless(data->attrlist[0] != NULL, "talloc_array failed."); + data->attrlist[1] = NULL; + + ret = test_memberof_store_group(data); +-- +2.4.11 + diff --git a/SOURCES/0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch b/SOURCES/0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch deleted file mode 100644 index abf0e7f..0000000 --- a/SOURCES/0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch +++ /dev/null @@ -1,194 +0,0 @@ -From e1936ccbb810965e90d030c2ed8f420c084b6a22 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 8 Jul 2015 09:08:03 -0400 -Subject: [PATCH 16/19] DYNDNS: support mult. interfaces for dyndns_iface opt - -Resolves: -https://fedorahosted.org/sssd/ticket/2549 ---- - src/man/sssd-ad.5.xml | 11 +++--- - src/man/sssd-ipa.5.xml | 10 ++++-- - src/providers/dp_dyndns.c | 6 ++++ - src/providers/dp_dyndns.h | 4 +++ - src/providers/ldap/sdap_dyndns.c | 72 +++++++++++++++++++++++++++++++++++----- - 5 files changed, 87 insertions(+), 16 deletions(-) - -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index 938a443e027b9bf83c75c240a7d6b2a0876b92c8..ff43ea37066514a87934d07b141e680416dcc05b 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -754,15 +754,16 @@ ad_gpo_map_deny = +my_pam_service - - - Optional. Applicable only when dyndns_update -- is true. Choose the interface whose IP address -- should be used for dynamic DNS updates. -- -- -- NOTE: This option currently supports only one interface. -+ is true. Choose the interface or a list of interfaces -+ whose IP addresses should be used for dynamic DNS -+ updates. - - - Default: Use the IP address of the AD LDAP connection - -+ -+ Example: dyndns_iface = em1, vnet1, vnet2 -+ - - - -diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml -index 0716b6235f93965170983856b930799bfded6258..d450c2fadbb1713096ff766bf536702195cfd137 100644 ---- a/src/man/sssd-ipa.5.xml -+++ b/src/man/sssd-ipa.5.xml -@@ -166,11 +166,12 @@ - - - Optional. Applicable only when dyndns_update -- is true. Choose the interface whose IP address -- should be used for dynamic DNS updates. -+ is true. Choose the interface or a list of interfaces -+ whose IP addresses should be used for dynamic DNS -+ updates. - - -- NOTE: This option currently supports only one interface. -+ NOTE: This option currently supports multiple interfaces. - - - NOTE: While it is still possible to use the old -@@ -181,6 +182,9 @@ - - Default: Use the IP address of the IPA LDAP connection - -+ -+ Example: dyndns_iface = em1, vnet1, vnet2 -+ - - - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 2ac43a108ff6197d9e2662198a6da976ca348e76..76562840ef1d427629e41617b871caaedab779d4 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -49,6 +49,12 @@ struct sss_iface_addr { - struct sockaddr_storage *addr; - }; - -+void sss_iface_addr_concatenate(struct sss_iface_addr **list, -+ struct sss_iface_addr *list2) -+{ -+ DLIST_CONCATENATE((*list), list2, struct sss_iface_addr*); -+} -+ - struct sss_iface_addr * - sss_iface_addr_add(TALLOC_CTX *mem_ctx, struct sss_iface_addr **list, - struct sockaddr_storage *ss) -diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h -index 23b833dace58a0ecbb1e2e21963a55186f1d06a8..deba112538ad22cd7f59be07934778ee9d4361e7 100644 ---- a/src/providers/dp_dyndns.h -+++ b/src/providers/dp_dyndns.h -@@ -128,4 +128,8 @@ nsupdate_get_addrs_recv(struct tevent_req *req, - struct sss_iface_addr **_addrlist, - size_t *_count); - -+void -+sss_iface_addr_concatenate(struct sss_iface_addr **list, -+ struct sss_iface_addr *list2); -+ - #endif /* DP_DYNDNS_H_ */ -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index e99a4f6687035928f6775c38b9df6b2a06d38f38..f5929cff3db6f724efcedeb963e3a12d04f6e1d3 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -482,6 +482,65 @@ static void sdap_dyndns_get_addrs_done(struct tevent_req *subreq); - static errno_t sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state, - struct sdap_handle *sh); - -+static errno_t get_ifaces_addrs(TALLOC_CTX *mem_ctx, -+ const char *iface, -+ struct sss_iface_addr **_result) -+{ -+ struct sss_iface_addr *result_addrs = NULL; -+ struct sss_iface_addr *intf_addrs; -+ TALLOC_CTX *tmp_ctx; -+ char **list_of_intfs; -+ int num_of_intfs; -+ errno_t ret; -+ int i; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = split_on_separator(tmp_ctx, iface, ',', true, true, &list_of_intfs, -+ &num_of_intfs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Parsing names of interfaces failed - %d:[%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ for (i = 0; i < num_of_intfs; i++) { -+ ret = sss_iface_addr_list_get(tmp_ctx, list_of_intfs[i], &intf_addrs); -+ if (ret == EOK) { -+ if (result_addrs != NULL) { -+ /* If there is already an existing list, head of this existing -+ * list will be considered as parent talloc context for the -+ * new list. -+ */ -+ talloc_steal(result_addrs, intf_addrs); -+ } -+ sss_iface_addr_concatenate(&result_addrs, intf_addrs); -+ } else if (ret == ENOENT) { -+ /* non-critical failure */ -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Cannot get interface %s or there are no addresses " -+ "bind to it.\n", list_of_intfs[i]); -+ } else { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot get list of addresses from interface %s - %d:[%s]\n", -+ list_of_intfs[i], ret, sss_strerror(ret)); -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+ *_result = talloc_steal(mem_ctx, result_addrs); -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ - static struct tevent_req * - sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, -@@ -500,14 +559,11 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx, - } - - if (iface) { -- ret = sss_iface_addr_list_get(state, iface, &state->addresses); -- if (ret != EOK) { -- DEBUG(ret == ENOENT ? SSSDBG_MINOR_FAILURE : SSSDBG_OP_FAILURE, -- "Cannot get list of addresses from interface %s\n", iface); -- /* non critical failure */ -- if (ret == ENOENT) { -- ret = EOK; -- } -+ ret = get_ifaces_addrs(state, iface, &state->addresses); -+ if (ret != EOK || state->addresses == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "get_ifaces_addrs() failed: %d:[%s]\n", -+ ret, sss_strerror(ret)); - } - /* We're done. Just fake an async request completion */ - goto done; --- -2.4.3 - diff --git a/SOURCES/0016-PROVIDERS-Setting-right-u-g-id-if-unprivileged.patch b/SOURCES/0016-PROVIDERS-Setting-right-u-g-id-if-unprivileged.patch new file mode 100644 index 0000000..cdc951f --- /dev/null +++ b/SOURCES/0016-PROVIDERS-Setting-right-u-g-id-if-unprivileged.patch @@ -0,0 +1,41 @@ +From 0686ce29cadb7875638d5f782199ea4bb186dee3 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 12 Jul 2016 16:14:04 +0200 +Subject: [PATCH 16/18] PROVIDERS: Setting right {u,g}id if unprivileged +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +be_ctx had talloc_zero() initialized uid and gid which was used +in function dp_init(). Therefore back-end was every time started as root +and therefore non-root responders could not communicate with back-end +due to wrong permission of unix sockets. + +This patch sets right uid and gid to data-providers if sssd runs +as non-root user. + +Resolves: +https://fedorahosted.org/sssd/ticket/3077 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 75dead699a19dda7d8dfca89e2f97efbf0c264a2) +--- + src/providers/data_provider_be.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c +index 78efed851b2bf053ba890caa05e655431996892a..2ae713054429e789c1ba79c1f5e7a3889af3b291 100644 +--- a/src/providers/data_provider_be.c ++++ b/src/providers/data_provider_be.c +@@ -386,6 +386,8 @@ errno_t be_process_init(TALLOC_CTX *mem_ctx, + + be_ctx->ev = ev; + be_ctx->cdb = cdb; ++ be_ctx->uid = uid; ++ be_ctx->gid = gid; + be_ctx->identity = talloc_asprintf(be_ctx, "%%BE_%s", be_domain); + be_ctx->conf_path = talloc_asprintf(be_ctx, CONFDB_DOMAIN_PATH_TMPL, be_domain); + if (be_ctx->identity == NULL || be_ctx->conf_path == NULL) { +-- +2.4.11 + diff --git a/SOURCES/0017-DYNDNS-special-value-for-dyndns_iface-option.patch b/SOURCES/0017-DYNDNS-special-value-for-dyndns_iface-option.patch deleted file mode 100644 index c7f7abc..0000000 --- a/SOURCES/0017-DYNDNS-special-value-for-dyndns_iface-option.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 65976fe3f9db1fc9581bb00060be38c48512b672 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Tue, 14 Jul 2015 04:21:34 -0400 -Subject: [PATCH 17/19] DYNDNS: special value '*' for dyndns_iface option - -Option dyndns_iface has now special value '*' which implies that IPs -from add interfaces should be sent during DDNS update. ---- - src/man/sssd-ad.5.xml | 6 ++++-- - src/man/sssd-ipa.5.xml | 9 ++++----- - src/providers/dp_dyndns.c | 20 ++++++++++++++++---- - 3 files changed, 24 insertions(+), 11 deletions(-) - -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index ff43ea37066514a87934d07b141e680416dcc05b..3cbc10520098372d984d00425d03832d002d6672 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -756,10 +756,12 @@ ad_gpo_map_deny = +my_pam_service - Optional. Applicable only when dyndns_update - is true. Choose the interface or a list of interfaces - whose IP addresses should be used for dynamic DNS -- updates. -+ updates. Special value * implies that -+ IPs from all interfaces should be used. - - -- Default: Use the IP address of the AD LDAP connection -+ Default: Use the IP addresses of the interface which -+ is used for AD LDAP connection - - - Example: dyndns_iface = em1, vnet1, vnet2 -diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml -index d450c2fadbb1713096ff766bf536702195cfd137..2e985991fde10827aff0e7c8e67f29a009683450 100644 ---- a/src/man/sssd-ipa.5.xml -+++ b/src/man/sssd-ipa.5.xml -@@ -168,10 +168,8 @@ - Optional. Applicable only when dyndns_update - is true. Choose the interface or a list of interfaces - whose IP addresses should be used for dynamic DNS -- updates. -- -- -- NOTE: This option currently supports multiple interfaces. -+ updates. Special value * implies that -+ IPs from all interfaces should be used. - - - NOTE: While it is still possible to use the old -@@ -180,7 +178,8 @@ - in their config file. - - -- Default: Use the IP address of the IPA LDAP connection -+ Default: Use the IP addresses of the interface which -+ is used for IPA LDAP connection - - - Example: dyndns_iface = em1, vnet1, vnet2 -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 76562840ef1d427629e41617b871caaedab779d4..03389acfba13e566540ca8b0570c0d009173575f 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -42,6 +42,9 @@ - #define DYNDNS_TIMEOUT 15 - #endif /* DYNDNS_TIMEOUT */ - -+/* MASK represents special value for matching all interfaces */ -+#define MASK "*" -+ - struct sss_iface_addr { - struct sss_iface_addr *next; - struct sss_iface_addr *prev; -@@ -171,6 +174,16 @@ ok_for_dns(struct sockaddr *sa) - return true; - } - -+static bool supported_address_family(sa_family_t sa_family) -+{ -+ return sa_family == AF_INET || sa_family == AF_INET6; -+} -+ -+static bool matching_name(const char *ifname, const char *ifname2) -+{ -+ return (strcmp(MASK, ifname) == 0) || (strcasecmp(ifname, ifname2) == 0); -+} -+ - /* Collect IP addresses associated with an interface */ - errno_t - sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname, -@@ -200,10 +213,9 @@ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname, - if (!ifa->ifa_addr) continue; - - /* Add IP addresses to the list */ -- if ((ifa->ifa_addr->sa_family == AF_INET || -- ifa->ifa_addr->sa_family == AF_INET6) && -- strcasecmp(ifa->ifa_name, ifname) == 0 && -- ok_for_dns(ifa->ifa_addr)) { -+ if (supported_address_family(ifa->ifa_addr->sa_family) -+ && matching_name(ifname, ifa->ifa_name) -+ && ok_for_dns(ifa->ifa_addr)) { - - /* Add this address to the IP address list */ - address = talloc_zero(mem_ctx, struct sss_iface_addr); --- -2.4.3 - diff --git a/SOURCES/0017-config-Allow-timeout-for-all-sevices.patch b/SOURCES/0017-config-Allow-timeout-for-all-sevices.patch new file mode 100644 index 0000000..fae8cf5 --- /dev/null +++ b/SOURCES/0017-config-Allow-timeout-for-all-sevices.patch @@ -0,0 +1,117 @@ +From 18b2f16e2b086509cafb453943387fff2d1b0d19 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 11 Jul 2016 13:03:28 +0200 +Subject: [PATCH 17/18] config: Allow timeout for all sevices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Allow option "timeout" for all sevices. +Also remove unused macro CONFDB_SERVICE_TIMEOUT. + +Resolves: +https://fedorahosted.org/sssd/ticket/3068 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 1b9b5477027d86a2afb2e72981253d108c5398da) +--- + src/confdb/confdb.h | 1 - + src/config/cfg_rules.ini | 7 +++++++ + src/config/etc/sssd.api.conf | 2 +- + 3 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index 54b1cbc82546a76013c35c6cd3b1924663e9bb23..cc8f66f02eb5ac10ced826326f80bbf5eda82ee1 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -58,7 +58,6 @@ + #define CONFDB_SERVICE_DEBUG_TIMESTAMPS "debug_timestamps" + #define CONFDB_SERVICE_DEBUG_MICROSECONDS "debug_microseconds" + #define CONFDB_SERVICE_DEBUG_TO_FILES "debug_to_files" +-#define CONFDB_SERVICE_TIMEOUT "timeout" + #define CONFDB_SERVICE_FORCE_TIMEOUT "force_timeout" + #define CONFDB_SERVICE_RECON_RETRIES "reconnection_retries" + #define CONFDB_SERVICE_FD_LIMIT "fd_limit" +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index 85a15be3493cf4b8c5a612b0f66ae4c86d39b1ab..5c8d05a817331dd23fd7e349719bd4b44a5bdd02 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -44,6 +44,7 @@ option = override_space + validator = ini_allowed_options + section_re = ^nss$ + ++option = timeout + option = debug + option = debug_level + option = debug_timestamps +@@ -82,6 +83,7 @@ option = memcache_timeout + validator = ini_allowed_options + section_re = ^pam$ + ++option = timeout + option = debug + option = debug_level + option = debug_timestamps +@@ -115,6 +117,7 @@ option = p11_child_timeout + validator = ini_allowed_options + section_re = ^sudo$ + ++option = timeout + option = debug + option = debug_level + option = debug_timestamps +@@ -136,6 +139,7 @@ option = sudo_inverse_order + validator = ini_allowed_options + section_re = ^autofs$ + ++option = timeout + option = debug + option = debug_level + option = debug_timestamps +@@ -156,6 +160,7 @@ option = autofs_negative_timeout + validator = ini_allowed_options + section_re = ^ssh$ + ++option = timeout + option = debug + option = debug_level + option = debug_timestamps +@@ -178,6 +183,7 @@ option = ca_db + validator = ini_allowed_options + section_re = ^pac$ + ++option = timeout + option = debug + option = debug_level + option = debug_timestamps +@@ -199,6 +205,7 @@ option = pac_lifetime + validator = ini_allowed_options + section_re = ^ifp$ + ++option = timeout + option = debug + option = debug_level + option = debug_timestamps +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index 2d7c5049f5e5bf9df6e5445ee6e5c62211bf1c45..e4011a384cdb3fb3bce93494cbb278ec2622ee40 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -3,6 +3,7 @@ + + [service] + # Options available to all services ++timeout = int, None, false + debug = int, None, false + debug_level = int, None, false + debug_timestamps = bool, None, false +@@ -20,7 +21,6 @@ diag_cmd = str, None, false + # Monitor service + services = list, str, true, nss, pam + domains = list, str, true +-timeout = int, None, false + sbus_timeout = int, None, false + re_expression = str, None, false + full_name_format = str, None, false +-- +2.4.11 + diff --git a/SOURCES/0018-TESTS-dyndns-tests-support-AAAA-addresses.patch b/SOURCES/0018-TESTS-dyndns-tests-support-AAAA-addresses.patch deleted file mode 100644 index aa8f434..0000000 --- a/SOURCES/0018-TESTS-dyndns-tests-support-AAAA-addresses.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 73047b51048037689b21925f7d480ffd72a50485 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Wed, 15 Jul 2015 10:58:38 -0400 -Subject: [PATCH 18/19] TESTS: dyndns tests support AAAA addresses - -Resolves: -https://fedorahosted.org/sssd/ticket/2558 ---- - src/tests/cmocka/test_dyndns.c | 51 +++++++++++++++++++++++++++++++----------- - 1 file changed, 38 insertions(+), 13 deletions(-) - -diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c -index 3214e90c063ea9a4cf6f6bc6507bf4e37b7d23a4..e9d42cea37472b38ae2eb900368f2ce3f409fefc 100644 ---- a/src/tests/cmocka/test_dyndns.c -+++ b/src/tests/cmocka/test_dyndns.c -@@ -97,7 +97,9 @@ int __wrap_getifaddrs(struct ifaddrs **_ifap) - struct ifaddrs *ifap_head = NULL; - char *name; - char *straddr; -+ int ad_family; - struct sockaddr_in *sa; -+ void *dst; - - while ((name = sss_mock_ptr_type(char *)) != NULL) { - straddr = sss_mock_ptr_type(char *); -@@ -105,6 +107,7 @@ int __wrap_getifaddrs(struct ifaddrs **_ifap) - errno = EINVAL; - goto fail; - } -+ ad_family = sss_mock_type(int); - - ifap = talloc_zero(global_mock_context, struct ifaddrs); - if (ifap == NULL) { -@@ -127,15 +130,33 @@ int __wrap_getifaddrs(struct ifaddrs **_ifap) - - /* Do not alocate directly on ifap->ifa_addr to - * avoid alignment warnings */ -- sa = talloc(ifap, struct sockaddr_in); -+ if (ad_family == AF_INET) { -+ sa = talloc(ifap, struct sockaddr_in); -+ } else if (ad_family == AF_INET6) { -+ sa = (struct sockaddr_in *) talloc(ifap, struct sockaddr_in6); -+ } else { -+ errno = EINVAL; -+ goto fail; -+ } -+ - if (sa == NULL) { - errno = ENOMEM; - goto fail; - } -- sa->sin_family = AF_INET; -+ -+ sa->sin_family = ad_family; -+ -+ if (ad_family == AF_INET) { -+ dst = &sa->sin_addr; -+ } else if (ad_family == AF_INET6) { -+ dst = &((struct sockaddr_in6 *)sa)->sin6_addr; -+ } else { -+ errno = EINVAL; -+ goto fail; -+ } - - /* convert straddr into ifa_addr */ -- if (inet_pton(AF_INET, straddr, &sa->sin_addr) != 1) { -+ if (inet_pton(ad_family, straddr, dst) != 1) { - goto fail; - } - -@@ -167,12 +188,16 @@ static void dyndns_test_done(struct tevent_req *req) - ctx->tctx->done = true; - } - --void will_return_getifaddrs(const char *ifname, const char *straddr) -+void will_return_getifaddrs(const char *ifname, const char *straddr, -+ int af_family) - { - will_return(__wrap_getifaddrs, ifname); - if (ifname) { - will_return(__wrap_getifaddrs, straddr); - } -+ if (straddr) { -+ will_return(__wrap_getifaddrs, af_family); -+ } - } - - void dyndns_test_get_ifaddr(void **state) -@@ -182,9 +207,9 @@ void dyndns_test_get_ifaddr(void **state) - char straddr[128]; - - check_leaks_push(dyndns_test_ctx); -- will_return_getifaddrs("eth0", "192.168.0.1"); -- will_return_getifaddrs("eth1", "192.168.0.2"); -- will_return_getifaddrs(NULL, NULL); /* sentinel */ -+ will_return_getifaddrs("eth0", "192.168.0.1", AF_INET); -+ will_return_getifaddrs("eth1", "192.168.0.2", AF_INET); -+ will_return_getifaddrs(NULL, NULL, 0); /* sentinel */ - ret = sss_iface_addr_list_get(dyndns_test_ctx, "eth0", &addrlist); - assert_int_equal(ret, EOK); - -@@ -212,9 +237,9 @@ void dyndns_test_get_multi_ifaddr(void **state) - char straddr[128]; - - check_leaks_push(dyndns_test_ctx); -- will_return_getifaddrs("eth0", "192.168.0.2"); -- will_return_getifaddrs("eth0", "192.168.0.1"); -- will_return_getifaddrs(NULL, NULL); /* sentinel */ -+ will_return_getifaddrs("eth0", "192.168.0.2", AF_INET); -+ will_return_getifaddrs("eth0", "192.168.0.1", AF_INET); -+ will_return_getifaddrs(NULL, NULL, 0); /* sentinel */ - ret = sss_iface_addr_list_get(dyndns_test_ctx, "eth0", &addrlist); - assert_int_equal(ret, EOK); - -@@ -253,9 +278,9 @@ void dyndns_test_get_ifaddr_enoent(void **state) - struct sss_iface_addr *addrlist = NULL; - - check_leaks_push(dyndns_test_ctx); -- will_return_getifaddrs("eth0", "192.168.0.1"); -- will_return_getifaddrs("eth1", "192.168.0.2"); -- will_return_getifaddrs(NULL, NULL); /* sentinel */ -+ will_return_getifaddrs("eth0", "192.168.0.1", AF_INET); -+ will_return_getifaddrs("eth1", "192.168.0.2", AF_INET); -+ will_return_getifaddrs(NULL, NULL, 0); /* sentinel */ - ret = sss_iface_addr_list_get(dyndns_test_ctx, "non_existing_interface", - &addrlist); - assert_int_equal(ret, ENOENT); --- -2.4.3 - diff --git a/SOURCES/0018-config-Add-config_file_version-to-schema.patch b/SOURCES/0018-config-Add-config_file_version-to-schema.patch new file mode 100644 index 0000000..3d47710 --- /dev/null +++ b/SOURCES/0018-config-Add-config_file_version-to-schema.patch @@ -0,0 +1,58 @@ +From 5e8d4f0107c5e6f1836740945b610a54c216bd7f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 11 Jul 2016 13:34:03 +0200 +Subject: [PATCH 18/18] config: Add config_file_version to schema +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/3068 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit aeab20358006d728a284f969f92f3890498cd651) +--- + src/config/SSSDConfigTest.py | 1 + + src/config/cfg_rules.ini | 1 + + src/config/etc/sssd.api.conf | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 5fa9bce8e6502c0ebf42671058c5e3d5de00ea0d..332d8702d983b6ec8bf12ec781a1bbf296b552e0 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -289,6 +289,7 @@ class SSSDConfigTestSSSDService(unittest.TestCase): + + options = service.list_options() + control_list = [ ++ 'config_file_version', + 'services', + 'domains', + 'timeout', +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index 5c8d05a817331dd23fd7e349719bd4b44a5bdd02..635c078436e8ca47f60e8d82341cb131469fe4c9 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -39,6 +39,7 @@ option = user + option = default_domain_suffix + option = certificate_verification + option = override_space ++option = config_file_version + + [rule/allowed_nss_options] + validator = ini_allowed_options +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index e4011a384cdb3fb3bce93494cbb278ec2622ee40..737f0e149d56bd07b078cb83acbc43ea2ed3a057 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -19,6 +19,7 @@ diag_cmd = str, None, false + + [sssd] + # Monitor service ++config_file_version = int, None, false + services = list, str, true, nss, pam + domains = list, str, true + sbus_timeout = int, None, false +-- +2.4.11 + diff --git a/SOURCES/0019-DYNDNS-support-for-dualstack.patch b/SOURCES/0019-DYNDNS-support-for-dualstack.patch deleted file mode 100644 index 75f53f2..0000000 --- a/SOURCES/0019-DYNDNS-support-for-dualstack.patch +++ /dev/null @@ -1,437 +0,0 @@ -From 856cb96e313c164aa80915410ba758ad21cb6173 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Tue, 14 Jul 2015 09:56:59 -0400 -Subject: [PATCH 19/19] DYNDNS: support for dualstack - -When dyndns_iface option was not used, address of connection to LDAP -was used. This patch proposes following change: - * Interface containing address of connection is found. - * All A and AAAA addresses of this interface are collected. - * Collected addresses are sent during DDNS update. - * Function sss_iface_addr_add() is removed. - -Resolves: -https://fedorahosted.org/sssd/ticket/2558 ---- - src/providers/dp_dyndns.c | 135 +++++++++++++++++++++++------ - src/providers/dp_dyndns.h | 8 +- - src/providers/ldap/sdap_dyndns.c | 20 ++--- - src/tests/cmocka/test_dyndns.c | 178 +++++++++++++++++++++++++++++++++++++++ - 4 files changed, 302 insertions(+), 39 deletions(-) - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 03389acfba13e566540ca8b0570c0d009173575f..c254d78936f412626db0533f559350de57017618 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -58,31 +58,6 @@ void sss_iface_addr_concatenate(struct sss_iface_addr **list, - DLIST_CONCATENATE((*list), list2, struct sss_iface_addr*); - } - --struct sss_iface_addr * --sss_iface_addr_add(TALLOC_CTX *mem_ctx, struct sss_iface_addr **list, -- struct sockaddr_storage *ss) --{ -- struct sss_iface_addr *address; -- -- address = talloc(mem_ctx, struct sss_iface_addr); -- if (address == NULL) { -- return NULL; -- } -- -- address->addr = talloc_memdup(address, ss, -- sizeof(struct sockaddr_storage)); -- if(address->addr == NULL) { -- talloc_zfree(address); -- return NULL; -- } -- -- /* steal old dlist to the new head */ -- talloc_steal(address, *list); -- DLIST_ADD(*list, address); -- -- return address; --} -- - errno_t - sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx, - struct sss_iface_addr *ifaddr_list, -@@ -1258,3 +1233,113 @@ errno_t be_nsupdate_init_timer(struct be_nsupdate_ctx *ctx, - - return ERR_OK; - } -+ -+static bool match_ip(const struct sockaddr *sa, -+ const struct sockaddr *sb) -+{ -+ size_t addrsize; -+ bool res; -+ const void *addr_a; -+ const void *addr_b; -+ -+ if (sa->sa_family == AF_INET) { -+ addrsize = sizeof(struct in_addr); -+ addr_a = (const void *) &((const struct sockaddr_in *) sa)->sin_addr; -+ addr_b = (const void *) &((const struct sockaddr_in *) sb)->sin_addr; -+ } else if (sa->sa_family == AF_INET6) { -+ addrsize = sizeof(struct in6_addr); -+ addr_a = (const void *) &((const struct sockaddr_in6 *) sa)->sin6_addr; -+ addr_b = (const void *) &((const struct sockaddr_in6 *) sb)->sin6_addr; -+ } else { -+ res = false; -+ goto done; -+ } -+ -+ if (sa->sa_family != sb->sa_family) { -+ res = false; -+ goto done; -+ } -+ -+ res = memcmp(addr_a, addr_b, addrsize) == 0; -+ -+done: -+ return res; -+} -+ -+static errno_t find_iface_by_addr(TALLOC_CTX *mem_ctx, -+ const struct sockaddr *ss, -+ const char **_iface_name) -+{ -+ struct ifaddrs *ifaces = NULL; -+ struct ifaddrs *ifa; -+ errno_t ret; -+ -+ ret = getifaddrs(&ifaces); -+ if (ret == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not read interfaces [%d][%s]\n", ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ for (ifa = ifaces; ifa != NULL; ifa = ifa->ifa_next) { -+ -+ /* Some interfaces don't have an ifa_addr */ -+ if (!ifa->ifa_addr) continue; -+ -+ if (match_ip(ss, ifa->ifa_addr)) { -+ const char *iface_name; -+ iface_name = talloc_strdup(mem_ctx, ifa->ifa_name); -+ if (iface_name == NULL) { -+ ret = ENOMEM; -+ } else { -+ *_iface_name = iface_name; -+ ret = EOK; -+ } -+ goto done; -+ } -+ } -+ ret = ENOENT; -+ -+done: -+ freeifaddrs(ifaces); -+ return ret; -+} -+ -+errno_t sss_get_dualstack_addresses(TALLOC_CTX *mem_ctx, -+ struct sockaddr *ss, -+ struct sss_iface_addr **_iface_addrs) -+{ -+ struct sss_iface_addr *iface_addrs; -+ const char *iface_name = NULL; -+ TALLOC_CTX *tmp_ctx; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = find_iface_by_addr(tmp_ctx, ss, &iface_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "find_iface_by_addr failed: %d:[%s]\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = sss_iface_addr_list_get(tmp_ctx, iface_name, &iface_addrs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "sss_iface_addr_list_get failed: %d:[%s]\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ *_iface_addrs = talloc_steal(mem_ctx, iface_addrs); -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h -index deba112538ad22cd7f59be07934778ee9d4361e7..a8a20ec6f8a1a63cd8c85aaec3f54f9fddb42049 100644 ---- a/src/providers/dp_dyndns.h -+++ b/src/providers/dp_dyndns.h -@@ -81,10 +81,6 @@ errno_t - sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname, - struct sss_iface_addr **_addrlist); - --struct sss_iface_addr * --sss_iface_addr_add(TALLOC_CTX *mem_ctx, struct sss_iface_addr **list, -- struct sockaddr_storage *ss); -- - errno_t - sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx, - struct sss_iface_addr *ifaddr_list, -@@ -132,4 +128,8 @@ void - sss_iface_addr_concatenate(struct sss_iface_addr **list, - struct sss_iface_addr *list2); - -+errno_t -+sss_get_dualstack_addresses(TALLOC_CTX *mem_ctx, -+ struct sockaddr *ss, -+ struct sss_iface_addr **_iface_addrs); - #endif /* DP_DYNDNS_H_ */ -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index f5929cff3db6f724efcedeb963e3a12d04f6e1d3..a463a2fce08f42b325010cd37c501ef23aee173f 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -644,7 +644,6 @@ sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state, - { - int ret; - int fd; -- struct sss_iface_addr *address; - struct sockaddr_storage ss; - socklen_t ss_len = sizeof(ss); - -@@ -666,20 +665,21 @@ sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state, - return ret; - } - -- switch(ss.ss_family) { -- case AF_INET: -- case AF_INET6: -- address = sss_iface_addr_add(state, &state->addresses, &ss); -- if (address == NULL) { -- return ENOMEM; -- } -- break; -- default: -+ if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Connection to LDAP is neither IPv4 nor IPv6\n"); - return EIO; - } - -+ ret = sss_get_dualstack_addresses(state, (struct sockaddr *) &ss, -+ &state->addresses); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "sss_get_dualstack_addresses failed: %d:[%s]\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ - return EOK; - } - -diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c -index e9d42cea37472b38ae2eb900368f2ce3f409fefc..8118e9438e89465674155c11f4523d2313f6a59c 100644 ---- a/src/tests/cmocka/test_dyndns.c -+++ b/src/tests/cmocka/test_dyndns.c -@@ -289,6 +289,173 @@ void dyndns_test_get_ifaddr_enoent(void **state) - assert_true(check_leaks_pop(dyndns_test_ctx) == true); - } - -+void dyndns_test_dualstack(void **state) -+{ -+ errno_t ret; -+ struct sss_iface_addr *addrlist; -+ struct sss_iface_addr *sss_if_addrs; -+ char straddr[128]; -+ int i; -+ -+ check_leaks_push(dyndns_test_ctx); -+ -+ /* getifaddrs is called twice in sss_get_dualstack_addresses() */ -+ for (i = 0; i < 2; i++) { -+ will_return_getifaddrs("eth0", "192.168.0.2", AF_INET); -+ will_return_getifaddrs("eth1", "192.168.0.1", AF_INET); -+ will_return_getifaddrs("eth0", "2001:cdba::555", AF_INET6); -+ will_return_getifaddrs("eth1", "2001:cdba::444", AF_INET6); -+ will_return_getifaddrs(NULL, NULL, 0); /* sentinel */ -+ } -+ -+ struct sockaddr_in sin; -+ memset (&sin, 0, sizeof (sin)); -+ sin.sin_family = AF_INET; -+ sin.sin_addr.s_addr = inet_addr ("192.168.0.2"); -+ ret = sss_get_dualstack_addresses(dyndns_test_ctx, -+ (struct sockaddr *) &sin, -+ &addrlist); -+ assert_int_equal(ret, EOK); -+ -+ sss_if_addrs = addrlist; -+ assert_non_null(sss_if_addrs); -+ assert_non_null(sss_if_addrs->addr); -+ assert_non_null(sss_if_addrs->next); -+ assert_null(sss_if_addrs->prev); -+ -+ assert_non_null(inet_ntop(AF_INET6, -+ &((struct sockaddr_in6 *) sss_if_addrs->addr)->sin6_addr, -+ straddr, INET6_ADDRSTRLEN)); -+ /* ip addresses are returned in different order */ -+ assert_string_equal(straddr, "2001:cdba::555"); -+ -+ sss_if_addrs = addrlist->next; -+ assert_non_null(sss_if_addrs); -+ assert_non_null(sss_if_addrs->addr); -+ assert_null(sss_if_addrs->next); -+ assert_non_null(sss_if_addrs->prev); -+ -+ assert_non_null(inet_ntop(AF_INET, -+ &((struct sockaddr_in *) sss_if_addrs->addr)->sin_addr, -+ straddr, INET_ADDRSTRLEN)); -+ /* ip addresses are returned in different order */ -+ assert_string_equal(straddr, "192.168.0.2"); -+ -+ talloc_free(addrlist); -+ -+ assert_true(check_leaks_pop(dyndns_test_ctx) == true); -+} -+ -+void dyndns_test_dualstack_multiple_addresses(void **state) -+{ -+ errno_t ret; -+ struct sss_iface_addr *addrlist; -+ struct sss_iface_addr *sss_if_addrs; -+ char straddr[128]; -+ int i; -+ -+ check_leaks_push(dyndns_test_ctx); -+ -+ /* getifaddrs is called twice in sss_get_dualstack_addresses() */ -+ for (i = 0; i < 2; i++) { -+ will_return_getifaddrs("eth0", "192.168.0.2", AF_INET); -+ will_return_getifaddrs("eth0", "192.168.0.1", AF_INET); -+ /* loopback - invalid for dns (should be skipped) */ -+ will_return_getifaddrs("eth0", "::1", AF_INET6); -+ /* linklocal - invalid for dns (should be skipped) */ -+ will_return_getifaddrs("eth0", "fe80::5054:ff:fe4a:65ae", AF_INET6); -+ will_return_getifaddrs("eth0", "2001:cdba::555", AF_INET6); -+ will_return_getifaddrs("eth0", "2001:cdba::444", AF_INET6); -+ will_return_getifaddrs(NULL, NULL, 0); /* sentinel */ -+ } -+ -+ struct sockaddr_in sin; -+ memset (&sin, 0, sizeof (sin)); -+ sin.sin_family = AF_INET; -+ sin.sin_addr.s_addr = inet_addr ("192.168.0.2"); -+ ret = sss_get_dualstack_addresses(dyndns_test_ctx, -+ (struct sockaddr *) &sin, -+ &addrlist); -+ assert_int_equal(ret, EOK); -+ -+ sss_if_addrs = addrlist; -+ assert_non_null(sss_if_addrs); -+ assert_non_null(sss_if_addrs->addr); -+ assert_non_null(sss_if_addrs->next); -+ assert_null(sss_if_addrs->prev); -+ -+ assert_non_null(inet_ntop(AF_INET6, -+ &((struct sockaddr_in6 *) sss_if_addrs->addr)->sin6_addr, -+ straddr, INET6_ADDRSTRLEN)); -+ /* ip addresses are returned in different order */ -+ assert_string_equal(straddr, "2001:cdba::444"); -+ -+ sss_if_addrs = sss_if_addrs->next; -+ assert_non_null(sss_if_addrs); -+ assert_non_null(sss_if_addrs->addr); -+ assert_non_null(sss_if_addrs->prev); -+ assert_non_null(sss_if_addrs->next); -+ -+ assert_non_null(inet_ntop(AF_INET6, -+ &((struct sockaddr_in6 *) sss_if_addrs->addr)->sin6_addr, -+ straddr, INET6_ADDRSTRLEN)); -+ /* ip addresses are returned in different order */ -+ assert_string_equal(straddr, "2001:cdba::555"); -+ -+ sss_if_addrs = sss_if_addrs->next; -+ assert_non_null(sss_if_addrs); -+ assert_non_null(sss_if_addrs->addr); -+ assert_non_null(sss_if_addrs->next); -+ assert_non_null(sss_if_addrs->prev); -+ -+ assert_non_null(inet_ntop(AF_INET, -+ &((struct sockaddr_in *) sss_if_addrs->addr)->sin_addr, -+ straddr, INET_ADDRSTRLEN)); -+ /* ip addresses are returned in different order */ -+ assert_string_equal(straddr, "192.168.0.1"); -+ -+ sss_if_addrs = sss_if_addrs->next; -+ assert_non_null(sss_if_addrs); -+ assert_non_null(sss_if_addrs->addr); -+ assert_null(sss_if_addrs->next); -+ assert_non_null(sss_if_addrs->prev); -+ -+ assert_non_null(inet_ntop(AF_INET, -+ &((struct sockaddr_in *) sss_if_addrs->addr)->sin_addr, -+ straddr, INET_ADDRSTRLEN)); -+ /* ip addresses are returned in different order */ -+ assert_string_equal(straddr, "192.168.0.2"); -+ -+ talloc_free(addrlist); -+ -+ assert_true(check_leaks_pop(dyndns_test_ctx) == true); -+} -+ -+void dyndns_test_dualstack_no_iface(void **state) -+{ -+ errno_t ret; -+ struct sss_iface_addr *addrlist; -+ -+ check_leaks_push(dyndns_test_ctx); -+ -+ will_return_getifaddrs("eth0", "192.168.0.2", AF_INET); -+ will_return_getifaddrs("eth1", "192.168.0.1", AF_INET); -+ will_return_getifaddrs("eth0", "2001:cdba::555", AF_INET6); -+ will_return_getifaddrs("eth1", "2001:cdba::444", AF_INET6); -+ will_return_getifaddrs(NULL, NULL, 0); /* sentinel */ -+ -+ struct sockaddr_in sin; -+ memset (&sin, 0, sizeof (sin)); -+ sin.sin_family = AF_INET; -+ sin.sin_addr.s_addr = inet_addr ("192.168.0.3"); -+ ret = sss_get_dualstack_addresses(dyndns_test_ctx, -+ (struct sockaddr *) &sin, -+ &addrlist); -+ assert_int_equal(ret, ENOENT); -+ -+ assert_true(check_leaks_pop(dyndns_test_ctx) == true); -+} -+ - void dyndns_test_ok(void **state) - { - struct tevent_req *req; -@@ -519,6 +686,17 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(dyndns_test_interval, - dyndns_test_setup, - dyndns_test_teardown), -+ -+ /* Dynamic DNS dualstack unit tests*/ -+ cmocka_unit_test_setup_teardown(dyndns_test_dualstack, -+ dyndns_test_simple_setup, -+ dyndns_test_teardown), -+ cmocka_unit_test_setup_teardown(dyndns_test_dualstack_multiple_addresses, -+ dyndns_test_simple_setup, -+ dyndns_test_teardown), -+ cmocka_unit_test_setup_teardown(dyndns_test_dualstack_no_iface, -+ dyndns_test_simple_setup, -+ dyndns_test_teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.4.3 - diff --git a/SOURCES/0019-dyndns-Add-checks-for-NULL.patch b/SOURCES/0019-dyndns-Add-checks-for-NULL.patch new file mode 100644 index 0000000..f038acd --- /dev/null +++ b/SOURCES/0019-dyndns-Add-checks-for-NULL.patch @@ -0,0 +1,57 @@ +From b0330a760d838b30c88d6f02f0148b84093761c3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Tue, 12 Jul 2016 12:11:18 +0200 +Subject: [PATCH 19/19] dyndns: Add checks for NULL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fixes: +https://fedorahosted.org/sssd/ticket/3076 + +We segfaulted in this area once. This patch +makes the code more defensive and adds +some DEBUG messages. + +Normally the structures are filled in online +and/or resolve callbacks. + +Reviewed-by: Pavel Březina +--- + src/providers/ipa/ipa_dyndns.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c +index 7217c61452e7ead2949a9f7d57b2f2fc58953af1..dc910770c771d4b7a7ee62d25be7c48e16c988a7 100644 +--- a/src/providers/ipa/ipa_dyndns.c ++++ b/src/providers/ipa/ipa_dyndns.c +@@ -162,6 +162,26 @@ ipa_dyndns_update_send(struct ipa_options *ctx) + } + state->ipa_ctx = ctx; + ++ /* The following three checks are here to prevent SEGFAULT ++ * from ticket #3076. */ ++ if (ctx->service == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "service structure not initialized\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ if (ctx->service->sdap == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "sdap structure not initialized\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ if (ctx->service->sdap->uri == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "LDAP uri not set\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ + if (ctx->dyndns_ctx->last_refresh + 60 > time(NULL) || + ctx->dyndns_ctx->timer_in_progress) { + DEBUG(SSSDBG_FUNC_DATA, "Last periodic update ran recently or timer " +-- +2.4.11 + diff --git a/SOURCES/0020-VIEWS-TEST-add-null-check.patch b/SOURCES/0020-VIEWS-TEST-add-null-check.patch deleted file mode 100644 index 912c030..0000000 --- a/SOURCES/0020-VIEWS-TEST-add-null-check.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 681fd36964b873135b2b8dd5200ddcfd1e420214 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Mon, 27 Jul 2015 17:24:45 +0200 -Subject: [PATCH 20/23] VIEWS TEST: add null-check - -Reviewed-by: Jakub Hrozek ---- - src/tests/cmocka/test_sysdb_views.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c -index 1fb598219e9ee581e465ddbb32ba9f2544600c26..123d4c5cb613f41e1bca9e89feed701a1e86f8d3 100644 ---- a/src/tests/cmocka/test_sysdb_views.c -+++ b/src/tests/cmocka/test_sysdb_views.c -@@ -225,10 +225,12 @@ void test_sysdb_add_overrides_to_object(void **state) - assert_non_null(orig); - - tmp_str = talloc_strdup(orig, "ORIGNAME"); -+ assert_non_null(tmp_str); - ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str); - assert_int_equal(ret, EOK); - - tmp_str = talloc_strdup(orig, "ORIGGECOS"); -+ assert_non_null(tmp_str); - ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str); - assert_int_equal(ret, EOK); - -@@ -236,18 +238,22 @@ void test_sysdb_add_overrides_to_object(void **state) - assert_non_null(override); - - tmp_str = talloc_strdup(override, "OVERRIDENAME"); -+ assert_non_null(tmp_str); - ret = ldb_msg_add_string(override, SYSDB_NAME, tmp_str); - assert_int_equal(ret, EOK); - - tmp_str = talloc_strdup(override, "OVERRIDEGECOS"); -+ assert_non_null(tmp_str); - ret = ldb_msg_add_string(override, SYSDB_GECOS, tmp_str); - assert_int_equal(ret, EOK); - - tmp_str = talloc_strdup(override, "OVERRIDEKEY1"); -+ assert_non_null(tmp_str); - ret = ldb_msg_add_string(override, SYSDB_SSH_PUBKEY, tmp_str); - assert_int_equal(ret, EOK); - - tmp_str = talloc_strdup(override, "OVERRIDEKEY2"); -+ assert_non_null(tmp_str); - ret = ldb_msg_add_string(override, SYSDB_SSH_PUBKEY, tmp_str); - assert_int_equal(ret, EOK); - --- -2.4.3 - diff --git a/SOURCES/0020-sdap-Fix-ldap_rfc_2307_fallback_to_local_users.patch b/SOURCES/0020-sdap-Fix-ldap_rfc_2307_fallback_to_local_users.patch new file mode 100644 index 0000000..331cf4d --- /dev/null +++ b/SOURCES/0020-sdap-Fix-ldap_rfc_2307_fallback_to_local_users.patch @@ -0,0 +1,42 @@ +From dad90587794fdc2112f2099d5f6cdd9e138781be Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 13 Jul 2016 20:02:47 +0200 +Subject: [PATCH 20/27] sdap: Fix ldap_rfc_2307_fallback_to_local_users +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We wrongly tried to store empty +user attributes instead of the +local user attributes with +ldap_rfc_2307_fallback_to_local_users +set to true. This gave us bad +initgroups results and caused +segfaults. + +Resolves: +https://fedorahosted.org/sssd/ticket/3045 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit aa8ec3758d885d6ae4088174369d30f8493ec898) +--- + src/providers/ldap/sdap_async_initgroups.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index d14563cb045a0ce34b72051744894362fc32d003..17593f0a268813662d6c7fbf658b1eb4599ce3c3 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2893,6 +2893,9 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) + (dp_opt_get_bool(state->opts->basic, + SDAP_RFC2307_FALLBACK_TO_LOCAL_USERS) == true)) { + ret = sdap_fallback_local_user(state, state->shortname, -1, &usr_attrs); ++ if (ret == EOK) { ++ state->orig_user = usr_attrs[0]; ++ } + } else { + ret = ENOENT; + } +-- +2.4.11 + diff --git a/SOURCES/0021-SYSDB-prepare-for-LOCAL-view.patch b/SOURCES/0021-SYSDB-prepare-for-LOCAL-view.patch deleted file mode 100644 index 43ac1e7..0000000 --- a/SOURCES/0021-SYSDB-prepare-for-LOCAL-view.patch +++ /dev/null @@ -1,177 +0,0 @@ -From ea6cfe4e1d7c84370bfcc86251ea10b2658b52d3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 24 Jul 2015 09:55:28 +0200 -Subject: [PATCH 21/23] SYSDB: prepare for LOCAL view - -Objects doesn't have to have overrideDN specified when using LOCAL view. -Since the view is not stored on the server we do not want to contact -LDAP therefore we special case LOCAL view saying that it is OK that -this attribute is missing. - -Preparation for: -https://fedorahosted.org/sssd/ticket/2584 - -Reviewed-by: Jakub Hrozek ---- - src/db/sysdb.h | 14 +++++++- - src/db/sysdb_views.c | 7 ++++ - src/providers/ipa/ipa_subdomains.c | 3 +- - src/tests/cmocka/test_sysdb_views.c | 66 +++++++++++++++++++++++++++++++++++++ - 4 files changed, 88 insertions(+), 2 deletions(-) - -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 0f745ccb1a646d77ba4ad3d714d5f4dce0a51211..9e28b5c6691f3710e3051d9746ac5fa47aff8424 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -157,9 +157,10 @@ - #define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires" - #define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl" - -+#define SYSDB_DEFAULT_VIEW_NAME "default" -+#define SYSDB_LOCAL_VIEW_NAME "LOCAL" /* reserved for client-side overrides */ - #define SYSDB_VIEW_CLASS "view" - #define SYSDB_VIEW_NAME "viewName" --#define SYSDB_DEFAULT_VIEW_NAME "default" - #define SYSDB_OVERRIDE_CLASS "overrride" - #define SYSDB_OVERRIDE_ANCHOR_UUID "overrideAnchorUUID" - #define SYSDB_OVERRIDE_USER_CLASS "userOverride" -@@ -473,6 +474,17 @@ static inline bool is_default_view(const char *view_name) - } - } - -+static inline bool is_local_view(const char *view_name) -+{ -+ /* NULL is treated as default */ -+ if (view_name != NULL -+ && strcmp(view_name, SYSDB_LOCAL_VIEW_NAME) == 0) { -+ return true; -+ } else { -+ return false; -+ } -+} -+ - errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name); - - errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb); -diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c -index aadd6018f4d1e2ca33e2e00dd8b13b55a8c03f3e..1db6c892de9e4764b673608166830800744b1148 100644 ---- a/src/db/sysdb_views.c -+++ b/src/db/sysdb_views.c -@@ -1186,9 +1186,16 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain, - override_dn_str = ldb_msg_find_attr_as_string(obj, - SYSDB_OVERRIDE_DN, NULL); - if (override_dn_str == NULL) { -+ if (is_local_view(domain->view_name)) { -+ /* LOCAL view doesn't have to have overrideDN specified. */ -+ ret = EOK; -+ goto done; -+ } -+ - DEBUG(SSSDBG_CRIT_FAILURE, - "Missing override DN for objext [%s].\n", - ldb_dn_get_linearized(obj->dn)); -+ - ret = ENOENT; - goto done; - } -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index cf72784473747c67d44a5d887faf867cfe62ce2b..cec8b3918b8f832e2c7376a867448fe876da6ffc 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -905,7 +905,8 @@ static void ipa_get_view_name_done(struct tevent_req *req) - goto done; - } - -- if (!is_default_view(ctx->sd_ctx->id_ctx->view_name)) { -+ if (!is_default_view(ctx->sd_ctx->id_ctx->view_name) -+ && !is_local_view(ctx->sd_ctx->id_ctx->view_name)) { - /* Old view was not the default view, delete view tree */ - ret = sysdb_delete_view_tree( - ctx->sd_ctx->be_ctx->domain->sysdb, -diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c -index 123d4c5cb613f41e1bca9e89feed701a1e86f8d3..83007b76a625edef67109850648b2d71645e22bb 100644 ---- a/src/tests/cmocka/test_sysdb_views.c -+++ b/src/tests/cmocka/test_sysdb_views.c -@@ -281,6 +281,68 @@ void test_sysdb_add_overrides_to_object(void **state) - assert_int_equal(ldb_val_string_cmp(&el->values[1], "OVERRIDEKEY2"), 0); - } - -+void test_sysdb_add_overrides_to_object_local(void **state) -+{ -+ int ret; -+ struct ldb_message *orig; -+ struct ldb_message_element *el; -+ char *tmp_str; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ -+ orig = ldb_msg_new(test_ctx); -+ assert_non_null(orig); -+ -+ tmp_str = talloc_strdup(orig, "ORIGNAME"); -+ assert_non_null(tmp_str); -+ ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str); -+ assert_int_equal(ret, EOK); -+ -+ tmp_str = talloc_strdup(orig, "ORIGGECOS"); -+ assert_non_null(tmp_str); -+ ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str); -+ assert_int_equal(ret, EOK); -+ -+ test_ctx->domain->has_views = true; -+ test_ctx->domain->view_name = "LOCAL"; -+ -+ ret = sysdb_add_overrides_to_object(test_ctx->domain, orig, NULL, NULL); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_sysdb_add_overrides_to_object_missing_overridedn(void **state) -+{ -+ int ret; -+ struct ldb_message *orig; -+ struct ldb_message_element *el; -+ char *tmp_str; -+ struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, -+ struct sysdb_test_ctx); -+ -+ orig = ldb_msg_new(test_ctx); -+ assert_non_null(orig); -+ -+ orig->dn = ldb_dn_new(orig, test_ctx->domain->sysdb->ldb, -+ "cn=somedn,dc=example,dc=com"); -+ assert_non_null(orig->dn); -+ -+ tmp_str = talloc_strdup(orig, "ORIGNAME"); -+ assert_non_null(tmp_str); -+ ret = ldb_msg_add_string(orig, SYSDB_NAME, tmp_str); -+ assert_int_equal(ret, EOK); -+ -+ tmp_str = talloc_strdup(orig, "ORIGGECOS"); -+ assert_non_null(tmp_str); -+ ret = ldb_msg_add_string(orig, SYSDB_GECOS, tmp_str); -+ assert_int_equal(ret, EOK); -+ -+ test_ctx->domain->has_views = true; -+ test_ctx->domain->view_name = "NON-LOCAL"; -+ -+ ret = sysdb_add_overrides_to_object(test_ctx->domain, orig, NULL, NULL); -+ assert_int_equal(ret, ENOENT); -+} -+ - void test_split_ipa_anchor(void **state) - { - int ret; -@@ -923,6 +985,10 @@ int main(int argc, const char *argv[]) - test_sysdb_setup, test_sysdb_teardown), - cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object, - test_sysdb_setup, test_sysdb_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object_local, -+ test_sysdb_setup, test_sysdb_teardown), -+ cmocka_unit_test_setup_teardown(test_sysdb_add_overrides_to_object_missing_overridedn, -+ test_sysdb_setup, test_sysdb_teardown), - cmocka_unit_test_setup_teardown(test_split_ipa_anchor, - test_sysdb_setup, test_sysdb_teardown), - cmocka_unit_test_setup_teardown(test_sysdb_delete_view_tree, --- -2.4.3 - diff --git a/SOURCES/0021-test_utils-Clean-files-after-sss_write_krb5_conf_sni.patch b/SOURCES/0021-test_utils-Clean-files-after-sss_write_krb5_conf_sni.patch new file mode 100644 index 0000000..7ad0c30 --- /dev/null +++ b/SOURCES/0021-test_utils-Clean-files-after-sss_write_krb5_conf_sni.patch @@ -0,0 +1,56 @@ +From a2e8989fd06af0dcf4dd7b8013bda6bcb49839f0 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Tue, 12 Jul 2016 12:37:16 +0200 +Subject: [PATCH 21/27] test_utils: Clean files after + sss_write_krb5_conf_snippet +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The test directory was not removed (tp_test_utils-test_utils) +because it contain the snippet for krb5_libdefaults. + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 059904af2d20debcb8ffe1c6f45b996c2c57574e) +--- + src/tests/cmocka/test_utils.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c +index fd20990ce7ac632b3b62bf84a20cc75a5ec0e968..b08b19708bb59a076a79805fa37a15924152b8e2 100644 +--- a/src/tests/cmocka/test_utils.c ++++ b/src/tests/cmocka/test_utils.c +@@ -1252,6 +1252,7 @@ void test_sss_write_krb5_conf_snippet(void **state) + char *cwd; + char *path; + char *file; ++ char *file_krb5_libdefaults; + + ret = sss_write_krb5_conf_snippet(NULL, false); + assert_int_equal(ret, EINVAL); +@@ -1274,6 +1275,10 @@ void test_sss_write_krb5_conf_snippet(void **state) + ret = asprintf(&file, "%s/%s/localauth_plugin", cwd, TESTS_PATH); + assert_true(ret > 0); + ++ ret = asprintf(&file_krb5_libdefaults, ++ "%s/%s/krb5_libdefaults", cwd, TESTS_PATH); ++ assert_true(ret > 0); ++ + ret = sss_write_krb5_conf_snippet(path, true); + assert_int_equal(ret, EOK); + +@@ -1286,7 +1291,11 @@ void test_sss_write_krb5_conf_snippet(void **state) + assert_int_equal(ret, EOK); + #endif + ++ ret = unlink(file_krb5_libdefaults); ++ assert_int_equal(ret, EOK); ++ + free(file); ++ free(file_krb5_libdefaults); + free(path); + } + +-- +2.4.11 + diff --git a/SOURCES/0022-IPA-read-ipaNTAdditionalSuffixes-for-master-and-trus.patch b/SOURCES/0022-IPA-read-ipaNTAdditionalSuffixes-for-master-and-trus.patch new file mode 100644 index 0000000..478a9ba --- /dev/null +++ b/SOURCES/0022-IPA-read-ipaNTAdditionalSuffixes-for-master-and-trus.patch @@ -0,0 +1,47 @@ +From 4ec714f1681355d95420733a40e3c37cd0bfe6ee Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 23 Jun 2016 11:58:30 +0200 +Subject: [PATCH 22/27] IPA: read ipaNTAdditionalSuffixes for master and + trusted domains + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 39f21d2b61685362642d42bc2f94f829671cd5ef) +--- + src/providers/ipa/ipa_subdomains.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index a02a65d97dde68f1da900b9fdca05c54035ce005..263d6207960c232d08114bd0163b3fd03a690685 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -40,6 +40,7 @@ + #define IPA_SID "ipaNTSecurityIdentifier" + #define IPA_TRUSTED_DOMAIN_SID "ipaNTTrustedDomainSID" + #define IPA_RANGE_TYPE "ipaRangeType" ++#define IPA_ADDITIONAL_SUFFIXES "ipaNTAdditionalSuffixes" + + #define IPA_BASE_ID "ipaBaseID" + #define IPA_ID_RANGE_SIZE "ipaIDRangeSize" +@@ -788,7 +789,8 @@ ipa_subdomains_master_send(TALLOC_CTX *mem_ctx, + struct tevent_req *subreq; + struct tevent_req *req; + errno_t ret; +- const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_SID, NULL }; ++ const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_SID, ++ IPA_ADDITIONAL_SUFFIXES, NULL }; + + req = tevent_req_create(mem_ctx, &state, + struct ipa_subdomains_master_state); +@@ -939,7 +941,8 @@ ipa_subdomains_slave_send(TALLOC_CTX *mem_ctx, + struct tevent_req *req; + errno_t ret; + const char *attrs[] = { IPA_CN, IPA_FLATNAME, IPA_TRUSTED_DOMAIN_SID, +- IPA_TRUST_DIRECTION, NULL }; ++ IPA_TRUST_DIRECTION, IPA_ADDITIONAL_SUFFIXES, ++ NULL }; + + req = tevent_req_create(mem_ctx, &state, + struct ipa_subdomains_slave_state); +-- +2.4.11 + diff --git a/SOURCES/0022-TOOLS-add-common-command-framework.patch b/SOURCES/0022-TOOLS-add-common-command-framework.patch deleted file mode 100644 index b5689c8..0000000 --- a/SOURCES/0022-TOOLS-add-common-command-framework.patch +++ /dev/null @@ -1,555 +0,0 @@ -From edb91d864b48bf6e6240fe7eee84e68cdaaf012a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 22 Jul 2015 10:02:02 +0200 -Subject: [PATCH 22/23] TOOLS: add common command framework - -Add general framework to simplify creating "cmd COMMAND [OPTIONS...]" -style tools. - -Preparation for: -https://fedorahosted.org/sssd/ticket/2584 - -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 5 +- - src/tools/common/sss_tools.c | 406 +++++++++++++++++++++++++++++++++++++++++++ - src/tools/common/sss_tools.h | 91 ++++++++++ - 3 files changed, 501 insertions(+), 1 deletion(-) - create mode 100644 src/tools/common/sss_tools.c - create mode 100644 src/tools/common/sss_tools.h - -diff --git a/Makefile.am b/Makefile.am -index b8cbc6df23ded1edb945a709b6dbe1c44eb54017..1edecc483c61d04562b7bfd9086146e93963b74e 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -445,7 +445,9 @@ SSSD_TOOLS_OBJ = \ - src/tools/tools_util.c \ - src/tools/files.c \ - src/tools/selinux.c \ -- src/util/nscd.c -+ src/tools/common/sss_tools.c \ -+ src/util/nscd.c \ -+ $(NULL) - - SSSD_LCL_TOOLS_OBJ = \ - src/sss_client/common.c \ -@@ -641,6 +643,7 @@ dist_noinst_HEADERS = \ - src/lib/idmap/sss_idmap_private.h \ - src/lib/sifp/sss_sifp_private.h \ - src/tests/cmocka/test_utils.h \ -+ src/tools/common/sss_tools.h \ - $(NULL) - - -diff --git a/src/tools/common/sss_tools.c b/src/tools/common/sss_tools.c -new file mode 100644 -index 0000000000000000000000000000000000000000..6bbce3a25ddddc0b23ebc108a917a38e94981b65 ---- /dev/null -+++ b/src/tools/common/sss_tools.c -@@ -0,0 +1,406 @@ -+/* -+ Authors: -+ Pavel Březina -+ -+ Copyright (C) 2015 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+#include -+#include -+#include -+ -+#include "config.h" -+#include "util/util.h" -+#include "confdb/confdb.h" -+#include "db/sysdb.h" -+#include "tools/common/sss_tools.h" -+ -+struct sss_cmdline { -+ const char *exec; /* argv[0] */ -+ const char *command; /* command name */ -+ int argc; /* rest of arguments */ -+ const char **argv; -+}; -+ -+static void sss_tool_common_opts(struct sss_tool_ctx *tool_ctx, -+ int *argc, const char **argv) -+{ -+ poptContext pc; -+ int debug = SSSDBG_DEFAULT; -+ int orig_argc = *argc; -+ int opt; -+ -+ struct poptOption options[] = { -+ {"debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_STRIP, &debug, -+ 0, _("The debug level to run with"), NULL }, -+ POPT_TABLEEND -+ }; -+ -+ pc = poptGetContext(argv[0], orig_argc, argv, options, 0); -+ while ((opt = poptGetNextOpt(pc)) != -1) { -+ /* do nothing */ -+ } -+ -+ /* Strip common options from arguments. We will discard_const here, -+ * since it is not worth the trouble to convert it back and forth. */ -+ *argc = poptStrippedArgv(pc, orig_argc, discard_const_p(char *, argv)); -+ -+ DEBUG_CLI_INIT(debug); -+ -+ poptFreeContext(pc); -+} -+ -+static errno_t sss_tool_confdb_init(TALLOC_CTX *mem_ctx, -+ struct confdb_ctx **_confdb) -+{ -+ struct confdb_ctx *confdb; -+ char *path; -+ errno_t ret; -+ -+ path = talloc_asprintf(mem_ctx, "%s/%s", DB_PATH, CONFDB_FILE); -+ if (path == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = confdb_init(mem_ctx, &confdb, path); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Could not initialize connection to the confdb\n"); -+ talloc_free(path); -+ return ret; -+ } -+ -+ if (_confdb != NULL) { -+ *_confdb = confdb; -+ } -+ -+ return EOK; -+} -+ -+static errno_t sss_tool_domains_init(TALLOC_CTX *mem_ctx, -+ struct confdb_ctx *confdb, -+ struct sss_domain_info **_domains) -+{ -+ struct sss_domain_info *domains; -+ struct sss_domain_info *dom; -+ errno_t ret; -+ -+ ret = confdb_get_domains(confdb, &domains); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup domains [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ -+ ret = sysdb_init(mem_ctx, domains, false); -+ SYSDB_VERSION_ERROR(ret); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Could not initialize connection to the sysdb\n"); -+ return ret; -+ } -+ -+ for (dom = domains; dom != NULL; dom = get_next_domain(dom, true)) { -+ if (!IS_SUBDOMAIN(dom)) { -+ /* Update list of subdomains for this domain */ -+ ret = sysdb_update_subdomains(dom); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Failed to update subdomains for domain %s.\n", -+ dom->name); -+ } -+ } -+ } -+ -+ for (dom = domains; dom != NULL; dom = get_next_domain(dom, true)) { -+ ret = sss_names_init(mem_ctx, confdb, dom->name, &dom->names); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "sss_names_init() failed\n"); -+ return ret; -+ } -+ } -+ -+ *_domains = domains; -+ -+ return ret; -+} -+ -+struct sss_tool_ctx *sss_tool_init(TALLOC_CTX *mem_ctx, -+ int *argc, const char **argv) -+{ -+ struct sss_tool_ctx *tool_ctx; -+ errno_t ret; -+ -+ tool_ctx = talloc_zero(mem_ctx, struct sss_tool_ctx); -+ if (tool_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n"); -+ return NULL; -+ } -+ -+ sss_tool_common_opts(tool_ctx, argc, argv); -+ -+ /* Connect to confdb. */ -+ ret = sss_tool_confdb_init(tool_ctx, &tool_ctx->confdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to open confdb [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ /* Setup domains. */ -+ ret = sss_tool_domains_init(tool_ctx, tool_ctx->confdb, &tool_ctx->domains); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup domains [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = confdb_get_string(tool_ctx->confdb, tool_ctx, -+ CONFDB_MONITOR_CONF_ENTRY, -+ CONFDB_MONITOR_DEFAULT_DOMAIN, -+ NULL, &tool_ctx->default_domain); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Cannot get the default domain [%d]: %s\n", -+ ret, strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_zfree(tool_ctx); -+ } -+ -+ return tool_ctx; -+} -+ -+int sss_tool_usage(const char *tool_name, -+ struct sss_route_cmd *commands) -+{ -+ int i; -+ -+ fprintf(stderr, _("Usage:\n%s COMMAND COMMAND-ARGS\n\n"), tool_name); -+ fprintf(stderr, _("Available commands:\n")); -+ -+ for (i = 0; commands[i].command != NULL; i++) { -+ fprintf(stderr, "* %s\n", commands[i].command); -+ } -+ -+ return EXIT_FAILURE; -+} -+ -+int sss_tool_route(int argc, const char **argv, -+ struct sss_tool_ctx *tool_ctx, -+ struct sss_route_cmd *commands, -+ void *pvt) -+{ -+ struct sss_cmdline cmdline; -+ const char *cmd; -+ int i; -+ -+ if (commands == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: commands can't be NULL!\n"); -+ return EXIT_FAILURE; -+ } -+ -+ if (argc < 2) { -+ return sss_tool_usage(argv[0], commands); -+ } -+ -+ cmd = argv[1]; -+ for (i = 0; commands[i].command != NULL; i++) { -+ if (strcmp(commands[i].command, cmd) == 0) { -+ cmdline.exec = argv[0]; -+ cmdline.command = argv[1]; -+ cmdline.argc = argc - 2; -+ cmdline.argv = argv + 2; -+ -+ return commands[i].fn(&cmdline, tool_ctx, pvt); -+ } -+ } -+ -+ return sss_tool_usage(argv[0], commands); -+} -+ -+int sss_tool_popt_ex(struct sss_cmdline *cmdline, -+ struct poptOption *options, -+ enum sss_tool_opt require_option, -+ sss_popt_fn popt_fn, -+ void *popt_fn_pvt, -+ const char *fopt_name, -+ const char *fopt_help, -+ const char **_fopt) -+{ -+ const char *optstr; -+ char *help; -+ poptContext pc; -+ int ret; -+ -+ /* Create help option string. We always need to append command name since -+ * we use POPT_CONTEXT_KEEP_FIRST. */ -+ optstr = options == NULL ? "" : _(" [OPTIONS...]"); -+ if (fopt_name == NULL) { -+ help = talloc_asprintf(NULL, "%s %s%s", -+ cmdline->exec, cmdline->command, optstr); -+ } else { -+ help = talloc_asprintf(NULL, "%s %s %s%s", -+ cmdline->exec, cmdline->command, fopt_name, optstr); -+ } -+ if (help == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); -+ return EXIT_FAILURE; -+ } -+ -+ /* Create popt context. This function is supposed to be called on -+ * command argv which does not contain executable (argv[0]), therefore -+ * we need to use KEEP_FIRST that ensures argv[0] is also processed. */ -+ pc = poptGetContext(cmdline->exec, cmdline->argc, cmdline->argv, -+ options, POPT_CONTEXT_KEEP_FIRST); -+ -+ poptSetOtherOptionHelp(pc, help); -+ -+ /* Parse options. Invoke custom function if provided. If no parsing -+ * function is provided, print error on unknown option. */ -+ while ((ret = poptGetNextOpt(pc)) != -1) { -+ if (popt_fn != NULL) { -+ ret = popt_fn(pc, ret, popt_fn_pvt); -+ if (ret != EOK) { -+ ret = EXIT_FAILURE; -+ goto done; -+ } -+ } else { -+ fprintf(stderr, _("Invalid option %s: %s\n\n"), -+ poptBadOption(pc, 0), poptStrerror(ret)); -+ poptPrintHelp(pc, stderr, 0); -+ ret = EXIT_FAILURE; -+ goto done; -+ } -+ } -+ -+ /* Parse free option which is always required if requested. */ -+ if (_fopt != NULL) { -+ *_fopt = poptGetArg(pc); -+ if (*_fopt == NULL) { -+ fprintf(stderr, _("Missing option: %s\n\n"), fopt_help); -+ poptPrintHelp(pc, stderr, 0); -+ ret = EXIT_FAILURE; -+ goto done; -+ } -+ -+ /* No more arguments expected. If something follows it is an error. */ -+ if (poptGetArg(pc)) { -+ fprintf(stderr, _("Only one free argument is expected!\n\n")); -+ poptPrintHelp(pc, stderr, 0); -+ ret = EXIT_FAILURE; -+ goto done; -+ } -+ } -+ -+ /* If at least one option is required and not provided, print error. */ -+ if (require_option == SSS_TOOL_OPT_REQUIRED -+ && ((_fopt != NULL && cmdline->argc < 2) || cmdline->argc < 1)) { -+ fprintf(stderr, _("At least one option is required!\n\n")); -+ poptPrintHelp(pc, stderr, 0); -+ ret = EXIT_FAILURE; -+ goto done; -+ } -+ -+ ret = EXIT_SUCCESS; -+ -+done: -+ poptFreeContext(pc); -+ talloc_free(help); -+ return ret; -+} -+ -+int sss_tool_popt(struct sss_cmdline *cmdline, -+ struct poptOption *options, -+ enum sss_tool_opt require_option, -+ sss_popt_fn popt_fn, -+ void *popt_fn_pvt) -+{ -+ return sss_tool_popt_ex(cmdline, options, require_option, -+ popt_fn, popt_fn_pvt, NULL, NULL, NULL); -+} -+ -+int sss_tool_main(int argc, const char **argv, -+ struct sss_route_cmd *commands, -+ void *pvt) -+{ -+ struct sss_tool_ctx *tool_ctx; -+ uid_t uid; -+ int ret; -+ -+ uid = getuid(); -+ if (uid != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Running under %d, must be root\n", uid); -+ ERROR("%1$s must be run as root\n", argv[0]); -+ return EXIT_FAILURE; -+ } -+ -+ tool_ctx = sss_tool_init(NULL, &argc, argv); -+ if (tool_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tool context\n"); -+ return EXIT_FAILURE; -+ } -+ -+ ret = sss_tool_route(argc, argv, tool_ctx, commands, pvt); -+ talloc_free(tool_ctx); -+ -+ return ret; -+} -+ -+int sss_tool_parse_name(TALLOC_CTX *mem_ctx, -+ struct sss_tool_ctx *tool_ctx, -+ const char *input, -+ const char **_username, -+ struct sss_domain_info **_domain) -+{ -+ char *username = NULL; -+ char *domname = NULL; -+ struct sss_domain_info *domain; -+ int ret; -+ -+ ret = sss_parse_name_for_domains(mem_ctx, tool_ctx->domains, -+ tool_ctx->default_domain, input, -+ &domname, &username); -+ if (ret == EAGAIN) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find domain. The domain name may " -+ "be a subdomain that was not yet found.\n"); -+ goto done; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ domain = find_domain_by_name(tool_ctx->domains, domname, true); -+ -+ *_username = username; -+ *_domain = domain; -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_zfree(username); -+ talloc_zfree(domname); -+ } -+ -+ return ret; -+} -diff --git a/src/tools/common/sss_tools.h b/src/tools/common/sss_tools.h -new file mode 100644 -index 0000000000000000000000000000000000000000..cfe11d06e1dadf8e49efe155c8a53f99a31e97fb ---- /dev/null -+++ b/src/tools/common/sss_tools.h -@@ -0,0 +1,91 @@ -+/* -+ Authors: -+ Pavel Březina -+ -+ Copyright (C) 2015 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#ifndef _SSS_TOOLS_H_ -+#define _SSS_TOOLS_H_ -+ -+#include -+#include -+ -+#include "confdb/confdb.h" -+ -+struct sss_tool_ctx { -+ struct confdb_ctx *confdb; -+ -+ char *default_domain; -+ struct sss_domain_info *domains; -+}; -+ -+struct sss_tool_ctx *sss_tool_init(TALLOC_CTX *mem_ctx, -+ int *argc, const char **argv); -+ -+struct sss_cmdline; -+ -+typedef int -+(*sss_route_fn)(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt); -+ -+struct sss_route_cmd { -+ const char *command; -+ sss_route_fn fn; -+}; -+ -+int sss_tool_usage(const char *tool_name, -+ struct sss_route_cmd *commands); -+ -+int sss_tool_route(int argc, const char **argv, -+ struct sss_tool_ctx *tool_ctx, -+ struct sss_route_cmd *commands, -+ void *pvt); -+ -+typedef int (*sss_popt_fn)(poptContext pc, char option, void *pvt); -+ -+enum sss_tool_opt { -+ SSS_TOOL_OPT_REQUIRED, -+ SSS_TOOL_OPT_OPTIONAL -+}; -+ -+int sss_tool_popt_ex(struct sss_cmdline *cmdline, -+ struct poptOption *options, -+ enum sss_tool_opt require_option, -+ sss_popt_fn popt_fn, -+ void *popt_fn_pvt, -+ const char *free_opt_name, -+ const char *free_opt_help, -+ const char **_free_opt); -+ -+int sss_tool_popt(struct sss_cmdline *cmdline, -+ struct poptOption *options, -+ enum sss_tool_opt require_option, -+ sss_popt_fn popt_fn, -+ void *popt_fn_pvt); -+ -+int sss_tool_main(int argc, const char **argv, -+ struct sss_route_cmd *commands, -+ void *pvt); -+ -+int sss_tool_parse_name(TALLOC_CTX *mem_ctx, -+ struct sss_tool_ctx *tool_ctx, -+ const char *input, -+ const char **_username, -+ struct sss_domain_info **_domain); -+ -+#endif /* SRC_TOOLS_COMMON_SSS_TOOLS_H_ */ --- -2.4.3 - diff --git a/SOURCES/0023-TOOLS-add-sss_override-for-local-overrides.patch b/SOURCES/0023-TOOLS-add-sss_override-for-local-overrides.patch deleted file mode 100644 index ebf1051..0000000 --- a/SOURCES/0023-TOOLS-add-sss_override-for-local-overrides.patch +++ /dev/null @@ -1,939 +0,0 @@ -From a3b608a72f2cba3cece3a28dbc1c5d532d91ce14 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 24 Jul 2015 09:58:11 +0200 -Subject: [PATCH 23/23] TOOLS: add sss_override for local overrides - -Resolves: -https://fedorahosted.org/sssd/ticket/2584 - -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 16 +- - contrib/sssd.spec.in | 2 + - src/man/Makefile.am | 1 + - src/man/po/po4a.cfg | 1 + - src/man/sss_override.8.xml | 108 +++++++ - src/tools/sss_override.c | 718 +++++++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 845 insertions(+), 1 deletion(-) - create mode 100644 src/man/sss_override.8.xml - create mode 100644 src/tools/sss_override.c - -diff --git a/Makefile.am b/Makefile.am -index 1edecc483c61d04562b7bfd9086146e93963b74e..912bfc6641465ef5cd2ff2cce9975b4027c3218d 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -117,7 +117,9 @@ sbin_PROGRAMS = \ - sss_groupshow \ - sss_cache \ - sss_debuglevel \ -- sss_seed -+ sss_override \ -+ sss_seed \ -+ $(NULL) - - sssdlibexec_PROGRAMS = \ - sssd_nss \ -@@ -1297,6 +1299,18 @@ sss_signal_LDADD = \ - $(SSSD_INTERNAL_LTLIBS) \ - $(NULL) - -+sss_override_SOURCES = \ -+ src/tools/sss_override.c \ -+ $(SSSD_TOOLS_OBJ) \ -+ $(NULL) -+sss_override_LDADD = \ -+ $(TOOLS_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ $(NULL) -+sss_override_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(NULL) -+ - if BUILD_SUDO - sss_sudo_cli_SOURCES = \ - src/sss_client/common.c \ -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 15f7c582cba1b9052e180596625be7dd5749599f..f050501ff9d0711a0da7f094ee968cae87a3f49b 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -837,6 +837,7 @@ rm -rf $RPM_BUILD_ROOT - %{_sbindir}/sss_groupmod - %{_sbindir}/sss_groupshow - %{_sbindir}/sss_obfuscate -+%{_sbindir}/sss_override - %{_sbindir}/sss_debuglevel - %{_sbindir}/sss_seed - %{_mandir}/man8/sss_groupadd.8* -@@ -847,6 +848,7 @@ rm -rf $RPM_BUILD_ROOT - %{_mandir}/man8/sss_userdel.8* - %{_mandir}/man8/sss_usermod.8* - %{_mandir}/man8/sss_obfuscate.8* -+%{_mandir}/man8/sss_override.8* - %{_mandir}/man8/sss_debuglevel.8* - %{_mandir}/man8/sss_seed.8* - -diff --git a/src/man/Makefile.am b/src/man/Makefile.am -index 1ef1da48cce74f7d1ad77e3751ee6ac3450f0259..70cadf5951f56b78ff0bfbcb303e255478af5fec 100644 ---- a/src/man/Makefile.am -+++ b/src/man/Makefile.am -@@ -51,6 +51,7 @@ man_MANS = \ - sssd-krb5.5 sssd-simple.5 \ - sssd_krb5_locator_plugin.8 sss_groupshow.8 \ - pam_sss.8 sss_obfuscate.8 sss_cache.8 sss_debuglevel.8 sss_seed.8 \ -+ sss_override.8 - $(NULL) - - if BUILD_SAMBA -diff --git a/src/man/po/po4a.cfg b/src/man/po/po4a.cfg -index 25d20c6f0c23a0900469573d47ab96ebc8898e50..67e87ba7006f0bb1346e5b845428f2bed1a324db 100644 ---- a/src/man/po/po4a.cfg -+++ b/src/man/po/po4a.cfg -@@ -11,6 +11,7 @@ - [type:docbook] sssd-sudo.5.xml $lang:$(builddir)/$lang/sssd-sudo.5.xml - [type:docbook] sssd.8.xml $lang:$(builddir)/$lang/sssd.8.xml - [type:docbook] sss_obfuscate.8.xml $lang:$(builddir)/$lang/sss_obfuscate.8.xml -+[type:docbook] sss_override.8.xml $lang:$(builddir)/$lang/sss_override.8.xml - [type:docbook] sss_useradd.8.xml $lang:$(builddir)/$lang/sss_useradd.8.xml - [type:docbook] sssd-krb5.5.xml $lang:$(builddir)/$lang/sssd-krb5.5.xml - [type:docbook] sss_groupadd.8.xml $lang:$(builddir)/$lang/sss_groupadd.8.xml -diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml -new file mode 100644 -index 0000000000000000000000000000000000000000..ec9a7bb75c13f4f18ece7f5f84baede14a8a1e2e ---- /dev/null -+++ b/src/man/sss_override.8.xml -@@ -0,0 +1,108 @@ -+ -+ -+ -+SSSD Manual pages -+ -+ -+ -+ -+ sss_override -+ 8 -+ -+ -+ -+ sss_override -+ create local overrides of user and group attributes -+ -+ -+ -+ -+ sss_override -+ COMMAND -+ -+ options -+ -+ -+ -+ -+ -+ DESCRIPTION -+ -+ sss_override enables to create a client-side -+ view and allows to change selected values of specific user -+ and groups. This change takes effect only on local machine. -+ -+ -+ Overrides data are stored in SSSD cache. If the cache is deleted -+ all local overrides are lost. -+ -+ -+ -+ -+ AVAILABLE COMMANDS -+ -+ Argument NAME is the name of original object -+ in all commands. It is not possible to override -+ uid or gid to 0. -+ -+ -+ -+ -+ -+ NAME -+ NAME -+ UID -+ GID -+ HOME -+ SHELL -+ GECOS -+ -+ -+ -+ Override attributes of an user. -+ -+ -+ -+ -+ -+ -+ NAME -+ -+ -+ -+ Remove user overrides. -+ -+ -+ -+ -+ -+ -+ NAME -+ NAME -+ GID -+ -+ -+ -+ Override attributes of a group. -+ -+ -+ -+ -+ -+ -+ NAME -+ -+ -+ -+ Remove group overrides. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c -new file mode 100644 -index 0000000000000000000000000000000000000000..5e901e2e31de64dacb171337defc03d428f8ed57 ---- /dev/null -+++ b/src/tools/sss_override.c -@@ -0,0 +1,718 @@ -+/* -+ Authors: -+ Pavel Březina -+ -+ Copyright (C) 2015 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+ -+#include "util/util.h" -+#include "db/sysdb.h" -+#include "tools/common/sss_tools.h" -+ -+#define LOCALVIEW SYSDB_LOCAL_VIEW_NAME -+ -+struct override_user { -+ const char *input_name; -+ const char *orig_name; -+ struct sss_domain_info *domain; -+ -+ const char *name; -+ uid_t uid; -+ gid_t gid; -+ const char *home; -+ const char *shell; -+ const char *gecos; -+}; -+ -+struct override_group { -+ const char *input_name; -+ const char *orig_name; -+ struct sss_domain_info *domain; -+ -+ const char *name; -+ gid_t gid; -+}; -+ -+static int parse_cmdline(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ struct poptOption *options, -+ const char **_input_name, -+ const char **_orig_name, -+ struct sss_domain_info **_domain) -+{ -+ enum sss_tool_opt require; -+ const char *input_name; -+ const char *orig_name; -+ struct sss_domain_info *domain; -+ int ret; -+ -+ require = options == NULL ? SSS_TOOL_OPT_OPTIONAL : SSS_TOOL_OPT_REQUIRED; -+ -+ ret = sss_tool_popt_ex(cmdline, options, require, -+ NULL, NULL, "NAME", _("Specify name of modified " -+ "object."), &input_name); -+ if (ret != EXIT_SUCCESS) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); -+ return ret; -+ } -+ -+ ret = sss_tool_parse_name(tool_ctx, tool_ctx, input_name, -+ &orig_name, &domain); -+ if (ret != EOK) { -+ fprintf(stderr, _("Unable to parse name.\n")); -+ return ret; -+ } -+ -+ *_input_name = input_name; -+ *_orig_name = orig_name; -+ *_domain = domain; -+ -+ return EXIT_SUCCESS; -+} -+ -+static int parse_cmdline_user_add(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ struct override_user *user) -+{ -+ struct poptOption options[] = { -+ POPT_AUTOHELP -+ {"name", 'n', POPT_ARG_STRING, &user->name, 0, _("Override name"), NULL }, -+ {"uid", 'u', POPT_ARG_INT, &user->uid, 0, _("Override uid (non-zero value)"), NULL }, -+ {"gid", 'g', POPT_ARG_INT, &user->gid, 0, _("Override gid (non-zero value)"), NULL }, -+ {"home", 'h', POPT_ARG_STRING, &user->home, 0, _("Override home directory"), NULL }, -+ {"shell", 's', POPT_ARG_STRING, &user->shell, 0, _("Override shell"), NULL }, -+ {"gecos", 'c', POPT_ARG_STRING, &user->gecos, 0, _("Override gecos"), NULL }, -+ POPT_TABLEEND -+ }; -+ -+ return parse_cmdline(cmdline, tool_ctx, options, &user->input_name, -+ &user->orig_name, &user->domain); -+} -+ -+static int parse_cmdline_user_del(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ struct override_user *user) -+{ -+ return parse_cmdline(cmdline, tool_ctx, NULL, &user->input_name, -+ &user->orig_name, &user->domain); -+} -+ -+static int parse_cmdline_group_add(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ struct override_group *group) -+{ -+ struct poptOption options[] = { -+ POPT_AUTOHELP -+ {"name", 'n', POPT_ARG_STRING, &group->name, 0, _("Override name"), NULL }, -+ {"gid", 'g', POPT_ARG_INT, &group->gid, 0, _("Override gid"), NULL }, -+ POPT_TABLEEND -+ }; -+ -+ return parse_cmdline(cmdline, tool_ctx, options, &group->input_name, -+ &group->orig_name, &group->domain); -+} -+ -+static int parse_cmdline_group_del(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ struct override_group *group) -+{ -+ return parse_cmdline(cmdline, tool_ctx, NULL, &group->input_name, -+ &group->orig_name, &group->domain); -+} -+ -+static errno_t prepare_view(struct sss_domain_info *domain) -+{ -+ char *viewname = NULL; -+ errno_t ret; -+ -+ ret = sysdb_get_view_name(NULL, domain->sysdb, &viewname); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name() failed.\n"); -+ return ret; -+ } -+ -+ if (ret == EOK) { -+ if (is_local_view(viewname)) { -+ DEBUG(SSSDBG_TRACE_FUNC, "%s view is already present.\n", viewname); -+ ret = EOK; -+ goto done; -+ } else if (viewname != NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "There already exists view %s. " -+ "Only one view is supported. Nothing to do.\n", viewname); -+ ret = EEXIST; -+ goto done; -+ } -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Creating %s view.\n", LOCALVIEW); -+ -+ ret = sysdb_update_view_name(domain->sysdb, LOCALVIEW); -+ if (ret == EOK) { -+ printf("SSSD needs to be restarted for the changes to take effect.\n"); -+ } -+ -+done: -+ talloc_free(viewname); -+ return ret; -+} -+ -+static char *build_anchor(TALLOC_CTX *mem_ctx, const char *obj_dn) -+{ -+ char *anchor; -+ char *safe_dn; -+ errno_t ret; -+ -+ ret = sysdb_dn_sanitize(mem_ctx, obj_dn, &safe_dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_dn_sanitize() failed\n"); -+ return NULL; -+ } -+ -+ anchor = talloc_asprintf(mem_ctx, ":%s:%s", LOCALVIEW, safe_dn); -+ -+ talloc_free(safe_dn); -+ -+ return anchor; -+} -+ -+static struct sysdb_attrs *build_attrs(TALLOC_CTX *mem_ctx, -+ const char *name, -+ uid_t uid, -+ gid_t gid, -+ const char *home, -+ const char *shell, -+ const char *gecos) -+{ -+ struct sysdb_attrs *attrs; -+ errno_t ret; -+ -+ attrs = sysdb_new_attrs(mem_ctx); -+ if (attrs == NULL) { -+ return NULL; -+ } -+ -+ if (name != NULL) { -+ ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ if (uid != 0) { -+ ret = sysdb_attrs_add_uint32(attrs, SYSDB_UIDNUM, uid); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ if (gid != 0) { -+ ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ if (home != NULL) { -+ ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, home); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ if (shell != NULL) { -+ ret = sysdb_attrs_add_string(attrs, SYSDB_SHELL, shell); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ if (gecos != NULL) { -+ ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, gecos); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(attrs); -+ return NULL; -+ } -+ -+ return attrs; -+} -+ -+static struct sysdb_attrs *build_user_attrs(TALLOC_CTX *mem_ctx, -+ struct override_user *user) -+{ -+ return build_attrs(mem_ctx, user->name, user->uid, user->gid, user->home, -+ user->shell, user->gecos); -+} -+ -+static struct sysdb_attrs *build_group_attrs(TALLOC_CTX *mem_ctx, -+ struct override_group *group) -+{ -+ return build_attrs(mem_ctx, group->name, 0, group->gid, 0, NULL, NULL); -+} -+ -+static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx, -+ enum sysdb_member_type type, -+ const char *name, -+ struct sss_domain_info *domain, -+ struct sss_domain_info *domains, -+ struct sss_domain_info **_new_domain) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct sss_domain_info *dom; -+ struct ldb_result *res; -+ const char *dn; -+ const char *strtype; -+ bool check_next; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return NULL; -+ } -+ -+ /* Ensure that the object is in cache. */ -+ switch (type) { -+ case SYSDB_MEMBER_USER: -+ if (getpwnam(name) == NULL) { -+ ret = ENOENT; -+ goto done; -+ } -+ break; -+ case SYSDB_MEMBER_GROUP: -+ if (getgrnam(name) == NULL) { -+ ret = ENOENT; -+ goto done; -+ } -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ /* Find domain if it is unknown. */ -+ if (domain == NULL) { -+ check_next = true; -+ dom = domains; -+ } else { -+ check_next = false; -+ dom = domain; -+ } -+ -+ do { -+ switch (type) { -+ case SYSDB_MEMBER_USER: -+ DEBUG(SSSDBG_TRACE_FUNC, "Trying to find user %s@%s\n", -+ name, dom->name); -+ ret = sysdb_getpwnam(tmp_ctx, dom, name, &res); -+ strtype = "user"; -+ break; -+ case SYSDB_MEMBER_GROUP: -+ DEBUG(SSSDBG_TRACE_FUNC, "Trying to find group %s@%s\n", -+ name, dom->name); -+ ret = sysdb_getgrnam(tmp_ctx, dom, name, &res); -+ strtype = "group"; -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ if (ret == EOK && res->count == 0) { -+ ret = ENOENT; -+ -+ if (check_next) { -+ dom = dom->next; -+ continue; -+ } -+ } -+ -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find %s %s@%s [%d]: %s\n", -+ strtype, name, dom->name, ret, sss_strerror(ret)); -+ goto done; -+ } else if (res->count != 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "More than one %s found?\n", strtype); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ check_next = false; -+ } while (check_next && dom != NULL); -+ -+ if (dom == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "No domain match for %s\n", name); -+ ret = ENOENT; -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Domain of %s %s is %s\n", -+ strtype, name, dom->name); -+ -+ dn = ldb_dn_get_linearized(res->msgs[0]->dn); -+ if (dn == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized() failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ talloc_steal(mem_ctx, dn); -+ *_new_domain = dom; -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ if (ret != EOK) { -+ return NULL; -+ } -+ -+ return dn; -+} -+ -+static const char * get_user_dn_and_domain(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, -+ struct override_user *user) -+{ -+ return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_USER, -+ user->orig_name, user->domain, domains, -+ &user->domain); -+} -+ -+static const char * get_group_dn_and_domain(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domains, -+ struct override_group *group) -+{ -+ return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_GROUP, -+ group->orig_name, group->domain, domains, -+ &group->domain); -+} -+ -+static errno_t override_object_add(struct sss_domain_info *domain, -+ enum sysdb_member_type type, -+ struct sysdb_attrs *attrs, -+ const char *obj_dn) -+{ -+ TALLOC_CTX *tmp_ctx; -+ const char *anchor; -+ struct ldb_dn *ldb_dn; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ldb_dn = ldb_dn_new(tmp_ctx, sysdb_ctx_get_ldb(domain->sysdb), obj_dn); -+ if (ldb_dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ anchor = build_anchor(tmp_ctx, obj_dn); -+ if (anchor == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, anchor); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Creating override for %s\n", obj_dn); -+ -+ ret = sysdb_store_override(domain, LOCALVIEW, type, attrs, ldb_dn); -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t override_object_del(struct sss_domain_info *domain, -+ const char *obj_dn) -+{ -+ TALLOC_CTX *tmp_ctx; -+ const char *anchor; -+ struct ldb_dn *override_dn; -+ struct ldb_message *msg; -+ errno_t ret; -+ int sret; -+ bool in_transaction = false; -+ struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb); -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ anchor = build_anchor(tmp_ctx, obj_dn); -+ if (anchor == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ override_dn = ldb_dn_new_fmt(tmp_ctx, ldb, -+ SYSDB_TMPL_OVERRIDE, anchor, LOCALVIEW); -+ if (override_dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Removing override for %s\n", obj_dn); -+ -+ ret = sysdb_transaction_start(domain->sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start() failed.\n"); -+ goto done; -+ } -+ in_transaction = true; -+ -+ ret = sysdb_delete_entry(domain->sysdb, override_dn, true); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_entry() failed.\n"); -+ goto done; -+ } -+ -+ msg = ldb_msg_new(tmp_ctx); -+ if (msg == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ msg->dn = ldb_dn_new(msg, ldb, obj_dn); -+ if (msg->dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_DELETE, NULL); -+ if (ret != LDB_SUCCESS) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty() failed\n"); -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ ret = ldb_modify(ldb, msg); -+ if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "ldb_modify() failed: [%s](%d)[%s]\n", -+ ldb_strerror(ret), ret, ldb_errstring(ldb)); -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ ret = sysdb_transaction_commit(domain->sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); -+ goto done; -+ } -+ in_transaction = false; -+ -+ ret = EOK; -+ -+done: -+ if (in_transaction) { -+ sret = sysdb_transaction_cancel(domain->sysdb); -+ if (sret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); -+ } -+ } -+ -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static int override_user_add(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ struct override_user user = {NULL}; -+ struct sysdb_attrs *attrs; -+ const char *dn; -+ int ret; -+ -+ ret = parse_cmdline_user_add(cmdline, tool_ctx, &user); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user); -+ if (dn == NULL) { -+ fprintf(stderr, _("Unable to find user %s@%s.\n"), -+ user.orig_name, -+ user.domain == NULL ? "[unknown]" : user.domain->name); -+ return EXIT_FAILURE; -+ } -+ -+ ret = prepare_view(user.domain); -+ if (ret == EEXIST) { -+ fprintf(stderr, _("Other than LOCAL view already exist in " -+ "domain %s.\n"), user.domain->name); -+ return EXIT_FAILURE; -+ } else if (ret != EOK) { -+ fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"), -+ ret, sss_strerror(ret)); -+ return EXIT_FAILURE; -+ } -+ -+ attrs = build_user_attrs(tool_ctx, &user); -+ if (attrs == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ ret = override_object_add(user.domain, SYSDB_MEMBER_USER, attrs, dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ return EXIT_SUCCESS; -+} -+ -+static int override_user_del(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ struct override_user user = {NULL}; -+ const char *dn; -+ int ret; -+ -+ ret = parse_cmdline_user_del(cmdline, tool_ctx, &user); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user); -+ if (dn == NULL) { -+ fprintf(stderr, _("Unable to find user %s@%s.\n"), -+ user.orig_name, user.domain->name); -+ return EXIT_FAILURE; -+ } -+ -+ ret = override_object_del(user.domain, dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ return EXIT_SUCCESS; -+} -+ -+static int override_group_add(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ struct override_group group = {NULL}; -+ struct sysdb_attrs *attrs; -+ const char *dn; -+ int ret; -+ -+ ret = parse_cmdline_group_add(cmdline, tool_ctx, &group); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group); -+ if (dn == NULL) { -+ fprintf(stderr, _("Unable to find group %s@%s.\n"), -+ group.orig_name, group.domain->name); -+ return EXIT_FAILURE; -+ } -+ -+ ret = prepare_view(group.domain); -+ if (ret == EEXIST) { -+ fprintf(stderr, _("Other than LOCAL view already exist in " -+ "domain %s.\n"), group.domain->name); -+ return EXIT_FAILURE; -+ } else if (ret != EOK) { -+ fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"), -+ ret, sss_strerror(ret)); -+ return EXIT_FAILURE; -+ } -+ -+ attrs = build_group_attrs(tool_ctx, &group); -+ if (attrs == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ ret = override_object_add(group.domain, SYSDB_MEMBER_GROUP, attrs, dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ return EXIT_SUCCESS; -+} -+ -+static int override_group_del(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ struct override_group group = {NULL}; -+ const char *dn; -+ int ret; -+ -+ ret = parse_cmdline_group_del(cmdline, tool_ctx, &group); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group); -+ if (dn == NULL) { -+ fprintf(stderr, _("Unable to find group %s@%s.\n"), -+ group.orig_name, group.domain->name); -+ return EXIT_FAILURE; -+ } -+ -+ ret = override_object_del(group.domain, dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ return EXIT_SUCCESS; -+} -+ -+int main(int argc, const char **argv) -+{ -+ struct sss_route_cmd commands[] = { -+ {"user-add", override_user_add}, -+ {"user-del", override_user_del}, -+ {"group-add", override_group_add}, -+ {"group-del", override_group_del}, -+ {NULL, NULL} -+ }; -+ -+ return sss_tool_main(argc, argv, commands, NULL); -+} --- -2.4.3 - diff --git a/SOURCES/0023-sysdb-add-UPN-suffix-support-for-the-master-domain.patch b/SOURCES/0023-sysdb-add-UPN-suffix-support-for-the-master-domain.patch new file mode 100644 index 0000000..f58a855 --- /dev/null +++ b/SOURCES/0023-sysdb-add-UPN-suffix-support-for-the-master-domain.patch @@ -0,0 +1,277 @@ +From 2ffd083501491a8ac3880dc834d01f7ee00fddfc Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 30 Jun 2016 13:48:58 +0200 +Subject: [PATCH 23/27] sysdb: add UPN suffix support for the master domain + +sysdb_master_domain_update() and sysdb_master_domain_add_info() are now +aware of the UPN suffix attribute. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 132b31fd5fb74a7627896cdceaf29c7601ed4795) +--- + src/confdb/confdb.h | 1 + + src/db/sysdb.h | 4 ++- + src/db/sysdb_subdomains.c | 49 ++++++++++++++++++++++++++++++-- + src/providers/ad/ad_id.c | 2 +- + src/providers/ad/ad_subdomains.c | 2 +- + src/providers/ipa/ipa_subdomains.c | 10 ++++++- + src/tests/cmocka/test_sysdb_subdomains.c | 18 ++++++++---- + 7 files changed, 74 insertions(+), 12 deletions(-) + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index cc8f66f02eb5ac10ced826326f80bbf5eda82ee1..0265ccac5ee2e7b8baa05bf6b09df39ea5b4059a 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -315,6 +315,7 @@ struct sss_domain_info { + */ + char *forest; + struct sss_domain_info *forest_root; ++ char **upn_suffixes; + }; + + /** +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 609921fbb0f29561d7e52e8d1404a929af3c5b26..a8dcaa4a9ac5715150487f7efc9c35b778fa0163 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -147,6 +147,7 @@ + #define SYSDB_SUBDOMAIN_ENUM "enumerate" + #define SYSDB_SUBDOMAIN_FOREST "memberOfForest" + #define SYSDB_SUBDOMAIN_TRUST_DIRECTION "trustDirection" ++#define SYSDB_UPN_SUFFIXES "upnSuffixes" + + #define SYSDB_BASE_ID "baseID" + #define SYSDB_ID_RANGE_SIZE "idRangeSize" +@@ -475,7 +476,8 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, + const char *realm, + const char *flat, + const char *id, +- const char* forest); ++ const char *forest, ++ struct ldb_message_element *alt_dom_suf); + + 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 456e6621b3434a9dbf2e611ad880facbc171c174..c0a190f36d886325a5be1e5d1145b6aef6860ffc 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -448,6 +448,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain) + errno_t ret; + TALLOC_CTX *tmp_ctx; + const char *tmp_str; ++ struct ldb_message_element **tmp_el; + struct ldb_dn *basedn; + struct ldb_result *res; + const char *attrs[] = {"cn", +@@ -455,6 +456,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain) + SYSDB_SUBDOMAIN_FLAT, + SYSDB_SUBDOMAIN_ID, + SYSDB_SUBDOMAIN_FOREST, ++ SYSDB_UPN_SUFFIXES, + NULL}; + char *view_name = NULL; + +@@ -539,6 +541,19 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain) + } + } + ++ tmp_el = ldb_msg_find_element(res->msgs[0], SYSDB_UPN_SUFFIXES); ++ if (tmp_el != NULL) { ++ talloc_free(domain->upn_suffixes); ++ domain->upn_suffixes = sss_ldb_el_to_string_list(domain, tmp_el); ++ if (domain->upn_suffixes == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sss_ldb_el_to_string_list failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } else { ++ talloc_zfree(domain->upn_suffixes); ++ } ++ + ret = sysdb_get_view_name(tmp_ctx, domain->sysdb, &view_name); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name failed.\n"); +@@ -633,7 +648,8 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, + const char *realm, + const char *flat, + const char *id, +- const char* forest) ++ const char *forest, ++ struct ldb_message_element *upn_suffixes) + { + TALLOC_CTX *tmp_ctx; + struct ldb_message *msg; +@@ -720,7 +736,6 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, + ret = sysdb_error_to_errno(ret); + goto done; + } +- + ret = ldb_msg_add_string(msg, SYSDB_SUBDOMAIN_REALM, realm); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); +@@ -730,6 +745,36 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, + do_update = true; + } + ++ if (upn_suffixes != NULL) { ++ talloc_free(discard_const(upn_suffixes->name)); ++ upn_suffixes->name = talloc_strdup(upn_suffixes, SYSDB_UPN_SUFFIXES); ++ if (upn_suffixes->name == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = ldb_msg_add(msg, upn_suffixes, LDB_FLAG_MOD_REPLACE); ++ if (ret != LDB_SUCCESS) { ++ ret = sysdb_error_to_errno(ret); ++ goto done; ++ } ++ ++ do_update = true; ++ } else { ++ /* Remove alternative_domain_suffixes from the cache */ ++ if (domain->upn_suffixes != NULL) { ++ ret = ldb_msg_add_empty(msg, SYSDB_UPN_SUFFIXES, ++ LDB_FLAG_MOD_DELETE, NULL); ++ 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_id.c b/src/providers/ad/ad_id.c +index 92ac4ab6a13d7094f7a663b4a070feea3be09571..98915b4b966e2665dbd34257e4002d72b95d76b2 100644 +--- a/src/providers/ad/ad_id.c ++++ b/src/providers/ad/ad_id.c +@@ -631,7 +631,7 @@ ad_enumeration_master_done(struct tevent_req *subreq) + } + + ret = sysdb_master_domain_add_info(state->sdom->dom, state->realm, +- flat_name, master_sid, forest); ++ flat_name, master_sid, forest, NULL); + 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 05dfc3085fb14a87b5703518d784056b71bf5de0..0a8d1f53cb005507abe4ac55d0fa1ccc9e32b173 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -1131,7 +1131,7 @@ static void ad_subdomains_refresh_master_done(struct tevent_req *subreq) + } + + ret = sysdb_master_domain_add_info(state->be_ctx->domain, realm, +- flat_name, master_sid, forest); ++ flat_name, master_sid, forest, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot save master domain info [%d]: %s\n", + ret, sss_strerror(ret)); +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index 263d6207960c232d08114bd0163b3fd03a690685..62b8f65e5d29a4850f90ea7c19abd297becc96f5 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -855,6 +855,7 @@ static void ipa_subdomains_master_done(struct tevent_req *subreq) + const char *flat = NULL; + const char *id = NULL; + const char *realm = NULL; ++ struct ldb_message_element *alternative_domain_suffixes = NULL; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); +@@ -879,6 +880,12 @@ static void ipa_subdomains_master_done(struct tevent_req *subreq) + if (ret != EOK) { + goto done; + } ++ ++ ret = sysdb_attrs_get_el_ext(reply[0], IPA_ADDITIONAL_SUFFIXES, false, ++ &alternative_domain_suffixes); ++ if (ret != EOK && ret != ENOENT) { ++ goto done; ++ } + } else { + /* All search paths are searched and no master domain record was + * found. +@@ -896,7 +903,8 @@ static void ipa_subdomains_master_done(struct tevent_req *subreq) + goto done; + } + +- ret = sysdb_master_domain_add_info(state->domain, realm, flat, id, NULL); ++ ret = sysdb_master_domain_add_info(state->domain, realm, flat, id, NULL, ++ alternative_domain_suffixes); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add master domain info " + "[%d]: %s\n", ret, sss_strerror(ret)); +diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c +index f55c2918015900351483e3471bf946ea60872dae..6d1ec884284487a12bcbfad77c00cd6c30f67707 100644 +--- a/src/tests/cmocka/test_sysdb_subdomains.c ++++ b/src/tests/cmocka/test_sysdb_subdomains.c +@@ -165,7 +165,8 @@ static void test_sysdb_master_domain_ops(void **state) + talloc_get_type(*state, struct subdom_test_ctx); + + ret = sysdb_master_domain_add_info(test_ctx->tctx->dom, +- "realm1", "flat1", "id1", "forest1"); ++ "realm1", "flat1", "id1", "forest1", ++ NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_master_domain_update(test_ctx->tctx->dom); +@@ -177,7 +178,8 @@ static void test_sysdb_master_domain_ops(void **state) + assert_string_equal(test_ctx->tctx->dom->forest, "forest1"); + + ret = sysdb_master_domain_add_info(test_ctx->tctx->dom, +- "realm2", "flat2", "id2", "forest2"); ++ "realm2", "flat2", "id2", "forest2", ++ NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_master_domain_update(test_ctx->tctx->dom); +@@ -298,7 +300,8 @@ static void test_sysdb_link_forest_root_ad(void **state) + TEST_REALM, + TEST_FLAT_NAME, + TEST_SID, +- TEST_FOREST); ++ TEST_FOREST, ++ NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, +@@ -374,7 +377,8 @@ static void test_sysdb_link_forest_member_ad(void **state) + child_dom[1], + child_dom[2], + child_dom[3], +- TEST_FOREST); ++ TEST_FOREST, ++ NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, +@@ -457,7 +461,8 @@ static void test_sysdb_link_ad_multidom(void **state) + TEST_REALM, + TEST_FLAT_NAME, + TEST_SID, +- TEST_FOREST); ++ TEST_FOREST, ++ NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(main_dom1->sysdb, +@@ -477,7 +482,8 @@ static void test_sysdb_link_ad_multidom(void **state) + TEST_REALM2, + TEST_FLAT_NAME2, + TEST_SID2, +- TEST_FOREST2); ++ TEST_FOREST2, ++ NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(main_dom2->sysdb, +-- +2.4.11 + diff --git a/SOURCES/0024-IPA-Better-debugging.patch b/SOURCES/0024-IPA-Better-debugging.patch deleted file mode 100644 index d589ad3..0000000 --- a/SOURCES/0024-IPA-Better-debugging.patch +++ /dev/null @@ -1,27 +0,0 @@ -From a42ad73cc1aca7b923c3a7ebd01580378888f002 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Jul 2015 15:17:57 +0200 -Subject: [PATCH 24/27] IPA: Better debugging - -Reviewed-by: Alexander Bokovoy ---- - src/providers/ipa/ipa_subdomains_server.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c -index cd8c6301c4e4fbbf194ca98ce7a7bfe6215b381c..a9e2c1f700ef47716be868bad68590b8d5d0d42a 100644 ---- a/src/providers/ipa/ipa_subdomains_server.c -+++ b/src/providers/ipa/ipa_subdomains_server.c -@@ -623,6 +623,9 @@ ipa_server_trust_add_send(TALLOC_CTX *mem_ctx, - - immediate: - if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not add trusted subdomain %s from forest %s\n", -+ subdom->name, state->forest); - tevent_req_error(req, ret); - } else { - tevent_req_done(req); --- -2.4.3 - diff --git a/SOURCES/0024-sysdb-make-subdomain-calls-aware-of-upn_suffixes.patch b/SOURCES/0024-sysdb-make-subdomain-calls-aware-of-upn_suffixes.patch new file mode 100644 index 0000000..4b900cf --- /dev/null +++ b/SOURCES/0024-sysdb-make-subdomain-calls-aware-of-upn_suffixes.patch @@ -0,0 +1,428 @@ +From f3be4b46d39c1a0106b60d561bbdeee4c80961aa Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 1 Jul 2016 12:54:39 +0200 +Subject: [PATCH 24/27] sysdb: make subdomain calls aware of upn_suffixes + +sysdb_subdomain_store() and sysdb_update_subdomains() can now update +upn_suffixes as well. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 20348a30feb4be619b3b691c24c9be8131507c46) +--- + src/confdb/confdb.h | 2 +- + src/db/sysdb.h | 3 +- + src/db/sysdb_subdomains.c | 56 +++++++++++++++++++++++++-- + src/providers/ad/ad_subdomains.c | 2 +- + src/providers/ipa/ipa_subdomains.c | 9 ++++- + src/tests/cmocka/test_ipa_subdomains_server.c | 4 +- + src/tests/cmocka/test_nss_srv.c | 2 +- + src/tests/cmocka/test_sysdb_subdomains.c | 28 +++++++------- + src/tests/sysdb-tests.c | 6 +-- + 9 files changed, 85 insertions(+), 27 deletions(-) + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index 0265ccac5ee2e7b8baa05bf6b09df39ea5b4059a..72adbd80ea534eb0becd3e517c00b0c26d00444c 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -315,7 +315,7 @@ struct sss_domain_info { + */ + char *forest; + struct sss_domain_info *forest_root; +- char **upn_suffixes; ++ const char **upn_suffixes; + }; + + /** +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index a8dcaa4a9ac5715150487f7efc9c35b778fa0163..407ce3c18a7077e8fe45c3c9c7576ae626105122 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -466,7 +466,8 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, + const char *name, const char *realm, + const char *flat_name, const char *domain_id, + bool mpg, bool enumerate, const char *forest, +- uint32_t trust_direction); ++ uint32_t trust_direction, ++ struct ldb_message_element *upn_suffixes); + + errno_t sysdb_update_subdomains(struct sss_domain_info *domain); + +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index c0a190f36d886325a5be1e5d1145b6aef6860ffc..02206e470e8e035cc05848137df6a1eb04806869 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -237,6 +237,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) + SYSDB_SUBDOMAIN_ENUM, + SYSDB_SUBDOMAIN_FOREST, + SYSDB_SUBDOMAIN_TRUST_DIRECTION, ++ SYSDB_UPN_SUFFIXES, + NULL}; + struct sss_domain_info *dom; + struct ldb_dn *basedn; +@@ -248,6 +249,8 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) + bool mpg; + bool enumerate; + uint32_t trust_direction; ++ struct ldb_message_element *tmp_el; ++ const char **upn_suffixes; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { +@@ -308,6 +311,17 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) + forest = ldb_msg_find_attr_as_string(res->msgs[i], + SYSDB_SUBDOMAIN_FOREST, NULL); + ++ upn_suffixes = NULL; ++ tmp_el = ldb_msg_find_element(res->msgs[0], SYSDB_UPN_SUFFIXES); ++ if (tmp_el != NULL) { ++ upn_suffixes = sss_ldb_el_to_string_list(tmp_ctx, tmp_el); ++ if (upn_suffixes == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sss_ldb_el_to_string_list failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ + trust_direction = ldb_msg_find_attr_as_int(res->msgs[i], + SYSDB_SUBDOMAIN_TRUST_DIRECTION, + 0); +@@ -382,6 +396,9 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) + } + } + ++ talloc_zfree(dom->upn_suffixes); ++ dom->upn_suffixes = talloc_steal(dom, upn_suffixes); ++ + if (!dom->has_views && dom->view_name == NULL) { + /* maybe views are not initialized, copy from parent */ + dom->has_views = dom->parent->has_views; +@@ -448,7 +465,7 @@ errno_t sysdb_master_domain_update(struct sss_domain_info *domain) + errno_t ret; + TALLOC_CTX *tmp_ctx; + const char *tmp_str; +- struct ldb_message_element **tmp_el; ++ struct ldb_message_element *tmp_el; + struct ldb_dn *basedn; + struct ldb_result *res; + const char *attrs[] = {"cn", +@@ -806,7 +823,8 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, + const char *name, const char *realm, + const char *flat_name, const char *domain_id, + bool mpg, bool enumerate, const char *forest, +- uint32_t trust_direction) ++ uint32_t trust_direction, ++ struct ldb_message_element *upn_suffixes) + { + TALLOC_CTX *tmp_ctx; + struct ldb_message *msg; +@@ -820,8 +838,10 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, + SYSDB_SUBDOMAIN_ENUM, + SYSDB_SUBDOMAIN_FOREST, + SYSDB_SUBDOMAIN_TRUST_DIRECTION, ++ SYSDB_UPN_SUFFIXES, + NULL}; + const char *tmp_str; ++ struct ldb_message_element *tmp_el; + bool tmp_bool; + bool store = false; + int realm_flags = 0; +@@ -831,6 +851,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, + int enum_flags = 0; + int forest_flags = 0; + int td_flags = 0; ++ int upn_flags = 0; + uint32_t tmp_td; + int ret; + +@@ -864,6 +885,7 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, + enum_flags = LDB_FLAG_MOD_ADD; + if (forest) forest_flags = LDB_FLAG_MOD_ADD; + if (trust_direction) td_flags = LDB_FLAG_MOD_ADD; ++ if (upn_suffixes) upn_flags = LDB_FLAG_MOD_ADD; + } else if (res->count != 1) { + ret = EINVAL; + goto done; +@@ -915,11 +937,21 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, + if (tmp_td != trust_direction) { + td_flags = LDB_FLAG_MOD_REPLACE; + } ++ ++ if (upn_suffixes) { ++ tmp_el = ldb_msg_find_element(res->msgs[0], SYSDB_UPN_SUFFIXES); ++ /* Luckily ldb_msg_element_compare() only compares the values and ++ * not the name. */ ++ if (tmp_el == NULL ++ || ldb_msg_element_compare(upn_suffixes, tmp_el) != 0) { ++ upn_flags = LDB_FLAG_MOD_REPLACE; ++ } ++ } + } + + if (!store && realm_flags == 0 && flat_flags == 0 && id_flags == 0 + && mpg_flags == 0 && enum_flags == 0 && forest_flags == 0 +- && td_flags == 0) { ++ && td_flags == 0 && upn_flags == 0) { + ret = EOK; + goto done; + } +@@ -1048,6 +1080,24 @@ errno_t sysdb_subdomain_store(struct sysdb_ctx *sysdb, + } + } + ++ if (upn_flags) { ++ tmp_el = talloc_zero(tmp_ctx, struct ldb_message_element); ++ if (tmp_el == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ tmp_el->name = SYSDB_UPN_SUFFIXES; ++ tmp_el->num_values = upn_suffixes->num_values; ++ tmp_el->values = upn_suffixes->values; ++ ret = ldb_msg_add(msg, tmp_el, upn_flags); ++ if (ret != LDB_SUCCESS) { ++ ret = sysdb_error_to_errno(ret); ++ goto done; ++ } ++ } ++ + ret = ldb_modify(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to add subdomain attributes to " +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index 0a8d1f53cb005507abe4ac55d0fa1ccc9e32b173..928c4fe93cc6afa5c3f69c14503896db820a4c0a 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -252,7 +252,7 @@ ad_subdom_store(struct sdap_idmap_ctx *idmap_ctx, + mpg = sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx, name, sid_str); + + ret = sysdb_subdomain_store(domain->sysdb, name, realm, flat, sid_str, +- mpg, enumerate, domain->forest, 0); ++ mpg, enumerate, domain->forest, 0, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n"); + goto done; +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index 62b8f65e5d29a4850f90ea7c19abd297becc96f5..925b1d8b133eb56724ee4f9133a2487090982a8b 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -375,6 +375,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent, + bool mpg; + bool enumerate; + uint32_t direction; ++ struct ldb_message_element *alternative_domain_suffixes = NULL; + + tmp_ctx = talloc_new(parent); + if (tmp_ctx == NULL) { +@@ -405,6 +406,12 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent, + goto done; + } + ++ ret = sysdb_attrs_get_el_ext(attrs, IPA_ADDITIONAL_SUFFIXES, false, ++ &alternative_domain_suffixes); ++ if (ret != EOK && ret != ENOENT) { ++ goto done; ++ } ++ + mpg = sdap_idmap_domain_has_algorithmic_mapping(sdap_idmap_ctx, name, id); + + ret = ipa_subdom_get_forest(tmp_ctx, sysdb_ctx_get_ldb(parent->sysdb), +@@ -431,7 +438,7 @@ static errno_t ipa_subdom_store(struct sss_domain_info *parent, + "Trust direction of %s is %s\n", name, ipa_trust_dir2str(direction)); + ret = sysdb_subdomain_store(parent->sysdb, name, realm, flat, + id, mpg, enumerate, forest, +- direction); ++ direction, alternative_domain_suffixes); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_subdomain_store failed.\n"); + goto done; +diff --git a/src/tests/cmocka/test_ipa_subdomains_server.c b/src/tests/cmocka/test_ipa_subdomains_server.c +index 0fddc951894dee45658497851473b9bddbba0ef7..123cf11c01ef4687eecad31a9d73120a87c643e1 100644 +--- a/src/tests/cmocka/test_ipa_subdomains_server.c ++++ b/src/tests/cmocka/test_ipa_subdomains_server.c +@@ -253,14 +253,14 @@ static void add_test_subdomains(struct trust_test_ctx *test_ctx, + SUBDOM_NAME, SUBDOM_REALM, + NULL, SUBDOM_SID, + true, false, SUBDOM_REALM, +- direction); ++ direction, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + CHILD_NAME, CHILD_REALM, + CHILD_FLAT, CHILD_SID, + true, false, SUBDOM_REALM, +- direction); ++ direction, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); +diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c +index 4137e9151be561a57a8f2e674f385ecb37119255..82a304feed864b09168d0f3e06a4e1bb120df7e4 100644 +--- a/src/tests/cmocka/test_nss_srv.c ++++ b/src/tests/cmocka/test_nss_srv.c +@@ -3089,7 +3089,7 @@ static int nss_subdom_test_setup(void **state) + + ret = sysdb_subdomain_store(nss_test_ctx->tctx->sysdb, + testdom[0], testdom[1], testdom[2], testdom[3], +- false, false, NULL, 0); ++ false, false, NULL, 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(nss_test_ctx->tctx->dom); +diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c +index 6d1ec884284487a12bcbfad77c00cd6c30f67707..c9db56841e841472c81d00a79f475dbbd975ccb0 100644 +--- a/src/tests/cmocka/test_sysdb_subdomains.c ++++ b/src/tests/cmocka/test_sysdb_subdomains.c +@@ -103,7 +103,7 @@ static void test_sysdb_subdomain_create(void **state) + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom1[0], dom1[1], dom1[2], dom1[3], +- false, false, NULL, 0); ++ false, false, NULL, 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); +@@ -115,7 +115,7 @@ static void test_sysdb_subdomain_create(void **state) + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom2[0], dom2[1], dom2[2], dom2[3], +- false, false, NULL, 1); ++ false, false, NULL, 1, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); +@@ -128,12 +128,12 @@ static void test_sysdb_subdomain_create(void **state) + /* Reverse the trust directions */ + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom1[0], dom1[1], dom1[2], dom1[3], +- false, false, NULL, 1); ++ false, false, NULL, 1, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom2[0], dom2[1], dom2[2], dom2[3], +- false, false, NULL, 0); ++ false, false, NULL, 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); +@@ -215,27 +215,27 @@ static void test_sysdb_link_forest_root_ipa(void **state) + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom1[0], dom1[1], dom1[2], dom1[3], +- false, false, dom1[4], 0); ++ false, false, dom1[4], 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + child_dom1[0], child_dom1[1], + child_dom1[2], child_dom1[3], + false, false, child_dom1[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + dom2[0], dom2[1], dom2[2], dom2[3], + false, false, dom2[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + child_dom2[0], child_dom2[1], + child_dom2[2], child_dom2[3], + false, false, child_dom2[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); +@@ -308,14 +308,14 @@ static void test_sysdb_link_forest_root_ad(void **state) + child_dom[0], child_dom[1], + child_dom[2], child_dom[3], + false, false, child_dom[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + sub_dom[0], sub_dom[1], + sub_dom[2], sub_dom[3], + false, false, sub_dom[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_update_subdomains(test_ctx->tctx->dom); +@@ -385,14 +385,14 @@ static void test_sysdb_link_forest_member_ad(void **state) + sub_dom[0], sub_dom[1], + sub_dom[2], sub_dom[3], + false, false, sub_dom[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_subdomain_store(test_ctx->tctx->sysdb, + forest_root[0], forest_root[1], + forest_root[2], forest_root[3], + false, false, forest_root[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_master_domain_update(test_ctx->tctx->dom); +@@ -469,7 +469,7 @@ static void test_sysdb_link_ad_multidom(void **state) + child_dom[0], child_dom[1], + child_dom[2], child_dom[3], + false, false, child_dom[4], +- 0); ++ 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_master_domain_update(main_dom1); +@@ -489,7 +489,7 @@ static void test_sysdb_link_ad_multidom(void **state) + ret = sysdb_subdomain_store(main_dom2->sysdb, + dom2_forest_root[0], dom2_forest_root[1], + dom2_forest_root[2], dom2_forest_root[3], +- false, false, dom2_forest_root[4], 0); ++ false, false, dom2_forest_root[4], 0, NULL); + assert_int_equal(ret, EOK); + + ret = sysdb_master_domain_update(main_dom2); +diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c +index bac8a8788b4fde0d6039121efead6fc20fa046f9..d1450015cb0f0b073045e7b6031423e3f5494d78 100644 +--- a/src/tests/sysdb-tests.c ++++ b/src/tests/sysdb-tests.c +@@ -5472,7 +5472,7 @@ START_TEST(test_sysdb_subdomain_store_user) + fail_unless(subdomain != NULL, "Failed to create new subdomin."); + ret = sysdb_subdomain_store(test_ctx->sysdb, + testdom[0], testdom[1], testdom[2], testdom[3], +- false, false, NULL, 0); ++ false, false, NULL, 0, NULL); + fail_if(ret != EOK, "Could not set up the test (test subdom)"); + + ret = sysdb_update_subdomains(test_ctx->domain); +@@ -5551,7 +5551,7 @@ START_TEST(test_sysdb_subdomain_user_ops) + fail_unless(subdomain != NULL, "Failed to create new subdomin."); + ret = sysdb_subdomain_store(test_ctx->sysdb, + testdom[0], testdom[1], testdom[2], testdom[3], +- false, false, NULL, 0); ++ false, false, NULL, 0, NULL); + fail_if(ret != EOK, "Could not set up the test (test subdom)"); + + ret = sysdb_update_subdomains(test_ctx->domain); +@@ -5624,7 +5624,7 @@ START_TEST(test_sysdb_subdomain_group_ops) + fail_unless(subdomain != NULL, "Failed to create new subdomin."); + ret = sysdb_subdomain_store(test_ctx->sysdb, + testdom[0], testdom[1], testdom[2], testdom[3], +- false, false, NULL, 0); ++ false, false, NULL, 0, NULL); + fail_if(ret != EOK, "Could not set up the test (test subdom)"); + + ret = sysdb_update_subdomains(test_ctx->domain); +-- +2.4.11 + diff --git a/SOURCES/0025-DP-add-dp_get_module_data.patch b/SOURCES/0025-DP-add-dp_get_module_data.patch new file mode 100644 index 0000000..bd41853 --- /dev/null +++ b/SOURCES/0025-DP-add-dp_get_module_data.patch @@ -0,0 +1,44 @@ +From 5ce7c218a7bd34672bd19359dcbeed51cc237474 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 1 Jul 2016 17:57:31 +0200 +Subject: [PATCH 25/27] DP: add dp_get_module_data() + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 35fa5a83ce8badf6bc868937047f44c3f32b7c28) +--- + src/providers/data_provider/dp.h | 2 ++ + src/providers/data_provider/dp_targets.c | 5 +++++ + 2 files changed, 7 insertions(+) + +diff --git a/src/providers/data_provider/dp.h b/src/providers/data_provider/dp.h +index 8cdbd7768a0b3f7f234b6bce6abab02419b3b9d1..5b36baf3489be4cce463dfb42c65a0b7f7ece9ef 100644 +--- a/src/providers/data_provider/dp.h ++++ b/src/providers/data_provider/dp.h +@@ -118,6 +118,8 @@ bool _dp_target_enabled(struct data_provider *provider, + struct dp_module *dp_target_module(struct data_provider *provider, + enum dp_targets target); + ++void *dp_get_module_data(struct dp_module *dp_module); ++ + void _dp_set_method(struct dp_method *methods, + enum dp_methods method, + dp_req_send_fn send_fn, +diff --git a/src/providers/data_provider/dp_targets.c b/src/providers/data_provider/dp_targets.c +index e19cf93a3693dede98567d2105021488380b5408..87ecfe55daa805eec0265795ef76751a1568c474 100644 +--- a/src/providers/data_provider/dp_targets.c ++++ b/src/providers/data_provider/dp_targets.c +@@ -88,6 +88,11 @@ struct dp_module *dp_target_module(struct data_provider *provider, + return provider->targets[target]->module; + } + ++void *dp_get_module_data(struct dp_module *dp_module) ++{ ++ return dp_module == NULL ? NULL : dp_module->module_data; ++} ++ + const char *dp_target_to_string(enum dp_targets target) + { + switch (target) { +-- +2.4.11 + diff --git a/SOURCES/0025-UTIL-Lower-debug-level-in-perform_checks.patch b/SOURCES/0025-UTIL-Lower-debug-level-in-perform_checks.patch deleted file mode 100644 index c0b93de..0000000 --- a/SOURCES/0025-UTIL-Lower-debug-level-in-perform_checks.patch +++ /dev/null @@ -1,50 +0,0 @@ -From ce03dffa77053f837ff4d7e0fbb3208118f2d768 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Jul 2015 16:29:09 +0200 -Subject: [PATCH 25/27] UTIL: Lower debug level in perform_checks() - -Failures in perform_checks() don't have to be fatal, therefore the debug -messages shouldn't be either. - -Reviewed-by: Alexander Bokovoy ---- - src/util/check_and_open.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/util/check_and_open.c b/src/util/check_and_open.c -index 59b90bf4b96731e385fcf92ed8bc251cb94abfda..b40ae2003e3de22ce9e4ca07cecc68e18a7abab4 100644 ---- a/src/util/check_and_open.c -+++ b/src/util/check_and_open.c -@@ -99,12 +99,12 @@ static errno_t perform_checks(struct stat *stat_buf, - } - - if ((mode & S_IFMT) != (st_mode & S_IFMT)) { -- DEBUG(SSSDBG_CRIT_FAILURE, "File is not the right type.\n"); -+ DEBUG(SSSDBG_TRACE_LIBS, "File is not the right type.\n"); - return EINVAL; - } - - if ((st_mode & ALLPERMS) != (mode & ALLPERMS)) { -- DEBUG(SSSDBG_CRIT_FAILURE, -+ DEBUG(SSSDBG_TRACE_LIBS, - "File has the wrong (bit masked) mode [%.7o], " - "expected [%.7o].\n", - (st_mode & ALLPERMS), (mode & ALLPERMS)); -@@ -112,12 +112,12 @@ static errno_t perform_checks(struct stat *stat_buf, - } - - if (uid != (uid_t)(-1) && stat_buf->st_uid != uid) { -- DEBUG(SSSDBG_CRIT_FAILURE, "File must be owned by uid [%d].\n", uid); -+ DEBUG(SSSDBG_TRACE_LIBS, "File must be owned by uid [%d].\n", uid); - return EINVAL; - } - - if (gid != (gid_t)(-1) && stat_buf->st_gid != gid) { -- DEBUG(SSSDBG_CRIT_FAILURE, "File must be owned by gid [%d].\n", gid); -+ DEBUG(SSSDBG_TRACE_LIBS, "File must be owned by gid [%d].\n", gid); - return EINVAL; - } - --- -2.4.3 - diff --git a/SOURCES/0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch b/SOURCES/0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch deleted file mode 100644 index fceec58..0000000 --- a/SOURCES/0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch +++ /dev/null @@ -1,116 +0,0 @@ -From dba7ccc7594be1881967aa274090d61a97aec5fa Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 22 Jul 2015 17:20:11 +0200 -Subject: [PATCH 26/27] IPA: Handle sssd-owned keytabs when running as root - -https://fedorahosted.org/sssd/ticket/2718 - -This patch handles the case where the keytab is created with sssd:sssd -ownership (perhaps by the IPA oddjob script) but SSSD runs as root, -which is the default in many distributions. - -Reviewed-by: Alexander Bokovoy ---- - src/providers/ipa/ipa_subdomains.h | 3 ++ - src/providers/ipa/ipa_subdomains_server.c | 46 +++++++++++++++++++++++++------ - 2 files changed, 41 insertions(+), 8 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h -index 5bc63a173a1a8967eb5de30a2da84a81377d3900..2302c5f03e80de2ea1efad424769e777cd6dd8d5 100644 ---- a/src/providers/ipa/ipa_subdomains.h -+++ b/src/providers/ipa/ipa_subdomains.h -@@ -94,6 +94,9 @@ struct ipa_server_mode_ctx { - - struct ipa_ad_server_ctx *trusts; - struct ipa_ext_groups *ext_groups; -+ -+ uid_t kt_owner_uid; -+ uid_t kt_owner_gid; - }; - - int ipa_ad_subdom_init(struct be_ctx *be_ctx, -diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c -index a9e2c1f700ef47716be868bad68590b8d5d0d42a..4bfea61e6dd0a02f6b723a39f7ba236c914009b0 100644 ---- a/src/providers/ipa/ipa_subdomains_server.c -+++ b/src/providers/ipa/ipa_subdomains_server.c -@@ -520,16 +520,28 @@ static errno_t ipa_getkeytab_recv(struct tevent_req *req, int *child_status) - return EOK; - } - --static errno_t ipa_check_keytab(const char *keytab) -+static errno_t ipa_check_keytab(const char *keytab, -+ uid_t kt_owner_uid, -+ gid_t kt_owner_gid) - { - errno_t ret; - - ret = check_file(keytab, getuid(), getgid(), S_IFREG|0600, 0, NULL, false); -- if (ret != EOK) { -- if (ret != ENOENT) { -- DEBUG(SSSDBG_OP_FAILURE, "Failed to check for %s\n", keytab); -- } else { -- DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab); -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab); -+ goto done; -+ } else if (ret != EOK) { -+ if (kt_owner_uid) { -+ ret = check_file(keytab, kt_owner_uid, kt_owner_gid, -+ S_IFREG|0600, 0, NULL, false); -+ } -+ -+ if (ret != EOK) { -+ if (ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to check for %s\n", keytab); -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, "Keytab %s is not present\n", keytab); -+ } - } - goto done; - } -@@ -648,7 +660,9 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req) - return EIO; - } - -- ret = ipa_check_keytab(state->keytab); -+ ret = ipa_check_keytab(state->keytab, -+ state->id_ctx->server_mode->kt_owner_uid, -+ state->id_ctx->server_mode->kt_owner_gid); - if (ret == EOK) { - DEBUG(SSSDBG_TRACE_FUNC, - "Keytab already present, can add the trust\n"); -@@ -704,7 +718,9 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq) - DEBUG(SSSDBG_TRACE_FUNC, - "Keytab successfully retrieved to %s\n", state->keytab); - -- ret = ipa_check_keytab(state->keytab); -+ ret = ipa_check_keytab(state->keytab, -+ state->id_ctx->server_mode->kt_owner_uid, -+ state->id_ctx->server_mode->kt_owner_gid); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ipa_check_keytab failed: %d\n", ret); - tevent_req_error(req, ret); -@@ -1029,6 +1045,20 @@ int ipa_ad_subdom_init(struct be_ctx *be_ctx, - id_ctx->server_mode->hostname = hostname; - id_ctx->server_mode->trusts = NULL; - id_ctx->server_mode->ext_groups = NULL; -+ id_ctx->server_mode->kt_owner_uid = 0; -+ id_ctx->server_mode->kt_owner_gid = 0; -+ -+ if (getuid() == 0) { -+ /* We need to handle keytabs created by IPA oddjob script gracefully -+ * even if we're running as root and IPA creates them as the SSSD user -+ */ -+ ret = sss_user_by_name_or_uid(SSSD_USER, -+ &id_ctx->server_mode->kt_owner_uid, -+ &id_ctx->server_mode->kt_owner_gid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "Failed to get ID of %s\n", SSSD_USER); -+ } -+ } - - ret = ipa_ad_subdom_reinit(be_ctx, be_ctx->ev, - be_ctx, id_ctx, be_ctx->domain); --- -2.4.3 - diff --git a/SOURCES/0026-IPA-add-ipa_init_get_krb5_auth_ctx.patch b/SOURCES/0026-IPA-add-ipa_init_get_krb5_auth_ctx.patch new file mode 100644 index 0000000..878d78e --- /dev/null +++ b/SOURCES/0026-IPA-add-ipa_init_get_krb5_auth_ctx.patch @@ -0,0 +1,60 @@ +From ec460578800d850e5a4f9d522920db1d79147dd6 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 1 Jul 2016 17:58:02 +0200 +Subject: [PATCH 26/27] IPA: add ipa_init_get_krb5_auth_ctx() + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 17dccc24e4490dfda2820d46b62a029b14ba2359) +--- + src/providers/ipa/ipa_common.h | 5 +++++ + src/providers/ipa/ipa_init.c | 13 +++++++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h +index 939c898e1a690806abd37493aabfb7bdec3e87a9..add9df87692c732b3567eee5584e7698991c66ca 100644 +--- a/src/providers/ipa/ipa_common.h ++++ b/src/providers/ipa/ipa_common.h +@@ -34,6 +34,8 @@ struct ipa_service { + struct krb5_service *krb5_service; + }; + ++struct ipa_init_ctx; ++ + enum ipa_basic_opt { + IPA_DOMAIN = 0, + IPA_SERVER, +@@ -287,4 +289,7 @@ errno_t ipa_idmap_get_ranges_from_sysdb(struct sdap_idmap_ctx *idmap_ctx, + errno_t ipa_idmap_init(TALLOC_CTX *mem_ctx, + struct sdap_id_ctx *id_ctx, + struct sdap_idmap_ctx **_idmap_ctx); ++ ++ ++struct krb5_ctx *ipa_init_get_krb5_auth_ctx(void *data); + #endif /* _IPA_COMMON_H_ */ +diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c +index d3093b3b5d269e6acd29f35560cf8299017c72b5..959cdb4a7c40c1be03dd1e7c66dee6e65ca76607 100644 +--- a/src/providers/ipa/ipa_init.c ++++ b/src/providers/ipa/ipa_init.c +@@ -58,6 +58,19 @@ struct ipa_init_ctx { + struct ipa_auth_ctx *auth_ctx; + }; + ++ ++struct krb5_ctx *ipa_init_get_krb5_auth_ctx(void *data) ++{ ++ struct ipa_init_ctx *ipa_init_ctx; ++ ++ ipa_init_ctx = talloc_get_type(data, struct ipa_init_ctx); ++ if (ipa_init_ctx == NULL || ipa_init_ctx->auth_ctx == NULL) { ++ return NULL; ++ } ++ ++ return ipa_init_ctx->auth_ctx->krb5_auth_ctx; ++} ++ + static bool srv_in_server_list(const char *servers) + { + TALLOC_CTX *tmp_ctx; +-- +2.4.11 + diff --git a/SOURCES/0027-IPA-enable-enterprise-principals-if-server-supports-.patch b/SOURCES/0027-IPA-enable-enterprise-principals-if-server-supports-.patch new file mode 100644 index 0000000..8589359 --- /dev/null +++ b/SOURCES/0027-IPA-enable-enterprise-principals-if-server-supports-.patch @@ -0,0 +1,149 @@ +From 6b5b0732b7f4fab195a6205e1046a8402f5d3040 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 1 Jul 2016 18:18:14 +0200 +Subject: [PATCH 27/27] IPA: enable enterprise principals if server supports + them + +If there are alternative UPN suffixes found on the server we can safely +assume that the IPA server supports enterprise principals. + +Resolves https://fedorahosted.org/sssd/ticket/3018 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 70673115c03c37ddc64c951b53d92df9d3310762) +--- + src/man/sssd-krb5.5.xml | 6 +++ + src/providers/ipa/ipa_subdomains.c | 86 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 92 insertions(+) + +diff --git a/src/man/sssd-krb5.5.xml b/src/man/sssd-krb5.5.xml +index e7fdd19e07db99314a9491faff9974d7d5e617e6..60b7dfb508c0d054a421fd46957574f52e0333d7 100644 +--- a/src/man/sssd-krb5.5.xml ++++ b/src/man/sssd-krb5.5.xml +@@ -513,6 +513,12 @@ + + Default: false (AD provider: true) + ++ ++ The IPA provider will set to option to 'true' if it ++ detects that the server is capable of handling ++ enterprise principals and the option is not set ++ explicitly in the config file. ++ + + + +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index 925b1d8b133eb56724ee4f9133a2487090982a8b..4e5bceb8c761bf4476928168d620baf2beb62ad5 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -28,6 +28,7 @@ + #include "providers/ipa/ipa_subdomains.h" + #include "providers/ipa/ipa_common.h" + #include "providers/ipa/ipa_id.h" ++#include "providers/ipa/ipa_opts.h" + + #include + +@@ -999,6 +1000,84 @@ immediately: + return req; + } + ++static errno_t ipa_enable_enterprise_principals(struct be_ctx *be_ctx) ++{ ++ int ret; ++ struct sss_domain_info *d; ++ TALLOC_CTX *tmp_ctx; ++ char **vals = NULL; ++ struct dp_module *auth; ++ struct krb5_ctx *krb5_auth_ctx; ++ ++ d = get_domains_head(be_ctx->domain); ++ ++ while (d != NULL) { ++ DEBUG(SSSDBG_TRACE_ALL, "checking [%s].\n", d->name); ++ if (d->upn_suffixes != NULL) { ++ break; ++ } ++ d = get_next_domain(d, SSS_GND_DESCEND); ++ } ++ ++ if (d == NULL) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "No UPN suffixes found, " ++ "no need to enable enterprise principals.\n"); ++ return EOK; ++ } ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); ++ return ENOMEM; ++ } ++ ++ ret = confdb_get_param(be_ctx->cdb, tmp_ctx, be_ctx->conf_path, ++ ipa_def_krb5_opts[KRB5_USE_ENTERPRISE_PRINCIPAL].opt_name, ++ &vals); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "confdb_get_param failed.\n"); ++ goto done; ++ } ++ ++ if (vals[0]) { ++ DEBUG(SSSDBG_CONF_SETTINGS, ++ "Parameter [%s] set in config file and will not be changed.\n", ++ ipa_def_krb5_opts[KRB5_USE_ENTERPRISE_PRINCIPAL].opt_name); ++ return EOK; ++ } ++ ++ auth = dp_target_module(be_ctx->provider, DPT_AUTH); ++ if (auth == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to find auth proivder.\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ krb5_auth_ctx = ipa_init_get_krb5_auth_ctx(dp_get_module_data(auth)); ++ if (krb5_auth_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to find auth proivder data.\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ ret = dp_opt_set_bool(krb5_auth_ctx->opts, ++ KRB5_USE_ENTERPRISE_PRINCIPAL, true); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "dp_opt_set_bool failed.\n"); ++ goto done; ++ } ++ ++ DEBUG(SSSDBG_CONF_SETTINGS, "Enterprise principals enabled.\n"); ++ ++ ret = EOK; ++ ++done: ++ talloc_free(tmp_ctx); ++ ++ return ret; ++} ++ + static void ipa_subdomains_slave_search_done(struct tevent_req *subreq) + { + struct ipa_subdomains_slave_state *state; +@@ -1037,6 +1116,13 @@ static void ipa_subdomains_slave_search_done(struct tevent_req *subreq) + goto done; + } + ++ ret = ipa_enable_enterprise_principals(state->sd_ctx->be_ctx); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "ipa_enable_enterprise_principals failed. " ++ "Enterprise principals might not work as " ++ "expected.\n"); ++ } ++ + if (state->sd_ctx->ipa_id_ctx->server_mode == NULL) { + ret = EOK; + goto done; +-- +2.4.11 + diff --git a/SOURCES/0027-TESTS-fix-compiler-warnings.patch b/SOURCES/0027-TESTS-fix-compiler-warnings.patch deleted file mode 100644 index 92545e5..0000000 --- a/SOURCES/0027-TESTS-fix-compiler-warnings.patch +++ /dev/null @@ -1,50 +0,0 @@ -From b211247a005257a4e2dec0d43b719600c51a14d4 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Tue, 28 Jul 2015 04:12:48 -0400 -Subject: [PATCH 27/27] TESTS: fix compiler warnings -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Lukáš Slebodník ---- - src/confdb/confdb.h | 2 +- - src/tests/cmocka/test_sysdb_views.c | 2 -- - 2 files changed, 1 insertion(+), 3 deletions(-) - -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index 36df6aea268cc5c82696f20b1a65963350d5e100..0b0ae0dcf2cd26462a9b0c895d833faf5c85b4e5 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -266,7 +266,7 @@ struct sss_domain_info { - struct timeval subdomains_last_checked; - - bool has_views; -- char *view_name; -+ const char *view_name; - - struct sss_domain_info *prev; - struct sss_domain_info *next; -diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c -index 83007b76a625edef67109850648b2d71645e22bb..c53d8187b181a5937f642eec32af28e8207b292b 100644 ---- a/src/tests/cmocka/test_sysdb_views.c -+++ b/src/tests/cmocka/test_sysdb_views.c -@@ -285,7 +285,6 @@ void test_sysdb_add_overrides_to_object_local(void **state) - { - int ret; - struct ldb_message *orig; -- struct ldb_message_element *el; - char *tmp_str; - struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, - struct sysdb_test_ctx); -@@ -314,7 +313,6 @@ void test_sysdb_add_overrides_to_object_missing_overridedn(void **state) - { - int ret; - struct ldb_message *orig; -- struct ldb_message_element *el; - char *tmp_str; - struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state, - struct sysdb_test_ctx); --- -2.4.3 - diff --git a/SOURCES/0028-intg-Invalidate-memory-cache-before-removing-files.patch b/SOURCES/0028-intg-Invalidate-memory-cache-before-removing-files.patch deleted file mode 100644 index 80cc677..0000000 --- a/SOURCES/0028-intg-Invalidate-memory-cache-before-removing-files.patch +++ /dev/null @@ -1,31 +0,0 @@ -From daf44387652fe46a2c8e694720f6b14436a6f31f Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 24 Jul 2015 12:31:42 +0200 -Subject: [PATCH 28/37] intg: Invalidate memory cache before removing files -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Workaround for: -https://fedorahosted.org/sssd/ticket/2726 - -Reviewed-by: Michal Židek ---- - src/tests/intg/ldap_test.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/tests/intg/ldap_test.py b/src/tests/intg/ldap_test.py -index afc77d7023ea31757def84f21e5d15997ba72013..bfe4e65ee54e232cd37d91f8ca5b6e9edf42b49d 100644 ---- a/src/tests/intg/ldap_test.py -+++ b/src/tests/intg/ldap_test.py -@@ -90,6 +90,7 @@ def create_sssd_fixture(request): - time.sleep(1) - except: - pass -+ subprocess.call(["sss_cache", "-E"]) - for path in os.listdir(config.DB_PATH): - os.unlink(config.DB_PATH + "/" + path) - for path in os.listdir(config.MCACHE_PATH): --- -2.4.3 - diff --git a/SOURCES/0028-views-allow-override-added-for-non-default-views-at-.patch b/SOURCES/0028-views-allow-override-added-for-non-default-views-at-.patch new file mode 100644 index 0000000..fb5707c --- /dev/null +++ b/SOURCES/0028-views-allow-override-added-for-non-default-views-at-.patch @@ -0,0 +1,74 @@ +From 845e3a3acea6f83b15ed3d887fcc4ed42cb3eb5a Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 11 Jul 2016 15:04:32 +0200 +Subject: [PATCH 28/31] views: allow override added for non-default views at + runtime +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently a new override for a non-default view cannot be displayed at +run-time. It even does not only require a restart but the view must be +un-applied and applied again to make the changes visible. + +This patch fixes this and makes non-default view behave like the default +view where the data from a newly added override are displayed after the +cached entry of the related object is expired. + +Resolves https://fedorahosted.org/sssd/ticket/3092 + +Reviewed-by: Pavel Březina +(cherry picked from commit 26a3d4f2ef35a088e4c5fc928290052c89a2ff43) +--- + src/db/sysdb_views.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c +index 7adc1523050243b8936cb98be3c71ce4364a03db..2b89e5ca41f719e1217ef3b9e0fd683656e05d42 100644 +--- a/src/db/sysdb_views.c ++++ b/src/db/sysdb_views.c +@@ -454,15 +454,23 @@ errno_t sysdb_store_override(struct sss_domain_info *domain, + obj_override_dn = ldb_msg_find_attr_as_string(msgs[0], SYSDB_OVERRIDE_DN, + NULL); + if (obj_override_dn != NULL) { ++ /* obj_override_dn can either point to the object itself, i.e there is ++ * no override, or to a overide object. This means it can change from ++ * the object DN to a override DN and back but not from one override ++ * DN to a different override DN. If the new and the old DN are the ++ * same we do not need to update the original object. */ + if (strcmp(obj_override_dn, override_dn_str) != 0) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Existing [%s] and new [%s] override DN do not match.\n", +- obj_override_dn, override_dn_str); +- ret = EINVAL; +- goto done; ++ if (strcmp(obj_override_dn, obj_dn_str) != 0 ++ && strcmp(override_dn_str, obj_dn_str) != 0) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Existing [%s] and new [%s] override DN do not match.\n", ++ obj_override_dn, override_dn_str); ++ ret = EINVAL; ++ goto done; ++ } ++ } else { ++ add_ref = false; + } +- +- add_ref = false; + } + + ret = ldb_transaction_start(domain->sysdb->ldb); +@@ -580,7 +588,9 @@ errno_t sysdb_store_override(struct sss_domain_info *domain, + + msg->dn = obj_dn; + +- ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_ADD, ++ ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, ++ obj_override_dn == NULL ? LDB_FLAG_MOD_ADD ++ : LDB_FLAG_MOD_REPLACE, + NULL); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n"); +-- +2.4.11 + diff --git a/SOURCES/0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch b/SOURCES/0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch deleted file mode 100644 index 1399bd5..0000000 --- a/SOURCES/0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 8ffbe4698421aaafa59f0813232883c4fc41514d Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 23 Jul 2015 15:56:44 +0200 -Subject: [PATCH 29/37] krb5: do not send SSS_OTP if two factors were used - -Resolves https://fedorahosted.org/sssd/ticket/2729 - -Reviewed-by: Jakub Hrozek ---- - src/providers/krb5/krb5_auth.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c -index 8886456c00c86914da364fd08efc25a488b0e686..d1bf4025b052d82413d1f370a36b0b99720d6f05 100644 ---- a/src/providers/krb5/krb5_auth.c -+++ b/src/providers/krb5/krb5_auth.c -@@ -1091,7 +1091,12 @@ static void krb5_auth_done(struct tevent_req *subreq) - krb5_auth_store_creds(state->domain, pd); - } - -- if (res->otp == true && pd->cmd == SSS_PAM_AUTHENTICATE) { -+ /* The SSS_OTP message will prevent pam_sss from putting the entered -+ * password on the PAM stack for other modules to use. This is not needed -+ * when both factors were entered separately because here the first factor -+ * (long term password) can be passed to the other modules. */ -+ if (res->otp == true && pd->cmd == SSS_PAM_AUTHENTICATE -+ && sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_2FA) { - uint32_t otp_flag = 1; - ret = pam_add_response(pd, SSS_OTP, sizeof(uint32_t), - (const uint8_t *) &otp_flag); --- -2.4.3 - diff --git a/SOURCES/0029-sssctl-move-filter-creation-to-separate-function.patch b/SOURCES/0029-sssctl-move-filter-creation-to-separate-function.patch new file mode 100644 index 0000000..6abaf60 --- /dev/null +++ b/SOURCES/0029-sssctl-move-filter-creation-to-separate-function.patch @@ -0,0 +1,129 @@ +From 634311d9250903599a61b2f5e205e2568ae92497 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 12 Jul 2016 12:59:48 +0200 +Subject: [PATCH 29/31] sssctl: move filter creation to separate function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 3c6e15e8aa38d9dfa02a7255fad56149bdfb35a6) +--- + src/tools/sssctl/sssctl_cache.c | 81 +++++++++++++++++++++++------------------ + 1 file changed, 46 insertions(+), 35 deletions(-) + +diff --git a/src/tools/sssctl/sssctl_cache.c b/src/tools/sssctl/sssctl_cache.c +index e23bb89db95217e66a441b7e4d6d32e668486cc8..3e7644e327eb3e5a0e33023e7a3f5f0f15e03cf6 100644 +--- a/src/tools/sssctl/sssctl_cache.c ++++ b/src/tools/sssctl/sssctl_cache.c +@@ -285,27 +285,16 @@ done: + return ret; + } + +-static errno_t sssctl_find_object(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domains, +- struct sss_domain_info *domain, +- sssctl_basedn_fn basedn_fn, +- enum cache_object obj_type, +- const char *attr_name, +- const char *attr_value, +- const char **attrs, +- struct sysdb_attrs **_entry, +- struct sss_domain_info **_dom) ++static const char *sssctl_create_filter(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *dom, ++ enum cache_object obj_type, ++ const char *attr_name, ++ const char *attr_value) + { +- TALLOC_CTX *tmp_ctx; +- struct sss_domain_info *dom; +- struct sysdb_attrs *entry; +- struct ldb_dn *base_dn; +- bool fqn_provided; +- bool qualify_attr = false; +- char *filter; +- errno_t ret; + const char *class; ++ const char *filter; + char *filter_value; ++ bool qualify_attr = false; + + if (strcmp(attr_name, SYSDB_NAME) == 0 && + (obj_type == CACHED_USER || +@@ -326,9 +315,44 @@ static errno_t sssctl_find_object(TALLOC_CTX *mem_ctx, + default: + DEBUG(SSSDBG_FATAL_FAILURE, + "sssctl doesn't handle this object type (type=%d)\n", obj_type); +- return EINVAL; ++ return NULL; + } + ++ if (qualify_attr) { ++ filter_value = sss_create_internal_fqname(NULL, attr_value, dom->name); ++ } else { ++ filter_value = talloc_strdup(NULL, attr_value); ++ } ++ if (filter_value == NULL) { ++ return NULL; ++ } ++ ++ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))", ++ class, attr_name, filter_value); ++ talloc_free(filter_value); ++ ++ return filter; ++} ++ ++static errno_t sssctl_find_object(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domains, ++ struct sss_domain_info *domain, ++ sssctl_basedn_fn basedn_fn, ++ enum cache_object obj_type, ++ const char *attr_name, ++ const char *attr_value, ++ const char **attrs, ++ struct sysdb_attrs **_entry, ++ struct sss_domain_info **_dom) ++{ ++ TALLOC_CTX *tmp_ctx; ++ struct sss_domain_info *dom; ++ struct sysdb_attrs *entry; ++ struct ldb_dn *base_dn; ++ bool fqn_provided; ++ const char *filter; ++ errno_t ret; ++ + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); +@@ -349,23 +373,10 @@ static errno_t sssctl_find_object(TALLOC_CTX *mem_ctx, + goto done; + } + +- if (qualify_attr) { +- filter_value = sss_create_internal_fqname(tmp_ctx, +- attr_value, +- dom->name); +- } else { +- filter_value = talloc_strdup(tmp_ctx, attr_value); +- } +- if (filter_value == NULL) { +- ret = ENOMEM; +- goto done; +- } +- +- filter = talloc_asprintf(tmp_ctx, "(&(objectClass=%s)(%s=%s))", +- class, attr_name, filter_value); +- talloc_free(filter_value); ++ filter = sssctl_create_filter(tmp_ctx, dom, obj_type, ++ attr_name, attr_value); + if (filter == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create filter\n"); + ret = ENOMEM; + goto done; + } +-- +2.4.11 + diff --git a/SOURCES/0030-sssctl-improve-readability-of-a-condition.patch b/SOURCES/0030-sssctl-improve-readability-of-a-condition.patch new file mode 100644 index 0000000..88e259d --- /dev/null +++ b/SOURCES/0030-sssctl-improve-readability-of-a-condition.patch @@ -0,0 +1,36 @@ +From 5ff189fbc8135d5900ac97120c587128a35f56eb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 13 Jul 2016 10:41:00 +0200 +Subject: [PATCH 30/31] sssctl: improve readability of a condition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit aa691837a2fa2fe2e38a55d576644074e0f45bd8) +--- + src/tools/sssctl/sssctl_cache.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/tools/sssctl/sssctl_cache.c b/src/tools/sssctl/sssctl_cache.c +index 3e7644e327eb3e5a0e33023e7a3f5f0f15e03cf6..22e3fad89e3c1bbfce48439b43acd2346da3e56f 100644 +--- a/src/tools/sssctl/sssctl_cache.c ++++ b/src/tools/sssctl/sssctl_cache.c +@@ -296,10 +296,10 @@ static const char *sssctl_create_filter(TALLOC_CTX *mem_ctx, + char *filter_value; + bool qualify_attr = false; + +- if (strcmp(attr_name, SYSDB_NAME) == 0 && +- (obj_type == CACHED_USER || +- obj_type == CACHED_GROUP)) { +- qualify_attr = true; ++ if (strcmp(attr_name, SYSDB_NAME) == 0) { ++ if (obj_type == CACHED_USER || obj_type == CACHED_GROUP) { ++ qualify_attr = true; ++ } + } + + switch (obj_type) { +-- +2.4.11 + diff --git a/SOURCES/0030-utils-add-NSS-version-of-cert-utils.patch b/SOURCES/0030-utils-add-NSS-version-of-cert-utils.patch deleted file mode 100644 index d66d074..0000000 --- a/SOURCES/0030-utils-add-NSS-version-of-cert-utils.patch +++ /dev/null @@ -1,345 +0,0 @@ -From cbbdb6250744154bf9b5d0718ec68f2b63dfaff0 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Mon, 22 Jun 2015 16:36:36 +0200 -Subject: [PATCH 30/37] utils: add NSS version of cert utils - -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 29 ++++- - configure.ac | 4 +- - contrib/sssd.spec.in | 1 - - src/tests/cmocka/test_cert_utils.c | 4 + - src/util/cert/nss/cert.c | 212 +++++++++++++++++++++++++++++++++++++ - 5 files changed, 244 insertions(+), 6 deletions(-) - create mode 100644 src/util/cert/nss/cert.c - -diff --git a/Makefile.am b/Makefile.am -index 912bfc6641465ef5cd2ff2cce9975b4027c3218d..277166ec66b3d67101e628990e68704c886b0c59 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -709,6 +709,17 @@ if HAVE_NSS - src/util/crypto/nss/nss_util.c - SSS_CRYPT_CFLAGS = $(NSS_CFLAGS) - SSS_CRYPT_LIBS = $(NSS_LIBS) -+ -+ SSS_CERT_SOURCES = \ -+ src/util/cert/cert_common.c \ -+ src/util/cert/nss/cert.c \ -+ $(NULL) -+ SSS_CERT_CFLAGS = \ -+ $(NSS_CFLAGS) \ -+ $(NULL) -+ SSS_CERT_LIBS = \ -+ $(NSS_LIBS) \ -+ $(NULL) - else - SSS_CRYPT_SOURCES = src/util/crypto/libcrypto/crypto_base64.c \ - src/util/crypto/libcrypto/crypto_hmac_sha1.c \ -@@ -716,6 +727,17 @@ else - src/util/crypto/libcrypto/crypto_obfuscate.c - SSS_CRYPT_CFLAGS = $(CRYPTO_CFLAGS) - SSS_CRYPT_LIBS = $(CRYPTO_LIBS) -+ -+ SSS_CERT_SOURCES = \ -+ src/util/cert/cert_common.c \ -+ src/util/cert/libcrypto/cert.c \ -+ $(NULL) -+ SSS_CERT_CFLAGS = \ -+ $(CRYPTO_CFLAGS) \ -+ $(NULL) -+ SSS_CERT_LIBS = \ -+ $(CRYPTO_LIBS) \ -+ $(NULL) - endif - - libsss_crypt_la_SOURCES = \ -@@ -735,14 +757,13 @@ libsss_crypt_la_LDFLAGS = \ - pkglib_LTLIBRARIES += libsss_cert.la - - libsss_cert_la_SOURCES = \ -- src/util/cert/cert_common.c \ -- src/util/cert/libcrypto/cert.c \ -+ $(SSS_CERT_SOURCES) \ - $(NULL) - libsss_cert_la_CFLAGS = \ -- $(CRYPTO_CFLAGS) \ -+ $(SSS_CERT_CFLAGS) \ - $(NULL) - libsss_cert_la_LIBADD = \ -- $(CRYPTO_LIBS) \ -+ $(SSS_CERT_LIBS) \ - $(TALLOC_LIBS) \ - libsss_crypt.la \ - libsss_debug.la \ -diff --git a/configure.ac b/configure.ac -index 29bedf74db6594b5788d51570514a07e082d5e42..4b4f8f3228bf13c594c86e1e39474a1d02ffd984 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -341,7 +341,9 @@ if test x$cryptolib = xnss; then - AM_CHECK_NSS - fi - --AM_CHECK_LIBCRYPTO -+if test x$cryptolib = xlibcrypto; then -+ AM_CHECK_LIBCRYPTO -+fi - - AM_CHECK_INOTIFY - -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index f050501ff9d0711a0da7f094ee968cae87a3f49b..54260e32e24ece372ed7130ab29d766bb1923f77 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -106,7 +106,6 @@ BuildRequires: dbus-libs - BuildRequires: openldap-devel - BuildRequires: pam-devel - BuildRequires: nss-devel --BuildRequires: openssl-devel - BuildRequires: nspr-devel - BuildRequires: pcre-devel - BuildRequires: libxslt -diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c -index 5bcbafb27dbdff596c07b8aad10ca15a35ff4ef5..8063b1a65e8692142cbb3cf82fe41afa6567bc91 100644 ---- a/src/tests/cmocka/test_cert_utils.c -+++ b/src/tests/cmocka/test_cert_utils.c -@@ -23,7 +23,9 @@ - */ - - #include -+#ifdef HAVE_LIBCRYPTO - #include -+#endif - - #include "util/cert.h" - #include "tests/cmocka/common_mock.h" -@@ -349,7 +351,9 @@ int main(int argc, const char *argv[]) - - ret = cmocka_run_group_tests(tests, NULL, NULL); - -+#ifdef HAVE_LIBCRYPTO - CRYPTO_cleanup_all_ex_data(); /* to make valgrind happy */ -+#endif - - #ifdef HAVE_NSS - /* Cleanup NSS and NSPR to make valgrind happy. */ -diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c -new file mode 100644 -index 0000000000000000000000000000000000000000..a20abf63a10de9a5e9810f1c7d56686d063d60c7 ---- /dev/null -+++ b/src/util/cert/nss/cert.c -@@ -0,0 +1,212 @@ -+ -+/* -+ SSSD - certificate handling utils - NSS version -+ -+ Copyright (C) Sumit Bose 2015 -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include "util/util.h" -+ -+#include -+#include -+ -+#include "util/crypto/nss/nss_util.h" -+ -+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----" -+#define NS_CERT_TRAILER "-----END CERTIFICATE-----" -+#define NS_CERT_HEADER_LEN ((sizeof NS_CERT_HEADER) - 1) -+#define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1) -+ -+errno_t sss_cert_der_to_pem(TALLOC_CTX *mem_ctx, const uint8_t *der_blob, -+ size_t der_size, char **pem, size_t *pem_size) -+{ -+ -+ CERTCertDBHandle *handle; -+ CERTCertificate *cert = NULL; -+ SECItem der_item; -+ char *ascii_crlf = NULL; -+ size_t ascii_crlf_len; -+ char *ascii_lf = NULL; -+ char *pem_cert_str = NULL; -+ int ret; -+ size_t c; -+ size_t d; -+ -+ /* initialize NSS if needed */ -+ ret = nspr_nss_init(); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n"); -+ return ret; -+ } -+ -+ handle = CERT_GetDefaultCertDB(); -+ -+ der_item.len = der_size; -+ der_item.data = discard_const(der_blob); -+ -+ cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE); -+ if (cert == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n"); -+ return EINVAL; -+ } -+ -+ ascii_crlf = BTOA_DataToAscii(cert->derCert.data, cert->derCert.len); -+ if (ascii_crlf == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "BTOA_DataToAscii failed.\n"); -+ ret = EIO; -+ goto done; -+ } -+ -+ ascii_crlf_len = strlen(ascii_crlf) + 1; -+ ascii_lf = talloc_size(mem_ctx, ascii_crlf_len * sizeof(char)); -+ if (ascii_lf == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "malloc failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ d = 0; -+ for (c = 0; c < ascii_crlf_len; c++) { -+ if (ascii_crlf[c] != '\r') { -+ ascii_lf[d++] = ascii_crlf[c]; -+ } -+ } -+ -+ pem_cert_str = talloc_asprintf(mem_ctx, "%s\n%s\n%s\n", NS_CERT_HEADER, -+ ascii_lf, -+ NS_CERT_TRAILER); -+ if (pem_cert_str == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ if (pem_size != NULL) { -+ *pem_size = strlen(pem_cert_str); -+ } -+ -+ if (pem != NULL) { -+ *pem = pem_cert_str; -+ pem_cert_str = NULL; -+ } -+ -+ ret = EOK; -+done: -+ talloc_free(pem_cert_str); -+ talloc_free(ascii_lf); -+ PORT_Free(ascii_crlf); -+ CERT_DestroyCertificate(cert); -+ -+ return ret; -+} -+ -+errno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem, -+ uint8_t **_der_blob, size_t *_der_size) -+{ -+ const char *ps; -+ const char *pe; -+ size_t pem_len; -+ uint8_t *der_blob = NULL; -+ unsigned int der_size; /* unsigned int to match 2nd parameter of -+ ATOB_AsciiToData */ -+ CERTCertDBHandle *handle; -+ CERTCertificate *cert = NULL; -+ SECItem der_item; -+ int ret; -+ char *b64 = NULL; -+ -+ /* initialize NSS if needed */ -+ ret = nspr_nss_init(); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n"); -+ return ret; -+ } -+ -+ if (pem == NULL || *pem == '\0') { -+ return EINVAL; -+ } -+ -+ pem_len = strlen(pem); -+ if (pem_len <= NS_CERT_HEADER_LEN + NS_CERT_TRAILER_LEN) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "PEM data too short.\n"); -+ return EINVAL; -+ } -+ -+ if (strncmp(pem, NS_CERT_HEADER, NS_CERT_HEADER_LEN) != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM header.\n"); -+ return EINVAL; -+ } -+ if (pem[NS_CERT_HEADER_LEN] != '\n') { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing newline in PEM data.\n"); -+ return EINVAL; -+ } -+ -+ pe = pem + pem_len - NS_CERT_TRAILER_LEN; -+ if (pem[pem_len - 1] == '\n') { -+ pe--; -+ } -+ if (strncmp(pe, NS_CERT_TRAILER, NS_CERT_TRAILER_LEN) != 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM trailer.\n"); -+ return EINVAL; -+ } -+ -+ ps = pem + NS_CERT_HEADER_LEN + 1; -+ -+ b64 = talloc_strndup(mem_ctx, ps, pe - ps); -+ if(b64 == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ der_blob = ATOB_AsciiToData(b64, &der_size); -+ if (der_blob == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "ATOB_AsciiToData failed.\n"); -+ return EIO; -+ } -+ -+ handle = CERT_GetDefaultCertDB(); -+ -+ der_item.len = der_size; -+ der_item.data = der_blob; -+ -+ cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE); -+ if (cert == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (_der_blob != NULL) { -+ *_der_blob = talloc_memdup(mem_ctx, cert->derCert.data, -+ cert->derCert.len); -+ if (*_der_blob == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_memdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ if (_der_size != NULL) { -+ *_der_size = cert->derCert.len; -+ } -+done: -+ PORT_Free(der_blob); -+ talloc_free(b64); -+ CERT_DestroyCertificate(cert); -+ -+ return ret; -+} --- -2.4.3 - diff --git a/SOURCES/0031-Add-NSS-version-of-p11_child.patch b/SOURCES/0031-Add-NSS-version-of-p11_child.patch deleted file mode 100644 index 81896fc..0000000 --- a/SOURCES/0031-Add-NSS-version-of-p11_child.patch +++ /dev/null @@ -1,720 +0,0 @@ -From 95bea503429c3f44654265486a07f1696b017e84 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 10 Jul 2015 12:10:53 +0200 -Subject: [PATCH 31/37] Add NSS version of p11_child - -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 25 +- - contrib/sssd.spec.in | 1 + - src/p11_child/p11_child_nss.c | 636 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 661 insertions(+), 1 deletion(-) - create mode 100644 src/p11_child/p11_child_nss.c - -diff --git a/Makefile.am b/Makefile.am -index 277166ec66b3d67101e628990e68704c886b0c59..e4add9757058773915f1971786b8a9ad584ec51f 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -148,7 +148,9 @@ endif - if BUILD_SEMANAGE - sssdlibexec_PROGRAMS += selinux_child - endif -- -+if HAVE_NSS -+sssdlibexec_PROGRAMS += p11_child -+endif - - if BUILD_PAC_RESPONDER - sssdlibexec_PROGRAMS += sssd_pac -@@ -3146,6 +3148,23 @@ proxy_child_LDADD = \ - $(SSSD_LIBS) \ - $(SSSD_INTERNAL_LTLIBS) - -+p11_child_SOURCES = \ -+ src/p11_child/p11_child_nss.c \ -+ src/util/atomic_io.c \ -+ $(NULL) -+p11_child_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ $(POPT_CFLAGS) \ -+ $(NSS_CFLAGS) \ -+ $(NULL) -+p11_child_LDADD = \ -+ libsss_debug.la \ -+ $(TALLOC_LIBS) \ -+ $(POPT_LIBS) \ -+ $(NSS_LIBS) \ -+ libsss_crypt.la \ -+ $(NULL) -+ - memberof_la_SOURCES = \ - src/ldb_modules/memberof.c \ - src/util/util.c -@@ -3541,6 +3560,10 @@ if BUILD_SEMANAGE - -chgrp $(SSSD_USER) $(DESTDIR)$(sssdlibexecdir)/selinux_child - chmod 4750 $(DESTDIR)$(sssdlibexecdir)/selinux_child - endif -+if HAVE_NSS -+ -chgrp $(SSSD_USER) $(DESTDIR)$(sssdlibexecdir)/p11_child -+ chmod 4750 $(DESTDIR)$(sssdlibexecdir)/p11_child -+endif - endif - - install-data-hook: -diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in -index 54260e32e24ece372ed7130ab29d766bb1923f77..9ca9a8b4dce5c5d70fb4df268270bcfb0c9b17bb 100644 ---- a/contrib/sssd.spec.in -+++ b/contrib/sssd.spec.in -@@ -684,6 +684,7 @@ rm -rf $RPM_BUILD_ROOT - %{_libexecdir}/%{servicename}/sssd_autofs - %{_libexecdir}/%{servicename}/sssd_ssh - %{_libexecdir}/%{servicename}/sssd_sudo -+%attr(4750,root,sssd) %{_libexecdir}/%{servicename}/p11_child - - %dir %{_libdir}/%{name} - %{_libdir}/%{name}/libsss_simple.so -diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c -new file mode 100644 -index 0000000000000000000000000000000000000000..6948c142aa7843cda5ff6d18f5853b10c387c224 ---- /dev/null -+++ b/src/p11_child/p11_child_nss.c -@@ -0,0 +1,636 @@ -+/* -+ SSSD -+ -+ Helper child to commmunicate with SmartCard via NSS -+ -+ Authors: -+ Sumit Bose -+ -+ Copyright (C) 2015 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "util/util.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "util/child_common.h" -+#include "providers/dp_backend.h" -+#include "util/crypto/sss_crypto.h" -+ -+enum op_mode { -+ OP_NONE, -+ OP_AUTH, -+ OP_PREAUTH -+}; -+ -+enum pin_mode { -+ PIN_NONE, -+ PIN_STDIN, -+ PIN_KEYPAD -+}; -+ -+static char *password_passthrough(PK11SlotInfo *slot, PRBool retry, void *arg) -+{ -+ /* give up if 1) no password was supplied, or 2) the password has already -+ * been rejected once by this token. */ -+ if (retry || (arg == NULL)) { -+ return NULL; -+ } -+ return PL_strdup((char *)arg); -+} -+ -+ -+ -+int do_work(TALLOC_CTX *mem_ctx, const char *nss_db, const char *slot_name_in, -+ enum op_mode mode, const char *pin, char **cert, -+ char **token_name_out) -+{ -+ int ret; -+ SECStatus rv; -+ NSSInitContext *nss_ctx; -+ SECMODModuleList *mod_list; -+ SECMODModuleList *mod_list_item; -+ const char *slot_name; -+ const char *token_name; -+ uint32_t flags = NSS_INIT_READONLY -+ | NSS_INIT_FORCEOPEN -+ | NSS_INIT_NOROOTINIT -+ | NSS_INIT_OPTIMIZESPACE -+ | NSS_INIT_PK11RELOAD; -+ NSSInitParameters parameters = { 0 }; -+ parameters.length = sizeof (parameters); -+ PK11SlotInfo *slot = NULL; -+ CK_SLOT_ID slot_id; -+ SECMODModuleID module_id; -+ CERTCertList *cert_list = NULL; -+ CERTCertListNode *cert_list_node; -+ const PK11DefaultArrayEntry friendly_attr = { "Publicly-readable certs", -+ SECMOD_FRIENDLY_FLAG, -+ CKM_INVALID_MECHANISM }; -+ CERTCertDBHandle *handle; -+ unsigned char random_value[128]; -+ SECKEYPrivateKey *priv_key; -+ SECOidTag algtag; -+ SECItem signed_random_value = {0}; -+ SECKEYPublicKey *pub_key; -+ CERTCertificate *found_cert = NULL; -+ PK11SlotList *list = NULL; -+ PK11SlotListElement *le; -+ -+ -+ nss_ctx = NSS_InitContext(nss_db, "", "", SECMOD_DB, ¶meters, flags); -+ if (nss_ctx == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "NSS_InitContext failed [%d].\n", -+ PR_GetError()); -+ return EIO; -+ } -+ -+ PK11_SetPasswordFunc(password_passthrough); -+ -+ DEBUG(SSSDBG_TRACE_ALL, "Default Module List:\n"); -+ mod_list = SECMOD_GetDefaultModuleList(); -+ for (mod_list_item = mod_list; mod_list_item != NULL; -+ mod_list_item = mod_list_item->next) { -+ DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n", -+ mod_list_item->module->commonName); -+ DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n", -+ mod_list_item->module->dllName); -+ } -+ -+ DEBUG(SSSDBG_TRACE_ALL, "Dead Module List:\n"); -+ mod_list = SECMOD_GetDeadModuleList(); -+ for (mod_list_item = mod_list; mod_list_item != NULL; -+ mod_list_item = mod_list_item->next) { -+ DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n", -+ mod_list_item->module->commonName); -+ DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n", -+ mod_list_item->module->dllName); -+ } -+ -+ DEBUG(SSSDBG_TRACE_ALL, "DB Module List:\n"); -+ mod_list = SECMOD_GetDBModuleList(); -+ for (mod_list_item = mod_list; mod_list_item != NULL; -+ mod_list_item = mod_list_item->next) { -+ DEBUG(SSSDBG_TRACE_ALL, "common name: [%s].\n", -+ mod_list_item->module->commonName); -+ DEBUG(SSSDBG_TRACE_ALL, "dll name: [%s].\n", -+ mod_list_item->module->dllName); -+ } -+ -+ if (slot_name_in != NULL) { -+ slot = PK11_FindSlotByName(slot_name_in); -+ if (slot == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "PK11_FindSlotByName failed for [%s]: [%d].\n", -+ slot_name_in, PR_GetError()); -+ return EIO; -+ } -+ } else { -+ -+ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, -+ NULL); -+ if (list == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "PK11_GetAllTokens failed.\n"); -+ return EIO; -+ } -+ -+ for (le = list->head; le; le = le->next) { -+ CK_SLOT_INFO slInfo; -+ -+ slInfo.flags = 0; -+ rv = PK11_GetSlotInfo(le->slot, &slInfo); -+ DEBUG(SSSDBG_TRACE_ALL, -+ "Description [%s] Manufacturer [%s] flags [%lu].\n", -+ slInfo.slotDescription, slInfo.manufacturerID, slInfo.flags); -+ if (rv == SECSuccess && (slInfo.flags & CKF_REMOVABLE_DEVICE)) { -+ slot = PK11_ReferenceSlot(le->slot); -+ break; -+ } -+ } -+ PK11_FreeSlotList(list); -+ if (slot == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "No removable slots found.\n"); -+ return EIO; -+ } -+ } -+ -+ -+ slot_id = PK11_GetSlotID(slot); -+ module_id = PK11_GetModuleID(slot); -+ slot_name = PK11_GetSlotName(slot); -+ token_name = PK11_GetTokenName(slot); -+ DEBUG(SSSDBG_TRACE_ALL, "Found [%s] in slot [%s][%d] of module [%d].\n", -+ token_name, slot_name, (int) slot_id, (int) module_id); -+ -+ if (PK11_IsFriendly(slot)) { -+ DEBUG(SSSDBG_TRACE_ALL, "Token is friendly.\n"); -+ } else { -+ DEBUG(SSSDBG_TRACE_ALL, -+ "Token is NOT friendly.\n"); -+ if (mode == OP_PREAUTH) { -+ DEBUG(SSSDBG_TRACE_ALL, "Trying to switch to friendly to read certificate.\n"); -+ rv = PK11_UpdateSlotAttribute(slot, &friendly_attr, PR_TRUE); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "PK11_UpdateSlotAttribute failed, continue.\n"); -+ } -+ } -+ } -+ -+ /* TODO: check PK11_ProtectedAuthenticationPath() and return the result */ -+ if (mode == OP_AUTH || PK11_NeedLogin(slot)) { -+ DEBUG(SSSDBG_TRACE_ALL, "Login required.\n"); -+ if (pin != NULL) { -+ rv = PK11_Authenticate(slot, PR_FALSE, discard_const(pin)); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, "PK11_Authenticate failed: [%d].\n", -+ PR_GetError()); -+ return EIO; -+ } -+ } else { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Login required but no pin available, continue.\n"); -+ } -+ } else { -+ DEBUG(SSSDBG_TRACE_ALL, "Login NOT required.\n"); -+ } -+ -+ cert_list = PK11_ListCertsInSlot(slot); -+ if (cert_list == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "PK11_ListCertsInSlot failed: [%d].\n", -+ PR_GetError()); -+ return EIO; -+ } -+ -+ for (cert_list_node = CERT_LIST_HEAD(cert_list); -+ !CERT_LIST_END(cert_list_node, cert_list); -+ cert_list_node = CERT_LIST_NEXT(cert_list_node)) { -+ if (cert_list_node->cert) { -+ DEBUG(SSSDBG_TRACE_ALL, "found cert[%s][%s]\n", -+ cert_list_node->cert->nickname, -+ cert_list_node->cert->subjectName); -+ } else { -+ DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n"); -+ } -+ } -+ -+ rv = CERT_FilterCertListByUsage(cert_list, certUsageSSLClient, PR_FALSE); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListByUsage failed: [%d].\n", -+ PR_GetError()); -+ return EIO; -+ } -+ -+ rv = CERT_FilterCertListForUserCerts(cert_list); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, "CERT_FilterCertListForUserCerts failed: [%d].\n", -+ PR_GetError()); -+ return EIO; -+ } -+ -+ -+ handle = CERT_GetDefaultCertDB(); -+ if (handle == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "CERT_GetDefaultCertDB failed: [%d].\n", -+ PR_GetError()); -+ return EIO; -+ } -+ -+ -+ found_cert = NULL; -+ DEBUG(SSSDBG_TRACE_ALL, "Filtered certificates:\n"); -+ for (cert_list_node = CERT_LIST_HEAD(cert_list); -+ !CERT_LIST_END(cert_list_node, cert_list); -+ cert_list_node = CERT_LIST_NEXT(cert_list_node)) { -+ if (cert_list_node->cert) { -+ DEBUG(SSSDBG_TRACE_ALL, "found cert[%s][%s]\n", -+ cert_list_node->cert->nickname, -+ cert_list_node->cert->subjectName); -+ -+ if (found_cert == NULL) { -+ found_cert = cert_list_node->cert; -+ } else { -+ DEBUG(SSSDBG_TRACE_ALL, "More than one certificate found, " \ -+ "using just the first one.\n"); -+ } -+ } else { -+ DEBUG(SSSDBG_TRACE_ALL, "--- empty cert list node ---\n"); -+ } -+ } -+ -+ if (found_cert == NULL) { -+ DEBUG(SSSDBG_TRACE_ALL, "No certificate found.\n"); -+ *cert = NULL; -+ *token_name_out = NULL; -+ ret = EOK; -+ goto done; -+ } -+ -+ rv = CERT_VerifyCertificateNow(handle, found_cert, PR_TRUE, -+ certificateUsageSSLClient, NULL, NULL); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "CERT_VerifyCertificateNow failed [%d].\n", -+ PR_GetError()); -+ ret = EIO; -+ goto done; -+ } -+ -+ if (mode == OP_AUTH) { -+ rv = PK11_GenerateRandom(random_value, sizeof(random_value)); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "PK11_GenerateRandom failed [%d].\n", PR_GetError()); -+ return EIO; -+ } -+ -+ priv_key = PK11_FindPrivateKeyFromCert(slot, found_cert, NULL); -+ if (priv_key == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "PK11_FindPrivateKeyFromCert failed [%d]." \ -+ "Maybe pin is missing.\n", PR_GetError()); -+ ret = EIO; -+ goto done; -+ } -+ -+ algtag = SEC_GetSignatureAlgorithmOidTag(priv_key->keyType, -+ SEC_OID_SHA1); -+ if (algtag == SEC_OID_UNKNOWN) { -+ SECKEY_DestroyPrivateKey(priv_key); -+ DEBUG(SSSDBG_OP_FAILURE, -+ "SEC_GetSignatureAlgorithmOidTag failed [%d].", -+ PR_GetError()); -+ ret = EIO; -+ goto done; -+ } -+ -+ rv = SEC_SignData(&signed_random_value, -+ random_value, sizeof(random_value), -+ priv_key, algtag); -+ SECKEY_DestroyPrivateKey(priv_key); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, "SEC_SignData failed [%d].", -+ PR_GetError()); -+ ret = EIO; -+ goto done; -+ } -+ -+ pub_key = CERT_ExtractPublicKey(found_cert); -+ if (pub_key == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "CERT_ExtractPublicKey failed [%d].", PR_GetError()); -+ ret = EIO; -+ goto done; -+ } -+ -+ rv = VFY_VerifyData(random_value, sizeof(random_value), -+ pub_key, &signed_random_value, algtag, -+ NULL); -+ SECKEY_DestroyPublicKey(pub_key); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, "VFY_VerifyData failed [%d].", -+ PR_GetError()); -+ ret = EACCES; -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_ALL, -+ "Certificate verified and validated.\n"); -+ } -+ -+ *cert = sss_base64_encode(mem_ctx, found_cert->derCert.data, -+ found_cert->derCert.len); -+ if (*cert == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "sss_base64_encode failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ *token_name_out = talloc_strdup(mem_ctx, token_name); -+ if (*token_name_out == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy slot name.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (slot != NULL) { -+ PK11_FreeSlot(slot); -+ } -+ -+ if (cert_list != NULL) { -+ CERT_DestroyCertList(cert_list); -+ } -+ -+ PORT_Free(signed_random_value.data); -+ -+ rv = NSS_ShutdownContext(nss_ctx); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n", -+ PR_GetError()); -+ } -+ -+ return ret; -+} -+ -+static errno_t p11c_recv_data(TALLOC_CTX *mem_ctx, int fd, char **pin) -+{ -+ uint8_t buf[IN_BUF_SIZE]; -+ ssize_t len; -+ errno_t ret; -+ char *str; -+ -+ errno = 0; -+ len = sss_atomic_read_s(fd, buf, IN_BUF_SIZE); -+ if (len == -1) { -+ ret = errno; -+ ret = (ret == 0) ? EINVAL: ret; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "read failed [%d][%s].\n", ret, strerror(ret)); -+ return ret; -+ } -+ -+ if (len == 0 || *buf == '\0') { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing PIN.\n"); -+ return EINVAL; -+ } -+ -+ str = talloc_strndup(mem_ctx, (char *) buf, len); -+ if (str == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); -+ return ENOMEM; -+ } -+ -+ if (strlen(str) != len) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Input contains additional data, only PIN expected.\n"); -+ talloc_free(str); -+ return EINVAL; -+ } -+ -+ *pin = str; -+ -+ return EOK; -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ int opt; -+ poptContext pc; -+ int debug_fd = -1; -+ errno_t ret; -+ TALLOC_CTX *main_ctx = NULL; -+ char *cert; -+ enum op_mode mode = OP_NONE; -+ enum pin_mode pin_mode = PIN_NONE; -+ char *pin = NULL; -+ char *slot_name_in = NULL; -+ char *token_name_out = NULL; -+ char *nss_db = NULL; -+ -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ {"debug-level", 'd', POPT_ARG_INT, &debug_level, 0, -+ _("Debug level"), NULL}, -+ {"debug-timestamps", 0, POPT_ARG_INT, &debug_timestamps, 0, -+ _("Add debug timestamps"), NULL}, -+ {"debug-microseconds", 0, POPT_ARG_INT, &debug_microseconds, 0, -+ _("Show timestamps with microseconds"), NULL}, -+ {"debug-fd", 0, POPT_ARG_INT, &debug_fd, 0, -+ _("An open file descriptor for the debug logs"), NULL}, -+ {"debug-to-stderr", 0, POPT_ARG_NONE | POPT_ARGFLAG_DOC_HIDDEN, -+ &debug_to_stderr, 0, -+ _("Send the debug output to stderr directly."), NULL }, -+ {"auth", 0, POPT_ARG_NONE, NULL, 'a', _("Run in auth mode"), NULL}, -+ {"pre", 0, POPT_ARG_NONE, NULL, 'p', _("Run in pre-auth mode"), NULL}, -+ {"pin", 0, POPT_ARG_NONE, NULL, 'i', _("Expect PIN on stdin"), NULL}, -+ {"keypad", 0, POPT_ARG_NONE, NULL, 'k', _("Expect PIN on keypad"), -+ NULL}, -+ {"nssdb", 0, POPT_ARG_STRING, &nss_db, 0, _("NSS DB to use"), -+ NULL}, -+ POPT_TABLEEND -+ }; -+ -+ /* Set debug level to invalid value so we can decide if -d 0 was used. */ -+ debug_level = SSSDBG_INVALID; -+ -+ pc = poptGetContext(argv[0], argc, argv, long_options, 0); -+ while ((opt = poptGetNextOpt(pc)) != -1) { -+ switch(opt) { -+ case 'a': -+ if (mode != OP_NONE) { -+ fprintf(stderr, -+ "\n--auth and --pre are mutually exclusive and " \ -+ "should be only used once.\n\n"); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } -+ mode = OP_AUTH; -+ break; -+ case 'p': -+ if (mode != OP_NONE) { -+ fprintf(stderr, -+ "\n--auth and --pre are mutually exclusive and " \ -+ "should be only used once.\n\n"); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } -+ mode = OP_PREAUTH; -+ break; -+ case 'i': -+ if (pin_mode != PIN_NONE) { -+ fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \ -+ "and should be only used once.\n\n"); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } -+ pin_mode = PIN_STDIN; -+ break; -+ case 'k': -+ if (pin_mode != PIN_NONE) { -+ fprintf(stderr, "\n--pin and --keypad are mutually exclusive " \ -+ "and should be only used once.\n\n"); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } -+ pin_mode = PIN_KEYPAD; -+ break; -+ default: -+ fprintf(stderr, "\nInvalid option %s: %s\n\n", -+ poptBadOption(pc, 0), poptStrerror(opt)); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } -+ } -+ -+ if (nss_db == NULL) { -+ fprintf(stderr, "\nMissing NSS DB --nssdb must be specified.\n\n"); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } -+ -+ if (mode == OP_NONE) { -+ fprintf(stderr, "\nMissing operation mode, " \ -+ "either --auth or --pre must be specified.\n\n"); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } else if (mode == OP_AUTH && pin_mode == PIN_NONE) { -+ fprintf(stderr, "\nMissing pin mode for authentication, " \ -+ "either --pin or --keypad must be specified.\n"); -+ poptPrintUsage(pc, stderr, 0); -+ _exit(-1); -+ } -+ -+ poptFreeContext(pc); -+ -+ DEBUG_INIT(debug_level); -+ -+ debug_prg_name = talloc_asprintf(NULL, "[sssd[p11_child[%d]]]", getpid()); -+ if (debug_prg_name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n"); -+ goto fail; -+ } -+ -+ if (debug_fd != -1) { -+ ret = set_debug_file_from_fd(debug_fd); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "set_debug_file_from_fd failed.\n"); -+ } -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "p11_child started.\n"); -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Running in [%s] mode.\n", -+ mode == OP_AUTH ? "auth" -+ : (mode == OP_PREAUTH ? "pre-auth" : "unknown")); -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Running with effective IDs: [%"SPRIuid"][%"SPRIgid"].\n", -+ geteuid(), getegid()); -+ -+ if (getuid() != 0) { -+ ret = setuid(0); -+ if (ret == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "setuid failed: %d, p11_child might not work!\n", ret); -+ } -+ } -+ -+ if (getgid() != 0) { -+ ret = setgid(0); -+ if (ret == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "setgid failed: %d, p11_child might not work!\n", ret); -+ } -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Running with real IDs [%"SPRIuid"][%"SPRIgid"].\n", -+ getuid(), getgid()); -+ -+ main_ctx = talloc_new(NULL); -+ if (main_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new failed.\n"); -+ talloc_free(discard_const(debug_prg_name)); -+ goto fail; -+ } -+ talloc_steal(main_ctx, debug_prg_name); -+ -+ -+ if (mode == OP_AUTH && pin_mode == PIN_STDIN) { -+ ret = p11c_recv_data(main_ctx, STDIN_FILENO, &pin); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read pin.\n"); -+ goto fail; -+ } -+ } -+ -+ ret = do_work(main_ctx, nss_db, slot_name_in, mode, pin, &cert, -+ &token_name_out); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n"); -+ goto fail; -+ } -+ -+ if (cert != NULL) { -+ fprintf(stdout, "%s\n", token_name_out); -+ fprintf(stdout, "%s\n", cert); -+ } -+ -+ talloc_free(main_ctx); -+ return EXIT_SUCCESS; -+fail: -+ DEBUG(SSSDBG_CRIT_FAILURE, "p11_child failed!\n"); -+ close(STDOUT_FILENO); -+ talloc_free(main_ctx); -+ return EXIT_FAILURE; -+} --- -2.4.3 - diff --git a/SOURCES/0031-sssctl-Use-localtime-for-time-stamps.patch b/SOURCES/0031-sssctl-Use-localtime-for-time-stamps.patch new file mode 100644 index 0000000..d94a0eb --- /dev/null +++ b/SOURCES/0031-sssctl-Use-localtime-for-time-stamps.patch @@ -0,0 +1,34 @@ +From e6cfc113e6f3f7cc1c941d12e0ac7032f19affb9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Thu, 14 Jul 2016 15:33:19 +0200 +Subject: [PATCH 31/31] sssctl: Use localtime for time stamps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/3096 + +Signed-off-by: Fabiano Fidêncio +Reviewed-by: Pavel Březina +(cherry picked from commit f316e5446313bbf61c96b6763badc21604bff4a3) +--- + src/tools/sssctl/sssctl_cache.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tools/sssctl/sssctl_cache.c b/src/tools/sssctl/sssctl_cache.c +index 22e3fad89e3c1bbfce48439b43acd2346da3e56f..4a1f3558ed7064ca40ccf9313d99fbab36e6e4c9 100644 +--- a/src/tools/sssctl/sssctl_cache.c ++++ b/src/tools/sssctl/sssctl_cache.c +@@ -67,7 +67,7 @@ static errno_t time_to_string(TALLOC_CTX *mem_ctx, + char str[255]; + size_t ret; + +- tm = gmtime(×tamp); ++ tm = localtime(×tamp); + if (tm == NULL) { + return ENOMEM; + } +-- +2.4.11 + diff --git a/SOURCES/0032-SECRETS-Log-message-for-failures-with-removing-file.patch b/SOURCES/0032-SECRETS-Log-message-for-failures-with-removing-file.patch new file mode 100644 index 0000000..10627ef --- /dev/null +++ b/SOURCES/0032-SECRETS-Log-message-for-failures-with-removing-file.patch @@ -0,0 +1,38 @@ +From 38b3bd9bde495d44283de2b837ab0239140edb3d Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 22 Jul 2016 09:53:40 +0200 +Subject: [PATCH 32/44] SECRETS: Log message for failures with removing file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Type: Unchecked return value +Reported by coverity + +Reviewed-by: Petr Čech +--- + src/responder/secrets/local.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c +index 620134ea6b45629114ba795d0e232f414f6e5009..2a85ac06945322265fbd1012c9697728c37b77a0 100644 +--- a/src/responder/secrets/local.c ++++ b/src/responder/secrets/local.c +@@ -624,7 +624,13 @@ int generate_master_key(const char *filename, size_t size) + rsize = sss_atomic_io_s(fd, buf, size, false); + close(fd); + if (rsize != size) { +- unlink(filename); ++ ret = unlink(filename); ++ /* non-fatal failure */ ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Failed to remove file: %s - %d [%s]!\n", ++ filename, ret, sss_strerror(ret)); ++ } + return EFAULT; + } + +-- +2.4.11 + diff --git a/SOURCES/0032-pack_message_v3-allow-empty-name.patch b/SOURCES/0032-pack_message_v3-allow-empty-name.patch deleted file mode 100644 index 695df0f..0000000 --- a/SOURCES/0032-pack_message_v3-allow-empty-name.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 1b9a3d516341560ccf8b5f9fab0886f3d05defce Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 26 Jun 2015 14:45:21 +0200 -Subject: [PATCH 32/37] pack_message_v3: allow empty name - -Reviewed-by: Jakub Hrozek ---- - src/sss_client/pam_message.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/sss_client/pam_message.c b/src/sss_client/pam_message.c -index b8104c680d0e733b713c665e6206dc4b0d379237..b239f6f53da54054c52e484bdd076193709cb003 100644 ---- a/src/sss_client/pam_message.c -+++ b/src/sss_client/pam_message.c -@@ -107,9 +107,10 @@ int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer) - uint8_t *buf; - size_t rp; - -- len = sizeof(uint32_t) + -- 2*sizeof(uint32_t) + pi->pam_user_size + -- sizeof(uint32_t); -+ len = sizeof(uint32_t) + sizeof(uint32_t); -+ -+ len += *pi->pam_user != '\0' ? -+ 2*sizeof(uint32_t) + pi->pam_user_size : 0; - len += *pi->pam_service != '\0' ? - 2*sizeof(uint32_t) + pi->pam_service_size : 0; - len += *pi->pam_tty != '\0' ? --- -2.4.3 - diff --git a/SOURCES/0033-IPA-fix-capaths-output.patch b/SOURCES/0033-IPA-fix-capaths-output.patch new file mode 100644 index 0000000..f5b2f92 --- /dev/null +++ b/SOURCES/0033-IPA-fix-capaths-output.patch @@ -0,0 +1,67 @@ +From cf161fe0317fd37e1c5ad826cb783905aaf1f048 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 18 Jul 2016 17:19:36 +0200 +Subject: [PATCH 33/44] IPA: fix [capaths] output + +the capaths for a single domain should be collected in a single +sub-section in the MIT Kerberos configuration not spread over multiple +one. See the capaths section of the krb5.conf man page for details. + +Resolves: +https://fedorahosted.org/sssd/ticket/3103 + +Reviewed-by: Jakub Hrozek +--- + src/util/domain_info_utils.c | 29 ++++++++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c +index 360f70376c472466168d93d45b6c547d51dd18c6..8cdd50d8d521d734e9ffd9b4e81cd6fbd7d158c7 100644 +--- a/src/util/domain_info_utils.c ++++ b/src/util/domain_info_utils.c +@@ -280,6 +280,7 @@ sss_write_domain_mappings(struct sss_domain_info *domain) + bool capaths_started = false; + char *uc_forest; + char *uc_parent; ++ char *parent_capaths = NULL; + + if (domain == NULL || domain->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "No domain name provided\n"); +@@ -399,9 +400,31 @@ sss_write_domain_mappings(struct sss_domain_info *domain) + capaths_started = true; + } + +- ret = fprintf(fstream, "%s = {\n %s = %s\n}\n%s = {\n %s = %s\n}\n", +- dom->realm, uc_parent, uc_forest, +- uc_parent, dom->realm, uc_forest); ++ ret = fprintf(fstream, "%s = {\n %s = %s\n}\n", ++ dom->realm, uc_parent, uc_forest); ++ if (ret < 0) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "fprintf failed\n"); ++ goto done; ++ } ++ ++ if (parent_capaths == NULL) { ++ parent_capaths = talloc_asprintf(tmp_ctx, " %s = %s\n", dom->realm, ++ uc_forest); ++ } else { ++ parent_capaths = talloc_asprintf_append(parent_capaths, ++ " %s = %s\n", dom->realm, ++ uc_forest); ++ } ++ if (parent_capaths == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "talloc_asprintf/talloc_asprintf_append failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ if (parent_capaths != NULL) { ++ ret = fprintf(fstream, "%s = {\n%s}\n", uc_parent, parent_capaths); + if (ret < 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "fprintf failed\n"); + goto done; +-- +2.4.11 + diff --git a/SOURCES/0033-authok-add-support-for-Smart-Card-related-authtokens.patch b/SOURCES/0033-authok-add-support-for-Smart-Card-related-authtokens.patch deleted file mode 100644 index 891e411..0000000 --- a/SOURCES/0033-authok-add-support-for-Smart-Card-related-authtokens.patch +++ /dev/null @@ -1,287 +0,0 @@ -From f9a027877ecdd697a052f6135963fb3726692310 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 26 Jun 2015 17:55:23 +0200 -Subject: [PATCH 33/37] authok: add support for Smart Card related authtokens - -Reviewed-by: Jakub Hrozek ---- - src/sss_client/sss_cli.h | 7 ++++ - src/tests/cmocka/test_authtok.c | 75 +++++++++++++++++++++++++++++++++++++++++ - src/util/authtok.c | 64 +++++++++++++++++++++++++++++++++++ - src/util/authtok.h | 41 ++++++++++++++++++++++ - 4 files changed, 187 insertions(+) - -diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h -index 0dfb525bacba5f6928e8ece76e05f60d7f2eebd5..3c4e938ae37c042879b1ae26fe389fa37cef682c 100644 ---- a/src/sss_client/sss_cli.h -+++ b/src/sss_client/sss_cli.h -@@ -308,6 +308,13 @@ enum sss_authtok_type { - SSS_AUTHTOK_TYPE_2FA = 0x0003, /**< Authentication token has two - * factors, they may or may no contain - * a trailing \\0 */ -+ SSS_AUTHTOK_TYPE_SC_PIN = 0x0004, /**< Authentication token is a Smart -+ * Card pin, it may or may no contain -+ * a trailing \\0 */ -+ SSS_AUTHTOK_TYPE_SC_KEYPAD = 0x0005, /**< Authentication token indicates -+ * Smart Card authentication is used -+ * and that the pin will be entered -+ * at the card reader. */ - }; - - /** -diff --git a/src/tests/cmocka/test_authtok.c b/src/tests/cmocka/test_authtok.c -index 5aa47c7b6b8c955666a9c73d5f9627d6378d13e0..30dcc9c8401103a275bd592fe8afd2c2f396ffb1 100644 ---- a/src/tests/cmocka/test_authtok.c -+++ b/src/tests/cmocka/test_authtok.c -@@ -488,6 +488,77 @@ void test_sss_authtok_2fa_blobs_missing_null(void **state) - MISSING_NULL_CHECK; - } - -+void test_sss_authtok_sc_keypad(void **state) -+{ -+ struct test_state *ts; -+ -+ ts = talloc_get_type_abort(*state, struct test_state); -+ -+ sss_authtok_set_sc_keypad(NULL); -+ -+ sss_authtok_set_sc_keypad(ts->authtoken); -+ assert_int_equal(sss_authtok_get_type(ts->authtoken), -+ SSS_AUTHTOK_TYPE_SC_KEYPAD); -+ assert_int_equal(sss_authtok_get_size(ts->authtoken), 0); -+ assert_null(sss_authtok_get_data(ts->authtoken)); -+} -+ -+void test_sss_authtok_sc_pin(void **state) -+{ -+ struct test_state *ts; -+ int ret; -+ size_t size; -+ const char *pin; -+ size_t len; -+ -+ ts = talloc_get_type_abort(*state, struct test_state); -+ -+ ret = sss_authtok_set_sc_pin(NULL, NULL, 0); -+ assert_int_equal(ret, EFAULT); -+ -+ ret = sss_authtok_set_sc_pin(ts->authtoken, NULL, 0); -+ assert_int_equal(ret, EINVAL); -+ -+ ret = sss_authtok_set_sc_pin(ts->authtoken, "12345678", 0); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(sss_authtok_get_type(ts->authtoken), -+ SSS_AUTHTOK_TYPE_SC_PIN); -+ size = sss_authtok_get_size(ts->authtoken); -+ assert_int_equal(size, 9); -+ assert_memory_equal(sss_authtok_get_data(ts->authtoken), "12345678\0", -+ size); -+ -+ ret = sss_authtok_set_sc_pin(ts->authtoken, "12345678", 5); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(sss_authtok_get_type(ts->authtoken), -+ SSS_AUTHTOK_TYPE_SC_PIN); -+ size = sss_authtok_get_size(ts->authtoken); -+ assert_int_equal(size, 6); -+ assert_memory_equal(sss_authtok_get_data(ts->authtoken), "12345\0", -+ size); -+ -+ ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(len, 5); -+ assert_string_equal(pin, "12345"); -+ -+ sss_authtok_set_empty(ts->authtoken); -+ -+ ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len); -+ assert_int_equal(ret, ENOENT); -+ -+ ret = sss_authtok_set_password(ts->authtoken, "12345", 0); -+ assert_int_equal(ret, EOK); -+ -+ ret = sss_authtok_get_sc_pin(ts->authtoken, &pin, &len); -+ assert_int_equal(ret, EACCES); -+ -+ sss_authtok_set_empty(ts->authtoken); -+ -+ ret = sss_authtok_get_sc_pin(NULL, &pin, &len); -+ assert_int_equal(ret, EFAULT); -+} -+ - int main(int argc, const char *argv[]) - { - poptContext pc; -@@ -517,6 +588,10 @@ int main(int argc, const char *argv[]) - setup, teardown), - cmocka_unit_test_setup_teardown(test_sss_authtok_2fa_blobs_missing_null, - setup, teardown), -+ cmocka_unit_test_setup_teardown(test_sss_authtok_sc_keypad, -+ setup, teardown), -+ cmocka_unit_test_setup_teardown(test_sss_authtok_sc_pin, -+ setup, teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ -diff --git a/src/util/authtok.c b/src/util/authtok.c -index 45761df80175fded8a6c6e5dac8a90180b11d225..6062cd875ce2c6b541ef237e7f7bdddac80366c5 100644 ---- a/src/util/authtok.c -+++ b/src/util/authtok.c -@@ -39,6 +39,8 @@ size_t sss_authtok_get_size(struct sss_auth_token *tok) - case SSS_AUTHTOK_TYPE_PASSWORD: - case SSS_AUTHTOK_TYPE_CCFILE: - case SSS_AUTHTOK_TYPE_2FA: -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: - return tok->length; - case SSS_AUTHTOK_TYPE_EMPTY: - return 0; -@@ -72,6 +74,8 @@ errno_t sss_authtok_get_password(struct sss_auth_token *tok, - return EOK; - case SSS_AUTHTOK_TYPE_CCFILE: - case SSS_AUTHTOK_TYPE_2FA: -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: - return EACCES; - } - -@@ -95,6 +99,8 @@ errno_t sss_authtok_get_ccfile(struct sss_auth_token *tok, - return EOK; - case SSS_AUTHTOK_TYPE_PASSWORD: - case SSS_AUTHTOK_TYPE_2FA: -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: - return EACCES; - } - -@@ -144,9 +150,11 @@ void sss_authtok_set_empty(struct sss_auth_token *tok) - return; - case SSS_AUTHTOK_TYPE_PASSWORD: - case SSS_AUTHTOK_TYPE_2FA: -+ case SSS_AUTHTOK_TYPE_SC_PIN: - safezero(tok->data, tok->length); - break; - case SSS_AUTHTOK_TYPE_CCFILE: -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: - break; - } - -@@ -187,6 +195,11 @@ errno_t sss_authtok_set(struct sss_auth_token *tok, - return sss_authtok_set_ccfile(tok, (const char *)data, len); - case SSS_AUTHTOK_TYPE_2FA: - return sss_authtok_set_2fa_from_blob(tok, data, len); -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ return sss_authtok_set_sc_pin(tok, (const char*)data, len); -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: -+ sss_authtok_set_sc_keypad(tok); -+ return EOK; - case SSS_AUTHTOK_TYPE_EMPTY: - sss_authtok_set_empty(tok); - return EOK; -@@ -411,3 +424,54 @@ errno_t sss_authtok_set_2fa(struct sss_auth_token *tok, - - return EOK; - } -+ -+errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin, -+ size_t len) -+{ -+ if (tok == NULL) { -+ return EFAULT; -+ } -+ if (pin == NULL) { -+ return EINVAL; -+ } -+ -+ sss_authtok_set_empty(tok); -+ -+ return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_SC_PIN, -+ "sc_pin", pin, len); -+} -+ -+errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin, -+ size_t *len) -+{ -+ if (!tok) { -+ return EFAULT; -+ } -+ switch (tok->type) { -+ case SSS_AUTHTOK_TYPE_EMPTY: -+ return ENOENT; -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ *pin = (const char *)tok->data; -+ if (len) { -+ *len = tok->length - 1; -+ } -+ return EOK; -+ case SSS_AUTHTOK_TYPE_PASSWORD: -+ case SSS_AUTHTOK_TYPE_CCFILE: -+ case SSS_AUTHTOK_TYPE_2FA: -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: -+ return EACCES; -+ } -+ -+ return EINVAL; -+} -+ -+void sss_authtok_set_sc_keypad(struct sss_auth_token *tok) -+{ -+ if (!tok) { -+ return; -+ } -+ sss_authtok_set_empty(tok); -+ -+ tok->type = SSS_AUTHTOK_TYPE_SC_KEYPAD; -+} -diff --git a/src/util/authtok.h b/src/util/authtok.h -index cb366270832852281a222018f8e27feb1500ff01..f1a01a42306a720fc39e701078550a071835e980 100644 ---- a/src/util/authtok.h -+++ b/src/util/authtok.h -@@ -223,4 +223,45 @@ errno_t sss_authtok_set_2fa(struct sss_auth_token *tok, - errno_t sss_authtok_get_2fa(struct sss_auth_token *tok, - const char **fa1, size_t *fa1_len, - const char **fa2, size_t *fa2_len); -+ -+/** -+ * @brief Set a Smart Card pin into a an auth token, replacing any previous data -+ * -+ * @param tok A pointer to a sss_auth_token structure to change, also -+ * used as a memory context to allocate the internal data. -+ * @param pin A string -+ * @param len The length of the string or, if 0 is passed, -+ * then strlen(password) will be used internally. -+ * -+ * @return EOK on success -+ * ENOMEM on error -+ */ -+errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin, -+ size_t len); -+ -+/** -+ * @brief Returns a Smart Card pin as const string if the auth token is of -+ * type SSS_AUTHTOK_TYPE_SC_PIN, otherwise it returns an error -+ * -+ * @param tok A pointer to an sss_auth_token -+ * @param pin A pointer to a const char *, that will point to a null -+ * terminated string -+ * @param len The length of the pin string -+ * -+ * @return EOK on success -+ * ENOENT if the token is empty -+ * EACCESS if the token is not a Smart Card pin token -+ */ -+errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin, -+ size_t *len); -+ -+/** -+ * @brief Sets an auth token to type SSS_AUTHTOK_TYPE_SC_KEYPAD, replacing any -+ * previous data -+ * -+ * @param tok A pointer to a sss_auth_token structure to change, also -+ * used as a memory context to allocate the internal data. -+ */ -+void sss_authtok_set_sc_keypad(struct sss_auth_token *tok); -+ - #endif /* __AUTHTOK_H__ */ --- -2.4.3 - diff --git a/SOURCES/0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch b/SOURCES/0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch deleted file mode 100644 index 8f70539..0000000 --- a/SOURCES/0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch +++ /dev/null @@ -1,1732 +0,0 @@ -unchanged: ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -115,6 +115,8 @@ - #define CONFDB_PAM_TRUSTED_USERS "pam_trusted_users" - #define CONFDB_PAM_PUBLIC_DOMAINS "pam_public_domains" - #define CONFDB_PAM_ACCOUNT_EXPIRED_MESSAGE "pam_account_expired_message" -+#define CONFDB_PAM_CERT_AUTH "pam_cert_auth" -+#define CONFDB_PAM_CERT_DB_PATH "pam_cert_db_path" - - /* SUDO */ - #define CONFDB_SUDO_CONF_ENTRY "config/sudo" -unchanged: ---- a/Makefile.am -+++ b/Makefile.am -@@ -382,6 +382,8 @@ dist_noinst_DATA = \ - contrib/ci/distro.sh \ - contrib/ci/misc.sh \ - contrib/ci/sssd.supp \ -+ src/tests/cmocka/p11_nssdb/cert9.db \ -+ src/tests/cmocka/p11_nssdb/key4.db \ - $(NULL) - - ############################### -@@ -1086,6 +1088,7 @@ sssd_pam_SOURCES = \ - src/responder/pam/pam_LOCAL_domain.c \ - src/responder/pam/pamsrv.c \ - src/responder/pam/pamsrv_cmd.c \ -+ src/responder/pam/pamsrv_p11.c \ - src/responder/pam/pamsrv_dp.c \ - src/responder/pam/pam_helpers.c \ - $(SSSD_RESPONDER_OBJ) -@@ -1877,11 +1880,13 @@ pam_srv_tests_SOURCES = \ - src/tests/cmocka/test_pam_srv.c \ - src/sss_client/pam_message.c \ - src/responder/pam/pamsrv_cmd.c \ -+ src/responder/pam/pamsrv_p11.c \ - src/responder/pam/pam_helpers.c \ - src/responder/pam/pamsrv_dp.c \ - src/responder/pam/pam_LOCAL_domain.c \ - $(NULL) - pam_srv_tests_CFLAGS = \ -+ -U SSSD_LIBEXEC_PATH -DSSSD_LIBEXEC_PATH=\"$(abs_builddir)\" \ - $(AM_CFLAGS) \ - $(NULL) - pam_srv_tests_LDFLAGS = \ -unchanged: ---- a/configure.ac -+++ b/configure.ac -@@ -400,6 +400,9 @@ abs_build_dir=`pwd` - AC_DEFINE_UNQUOTED([ABS_BUILD_DIR], ["$abs_build_dir"], [Absolute path to the build directory]) - AC_SUBST([abs_builddir], $abs_build_dir) - -+my_srcdir=`readlink -f $srcdir` -+AC_DEFINE_UNQUOTED([ABS_SRC_DIR], ["$my_srcdir"], [Absolute path to the source directory]) -+ - AC_CONFIG_FILES([Makefile contrib/sssd.spec src/examples/rwtab src/doxy.config - src/sysv/sssd src/sysv/gentoo/sssd src/sysv/SUSE/sssd - po/Makefile.in src/man/Makefile src/tests/cwrap/Makefile -unchanged: ---- a/src/responder/pam/pamsrv.c -+++ b/src/responder/pam/pamsrv.c -@@ -50,6 +50,8 @@ - #define ALL_DOMAIMS_ARE_PUBLIC "all" - #define NO_DOMAIMS_ARE_PUBLIC "none" - #define DEFAULT_ALLOWED_UIDS ALL_UIDS_ALLOWED -+#define DEFAULT_PAM_CERT_AUTH false -+#define DEFAULT_PAM_CERT_DB_PATH SYSCONFDIR"/pki/nssdb" - - struct mon_cli_iface monitor_pam_methods = { - { &mon_cli_iface_meta, 0 }, -@@ -302,6 +304,38 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, - goto done; - } - -+ /* Check if certificate based authentication is enabled */ -+ ret = confdb_get_bool(pctx->rctx->cdb, -+ CONFDB_PAM_CONF_ENTRY, -+ CONFDB_PAM_CERT_AUTH, -+ DEFAULT_PAM_CERT_AUTH, -+ &pctx->cert_auth); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to determine get cert db path.\n"); -+ goto done; -+ } -+ -+ pctx->p11_child_debug_fd = -1; -+ if (pctx->cert_auth) { -+ ret = p11_child_init(pctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "p11_child_init failed.\n"); -+ goto done; -+ } -+ -+ ret = confdb_get_string(pctx->rctx->cdb, pctx, -+ CONFDB_PAM_CONF_ENTRY, -+ CONFDB_PAM_CERT_DB_PATH, -+ DEFAULT_PAM_CERT_DB_PATH, -+ &pctx->nss_db); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, -+ "Failed to determine if certificate based authentication is " \ -+ "enabled or not.\n"); -+ goto done; -+ } -+ } -+ - ret = EOK; - - done: -unchanged: ---- a/src/responder/pam/pamsrv.h -+++ b/src/responder/pam/pamsrv.h -@@ -43,6 +43,10 @@ struct pam_ctx { - /* List of domains that are accessible even for untrusted users. */ - char **public_domains; - int public_domains_count; -+ -+ bool cert_auth; -+ int p11_child_debug_fd; -+ char *nss_db; - }; - - struct pam_auth_dp_req { -@@ -65,6 +69,9 @@ struct pam_auth_req { - bool cached_auth_failed; - - struct pam_auth_dp_req *dpreq_spy; -+ -+ struct ldb_message *cert_user_obj; -+ char *token_name; - }; - - struct sss_cmd_table *get_pam_cmds(void); -@@ -73,4 +80,19 @@ int pam_dp_send_req(struct pam_auth_req *preq, int timeout); - - int LOCAL_pam_handler(struct pam_auth_req *preq); - -+errno_t p11_child_init(struct pam_ctx *pctx); -+ -+struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ int child_debug_fd, -+ const char *nss_db, -+ time_t timeout, -+ struct pam_data *pd); -+errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, -+ char **cert, char **token_name); -+ -+errno_t add_pam_cert_response(struct pam_data *pd, const char *user, -+ const char *token_name); -+ -+bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd); - #endif /* __PAMSRV_H__ */ -unchanged: ---- a/src/responder/pam/pamsrv_cmd.c -+++ b/src/responder/pam/pamsrv_cmd.c -@@ -31,6 +31,7 @@ - #include "providers/data_provider.h" - #include "responder/pam/pamsrv.h" - #include "responder/pam/pam_helpers.h" -+#include "responder/common/responder_cache_req.h" - #include "db/sysdb.h" - - enum pam_verbosity { -@@ -49,6 +50,7 @@ static errno_t - pam_get_last_online_auth_with_curr_token(struct sss_domain_info *domain, - const char *name, - uint64_t *_value); -+ - static void pam_reply(struct pam_auth_req *preq); - - static errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx, -@@ -154,6 +156,13 @@ static int extract_authtok_v2(struct sss_auth_token *tok, - ret = sss_authtok_set(tok, SSS_AUTHTOK_TYPE_2FA, - auth_token_data, auth_token_length); - break; -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ ret = sss_authtok_set_sc_pin(tok, (const char *) auth_token_data, -+ auth_token_length); -+ break; -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: -+ sss_authtok_set_sc_keypad(tok); -+ break; - default: - return EINVAL; - } -@@ -892,6 +901,7 @@ static void pam_handle_cached_login(struct pam_auth_req *preq, int ret, - } - - static void pam_forwarder_cb(struct tevent_req *req); -+static void pam_forwarder_cert_cb(struct tevent_req *req); - static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min, - const char *err_msg, void *ptr); - static int pam_check_user_search(struct pam_auth_req *preq); -@@ -939,9 +949,22 @@ static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *p - goto done; - } - -- ret = sss_parse_name_for_domains(pd, cctx->rctx->domains, -- cctx->rctx->default_domain, pd->logon_name, -- &pd->domain, &pd->user); -+ if (pd->logon_name != NULL) { -+ ret = sss_parse_name_for_domains(pd, cctx->rctx->domains, -+ cctx->rctx->default_domain, -+ pd->logon_name, -+ &pd->domain, &pd->user); -+ } else { -+ /* Only SSS_PAM_PREAUTH request may have a missing name, e.g. if the -+ * name is determined with the help of a certificate */ -+ if (pd->cmd == SSS_PAM_PREAUTH) { -+ ret = EOK; -+ } else { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ } - - DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd); - -@@ -1052,49 +1075,66 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) - goto done; - } - -- /* now check user is valid */ -- if (pd->domain) { -- preq->domain = responder_get_domain(cctx->rctx, pd->domain); -- if (!preq->domain) { -- ret = ENOENT; -- goto done; -- } -- -- ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout, -- preq->domain, pd->user); -- if (ncret == EEXIST) { -- /* User found in the negative cache */ -- ret = ENOENT; -- goto done; -- } -- } else { -- for (dom = preq->cctx->rctx->domains; -- dom; -- dom = get_next_domain(dom, false)) { -- if (dom->fqnames) continue; -+ if (pd->user != NULL) { -+ /* now check user is valid */ -+ if (pd->domain) { -+ preq->domain = responder_get_domain(cctx->rctx, pd->domain); -+ if (!preq->domain) { -+ ret = ENOENT; -+ goto done; -+ } - - ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout, -- dom, pd->user); -- if (ncret == ENOENT) { -- /* User not found in the negative cache -- * Proceed with PAM actions -- */ -- break; -+ preq->domain, pd->user); -+ if (ncret == EEXIST) { -+ /* User found in the negative cache */ -+ ret = ENOENT; -+ goto done; - } -+ } else { -+ for (dom = preq->cctx->rctx->domains; -+ dom; -+ dom = get_next_domain(dom, false)) { -+ if (dom->fqnames) continue; - -- /* Try the next domain */ -- DEBUG(SSSDBG_TRACE_FUNC, -- "User [%s@%s] filtered out (negative cache). " -- "Trying next domain.\n", pd->user, dom->name); -+ ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout, -+ dom, pd->user); -+ if (ncret == ENOENT) { -+ /* User not found in the negative cache -+ * Proceed with PAM actions -+ */ -+ break; -+ } -+ -+ /* Try the next domain */ -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "User [%s@%s] filtered out (negative cache). " -+ "Trying next domain.\n", pd->user, dom->name); -+ } -+ -+ if (!dom) { -+ ret = ENOENT; -+ goto done; -+ } -+ preq->domain = dom; - } -+ } - -- if (!dom) { -- ret = ENOENT; -- goto done; -+ if (may_do_cert_auth(pctx, pd)) { -+ req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd, -+ pctx->nss_db, 10, pd); -+ if (req == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n"); -+ ret = ENOMEM; -+ } else { -+ tevent_req_set_callback(req, pam_forwarder_cert_cb, preq); -+ ret = EAGAIN; - } -- preq->domain = dom; -+ -+ goto done; - } - -+ - if (preq->domain->provider == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Domain [%s] has no auth provider.\n", preq->domain->name); -@@ -1113,6 +1153,142 @@ done: - return pam_check_user_done(preq, ret); - } - -+static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req); -+static void pam_forwarder_cert_cb(struct tevent_req *req) -+{ -+ struct pam_auth_req *preq = tevent_req_callback_data(req, -+ struct pam_auth_req); -+ struct cli_ctx *cctx = preq->cctx; -+ struct pam_data *pd; -+ errno_t ret = EOK; -+ char *cert; -+ struct pam_ctx *pctx = -+ talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); -+ -+ ret = pam_check_cert_recv(req, preq, &cert, &preq->token_name); -+ talloc_free(req); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "get_cert request failed.\n"); -+ goto done; -+ } -+ -+ pd = preq->pd; -+ -+ if (cert == NULL) { -+ if (pd->logon_name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "No certificate found and no logon name given, " \ -+ "authentication not possible.\n");; -+ ret = ENOENT; -+ } else { -+ if (pd->cmd == SSS_PAM_AUTHENTICATE) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "No certificate returned, authentication failed.\n"); -+ ret = ENOENT; -+ } else { -+ ret = pam_check_user_search(preq); -+ if (ret == EOK) { -+ pam_dom_forwarder(preq); -+ } -+ } -+ -+ } -+ goto done; -+ } -+ -+ -+ req = cache_req_user_by_cert_send(preq, cctx->ev, cctx->rctx, -+ pctx->ncache, pctx->neg_timeout, -+ 0, NULL, cert); -+ if (req == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ tevent_req_set_callback(req, pam_forwarder_lookup_by_cert_done, preq); -+ return; -+ -+done: -+ pam_check_user_done(preq, ret); -+} -+ -+static void pam_forwarder_lookup_by_cert_done(struct tevent_req *req) -+{ -+ int ret; -+ struct ldb_result *res; -+ struct sss_domain_info *domain; -+ struct pam_auth_req *preq = tevent_req_callback_data(req, -+ struct pam_auth_req); -+ const char *cert_user; -+ -+ -+ ret = cache_req_user_by_cert_recv(preq, req, &res, &domain, NULL); -+ talloc_zfree(req); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert request failed.\n"); -+ goto done; -+ } -+ -+ if (ret == EOK && res->count > 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Search by certificate returned more than one result.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (ret == EOK) { -+ if (preq->domain == NULL) { -+ preq->domain = domain; -+ } -+ -+ preq->cert_user_obj = talloc_steal(preq, res->msgs[0]); -+ -+ if (preq->pd->logon_name == NULL) { -+ cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj, -+ SYSDB_NAME, NULL); -+ if (cert_user == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Certificate user object has not name.\n"); -+ ret = ENOENT; -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_FUNC_DATA, "Found certificate user [%s].\n", -+ cert_user); -+ -+ ret = add_pam_cert_response(preq->pd, cert_user, preq->token_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n"); -+ } -+ -+ preq->pd->domain = talloc_strdup(preq->pd, domain->name); -+ if (preq->pd->domain == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ preq->pd->pam_status = PAM_SUCCESS; -+ pam_reply(preq); -+ return; -+ } -+ } else { -+ if (preq->pd->logon_name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Missing logon name and no certificate user found.\n"); -+ ret = ENOENT; -+ goto done; -+ } -+ } -+ -+ ret = pam_check_user_search(preq); -+ if (ret == EOK) { -+ pam_dom_forwarder(preq); -+ } -+ -+done: -+ pam_check_user_done(preq, ret); -+} -+ - static void pam_forwarder_cb(struct tevent_req *req) - { - struct pam_auth_req *preq = tevent_req_callback_data(req, -@@ -1120,6 +1296,8 @@ static void pam_forwarder_cb(struct tevent_req *req) - struct cli_ctx *cctx = preq->cctx; - struct pam_data *pd; - errno_t ret = EOK; -+ struct pam_ctx *pctx = -+ talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); - - ret = sss_dp_get_domains_recv(req); - talloc_free(req); -@@ -1158,6 +1336,20 @@ static void pam_forwarder_cb(struct tevent_req *req) - } - } - -+ if (may_do_cert_auth(pctx, pd)) { -+ req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd, -+ pctx->nss_db, 10, pd); -+ if (req == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n"); -+ ret = ENOMEM; -+ } else { -+ tevent_req_set_callback(req, pam_forwarder_cert_cb, preq); -+ ret = EAGAIN; -+ } -+ -+ goto done; -+ } -+ - ret = pam_check_user_search(preq); - if (ret == EOK) { - pam_dom_forwarder(preq); -@@ -1542,6 +1734,7 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) - int ret; - struct pam_ctx *pctx = - talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); -+ const char *cert_user; - - if (!preq->pd->domain) { - preq->pd->domain = preq->domain->name; -@@ -1579,6 +1772,51 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) - return; - } - -+ if (may_do_cert_auth(pctx, preq->pd) && preq->cert_user_obj != NULL) { -+ /* Check if user matches certificate user */ -+ cert_user = ldb_msg_find_attr_as_string(preq->cert_user_obj, SYSDB_NAME, -+ NULL); -+ if (cert_user == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Certificate user object has not name.\n"); -+ preq->pd->pam_status = PAM_USER_UNKNOWN; -+ pam_reply(preq); -+ return; -+ } -+ -+ /* pam_check_user_search() calls pd_set_primary_name() is the search -+ * was successful, so pd->user contains the canonical name as well */ -+ if (strcmp(cert_user, preq->pd->user) == 0) { -+ -+ preq->pd->pam_status = PAM_SUCCESS; -+ -+ if (preq->pd->cmd == SSS_PAM_PREAUTH) { -+ ret = add_pam_cert_response(preq->pd, cert_user, -+ preq->token_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "add_pam_cert_response failed.\n"); -+ preq->pd->pam_status = PAM_AUTHINFO_UNAVAIL; -+ } -+ } -+ -+ preq->callback = pam_reply; -+ pam_reply(preq); -+ return; -+ } else { -+ if (preq->pd->cmd == SSS_PAM_PREAUTH) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "User and certificate user do not match, " \ -+ "continue with other authentication methods.\n"); -+ } else { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "User and certificate user do not match.\n"); -+ preq->pd->pam_status = PAM_AUTH_ERR; -+ pam_reply(preq); -+ return; -+ } -+ } -+ } -+ - if (!NEED_CHECK_PROVIDER(preq->domain->provider) ) { - preq->callback = pam_reply; - ret = LOCAL_pam_handler(preq); -unchanged: ---- /dev/null -+++ b/src/responder/pam/pamsrv_p11.c -@@ -0,0 +1,527 @@ -+/* -+ SSSD -+ -+ PAM Responder - certificate realted requests -+ -+ Copyright (C) Sumit Bose 2015 -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+ -+#include "util/util.h" -+#include "providers/data_provider.h" -+#include "util/child_common.h" -+#include "util/strtonum.h" -+#include "responder/pam/pamsrv.h" -+ -+ -+#ifndef SSSD_LIBEXEC_PATH -+#error "SSSD_LIBEXEC_PATH not defined" -+#endif /* SSSD_LIBEXEC_PATH */ -+ -+#define P11_CHILD_LOG_FILE "p11_child" -+#define P11_CHILD_PATH SSSD_LIBEXEC_PATH"/p11_child" -+ -+errno_t p11_child_init(struct pam_ctx *pctx) -+{ -+ return child_debug_init(P11_CHILD_LOG_FILE, &pctx->p11_child_debug_fd); -+} -+ -+bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd) -+{ -+ size_t c; -+ const char *sc_services[] = { "login", "su", "su-l", "gdm-smartcard", -+ "gdm-password", "kdm", "sudo", "sudo-i", -+ NULL }; -+ if (!pctx->cert_auth) { -+ return false; -+ } -+ -+ if (pd->cmd != SSS_PAM_PREAUTH && pd->cmd != SSS_PAM_AUTHENTICATE) { -+ return false; -+ } -+ -+ if (pd->cmd == SSS_PAM_AUTHENTICATE -+ && sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_SC_PIN -+ && sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_SC_KEYPAD) { -+ return false; -+ } -+ -+ /* TODO: make services configurable */ -+ if (pd->service == NULL || *pd->service == '\0') { -+ return false; -+ } -+ for (c = 0; sc_services[c] != NULL; c++) { -+ if (strcmp(pd->service, sc_services[c]) == 0) { -+ break; -+ } -+ } -+ if (sc_services[c] == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Smartcard authentication for service [%s] not supported.\n", -+ pd->service); -+ return false; -+ } -+ -+ return true; -+} -+ -+static errno_t get_p11_child_write_buffer(TALLOC_CTX *mem_ctx, -+ struct pam_data *pd, -+ uint8_t **_buf, size_t *_len) -+{ -+ int ret; -+ uint8_t *buf; -+ size_t len; -+ const char *pin = NULL; -+ -+ if (pd == NULL || pd->authtok == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing authtok.\n"); -+ return EINVAL; -+ } -+ -+ switch (sss_authtok_get_type(pd->authtok)) { -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ ret = sss_authtok_get_sc_pin(pd->authtok, &pin, &len); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc_pin failed.\n"); -+ return ret; -+ } -+ if (pin == NULL || len == 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing PIN.\n"); -+ return EINVAL; -+ } -+ -+ buf = talloc_size(mem_ctx, len); -+ if (buf == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n"); -+ return ENOMEM; -+ } -+ -+ safealign_memcpy(buf, pin, len, NULL); -+ -+ break; -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: -+ /* Nothing to send */ -+ len = 0; -+ buf = NULL; -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported authtok type [%d].\n", -+ sss_authtok_get_type(pd->authtok)); -+ return EINVAL; -+ } -+ -+ *_len = len; -+ *_buf = buf; -+ -+ return EOK; -+} -+ -+static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, -+ ssize_t buf_len, char **_cert, -+ char **_token_name) -+{ -+ int ret; -+ TALLOC_CTX *tmp_ctx = NULL; -+ uint8_t *p; -+ uint8_t *pn; -+ char *cert = NULL; -+ char *token_name = NULL; -+ -+ if (buf_len < 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Error occured while reading data from p11_child.\n"); -+ return EIO; -+ } -+ -+ if (buf_len == 0) { -+ DEBUG(SSSDBG_TRACE_LIBS, "No certificate found.\n"); -+ ret = EOK; -+ goto done; -+ } -+ -+ p = memchr(buf, '\n', buf_len); -+ if (p == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "Missing new-line in p11_child response.\n"); -+ return EINVAL; -+ } -+ if (p == buf) { -+ DEBUG(SSSDBG_OP_FAILURE, "Missing counter in p11_child response.\n"); -+ return EINVAL; -+ } -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); -+ return ENOMEM; -+ } -+ -+ token_name = talloc_strndup(tmp_ctx, (char*) buf, (p - buf)); -+ if (token_name == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ p++; -+ pn = memchr(p, '\n', buf_len - (p - buf)); -+ if (pn == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Missing new-line in p11_child response.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ if (pn == p) { -+ DEBUG(SSSDBG_OP_FAILURE, "Missing cert in p11_child response.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ cert = talloc_strndup(tmp_ctx, (char *) p, (pn - p)); -+ if(cert == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ DEBUG(SSSDBG_TRACE_ALL, "Found cert [%s].\n", cert); -+ -+ ret = EOK; -+ -+done: -+ if (ret == EOK) { -+ *_token_name = talloc_steal(mem_ctx, token_name); -+ *_cert = talloc_steal(mem_ctx, cert); -+ } -+ -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -+ -+struct pam_check_cert_state { -+ int child_status; -+ struct sss_child_ctx_old *child_ctx; -+ struct tevent_timer *timeout_handler; -+ struct tevent_context *ev; -+ -+ int write_to_child_fd; -+ int read_from_child_fd; -+ char *cert; -+ char *token_name; -+}; -+ -+static void p11_child_write_done(struct tevent_req *subreq); -+static void p11_child_done(struct tevent_req *subreq); -+static void p11_child_timeout(struct tevent_context *ev, -+ struct tevent_timer *te, -+ struct timeval tv, void *pvt); -+ -+struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ int child_debug_fd, -+ const char *nss_db, -+ time_t timeout, -+ struct pam_data *pd) -+{ -+ errno_t ret; -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct pam_check_cert_state *state; -+ pid_t child_pid; -+ struct timeval tv; -+ int pipefd_to_child[2]; -+ int pipefd_from_child[2]; -+ const char *extra_args[5] = {NULL, NULL, NULL, NULL, NULL}; -+ uint8_t *write_buf = NULL; -+ size_t write_buf_len = 0; -+ -+ req = tevent_req_create(mem_ctx, &state, struct pam_check_cert_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ if (nss_db == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing NSS DB.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ /* extra_args are added in revers order */ -+ extra_args[1] = "--nssdb"; -+ extra_args[0] = nss_db; -+ if (pd->cmd == SSS_PAM_AUTHENTICATE) { -+ extra_args[2] = "--auth"; -+ switch (sss_authtok_get_type(pd->authtok)) { -+ case SSS_AUTHTOK_TYPE_SC_PIN: -+ extra_args[3] = "--pin"; -+ break; -+ case SSS_AUTHTOK_TYPE_SC_KEYPAD: -+ extra_args[3] = "--keypad"; -+ break; -+ default: -+ DEBUG(SSSDBG_OP_FAILURE, "Unsupported authtok type.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ } else if (pd->cmd == SSS_PAM_PREAUTH) { -+ extra_args[2] = "--pre"; -+ } else { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected PAM command [%d}.\n", pd->cmd); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ state->ev = ev; -+ state->child_status = EFAULT; -+ state->read_from_child_fd = -1; -+ state->write_to_child_fd = -1; -+ state->cert = NULL; -+ state->token_name = NULL; -+ -+ ret = pipe(pipefd_from_child); -+ if (ret == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "pipe failed [%d][%s].\n", ret, strerror(ret)); -+ goto done; -+ } -+ ret = pipe(pipefd_to_child); -+ if (ret == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "pipe failed [%d][%s].\n", ret, strerror(ret)); -+ goto done; -+ } -+ -+ if (child_debug_fd == -1) { -+ child_debug_fd = STDERR_FILENO; -+ } -+ -+ child_pid = fork(); -+ if (child_pid == 0) { /* child */ -+ ret = exec_child_ex(state, pipefd_to_child, pipefd_from_child, -+ P11_CHILD_PATH, child_debug_fd, extra_args, -+ STDIN_FILENO, STDOUT_FILENO); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec p11 child: [%d][%s].\n", -+ ret, strerror(ret)); -+ goto done; -+ } -+ } else if (child_pid > 0) { /* parent */ -+ -+ state->read_from_child_fd = pipefd_from_child[0]; -+ close(pipefd_from_child[1]); -+ sss_fd_nonblocking(state->read_from_child_fd); -+ -+ state->write_to_child_fd = pipefd_to_child[1]; -+ close(pipefd_to_child[0]); -+ sss_fd_nonblocking(state->write_to_child_fd); -+ -+ /* Set up SIGCHLD handler */ -+ ret = child_handler_setup(ev, child_pid, NULL, NULL, &state->child_ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Could not set up child handlers [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ ret = ERR_P11_CHILD; -+ goto done; -+ } -+ -+ /* Set up timeout handler */ -+ tv = tevent_timeval_current_ofs(timeout, 0); -+ state->timeout_handler = tevent_add_timer(ev, req, tv, -+ p11_child_timeout, req); -+ if(state->timeout_handler == NULL) { -+ ret = ERR_P11_CHILD; -+ goto done; -+ } -+ -+ if (pd->cmd == SSS_PAM_AUTHENTICATE) { -+ ret = get_p11_child_write_buffer(state, pd, &write_buf, -+ &write_buf_len); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "get_p11_child_write_buffer failed.\n"); -+ goto done; -+ } -+ } -+ -+ if (write_buf_len != 0) { -+ subreq = write_pipe_send(state, ev, write_buf, write_buf_len, -+ state->write_to_child_fd); -+ if (subreq == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "write_pipe_send failed.\n"); -+ ret = ERR_P11_CHILD; -+ goto done; -+ } -+ tevent_req_set_callback(subreq, p11_child_write_done, req); -+ } else { -+ subreq = read_pipe_send(state, ev, state->read_from_child_fd); -+ if (subreq == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "read_pipe_send failed.\n"); -+ ret = ERR_P11_CHILD; -+ goto done; -+ } -+ tevent_req_set_callback(subreq, p11_child_done, req); -+ } -+ -+ /* Now either wait for the timeout to fire or the child -+ * to finish -+ */ -+ } else { /* error */ -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, "fork failed [%d][%s].\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ } -+ return req; -+} -+ -+static void p11_child_write_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct pam_check_cert_state *state = tevent_req_data(req, -+ struct pam_check_cert_state); -+ int ret; -+ -+ ret = write_pipe_recv(subreq); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ close(state->write_to_child_fd); -+ state->write_to_child_fd = -1; -+ -+ subreq = read_pipe_send(state, state->ev, state->read_from_child_fd); -+ if (subreq == NULL) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, p11_child_done, req); -+} -+ -+static void p11_child_done(struct tevent_req *subreq) -+{ -+ uint8_t *buf; -+ ssize_t buf_len; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct pam_check_cert_state *state = tevent_req_data(req, -+ struct pam_check_cert_state); -+ int ret; -+ -+ talloc_zfree(state->timeout_handler); -+ -+ ret = read_pipe_recv(subreq, state, &buf, &buf_len); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ close(state->read_from_child_fd); -+ state->read_from_child_fd = -1; -+ -+ ret = parse_p11_child_response(state, buf, buf_len, &state->cert, -+ &state->token_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "parse_p11_child_respose failed.\n"); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+ return; -+} -+ -+static void p11_child_timeout(struct tevent_context *ev, -+ struct tevent_timer *te, -+ struct timeval tv, void *pvt) -+{ -+ struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); -+ struct pam_check_cert_state *state = -+ tevent_req_data(req, struct pam_check_cert_state); -+ -+ DEBUG(SSSDBG_CRIT_FAILURE, "Timeout reached for p11_child.\n"); -+ child_handler_destroy(state->child_ctx); -+ state->child_ctx = NULL; -+ state->child_status = ETIMEDOUT; -+ tevent_req_error(req, ERR_P11_CHILD); -+} -+ -+errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, -+ char **cert, char **token_name) -+{ -+ struct pam_check_cert_state *state = -+ tevent_req_data(req, struct pam_check_cert_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ if (cert != NULL) { -+ *cert = talloc_steal(mem_ctx, state->cert); -+ } -+ -+ if (token_name != NULL) { -+ *token_name = talloc_steal(mem_ctx, state->token_name); -+ } -+ -+ return EOK; -+} -+ -+errno_t add_pam_cert_response(struct pam_data *pd, const char *user, -+ const char *token_name) -+{ -+ uint8_t *msg = NULL; -+ size_t user_len; -+ size_t msg_len; -+ size_t slot_len; -+ int ret; -+ -+ if (user == NULL || token_name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing mandatory user or slot name.\n"); -+ return EINVAL; -+ } -+ -+ user_len = strlen(user) + 1; -+ slot_len = strlen(token_name) + 1; -+ msg_len = user_len + slot_len; -+ -+ msg = talloc_zero_size(pd, msg_len); -+ if (msg == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n"); -+ return ENOMEM; -+ } -+ -+ memcpy(msg, user, user_len); -+ memcpy(msg + user_len, token_name, slot_len); -+ -+ ret = pam_add_response(pd, SSS_PAM_CERT_INFO, msg_len, msg); -+ talloc_free(msg); -+ -+ return ret; -+} -unchanged: ---- a/src/sss_client/sss_cli.h -+++ b/src/sss_client/sss_cli.h -@@ -417,6 +417,7 @@ enum response_type { - * @param Three zero terminated strings, if one of the - * strings is missing the message will contain only - * an empty string (\0) for that component. */ -+ SSS_PAM_CERT_INFO, - SSS_OTP, /**< Indicates that the autotok was a OTP, so don't - * cache it. There is no message. - * @param None. */ -unchanged: ---- a/src/tests/cmocka/test_pam_srv.c -+++ b/src/tests/cmocka/test_pam_srv.c -@@ -32,7 +32,10 @@ - #include "sss_client/pam_message.h" - #include "sss_client/sss_cli.h" - -+#include "util/crypto/sss_crypto.h" -+#ifdef HAVE_NSS - #include "util/crypto/nss/nss_util.h" -+#endif - - #define TESTS_PATH "tests_pam" - #define TEST_CONF_DB "test_pam_conf.ldb" -@@ -40,6 +43,34 @@ - #define TEST_SUBDOM_NAME "test.subdomain" - #define TEST_ID_PROVIDER "ldap" - -+#define NSS_DB_PATH "./sssd_test_nssdb" -+#define NSS_DB "sql:"NSS_DB_PATH -+ -+#define TEST_TOKEN_NAME "SSSD Test Token" -+#define TEST_TOKEN_CERT \ -+"MIIECTCCAvGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \ -+"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA2MjMx" \ -+"NjMyMDdaFw0xNzA2MjMxNjMyMDdaMDIxEjAQBgNVBAoMCUlQQS5ERVZFTDEcMBoG" \ -+"A1UEAwwTaXBhLWRldmVsLmlwYS5kZXZlbDCCASIwDQYJKoZIhvcNAQEBBQADggEP" \ -+"ADCCAQoCggEBALXUq56VlY+Z0aWLLpFAjFfbElPBXGQsbZb85J3cGyPjaMHC9wS+" \ -+"wjB6Ve4HmQyPLx8hbINdDmbawMHYQvTScLYfsqLtj0Lqw20sUUmedk+Es5Oh9VHo" \ -+"nd8MavYx25Du2u+T0iSgNIDikXguiwCmtAj8VC49ebbgITcjJGzMmiiuJkV3o93Y" \ -+"vvYF0VjLGDQbQWOy7IxzYJeNVJnZWKo67CHdok6qOrm9rxQt81rzwV/mGLbCMUbr" \ -+"+N4M8URtd7EmzaYZQmNm//s2owFrCYMxpLiURPj+URZVuB72504/Ix7X0HCbA/AV" \ -+"26J27fPY5nc8DMwfhUDCbTqPH/JEjd3mvY8CAwEAAaOCASYwggEiMB8GA1UdIwQY" \ -+"MBaAFJOq+KAQmPEnNp8Wok23eGTdE7aDMDsGCCsGAQUFBwEBBC8wLTArBggrBgEF" \ -+"BQcwAYYfaHR0cDovL2lwYS1jYS5pcGEuZGV2ZWwvY2Evb2NzcDAOBgNVHQ8BAf8E" \ -+"BAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHQGA1UdHwRtMGsw" \ -+"aaAxoC+GLWh0dHA6Ly9pcGEtY2EuaXBhLmRldmVsL2lwYS9jcmwvTWFzdGVyQ1JM" \ -+"LmJpbqI0pDIwMDEOMAwGA1UECgwFaXBhY2ExHjAcBgNVBAMMFUNlcnRpZmljYXRl" \ -+"IEF1dGhvcml0eTAdBgNVHQ4EFgQUFaDNd5a53QGpaw5m63hnwXicMQ8wDQYJKoZI" \ -+"hvcNAQELBQADggEBADH7Nj00qqGhGJeXJQAsepqSskz/wooqXh8vgVyb8SS4N0/c" \ -+"0aQtVmY81xamlXE12ZFpwDX43d+EufBkwCUKFX/+8JFDd2doAyeJxv1xM22kKRpc" \ -+"AqITPgMsa9ToGMWxjbVpc/X/5YfZixWPF0/eZUTotBj9oaR039UrhGfyN7OguF/G" \ -+"rzmxtB5y4ZrMpcD/Oe90mkd9HY7sA/fB8OWOUgeRfQoh97HNS0UiDWsPtfxmjQG5" \ -+"zotpoBIZmdH+ipYsu58HohHVlM9Wi5H4QmiiXl+Soldkq7eXYlafcmT7wv8+cKwz" \ -+"Nz0Tm3+eYpFqRo3skr6QzXi525Jkg3r6r+kkhxU=" \ -+ - struct pam_test_ctx { - struct sss_test_ctx *tctx; - struct sss_domain_info *subdom; -@@ -56,6 +87,84 @@ struct pam_test_ctx { - /* Must be global because it is needed in some wrappers */ - struct pam_test_ctx *pam_test_ctx; - -+static errno_t setup_nss_db(void) -+{ -+ int ret; -+ FILE *fp; -+ int status; -+ pid_t child_pid; -+ -+ ret = mkdir(NSS_DB_PATH, 0775); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to create " NSS_DB_PATH ".\n"); -+ return ret; -+ } -+ -+ child_pid = fork(); -+ if (child_pid == 0) { /* child */ -+ ret = execlp("certutil", "certutil", "-N", "--empty-password", "-d", -+ NSS_DB, NULL); -+ if (ret == -1) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "execl() failed.\n"); -+ exit(-1); -+ } -+ } else if (child_pid > 0) { -+ wait(&status); -+ } else { -+ ret = errno; -+ DEBUG(SSSDBG_FATAL_FAILURE, "fork() failed\n"); -+ return ret; -+ } -+ -+ fp = fopen(NSS_DB_PATH"/pkcs11.txt", "w"); -+ if (fp == NULL) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fopen() failed.\n"); -+ return ret; -+ } -+ ret = fprintf(fp, "library=libsoftokn3.so\nname=soft\n"); -+ if (ret < 0) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fprintf() failed.\n"); -+ return ret; -+ } -+ ret = fprintf(fp, "parameters=configdir='sql:%s/src/tests/cmocka/p11_nssdb' dbSlotDescription='SSSD Test Slot' dbTokenDescription='SSSD Test Token' secmod='secmod.db' flags=readOnly \n\n", ABS_SRC_DIR); -+ if (ret < 0) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fprintf() failed.\n"); -+ return ret; -+ } -+ ret = fclose(fp); -+ if (ret != 0) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "fclose() failed.\n"); -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+static void cleanup_nss_db(void) -+{ -+ int ret; -+ -+ ret = unlink(NSS_DB_PATH"/cert9.db"); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove cert9.db.\n"); -+ } -+ -+ ret = unlink(NSS_DB_PATH"/key4.db"); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove key4.db.\n"); -+ } -+ -+ ret = unlink(NSS_DB_PATH"/pkcs11.txt"); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove pkcs11.db.\n"); -+ } -+ -+ ret = rmdir(NSS_DB_PATH); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "Failed to remove " NSS_DB_PATH "\n"); -+ } -+} -+ - struct pam_ctx *mock_pctx(TALLOC_CTX *mem_ctx) - { - struct pam_ctx *pctx; -@@ -113,6 +222,7 @@ void test_pam_setup(struct sss_test_conf_param params[], - assert_non_null(pam_test_ctx->cctx); - - pam_test_ctx->cctx->cli_protocol_version = register_cli_protocol_version(); -+ pam_test_ctx->cctx->ev = pam_test_ctx->tctx->ev; - } - - static int pam_test_setup(void **state) -@@ -141,6 +251,22 @@ static int pam_test_setup(void **state) - discard_const("pamuser"), - pam_test_ctx->pctx->id_timeout); - assert_int_equal(ret, EOK); -+ -+ /* Prime the cache with a user for wrong matches */ -+ ret = sysdb_add_user(pam_test_ctx->tctx->dom, -+ "wronguser", 321, 654, "wrong user", -+ "/home/wringuser", "/bin/sh", NULL, -+ NULL, 300, 0); -+ assert_int_equal(ret, EOK); -+ -+ /* Add entry to the initgr cache to make sure no initgr request is sent to -+ * the backend */ -+ ret = pam_initgr_cache_set(pam_test_ctx->pctx->rctx->ev, -+ pam_test_ctx->pctx->id_table, -+ discard_const("wronguser"), -+ pam_test_ctx->pctx->id_timeout); -+ assert_int_equal(ret, EOK); -+ - return 0; - } - -@@ -151,12 +277,19 @@ static int pam_test_teardown(void **state) - ret = sysdb_delete_user(pam_test_ctx->tctx->dom, "pamuser", 0); - assert_int_equal(ret, EOK); - -+ ret = sysdb_delete_user(pam_test_ctx->tctx->dom, "wronguser", 0); -+ assert_int_equal(ret, EOK); -+ - talloc_free(pam_test_ctx); - return 0; - } - - typedef int (*cmd_cb_fn_t)(uint32_t, uint8_t *, size_t); - -+ -+int __real_read_pipe_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, -+ uint8_t **buf, ssize_t *len); -+ - void __real_sss_packet_get_body(struct sss_packet *packet, - uint8_t **body, size_t *blen); - -@@ -239,8 +372,13 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name, - size_t needed_size; - uint8_t *authtok; - -- pi.pam_user = name; -- pi.pam_user_size = strlen(pi.pam_user) + 1; -+ if (name != NULL) { -+ pi.pam_user = name; -+ pi.pam_user_size = strlen(pi.pam_user) + 1; -+ } else { -+ pi.pam_user = ""; -+ pi.pam_user_size = 0; -+ } - - if (pwd != NULL) { - if (fa2 != NULL) { -@@ -287,6 +425,52 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name, - will_return(__wrap_sss_packet_get_body, buf_size); - } - -+static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name, -+ const char *pin) -+{ -+ size_t buf_size; -+ uint8_t *m_buf; -+ uint8_t *buf; -+ struct pam_items pi = { 0 }; -+ int ret; -+ -+ if (name != NULL) { -+ pi.pam_user = name; -+ pi.pam_user_size = strlen(pi.pam_user) + 1; -+ } else { -+ pi.pam_user = ""; -+ pi.pam_user_size = 0; -+ } -+ -+ if (pin != NULL) { -+ pi.pam_authtok = discard_const(pin); -+ pi.pam_authtok_size = strlen(pi.pam_authtok) + 1; -+ pi.pam_authtok_type = SSS_AUTHTOK_TYPE_SC_PIN; -+ } -+ -+ pi.pam_service = "login"; -+ pi.pam_service_size = strlen(pi.pam_service) + 1; -+ pi.pam_tty = "/dev/tty"; -+ pi.pam_tty_size = strlen(pi.pam_tty) + 1; -+ pi.pam_ruser = "remuser"; -+ pi.pam_ruser_size = strlen(pi.pam_ruser) + 1; -+ pi.pam_rhost = "remhost"; -+ pi.pam_rhost_size = strlen(pi.pam_rhost) + 1; -+ pi.requested_domains = ""; -+ pi.cli_pid = 12345; -+ -+ ret = pack_message_v3(&pi, &buf_size, &m_buf); -+ assert_int_equal(ret, 0); -+ -+ buf = talloc_memdup(mem_ctx, m_buf, buf_size); -+ free(m_buf); -+ assert_non_null(buf); -+ -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER); -+ will_return(__wrap_sss_packet_get_body, buf); -+ will_return(__wrap_sss_packet_get_body, buf_size); -+} -+ - static int test_pam_simple_check(uint32_t status, uint8_t *body, size_t blen) - { - size_t rp = 0; -@@ -312,6 +496,46 @@ static int test_pam_simple_check(uint32_t status, uint8_t *body, size_t blen) - return EOK; - } - -+static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen) -+{ -+ size_t rp = 0; -+ uint32_t val; -+ -+ assert_int_equal(status, 0); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, pam_test_ctx->exp_pam_status); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, 2); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, SSS_PAM_DOMAIN_NAME); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, 9); -+ -+ assert_int_equal(*(body + rp + val - 1), 0); -+ assert_string_equal(body + rp, TEST_DOM_NAME); -+ rp += val; -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, SSS_PAM_CERT_INFO); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, (sizeof("pamuser") + sizeof(TEST_TOKEN_NAME))); -+ -+ assert_int_equal(*(body + rp + sizeof("pamuser") - 1), 0); -+ assert_string_equal(body + rp, "pamuser"); -+ rp += sizeof("pamuser"); -+ -+ assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0); -+ assert_string_equal(body + rp, TEST_TOKEN_NAME); -+ -+ return EOK; -+} -+ -+ - static int test_pam_offline_chauthtok_check(uint32_t status, - uint8_t *body, size_t blen) - { -@@ -372,6 +596,23 @@ static int test_pam_wrong_pw_offline_auth_check(uint32_t status, - return test_pam_simple_check(status, body, blen); - } - -+static int test_pam_user_unknown_check(uint32_t status, -+ uint8_t *body, size_t blen) -+{ -+ size_t rp = 0; -+ uint32_t val; -+ -+ assert_int_equal(status, 0); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, PAM_USER_UNKNOWN); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, 0); -+ -+ return EOK; -+} -+ - void test_pam_authenticate(void **state) - { - int ret; -@@ -859,6 +1100,245 @@ void test_pam_offline_chauthtok(void **state) - assert_int_equal(ret, EOK); - } - -+static void set_cert_auth_param(struct pam_ctx *pctx, const char *dbpath) -+{ -+ pam_test_ctx->pctx->cert_auth = true; -+ pam_test_ctx->pctx->nss_db = discard_const(dbpath); -+} -+ -+void test_pam_preauth_cert_nocert(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, "/no/path"); -+ -+ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ set_cmd_cb(test_pam_simple_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+static int test_lookup_by_cert_cb(void *pvt) -+{ -+ int ret; -+ struct sysdb_attrs *attrs; -+ unsigned char *der = NULL; -+ size_t der_size; -+ -+ if (pvt != NULL) { -+ -+ attrs = sysdb_new_attrs(pam_test_ctx); -+ assert_non_null(attrs); -+ -+ der = sss_base64_decode(pam_test_ctx, pvt, &der_size); -+ assert_non_null(der); -+ -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ talloc_free(der); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, "pamuser", attrs, -+ LDB_FLAG_MOD_ADD); -+ assert_int_equal(ret, EOK); -+ } -+ -+ return EOK; -+} -+ -+static int test_lookup_by_cert_wrong_user_cb(void *pvt) -+{ -+ int ret; -+ struct sysdb_attrs *attrs; -+ unsigned char *der = NULL; -+ size_t der_size; -+ -+ if (pvt != NULL) { -+ attrs = sysdb_new_attrs(pam_test_ctx); -+ assert_non_null(attrs); -+ -+ der = sss_base64_decode(pam_test_ctx, pvt, &der_size); -+ assert_non_null(der); -+ -+ ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); -+ talloc_free(der); -+ assert_int_equal(ret, EOK); -+ -+ ret = sysdb_set_user_attr(pam_test_ctx->tctx->dom, "wronguser", attrs, -+ LDB_FLAG_MOD_ADD); -+ assert_int_equal(ret, EOK); -+ } -+ -+ return EOK; -+} -+ -+ -+void test_pam_preauth_cert_nomatch(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); -+ -+ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, NULL); -+ -+ set_cmd_cb(test_pam_simple_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_pam_preauth_cert_match(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); -+ -+ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, -+ discard_const(TEST_TOKEN_CERT)); -+ -+ set_cmd_cb(test_pam_cert_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_pam_preauth_cert_match_wrong_user(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); -+ -+ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ mock_account_recv(0, 0, NULL, test_lookup_by_cert_wrong_user_cb, -+ discard_const(TEST_TOKEN_CERT)); -+ -+ set_cmd_cb(test_pam_simple_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+ -+void test_pam_preauth_cert_no_logon_name(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); -+ -+ mock_input_pam_cert(pam_test_ctx, NULL, NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, -+ discard_const(TEST_TOKEN_CERT)); -+ -+ set_cmd_cb(test_pam_cert_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_pam_preauth_no_cert_no_logon_name(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, "/no/path"); -+ -+ mock_input_pam_cert(pam_test_ctx, NULL, NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ set_cmd_cb(test_pam_user_unknown_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_pam_preauth_cert_no_logon_name_no_match(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); -+ -+ mock_input_pam_cert(pam_test_ctx, NULL, NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, NULL); -+ -+ set_cmd_cb(test_pam_user_unknown_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+void test_pam_cert_auth(void **state) -+{ -+ int ret; -+ -+ set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); -+ -+ mock_input_pam_cert(pam_test_ctx, "pamuser", "123456"); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, -+ discard_const(TEST_TOKEN_CERT)); -+ -+ set_cmd_cb(test_pam_simple_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ - int main(int argc, const char *argv[]) - { - int rv; -@@ -925,6 +1405,23 @@ int main(int argc, const char *argv[]) - pam_test_setup, pam_test_teardown), - cmocka_unit_test_setup_teardown(test_pam_offline_chauthtok, - pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nocert, -+ pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nomatch, -+ pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_preauth_cert_match, -+ pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_preauth_cert_match_wrong_user, -+ pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_preauth_cert_no_logon_name, -+ pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_preauth_no_cert_no_logon_name, -+ pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown( -+ test_pam_preauth_cert_no_logon_name_no_match, -+ pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_cert_auth, -+ pam_test_setup, pam_test_teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ -@@ -950,8 +1447,16 @@ int main(int argc, const char *argv[]) - test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); - test_dom_suite_setup(TESTS_PATH); - -+ cleanup_nss_db(); -+ rv = setup_nss_db(); -+ if (rv != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "setup_nss_db failed.\n"); -+ exit(-1); -+ } -+ - rv = cmocka_run_group_tests(tests, NULL, NULL); - if (rv == 0 && !no_cleanup) { -+ cleanup_nss_db(); - test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); - } - -unchanged: ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -78,6 +78,7 @@ struct err_string error_to_str[] = { - { "Unsupported trust direction" }, /* ERR_TRUST_NOT_SUPPORTED */ - { "Retrieving keytab failed" }, /* ERR_IPA_GETKEYTAB_FAILED */ - { "Trusted forest root unknown" }, /* ERR_TRUST_FOREST_UNKNOWN */ -+ { "p11_child failed" }, /* ERR_P11_CHILD */ - { "ERR_LAST" } /* ERR_LAST */ - }; - -only in patch2: -unchanged: ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -100,6 +100,7 @@ enum sssd_errors { - ERR_TRUST_NOT_SUPPORTED, - ERR_IPA_GETKEYTAB_FAILED, - ERR_TRUST_FOREST_UNKNOWN, -+ ERR_P11_CHILD, - ERR_LAST /* ALWAYS LAST */ - }; - diff --git a/SOURCES/0034-UTIL-make-domain-mapping-content-testable.patch b/SOURCES/0034-UTIL-make-domain-mapping-content-testable.patch new file mode 100644 index 0000000..c3dcc69 --- /dev/null +++ b/SOURCES/0034-UTIL-make-domain-mapping-content-testable.patch @@ -0,0 +1,286 @@ +From 9d02728f8d64742e28f32fdf5bfdf083dc15a5c8 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 18 Jul 2016 17:37:49 +0200 +Subject: [PATCH 34/44] UTIL: make domain mapping content testable + +Reviewed-by: Jakub Hrozek +--- + src/util/domain_info_utils.c | 216 +++++++++++++++++++++++++++---------------- + src/util/util.h | 4 + + 2 files changed, 138 insertions(+), 82 deletions(-) + +diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c +index 8cdd50d8d521d734e9ffd9b4e81cd6fbd7d158c7..587a6b993d2bd70662df8e0b0d5963fa00c84cf8 100644 +--- a/src/util/domain_info_utils.c ++++ b/src/util/domain_info_utils.c +@@ -262,11 +262,135 @@ sss_krb5_touch_config(void) + return EOK; + } + ++errno_t sss_get_domain_mappings_content(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain, ++ char **content) ++{ ++ int ret; ++ char *o = NULL; ++ struct sss_domain_info *dom; ++ struct sss_domain_info *parent_dom; ++ char *uc_parent = NULL; ++ char *uc_forest = NULL; ++ char *parent_capaths = NULL; ++ bool capaths_started = false; ++ ++ if (domain == NULL || content == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Missing parameter.\n"); ++ return EINVAL; ++ } ++ ++ o = talloc_strdup(mem_ctx, "[domain_realm]\n"); ++ if (o == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ /* This loops skips the starting parent and start rigth with the first ++ * subdomain. Although in all the interesting cases (AD and IPA) the ++ * default is that realm and DNS domain are the same strings (expect case) ++ * and no domain_realm mapping is needed we might consider to add this ++ * domain here as well to cover corner cases? */ ++ for (dom = get_next_domain(domain, SSS_GND_DESCEND); ++ dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ ++ dom = get_next_domain(dom, 0)) { ++ o = talloc_asprintf_append(o, ".%s = %s\n%s = %s\n", ++ dom->name, dom->realm, dom->name, dom->realm); ++ if (o == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf_append failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ parent_dom = domain; ++ uc_parent = get_uppercase_realm(mem_ctx, parent_dom->name); ++ if (uc_parent == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "get_uppercase_realm failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ for (dom = get_next_domain(domain, SSS_GND_DESCEND); ++ dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ ++ dom = get_next_domain(dom, 0)) { ++ ++ if (dom->forest == NULL) { ++ continue; ++ } ++ ++ talloc_free(uc_forest); ++ uc_forest = get_uppercase_realm(mem_ctx, dom->forest); ++ if (uc_forest == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "get_uppercase_realm failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ if (!capaths_started) { ++ o = talloc_asprintf_append(o, "[capaths]\n"); ++ if (o == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf_append failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ capaths_started = true; ++ } ++ ++ o = talloc_asprintf_append(o, "%s = {\n %s = %s\n}\n", ++ dom->realm, uc_parent, uc_forest); ++ if (o == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf_append failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ if (parent_capaths == NULL) { ++ parent_capaths = talloc_asprintf(mem_ctx, " %s = %s\n", dom->realm, ++ uc_forest); ++ } else { ++ parent_capaths = talloc_asprintf_append(parent_capaths, ++ " %s = %s\n", dom->realm, ++ uc_forest); ++ } ++ if (parent_capaths == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "talloc_asprintf/talloc_asprintf_append failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ if (parent_capaths != NULL) { ++ o = talloc_asprintf_append(o, "%s = {\n%s}\n", uc_parent, ++ parent_capaths); ++ if (o == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf_append failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ ret = EOK; ++ ++done: ++ talloc_free(parent_capaths); ++ talloc_free(uc_parent); ++ talloc_free(uc_forest); ++ ++ if (ret == EOK) { ++ *content = o; ++ } else { ++ talloc_free(o); ++ } ++ ++ return ret; ++} ++ + errno_t + sss_write_domain_mappings(struct sss_domain_info *domain) + { +- struct sss_domain_info *dom; +- struct sss_domain_info *parent_dom; + errno_t ret; + errno_t err; + TALLOC_CTX *tmp_ctx; +@@ -277,10 +401,7 @@ sss_write_domain_mappings(struct sss_domain_info *domain) + mode_t old_mode; + FILE *fstream = NULL; + int i; +- bool capaths_started = false; +- char *uc_forest; +- char *uc_parent; +- char *parent_capaths = NULL; ++ char *content = NULL; + + if (domain == NULL || domain->name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "No domain name provided\n"); +@@ -290,6 +411,12 @@ sss_write_domain_mappings(struct sss_domain_info *domain) + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return ENOMEM; + ++ ret = sss_get_domain_mappings_content(tmp_ctx, domain, &content); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sss_get_domain_mappings_content failed.\n"); ++ goto done; ++ } ++ + sanitized_domain = talloc_strdup(tmp_ctx, domain->name); + if (sanitized_domain == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); +@@ -349,88 +476,13 @@ sss_write_domain_mappings(struct sss_domain_info *domain) + goto done; + } + +- ret = fprintf(fstream, "[domain_realm]\n"); ++ ret = fprintf(fstream, "%s", content); + if (ret < 0) { + DEBUG(SSSDBG_OP_FAILURE, "fprintf failed\n"); + ret = EIO; + goto done; + } + +- for (dom = get_next_domain(domain, SSS_GND_DESCEND); +- dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ +- dom = get_next_domain(dom, 0)) { +- ret = fprintf(fstream, ".%s = %s\n%s = %s\n", +- dom->name, dom->realm, dom->name, dom->realm); +- if (ret < 0) { +- DEBUG(SSSDBG_CRIT_FAILURE, "fprintf failed\n"); +- goto done; +- } +- } +- +- parent_dom = domain; +- uc_parent = get_uppercase_realm(tmp_ctx, parent_dom->name); +- if (uc_parent == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "get_uppercase_realm failed.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- for (dom = get_next_domain(domain, SSS_GND_DESCEND); +- dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ +- dom = get_next_domain(dom, 0)) { +- +- if (dom->forest == NULL) { +- continue; +- } +- +- uc_forest = get_uppercase_realm(tmp_ctx, dom->forest); +- if (uc_forest == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "get_uppercase_realm failed.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- if (!capaths_started) { +- ret = fprintf(fstream, "[capaths]\n"); +- if (ret < 0) { +- DEBUG(SSSDBG_OP_FAILURE, "fprintf failed\n"); +- ret = EIO; +- goto done; +- } +- capaths_started = true; +- } +- +- ret = fprintf(fstream, "%s = {\n %s = %s\n}\n", +- dom->realm, uc_parent, uc_forest); +- if (ret < 0) { +- DEBUG(SSSDBG_CRIT_FAILURE, "fprintf failed\n"); +- goto done; +- } +- +- if (parent_capaths == NULL) { +- parent_capaths = talloc_asprintf(tmp_ctx, " %s = %s\n", dom->realm, +- uc_forest); +- } else { +- parent_capaths = talloc_asprintf_append(parent_capaths, +- " %s = %s\n", dom->realm, +- uc_forest); +- } +- if (parent_capaths == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, +- "talloc_asprintf/talloc_asprintf_append failed.\n"); +- ret = ENOMEM; +- goto done; +- } +- } +- +- if (parent_capaths != NULL) { +- ret = fprintf(fstream, "%s = {\n%s}\n", uc_parent, parent_capaths); +- if (ret < 0) { +- DEBUG(SSSDBG_CRIT_FAILURE, "fprintf failed\n"); +- goto done; +- } +- } +- + ret = fclose(fstream); + fstream = NULL; + if (ret != 0) { +diff --git a/src/util/util.h b/src/util/util.h +index 8a5caa52c2dc5243c3ae51c5a38fd65a949f4ac4..122be90b967fb7793adaff95f3754d7a199fcf48 100644 +--- a/src/util/util.h ++++ b/src/util/util.h +@@ -540,6 +540,10 @@ errno_t sssd_domain_init(TALLOC_CTX *mem_ctx, + * written to */ + #define KRB5_MAPPING_DIR PUBCONF_PATH"/krb5.include.d" + ++errno_t sss_get_domain_mappings_content(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain, ++ char **content); ++ + errno_t sss_write_domain_mappings(struct sss_domain_info *domain); + + errno_t sss_write_krb5_conf_snippet(const char *path, bool canonicalize); +-- +2.4.11 + diff --git a/SOURCES/0035-pam_sss-add-sc-support.patch b/SOURCES/0035-pam_sss-add-sc-support.patch deleted file mode 100644 index d5a550d..0000000 --- a/SOURCES/0035-pam_sss-add-sc-support.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 98be4f0858e7c38f18b73fda6949edf7790bcad6 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 3 Jul 2015 14:05:11 +0200 -Subject: [PATCH 35/37] pam_sss: add sc support - -Reviewed-by: Jakub Hrozek ---- - src/sss_client/pam_message.h | 3 ++ - src/sss_client/pam_sss.c | 94 +++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 96 insertions(+), 1 deletion(-) - -diff --git a/src/sss_client/pam_message.h b/src/sss_client/pam_message.h -index 3b3841a2c66b46d78855164099684ef2ac98ed77..f0a7a076cf38a4efc8befcc2fb835ae26e9415a4 100644 ---- a/src/sss_client/pam_message.h -+++ b/src/sss_client/pam_message.h -@@ -56,6 +56,9 @@ struct pam_items { - char *otp_token_id; - char *otp_challenge; - char *first_factor; -+ -+ char *cert_user; -+ char *token_name; - }; - - int pack_message_v3(struct pam_items *pi, size_t *size, uint8_t **buffer); -diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c -index e4fa83e12c71bb05dd329686cf2d2df6323ff3bd..431f5dc62655dd1e6901f16f72dcad9703f037ac 100644 ---- a/src/sss_client/pam_sss.c -+++ b/src/sss_client/pam_sss.c -@@ -155,6 +155,12 @@ static void overwrite_and_free_pam_items(struct pam_items *pi) - - free(pi->otp_challenge); - pi->otp_challenge = NULL; -+ -+ free(pi->cert_user); -+ pi->cert_user = NULL; -+ -+ free(pi->token_name); -+ pi->token_name = NULL; - } - - static int null_strcmp(const char *s1, const char *s2) { -@@ -922,7 +928,7 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf, - break; - case SSS_PAM_OTP_INFO: - if (buf[p + (len - 1)] != '\0') { -- D(("system info does not end with \\0.")); -+ D(("otp info does not end with \\0.")); - break; - } - -@@ -959,6 +965,33 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf, - } - - break; -+ case SSS_PAM_CERT_INFO: -+ if (buf[p + (len - 1)] != '\0') { -+ D(("cert info does not end with \\0.")); -+ break; -+ } -+ -+ pi->cert_user = strdup((char *) &buf[p]); -+ if (pi->cert_user == NULL) { -+ D(("strdup failed")); -+ break; -+ } -+ -+ offset = strlen(pi->cert_user) + 1; -+ if (offset >= len) { -+ D(("Cert message size mismatch")); -+ free(pi->cert_user); -+ pi->cert_user = NULL; -+ break; -+ } -+ pi->token_name = strdup((char *) &buf[p + offset]); -+ if (pi->token_name == NULL) { -+ D(("strdup failed")); -+ break; -+ } -+ D(("cert user: [%s] token name: [%s]", pi->cert_user, -+ pi->token_name)); -+ break; - default: - D(("Unknown response type [%d]", type)); - } -@@ -1039,6 +1072,9 @@ static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi) - pi->otp_token_id = NULL; - pi->otp_challenge = NULL; - -+ pi->cert_user = NULL; -+ pi->token_name = NULL; -+ - return PAM_SUCCESS; - } - -@@ -1345,6 +1381,60 @@ done: - return ret; - } - -+#define SC_PROMPT_FMT "PIN for %s for user %s" -+static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi) -+{ -+ int ret; -+ char *answer = NULL; -+ char *prompt; -+ size_t size; -+ -+ if (pi->token_name == NULL || *pi->token_name == '\0' -+ || pi->cert_user == NULL || *pi->cert_user == '\0') { -+ return EINVAL; -+ } -+ -+ size = sizeof(SC_PROMPT_FMT) + strlen(pi->token_name) + -+ strlen(pi->cert_user); -+ prompt = malloc(size); -+ if (prompt == NULL) { -+ D(("malloc failed.")); -+ return ENOMEM; -+ } -+ -+ ret = snprintf(prompt, size, SC_PROMPT_FMT, pi->token_name, pi->cert_user); -+ if (ret < 0 || ret >= size) { -+ D(("snprintf failed.")); -+ free(prompt); -+ return EFAULT; -+ } -+ -+ ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, NULL, &answer); -+ free(prompt); -+ if (ret != PAM_SUCCESS) { -+ D(("do_pam_conversation failed.")); -+ return ret; -+ } -+ -+ if (answer == NULL) { -+ pi->pam_authtok = NULL; -+ pi->pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY; -+ pi->pam_authtok_size=0; -+ } else { -+ pi->pam_authtok = strdup(answer); -+ _pam_overwrite((void *)answer); -+ free(answer); -+ answer=NULL; -+ if (pi->pam_authtok == NULL) { -+ return PAM_BUF_ERR; -+ } -+ pi->pam_authtok_type = SSS_AUTHTOK_TYPE_SC_PIN; -+ pi->pam_authtok_size=strlen(pi->pam_authtok); -+ } -+ -+ return PAM_SUCCESS; -+} -+ - static int prompt_new_password(pam_handle_t *pamh, struct pam_items *pi) - { - int ret; -@@ -1458,6 +1548,8 @@ static int get_authtok_for_authentication(pam_handle_t *pamh, - && pi->otp_challenge != NULL)) { - ret = prompt_2fa(pamh, pi, _("First Factor: "), - _("Second Factor: ")); -+ } else if (pi->cert_user != NULL) { -+ ret = prompt_sc_pin(pamh, pi); - } else { - ret = prompt_password(pamh, pi, _("Password: ")); - } --- -2.4.3 - diff --git a/SOURCES/0035-tests-add-tests-for-sss_get_domain_mappings_content.patch b/SOURCES/0035-tests-add-tests-for-sss_get_domain_mappings_content.patch new file mode 100644 index 0000000..d2d75a0 --- /dev/null +++ b/SOURCES/0035-tests-add-tests-for-sss_get_domain_mappings_content.patch @@ -0,0 +1,201 @@ +From 16495f6aca6fb1a3f0cdb30b4a50493453e8ca0f Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 20 Jul 2016 12:03:48 +0200 +Subject: [PATCH 35/44] tests: add tests for sss_get_domain_mappings_content() + +Reviewed-by: Jakub Hrozek +--- + src/tests/cmocka/test_utils.c | 163 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 163 insertions(+) + +diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c +index b08b19708bb59a076a79805fa37a15924152b8e2..4c72a59437105e683cec2d39c36951aeff63767b 100644 +--- a/src/tests/cmocka/test_utils.c ++++ b/src/tests/cmocka/test_utils.c +@@ -55,6 +55,95 @@ struct dom_list_test_ctx { + struct sss_domain_info *dom_list; + }; + ++static int setup_dom_list_with_subdomains(void **state) ++{ ++ struct dom_list_test_ctx *test_ctx; ++ struct sss_domain_info *dom = NULL; ++ struct sss_domain_info *c = NULL; ++ ++ assert_true(leak_check_setup()); ++ ++ test_ctx = talloc_zero(global_talloc_context, struct dom_list_test_ctx); ++ assert_non_null(test_ctx); ++ ++ dom = talloc_zero(test_ctx, struct sss_domain_info); ++ assert_non_null(dom); ++ ++ dom->name = talloc_asprintf(dom, "configured.dom"); ++ assert_non_null(dom->name); ++ ++ dom->realm = talloc_asprintf(dom, "CONFIGURED.DOM"); ++ assert_non_null(dom->realm); ++ ++ dom->flat_name = talloc_asprintf(dom, "CONFIGURED"); ++ assert_non_null(dom->flat_name); ++ ++ dom->domain_id = talloc_asprintf(dom, "S-1-5-21-1-2-1"); ++ assert_non_null(dom->domain_id); ++ ++ DLIST_ADD(test_ctx->dom_list, dom); ++ ++ c = talloc_zero(test_ctx, struct sss_domain_info); ++ assert_non_null(c); ++ ++ c->name = talloc_asprintf(c, "subdom1.dom"); ++ assert_non_null(c->name); ++ ++ c->realm = talloc_asprintf(c, "SUBDOM1.DOM"); ++ assert_non_null(c->realm); ++ ++ c->flat_name = talloc_asprintf(c, "subdom1"); ++ assert_non_null(c->flat_name); ++ ++ c->domain_id = talloc_asprintf(c, "S-1-5-21-1-2-2"); ++ assert_non_null(c->domain_id); ++ ++ c->parent = dom; ++ ++ DLIST_ADD_END(test_ctx->dom_list, c, struct sss_domain_info *); ++ ++ c = talloc_zero(test_ctx, struct sss_domain_info); ++ assert_non_null(c); ++ ++ c->name = talloc_asprintf(c, "subdom2.dom"); ++ assert_non_null(c->name); ++ ++ c->realm = talloc_asprintf(c, "SUBDOM2.DOM"); ++ assert_non_null(c->realm); ++ ++ c->flat_name = talloc_asprintf(c, "subdom2"); ++ assert_non_null(c->flat_name); ++ ++ c->domain_id = talloc_asprintf(c, "S-1-5-21-1-2-3"); ++ assert_non_null(c->domain_id); ++ ++ c->parent = dom; ++ ++ DLIST_ADD_END(test_ctx->dom_list, c, struct sss_domain_info *); ++ ++ c = talloc_zero(test_ctx, struct sss_domain_info); ++ assert_non_null(c); ++ ++ c->name = talloc_asprintf(c, "subdom3.dom"); ++ assert_non_null(c->name); ++ ++ c->realm = talloc_asprintf(c, "SUBDOM3.DOM"); ++ assert_non_null(c->realm); ++ ++ c->flat_name = talloc_asprintf(c, "subdom3"); ++ assert_non_null(c->flat_name); ++ ++ c->domain_id = talloc_asprintf(c, "S-1-5-21-1-2-4"); ++ assert_non_null(c->domain_id); ++ ++ c->parent = dom; ++ ++ DLIST_ADD_END(test_ctx->dom_list, c, struct sss_domain_info *); ++ ++ check_leaks_push(test_ctx); ++ *state = test_ctx; ++ return 0; ++} + + static int setup_dom_list(void **state) + { +@@ -1682,6 +1771,77 @@ static void test_sss_output_name(void **state) + assert_true(check_leaks_pop(global_talloc_context) == true); + } + ++static void test_sss_get_domain_mappings_content(void **state) ++{ ++ struct dom_list_test_ctx *test_ctx; ++ int ret; ++ struct sss_domain_info *dom; ++ char *content; ++ struct sss_domain_info *c; ++ ++ ret = sss_get_domain_mappings_content(NULL, NULL, NULL); ++ assert_int_equal(ret, EINVAL); ++ ++ test_ctx = talloc_get_type(*state, struct dom_list_test_ctx); ++ assert_non_null(test_ctx); ++ ++ dom = get_domains_head(test_ctx->dom_list); ++ assert_non_null(dom); ++ ++ /* no forest */ ++ ret = sss_get_domain_mappings_content(test_ctx, dom, &content); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(content, ++ "[domain_realm]\n" ++ ".subdom1.dom = SUBDOM1.DOM\n" ++ "subdom1.dom = SUBDOM1.DOM\n" ++ ".subdom2.dom = SUBDOM2.DOM\n" ++ "subdom2.dom = SUBDOM2.DOM\n" ++ ".subdom3.dom = SUBDOM3.DOM\n" ++ "subdom3.dom = SUBDOM3.DOM\n"); ++ talloc_free(content); ++ ++ /* IPA with forest */ ++ c = find_domain_by_name(dom, "subdom2.dom", true); ++ assert_non_null(c); ++ c->forest_root = find_domain_by_name(dom, "subdom1.dom", true); ++ assert_non_null(c->forest_root); ++ c->forest = "subdom1.dom"; ++ ++ c = find_domain_by_name(dom, "subdom3.dom", true); ++ assert_non_null(c); ++ c->forest_root = find_domain_by_name(dom, "subdom1.dom", true); ++ assert_non_null(c->forest_root); ++ c->forest = "subdom1.dom"; ++ ++ ret = sss_get_domain_mappings_content(test_ctx, dom, &content); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(content, ++ "[domain_realm]\n" ++ ".subdom1.dom = SUBDOM1.DOM\n" ++ "subdom1.dom = SUBDOM1.DOM\n" ++ ".subdom2.dom = SUBDOM2.DOM\n" ++ "subdom2.dom = SUBDOM2.DOM\n" ++ ".subdom3.dom = SUBDOM3.DOM\n" ++ "subdom3.dom = SUBDOM3.DOM\n" ++ "[capaths]\n" ++ "SUBDOM2.DOM = {\n" ++ " CONFIGURED.DOM = SUBDOM1.DOM\n" ++ "}\n" ++ "SUBDOM3.DOM = {\n" ++ " CONFIGURED.DOM = SUBDOM1.DOM\n" ++ "}\n" ++ "CONFIGURED.DOM = {\n" ++ " SUBDOM2.DOM = SUBDOM1.DOM\n" ++ " SUBDOM3.DOM = SUBDOM1.DOM\n" ++ "}\n"); ++ talloc_free(content); ++ ++ /* Next steps, test AD domain setup. If we join a child domain we have a ++ * similar case as with IPA but if we join the forest root the generate ++ * capaths might not be as expected. */ ++} ++ + int main(int argc, const char *argv[]) + { + poptContext pc; +@@ -1773,6 +1933,9 @@ int main(int argc, const char *argv[]) + cmocka_unit_test_setup_teardown(test_sss_output_name, + setup_leak_tests, + teardown_leak_tests), ++ cmocka_unit_test_setup_teardown(test_sss_get_domain_mappings_content, ++ setup_dom_list_with_subdomains, ++ teardown_dom_list), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ +-- +2.4.11 + diff --git a/SOURCES/0036-Amend-debug-messages-after-failure-of-unlink.patch b/SOURCES/0036-Amend-debug-messages-after-failure-of-unlink.patch new file mode 100644 index 0000000..5a2a303 --- /dev/null +++ b/SOURCES/0036-Amend-debug-messages-after-failure-of-unlink.patch @@ -0,0 +1,151 @@ +From ce5063550ef45f7abb3ec2ec3cb52a190bb38af5 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 25 Jul 2016 09:11:08 +0200 +Subject: [PATCH 36/44] Amend debug messages after failure of unlink +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some messages did not have errno or name of problematic file. +There was also improper use of negative value. +The function strerror was called with -1 instead of errno + +Reviewed-by: Petr Čech +--- + src/providers/ipa/ipa_init.c | 5 +++-- + src/responder/common/responder_common.c | 3 ++- + src/responder/secrets/local.c | 1 + + src/sbus/sssd_dbus_server.c | 9 +++++---- + src/tools/files.c | 3 ++- + src/tools/tools_mc_util.c | 7 ++++--- + src/util/util.c | 6 ++++-- + 7 files changed, 21 insertions(+), 13 deletions(-) + +diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c +index 959cdb4a7c40c1be03dd1e7c66dee6e65ca76607..c31e195f48b2f369de1b78b38a0f3522d73d8dce 100644 +--- a/src/providers/ipa/ipa_init.c ++++ b/src/providers/ipa/ipa_init.c +@@ -440,9 +440,10 @@ static void cleanup_ipa_preauth_indicator(void) + + ret = unlink(PAM_PREAUTH_INDICATOR); + if (ret != EOK) { ++ ret = errno; + DEBUG(SSSDBG_OP_FAILURE, +- "Failed to remove preauth indicator file [%s].\n", +- PAM_PREAUTH_INDICATOR); ++ "Failed to remove preauth indicator file [%s] %d [%s].\n", ++ PAM_PREAUTH_INDICATOR, ret, sss_strerror(ret)); + } + } + +diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c +index 02a64368cad60990436497865aa0c772a39cde5a..7f6264ae70e5073063b5cfcd73098eefad2ce653 100644 +--- a/src/responder/common/responder_common.c ++++ b/src/responder/common/responder_common.c +@@ -629,7 +629,8 @@ int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval) + if (ret != 0 && errno != ENOENT) { + ret = errno; + DEBUG(SSSDBG_MINOR_FAILURE, +- "Cannot remove old socket (errno=%d), bind might fail!\n", ret); ++ "Cannot remove old socket (errno=%d [%s]), bind might fail!\n", ++ ret, sss_strerror(ret)); + } + + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { +diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c +index 2a85ac06945322265fbd1012c9697728c37b77a0..470aec0e195a54dd2af2b929ff1b7a304331a214 100644 +--- a/src/responder/secrets/local.c ++++ b/src/responder/secrets/local.c +@@ -627,6 +627,7 @@ int generate_master_key(const char *filename, size_t size) + ret = unlink(filename); + /* non-fatal failure */ + if (ret != EOK) { ++ ret = errno; + DEBUG(SSSDBG_MINOR_FAILURE, + "Failed to remove file: %s - %d [%s]!\n", + filename, ret, sss_strerror(ret)); +diff --git a/src/sbus/sssd_dbus_server.c b/src/sbus/sssd_dbus_server.c +index 0a1cace415b3514a6904e92a2d879538ce51a593..6cc4172a07118ff99bb6f122c3a1de25cee18c8c 100644 +--- a/src/sbus/sssd_dbus_server.c ++++ b/src/sbus/sssd_dbus_server.c +@@ -103,8 +103,9 @@ create_socket_symlink(const char *filename, const char *symlink_filename) + ret = unlink(symlink_filename); + if (ret != 0) { + ret = errno; +- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot remove old symlink: [%d][%s].\n", +- ret, strerror(ret)); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot remove old symlink '%s': [%d][%s].\n", ++ symlink_filename, ret, strerror(ret)); + return EIO; + } + errno = 0; +@@ -351,8 +352,8 @@ done: + if (tmp_ret != EOK) { + tmp_ret = errno; + DEBUG(SSSDBG_MINOR_FAILURE, +- "Failed to remove symbolic link: %d [%s]!\n", +- tmp_ret, sss_strerror(tmp_ret)); ++ "Failed to remove symbolic link '%s': %d [%s]!\n", ++ symlink_filename, tmp_ret, sss_strerror(tmp_ret)); + } + } + talloc_free(tmp_ctx); +diff --git a/src/tools/files.c b/src/tools/files.c +index 5364f5c0dd53aad71452e18b8d7f1f04532132a4..8f1aa68beeb2676b56733f49550de170b404c789 100644 +--- a/src/tools/files.c ++++ b/src/tools/files.c +@@ -225,7 +225,8 @@ static int remove_tree_with_ctx(TALLOC_CTX *mem_ctx, + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "Removing file failed: [%d][%s]\n", ret, strerror(ret)); ++ "Removing file failed '%s': [%d][%s]\n", ++ result->d_name, ret, strerror(ret)); + goto fail; + } + } +diff --git a/src/tools/tools_mc_util.c b/src/tools/tools_mc_util.c +index ce899eb3c674afe8271be526dc83aa909cbecf89..2516a1981ddd965d4cae8c469ed79aaef8fa7193 100644 +--- a/src/tools/tools_mc_util.c ++++ b/src/tools/tools_mc_util.c +@@ -117,10 +117,11 @@ done: + if (ret == EOK) { + pret = unlink(mc_filename); + if (pret == -1) { ++ pret = errno; + DEBUG(SSSDBG_MINOR_FAILURE, +- "Failed to unlink file %s. " +- "Will be unlinked later by sssd_nss.\n", +- mc_filename); ++ "Failed to unlink file %s, %d [%s]. " ++ "Will be unlinked later by sssd_nss.\n", ++ mc_filename, pret, strerror(pret)); + } + } + } +diff --git a/src/util/util.c b/src/util/util.c +index 89abfe734873161008dc9a7a42e7a87364f8074a..d4878bfaf4f0e92672756f12137d79ec65ef48f6 100644 +--- a/src/util/util.c ++++ b/src/util/util.c +@@ -990,13 +990,15 @@ static int unlink_dbg(const char *filename) + + ret = unlink(filename); + if (ret != 0) { +- if (errno == 2) { ++ ret = errno; ++ if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "File already removed: [%s]\n", filename); + return 0; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Cannot remove temporary file [%s]\n", filename); ++ "Cannot remove temporary file [%s] %d [%s]\n", ++ filename, ret, strerror(ret)); + return -1; + } + } +-- +2.4.11 + diff --git a/SOURCES/0036-ssh-generate-public-keys-from-certificate.patch b/SOURCES/0036-ssh-generate-public-keys-from-certificate.patch deleted file mode 100644 index d01d9e7..0000000 --- a/SOURCES/0036-ssh-generate-public-keys-from-certificate.patch +++ /dev/null @@ -1,618 +0,0 @@ -From ace8a2f80fe5bb755512e4a7281146ce4fe311a6 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 15 Jul 2015 09:40:00 +0200 -Subject: [PATCH 36/37] ssh: generate public keys from certificate - -Resolves: https://fedorahosted.org/sssd/ticket/2711 - -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 7 +- - src/confdb/confdb.h | 2 + - src/config/SSSDConfig/__init__.py.in | 1 + - src/config/etc/sssd.api.conf | 1 + - src/man/sssd.conf.5.xml | 13 ++++ - src/responder/ssh/sshsrv.c | 9 +++ - src/responder/ssh/sshsrv_cmd.c | 54 ++++++++++++--- - src/responder/ssh/sshsrv_private.h | 1 + - src/tests/cmocka/test_cert_utils.c | 62 +++++++++++++++++ - src/util/cert.h | 4 ++ - src/util/cert/libcrypto/cert.c | 93 +++++++++++++++++++++++++ - src/util/cert/nss/cert.c | 130 +++++++++++++++++++++++++++++++++++ - 12 files changed, 364 insertions(+), 13 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index fd78c1bb770b98adee9a6c1ead3b0d6f4345fb9b..5345d90d22cd285a5268ac50a6b527645acdb351 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1129,10 +1129,13 @@ sssd_ssh_SOURCES = \ - src/responder/ssh/sshsrv.c \ - src/responder/ssh/sshsrv_dp.c \ - src/responder/ssh/sshsrv_cmd.c \ -- $(SSSD_RESPONDER_OBJ) -+ $(SSSD_RESPONDER_OBJ) \ -+ $(NULL) - sssd_ssh_LDADD = \ - $(SSSD_LIBS) \ -- $(SSSD_INTERNAL_LTLIBS) -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_cert.la \ -+ $(NULL) - endif - - sssd_pac_SOURCES = \ -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index c3cdf49e08d10367e9e98c093a4aa2569b985170..df454337ab4d89c5857e73ee0e5392c2b4bba8b4 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -135,6 +135,8 @@ - #define CONFDB_DEFAULT_SSH_HASH_KNOWN_HOSTS true - #define CONFDB_SSH_KNOWN_HOSTS_TIMEOUT "ssh_known_hosts_timeout" - #define CONFDB_DEFAULT_SSH_KNOWN_HOSTS_TIMEOUT 180 -+#define CONFDB_SSH_CA_DB "ca_db" -+#define CONFDB_DEFAULT_SSH_CA_DB SYSCONFDIR"/pki/nssdb" - - /* PAC */ - #define CONFDB_PAC_CONF_ENTRY "config/pac" -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 4b519eddd04cde83c209f5a1940832cc7f41c736..7d361026c09ce8fd8d6a69f6bb3f3817bc3d68ba 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -99,6 +99,7 @@ option_strings = { - # [ssh] - 'ssh_hash_known_hosts': _('Whether to hash host names and addresses in the known_hosts file'), - 'ssh_known_hosts_timeout': _('How many seconds to keep a host in the known_hosts file after its host keys were requested'), -+ 'ca_db': _('Path to storage of trusted CA certificates'), - - # [pac] - 'allowed_uids': _('List of UIDs or user names allowed to access the PAC responder'), -diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf -index 29fd896ccd7a3aa5ff81e15b771746a80ffc01af..cf6ce63012176d49f757afbc8a343b24aef869e8 100644 ---- a/src/config/etc/sssd.api.conf -+++ b/src/config/etc/sssd.api.conf -@@ -72,6 +72,7 @@ autofs_negative_timeout = int, None, false - # ssh service - ssh_hash_known_hosts = bool, None, false - ssh_known_hosts_timeout = int, None, false -+ca_db = str, None, false - - [pac] - # PAC responder -diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml -index 7d3a57b0eadec48d64cc9ddcb226b89a1600b432..37e73515fbfcae0da492533de72ad3208c870e9b 100644 ---- a/src/man/sssd.conf.5.xml -+++ b/src/man/sssd.conf.5.xml -@@ -1082,6 +1082,19 @@ pam_account_expired_message = Account expired, please call help desk. - - - -+ -+ ca_db (string) -+ -+ -+ Path to a storage of trusted CA certificates. The -+ option is used to validate user certificates before -+ deriving public ssh keys from them. -+ -+ -+ Default: /etc/pki/nssdb -+ -+ -+ - - - -diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c -index 9439b9d89ae47dc66d392f0c434f4de1c1c0b4ea..d4e202d87f520f1bdcd521733592027773a821d6 100644 ---- a/src/responder/ssh/sshsrv.c -+++ b/src/responder/ssh/sshsrv.c -@@ -163,6 +163,15 @@ int ssh_process_init(TALLOC_CTX *mem_ctx, - goto fail; - } - -+ ret = confdb_get_string(ssh_ctx->rctx->cdb, ssh_ctx, -+ CONFDB_SSH_CONF_ENTRY, CONFDB_SSH_CA_DB, -+ CONFDB_DEFAULT_SSH_CA_DB, &ssh_ctx->ca_db); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Error reading CA DB from confdb (%d) [%s]\n", -+ ret, strerror(ret)); -+ goto fail; -+ } -+ - ret = schedule_get_domains_task(rctx, rctx->ev, rctx, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "schedule_get_domains_tasks failed.\n"); -diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c -index 4833587910cade32ecb0b5f65b417d58a498b01e..f630e5f0311dadc69bee59afb672720f7018169d 100644 ---- a/src/responder/ssh/sshsrv_cmd.c -+++ b/src/responder/ssh/sshsrv_cmd.c -@@ -27,6 +27,7 @@ - #include "util/util.h" - #include "util/crypto/sss_crypto.h" - #include "util/sss_ssh.h" -+#include "util/cert.h" - #include "db/sysdb.h" - #include "db/sysdb_ssh.h" - #include "providers/data_provider.h" -@@ -219,7 +220,8 @@ static errno_t - ssh_user_pubkeys_search_next(struct ssh_cmd_ctx *cmd_ctx) - { - errno_t ret; -- const char *attrs[] = { SYSDB_NAME, SYSDB_SSH_PUBKEY, NULL }; -+ const char *attrs[] = { SYSDB_NAME, SYSDB_SSH_PUBKEY, SYSDB_USER_CERT, -+ NULL }; - struct ldb_result *res; - - DEBUG(SSSDBG_TRACE_FUNC, -@@ -794,6 +796,8 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx) - - static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx, - struct ldb_message_element *el, -+ bool cert_data, -+ struct ssh_ctx *ssh_ctx, - size_t fqname_len, - const char *fqname, - size_t *c) -@@ -819,12 +823,22 @@ static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx, - } - - for (d = 0; d < el->num_values; d++) { -- key = sss_base64_decode(tmp_ctx, (const char *) el->values[d].data, -- &key_len); -- if (key == NULL) { -- DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n"); -- ret = ENOMEM; -- goto done; -+ if (cert_data) { -+ ret = cert_to_ssh_key(tmp_ctx, ssh_ctx->ca_db, -+ el->values[d].data, el->values[d].length, -+ &key, &key_len); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "cert_to_ssh_key failed.\n"); -+ return ret; -+ } -+ } else { -+ key = sss_base64_decode(tmp_ctx, (const char *) el->values[d].data, -+ &key_len); -+ if (key == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } - } - - ret = sss_packet_grow(cctx->creq->out, -@@ -862,10 +876,13 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx) - struct ldb_message_element *el = NULL; - struct ldb_message_element *el_override = NULL; - struct ldb_message_element *el_orig = NULL; -+ struct ldb_message_element *el_user_cert = NULL; - uint32_t count = 0; - const char *name; - char *fqname; - uint32_t fqname_len; -+ struct ssh_ctx *ssh_ctx = talloc_get_type(cctx->rctx->pvt_ctx, -+ struct ssh_ctx); - - ret = sss_packet_new(cctx->creq, 0, - sss_packet_get_cmd(cctx->creq->in), -@@ -893,6 +910,12 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx) - } - } - -+ el_user_cert = ldb_msg_find_element(cmd_ctx->result, SYSDB_USER_CERT); -+ if (el_user_cert) { -+ /* TODO check if cert is valid */ -+ count += el_user_cert->num_values; -+ } -+ - ret = sss_packet_grow(cctx->creq->out, 2*sizeof(uint32_t)); - if (ret != EOK) { - return ret; -@@ -922,20 +945,29 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx) - - fqname_len = strlen(fqname)+1; - -- ret = decode_and_add_base64_data(cmd_ctx, el, fqname_len, fqname, &c); -+ ret = decode_and_add_base64_data(cmd_ctx, el, false, ssh_ctx, -+ fqname_len, fqname, &c); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n"); - return ret; - } - -- ret = decode_and_add_base64_data(cmd_ctx, el_orig, fqname_len, fqname, &c); -+ ret = decode_and_add_base64_data(cmd_ctx, el_orig, false, ssh_ctx, -+ fqname_len, fqname, &c); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n"); - return ret; - } - -- ret = decode_and_add_base64_data(cmd_ctx, el_override, fqname_len, fqname, -- &c); -+ ret = decode_and_add_base64_data(cmd_ctx, el_override, false, ssh_ctx, -+ fqname_len, fqname, &c); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n"); -+ return ret; -+ } -+ -+ ret = decode_and_add_base64_data(cmd_ctx, el_user_cert, true, ssh_ctx, -+ fqname_len, fqname, &c); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n"); - return ret; -diff --git a/src/responder/ssh/sshsrv_private.h b/src/responder/ssh/sshsrv_private.h -index ebb30ce7cbc982bb29b73592d5873e7d3652228a..beb8e18db77d8224e49df141748484ce61b11dac 100644 ---- a/src/responder/ssh/sshsrv_private.h -+++ b/src/responder/ssh/sshsrv_private.h -@@ -32,6 +32,7 @@ struct ssh_ctx { - - bool hash_known_hosts; - int known_hosts_timeout; -+ char *ca_db; - }; - - struct ssh_cmd_ctx { -diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c -index 8063b1a65e8692142cbb3cf82fe41afa6567bc91..7bd8cf2344003421e9ec84dc5e1b2305a861ab38 100644 ---- a/src/tests/cmocka/test_cert_utils.c -+++ b/src/tests/cmocka/test_cert_utils.c -@@ -21,15 +21,18 @@ - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -+#include "config.h" - - #include - #ifdef HAVE_LIBCRYPTO - #include -+#include - #endif - - #include "util/cert.h" - #include "tests/cmocka/common_mock.h" - #include "util/crypto/nss/nss_util.h" -+#include "util/crypto/sss_crypto.h" - - - /* TODO: create a certificate for this test */ -@@ -306,6 +309,63 @@ void test_sss_cert_derb64_to_ldap_filter(void **state) - talloc_free(filter); - } - -+ -+#define SSH_TEST_CERT \ -+"MIIECTCCAvGgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA0MRIwEAYDVQQKDAlJUEEu" \ -+"REVWRUwxHjAcBgNVBAMMFUNlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNTA2MjMx" \ -+"NjMyMDdaFw0xNzA2MjMxNjMyMDdaMDIxEjAQBgNVBAoMCUlQQS5ERVZFTDEcMBoG" \ -+"A1UEAwwTaXBhLWRldmVsLmlwYS5kZXZlbDCCASIwDQYJKoZIhvcNAQEBBQADggEP" \ -+"ADCCAQoCggEBALXUq56VlY+Z0aWLLpFAjFfbElPBXGQsbZb85J3cGyPjaMHC9wS+" \ -+"wjB6Ve4HmQyPLx8hbINdDmbawMHYQvTScLYfsqLtj0Lqw20sUUmedk+Es5Oh9VHo" \ -+"nd8MavYx25Du2u+T0iSgNIDikXguiwCmtAj8VC49ebbgITcjJGzMmiiuJkV3o93Y" \ -+"vvYF0VjLGDQbQWOy7IxzYJeNVJnZWKo67CHdok6qOrm9rxQt81rzwV/mGLbCMUbr" \ -+"+N4M8URtd7EmzaYZQmNm//s2owFrCYMxpLiURPj+URZVuB72504/Ix7X0HCbA/AV" \ -+"26J27fPY5nc8DMwfhUDCbTqPH/JEjd3mvY8CAwEAAaOCASYwggEiMB8GA1UdIwQY" \ -+"MBaAFJOq+KAQmPEnNp8Wok23eGTdE7aDMDsGCCsGAQUFBwEBBC8wLTArBggrBgEF" \ -+"BQcwAYYfaHR0cDovL2lwYS1jYS5pcGEuZGV2ZWwvY2Evb2NzcDAOBgNVHQ8BAf8E" \ -+"BAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHQGA1UdHwRtMGsw" \ -+"aaAxoC+GLWh0dHA6Ly9pcGEtY2EuaXBhLmRldmVsL2lwYS9jcmwvTWFzdGVyQ1JM" \ -+"LmJpbqI0pDIwMDEOMAwGA1UECgwFaXBhY2ExHjAcBgNVBAMMFUNlcnRpZmljYXRl" \ -+"IEF1dGhvcml0eTAdBgNVHQ4EFgQUFaDNd5a53QGpaw5m63hnwXicMQ8wDQYJKoZI" \ -+"hvcNAQELBQADggEBADH7Nj00qqGhGJeXJQAsepqSskz/wooqXh8vgVyb8SS4N0/c" \ -+"0aQtVmY81xamlXE12ZFpwDX43d+EufBkwCUKFX/+8JFDd2doAyeJxv1xM22kKRpc" \ -+"AqITPgMsa9ToGMWxjbVpc/X/5YfZixWPF0/eZUTotBj9oaR039UrhGfyN7OguF/G" \ -+"rzmxtB5y4ZrMpcD/Oe90mkd9HY7sA/fB8OWOUgeRfQoh97HNS0UiDWsPtfxmjQG5" \ -+"zotpoBIZmdH+ipYsu58HohHVlM9Wi5H4QmiiXl+Soldkq7eXYlafcmT7wv8+cKwz" \ -+"Nz0Tm3+eYpFqRo3skr6QzXi525Jkg3r6r+kkhxU=" -+ -+#define SSH_PUB_KEY "AAAAB3NzaC1yc2EAAAADAQABAAABAQC11KuelZWPmdGliy6RQIxX2xJTwVxkLG2W/OSd3Bsj42jBwvcEvsIwelXuB5kMjy8fIWyDXQ5m2sDB2EL00nC2H7Ki7Y9C6sNtLFFJnnZPhLOTofVR6J3fDGr2MduQ7trvk9IkoDSA4pF4LosAprQI/FQuPXm24CE3IyRszJooriZFd6Pd2L72BdFYyxg0G0FjsuyMc2CXjVSZ2ViqOuwh3aJOqjq5va8ULfNa88Ff5hi2wjFG6/jeDPFEbXexJs2mGUJjZv/7NqMBawmDMaS4lET4/lEWVbge9udOPyMe19BwmwPwFduidu3z2OZ3PAzMH4VAwm06jx/yRI3d5r2P" -+ -+void test_cert_to_ssh_key(void **state) -+{ -+ int ret; -+ uint8_t *key; -+ size_t key_size; -+ uint8_t *exp_key; -+ size_t exp_key_size; -+ uint8_t *der; -+ size_t der_size; -+ -+ struct test_state *ts = talloc_get_type_abort(*state, struct test_state); -+ assert_non_null(ts); -+ -+ der = sss_base64_decode(ts, SSH_TEST_CERT, &der_size); -+ assert_non_null(der); -+ -+ exp_key = sss_base64_decode(ts, SSH_PUB_KEY, &exp_key_size); -+ assert_non_null(exp_key); -+ -+ ret = cert_to_ssh_key(ts, "sql:" ABS_SRC_DIR "/src/tests/cmocka/p11_nssdb", -+ der, der_size, &key, &key_size); -+ assert_int_equal(ret, EOK); -+ assert_int_equal(key_size, exp_key_size); -+ assert_memory_equal(key, exp_key, exp_key_size); -+ -+ talloc_free(der); -+ talloc_free(key); -+ talloc_free(exp_key); -+} -+ - int main(int argc, const char *argv[]) - { - poptContext pc; -@@ -330,6 +390,8 @@ int main(int argc, const char *argv[]) - setup, teardown), - cmocka_unit_test_setup_teardown(test_sss_cert_derb64_to_ldap_filter, - setup, teardown), -+ cmocka_unit_test_setup_teardown(test_cert_to_ssh_key, -+ setup, teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ -diff --git a/src/util/cert.h b/src/util/cert.h -index 79ea1a4ab58149a312bece265798ab3a3f459114..edbafc492a1ed42ad616d0bf2fae882046711746 100644 ---- a/src/util/cert.h -+++ b/src/util/cert.h -@@ -44,4 +44,8 @@ errno_t sss_cert_derb64_to_ldap_filter(TALLOC_CTX *mem_ctx, const char *derb64, - errno_t bin_to_ldap_filter_value(TALLOC_CTX *mem_ctx, - const uint8_t *blob, size_t blob_size, - char **_str); -+ -+errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db, -+ const uint8_t *der_blob, size_t der_size, -+ uint8_t **key, size_t *key_size); - #endif /* __CERT_H__ */ -diff --git a/src/util/cert/libcrypto/cert.c b/src/util/cert/libcrypto/cert.c -index 1a250f60d1a7dfd5c883ec7e9b1f9491fb74c9b0..01f9554b990d6a139bb9a1d8d558c1c3f6bb745c 100644 ---- a/src/util/cert/libcrypto/cert.c -+++ b/src/util/cert/libcrypto/cert.c -@@ -166,3 +166,96 @@ done: - return ret; - - } -+ -+#define SSH_RSA_HEADER "ssh-rsa" -+#define SSH_RSA_HEADER_LEN (sizeof(SSH_RSA_HEADER) - 1) -+ -+errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db, -+ const uint8_t *der_blob, size_t der_size, -+ uint8_t **key, size_t *key_size) -+{ -+ int ret; -+ size_t size; -+ const unsigned char *d; -+ uint8_t *buf = NULL; -+ size_t c; -+ X509 *cert = NULL; -+ EVP_PKEY *cert_pub_key = NULL; -+ int modulus_len; -+ unsigned char modulus[OPENSSL_RSA_MAX_MODULUS_BITS/8]; -+ int exponent_len; -+ unsigned char exponent[OPENSSL_RSA_MAX_PUBEXP_BITS/8]; -+ -+ if (der_blob == NULL || der_size == 0) { -+ return EINVAL; -+ } -+ -+ d = (const unsigned char *) der_blob; -+ -+ cert = d2i_X509(NULL, &d, (int) der_size); -+ if (cert == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "d2i_X509 failed.\n"); -+ return EINVAL; -+ } -+ -+ /* TODO: verify certificate !!!!! */ -+ -+ cert_pub_key = X509_get_pubkey(cert); -+ if (cert_pub_key == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "X509_get_pubkey failed.\n"); -+ ret = EIO; -+ goto done; -+ } -+ -+ if (cert_pub_key->type != EVP_PKEY_RSA) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Expected RSA public key, found unsupported [%d].\n", -+ cert_pub_key->type); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ modulus_len = BN_bn2bin(cert_pub_key->pkey.rsa->n, modulus); -+ exponent_len = BN_bn2bin(cert_pub_key->pkey.rsa->e, exponent); -+ -+ size = SSH_RSA_HEADER_LEN + 3 * sizeof(uint32_t) -+ + modulus_len -+ + exponent_len -+ + 1; /* see comment about missing 00 below */ -+ -+ buf = talloc_size(mem_ctx, size); -+ if (buf == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ c = 0; -+ -+ SAFEALIGN_SET_UINT32(buf, htobe32(SSH_RSA_HEADER_LEN), &c); -+ safealign_memcpy(&buf[c], SSH_RSA_HEADER, SSH_RSA_HEADER_LEN, &c); -+ SAFEALIGN_SET_UINT32(&buf[c], htobe32(exponent_len), &c); -+ safealign_memcpy(&buf[c], exponent, exponent_len, &c); -+ -+ /* Adding missing 00 which afaik is added to make sure -+ * the bigint is handled as positive number */ -+ /* TODO: make a better check if 00 must be added or not, e.g. ... & 0x80) -+ */ -+ SAFEALIGN_SET_UINT32(&buf[c], htobe32(modulus_len + 1), &c); -+ SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c); -+ safealign_memcpy(&buf[c], modulus, modulus_len, &c); -+ -+ *key = buf; -+ *key_size = size; -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(buf); -+ } -+ EVP_PKEY_free(cert_pub_key); -+ X509_free(cert); -+ -+ return ret; -+} -diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c -index a20abf63a10de9a5e9810f1c7d56686d063d60c7..1ada35b6321b9e0f3daf87b3412cf7a124cbf2c7 100644 ---- a/src/util/cert/nss/cert.c -+++ b/src/util/cert/nss/cert.c -@@ -20,9 +20,13 @@ - - #include "util/util.h" - -+#include - #include - #include -+#include -+#include - -+#include "util/crypto/sss_crypto.h" - #include "util/crypto/nss/nss_util.h" - - #define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----" -@@ -210,3 +214,129 @@ done: - - return ret; - } -+ -+#define SSH_RSA_HEADER "ssh-rsa" -+#define SSH_RSA_HEADER_LEN (sizeof(SSH_RSA_HEADER) - 1) -+ -+errno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db, -+ const uint8_t *der_blob, size_t der_size, -+ uint8_t **key, size_t *key_size) -+{ -+ CERTCertDBHandle *handle; -+ CERTCertificate *cert = NULL; -+ SECItem der_item; -+ SECKEYPublicKey *cert_pub_key = NULL; -+ int ret; -+ size_t size; -+ uint8_t *buf = NULL; -+ size_t c; -+ NSSInitContext *nss_ctx; -+ NSSInitParameters parameters = { 0 }; -+ parameters.length = sizeof (parameters); -+ SECStatus rv; -+ -+ if (der_blob == NULL || der_size == 0) { -+ return EINVAL; -+ } -+ -+ /* initialize NSS with context, we might have already called -+ * NSS_NoDB_Init() but for validation we need to have access to a DB with -+ * the trusted issuer cert. Only NSS_InitContext will really open the DB -+ * in this case. I'm not sure about how long validation might need e.g. if -+ * CRLs or OSCP is enabled, maybe it would be better to run validation in -+ * p11_child ? */ -+ nss_ctx = NSS_InitContext(ca_db, "", "", SECMOD_DB, ¶meters, -+ NSS_INIT_READONLY); -+ if (nss_ctx == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "NSS_InitContext failed [%d].\n", -+ PR_GetError()); -+ return EIO; -+ } -+ -+ handle = CERT_GetDefaultCertDB(); -+ -+ der_item.len = der_size; -+ der_item.data = discard_const(der_blob); -+ -+ cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE); -+ if (cert == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE, -+ certificateUsageSSLClient, NULL, NULL); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "CERT_VerifyCertificateNow failed [%d].\n", -+ PR_GetError()); -+ ret = EACCES; -+ goto done; -+ } -+ -+ cert_pub_key = CERT_ExtractPublicKey(cert); -+ if (cert_pub_key == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "CERT_ExtractPublicKey failed.\n"); -+ ret = EIO; -+ goto done; -+ } -+ -+ if (cert_pub_key->keyType != rsaKey) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Expected RSA public key, found unsupported [%d].\n", -+ cert_pub_key->keyType); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ size = SSH_RSA_HEADER_LEN + 3 * sizeof(uint32_t) -+ + cert_pub_key->u.rsa.modulus.len -+ + cert_pub_key->u.rsa.publicExponent.len -+ + 1; /* see comment about missing 00 below */ -+ -+ buf = talloc_size(mem_ctx, size); -+ if (buf == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ c = 0; -+ -+ SAFEALIGN_SET_UINT32(buf, htobe32(SSH_RSA_HEADER_LEN), &c); -+ safealign_memcpy(&buf[c], SSH_RSA_HEADER, SSH_RSA_HEADER_LEN, &c); -+ SAFEALIGN_SET_UINT32(&buf[c], -+ htobe32(cert_pub_key->u.rsa.publicExponent.len), &c); -+ safealign_memcpy(&buf[c], cert_pub_key->u.rsa.publicExponent.data, -+ cert_pub_key->u.rsa.publicExponent.len, &c); -+ -+ /* Looks like nss drops the leading 00 which afaik is added to make sure -+ * the bigint is handled as positive number */ -+ /* TODO: make a better check if 00 must be added or not, e.g. ... & 0x80) -+ */ -+ SAFEALIGN_SET_UINT32(&buf[c], -+ htobe32(cert_pub_key->u.rsa.modulus.len + 1 ), &c); -+ SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c); -+ safealign_memcpy(&buf[c], cert_pub_key->u.rsa.modulus.data, -+ cert_pub_key->u.rsa.modulus.len, &c); -+ -+ *key = buf; -+ *key_size = size; -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(buf); -+ } -+ SECKEY_DestroyPublicKey(cert_pub_key); -+ CERT_DestroyCertificate(cert); -+ -+ rv = NSS_ShutdownContext(nss_ctx); -+ if (rv != SECSuccess) { -+ DEBUG(SSSDBG_OP_FAILURE, "NSS_ShutdownContext failed [%d].\n", -+ PR_GetError()); -+ } -+ -+ return ret; -+} --- -2.4.3 - diff --git a/SOURCES/0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch b/SOURCES/0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch deleted file mode 100644 index 222e9e3..0000000 --- a/SOURCES/0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch +++ /dev/null @@ -1,88 +0,0 @@ -From e10bcf99c6105b733b043a50ea96223a46784581 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 21 Jul 2015 11:44:03 +0200 -Subject: [PATCH 37/37] IPA: Remove MPG groups if getgrgid was called before - getpw() - -https://fedorahosted.org/sssd/ticket/2724 - -This bug only affects IPA clients that are connected to IPA servers with -AD trust and ID mapping in effect. - -If an IPA client calls getgrgid() for an ID that matches a user, the -user's private group would be returned and stored as a group entry. - -Subsequent queries for that user would fail, because MPG domains impose -uniqueness restriction for both the ID and name space across groups and -users. - -To work around that, we remove the UPG groups in MPG domains during a -group lookup. - -Reviewed-by: Sumit Bose ---- - src/providers/ipa/ipa_s2n_exop.c | 41 ++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 39 insertions(+), 2 deletions(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 812a4bbd707faf5c184594b562c148d1e704fd58..1e6368dc7ef1a6f60b541409f7f6740d602f0d43 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -1764,6 +1764,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - int tret; - struct sysdb_attrs *gid_override_attrs = NULL; - char ** exop_grouplist; -+ struct ldb_message *msg; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { -@@ -2005,8 +2006,44 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - attrs->a.user.pw_dir, attrs->a.user.pw_shell, - NULL, attrs->sysdb_attrs, NULL, - timeout, now); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_user failed.\n"); -+ if (ret == EEXIST && dom->mpg == true) { -+ /* This handles the case where getgrgid() was called for -+ * this user, so a group was created in the cache -+ */ -+ ret = sysdb_search_group_by_name(tmp_ctx, dom, name, NULL, &msg); -+ if (ret != EOK) { -+ /* Fail even on ENOENT, the group must be around */ -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not delete MPG group [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = sysdb_delete_group(dom, NULL, attrs->a.user.pw_uid); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_delete_group failed for MPG group [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = sysdb_store_user(dom, name, NULL, -+ attrs->a.user.pw_uid, -+ gid, attrs->a.user.pw_gecos, -+ attrs->a.user.pw_dir, -+ attrs->a.user.pw_shell, -+ NULL, attrs->sysdb_attrs, NULL, -+ timeout, now); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_store_user failed for MPG user [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "sysdb_store_user failed [%d]: %s\n", -+ ret, sss_strerror(ret)); - goto done; - } - --- -2.4.3 - diff --git a/SOURCES/0037-SYSDB-Do-not-try-to-modify-ts-cache-for-unsupported-.patch b/SOURCES/0037-SYSDB-Do-not-try-to-modify-ts-cache-for-unsupported-.patch new file mode 100644 index 0000000..ca36fa7 --- /dev/null +++ b/SOURCES/0037-SYSDB-Do-not-try-to-modify-ts-cache-for-unsupported-.patch @@ -0,0 +1,40 @@ +From af7accb9071ca5f73632e2b47c13f2ce7d26995e Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 25 Jul 2016 08:31:17 +0200 +Subject: [PATCH 37/44] SYSDB: Do not try to modify ts cache for unsupported + DNs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Only users and groups have timestamp data in separate cache. +It caused false positive warnings for autofs, netgroup ... + +Reviewed-by: Petr Čech +--- + src/db/sysdb_ops.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 4755ea3427b99a51d73b7b9134e357cf2b987613..19d6be03ede1bcec3bc7a4ed777e326460d80591 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -1198,9 +1198,14 @@ int sysdb_set_entry_attr(struct sysdb_ctx *sysdb, + sysdb_write = sysdb_entry_attrs_diff(sysdb, entry_dn, attrs, mod_op); + if (sysdb_write == true) { + ret = sysdb_set_cache_entry_attr(sysdb->ldb, entry_dn, attrs, mod_op); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Cannot set attrs for %s, %d [%s]\n", ++ ldb_dn_get_linearized(entry_dn), ret, sss_strerror(ret)); ++ } + } + +- if (ret == EOK) { ++ if (ret == EOK && is_ts_ldb_dn(entry_dn)) { + tret = sysdb_set_ts_entry_attr(sysdb, entry_dn, attrs, mod_op); + if (tret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, +-- +2.4.11 + diff --git a/SOURCES/0038-AD-avoid-memory-leak-in-netlogon_get_domain_info-and.patch b/SOURCES/0038-AD-avoid-memory-leak-in-netlogon_get_domain_info-and.patch new file mode 100644 index 0000000..d92dc85 --- /dev/null +++ b/SOURCES/0038-AD-avoid-memory-leak-in-netlogon_get_domain_info-and.patch @@ -0,0 +1,96 @@ +From 83f4fbf2cb3f9318aedfa03e526671e3c444c40b Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 12 Jul 2016 13:16:43 +0200 +Subject: [PATCH 38/44] AD: avoid memory leak in netlogon_get_domain_info() and + make it public + +Reviewed-by: Jakub Hrozek +--- + src/providers/ad/ad_common.h | 6 ++++++ + src/providers/ad/ad_domain_info.c | 29 ++++++++++++++++++++--------- + 2 files changed, 26 insertions(+), 9 deletions(-) + +diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h +index ce363c5a4122aa5e48ca83b0b2bdf63ff4372d91..f4a90e4f0a3fe5910071d5fe690d0a356e2a0bd1 100644 +--- a/src/providers/ad/ad_common.h ++++ b/src/providers/ad/ad_common.h +@@ -185,4 +185,10 @@ errno_t ad_autofs_init(TALLOC_CTX *mem_ctx, + errno_t ad_machine_account_password_renewal_init(struct be_ctx *be_ctx, + struct ad_options *ad_opts); + ++errno_t netlogon_get_domain_info(TALLOC_CTX *mem_ctx, ++ struct sysdb_attrs *reply, ++ char **_flat_name, ++ char **_site, ++ char **_forest); ++ + #endif /* AD_COMMON_H_ */ +diff --git a/src/providers/ad/ad_domain_info.c b/src/providers/ad/ad_domain_info.c +index 5f17ae5427b1206af3ad03dccce9452aefc2e6e2..a06379c263878aa95741055636d0a12764f3ad8c 100644 +--- a/src/providers/ad/ad_domain_info.c ++++ b/src/providers/ad/ad_domain_info.c +@@ -35,12 +35,11 @@ + #include "providers/ad/ad_common.h" + #include "util/util.h" + +-static errno_t +-netlogon_get_domain_info(TALLOC_CTX *mem_ctx, +- struct sysdb_attrs *reply, +- char **_flat_name, +- char **_site, +- char **_forest) ++errno_t netlogon_get_domain_info(TALLOC_CTX *mem_ctx, ++ struct sysdb_attrs *reply, ++ char **_flat_name, ++ char **_site, ++ char **_forest) + { + errno_t ret; + struct ldb_message_element *el; +@@ -51,6 +50,7 @@ netlogon_get_domain_info(TALLOC_CTX *mem_ctx, + const char *flat_name; + const char *site; + const char *forest; ++ TALLOC_CTX *tmp_ctx; + + ret = sysdb_attrs_get_el(reply, AD_AT_NETLOGON, &el); + if (ret != EOK) { +@@ -66,13 +66,24 @@ netlogon_get_domain_info(TALLOC_CTX *mem_ctx, + return EIO; + } + ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); ++ return ENOMEM; ++ } ++ + blob.data = el->values[0].data; + blob.length = el->values[0].length; + +- ndr_pull = ndr_pull_init_blob(&blob, mem_ctx); ++ /* The ndr_pull_* calls do not use ndr_pull as a talloc context to ++ * allocate memory but the second argument of ndr_pull_init_blob(). To ++ * make sure no memory is leaked here a temporary talloc context is ++ * needed. */ ++ ndr_pull = ndr_pull_init_blob(&blob, tmp_ctx); + if (ndr_pull == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ndr_pull_init_blob() failed.\n"); +- return ENOMEM; ++ ret = ENOMEM; ++ goto done; + } + + ndr_err = ndr_pull_netlogon_samlogon_response(ndr_pull, NDR_SCALARS, +@@ -146,7 +157,7 @@ netlogon_get_domain_info(TALLOC_CTX *mem_ctx, + + ret = EOK; + done: +- talloc_free(ndr_pull); ++ talloc_free(tmp_ctx); + return ret; + } + +-- +2.4.11 + diff --git a/SOURCES/0038-mmap_cache-Rename-variables.patch b/SOURCES/0038-mmap_cache-Rename-variables.patch deleted file mode 100644 index 3b5f30a..0000000 --- a/SOURCES/0038-mmap_cache-Rename-variables.patch +++ /dev/null @@ -1,122 +0,0 @@ -From fca34746951f740c544e62a5b60929c41a198fd1 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 16 Jul 2015 16:54:00 +0200 -Subject: [PATCH 38/47] mmap_cache: Rename variables -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -(cherry picked from commit 39b31427e2d11ca318df11fd48db33a7cc610aa7) ---- - src/responder/nss/nsssrv_mmap_cache.c | 16 ++++++++-------- - src/responder/nss/nsssrv_mmap_cache.h | 4 ++-- - src/sss_client/nss_mc_initgr.c | 10 +++++----- - src/util/mmap_cache.h | 2 +- - 4 files changed, 16 insertions(+), 16 deletions(-) - -diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c -index ebda8ac6fab3dd87f5a1d8e43717bf7a5b5a9878..16bc926f3ba4f5ab096bd0fb43895edef2b57c50 100644 ---- a/src/responder/nss/nsssrv_mmap_cache.c -+++ b/src/responder/nss/nsssrv_mmap_cache.c -@@ -959,8 +959,8 @@ done: - - errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - struct sized_string *name, -- uint32_t memnum, -- uint8_t *membuf) -+ uint32_t num_groups, -+ uint8_t *gids_buf) - { - struct sss_mc_ctx *mcc = *_mcc; - struct sss_mc_rec *rec; -@@ -974,8 +974,8 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - return EINVAL; - } - -- /* memnum + reserved + array of members + name*/ -- data_len = (2 + memnum) * sizeof(uint32_t) + name->len; -+ /* num_groups + reserved + array of gids + name*/ -+ data_len = (2 + num_groups) * sizeof(uint32_t) + name->len; - rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data) - + data_len; - if (rec_len > mcc->dt_size) { -@@ -998,10 +998,10 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - name->str, name->len, name->str, name->len); - - /* initgroups struct */ -- data->members = memnum; -- memcpy(data->gids, membuf, memnum * sizeof(uint32_t)); -- memcpy(&data->gids[memnum], name->str, name->len); -- data->name = MC_PTR_DIFF(&data->gids[memnum], data); -+ data->num_groups = num_groups; -+ memcpy(data->gids, gids_buf, num_groups * sizeof(uint32_t)); -+ memcpy(&data->gids[num_groups], name->str, name->len); -+ data->name = MC_PTR_DIFF(&data->gids[num_groups], data); - - MC_LOWER_BARRIER(rec); - -diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h -index 3a6764dd36bf3346d789bb287b3a94df120f36ee..b09e4a6f8efa364ae7a6407bab9d8a2a2143c812 100644 ---- a/src/responder/nss/nsssrv_mmap_cache.h -+++ b/src/responder/nss/nsssrv_mmap_cache.h -@@ -53,8 +53,8 @@ errno_t sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc, - - errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - struct sized_string *name, -- uint32_t memnum, -- uint8_t *membuf); -+ uint32_t num_groups, -+ uint8_t *gids_buf); - - errno_t sss_mmap_cache_pw_invalidate(struct sss_mc_ctx *mcc, - struct sized_string *name); -diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c -index bfb09d6550c310fbab254dc9b3ab7b306b7d3f06..e21b9f40aba00f9cc2385a561fc2bcc163c5791a 100644 ---- a/src/sss_client/nss_mc_initgr.c -+++ b/src/sss_client/nss_mc_initgr.c -@@ -42,7 +42,7 @@ static errno_t sss_nss_mc_parse_result(struct sss_mc_rec *rec, - struct sss_mc_initgr_data *data; - time_t expire; - long int i; -- uint32_t gid_count; -+ uint32_t num_groups; - long int max_ret; - - /* additional checks before filling result*/ -@@ -53,15 +53,15 @@ static errno_t sss_nss_mc_parse_result(struct sss_mc_rec *rec, - } - - data = (struct sss_mc_initgr_data *)rec->data; -- gid_count = data->members; -- max_ret = gid_count; -+ num_groups = data->num_groups; -+ max_ret = num_groups; - - /* check we have enough space in the buffer */ -- if ((*size - *start) < gid_count) { -+ if ((*size - *start) < num_groups) { - long int newsize; - gid_t *newgroups; - -- newsize = *size + gid_count; -+ newsize = *size + num_groups; - if ((limit > 0) && (newsize > limit)) { - newsize = limit; - max_ret = newsize - *start; -diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h -index 438e28a3d217041278fc1bb60aa553d098516035..a8703d5da4022e11c4bc2f3e2f8710e7f9d982bf 100644 ---- a/src/util/mmap_cache.h -+++ b/src/util/mmap_cache.h -@@ -139,7 +139,7 @@ struct sss_mc_grp_data { - - struct sss_mc_initgr_data { - rel_ptr_t name; /* ptr to name string, rel. to struct base addr */ -- uint32_t members; /* number of members in groups */ -+ uint32_t num_groups; /* number of groups */ - uint32_t gids[0]; /* array of all groups - * string with name is stored after gids */ - }; --- -2.4.3 - diff --git a/SOURCES/0039-AD-netlogon_get_domain_info-allow-missing-arguments-.patch b/SOURCES/0039-AD-netlogon_get_domain_info-allow-missing-arguments-.patch new file mode 100644 index 0000000..f81ee20 --- /dev/null +++ b/SOURCES/0039-AD-netlogon_get_domain_info-allow-missing-arguments-.patch @@ -0,0 +1,217 @@ +From df00f0d33874381fc36ee59eaf28a4918ae5dc56 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 12 Jul 2016 13:29:33 +0200 +Subject: [PATCH 39/44] AD: netlogon_get_domain_info() allow missing arguments + and empty results + +netlogon_get_domain_info() should not fail if not all parameters can be +retrieved. It should be the responsibility of the caller to see if the +needed data is available and act accordingly. + +Resolves: +https://fedorahosted.org/sssd/ticket/3104 + +Reviewed-by: Jakub Hrozek +--- + src/providers/ad/ad_common.h | 1 + + src/providers/ad/ad_domain_info.c | 108 +++++++++++++++++++++----------------- + src/providers/ad/ad_gpo.c | 2 +- + src/providers/ad/ad_subdomains.c | 3 +- + 4 files changed, 64 insertions(+), 50 deletions(-) + +diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h +index f4a90e4f0a3fe5910071d5fe690d0a356e2a0bd1..7e86faf1142d7be49eef01e1ddd7bfafea2fcedc 100644 +--- a/src/providers/ad/ad_common.h ++++ b/src/providers/ad/ad_common.h +@@ -187,6 +187,7 @@ errno_t ad_machine_account_password_renewal_init(struct be_ctx *be_ctx, + + errno_t netlogon_get_domain_info(TALLOC_CTX *mem_ctx, + struct sysdb_attrs *reply, ++ bool check_next_nearest_site_as_well, + char **_flat_name, + char **_site, + char **_forest); +diff --git a/src/providers/ad/ad_domain_info.c b/src/providers/ad/ad_domain_info.c +index a06379c263878aa95741055636d0a12764f3ad8c..5302c8083bd832d0772829d9f3a4b8e9537d34b9 100644 +--- a/src/providers/ad/ad_domain_info.c ++++ b/src/providers/ad/ad_domain_info.c +@@ -37,6 +37,7 @@ + + errno_t netlogon_get_domain_info(TALLOC_CTX *mem_ctx, + struct sysdb_attrs *reply, ++ bool check_next_nearest_site_as_well, + char **_flat_name, + char **_site, + char **_forest) +@@ -47,9 +48,6 @@ errno_t netlogon_get_domain_info(TALLOC_CTX *mem_ctx, + struct ndr_pull *ndr_pull = NULL; + enum ndr_err_code ndr_err; + struct netlogon_samlogon_response response; +- const char *flat_name; +- const char *site; +- const char *forest; + TALLOC_CTX *tmp_ctx; + + ret = sysdb_attrs_get_el(reply, AD_AT_NETLOGON, &el); +@@ -102,57 +100,73 @@ errno_t netlogon_get_domain_info(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 domain name data available\n"); +- ret = ENOENT; +- goto done; ++ /* get flat domain name */ ++ if (_flat_name != NULL) { ++ if (response.data.nt5_ex.domain_name != NULL && ++ *response.data.nt5_ex.domain_name != '\0') { ++ *_flat_name = talloc_strdup(mem_ctx, ++ response.data.nt5_ex.domain_name); ++ if (*_flat_name == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "No netlogon flat domain name data available.\n"); ++ *_flat_name = NULL; ++ } + } + +- *_flat_name = talloc_strdup(mem_ctx, flat_name); +- if (*_flat_name == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); +- 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; ++ if (_forest != NULL) { ++ if (response.data.nt5_ex.forest != NULL && ++ *response.data.nt5_ex.forest != '\0') { ++ *_forest = talloc_strdup(mem_ctx, response.data.nt5_ex.forest); ++ if (*_forest == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, "No netlogon forest data available.\n"); ++ *_forest = NULL; ++ } + } + + /* get site name */ +- if (response.data.nt5_ex.client_site != NULL +- && response.data.nt5_ex.client_site[0] != '\0') { +- site = response.data.nt5_ex.client_site; +- } else { +- DEBUG(SSSDBG_MINOR_FAILURE, +- "No netlogon site name data available\n"); +- ret = ENOENT; +- goto done; +- } ++ if (_site != NULL) { ++ if (response.data.nt5_ex.client_site != NULL ++ && response.data.nt5_ex.client_site[0] != '\0') { ++ *_site = talloc_strdup(mem_ctx, response.data.nt5_ex.client_site); ++ if (*_site == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "No netlogon site name data available.\n"); ++ *_site = NULL; + +- *_site = talloc_strdup(mem_ctx, site); +- if (*_site == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); +- ret = ENOMEM; +- goto done; ++ if (check_next_nearest_site_as_well) { ++ if (response.data.nt5_ex.next_closest_site != NULL ++ && response.data.nt5_ex.next_closest_site[0] != '\0') { ++ *_site = talloc_strdup(mem_ctx, ++ response.data.nt5_ex.next_closest_site); ++ if (*_site == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "No netlogon next closest site name data " ++ "available.\n"); ++ } ++ } ++ } + } + + ret = EOK; +@@ -388,7 +402,7 @@ ad_master_domain_netlogon_done(struct tevent_req *subreq) + + /* Exactly one flat name. Carry on */ + +- ret = netlogon_get_domain_info(state, reply[0], &state->flat, ++ ret = netlogon_get_domain_info(state, reply[0], false, &state->flat, + &state->site, &state->forest); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index 3e54fd8b5932a97779e178c7d3c5b9f6d3b3277c..f609d28136918adfe6a8d5e95319b27ffcab79c0 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -2801,7 +2801,7 @@ ad_gpo_site_name_retrieval_done(struct tevent_req *subreq) + ret = ad_master_domain_recv(subreq, state, NULL, NULL, &site, NULL); + talloc_zfree(subreq); + +- if (ret != EOK) { ++ if (ret != EOK || site == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot retrieve master domain info\n"); + tevent_req_error(req, ENOENT); + return; +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index 928c4fe93cc6afa5c3f69c14503896db820a4c0a..e9da04e384e598927f9c8c203a751bcccd29e895 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -1108,14 +1108,13 @@ static void ad_subdomains_refresh_master_done(struct tevent_req *subreq) + char *master_sid; + char *flat_name; + char *forest; +- char *site; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ad_subdomains_refresh_state); + + ret = ad_master_domain_recv(subreq, state, &flat_name, &master_sid, +- &site, &forest); ++ NULL, &forest); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get master domain information " +-- +2.4.11 + diff --git a/SOURCES/0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch b/SOURCES/0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch deleted file mode 100644 index 209ff16..0000000 --- a/SOURCES/0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 8ca168c6f459d77cdf8f46d27a392d0847343703 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 16 Jul 2015 17:00:12 +0200 -Subject: [PATCH 39/47] mmap_cache: "Override" functions for initgr mmap cache -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Functions sss_mc_get_strs_offset and sss_mc_get_strs_len provides -data about strings for individual memory caches (passwd, ...) -Their are used in generic responder mmap cache code to find a record -in mmap cache (sss_mc_find_record). Data provided from functions sss_mc_get_* -are used for checking the validity of record. So in case of corrupted record -the whole mmap cache can be invalidated. - -Functions sss_mc_get_strs_offset and sss_mc_get_strs_len did not provide -data for initgroups mmap cache and therefore particular record could not be -invalidated. - -Resolves: -https://fedorahosted.org/sssd/ticket/2716 - -Reviewed-by: Michal Židek -(cherry picked from commit 225dc6914cdc8920b02a129b98ece1ed97b99c03) ---- - src/responder/nss/nsssrv_mmap_cache.c | 15 ++++++++++++--- - src/sss_client/nss_mc_initgr.c | 16 +++++++++++----- - src/util/mmap_cache.h | 6 +++++- - 3 files changed, 28 insertions(+), 9 deletions(-) - -diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c -index 16bc926f3ba4f5ab096bd0fb43895edef2b57c50..ab9e769b1f4d5d17a8c41429afce292298239bc5 100644 ---- a/src/responder/nss/nsssrv_mmap_cache.c -+++ b/src/responder/nss/nsssrv_mmap_cache.c -@@ -475,6 +475,9 @@ static errno_t sss_mc_get_strs_offset(struct sss_mc_ctx *mcc, - case SSS_MC_GROUP: - *_offset = offsetof(struct sss_mc_grp_data, strs); - return EOK; -+ case SSS_MC_INITGROUPS: -+ *_offset = offsetof(struct sss_mc_initgr_data, gids); -+ return EOK; - default: - DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n"); - return EINVAL; -@@ -492,6 +495,9 @@ static errno_t sss_mc_get_strs_len(struct sss_mc_ctx *mcc, - case SSS_MC_GROUP: - *_len = ((struct sss_mc_grp_data *)&rec->data)->strs_len; - return EOK; -+ case SSS_MC_INITGROUPS: -+ *_len = ((struct sss_mc_initgr_data *)&rec->data)->data_len; -+ return EOK; - default: - DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n"); - return EINVAL; -@@ -974,8 +980,8 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - return EINVAL; - } - -- /* num_groups + reserved + array of gids + name*/ -- data_len = (2 + num_groups) * sizeof(uint32_t) + name->len; -+ /* array of gids + name */ -+ data_len = num_groups * sizeof(uint32_t) + name->len; - rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data) - + data_len; - if (rec_len > mcc->dt_size) { -@@ -998,10 +1004,13 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - name->str, name->len, name->str, name->len); - - /* initgroups struct */ -+ data->strs_len = name->len; -+ data->data_len = data_len; -+ data->reserved = MC_INVALID_VAL32; - data->num_groups = num_groups; - memcpy(data->gids, gids_buf, num_groups * sizeof(uint32_t)); - memcpy(&data->gids[num_groups], name->str, name->len); -- data->name = MC_PTR_DIFF(&data->gids[num_groups], data); -+ data->strs = data->name = MC_PTR_DIFF(&data->gids[num_groups], data); - - MC_LOWER_BARRIER(rec); - -diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c -index e21b9f40aba00f9cc2385a561fc2bcc163c5791a..153617ea9c6489b7439b9676904b42b042f6697c 100644 ---- a/src/sss_client/nss_mc_initgr.c -+++ b/src/sss_client/nss_mc_initgr.c -@@ -93,6 +93,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len, - uint32_t hash; - uint32_t slot; - int ret; -+ const size_t data_offset = offsetof(struct sss_mc_initgr_data, gids); - uint8_t *max_addr; - - ret = sss_nss_mc_get_ctx("initgroups", &initgr_mc_ctx); -@@ -128,16 +129,21 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len, - } - - data = (struct sss_mc_initgr_data *)rec->data; -+ rec_name = (char *)data + data->name; - /* Integrity check -- * - array with gids must be within data_table -- * - string must be within data_table */ -- if ((uint8_t *)data->gids > max_addr -- || (uint8_t *)data + data->name + name_len > max_addr) { -+ * - name_len cannot be longer than all strings or data -+ * - data->name cannot point outside strings -+ * - all data must be within data_table -+ * - name must be within data_table */ -+ if (name_len > data->data_len -+ || name_len > data->strs_len -+ || (data->strs + name_len) > (data_offset + data->data_len) -+ || (uint8_t *)data->gids + data->data_len > max_addr -+ || (uint8_t *)rec_name + name_len > max_addr) { - ret = ENOENT; - goto done; - } - -- rec_name = (char *)data + data->name; - if (strcmp(name, rec_name) == 0) { - break; - } -diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h -index a8703d5da4022e11c4bc2f3e2f8710e7f9d982bf..b5917b3c0973276e43e9fe160cec7528b1224f8f 100644 ---- a/src/util/mmap_cache.h -+++ b/src/util/mmap_cache.h -@@ -79,7 +79,7 @@ typedef uint32_t rel_ptr_t; - - - #define SSS_MC_MAJOR_VNO 1 --#define SSS_MC_MINOR_VNO 0 -+#define SSS_MC_MINOR_VNO 1 - - #define SSS_MC_HEADER_UNINIT 0 /* after ftruncate or before reset */ - #define SSS_MC_HEADER_ALIVE 1 /* current and in use */ -@@ -139,6 +139,10 @@ struct sss_mc_grp_data { - - struct sss_mc_initgr_data { - rel_ptr_t name; /* ptr to name string, rel. to struct base addr */ -+ rel_ptr_t strs; /* ptr to concatenation of all strings */ -+ uint32_t reserved; -+ uint32_t strs_len; /* length of strs */ -+ uint32_t data_len; /* all initgroups data len */ - uint32_t num_groups; /* number of groups */ - uint32_t gids[0]; /* array of all groups - * string with name is stored after gids */ --- -2.4.3 - diff --git a/SOURCES/0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch b/SOURCES/0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch deleted file mode 100644 index 579937b..0000000 --- a/SOURCES/0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 999edf37f10c90f8a2e87c16183bac2d0c6fe833 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 3 Aug 2015 12:58:03 +0200 -Subject: [PATCH 40/47] mmap: Invalidate initgroups memory cache after any - change -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Initgroups memory cache was invalidated only in case on removed user. -it should be invalidated also after changes in group membership. - -Resolves: -https://fedorahosted.org/sssd/ticket/2716 - -Reviewed-by: Michal Židek -(cherry picked from commit ea7839cec593b4a7c678fab52ab864518db6699b) ---- - src/responder/nss/nsssrv_cmd.c | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index b3998015fa621cad8e06a126a674f94d26158dda..0bfbf0eab115826ebde53b4cfcf6661f2f6328c7 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -3903,14 +3903,6 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, - ret, strerror(ret)); - } - -- ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx, -- &delete_name); -- if (ret != EOK && ret != ENOENT) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Internal failure in memory cache code: %d [%s]\n", -- ret, strerror(ret)); -- } -- - /* Also invalidate his groups */ - changed = true; - } else { -@@ -3958,6 +3950,15 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, - ret, strerror(ret)); - } - } -+ -+ to_sized_string(&delete_name, name); -+ ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx, -+ &delete_name); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Internal failure in memory cache code: %d [%s]\n", -+ ret, strerror(ret)); -+ } - } - - done: --- -2.4.3 - diff --git a/SOURCES/0040-tests-add-tests-for-netlogon_get_domain_info.patch b/SOURCES/0040-tests-add-tests-for-netlogon_get_domain_info.patch new file mode 100644 index 0000000..b429a27 --- /dev/null +++ b/SOURCES/0040-tests-add-tests-for-netlogon_get_domain_info.patch @@ -0,0 +1,125 @@ +From 4319dabb39ea91d1c1cd9fe5294e17706045bd48 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 11 Jul 2016 17:05:29 +0200 +Subject: [PATCH 40/44] tests: add tests for netlogon_get_domain_info + +Reviewed-by: Jakub Hrozek +--- + Makefile.am | 1 + + src/tests/cmocka/test_ad_common.c | 81 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 82 insertions(+) + +diff --git a/Makefile.am b/Makefile.am +index d05919705910fa565ff954224ce40feb5d7ff39f..cefd9a43442fc19933f1e373d4f2ed4bb3ba3201 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -2470,6 +2470,7 @@ ad_common_tests_SOURCES = \ + src/providers/ad/ad_opts.c \ + src/providers/ad/ad_pac.c \ + src/providers/ad/ad_pac_common.c \ ++ src/providers/ad/ad_domain_info.c \ + src/providers/ldap/sdap_async_initgroups_ad.c \ + $(NULL) + ad_common_tests_CFLAGS = \ +diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c +index b7a5838de04e1a788bb9a61e84df00fc9bcc784b..7987330e2d0f5df93b62e4a68f34bc4ae23bd79b 100644 +--- a/src/tests/cmocka/test_ad_common.c ++++ b/src/tests/cmocka/test_ad_common.c +@@ -802,6 +802,84 @@ void test_user_conn_list(void **state) + talloc_free(conn_list); + } + ++void test_netlogon_get_domain_info(void **state) ++{ ++ int ret; ++ struct sysdb_attrs *attrs; ++ struct ldb_val val = { 0 }; ++ char *flat_name; ++ char *site; ++ char *forest; ++ ++ struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, ++ struct ad_common_test_ctx); ++ assert_non_null(test_ctx); ++ ++ attrs = sysdb_new_attrs(test_ctx); ++ assert_non_null(attrs); ++ ++ ret = netlogon_get_domain_info(test_ctx, attrs, false, NULL, NULL, NULL); ++ assert_int_equal(ret, ENOENT); ++ ++ ret = sysdb_attrs_add_val(attrs, AD_AT_NETLOGON, &val); ++ assert_int_equal(ret, EOK); ++ ++ ret = netlogon_get_domain_info(test_ctx, attrs, false, NULL, NULL, NULL); ++ assert_int_equal(ret, EBADMSG); ++ ++ talloc_free(attrs); ++ attrs = sysdb_new_attrs(test_ctx); ++ assert_non_null(attrs); ++ ++ val.data = sss_base64_decode(test_ctx, "FwAAAP0zAABsGcIYI7j2TL97Rd+TvpATAmFkBWRldmVsAMAYCWFkLXNlcnZlcsAYAkFEAAlBRC1TRVJWRVIAABdEZWZhdWx0LUZpcnN0LVNpdGUtTmFtZQDAQAUAAAD/////", &val.length); ++ assert_non_null(val.data); ++ ++ ret = sysdb_attrs_add_val(attrs, AD_AT_NETLOGON, &val); ++ assert_int_equal(ret, EOK); ++ ++ ret = netlogon_get_domain_info(test_ctx, attrs, false, &flat_name, &site, &forest); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(flat_name, "AD"); ++ assert_string_equal(site, "Default-First-Site-Name"); ++ assert_string_equal(forest, "ad.devel"); ++ ++ /* missing site */ ++ talloc_free(flat_name); ++ talloc_free(site); ++ talloc_free(forest); ++ talloc_free(val.data); ++ talloc_free(attrs); ++ attrs = sysdb_new_attrs(test_ctx); ++ assert_non_null(attrs); ++ ++ val.data = sss_base64_decode(test_ctx, "FwAAAH0zAABsGcIYI7j2TL97Rd+TvpATAmFkBWRldmVsAMAYCWFkLXNlcnZlcsAYAkFEAAlBRC1TRVJWRVIAABdEZWZhdWx0LUZpcnN0LVNpdGUtTmFtZQAABQAAAP////8=", &val.length); ++ assert_non_null(val.data); ++ ++ ret = sysdb_attrs_add_val(attrs, AD_AT_NETLOGON, &val); ++ assert_int_equal(ret, EOK); ++ ++ ret = netlogon_get_domain_info(test_ctx, attrs, false, &flat_name, &site, &forest); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(flat_name, "AD"); ++ assert_null(site); ++ assert_string_equal(forest, "ad.devel"); ++ ++ talloc_free(flat_name); ++ talloc_free(site); ++ talloc_free(forest); ++ ret = netlogon_get_domain_info(test_ctx, attrs, true, &flat_name, &site, &forest); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(flat_name, "AD"); ++ assert_null(site); ++ assert_string_equal(forest, "ad.devel"); ++ ++ talloc_free(flat_name); ++ talloc_free(site); ++ talloc_free(forest); ++ talloc_free(val.data); ++ talloc_free(attrs); ++} ++ + int main(int argc, const char *argv[]) + { + poptContext pc; +@@ -845,6 +923,9 @@ int main(int argc, const char *argv[]) + cmocka_unit_test_setup_teardown(test_ad_get_pac_data_from_user_entry, + test_ad_common_setup, + test_ad_common_teardown), ++ cmocka_unit_test_setup_teardown(test_netlogon_get_domain_info, ++ test_ad_common_setup, ++ test_ad_common_teardown), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ +-- +2.4.11 + diff --git a/SOURCES/0041-AD-replace-ad_get_client_site_parse_ndr-with-netlogo.patch b/SOURCES/0041-AD-replace-ad_get_client_site_parse_ndr-with-netlogo.patch new file mode 100644 index 0000000..28bfa38 --- /dev/null +++ b/SOURCES/0041-AD-replace-ad_get_client_site_parse_ndr-with-netlogo.patch @@ -0,0 +1,217 @@ +From b0873f4a99f44eabae11e1cc62f6ec49c07466f0 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 18 Jul 2016 11:25:47 +0200 +Subject: [PATCH 41/44] AD: replace ad_get_client_site_parse_ndr() with + netlogon_get_domain_info() + +netlogon_get_domain_info() does not fail if only the site is missing in +the CLDAP ping respond. If the site is not available a Global Catalog +can still be looked up with the forest name. Only if the forest name is +missing as well we fall back to the configured domain name. + +Resolves: +https://fedorahosted.org/sssd/ticket/3104 + +Reviewed-by: Jakub Hrozek +--- + src/providers/ad/ad_srv.c | 153 ++++++++++------------------------------------ + 1 file changed, 33 insertions(+), 120 deletions(-) + +diff --git a/src/providers/ad/ad_srv.c b/src/providers/ad/ad_srv.c +index 9602945e66aa0529938bdd63067f00971dbcbe89..ff01ee95c4d2c6875a989394489f1a0495cc3003 100644 +--- a/src/providers/ad/ad_srv.c ++++ b/src/providers/ad/ad_srv.c +@@ -405,93 +405,10 @@ done: + return; + } + +-static errno_t ad_get_client_site_parse_ndr(TALLOC_CTX *mem_ctx, +- uint8_t *data, +- size_t length, +- char **_site_name, +- char **_forest_name) +-{ +- TALLOC_CTX *tmp_ctx = NULL; +- struct ndr_pull *ndr_pull = NULL; +- struct netlogon_samlogon_response response; +- enum ndr_err_code ndr_err; +- char *site = NULL; +- char *forest = NULL; +- DATA_BLOB blob; +- errno_t ret; +- +- tmp_ctx = talloc_new(NULL); +- if (tmp_ctx == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); +- return ENOMEM; +- } +- +- blob.data = data; +- blob.length = length; +- +- ndr_pull = ndr_pull_init_blob(&blob, mem_ctx); +- if (ndr_pull == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "ndr_pull_init_blob() failed.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- ndr_err = ndr_pull_netlogon_samlogon_response(ndr_pull, NDR_SCALARS, +- &response); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- DEBUG(SSSDBG_OP_FAILURE, "ndr_pull_netlogon_samlogon_response() " +- "failed [%d]\n", ndr_err); +- ret = EBADMSG; +- goto done; +- } +- +- if (!(response.ntver & NETLOGON_NT_VERSION_5EX)) { +- DEBUG(SSSDBG_OP_FAILURE, "This NT version does not provide site " +- "information [%x]\n", response.ntver); +- ret = EBADMSG; +- goto done; +- } +- +- if (response.data.nt5_ex.client_site != NULL +- && response.data.nt5_ex.client_site[0] != '\0') { +- site = talloc_strdup(tmp_ctx, response.data.nt5_ex.client_site); +- } else if (response.data.nt5_ex.next_closest_site != NULL +- && response.data.nt5_ex.next_closest_site[0] != '\0') { +- site = talloc_strdup(tmp_ctx, response.data.nt5_ex.next_closest_site); +- } else { +- ret = ENOENT; +- goto done; +- } +- +- if (response.data.nt5_ex.forest != NULL +- && response.data.nt5_ex.forest[0] != '\0') { +- forest = talloc_strdup(tmp_ctx, response.data.nt5_ex.forest); +- } else { +- ret = ENOENT; +- goto done; +- } +- +- +- if (site == NULL || forest == NULL) { +- ret = ENOMEM; +- goto done; +- } +- +- *_site_name = talloc_steal(mem_ctx, site); +- *_forest_name = talloc_steal(mem_ctx, forest); +- +- ret = EOK; +- +-done: +- talloc_free(tmp_ctx); +- return ret; +-} +- + static void ad_get_client_site_done(struct tevent_req *subreq) + { + struct ad_get_client_site_state *state = NULL; + struct tevent_req *req = NULL; +- struct ldb_message_element *el = NULL; + struct sysdb_attrs **reply = NULL; + size_t reply_count; + errno_t ret; +@@ -520,25 +437,8 @@ static void ad_get_client_site_done(struct tevent_req *subreq) + goto done; + } + +- ret = sysdb_attrs_get_el(reply[0], AD_AT_NETLOGON, &el); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el() failed\n"); +- goto done; +- } +- +- if (el->num_values == 0) { +- DEBUG(SSSDBG_OP_FAILURE, "netlogon has no value\n"); +- ret = ENOENT; +- goto done; +- } else if (el->num_values > 1) { +- DEBUG(SSSDBG_OP_FAILURE, "More than one netlogon value?\n"); +- ret = EIO; +- goto done; +- } +- +- ret = ad_get_client_site_parse_ndr(state, el->values[0].data, +- el->values[0].length, &state->site, +- &state->forest); ++ ret = netlogon_get_domain_info(state, reply[0], true, NULL, &state->site, ++ &state->forest); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve site name [%d]: %s\n", + ret, strerror(ret)); +@@ -547,6 +447,7 @@ static void ad_get_client_site_done(struct tevent_req *subreq) + } + + DEBUG(SSSDBG_TRACE_FUNC, "Found site: %s\n", state->site); ++ DEBUG(SSSDBG_TRACE_FUNC, "Found forest: %s\n", state->forest); + + done: + if (ret != EOK) { +@@ -803,30 +704,42 @@ static void ad_srv_plugin_site_done(struct tevent_req *subreq) + + ret = EOK; + } ++ ++ primary_domain = state->discovery_domain; ++ backup_domain = NULL; ++ + if (ret == EOK) { + if (strcmp(state->service, "gc") == 0) { +- primary_domain = talloc_asprintf(state, AD_SITE_DOMAIN_FMT, +- state->site, state->forest); +- if (primary_domain == NULL) { +- ret = ENOMEM; +- goto done; +- } ++ if (state->forest != NULL) { ++ if (state->site != NULL) { ++ primary_domain = talloc_asprintf(state, AD_SITE_DOMAIN_FMT, ++ state->site, ++ state->forest); ++ if (primary_domain == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } + +- backup_domain = state->forest; ++ backup_domain = state->forest; ++ } else { ++ primary_domain = state->forest; ++ backup_domain = NULL; ++ } ++ } + } else { +- primary_domain = talloc_asprintf(state, AD_SITE_DOMAIN_FMT, +- state->site, state->discovery_domain); +- if (primary_domain == NULL) { +- ret = ENOMEM; +- goto done; +- } ++ if (state->site != NULL) { ++ primary_domain = talloc_asprintf(state, AD_SITE_DOMAIN_FMT, ++ state->site, ++ state->discovery_domain); ++ if (primary_domain == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } + +- backup_domain = state->discovery_domain; ++ backup_domain = state->discovery_domain; ++ } + } +- } else if (ret == ENOENT) { +- primary_domain = state->discovery_domain; +- backup_domain = NULL; +- } else { ++ } else if (ret != ENOENT && ret != EOK) { + goto done; + } + +-- +2.4.11 + diff --git a/SOURCES/0041-sss_client-Update-integrity-check-of-records-in-mmap.patch b/SOURCES/0041-sss_client-Update-integrity-check-of-records-in-mmap.patch deleted file mode 100644 index c59a460..0000000 --- a/SOURCES/0041-sss_client-Update-integrity-check-of-records-in-mmap.patch +++ /dev/null @@ -1,227 +0,0 @@ -From e115f70d717ab8232172b358739ba7a0e1102caa Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 30 Jul 2015 10:50:47 +0200 -Subject: [PATCH 41/47] sss_client: Update integrity check of records in mmap - cache -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The function sss_nss_mc_get_record return copy of record from memory -cache in last argument. Because we should not access data directly -to avoid problems with consistency of record. -The function sss_nss_mc_get_record also check whether length of record -is within data area (with macro MC_CHECK_RECORD_LENGTH) - -However we also tried to do the same check in functions sss_nss_mc_get{gr, pw}* -Pointer to end of strings in record was compared to pointer to the end -of data table. But these two pointers are not within the same allocated area -and does not make sense to compare them. Sometimes record can be allocated -before mmaped area and sometime after. Sometimes it will return cached data -and other time will fall back to responder. - -Resolves: -https://fedorahosted.org/sssd/ticket/2743 - -Reviewed-by: Michal Židek -(cherry picked from commit ba847347cade817ee927397d82c952b51b0dcb2b) ---- - src/sss_client/nss_mc_group.c | 19 ++++++++++--------- - src/sss_client/nss_mc_initgr.c | 26 +++++++++++++------------- - src/sss_client/nss_mc_passwd.c | 20 ++++++++++---------- - 3 files changed, 33 insertions(+), 32 deletions(-) - -diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c -index e0fdb97f628ac19741409be29566e4af5a391f74..aacf59d9fd8b81ea895f4660de08f3e44f0ce645 100644 ---- a/src/sss_client/nss_mc_group.c -+++ b/src/sss_client/nss_mc_group.c -@@ -112,16 +112,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, - uint32_t hash; - uint32_t slot; - int ret; -- size_t strs_offset; -- uint8_t *max_addr; -+ const size_t strs_offset = offsetof(struct sss_mc_grp_data, strs); -+ size_t data_size; - - ret = sss_nss_mc_get_ctx("group", &gr_mc_ctx); - if (ret) { - return ret; - } - -- /* Get max address of data table. */ -- max_addr = gr_mc_ctx.data_table + gr_mc_ctx.dt_size; -+ /* Get max size of data table. */ -+ data_size = gr_mc_ctx.dt_size; - - /* hashes are calculated including the NULL terminator */ - hash = sss_nss_mc_hash(&gr_mc_ctx, name, name_len + 1); -@@ -130,7 +130,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, - /* If slot is not within the bounds of mmaped region and - * it's value is not MC_INVALID_VAL, then the cache is - * probbably corrupted. */ -- while (MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) { -+ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { - /* free record from previous iteration */ - free(rec); - rec = NULL; -@@ -147,15 +147,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, - continue; - } - -- strs_offset = offsetof(struct sss_mc_grp_data, strs); - data = (struct sss_mc_grp_data *)rec->data; - /* Integrity check - * - name_len cannot be longer than all strings - * - data->name cannot point outside strings -- * - all strings must be within data_table */ -+ * - all strings must be within copy of record -+ * - size of record must be lower that data table size */ - if (name_len > data->strs_len - || (data->name + name_len) > (strs_offset + data->strs_len) -- || (uint8_t *)data->strs + data->strs_len > max_addr) { -+ || data->strs_len > rec->len -+ || rec->len > data_size) { - ret = ENOENT; - goto done; - } -@@ -168,7 +169,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len, - slot = sss_nss_mc_next_slot_with_hash(rec, hash); - } - -- if (!MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) { -+ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { - ret = ENOENT; - goto done; - } -diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c -index 153617ea9c6489b7439b9676904b42b042f6697c..74143d9fb3c674c3116d7f4cf0b4c03d993743a2 100644 ---- a/src/sss_client/nss_mc_initgr.c -+++ b/src/sss_client/nss_mc_initgr.c -@@ -94,15 +94,15 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len, - uint32_t slot; - int ret; - const size_t data_offset = offsetof(struct sss_mc_initgr_data, gids); -- uint8_t *max_addr; -+ size_t data_size; - - ret = sss_nss_mc_get_ctx("initgroups", &initgr_mc_ctx); - if (ret) { - return ret; - } - -- /* Get max address of data table. */ -- max_addr = initgr_mc_ctx.data_table + initgr_mc_ctx.dt_size; -+ /* Get max size of data table. */ -+ data_size = initgr_mc_ctx.dt_size; - - /* hashes are calculated including the NULL terminator */ - hash = sss_nss_mc_hash(&initgr_mc_ctx, name, name_len + 1); -@@ -111,7 +111,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len, - /* If slot is not within the bounds of mmaped region and - * it's value is not MC_INVALID_VAL, then the cache is - * probbably corrupted. */ -- while (MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) { -+ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { - /* free record from previous iteration */ - free(rec); - rec = NULL; -@@ -132,14 +132,14 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len, - rec_name = (char *)data + data->name; - /* Integrity check - * - name_len cannot be longer than all strings or data -- * - data->name cannot point outside strings -- * - all data must be within data_table -- * - name must be within data_table */ -- if (name_len > data->data_len -- || name_len > data->strs_len -- || (data->strs + name_len) > (data_offset + data->data_len) -- || (uint8_t *)data->gids + data->data_len > max_addr -- || (uint8_t *)rec_name + name_len > max_addr) { -+ * - all data must be within copy of record -+ * - size of record must be lower that data table size -+ * - data->strs cannot point outside strings */ -+ if (name_len > data->strs_len -+ || data->strs_len > data->data_len -+ || data->data_len > rec->len -+ || rec->len > data_size -+ || (data->strs + name_len) > (data_offset + data->data_len)) { - ret = ENOENT; - goto done; - } -@@ -151,7 +151,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len, - slot = sss_nss_mc_next_slot_with_hash(rec, hash); - } - -- if (!MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) { -+ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { - ret = ENOENT; - goto done; - } -diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c -index 10e43e2af43c5e7f1738e281b3ed260d89f3a004..0da7ad0aeece7d38ca34bb3fde64adc898eaf0ae 100644 ---- a/src/sss_client/nss_mc_passwd.c -+++ b/src/sss_client/nss_mc_passwd.c -@@ -105,16 +105,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, - uint32_t hash; - uint32_t slot; - int ret; -- size_t strs_offset; -- uint8_t *max_addr; -+ const size_t strs_offset = offsetof(struct sss_mc_pwd_data, strs); -+ size_t data_size; - - ret = sss_nss_mc_get_ctx("passwd", &pw_mc_ctx); - if (ret) { - return ret; - } - -- /* Get max address of data table. */ -- max_addr = pw_mc_ctx.data_table + pw_mc_ctx.dt_size; -+ /* Get max size of data table. */ -+ data_size = pw_mc_ctx.dt_size; - - /* hashes are calculated including the NULL terminator */ - hash = sss_nss_mc_hash(&pw_mc_ctx, name, name_len + 1); -@@ -123,7 +123,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, - /* If slot is not within the bounds of mmaped region and - * it's value is not MC_INVALID_VAL, then the cache is - * probbably corrupted. */ -- while (MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) { -+ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { - /* free record from previous iteration */ - free(rec); - rec = NULL; -@@ -140,16 +140,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, - continue; - } - -- strs_offset = offsetof(struct sss_mc_pwd_data, strs); -- - data = (struct sss_mc_pwd_data *)rec->data; - /* Integrity check - * - name_len cannot be longer than all strings - * - data->name cannot point outside strings -- * - all strings must be within data_table */ -+ * - all strings must be within copy of record -+ * - size of record must be lower that data table size */ - if (name_len > data->strs_len - || (data->name + name_len) > (strs_offset + data->strs_len) -- || (uint8_t *)data->strs + data->strs_len > max_addr) { -+ || data->strs_len > rec->len -+ || rec->len > data_size) { - ret = ENOENT; - goto done; - } -@@ -162,7 +162,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len, - slot = sss_nss_mc_next_slot_with_hash(rec, hash); - } - -- if (!MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) { -+ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) { - ret = ENOENT; - goto done; - } --- -2.4.3 - diff --git a/SOURCES/0042-intg_test-Add-module-for-simulation-of-utility-id.patch b/SOURCES/0042-intg_test-Add-module-for-simulation-of-utility-id.patch deleted file mode 100644 index 71ff852..0000000 --- a/SOURCES/0042-intg_test-Add-module-for-simulation-of-utility-id.patch +++ /dev/null @@ -1,155 +0,0 @@ -From b47156c92867daaa2c30a7f4ad884a27273e54ff Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 29 Jul 2015 14:35:52 +0200 -Subject: [PATCH 42/47] intg_test: Add module for simulation of utility id -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -(cherry picked from commit 38b07019861240cf5107f5d51fc0027519e21619) ---- - src/tests/intg/Makefile.am | 1 + - src/tests/intg/sssd_id.py | 119 +++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 120 insertions(+) - create mode 100644 src/tests/intg/sssd_id.py - -diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am -index 9383e112002baa7b0d200a3dc205aa2856089c97..7488022ed59dd894ba7b6808c5573706412098c7 100644 ---- a/src/tests/intg/Makefile.am -+++ b/src/tests/intg/Makefile.am -@@ -1,5 +1,6 @@ - dist_noinst_DATA = \ - config.py.m4 \ -+ sssd_id.py \ - ds.py \ - ds_openldap.py \ - ent.py \ -diff --git a/src/tests/intg/sssd_id.py b/src/tests/intg/sssd_id.py -new file mode 100644 -index 0000000000000000000000000000000000000000..45f2822b5b33d99b6a7cbbbba0450c774e05ff11 ---- /dev/null -+++ b/src/tests/intg/sssd_id.py -@@ -0,0 +1,119 @@ -+# -+# Module for simulation of utility "id" from coreutils -+# -+# Copyright (c) 2015 Red Hat, Inc. -+# Author: Lukas Slebodnik -+# -+# This is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by -+# the Free Software Foundation; version 2 only -+# -+# This program is distributed in the hope that it will be useful, but -+# WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+# General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+# -+import config -+import pwd -+import grp -+from ctypes import (cdll, c_int, c_char, c_uint32, c_long, c_char_p, -+ POINTER, pointer) -+ -+ -+class NssReturnCode(object): -+ """ 'enum' class for name service switch retrn code """ -+ TRYAGAIN = -2, -+ UNAVAIL = -1 -+ NOTFOUND = 0 -+ SUCCESS = 1 -+ RETURN = 2 -+ -+ -+def call_sssd_initgroups(user, gid): -+ """ -+ Function will initialize the supplementary group access list -+ for given user. It will gather groups only provided by sssd. -+ -+ Arguments are the same as for C function initgroups -+ @param string user name of user -+ @param int gid the additional gid will be also added to the list. -+ -+ @return (int, int, List[int]) (err, errno, gids) -+ gids shoudl contain user group IDs if err is NssReturnCode.SUCCESS -+ otherwise errno will contain non-zero vlaue. -+ """ -+ libnss_sss_path = config.PREFIX + "/lib/libnss_sss.so.2" -+ libnss_sss = cdll.LoadLibrary(libnss_sss_path) -+ -+ func = libnss_sss._nss_sss_initgroups_dyn -+ func.restype = c_int -+ func.argtypes = [POINTER(c_char), c_uint32, POINTER(c_long), -+ POINTER(c_long), POINTER(POINTER(c_uint32)), c_long, -+ POINTER(c_int)] -+ -+ start = POINTER(c_long)(c_long(0)) -+ size = POINTER(c_long)(c_long(0)) -+ groups = POINTER(c_uint32)() -+ p_groups = pointer(groups) -+ limit = c_long(-1) -+ errno = POINTER(c_int)(c_int(0)) -+ -+ res = func(c_char_p(user), c_uint32(gid), start, size, p_groups, limit, -+ errno) -+ -+ gids = [] -+ if res == NssReturnCode.SUCCESS: -+ gids_count = size[0] -+ assert gids_count > 0, "_nss_sss_initgroups_dyn shoulld return " \ -+ "one gid" -+ -+ for i in range(0, gids_count): -+ gids.append(int(p_groups.contents[i])) -+ -+ return (int(res), errno[0], gids) -+ -+ -+def get_user_gids(user): -+ """ -+ Function will initialize the supplementary group access list -+ for given user. It will gather groups only provided by sssd. -+ -+ Arguments are the same as for C function initgroups -+ @param string user name of user -+ -+ @return (int, int, List[int]) (err, errno, gids) -+ gids shoudl contain user group IDs if err is NssReturnCode.SUCCESS -+ otherwise errno will contain non-zero vlaue. -+ """ -+ pwd_user = pwd.getpwnam(user) -+ uid = pwd_user.pw_uid -+ gid = pwd_user.pw_gid -+ -+ user = pwd.getpwuid(uid).pw_name -+ -+ return call_sssd_initgroups(user, gid) -+ -+ -+def get_user_groups(user): -+ """ -+ Function will initialize the supplementary group access list -+ for given user. It will gather groups only provided by sssd. -+ -+ Arguments are the same as for C function initgroups -+ @param string user name of user -+ -+ @return (int, int, List[string]) (err, errno, groups) -+ roups shoudl contain names of user groups -+ if err is NssReturnCode.SUCCESS -+ otherwise errno will contain non-zero vlaue. -+ """ -+ (res, errno, gids) = get_user_gids(user) -+ groups = [] -+ -+ if res == NssReturnCode.SUCCESS: -+ groups = [grp.getgrgid(gid).gr_name for gid in gids] -+ -+ return (res, errno, groups) --- -2.4.3 - diff --git a/SOURCES/0042-sysdb_master_domain_add_info-properly-set-do_update.patch b/SOURCES/0042-sysdb_master_domain_add_info-properly-set-do_update.patch new file mode 100644 index 0000000..15f9cbc --- /dev/null +++ b/SOURCES/0042-sysdb_master_domain_add_info-properly-set-do_update.patch @@ -0,0 +1,35 @@ +From 9899507b2da55a374baef13c4dc3914fe853cf87 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 25 Jul 2016 17:37:51 +0200 +Subject: [PATCH 42/44] sysdb_master_domain_add_info: properly set do_update +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +do_update should be only set if there is a change, i.e if something was +added to the ldb_message. + +Reviewed-by: Lukáš Slebodník +--- + src/db/sysdb_subdomains.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index 02206e470e8e035cc05848137df6a1eb04806869..ff83f914f31d566e050c74a3ef5f5745f8c93add 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -787,9 +787,9 @@ errno_t sysdb_master_domain_add_info(struct sss_domain_info *domain, + ret = sysdb_error_to_errno(ret); + goto done; + } +- } + +- do_update = true; ++ do_update = true; ++ } + } + + if (do_update == false) { +-- +2.4.11 + diff --git a/SOURCES/0043-SYSDB-Removing-of-duplication-of-sysdb_ts_cache_attr.patch b/SOURCES/0043-SYSDB-Removing-of-duplication-of-sysdb_ts_cache_attr.patch new file mode 100644 index 0000000..20883fd --- /dev/null +++ b/SOURCES/0043-SYSDB-Removing-of-duplication-of-sysdb_ts_cache_attr.patch @@ -0,0 +1,30 @@ +From bfbafa51da5e407659c924eed5970f17510ae913 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 19 Jul 2016 14:28:35 +0200 +Subject: [PATCH 43/44] SYSDB: Removing of duplication of sysdb_ts_cache_attrs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Fabiano Fidêncio +--- + src/db/sysdb.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 407ce3c18a7077e8fe45c3c9c7576ae626105122..0cc550a4c389b4a1a2b78aff760f4b5cbf94e17f 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -315,9 +315,6 @@ struct range_info { + /* These attributes are stored in the timestamp cache */ + extern const char *sysdb_ts_cache_attrs[]; + +-/* These attributes are stored in the timestamp cache */ +-extern const char *sysdb_ts_cache_attrs[]; +- + /* values are copied in the structure, allocated on "attrs" */ + int sysdb_attrs_add_val(struct sysdb_attrs *attrs, + const char *name, const struct ldb_val *val); +-- +2.4.11 + diff --git a/SOURCES/0043-intg_test-Add-integration-test-for-memory-cache.patch b/SOURCES/0043-intg_test-Add-integration-test-for-memory-cache.patch deleted file mode 100644 index 67012ce..0000000 --- a/SOURCES/0043-intg_test-Add-integration-test-for-memory-cache.patch +++ /dev/null @@ -1,384 +0,0 @@ -From a45f9034e912b6242459a8d576f60ff829508bc3 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 21 Jul 2015 08:55:14 +0200 -Subject: [PATCH 43/47] intg_test: Add integration test for memory cache -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -(cherry picked from commit a2c10cf31d14bac598f5cd008973375c3f9575a6) ---- - src/tests/intg/Makefile.am | 1 + - src/tests/intg/test_memory_cache.py | 347 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 348 insertions(+) - create mode 100644 src/tests/intg/test_memory_cache.py - -diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am -index 7488022ed59dd894ba7b6808c5573706412098c7..6819c2f2cea137c7544e94b0b29391611533b20c 100644 ---- a/src/tests/intg/Makefile.am -+++ b/src/tests/intg/Makefile.am -@@ -8,6 +8,7 @@ dist_noinst_DATA = \ - ldap_ent.py \ - ldap_test.py \ - util.py \ -+ test_memory_cache.py \ - $(NULL) - - config.py: config.py.m4 -diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py -new file mode 100644 -index 0000000000000000000000000000000000000000..5a1f07651b70a5bf1fbacceeae6825ea4341e3b5 ---- /dev/null -+++ b/src/tests/intg/test_memory_cache.py -@@ -0,0 +1,347 @@ -+# -+# LDAP integration test -+# -+# Copyright (c) 2015 Red Hat, Inc. -+# Author: Lukas Slebodnik -+# -+# This is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by -+# the Free Software Foundation; version 2 only -+# -+# This program is distributed in the hope that it will be useful, but -+# WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+# General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+# -+import os -+import stat -+import ent -+import config -+import signal -+import subprocess -+import time -+import pytest -+import ds_openldap -+import ldap_ent -+import sssd_id -+from util import unindent -+ -+LDAP_BASE_DN = "dc=example,dc=com" -+ -+ -+@pytest.fixture(scope="module") -+def ds_inst(request): -+ """LDAP server instance fixture""" -+ ds_inst = ds_openldap.DSOpenLDAP( -+ config.PREFIX, 10389, LDAP_BASE_DN, -+ "cn=admin", "Secret123") -+ try: -+ ds_inst.setup() -+ except: -+ ds_inst.teardown() -+ raise -+ request.addfinalizer(lambda: ds_inst.teardown()) -+ return ds_inst -+ -+ -+@pytest.fixture(scope="module") -+def ldap_conn(request, ds_inst): -+ """LDAP server connection fixture""" -+ ldap_conn = ds_inst.bind() -+ ldap_conn.ds_inst = ds_inst -+ request.addfinalizer(lambda: ldap_conn.unbind_s()) -+ return ldap_conn -+ -+ -+def create_ldap_fixture(request, ldap_conn, ent_list): -+ """Add LDAP entries and add teardown for removing them""" -+ for entry in ent_list: -+ ldap_conn.add_s(entry[0], entry[1]) -+ -+ def teardown(): -+ for entry in ent_list: -+ ldap_conn.delete_s(entry[0]) -+ request.addfinalizer(teardown) -+ -+ -+def create_conf_fixture(request, contents): -+ """Generate sssd.conf and add teardown for removing it""" -+ conf = open(config.CONF_PATH, "w") -+ conf.write(contents) -+ conf.close() -+ os.chmod(config.CONF_PATH, stat.S_IRUSR | stat.S_IWUSR) -+ request.addfinalizer(lambda: os.unlink(config.CONF_PATH)) -+ -+ -+def stop_sssd(): -+ pid_file = open(config.PIDFILE_PATH, "r") -+ pid = int(pid_file.read()) -+ os.kill(pid, signal.SIGTERM) -+ while True: -+ try: -+ os.kill(pid, signal.SIGCONT) -+ except: -+ break -+ time.sleep(1) -+ -+ -+def create_sssd_fixture(request): -+ """Start sssd and add teardown for stopping it and removing state""" -+ if subprocess.call(["sssd", "-D", "-f"]) != 0: -+ raise Exception("sssd start failed") -+ -+ def teardown(): -+ try: -+ stop_sssd() -+ except: -+ pass -+ subprocess.call(["sss_cache", "-E"]) -+ for path in os.listdir(config.DB_PATH): -+ os.unlink(config.DB_PATH + "/" + path) -+ for path in os.listdir(config.MCACHE_PATH): -+ os.unlink(config.MCACHE_PATH + "/" + path) -+ request.addfinalizer(teardown) -+ -+ -+@pytest.fixture -+def sanity_rfc2307(request, ldap_conn): -+ ent_list = ldap_ent.List(LDAP_BASE_DN) -+ ent_list.add_user("user1", 1001, 2001) -+ ent_list.add_user("user2", 1002, 2002) -+ ent_list.add_user("user3", 1003, 2003) -+ ent_list.add_user("user11", 1011, 2001) -+ ent_list.add_user("user12", 1012, 2002) -+ ent_list.add_user("user13", 1013, 2003) -+ ent_list.add_user("user21", 1021, 2001) -+ ent_list.add_user("user22", 1022, 2002) -+ ent_list.add_user("user23", 1023, 2003) -+ -+ ent_list.add_group("group1", 2001, ["user1", "user11", "user21"]) -+ ent_list.add_group("group2", 2002, ["user2", "user12", "user22"]) -+ ent_list.add_group("group3", 2003, ["user3", "user13", "user23"]) -+ -+ ent_list.add_group("group0x", 2000, ["user1", "user2", "user3"]) -+ ent_list.add_group("group1x", 2010, ["user11", "user12", "user13"]) -+ ent_list.add_group("group2x", 2020, ["user21", "user22", "user23"]) -+ create_ldap_fixture(request, ldap_conn, ent_list) -+ -+ conf = unindent("""\ -+ [sssd] -+ config_file_version = 2 -+ domains = LDAP -+ services = nss -+ -+ [nss] -+ -+ [domain/LDAP] -+ ldap_auth_disable_tls_never_use_in_production = true -+ ldap_schema = rfc2307 -+ id_provider = ldap -+ auth_provider = ldap -+ sudo_provider = ldap -+ ldap_uri = {ldap_conn.ds_inst.ldap_url} -+ ldap_search_base = {ldap_conn.ds_inst.base_dn} -+ """).format(**locals()) -+ create_conf_fixture(request, conf) -+ create_sssd_fixture(request) -+ return None -+ -+ -+def test_getpwnam(ldap_conn, sanity_rfc2307): -+ ent.assert_passwd_by_name( -+ 'user1', -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1001, -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user2', -+ dict(name='user2', passwd='*', uid=1002, gid=2002, -+ gecos='1002', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1002, -+ dict(name='user2', passwd='*', uid=1002, gid=2002, -+ gecos='1002', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user3', -+ dict(name='user3', passwd='*', uid=1003, gid=2003, -+ gecos='1003', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1003, -+ dict(name='user3', passwd='*', uid=1003, gid=2003, -+ gecos='1003', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user11', -+ dict(name='user11', passwd='*', uid=1011, gid=2001, -+ gecos='1011', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1011, -+ dict(name='user11', passwd='*', uid=1011, gid=2001, -+ gecos='1011', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user12', -+ dict(name='user12', passwd='*', uid=1012, gid=2002, -+ gecos='1012', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1012, -+ dict(name='user12', passwd='*', uid=1012, gid=2002, -+ gecos='1012', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user13', -+ dict(name='user13', passwd='*', uid=1013, gid=2003, -+ gecos='1013', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1013, -+ dict(name='user13', passwd='*', uid=1013, gid=2003, -+ gecos='1013', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user21', -+ dict(name='user21', passwd='*', uid=1021, gid=2001, -+ gecos='1021', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1021, -+ dict(name='user21', passwd='*', uid=1021, gid=2001, -+ gecos='1021', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user22', -+ dict(name='user22', passwd='*', uid=1022, gid=2002, -+ gecos='1022', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1022, -+ dict(name='user22', passwd='*', uid=1022, gid=2002, -+ gecos='1022', shell='/bin/bash')) -+ -+ ent.assert_passwd_by_name( -+ 'user23', -+ dict(name='user23', passwd='*', uid=1023, gid=2003, -+ gecos='1023', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1023, -+ dict(name='user23', passwd='*', uid=1023, gid=2003, -+ gecos='1023', shell='/bin/bash')) -+ -+ -+def test_getpwnam_with_mc(ldap_conn, sanity_rfc2307): -+ test_getpwnam(ldap_conn, sanity_rfc2307) -+ stop_sssd() -+ test_getpwnam(ldap_conn, sanity_rfc2307) -+ -+ -+def test_getgrnam_simple(ldap_conn, sanity_rfc2307): -+ ent.assert_group_by_name("group1", dict(name="group1", gid=2001)) -+ ent.assert_group_by_gid(2001, dict(name="group1", gid=2001)) -+ -+ ent.assert_group_by_name("group2", dict(name="group2", gid=2002)) -+ ent.assert_group_by_gid(2002, dict(name="group2", gid=2002)) -+ -+ ent.assert_group_by_name("group3", dict(name="group3", gid=2003)) -+ ent.assert_group_by_gid(2003, dict(name="group3", gid=2003)) -+ -+ ent.assert_group_by_name("group0x", dict(name="group0x", gid=2000)) -+ ent.assert_group_by_gid(2000, dict(name="group0x", gid=2000)) -+ -+ ent.assert_group_by_name("group1x", dict(name="group1x", gid=2010)) -+ ent.assert_group_by_gid(2010, dict(name="group1x", gid=2010)) -+ -+ ent.assert_group_by_name("group2x", dict(name="group2x", gid=2020)) -+ ent.assert_group_by_gid(2020, dict(name="group2x", gid=2020)) -+ -+ -+def test_getgrnam_simple_with_mc(ldap_conn, sanity_rfc2307): -+ test_getgrnam_simple(ldap_conn, sanity_rfc2307) -+ stop_sssd() -+ test_getgrnam_simple(ldap_conn, sanity_rfc2307) -+ -+ -+def test_getgrnam_membership(ldap_conn, sanity_rfc2307): -+ ent.assert_group_by_name( -+ "group1", -+ dict(mem=ent.contains_only("user1", "user11", "user21"))) -+ ent.assert_group_by_gid( -+ 2001, -+ dict(mem=ent.contains_only("user1", "user11", "user21"))) -+ -+ ent.assert_group_by_name( -+ "group2", -+ dict(mem=ent.contains_only("user2", "user12", "user22"))) -+ ent.assert_group_by_gid( -+ 2002, -+ dict(mem=ent.contains_only("user2", "user12", "user22"))) -+ -+ ent.assert_group_by_name( -+ "group3", -+ dict(mem=ent.contains_only("user3", "user13", "user23"))) -+ ent.assert_group_by_gid( -+ 2003, -+ dict(mem=ent.contains_only("user3", "user13", "user23"))) -+ -+ ent.assert_group_by_name( -+ "group0x", -+ dict(mem=ent.contains_only("user1", "user2", "user3"))) -+ ent.assert_group_by_gid( -+ 2000, -+ dict(mem=ent.contains_only("user1", "user2", "user3"))) -+ -+ ent.assert_group_by_name( -+ "group1x", -+ dict(mem=ent.contains_only("user11", "user12", "user13"))) -+ ent.assert_group_by_gid( -+ 2010, -+ dict(mem=ent.contains_only("user11", "user12", "user13"))) -+ -+ ent.assert_group_by_name( -+ "group2x", -+ dict(mem=ent.contains_only("user21", "user22", "user23"))) -+ ent.assert_group_by_gid( -+ 2020, -+ dict(mem=ent.contains_only("user21", "user22", "user23"))) -+ -+ -+def test_getgrnam_membership_with_mc(ldap_conn, sanity_rfc2307): -+ test_getgrnam_membership(ldap_conn, sanity_rfc2307) -+ stop_sssd() -+ test_getgrnam_membership(ldap_conn, sanity_rfc2307) -+ -+ -+def assert_user_gids_equal(user, expected_gids): -+ (res, errno, gids) = sssd_id.get_user_gids(user) -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user %s, %d" % (user, errno) -+ -+ assert sorted(gids) == sorted(expected_gids), \ -+ "result: %s\n expected %s" % ( -+ ", ".join(["%s" % s for s in sorted(gids)]), -+ ", ".join(["%s" % s for s in sorted(expected_gids)]) -+ ) -+ -+ -+def test_initgroups(ldap_conn, sanity_rfc2307): -+ assert_user_gids_equal('user1', [2000, 2001]) -+ assert_user_gids_equal('user2', [2000, 2002]) -+ assert_user_gids_equal('user3', [2000, 2003]) -+ -+ assert_user_gids_equal('user11', [2010, 2001]) -+ assert_user_gids_equal('user12', [2010, 2002]) -+ assert_user_gids_equal('user13', [2010, 2003]) -+ -+ assert_user_gids_equal('user21', [2020, 2001]) -+ assert_user_gids_equal('user22', [2020, 2002]) -+ assert_user_gids_equal('user23', [2020, 2003]) -+ -+ -+def test_initgroups_with_mc(ldap_conn, sanity_rfc2307): -+ test_initgroups(ldap_conn, sanity_rfc2307) -+ stop_sssd() -+ test_initgroups(ldap_conn, sanity_rfc2307) --- -2.4.3 - diff --git a/SOURCES/0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch b/SOURCES/0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch deleted file mode 100644 index ce3e241..0000000 --- a/SOURCES/0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch +++ /dev/null @@ -1,257 +0,0 @@ -From 5c5a094438ac6c81d99066ec58778cab23e0a939 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 13 Jul 2015 10:40:06 +0200 -Subject: [PATCH 44/47] NSS: Initgr memory cache should work with fq names -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We need to stored two versions of name to the initgroups memory cache. -Otherwise it could be stored many times if sssd is configured with -case_sensitive = false. It would be impossible to invalidate all -version of names after user login. As a result of this wrong user -groups could be returned from initgroups memory cache. - -Therefore we store raw name provided by glibc function -and internal sanitized fully qualified name, -which is unique for particular user. - -This patch also increase average space for initgroups -because there are also stored two quite long names in case of -fq names. - -Resolves: -https://fedorahosted.org/sssd/ticket/2712 - -Reviewed-by: Michal Židek -(cherry picked from commit dda0258705de7255e6ec54b7f9adbde83a220996) ---- - src/responder/nss/nsssrv_cmd.c | 30 +++++++++++++++++++++++++----- - src/responder/nss/nsssrv_mmap_cache.c | 32 +++++++++++++++++++++----------- - src/responder/nss/nsssrv_mmap_cache.h | 1 + - src/responder/nss/nsssrv_private.h | 2 ++ - src/util/mmap_cache.h | 7 ++++--- - 5 files changed, 53 insertions(+), 19 deletions(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index 0bfbf0eab115826ebde53b4cfcf6661f2f6328c7..aa64432d51f15ed17212b8c40eebf5c9322bc784 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -1354,6 +1354,7 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx) - } - - rawname = (const char *)body; -+ dctx->mc_name = rawname; - - DEBUG(SSSDBG_TRACE_FUNC, "Running command [%d] with input [%s].\n", - dctx->cmdctx->cmd, rawname); -@@ -3940,6 +3941,13 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, - } - - if (changed) { -+ char *fq_name = sss_tc_fqname(tmp_ctx, dom->names, dom, name); -+ if (!fq_name) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Could not create fq name\n"); -+ goto done; -+ } -+ - for (i = 0; i < gnum; i++) { - id = groups[i]; - -@@ -3951,7 +3959,7 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, - } - } - -- to_sized_string(&delete_name, name); -+ to_sized_string(&delete_name, fq_name); - ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx, - &delete_name); - if (ret != EOK && ret != ENOENT) { -@@ -3971,6 +3979,7 @@ static int fill_initgr(struct sss_packet *packet, - struct sss_domain_info *dom, - struct ldb_result *res, - struct nss_ctx *nctx, -+ const char *mc_name, - const char *name) - { - uint8_t *body; -@@ -4059,9 +4068,18 @@ static int fill_initgr(struct sss_packet *packet, - } - - if (nctx->initgr_mc_ctx) { -- to_sized_string(&rawname, name); -+ struct sized_string unique_name; -+ char *fq_name = sss_tc_fqname(packet, dom->names, dom, name); -+ if (!fq_name) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Could not create fq name\n"); -+ return ENOMEM; -+ } -+ -+ to_sized_string(&rawname, mc_name); -+ to_sized_string(&unique_name, fq_name); - ret = sss_mmap_cache_initgr_store(&nctx->initgr_mc_ctx, &rawname, -- num - skipped, gids); -+ &unique_name, num - skipped, gids); - if (ret != EOK && ret != ENOMEM) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to store user %s(%s) in mmap cache!\n", -@@ -4089,7 +4107,7 @@ static int nss_cmd_initgr_send_reply(struct nss_dom_ctx *dctx) - } - - ret = fill_initgr(cctx->creq->out, dctx->domain, dctx->res, nctx, -- dctx->rawname); -+ dctx->mc_name, cmdctx->name); - if (ret) { - return ret; - } -@@ -4137,8 +4155,10 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx) - name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive); - if (!name) return ENOMEM; - -- name = sss_reverse_replace_space(dctx, name, -+ name = sss_reverse_replace_space(cmdctx, name, - nctx->rctx->override_space); -+ /* save name so it can be used in initgr reply */ -+ cmdctx->name = name; - if (name == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sss_reverse_replace_space failed\n"); -diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c -index ab9e769b1f4d5d17a8c41429afce292298239bc5..62f4c543c628712810b6dfbc669c586c39ca609d 100644 ---- a/src/responder/nss/nsssrv_mmap_cache.c -+++ b/src/responder/nss/nsssrv_mmap_cache.c -@@ -31,8 +31,8 @@ - #define SSS_AVG_PASSWD_PAYLOAD (MC_SLOT_SIZE * 4) - /* short group name and no gids (private user group */ - #define SSS_AVG_GROUP_PAYLOAD (MC_SLOT_SIZE * 3) --/* average place for 40 supplementary groups */ --#define SSS_AVG_INITGROUP_PAYLOAD (MC_SLOT_SIZE * 4) -+/* average place for 40 supplementary groups + 2 names */ -+#define SSS_AVG_INITGROUP_PAYLOAD (MC_SLOT_SIZE * 5) - - #define MC_NEXT_BARRIER(val) ((((val) + 1) & 0x00ffffff) | 0xf0000000) - -@@ -965,6 +965,7 @@ done: - - errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - struct sized_string *name, -+ struct sized_string *unique_name, - uint32_t num_groups, - uint8_t *gids_buf) - { -@@ -973,6 +974,7 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - struct sss_mc_initgr_data *data; - size_t data_len; - size_t rec_len; -+ size_t pos; - int ret; - - if (mcc == NULL) { -@@ -980,20 +982,22 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - return EINVAL; - } - -- /* array of gids + name */ -- data_len = num_groups * sizeof(uint32_t) + name->len; -+ /* array of gids + name + unique_name */ -+ data_len = num_groups * sizeof(uint32_t) + name->len + unique_name->len; - rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data) - + data_len; - if (rec_len > mcc->dt_size) { - return ENOMEM; - } - -- ret = sss_mc_get_record(_mcc, rec_len, name, &rec); -+ /* use unique name for searching potential old records */ -+ ret = sss_mc_get_record(_mcc, rec_len, unique_name, &rec); - if (ret != EOK) { - return ret; - } - - data = (struct sss_mc_initgr_data *)rec->data; -+ pos = 0; - - MC_RAISE_BARRIER(rec); - -@@ -1001,16 +1005,22 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - * Use the first key twice. - */ - sss_mmap_set_rec_header(mcc, rec, rec_len, mcc->valid_time_slot, -- name->str, name->len, name->str, name->len); -+ name->str, name->len, -+ unique_name->str, unique_name->len); - - /* initgroups struct */ -- data->strs_len = name->len; -+ data->strs_len = name->len + unique_name->len; - data->data_len = data_len; -- data->reserved = MC_INVALID_VAL32; - data->num_groups = num_groups; -- memcpy(data->gids, gids_buf, num_groups * sizeof(uint32_t)); -- memcpy(&data->gids[num_groups], name->str, name->len); -- data->strs = data->name = MC_PTR_DIFF(&data->gids[num_groups], data); -+ memcpy((char *)data->gids + pos, gids_buf, num_groups * sizeof(uint32_t)); -+ pos += num_groups * sizeof(uint32_t); -+ -+ memcpy((char *)data->gids + pos, unique_name->str, unique_name->len); -+ data->strs = data->unique_name = MC_PTR_DIFF((char *)data->gids + pos, data); -+ pos += unique_name->len; -+ -+ memcpy((char *)data->gids + pos, name->str, name->len); -+ data->name = MC_PTR_DIFF((char *)data->gids + pos, data); - - MC_LOWER_BARRIER(rec); - -diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h -index b09e4a6f8efa364ae7a6407bab9d8a2a2143c812..b84fbc8edef69db96c17a48a4862d63942297c66 100644 ---- a/src/responder/nss/nsssrv_mmap_cache.h -+++ b/src/responder/nss/nsssrv_mmap_cache.h -@@ -53,6 +53,7 @@ errno_t sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc, - - errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc, - struct sized_string *name, -+ struct sized_string *unique_name, - uint32_t num_groups, - uint8_t *gids_buf); - -diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h -index e9f00b114975ef760aaaac45e6e91f6e40c52b9a..e5a2486f1fb9a8de39ec90f802f596b2c2f6af7f 100644 ---- a/src/responder/nss/nsssrv_private.h -+++ b/src/responder/nss/nsssrv_private.h -@@ -79,6 +79,8 @@ struct nss_dom_ctx { - - /* Service-specific */ - const char *protocol; -+ -+ const char *mc_name; - }; - - struct setent_step_ctx { -diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h -index b5917b3c0973276e43e9fe160cec7528b1224f8f..22c1ae62d1ff0c816c23bd8b26140990d692134c 100644 ---- a/src/util/mmap_cache.h -+++ b/src/util/mmap_cache.h -@@ -138,14 +138,15 @@ struct sss_mc_grp_data { - }; - - struct sss_mc_initgr_data { -- rel_ptr_t name; /* ptr to name string, rel. to struct base addr */ -+ rel_ptr_t unique_name; /* ptr to unique name string, rel. to struct base addr */ -+ rel_ptr_t name; /* ptr to raw name string, rel. to struct base addr */ - rel_ptr_t strs; /* ptr to concatenation of all strings */ -- uint32_t reserved; - uint32_t strs_len; /* length of strs */ - uint32_t data_len; /* all initgroups data len */ - uint32_t num_groups; /* number of groups */ - uint32_t gids[0]; /* array of all groups -- * string with name is stored after gids */ -+ * string with name and unique_name is stored -+ * after gids */ - }; - - #pragma pack() --- -2.4.3 - diff --git a/SOURCES/0044-test_utils-Fixing-assignment-discards-const-qualifie.patch b/SOURCES/0044-test_utils-Fixing-assignment-discards-const-qualifie.patch new file mode 100644 index 0000000..053dc43 --- /dev/null +++ b/SOURCES/0044-test_utils-Fixing-assignment-discards-const-qualifie.patch @@ -0,0 +1,37 @@ +From 2af91b3728470b9831a748d51d081b117648ae91 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 26 Jul 2016 10:37:19 +0200 +Subject: [PATCH 44/44] test_utils: Fixing assignment discards 'const' + qualifier +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Lukáš Slebodník +--- + src/tests/cmocka/test_utils.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c +index 4c72a59437105e683cec2d39c36951aeff63767b..5349accc5c6b55f7d725bfdeaf318b90289880dd 100644 +--- a/src/tests/cmocka/test_utils.c ++++ b/src/tests/cmocka/test_utils.c +@@ -1806,13 +1806,13 @@ static void test_sss_get_domain_mappings_content(void **state) + assert_non_null(c); + c->forest_root = find_domain_by_name(dom, "subdom1.dom", true); + assert_non_null(c->forest_root); +- c->forest = "subdom1.dom"; ++ c->forest = discard_const_p(char, "subdom1.dom"); + + c = find_domain_by_name(dom, "subdom3.dom", true); + assert_non_null(c); + c->forest_root = find_domain_by_name(dom, "subdom1.dom", true); + assert_non_null(c->forest_root); +- c->forest = "subdom1.dom"; ++ c->forest = discard_const_p(char, "subdom1.dom"); + + ret = sss_get_domain_mappings_content(test_ctx, dom, &content); + assert_int_equal(ret, EOK); +-- +2.4.11 + diff --git a/SOURCES/0045-IPA-make-ipa_resolve_user_list_-send-recv-public-and.patch b/SOURCES/0045-IPA-make-ipa_resolve_user_list_-send-recv-public-and.patch new file mode 100644 index 0000000..bd9f1d8 --- /dev/null +++ b/SOURCES/0045-IPA-make-ipa_resolve_user_list_-send-recv-public-and.patch @@ -0,0 +1,85 @@ +From 9812095cc83c7258584235528d355c301c492b92 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 12 Jul 2016 17:09:00 +0200 +Subject: [PATCH 45/62] IPA: make ipa_resolve_user_list_{send|recv} public and + allow AD users + +Reviewed-by: Jakub Hrozek +(cherry picked from commit f2e8a7c3230fac11175c0bd17c14c66a8e9b25ad) +--- + src/providers/ipa/ipa_id.c | 20 ++++++++++++++++---- + src/providers/ipa/ipa_id.h | 8 ++++++++ + 2 files changed, 24 insertions(+), 4 deletions(-) + +diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c +index e092cd2f80d3c102f88a9bc48a352e1a140b14e8..7cc79f92b5dcd481706353d403125c46d587e7f6 100644 +--- a/src/providers/ipa/ipa_id.c ++++ b/src/providers/ipa/ipa_id.c +@@ -71,7 +71,7 @@ struct ipa_resolve_user_list_state { + 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 * ++struct tevent_req * + ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev, + struct ipa_id_ctx *ipa_ctx, + const char *domain_name, +@@ -132,7 +132,14 @@ 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 = ipa_id_get_account_info_send(state, state->ev, state->ipa_ctx, ar); ++ if (strcasecmp(state->domain_name, ++ state->ipa_ctx->sdap_id_ctx->be->domain->name) != 0) { ++ subreq = ipa_subdomain_account_send(state, state->ev, state->ipa_ctx, ++ ar); ++ } else { ++ subreq = ipa_id_get_account_info_send(state, state->ev, state->ipa_ctx, ++ ar); ++ } + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct_req_send failed.\n"); + return ENOMEM; +@@ -151,7 +158,12 @@ static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq) + struct ipa_resolve_user_list_state); + int ret; + +- ret = ipa_id_get_account_info_recv(subreq, &state->dp_error); ++ if (strcasecmp(state->domain_name, ++ state->ipa_ctx->sdap_id_ctx->be->domain->name) != 0) { ++ ret = ipa_subdomain_account_recv(subreq, &state->dp_error); ++ } else { ++ 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); +@@ -182,7 +194,7 @@ done: + return; + } + +-static int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error) ++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); +diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h +index 17db5226a29a54485f7b26eb9853ef2380426bdf..485fa3f8e6af48ddcf1178c3486456753035c948 100644 +--- a/src/providers/ipa/ipa_id.h ++++ b/src/providers/ipa/ipa_id.h +@@ -135,4 +135,12 @@ struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx, + struct ldb_message *user_msg); + + errno_t ipa_get_subdom_acct_process_pac_recv(struct tevent_req *req); ++ ++struct tevent_req * ++ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev, ++ struct ipa_id_ctx *ipa_ctx, ++ const char *domain_name, ++ struct ldb_message_element *users); ++int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error); ++ + #endif +-- +2.4.11 + diff --git a/SOURCES/0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch b/SOURCES/0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch deleted file mode 100644 index af7a5dd..0000000 --- a/SOURCES/0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch +++ /dev/null @@ -1,187 +0,0 @@ -From b54fa4dacbb9cb225159d21976b637a78e461060 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 24 Jul 2015 15:13:01 +0200 -Subject: [PATCH 45/47] test_memory_cache: Add test for initgroups mc with fq - names -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek -(cherry picked from commit cb8c24707275c5bda7310d67e7f46c75d3ac36ea) ---- - src/tests/intg/test_memory_cache.py | 140 +++++++++++++++++++++++++++++++++++- - 1 file changed, 138 insertions(+), 2 deletions(-) - -diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py -index 5a1f07651b70a5bf1fbacceeae6825ea4341e3b5..12ce3c5054fe76560e31137d88043baf20641d3a 100644 ---- a/src/tests/intg/test_memory_cache.py -+++ b/src/tests/intg/test_memory_cache.py -@@ -106,8 +106,7 @@ def create_sssd_fixture(request): - request.addfinalizer(teardown) - - --@pytest.fixture --def sanity_rfc2307(request, ldap_conn): -+def load_data_to_ldap(request, ldap_conn): - ent_list = ldap_ent.List(LDAP_BASE_DN) - ent_list.add_user("user1", 1001, 2001) - ent_list.add_user("user2", 1002, 2002) -@@ -128,6 +127,64 @@ def sanity_rfc2307(request, ldap_conn): - ent_list.add_group("group2x", 2020, ["user21", "user22", "user23"]) - create_ldap_fixture(request, ldap_conn, ent_list) - -+ -+@pytest.fixture -+def sanity_rfc2307(request, ldap_conn): -+ load_data_to_ldap(request, ldap_conn) -+ -+ conf = unindent("""\ -+ [sssd] -+ config_file_version = 2 -+ domains = LDAP -+ services = nss -+ -+ [nss] -+ -+ [domain/LDAP] -+ ldap_auth_disable_tls_never_use_in_production = true -+ ldap_schema = rfc2307 -+ id_provider = ldap -+ auth_provider = ldap -+ sudo_provider = ldap -+ ldap_uri = {ldap_conn.ds_inst.ldap_url} -+ ldap_search_base = {ldap_conn.ds_inst.base_dn} -+ """).format(**locals()) -+ create_conf_fixture(request, conf) -+ create_sssd_fixture(request) -+ return None -+ -+ -+@pytest.fixture -+def fqname_rfc2307(request, ldap_conn): -+ load_data_to_ldap(request, ldap_conn) -+ -+ conf = unindent("""\ -+ [sssd] -+ config_file_version = 2 -+ domains = LDAP -+ services = nss -+ -+ [nss] -+ -+ [domain/LDAP] -+ ldap_auth_disable_tls_never_use_in_production = true -+ ldap_schema = rfc2307 -+ id_provider = ldap -+ auth_provider = ldap -+ sudo_provider = ldap -+ ldap_uri = {ldap_conn.ds_inst.ldap_url} -+ ldap_search_base = {ldap_conn.ds_inst.base_dn} -+ use_fully_qualified_names = true -+ """).format(**locals()) -+ create_conf_fixture(request, conf) -+ create_sssd_fixture(request) -+ return None -+ -+ -+@pytest.fixture -+def fqname_case_insensitive_rfc2307(request, ldap_conn): -+ load_data_to_ldap(request, ldap_conn) -+ - conf = unindent("""\ - [sssd] - config_file_version = 2 -@@ -144,6 +201,8 @@ def sanity_rfc2307(request, ldap_conn): - sudo_provider = ldap - ldap_uri = {ldap_conn.ds_inst.ldap_url} - ldap_search_base = {ldap_conn.ds_inst.base_dn} -+ use_fully_qualified_names = true -+ case_sensitive = false - """).format(**locals()) - create_conf_fixture(request, conf) - create_sssd_fixture(request) -@@ -345,3 +404,80 @@ def test_initgroups_with_mc(ldap_conn, sanity_rfc2307): - test_initgroups(ldap_conn, sanity_rfc2307) - stop_sssd() - test_initgroups(ldap_conn, sanity_rfc2307) -+ -+ -+def test_initgroups_fqname_with_mc(ldap_conn, fqname_rfc2307): -+ assert_user_gids_equal('user1@LDAP', [2000, 2001]) -+ stop_sssd() -+ assert_user_gids_equal('user1@LDAP', [2000, 2001]) -+ -+ -+def assert_initgroups_equal(user, primary_gid, expected_gids): -+ (res, errno, gids) = sssd_id.call_sssd_initgroups(user, primary_gid) -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user %s, %d" % (user, errno) -+ -+ assert sorted(gids) == sorted(expected_gids), \ -+ "result: %s\n expected %s" % ( -+ ", ".join(["%s" % s for s in sorted(gids)]), -+ ", ".join(["%s" % s for s in sorted(expected_gids)]) -+ ) -+ -+ -+def assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last, -+ primary_gid, expected_gids): -+ -+ assert_initgroups_equal(user1_case1, primary_gid, expected_gids) -+ assert_initgroups_equal(user1_case2, primary_gid, expected_gids) -+ assert_initgroups_equal(user1_case_last, primary_gid, expected_gids) -+ stop_sssd() -+ -+ user = user1_case1 -+ (res, errno, gids) = sssd_id.call_sssd_initgroups(user, primary_gid) -+ assert res == sssd_id.NssReturnCode.UNAVAIL, \ -+ "Initgroups for user shoudl fail user %s, %d" % (user, res) -+ -+ user = user1_case2 -+ (res, errno, gids) = sssd_id.call_sssd_initgroups(user, primary_gid) -+ assert res == sssd_id.NssReturnCode.UNAVAIL, \ -+ "Initgroups for user shoudl fail user %s, %d" % (user, res) -+ -+ # Just last invocation of initgroups shoudl PASS -+ # Otherwise, we would not be able to invalidate it -+ assert_initgroups_equal(user1_case_last, primary_gid, expected_gids) -+ -+ -+def test_initgroups_case_insensitive_with_mc1(ldap_conn, -+ fqname_case_insensitive_rfc2307): -+ user1_case1 = 'User1@LDAP' -+ user1_case2 = 'uSer1@LDAP' -+ user1_case_last = 'usEr1@LDAP' -+ primary_gid = 2001 -+ expected_gids = [2000, 2001] -+ -+ assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last, -+ primary_gid, expected_gids) -+ -+ -+def test_initgroups_case_insensitive_with_mc2(ldap_conn, -+ fqname_case_insensitive_rfc2307): -+ user1_case1 = 'usEr1@LDAP' -+ user1_case2 = 'User1@LDAP' -+ user1_case_last = 'uSer1@LDAP' -+ primary_gid = 2001 -+ expected_gids = [2000, 2001] -+ -+ assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last, -+ primary_gid, expected_gids) -+ -+ -+def test_initgroups_case_insensitive_with_mc3(ldap_conn, -+ fqname_case_insensitive_rfc2307): -+ user1_case1 = 'uSer1@LDAP' -+ user1_case2 = 'usEr1@LDAP' -+ user1_case_last = 'User1@LDAP' -+ primary_gid = 2001 -+ expected_gids = [2000, 2001] -+ -+ assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last, -+ primary_gid, expected_gids) --- -2.4.3 - diff --git a/SOURCES/0046-IPA-expand-ghost-members-of-AD-groups-in-server-mode.patch b/SOURCES/0046-IPA-expand-ghost-members-of-AD-groups-in-server-mode.patch new file mode 100644 index 0000000..9b41801 --- /dev/null +++ b/SOURCES/0046-IPA-expand-ghost-members-of-AD-groups-in-server-mode.patch @@ -0,0 +1,115 @@ +From c17e7bc80adf9741054e53dc6e8d8f6afa273e18 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 12 Jul 2016 17:09:40 +0200 +Subject: [PATCH 46/62] IPA: expand ghost members of AD groups in server-mode + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 160ba891ec483c5b7d2a3fcca5bd992fc790efe0) +--- + src/providers/ipa/ipa_subdomains_id.c | 79 ++++++++++++++++++++++++++++++++++- + 1 file changed, 78 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c +index 65bfd33765d5799037075e599049761f18466bb2..542c596a983bcb48f4eac699f78eb956326cefa2 100644 +--- a/src/providers/ipa/ipa_subdomains_id.c ++++ b/src/providers/ipa/ipa_subdomains_id.c +@@ -1201,6 +1201,67 @@ fail: + return; + } + ++static void ipa_check_ghost_members_done(struct tevent_req *subreq); ++static errno_t ipa_check_ghost_members(struct tevent_req *req) ++{ ++ struct ipa_get_ad_acct_state *state = tevent_req_data(req, ++ struct ipa_get_ad_acct_state); ++ errno_t ret; ++ struct tevent_req *subreq; ++ struct ldb_message_element *ghosts = NULL; ++ ++ ++ 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"); ++ return EOK; ++ } else if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n"); ++ return ret; ++ } ++ } ++ ++ ghosts = ldb_msg_find_element(state->obj_msg, SYSDB_GHOST); ++ ++ if (ghosts != NULL) { ++ /* Resolve ghost members */ ++ subreq = ipa_resolve_user_list_send(state, state->ev, ++ state->ipa_ctx, ++ state->obj_dom->name, ++ ghosts); ++ if (subreq == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list_send failed.\n"); ++ return ENOMEM; ++ } ++ tevent_req_set_callback(subreq, ipa_check_ghost_members_done, req); ++ return EAGAIN; ++ } ++ ++ return EOK; ++} ++ ++static void ipa_check_ghost_members_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = tevent_req_callback_data(subreq, ++ struct tevent_req); ++ int ret; ++ ++ ret = ipa_resolve_user_list_recv(subreq, NULL); ++ talloc_zfree(subreq); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list request failed [%d]\n", ++ ret); ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ tevent_req_done(req); ++ return; ++} ++ + static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req) + { + struct ipa_get_ad_acct_state *state = tevent_req_data(req, +@@ -1228,11 +1289,27 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req) + 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) { ++ && entry_type != BE_REQ_BY_SECID ++ && entry_type != BE_REQ_GROUP) { + tevent_req_done(req); + return EOK; + } + ++ /* expand ghost members, if any, to get group members with overrides ++ * right. */ ++ if (entry_type == BE_REQ_GROUP) { ++ ret = ipa_check_ghost_members(req); ++ if (ret == EOK) { ++ tevent_req_done(req); ++ return EOK; ++ } else if (ret == EAGAIN) { ++ return EOK; ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, "ipa_check_ghost_members failed.\n"); ++ return ret; ++ } ++ } ++ + /* Replace ID with name in search filter */ + if ((entry_type == BE_REQ_USER && state->ar->filter_type == BE_FILTER_IDNUM) + || (entry_type == BE_REQ_INITGROUPS +-- +2.4.11 + diff --git a/SOURCES/0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch b/SOURCES/0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch deleted file mode 100644 index e258a2f..0000000 --- a/SOURCES/0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 2d4478e11739f3934d788a9c47c8d990e41afd67 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 4 Aug 2015 11:59:35 +0200 -Subject: [PATCH 46/47] test_memory_cache: Test mmap cache after initgroups -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek ---- - src/tests/intg/test_memory_cache.py | 89 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 89 insertions(+) - -diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py -index 12ce3c5054fe76560e31137d88043baf20641d3a..c809a4b6daacfd04834db46d21bfb97ad025ada6 100644 ---- a/src/tests/intg/test_memory_cache.py -+++ b/src/tests/intg/test_memory_cache.py -@@ -19,6 +19,7 @@ - import os - import stat - import ent -+import grp - import config - import signal - import subprocess -@@ -481,3 +482,91 @@ def test_initgroups_case_insensitive_with_mc3(ldap_conn, - - assert_stored_last_initgroups(user1_case1, user1_case2, user1_case_last, - primary_gid, expected_gids) -+ -+ -+def run_simple_test_with_initgroups(): -+ ent.assert_passwd_by_name( -+ 'user1', -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1001, -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ -+ ent.assert_group_by_name( -+ "group1", -+ dict(mem=ent.contains_only("user1", "user11", "user21"))) -+ ent.assert_group_by_gid( -+ 2001, -+ dict(mem=ent.contains_only("user1", "user11", "user21"))) -+ -+ # unrelated group to user1 -+ ent.assert_group_by_name( -+ "group2", -+ dict(mem=ent.contains_only("user2", "user12", "user22"))) -+ ent.assert_group_by_gid( -+ 2002, -+ dict(mem=ent.contains_only("user2", "user12", "user22"))) -+ -+ assert_initgroups_equal("user1", 2001, [2000, 2001]) -+ -+ -+def test_invalidation_of_gids_after_initgroups(ldap_conn, sanity_rfc2307): -+ -+ # the sssd cache was empty and not all user's group were -+ # resolved with getgr{nm,gid}. Therefore there is a change in -+ # group membership => user groups should be invalidated -+ run_simple_test_with_initgroups() -+ assert_initgroups_equal("user1", 2001, [2000, 2001]) -+ -+ stop_sssd() -+ -+ ent.assert_passwd_by_name( -+ 'user1', -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1001, -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ -+ # unrelated group to user1 must be returned -+ ent.assert_group_by_name( -+ "group2", -+ dict(mem=ent.contains_only("user2", "user12", "user22"))) -+ ent.assert_group_by_gid( -+ 2002, -+ dict(mem=ent.contains_only("user2", "user12", "user22"))) -+ -+ assert_initgroups_equal("user1", 2001, [2000, 2001]) -+ -+ # user groups must be invalidated -+ for group in ["group1", "group0x"]: -+ with pytest.raises(KeyError): -+ grp.getgrnam(group) -+ -+ for gid in [2000, 2001]: -+ with pytest.raises(KeyError): -+ grp.getgrgid(gid) -+ -+ -+def test_initgroups_without_change_in_membership(ldap_conn, sanity_rfc2307): -+ -+ # the sssd cache was empty and not all user's group were -+ # resolved with getgr{nm,gid}. Therefore there is a change in -+ # group membership => user groups should be invalidated -+ run_simple_test_with_initgroups() -+ -+ # invalidate cache -+ subprocess.call(["sss_cache", "-E"]) -+ -+ # all users and groups will be just refreshed from LDAP -+ # but there will not be a change in group membership -+ # user groups should not be invlaidated -+ run_simple_test_with_initgroups() -+ -+ stop_sssd() -+ -+ # everything should be in memory cache -+ run_simple_test_with_initgroups() --- -2.4.3 - diff --git a/SOURCES/0047-sysdb-add-sysdb_get_user_members_recursively.patch b/SOURCES/0047-sysdb-add-sysdb_get_user_members_recursively.patch new file mode 100644 index 0000000..037cdd0 --- /dev/null +++ b/SOURCES/0047-sysdb-add-sysdb_get_user_members_recursively.patch @@ -0,0 +1,103 @@ +From a1e606d051c54dd603bf09adb2bd6d0d7db2663f Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 20 Jul 2016 18:42:27 +0200 +Subject: [PATCH 47/62] sysdb: add sysdb_get_user_members_recursively() + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 17bfd9f69251781140e4b2b55ffeb649d7a79e86) +--- + src/db/sysdb.h | 5 +++++ + src/db/sysdb_ops.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 66 insertions(+) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 0cc550a4c389b4a1a2b78aff760f4b5cbf94e17f..405f89e2f1ac6fabc06e77c345de8693845f9d92 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -1257,6 +1257,11 @@ errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx, + const char ***_dns, + size_t *_n); + ++errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *dom, ++ struct ldb_dn *group_dn, ++ struct ldb_result **members); ++ + errno_t sysdb_handle_original_uuid(const char *orig_name, + struct sysdb_attrs *src_attrs, + const char *src_name, +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 19d6be03ede1bcec3bc7a4ed777e326460d80591..9a8a55ed8aa69e1638d0ab6f636e43baa3d0bfea 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -4711,6 +4711,67 @@ done: + return ret; + } + ++errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *dom, ++ struct ldb_dn *group_dn, ++ struct ldb_result **members) ++{ ++ TALLOC_CTX *tmp_ctx; ++ int ret; ++ size_t count; ++ struct ldb_result *res; ++ struct ldb_dn *base_dn; ++ char *filter; ++ const char *attrs[] = SYSDB_PW_ATTRS; ++ struct ldb_message **msgs; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ base_dn = sysdb_base_dn(dom->sysdb, tmp_ctx); ++ if (base_dn == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_base_dn failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ filter = talloc_asprintf(tmp_ctx, "(&("SYSDB_UC")("SYSDB_MEMBEROF"=%s))", ++ ldb_dn_get_linearized(group_dn)); ++ if (filter == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = sysdb_search_entry(tmp_ctx, dom->sysdb, base_dn, LDB_SCOPE_SUBTREE, ++ filter, attrs, &count, &msgs); ++ ++ res = talloc_zero(tmp_ctx, struct ldb_result); ++ if (res == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ res->count = count; ++ res->msgs = talloc_steal(res, msgs); ++ ++ ret = EOK; ++ ++done: ++ if (ret == EOK) { ++ *members = talloc_steal(mem_ctx, res); ++ } else if (ret == ENOENT) { ++ DEBUG(SSSDBG_TRACE_FUNC, "No such entry\n"); ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, "Error: %d (%s)\n", ret, strerror(ret)); ++ } ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ + errno_t sysdb_handle_original_uuid(const char *orig_name, + struct sysdb_attrs *src_attrs, + const char *src_name, +-- +2.4.11 + diff --git a/SOURCES/0047-test_memory_cache-Test-invalidation-with-sss_cache.patch b/SOURCES/0047-test_memory_cache-Test-invalidation-with-sss_cache.patch deleted file mode 100644 index 9706b50..0000000 --- a/SOURCES/0047-test_memory_cache-Test-invalidation-with-sss_cache.patch +++ /dev/null @@ -1,207 +0,0 @@ -From aae797abf3bfcfda124f111d8b4e805e77bee691 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Tue, 4 Aug 2015 12:47:58 +0200 -Subject: [PATCH 47/47] test_memory_cache: Test invalidation with sss_cache -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Michal Židek ---- - src/tests/intg/test_memory_cache.py | 176 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 176 insertions(+) - -diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py -index c809a4b6daacfd04834db46d21bfb97ad025ada6..1fd577e652d278c35211b55c871797a3dee98b13 100644 ---- a/src/tests/intg/test_memory_cache.py -+++ b/src/tests/intg/test_memory_cache.py -@@ -20,6 +20,7 @@ import os - import stat - import ent - import grp -+import pwd - import config - import signal - import subprocess -@@ -570,3 +571,178 @@ def test_initgroups_without_change_in_membership(ldap_conn, sanity_rfc2307): - - # everything should be in memory cache - run_simple_test_with_initgroups() -+ -+ -+def assert_mc_records_for_user1(): -+ ent.assert_passwd_by_name( -+ 'user1', -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ ent.assert_passwd_by_uid( -+ 1001, -+ dict(name='user1', passwd='*', uid=1001, gid=2001, -+ gecos='1001', shell='/bin/bash')) -+ -+ ent.assert_group_by_name( -+ "group1", -+ dict(mem=ent.contains_only("user1", "user11", "user21"))) -+ ent.assert_group_by_gid( -+ 2001, -+ dict(mem=ent.contains_only("user1", "user11", "user21"))) -+ ent.assert_group_by_name( -+ "group0x", -+ dict(mem=ent.contains_only("user1", "user2", "user3"))) -+ ent.assert_group_by_gid( -+ 2000, -+ dict(mem=ent.contains_only("user1", "user2", "user3"))) -+ -+ assert_initgroups_equal("user1", 2001, [2000, 2001]) -+ -+ -+def assert_missing_mc_records_for_user1(): -+ with pytest.raises(KeyError): -+ pwd.getpwnam("user1") -+ with pytest.raises(KeyError): -+ pwd.getpwuid(1001) -+ -+ for gid in [2000, 2001]: -+ with pytest.raises(KeyError): -+ grp.getgrgid(gid) -+ for group in ["group0x", "group1"]: -+ with pytest.raises(KeyError): -+ grp.getgrnam(group) -+ -+ (res, err, _) = sssd_id.call_sssd_initgroups("user1", 2001) -+ assert res == sssd_id.NssReturnCode.UNAVAIL, \ -+ "Initgroups should not find anything after invalidation of mc.\n" \ -+ "User %s, errno:%d" % (user, err) -+ -+ -+def test_invalidate_user_before_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ subprocess.call(["sss_cache", "-u", "user1"]) -+ stop_sssd() -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_user_after_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ stop_sssd() -+ subprocess.call(["sss_cache", "-u", "user1"]) -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_users_before_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ subprocess.call(["sss_cache", "-U"]) -+ stop_sssd() -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_users_after_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ stop_sssd() -+ subprocess.call(["sss_cache", "-U"]) -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_group_before_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ subprocess.call(["sss_cache", "-g", "group1"]) -+ stop_sssd() -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_group_after_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ stop_sssd() -+ subprocess.call(["sss_cache", "-g", "group1"]) -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_groups_before_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ subprocess.call(["sss_cache", "-G"]) -+ stop_sssd() -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_groups_after_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ stop_sssd() -+ subprocess.call(["sss_cache", "-G"]) -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_everything_before_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ subprocess.call(["sss_cache", "-E"]) -+ stop_sssd() -+ -+ assert_missing_mc_records_for_user1() -+ -+ -+def test_invalidate_everything_after_stop(ldap_conn, sanity_rfc2307): -+ # initialize cache with full ID -+ (res, errno, _) = sssd_id.get_user_groups("user1") -+ assert res == sssd_id.NssReturnCode.SUCCESS, \ -+ "Could not find groups for user1 %s, %d" % errno -+ assert_mc_records_for_user1() -+ -+ stop_sssd() -+ subprocess.call(["sss_cache", "-E"]) -+ -+ assert_missing_mc_records_for_user1() --- -2.4.3 - diff --git a/SOURCES/0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch b/SOURCES/0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch deleted file mode 100644 index 5ffa313..0000000 --- a/SOURCES/0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 5654903a0be960a2ec5be5bfb77cc3263e11e58c Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 30 Jul 2015 16:52:42 +0200 -Subject: [PATCH 48/57] krb5 utils: add sss_krb5_realm_has_proxy() - -Reviewed-by: Alexander Bokovoy -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 1 + - src/tests/krb5_proxy_check_test_data.conf | 8 +++++ - src/tests/krb5_utils-tests.c | 17 +++++++++ - src/util/sss_krb5.c | 57 +++++++++++++++++++++++++++++++ - src/util/sss_krb5.h | 2 ++ - 5 files changed, 85 insertions(+) - create mode 100644 src/tests/krb5_proxy_check_test_data.conf - -diff --git a/Makefile.am b/Makefile.am -index 5345d90d22cd285a5268ac50a6b527645acdb351..8b64317d6dce9a1ee8614916395b9afd9f11f382 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -366,6 +366,7 @@ dist_noinst_SCRIPTS = \ - src/tests/pysss_murmur-test.py2.sh \ - src/tests/pysss_murmur-test.py3.sh \ - src/tests/python-test.py \ -+ src/tests/krb5_proxy_check_test_data.conf \ - $(NULL) - - dist_noinst_DATA = \ -diff --git a/src/tests/krb5_proxy_check_test_data.conf b/src/tests/krb5_proxy_check_test_data.conf -new file mode 100644 -index 0000000000000000000000000000000000000000..eb74dbfa47d643668688d5c789b5962698c3d17c ---- /dev/null -+++ b/src/tests/krb5_proxy_check_test_data.conf -@@ -0,0 +1,8 @@ -+[realms] -+ REALM = { -+ kdc = hello -+ } -+ -+ REALM_PROXY = { -+ kdc = https://hello -+ } -diff --git a/src/tests/krb5_utils-tests.c b/src/tests/krb5_utils-tests.c -index 650ed48592768c214156d5274e654a447be98e36..9a25b09cdc136651a7117327036dd51b8ff23606 100644 ---- a/src/tests/krb5_utils-tests.c -+++ b/src/tests/krb5_utils-tests.c -@@ -684,6 +684,22 @@ START_TEST(test_parse_krb5_map_user) - } - END_TEST - -+START_TEST(test_sss_krb5_realm_has_proxy) -+{ -+ krb5_error_code kerr; -+ long perr; -+ -+ fail_unless(sss_krb5_realm_has_proxy(NULL) == false); -+ -+ setenv("KRB5_CONFIG", "/dev/null", 1); -+ fail_unless(sss_krb5_realm_has_proxy("REALM") == false); -+ -+ setenv("KRB5_CONFIG", ABS_SRC_DIR"/src/tests/krb5_proxy_check_test_data.conf", 1); -+ fail_unless(sss_krb5_realm_has_proxy("REALM") == false); -+ fail_unless(sss_krb5_realm_has_proxy("REALM_PROXY") == true); -+} -+END_TEST -+ - Suite *krb5_utils_suite (void) - { - Suite *s = suite_create ("krb5_utils"); -@@ -723,6 +739,7 @@ Suite *krb5_utils_suite (void) - TCase *tc_krb5_helpers = tcase_create("Helper functions"); - tcase_add_test(tc_krb5_helpers, test_compare_principal_realm); - tcase_add_test(tc_krb5_helpers, test_parse_krb5_map_user); -+ tcase_add_test(tc_krb5_helpers, test_sss_krb5_realm_has_proxy); - suite_add_tcase(s, tc_krb5_helpers); - - return s; -diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c -index e5c2121da575b174c8b6a9a90835f2c97f807f37..2e128db3c9fcb0dfa88cab1ed799abd714ad8ba6 100644 ---- a/src/util/sss_krb5.c -+++ b/src/util/sss_krb5.c -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - - #include "config.h" - -@@ -1069,3 +1070,59 @@ krb5_error_code sss_krb5_kt_have_content(krb5_context context, - return 0; - #endif - } -+ -+#define KDC_PROXY_INDICATOR "https://" -+#define KDC_PROXY_INDICATOR_LEN (sizeof(KDC_PROXY_INDICATOR) - 1) -+ -+bool sss_krb5_realm_has_proxy(const char *realm) -+{ -+ krb5_context context = NULL; -+ krb5_error_code kerr; -+ struct _profile_t *profile = NULL; -+ const char *profile_path[4] = {"realms", NULL, "kdc", NULL}; -+ char **list = NULL; -+ bool res = false; -+ size_t c; -+ -+ if (realm == NULL) { -+ return false; -+ } -+ -+ kerr = krb5_init_context(&context); -+ if (kerr != 0) { -+ DEBUG(SSSDBG_OP_FAILURE, "krb5_init_context failed.\n"); -+ return false; -+ } -+ -+ kerr = krb5_get_profile(context, &profile); -+ if (kerr != 0) { -+ DEBUG(SSSDBG_OP_FAILURE, "krb5_get_profile failed.\n"); -+ goto done; -+ } -+ -+ profile_path[1] = realm; -+ -+ kerr = profile_get_values(profile, profile_path, &list); -+ if (kerr != 0) { -+ DEBUG(SSSDBG_OP_FAILURE, "profile_get_values failed.\n"); -+ goto done; -+ } -+ -+ for (c = 0; list[c] != NULL; c++) { -+ if (strncasecmp(KDC_PROXY_INDICATOR, list[c], -+ KDC_PROXY_INDICATOR_LEN) == 0) { -+ DEBUG(SSSDBG_TRACE_ALL, -+ "Found KDC Proxy indicator [%s] in [%s].\n", -+ KDC_PROXY_INDICATOR, list[c]); -+ res = true; -+ break; -+ } -+ } -+ -+done: -+ profile_free_list(list); -+ profile_release(profile); -+ krb5_free_context(context); -+ -+ return res; -+} -diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h -index 462dbbe0bda8969432c8ac2f062a0123c1f098f0..fdaeb49314764e096448f342a054dc6938f0c248 100644 ---- a/src/util/sss_krb5.h -+++ b/src/util/sss_krb5.h -@@ -189,4 +189,6 @@ sss_krb5_get_primary(TALLOC_CTX *mem_ctx, - - krb5_error_code sss_krb5_kt_have_content(krb5_context context, - krb5_keytab keytab); -+ -+bool sss_krb5_realm_has_proxy(const char *realm); - #endif /* __SSS_KRB5_H__ */ --- -2.4.3 - diff --git a/SOURCES/0048-views-properly-override-group-member-names.patch b/SOURCES/0048-views-properly-override-group-member-names.patch new file mode 100644 index 0000000..c86debf --- /dev/null +++ b/SOURCES/0048-views-properly-override-group-member-names.patch @@ -0,0 +1,455 @@ +From 11f6fcedb0ac04528dd319fcf95d1fbaa4ea8bd1 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 7 Jul 2016 18:54:02 +0200 +Subject: [PATCH 48/62] views: properly override group member names + +Resolves https://fedorahosted.org/sssd/ticket/2948 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 1594701fbdc341069e11cff9a85e7a795e52db3d) +--- + src/db/sysdb.h | 3 +- + src/db/sysdb_search.c | 99 ++++++++++++++++------------- + src/db/sysdb_views.c | 136 ++++++++++++++++++---------------------- + src/responder/nss/nsssrv_cmd.c | 7 ++- + src/tests/cmocka/test_nss_srv.c | 18 +++--- + 5 files changed, 134 insertions(+), 129 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 405f89e2f1ac6fabc06e77c345de8693845f9d92..a27552224bb40bd07c7dee4dfe35bfb7a0b4f2c3 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -572,7 +572,8 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain, + const char **req_attrs); + + errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, +- struct ldb_message *obj); ++ struct ldb_message *obj, ++ bool expect_override_dn); + + errno_t sysdb_getpwnam_with_views(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, +diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c +index e40b36c38e28992e185447497d1bf69cabc09821..cfee5784dbadd692f30d0758e7e5c3c9fb2814cb 100644 +--- a/src/db/sysdb_search.c ++++ b/src/db/sysdb_search.c +@@ -771,28 +771,33 @@ int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx, + + /* If there are views we have to check if override values must be added to + * the original object. */ +- if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) { +- if (!is_local_view(domain->view_name)) { +- el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); +- if (el != NULL && el->num_values != 0) { +- DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost " +- "entries which must be resolved before overrides can be " +- "applied.\n", +- ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); +- ret = ENOENT; ++ if (orig_obj->count == 1) { ++ if (DOM_HAS_VIEWS(domain)) { ++ if (!is_local_view(domain->view_name)) { ++ el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); ++ if (el != NULL && el->num_values != 0) { ++ DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost " ++ "entries which must be resolved before overrides can be " ++ "applied.\n", ++ ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); ++ ret = ENOENT; ++ goto done; ++ } ++ } ++ ++ ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], ++ 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; + } + } + +- ret = sysdb_add_overrides_to_object(domain, orig_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; +- } +- +- ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]); ++ /* Must be called even without views to check to ++ * SYSDB_DEFAULT_OVERRIDE_NAME */ ++ ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0], ++ DOM_HAS_VIEWS(domain)); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_add_group_member_overrides failed.\n"); +@@ -922,28 +927,33 @@ int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx, + + /* If there are views we have to check if override values must be added to + * the original object. */ +- if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) { +- if (!is_local_view(domain->view_name)) { +- el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); +- if (el != NULL && el->num_values != 0) { +- DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost " +- "entries which must be resolved before overrides can be " +- "applied.\n", +- ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); +- ret = ENOENT; ++ if (orig_obj->count == 1) { ++ if (DOM_HAS_VIEWS(domain)) { ++ if (!is_local_view(domain->view_name)) { ++ el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); ++ if (el != NULL && el->num_values != 0) { ++ DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost " ++ "entries which must be resolved before overrides can be " ++ "applied.\n", ++ ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); ++ ret = ENOENT; ++ goto done; ++ } ++ } ++ ++ ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], ++ 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; + } + } + +- ret = sysdb_add_overrides_to_object(domain, orig_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; +- } +- +- ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0]); ++ /* Must be called even without views to check to ++ * SYSDB_DEFAULT_OVERRIDE_NAME */ ++ ret = sysdb_add_group_member_overrides(domain, orig_obj->msgs[0], ++ DOM_HAS_VIEWS(domain)); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_add_group_member_overrides failed.\n"); +@@ -1157,8 +1167,8 @@ int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx, + goto done; + } + +- if (DOM_HAS_VIEWS(domain)) { +- for (c = 0; c < res->count; c++) { ++ for (c = 0; c < res->count; c++) { ++ if (DOM_HAS_VIEWS(domain)) { + 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 +@@ -1167,13 +1177,14 @@ int sysdb_enumgrent_filter_with_views(TALLOC_CTX *mem_ctx, + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_overrides_to_object failed.\n"); + goto done; + } ++ } + +- ret = sysdb_add_group_member_overrides(domain, res->msgs[c]); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "sysdb_add_group_member_overrides failed.\n"); +- goto done; +- } ++ ret = sysdb_add_group_member_overrides(domain, res->msgs[c], ++ DOM_HAS_VIEWS(domain)); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_add_group_member_overrides failed.\n"); ++ goto done; + } + } + +diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c +index 2b89e5ca41f719e1217ef3b9e0fd683656e05d42..79f513d13ba41212a6cd84e1d9e609df6acba29c 100644 +--- a/src/db/sysdb_views.c ++++ b/src/db/sysdb_views.c +@@ -1348,14 +1348,13 @@ done: + } + + errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, +- struct ldb_message *obj) ++ struct ldb_message *obj, ++ bool expect_override_dn) + { + int ret; + size_t c; +- struct ldb_message_element *members; ++ struct ldb_result *res_members; + TALLOC_CTX *tmp_ctx; +- struct ldb_dn *member_dn; +- struct ldb_result *member_obj; + struct ldb_result *override_obj; + static const char *member_attrs[] = SYSDB_PW_ATTRS; + const char *override_dn_str; +@@ -1366,12 +1365,6 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + char *val; + struct sss_domain_info *orig_dom; + +- members = ldb_msg_find_element(obj, SYSDB_MEMBER); +- if (members == NULL || members->num_values == 0) { +- DEBUG(SSSDBG_TRACE_ALL, "Group has no members.\n"); +- return EOK; +- } +- + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); +@@ -1379,38 +1372,30 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + goto done; + } + +- for (c = 0; c < members->num_values; c++) { +- member_dn = ldb_dn_from_ldb_val(tmp_ctx, domain->sysdb->ldb, +- &members->values[c]); +- if (member_dn == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_from_ldb_val failed.\n"); +- ret = ENOMEM; +- goto done; +- } ++ ret = sysdb_get_user_members_recursively(tmp_ctx, domain, obj->dn, ++ &res_members); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_get_user_members_recursively failed.\n"); ++ goto done; ++ } + +- ret = ldb_search(domain->sysdb->ldb, member_dn, &member_obj, member_dn, +- LDB_SCOPE_BASE, member_attrs, NULL); +- if (ret != LDB_SUCCESS) { +- ret = sysdb_error_to_errno(ret); +- goto done; +- } ++ for (c = 0; c < res_members->count; c++) { + +- if (member_obj->count != 1) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Base search for member object returned [%d] results.\n", +- member_obj->count); +- ret = EINVAL; +- goto done; +- } +- +- if (ldb_msg_find_attr_as_uint64(member_obj->msgs[0], ++ if (ldb_msg_find_attr_as_uint64(res_members->msgs[c], + 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 (expect_override_dn) { ++ override_dn_str = ldb_msg_find_attr_as_string(res_members->msgs[c], ++ SYSDB_OVERRIDE_DN, ++ NULL); ++ } else { ++ override_dn_str = ldb_dn_get_linearized(res_members->msgs[c]->dn); ++ } ++ + if (override_dn_str == NULL) { + if (is_local_view(domain->view_name)) { + /* LOCAL view doesn't have to have overrideDN specified. */ +@@ -1420,12 +1405,12 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + + DEBUG(SSSDBG_CRIT_FAILURE, + "Missing override DN for object [%s].\n", +- ldb_dn_get_linearized(member_obj->msgs[0]->dn)); ++ ldb_dn_get_linearized(res_members->msgs[c]->dn)); + ret = ENOENT; + goto done; + } + +- override_dn = ldb_dn_new(member_obj, domain->sysdb->ldb, ++ override_dn = ldb_dn_new(res_members, domain->sysdb->ldb, + override_dn_str); + if (override_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); +@@ -1433,22 +1418,27 @@ 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], ++ orig_name = ldb_msg_find_attr_as_string(res_members->msgs[c], + 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)); ++ ldb_dn_get_linearized(res_members->msgs[c]->dn)); + ret = EINVAL; + goto done; + } + +- memberuid = NULL; +- if (ldb_dn_compare(member_obj->msgs[0]->dn, override_dn) != 0) { ++ /* start with default view name, if it exists or use NULL */ ++ memberuid = ldb_msg_find_attr_as_string(res_members->msgs[c], ++ SYSDB_DEFAULT_OVERRIDE_NAME, ++ NULL); ++ ++ /* If there is an override object, check if the name is overridden */ ++ if (ldb_dn_compare(res_members->msgs[c]->dn, override_dn) != 0) { + DEBUG(SSSDBG_TRACE_ALL, "Checking override for object [%s].\n", +- ldb_dn_get_linearized(member_obj->msgs[0]->dn)); ++ ldb_dn_get_linearized(res_members->msgs[c]->dn)); + +- ret = ldb_search(domain->sysdb->ldb, member_obj, &override_obj, ++ ret = ldb_search(domain->sysdb->ldb, res_members, &override_obj, + override_dn, LDB_SCOPE_BASE, member_attrs, NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); +@@ -1458,43 +1448,44 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + if (override_obj->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Base search for override object returned [%d] results.\n", +- member_obj->count); ++ override_obj->count); + ret = EINVAL; + goto done; + } + + memberuid = ldb_msg_find_attr_as_string(override_obj->msgs[0], + SYSDB_NAME, +- NULL); ++ memberuid); ++ } + +- if (memberuid != NULL) { +- ret = sss_parse_internal_fqname(tmp_ctx, orig_name, +- NULL, &orig_domain); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "sss_parse_internal_fqname failed to split [%s].\n", +- orig_name); ++ /* add domain name if memberuid is a short name */ ++ if (memberuid != NULL && strchr(memberuid, '@') == NULL) { ++ ret = sss_parse_internal_fqname(tmp_ctx, orig_name, ++ NULL, &orig_domain); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sss_parse_internal_fqname failed to split [%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 = ERR_DOMAIN_NOT_FOUND; + 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 = ERR_DOMAIN_NOT_FOUND; +- goto done; +- } +- memberuid = sss_create_internal_fqname(tmp_ctx, memberuid, +- orig_dom->name); +- if (memberuid == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, +- "sss_create_internal_fqname failed.\n"); +- ret = ENOMEM; +- goto done; +- } ++ memberuid = sss_create_internal_fqname(tmp_ctx, memberuid, ++ orig_dom->name); ++ if (memberuid == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sss_create_internal_fqname failed.\n"); ++ ret = ENOMEM; ++ goto done; + } + } + } +@@ -1521,9 +1512,6 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + 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. */ +- talloc_free(member_dn); + } + + ret = EOK; +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index 1ae17969688fa29734ca14fd2b152decef1fdbca..4e84b3202cbf367e70a47a3c7edb06e357657538 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -2976,7 +2976,12 @@ static int fill_grent(struct sss_packet *packet, + + memnum = 0; + if (!dom->ignore_group_members) { +- el = sss_view_ldb_msg_find_element(dom, msg, SYSDB_MEMBERUID); ++ /* unconditionally prefer OVERRIDE_PREFIX SYSDB_MEMBERUID, it ++ * might contain override names from the default view */ ++ el = ldb_msg_find_element(msg, OVERRIDE_PREFIX SYSDB_MEMBERUID); ++ if (el == NULL) { ++ el = ldb_msg_find_element(msg, SYSDB_MEMBERUID); ++ } + if (el) { + ret = fill_members(packet, nctx->rctx, dom, nctx, el, + &rzero, &rsize, &memnum); +diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c +index 82a304feed864b09168d0f3e06a4e1bb120df7e4..41425e76f3b76fafa917f33fcfef0946f2f71c7d 100644 +--- a/src/tests/cmocka/test_nss_srv.c ++++ b/src/tests/cmocka/test_nss_srv.c +@@ -1619,11 +1619,11 @@ static int test_nss_getgrnam_check_mix_dom(uint32_t status, + tmp_ctx = talloc_new(nss_test_ctx); + assert_non_null(tmp_ctx); + +- exp_members[0] = testmember1.pw_name; +- exp_members[1] = testmember2.pw_name; +- exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, ++ exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, + nss_test_ctx->subdom, submember1.pw_name); +- assert_non_null(exp_members[2]); ++ assert_non_null(exp_members[0]); ++ exp_members[1] = testmember1.pw_name; ++ exp_members[2] = testmember2.pw_name; + + assert_int_equal(status, EOK); + +@@ -1682,14 +1682,14 @@ static int test_nss_getgrnam_check_mix_dom_fqdn(uint32_t status, + tmp_ctx = talloc_new(nss_test_ctx); + assert_non_null(tmp_ctx); + +- exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, +- nss_test_ctx->tctx->dom, testmember1.pw_name); ++ exp_members[0] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, ++ nss_test_ctx->subdom, submember1.pw_name); + assert_non_null(exp_members[0]); + exp_members[1] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, +- nss_test_ctx->tctx->dom, testmember2.pw_name); ++ nss_test_ctx->tctx->dom, testmember1.pw_name); + assert_non_null(exp_members[1]); +- exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->subdom->names, +- nss_test_ctx->subdom, submember1.pw_name); ++ exp_members[2] = sss_tc_fqname(tmp_ctx, nss_test_ctx->tctx->dom->names, ++ nss_test_ctx->tctx->dom, testmember2.pw_name); + assert_non_null(exp_members[2]); + + expected.gr_name = sss_tc_fqname(tmp_ctx, +-- +2.4.11 + diff --git a/SOURCES/0049-IPA-fix-lookup-by-UPN-for-subdomains.patch b/SOURCES/0049-IPA-fix-lookup-by-UPN-for-subdomains.patch new file mode 100644 index 0000000..abd98c4 --- /dev/null +++ b/SOURCES/0049-IPA-fix-lookup-by-UPN-for-subdomains.patch @@ -0,0 +1,61 @@ +From 196e4a16c32e2f5d7e63f2dacd4f3cf4128f6814 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 22 Jul 2016 17:35:43 +0200 +Subject: [PATCH 49/62] IPA: fix lookup by UPN for subdomains + +Currently the user name used in the extdom exop request is +unconditionally set to the short name. While this is correct for the +general name based lookups it breaks UPN/email based lookups where the +name part after the @-sign might not match to domain name. I guess this +was introduce during the sysdb refactoring. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 530458a4ef7cd8429d1db2f3dfae92d9c44e38ef) +--- + src/providers/ipa/ipa_subdomains_id.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c +index 542c596a983bcb48f4eac699f78eb956326cefa2..002857699b65c86a6ed0c912a2a7ae06a8f9e507 100644 +--- a/src/providers/ipa/ipa_subdomains_id.c ++++ b/src/providers/ipa/ipa_subdomains_id.c +@@ -344,6 +344,7 @@ struct ipa_get_subdom_acct { + int entry_type; + const char *filter; + int filter_type; ++ const char *extra_value; + bool use_pac; + struct ldb_message *user_msg; + +@@ -393,6 +394,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, + state->entry_type = (ar->entry_type & BE_REQ_TYPE_MASK); + state->filter = ar->filter_value; + state->filter_type = ar->filter_type; ++ state->extra_value = ar->extra_value; + + switch (state->entry_type) { + case BE_REQ_USER: +@@ -499,10 +501,16 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) + switch (state->filter_type) { + case BE_FILTER_NAME: + req_input->type = REQ_INP_NAME; +- /* The extdom plugin expects the shortname and domain separately */ +- ret = sss_parse_internal_fqname(req_input, state->filter, +- &shortname, NULL); +- req_input->inp.name = talloc_steal(req_input, shortname); ++ /* The extdom plugin expects the shortname and domain separately, ++ * but for UPN/email lookup we need to send the raw name */ ++ if (state->extra_value != NULL ++ && strcmp(state->extra_value, EXTRA_NAME_IS_UPN) == 0) { ++ req_input->inp.name = talloc_strdup(req_input, state->filter); ++ } else { ++ ret = sss_parse_internal_fqname(req_input, state->filter, ++ &shortname, NULL); ++ req_input->inp.name = talloc_steal(req_input, shortname); ++ } + if (req_input->inp.name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + tevent_req_error(req, ENOMEM); +-- +2.4.11 + diff --git a/SOURCES/0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch b/SOURCES/0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch deleted file mode 100644 index 86016bd..0000000 --- a/SOURCES/0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 61faa93f3ad91afdeba09d4e248d596875aa6d5a Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 31 Jul 2015 11:05:48 +0200 -Subject: [PATCH 49/57] krb5: do not create kdcinfo file if proxy configuration - exists - -Resolves https://fedorahosted.org/sssd/ticket/2652 - -Reviewed-by: Alexander Bokovoy -Reviewed-by: Jakub Hrozek ---- - src/providers/krb5/krb5_common.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c -index 81d4048b63dba98706bbef1936df7f10f79e1ae5..be6c9e3540ad470307f4edb168f0ff6cc581632f 100644 ---- a/src/providers/krb5/krb5_common.c -+++ b/src/providers/krb5/krb5_common.c -@@ -428,6 +428,13 @@ errno_t write_krb5info_file(const char *realm, const char *server, - return EINVAL; - } - -+ if (sss_krb5_realm_has_proxy(realm)) { -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ "KDC Proxy available for realm [%s], no kdcinfo file created.\n", -+ realm); -+ return EOK; -+ } -+ - if (strcmp(service, SSS_KRB5KDC_FO_SRV) == 0) { - name_tmpl = KDCINFO_TMPL; - } else if (strcmp(service, SSS_KRB5KPASSWD_FO_SRV) == 0) { --- -2.4.3 - diff --git a/SOURCES/0050-LDAP-allow-multiple-user-principals.patch b/SOURCES/0050-LDAP-allow-multiple-user-principals.patch new file mode 100644 index 0000000..de62b4a --- /dev/null +++ b/SOURCES/0050-LDAP-allow-multiple-user-principals.patch @@ -0,0 +1,70 @@ +From f1eb45c3e8a198615c6731dfe9d965ab421723e8 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 22 Jul 2016 12:19:26 +0200 +Subject: [PATCH 50/62] LDAP: allow multiple user principals + +In general a user can have multiple principals and recent IPA version +added support to defined multiple principals. With this patch SSSD does +not only store the first but all principals read by LDAP from a server. + +Resolves https://fedorahosted.org/sssd/ticket/2958 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 0d5d490fb5ec685fd8ef7a75e612e6ec7ef6bde3) +--- + src/providers/ldap/sdap_async_users.c | 32 ++++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c +index e44c045b3f8ff6aed33a42cf2919bc01aa41a243..28101a2d8a38f97d09d50a9f7e071a030b4f9719 100644 +--- a/src/providers/ldap/sdap_async_users.c ++++ b/src/providers/ldap/sdap_async_users.c +@@ -142,6 +142,7 @@ int sdap_save_user(TALLOC_CTX *memctx, + char *sid_str; + char *dom_sid_str = NULL; + struct sss_domain_info *subdomain; ++ size_t c; + + DEBUG(SSSDBG_TRACE_FUNC, "Save user\n"); + +@@ -440,20 +441,23 @@ int sdap_save_user(TALLOC_CTX *memctx, + DEBUG(SSSDBG_TRACE_FUNC, + "User principal is not available for [%s].\n", user_name); + } else { +- upn = talloc_strdup(user_attrs, (const char*) el->values[0].data); +- if (!upn) { +- ret = ENOMEM; +- goto done; +- } +- if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) { +- make_realm_upper_case(upn); +- } +- DEBUG(SSSDBG_TRACE_FUNC, +- "Adding user principal [%s] to attributes of [%s].\n", +- upn, user_name); +- ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn); +- if (ret) { +- goto done; ++ for (c = 0; c < el->num_values; c++) { ++ upn = talloc_strdup(tmpctx, (const char*) el->values[c].data); ++ if (!upn) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) { ++ make_realm_upper_case(upn); ++ } ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Adding user principal [%s] to attributes of [%s].\n", ++ upn, user_name); ++ ret = sysdb_attrs_add_string(user_attrs, SYSDB_UPN, upn); ++ if (ret) { ++ goto done; ++ } + } + } + +-- +2.4.11 + diff --git a/SOURCES/0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch b/SOURCES/0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch deleted file mode 100644 index dc90393..0000000 --- a/SOURCES/0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 860b0e5e2f34a270a5e40912fd07efbe093a29f8 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Fri, 31 Jul 2015 11:06:54 +0200 -Subject: [PATCH 50/57] krb5: assume online state if KDC proxy is configured - -If a KDC proxy is configured a request in the KRB5 provider will assume -online state even if the backend is offline without changing the state -of the backend. - -Resolves https://fedorahosted.org/sssd/ticket/2700 - -Reviewed-by: Alexander Bokovoy -Reviewed-by: Jakub Hrozek ---- - src/providers/krb5/krb5_auth.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c -index d1bf4025b052d82413d1f370a36b0b99720d6f05..da8309d0504a6815902513693343a3500f454557 100644 ---- a/src/providers/krb5/krb5_auth.c -+++ b/src/providers/krb5/krb5_auth.c -@@ -754,6 +754,12 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq) - kr->is_offline = be_is_offline(state->be_ctx); - } - -+ if (kr->is_offline -+ && sss_krb5_realm_has_proxy(dp_opt_get_cstring(kr->krb5_ctx->opts, -+ KRB5_REALM))) { -+ kr->is_offline = false; -+ } -+ - subreq = handle_child_send(state, state->ev, kr); - if (subreq == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "handle_child_send failed.\n"); --- -2.4.3 - diff --git a/SOURCES/0051-LDAP-new-attribute-option-ldap_user_email.patch b/SOURCES/0051-LDAP-new-attribute-option-ldap_user_email.patch new file mode 100644 index 0000000..85b5898 --- /dev/null +++ b/SOURCES/0051-LDAP-new-attribute-option-ldap_user_email.patch @@ -0,0 +1,171 @@ +From 03d7bda082c8719bfb4ea63c9126442c98a27be1 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Sat, 18 Jun 2016 18:24:50 +0200 +Subject: [PATCH 51/62] LDAP: new attribute option ldap_user_email + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 83a796ec8de4bde65b11cc8032675406950641fa) +--- + 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 | 13 +++++++++++++ + src/providers/ad/ad_opts.c | 1 + + src/providers/ipa/ipa_opts.c | 1 + + src/providers/ldap/ldap_opts.c | 3 +++ + src/providers/ldap/sdap.h | 1 + + 10 files changed, 24 insertions(+) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index b5e078d0118a15c10b43fbe050176943ec90e0ee..7856c4c6b2d675b7f7f0f5f2048086044e8fb5ea 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -325,6 +325,7 @@ option_strings = { + 'ldap_user_ssh_public_key' : _('SSH public key attribute'), + 'ldap_user_auth_type' : _('attribute listing allowed authentication types for a user'), + 'ldap_user_certificate' : _('attribute containing the X509 certificate of the user'), ++ 'ldap_user_email' : _('attribute containing the email address of the user'), + + 'ldap_user_extra_attrs' : _('A list of extra attributes to download along with the user entry'), + +diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf +index 23006d26ca6fe7ca2b912ef091b4c73d5d23bee1..87a74f4af0770874c71baaea02d2313721db78bf 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_pwd_attribute = str, None, false + ldap_user_ssh_public_key = str, None, false + ldap_user_auth_type = str, None, false + ldap_user_certificate = str, None, false ++ldap_user_email = str, None, false + ldap_group_search_base = str, None, false + ldap_group_search_scope = str, None, false + ldap_group_search_filter = 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 67a46102b4e8dfff2b44b21ac18c0ad8822d7f3a..88da36ef4a0a067530dfd44b7a231f4f74c800f2 100644 +--- a/src/config/etc/sssd.api.d/sssd-ipa.conf ++++ b/src/config/etc/sssd.api.d/sssd-ipa.conf +@@ -92,6 +92,7 @@ ldap_pwd_attribute = str, None, false + ldap_user_ssh_public_key = str, None, false + ldap_user_auth_type = str, None, false + ldap_user_certificate = str, None, false ++ldap_user_email = str, None, false + ldap_group_search_base = str, None, false + ldap_group_search_scope = str, None, false + ldap_group_search_filter = 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 8b52f268af195bc68d45389cda52a0ad0aba1aa3..c2ad3463d26cd73b8146604c8060224449421fe6 100644 +--- a/src/config/etc/sssd.api.d/sssd-ldap.conf ++++ b/src/config/etc/sssd.api.d/sssd-ldap.conf +@@ -86,6 +86,7 @@ ldap_user_nds_login_allowed_time_map = str, None, false + ldap_user_ssh_public_key = str, None, false + ldap_user_auth_type = str, None, false + ldap_user_certificate = str, None, false ++ldap_user_email = str, None, false + ldap_group_search_base = str, None, false + ldap_group_search_scope = str, None, false + ldap_group_search_filter = str, None, false +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index a27552224bb40bd07c7dee4dfe35bfb7a0b4f2c3..f3952f8a56f1c9f26f2167b64abdf3e9794af17e 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -139,6 +139,7 @@ + + #define SYSDB_AUTH_TYPE "authType" + #define SYSDB_USER_CERT "userCertificate" ++#define SYSDB_USER_EMAIL "mail" + + #define SYSDB_SUBDOMAIN_REALM "realmName" + #define SYSDB_SUBDOMAIN_FLAT "flatName" +diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml +index ce2051d9d3c7df51e26e54abf49e8a20bf5ba3d3..6009dd8dfa787874c085c293b2d1f8aac6d95714 100644 +--- a/src/man/sssd-ldap.5.xml ++++ b/src/man/sssd-ldap.5.xml +@@ -828,6 +828,19 @@ + + + ++ ldap_user_email (string) ++ ++ ++ Name of the LDAP attribute containing the email ++ address of the user. ++ ++ ++ Default: mail ++ ++ ++ ++ ++ + ldap_group_object_class (string) + + +diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c +index 57dfcca6b998083c7cf9ac0bcb142ff7736cc8b9..829f9d9556bc3fa74a95eb76db0e31b19befe8fe 100644 +--- a/src/providers/ad/ad_opts.c ++++ b/src/providers/ad/ad_opts.c +@@ -218,6 +218,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = { + { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL }, + { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", "userCertificate;binary", SYSDB_USER_CERT, NULL }, ++ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c +index a0c318a511693d884f03f0372c592d633ebdcbae..cd3fe9ae4302ff4837a500b9a0c834dadb11f87d 100644 +--- a/src/providers/ipa/ipa_opts.c ++++ b/src/providers/ipa/ipa_opts.c +@@ -204,6 +204,7 @@ struct sdap_attr_map ipa_user_map[] = { + { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL }, + { "ldap_user_auth_type", "ipaUserAuthType", SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", "userCertificate;binary", SYSDB_USER_CERT, NULL }, ++ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c +index 524579d4fcd478f20678bebf2c3ce18f61ed0cb9..c6efe332f53c04f3cdc80875d5ca339ad90cb7ee 100644 +--- a/src/providers/ldap/ldap_opts.c ++++ b/src/providers/ldap/ldap_opts.c +@@ -180,6 +180,7 @@ struct sdap_attr_map rfc2307_user_map[] = { + { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL }, + { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL }, ++ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +@@ -237,6 +238,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = { + { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL }, + { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL }, ++ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +@@ -294,6 +296,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = { + { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL }, + { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL }, + { "ldap_user_certificate", NULL, SYSDB_USER_CERT, NULL }, ++ { "ldap_user_email", "mail", SYSDB_USER_EMAIL, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index 81da1144c657cb71ac860bbe82127a18759e0439..e3cb8464ff40538e1e7f1ba853ed71d9a5cc3c98 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -284,6 +284,7 @@ enum sdap_user_attrs { + SDAP_AT_USER_SSH_PUBLIC_KEY, + SDAP_AT_USER_AUTH_TYPE, + SDAP_AT_USER_CERT, ++ SDAP_AT_USER_EMAIL, + + SDAP_OPTS_USER /* attrs counter */ + }; +-- +2.4.11 + diff --git a/SOURCES/0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch b/SOURCES/0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch deleted file mode 100644 index 78a6176..0000000 --- a/SOURCES/0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch +++ /dev/null @@ -1,88 +0,0 @@ -From a09b3853da819cc773c0098100f9dd96af08f933 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Mon, 10 Aug 2015 10:16:58 +0200 -Subject: [PATCH 51/57] sss_cache: Wait a while for invalidation of mc by nss - responder -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The sss_cache cannot invalidate memory cache directly -because the nss responder owns file locks to memory caches. -Therefore sss_cache just "tell" nss responder to invalidate -memory cache. - -However there might be short interval between calling -the utility sss_cache and stopping sssd. So nss responder -needn't be so fast and therefore memory cache needn't be invalidated. - -Resolves: -https://fedorahosted.org/sssd/ticket/2748 - -Reviewed-by: Michal Židek ---- - src/tools/tools_mc_util.c | 34 ++++++++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - -diff --git a/src/tools/tools_mc_util.c b/src/tools/tools_mc_util.c -index c1b5c616d0e6d50147ecd81308aaa1e69304af92..65c461093e859d4da73761782a3a694bf5bda8fb 100644 ---- a/src/tools/tools_mc_util.c -+++ b/src/tools/tools_mc_util.c -@@ -21,6 +21,7 @@ - - #include - #include -+#include - - #include "db/sysdb.h" - #include "util/util.h" -@@ -161,6 +162,33 @@ static int clear_fastcache(bool *sssd_nss_is_off) - return EOK; - } - -+static errno_t wait_till_nss_responder_invalidate_cache(void) -+{ -+ struct stat stat_buf = { 0 }; -+ const time_t max_wait = 1000000; /* 1 second */ -+ const time_t step_time = 5000; /* 5 miliseconds */ -+ const size_t steps_count = max_wait / step_time; -+ int ret; -+ -+ for (size_t i = 0; i < steps_count; ++i) { -+ ret = stat(SSS_NSS_MCACHE_DIR "/" CLEAR_MC_FLAG, &stat_buf); -+ if (ret == -1) { -+ ret = errno; -+ if (ret == ENOENT) { -+ /* nss responder has already invalidated memory caches */ -+ return EOK; -+ } -+ -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "stat failed: %s (%d)\n", sss_strerror(ret), ret); -+ } -+ -+ usleep(step_time); -+ } -+ -+ return EAGAIN; -+} -+ - errno_t sss_memcache_clear_all(void) - { - errno_t ret; -@@ -196,6 +224,12 @@ errno_t sss_memcache_clear_all(void) - "Failed to send SIGHUP to monitor.\n"); - return EIO; - } -+ -+ ret = wait_till_nss_responder_invalidate_cache(); -+ if (ret != EOK) { -+ ERROR("The fast memory caches was not invalidated by NSS " -+ "responder.\n"); -+ } - } - - return EOK; --- -2.4.3 - diff --git a/SOURCES/0052-IFP-use-default-limit-if-provided-is-0.patch b/SOURCES/0052-IFP-use-default-limit-if-provided-is-0.patch deleted file mode 100644 index 3c45595..0000000 --- a/SOURCES/0052-IFP-use-default-limit-if-provided-is-0.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 504604a3e90c8bad36d1919e13e0bf37f094ee2a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Thu, 13 Aug 2015 12:46:59 +0200 -Subject: [PATCH 52/57] IFP: use default limit if provided is 0 - -Returning zero values doesn't make any sense, so we may use it as -"use sssd configuration instead". - -Reviewed-by: Petr Cech ---- - src/responder/ifp/ifpsrv_util.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c -index 3b02fd06f5227e4ffc3d40ffb20fed981c5028a7..904c4f62ec5653a534877fd6870832128720b694 100644 ---- a/src/responder/ifp/ifpsrv_util.c -+++ b/src/responder/ifp/ifpsrv_util.c -@@ -274,7 +274,9 @@ ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr) - - static uint32_t ifp_list_limit(struct ifp_ctx *ctx, uint32_t limit) - { -- if (ctx->wildcard_limit) { -+ if (limit == 0) { -+ return ctx->wildcard_limit; -+ } else if (ctx->wildcard_limit) { - return MIN(ctx->wildcard_limit, limit); - } else { - return limit; --- -2.4.3 - diff --git a/SOURCES/0052-sysdb-include-email-in-UPN-searches.patch b/SOURCES/0052-sysdb-include-email-in-UPN-searches.patch new file mode 100644 index 0000000..4dd7f04 --- /dev/null +++ b/SOURCES/0052-sysdb-include-email-in-UPN-searches.patch @@ -0,0 +1,57 @@ +From 2e9ea4e5c12c0d50509904415beda6b841b91f65 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 20 Jun 2016 12:57:43 +0200 +Subject: [PATCH 52/62] sysdb: include email in UPN searches + +Email addresses and Kerberos user principals names (UPNs) do not only +look similar they also can be used to identify a user uniquely. + +In future this approach should be replace by a more generic one where +the attributes which can uniquely identifies a user can be configured to +support even a wider range of login names. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 78677495a7762469002b0976809fa20ac2196f42) +--- + src/db/sysdb.h | 2 +- + src/db/sysdb_ops.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index f3952f8a56f1c9f26f2167b64abdf3e9794af17e..c2f58ccb97c37d93391e72ee2d77835283a6c12f 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -185,7 +185,7 @@ + #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_PWUPN_FILTER "(&("SYSDB_UC")(|("SYSDB_UPN"=%s)("SYSDB_CANONICAL_UPN"=%s)))" ++#define SYSDB_PWUPN_FILTER "(&("SYSDB_UC")(|("SYSDB_UPN"=%s)("SYSDB_CANONICAL_UPN"=%s)("SYSDB_USER_EMAIL"=%s)))" + #define SYSDB_PWENT_FILTER "("SYSDB_UC")" + + #define SYSDB_GRNAM_FILTER "(&("SYSDB_GC")(|("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME_ALIAS"=%s)("SYSDB_NAME"=%s)))" +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 9a8a55ed8aa69e1638d0ab6f636e43baa3d0bfea..ed177d1730723a61e01167a75a0baca6d81252f8 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -537,7 +537,7 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx, + struct ldb_dn *base_dn; + int ret; + const char *def_attrs[] = { SYSDB_NAME, SYSDB_UPN, SYSDB_CANONICAL_UPN, +- NULL }; ++ SYSDB_USER_EMAIL, NULL }; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { +@@ -553,7 +553,7 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx, + + ret = ldb_search(domain->sysdb->ldb, tmp_ctx, &res, + base_dn, LDB_SCOPE_SUBTREE, attrs ? attrs : def_attrs, +- SYSDB_PWUPN_FILTER, upn, upn); ++ SYSDB_PWUPN_FILTER, upn, upn, upn); + if (ret != EOK) { + ret = sysdb_error_to_errno(ret); + goto done; +-- +2.4.11 + diff --git a/SOURCES/0053-LDAP-include-email-in-UPN-searches.patch b/SOURCES/0053-LDAP-include-email-in-UPN-searches.patch new file mode 100644 index 0000000..878b42a --- /dev/null +++ b/SOURCES/0053-LDAP-include-email-in-UPN-searches.patch @@ -0,0 +1,115 @@ +From c333512b85f979ae0694055a36d8dafcf4105248 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 20 Jun 2016 12:58:16 +0200 +Subject: [PATCH 53/62] LDAP: include email in UPN searches + +Reviewed-by: Jakub Hrozek +(cherry picked from commit ba9ebfc49ab3bacb96213c8620411128c09f39da) +--- + src/providers/ldap/ldap_id.c | 18 +++++++++++++---- + src/providers/ldap/sdap_async_initgroups.c | 32 ++++++++++++++++++++++++------ + 2 files changed, 40 insertions(+), 10 deletions(-) + +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index 0106a7b965b8d7debbefe82f60088df9ef8c608b..5b303ddbd46fd44646cdd50856c784640426ee25 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -127,12 +127,22 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, + break; + case BE_FILTER_NAME: + if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) { +- attr_name = ctx->opts->user_map[SDAP_AT_USER_PRINC].name; +- + ret = sss_filter_sanitize(state, filter_value, &clean_value); + if (ret != EOK) { + goto done; + } ++ /* TODO: Do we have to check the attribute names more carefully? */ ++ user_filter = talloc_asprintf(state, "(|(%s=%s)(%s=%s))", ++ ctx->opts->user_map[SDAP_AT_USER_PRINC].name, ++ clean_value, ++ ctx->opts->user_map[SDAP_AT_USER_EMAIL].name, ++ clean_value); ++ talloc_zfree(clean_value); ++ if (user_filter == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } + } else { + attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name; + +@@ -242,8 +252,8 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, + goto done; + } + +- if (attr_name == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name.\n"); ++ if (attr_name == NULL && user_filter == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name or filter.\n"); + ret = EINVAL; + goto done; + } +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 17593f0a268813662d6c7fbf658b1eb4599ce3c3..0a42b18662a8fe12cf048aadfef257b5d9cb48a3 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2736,13 +2736,25 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + break; + case BE_FILTER_NAME: + if (extra_value && strcmp(extra_value, EXTRA_NAME_IS_UPN) == 0) { +- search_attr = state->opts->user_map[SDAP_AT_USER_PRINC].name; + + ret = sss_filter_sanitize(state, state->filter_value, &clean_name); + if (ret != EOK) { + talloc_zfree(req); + return NULL; + } ++ ++ state->user_base_filter = ++ talloc_asprintf(state, ++ "(&(|(%s=%s)(%s=%s))(objectclass=%s)", ++ state->opts->user_map[SDAP_AT_USER_PRINC].name, ++ clean_name, ++ state->opts->user_map[SDAP_AT_USER_EMAIL].name, ++ clean_name, ++ state->opts->user_map[SDAP_OC_USER].name); ++ if (state->user_base_filter == NULL) { ++ talloc_zfree(req); ++ return NULL; ++ } + } else { + search_attr = state->opts->user_map[SDAP_AT_USER_NAME].name; + +@@ -2766,15 +2778,23 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + return NULL; + } + +- state->user_base_filter = +- talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)", +- search_attr, clean_name, +- state->opts->user_map[SDAP_OC_USER].name); +- if (!state->user_base_filter) { ++ if (search_attr == NULL && state->user_base_filter == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Missing search attribute name or filter.\n"); + talloc_zfree(req); + return NULL; + } + ++ if (state->user_base_filter == NULL) { ++ state->user_base_filter = ++ talloc_asprintf(state, "(&(%s=%s)(objectclass=%s)", ++ search_attr, clean_name, ++ state->opts->user_map[SDAP_OC_USER].name); ++ if (!state->user_base_filter) { ++ talloc_zfree(req); ++ return NULL; ++ } ++ } ++ + if (use_id_mapping) { + /* 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 +-- +2.4.11 + diff --git a/SOURCES/0053-sudo-use-higher-value-wins-when-ordering-rules.patch b/SOURCES/0053-sudo-use-higher-value-wins-when-ordering-rules.patch deleted file mode 100644 index b28cdf5..0000000 --- a/SOURCES/0053-sudo-use-higher-value-wins-when-ordering-rules.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 7c3fefc9c840fd0eb46048d7d2be0a0b8347f713 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 29 Jul 2015 14:51:30 +0200 -Subject: [PATCH 53/57] sudo: use "higher value wins" when ordering rules - -This commit changes the default ordering logic (lower value wins) to -a correct one that is used by native ldap support. It also adds a new -option sudo_inverse_order to switch to the original SSSD (incorrect) -behaviour if needed. - -Resolves: -https://fedorahosted.org/sssd/ticket/2682 - -Reviewed-by: Jakub Hrozek ---- - src/confdb/confdb.h | 2 ++ - src/config/SSSDConfig/__init__.py.in | 1 + - src/config/etc/sssd.api.conf | 1 + - src/responder/sudo/sudosrv.c | 11 ++++++ - src/responder/sudo/sudosrv_get_sudorules.c | 54 ++++++++++++++++++++++++------ - src/responder/sudo/sudosrv_private.h | 1 + - 6 files changed, 60 insertions(+), 10 deletions(-) - -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index df454337ab4d89c5857e73ee0e5392c2b4bba8b4..9aa264899e789f2491b9873daf44bb55aff1c95d 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -124,6 +124,8 @@ - #define CONFDB_DEFAULT_SUDO_CACHE_TIMEOUT 180 - #define CONFDB_SUDO_TIMED "sudo_timed" - #define CONFDB_DEFAULT_SUDO_TIMED false -+#define CONFDB_SUDO_INVERSE_ORDER "sudo_inverse_order" -+#define CONFDB_DEFAULT_SUDO_INVERSE_ORDER false - - /* autofs */ - #define CONFDB_AUTOFS_CONF_ENTRY "config/autofs" -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index 7d361026c09ce8fd8d6a69f6bb3f3817bc3d68ba..fed2682f121103cefa27e689b29ce29b7d28f968 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -92,6 +92,7 @@ option_strings = { - - # [sudo] - 'sudo_timed' : _('Whether to evaluate the time-based attributes in sudo rules'), -+ 'sudo_inverse_order' : _('If true, SSSD will switch back to lower-wins ordering logic'), - - # [autofs] - 'autofs_negative_timeout' : _('Negative cache timeout length (seconds)'), -diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf -index cf6ce63012176d49f757afbc8a343b24aef869e8..2e5b02e3e30c13f805e172eab481f7501f57bb05 100644 ---- a/src/config/etc/sssd.api.conf -+++ b/src/config/etc/sssd.api.conf -@@ -63,6 +63,7 @@ pam_account_expired_message = str, None, false - [sudo] - # sudo service - sudo_timed = bool, None, false -+sudo_inverse_order = bool, None, false - - [autofs] - # autofs service -diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c -index 2499586eb11e49f8652ce62e53c88d7a2e54fb32..ff5d92e7005db9f6e883c78cf1a6218e9a150e0a 100644 ---- a/src/responder/sudo/sudosrv.c -+++ b/src/responder/sudo/sudosrv.c -@@ -167,6 +167,17 @@ int sudo_process_init(TALLOC_CTX *mem_ctx, - goto fail; - } - -+ /* Get sudo_inverse_order option */ -+ ret = confdb_get_bool(sudo_ctx->rctx->cdb, -+ CONFDB_SUDO_CONF_ENTRY, CONFDB_SUDO_INVERSE_ORDER, -+ CONFDB_DEFAULT_SUDO_INVERSE_ORDER, -+ &sudo_ctx->inverse_order); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) [%s]\n", -+ ret, strerror(ret)); -+ goto fail; -+ } -+ - ret = schedule_get_domains_task(rctx, rctx->ev, rctx, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "schedule_get_domains_tasks failed.\n"); -diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c -index 34d63bd74741c3cab5168fd0b0108cb05528d218..a0b09e69b71f963c353c9c6331c0708cc364924c 100644 ---- a/src/responder/sudo/sudosrv_get_sudorules.c -+++ b/src/responder/sudo/sudosrv_get_sudorules.c -@@ -325,6 +325,7 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx, - const char *username, - uid_t uid, - char **groupnames, -+ bool inverse_order, - struct sysdb_attrs ***_rules, - uint32_t *_count); - -@@ -386,6 +387,7 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx) - cmd_ctx->domain, attrs, flags, - cmd_ctx->orig_username, - cmd_ctx->uid, groupnames, -+ cmd_ctx->sudo_ctx->inverse_order, - &expired_rules, &expired_rules_num); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve expired sudo rules " -@@ -597,6 +599,7 @@ static errno_t sudosrv_get_sudorules_from_cache(TALLOC_CTX *mem_ctx, - cmd_ctx->domain, attrs, flags, - cmd_ctx->orig_username, - cmd_ctx->uid, groupnames, -+ cmd_ctx->sudo_ctx->inverse_order, - &rules, &num_rules); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, -@@ -622,7 +625,7 @@ done: - } - - static errno_t --sort_sudo_rules(struct sysdb_attrs **rules, size_t count); -+sort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool higher_wins); - - static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, -@@ -631,6 +634,7 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx, - const char *username, - uid_t uid, - char **groupnames, -+ bool inverse_order, - struct sysdb_attrs ***_rules, - uint32_t *_count) - { -@@ -680,7 +684,7 @@ static errno_t sudosrv_get_sudorules_query_cache(TALLOC_CTX *mem_ctx, - goto done; - } - -- ret = sort_sudo_rules(rules, count); -+ ret = sort_sudo_rules(rules, count, inverse_order); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Could not sort rules by sudoOrder\n"); -@@ -697,7 +701,7 @@ done: - } - - static int --sudo_order_cmp_fn(const void *a, const void *b) -+sudo_order_cmp(const void *a, const void *b, bool lower_wins) - { - struct sysdb_attrs *r1, *r2; - uint32_t o1, o2; -@@ -730,19 +734,49 @@ sudo_order_cmp_fn(const void *a, const void *b) - return 0; - } - -- if (o1 > o2) { -- return 1; -- } else if (o1 < o2) { -- return -1; -+ if (lower_wins) { -+ /* The lowest value takes priority. Original wrong SSSD behaviour. */ -+ if (o1 > o2) { -+ return 1; -+ } else if (o1 < o2) { -+ return -1; -+ } -+ } else { -+ /* The higher value takes priority. Standard LDAP behaviour. */ -+ if (o1 < o2) { -+ return 1; -+ } else if (o1 > o2) { -+ return -1; -+ } - } - - return 0; - } - -+static int -+sudo_order_low_cmp_fn(const void *a, const void *b) -+{ -+ return sudo_order_cmp(a, b, true); -+} -+ -+static int -+sudo_order_high_cmp_fn(const void *a, const void *b) -+{ -+ return sudo_order_cmp(a, b, false); -+} -+ - static errno_t --sort_sudo_rules(struct sysdb_attrs **rules, size_t count) -+sort_sudo_rules(struct sysdb_attrs **rules, size_t count, bool lower_wins) - { -- qsort(rules, count, sizeof(struct sysdb_attrs *), -- sudo_order_cmp_fn); -+ if (lower_wins) { -+ DEBUG(SSSDBG_TRACE_FUNC, "Sorting rules with lower-wins logic\n"); -+ qsort(rules, count, sizeof(struct sysdb_attrs *), -+ sudo_order_low_cmp_fn); -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, "Sorting rules with higher-wins logic\n"); -+ qsort(rules, count, sizeof(struct sysdb_attrs *), -+ sudo_order_high_cmp_fn); -+ } -+ - return EOK; - } -diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h -index 3c53755f9e8ec56f3dea52021d14b50f715a54e7..186ed2cb5114d00524b41b801b5f32bac50f7153 100644 ---- a/src/responder/sudo/sudosrv_private.h -+++ b/src/responder/sudo/sudosrv_private.h -@@ -50,6 +50,7 @@ struct sudo_ctx { - * options - */ - bool timed; -+ bool inverse_order; - }; - - struct sudo_cmd_ctx { --- -2.4.3 - diff --git a/SOURCES/0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch b/SOURCES/0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch deleted file mode 100644 index 6c277fd..0000000 --- a/SOURCES/0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 1d42e3c3a4f9536ee3539683a810c95314fd1c5d Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 10 Aug 2015 12:40:30 +0200 -Subject: [PATCH 54/57] LDAP: use ldb_binary_encode when printing attribute - values -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina ---- - src/providers/ldap/sdap_utils.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c -index f5ce8ee54f60a6c4c4cdbd5e50b20d973c175e83..9da46ea70bf80e7f4d12fdfc7d1c97e99de8d000 100644 ---- a/src/providers/ldap/sdap_utils.c -+++ b/src/providers/ldap/sdap_utils.c -@@ -35,6 +35,7 @@ sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs, - const char *objname = name ?: "object"; - const char *desc = attr_desc ?: attr_name; - unsigned int num_values, i; -+ char *printable; - - ret = sysdb_attrs_get_el(ldap_attrs, attr_name, &el); - if (ret) { -@@ -50,8 +51,16 @@ sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs, - } else { - num_values = multivalued ? el->num_values : 1; - for (i = 0; i < num_values; i++) { -+ printable = ldb_binary_encode(ldap_attrs, el->values[i]); -+ if (printable == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "ldb_binary_encode failed..\n"); -+ continue; -+ } -+ - DEBUG(SSSDBG_TRACE_INTERNAL, "Adding %s [%s] to attributes " -- "of [%s].\n", desc, el->values[i].data, objname); -+ "of [%s].\n", desc, printable, objname); -+ -+ talloc_zfree(printable); - - ret = sysdb_attrs_add_mem(attrs, attr_name, el->values[i].data, - el->values[i].length); --- -2.4.3 - diff --git a/SOURCES/0054-NSS-add-user-email-to-fill_orig.patch b/SOURCES/0054-NSS-add-user-email-to-fill_orig.patch new file mode 100644 index 0000000..b748512 --- /dev/null +++ b/SOURCES/0054-NSS-add-user-email-to-fill_orig.patch @@ -0,0 +1,50 @@ +From ac8bc2cbea5081f1f0a9395fbaf76616fe5b6fb9 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 20 Jun 2016 13:37:56 +0200 +Subject: [PATCH 54/62] NSS: add user email to fill_orig() + +The IPA server must send the email address of a user to the clients to +allow login by email. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 91767924bdf9b5a28e8902206a40348d6c83a139) +--- + src/db/sysdb.h | 1 + + src/responder/nss/nsssrv_cmd.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index c2f58ccb97c37d93391e72ee2d77835283a6c12f..8713efa6e8fcc6fb620340fe152989a5dae58434 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -220,6 +220,7 @@ + SYSDB_SID_STR, \ + SYSDB_UPN, \ + SYSDB_USER_CERT, \ ++ SYSDB_USER_EMAIL, \ + SYSDB_OVERRIDE_DN, \ + SYSDB_OVERRIDE_OBJECT_DN, \ + SYSDB_DEFAULT_OVERRIDE_NAME, \ +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index 4e84b3202cbf367e70a47a3c7edb06e357657538..77e540d8da969614e4ab40c62e6ae1f271962f31 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -4421,6 +4421,7 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx) + SYSDB_AD_USER_ACCOUNT_CONTROL, + SYSDB_SSH_PUBKEY, + SYSDB_USER_CERT, ++ SYSDB_USER_EMAIL, + SYSDB_ORIG_DN, + SYSDB_ORIG_MEMBEROF, + SYSDB_DEFAULT_ATTRS, NULL}; +@@ -4977,6 +4978,7 @@ static errno_t fill_orig(struct sss_packet *packet, + SYSDB_AD_USER_ACCOUNT_CONTROL, + SYSDB_SSH_PUBKEY, + SYSDB_USER_CERT, ++ SYSDB_USER_EMAIL, + SYSDB_ORIG_DN, + SYSDB_ORIG_MEMBEROF, + NULL}; +-- +2.4.11 + diff --git a/SOURCES/0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch b/SOURCES/0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch deleted file mode 100644 index 14f2998..0000000 --- a/SOURCES/0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 4d400c7374e0ca6af7c8f990e27c1e58a18ad7d4 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 10 Aug 2015 12:40:39 +0200 -Subject: [PATCH 55/57] IPA: Change the default of ldap_user_certificate to - userCertificate;binary -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is safe from ldb point of view, because ldb gurantees the data is -NULL-terminated. We must be careful before we save the data, though. - -Resolves: -https://fedorahosted.org/sssd/ticket/2742 - -Reviewed-by: Pavel Březina ---- - src/man/sssd-ldap.5.xml | 2 +- - src/providers/ipa/ipa_opts.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml -index 9ac175f8d4a8aa01ca2434b800ebae1be88575f5..49e84560f825b1bff255c1ad131487ba3243300d 100644 ---- a/src/man/sssd-ldap.5.xml -+++ b/src/man/sssd-ldap.5.xml -@@ -821,7 +821,7 @@ - certificate of the user. - - -- Default: no set in the general case, userCertificate -+ Default: no set in the general case, userCertificate;binary - for IPA - - -diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h -index 9576228d1bf3424c8867bda058b59c3ca6b2216b..f6c40dddbb58cd8af1079a351137422083e26cfe 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -204,7 +204,7 @@ struct sdap_attr_map ipa_user_map[] = { - { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL }, - { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL }, - { "ldap_user_auth_type", "ipaUserAuthType", SYSDB_AUTH_TYPE, NULL }, -- { "ldap_user_certificate", "userCertificate", SYSDB_USER_CERT, NULL }, -+ { "ldap_user_certificate", "userCertificate;binary", SYSDB_USER_CERT, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - --- -2.4.3 - diff --git a/SOURCES/0055-utils-add-is_email_from_domain.patch b/SOURCES/0055-utils-add-is_email_from_domain.patch new file mode 100644 index 0000000..e75ddfc --- /dev/null +++ b/SOURCES/0055-utils-add-is_email_from_domain.patch @@ -0,0 +1,102 @@ +From 3f7b69c3af7b810443a94a1004d41b87e5ca79d8 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 20 Jun 2016 16:11:11 +0200 +Subject: [PATCH 55/62] utils: add is_email_from_domain() + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 04d4c4d45f3942a813b7f772737f801f877f4e64) +--- + src/tests/cmocka/test_utils.c | 21 +++++++++++++++++++++ + src/util/domain_info_utils.c | 27 +++++++++++++++++++++++++++ + src/util/util.h | 1 + + 3 files changed, 49 insertions(+) + +diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c +index 5349accc5c6b55f7d725bfdeaf318b90289880dd..09273692968b544aed88de00c747e85ff0b6695c 100644 +--- a/src/tests/cmocka/test_utils.c ++++ b/src/tests/cmocka/test_utils.c +@@ -1842,6 +1842,25 @@ static void test_sss_get_domain_mappings_content(void **state) + * capaths might not be as expected. */ + } + ++static void test_is_email_from_domain(void **state) ++{ ++ struct dom_list_test_ctx *test_ctx = talloc_get_type(*state, ++ struct dom_list_test_ctx); ++ struct sss_domain_info *d; ++ ++ d = find_domain_by_name(test_ctx->dom_list, "name_0.dom", false); ++ assert_non_null(d); ++ ++ assert_false(is_email_from_domain(NULL, NULL)); ++ assert_false(is_email_from_domain("hello", NULL)); ++ assert_false(is_email_from_domain(NULL, d)); ++ assert_false(is_email_from_domain("hello", d)); ++ assert_false(is_email_from_domain("hello@hello", d)); ++ ++ assert_true(is_email_from_domain("hello@name_0.dom", d)); ++ assert_true(is_email_from_domain("hello@NaMe_0.DoM", d)); ++} ++ + int main(int argc, const char *argv[]) + { + poptContext pc; +@@ -1870,6 +1889,8 @@ int main(int argc, const char *argv[]) + setup_dom_list, teardown_dom_list), + cmocka_unit_test_setup_teardown(test_find_domain_by_name_disabled, + setup_dom_list, teardown_dom_list), ++ cmocka_unit_test_setup_teardown(test_is_email_from_domain, ++ setup_dom_list, teardown_dom_list), + + cmocka_unit_test_setup_teardown(test_sss_names_init, + confdb_test_setup, +diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c +index 587a6b993d2bd70662df8e0b0d5963fa00c84cf8..0feda148bd44b9cefc43c094ddc5a72820412322 100644 +--- a/src/util/domain_info_utils.c ++++ b/src/util/domain_info_utils.c +@@ -824,3 +824,30 @@ void sss_domain_set_state(struct sss_domain_info *dom, + { + dom->state = state; + } ++ ++bool is_email_from_domain(const char *email, struct sss_domain_info *dom) ++{ ++ const char *p; ++ ++ if (email == NULL || dom == NULL) { ++ return false; ++ } ++ ++ p = strchr(email, '@'); ++ if (p == NULL) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "Input [%s] does not look like an email address.\n", email); ++ return false; ++ } ++ ++ if (strcasecmp(p+1, dom->name) == 0) { ++ DEBUG(SSSDBG_TRACE_ALL, "Email [%s] is from domain [%s].\n", email, ++ dom->name); ++ return true; ++ } ++ ++ DEBUG(SSSDBG_TRACE_ALL, "Email [%s] is not from domain [%s].\n", email, ++ dom->name); ++ ++ return false; ++} +diff --git a/src/util/util.h b/src/util/util.h +index 122be90b967fb7793adaff95f3754d7a199fcf48..4449315f8b1a79ec915bc340b46188c440a27fa3 100644 +--- a/src/util/util.h ++++ b/src/util/util.h +@@ -514,6 +514,7 @@ struct sss_domain_info *find_domain_by_sid(struct sss_domain_info *domain, + enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom); + void sss_domain_set_state(struct sss_domain_info *dom, + enum sss_domain_state state); ++bool is_email_from_domain(const char *email, struct sss_domain_info *dom); + + struct sss_domain_info* + sss_get_domain_by_sid_ldap_fallback(struct sss_domain_info *domain, +-- +2.4.11 + diff --git a/SOURCES/0056-LDAP-IPA-add-local-email-address-to-aliases.patch b/SOURCES/0056-LDAP-IPA-add-local-email-address-to-aliases.patch new file mode 100644 index 0000000..51ebcba --- /dev/null +++ b/SOURCES/0056-LDAP-IPA-add-local-email-address-to-aliases.patch @@ -0,0 +1,126 @@ +From 24ed6bff6cf81c7ba732a5515a2194d9e32cf354 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 20 Jun 2016 16:30:03 +0200 +Subject: [PATCH 56/62] LDAP/IPA: add local email address to aliases + +Adding email-addresses from the local domain to the alias names is +strictly not needed by might help to speed up lookups in the NSS +responder. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 9a310913d696d190db14c625080678db853a33fd) +--- + src/providers/ipa/ipa_s2n_exop.c | 49 ++++++++++++++++++++++++++++++++++++++++ + src/providers/ldap/sdap_utils.c | 22 ++++++++++++++++++ + 2 files changed, 71 insertions(+) + +diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c +index b28cc415b1c6dfcf06e0cb9769a36135da01b991..255dad45037a6cb8f399bf2df500215f6fb25b59 100644 +--- a/src/providers/ipa/ipa_s2n_exop.c ++++ b/src/providers/ipa/ipa_s2n_exop.c +@@ -1885,6 +1885,49 @@ done: + return ret; + } + ++static errno_t add_emails_to_aliases(struct sysdb_attrs *attrs, ++ struct sss_domain_info *dom) ++{ ++ int ret; ++ const char **emails; ++ size_t c; ++ TALLOC_CTX *tmp_ctx; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); ++ return ENOMEM; ++ } ++ ++ ret = sysdb_attrs_get_string_array(attrs, SYSDB_USER_EMAIL, tmp_ctx, ++ &emails); ++ if (ret == EOK) { ++ for (c = 0; emails[c] != NULL; c++) { ++ if (is_email_from_domain(emails[c], dom)) { ++ ret = sysdb_attrs_add_lc_name_alias_safe(attrs, emails[c]); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to add lower-cased version of email [%s] " ++ "into the alias list\n", emails[c]); ++ goto done; ++ } ++ } ++ } ++ } else if (ret == ENOENT) { ++ DEBUG(SSSDBG_TRACE_ALL, "No email addresses available.\n"); ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_attrs_get_string_array failed, skipping ...\n"); ++ } ++ ++ ret = EOK; ++ ++done: ++ talloc_free(tmp_ctx); ++ ++ return ret; ++} ++ + static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, + struct req_input *req_input, + struct resp_attrs *attrs, +@@ -2030,6 +2073,12 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, + goto done; + } + ++ ret = add_emails_to_aliases(attrs->sysdb_attrs, dom); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "add_emails_to_aliases failed, skipping ...\n"); ++ } ++ + if (upn == NULL) { + /* We also have to store a fake UPN here, because otherwise the + * krb5 child later won't be able to properly construct one as +diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c +index 696af51d66e279d718e9af142ce5ed871eae7727..a3a9642171ca057be5a59dfae192803b84c501c8 100644 +--- a/src/providers/ldap/sdap_utils.c ++++ b/src/providers/ldap/sdap_utils.c +@@ -87,6 +87,7 @@ sdap_save_all_names(const char *name, + int i; + bool lowercase = !dom->case_sensitive; + bool store_as_fqdn; ++ const char **emails; + + switch (entry_type) { + case SYSDB_MEMBER_USER: +@@ -143,6 +144,27 @@ sdap_save_all_names(const char *name, + + } + ++ ret = sysdb_attrs_get_string_array(ldap_attrs, SYSDB_USER_EMAIL, tmp_ctx, ++ &emails); ++ if (ret == EOK) { ++ for (i = 0; emails[i] != NULL; i++) { ++ if (is_email_from_domain(emails[i], dom)) { ++ ret = sysdb_attrs_add_lc_name_alias_safe(attrs, emails[i]); ++ if (ret) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to add lower-cased version of email [%s] " ++ "into the alias list\n", emails[i]); ++ goto done; ++ } ++ } ++ } ++ } else if (ret == ENOENT) { ++ DEBUG(SSSDBG_TRACE_ALL, "No email addresses available.\n"); ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_attrs_get_string_array failed, skipping ...\n"); ++ } ++ + ret = EOK; + done: + talloc_free(tmp_ctx); +-- +2.4.11 + diff --git a/SOURCES/0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch b/SOURCES/0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch deleted file mode 100644 index 0d73afe..0000000 --- a/SOURCES/0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch +++ /dev/null @@ -1,377 +0,0 @@ -From 2b13d8192f0d7a08bb16a3e488e772d54b10d81a Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 12 Aug 2015 12:41:44 +0200 -Subject: [PATCH 56/57] UTIL: Provide a common interface to safely create - temporary files -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina ---- - src/tests/cmocka/test_utils.c | 175 ++++++++++++++++++++++++++++++++++++++++++ - src/util/util.c | 127 ++++++++++++++++++++++++++++++ - src/util/util.h | 21 +++++ - 3 files changed, 323 insertions(+) - -diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c -index d3d00feda0bdd4048519f90ba48ae9d1042a95a1..c7ebe0997ec00197e8852bedbcf26ef1f6394fc3 100644 ---- a/src/tests/cmocka/test_utils.c -+++ b/src/tests/cmocka/test_utils.c -@@ -1212,6 +1212,168 @@ void test_fix_domain_in_name_list(void **state) - talloc_free(dom); - } - -+struct unique_file_test_ctx { -+ char *filename; -+}; -+ -+static int unique_file_test_setup(void **state) -+{ -+ struct unique_file_test_ctx *test_ctx; -+ -+ assert_true(leak_check_setup()); -+ check_leaks_push(global_talloc_context); -+ -+ test_ctx = talloc_zero(global_talloc_context, struct unique_file_test_ctx); -+ assert_non_null(test_ctx); -+ -+ test_ctx->filename = talloc_strdup(test_ctx, "test_unique_file_XXXXXX"); -+ assert_non_null(test_ctx); -+ -+ *state = test_ctx; -+ return 0; -+} -+ -+static int unique_file_test_teardown(void **state) -+{ -+ struct unique_file_test_ctx *test_ctx; -+ errno_t ret; -+ -+ test_ctx = talloc_get_type(*state, struct unique_file_test_ctx); -+ -+ errno = 0; -+ ret = unlink(test_ctx->filename); -+ if (ret != 0 && errno != ENOENT) { -+ fail(); -+ } -+ -+ talloc_free(test_ctx); -+ assert_true(check_leaks_pop(global_talloc_context) == true); -+ assert_true(leak_check_teardown()); -+ return 0; -+} -+ -+static void assert_destructor(TALLOC_CTX *owner, -+ struct unique_file_test_ctx *test_ctx) -+{ -+ int fd; -+ errno_t ret; -+ char *check_filename; -+ -+ /* Test that the destructor works */ -+ if (owner == NULL) { -+ return; -+ } -+ -+ check_filename = talloc_strdup(test_ctx, test_ctx->filename); -+ assert_non_null(check_filename); -+ -+ talloc_free(owner); -+ -+ ret = check_and_open_readonly(test_ctx->filename, &fd, -+ geteuid(), getegid(), -+ (S_IRUSR | S_IWUSR | S_IFREG), 0); -+ close(fd); -+ assert_int_not_equal(ret, EOK); -+} -+ -+static void sss_unique_file_test(struct unique_file_test_ctx *test_ctx, -+ bool test_destructor) -+{ -+ int fd; -+ errno_t ret; -+ struct stat sb; -+ TALLOC_CTX *owner = NULL; -+ -+ if (test_destructor) { -+ owner = talloc_new(test_ctx); -+ assert_non_null(owner); -+ } -+ -+ fd = sss_unique_file(owner, test_ctx->filename, &ret); -+ assert_int_not_equal(fd, -1); -+ assert_int_equal(ret, EOK); -+ -+ ret = check_fd(fd, geteuid(), getegid(), -+ (S_IRUSR | S_IWUSR | S_IFREG), 0, &sb); -+ close(fd); -+ assert_int_equal(ret, EOK); -+ -+ assert_destructor(owner, test_ctx); -+} -+ -+static void test_sss_unique_file(void **state) -+{ -+ struct unique_file_test_ctx *test_ctx; -+ test_ctx = talloc_get_type(*state, struct unique_file_test_ctx); -+ sss_unique_file_test(test_ctx, false); -+} -+ -+static void test_sss_unique_file_destruct(void **state) -+{ -+ struct unique_file_test_ctx *test_ctx; -+ test_ctx = talloc_get_type(*state, struct unique_file_test_ctx); -+ sss_unique_file_test(test_ctx, true); -+} -+ -+static void test_sss_unique_file_neg(void **state) -+{ -+ int fd; -+ errno_t ret; -+ -+ fd = sss_unique_file(NULL, discard_const("badpattern"), &ret); -+ assert_int_equal(fd, -1); -+ assert_int_equal(ret, EINVAL); -+} -+ -+static void sss_unique_filename_test(struct unique_file_test_ctx *test_ctx, -+ bool test_destructor) -+{ -+ int fd; -+ errno_t ret; -+ char *tmp_filename; -+ TALLOC_CTX *owner = NULL; -+ -+ tmp_filename = talloc_strdup(test_ctx, test_ctx->filename); -+ assert_non_null(tmp_filename); -+ -+ if (test_destructor) { -+ owner = talloc_new(test_ctx); -+ assert_non_null(owner); -+ } -+ -+ ret = sss_unique_filename(owner, test_ctx->filename); -+ assert_int_equal(ret, EOK); -+ -+ assert_int_equal(strncmp(test_ctx->filename, -+ tmp_filename, -+ strlen(tmp_filename) - sizeof("XXXXXX")), -+ 0); -+ -+ ret = check_and_open_readonly(test_ctx->filename, &fd, -+ geteuid(), getegid(), -+ (S_IRUSR | S_IWUSR | S_IFREG), 0); -+ close(fd); -+ assert_int_equal(ret, EOK); -+ -+ assert_destructor(owner, test_ctx); -+} -+ -+static void test_sss_unique_filename(void **state) -+{ -+ struct unique_file_test_ctx *test_ctx; -+ -+ test_ctx = talloc_get_type(*state, struct unique_file_test_ctx); -+ sss_unique_filename_test(test_ctx, false); -+} -+ -+static void test_sss_unique_filename_destruct(void **state) -+{ -+ struct unique_file_test_ctx *test_ctx; -+ -+ test_ctx = talloc_get_type(*state, struct unique_file_test_ctx); -+ sss_unique_filename_test(test_ctx, true); -+} -+ - int main(int argc, const char *argv[]) - { - poptContext pc; -@@ -1275,6 +1437,19 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(test_fix_domain_in_name_list, - confdb_test_setup, - confdb_test_teardown), -+ cmocka_unit_test_setup_teardown(test_sss_unique_file, -+ unique_file_test_setup, -+ unique_file_test_teardown), -+ cmocka_unit_test_setup_teardown(test_sss_unique_file_destruct, -+ unique_file_test_setup, -+ unique_file_test_teardown), -+ cmocka_unit_test(test_sss_unique_file_neg), -+ cmocka_unit_test_setup_teardown(test_sss_unique_filename, -+ unique_file_test_setup, -+ unique_file_test_teardown), -+ cmocka_unit_test_setup_teardown(test_sss_unique_filename_destruct, -+ unique_file_test_setup, -+ unique_file_test_teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ -diff --git a/src/util/util.c b/src/util/util.c -index 782cd026b7928e607a8980fb5f333c794feb5b1a..f0925051a08970b191f61a533cd49dd53ae128e0 100644 ---- a/src/util/util.c -+++ b/src/util/util.c -@@ -979,3 +979,130 @@ errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *_unix_tim - *_unix_time = ut; - return EOK; - } -+ -+struct tmpfile_watch { -+ const char *filename; -+}; -+ -+static int unlink_dbg(const char *filename) -+{ -+ errno_t ret; -+ -+ ret = unlink(filename); -+ if (ret != 0) { -+ if (errno == 2) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "File already removed: [%s]\n", filename); -+ return 0; -+ } else { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot remove temporary file [%s]\n", filename); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+static int unique_filename_destructor(void *memptr) -+{ -+ struct tmpfile_watch *tw = talloc_get_type(memptr, struct tmpfile_watch); -+ -+ if (tw == NULL || tw->filename == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: Wrong private pointer\n"); -+ return -1; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Unlinking [%s]\n", tw->filename); -+ -+ return unlink_dbg(tw->filename); -+} -+ -+static struct tmpfile_watch *tmpfile_watch_set(TALLOC_CTX *owner, -+ const char *filename) -+{ -+ struct tmpfile_watch *tw = NULL; -+ -+ tw = talloc_zero(owner, struct tmpfile_watch); -+ if (tw == NULL) { -+ return NULL; -+ } -+ -+ tw->filename = talloc_strdup(tw, filename); -+ if (tw->filename == NULL) { -+ talloc_free(tw); -+ return NULL; -+ } -+ -+ talloc_set_destructor((TALLOC_CTX *) tw, -+ unique_filename_destructor); -+ return tw; -+} -+ -+int sss_unique_file_ex(TALLOC_CTX *owner, -+ char *path_tmpl, -+ mode_t file_umask, -+ errno_t *_err) -+{ -+ size_t tmpl_len; -+ errno_t ret; -+ int fd = -1; -+ mode_t old_umask; -+ struct tmpfile_watch *tw = NULL; -+ -+ tmpl_len = strlen(path_tmpl); -+ if (tmpl_len < 6 || strcmp(path_tmpl + (tmpl_len - 6), "XXXXXX") != 0) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Template too short or doesn't end with XXXXXX!\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ old_umask = umask(file_umask); -+ fd = mkstemp(path_tmpl); -+ umask(old_umask); -+ if (fd == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_OP_FAILURE, -+ "mkstemp(\"%s\") failed [%d]: %s!\n", -+ path_tmpl, ret, strerror(ret)); -+ goto done; -+ } -+ -+ if (owner != NULL) { -+ tw = tmpfile_watch_set(owner, path_tmpl); -+ if (tw == NULL) { -+ unlink_dbg(path_tmpl); -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+done: -+ if (_err) { -+ *_err = ret; -+ } -+ return fd; -+} -+ -+int sss_unique_file(TALLOC_CTX *owner, -+ char *path_tmpl, -+ errno_t *_err) -+{ -+ return sss_unique_file_ex(owner, path_tmpl, 077, _err); -+} -+ -+errno_t sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl) -+{ -+ int fd; -+ errno_t ret; -+ -+ fd = sss_unique_file(owner, path_tmpl, &ret); -+ /* We only care about a unique file name */ -+ if (fd >= 0) { -+ close(fd); -+ } -+ -+ return ret; -+} -diff --git a/src/util/util.h b/src/util/util.h -index 94a3ddea839f0998cb7796f1d2fe13f743de3aaf..a20d1d82eb8f10dac515ad25e7e424713bb1c099 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -658,4 +658,25 @@ int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name, - /* convert time from generalized form to unix time */ - errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *unix_time); - -+/* Creates a unique file using mkstemp with provided umask. The template -+ * must end with XXXXXX. Returns the fd, sets _err to an errno value on error. -+ * -+ * Prefer using sss_unique_file() as it uses a secure umask internally. -+ */ -+int sss_unique_file_ex(TALLOC_CTX *mem_ctx, -+ char *path_tmpl, -+ mode_t file_umask, -+ errno_t *_err); -+int sss_unique_file(TALLOC_CTX *owner, -+ char *path_tmpl, -+ errno_t *_err); -+ -+/* Creates a unique filename using mkstemp with secure umask. The template -+ * must end with XXXXXX -+ * -+ * path_tmpl must be a talloc context. Destructor would be set on the filename -+ * so that it's guaranteed the file is removed. -+ */ -+int sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl); -+ - #endif /* __SSSD_UTIL_H__ */ --- -2.4.3 - diff --git a/SOURCES/0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch b/SOURCES/0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch deleted file mode 100644 index dabccbf..0000000 --- a/SOURCES/0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch +++ /dev/null @@ -1,447 +0,0 @@ -From 366631d15723db68fdb5c47e18ff9253689648ab Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 24 Jul 2015 13:13:08 +0200 -Subject: [PATCH 57/57] IPA: Always re-fetch the keytab from the IPA server -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Even if a keytab for one-way trust exists, re-fetch the keytab again and -try to use it. Fall back to the previous one if it exists. - -This is in order to allow the admin to re-establish the trust keytabs -with a simple sssd restart. - -Reviewed-by: Pavel Březina ---- - Makefile.am | 2 + - src/providers/ipa/ipa_subdomains.c | 4 +- - src/providers/ipa/ipa_subdomains_server.c | 83 +++++++++---- - src/tests/cmocka/test_ipa_subdomains_server.c | 166 ++++++++++++++++++++++++-- - 4 files changed, 221 insertions(+), 34 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 8b64317d6dce9a1ee8614916395b9afd9f11f382..ed107fd5dc76b768176a3d7236b0bf1c75f212bf 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -2550,6 +2550,8 @@ test_ipa_subdom_server_LDFLAGS = \ - -Wl,-wrap,krb5_kt_default \ - -Wl,-wrap,execle \ - -Wl,-wrap,execve \ -+ -Wl,-wrap,rename \ -+ -Wl,-wrap,sss_unique_filename \ - $(NULL) - test_ipa_subdom_server_LDADD = \ - $(PAM_LIBS) \ -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index cec8b3918b8f832e2c7376a867448fe876da6ffc..b2e2fec353f7b168d28a880cb0f1b6181abb1ccb 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -264,7 +264,7 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - ret = get_idmap_data_from_range(r, domain_name, &name1, &sid1, &rid1, - &range1, &mapping1); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, ("get_idmap_data_from_range failed.\n")); -+ DEBUG(SSSDBG_OP_FAILURE, "get_idmap_data_from_range failed.\n"); - goto done; - } - for (d = 0; d < c; d++) { -@@ -272,7 +272,7 @@ static errno_t ipa_ranges_parse_results(TALLOC_CTX *mem_ctx, - &sid2, &rid2, &range2, &mapping2); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, -- ("get_idmap_data_from_range failed.\n")); -+ "get_idmap_data_from_range failed.\n"); - goto done; - } - -diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c -index 4bfea61e6dd0a02f6b723a39f7ba236c914009b0..dfecab1bc362b5772379bae6d51f9cef8443f225 100644 ---- a/src/providers/ipa/ipa_subdomains_server.c -+++ b/src/providers/ipa/ipa_subdomains_server.c -@@ -445,6 +445,17 @@ static void ipa_getkeytab_exec(const char *ccache, - exit(1); - } - -+ /* ipa-getkeytab cannot add keys to an empty file, let's unlink it and only -+ * use the filename */ -+ ret = unlink(keytab_path); -+ if (ret == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to unlink the temporary ccname [%d][%s]\n", -+ ret, sss_strerror(ret)); -+ exit(1); -+ } -+ - errno = 0; - ret = execle(IPA_GETKEYTAB_PATH, IPA_GETKEYTAB_PATH, - "-r", "-s", server, "-p", principal, "-k", keytab_path, NULL, -@@ -561,6 +572,7 @@ struct ipa_server_trust_add_state { - uint32_t direction; - const char *forest; - const char *keytab; -+ char *new_keytab; - const char *principal; - const char *forest_realm; - const char *ccache; -@@ -660,21 +672,20 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req) - return EIO; - } - -- ret = ipa_check_keytab(state->keytab, -- state->id_ctx->server_mode->kt_owner_uid, -- state->id_ctx->server_mode->kt_owner_gid); -- if (ret == EOK) { -- DEBUG(SSSDBG_TRACE_FUNC, -- "Keytab already present, can add the trust\n"); -- return EOK; -- } else if (ret != ENOENT) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to check for keytab: %d\n", ret); -+ state->new_keytab = talloc_asprintf(state, "%sXXXXXX", state->keytab); -+ if (state->new_keytab == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up ipa_get_keytab\n"); -+ return ENOMEM; -+ } -+ -+ ret = sss_unique_filename(state, state->new_keytab); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create temporary keytab name\n"); - return ret; - } - - DEBUG(SSSDBG_TRACE_FUNC, -- "No keytab for %s\n", state->subdom->name); -+ "Will re-fetch keytab for %s\n", state->subdom->name); - - hostname = dp_opt_get_string(state->id_ctx->ipa_options->basic, - IPA_HOSTNAME); -@@ -691,7 +702,7 @@ static errno_t ipa_server_trust_add_1way(struct tevent_req *req) - state->ccache, - hostname, - state->principal, -- state->keytab); -+ state->new_keytab); - if (subreq == NULL) { - return ENOMEM; - } -@@ -710,23 +721,49 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq) - ret = ipa_getkeytab_recv(subreq, NULL); - talloc_zfree(subreq); - if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, "ipa_getkeytab_recv failed: %d\n", ret); -- tevent_req_error(req, ret); -- return; -+ /* Do not fail here, but try to check and use the previous keytab, -+ * if any */ -+ DEBUG(SSSDBG_MINOR_FAILURE, "ipa_getkeytab_recv failed: %d\n", ret); -+ } else { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Keytab successfully retrieved to %s\n", state->new_keytab); - } - -- DEBUG(SSSDBG_TRACE_FUNC, -- "Keytab successfully retrieved to %s\n", state->keytab); -- -- ret = ipa_check_keytab(state->keytab, -+ ret = ipa_check_keytab(state->new_keytab, - state->id_ctx->server_mode->kt_owner_uid, - state->id_ctx->server_mode->kt_owner_gid); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, "ipa_check_keytab failed: %d\n", ret); -- tevent_req_error(req, ret); -- return; -+ if (ret == EOK) { -+ ret = rename(state->new_keytab, state->keytab); -+ if (ret == -1) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "rename failed [%d][%s].\n", ret, strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Keytab renamed to %s\n", state->keytab); -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Trying to recover and use the previous keytab, if available\n"); -+ ret = ipa_check_keytab(state->keytab, -+ state->id_ctx->server_mode->kt_owner_uid, -+ state->id_ctx->server_mode->kt_owner_gid); -+ if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "The previous keytab %s contains the expected principal\n", -+ state->keytab); -+ } else { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot use the old keytab: %d\n", ret); -+ /* Nothing we can do now */ -+ tevent_req_error(req, ret); -+ return; -+ } - } - -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Keytab %s contains the expected principals\n", state->new_keytab); -+ - ret = ipa_server_trust_add_step(req); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, -diff --git a/src/tests/cmocka/test_ipa_subdomains_server.c b/src/tests/cmocka/test_ipa_subdomains_server.c -index a4cb8c2b7538dc84b74e0227205b73780844b652..fb9bd80e299c05fa230599d442fa361ae757dcd3 100644 ---- a/src/tests/cmocka/test_ipa_subdomains_server.c -+++ b/src/tests/cmocka/test_ipa_subdomains_server.c -@@ -66,33 +66,79 @@ - #define ONEWAY_PRINC DOM_FLAT"$" - #define ONEWAY_AUTHID ONEWAY_PRINC"@"SUBDOM_REALM - -+static bool global_rename_called; -+ - krb5_error_code __wrap_krb5_kt_default(krb5_context context, krb5_keytab *id) - { - return krb5_kt_resolve(context, KEYTAB_PATH, id); - } - --static void create_dummy_keytab(void) -+static void create_dummy_keytab(const char *dummy_kt) - { - errno_t ret; - -- assert_non_null(ONEWAY_KEYTAB); -+ assert_non_null(dummy_kt); - mock_keytab_with_contents(global_talloc_context, -- ONEWAY_KEYTAB, ONEWAY_AUTHID); -+ dummy_kt, ONEWAY_AUTHID); - -- ret = access(ONEWAY_KEYTAB, R_OK); -+ ret = access(dummy_kt, R_OK); - assert_int_equal(ret, 0); - } - -+static int wrap_exec(void) -+{ -+ const char *test_kt; -+ const char *fail_creating_kt; -+ -+ test_kt = getenv("TEST_KT_ENV"); -+ if (test_kt == NULL) { -+ _exit(1); -+ } -+ unsetenv("TEST_KT_ENV"); -+ -+ fail_creating_kt = getenv("KT_CREATE_FAIL"); -+ if (fail_creating_kt != NULL) { -+ _exit(1); -+ } -+ -+ create_dummy_keytab(test_kt); -+ _exit(0); -+ -+ return 1; /* Should not happen */ -+} -+ - int __wrap_execle(const char *path, const char *arg, ...) - { -- create_dummy_keytab(); -- _exit(0); -+ return wrap_exec(); - } - - int __wrap_execve(const char *path, const char *arg, ...) - { -- create_dummy_keytab(); -- _exit(0); -+ return wrap_exec(); -+} -+ -+errno_t __real_sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl); -+ -+errno_t __wrap_sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl) -+{ -+ int ret; -+ int sret; -+ -+ ret = __real_sss_unique_filename(owner, path_tmpl); -+ if (ret == EOK) { -+ -+ sret = setenv("TEST_KT_ENV", path_tmpl, 1); -+ assert_int_equal(sret, 0); -+ } -+ return ret; -+} -+ -+int __real_rename(const char *old, const char *new); -+ -+int __wrap_rename(const char *old, const char *new) -+{ -+ global_rename_called = true; -+ return __real_rename(old, new); - } - - struct trust_test_ctx { -@@ -100,6 +146,7 @@ struct trust_test_ctx { - struct be_ctx *be_ctx; - - struct ipa_id_ctx *ipa_ctx; -+ bool expect_rename; - }; - - static struct ipa_id_ctx *mock_ipa_ctx(TALLOC_CTX *mem_ctx, -@@ -244,6 +291,8 @@ static int test_ipa_server_create_trusts_setup(void **state) - - mock_keytab_with_contents(test_ctx, KEYTAB_PATH, KEYTAB_TEST_PRINC); - -+ global_rename_called = false; -+ - *state = test_ctx; - return 0; - } -@@ -260,6 +309,11 @@ static int test_ipa_server_create_trusts_teardown(void **state) - unlink(ONEWAY_KEYTAB); - /* Ignore failures */ - -+ /* If a test needs this variable, it should be set again in -+ * each test -+ */ -+ unsetenv("KT_CREATE_FAIL"); -+ - talloc_free(test_ctx); - return 0; - } -@@ -612,6 +666,8 @@ static void test_ipa_server_create_oneway(void **state) - - assert_null(test_ctx->ipa_ctx->server_mode->trusts); - -+ test_ctx->expect_rename = true; -+ - req = ipa_server_create_trusts_send(test_ctx, - test_ctx->tctx->ev, - test_ctx->be_ctx, -@@ -635,6 +691,8 @@ static void test_ipa_server_create_trusts_oneway(struct tevent_req *req) - talloc_zfree(req); - assert_int_equal(ret, EOK); - -+ assert_true(test_ctx->expect_rename == global_rename_called); -+ - ret = access(ONEWAY_KEYTAB, R_OK); - assert_int_equal(ret, 0); - -@@ -674,10 +732,46 @@ static void test_ipa_server_create_oneway_kt_exists(void **state) - - add_test_1way_subdomains(test_ctx); - -- create_dummy_keytab(); -+ create_dummy_keytab(ONEWAY_KEYTAB); - ret = access(ONEWAY_KEYTAB, R_OK); - assert_int_equal(ret, 0); - -+ test_ctx->expect_rename = true; -+ -+ assert_null(test_ctx->ipa_ctx->server_mode->trusts); -+ -+ req = ipa_server_create_trusts_send(test_ctx, -+ test_ctx->tctx->ev, -+ test_ctx->be_ctx, -+ test_ctx->ipa_ctx, -+ test_ctx->be_ctx->domain); -+ assert_non_null(req); -+ -+ tevent_req_set_callback(req, test_ipa_server_create_trusts_oneway, test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ERR_OK); -+} -+ -+/* Test scenario where a keytab already exists, but refresh fails. In this case, -+ * sssd should attempt to reuse the previous keytab -+ */ -+static void test_ipa_server_create_oneway_kt_refresh_fallback(void **state) -+{ -+ struct trust_test_ctx *test_ctx = -+ talloc_get_type(*state, struct trust_test_ctx); -+ struct tevent_req *req; -+ errno_t ret; -+ -+ add_test_1way_subdomains(test_ctx); -+ -+ create_dummy_keytab(ONEWAY_KEYTAB); -+ ret = access(ONEWAY_KEYTAB, R_OK); -+ assert_int_equal(ret, 0); -+ -+ setenv("KT_CREATE_FAIL", "1", 1); -+ test_ctx->expect_rename = false; -+ - assert_null(test_ctx->ipa_ctx->server_mode->trusts); - - req = ipa_server_create_trusts_send(test_ctx, -@@ -693,6 +787,54 @@ static void test_ipa_server_create_oneway_kt_exists(void **state) - assert_int_equal(ret, ERR_OK); - } - -+/* Tests case where there's no keytab and retrieving fails. Just fail the -+ * request in that case -+ */ -+static void test_ipa_server_create_trusts_oneway_fail(struct tevent_req *req); -+ -+static void test_ipa_server_create_oneway_kt_refresh_fail(void **state) -+{ -+ struct trust_test_ctx *test_ctx = -+ talloc_get_type(*state, struct trust_test_ctx); -+ struct tevent_req *req; -+ errno_t ret; -+ -+ add_test_1way_subdomains(test_ctx); -+ -+ setenv("KT_CREATE_FAIL", "1", 1); -+ test_ctx->expect_rename = false; -+ -+ assert_null(test_ctx->ipa_ctx->server_mode->trusts); -+ -+ req = ipa_server_create_trusts_send(test_ctx, -+ test_ctx->tctx->ev, -+ test_ctx->be_ctx, -+ test_ctx->ipa_ctx, -+ test_ctx->be_ctx->domain); -+ assert_non_null(req); -+ -+ tevent_req_set_callback(req, -+ test_ipa_server_create_trusts_oneway_fail, -+ test_ctx); -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, ERR_OK); -+} -+ -+static void test_ipa_server_create_trusts_oneway_fail(struct tevent_req *req) -+{ -+ struct trust_test_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct trust_test_ctx); -+ errno_t ret; -+ -+ ret = ipa_server_create_trusts_recv(req); -+ assert_int_not_equal(ret, EOK); -+ -+ assert_true(test_ctx->expect_rename == global_rename_called); -+ -+ test_ev_done(test_ctx->tctx, EOK); -+} -+ - static void test_ipa_server_trust_oneway_init(void **state) - { - struct trust_test_ctx *test_ctx = -@@ -749,6 +891,12 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(test_ipa_server_create_oneway_kt_exists, - test_ipa_server_create_trusts_setup, - test_ipa_server_create_trusts_teardown), -+ cmocka_unit_test_setup_teardown(test_ipa_server_create_oneway_kt_refresh_fallback, -+ test_ipa_server_create_trusts_setup, -+ test_ipa_server_create_trusts_teardown), -+ cmocka_unit_test_setup_teardown(test_ipa_server_create_oneway_kt_refresh_fail, -+ test_ipa_server_create_trusts_setup, -+ test_ipa_server_create_trusts_teardown), - cmocka_unit_test_setup_teardown(test_ipa_server_trust_oneway_init, - test_ipa_server_create_trusts_setup, - test_ipa_server_create_trusts_teardown), --- -2.4.3 - diff --git a/SOURCES/0057-NSS-continue-with-UPN-email-search-if-name-was-not-f.patch b/SOURCES/0057-NSS-continue-with-UPN-email-search-if-name-was-not-f.patch new file mode 100644 index 0000000..0155ae1 --- /dev/null +++ b/SOURCES/0057-NSS-continue-with-UPN-email-search-if-name-was-not-f.patch @@ -0,0 +1,98 @@ +From 481bd8fd5db7a92954ff351ab64ab32b4249bf19 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 21 Jun 2016 11:06:19 +0200 +Subject: [PATCH 57/62] NSS: continue with UPN/email search if name was not + found + +Currently we only search for UPNs if the domain part of the name was not +know, with Kerberos aliases and email addresses we have to do this even +if the domain name is a know domain. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 447b1da857368678990b54cd6b9cfed940357c44) +--- + src/responder/nss/nsssrv_cmd.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index 77e540d8da969614e4ab40c62e6ae1f271962f31..cd15b41886ad046d1d70dbd8ad54af5a4eccee5d 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -980,6 +980,7 @@ done: + + static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min, + const char *err_msg, void *ptr); ++static int nss_cmd_assume_upn(struct nss_dom_ctx *dctx); + + /* search for a user. + * Returns: +@@ -1051,6 +1052,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + /* There are no further domains or this was a + * fully-qualified user request. + */ ++ + return ENOENT; + } + +@@ -1144,8 +1146,6 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + if (dom) continue; + } + +- DEBUG(SSSDBG_OP_FAILURE, "No results for getpwnam call\n"); +- + /* User not found in ldb -> delete user from memory cache. */ + ret = delete_entry_from_memcache(dctx->domain, name, nctx->rctx, + nctx->pwd_mc_ctx, SSS_MC_PASSWD); +@@ -1163,6 +1163,8 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + "Deleting user from memcache failed.\n"); + } + ++ DEBUG(SSSDBG_OP_FAILURE, "No results for getpwnam call\n"); ++ + return ENOENT; + } + +@@ -1215,7 +1217,7 @@ static int nss_cmd_assume_upn(struct nss_dom_ctx *dctx) + { + int ret; + +- if (dctx->domain == NULL) { ++ if (dctx->cmdctx->name_is_upn == false) { + dctx->domain = dctx->cmdctx->cctx->rctx->domains; + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + dctx->cmdctx->check_next = true; +@@ -1563,6 +1565,7 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx) + + rawname = (const char *)body; + dctx->mc_name = rawname; ++ dctx->rawname = rawname; + + DEBUG(SSSDBG_TRACE_FUNC, "Running command [%d][%s] with input [%s].\n", + cmd, sss_cmd2str(dctx->cmdctx->cmd), rawname); +@@ -1588,7 +1591,6 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx) + if (req == NULL) { + ret = ENOMEM; + } else { +- dctx->rawname = rawname; + tevent_req_set_callback(req, nss_cmd_getbynam_done, dctx); + ret = EAGAIN; + } +@@ -1604,7 +1606,6 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx) + if (req == NULL) { + ret = ENOMEM; + } else { +- dctx->rawname = rawname; + tevent_req_set_callback(req, nss_cmd_getbynam_done, dctx); + ret = EAGAIN; + } +@@ -1626,7 +1627,6 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx) + } + } else { + /* this is a multidomain search */ +- dctx->rawname = rawname; + dctx->domain = cctx->rctx->domains; + cmdctx->check_next = true; + if (cctx->rctx->get_domains_last_call.tv_sec == 0) { +-- +2.4.11 + diff --git a/SOURCES/0058-PAM-continue-with-UPN-email-search-if-name-was-not-f.patch b/SOURCES/0058-PAM-continue-with-UPN-email-search-if-name-was-not-f.patch new file mode 100644 index 0000000..3910eb3 --- /dev/null +++ b/SOURCES/0058-PAM-continue-with-UPN-email-search-if-name-was-not-f.patch @@ -0,0 +1,90 @@ +From d8c0b5421934cae887a44be42250d5df5631d3de Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 22 Jun 2016 18:21:11 +0200 +Subject: [PATCH 58/62] PAM: continue with UPN/email search if name was not + found + +Currently we only search for UPNs if the domain part of the name was not +know, with Kerberos aliases and email addresses we have to do this even +if the domain name is a know domain. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 3381d9736b698d6111d10e219a0b5b898a4c757c) +--- + src/responder/pam/pamsrv_cmd.c | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 3a35c3f08821aa23051989599d45b8b7b0677da4..1c759f009321cbb322fce624b506ed07f93f997b 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -924,6 +924,39 @@ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min, + static int pam_check_user_search(struct pam_auth_req *preq); + static int pam_check_user_done(struct pam_auth_req *preq, int ret); + ++static errno_t pam_cmd_assume_upn(struct pam_auth_req *preq) ++{ ++ int ret; ++ ++ if (!preq->pd->name_is_upn ++ && preq->pd->logon_name != NULL ++ && strchr(preq->pd->logon_name, '@') != NULL) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "No entry found so far, trying UPN/email lookup with [%s].\n", ++ preq->pd->logon_name); ++ /* Assuming Kerberos principal */ ++ preq->domain = preq->cctx->rctx->domains; ++ preq->check_provider = ++ NEED_CHECK_PROVIDER(preq->domain->provider); ++ preq->pd->user = talloc_strdup(preq->pd, preq->pd->logon_name); ++ if (preq->pd->user == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ return ENOMEM; ++ } ++ preq->pd->name_is_upn = true; ++ preq->pd->domain = NULL; ++ ++ ret = pam_check_user_search(preq); ++ if (ret == EOK) { ++ pam_dom_forwarder(preq); ++ } ++ return EOK; ++ } ++ ++ return ENOENT; ++} ++ ++ + /* TODO: we should probably return some sort of cookie that is set in the + * PAM_ENVIRONMENT, so that we can save performing some calls and cache + * data. */ +@@ -1220,6 +1253,8 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) + ret = pam_check_user_search(preq); + if (ret == EOK) { + pam_dom_forwarder(preq); ++ } else if (ret == ENOENT) { ++ ret = pam_cmd_assume_upn(preq); + } + + done: +@@ -1417,6 +1452,8 @@ static void pam_forwarder_cb(struct tevent_req *req) + ret = pam_check_user_search(preq); + if (ret == EOK) { + pam_dom_forwarder(preq); ++ } else if (ret == ENOENT) { ++ ret = pam_cmd_assume_upn(preq); + } + + done: +@@ -1694,6 +1731,8 @@ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min, + } + + pam_dom_forwarder(preq); ++ } else if (ret == ENOENT) { ++ ret = pam_cmd_assume_upn(preq); + } + + ret = pam_check_user_done(preq, ret); +-- +2.4.11 + diff --git a/SOURCES/0058-p11child-set-restrictive-umask-and-clear-environment.patch b/SOURCES/0058-p11child-set-restrictive-umask-and-clear-environment.patch deleted file mode 100644 index e2448b9..0000000 --- a/SOURCES/0058-p11child-set-restrictive-umask-and-clear-environment.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 5845a325b10e48b1e4c21976b0856ad1d012bbb4 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 5 Aug 2015 17:25:20 +0200 -Subject: [PATCH 58/59] p11child: set restrictive umask and clear environment -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2754 - -Before doing any calls, set a very restrictive umask and clear -environment variables to harden p11child execution. - -Reviewed-by: Lukáš Slebodník ---- - src/p11_child/p11_child_nss.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/p11_child/p11_child_nss.c b/src/p11_child/p11_child_nss.c -index 6948c142aa7843cda5ff6d18f5853b10c387c224..44ba6678893408dbfc0c6c7cfd5edcdaa789f518 100644 ---- a/src/p11_child/p11_child_nss.c -+++ b/src/p11_child/p11_child_nss.c -@@ -481,6 +481,9 @@ int main(int argc, const char *argv[]) - /* Set debug level to invalid value so we can decide if -d 0 was used. */ - debug_level = SSSDBG_INVALID; - -+ clearenv(); -+ umask(077); -+ - pc = poptGetContext(argv[0], argc, argv, long_options, 0); - while ((opt = poptGetNextOpt(pc)) != -1) { - switch(opt) { --- -2.4.3 - diff --git a/SOURCES/0059-NSS-use-different-neg-cache-name-for-UPN-searches.patch b/SOURCES/0059-NSS-use-different-neg-cache-name-for-UPN-searches.patch new file mode 100644 index 0000000..e77eb21 --- /dev/null +++ b/SOURCES/0059-NSS-use-different-neg-cache-name-for-UPN-searches.patch @@ -0,0 +1,59 @@ +From e5b8922062e127d1014609df16f1909da49850bf Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 22 Jul 2016 16:01:38 +0200 +Subject: [PATCH 59/62] NSS: use different neg cache name for UPN searches + +If Kerberos principals or email address have the same domain suffix as +the domain itself the first user lookup by name might have already added +the name to the negative cache and the second lookup by UPN/email will +skip the domain because of the neg cache entry. To avoid this a special +name with a '@' prefix is used here. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 62df78512145db94b51c5573d4df1737197e368a) +--- + src/responder/nss/nsssrv_cmd.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index cd15b41886ad046d1d70dbd8ad54af5a4eccee5d..f3b6ac4afb5d1571f283933b48e0256b91c56391 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -1002,6 +1002,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + struct ldb_message *msg; + const char *extra_flag = NULL; + const char *sysdb_name; ++ char *neg_cache_name; + + nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); + +@@ -1031,9 +1032,15 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + return ENOMEM; + } + ++ if (cmdctx->name_is_upn) { ++ neg_cache_name = talloc_asprintf(name, "@%s", name); ++ } else { ++ neg_cache_name = name; ++ } ++ + /* verify this user has not yet been negatively cached, + * or has been permanently filtered */ +- ret = sss_ncache_check_user(nctx->rctx->ncache, dom, name); ++ ret = sss_ncache_check_user(nctx->rctx->ncache, dom, neg_cache_name); + + /* if neg cached, return we didn't find it */ + if (ret == EEXIST) { +@@ -1130,7 +1137,8 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) + + if (dctx->res->count == 0 && !dctx->check_provider) { + /* set negative cache only if not result of cache check */ +- ret = sss_ncache_set_user(nctx->rctx->ncache, false, dom, name); ++ ret = sss_ncache_set_user(nctx->rctx->ncache, false, dom, ++ neg_cache_name); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set negcache for %s\n", + name); +-- +2.4.11 + diff --git a/SOURCES/0059-pam-Incerease-p11-child-timeout.patch b/SOURCES/0059-pam-Incerease-p11-child-timeout.patch deleted file mode 100644 index 8ff29a0..0000000 --- a/SOURCES/0059-pam-Incerease-p11-child-timeout.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 8cc5a9b94d6d660d61cce62543b6714d95e19697 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20=C5=BDidek?= -Date: Thu, 13 Aug 2015 14:03:24 +0200 -Subject: [PATCH 59/59] pam: Incerease p11 child timeout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Ticket: -https://fedorahosted.org/sssd/ticket/2746 - -It was timeouting often in CI machines. - -Reviewed-by: Lukáš Slebodník ---- - Makefile.am | 1 + - src/responder/pam/pamsrv_cmd.c | 9 +++++++-- - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index ed107fd5dc76b768176a3d7236b0bf1c75f212bf..7dc4875c9cb05bf146505c0dc0dab543fb326bd3 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1892,6 +1892,7 @@ pam_srv_tests_SOURCES = \ - pam_srv_tests_CFLAGS = \ - -U SSSD_LIBEXEC_PATH -DSSSD_LIBEXEC_PATH=\"$(abs_builddir)\" \ - $(AM_CFLAGS) \ -+ -DSSS_P11_CHILD_TIMEOUT=30 \ - $(NULL) - pam_srv_tests_LDFLAGS = \ - -Wl,-wrap,sss_packet_get_body \ -diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c -index 3b84fb864c5a1b08dc4126ff97e258a792f312bc..aa5c20906a36351e425304122517c81676e730b7 100644 ---- a/src/responder/pam/pamsrv_cmd.c -+++ b/src/responder/pam/pamsrv_cmd.c -@@ -43,6 +43,11 @@ enum pam_verbosity { - - #define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT - -+/* TODO: Should we make this configurable? */ -+#ifndef SSS_P11_CHILD_TIMEOUT -+#define SSS_P11_CHILD_TIMEOUT 10 -+#endif -+ - static errno_t - pam_null_last_online_auth_with_curr_token(struct sss_domain_info *domain, - const char *username); -@@ -1122,7 +1127,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) - - if (may_do_cert_auth(pctx, pd)) { - req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd, -- pctx->nss_db, 10, pd); -+ pctx->nss_db, SSS_P11_CHILD_TIMEOUT, pd); - if (req == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n"); - ret = ENOMEM; -@@ -1338,7 +1343,7 @@ static void pam_forwarder_cb(struct tevent_req *req) - - if (may_do_cert_auth(pctx, pd)) { - req = pam_check_cert_send(cctx, cctx->ev, pctx->p11_child_debug_fd, -- pctx->nss_db, 10, pd); -+ pctx->nss_db, SSS_P11_CHILD_TIMEOUT, pd); - if (req == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "pam_check_cert_send failed.\n"); - ret = ENOMEM; --- -2.4.3 - diff --git a/SOURCES/0060-PAM-Fix-domain-for-UPN-based-lookups.patch b/SOURCES/0060-PAM-Fix-domain-for-UPN-based-lookups.patch new file mode 100644 index 0000000..ca64d2b --- /dev/null +++ b/SOURCES/0060-PAM-Fix-domain-for-UPN-based-lookups.patch @@ -0,0 +1,52 @@ +From 3467754b1e32e648b3013244dcbac51677a089eb Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 22 Jul 2016 17:34:20 +0200 +Subject: [PATCH 60/62] PAM: Fix domain for UPN based lookups + +Since sysdb_search_user_by_upn() searches the whole cache we have to set +the domain so that it matches the result. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 9b8fcf685c5ca70a5067a621385bcdc8d9fd6469) +--- + src/responder/pam/pamsrv_cmd.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 1c759f009321cbb322fce624b506ed07f93f997b..66564f5d301a53dcdb5967f43ef4afdb897e9974 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -1474,6 +1474,7 @@ static int pam_check_user_search(struct pam_auth_req *preq) + static const char *user_attrs[] = SYSDB_PW_ATTRS; + struct ldb_message *msg; + struct ldb_result *res; ++ const char *sysdb_name; + + while (dom) { + /* if it is a domainless search, skip domains that require fully +@@ -1533,6 +1534,22 @@ static int pam_check_user_search(struct pam_auth_req *preq) + + if (preq->pd->name_is_upn) { + ret = sysdb_search_user_by_upn(preq, dom, name, user_attrs, &msg); ++ ++ /* Since sysdb_search_user_by_upn() searches the whole cache we ++ * have to set the domain so that it matches the result. */ ++ sysdb_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); ++ if (sysdb_name == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Cached entry has no name.\n"); ++ return EINVAL; ++ } ++ preq->domain = find_domain_by_object_name(get_domains_head(dom), ++ sysdb_name); ++ if (preq->domain == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot find matching domain for [%s].\n", ++ sysdb_name); ++ return EINVAL; ++ } + } else { + ret = sysdb_getpwnam_with_views(preq, dom, name, &res); + if (res->count > 1) { +-- +2.4.11 + diff --git a/SOURCES/0060-SYSDB-Index-the-objectSIDString-attribute.patch b/SOURCES/0060-SYSDB-Index-the-objectSIDString-attribute.patch deleted file mode 100644 index 660e3a1..0000000 --- a/SOURCES/0060-SYSDB-Index-the-objectSIDString-attribute.patch +++ /dev/null @@ -1,130 +0,0 @@ -From c50681fc7a1296c278466e834eaddfbf2bc54afb Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 25 Jun 2015 17:33:47 +0200 -Subject: [PATCH] SYSDB: Index the objectSIDString attribute - ---- - src/db/sysdb.c | 7 +++++++ - src/db/sysdb_private.h | 5 ++++- - src/db/sysdb_upgrade.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 61 insertions(+), 1 deletion(-) - -diff --git a/src/db/sysdb.c b/src/db/sysdb.c -index 9da655759c0c35d52854b668693195b3360c5f8b..07a83a8a8e30df1b8e461a8d04866f2dbc53baf8 100644 ---- a/src/db/sysdb.c -+++ b/src/db/sysdb.c -@@ -1265,6 +1265,13 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, - } - } - -+ if (strcmp(version, SYSDB_VERSION_0_16) == 0) { -+ ret = sysdb_upgrade_16(sysdb, &version); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ - /* The version should now match SYSDB_VERSION. - * If not, it means we didn't match any of the - * known older versions. The DB might be -diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h -index 2adb9ff9166441014a8b446ffc170225f2a9629d..c2c8d7a0585463806997c43bd020436edddd8517 100644 ---- a/src/db/sysdb_private.h -+++ b/src/db/sysdb_private.h -@@ -23,6 +23,7 @@ - #ifndef __INT_SYS_DB_H__ - #define __INT_SYS_DB_H__ - -+#define SYSDB_VERSION_0_17 "0.17" - #define SYSDB_VERSION_0_16 "0.16" - #define SYSDB_VERSION_0_15 "0.15" - #define SYSDB_VERSION_0_14 "0.14" -@@ -40,7 +41,7 @@ - #define SYSDB_VERSION_0_2 "0.2" - #define SYSDB_VERSION_0_1 "0.1" - --#define SYSDB_VERSION SYSDB_VERSION_0_16 -+#define SYSDB_VERSION SYSDB_VERSION_0_17 - - #define SYSDB_BASE_LDIF \ - "dn: @ATTRIBUTES\n" \ -@@ -68,6 +69,7 @@ - "@IDXATTR: serviceProtocol\n" \ - "@IDXATTR: sudoUser\n" \ - "@IDXATTR: sshKnownHostsExpire\n" \ -+ "@IDXATTR: objectSIDString\n" \ - "@IDXONE: 1\n" \ - "\n" \ - "dn: @MODULES\n" \ -@@ -120,6 +122,7 @@ int sysdb_upgrade_12(struct sysdb_ctx *sysdb, const char **ver); - int sysdb_upgrade_13(struct sysdb_ctx *sysdb, const char **ver); - int sysdb_upgrade_14(struct sysdb_ctx *sysdb, const char **ver); - int sysdb_upgrade_15(struct sysdb_ctx *sysdb, const char **ver); -+int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver); - - int add_string(struct ldb_message *msg, int flags, - const char *attr, const char *value); -diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c -index 6cebc877b86df7a8035bf95cfa51aa4dae464372..113f24644e3e3de1d4c46d375492c2fe1e6b2f83 100644 ---- a/src/db/sysdb_upgrade.c -+++ b/src/db/sysdb_upgrade.c -@@ -1584,6 +1584,56 @@ done: - return ret; - } - -+int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver) -+{ -+ struct ldb_message *msg; -+ struct upgrade_ctx *ctx; -+ errno_t ret; -+ -+ ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_17, &ctx); -+ if (ret) { -+ return ret; -+ } -+ -+ msg = ldb_msg_new(ctx); -+ if (msg == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST"); -+ if (msg->dn == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ /* add index for objectSIDString */ -+ ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); -+ if (ret != LDB_SUCCESS) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = ldb_msg_add_string(msg, "@IDXATTR", "objectSIDString"); -+ if (ret != LDB_SUCCESS) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = ldb_modify(sysdb->ldb, msg); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ goto done; -+ } -+ -+ /* conversion done, update version number */ -+ ret = update_version(ctx); -+ -+done: -+ ret = finish_upgrade(ret, &ctx, ver); -+ return ret; -+} -+ - /* - * Example template for future upgrades. - * Copy and change version numbers as appropriate. --- -2.4.3 - diff --git a/SOURCES/0061-SDAP-add-special-handling-for-IPA-Kerberos-enterpris.patch b/SOURCES/0061-SDAP-add-special-handling-for-IPA-Kerberos-enterpris.patch new file mode 100644 index 0000000..13145e0 --- /dev/null +++ b/SOURCES/0061-SDAP-add-special-handling-for-IPA-Kerberos-enterpris.patch @@ -0,0 +1,56 @@ +From c2fe77b2277513d01b56dc26391e8e7cfcbe7429 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 22 Jul 2016 12:20:33 +0200 +Subject: [PATCH 61/62] SDAP: add special handling for IPA Kerberos enterprise + principal strings + +Unfortunately principal aliases with an alternative realm are stored in +IPA as the string representation of an enterprise principal, i.e. +name\@alt.realm@IPA.REALM. To allow searches with the plain alias +'name@alt.realm' the returned value is converted before it is saved to +the cache. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 15694ca762f61a414f0017c57ed97a8d57456b80) +--- + src/providers/ldap/sdap_async_users.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c +index 28101a2d8a38f97d09d50a9f7e071a030b4f9719..cccd2506b3e1849101a8a06c39fe6cab263777b6 100644 +--- a/src/providers/ldap/sdap_async_users.c ++++ b/src/providers/ldap/sdap_async_users.c +@@ -143,6 +143,8 @@ int sdap_save_user(TALLOC_CTX *memctx, + char *dom_sid_str = NULL; + struct sss_domain_info *subdomain; + size_t c; ++ char *p1; ++ char *p2; + + DEBUG(SSSDBG_TRACE_FUNC, "Save user\n"); + +@@ -448,6 +450,21 @@ int sdap_save_user(TALLOC_CTX *memctx, + goto done; + } + ++ /* Check for IPA Kerberos enterprise principal strings ++ * 'user\@my.realm@IPA.REALM' and use 'user@my.realm' */ ++ if ( (p1 = strchr(upn,'\\')) != NULL ++ && *(p1 + 1) == '@' ++ && (p2 = strchr(p1 + 2, '@')) != NULL) { ++ *p1 = '\0'; ++ *p2 = '\0'; ++ upn = talloc_asprintf(tmpctx, "%s%s", upn, p1 + 1); ++ if (upn == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ + if (dp_opt_get_bool(opts->basic, SDAP_FORCE_UPPER_CASE_REALM)) { + make_realm_upper_case(upn); + } +-- +2.4.11 + diff --git a/SOURCES/0061-sss_override-print-input-name-if-unable-to-parse-it.patch b/SOURCES/0061-sss_override-print-input-name-if-unable-to-parse-it.patch deleted file mode 100644 index 88aa0bb..0000000 --- a/SOURCES/0061-sss_override-print-input-name-if-unable-to-parse-it.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 90c45ac5b4e67703455b2cf04334ae0fc90188b3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Sat, 15 Aug 2015 13:53:25 +0200 -Subject: [PATCH 61/66] sss_override: print input name if unable to parse it - -Reviewed-by: Jakub Hrozek ---- - src/tools/sss_override.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c -index 5e901e2e31de64dacb171337defc03d428f8ed57..e84a7b922dfcf179f8010dc4cced0eafd89a2c76 100644 ---- a/src/tools/sss_override.c -+++ b/src/tools/sss_override.c -@@ -74,7 +74,7 @@ static int parse_cmdline(struct sss_cmdline *cmdline, - ret = sss_tool_parse_name(tool_ctx, tool_ctx, input_name, - &orig_name, &domain); - if (ret != EOK) { -- fprintf(stderr, _("Unable to parse name.\n")); -+ fprintf(stderr, _("Unable to parse name %s.\n"), input_name); - return ret; - } - --- -2.4.3 - diff --git a/SOURCES/0062-SDAP-add-enterprise-principal-strings-for-user-searc.patch b/SOURCES/0062-SDAP-add-enterprise-principal-strings-for-user-searc.patch new file mode 100644 index 0000000..2077c69 --- /dev/null +++ b/SOURCES/0062-SDAP-add-enterprise-principal-strings-for-user-searc.patch @@ -0,0 +1,201 @@ +From 0274cb7aa22e388e46580b288a7dd957ad955e04 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 22 Jul 2016 20:10:42 +0200 +Subject: [PATCH 62/62] SDAP: add enterprise principal strings for user + searches + +Unfortunately principal aliases with an alternative realm are stored in +IPA as the string representation of an enterprise principal, i.e. +name\@alt.realm@IPA.REALM. To be able to lookup the alternative +principal in LDAP properly the UPN search filter is extended to search +for this type of name as well. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 50a7a92f92e1584702bf25e61a50cb1c09c7e260) +--- + src/providers/ldap/ldap_common.h | 5 +++++ + src/providers/ldap/ldap_id.c | 10 +++++++-- + src/providers/ldap/sdap_async_initgroups.c | 9 ++++++-- + src/providers/ldap/sdap_utils.c | 28 ++++++++++++++++++++++++ + src/tests/cmocka/test_nested_groups.c | 34 ++++++++++++++++++++++++++++++ + 5 files changed, 82 insertions(+), 4 deletions(-) + +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index b39f6789275cf49dd69068ae3de0628b582e4cc5..acdcf47cc5992609cdbf73e4ed9655eade55e214 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -300,6 +300,11 @@ char *sdap_combine_filters(TALLOC_CTX *mem_ctx, + const char *base_filter, + const char *extra_filter); + ++char *get_enterprise_principal_string_filter(TALLOC_CTX *mem_ctx, ++ const char *attr_name, ++ const char *princ, ++ struct dp_option *sdap_basic_opts); ++ + char *sdap_get_access_filter(TALLOC_CTX *mem_ctx, + const char *base_filter); + +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index 5b303ddbd46fd44646cdd50856c784640426ee25..beb31fba16be76ba2ac01f99b87ee6362704f417 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -89,6 +89,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, + enum idmap_error_code err; + char *sid; + char *user_filter = NULL; ++ char *ep_filter; + + req = tevent_req_create(memctx, &state, struct users_get_state); + if (!req) return NULL; +@@ -131,12 +132,17 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, + if (ret != EOK) { + goto done; + } ++ ++ ep_filter = get_enterprise_principal_string_filter(state, ++ ctx->opts->user_map[SDAP_AT_USER_PRINC].name, ++ clean_value, ctx->opts->basic); + /* TODO: Do we have to check the attribute names more carefully? */ +- user_filter = talloc_asprintf(state, "(|(%s=%s)(%s=%s))", ++ user_filter = talloc_asprintf(state, "(|(%s=%s)(%s=%s)%s)", + ctx->opts->user_map[SDAP_AT_USER_PRINC].name, + clean_value, + ctx->opts->user_map[SDAP_AT_USER_EMAIL].name, +- clean_value); ++ clean_value, ++ ep_filter == NULL ? "" : ep_filter); + talloc_zfree(clean_value); + if (user_filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 0a42b18662a8fe12cf048aadfef257b5d9cb48a3..7029427724cc37a4508e11ef5448b421e94dc787 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2682,7 +2682,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + int ret; + char *clean_name; + bool use_id_mapping; +- const char *search_attr; ++ const char *search_attr = NULL; ++ char *ep_filter; + + DEBUG(SSSDBG_TRACE_ALL, "Retrieving info for initgroups call\n"); + +@@ -2743,13 +2744,17 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + return NULL; + } + ++ ep_filter = get_enterprise_principal_string_filter(state, ++ state->opts->user_map[SDAP_AT_USER_PRINC].name, ++ clean_name, state->opts->basic); + state->user_base_filter = + talloc_asprintf(state, +- "(&(|(%s=%s)(%s=%s))(objectclass=%s)", ++ "(&(|(%s=%s)(%s=%s)%s)(objectclass=%s)", + state->opts->user_map[SDAP_AT_USER_PRINC].name, + clean_name, + state->opts->user_map[SDAP_AT_USER_EMAIL].name, + clean_name, ++ ep_filter == NULL ? "" : ep_filter, + state->opts->user_map[SDAP_OC_USER].name); + if (state->user_base_filter == NULL) { + talloc_zfree(req); +diff --git a/src/providers/ldap/sdap_utils.c b/src/providers/ldap/sdap_utils.c +index a3a9642171ca057be5a59dfae192803b84c501c8..0ac3ab2e416d887d00480b5123859c611f514274 100644 +--- a/src/providers/ldap/sdap_utils.c ++++ b/src/providers/ldap/sdap_utils.c +@@ -227,3 +227,31 @@ char *sdap_combine_filters(TALLOC_CTX *mem_ctx, + { + return sdap_combine_filters_ex(mem_ctx, '&', base_filter, extra_filter); + } ++ ++char *get_enterprise_principal_string_filter(TALLOC_CTX *mem_ctx, ++ const char *attr_name, ++ const char *princ, ++ struct dp_option *sdap_basic_opts) ++{ ++ const char *realm; ++ char *p; ++ ++ if (attr_name == NULL || princ == NULL || sdap_basic_opts == NULL) { ++ return NULL; ++ } ++ ++ realm = dp_opt_get_cstring(sdap_basic_opts, SDAP_KRB5_REALM); ++ if (realm == NULL) { ++ return NULL; ++ } ++ ++ p = strchr(princ, '@'); ++ if (p == NULL) { ++ return NULL; ++ } ++ ++ return talloc_asprintf(mem_ctx, "(%s=%.*s\\\\@%s@%s)", attr_name, ++ (int) (p - princ), ++ princ, ++ p + 1, realm); ++} +diff --git a/src/tests/cmocka/test_nested_groups.c b/src/tests/cmocka/test_nested_groups.c +index 6af7e1f4393992e7f16d72b86e40664487896ea1..c8e80f29fb65f8f8935fea32cd4bf3e16de7d06f 100644 +--- a/src/tests/cmocka/test_nested_groups.c ++++ b/src/tests/cmocka/test_nested_groups.c +@@ -31,6 +31,7 @@ + #include "providers/ldap/sdap.h" + #include "providers/ldap/sdap_idmap.h" + #include "providers/ldap/sdap_async_private.h" ++#include "providers/ldap/ldap_opts.h" + + #define TESTS_PATH "tp_" BASE_FILE_STEM + #define TEST_CONF_DB "test_ldap_nested_groups_conf.ldb" +@@ -1242,6 +1243,38 @@ static void nested_group_external_member_test(void **state) + nested_group.gr_name); + } + ++static void test_get_enterprise_principal_string_filter(void **state) ++{ ++ int ret; ++ char *ep_filter; ++ struct dp_option *no_krb5_realm_opt = default_basic_opts; ++ ++ struct dp_option *krb5_realm_opt; ++ ++ ret = dp_copy_defaults(NULL, default_basic_opts, SDAP_OPTS_BASIC, ++ &krb5_realm_opt); ++ assert_int_equal(ret, EOK); ++ ++ ret = dp_opt_set_string(krb5_realm_opt, SDAP_KRB5_REALM, "TEST.DOM"); ++ assert_int_equal(ret, EOK); ++ ++ ep_filter = get_enterprise_principal_string_filter(NULL, NULL, NULL, NULL); ++ assert_null(ep_filter); ++ ++ ep_filter = get_enterprise_principal_string_filter(NULL, "aBC", "p@d.c", ++ no_krb5_realm_opt); ++ assert_null(ep_filter); ++ ++ ep_filter = get_enterprise_principal_string_filter(NULL, "aBC", "p", ++ krb5_realm_opt); ++ assert_null(ep_filter); ++ ++ ep_filter = get_enterprise_principal_string_filter(NULL, "aBC", "p@d.c", ++ krb5_realm_opt); ++ assert_non_null(ep_filter); ++ assert_string_equal(ep_filter, "(aBC=p\\\\@d.c@TEST.DOM)"); ++ talloc_free(ep_filter); ++} + + int main(int argc, const char *argv[]) + { +@@ -1268,6 +1301,7 @@ int main(int argc, const char *argv[]) + cmocka_unit_test_setup_teardown(nested_group_external_member_test, + nested_group_external_member_setup, + nested_group_external_member_teardown), ++ cmocka_unit_test(test_get_enterprise_principal_string_filter), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ +-- +2.4.11 + diff --git a/SOURCES/0062-sss_override-support-domains-that-require-fqname.patch b/SOURCES/0062-sss_override-support-domains-that-require-fqname.patch deleted file mode 100644 index 366c47c..0000000 --- a/SOURCES/0062-sss_override-support-domains-that-require-fqname.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 83e150a2b200ec50f2f02229d9662e1468e286df Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 19 Aug 2015 12:28:21 +0200 -Subject: [PATCH 62/66] sss_override: support domains that require fqname - -Resolves: -https://fedorahosted.org/sssd/ticket/2757 - -Reviewed-by: Jakub Hrozek ---- - src/tools/sss_override.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 57 insertions(+), 2 deletions(-) - -diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c -index e84a7b922dfcf179f8010dc4cced0eafd89a2c76..84b51c537842b7281a523f58c2cfbdfd38e54c72 100644 ---- a/src/tools/sss_override.c -+++ b/src/tools/sss_override.c -@@ -272,6 +272,54 @@ static struct sysdb_attrs *build_group_attrs(TALLOC_CTX *mem_ctx, - return build_attrs(mem_ctx, group->name, 0, group->gid, 0, NULL, NULL); - } - -+static char *get_fqname(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name) -+{ -+ char *fqname; -+ size_t fqlen; -+ size_t check; -+ -+ if (domain == NULL) { -+ return NULL; -+ } -+ -+ /* Get length. */ -+ fqlen = sss_fqname(NULL, 0, domain->names, domain, name); -+ if (fqlen > 0) { -+ fqlen++; /* \0 */ -+ } else { -+ return NULL; -+ } -+ -+ fqname = talloc_zero_array(mem_ctx, char, fqlen); -+ if (fqname == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n"); -+ return NULL; -+ } -+ -+ check = sss_fqname(fqname, fqlen, domain->names, domain, name); -+ if (check != fqlen - 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate a fully qualified name " -+ "for user [%s] in [%s]! Skipping user.\n", name, domain->name); -+ talloc_free(fqname); -+ return NULL; -+ } -+ -+ return fqname; -+} -+ -+static char *get_sysname(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *name) -+{ -+ if (domain == NULL || !domain->fqnames) { -+ return talloc_strdup(mem_ctx, name); -+ } -+ -+ return get_fqname(mem_ctx, domain, name); -+} -+ - static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx, - enum sysdb_member_type type, - const char *name, -@@ -284,6 +332,7 @@ static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx, - struct ldb_result *res; - const char *dn; - const char *strtype; -+ char *sysname; - bool check_next; - errno_t ret; - -@@ -292,16 +341,22 @@ static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx, - return NULL; - } - -+ sysname = get_sysname(tmp_ctx, domain, name); -+ if (sysname == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ - /* Ensure that the object is in cache. */ - switch (type) { - case SYSDB_MEMBER_USER: -- if (getpwnam(name) == NULL) { -+ if (getpwnam(sysname) == NULL) { - ret = ENOENT; - goto done; - } - break; - case SYSDB_MEMBER_GROUP: -- if (getgrnam(name) == NULL) { -+ if (getgrnam(sysname) == NULL) { - ret = ENOENT; - goto done; - } --- -2.4.3 - diff --git a/SOURCES/0063-LDAP-Fix-storing-initgroups-for-users-with-no-supple.patch b/SOURCES/0063-LDAP-Fix-storing-initgroups-for-users-with-no-supple.patch new file mode 100644 index 0000000..ea50e9c --- /dev/null +++ b/SOURCES/0063-LDAP-Fix-storing-initgroups-for-users-with-no-supple.patch @@ -0,0 +1,70 @@ +From e84b8e754f007cd94d9b535d562d8d315f692e8f Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 8 Jul 2016 13:19:31 +0200 +Subject: [PATCH 63/74] LDAP: Fix storing initgroups for users with no + supplementary groups +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If there are no supplementary groups, we tried to qualify a NULL pointer +to an array which resulted in an error. + +Reviewed-by: Lukáš Slebodník +--- + src/providers/ldap/sdap_async_initgroups.c | 32 +++++++++++++++++------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 7029427724cc37a4508e11ef5448b421e94dc787..cc63dff781338e33a9802f97d98174fce2167b4b 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -301,13 +301,15 @@ int sdap_initgr_common_store(struct sysdb_ctx *sysdb, + /* Find the differences between the sysdb and LDAP lists + * Groups in the sysdb only must be removed. + */ +- ldap_fqdnlist = sss_create_internal_fqname_list( +- tmp_ctx, +- (const char * const *) ldap_grouplist, +- domain->name); +- if (ldap_fqdnlist == NULL) { +- ret = ENOMEM; +- goto done; ++ if (ldap_grouplist != NULL) { ++ ldap_fqdnlist = sss_create_internal_fqname_list( ++ tmp_ctx, ++ (const char * const *) ldap_grouplist, ++ domain->name); ++ if (ldap_fqdnlist == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } + } + + ret = diff_string_lists(tmp_ctx, ldap_fqdnlist, sysdb_grouplist, +@@ -1288,13 +1290,15 @@ sdap_initgr_store_user_memberships(struct sdap_initgr_nested_state *state) + } + } + +- ldap_fqdnlist = sss_create_internal_fqname_list( +- tmp_ctx, +- (const char * const *) ldap_parent_name_list, +- state->dom->name); +- if (ldap_fqdnlist == NULL) { +- ret = ENOMEM; +- goto done; ++ if (ldap_parent_name_list) { ++ ldap_fqdnlist = sss_create_internal_fqname_list( ++ tmp_ctx, ++ (const char * const *) ldap_parent_name_list, ++ state->dom->name); ++ if (ldap_fqdnlist == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } + } + + ret = sysdb_get_direct_parents(tmp_ctx, state->dom, SYSDB_MEMBER_USER, +-- +2.4.11 + diff --git a/SOURCES/0063-TOOLS-add-sss_colondb-API.patch b/SOURCES/0063-TOOLS-add-sss_colondb-API.patch deleted file mode 100644 index 0ca7cd6..0000000 --- a/SOURCES/0063-TOOLS-add-sss_colondb-API.patch +++ /dev/null @@ -1,408 +0,0 @@ -From d28ed42ad2030090bc511f5b3381b5137885175d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 19 Aug 2015 12:34:08 +0200 -Subject: [PATCH 63/66] TOOLS: add sss_colondb API - -To simplify import/export users and groups. - -Reviewed-by: Jakub Hrozek ---- - src/tools/common/sss_colondb.c | 305 +++++++++++++++++++++++++++++++++++++++++ - src/tools/common/sss_colondb.h | 73 ++++++++++ - 2 files changed, 378 insertions(+) - create mode 100644 src/tools/common/sss_colondb.c - create mode 100644 src/tools/common/sss_colondb.h - -diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c -new file mode 100644 -index 0000000000000000000000000000000000000000..6b340c80e703342defb8582537db2e4ef3926155 ---- /dev/null -+++ b/src/tools/common/sss_colondb.c -@@ -0,0 +1,305 @@ -+/* -+ Authors: -+ Pavel Březina -+ -+ Copyright (C) 2015 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+ -+#include "util/util.h" -+#include "util/strtonum.h" -+#include "tools/common/sss_colondb.h" -+ -+#define IS_STD_FILE(db) ((db)->file == stdin || (db)->file == stdout) -+ -+static char *read_field_as_string(char *line, -+ const char **_value) -+{ -+ char *rest; -+ char *value; -+ -+ if (line == NULL || *line == '\n' || *line == '\0') { -+ /* There is nothing else to read. */ -+ rest = NULL; -+ value = NULL; -+ goto done; -+ } -+ -+ if (*line == ':') { -+ /* Special case for empty value. */ -+ *line = '\0'; -+ rest = line + 1; -+ value = NULL; -+ goto done; -+ } -+ -+ /* Value starts at current position. */ -+ value = line; -+ -+ /* Find next field delimiter. */ -+ rest = strchr(line, ':'); -+ if (rest == NULL) { -+ /* There is no more field. Remove \n from the end. */ -+ rest = strchr(line, '\n'); -+ if (rest != NULL) { -+ *rest = '\0'; -+ rest = NULL; -+ } -+ goto done; -+ } -+ -+ /* Remove it and step one character further. */ -+ *rest = '\0'; -+ rest++; -+ -+done: -+ *_value = value; -+ -+ return rest; -+} -+ -+static char *read_field_as_uint32(char *line, -+ uint32_t *_value) -+{ -+ const char *str; -+ char *rest; -+ errno_t ret; -+ -+ rest = read_field_as_string(line, &str); -+ if (str == NULL) { -+ *_value = 0; -+ return rest; -+ } -+ -+ *_value = strtouint32(str, NULL, 10); -+ if (errno != 0) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse number [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ -+ *_value = 0; -+ } -+ -+ return rest; -+} -+ -+struct sss_colondb { -+ FILE *file; -+ enum sss_colondb_mode mode; -+}; -+ -+errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx, -+ struct sss_colondb *db, -+ struct sss_colondb_read_field *table) -+{ -+ int readchars; -+ size_t linelen = 0; -+ char *line = NULL; -+ char *tcline; -+ char *rest; -+ errno_t ret; -+ int i; -+ -+ if (db->mode != SSS_COLONDB_READ) { -+ return ERR_INTERNAL; -+ } -+ -+ readchars = getline(&line, &linelen, db->file); -+ if (readchars == -1) { -+ /* Nothing was read. */ -+ if (errno != 0) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read line [%d]: %s", -+ ret, sss_strerror(ret)); -+ return ret; -+ } -+ -+ return EOF; -+ } -+ -+ /* Copy line to mem_ctx. */ -+ tcline = talloc_strdup(mem_ctx, line); -+ -+ free(line); -+ line = NULL; -+ -+ if (tcline == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); -+ return ENOMEM; -+ } -+ -+ rest = tcline; -+ for (i = 0; table[i].type != SSS_COLONDB_SENTINEL; i++) { -+ switch (table[i].type) { -+ case SSS_COLONDB_UINT32: -+ rest = read_field_as_uint32(rest, table[i].data.uint32); -+ break; -+ case SSS_COLONDB_STRING: -+ rest = read_field_as_string(rest, table[i].data.str); -+ break; -+ case SSS_COLONDB_SENTINEL: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Trying to process sentinel?!\n"); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ if (rest == NULL && table[i + 1].type != SSS_COLONDB_SENTINEL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Line contains less values than expected!\n"); -+ ret = EINVAL; -+ goto done; -+ } else if (rest != NULL && table[i + 1].type == SSS_COLONDB_SENTINEL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Line contains more values than expected!\n"); -+ ret = EINVAL; -+ goto done; -+ } -+ } -+ -+ ret = EOK; -+ -+done: -+ if (ret != EOK) { -+ talloc_free(tcline); -+ } -+ -+ return ret; -+} -+ -+errno_t sss_colondb_writeline(struct sss_colondb *db, -+ struct sss_colondb_write_field *table) -+{ -+ TALLOC_CTX *tmp_ctx; -+ char *line = NULL; -+ errno_t ret; -+ int i; -+ -+ if (db->mode != SSS_COLONDB_WRITE) { -+ return ERR_INTERNAL; -+ } -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); -+ return ENOMEM; -+ } -+ -+ for (i = 0; table[i].type != SSS_COLONDB_SENTINEL; i++) { -+ switch (table[i].type) { -+ case SSS_COLONDB_UINT32: -+ if (table[i].data.uint32 == 0) { -+ line = talloc_asprintf_append(line, ":"); -+ } else { -+ line = talloc_asprintf_append(line, ":%u", table[i].data.uint32); -+ } -+ break; -+ case SSS_COLONDB_STRING: -+ if (table[i].data.str == NULL) { -+ line = talloc_asprintf_append(line, ":"); -+ } else { -+ line = talloc_asprintf_append(line, ":%s", table[i].data.str); -+ } -+ break; -+ case SSS_COLONDB_SENTINEL: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Trying to process sentinel?!\n"); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ if (line == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ /* Remove starting : */ -+ line++; -+ -+ fprintf(db->file, "%s\n", line); -+ fflush(db->file); -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -+ -+static int sss_colondb_close(void *pvt) -+{ -+ struct sss_colondb *db = talloc_get_type(pvt, struct sss_colondb); -+ -+ if (db->file == NULL || IS_STD_FILE(db)) { -+ return 0; -+ } -+ -+ fclose(db->file); -+ db->file = NULL; -+ -+ return 0; -+} -+ -+static FILE *open_db(const char *filename, enum sss_colondb_mode mode) -+{ -+ FILE *fp = NULL; -+ errno_t ret; -+ -+ errno = 0; -+ -+ switch (mode) { -+ case SSS_COLONDB_READ: -+ fp = filename == NULL ? stdin : fopen(filename, "r"); -+ break; -+ case SSS_COLONDB_WRITE: -+ fp = filename == NULL ? stdout : fopen(filename, "w"); -+ break; -+ } -+ -+ if (fp == NULL && filename != NULL) { -+ ret = errno; -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to open file %s [%d]: %s\n", -+ filename, ret, sss_strerror(ret)); -+ } -+ -+ return fp; -+} -+ -+struct sss_colondb *sss_colondb_open(TALLOC_CTX *mem_ctx, -+ enum sss_colondb_mode mode, -+ const char *filename) -+{ -+ struct sss_colondb *db; -+ -+ db = talloc_zero(mem_ctx, struct sss_colondb); -+ if (db == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n"); -+ return NULL; -+ } -+ -+ db->file = open_db(filename, mode); -+ db->mode = mode; -+ -+ if (db->file == NULL) { -+ talloc_free(db); -+ return NULL; -+ } -+ -+ talloc_set_destructor((TALLOC_CTX *)db, sss_colondb_close); -+ -+ return db; -+} -diff --git a/src/tools/common/sss_colondb.h b/src/tools/common/sss_colondb.h -new file mode 100644 -index 0000000000000000000000000000000000000000..6edd99cbe3b9ef5c86a48632ac3fc71e8a3e55fe ---- /dev/null -+++ b/src/tools/common/sss_colondb.h -@@ -0,0 +1,73 @@ -+/* -+ Authors: -+ Pavel Březina -+ -+ Copyright (C) 2015 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#ifndef _SSS_COLONDB_H_ -+#define _SSS_COLONDB_H_ -+ -+#include -+#include -+#include -+#include -+ -+struct sss_colondb; -+ -+enum sss_colondb_mode { -+ SSS_COLONDB_READ, -+ SSS_COLONDB_WRITE -+}; -+ -+enum sss_colondb_type { -+ SSS_COLONDB_UINT32, -+ SSS_COLONDB_STRING, -+ SSS_COLONDB_SENTINEL -+}; -+ -+union sss_colondb_write_data { -+ uint32_t uint32; -+ const char *str; -+}; -+ -+union sss_colondb_read_data { -+ uint32_t *uint32; -+ const char **str; -+}; -+ -+struct sss_colondb_write_field { -+ enum sss_colondb_type type; -+ union sss_colondb_write_data data; -+}; -+ -+struct sss_colondb_read_field { -+ enum sss_colondb_type type; -+ union sss_colondb_read_data data; -+}; -+ -+struct sss_colondb *sss_colondb_open(TALLOC_CTX *mem_ctx, -+ enum sss_colondb_mode mode, -+ const char *filename); -+ -+errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx, -+ struct sss_colondb *db, -+ struct sss_colondb_read_field *table); -+ -+errno_t sss_colondb_writeline(struct sss_colondb *db, -+ struct sss_colondb_write_field *table); -+ -+#endif /* _SSS_COLONDB_H_ */ --- -2.4.3 - diff --git a/SOURCES/0064-LDAP-Changing-of-confusing-debug-message.patch b/SOURCES/0064-LDAP-Changing-of-confusing-debug-message.patch new file mode 100644 index 0000000..915b84e --- /dev/null +++ b/SOURCES/0064-LDAP-Changing-of-confusing-debug-message.patch @@ -0,0 +1,31 @@ +From 256f6eafd5ca3cf1ea0a573ec44b3e5e4b74919c Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 12 Jul 2016 09:32:44 +0200 +Subject: [PATCH 64/74] LDAP: Changing of confusing debug message + +This debug message used to confuse our customer. So this patch changes it. + +Resolves: +https://fedorahosted.org/sssd/ticket/3091 + +Reviewed-by: Stephen Gallagher +--- + 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 0c67e54c8a981442b7983a3f68db1bde3a2a6280..4195ba95d911f3956f8cca665310b4b92091e6cd 100644 +--- a/src/providers/ldap/sdap_async.c ++++ b/src/providers/ldap/sdap_async.c +@@ -167,7 +167,7 @@ static void sdap_process_result(struct tevent_context *ev, void *pvt) + if (ret == 0) { + /* this almost always means we have reached the end of + * the list of received messages */ +- DEBUG(SSSDBG_TRACE_INTERNAL, "Trace: ldap_result found nothing!\n"); ++ DEBUG(SSSDBG_TRACE_INTERNAL, "Trace: end of ldap_result list\n"); + return; + } + +-- +2.4.11 + diff --git a/SOURCES/0064-sss_override-decompose-code-better.patch b/SOURCES/0064-sss_override-decompose-code-better.patch deleted file mode 100644 index d1d078a..0000000 --- a/SOURCES/0064-sss_override-decompose-code-better.patch +++ /dev/null @@ -1,478 +0,0 @@ -From fdc64e169e988c4d1bc105ad6ccdfe4817db4c53 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 19 Aug 2015 12:43:15 +0200 -Subject: [PATCH 64/66] sss_override: decompose code better - -Preparation for: -https://fedorahosted.org/sssd/ticket/2737 - -Reviewed-by: Jakub Hrozek ---- - src/tools/sss_override.c | 290 +++++++++++++++++++++++++++++------------------ - 1 file changed, 181 insertions(+), 109 deletions(-) - -diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c -index 84b51c537842b7281a523f58c2cfbdfd38e54c72..9e2ce3325c0bfa33fadb970f725098d7d12ac432 100644 ---- a/src/tools/sss_override.c -+++ b/src/tools/sss_override.c -@@ -171,6 +171,22 @@ done: - return ret; - } - -+errno_t prepare_view_msg(struct sss_domain_info *domain) -+{ -+ errno_t ret; -+ -+ ret = prepare_view(domain); -+ if (ret == EEXIST) { -+ fprintf(stderr, _("Other than " LOCALVIEW " view already exist " -+ "in domain %s.\n"), domain->name); -+ } else if (ret != EOK) { -+ fprintf(stderr, _("Unable to prepare " LOCALVIEW -+ " view in domain %s.\n"), domain->name); -+ } -+ -+ return ret; -+} -+ - static char *build_anchor(TALLOC_CTX *mem_ctx, const char *obj_dn) - { - char *anchor; -@@ -320,17 +336,15 @@ static char *get_sysname(TALLOC_CTX *mem_ctx, - return get_fqname(mem_ctx, domain, name); - } - --static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx, -- enum sysdb_member_type type, -- const char *name, -- struct sss_domain_info *domain, -- struct sss_domain_info *domains, -- struct sss_domain_info **_new_domain) -+static struct sss_domain_info * -+get_object_domain(enum sysdb_member_type type, -+ const char *name, -+ struct sss_domain_info *domain, -+ struct sss_domain_info *domains) - { - TALLOC_CTX *tmp_ctx; - struct sss_domain_info *dom; - struct ldb_result *res; -- const char *dn; - const char *strtype; - char *sysname; - bool check_next; -@@ -427,18 +441,6 @@ static const char *get_object_dn_and_domain(TALLOC_CTX *mem_ctx, - DEBUG(SSSDBG_TRACE_FUNC, "Domain of %s %s is %s\n", - strtype, name, dom->name); - -- dn = ldb_dn_get_linearized(res->msgs[0]->dn); -- if (dn == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "ldb_dn_get_linearized() failed.\n"); -- ret = ENOMEM; -- goto done; -- } -- -- talloc_steal(mem_ctx, dn); -- *_new_domain = dom; -- -- ret = EOK; -- - done: - talloc_free(tmp_ctx); - -@@ -446,35 +448,94 @@ done: - return NULL; - } - -- return dn; -+ return dom; - } - --static const char * get_user_dn_and_domain(TALLOC_CTX *mem_ctx, -- struct sss_domain_info *domains, -- struct override_user *user) -+static errno_t get_user_domain_msg(struct sss_tool_ctx *tool_ctx, -+ struct override_user *user) - { -- return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_USER, -- user->orig_name, user->domain, domains, -- &user->domain); -+ struct sss_domain_info *newdom; -+ const char *domname; -+ -+ newdom = get_object_domain(SYSDB_MEMBER_USER, user->orig_name, -+ user->domain, tool_ctx->domains); -+ if (newdom == NULL) { -+ domname = user->domain == NULL ? "[unknown]" : user->domain->name; -+ fprintf(stderr, _("Unable to find user %s@%s.\n"), -+ user->orig_name, domname); -+ return ENOENT; -+ } -+ -+ user->domain = newdom; -+ return EOK; -+} -+ -+static errno_t get_group_domain_msg(struct sss_tool_ctx *tool_ctx, -+ struct override_group *group) -+{ -+ struct sss_domain_info *newdom; -+ const char *domname; -+ -+ newdom = get_object_domain(SYSDB_MEMBER_GROUP, group->orig_name, -+ group->domain, tool_ctx->domains); -+ if (newdom == NULL) { -+ domname = group->domain == NULL ? "[unknown]" : group->domain->name; -+ fprintf(stderr, _("Unable to find group %s@%s.\n"), -+ group->orig_name, domname); -+ return ENOENT; -+ } -+ -+ group->domain = newdom; -+ return EOK; - } - --static const char * get_group_dn_and_domain(TALLOC_CTX *mem_ctx, -- struct sss_domain_info *domains, -- struct override_group *group) -+static errno_t get_object_dn(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ enum sysdb_member_type type, -+ const char *name, -+ struct ldb_dn **_ldb_dn, -+ const char **_str_dn) - { -- return get_object_dn_and_domain(mem_ctx, SYSDB_MEMBER_GROUP, -- group->orig_name, group->domain, domains, -- &group->domain); -+ struct ldb_dn *ldb_dn; -+ -+ switch (type) { -+ case SYSDB_MEMBER_USER: -+ ldb_dn = sysdb_user_dn(mem_ctx, domain, name); -+ break; -+ case SYSDB_MEMBER_GROUP: -+ ldb_dn = sysdb_group_dn(mem_ctx, domain, name); -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type); -+ return ERR_INTERNAL; -+ } -+ -+ if (ldb_dn == NULL) { -+ return ENOMEM; -+ } -+ -+ if (_str_dn != NULL) { -+ *_str_dn = ldb_dn_get_linearized(ldb_dn); -+ } -+ -+ if (_ldb_dn != NULL) { -+ *_ldb_dn = ldb_dn; -+ } else { -+ talloc_free(ldb_dn); -+ } -+ -+ return EOK; - } - - static errno_t override_object_add(struct sss_domain_info *domain, - enum sysdb_member_type type, - struct sysdb_attrs *attrs, -- const char *obj_dn) -+ const char *name) - { - TALLOC_CTX *tmp_ctx; - const char *anchor; - struct ldb_dn *ldb_dn; -+ const char *str_dn; - errno_t ret; - - tmp_ctx = talloc_new(NULL); -@@ -482,13 +543,12 @@ static errno_t override_object_add(struct sss_domain_info *domain, - return ENOMEM; - } - -- ldb_dn = ldb_dn_new(tmp_ctx, sysdb_ctx_get_ldb(domain->sysdb), obj_dn); -- if (ldb_dn == NULL) { -- ret = ENOMEM; -+ ret = get_object_dn(tmp_ctx, domain, type, name, &ldb_dn, &str_dn); -+ if (ret != EOK) { - goto done; - } - -- anchor = build_anchor(tmp_ctx, obj_dn); -+ anchor = build_anchor(tmp_ctx, str_dn); - if (anchor == NULL) { - ret = ENOMEM; - goto done; -@@ -499,7 +559,7 @@ static errno_t override_object_add(struct sss_domain_info *domain, - goto done; - } - -- DEBUG(SSSDBG_TRACE_FUNC, "Creating override for %s\n", obj_dn); -+ DEBUG(SSSDBG_TRACE_FUNC, "Creating override for %s\n", str_dn); - - ret = sysdb_store_override(domain, LOCALVIEW, type, attrs, ldb_dn); - -@@ -508,13 +568,70 @@ done: - return ret; - } - -+static errno_t override_user(struct sss_tool_ctx *tool_ctx, -+ struct override_user *user) -+{ -+ struct sysdb_attrs *attrs; -+ errno_t ret; -+ -+ ret = prepare_view_msg(user->domain); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ attrs = build_user_attrs(tool_ctx, user); -+ if (attrs == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -+ return ENOMEM; -+ } -+ -+ ret = override_object_add(user->domain, SYSDB_MEMBER_USER, attrs, -+ user->orig_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+static errno_t override_group(struct sss_tool_ctx *tool_ctx, -+ struct override_group *group) -+{ -+ struct sysdb_attrs *attrs; -+ errno_t ret; -+ -+ ret = prepare_view_msg(group->domain); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ attrs = build_group_attrs(tool_ctx, group); -+ if (attrs == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -+ return ENOMEM; -+ } -+ -+ ret = override_object_add(group->domain, SYSDB_MEMBER_GROUP, attrs, -+ group->orig_name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ return ret; -+ } -+ -+ return EOK; -+} -+ - static errno_t override_object_del(struct sss_domain_info *domain, -- const char *obj_dn) -+ enum sysdb_member_type type, -+ const char *name) - { - TALLOC_CTX *tmp_ctx; -- const char *anchor; -- struct ldb_dn *override_dn; - struct ldb_message *msg; -+ struct ldb_dn *override_dn; -+ struct ldb_dn *ldb_dn; -+ const char *str_dn; -+ const char *anchor; - errno_t ret; - int sret; - bool in_transaction = false; -@@ -525,7 +642,12 @@ static errno_t override_object_del(struct sss_domain_info *domain, - return ENOMEM; - } - -- anchor = build_anchor(tmp_ctx, obj_dn); -+ ret = get_object_dn(tmp_ctx, domain, type, name, &ldb_dn, &str_dn); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ anchor = build_anchor(tmp_ctx, str_dn); - if (anchor == NULL) { - ret = ENOMEM; - goto done; -@@ -538,7 +660,7 @@ static errno_t override_object_del(struct sss_domain_info *domain, - goto done; - } - -- DEBUG(SSSDBG_TRACE_FUNC, "Removing override for %s\n", obj_dn); -+ DEBUG(SSSDBG_TRACE_FUNC, "Removing override for %s\n", str_dn); - - ret = sysdb_transaction_start(domain->sysdb); - if (ret != EOK) { -@@ -559,7 +681,7 @@ static errno_t override_object_del(struct sss_domain_info *domain, - goto done; - } - -- msg->dn = ldb_dn_new(msg, ldb, obj_dn); -+ msg->dn = talloc_steal(msg, ldb_dn); - if (msg->dn == NULL) { - ret = ENOMEM; - goto done; -@@ -607,8 +729,6 @@ static int override_user_add(struct sss_cmdline *cmdline, - void *pvt) - { - struct override_user user = {NULL}; -- struct sysdb_attrs *attrs; -- const char *dn; - int ret; - - ret = parse_cmdline_user_add(cmdline, tool_ctx, &user); -@@ -617,34 +737,13 @@ static int override_user_add(struct sss_cmdline *cmdline, - return EXIT_FAILURE; - } - -- dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user); -- if (dn == NULL) { -- fprintf(stderr, _("Unable to find user %s@%s.\n"), -- user.orig_name, -- user.domain == NULL ? "[unknown]" : user.domain->name); -- return EXIT_FAILURE; -- } -- -- ret = prepare_view(user.domain); -- if (ret == EEXIST) { -- fprintf(stderr, _("Other than LOCAL view already exist in " -- "domain %s.\n"), user.domain->name); -- return EXIT_FAILURE; -- } else if (ret != EOK) { -- fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"), -- ret, sss_strerror(ret)); -- return EXIT_FAILURE; -- } -- -- attrs = build_user_attrs(tool_ctx, &user); -- if (attrs == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -+ ret = get_user_domain_msg(tool_ctx, &user); -+ if (ret != EOK) { - return EXIT_FAILURE; - } - -- ret = override_object_add(user.domain, SYSDB_MEMBER_USER, attrs, dn); -+ ret = override_user(tool_ctx, &user); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); - return EXIT_FAILURE; - } - -@@ -656,7 +755,6 @@ static int override_user_del(struct sss_cmdline *cmdline, - void *pvt) - { - struct override_user user = {NULL}; -- const char *dn; - int ret; - - ret = parse_cmdline_user_del(cmdline, tool_ctx, &user); -@@ -665,16 +763,14 @@ static int override_user_del(struct sss_cmdline *cmdline, - return EXIT_FAILURE; - } - -- dn = get_user_dn_and_domain(tool_ctx, tool_ctx->domains, &user); -- if (dn == NULL) { -- fprintf(stderr, _("Unable to find user %s@%s.\n"), -- user.orig_name, user.domain->name); -+ ret = get_user_domain_msg(tool_ctx, &user); -+ if (ret != EOK) { - return EXIT_FAILURE; - } - -- ret = override_object_del(user.domain, dn); -+ ret = override_object_del(user.domain, SYSDB_MEMBER_USER, user.orig_name); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to delete override object.\n"); - return EXIT_FAILURE; - } - -@@ -686,8 +782,6 @@ static int override_group_add(struct sss_cmdline *cmdline, - void *pvt) - { - struct override_group group = {NULL}; -- struct sysdb_attrs *attrs; -- const char *dn; - int ret; - - ret = parse_cmdline_group_add(cmdline, tool_ctx, &group); -@@ -696,33 +790,13 @@ static int override_group_add(struct sss_cmdline *cmdline, - return EXIT_FAILURE; - } - -- dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group); -- if (dn == NULL) { -- fprintf(stderr, _("Unable to find group %s@%s.\n"), -- group.orig_name, group.domain->name); -- return EXIT_FAILURE; -- } -- -- ret = prepare_view(group.domain); -- if (ret == EEXIST) { -- fprintf(stderr, _("Other than LOCAL view already exist in " -- "domain %s.\n"), group.domain->name); -- return EXIT_FAILURE; -- } else if (ret != EOK) { -- fprintf(stderr, _("Unable to prepare view [%d]: %s.\n"), -- ret, sss_strerror(ret)); -- return EXIT_FAILURE; -- } -- -- attrs = build_group_attrs(tool_ctx, &group); -- if (attrs == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -+ ret = get_group_domain_msg(tool_ctx, &group); -+ if (ret != EOK) { - return EXIT_FAILURE; - } - -- ret = override_object_add(group.domain, SYSDB_MEMBER_GROUP, attrs, dn); -+ ret = override_group(tool_ctx, &group); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); - return EXIT_FAILURE; - } - -@@ -734,7 +808,6 @@ static int override_group_del(struct sss_cmdline *cmdline, - void *pvt) - { - struct override_group group = {NULL}; -- const char *dn; - int ret; - - ret = parse_cmdline_group_del(cmdline, tool_ctx, &group); -@@ -743,16 +816,15 @@ static int override_group_del(struct sss_cmdline *cmdline, - return EXIT_FAILURE; - } - -- dn = get_group_dn_and_domain(tool_ctx, tool_ctx->domains, &group); -- if (dn == NULL) { -- fprintf(stderr, _("Unable to find group %s@%s.\n"), -- group.orig_name, group.domain->name); -+ ret = get_group_domain_msg(tool_ctx, &group); -+ if (ret != EOK) { - return EXIT_FAILURE; - } - -- ret = override_object_del(group.domain, dn); -+ ret = override_object_del(group.domain, SYSDB_MEMBER_GROUP, -+ group.orig_name); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to delete override object.\n"); - return EXIT_FAILURE; - } - --- -2.4.3 - diff --git a/SOURCES/0065-LDAP-Use-FQDN-when-linking-parent-LDAP-groups.patch b/SOURCES/0065-LDAP-Use-FQDN-when-linking-parent-LDAP-groups.patch new file mode 100644 index 0000000..d381162 --- /dev/null +++ b/SOURCES/0065-LDAP-Use-FQDN-when-linking-parent-LDAP-groups.patch @@ -0,0 +1,35 @@ +From 8798dbf0af2850c5775e0d50165d70b17a031050 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 3 Aug 2016 13:18:51 +0200 +Subject: [PATCH 65/74] LDAP: Use FQDN when linking parent LDAP groups +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: + https://fedorahosted.org/sssd/ticket/3093 + +Because we compare the list of LDAP names with the list of sysdb names, +we need to qualify the list of LDAP names before running the diff. + +Reviewed-by: Lukáš Slebodník +--- + src/providers/ldap/sdap_async_initgroups.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index cc63dff781338e33a9802f97d98174fce2167b4b..82c708c226bf1a645ff5a395947dfdbad71e0f1f 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2080,7 +2080,7 @@ rfc2307bis_group_memberships_build(hash_entry_t *item, void *user_data) + } + + if (group->parents_count > 0) { +- ret = sysdb_attrs_primary_name_list(mstate->dom, tmp_ctx, ++ ret = sysdb_attrs_primary_fqdn_list(mstate->dom, tmp_ctx, + group->ldap_parents, group->parents_count, + mstate->opts->group_map[SDAP_AT_GROUP_NAME].name, + &ldap_parents_names_list); +-- +2.4.11 + diff --git a/SOURCES/0065-sss_override-support-import-and-export.patch b/SOURCES/0065-sss_override-support-import-and-export.patch deleted file mode 100644 index f9d2098..0000000 --- a/SOURCES/0065-sss_override-support-import-and-export.patch +++ /dev/null @@ -1,794 +0,0 @@ -From ee8f6d929ab3a047e05b4522cb0d61273293e2c4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Wed, 19 Aug 2015 12:35:12 +0200 -Subject: [PATCH 65/66] sss_override: support import and export - -Resolves: -https://fedorahosted.org/sssd/ticket/2737 - -Reviewed-by: Jakub Hrozek ---- - Makefile.am | 2 + - src/man/sss_override.8.xml | 88 +++++++ - src/tools/sss_override.c | 588 ++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 675 insertions(+), 3 deletions(-) - -diff --git a/Makefile.am b/Makefile.am -index 7dc4875c9cb05bf146505c0dc0dab543fb326bd3..e1102333b019e32c516c59c5fa969c970b688737 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -651,6 +651,7 @@ dist_noinst_HEADERS = \ - src/lib/sifp/sss_sifp_private.h \ - src/tests/cmocka/test_utils.h \ - src/tools/common/sss_tools.h \ -+ src/tools/common/sss_colondb.h \ - $(NULL) - - -@@ -1331,6 +1332,7 @@ sss_signal_LDADD = \ - - sss_override_SOURCES = \ - src/tools/sss_override.c \ -+ src/tools/common/sss_colondb.c \ - $(SSSD_TOOLS_OBJ) \ - $(NULL) - sss_override_LDADD = \ -diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml -index ec9a7bb75c13f4f18ece7f5f84baede14a8a1e2e..d289f5b7dfa7fbd328831b4c71d45b4c555225cf 100644 ---- a/src/man/sss_override.8.xml -+++ b/src/man/sss_override.8.xml -@@ -77,6 +77,50 @@ - - - -+ -+ FILE -+ -+ -+ -+ Import user overrides from FILE. -+ Data format is similar to standard passwd file. -+ The format is: -+ -+ -+ original_name:name:uid:gid:gecos:home:shell -+ -+ -+ where original_name is original name of the user whose -+ attributes should be overridden. The rest of fields -+ correspond to new values. You can omit a value simply -+ by leaving corresponding field empty. -+ -+ -+ Examples: -+ -+ -+ ckent:superman:::::: -+ -+ -+ ckent@krypton.com::501:501:Superman:/home/earth:/bin/bash -+ -+ -+ -+ -+ -+ -+ FILE -+ -+ -+ -+ Export all overridden attributes and store them in -+ FILE. See -+ user-import for data format. -+ -+ -+ -+ -+ - - NAME - NAME -@@ -99,6 +143,50 @@ - - - -+ -+ -+ -+ FILE -+ -+ -+ -+ Import group overrides from FILE. -+ Data format is similar to standard group file. -+ The format is: -+ -+ -+ original_name:name:gid -+ -+ -+ where original_name is original name of the group whose -+ attributes should be overridden. The rest of fields -+ correspond to new values. You can omit a value simply -+ by leaving corresponding field empty. -+ -+ -+ Examples: -+ -+ -+ admins:administrators: -+ -+ -+ Domain Users:Users:501 -+ -+ -+ -+ -+ -+ -+ FILE -+ -+ -+ -+ Export all overridden attributes and store them in -+ FILE. See -+ group-import for data format. -+ -+ -+ - - - -diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c -index 9e2ce3325c0bfa33fadb970f725098d7d12ac432..ee8351ea97e5efe0d449dc646c6136b32ceec2c6 100644 ---- a/src/tools/sss_override.c -+++ b/src/tools/sss_override.c -@@ -23,8 +23,10 @@ - #include "util/util.h" - #include "db/sysdb.h" - #include "tools/common/sss_tools.h" -+#include "tools/common/sss_colondb.h" - - #define LOCALVIEW SYSDB_LOCAL_VIEW_NAME -+#define ORIGNAME "originalName" - - struct override_user { - const char *input_name; -@@ -135,6 +137,40 @@ static int parse_cmdline_group_del(struct sss_cmdline *cmdline, - &group->orig_name, &group->domain); - } - -+static int parse_cmdline_import(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ const char **_file) -+{ -+ int ret; -+ -+ ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL, -+ NULL, NULL, "FILE", "File to import the data from.", -+ _file); -+ if (ret != EXIT_SUCCESS) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); -+ return ret; -+ } -+ -+ return EXIT_SUCCESS; -+} -+ -+static int parse_cmdline_export(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ const char **_file) -+{ -+ int ret; -+ -+ ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL, -+ NULL, NULL, "FILE", "File to export the data to.", -+ _file); -+ if (ret != EXIT_SUCCESS) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); -+ return ret; -+ } -+ -+ return EXIT_SUCCESS; -+} -+ - static errno_t prepare_view(struct sss_domain_info *domain) - { - char *viewname = NULL; -@@ -293,8 +329,8 @@ static char *get_fqname(TALLOC_CTX *mem_ctx, - const char *name) - { - char *fqname; -- size_t fqlen; -- size_t check; -+ int fqlen; -+ int check; - - if (domain == NULL) { - return NULL; -@@ -315,7 +351,7 @@ static char *get_fqname(TALLOC_CTX *mem_ctx, - } - - check = sss_fqname(fqname, fqlen, domain->names, domain, name); -- if (check != fqlen - 1) { -+ if (check < 0 || check != fqlen - 1) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate a fully qualified name " - "for user [%s] in [%s]! Skipping user.\n", name, domain->name); - talloc_free(fqname); -@@ -724,6 +760,246 @@ done: - return ret; - } - -+static errno_t append_name(struct sss_domain_info *domain, -+ struct ldb_message *override) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb); -+ struct ldb_dn *dn; -+ struct ldb_message **msgs; -+ const char *attrs[] = {SYSDB_NAME, NULL}; -+ const char *name; -+ const char *fqname; -+ size_t count; -+ errno_t ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); -+ return ENOMEM; -+ } -+ -+ dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, override, -+ SYSDB_OVERRIDE_OBJECT_DN); -+ if (dn == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing overrideObjectDN?\n"); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_BASE, -+ NULL, attrs, &count, &msgs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } else if (count != 1) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "More than one user found?\n"); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL); -+ if (name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Object with no name?\n"); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ fqname = get_fqname(tmp_ctx, domain, name); -+ if (fqname == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get fqname\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ret = ldb_msg_add_string(override, ORIGNAME, fqname); -+ if (ret != LDB_SUCCESS) { -+ ret = sysdb_error_to_errno(ret); -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute to msg\n"); -+ goto done; -+ } -+ -+ talloc_steal(override, fqname); -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -+ -+static errno_t list_overrides(TALLOC_CTX *mem_ctx, -+ const char *filter, -+ const char **attrs, -+ struct sss_domain_info *domain, -+ size_t *_count, -+ struct ldb_message ***_msgs) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_dn *dn; -+ struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb); -+ size_t count; -+ struct ldb_message **msgs; -+ size_t i; -+ int ret; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); -+ return ENOMEM; -+ } -+ -+ /* Acquire list of override objects. */ -+ dn = ldb_dn_new_fmt(tmp_ctx, ldb, SYSDB_TMPL_VIEW_SEARCH_BASE, LOCALVIEW); -+ if (dn == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt() failed.\n"); -+ ret = EIO; -+ goto done; -+ } -+ -+ ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_SUBTREE, -+ filter, attrs, &count, &msgs); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ /* Amend messages with original name. */ -+ for (i = 0; i < count; i++) { -+ ret = append_name(domain, msgs[i]); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to append name [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ } -+ -+ *_msgs = talloc_steal(mem_ctx, msgs); -+ *_count = count; -+ -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ return ret; -+} -+ -+static struct override_user * -+list_user_overrides(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct override_user *objs; -+ struct ldb_message **msgs; -+ size_t count; -+ size_t i; -+ errno_t ret; -+ const char *attrs[] = SYSDB_PW_ATTRS; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); -+ return NULL; -+ } -+ -+ ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_USER_CLASS ")", -+ attrs, domain, &count, &msgs); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ objs = talloc_zero_array(tmp_ctx, struct override_user, count + 1); -+ if (objs == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (i = 0; i < count; i++) { -+ objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME, -+ NULL); -+ if (objs[i].orig_name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n"); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL); -+ objs[i].uid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_UIDNUM, 0); -+ objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0); -+ objs[i].home = ldb_msg_find_attr_as_string(msgs[i], SYSDB_HOMEDIR, NULL); -+ objs[i].shell = ldb_msg_find_attr_as_string(msgs[i], SYSDB_SHELL, NULL); -+ objs[i].gecos = ldb_msg_find_attr_as_string(msgs[i], SYSDB_GECOS, NULL); -+ } -+ -+ talloc_steal(mem_ctx, objs); -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ if (ret != EOK) { -+ return NULL; -+ } -+ -+ return objs; -+} -+ -+static struct override_group * -+list_group_overrides(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct override_group *objs; -+ struct ldb_message **msgs; -+ size_t count; -+ size_t i; -+ errno_t ret; -+ const char *attrs[] = SYSDB_GRSRC_ATTRS; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); -+ return NULL; -+ } -+ -+ ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_GROUP_CLASS ")", -+ attrs, domain, &count, &msgs); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ objs = talloc_zero_array(tmp_ctx, struct override_group, count + 1); -+ if (objs == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (i = 0; i < count; i++) { -+ objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME, -+ NULL); -+ if (objs[i].orig_name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n"); -+ ret = ERR_INTERNAL; -+ goto done; -+ } -+ -+ objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL); -+ objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0); -+ } -+ -+ talloc_steal(mem_ctx, objs); -+ -+done: -+ talloc_free(tmp_ctx); -+ -+ if (ret != EOK) { -+ return NULL; -+ } -+ -+ return objs; -+} -+ - static int override_user_add(struct sss_cmdline *cmdline, - struct sss_tool_ctx *tool_ctx, - void *pvt) -@@ -777,6 +1053,161 @@ static int override_user_del(struct sss_cmdline *cmdline, - return EXIT_SUCCESS; - } - -+static int override_user_import(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct sss_colondb *db; -+ const char *filename; -+ struct override_user obj; -+ int linenum = 1; -+ errno_t ret; -+ int exit; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ /** -+ * Format: orig_name:name:uid:gid:gecos:home:shell -+ */ -+ struct sss_colondb_read_field table[] = { -+ {SSS_COLONDB_STRING, {.str = &obj.input_name}}, -+ {SSS_COLONDB_STRING, {.str = &obj.name}}, -+ {SSS_COLONDB_UINT32, {.uint32 = &obj.uid}}, -+ {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}}, -+ {SSS_COLONDB_STRING, {.str = &obj.gecos}}, -+ {SSS_COLONDB_STRING, {.str = &obj.home}}, -+ {SSS_COLONDB_STRING, {.str = &obj.shell}}, -+ {SSS_COLONDB_SENTINEL, {0}} -+ }; -+ -+ ret = parse_cmdline_import(cmdline, tool_ctx, &filename); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename); -+ if (db == NULL) { -+ fprintf(stderr, _("Unable to open %s.\n"), filename); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) { -+ linenum++; -+ -+ ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name, -+ &obj.orig_name, &obj.domain); -+ if (ret != EOK) { -+ fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ ret = get_user_domain_msg(tool_ctx, &obj); -+ if (ret != EOK) { -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ ret = override_user(tool_ctx, &obj); -+ if (ret != EOK) { -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ talloc_free_children(tmp_ctx); -+ } -+ -+ if (ret != EOF) { -+ fprintf(stderr, _("Invalid format on line %d. " -+ "Use --debug option for more information.\n"), linenum); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ exit = EXIT_SUCCESS; -+ -+done: -+ talloc_free(tmp_ctx); -+ return exit; -+} -+ -+static int override_user_export(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ struct sss_colondb *db; -+ const char *filename; -+ struct override_user *objs; -+ struct sss_domain_info *dom; -+ errno_t ret; -+ int exit; -+ int i; -+ -+ ret = parse_cmdline_export(cmdline, tool_ctx, &filename); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename); -+ if (db == NULL) { -+ fprintf(stderr, _("Unable to open %s.\n"), filename); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ dom = tool_ctx->domains; -+ do { -+ objs = list_user_overrides(tool_ctx, tool_ctx->domains); -+ if (objs == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ for (i = 0; objs[i].orig_name != NULL; i++) { -+ /** -+ * Format: orig_name:name:uid:gid:gecos:home:shell -+ */ -+ struct sss_colondb_write_field table[] = { -+ {SSS_COLONDB_STRING, {.str = objs[i].orig_name}}, -+ {SSS_COLONDB_STRING, {.str = objs[i].name}}, -+ {SSS_COLONDB_UINT32, {.uint32 = objs[i].uid}}, -+ {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}}, -+ {SSS_COLONDB_STRING, {.str = objs[i].gecos}}, -+ {SSS_COLONDB_STRING, {.str = objs[i].home}}, -+ {SSS_COLONDB_STRING, {.str = objs[i].shell}}, -+ {SSS_COLONDB_SENTINEL, {0}} -+ }; -+ -+ ret = sss_colondb_writeline(db, table); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ } -+ -+ /* All overrides are under the same subtree, so we don't want to -+ * descent into subdomains. */ -+ dom = get_next_domain(dom, false); -+ } while (dom != NULL); -+ -+ exit = EXIT_SUCCESS; -+ -+done: -+ return exit; -+} -+ - static int override_group_add(struct sss_cmdline *cmdline, - struct sss_tool_ctx *tool_ctx, - void *pvt) -@@ -831,13 +1262,164 @@ static int override_group_del(struct sss_cmdline *cmdline, - return EXIT_SUCCESS; - } - -+static int override_group_import(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct sss_colondb *db; -+ const char *filename; -+ struct override_group obj; -+ int linenum = 1; -+ errno_t ret; -+ int exit; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); -+ return EXIT_FAILURE; -+ } -+ -+ /** -+ * Format: orig_name:name:gid -+ */ -+ struct sss_colondb_read_field table[] = { -+ {SSS_COLONDB_STRING, {.str = &obj.input_name}}, -+ {SSS_COLONDB_STRING, {.str = &obj.name}}, -+ {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}}, -+ {SSS_COLONDB_SENTINEL, {0}} -+ }; -+ -+ ret = parse_cmdline_import(cmdline, tool_ctx, &filename); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename); -+ if (db == NULL) { -+ fprintf(stderr, _("Unable to open %s.\n"), filename); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) { -+ linenum++; -+ -+ ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name, -+ &obj.orig_name, &obj.domain); -+ if (ret != EOK) { -+ fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ ret = get_group_domain_msg(tool_ctx, &obj); -+ if (ret != EOK) { -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ ret = override_group(tool_ctx, &obj); -+ if (ret != EOK) { -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ talloc_free_children(tmp_ctx); -+ } -+ -+ if (ret != EOF) { -+ fprintf(stderr, _("Invalid format on line %d. " -+ "Use --debug option for more information.\n"), linenum); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ exit = EXIT_SUCCESS; -+ -+done: -+ talloc_free(tmp_ctx); -+ return exit; -+} -+ -+static int override_group_export(struct sss_cmdline *cmdline, -+ struct sss_tool_ctx *tool_ctx, -+ void *pvt) -+{ -+ struct sss_colondb *db; -+ const char *filename; -+ struct override_group *objs; -+ struct sss_domain_info *dom; -+ errno_t ret; -+ int exit; -+ int i; -+ -+ ret = parse_cmdline_export(cmdline, tool_ctx, &filename); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename); -+ if (db == NULL) { -+ fprintf(stderr, _("Unable to open %s.\n"), filename); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ dom = tool_ctx->domains; -+ do { -+ objs = list_group_overrides(tool_ctx, tool_ctx->domains); -+ if (objs == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ -+ for (i = 0; objs[i].orig_name != NULL; i++) { -+ /** -+ * Format: orig_name:name:uid:gid:gecos:home:shell -+ */ -+ struct sss_colondb_write_field table[] = { -+ {SSS_COLONDB_STRING, {.str = objs[i].orig_name}}, -+ {SSS_COLONDB_STRING, {.str = objs[i].name}}, -+ {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}}, -+ {SSS_COLONDB_SENTINEL, {0}} -+ }; -+ -+ ret = sss_colondb_writeline(db, table); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n"); -+ exit = EXIT_FAILURE; -+ goto done; -+ } -+ } -+ -+ /* All overrides are under the same subtree, so we don't want to -+ * descent into subdomains. */ -+ dom = get_next_domain(dom, false); -+ } while (dom != NULL); -+ -+ exit = EXIT_SUCCESS; -+ -+done: -+ return exit; -+} -+ - int main(int argc, const char **argv) - { - struct sss_route_cmd commands[] = { - {"user-add", override_user_add}, - {"user-del", override_user_del}, -+ {"user-import", override_user_import}, -+ {"user-export", override_user_export}, - {"group-add", override_group_add}, - {"group-del", override_group_del}, -+ {"group-import", override_group_import}, -+ {"group-export", override_group_export}, - {NULL, NULL} - }; - --- -2.4.3 - diff --git a/SOURCES/0066-NSS-Fix-use-after-free.patch b/SOURCES/0066-NSS-Fix-use-after-free.patch deleted file mode 100644 index 8b2a8f4..0000000 --- a/SOURCES/0066-NSS-Fix-use-after-free.patch +++ /dev/null @@ -1,89 +0,0 @@ -From ddcdb9ecfbbfb7e3ce57c7b97eefa3e59b5a0e78 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 7 Aug 2015 14:29:45 +0200 -Subject: [PATCH 66/66] NSS: Fix use after free - -It can happed if there are two domains and user is not found -in the first one. - -==29279== Invalid read of size 1 -==29279== at 0x4C2CBA2: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) -==29279== by 0x89A7AC4: talloc_strdup (in /usr/lib64/libtalloc.so.2.1.2) -==29279== by 0x11668A: nss_cmd_initgroups_search (nsssrv_cmd.c:4191) -==29279== by 0x118B27: nss_cmd_getby_dp_callback (nsssrv_cmd.c:1208) -==29279== by 0x10F2B4: nsssrv_dp_send_acct_req_done (nsssrv_cmd.c:759) -==29279== by 0x126AFB: sss_dp_internal_get_done (responder_dp.c:802) -==29279== by 0x56EA861: ??? (in /usr/lib64/libdbus-1.so.3.7.4) -==29279== by 0x56EDB50: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.7.4) -==29279== by 0x50721E1: sbus_dispatch (sssd_dbus_connection.c:96) -==29279== by 0x879B22E: tevent_common_loop_timer_delay (tevent_timed.c:341) -==29279== by 0x879C239: epoll_event_loop_once (tevent_epoll.c:911) -==29279== by 0x879A936: std_event_loop_once (tevent_standard.c:114) -==29279== Address 0xbbad240 is 96 bytes inside a block of size 106 free'd -==29279== at 0x4C2AD17: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) -==29279== by 0x89A46E3: _talloc_free (in /usr/lib64/libtalloc.so.2.1.2) -==29279== by 0x116679: nss_cmd_initgroups_search (nsssrv_cmd.c:4190) -==29279== by 0x118B27: nss_cmd_getby_dp_callback (nsssrv_cmd.c:1208) -==29279== by 0x10F2B4: nsssrv_dp_send_acct_req_done (nsssrv_cmd.c:759) -==29279== by 0x126AFB: sss_dp_internal_get_done (responder_dp.c:802) -==29279== by 0x56EA861: ??? (in /usr/lib64/libdbus-1.so.3.7.4) -==29279== by 0x56EDB50: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.7.4) -==29279== by 0x50721E1: sbus_dispatch (sssd_dbus_connection.c:96) -==29279== by 0x879B22E: tevent_common_loop_timer_delay (tevent_timed.c:341) -==29279== by 0x879C239: epoll_event_loop_once (tevent_epoll.c:911) -==29279== by 0x879A936: std_event_loop_once (tevent_standard.c:114) - -Resolves: -https://fedorahosted.org/sssd/ticket/2749 - -Reviewed-by: Jakub Hrozek ---- - src/responder/nss/nsssrv_cmd.c | 6 +++--- - src/responder/nss/nsssrv_private.h | 1 + - 2 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index aa64432d51f15ed17212b8c40eebf5c9322bc784..459634b8d7a590a196ad47a17cd52729fc633ee2 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -4107,7 +4107,7 @@ static int nss_cmd_initgr_send_reply(struct nss_dom_ctx *dctx) - } - - ret = fill_initgr(cctx->creq->out, dctx->domain, dctx->res, nctx, -- dctx->mc_name, cmdctx->name); -+ dctx->mc_name, cmdctx->normalized_name); - if (ret) { - return ret; - } -@@ -4151,14 +4151,14 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx) - /* make sure to update the dctx if we changed domain */ - dctx->domain = dom; - -- talloc_free(name); -+ talloc_zfree(cmdctx->normalized_name); - name = sss_get_cased_name(dctx, cmdctx->name, dom->case_sensitive); - if (!name) return ENOMEM; - - name = sss_reverse_replace_space(cmdctx, name, - nctx->rctx->override_space); - /* save name so it can be used in initgr reply */ -- cmdctx->name = name; -+ cmdctx->normalized_name = name; - if (name == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sss_reverse_replace_space failed\n"); -diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h -index e5a2486f1fb9a8de39ec90f802f596b2c2f6af7f..72f7b75604567f9b95937018e54ba2d60b771f9b 100644 ---- a/src/responder/nss/nsssrv_private.h -+++ b/src/responder/nss/nsssrv_private.h -@@ -31,6 +31,7 @@ struct nss_cmd_ctx { - struct cli_ctx *cctx; - enum sss_cli_command cmd; - char *name; -+ const char *normalized_name; - bool name_is_upn; - uint32_t id; - char *secid; --- -2.4.3 - diff --git a/SOURCES/0066-sssctl-Consistent-commands-naming.patch b/SOURCES/0066-sssctl-Consistent-commands-naming.patch new file mode 100644 index 0000000..35bd2e2 --- /dev/null +++ b/SOURCES/0066-sssctl-Consistent-commands-naming.patch @@ -0,0 +1,330 @@ +From 6f36e763802e35ff2c431e67be20664e221de85f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 25 Jul 2016 13:50:13 +0200 +Subject: [PATCH 66/74] sssctl: Consistent commands naming +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use TOPIC-ACTION pattern for sssctl command +names. + +Resolves: +https://fedorahosted.org/sssd/ticket/3087 + +Reviewed-by: Pavel Březina +Reviewed-by: Lukáš Slebodník +--- + src/tools/common/sss_tools.h | 2 ++ + src/tools/sss_override.c | 26 +++++++++++------------ + src/tools/sssctl/sssctl.c | 22 ++++++++++---------- + src/tools/sssctl/sssctl.h | 43 +++++++++++++++++++-------------------- + src/tools/sssctl/sssctl_cache.c | 18 ++++++++-------- + src/tools/sssctl/sssctl_data.c | 16 +++++++-------- + src/tools/sssctl/sssctl_domains.c | 6 +++--- + src/tools/sssctl/sssctl_logs.c | 4 ++-- + 8 files changed, 69 insertions(+), 68 deletions(-) + +diff --git a/src/tools/common/sss_tools.h b/src/tools/common/sss_tools.h +index a9ebabe21df14eba52f348046c179a91a6394b97..41c8b10e8c2dd8d6a86297b42a71dd5aaf9e556a 100644 +--- a/src/tools/common/sss_tools.h ++++ b/src/tools/common/sss_tools.h +@@ -46,7 +46,9 @@ typedef errno_t + void *pvt); + + #define SSS_TOOL_COMMAND(cmd, msg, err, fn) {cmd, _(msg), err, fn} ++#define SSS_TOOL_COMMAND_NOMSG(cmd, err, fn) {cmd, NULL, err, fn} + #define SSS_TOOL_DELIMITER(message) {"", (message), 0, NULL} ++#define SSS_TOOL_LAST {NULL, NULL, 0, NULL} + + struct sss_route_cmd { + const char *command; +diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c +index 45a28fd7f5366cd85e6ecd13a4846917d18e9613..d41da52e69acdb67b5a6d624254e3b89a8aa27b8 100644 +--- a/src/tools/sss_override.c ++++ b/src/tools/sss_override.c +@@ -1913,19 +1913,19 @@ static int override_group_export(struct sss_cmdline *cmdline, + int main(int argc, const char **argv) + { + struct sss_route_cmd commands[] = { +- {"user-add", NULL, 0, override_user_add}, +- {"user-del", NULL, 0, override_user_del}, +- {"user-find", NULL, 0, override_user_find}, +- {"user-show", NULL, 0, override_user_show}, +- {"user-import", NULL, 0, override_user_import}, +- {"user-export", NULL, 0, override_user_export}, +- {"group-add", NULL, 0, override_group_add}, +- {"group-del", NULL, 0, override_group_del}, +- {"group-find", NULL, 0, override_group_find}, +- {"group-show", NULL, 0, override_group_show}, +- {"group-import", NULL, 0, override_group_import}, +- {"group-export", NULL, 0, override_group_export}, +- {NULL, NULL, 0, NULL} ++ SSS_TOOL_COMMAND_NOMSG("user-add", 0, override_user_add), ++ SSS_TOOL_COMMAND_NOMSG("user-del", 0, override_user_del), ++ SSS_TOOL_COMMAND_NOMSG("user-find", 0, override_user_find), ++ SSS_TOOL_COMMAND_NOMSG("user-show", 0, override_user_show), ++ SSS_TOOL_COMMAND_NOMSG("user-import", 0, override_user_import), ++ SSS_TOOL_COMMAND_NOMSG("user-export", 0, override_user_export), ++ SSS_TOOL_COMMAND_NOMSG("group-add", 0, override_group_add), ++ SSS_TOOL_COMMAND_NOMSG("group-del", 0, override_group_del), ++ SSS_TOOL_COMMAND_NOMSG("group-find", 0, override_group_find), ++ SSS_TOOL_COMMAND_NOMSG("group-show", 0, override_group_show), ++ SSS_TOOL_COMMAND_NOMSG("group-import", 0, override_group_import), ++ SSS_TOOL_COMMAND_NOMSG("group-export", 0, override_group_export), ++ SSS_TOOL_LAST + }; + + return sss_tool_main(argc, argv, commands, NULL); +diff --git a/src/tools/sssctl/sssctl.c b/src/tools/sssctl/sssctl.c +index 86656f136c00234a230b8fc779a0d245f0d125d5..20ea26f8f71c26a925f5c37327635e346f497891 100644 +--- a/src/tools/sssctl/sssctl.c ++++ b/src/tools/sssctl/sssctl.c +@@ -257,25 +257,25 @@ int main(int argc, const char **argv) + { + struct sss_route_cmd commands[] = { + SSS_TOOL_DELIMITER("SSSD Status:"), +- SSS_TOOL_COMMAND("list-domains", "List available domains", 0, sssctl_list_domains), ++ SSS_TOOL_COMMAND("domain-list", "List available domains", 0, sssctl_domain_list), + SSS_TOOL_COMMAND("domain-status", "Print information about domain", 0, sssctl_domain_status), + SSS_TOOL_DELIMITER("Information about cached content:"), +- SSS_TOOL_COMMAND("user", "Information about cached user", 0, sssctl_user), +- SSS_TOOL_COMMAND("group", "Information about cached group", 0, sssctl_group), +- SSS_TOOL_COMMAND("netgroup", "Information about cached netgroup", 0, sssctl_netgroup), ++ SSS_TOOL_COMMAND("user-show", "Information about cached user", 0, sssctl_user_show), ++ SSS_TOOL_COMMAND("group-show", "Information about cached group", 0, sssctl_group_show), ++ SSS_TOOL_COMMAND("netgroup-show", "Information about cached netgroup", 0, sssctl_netgroup_show), + SSS_TOOL_DELIMITER("Local data tools:"), +- SSS_TOOL_COMMAND("backup-local-data", "Backup local data", 0, sssctl_backup_local_data), +- SSS_TOOL_COMMAND("restore-local-data", "Restore local data from backup", 0, sssctl_restore_local_data), +- SSS_TOOL_COMMAND("remove-cache", "Backup local data and remove cached content", 0, sssctl_remove_cache), +- SSS_TOOL_COMMAND("upgrade-cache", "Perform cache upgrade", ERR_SYSDB_VERSION_TOO_OLD, sssctl_upgrade_cache), ++ SSS_TOOL_COMMAND("client-data-backup", "Backup local data", 0, sssctl_client_data_backup), ++ SSS_TOOL_COMMAND("client-data-restore", "Restore local data from backup", 0, sssctl_client_data_restore), ++ SSS_TOOL_COMMAND("cache-remove", "Backup local data and remove cached content", 0, sssctl_cache_remove), ++ SSS_TOOL_COMMAND("cache-upgrade", "Perform cache upgrade", ERR_SYSDB_VERSION_TOO_OLD, sssctl_cache_upgrade), + SSS_TOOL_DELIMITER("Log files tools:"), +- SSS_TOOL_COMMAND("remove-logs", "Remove existing SSSD log files", 0, sssctl_remove_logs), +- SSS_TOOL_COMMAND("fetch-logs", "Archive SSSD log files in tarball", 0, sssctl_fetch_logs), ++ SSS_TOOL_COMMAND("logs-remove", "Remove existing SSSD log files", 0, sssctl_logs_remove), ++ SSS_TOOL_COMMAND("logs-fetch", "Archive SSSD log files in tarball", 0, sssctl_logs_fetch), + #ifdef HAVE_LIBINI_CONFIG_V1_3 + SSS_TOOL_DELIMITER("Configuration files tools:"), + SSS_TOOL_COMMAND("config-check", "Perform static analysis of SSSD configuration", 0, sssctl_config_check), + #endif +- {NULL, NULL, 0, NULL} ++ SSS_TOOL_LAST + }; + + return sss_tool_main(argc, argv, commands, NULL); +diff --git a/src/tools/sssctl/sssctl.h b/src/tools/sssctl/sssctl.h +index be624755de531df9ff5a97f5640266801695ef6e..72930ee5c3a1195e90c6e35768f715cbf6a1c4e1 100644 +--- a/src/tools/sssctl/sssctl.h ++++ b/src/tools/sssctl/sssctl.h +@@ -56,52 +56,51 @@ void _sssctl_sifp_error(sss_sifp_ctx *sifp, + #define sssctl_sifp_error(sifp, error, message) \ + _sssctl_sifp_error(sifp, error, _(message)) + +-errno_t sssctl_list_domains(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt); ++errno_t sssctl_domain_list(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt); + + errno_t sssctl_domain_status(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); + +-errno_t sssctl_backup_local_data(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt); +- +-errno_t sssctl_restore_local_data(struct sss_cmdline *cmdline, ++errno_t sssctl_client_data_backup(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); + +-errno_t sssctl_remove_cache(struct sss_cmdline *cmdline, ++errno_t sssctl_client_data_restore(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt); ++ ++errno_t sssctl_cache_remove(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); + +-errno_t sssctl_upgrade_cache(struct sss_cmdline *cmdline, ++errno_t sssctl_cache_upgrade(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); + +-errno_t sssctl_remove_logs(struct sss_cmdline *cmdline, ++errno_t sssctl_logs_remove(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); + +-errno_t sssctl_fetch_logs(struct sss_cmdline *cmdline, ++errno_t sssctl_logs_fetch(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); + +-errno_t sssctl_user(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt); ++errno_t sssctl_user_show(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt); + +-errno_t sssctl_group(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt); ++errno_t sssctl_group_show(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt); + +-errno_t sssctl_netgroup(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt); ++errno_t sssctl_netgroup_show(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt); + + errno_t sssctl_config_check(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); +- + #endif /* _SSSCTL_H_ */ +diff --git a/src/tools/sssctl/sssctl_cache.c b/src/tools/sssctl/sssctl_cache.c +index 4a1f3558ed7064ca40ccf9313d99fbab36e6e4c9..b1a7cc933d58d99fe34a05cb6eabe11a5270cee1 100644 +--- a/src/tools/sssctl/sssctl_cache.c ++++ b/src/tools/sssctl/sssctl_cache.c +@@ -569,9 +569,9 @@ struct sssctl_cache_opts { + int id; + }; + +-errno_t sssctl_user(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt) ++errno_t sssctl_user_show(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt) + { + struct sssctl_cache_opts opts = {0}; + const char *attr; +@@ -616,9 +616,9 @@ errno_t sssctl_user(struct sss_cmdline *cmdline, + return EOK; + } + +-errno_t sssctl_group(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt) ++errno_t sssctl_group_show(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt) + { + struct sssctl_cache_opts opts = {0}; + const char *attr; +@@ -662,9 +662,9 @@ errno_t sssctl_group(struct sss_cmdline *cmdline, + return EOK; + } + +-errno_t sssctl_netgroup(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt) ++errno_t sssctl_netgroup_show(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt) + { + struct sssctl_cache_opts opts = {0}; + errno_t ret; +diff --git a/src/tools/sssctl/sssctl_data.c b/src/tools/sssctl/sssctl_data.c +index 3ab2ddf20006b2d5a26e2f167819677431854eb6..a26ddd8d5200319e75282b738791cf270f0d75a8 100644 +--- a/src/tools/sssctl/sssctl_data.c ++++ b/src/tools/sssctl/sssctl_data.c +@@ -124,9 +124,9 @@ static errno_t sssctl_backup(bool force) + return ret; + } + +-errno_t sssctl_backup_local_data(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt) ++errno_t sssctl_client_data_backup(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt) + { + struct sssctl_data_opts opts = {0}; + errno_t ret; +@@ -184,9 +184,9 @@ static errno_t sssctl_restore(bool force_start, bool force_restart) + return ret; + } + +-errno_t sssctl_restore_local_data(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt) ++errno_t sssctl_client_data_restore(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt) + { + struct sssctl_data_opts opts = {0}; + errno_t ret; +@@ -207,7 +207,7 @@ errno_t sssctl_restore_local_data(struct sss_cmdline *cmdline, + return sssctl_restore(opts.start, opts.restart); + } + +-errno_t sssctl_remove_cache(struct sss_cmdline *cmdline, ++errno_t sssctl_cache_remove(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt) + { +@@ -259,7 +259,7 @@ errno_t sssctl_remove_cache(struct sss_cmdline *cmdline, + return EOK; + } + +-errno_t sssctl_upgrade_cache(struct sss_cmdline *cmdline, ++errno_t sssctl_cache_upgrade(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt) + { +diff --git a/src/tools/sssctl/sssctl_domains.c b/src/tools/sssctl/sssctl_domains.c +index 5aaaf770981a92b80b9376fd244d2d97e0502dac..cfc4e56133213e27496350033d4d28c3f5b5c63d 100644 +--- a/src/tools/sssctl/sssctl_domains.c ++++ b/src/tools/sssctl/sssctl_domains.c +@@ -27,9 +27,9 @@ + #include "sbus/sssd_dbus.h" + #include "responder/ifp/ifp_iface.h" + +-errno_t sssctl_list_domains(struct sss_cmdline *cmdline, +- struct sss_tool_ctx *tool_ctx, +- void *pvt) ++errno_t sssctl_domain_list(struct sss_cmdline *cmdline, ++ struct sss_tool_ctx *tool_ctx, ++ void *pvt) + { + sss_sifp_ctx *sifp; + sss_sifp_error error; +diff --git a/src/tools/sssctl/sssctl_logs.c b/src/tools/sssctl/sssctl_logs.c +index a203474648e3c1719e16146f8f7b484f9d62541c..883f2ac2fa688b672cd8f388e4c571d1a12a32af 100644 +--- a/src/tools/sssctl/sssctl_logs.c ++++ b/src/tools/sssctl/sssctl_logs.c +@@ -34,7 +34,7 @@ struct sssctl_logs_opts { + int archived; + }; + +-errno_t sssctl_remove_logs(struct sss_cmdline *cmdline, ++errno_t sssctl_logs_remove(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt) + { +@@ -74,7 +74,7 @@ errno_t sssctl_remove_logs(struct sss_cmdline *cmdline, + return EOK; + } + +-errno_t sssctl_fetch_logs(struct sss_cmdline *cmdline, ++errno_t sssctl_logs_fetch(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt) + { +-- +2.4.11 + diff --git a/SOURCES/0067-SDAP-sanitize-member-name-before-using-in-filter.patch b/SOURCES/0067-SDAP-sanitize-member-name-before-using-in-filter.patch new file mode 100644 index 0000000..ed5cdfa --- /dev/null +++ b/SOURCES/0067-SDAP-sanitize-member-name-before-using-in-filter.patch @@ -0,0 +1,57 @@ +From a711326867dd901d349c648392b55b6e318196db Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Tue, 2 Aug 2016 15:20:35 +0200 +Subject: [PATCH 67/74] SDAP: sanitize member name before using in filter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It caused an errors. + +(Tue Aug 2 06:29:39 2016) [sssd[be[LDAP]]] [sysdb_cache_search_users] +(0x2000): Search users with filter: +(&(objectclass=user)(nameAlias=t(u)ser@ldap)) +(Tue Aug 2 06:29:39 2016) [sssd[be[LDAP]]] [sysdb_cache_search_users] +(0x0080): Error: 5 (Input/output error) + +Resolves: +https://fedorahosted.org/sssd/ticket/3121 + +Reviewed-by: Pavel Březina +--- + src/providers/ldap/sdap_async_groups.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index 102c1c0384be6da8732d56b7a318ded5a5132360..f19b68b8c403734f88b51a411ba0d009977d3491 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -1501,6 +1501,7 @@ sdap_process_missing_member_2307(struct sdap_process_group_state *state, + const char *filter; + const char *username; + const char *user_dn; ++ char *sanitized_name; + size_t count; + struct ldb_message **msgs = NULL; + static const char *attrs[] = { SYSDB_NAME, NULL }; +@@ -1508,8 +1509,16 @@ sdap_process_missing_member_2307(struct sdap_process_group_state *state, + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) return ENOMEM; + ++ ret = sss_filter_sanitize(tmp_ctx, member_name, &sanitized_name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Failed to sanitize the given name:'%s'.\n", member_name); ++ goto done; ++ } ++ + /* Check for the alias in the sysdb */ +- filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME_ALIAS, member_name); ++ filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME_ALIAS, ++ sanitized_name); + if (!filter) { + ret = ENOMEM; + goto done; +-- +2.4.11 + diff --git a/SOURCES/0067-sss_override-document-debug-options.patch b/SOURCES/0067-sss_override-document-debug-options.patch deleted file mode 100644 index 3dadc13..0000000 --- a/SOURCES/0067-sss_override-document-debug-options.patch +++ /dev/null @@ -1,122 +0,0 @@ -From c8fcc0597ad6399fe42111512d5dc2ff1362f3c8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 25 Aug 2015 12:58:45 +0200 -Subject: [PATCH 67/68] sss_override: document --debug options - -Resolves: -https://fedorahosted.org/sssd/ticket/2758 - -Reviewed-by: Petr Cech ---- - src/man/sss_override.8.xml | 16 ++++++++++++++++ - src/tools/common/sss_tools.c | 25 +++++++++++++++++++++---- - 2 files changed, 37 insertions(+), 4 deletions(-) - -diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml -index d289f5b7dfa7fbd328831b4c71d45b4c555225cf..c2ec5dd41703c7272acf7c9d2c30f20351099791 100644 ---- a/src/man/sss_override.8.xml -+++ b/src/man/sss_override.8.xml -@@ -190,6 +190,22 @@ - - - -+ -+ COMMON OPTIONS -+ -+ Those options are available with all commands. -+ -+ -+ -+ -+ , -+ LEVEL -+ -+ -+ -+ -+ -+ - - - -diff --git a/src/tools/common/sss_tools.c b/src/tools/common/sss_tools.c -index 6bbce3a25ddddc0b23ebc108a917a38e94981b65..d50e9af7d348e984687108895f0fd3448ee9add0 100644 ---- a/src/tools/common/sss_tools.c -+++ b/src/tools/common/sss_tools.c -@@ -36,6 +36,13 @@ struct sss_cmdline { - const char **argv; - }; - -+static void sss_tool_print_common_opts(void) -+{ -+ fprintf(stderr, _("Common options:\n")); -+ fprintf(stderr, " --debug=INT %s\n", -+ _("Enable debug at level")); -+} -+ - static void sss_tool_common_opts(struct sss_tool_ctx *tool_ctx, - int *argc, const char **argv) - { -@@ -201,6 +208,9 @@ int sss_tool_usage(const char *tool_name, - fprintf(stderr, "* %s\n", commands[i].command); - } - -+ fprintf(stderr, _("\n")); -+ sss_tool_print_common_opts(); -+ - return EXIT_FAILURE; - } - -@@ -237,6 +247,13 @@ int sss_tool_route(int argc, const char **argv, - return sss_tool_usage(argv[0], commands); - } - -+static void sss_tool_popt_print_help(poptContext pc) -+{ -+ poptPrintHelp(pc, stderr, 0); -+ fprintf(stderr, "\n"); -+ sss_tool_print_common_opts(); -+} -+ - int sss_tool_popt_ex(struct sss_cmdline *cmdline, - struct poptOption *options, - enum sss_tool_opt require_option, -@@ -286,7 +303,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline, - } else { - fprintf(stderr, _("Invalid option %s: %s\n\n"), - poptBadOption(pc, 0), poptStrerror(ret)); -- poptPrintHelp(pc, stderr, 0); -+ sss_tool_popt_print_help(pc); - ret = EXIT_FAILURE; - goto done; - } -@@ -297,7 +314,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline, - *_fopt = poptGetArg(pc); - if (*_fopt == NULL) { - fprintf(stderr, _("Missing option: %s\n\n"), fopt_help); -- poptPrintHelp(pc, stderr, 0); -+ sss_tool_popt_print_help(pc); - ret = EXIT_FAILURE; - goto done; - } -@@ -305,7 +322,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline, - /* No more arguments expected. If something follows it is an error. */ - if (poptGetArg(pc)) { - fprintf(stderr, _("Only one free argument is expected!\n\n")); -- poptPrintHelp(pc, stderr, 0); -+ sss_tool_popt_print_help(pc); - ret = EXIT_FAILURE; - goto done; - } -@@ -315,7 +332,7 @@ int sss_tool_popt_ex(struct sss_cmdline *cmdline, - if (require_option == SSS_TOOL_OPT_REQUIRED - && ((_fopt != NULL && cmdline->argc < 2) || cmdline->argc < 1)) { - fprintf(stderr, _("At least one option is required!\n\n")); -- poptPrintHelp(pc, stderr, 0); -+ sss_tool_popt_print_help(pc); - ret = EXIT_FAILURE; - goto done; - } --- -2.4.3 - diff --git a/SOURCES/0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch b/SOURCES/0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch deleted file mode 100644 index e3ac8f9..0000000 --- a/SOURCES/0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch +++ /dev/null @@ -1,97 +0,0 @@ -From eaccdcf75b651a0cc4fc02526180f5991a16c553 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Fri, 28 Aug 2015 07:07:40 +0200 -Subject: [PATCH 68/68] NSS: Don't ignore backslash in usernames with ldap - provider - -The regression was caused by changing default domain regex -for ldap provider in ticket #2717 - -Resolves: -https://fedorahosted.org/sssd/ticket/2772 - -Reviewed-by: Sumit Bose ---- - src/responder/nss/nsssrv.c | 4 ++-- - src/tests/cmocka/test_nss_srv.c | 4 ++-- - src/util/usertools.c | 11 ++++++++++- - src/util/util.h | 3 +++ - 4 files changed, 17 insertions(+), 5 deletions(-) - -diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c -index 2b3bca892a5b9c483d1f6f099fd4a6493e9afcab..d8eff7968c4929663412aa56d08414689b921a22 100644 ---- a/src/responder/nss/nsssrv.c -+++ b/src/responder/nss/nsssrv.c -@@ -552,9 +552,9 @@ int nss_process_init(TALLOC_CTX *mem_ctx, - goto fail; - } - -- ret = sss_names_init(nctx, nctx->rctx->cdb, NULL, &nctx->global_names); -+ ret = sss_ad_default_names_ctx(nctx, &nctx->global_names); - if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, "sss_names_init failed.\n"); -+ DEBUG(SSSDBG_CRIT_FAILURE, "sss_ad_default_names_ctx failed.\n"); - goto fail; - } - -diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c -index 84d3413be70bc0af433b7fd23cf7d78b4b9298f1..3cf9f06e61b9e4f13d5d755f7cbd8020194d52d6 100644 ---- a/src/tests/cmocka/test_nss_srv.c -+++ b/src/tests/cmocka/test_nss_srv.c -@@ -1043,8 +1043,8 @@ void test_nss_setup(struct sss_test_conf_param params[], - nss_test_ctx->nctx = mock_nctx(nss_test_ctx); - assert_non_null(nss_test_ctx->nctx); - -- ret = sss_names_init(nss_test_ctx->nctx, nss_test_ctx->tctx->confdb, -- NULL, &nss_test_ctx->nctx->global_names); -+ ret = sss_ad_default_names_ctx(nss_test_ctx->nctx, -+ &nss_test_ctx->nctx->global_names); - assert_int_equal(ret, EOK); - assert_non_null(nss_test_ctx->nctx->global_names); - -diff --git a/src/util/usertools.c b/src/util/usertools.c -index 87a8d7411312c3a80c32374a1fd93bbf0e767a91..ccbf7a0c8c2fb6d1d07afbfe46d978fc33093432 100644 ---- a/src/util/usertools.c -+++ b/src/util/usertools.c -@@ -249,7 +249,8 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, - } - - if (!re_pattern) { -- re_pattern = talloc_strdup(tmpctx, IPA_AD_DEFAULT_RE); -+ re_pattern = talloc_strdup(tmpctx, -+ "(?P[^@]+)@?(?P[^@]*$)"); - if (!re_pattern) { - ret = ENOMEM; - goto done; -@@ -294,6 +295,14 @@ done: - return ret; - } - -+int sss_ad_default_names_ctx(TALLOC_CTX *mem_ctx, -+ struct sss_names_ctx **_out) -+{ -+ return sss_names_init_from_args(mem_ctx, IPA_AD_DEFAULT_RE, -+ CONFDB_DEFAULT_FULL_NAME_FORMAT, -+ _out); -+} -+ - int sss_parse_name(TALLOC_CTX *memctx, - struct sss_names_ctx *snctx, - const char *orig, char **_domain, char **_name) -diff --git a/src/util/util.h b/src/util/util.h -index a20d1d82eb8f10dac515ad25e7e424713bb1c099..c998e91f92b0a86e0f4308ff0c07ff802588b5cf 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -298,6 +298,9 @@ int sss_names_init(TALLOC_CTX *mem_ctx, - const char *domain, - struct sss_names_ctx **out); - -+int sss_ad_default_names_ctx(TALLOC_CTX *mem_ctx, -+ struct sss_names_ctx **_out); -+ - int sss_parse_name(TALLOC_CTX *memctx, - struct sss_names_ctx *snctx, - const char *orig, char **_domain, char **_name); --- -2.4.3 - diff --git a/SOURCES/0068-SDAP-sysdb_search_users-does-not-set-users_count-for.patch b/SOURCES/0068-SDAP-sysdb_search_users-does-not-set-users_count-for.patch new file mode 100644 index 0000000..f82f6d8 --- /dev/null +++ b/SOURCES/0068-SDAP-sysdb_search_users-does-not-set-users_count-for.patch @@ -0,0 +1,51 @@ +From 4e1111d869c8980f81a17b58844c48f1a342d774 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Thu, 4 Aug 2016 08:50:50 +0200 +Subject: [PATCH 68/74] SDAP: sysdb_search_users does not set users_count for + failures +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +==32577== Conditional jump or move depends on uninitialised value(s) +==32577== at 0x140DCE10: sdap_process_missing_member_2307 (sdap_async_groups.c:1556) +==32577== by 0x140DCE10: sdap_process_group_members_2307 (sdap_async_groups.c:1625) +==32577== by 0x140DCE10: sdap_process_group_send (sdap_async_groups.c:1298) +==32577== by 0x140DCE10: sdap_get_groups_process (sdap_async_groups.c:2130) +==32577== by 0x140CFDA8: generic_ext_search_handler.isra.3 (sdap_async.c:1688) +==32577== by 0x140D2416: sdap_get_generic_op_finished (sdap_async.c:1578) +==32577== by 0x140D0DFC: sdap_process_message (sdap_async.c:353) +==32577== by 0x140D0DFC: sdap_process_result (sdap_async.c:197) +==32577== by 0x8BF1B4E: tevent_common_loop_timer_delay (tevent_timed.c:341) +==32577== by 0x8BF2B59: epoll_event_loop_once (tevent_epoll.c:911) +==32577== by 0x8BF1256: std_event_loop_once (tevent_standard.c:114) +==32577== by 0x8BED40C: _tevent_loop_once (tevent.c:533) +==32577== by 0x8BED5AA: tevent_common_loop_wait (tevent.c:637) +==32577== by 0x8BF11F6: std_event_loop_wait (tevent_standard.c:140) +==32577== by 0x529DD02: server_loop (server.c:702) +==32577== by 0x110951: main (data_provider_be.c:587) + +Resolves: +https://fedorahosted.org/sssd/ticket/3121 + +Reviewed-by: Pavel Březina +--- + 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 f19b68b8c403734f88b51a411ba0d009977d3491..72760b75acae4cb6ce15c72f16dae8e859d89847 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -1553,7 +1553,7 @@ sdap_process_missing_member_2307(struct sdap_process_group_state *state, + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Could not add group member %s\n", username); + } +- } else if (ret == ENOENT || count == 0) { ++ } else if (ret == ENOENT) { + /* The entry really does not exist, add a ghost */ + DEBUG(SSSDBG_TRACE_FUNC, "Adding a ghost entry\n"); + ret = sdap_add_group_member_2307(state->ghost_dns, member_name); +-- +2.4.11 + diff --git a/SOURCES/0069-GPO-fix-memory-leak.patch b/SOURCES/0069-GPO-fix-memory-leak.patch deleted file mode 100644 index 7eb04e9..0000000 --- a/SOURCES/0069-GPO-fix-memory-leak.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 69bf6ed59e73e92a52c080b4af57f554f703ab52 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 3 Sep 2015 04:46:50 -0400 -Subject: [PATCH 69/73] GPO: fix memory leak -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves: -https://fedorahosted.org/sssd/ticket/2777 - -Reviewed-by: Michal Židek ---- - src/providers/ad/ad_gpo.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c -index 974fd04b99709055f25ed2a3b77821b3caec09ad..a7ba4b2210115a19a3e4430744d36fe76da20f09 100644 ---- a/src/providers/ad/ad_gpo.c -+++ b/src/providers/ad/ad_gpo.c -@@ -560,14 +560,14 @@ ad_gpo_get_sids(TALLOC_CTX *mem_ctx, - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_initgroups failed: [%d](%s)\n", - ret, sss_strerror(ret)); -- return ret; -+ goto done; - } - - if (res->count == 0) { - ret = ENOENT; - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_initgroups returned empty result\n"); -- return ret; -+ goto done; - } - - user_sid = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SID_STR, NULL); -@@ -602,7 +602,7 @@ ad_gpo_get_sids(TALLOC_CTX *mem_ctx, - *_group_size = num_group_sids + 1; - *_group_sids = talloc_steal(mem_ctx, group_sids); - *_user_sid = talloc_steal(mem_ctx, user_sid); -- return EOK; -+ ret = EOK; - - done: - talloc_free(tmp_ctx); --- -2.4.3 - diff --git a/SOURCES/0069-SYSDB-Sanitize-dn-in-sysdb_get_user_members_recursiv.patch b/SOURCES/0069-SYSDB-Sanitize-dn-in-sysdb_get_user_members_recursiv.patch new file mode 100644 index 0000000..24ea5be --- /dev/null +++ b/SOURCES/0069-SYSDB-Sanitize-dn-in-sysdb_get_user_members_recursiv.patch @@ -0,0 +1,69 @@ +From 0bb66d94542920870effa808861c0c20180111ba Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Tue, 2 Aug 2016 15:20:19 +0200 +Subject: [PATCH 69/74] SYSDB: Sanitize dn in + sysdb_get_user_members_recursively +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There was a crash in nss responder when a group contained +a user with special charactes which shoudl be sanitized before +using in filter. + +==31651== Conditional jump or move depends on uninitialised value(s) +==31651== at 0x8BEA7DE: _talloc_steal_loc (talloc.c:1215) +==31651== by 0x5264889: sysdb_get_user_members_recursively (sysdb_ops.c:4759) +==31651== by 0x5278F61: sysdb_add_group_member_overrides (sysdb_views.c:1375) +==31651== by 0x526677C: sysdb_getgrnam_with_views (sysdb_search.c:799) +==31651== by 0x1172F6: nss_cmd_getgrnam_search (nsssrv_cmd.c:3168) +==31651== by 0x119C67: nss_cmd_getby_dp_callback (nsssrv_cmd.c:1382) +==31651== by 0x10FD14: nsssrv_dp_send_acct_req_done (nsssrv_cmd.c:916) +==31651== by 0x12898B: sss_dp_internal_get_done (responder_dp.c:791) +==31651== by 0x58FF861: complete_pending_call_and_unlock (dbus-connection.c:2314) +==31651== by 0x5902B50: dbus_connection_dispatch (dbus-connection.c:4580) +==31651== by 0x527F261: sbus_dispatch (sssd_dbus_connection.c:96) +==31651== by 0x89D8B4E: tevent_common_loop_timer_delay (tevent_timed.c:341) + +Resolves: +https://fedorahosted.org/sssd/ticket/3121 + +Reviewed-by: Pavel Březina +--- + src/db/sysdb_ops.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index ed177d1730723a61e01167a75a0baca6d81252f8..342e16fb20e2c418745b137162425509ca1fd0cb 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -4722,6 +4722,7 @@ errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx, + struct ldb_result *res; + struct ldb_dn *base_dn; + char *filter; ++ char *sanitized_name; + const char *attrs[] = SYSDB_PW_ATTRS; + struct ldb_message **msgs; + +@@ -4737,8 +4738,17 @@ errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx, + goto done; + } + ++ ret = sss_filter_sanitize(tmp_ctx, ldb_dn_get_linearized(group_dn), ++ &sanitized_name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Failed to sanitize the given name:'%s'.\n", ++ ldb_dn_get_linearized(group_dn)); ++ goto done; ++ } ++ + filter = talloc_asprintf(tmp_ctx, "(&("SYSDB_UC")("SYSDB_MEMBEROF"=%s))", +- ldb_dn_get_linearized(group_dn)); ++ sanitized_name); + if (filter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); + ret = ENOMEM; +-- +2.4.11 + diff --git a/SOURCES/0070-SYSDB-Fix-setting-dataExpireTimestamp-if-sysdb-is-su.patch b/SOURCES/0070-SYSDB-Fix-setting-dataExpireTimestamp-if-sysdb-is-su.patch new file mode 100644 index 0000000..bed5cd3 --- /dev/null +++ b/SOURCES/0070-SYSDB-Fix-setting-dataExpireTimestamp-if-sysdb-is-su.patch @@ -0,0 +1,178 @@ +From ba87a54746b417ad32362f3c6e565c7af8d21afa Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 3 Aug 2016 14:23:39 +0200 +Subject: [PATCH 70/74] SYSDB: Fix setting dataExpireTimestamp if sysdb is + supposed to set the current time +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sysdb is already able to retrieve the current timestamp if the caller +doesn't specify it. However, for the timestamp cache this came too late +and the timestamp cache used zero as the 'now' time. + +Resolves: +https://fedorahosted.org/sssd/ticket/3064 + +Reviewed-by: Pavel Březina +--- + src/db/sysdb_ops.c | 20 ++++---- + src/tests/cmocka/test_sysdb_ts_cache.c | 83 ++++++++++++++++++++++++++++++++++ + 2 files changed, 93 insertions(+), 10 deletions(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 342e16fb20e2c418745b137162425509ca1fd0cb..67006c155098b9fde00a01d424014852c383a325 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -2465,6 +2465,11 @@ int sysdb_store_user(struct sss_domain_info *domain, + errno_t sret = EOK; + bool in_transaction = false; + ++ /* get transaction timestamp */ ++ if (now == 0) { ++ now = time(NULL); ++ } ++ + ret = sysdb_check_and_update_ts_usr(domain, name, attrs, + cache_timeout, now); + if (ret == EOK) { +@@ -2508,11 +2513,6 @@ int sysdb_store_user(struct sss_domain_info *domain, + DEBUG(SSSDBG_TRACE_LIBS, "User %s does not exist.\n", name); + } + +- /* get transaction timestamp */ +- if (!now) { +- now = time(NULL); +- } +- + if (ret == ENOENT) { + /* the user doesn't exist, turn into adding a user */ + ret = sysdb_store_new_user(domain, name, uid, gid, gecos, homedir, +@@ -2700,6 +2700,11 @@ int sysdb_store_group(struct sss_domain_info *domain, + errno_t sret = EOK; + bool in_transaction = false; + ++ /* get transaction timestamp */ ++ if (!now) { ++ now = time(NULL); ++ } ++ + ret = sysdb_check_and_update_ts_grp(domain, name, attrs, + cache_timeout, now); + if (ret == EOK) { +@@ -2741,11 +2746,6 @@ int sysdb_store_group(struct sss_domain_info *domain, + } + } + +- /* get transaction timestamp */ +- if (!now) { +- now = time(NULL); +- } +- + if (new_group) { + ret = sysdb_store_new_group(domain, name, gid, attrs, + cache_timeout, now); +diff --git a/src/tests/cmocka/test_sysdb_ts_cache.c b/src/tests/cmocka/test_sysdb_ts_cache.c +index d5492299647f54e379ea3f305ccc1501c7f6c79f..aa857e7e4823d2d8ba1e1a794b3e2474876e9ab0 100644 +--- a/src/tests/cmocka/test_sysdb_ts_cache.c ++++ b/src/tests/cmocka/test_sysdb_ts_cache.c +@@ -1348,6 +1348,86 @@ static void test_user_byupn(void **state) + talloc_free(res); + } + ++static void test_sysdb_zero_now(void **state) ++{ ++ int ret; ++ struct sysdb_ts_test_ctx *test_ctx = talloc_get_type_abort(*state, ++ struct sysdb_ts_test_ctx); ++ struct ldb_result *res = NULL; ++ uint64_t cache_expire_sysdb; ++ uint64_t cache_expire_ts; ++ struct sysdb_attrs *attrs = NULL; ++ ++ /* Nothing must be stored in either cache at the beginning of the test */ ++ res = sysdb_getpwnam_res(test_ctx, test_ctx->tctx->dom, TEST_USER_NAME); ++ assert_int_equal(res->count, 0); ++ talloc_free(res); ++ ++ res = sysdb_getgrnam_res(test_ctx, test_ctx->tctx->dom, TEST_GROUP_NAME); ++ assert_int_equal(res->count, 0); ++ talloc_free(res); ++ ++ attrs = create_modstamp_attrs(test_ctx, TEST_MODSTAMP_1); ++ assert_non_null(attrs); ++ ++ ret = sysdb_store_user(test_ctx->tctx->dom, TEST_USER_NAME, NULL, ++ TEST_USER_UID, TEST_USER_GID, TEST_USER_NAME, ++ "/home/"TEST_USER_NAME, "/bin/bash", NULL, ++ attrs, NULL, TEST_CACHE_TIMEOUT, ++ 0); ++ talloc_zfree(attrs); ++ assert_int_equal(ret, EOK); ++ ++ attrs = create_modstamp_attrs(test_ctx, TEST_MODSTAMP_1); ++ assert_non_null(attrs); ++ ++ ret = sysdb_store_group(test_ctx->tctx->dom, ++ TEST_GROUP_NAME, ++ TEST_GROUP_GID, ++ attrs, ++ TEST_CACHE_TIMEOUT, ++ 0); ++ talloc_zfree(attrs); ++ assert_int_equal(ret, EOK); ++ talloc_zfree(attrs); ++ ++ attrs = create_modstamp_attrs(test_ctx, TEST_MODSTAMP_1); ++ assert_non_null(attrs); ++ ++ ret = sysdb_store_user(test_ctx->tctx->dom, TEST_USER_NAME, NULL, ++ TEST_USER_UID, TEST_USER_GID, TEST_USER_NAME, ++ "/home/"TEST_USER_NAME, "/bin/bash", NULL, ++ attrs, NULL, TEST_CACHE_TIMEOUT, ++ 0); ++ talloc_zfree(attrs); ++ assert_int_equal(ret, EOK); ++ ++ attrs = create_modstamp_attrs(test_ctx, TEST_MODSTAMP_1); ++ assert_non_null(attrs); ++ ++ ret = sysdb_store_group(test_ctx->tctx->dom, ++ TEST_GROUP_NAME, ++ TEST_GROUP_GID, ++ attrs, ++ TEST_CACHE_TIMEOUT, ++ 0); ++ talloc_zfree(attrs); ++ assert_int_equal(ret, EOK); ++ ++ /* Even though we passed zero as the timestamp, the timestamp cache should ++ * have used the current time instead ++ */ ++ get_pw_timestamp_attrs(test_ctx, TEST_USER_NAME, ++ &cache_expire_sysdb, &cache_expire_ts); ++ assert_true(cache_expire_sysdb > TEST_CACHE_TIMEOUT); ++ assert_true(cache_expire_ts > TEST_CACHE_TIMEOUT); ++ ++ get_gr_timestamp_attrs(test_ctx, TEST_GROUP_NAME, ++ &cache_expire_sysdb, &cache_expire_ts); ++ assert_true(cache_expire_sysdb > TEST_CACHE_TIMEOUT); ++ assert_true(cache_expire_ts > TEST_CACHE_TIMEOUT); ++} ++ + int main(int argc, const char *argv[]) + { + int rv; +@@ -1396,6 +1476,9 @@ int main(int argc, const char *argv[]) + cmocka_unit_test_setup_teardown(test_user_byupn, + test_sysdb_ts_setup, + test_sysdb_ts_teardown), ++ cmocka_unit_test_setup_teardown(test_sysdb_zero_now, ++ test_sysdb_ts_setup, ++ test_sysdb_ts_teardown), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ +-- +2.4.11 + diff --git a/SOURCES/0070-sss_override-support-fqn-in-override-name.patch b/SOURCES/0070-sss_override-support-fqn-in-override-name.patch deleted file mode 100644 index 838a47e..0000000 --- a/SOURCES/0070-sss_override-support-fqn-in-override-name.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 90611687b8b7b9a4d2be4625c97301660412b605 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Tue, 15 Sep 2015 11:38:40 +0200 -Subject: [PATCH 70/73] sss_override: support fqn in override name - -Resolves: -https://fedorahosted.org/sssd/ticket/2782 - -Reviewed-by: Jakub Hrozek ---- - src/tools/sss_override.c | 111 +++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 93 insertions(+), 18 deletions(-) - -diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c -index ee8351ea97e5efe0d449dc646c6136b32ceec2c6..0d7a4690634a3993dee2119ee09fea328e494f1a 100644 ---- a/src/tools/sss_override.c -+++ b/src/tools/sss_override.c -@@ -604,58 +604,133 @@ done: - return ret; - } - -+static errno_t override_fqn(TALLOC_CTX *mem_ctx, -+ struct sss_tool_ctx *tool_ctx, -+ struct sss_domain_info *domain, -+ const char *input, -+ const char **_name) -+{ -+ struct sss_domain_info *dom; -+ errno_t ret; -+ -+ if (input == NULL) { -+ return EOK; -+ } -+ -+ ret = sss_tool_parse_name(mem_ctx, tool_ctx, input, _name, &dom); -+ if (ret == EAGAIN) { -+ DEBUG(SSSDBG_OP_FAILURE, "Unable to find domain from " -+ "fqn %s\n", input); -+ fprintf(stderr, _("Changing domain is not allowed!\n")); -+ ret = EINVAL; -+ } else if (ret == EOK && dom != NULL && dom != domain) { -+ DEBUG(SSSDBG_OP_FAILURE, "Trying to change domain from " -+ "%s to %s, not allowed!\n", domain->name, dom->name); -+ fprintf(stderr, _("Changing domain is not allowed!\n")); -+ ret = EINVAL; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name %s [%d]: %s\n", -+ input, ret, sss_strerror(ret)); -+ } -+ -+ return ret; -+} -+ - static errno_t override_user(struct sss_tool_ctx *tool_ctx, -- struct override_user *user) -+ struct override_user *input_user) - { -+ TALLOC_CTX *tmp_ctx; -+ struct override_user user; - struct sysdb_attrs *attrs; - errno_t ret; - -- ret = prepare_view_msg(user->domain); -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); -+ return ENOMEM; -+ } -+ -+ user = *input_user; -+ -+ /* We need to parse the name and ensure that domain did not change. */ -+ ret = override_fqn(tmp_ctx, tool_ctx, user.domain, user.name, &user.name); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = prepare_view_msg(user.domain); - if (ret != EOK) { -- return ret; -+ goto done; - } - -- attrs = build_user_attrs(tool_ctx, user); -+ attrs = build_user_attrs(tool_ctx, &user); - if (attrs == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -- return ENOMEM; -+ ret = ENOMEM; -+ goto done; - } - -- ret = override_object_add(user->domain, SYSDB_MEMBER_USER, attrs, -- user->orig_name); -+ ret = override_object_add(user.domain, SYSDB_MEMBER_USER, attrs, -+ user.orig_name); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -- return ret; -+ goto done; - } - -- return EOK; -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; - } - - static errno_t override_group(struct sss_tool_ctx *tool_ctx, -- struct override_group *group) -+ struct override_group *input_group) - { -+ TALLOC_CTX *tmp_ctx; -+ struct override_group group; - struct sysdb_attrs *attrs; - errno_t ret; - -- ret = prepare_view_msg(group->domain); -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); -+ return ENOMEM; -+ } -+ -+ group = *input_group; -+ -+ /* We need to parse the name and ensure that domain did not change. */ -+ ret = override_fqn(tmp_ctx, tool_ctx, group.domain, group.name, -+ &group.name); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = prepare_view_msg(group.domain); - if (ret != EOK) { -- return ret; -+ goto done; - } - -- attrs = build_group_attrs(tool_ctx, group); -+ attrs = build_group_attrs(tool_ctx, &group); - if (attrs == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n"); -- return ENOMEM; -+ ret = ENOMEM; -+ goto done; - } - -- ret = override_object_add(group->domain, SYSDB_MEMBER_GROUP, attrs, -- group->orig_name); -+ ret = override_object_add(group.domain, SYSDB_MEMBER_GROUP, attrs, -+ group.orig_name); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n"); -- return ret; -+ goto done; - } - -- return EOK; -+ ret = EOK; -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; - } - - static errno_t override_object_del(struct sss_domain_info *domain, --- -2.4.3 - diff --git a/SOURCES/0071-Revert-LDAP-Lookup-services-by-all-protocols-unless-.patch b/SOURCES/0071-Revert-LDAP-Lookup-services-by-all-protocols-unless-.patch new file mode 100644 index 0000000..0caae35 --- /dev/null +++ b/SOURCES/0071-Revert-LDAP-Lookup-services-by-all-protocols-unless-.patch @@ -0,0 +1,44 @@ +From e4fd5c67a8f63062b17e615ce746a19994ee310c Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Wed, 27 Jul 2016 11:13:04 +0200 +Subject: [PATCH 71/74] Revert "LDAP: Lookup services by all protocols unless a + protocol is specified" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit aa58e216c1f794bd335151f19e79adbb3ddf4c73. + +Reviewed-by: Pavel Březina +--- + src/providers/ldap/ldap_id_services.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c +index 401228c20af31ae2df9bb3d35ed25fb6f06b1839..77215127b53297d840eaa4d2f35a75eedb085e43 100644 +--- a/src/providers/ldap/ldap_id_services.c ++++ b/src/providers/ldap/ldap_id_services.c +@@ -89,9 +89,6 @@ services_get_send(TALLOC_CTX *mem_ctx, + state->sysdb = sdom->dom->sysdb; + state->name = name; + state->protocol = protocol; +- if (state->protocol != NULL && state->protocol[0] == '\0') { +- state->protocol = NULL; +- } + state->filter_type = filter_type; + state->noexist_delete = noexist_delete; + +@@ -117,8 +114,8 @@ services_get_send(TALLOC_CTX *mem_ctx, + ret = sss_filter_sanitize(state, name, &clean_name); + if (ret != EOK) goto error; + +- if (state->protocol != NULL) { +- ret = sss_filter_sanitize(state, state->protocol, &clean_protocol); ++ if (protocol) { ++ ret = sss_filter_sanitize(state, protocol, &clean_protocol); + if (ret != EOK) goto error; + } + +-- +2.4.11 + diff --git a/SOURCES/0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch b/SOURCES/0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch deleted file mode 100644 index a92663d..0000000 --- a/SOURCES/0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 58c6f691bed13095a48b4587e5baa7bb4dc7dae5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Thu, 17 Sep 2015 11:34:40 +0200 -Subject: [PATCH 71/73] views: do not require overrideDN in grous when LOCAL - view is set - -Resolves: -https://fedorahosted.org/sssd/ticket/2790 - -Reviewed-by: Sumit Bose ---- - src/db/sysdb_views.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c -index 1db6c892de9e4764b673608166830800744b1148..82b1f187dbc6aab032403854714474301ae3324c 100644 ---- a/src/db/sysdb_views.c -+++ b/src/db/sysdb_views.c -@@ -1337,6 +1337,12 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, - override_dn_str = ldb_msg_find_attr_as_string(member_obj->msgs[0], - SYSDB_OVERRIDE_DN, NULL); - if (override_dn_str == NULL) { -+ if (is_local_view(domain->view_name)) { -+ /* LOCAL view doesn't have to have overrideDN specified. */ -+ ret = EOK; -+ goto done; -+ } -+ - DEBUG(SSSDBG_CRIT_FAILURE, - "Missing override DN for objext [%s].\n", - ldb_dn_get_linearized(member_obj->msgs[0]->dn)); --- -2.4.3 - diff --git a/SOURCES/0072-PROVIDER-Conversion-empty-string-from-D-Bus-to-NULL.patch b/SOURCES/0072-PROVIDER-Conversion-empty-string-from-D-Bus-to-NULL.patch new file mode 100644 index 0000000..1e57a7b --- /dev/null +++ b/SOURCES/0072-PROVIDER-Conversion-empty-string-from-D-Bus-to-NULL.patch @@ -0,0 +1,59 @@ +From 0edb93b54bf79df41aa34a77e9a173cf8529559a Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Wed, 27 Jul 2016 11:13:32 +0200 +Subject: [PATCH 72/74] PROVIDER: Conversion empty string from D-Bus to NULL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch fixes the issue with empty string recieving from D-Bus. +Data providers obtains NULL. So this is simple conversin. + +Resolves: +https://fedorahosted.org/sssd/ticket/3084 + +Reviewed-by: Pavel Březina +--- + src/providers/data_provider/dp_target_id.c | 6 +++--- + src/providers/ldap/ldap_id_services.c | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c +index 7c882be2c17650d818cb3907197e381a8f635a77..1b06cbe5b96f56c33dd048cf6211b7c97819db8c 100644 +--- a/src/providers/data_provider/dp_target_id.c ++++ b/src/providers/data_provider/dp_target_id.c +@@ -62,15 +62,15 @@ static bool check_and_parse_filter(struct be_acct_req *data, + {0, 0, 0}}; + int i; + +- if (filter == NULL) { ++ if (SBUS_IS_STRING_EMPTY(filter)) { + return false; + } + + for (i = 0; types[i].name != NULL; i++) { + if (strncmp(filter, types[i].name, types[i].lenght) == 0) { + data->filter_type = types[i].type; +- data->filter_value = &filter[types[i].lenght]; +- data->extra_value = extra; ++ data->filter_value = SBUS_SET_STRING(&filter[types[i].lenght]); ++ data->extra_value = SBUS_SET_STRING(extra); + return true; + } + } +diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c +index 77215127b53297d840eaa4d2f35a75eedb085e43..e91fc52d731eaa22be7e98365fc75e7057cb8f1f 100644 +--- a/src/providers/ldap/ldap_id_services.c ++++ b/src/providers/ldap/ldap_id_services.c +@@ -114,7 +114,7 @@ services_get_send(TALLOC_CTX *mem_ctx, + ret = sss_filter_sanitize(state, name, &clean_name); + if (ret != EOK) goto error; + +- if (protocol) { ++ if (protocol == NULL) { + ret = sss_filter_sanitize(state, protocol, &clean_protocol); + if (ret != EOK) goto error; + } +-- +2.4.11 + diff --git a/SOURCES/0072-views-fix-two-typos-in-debug-messages.patch b/SOURCES/0072-views-fix-two-typos-in-debug-messages.patch deleted file mode 100644 index 454537c..0000000 --- a/SOURCES/0072-views-fix-two-typos-in-debug-messages.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 82a09d64a35e560d3715484b2f3f8e6e7c0af48c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Thu, 17 Sep 2015 11:35:56 +0200 -Subject: [PATCH 72/73] views: fix two typos in debug messages - -Reviewed-by: Sumit Bose ---- - src/db/sysdb_views.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c -index 82b1f187dbc6aab032403854714474301ae3324c..f0459fc174b94d7a735b7c416555eb5aaac42b7c 100644 ---- a/src/db/sysdb_views.c -+++ b/src/db/sysdb_views.c -@@ -1193,7 +1193,7 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain, - } - - DEBUG(SSSDBG_CRIT_FAILURE, -- "Missing override DN for objext [%s].\n", -+ "Missing override DN for object [%s].\n", - ldb_dn_get_linearized(obj->dn)); - - ret = ENOENT; -@@ -1344,7 +1344,7 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, - } - - DEBUG(SSSDBG_CRIT_FAILURE, -- "Missing override DN for objext [%s].\n", -+ "Missing override DN for object [%s].\n", - ldb_dn_get_linearized(member_obj->msgs[0]->dn)); - ret = ENOENT; - goto done; --- -2.4.3 - diff --git a/SOURCES/0073-LDAP-Fix-Dereference-after-NULL-check.patch b/SOURCES/0073-LDAP-Fix-Dereference-after-NULL-check.patch new file mode 100644 index 0000000..3d467ba --- /dev/null +++ b/SOURCES/0073-LDAP-Fix-Dereference-after-NULL-check.patch @@ -0,0 +1,36 @@ +From 33649cb41206f568e2bef582e13edbc721184a29 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 8 Aug 2016 09:03:47 +0200 +Subject: [PATCH 73/74] LDAP: Fix Dereference after NULL check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The commit dc30c60f166ad9adc63a47a1013508a71624ac87 +changed the logic in NULL check + - if (protocol) { + + if (protocol == NULL) { + +Found by Coverity: + +Reviewed-by: Petr Čech +--- + src/providers/ldap/ldap_id_services.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c +index e91fc52d731eaa22be7e98365fc75e7057cb8f1f..638cb619b39f135307090dcf0f2c6ab2cc4119d0 100644 +--- a/src/providers/ldap/ldap_id_services.c ++++ b/src/providers/ldap/ldap_id_services.c +@@ -114,7 +114,7 @@ services_get_send(TALLOC_CTX *mem_ctx, + ret = sss_filter_sanitize(state, name, &clean_name); + if (ret != EOK) goto error; + +- if (protocol == NULL) { ++ if (protocol != NULL) { + ret = sss_filter_sanitize(state, protocol, &clean_protocol); + if (ret != EOK) goto error; + } +-- +2.4.11 + diff --git a/SOURCES/0073-views-allow-ghost-members-for-LOCAL-view.patch b/SOURCES/0073-views-allow-ghost-members-for-LOCAL-view.patch deleted file mode 100644 index ade6944..0000000 --- a/SOURCES/0073-views-allow-ghost-members-for-LOCAL-view.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 8d728461964488b29cdcd431210872eaee9bc9f7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Thu, 17 Sep 2015 14:46:34 +0200 -Subject: [PATCH 73/73] views: allow ghost members for LOCAL view - -LOCAL view does not allow the case when both ghost member and -user override is created so it is safe to allow ghost members -for this view. - -Resolves: -https://fedorahosted.org/sssd/ticket/2790 - -Reviewed-by: Sumit Bose ---- - src/db/sysdb_search.c | 36 ++++++++++++++++++++---------------- - src/responder/nss/nsssrv_cmd.c | 3 ++- - 2 files changed, 22 insertions(+), 17 deletions(-) - -diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c -index 4f617b841bf3b3760d9cb05a06f4b46ea0c58ff5..efd583beefe78bb6bb26263a9833bf3bfafd0083 100644 ---- a/src/db/sysdb_search.c -+++ b/src/db/sysdb_search.c -@@ -482,14 +482,16 @@ int sysdb_getgrnam_with_views(TALLOC_CTX *mem_ctx, - /* If there are views we have to check if override values must be added to - * the original object. */ - if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) { -- el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); -- if (el != NULL && el->num_values != 0) { -- DEBUG(SSSDBG_TRACE_ALL, -- "Group object [%s], contains ghost entries which must be " \ -- "resolved before overrides can be applied.\n", -- ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); -- ret = ENOENT; -- goto done; -+ if (!is_local_view(domain->view_name)) { -+ el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); -+ if (el != NULL && el->num_values != 0) { -+ DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost " -+ "entries which must be resolved before overrides can be " -+ "applied.\n", -+ ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); -+ ret = ENOENT; -+ goto done; -+ } - } - - ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], -@@ -634,14 +636,16 @@ int sysdb_getgrgid_with_views(TALLOC_CTX *mem_ctx, - /* If there are views we have to check if override values must be added to - * the original object. */ - if (DOM_HAS_VIEWS(domain) && orig_obj->count == 1) { -- el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); -- if (el != NULL && el->num_values != 0) { -- DEBUG(SSSDBG_TRACE_ALL, -- "Group object [%s], contains ghost entries which must be " \ -- "resolved before overrides can be applied.\n", -- ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); -- ret = ENOENT; -- goto done; -+ if (!is_local_view(domain->view_name)) { -+ el = ldb_msg_find_element(orig_obj->msgs[0], SYSDB_GHOST); -+ if (el != NULL && el->num_values != 0) { -+ DEBUG(SSSDBG_TRACE_ALL, "Group object [%s], contains ghost " -+ "entries which must be resolved before overrides can be " -+ "applied.\n", -+ ldb_dn_get_linearized(orig_obj->msgs[0]->dn)); -+ ret = ENOENT; -+ goto done; -+ } - } - - ret = sysdb_add_overrides_to_object(domain, orig_obj->msgs[0], -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index 459634b8d7a590a196ad47a17cd52729fc633ee2..d177135db00369c2af69eb62f6a4a4aaf54ba510 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -2909,7 +2909,8 @@ static int fill_grent(struct sss_packet *packet, - } - el = ldb_msg_find_element(msg, SYSDB_GHOST); - if (el) { -- if (DOM_HAS_VIEWS(dom) && el->num_values != 0) { -+ if (DOM_HAS_VIEWS(dom) && !is_local_view(dom->view_name) -+ && el->num_values != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Domain has a view [%s] but group [%s] still has " \ - "ghost members.\n", dom->view_name, orig_name); --- -2.4.3 - diff --git a/SOURCES/0074-LDAP-Fixing-wrong-pam-error-code-for-passwd.patch b/SOURCES/0074-LDAP-Fixing-wrong-pam-error-code-for-passwd.patch new file mode 100644 index 0000000..913b219 --- /dev/null +++ b/SOURCES/0074-LDAP-Fixing-wrong-pam-error-code-for-passwd.patch @@ -0,0 +1,32 @@ +From 89f9598e19000fed30c1069eec01b094eeae0377 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 2 Aug 2016 10:11:14 +0200 +Subject: [PATCH 74/74] LDAP: Fixing wrong pam error code for passwd + +This patch adds right pam error code for sssd offline state. + +Resolves: +https://fedorahosted.org/sssd/ticket/3109 +--- + src/providers/ldap/ldap_auth.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c +index 107f6ded1a903904e088f0b6b0320fe82a52af52..35f16b0d4a6f8e566b0cf63b65ba46f31e7c1bcd 100644 +--- a/src/providers/ldap/ldap_auth.c ++++ b/src/providers/ldap/ldap_auth.c +@@ -1101,6 +1101,11 @@ sdap_pam_chpass_handler_send(TALLOC_CTX *mem_ctx, + state->auth_ctx = auth_ctx; + state->ev = params->ev; + ++ if (be_is_offline(state->be_ctx)) { ++ pd->pam_status = PAM_AUTHINFO_UNAVAIL; ++ goto immediately; ++ } ++ + if ((pd->priv == 1) && (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) && + (sss_authtok_get_type(pd->authtok) != SSS_AUTHTOK_TYPE_PASSWORD)) { + DEBUG(SSSDBG_CONF_SETTINGS, +-- +2.4.11 + diff --git a/SOURCES/0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch b/SOURCES/0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch deleted file mode 100644 index 55c4880..0000000 --- a/SOURCES/0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch +++ /dev/null @@ -1,303 +0,0 @@ -From 875a41bcd24d1deb2bd190eaaaf7a366de128cee Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 18 Aug 2015 15:15:44 +0000 -Subject: [PATCH 74/87] UTIL: Convert domain->disabled into tri-state with - domain states -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Required for: -https://fedorahosted.org/sssd/ticket/2637 - -This is a first step towards making it possible for domain to be around, -but not contacted by Data Provider. - -Also explicitly create domains as active, previously we only relied on -talloc_zero marking dom->disabled as false. - -Reviewed-by: Pavel Březina ---- - src/confdb/confdb.c | 2 ++ - src/confdb/confdb.h | 19 ++++++++++++++++++- - src/db/sysdb_subdomains.c | 7 +++++-- - src/providers/ad/ad_subdomains.c | 2 +- - src/providers/ipa/ipa_subdomains.c | 2 +- - src/responder/common/responder_common.c | 5 +++-- - src/tests/cmocka/test_sysdb_subdomains.c | 6 +++++- - src/tests/cmocka/test_utils.c | 6 +++--- - src/util/domain_info_utils.c | 20 +++++++++++++++++--- - src/util/util.h | 3 +++ - src/util/util_errors.c | 1 + - src/util/util_errors.h | 1 + - 12 files changed, 60 insertions(+), 14 deletions(-) - -diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c -index 3a8a1c01b92e62302ac4f787ccd085be9d8f05c3..c097aad7745eda4fff051c7da027776f95db0f03 100644 ---- a/src/confdb/confdb.c -+++ b/src/confdb/confdb.c -@@ -1342,6 +1342,8 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, - domain->has_views = false; - domain->view_name = NULL; - -+ domain->state = DOM_ACTIVE; -+ - *_domain = domain; - ret = EOK; - done: -diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h -index 9aa264899e789f2491b9873daf44bb55aff1c95d..e8c1caa67852a8f3d9d74fc61dbe6f8b4169daf7 100644 ---- a/src/confdb/confdb.h -+++ b/src/confdb/confdb.h -@@ -215,6 +215,23 @@ - struct confdb_ctx; - struct config_file_ctx; - -+/** sssd domain state */ -+enum sss_domain_state { -+ /** Domain is usable by both responders and providers. This -+ * is the default state after creating a new domain -+ */ -+ DOM_ACTIVE, -+ /** Domain was removed, should not be used be neither responders -+ * not providers. -+ */ -+ DOM_DISABLED, -+ /** Domain cannot be contacted. Providers return an offline error code -+ * when receiving request for inactive domain, but responders should -+ * return cached data -+ */ -+ DOM_INACTIVE, -+}; -+ - /** - * Data structure storing all of the basic features - * of a domain. -@@ -277,7 +294,7 @@ struct sss_domain_info { - struct sss_domain_info *prev; - struct sss_domain_info *next; - -- bool disabled; -+ enum sss_domain_state state; - char **sd_inherit; - - /* Do not use the forest pointer directly in new code, but rather the -diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c -index 142520c1836d74ef7bc5c5269487b8971f261b88..546dc1c8d7e5e30ce9e0b56b097894d24d8c94a7 100644 ---- a/src/db/sysdb_subdomains.c -+++ b/src/db/sysdb_subdomains.c -@@ -111,6 +111,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, - dom->enumerate = enumerate; - dom->fqnames = true; - dom->mpg = mpg; -+ dom->state = DOM_ACTIVE; -+ - /* If the parent domain filters out group members, the subdomain should - * as well if configured */ - inherit_option = string_in_list(CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS, -@@ -268,7 +270,7 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) - /* disable all domains, - * let the search result refresh any that are still valid */ - for (dom = domain->subdomains; dom; dom = get_next_domain(dom, false)) { -- dom->disabled = true; -+ sss_domain_set_state(dom, DOM_DISABLED); - } - - if (res->count == 0) { -@@ -312,7 +314,8 @@ errno_t sysdb_update_subdomains(struct sss_domain_info *domain) - /* explicitly use dom->next as we need to check 'disabled' domains */ - for (dom = domain->subdomains; dom; dom = dom->next) { - if (strcasecmp(dom->name, name) == 0) { -- dom->disabled = false; -+ sss_domain_set_state(dom, DOM_ACTIVE); -+ - /* in theory these may change, but it should never happen */ - if (strcasecmp(dom->realm, realm) != 0) { - DEBUG(SSSDBG_TRACE_INTERNAL, -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 9b42f03a0067ab5844432a0f19dd2930dcc200c9..d1d468043410c80e6bf7f0f48a13bd9e962552af 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -376,7 +376,7 @@ static errno_t ad_subdomains_refresh(struct ad_subdomains_ctx *ctx, - - if (c >= count) { - /* ok this subdomain does not exist anymore, let's clean up */ -- dom->disabled = true; -+ sss_domain_set_state(dom, DOM_DISABLED); - ret = sysdb_subdomain_delete(dom->sysdb, dom->name); - if (ret != EOK) { - goto done; -diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c -index b2e2fec353f7b168d28a880cb0f1b6181abb1ccb..089736b47d8f384a8024682dd203d324292df9ce 100644 ---- a/src/providers/ipa/ipa_subdomains.c -+++ b/src/providers/ipa/ipa_subdomains.c -@@ -528,7 +528,7 @@ static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx, - - if (c >= count) { - /* ok this subdomain does not exist anymore, let's clean up */ -- dom->disabled = true; -+ sss_domain_set_state(dom, DOM_DISABLED); - ret = sysdb_subdomain_delete(dom->sysdb, dom->name); - if (ret != EOK) { - goto done; -diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c -index 36e7f15948632e9c637886dee259b494e46ceecb..2097004cb0fc24d8b356f9d924243f948227ef58 100644 ---- a/src/responder/common/responder_common.c -+++ b/src/responder/common/responder_common.c -@@ -923,7 +923,7 @@ responder_get_domain(struct resp_ctx *rctx, const char *name) - struct sss_domain_info *ret_dom = NULL; - - for (dom = rctx->domains; dom; dom = get_next_domain(dom, true)) { -- if (dom->disabled) { -+ if (sss_domain_get_state(dom) == DOM_DISABLED) { - continue; - } - -@@ -958,7 +958,8 @@ errno_t responder_get_domain_by_id(struct resp_ctx *rctx, const char *id, - id_len = strlen(id); - - for (dom = rctx->domains; dom; dom = get_next_domain(dom, true)) { -- if (dom->disabled || dom->domain_id == NULL) { -+ if (sss_domain_get_state(dom) == DOM_DISABLED || -+ dom->domain_id == NULL) { - continue; - } - -diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c -index 82e77815ec848afcdedc90e35e440f7532b5c0b2..8d1a26a5918eaa9dec975c360f69840400e4bd2c 100644 ---- a/src/tests/cmocka/test_sysdb_subdomains.c -+++ b/src/tests/cmocka/test_sysdb_subdomains.c -@@ -151,7 +151,11 @@ static void test_sysdb_subdomain_create(void **state) - ret = sysdb_update_subdomains(test_ctx->tctx->dom); - assert_int_equal(ret, EOK); - -- assert_true(test_ctx->tctx->dom->subdomains->disabled); -+ assert_int_equal(sss_domain_get_state(test_ctx->tctx->dom->subdomains), -+ DOM_DISABLED); -+ assert_int_equal( -+ sss_domain_get_state(test_ctx->tctx->dom->subdomains->next), -+ DOM_DISABLED); - } - - static void test_sysdb_master_domain_ops(void **state) -diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c -index c7ebe0997ec00197e8852bedbcf26ef1f6394fc3..0f72434ca77fbfe1bd88a75fd932719dbfc59444 100644 ---- a/src/tests/cmocka/test_utils.c -+++ b/src/tests/cmocka/test_utils.c -@@ -259,7 +259,7 @@ void test_find_domain_by_name_disabled(void **state) - dom = dom->next; - } - assert_non_null(dom); -- dom->disabled = true; -+ sss_domain_set_state(dom, DOM_DISABLED); - - for (c = 0; c < test_ctx->dom_count; c++) { - name = talloc_asprintf(global_talloc_context, DOMNAME_TMPL, c); -@@ -426,7 +426,7 @@ void test_find_domain_by_sid_disabled(void **state) - dom = dom->next; - } - assert_non_null(dom); -- dom->disabled = true; -+ sss_domain_set_state(dom, DOM_DISABLED); - - for (c = 0; c < test_ctx->dom_count; c++) { - name = talloc_asprintf(global_talloc_context, DOMNAME_TMPL, c); -@@ -578,7 +578,7 @@ static void test_get_next_domain_disabled(void **state) - struct sss_domain_info *dom = NULL; - - for (dom = test_ctx->dom_list; dom; dom = get_next_domain(dom, true)) { -- dom->disabled = true; -+ sss_domain_set_state(dom, DOM_DISABLED); - } - - dom = get_next_domain(test_ctx->dom_list, true); -diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c -index 4eabcff7a0e0af342ec3833d24da26ede0cb5148..ffbb9475b27a45c07e2e0936464c6e68ed682052 100644 ---- a/src/util/domain_info_utils.c -+++ b/src/util/domain_info_utils.c -@@ -50,7 +50,10 @@ struct sss_domain_info *get_next_domain(struct sss_domain_info *domain, - } else { - dom = NULL; - } -- if (dom && !dom->disabled) break; -+ -+ if (dom && sss_domain_get_state(dom) != DOM_DISABLED) { -+ break; -+ } - } - - return dom; -@@ -91,7 +94,7 @@ struct sss_domain_info *find_domain_by_name(struct sss_domain_info *domain, - return NULL; - } - -- while (dom && dom->disabled) { -+ while (dom && sss_domain_get_state(dom) == DOM_DISABLED) { - dom = get_next_domain(dom, true); - } - while (dom) { -@@ -119,7 +122,7 @@ struct sss_domain_info *find_domain_by_sid(struct sss_domain_info *domain, - - sid_len = strlen(sid); - -- while (dom && dom->disabled) { -+ while (dom && sss_domain_get_state(dom) == DOM_DISABLED) { - dom = get_next_domain(dom, true); - } - -@@ -730,3 +733,14 @@ done: - - return ret; - } -+ -+enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom) -+{ -+ return dom->state; -+} -+ -+void sss_domain_set_state(struct sss_domain_info *dom, -+ enum sss_domain_state state) -+{ -+ dom->state = state; -+} -diff --git a/src/util/util.h b/src/util/util.h -index c998e91f92b0a86e0f4308ff0c07ff802588b5cf..4655e90a89b0ff3c457b80c943aefc4d6cf8e21f 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -565,6 +565,9 @@ struct sss_domain_info *find_domain_by_name(struct sss_domain_info *domain, - bool match_any); - struct sss_domain_info *find_domain_by_sid(struct sss_domain_info *domain, - const char *sid); -+enum sss_domain_state sss_domain_get_state(struct sss_domain_info *dom); -+void sss_domain_set_state(struct sss_domain_info *dom, -+ enum sss_domain_state state); - - struct sss_domain_info* - sss_get_domain_by_sid_ldap_fallback(struct sss_domain_info *domain, -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 735f6dcfc7af33edcc886fd106cb3655bcc9566a..0e288e3908bf03b4906bb449bd0f3445d22a303e 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -79,6 +79,7 @@ struct err_string error_to_str[] = { - { "Retrieving keytab failed" }, /* ERR_IPA_GETKEYTAB_FAILED */ - { "Trusted forest root unknown" }, /* ERR_TRUST_FOREST_UNKNOWN */ - { "p11_child failed" }, /* ERR_P11_CHILD */ -+ { "Subdomain is inactive" }, /* ERR_SUBDOM_INACTIVE */ - { "ERR_LAST" } /* ERR_LAST */ - }; - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index fbfbdef334be1fb8a525b78ab6336d616b31a189..da926db00121f569048ec515e95f0547ae6c4e35 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -101,6 +101,7 @@ enum sssd_errors { - ERR_IPA_GETKEYTAB_FAILED, - ERR_TRUST_FOREST_UNKNOWN, - ERR_P11_CHILD, -+ ERR_SUBDOM_INACTIVE, - ERR_LAST /* ALWAYS LAST */ - }; - --- -2.4.3 - diff --git a/SOURCES/0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch b/SOURCES/0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch deleted file mode 100644 index 32ad0fd..0000000 --- a/SOURCES/0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch +++ /dev/null @@ -1,499 +0,0 @@ -From 6c1e606c3e9da9910554e48a6409a9b3001deedb Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 4 Sep 2015 09:27:17 +0200 -Subject: [PATCH 75/87] DP: Provide a way to mark subdomain as disabled and - auto-enable it later with offline_timeout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2637 - -Adds a new Data Provider function be_mark_dom_offline() that is a -replacement for be_mark_offline(). When called, the function would -either set the whole back end offline, just like be_mark_offline or just -set the subdomain status to inactive. - -When a subdomain is inactive, there is a singleton timed task that would -re-set the subdomin after offline_timeout seconds. - -Reviewed-by: Pavel Březina ---- - Makefile.am | 26 +++ - src/providers/data_provider_be.c | 102 +++++++++++- - src/providers/dp_backend.h | 1 + - src/tests/cmocka/test_data_provider_be.c | 275 +++++++++++++++++++++++++++++++ - 4 files changed, 395 insertions(+), 9 deletions(-) - create mode 100644 src/tests/cmocka/test_data_provider_be.c - -diff --git a/Makefile.am b/Makefile.am -index e1102333b019e32c516c59c5fa969c970b688737..4e80701872c0e4e1391f0c6de8a2f68e719f8236 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -236,6 +236,7 @@ if HAVE_CMOCKA - test_ipa_subdom_server \ - test_krb5_wait_queue \ - test_cert_utils \ -+ test_data_provider_be \ - $(NULL) - - if HAVE_LIBRESOLV -@@ -2603,6 +2604,31 @@ test_cert_utils_LDADD = \ - libsss_cert.la \ - libsss_crypt.la \ - $(NULL) -+ -+test_data_provider_be_SOURCES = \ -+ $(sssd_be_SOURCES) \ -+ src/tests/cmocka/test_data_provider_be.c \ -+ src/tests/cmocka/common_mock_be.c \ -+ $(NULL) -+test_data_provider_be_CFLAGS = \ -+ $(AM_CFLAGS) \ -+ -DUNIT_TESTING \ -+ $(CRYPTO_CFLAGS) \ -+ $(NULL) -+test_data_provider_be_LDFLAGS = \ -+ -Wl,-wrap,_tevent_add_timer \ -+ $(NULL) -+test_data_provider_be_LDADD = \ -+ $(CMOCKA_LIBS) \ -+ $(CARES_LIBS) \ -+ $(POPT_LIBS) \ -+ $(PAM_LIBS) \ -+ $(TALLOC_LIBS) \ -+ $(SSSD_INTERNAL_LTLIBS) \ -+ libsss_debug.la \ -+ libsss_test_common.la \ -+ $(NULL) -+ - endif # HAVE_CMOCKA - - noinst_PROGRAMS = pam_test_client -diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c -index d147630248f0a24f5a632760b55b9284a6928e40..f477ac8bde2b1e3eea862e8e8f503566282ea8f3 100644 ---- a/src/providers/data_provider_be.c -+++ b/src/providers/data_provider_be.c -@@ -478,6 +478,24 @@ try_to_go_online(TALLOC_CTX *mem_ctx, - return EOK; - } - -+static int get_offline_timeout(struct be_ctx *ctx) -+{ -+ errno_t ret; -+ int offline_timeout; -+ -+ ret = confdb_get_int(ctx->cdb, ctx->conf_path, -+ CONFDB_DOMAIN_OFFLINE_TIMEOUT, 60, -+ &offline_timeout); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Failed to get offline_timeout from confdb. " -+ "Will use 60 seconds.\n"); -+ offline_timeout = 60; -+ } -+ -+ return offline_timeout; -+} -+ - void be_mark_offline(struct be_ctx *ctx) - { - int offline_timeout; -@@ -493,15 +511,9 @@ void be_mark_offline(struct be_ctx *ctx) - /* This is the first time we go offline - create a periodic task - * to check if we can switch to online. */ - DEBUG(SSSDBG_TRACE_INTERNAL, "Initialize check_if_online_ptask.\n"); -- ret = confdb_get_int(ctx->cdb, ctx->conf_path, -- CONFDB_DOMAIN_OFFLINE_TIMEOUT, 60, -- &offline_timeout); -- if (ret != EOK) { -- DEBUG(SSSDBG_CRIT_FAILURE, -- "Failed to get offline_timeout from confdb. " -- "Will use 60 seconds.\n"); -- offline_timeout = 60; -- } -+ -+ offline_timeout = get_offline_timeout(ctx); -+ - ret = be_ptask_create_sync(ctx, ctx, - offline_timeout, offline_timeout, - offline_timeout, 30, offline_timeout, -@@ -524,10 +536,82 @@ void be_mark_offline(struct be_ctx *ctx) - be_run_offline_cb(ctx); - } - -+static void be_subdom_reset_status(struct tevent_context *ev, -+ struct tevent_timer *te, -+ struct timeval current_time, -+ void *pvt) -+{ -+ struct sss_domain_info *subdom = talloc_get_type(pvt, -+ struct sss_domain_info); -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Resetting subdomain %s\n", subdom->name); -+ subdom->state = DOM_ACTIVE; -+} -+ -+static void be_mark_subdom_offline(struct sss_domain_info *subdom, -+ struct be_ctx *be_ctx) -+{ -+ struct timeval tv; -+ struct tevent_timer *timeout = NULL; -+ int reset_status_timeout; -+ -+ reset_status_timeout = get_offline_timeout(be_ctx); -+ tv = tevent_timeval_current_ofs(reset_status_timeout, 0); -+ -+ switch (subdom->state) { -+ case DOM_DISABLED: -+ DEBUG(SSSDBG_MINOR_FAILURE, "Won't touch disabled subdomain\n"); -+ return; -+ case DOM_INACTIVE: -+ DEBUG(SSSDBG_TRACE_ALL, "Subdomain already inactive\n"); -+ return; -+ case DOM_ACTIVE: -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Marking subdomain %s as inactive\n", subdom->name); -+ break; -+ } -+ -+ timeout = tevent_add_timer(be_ctx->ev, be_ctx, tv, -+ be_subdom_reset_status, subdom); -+ if (timeout == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "Cannot create timer\n"); -+ return; -+ } -+ -+ subdom->state = DOM_INACTIVE; -+} -+ -+void be_mark_dom_offline(struct sss_domain_info *dom, struct be_ctx *ctx) -+{ -+ if (IS_SUBDOMAIN(dom) == false) { -+ DEBUG(SSSDBG_TRACE_LIBS, "Marking back end offline\n"); -+ be_mark_offline(ctx); -+ } else { -+ DEBUG(SSSDBG_TRACE_LIBS, "Marking subdomain %s offline\n", dom->name); -+ be_mark_subdom_offline(dom, ctx); -+ } -+} -+ -+static void reactivate_subdoms(struct sss_domain_info *head) -+{ -+ struct sss_domain_info *dom; -+ -+ DEBUG(SSSDBG_TRACE_LIBS, "Resetting all subdomains"); -+ -+ for (dom = head; dom; dom = get_next_domain(dom, true)) { -+ if (sss_domain_get_state(dom) == DOM_INACTIVE) { -+ sss_domain_set_state(dom, DOM_ACTIVE); -+ } -+ } -+} -+ - static void be_reset_offline(struct be_ctx *ctx) - { - ctx->offstat.went_offline = 0; - ctx->offstat.offline = false; -+ -+ reactivate_subdoms(ctx->domain); -+ - be_ptask_disable(ctx->check_if_online_ptask); - be_run_online_cb(ctx); - } -diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h -index e4e22ea343a5cbf4c75f176c3002dc579c2893fe..4d54bf547682379bcb8cf855b8fae39214495728 100644 ---- a/src/providers/dp_backend.h -+++ b/src/providers/dp_backend.h -@@ -189,6 +189,7 @@ struct be_host_req { - - bool be_is_offline(struct be_ctx *ctx); - void be_mark_offline(struct be_ctx *ctx); -+void be_mark_dom_offline(struct sss_domain_info *dom, struct be_ctx *ctx); - - int be_add_reconnect_cb(TALLOC_CTX *mem_ctx, - struct be_ctx *ctx, -diff --git a/src/tests/cmocka/test_data_provider_be.c b/src/tests/cmocka/test_data_provider_be.c -new file mode 100644 -index 0000000000000000000000000000000000000000..68eb5841bee568bef64cb62461403036b1320bec ---- /dev/null -+++ b/src/tests/cmocka/test_data_provider_be.c -@@ -0,0 +1,275 @@ -+/* -+ Copyright (C) 2015 Red Hat -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "providers/dp_backend.h" -+#include "tests/cmocka/common_mock.h" -+#include "tests/cmocka/common_mock_be.h" -+#include "tests/common.h" -+ -+#define TESTS_PATH "tests_dp_be" -+#define TEST_CONF_DB "test_dp_be_conf.ldb" -+#define TEST_DOM_NAME "dp_be_test" -+#define TEST_ID_PROVIDER "ldap" -+ -+#define OFFLINE_TIMEOUT 2 -+#define AS_STR(param) (#param) -+ -+static TALLOC_CTX *global_mock_context = NULL; -+static bool global_timer_added; -+ -+struct tevent_timer *__real__tevent_add_timer(struct tevent_context *ev, -+ TALLOC_CTX *mem_ctx, -+ struct timeval next_event, -+ tevent_timer_handler_t handler, -+ void *private_data, -+ const char *handler_name, -+ const char *location); -+ -+struct tevent_timer *__wrap__tevent_add_timer(struct tevent_context *ev, -+ TALLOC_CTX *mem_ctx, -+ struct timeval next_event, -+ tevent_timer_handler_t handler, -+ void *private_data, -+ const char *handler_name, -+ const char *location) -+{ -+ global_timer_added = true; -+ -+ return __real__tevent_add_timer(ev, mem_ctx, next_event, -+ handler, private_data, handler_name, -+ location); -+} -+ -+ -+struct test_ctx { -+ struct sss_test_ctx *tctx; -+ struct be_ctx *be_ctx; -+}; -+ -+static struct sss_domain_info *named_domain(TALLOC_CTX *mem_ctx, -+ const char *name, -+ struct sss_domain_info *parent) -+{ -+ struct sss_domain_info *dom = NULL; -+ -+ dom = talloc_zero(mem_ctx, struct sss_domain_info); -+ assert_non_null(dom); -+ -+ dom->name = talloc_strdup(dom, name); -+ assert_non_null(dom->name); -+ -+ dom->parent = parent; -+ -+ return dom; -+} -+ -+static int test_setup(void **state) -+{ -+ struct test_ctx *test_ctx = NULL; -+ struct sss_test_conf_param params[] = { -+ { "offline_timeout", AS_STR(OFFLINE_TIMEOUT) }, -+ { NULL, NULL }, /* Sentinel */ -+ }; -+ -+ assert_true(leak_check_setup()); -+ global_mock_context = talloc_new(global_talloc_context); -+ assert_non_null(global_mock_context); -+ -+ test_ctx = talloc_zero(global_talloc_context, struct test_ctx); -+ assert_non_null(test_ctx); -+ -+ test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, -+ TEST_CONF_DB, TEST_DOM_NAME, -+ TEST_ID_PROVIDER, params); -+ assert_non_null(test_ctx->tctx); -+ -+ test_ctx->be_ctx = mock_be_ctx(test_ctx, test_ctx->tctx); -+ assert_non_null(test_ctx->be_ctx); -+ -+ test_ctx->be_ctx->domain->subdomains = named_domain(test_ctx, -+ "subdomains", -+ test_ctx->be_ctx->domain); -+ assert_non_null(test_ctx->be_ctx->domain->subdomains); -+ -+ *state = test_ctx; -+ -+ return 0; -+} -+ -+static int test_teardown(void **state) -+{ -+ talloc_zfree(*state); -+ assert_true(leak_check_teardown()); -+ return 0; -+} -+ -+static void assert_domain_state(struct sss_domain_info *dom, -+ enum sss_domain_state expected_state) -+{ -+ enum sss_domain_state dom_state; -+ -+ dom_state = sss_domain_get_state(dom); -+ assert_int_equal(dom_state, expected_state); -+} -+ -+static void test_mark_subdom_offline_check(struct tevent_context *ev, -+ struct tevent_timer *te, -+ struct timeval current_time, -+ void *pvt) -+{ -+ struct test_ctx *test_ctx = talloc_get_type(pvt, struct test_ctx); -+ -+ assert_domain_state(test_ctx->be_ctx->domain->subdomains, -+ DOM_ACTIVE); -+ -+ test_ctx->tctx->done = true; -+ test_ctx->tctx->error = EOK; -+} -+ -+static void test_mark_dom_offline(void **state) -+{ -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ -+ assert_domain_state(test_ctx->be_ctx->domain, DOM_ACTIVE); -+ assert_false(be_is_offline(test_ctx->be_ctx)); -+ -+ be_mark_dom_offline(test_ctx->be_ctx->domain, test_ctx->be_ctx); -+ -+ assert_true(be_is_offline(test_ctx->be_ctx)); -+ assert_domain_state(test_ctx->be_ctx->domain, DOM_ACTIVE); -+} -+ -+static void test_mark_subdom_offline(void **state) -+{ -+ struct timeval tv; -+ struct tevent_timer *check_ev = NULL; -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ errno_t ret; -+ -+ assert_domain_state(test_ctx->be_ctx->domain->subdomains, -+ DOM_ACTIVE); -+ assert_false(be_is_offline(test_ctx->be_ctx)); -+ -+ global_timer_added = false; -+ be_mark_dom_offline(test_ctx->be_ctx->domain->subdomains, test_ctx->be_ctx); -+ assert_domain_state(test_ctx->be_ctx->domain->subdomains, -+ DOM_INACTIVE); -+ -+ /* A timer must be added that resets the state back */ -+ assert_true(global_timer_added); -+ -+ /* Global offline state must not change */ -+ assert_false(be_is_offline(test_ctx->be_ctx)); -+ -+ /* Make sure we don't add a second timer */ -+ global_timer_added = false; -+ be_mark_dom_offline(test_ctx->be_ctx->domain->subdomains, test_ctx->be_ctx); -+ assert_domain_state(test_ctx->be_ctx->domain->subdomains, -+ DOM_INACTIVE); -+ assert_false(global_timer_added); -+ -+ /* Wait for the internal timer to reset our subdomain back */ -+ tv = tevent_timeval_current_ofs(OFFLINE_TIMEOUT + 1, 0); -+ -+ check_ev = tevent_add_timer(test_ctx->tctx->ev, test_ctx, tv, -+ test_mark_subdom_offline_check, -+ test_ctx); -+ if (check_ev == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "Cannot create timer\n"); -+ return; -+ } -+ -+ ret = test_ev_loop(test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ -+static void test_mark_subdom_offline_disabled(void **state) -+{ -+ struct test_ctx *test_ctx = talloc_get_type(*state, struct test_ctx); -+ -+ sss_domain_set_state(test_ctx->be_ctx->domain->subdomains, DOM_DISABLED); -+ assert_domain_state(test_ctx->be_ctx->domain->subdomains, -+ DOM_DISABLED); -+ -+ be_mark_dom_offline(test_ctx->be_ctx->domain->subdomains, test_ctx->be_ctx); -+ assert_domain_state(test_ctx->be_ctx->domain->subdomains, -+ DOM_DISABLED); -+} -+ -+int main(int argc, const char *argv[]) -+{ -+ poptContext pc; -+ int opt; -+ int rv; -+ int no_cleanup = 0; -+ struct poptOption long_options[] = { -+ POPT_AUTOHELP -+ SSSD_DEBUG_OPTS -+ {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0, -+ _("Do not delete the test database after a test run"), NULL }, -+ POPT_TABLEEND -+ }; -+ -+ const struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown(test_mark_dom_offline, -+ test_setup, -+ test_teardown), -+ cmocka_unit_test_setup_teardown(test_mark_subdom_offline, -+ test_setup, -+ test_teardown), -+ cmocka_unit_test_setup_teardown(test_mark_subdom_offline_disabled, -+ test_setup, -+ test_teardown), -+ }; -+ -+ /* Set debug level to invalid value so we can deside if -d 0 was used. */ -+ debug_level = SSSDBG_INVALID; -+ -+ pc = poptGetContext(argv[0], argc, argv, long_options, 0); -+ while((opt = poptGetNextOpt(pc)) != -1) { -+ switch(opt) { -+ default: -+ fprintf(stderr, "\nInvalid option %s: %s\n\n", -+ poptBadOption(pc, 0), poptStrerror(opt)); -+ poptPrintUsage(pc, stderr, 0); -+ return 1; -+ } -+ } -+ poptFreeContext(pc); -+ -+ DEBUG_CLI_INIT(debug_level); -+ -+ /* Even though normally the tests should clean up after themselves -+ * they might not after a failed run. Remove the old db to be sure */ -+ tests_set_cwd(); -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); -+ test_dom_suite_setup(TESTS_PATH); -+ -+ rv = cmocka_run_group_tests(tests, NULL, NULL); -+ if (rv == 0 && !no_cleanup) { -+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); -+ } -+ return rv; -+ -+ return cmocka_run_group_tests(tests, NULL, NULL); -+} --- -2.4.3 - diff --git a/SOURCES/0075-PAM-Do-not-act-on-ldb_message-in-case-of-a-failure.patch b/SOURCES/0075-PAM-Do-not-act-on-ldb_message-in-case-of-a-failure.patch new file mode 100644 index 0000000..8adb0ca --- /dev/null +++ b/SOURCES/0075-PAM-Do-not-act-on-ldb_message-in-case-of-a-failure.patch @@ -0,0 +1,60 @@ +From 86f099e6ca0e09dd5fe44816238a4323c63f9ee7 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 3 Aug 2016 17:43:14 +0200 +Subject: [PATCH 75/82] PAM: Do not act on ldb_message in case of a failure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Lukáš Slebodník +--- + src/responder/pam/pamsrv_cmd.c | 33 ++++++++++++++++++--------------- + 1 file changed, 18 insertions(+), 15 deletions(-) + +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 66564f5d301a53dcdb5967f43ef4afdb897e9974..be54fbf9b627d0ec1c3b0416401885245794cf9f 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -1534,21 +1534,24 @@ static int pam_check_user_search(struct pam_auth_req *preq) + + if (preq->pd->name_is_upn) { + ret = sysdb_search_user_by_upn(preq, dom, name, user_attrs, &msg); +- +- /* Since sysdb_search_user_by_upn() searches the whole cache we +- * have to set the domain so that it matches the result. */ +- sysdb_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); +- if (sysdb_name == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Cached entry has no name.\n"); +- return EINVAL; +- } +- preq->domain = find_domain_by_object_name(get_domains_head(dom), +- sysdb_name); +- if (preq->domain == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Cannot find matching domain for [%s].\n", +- sysdb_name); +- return EINVAL; ++ if (ret == EOK) { ++ /* Since sysdb_search_user_by_upn() searches the whole cache we ++ * have to set the domain so that it matches the result. */ ++ sysdb_name = ldb_msg_find_attr_as_string(msg, ++ SYSDB_NAME, NULL); ++ if (sysdb_name == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Cached entry has no name.\n"); ++ return EINVAL; ++ } ++ preq->domain = find_domain_by_object_name( ++ get_domains_head(dom), ++ sysdb_name); ++ if (preq->domain == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot find matching domain for [%s].\n", ++ sysdb_name); ++ return EINVAL; ++ } + } + } else { + ret = sysdb_getpwnam_with_views(preq, dom, name, &res); +-- +2.4.11 + diff --git a/SOURCES/0076-IPA-Check-the-return-value-of-sss_parse_internal_fqn.patch b/SOURCES/0076-IPA-Check-the-return-value-of-sss_parse_internal_fqn.patch new file mode 100644 index 0000000..1dfbf21 --- /dev/null +++ b/SOURCES/0076-IPA-Check-the-return-value-of-sss_parse_internal_fqn.patch @@ -0,0 +1,38 @@ +From 2e027e43f0adb1b7c80e51d5613fca5a497ca331 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 3 Aug 2016 18:03:59 +0200 +Subject: [PATCH 76/82] IPA: Check the return value of + sss_parse_internal_fqname +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We should fail the request if sss_parse_internal_fqname() fails. + +Reviewed-by: Lukáš Slebodník +--- + src/providers/ipa/ipa_subdomains_id.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c +index 002857699b65c86a6ed0c912a2a7ae06a8f9e507..2299523d0c52e3277db6d1061c79b320e78c8f72 100644 +--- a/src/providers/ipa/ipa_subdomains_id.c ++++ b/src/providers/ipa/ipa_subdomains_id.c +@@ -509,6 +509,14 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) + } else { + ret = sss_parse_internal_fqname(req_input, state->filter, + &shortname, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot parse internal name [%s]: %d\n", ++ state->filter, ret); ++ tevent_req_error(req, ret); ++ return; ++ } ++ + req_input->inp.name = talloc_steal(req_input, shortname); + } + if (req_input->inp.name == NULL) { +-- +2.4.11 + diff --git a/SOURCES/0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch b/SOURCES/0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch deleted file mode 100644 index 58bc0b3..0000000 --- a/SOURCES/0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch +++ /dev/null @@ -1,43 +0,0 @@ -From d170e144a1ae702ba55c508599ffbda4e95919e5 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 2 Sep 2015 13:40:48 +0200 -Subject: [PATCH 76/87] SDAP: Do not set is_offline if ignore_mark_offline is - set -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Required for: -https://fedorahosted.org/sssd/ticket/2637 - -The caller of the sdap_id_op requests can set the ignore_mark_offline -flag to avoid the sdap_id_op from marking the whole back end as offline. - -However, there was a small bug - the is_offline internal sdap_id_op flag -was still being set. As a consequence, the error code from the -connection was ignored and EAGAIN was always returned. - -Reviewed-by: Pavel Březina -(cherry picked from commit 0561d532cf76b035b73cfed929a6896071dac407) ---- - src/providers/ldap/sdap_id_op.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c -index 508bbd2ad3ebb3f9159a8b7f48258ff31a7cd6e2..0474a9cb7828ef43ef76cf6bebac077315296875 100644 ---- a/src/providers/ldap/sdap_id_op.c -+++ b/src/providers/ldap/sdap_id_op.c -@@ -567,9 +567,9 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq) - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to connect, going offline (%d [%s])\n", - ret, strerror(ret)); -+ is_offline = true; - be_mark_offline(conn_cache->id_conn->id_ctx->be); - } -- is_offline = true; - } - - if (ret == EOK) { --- -2.4.3 - diff --git a/SOURCES/0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch b/SOURCES/0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch deleted file mode 100644 index 2cf3e51..0000000 --- a/SOURCES/0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 4b9db04661f30625fb00bb22dc7ff84e77d2efb2 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 2 Sep 2015 13:42:06 +0200 -Subject: [PATCH 77/87] AD: Only ignore errors from SDAP lookups if there's - another connection to fallback to -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Required for: -https://fedorahosted.org/sssd/ticket/2637 - -The AD lookup code honors the ignore_mark_offline flag in the sense that -if it's set, the sdap return code is not reported to the upper layer, -but EOK is returned as request status and the sdap return code is -returned separately. - -This patch modifies the behaviour further to only apply if there is -another connection to fall back to. - -Reviewed-by: Pavel Březina -(cherry picked from commit 7fc8692d49cdaa0368072f196433c07b475da679) ---- - src/providers/ad/ad_id.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 7a0c6eccd2d2f0d4f8a545a9d4873a9447179a00..4f327f823173eb113153a556322dae4cc4b42f3e 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -146,6 +146,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq) - - ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err, &sdap_err); - if (dp_error == DP_ERR_OFFLINE -+ && state->conn[state->cindex+1] != NULL - && state->conn[state->cindex]->ignore_mark_offline) { - /* This is a special case: GC does not work. - * We need to Fall back to ldap --- -2.4.3 - diff --git a/SOURCES/0077-DP-Initialize-D-Bus-as-soon-as-possible.patch b/SOURCES/0077-DP-Initialize-D-Bus-as-soon-as-possible.patch new file mode 100644 index 0000000..9641722 --- /dev/null +++ b/SOURCES/0077-DP-Initialize-D-Bus-as-soon-as-possible.patch @@ -0,0 +1,93 @@ +From 178e61b6dc5b547bd77998f586f118bfa9b06d30 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 5 Aug 2016 11:32:43 +0200 +Subject: [PATCH 77/82] DP: Initialize D-Bus as soon as possible + +Resolves: +https://fedorahosted.org/sssd/ticket/3111 + +Reviewed-by: Petr Cech +--- + src/providers/data_provider/dp.c | 34 +++++++++++++++++++------------- + src/providers/data_provider/dp_methods.c | 6 ++++++ + 2 files changed, 26 insertions(+), 14 deletions(-) + +diff --git a/src/providers/data_provider/dp.c b/src/providers/data_provider/dp.c +index c4590e3152126fe166d0bc9e3be2a14978f90168..b672370aa153c9cd2031399a8d61c95fb16cd641 100644 +--- a/src/providers/data_provider/dp.c ++++ b/src/providers/data_provider/dp.c +@@ -86,6 +86,7 @@ errno_t dp_init(struct tevent_context *ev, + provider->gid = gid; + provider->be_ctx = be_ctx; + ++ /* Initialize request table. */ + ret = dp_req_table_init(provider, &provider->requests.reply_table); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize request table " +@@ -93,20 +94,11 @@ errno_t dp_init(struct tevent_context *ev, + goto done; + } + +- ret = dp_init_modules(provider, &provider->modules); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize DP modules " +- "[%d]: %s\n", ret, sss_strerror(ret)); +- goto done; +- } +- +- ret = dp_init_targets(provider, be_ctx, provider, provider->modules); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize DP targets " +- "[%d]: %s\n", ret, sss_strerror(ret)); +- goto done; +- } +- ++ /* Initialize data provider bus. Data provider can receive client ++ * registration and other D-Bus methods. However no data provider ++ * request will be executed as long as the modules and targets ++ * are not initialized. ++ */ + talloc_set_destructor(provider, dp_destructor); + + ret = dp_init_dbus_server(provider); +@@ -118,6 +110,20 @@ errno_t dp_init(struct tevent_context *ev, + + be_ctx->provider = provider; + ++ ret = dp_init_modules(provider, &provider->modules); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize DP modules " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ ret = dp_init_targets(provider, be_ctx, provider, provider->modules); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize DP targets " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ goto done; ++ } ++ + ret = EOK; + + done: +diff --git a/src/providers/data_provider/dp_methods.c b/src/providers/data_provider/dp_methods.c +index e4290beeeef3c0c4d156271ad88f891d3245af08..498676d1bec2da300ca4b33f7110debcbf0aac00 100644 +--- a/src/providers/data_provider/dp_methods.c ++++ b/src/providers/data_provider/dp_methods.c +@@ -76,6 +76,12 @@ bool dp_method_enabled(struct data_provider *provider, + return false; + } + ++ if (provider == NULL || provider->targets == NULL) { ++ DEBUG(SSSDBG_TRACE_FUNC, "Target %s is not yet initialized\n", ++ dp_target_to_string(target)); ++ return false; ++ } ++ + dp_target = provider->targets[target]; + if (dp_target == NULL || dp_target->initialized == false) { + DEBUG(SSSDBG_TRACE_FUNC, "Target %s is not configured\n", +-- +2.4.11 + diff --git a/SOURCES/0078-KRB5-Offline-operation-with-disabled-domain.patch b/SOURCES/0078-KRB5-Offline-operation-with-disabled-domain.patch deleted file mode 100644 index 690f4ac..0000000 --- a/SOURCES/0078-KRB5-Offline-operation-with-disabled-domain.patch +++ /dev/null @@ -1,59 +0,0 @@ -From adbeda40c0b39918b12c4f72c97a89156c6360c2 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 2 Sep 2015 15:53:34 +0200 -Subject: [PATCH 78/87] KRB5: Offline operation with disabled domain -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2637 - -If a subdomain is in the disabled state, switch krb5_child operation -into offline mode. - -Similarly, instead of marking the whole back end as offline, mark just -the domain as offline -- depending on the domain type, this would mark -the whole back end or just inactivate subdomain. - -Reviewed-by: Pavel Březina -(cherry picked from commit dd0a21738e1b71940bba11134734b5999e9fd8e9) ---- - src/providers/krb5/krb5_auth.c | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c -index da8309d0504a6815902513693343a3500f454557..7ee7fa738db32abeb4709927956d1297325e2d5b 100644 ---- a/src/providers/krb5/krb5_auth.c -+++ b/src/providers/krb5/krb5_auth.c -@@ -720,7 +720,7 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq) - * was found good, setting offline, - * but we still have to call the child to setup - * the ccache file if we are performing auth */ -- be_mark_offline(state->be_ctx); -+ be_mark_dom_offline(state->domain, state->be_ctx); - kr->is_offline = true; - - if (kr->pd->cmd == SSS_PAM_CHAUTHTOK || -@@ -754,9 +754,19 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq) - kr->is_offline = be_is_offline(state->be_ctx); - } - -+ if (!kr->is_offline -+ && sss_domain_get_state(state->domain) == DOM_INACTIVE) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Subdomain %s is inactive, will proceed offline\n", -+ state->domain->name); -+ kr->is_offline = true; -+ } -+ - if (kr->is_offline - && sss_krb5_realm_has_proxy(dp_opt_get_cstring(kr->krb5_ctx->opts, - KRB5_REALM))) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Resetting offline status, KDC proxy is in use\n"); - kr->is_offline = false; - } - --- -2.4.3 - diff --git a/SOURCES/0078-sssctl-Generic-help-for-cache-upgrade-and-config-che.patch b/SOURCES/0078-sssctl-Generic-help-for-cache-upgrade-and-config-che.patch new file mode 100644 index 0000000..bff746f --- /dev/null +++ b/SOURCES/0078-sssctl-Generic-help-for-cache-upgrade-and-config-che.patch @@ -0,0 +1,58 @@ +From 44b93ae9e80652661da7c1f35aa5aec532e6f04d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Tue, 26 Jul 2016 16:35:55 +0200 +Subject: [PATCH 78/82] sssctl: Generic help for cache-upgrade and config-check +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sssctl COMMAND --help should print at least +generic help, even if the command does not +accept any command specific options. + +Resolves: +https://fedorahosted.org/sssd/ticket/3086 + +Reviewed-by: Pavel Březina +--- + src/tools/sssctl/sssctl_config.c | 6 ++++++ + src/tools/sssctl/sssctl_data.c | 6 ++++++ + 2 files changed, 12 insertions(+) + +diff --git a/src/tools/sssctl/sssctl_config.c b/src/tools/sssctl/sssctl_config.c +index a66d7749c4aee9bd00c0ad2d296292658ffdb9b2..630df3c8ff5368ef253bb9753380e94c8c0a307d 100644 +--- a/src/tools/sssctl/sssctl_config.c ++++ b/src/tools/sssctl/sssctl_config.c +@@ -47,6 +47,12 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline, + char **strs = NULL; + TALLOC_CTX *tmp_ctx = NULL; + ++ ret = sss_tool_popt(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL, NULL, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); ++ return ret; ++ } ++ + tmp_ctx = talloc_new(NULL); + init_data = sss_ini_initdata_init(tmp_ctx); + if (!init_data) { +diff --git a/src/tools/sssctl/sssctl_data.c b/src/tools/sssctl/sssctl_data.c +index a26ddd8d5200319e75282b738791cf270f0d75a8..72823ab254344bba6f7679882a733b6ef2250525 100644 +--- a/src/tools/sssctl/sssctl_data.c ++++ b/src/tools/sssctl/sssctl_data.c +@@ -266,6 +266,12 @@ errno_t sssctl_cache_upgrade(struct sss_cmdline *cmdline, + struct sysdb_upgrade_ctx db_up_ctx; + errno_t ret; + ++ ret = sss_tool_popt(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL, NULL, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); ++ return ret; ++ } ++ + if (sss_deamon_running()) { + return ERR_SSSD_RUNNING; + } +-- +2.4.11 + diff --git a/SOURCES/0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch b/SOURCES/0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch deleted file mode 100644 index f299514..0000000 --- a/SOURCES/0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch +++ /dev/null @@ -1,197 +0,0 @@ -From 1055c11f7cafae490221e9203f33ddfa94f47c48 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 2 Sep 2015 15:52:51 +0200 -Subject: [PATCH 79/87] AD: Do not mark the whole back end as offline if - subdomain lookup fails -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Required for: -https://fedorahosted.org/sssd/ticket/2637 - -Rather mark the domain as inactive. It will be marked as active later, -in the meantime the main domain can continue to work online and -subdomain requests will be answered from cache. - -The lookup request itself just returns a special error code and lets the -caller handle the error code as appropriate (normally by disabling the -subdomain temporarily). - -Reviewed-by: Pavel Březina -(cherry picked from commit 64d4b1e5fd4a3c99ef8d8fef6ad0db52c5152c1c) ---- - src/providers/ad/ad_id.c | 81 +++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 67 insertions(+), 14 deletions(-) - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index 4f327f823173eb113153a556322dae4cc4b42f3e..ecaf6c993bf7ddb7ba565d40ef0ad250114f5536 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -91,17 +91,27 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx, - state->ad_options = ad_options; - state->cindex = 0; - -+ if (sss_domain_get_state(sdom->dom) == DOM_INACTIVE) { -+ ret = ERR_SUBDOM_INACTIVE; -+ goto immediate; -+ } -+ - ret = ad_handle_acct_info_step(req); -- if (ret == EOK) { -- tevent_req_done(req); -- tevent_req_post(req, be_ctx->ev); -- } else if (ret != EAGAIN) { -- tevent_req_error(req, ret); -- tevent_req_post(req, be_ctx->ev); -+ if (ret != EAGAIN) { -+ goto immediate; - } - - /* Lookup in progress */ - return req; -+ -+immediate: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } else { -+ tevent_req_done(req); -+ } -+ tevent_req_post(req, be_ctx->ev); -+ return req; - } - - static errno_t -@@ -160,8 +170,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq) - state->dp_error = dp_error; - state->err = err; - -- tevent_req_error(req, ret); -- return; -+ goto fail; - } - - if (sdap_err == EOK) { -@@ -170,8 +179,8 @@ ad_handle_acct_info_done(struct tevent_req *subreq) - } else if (sdap_err == ERR_NO_POSIX) { - disable_gc(state->ad_options); - } else if (sdap_err != ENOENT) { -- tevent_req_error(req, EIO); -- return; -+ ret = EIO; -+ goto fail; - } - - /* Ret is only ENOENT or ERR_NO_POSIX now. Try the next connection */ -@@ -188,12 +197,27 @@ ad_handle_acct_info_done(struct tevent_req *subreq) - /* No more connections */ - tevent_req_done(req); - } else { -- tevent_req_error(req, ret); -+ goto fail; - } - return; - } - - /* Another lookup in progress */ -+ return; -+ -+fail: -+ if (IS_SUBDOMAIN(state->sdom->dom)) { -+ /* Deactivate subdomain on lookup errors instead of going -+ * offline completely. -+ * This is a stopgap, until our failover is per-domain, -+ * not per-backend. Unfortunately, we can't rewrite the error -+ * code on some reported codes only, because sdap_id_op code -+ * encapsulated the failover as well.. -+ */ -+ ret = ERR_SUBDOM_INACTIVE; -+ } -+ tevent_req_error(req, ret); -+ return; - } - - errno_t -@@ -258,6 +282,16 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - break; - } - -+ /* Regardless of connection types, a subdomain error must not be allowed -+ * to set the whole back end offline, rather report an error and let the -+ * caller deal with it (normally disable the subdomain -+ */ -+ if (IS_SUBDOMAIN(dom)) { -+ for (cindex = 0; clist[cindex] != NULL; cindex++) { -+ clist[cindex]->ignore_mark_offline = true; -+ } -+ } -+ - return clist; - } - -@@ -328,6 +362,11 @@ done: - - static void ad_account_info_complete(struct tevent_req *req); - -+struct ad_account_info_state { -+ struct be_req *be_req; -+ struct sss_domain_info *dom; -+}; -+ - void - ad_account_info_handler(struct be_req *be_req) - { -@@ -341,6 +380,7 @@ ad_account_info_handler(struct be_req *be_req) - struct sdap_id_conn_ctx **clist; - bool shortcut; - errno_t ret; -+ struct ad_account_info_state *state; - - ad_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data, - struct ad_id_ctx); -@@ -391,13 +431,21 @@ ad_account_info_handler(struct be_req *be_req) - goto fail; - } - -+ state = talloc(be_req, struct ad_account_info_state); -+ if (state == NULL) { -+ ret = ENOMEM; -+ goto fail; -+ } -+ state->dom = sdom->dom; -+ state->be_req = be_req; -+ - req = ad_handle_acct_info_send(be_req, be_req, ar, sdap_id_ctx, - ad_ctx->ad_options, sdom, clist); - if (req == NULL) { - ret = ENOMEM; - goto fail; - } -- tevent_req_set_callback(req, ad_account_info_complete, be_req); -+ tevent_req_set_callback(req, ad_account_info_complete, state); - return; - - fail: -@@ -412,12 +460,17 @@ ad_account_info_complete(struct tevent_req *req) - int dp_error; - const char *error_text = "Internal error"; - const char *req_error_text; -+ struct ad_account_info_state *state; - -- be_req = tevent_req_callback_data(req, struct be_req); -+ state = tevent_req_callback_data(req, struct ad_account_info_state); -+ be_req = state->be_req; - - ret = ad_handle_acct_info_recv(req, &dp_error, &req_error_text); - talloc_zfree(req); -- if (dp_error == DP_ERR_OK) { -+ if (ret == ERR_SUBDOM_INACTIVE) { -+ be_mark_dom_offline(state->dom, be_req_get_be_ctx(be_req)); -+ return be_req_terminate(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline"); -+ } else if (dp_error == DP_ERR_OK) { - if (ret == EOK) { - error_text = NULL; - } else { --- -2.4.3 - diff --git a/SOURCES/0079-NSS-Do-not-check-local-users-with-disabled-local_neg.patch b/SOURCES/0079-NSS-Do-not-check-local-users-with-disabled-local_neg.patch new file mode 100644 index 0000000..b4c2e9e --- /dev/null +++ b/SOURCES/0079-NSS-Do-not-check-local-users-with-disabled-local_neg.patch @@ -0,0 +1,166 @@ +From acb2de04987b163d602aa02155b34c50bce93584 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 8 Aug 2016 13:55:52 +0200 +Subject: [PATCH 79/82] NSS: Do not check local users with disabled + local_negative_timeout + +sssd_nss can set different negative timeout for local users +and groups. However, checking whether user/group is local +is quite expensive operation. We can avoid such operations +if local_negative_timeout is not set. + +This fix improve performance(40%) of lookup non-existing +entries in offline mode and with disabled local_negative_timeout. + + sh$ cat pok.sh + for i in {1..10000}; do + getent passwd -s sss temp$i + getent group -s sss temp$i + done + + #without patch + sh $time /bin/bash pok.sh + real 0m41.534s + user 0m3.580s + sys 0m14.202s + + #with patch + sh $time /bin/bash pok.sh + real 0m26.686s + user 0m3.292s + sys 0m13.165s + +Resolves: +https://fedorahosted.org/sssd/ticket/3122 + +Reviewed-by: Petr Cech +--- + src/responder/common/negcache.c | 45 ++++++++++++++++++++++++----------------- + 1 file changed, 27 insertions(+), 18 deletions(-) + +diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c +index dfeb0d483e4db34cb2f25e1f82884611a707aabe..5b7ad69f432518be94b88e92e24265add722c852 100644 +--- a/src/responder/common/negcache.c ++++ b/src/responder/common/negcache.c +@@ -143,7 +143,7 @@ done: + } + + static int sss_ncache_set_str(struct sss_nc_ctx *ctx, char *str, +- bool permanent, bool is_local) ++ bool permanent, bool use_local_negative) + { + TDB_DATA key; + TDB_DATA data; +@@ -157,15 +157,16 @@ static int sss_ncache_set_str(struct sss_nc_ctx *ctx, char *str, + if (permanent) { + timest = talloc_strdup(ctx, "0"); + } else { +- if (is_local == true && ctx->local_timeout > 0) { +- timell = (unsigned long long int)time(NULL) + ctx->local_timeout; ++ if (use_local_negative == true && ctx->local_timeout > ctx->timeout) { ++ timell = ctx->local_timeout; + } else { +- if (ctx->timeout > 0) { +- timell = (unsigned long long int)time(NULL) + ctx->timeout; +- } else { ++ /* EOK is tested in cwrap based unit test */ ++ if (ctx->timeout == 0) { + return EOK; + } ++ timell = ctx->timeout; + } ++ timell += (unsigned long long int)time(NULL); + timest = talloc_asprintf(ctx, "%llu", timell); + } + if (!timest) return ENOMEM; +@@ -457,7 +458,7 @@ int sss_ncache_check_cert(struct sss_nc_ctx *ctx, const char *cert) + static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent, + const char *domain, const char *name) + { +- bool is_local; ++ bool use_local_negative = false; + char *str; + int ret; + +@@ -466,8 +467,10 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent, + str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name); + if (!str) return ENOMEM; + +- is_local = is_user_local_by_name(name); +- ret = sss_ncache_set_str(ctx, str, permanent, is_local); ++ if (ctx->local_timeout > 0) { ++ use_local_negative = is_user_local_by_name(name); ++ } ++ ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); + + talloc_free(str); + return ret; +@@ -476,7 +479,7 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent, + static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent, + const char *domain, const char *name) + { +- bool is_local; ++ bool use_local_negative = false; + char *str; + int ret; + +@@ -485,8 +488,10 @@ static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent, + str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name); + if (!str) return ENOMEM; + +- is_local = is_group_local_by_name(name); +- ret = sss_ncache_set_str(ctx, str, permanent, is_local); ++ if (ctx->local_timeout > 0) { ++ use_local_negative = is_group_local_by_name(name); ++ } ++ ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); + + talloc_free(str); + return ret; +@@ -550,7 +555,7 @@ int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent, + int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, + struct sss_domain_info *dom, uid_t uid) + { +- bool is_local; ++ bool use_local_negative = false; + char *str; + int ret; + +@@ -562,8 +567,10 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, + } + if (!str) return ENOMEM; + +- is_local = is_user_local_by_uid(uid); +- ret = sss_ncache_set_str(ctx, str, permanent, is_local); ++ if (ctx->local_timeout > 0) { ++ use_local_negative = is_user_local_by_uid(uid); ++ } ++ ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); + + talloc_free(str); + return ret; +@@ -572,7 +579,7 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, + int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent, + struct sss_domain_info *dom, gid_t gid) + { +- bool is_local; ++ bool use_local_negative = false; + char *str; + int ret; + +@@ -584,8 +591,10 @@ int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent, + } + if (!str) return ENOMEM; + +- is_local = is_group_local_by_gid(gid); +- ret = sss_ncache_set_str(ctx, str, permanent, is_local); ++ if (ctx->local_timeout > 0) { ++ use_local_negative = is_group_local_by_gid(gid); ++ } ++ ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); + + talloc_free(str); + return ret; +-- +2.4.11 + diff --git a/SOURCES/0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch b/SOURCES/0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch deleted file mode 100644 index 61941b7..0000000 --- a/SOURCES/0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch +++ /dev/null @@ -1,157 +0,0 @@ -From d89c2dc276a8974b20a77b54ba663d4a1fa5acd2 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 2 Sep 2015 12:10:03 +0000 -Subject: [PATCH 80/87] AD: Set ignore_mark_offline=false when resolving AD - root domain -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2637 - -Avoid going offline in cases where SSSD is connected to a child domain -but the root domain is not accessible. - -Reviewed-by: Pavel Březina -(cherry picked from commit ece345a74cec793e6d970a4955beb3d4a05935b3) ---- - src/providers/ad/ad_subdomains.c | 56 +++++++++++++++++++++++----------------- - 1 file changed, 33 insertions(+), 23 deletions(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index d1d468043410c80e6bf7f0f48a13bd9e962552af..8ed3dab0995f78a16f4a7df2e729ea88a39a782c 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -80,7 +80,8 @@ struct ad_subdomains_req_ctx { - struct ad_id_ctx *root_id_ctx; - struct sdap_id_op *root_op; - size_t root_base_iter; -- struct sysdb_attrs *root_domain; -+ struct sysdb_attrs *root_domain_attrs; -+ struct sss_domain_info *root_domain; - - size_t reply_count; - struct sysdb_attrs **reply; -@@ -689,6 +690,7 @@ static errno_t ad_subdomains_get_root(struct ad_subdomains_req_ctx *ctx) - return EAGAIN; - } - -+static struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx); - static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx); - static void ad_subdomains_root_conn_done(struct tevent_req *req); - -@@ -769,7 +771,14 @@ static void ad_subdomains_get_root_domain_done(struct tevent_req *req) - } - } - -- ctx->root_domain = reply[0]; -+ ctx->root_domain_attrs = reply[0]; -+ ctx->root_domain = ads_get_root_domain(ctx); -+ if (ctx->root_domain == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n"); -+ ret = EFAULT; -+ goto fail; -+ } -+ - ctx->root_id_ctx = ads_get_root_id_ctx(ctx); - if (ctx->root_id_ctx == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "Cannot create id ctx for the root domain\n"); -@@ -803,15 +812,13 @@ fail: - be_req_terminate(ctx->be_req, dp_error, ret, NULL); - } - --static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx) -+static struct sss_domain_info *ads_get_root_domain(struct ad_subdomains_req_ctx *ctx) - { - errno_t ret; - const char *name; - struct sss_domain_info *root; -- struct sdap_domain *sdom; -- struct ad_id_ctx *root_id_ctx; - -- ret = sysdb_attrs_get_string(ctx->root_domain, AD_AT_TRUST_PARTNER, &name); -+ ret = sysdb_attrs_get_string(ctx->root_domain_attrs, AD_AT_TRUST_PARTNER, &name); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); - return NULL; -@@ -820,32 +827,40 @@ static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx) - /* With a subsequent run, the root should already be known */ - root = find_domain_by_name(ctx->sd_ctx->be_ctx->domain, - name, false); -- if (root == NULL) { -- DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n"); -- return NULL; -- } - -- sdom = sdap_domain_get(ctx->sd_ctx->ad_id_ctx->sdap_id_ctx->opts, root); -+ return root; -+} -+ -+static struct ad_id_ctx *ads_get_root_id_ctx(struct ad_subdomains_req_ctx *ctx) -+{ -+ errno_t ret; -+ struct sdap_domain *sdom; -+ struct ad_id_ctx *root_id_ctx; -+ -+ sdom = sdap_domain_get(ctx->sd_ctx->ad_id_ctx->sdap_id_ctx->opts, -+ ctx->root_domain); - if (sdom == NULL) { - DEBUG(SSSDBG_OP_FAILURE, -- "Cannot get the sdom for %s!\n", root->name); -+ "Cannot get the sdom for %s!\n", ctx->root_domain->name); - return NULL; - } - - if (sdom->pvt == NULL) { - ret = ad_subdom_ad_ctx_new(ctx->sd_ctx->be_ctx, - ctx->sd_ctx->ad_id_ctx, -- root, -+ ctx->root_domain, - &root_id_ctx); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "ad_subdom_ad_ctx_new failed.\n"); - return NULL; - } -+ - sdom->pvt = root_id_ctx; - } else { - root_id_ctx = sdom->pvt; - } - -+ root_id_ctx->ldap_ctx->ignore_mark_offline = true; - return root_id_ctx; - } - -@@ -860,16 +875,11 @@ static void ad_subdomains_root_conn_done(struct tevent_req *req) - ret = sdap_id_op_connect_recv(req, &dp_error); - talloc_zfree(req); - if (ret) { -- if (dp_error == DP_ERR_OFFLINE) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- "No AD server is available, cannot get the " -- "subdomain list while offline\n"); -- } else { -- DEBUG(SSSDBG_OP_FAILURE, -- "Failed to connect to AD server: [%d](%s)\n", -- ret, strerror(ret)); -- } -+ be_mark_dom_offline(ctx->root_domain, be_req_get_be_ctx(ctx->be_req)); - -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to connect to AD server: [%d](%s)\n", -+ ret, strerror(ret)); - goto fail; - } - -@@ -1040,7 +1050,7 @@ static void ad_subdomains_get_slave_domain_done(struct tevent_req *req) - */ - ret = ad_subdomains_process(ctx, ctx->sd_ctx->be_ctx->domain, - ctx->reply_count, ctx->reply, -- ctx->root_domain, &nsubdoms, &subdoms); -+ ctx->root_domain_attrs, &nsubdoms, &subdoms); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, ("Cannot process subdomain list\n")); - tevent_req_error(req, ret); --- -2.4.3 - diff --git a/SOURCES/0080-config_schema-Add-ldap_user_email-to-schema.patch b/SOURCES/0080-config_schema-Add-ldap_user_email-to-schema.patch new file mode 100644 index 0000000..416c768 --- /dev/null +++ b/SOURCES/0080-config_schema-Add-ldap_user_email-to-schema.patch @@ -0,0 +1,31 @@ +From fad4c17acbc0170110a98806886e0eeec793c0c6 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Wed, 10 Aug 2016 08:17:02 +0200 +Subject: [PATCH 80/82] config_schema: Add ldap_user_email to schema +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/3068 + +Reviewed-by: Fabiano Fidêncio +--- + src/config/cfg_rules.ini | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index 635c078436e8ca47f60e8d82341cb131469fe4c9..09f53fa41eb2904f11a78af333b6d79619d2759c 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -588,6 +588,7 @@ option = ldap_user_authorized_host + option = ldap_user_authorized_service + option = ldap_user_auth_type + option = ldap_user_certificate ++option = ldap_user_email + option = ldap_user_entry_usn + option = ldap_user_extra_attrs + option = ldap_user_fullname +-- +2.4.11 + diff --git a/SOURCES/0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch b/SOURCES/0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch deleted file mode 100644 index 8b3f8b2..0000000 --- a/SOURCES/0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch +++ /dev/null @@ -1,57 +0,0 @@ -From fbf7fe9a713948eaf5e47518c776f2ad664b9e46 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 2 Sep 2015 13:41:26 +0200 -Subject: [PATCH 81/87] IPA: Do not allow the AD lookup code to set backend as - offline in server mode -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2637 - -In server mode, we should not allow the AD lookups to set the backend -offline. Rather just let them report an error and deal with the error -separately. - -Reviewed-by: Pavel Březina -(cherry picked from commit 20162352030d1c577bb69d44e967d2c5839e5c0e) ---- - src/providers/ipa/ipa_subdomains_id.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 610b1c58b3b180201cfb5b22f870f8937673e02e..ff14b4a4c68cb5c6e9865a66931ee4ecd6e49211 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -633,6 +633,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, - ret = ENOMEM; - goto fail; - } -+ clist[1]->ignore_mark_offline = true; - break; - default: - clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2); -@@ -641,6 +642,7 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, - goto fail; - } - clist[0] = ad_id_ctx->ldap_ctx; -+ clist[0]->ignore_mark_offline = true; - clist[1] = NULL; - } - -@@ -1036,7 +1038,11 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) - - ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL); - talloc_zfree(subreq); -- if (ret != EOK) { -+ if (ret == ERR_SUBDOM_INACTIVE) { -+ be_mark_dom_offline(state->obj_dom, be_req_get_be_ctx(state->be_req)); -+ tevent_req_error(req, ret); -+ return; -+ } else if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "AD lookup failed: %d\n", ret); - tevent_req_error(req, ret); - return; --- -2.4.3 - diff --git a/SOURCES/0081-NSS-Use-correct-name-for-invalidating-memory-cache.patch b/SOURCES/0081-NSS-Use-correct-name-for-invalidating-memory-cache.patch new file mode 100644 index 0000000..3cc0985 --- /dev/null +++ b/SOURCES/0081-NSS-Use-correct-name-for-invalidating-memory-cache.patch @@ -0,0 +1,113 @@ +From 1d0a914578ce72bad86cbe9e0beeda0c3b2d1dee Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 8 Aug 2016 17:30:29 +0200 +Subject: [PATCH 81/82] NSS: Use correct name for invalidating memory cache + +After refactoring of sysdb, we get and internal fully qualified +name from backend in org.freedesktop.sssd.dataprovider_rev.initgrCheck +Previously we got short name and we created fq name in +nss_update_initgr_memcache. Memory cache still need to use short names +if it was specified. + +This patch uses right name in different places. + +Reviewed-by: Petr Cech +Reviewed-by: Jakub Hrozek +--- + src/responder/nss/nsssrv_cmd.c | 31 +++++++++++++++++-------------- + src/responder/nss/nsssrv_private.h | 2 +- + 2 files changed, 18 insertions(+), 15 deletions(-) + +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index f3b6ac4afb5d1571f283933b48e0256b91c56391..573959ea76fc1277fe84f40b88dcd34093da468d 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -3961,13 +3961,13 @@ done: + } + + void nss_update_initgr_memcache(struct nss_ctx *nctx, +- const char *name, const char *domain, ++ const char *fq_name, const char *domain, + int gnum, uint32_t *groups) + { + TALLOC_CTX *tmp_ctx = NULL; + struct sss_domain_info *dom; + struct ldb_result *res; +- struct sized_string delete_name; ++ struct sized_string *delete_name; + bool changed = false; + uint32_t id; + uint32_t gids[gnum]; +@@ -3987,8 +3987,19 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, + } + + tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return; ++ } + +- ret = sysdb_initgroups(tmp_ctx, dom, name, &res); ++ ret = sized_output_name(tmp_ctx, nctx->rctx, fq_name, dom, &delete_name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sized_output_name failed for '%s': %d [%s]\n", ++ fq_name, ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ ret = sysdb_initgroups(tmp_ctx, dom, fq_name, &res); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to make request to our cache! [%d][%s]\n", +@@ -4002,8 +4013,7 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, + + if (ret == ENOENT || res->count == 0) { + /* The user is gone. Invalidate the mc record */ +- to_sized_string(&delete_name, name); +- ret = sss_mmap_cache_pw_invalidate(nctx->pwd_mc_ctx, &delete_name); ++ ret = sss_mmap_cache_pw_invalidate(nctx->pwd_mc_ctx, delete_name); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Internal failure in memory cache code: %d [%s]\n", +@@ -4047,13 +4057,6 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, + } + + if (changed) { +- char *fq_name = sss_tc_fqname(tmp_ctx, dom->names, dom, name); +- if (!fq_name) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Could not create fq name\n"); +- goto done; +- } +- + for (i = 0; i < gnum; i++) { + id = groups[i]; + +@@ -4065,9 +4068,9 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx, + } + } + +- to_sized_string(&delete_name, fq_name); ++ to_sized_string(delete_name, fq_name); + ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx, +- &delete_name); ++ delete_name); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Internal failure in memory cache code: %d [%s]\n", +diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h +index 79c7b7265f66f57e0ea89fe192a1da4f8992f1a3..391eaaf40f84a7436bee63fd699241e4957fdbeb 100644 +--- a/src/responder/nss/nsssrv_private.h ++++ b/src/responder/nss/nsssrv_private.h +@@ -146,7 +146,7 @@ errno_t check_cache(struct nss_dom_ctx *dctx, + void nss_update_pw_memcache(struct nss_ctx *nctx); + void nss_update_gr_memcache(struct nss_ctx *nctx); + void nss_update_initgr_memcache(struct nss_ctx *nctx, +- const char *name, const char *domain, ++ const char *fq_name, const char *domain, + int gnum, uint32_t *groups); + + int nss_connection_setup(struct cli_ctx *cctx); +-- +2.4.11 + diff --git a/SOURCES/0082-SYSDB-Avoid-optimisation-with-modifyTimestamp-for-us.patch b/SOURCES/0082-SYSDB-Avoid-optimisation-with-modifyTimestamp-for-us.patch new file mode 100644 index 0000000..9e36f14 --- /dev/null +++ b/SOURCES/0082-SYSDB-Avoid-optimisation-with-modifyTimestamp-for-us.patch @@ -0,0 +1,89 @@ +From d3925525068798e92cee1da95dbee0f838b2f36f Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Wed, 3 Aug 2016 18:48:04 +0200 +Subject: [PATCH 82/82] SYSDB: Avoid optimisation with modifyTimestamp for + users + +The usage of modifyTimestamp needn't be a reliable way +for detecting of changes in user entry in LDAP. +The authorisation need to rely current data from LDAP +and therefore we will temporary disable optimisation with +modifyTimestamp and we will rather rely on deep comparison +of attributes. In he future, it might be changed and +responders might control the optimization level. + +Resolves: +https://fedorahosted.org/sssd/ticket/3110 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 00f3c5cd03625357e226552084e499965512bf53) +--- + src/db/sysdb_ops.c | 19 ------------------- + src/tests/cmocka/test_sysdb_ts_cache.c | 14 -------------- + 2 files changed, 33 deletions(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 67006c155098b9fde00a01d424014852c383a325..44fb5b70e6d33fffbca5824f831a3229254ecb57 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -1101,16 +1101,6 @@ done: + return ret; + } + +-static errno_t sysdb_check_and_update_ts_usr(struct sss_domain_info *domain, +- const char *grp_name, +- struct sysdb_attrs *attrs, +- uint64_t cache_timeout, +- time_t now) +-{ +- return sysdb_check_and_update_ts_obj(domain, SYSDB_USER, grp_name, +- attrs, cache_timeout, now); +-} +- + static errno_t sysdb_check_and_update_ts_grp(struct sss_domain_info *domain, + const char *grp_name, + struct sysdb_attrs *attrs, +@@ -2470,15 +2460,6 @@ int sysdb_store_user(struct sss_domain_info *domain, + now = time(NULL); + } + +- ret = sysdb_check_and_update_ts_usr(domain, name, attrs, +- cache_timeout, now); +- if (ret == EOK) { +- DEBUG(SSSDBG_TRACE_LIBS, +- "The user record of %s did not change, only updated " +- "the timestamp cache\n", name); +- return EOK; +- } +- + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; +diff --git a/src/tests/cmocka/test_sysdb_ts_cache.c b/src/tests/cmocka/test_sysdb_ts_cache.c +index aa857e7e4823d2d8ba1e1a794b3e2474876e9ab0..e950f88631e4c78573bbb7290edfe94b5ced57cd 100644 +--- a/src/tests/cmocka/test_sysdb_ts_cache.c ++++ b/src/tests/cmocka/test_sysdb_ts_cache.c +@@ -980,20 +980,6 @@ static void test_sysdb_user_update(void **state) + assert_int_equal(cache_expire_sysdb, TEST_CACHE_TIMEOUT + TEST_NOW_2); + assert_int_equal(cache_expire_ts, TEST_CACHE_TIMEOUT + TEST_NOW_2); + +- /* Update the same attrs and the same modifyTimestamp. +- * Only the timestamp cache must be bumped */ +- ret = sysdb_store_user(test_ctx->tctx->dom, TEST_USER_NAME, NULL, +- TEST_USER_UID, TEST_USER_GID, TEST_USER_NAME, +- "/home/"TEST_USER_NAME, "/bin/bash", NULL, +- user_attrs, NULL, TEST_CACHE_TIMEOUT, +- TEST_NOW_3); +- assert_int_equal(ret, EOK); +- +- get_pw_timestamp_attrs(test_ctx, TEST_USER_NAME, +- &cache_expire_sysdb, &cache_expire_ts); +- assert_int_equal(cache_expire_sysdb, TEST_CACHE_TIMEOUT + TEST_NOW_2); +- assert_int_equal(cache_expire_ts, TEST_CACHE_TIMEOUT + TEST_NOW_3); +- + /* Update with different modifyTimestamp but same attrs as previously + * saved to the timestamp cache. We should detect the 'real' attributes + * are the same and only bump the timestamp cache +-- +2.4.11 + diff --git a/SOURCES/0082-sss_override-remove-d-from-manpage.patch b/SOURCES/0082-sss_override-remove-d-from-manpage.patch deleted file mode 100644 index 0d6456c..0000000 --- a/SOURCES/0082-sss_override-remove-d-from-manpage.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 76eb4e29154a9cea4b9189db0b6a0c4ee19e5231 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Fri, 18 Sep 2015 15:55:13 +0200 -Subject: [PATCH 82/87] sss_override: remove -d from manpage - -Short version of --debug is not acepted. - -Reviewed-by: Pavel Reichl -(cherry picked from commit 8ca1a503cf82fe2c9ed6af9d5903a158496be122) ---- - src/man/sss_override.8.xml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/man/sss_override.8.xml b/src/man/sss_override.8.xml -index c2ec5dd41703c7272acf7c9d2c30f20351099791..6381d7731761d3aa9e976475bae40941eb2264eb 100644 ---- a/src/man/sss_override.8.xml -+++ b/src/man/sss_override.8.xml -@@ -198,7 +198,7 @@ - - - -- , -+ - LEVEL - - --- -2.4.3 - diff --git a/SOURCES/0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch b/SOURCES/0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch deleted file mode 100644 index ecc6841..0000000 --- a/SOURCES/0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 075a5e689eb6983f412724b0324cec59726ae6e9 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Tue, 21 Jul 2015 21:00:27 +0200 -Subject: [PATCH 83/86] LDAP: imposing sizelimit=1 for single-entry searches - breaks overlapping domains -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2723 - -In case there are overlapping sdap domains, a search for a single user -might match and return multiple entries. For instance, with AD domains -represented by search bases: - DC=win,DC=trust,DC=test - DC=child,DC=win,DC=trust,DC=test - -A search for user from win.trust.test would be based at: - DC=win,DC=trust,DC=test -but would match both search bases and return both users. - -Instead of performing complex filtering, just save both users. The -responder would select the entry that matches the user's search. - -Reviewed-by: Lukáš Slebodník -(cherry picked from commit 67625b1b4f856510bf4e169649b3fb30c2c14152) ---- - src/providers/ldap/sdap_async_groups.c | 10 ---------- - src/providers/ldap/sdap_async_users.c | 3 --- - 2 files changed, 13 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 525c6fa09553d8c0232ce2317751184f83632d86..57a53af3f4eb46e6f31af9ee7c4d4625239d2a54 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -1874,8 +1874,6 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - - switch (state->lookup_type) { - case SDAP_LOOKUP_SINGLE: -- sizelimit = 1; -- need_paging = false; - break; - /* Only requests that can return multiple entries should require - * the paging control -@@ -1885,7 +1883,6 @@ static errno_t sdap_get_groups_next_base(struct tevent_req *req) - need_paging = true; - break; - case SDAP_LOOKUP_ENUMERATE: -- sizelimit = 0; /* unlimited */ - need_paging = true; - break; - } -@@ -1934,13 +1931,6 @@ static void sdap_get_groups_process(struct tevent_req *subreq) - DEBUG(SSSDBG_TRACE_FUNC, - "Search for groups, returned %zu results.\n", count); - -- if (state->lookup_type == SDAP_LOOKUP_SINGLE && count > 1) { -- DEBUG(SSSDBG_MINOR_FAILURE, -- "Individual group search returned multiple results\n"); -- tevent_req_error(req, EINVAL); -- return; -- } -- - if (state->lookup_type == SDAP_LOOKUP_WILDCARD || \ - state->lookup_type == SDAP_LOOKUP_ENUMERATE || \ - count == 0) { -diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c -index a864a8b2187de7972aa963b355856e97f7c692a9..e38f4cd1610e62aa2cf9f4add3a5f7ad5290e748 100644 ---- a/src/providers/ldap/sdap_async_users.c -+++ b/src/providers/ldap/sdap_async_users.c -@@ -692,8 +692,6 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - - switch (state->lookup_type) { - case SDAP_LOOKUP_SINGLE: -- sizelimit = 1; -- need_paging = false; - break; - /* Only requests that can return multiple entries should require - * the paging control -@@ -703,7 +701,6 @@ static errno_t sdap_search_user_next_base(struct tevent_req *req) - need_paging = true; - break; - case SDAP_LOOKUP_ENUMERATE: -- sizelimit = 0; /* unlimited */ - need_paging = true; - break; - } --- -2.4.3 - diff --git a/SOURCES/0083-SIMPLE-Do-not-parse-names-on-startup.patch b/SOURCES/0083-SIMPLE-Do-not-parse-names-on-startup.patch new file mode 100644 index 0000000..8185485 --- /dev/null +++ b/SOURCES/0083-SIMPLE-Do-not-parse-names-on-startup.patch @@ -0,0 +1,48 @@ +From 701cabea51526c3bd40607761dc02069c9c2e499 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Thu, 21 Jul 2016 12:18:01 +0200 +Subject: [PATCH 83/86] SIMPLE: Do not parse names on startup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's not required to parse names on SSSD startup in the simple access +provider. We can instead just parse the name when the access request is +processed. + +Resolves: +https://fedorahosted.org/sssd/ticket/3101 + +Reviewed-by: Lukáš Slebodník +--- + src/providers/simple/simple_access.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c +index cb72ada20727c63452936647876ef297106e17b0..ae90215351fe7db834898067d3b4bad71015ec5f 100644 +--- a/src/providers/simple/simple_access.c ++++ b/src/providers/simple/simple_access.c +@@ -284,7 +284,6 @@ errno_t sssm_simple_access_init(TALLOC_CTX *mem_ctx, + struct dp_method *dp_methods) + { + struct simple_ctx *ctx; +- errno_t ret; + + ctx = talloc_zero(mem_ctx, struct simple_ctx); + if (ctx == NULL) { +@@ -296,12 +295,6 @@ errno_t sssm_simple_access_init(TALLOC_CTX *mem_ctx, + ctx->be_ctx = be_ctx; + ctx->last_refresh_of_filter_lists = 0; + +- ret = simple_access_obtain_filter_lists(ctx); +- if (ret != EOK) { +- talloc_free(ctx); +- return ret; +- } +- + dp_set_method(dp_methods, DPM_ACCESS_HANDLER, + simple_access_handler_send, simple_access_handler_recv, ctx, + struct simple_ctx, struct pam_data, struct pam_data *); +-- +2.4.11 + diff --git a/SOURCES/0084-DYNDNS-Add-a-new-option-dyndns_server.patch b/SOURCES/0084-DYNDNS-Add-a-new-option-dyndns_server.patch deleted file mode 100644 index 8fa1811..0000000 --- a/SOURCES/0084-DYNDNS-Add-a-new-option-dyndns_server.patch +++ /dev/null @@ -1,208 +0,0 @@ -From b280fc0d8287e9bee25516eddc1a6670691c24a1 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Sun, 6 Jul 2014 22:53:27 +0200 -Subject: [PATCH 84/90] DYNDNS: Add a new option dyndns_server - -Some environments use a different DNS server than identity server. For -these environments, it would be useful to be able to override the DNS -server used to perform DNS updates. - -This patch adds a new option dyndns_server that, if set, would be used -to hardcode a DNS server address into the nsupdate message. - -Reviewed-by: Pavel Reichl -(cherry picked from commit 8145ab51b05aa86b2f1a21b49383f55e50b0a2e3) ---- - src/config/SSSDConfig/__init__.py.in | 1 + - src/config/SSSDConfigTest.py | 2 ++ - src/config/etc/sssd.api.conf | 1 + - src/man/sssd-ad.5.xml | 20 ++++++++++++++++++++ - src/man/sssd-ipa.5.xml | 19 +++++++++++++++++++ - src/providers/ad/ad_opts.h | 1 + - src/providers/dp_dyndns.c | 1 + - src/providers/dp_dyndns.h | 1 + - src/providers/ipa/ipa_opts.h | 1 + - src/providers/ldap/sdap_dyndns.c | 7 +++++++ - 10 files changed, 54 insertions(+) - -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index fed2682f121103cefa27e689b29ce29b7d28f968..a7cd1dd243a53e7038dc69628475c76ccdd93260 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -148,6 +148,7 @@ option_strings = { - 'dyndns_update_ptr' : _("Whether the provider should explicitly update the PTR record as well"), - 'dyndns_force_tcp' : _("Whether the nsupdate utility should default to using TCP"), - 'dyndns_auth' : _("What kind of authentication should be used to perform the DNS update"), -+ 'dyndns_server' : _("Override the DNS server used to perform the DNS update"), - 'subdomain_enumerate' : _('Control enumeration of trusted domains'), - 'subdomain_refresh_interval' : _('How often should subdomains list be refreshed'), - 'subdomain_inherit' : _('List of options that should be inherited into a subdomain'), -diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py -index 1d6107ceac1bde7acbfd2682cc144a4ef0881311..166ecd0ff0f5cfb38eefb1711e4ac5dd9f805d43 100755 ---- a/src/config/SSSDConfigTest.py -+++ b/src/config/SSSDConfigTest.py -@@ -527,6 +527,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): - 'dyndns_update_ptr', - 'dyndns_force_tcp', - 'dyndns_auth', -+ 'dyndns_server', - 'subdomain_enumerate', - 'override_gid', - 'case_sensitive', -@@ -891,6 +892,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): - 'dyndns_update_ptr', - 'dyndns_force_tcp', - 'dyndns_auth', -+ 'dyndns_server', - 'subdomain_enumerate', - 'override_gid', - 'case_sensitive', -diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf -index 2e5b02e3e30c13f805e172eab481f7501f57bb05..f28054860205831b0452e409c109e3c62aa8d28a 100644 ---- a/src/config/etc/sssd.api.conf -+++ b/src/config/etc/sssd.api.conf -@@ -155,6 +155,7 @@ dyndns_refresh_interval = int, None, false - dyndns_update_ptr = bool, None, false - dyndns_force_tcp = bool, None, false - dyndns_auth = str, None, false -+dyndns_server = str, None, false - - # Special providers - [provider/permit] -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index 3cbc10520098372d984d00425d03832d002d6672..7ccd29794a89fa6b69b744a47da04f908efc7ef9 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -812,6 +812,26 @@ ad_gpo_map_deny = +my_pam_service - - - -+ -+ dyndns_server (string) -+ -+ -+ The DNS server to use when performing a DNS -+ update. In most setups, it's recommended to leave -+ this option unset. -+ -+ -+ Setting this option makes sense for environments -+ where the DNS server is different from the identity -+ server. -+ -+ -+ Default: None (let nsupdate choose the server) -+ -+ -+ -+ -+ - - - -diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml -index 2e985991fde10827aff0e7c8e67f29a009683450..871c41607b97bd24fe5feaa282258def0fd0cc8b 100644 ---- a/src/man/sssd-ipa.5.xml -+++ b/src/man/sssd-ipa.5.xml -@@ -263,6 +263,25 @@ - - - -+ dyndns_server (string) -+ -+ -+ The DNS server to use when performing a DNS -+ update. In most setups, it's recommended to leave -+ this option unset. -+ -+ -+ Setting this option makes sense for environments -+ where the DNS server is different from the identity -+ server. -+ -+ -+ Default: None (let nsupdate choose the server) -+ -+ -+ -+ -+ - ipa_hbac_search_base (string) - - -diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h -index d685edcb44c771b0afc7a232a82c21fc9d1c89f9..00586a7ada63ad4c89630e9589d3ff75d1726703 100644 ---- a/src/providers/ad/ad_opts.h -+++ b/src/providers/ad/ad_opts.h -@@ -275,6 +275,7 @@ struct dp_option ad_dyndns_opts[] = { - { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, - { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING }, -+ { "dyndns_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - DP_OPTION_TERMINATOR - }; - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index c254d78936f412626db0533f559350de57017618..9a726bd431854342993212ce0a9759b86069cd5e 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -1180,6 +1180,7 @@ static struct dp_option default_dyndns_opts[] = { - { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE }, - { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING }, -+ { "dyndns_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - - DP_OPTION_TERMINATOR - }; -diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h -index a8a20ec6f8a1a63cd8c85aaec3f54f9fddb42049..3cc8d122646590365a3fb6dafa6a0f699b620ad9 100644 ---- a/src/providers/dp_dyndns.h -+++ b/src/providers/dp_dyndns.h -@@ -55,6 +55,7 @@ enum dp_dyndns_opts { - DP_OPT_DYNDNS_UPDATE_PTR, - DP_OPT_DYNDNS_FORCE_TCP, - DP_OPT_DYNDNS_AUTH, -+ DP_OPT_DYNDNS_SERVER, - - DP_OPT_DYNDNS /* attrs counter */ - }; -diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h -index f6c40dddbb58cd8af1079a351137422083e26cfe..78949e3ddec95f7f4303eab905bbbf6ec14ed6ae 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -62,6 +62,7 @@ struct dp_option ipa_dyndns_opts[] = { - { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING }, -+ { "dyndns_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - DP_OPTION_TERMINATOR - }; - -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index a463a2fce08f42b325010cd37c501ef23aee173f..01f4f17226f1b7dd417699403b425c571b780c3a 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -92,6 +92,7 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - struct tevent_req *req; - struct tevent_req *subreq; - struct sdap_dyndns_update_state *state; -+ const char *conf_servername; - - req = tevent_req_create(mem_ctx, &state, struct sdap_dyndns_update_state); - if (req == NULL) { -@@ -111,6 +112,12 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - state->auth_type = auth_type; - state->pass_num = 0; - -+ conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER); -+ if (conf_servername != NULL) { -+ state->servername = conf_servername; -+ state->use_server_with_nsupdate = true; -+ } -+ - if (ifname) { - /* Unless one family is restricted, just replace all - * address families during the update --- -2.4.3 - diff --git a/SOURCES/0084-SIMPLE-Fail-on-any-error-parsing-the-access-control-.patch b/SOURCES/0084-SIMPLE-Fail-on-any-error-parsing-the-access-control-.patch new file mode 100644 index 0000000..375b95e --- /dev/null +++ b/SOURCES/0084-SIMPLE-Fail-on-any-error-parsing-the-access-control-.patch @@ -0,0 +1,40 @@ +From b40c53b524816f9308c90d79662f887e6a2ac1eb Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Thu, 21 Jul 2016 13:33:18 +0200 +Subject: [PATCH 84/86] SIMPLE: Fail on any error parsing the access control + list +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Luckily this error was hidden by the fact that SSSD didn't start at all +when an unparseable name was encountered after startup. Otherwise, this +would have been a security issue. + +Nonetheless, we should just fail and deny access if we can't parse a +name in a simple access list. + +Reviewed-by: Lukáš Slebodník +--- + src/providers/simple/simple_access.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c +index ae90215351fe7db834898067d3b4bad71015ec5f..577e8354e9b574764734248b2bde4ef06c6fb4fc 100644 +--- a/src/providers/simple/simple_access.c ++++ b/src/providers/simple/simple_access.c +@@ -211,7 +211,10 @@ simple_access_handler_send(TALLOC_CTX *mem_ctx, + + ret = simple_access_obtain_filter_lists(simple_ctx); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Failed to refresh filter lists\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Failed to refresh filter lists, denying all access\n"); ++ pd->pam_status = PAM_PERM_DENIED; ++ goto immediately; + } + simple_ctx->last_refresh_of_filter_lists = now; + } +-- +2.4.11 + diff --git a/SOURCES/0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch b/SOURCES/0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch deleted file mode 100644 index 5e9f538..0000000 --- a/SOURCES/0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 6d1ba78ff110ee424e54025c3d823fb5c504aefa Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 23 Jul 2015 04:40:03 -0400 -Subject: [PATCH 85/90] DYNDNS: Don't use server cmd in nsupdate by default - -nsupdate command `server` should not be used for the first attempt -to udpate DNS. It should be used only in subsequent attempts after the -first attempt failed. - -Resolves: -https://fedorahosted.org/sssd/ticket/2495 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 7c3cc1ee2914bc7b38a992c1af254fc76af5a1ad) ---- - src/man/sssd-ad.5.xml | 6 +++++- - src/man/sssd-ipa.5.xml | 5 +++++ - src/providers/ldap/sdap_dyndns.c | 2 +- - 3 files changed, 11 insertions(+), 2 deletions(-) - -diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml -index 7ccd29794a89fa6b69b744a47da04f908efc7ef9..127e96582d71e8216db88d37a16d37d01748131d 100644 ---- a/src/man/sssd-ad.5.xml -+++ b/src/man/sssd-ad.5.xml -@@ -826,12 +826,16 @@ ad_gpo_map_deny = +my_pam_service - server. - - -+ Please note that this option will be only used in -+ fallback attempt when previous attempt using -+ autodetected settings failed. -+ -+ - Default: None (let nsupdate choose the server) - - - - -- - - - -diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml -index 871c41607b97bd24fe5feaa282258def0fd0cc8b..be390d58dd3ce5a6ca6d5212d2c7aa176d3a74c4 100644 ---- a/src/man/sssd-ipa.5.xml -+++ b/src/man/sssd-ipa.5.xml -@@ -276,6 +276,11 @@ - server. - - -+ Please note that this option will be only used in -+ fallback attempt when previous attempt using -+ autodetected settings failed. -+ -+ - Default: None (let nsupdate choose the server) - - -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index 01f4f17226f1b7dd417699403b425c571b780c3a..0f0e63ee2259d017c3e94afca5f3148f4fc2ce04 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -112,10 +112,10 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - state->auth_type = auth_type; - state->pass_num = 0; - -+ /* fallback servername is overriden by user option */ - conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER); - if (conf_servername != NULL) { - state->servername = conf_servername; -- state->use_server_with_nsupdate = true; - } - - if (ifname) { --- -2.4.3 - diff --git a/SOURCES/0085-SIMPLE-Make-the-DP-handlers-testable.patch b/SOURCES/0085-SIMPLE-Make-the-DP-handlers-testable.patch new file mode 100644 index 0000000..62c43fa --- /dev/null +++ b/SOURCES/0085-SIMPLE-Make-the-DP-handlers-testable.patch @@ -0,0 +1,113 @@ +From ab6ee9104826e286e0c67c9176c08b9a239e0622 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 26 Jul 2016 12:13:43 +0200 +Subject: [PATCH 85/86] SIMPLE: Make the DP handlers testable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To make it possible to call the whole DP handler in the unit test, not +just the evaluator part. + +Reviewed-by: Lukáš Slebodník +--- + Makefile.am | 1 + + src/providers/simple/simple_access.c | 5 ++-- + src/providers/simple/simple_access_pvt.h | 43 ++++++++++++++++++++++++++++++++ + 3 files changed, 47 insertions(+), 2 deletions(-) + create mode 100644 src/providers/simple/simple_access_pvt.h + +diff --git a/Makefile.am b/Makefile.am +index cefd9a43442fc19933f1e373d4f2ed4bb3ba3201..ee9b48c666a44781b582ba5d83102b705e898f29 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -665,6 +665,7 @@ dist_noinst_HEADERS = \ + src/providers/fail_over_srv.h \ + src/util/child_common.h \ + src/providers/simple/simple_access.h \ ++ src/providers/simple/simple_access_pvt.h \ + src/providers/krb5/krb5_auth.h \ + src/providers/krb5/krb5_common.h \ + src/providers/krb5/krb5_utils.h \ +diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c +index 577e8354e9b574764734248b2bde4ef06c6fb4fc..521beee84833b47b547bd1045c24e3384aa4d9a5 100644 +--- a/src/providers/simple/simple_access.c ++++ b/src/providers/simple/simple_access.c +@@ -22,6 +22,7 @@ + #include + + #include "providers/simple/simple_access.h" ++#include "providers/simple/simple_access_pvt.h" + #include "util/sss_utf8.h" + #include "providers/backend.h" + #include "db/sysdb.h" +@@ -176,7 +177,7 @@ struct simple_access_handler_state { + + static void simple_access_handler_done(struct tevent_req *subreq); + +-static struct tevent_req * ++struct tevent_req * + simple_access_handler_send(TALLOC_CTX *mem_ctx, + struct simple_ctx *simple_ctx, + struct pam_data *pd, +@@ -265,7 +266,7 @@ done: + tevent_req_done(req); + } + +-static errno_t ++errno_t + simple_access_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data) +diff --git a/src/providers/simple/simple_access_pvt.h b/src/providers/simple/simple_access_pvt.h +new file mode 100644 +index 0000000000000000000000000000000000000000..c133e1c5531be35861178e0b23aa7a09db9f7703 +--- /dev/null ++++ b/src/providers/simple/simple_access_pvt.h +@@ -0,0 +1,43 @@ ++/* ++ SSSD ++ ++ Simple access control ++ ++ Copyright (C) Sumit Bose 2010 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#ifndef __SIMPLE_ACCESS_PVT_H__ ++#define __SIMPLE_ACCESS_PVT_H__ ++ ++#include "providers/data_provider/dp.h" ++ ++/* We only 'export' the functions in a private header file to be able to call ++ * them from unit tests ++ */ ++struct tevent_req * ++simple_access_handler_send(TALLOC_CTX *mem_ctx, ++ struct simple_ctx *simple_ctx, ++ struct pam_data *pd, ++ struct dp_req_params *params); ++ ++errno_t ++simple_access_handler_recv(TALLOC_CTX *mem_ctx, ++ struct tevent_req *req, ++ struct pam_data **_data); ++ ++int simple_access_obtain_filter_lists(struct simple_ctx *ctx); ++ ++#endif /* __SIMPLE_ACCESS_PVT_H__ */ +-- +2.4.11 + diff --git a/SOURCES/0086-DYNDNS-remove-redundant-talloc_steal.patch b/SOURCES/0086-DYNDNS-remove-redundant-talloc_steal.patch deleted file mode 100644 index 8bbb5ed..0000000 --- a/SOURCES/0086-DYNDNS-remove-redundant-talloc_steal.patch +++ /dev/null @@ -1,31 +0,0 @@ -From efbf0e362238eaf0330384caf057521968f25758 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 23 Jul 2015 04:50:38 -0400 -Subject: [PATCH 86/90] DYNDNS: remove redundant talloc_steal() - -String 'update_msg' was already allocated on mem_ctx, so, there is no -need to steal it. - -Reviewed-by: Jakub Hrozek -(cherry picked from commit e4d6e9ccac14044d6bcd5a0dce7f45fdfab6bf3d) ---- - src/providers/dp_dyndns.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 9a726bd431854342993212ce0a9759b86069cd5e..3171e6909e5f92a98cd506278e6e8c3418b979fe 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -525,7 +525,8 @@ be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm, - update_msg); - - ret = ERR_OK; -- *_update_msg = talloc_steal(mem_ctx, update_msg); -+ *_update_msg = update_msg; -+ - done: - return ret; - } --- -2.4.3 - diff --git a/SOURCES/0086-TESTS-Use-the-DP-handlers-in-simple-provider-tests-a.patch b/SOURCES/0086-TESTS-Use-the-DP-handlers-in-simple-provider-tests-a.patch new file mode 100644 index 0000000..4eed171 --- /dev/null +++ b/SOURCES/0086-TESTS-Use-the-DP-handlers-in-simple-provider-tests-a.patch @@ -0,0 +1,308 @@ +From 157781d8a05975c034858a38d2c00cdd94d374b0 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 26 Jul 2016 12:14:47 +0200 +Subject: [PATCH 86/86] TESTS: Use the DP handlers in simple provider tests, + add more tests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use the full simple access control handlers, just like SSSD does in the +tests. + +Reviewed-by: Lukáš Slebodník +--- + src/tests/cmocka/test_simple_access.c | 186 ++++++++++++++++++++++++++++++---- + 1 file changed, 165 insertions(+), 21 deletions(-) + +diff --git a/src/tests/cmocka/test_simple_access.c b/src/tests/cmocka/test_simple_access.c +index 1f093cf7fee4d046dcc727aa8815fb9aafb68c52..d41bb295e24ef2104cf17636f37d487fd14d0b93 100644 +--- a/src/tests/cmocka/test_simple_access.c ++++ b/src/tests/cmocka/test_simple_access.c +@@ -21,12 +21,14 @@ + #include + #include + #include ++#include + + #include "tests/cmocka/common_mock.h" + #include "tests/cmocka/common_mock_be.h" + #include "tests/cmocka/common_mock_resp.h" + #include "db/sysdb_private.h" /* new_subdomain() */ + #include "providers/simple/simple_access.h" ++#include "providers/simple/simple_access_pvt.h" + + #define TESTS_PATH "tp_" BASE_FILE_STEM + #define TEST_CONF_DB "test_simple_conf.ldb" +@@ -34,8 +36,6 @@ + #define TEST_SUBDOM_NAME "test.subdomain" + #define TEST_ID_PROVIDER "ldap" + +-int simple_access_obtain_filter_lists(struct simple_ctx *ctx); +- + struct simple_test_ctx { + struct sss_test_ctx *tctx; + struct be_ctx *be_ctx; +@@ -43,6 +43,8 @@ struct simple_test_ctx { + + bool access_granted; + struct simple_ctx *ctx; ++ struct pam_data *pd; ++ struct dp_req_params *params; + }; + + static int test_simple_setup(struct sss_test_conf_param params[], void **state) +@@ -75,6 +77,19 @@ static int test_simple_setup(struct sss_test_conf_param params[], void **state) + return ENOMEM; + } + ++ simple_test_ctx->pd = talloc_zero(simple_test_ctx, struct pam_data); ++ if (simple_test_ctx->pd == NULL) { ++ return ENOMEM; ++ } ++ simple_test_ctx->pd->cmd = SSS_PAM_ACCT_MGMT; ++ ++ simple_test_ctx->params = talloc_zero(simple_test_ctx, ++ struct dp_req_params); ++ if (simple_test_ctx->params == NULL) { ++ return ENOMEM; ++ } ++ simple_test_ctx->params->ev = simple_test_ctx->tctx->ev; ++ + *state = simple_test_ctx; + return 0; + } +@@ -122,7 +137,7 @@ static int setup_with_params(struct simple_test_ctx *test_ctx, + return ret; + } + +- test_ctx->ctx = talloc(test_ctx, struct simple_ctx); ++ test_ctx->ctx = talloc_zero(test_ctx, struct simple_ctx); + if (test_ctx->ctx == NULL) { + return ENOMEM; + } +@@ -130,11 +145,6 @@ static int setup_with_params(struct simple_test_ctx *test_ctx, + test_ctx->ctx->be_ctx = test_ctx->be_ctx; + test_ctx->ctx->domain = test_ctx->tctx->dom; + +- ret = simple_access_obtain_filter_lists(test_ctx->ctx); +- if (ret != EOK) { +- return ret; +- } +- + return EOK; + } + +@@ -155,13 +165,14 @@ static int simple_test_teardown(void **state) + return 0; + } + +-static void simple_access_check_done(struct tevent_req *req) ++static void simple_access_handler_done(struct tevent_req *req) + { + struct simple_test_ctx *simple_test_ctx = + tevent_req_callback_data(req, struct simple_test_ctx); + +- simple_test_ctx->tctx->error = simple_access_check_recv(req, +- &simple_test_ctx->access_granted); ++ simple_test_ctx->tctx->error = simple_access_handler_recv(simple_test_ctx, ++ req, &simple_test_ctx->pd); ++ simple_test_ctx->access_granted = (simple_test_ctx->pd->pam_status == PAM_SUCCESS); + talloc_free(req); + simple_test_ctx->tctx->done = true; + } +@@ -175,10 +186,13 @@ static void run_simple_access_check(struct simple_test_ctx *simple_test_ctx, + struct tevent_req *req; + + simple_test_ctx->tctx->done = false; +- req = simple_access_check_send(simple_test_ctx, simple_test_ctx->tctx->ev, +- simple_test_ctx->ctx, username); ++ simple_test_ctx->pd->user = discard_const(username); ++ req = simple_access_handler_send(simple_test_ctx, ++ simple_test_ctx->ctx, ++ simple_test_ctx->pd, ++ simple_test_ctx->params); + assert_non_null(req); +- tevent_req_set_callback(req, simple_access_check_done, simple_test_ctx); ++ tevent_req_set_callback(req, simple_access_handler_done, simple_test_ctx); + + ret = test_ev_loop(simple_test_ctx->tctx); + assert_int_equal(ret, expected_rv); +@@ -487,23 +501,29 @@ static void test_group_allow_empty(void **state) + { NULL, NULL }, + }; + +- ret = setup_with_params(simple_test_ctx, simple_test_ctx->tctx->dom, params); ++ ret = setup_with_params(simple_test_ctx, ++ simple_test_ctx->tctx->dom, ++ params); + assert_int_equal(ret, EOK); + +- req = simple_access_check_send(simple_test_ctx, simple_test_ctx->tctx->ev, +- simple_test_ctx->ctx, "u1@simple_test"); ++ simple_test_ctx->pd->user = discard_const("u1@simple_test"); ++ req = simple_access_handler_send(simple_test_ctx, simple_test_ctx->ctx, ++ simple_test_ctx->pd, ++ simple_test_ctx->params); + assert_non_null(req); +- tevent_req_set_callback(req, simple_access_check_done, simple_test_ctx); ++ tevent_req_set_callback(req, simple_access_handler_done, simple_test_ctx); + + ret = test_ev_loop(simple_test_ctx->tctx); + assert_int_equal(ret, EOK); + assert_false(simple_test_ctx->access_granted); + + simple_test_ctx->tctx->done = false; +- req = simple_access_check_send(simple_test_ctx, simple_test_ctx->tctx->ev, +- simple_test_ctx->ctx, "u3@simple_test"); ++ simple_test_ctx->pd->user = discard_const("u3@simple_test"); ++ req = simple_access_handler_send(simple_test_ctx, simple_test_ctx->ctx, ++ simple_test_ctx->pd, ++ simple_test_ctx->params); + assert_non_null(req); +- tevent_req_set_callback(req, simple_access_check_done, simple_test_ctx); ++ tevent_req_set_callback(req, simple_access_handler_done, simple_test_ctx); + + ret = test_ev_loop(simple_test_ctx->tctx); + assert_int_equal(ret, EOK); +@@ -584,6 +604,118 @@ static void test_group_allow_case_insensitive(void **state) + run_simple_access_check(simple_test_ctx, "u1@simple_test", EOK, true); + } + ++static void test_unparseable_allow_user(void **state) ++{ ++ errno_t ret; ++ struct simple_test_ctx *simple_test_ctx = \ ++ talloc_get_type(*state, struct simple_test_ctx); ++ struct sss_test_conf_param params[] = { ++ { "simple_allow_users", "u1, user@no.such.domain" }, ++ { NULL, NULL }, ++ }; ++ ++ ret = setup_with_params(simple_test_ctx, ++ simple_test_ctx->tctx->dom, ++ params); ++ assert_int_equal(ret, EOK); ++ ++ /* Case-sensitive domain, wrong case */ ++ simple_test_ctx->tctx->done = false; ++ simple_test_ctx->tctx->dom->case_sensitive = false; ++ /* A user that would normally be denied access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u2@simple_test", EOK, false); ++ /* A user that would normally be allowed access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u1@simple_test", EOK, false); ++} ++ ++static void test_unparseable_deny_user(void **state) ++{ ++ errno_t ret; ++ struct simple_test_ctx *simple_test_ctx = \ ++ talloc_get_type(*state, struct simple_test_ctx); ++ struct sss_test_conf_param params[] = { ++ { "simple_deny_users", "u2, user@no.such.domain" }, ++ { NULL, NULL }, ++ }; ++ ++ ret = setup_with_params(simple_test_ctx, ++ simple_test_ctx->tctx->dom, ++ params); ++ assert_int_equal(ret, EOK); ++ ++ /* Case-sensitive domain, wrong case */ ++ simple_test_ctx->tctx->done = false; ++ simple_test_ctx->tctx->dom->case_sensitive = false; ++ /* A user that would normally be denied access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u2@simple_test", EOK, false); ++ /* A user that would normally be allowed access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u1@simple_test", EOK, false); ++} ++ ++static void test_unparseable_allow_group(void **state) ++{ ++ errno_t ret; ++ struct simple_test_ctx *simple_test_ctx = \ ++ talloc_get_type(*state, struct simple_test_ctx); ++ struct sss_test_conf_param params[] = { ++ { "simple_allow_groups", "g1, group@no.such.domain" }, ++ { NULL, NULL }, ++ }; ++ ++ ret = setup_with_params(simple_test_ctx, ++ simple_test_ctx->tctx->dom, ++ params); ++ assert_int_equal(ret, EOK); ++ ++ /* Case-sensitive domain, wrong case */ ++ simple_test_ctx->tctx->done = false; ++ simple_test_ctx->tctx->dom->case_sensitive = false; ++ /* A group that would normally be denied access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u2@simple_test", EOK, false); ++ /* A group that would normally be allowed access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u1@simple_test", EOK, false); ++} ++ ++static void test_unparseable_deny_group(void **state) ++{ ++ errno_t ret; ++ struct simple_test_ctx *simple_test_ctx = \ ++ talloc_get_type(*state, struct simple_test_ctx); ++ struct sss_test_conf_param params[] = { ++ { "simple_deny_groups", "g2, group@no.such.domain" }, ++ { NULL, NULL }, ++ }; ++ ++ ret = setup_with_params(simple_test_ctx, ++ simple_test_ctx->tctx->dom, ++ params); ++ assert_int_equal(ret, EOK); ++ ++ /* Case-sensitive domain, wrong case */ ++ simple_test_ctx->tctx->done = false; ++ simple_test_ctx->tctx->dom->case_sensitive = false; ++ /* A group that would normally be denied access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u2@simple_test", EOK, false); ++ /* A group that would normally be allowed access will be denied because ++ * the access list can't be parsed ++ */ ++ run_simple_access_check(simple_test_ctx, "u1@simple_test", EOK, false); ++} ++ + static void test_group_space(void **state) + { + errno_t ret; +@@ -659,6 +791,18 @@ int main(int argc, const char *argv[]) + cmocka_unit_test_setup_teardown(test_group_space, + simple_group_test_setup, + simple_group_test_teardown), ++ cmocka_unit_test_setup_teardown(test_unparseable_allow_user, ++ simple_test_setup, ++ simple_test_teardown), ++ cmocka_unit_test_setup_teardown(test_unparseable_deny_user, ++ simple_test_setup, ++ simple_test_teardown), ++ cmocka_unit_test_setup_teardown(test_unparseable_allow_group, ++ simple_test_setup, ++ simple_test_teardown), ++ cmocka_unit_test_setup_teardown(test_unparseable_deny_group, ++ simple_test_setup, ++ simple_test_teardown), + }; + + /* Set debug level to invalid value so we can decide if -d 0 was used. */ +-- +2.4.11 + diff --git a/SOURCES/0087-DYNDNS-remove-zone-command.patch b/SOURCES/0087-DYNDNS-remove-zone-command.patch deleted file mode 100644 index db57a1b..0000000 --- a/SOURCES/0087-DYNDNS-remove-zone-command.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 17f136d85a5ce0e2a6fa71d32eb2b048853b4800 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 23 Jul 2015 05:30:34 -0400 -Subject: [PATCH 87/90] DYNDNS: remove zone command - -Remove zone command from message to nsupsate. This command is generally -used to hint nsupdate. In correctly configured environment such -information should be obtained via DNS. - -If DNS does not provide necessary information we give other hints. - -For more details see: -https://fedorahosted.org/sssd/wiki/DesignDocs/DDNSMessagesUpdate - -Resolves: -https://fedorahosted.org/sssd/ticket/2495 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 4f2a07c422fa357ef6651bca8c48b8005280fa1d) ---- - src/providers/ad/ad_dyndns.c | 1 - - src/providers/dp_dyndns.c | 12 +----------- - src/providers/dp_dyndns.h | 2 +- - src/providers/ipa/ipa_dyndns.c | 16 ---------------- - src/providers/ldap/sdap_dyndns.c | 13 +------------ - src/providers/ldap/sdap_dyndns.h | 1 - - 6 files changed, 3 insertions(+), 42 deletions(-) - -diff --git a/src/providers/ad/ad_dyndns.c b/src/providers/ad/ad_dyndns.c -index aac7d8b0a170e07cba0cd150a6f19c538948d657..5f8638128b966f0981c85a44e50e3201c73d561e 100644 ---- a/src/providers/ad/ad_dyndns.c -+++ b/src/providers/ad/ad_dyndns.c -@@ -233,7 +233,6 @@ ad_dyndns_update_send(struct ad_options *ctx) - DP_OPT_DYNDNS_IFACE), - dp_opt_get_string(ctx->basic, - AD_HOSTNAME), -- NULL, - dp_opt_get_string(ctx->basic, - AD_KRB5_REALM), - state->servername, -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 3171e6909e5f92a98cd506278e6e8c3418b979fe..ae3f913ee392a6513f75aab497e7f2d784784748 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -436,7 +436,7 @@ fail: - - errno_t - be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm, -- const char *zone, const char *servername, -+ const char *servername, - const char *hostname, const unsigned int ttl, - uint8_t remove_af, struct sss_iface_addr *addresses, - char **_update_msg) -@@ -459,16 +459,6 @@ be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm, - goto done; - } - -- if (zone) { -- DEBUG(SSSDBG_FUNC_DATA, -- "Setting the zone explicitly to [%s].\n", zone); -- update_msg = talloc_asprintf_append(update_msg, "zone %s.\n", zone); -- if (update_msg == NULL) { -- ret = ENOMEM; -- goto done; -- } -- } -- - update_msg = nsupdate_msg_add_fwd(update_msg, addresses, hostname, - ttl, remove_af); - if (update_msg == NULL) { -diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h -index 3cc8d122646590365a3fb6dafa6a0f699b620ad9..9f72331b6fd68e17e9eb91505a13fc839d3f54e1 100644 ---- a/src/providers/dp_dyndns.h -+++ b/src/providers/dp_dyndns.h -@@ -89,7 +89,7 @@ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx, - - errno_t - be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm, -- const char *zone, const char *servername, -+ const char *servername, - const char *hostname, const unsigned int ttl, - uint8_t remove_af, struct sss_iface_addr *addresses, - char **_update_msg); -diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c -index 83009ff2a08cb8e4ae2b7a1e89039539b23b6d79..e7026eb275798f0ed21fb8490295b6e6d419d8ee 100644 ---- a/src/providers/ipa/ipa_dyndns.c -+++ b/src/providers/ipa/ipa_dyndns.c -@@ -153,9 +153,7 @@ ipa_dyndns_update_send(struct ipa_options *ctx) - struct ipa_dyndns_update_state *state; - struct tevent_req *req, *subreq; - struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx; -- char *dns_zone; - const char *servername; -- int i; - - DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n"); - -@@ -175,19 +173,6 @@ ipa_dyndns_update_send(struct ipa_options *ctx) - } - state->ipa_ctx->dyndns_ctx->last_refresh = time(NULL); - -- dns_zone = dp_opt_get_string(ctx->basic, IPA_DOMAIN); -- if (!dns_zone) { -- ret = EIO; -- goto done; -- } -- -- /* The DNS zone for IPA is the lower-case -- * version of the IPA domain -- */ -- for (i = 0; dns_zone[i] != '\0'; i++) { -- dns_zone[i] = tolower(dns_zone[i]); -- } -- - if (strncmp(ctx->service->sdap->uri, - "ldap://", 7) != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected format of LDAP URI.\n"); -@@ -209,7 +194,6 @@ ipa_dyndns_update_send(struct ipa_options *ctx) - DP_OPT_DYNDNS_IFACE), - dp_opt_get_string(ctx->basic, - IPA_HOSTNAME), -- dns_zone, - dp_opt_get_string(ctx->basic, - IPA_KRB5_REALM), - servername, -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index 0f0e63ee2259d017c3e94afca5f3148f4fc2ce04..f0e3dd855005d00ea19cb5dc283375f58b0d2cca 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -47,7 +47,6 @@ struct sdap_dyndns_update_state { - struct dp_option *opts; - - const char *hostname; -- const char *dns_zone; - const char *realm; - const char *servername; - int ttl; -@@ -61,7 +60,6 @@ struct sdap_dyndns_update_state { - enum be_nsupdate_auth auth_type; - bool use_server_with_nsupdate; - char *update_msg; -- size_t pass_num; - }; - - static void sdap_dyndns_update_addrs_done(struct tevent_req *subreq); -@@ -82,7 +80,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - enum be_nsupdate_auth auth_type, - const char *ifname, - const char *hostname, -- const char *dns_zone, - const char *realm, - const char *servername, - const int ttl, -@@ -101,7 +98,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - state->check_diff = check_diff; - state->update_ptr = dp_opt_get_bool(opts, DP_OPT_DYNDNS_UPDATE_PTR); - state->hostname = hostname; -- state->dns_zone = dns_zone; - state->realm = realm; - state->servername = servername; - state->use_server_with_nsupdate = false; -@@ -110,7 +106,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - state->ev = ev; - state->opts = opts; - state->auth_type = auth_type; -- state->pass_num = 0; - - /* fallback servername is overriden by user option */ - conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER); -@@ -317,7 +312,6 @@ sdap_dyndns_update_step(struct tevent_req *req) - struct sdap_dyndns_update_state *state; - const char *servername; - struct tevent_req *subreq; -- const char *dns_zone = NULL; - - state = tevent_req_data(req, struct sdap_dyndns_update_state); - -@@ -327,11 +321,7 @@ sdap_dyndns_update_step(struct tevent_req *req) - servername = state->servername; - } - -- if (state->pass_num > 0) { -- dns_zone = state->dns_zone; -- } -- -- ret = be_nsupdate_create_fwd_msg(state, state->realm, dns_zone, -+ ret = be_nsupdate_create_fwd_msg(state, state->realm, - servername, state->hostname, - state->ttl, state->remove_af, - state->addresses, -@@ -340,7 +330,6 @@ sdap_dyndns_update_step(struct tevent_req *req) - DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n"); - return ret; - } -- state->pass_num++; - - /* Fork a child process to perform the DNS update */ - subreq = be_nsupdate_send(state, state->ev, state->auth_type, -diff --git a/src/providers/ldap/sdap_dyndns.h b/src/providers/ldap/sdap_dyndns.h -index 7aaff5d2c69fbda55fff5208c97b953b970c55cc..a9481b7941be6af0f172afce5f4d54f57ef85e48 100644 ---- a/src/providers/ldap/sdap_dyndns.h -+++ b/src/providers/ldap/sdap_dyndns.h -@@ -39,7 +39,6 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - enum be_nsupdate_auth auth_type, - const char *ifname, - const char *hostname, -- const char *dns_zone, - const char *realm, - const char *servername, - const int ttl, --- -2.4.3 - diff --git a/SOURCES/0087-gpo-gPCMachineExtensionNames-with-just-whitespaces.patch b/SOURCES/0087-gpo-gPCMachineExtensionNames-with-just-whitespaces.patch new file mode 100644 index 0000000..d36a75a --- /dev/null +++ b/SOURCES/0087-gpo-gPCMachineExtensionNames-with-just-whitespaces.patch @@ -0,0 +1,91 @@ +From 662af3eaefdb11aff02947c0d34d31ba37c7b09c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Fri, 29 Jul 2016 16:09:16 +0200 +Subject: [PATCH 87/87] gpo: gPCMachineExtensionNames with just whitespaces + +Resolves: +https://fedorahosted.org/sssd/ticket/3114 + +We failed GPO procesing if the gPCMachineExtensionNames +attribute contained just whitespaces. This coused +failures in some server settings. + +Comment from Alexander Bokovoy quoting: + +You should use MS-GPOL spec. 2.2.4 'GPO Search' section says that when +processing gPCMachineExtensionNames, "Group Policy processing terminates +at the first out of sequence." +Since ' ' (space only) does not fall into defined syntax for +gPCMachineExtensionNames, this Group Policy processing is stopped and +its CSE GUIDs are set to 'empty list'. + +Because of the 3.2.5.1.10 'Extension Protocol Sequences' language +------------------------------------------------------------------------ +The Group Policy client MUST evaluate the subset of the abstract element +Filtered GPO list separately for each Group Policy extension by +including in the subset only those GPOs whose gPCUserExtensionNames (for +user policy mode) or gPCMachineExtensionNames (for computer policy mode) +attributes contain CSE GUID that correspond to the Group Policy +extension. If the CSE GUID corresponding to the Group Policy extension +is present in Extension List, it is invoked using the +Implementation Identifier field. Applicability is determined as +specified in section 3.2.1.5. The Group Policy Registry Extension MUST +always execute first. All other applicable Group Policy extensions in +the Extension List MUST be loaded and executed in Extension List order. +A failure in any Group Policy extension sequence MUST NOT affect the +execution of other Group Policy extensions. +------------------------------------------------------------------------- + +I think we can practically treat wrong content of +gPCMachineExtensionNames (and gPCUserExtensionNames) as inability of the +GPO to pass through the Filtered GPO list. Thus, the GPO would be +ignored. + +Reviewed-by: Alexander Bokovoy +Reviewed-by: Jakub Hrozek +--- + src/providers/ad/ad_gpo.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index f609d28136918adfe6a8d5e95319b27ffcab79c0..63c68ce35922ca0407ae6ea32c0a78100e14504b 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -3765,6 +3765,24 @@ done: + } + } + ++static bool machine_ext_names_is_blank(char *attr_value) ++{ ++ char *ptr; ++ ++ if (attr_value == NULL) { ++ return true; ++ } ++ ++ ptr = attr_value; ++ for (; *ptr != '\0'; ptr++) { ++ if (!isspace(*ptr)) { ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static errno_t + ad_gpo_sd_process_attrs(struct tevent_req *req, + char *smb_host, +@@ -3880,7 +3898,8 @@ ad_gpo_sd_process_attrs(struct tevent_req *req, + goto done; + } + +- if ((ret == ENOENT) || (el->num_values == 0)) { ++ if ((ret == ENOENT) || (el->num_values == 0) ++ || machine_ext_names_is_blank((char *) el[0].values[0].data)) { + /* + * if gpo has no machine_ext_names (which is perfectly valid: it could + * have only user_ext_names, for example), we continue to next gpo +-- +2.4.11 + diff --git a/SOURCES/0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch b/SOURCES/0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch deleted file mode 100644 index d8bae19..0000000 --- a/SOURCES/0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 9941803301b127d9326283b7eee9ad29f462574f Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 23 Jul 2015 09:52:47 -0400 -Subject: [PATCH 88/90] DYNDNS: rename field of sdap_dyndns_update_state - -Rename 'use_server_with_nsupdate' to more general name 'fallback_mode'. - -Resolves: -https://fedorahosted.org/sssd/ticket/2495 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 76604931b11594394a05df10f8370a1b8bb3e54b) ---- - src/providers/ldap/sdap_dyndns.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index f0e3dd855005d00ea19cb5dc283375f58b0d2cca..2a179fd1b5e88bdf2442657ff6fa1dcc55417467 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -58,7 +58,7 @@ struct sdap_dyndns_update_state { - bool update_ptr; - bool check_diff; - enum be_nsupdate_auth auth_type; -- bool use_server_with_nsupdate; -+ bool fallback_mode; - char *update_msg; - }; - -@@ -100,7 +100,7 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - state->hostname = hostname; - state->realm = realm; - state->servername = servername; -- state->use_server_with_nsupdate = false; -+ state->fallback_mode = false; - state->ttl = ttl; - state->be_res = be_ctx->be_res; - state->ev = ev; -@@ -316,7 +316,7 @@ sdap_dyndns_update_step(struct tevent_req *req) - state = tevent_req_data(req, struct sdap_dyndns_update_state); - - servername = NULL; -- if (state->use_server_with_nsupdate == true && -+ if (state->fallback_mode == true && - state->servername) { - servername = state->servername; - } -@@ -359,9 +359,9 @@ sdap_dyndns_update_done(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret != EOK) { - /* If the update didn't succeed, we can retry using the server name */ -- if (state->use_server_with_nsupdate == false && state->servername && -+ if (state->fallback_mode == false && state->servername && - WIFEXITED(child_status) && WEXITSTATUS(child_status) != 0) { -- state->use_server_with_nsupdate = true; -+ state->fallback_mode = true; - DEBUG(SSSDBG_MINOR_FAILURE, - "nsupdate failed, retrying with server name\n"); - ret = sdap_dyndns_update_step(req); -@@ -400,7 +400,7 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req) - state = tevent_req_data(req, struct sdap_dyndns_update_state); - - servername = NULL; -- if (state->use_server_with_nsupdate == true && -+ if (state->fallback_mode == true && - state->servername) { - servername = state->servername; - } -@@ -443,9 +443,9 @@ sdap_dyndns_update_ptr_done(struct tevent_req *subreq) - talloc_zfree(subreq); - if (ret != EOK) { - /* If the update didn't succeed, we can retry using the server name */ -- if (state->use_server_with_nsupdate == false && state->servername && -+ if (state->fallback_mode == false && state->servername && - WIFEXITED(child_status) && WEXITSTATUS(child_status) != 0) { -- state->use_server_with_nsupdate = true; -+ state->fallback_mode = true; - DEBUG(SSSDBG_MINOR_FAILURE, - "nsupdate failed, retrying with server name\n"); - ret = sdap_dyndns_update_ptr_step(req); --- -2.4.3 - diff --git a/SOURCES/0088-sss_ini-Change-debug-level-of-config-error-msgs.patch b/SOURCES/0088-sss_ini-Change-debug-level-of-config-error-msgs.patch new file mode 100644 index 0000000..1ed8612 --- /dev/null +++ b/SOURCES/0088-sss_ini-Change-debug-level-of-config-error-msgs.patch @@ -0,0 +1,44 @@ +From d049533953665fa3494a4932aeae7705ff84e107 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 27 Jul 2016 14:14:33 +0200 +Subject: [PATCH 088/102] sss_ini: Change debug level of config error msgs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Syntax errors in configuration files +prevent SSSD or sssctl to start completely. +It would be good to display these errors +by default with the highest level. + +Reviewed-by: Petr Čech +(cherry picked from commit 9dc081500979616f9af623ebe2d52837c211759f) +--- + src/util/sss_ini.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/util/sss_ini.c b/src/util/sss_ini.c +index d9bc46ad71fa820fd5f462cf71036213171fa92a..e56006c05555d6e0c5e726e83771abce5a72b139 100644 +--- a/src/util/sss_ini.c ++++ b/src/util/sss_ini.c +@@ -182,7 +182,7 @@ int sss_ini_get_mtime(struct sss_ini_initdata *init_data, + + /* Print ini_config errors */ + +-void sss_ini_config_print_errors(char **error_list) ++static void sss_ini_config_print_errors(char **error_list) + { + #ifdef HAVE_LIBINI_CONFIG_V1 + unsigned count = 0; +@@ -192,7 +192,7 @@ void sss_ini_config_print_errors(char **error_list) + } + + while (error_list[count]) { +- DEBUG(SSSDBG_CRIT_FAILURE, "%s\n", error_list[count]); ++ DEBUG(SSSDBG_FATAL_FAILURE, "%s\n", error_list[count]); + count++; + } + #endif +-- +2.4.11 + diff --git a/SOURCES/0089-CONFIG-full_name_format-is-an-allowed-option-for-all.patch b/SOURCES/0089-CONFIG-full_name_format-is-an-allowed-option-for-all.patch new file mode 100644 index 0000000..6c52b00 --- /dev/null +++ b/SOURCES/0089-CONFIG-full_name_format-is-an-allowed-option-for-all.patch @@ -0,0 +1,77 @@ +From c54b38573a93d1176a44935ba310e590904edb92 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 12 Aug 2016 13:23:16 +0200 +Subject: [PATCH 089/102] CONFIG: full_name_format is an allowed option for all + domains +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit cc4d1af16820b15595b60c3df15220fb852eb897) +--- + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/SSSDConfigTest.py | 2 ++ + src/config/cfg_rules.ini | 1 + + src/config/etc/sssd.api.conf | 1 + + 4 files changed, 5 insertions(+) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index 7856c4c6b2d675b7f7f0f5f2048086044e8fb5ea..3114d1da9fe8e833ae4050ac343ba2763dc56e68 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -163,6 +163,7 @@ option_strings = { + 'subdomain_refresh_interval' : _('How often should subdomains list be refreshed'), + 'subdomain_inherit' : _('List of options that should be inherited into a subdomain'), + 'cached_auth_timeout' : _('How long can cached credentials be used for cached authentication'), ++ 'full_name_format' : _('Printf-compatible format for displaying fully-qualified names'), + + # [provider/ipa] + 'ipa_domain' : _('IPA domain'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 332d8702d983b6ec8bf12ec781a1bbf296b552e0..bfb247ac45f752397000d43c54a20e57c6fbd9a5 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -560,6 +560,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'realmd_tags', + 'subdomain_refresh_interval', + 'subdomain_inherit', ++ 'full_name_format', + 'cached_auth_timeout'] + + self.assertTrue(type(options) == dict, +@@ -927,6 +928,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'realmd_tags', + 'subdomain_refresh_interval', + 'subdomain_inherit', ++ 'full_name_format', + 'cached_auth_timeout'] + + self.assertTrue(type(options) == dict, +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index 09f53fa41eb2904f11a78af333b6d79619d2759c..febe4289832f3778b7e974ef4e8b3f6d9d8bffd8 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -287,6 +287,7 @@ option = subdomain_refresh_interval + option = subdomain_inherit + option = cached_auth_timeout + option = wildcard_limit ++option = full_name_format + + #Entry cache timeouts + option = entry_cache_user_timeout +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index 737f0e149d56bd07b078cb83acbc43ea2ed3a057..2a43b8b68051c5133abc65a78f0d4a5561e760bd 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -147,6 +147,7 @@ realmd_tags = str, None, false + subdomain_refresh_interval = int, None, false + subdomain_inherit = str, None, false + cached_auth_timeout = int, None, false ++full_name_format = str, None, false + + #Entry cache timeouts + entry_cache_user_timeout = int, None, false +-- +2.4.11 + diff --git a/SOURCES/0089-DYNDNS-remove-code-duplication.patch b/SOURCES/0089-DYNDNS-remove-code-duplication.patch deleted file mode 100644 index 89270d9..0000000 --- a/SOURCES/0089-DYNDNS-remove-code-duplication.patch +++ /dev/null @@ -1,195 +0,0 @@ -From 194e127156332dcd29a7e2aa4a142b574e8b7eac Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Fri, 24 Jul 2015 08:24:48 -0400 -Subject: [PATCH 89/90] DYNDNS: remove code duplication - -Move copy pasted code for converting sockaddr_storage to string into -function. - -Resolves: -https://fedorahosted.org/sssd/ticket/2495 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit b42bf6c0c01db08208fb81d8295a2909d307284a) ---- - src/providers/dp_dyndns.c | 99 +++++++++++++++++++++-------------------------- - src/util/util_errors.c | 1 + - src/util/util_errors.h | 1 + - 3 files changed, 46 insertions(+), 55 deletions(-) - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index ae3f913ee392a6513f75aab497e7f2d784784748..0577743cb2daca9c0e86b5beb6bf059ee7b5783f 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -58,6 +58,39 @@ void sss_iface_addr_concatenate(struct sss_iface_addr **list, - DLIST_CONCATENATE((*list), list2, struct sss_iface_addr*); - } - -+static errno_t addr_to_str(struct sockaddr_storage *addr, -+ char *dst, size_t size) -+{ -+ const void *src; -+ const char *res; -+ errno_t ret; -+ -+ switch(addr->ss_family) { -+ case AF_INET: -+ src = &(((struct sockaddr_in *)addr)->sin_addr); -+ break; -+ case AF_INET6: -+ src = &(((struct sockaddr_in6 *)addr)->sin6_addr); -+ break; -+ default: -+ ret = ERR_ADDR_FAMILY_NOT_SUPPORTED; -+ goto done; -+ } -+ -+ res = inet_ntop(addr->ss_family, src, dst, size); -+ if (res == NULL) { -+ ret = errno; -+ DEBUG(SSSDBG_OP_FAILURE, "inet_ntop failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = EOK; -+ -+done: -+ return ret; -+} -+ - errno_t - sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx, - struct sss_iface_addr *ifaddr_list, -@@ -67,7 +100,6 @@ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx, - size_t count; - int ai; - char **straddrs; -- const char *ip; - char ip_addr[INET6_ADDRSTRLEN]; - errno_t ret; - -@@ -83,35 +115,17 @@ sss_iface_addr_list_as_str_list(TALLOC_CTX *mem_ctx, - - ai = 0; - DLIST_FOR_EACH(ifaddr, ifaddr_list) { -- switch(ifaddr->addr->ss_family) { -- case AF_INET: -- errno = 0; -- ip = inet_ntop(ifaddr->addr->ss_family, -- &(((struct sockaddr_in *)ifaddr->addr)->sin_addr), -- ip_addr, INET6_ADDRSTRLEN); -- if (ip == NULL) { -- ret = errno; -- goto fail; -- } -- break; - -- case AF_INET6: -- errno = 0; -- ip = inet_ntop(ifaddr->addr->ss_family, -- &(((struct sockaddr_in6 *)ifaddr->addr)->sin6_addr), -- ip_addr, INET6_ADDRSTRLEN); -- if (ip == NULL) { -- ret = errno; -- goto fail; -- } -- break; -- -- default: -- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n"); -+ ret = addr_to_str(ifaddr->addr, ip_addr, INET6_ADDRSTRLEN); -+ if (ret == ERR_ADDR_FAMILY_NOT_SUPPORTED) { - continue; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "addr_to_str failed: %d:[%s],\n", -+ ret, sss_strerror(ret)); -+ goto fail; - } - -- straddrs[ai] = talloc_strdup(straddrs, ip); -+ straddrs[ai] = talloc_strdup(straddrs, ip_addr); - if (straddrs[ai] == NULL) { - ret = ENOMEM; - goto fail; -@@ -237,7 +251,6 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses, - { - struct sss_iface_addr *new_record; - char ip_addr[INET6_ADDRSTRLEN]; -- const char *ip; - errno_t ret; - - /* Remove existing entries as needed */ -@@ -259,33 +272,10 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses, - } - - DLIST_FOR_EACH(new_record, addresses) { -- switch(new_record->addr->ss_family) { -- case AF_INET: -- ip = inet_ntop(new_record->addr->ss_family, -- &(((struct sockaddr_in *)new_record->addr)->sin_addr), -- ip_addr, INET6_ADDRSTRLEN); -- if (ip == NULL) { -- ret = errno; -- DEBUG(SSSDBG_OP_FAILURE, -- "inet_ntop failed [%d]: %s\n", ret, strerror(ret)); -- return NULL; -- } -- break; -- -- case AF_INET6: -- ip = inet_ntop(new_record->addr->ss_family, -- &(((struct sockaddr_in6 *)new_record->addr)->sin6_addr), -- ip_addr, INET6_ADDRSTRLEN); -- if (ip == NULL) { -- ret = errno; -- DEBUG(SSSDBG_OP_FAILURE, -- "inet_ntop failed [%d]: %s\n", ret, strerror(ret)); -- return NULL; -- } -- break; -- -- default: -- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n"); -+ ret = addr_to_str(new_record->addr, ip_addr, INET6_ADDRSTRLEN); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "addr_to_str failed: %d:[%s],\n", -+ ret, sss_strerror(ret)); - return NULL; - } - -@@ -298,7 +288,6 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses, - if (update_msg == NULL) { - return NULL; - } -- - } - - return talloc_asprintf_append(update_msg, "send\n"); -diff --git a/src/util/util_errors.c b/src/util/util_errors.c -index 0e288e3908bf03b4906bb449bd0f3445d22a303e..3041a1a28481aa8916bc1f5d972365e3c8007a4a 100644 ---- a/src/util/util_errors.c -+++ b/src/util/util_errors.c -@@ -80,6 +80,7 @@ struct err_string error_to_str[] = { - { "Trusted forest root unknown" }, /* ERR_TRUST_FOREST_UNKNOWN */ - { "p11_child failed" }, /* ERR_P11_CHILD */ - { "Subdomain is inactive" }, /* ERR_SUBDOM_INACTIVE */ -+ { "Address family not supported" }, /* ERR_ADDR_FAMILY_NOT_SUPPORTED */ - { "ERR_LAST" } /* ERR_LAST */ - }; - -diff --git a/src/util/util_errors.h b/src/util/util_errors.h -index da926db00121f569048ec515e95f0547ae6c4e35..660c370d600f6373d4515181cf88f62b42bcb7d7 100644 ---- a/src/util/util_errors.h -+++ b/src/util/util_errors.h -@@ -102,6 +102,7 @@ enum sssd_errors { - ERR_TRUST_FOREST_UNKNOWN, - ERR_P11_CHILD, - ERR_SUBDOM_INACTIVE, -+ ERR_ADDR_FAMILY_NOT_SUPPORTED, - ERR_LAST /* ALWAYS LAST */ - }; - --- -2.4.3 - diff --git a/SOURCES/0090-CONFIG-re_expression-is-an-allowed-option-for-all-do.patch b/SOURCES/0090-CONFIG-re_expression-is-an-allowed-option-for-all-do.patch new file mode 100644 index 0000000..61b409a --- /dev/null +++ b/SOURCES/0090-CONFIG-re_expression-is-an-allowed-option-for-all-do.patch @@ -0,0 +1,77 @@ +From 92302f81c25bc2b5ce9dbc2236c671d591fe69e0 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 12 Aug 2016 16:41:21 +0200 +Subject: [PATCH 090/102] CONFIG: re_expression is an allowed option for all + domains +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 6d19051c50c10fc4de056ebb385c63ec0ed221cb) +--- + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/SSSDConfigTest.py | 2 ++ + src/config/cfg_rules.ini | 1 + + src/config/etc/sssd.api.conf | 1 + + 4 files changed, 5 insertions(+) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index 3114d1da9fe8e833ae4050ac343ba2763dc56e68..ac538788b9878dc2613cb48b7483d392cca41d47 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -164,6 +164,7 @@ option_strings = { + 'subdomain_inherit' : _('List of options that should be inherited into a subdomain'), + 'cached_auth_timeout' : _('How long can cached credentials be used for cached authentication'), + 'full_name_format' : _('Printf-compatible format for displaying fully-qualified names'), ++ 're_expression' : _('Regex to parse username and domain'), + + # [provider/ipa] + 'ipa_domain' : _('IPA domain'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index bfb247ac45f752397000d43c54a20e57c6fbd9a5..00c688f1e57c5f481d3adba2fe0374145216bc33 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -561,6 +561,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'subdomain_refresh_interval', + 'subdomain_inherit', + 'full_name_format', ++ 're_expression', + 'cached_auth_timeout'] + + self.assertTrue(type(options) == dict, +@@ -929,6 +930,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'subdomain_refresh_interval', + 'subdomain_inherit', + 'full_name_format', ++ 're_expression', + 'cached_auth_timeout'] + + self.assertTrue(type(options) == dict, +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index febe4289832f3778b7e974ef4e8b3f6d9d8bffd8..bd0116f334e2605e7671a208225761421511a75a 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -288,6 +288,7 @@ option = subdomain_inherit + option = cached_auth_timeout + option = wildcard_limit + option = full_name_format ++option = re_expression + + #Entry cache timeouts + option = entry_cache_user_timeout +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index 2a43b8b68051c5133abc65a78f0d4a5561e760bd..5ac6f79521f5f776fc17319c3afb87d44961afca 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -148,6 +148,7 @@ subdomain_refresh_interval = int, None, false + subdomain_inherit = str, None, false + cached_auth_timeout = int, None, false + full_name_format = str, None, false ++re_expression = str, None, false + + #Entry cache timeouts + entry_cache_user_timeout = int, None, false +-- +2.4.11 + diff --git a/SOURCES/0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch b/SOURCES/0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch deleted file mode 100644 index 7883663..0000000 --- a/SOURCES/0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch +++ /dev/null @@ -1,471 +0,0 @@ -From 514240c29da65f8bbfc6d17e225655a5ac0f1b3c Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Sat, 12 Sep 2015 09:09:35 -0400 -Subject: [PATCH 90/90] DDNS: execute nsupdate for single update of PTR rec - -nsupdate fails definitely if any of update request fails when GSSAPI is used. - -As tmp solution nsupdate is executed for each update. - -Resolves: -https://fedorahosted.org/sssd/ticket/2783 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit eeac17ebbe38f16deaa8599231cccfc97aaac85c) ---- - src/providers/dp_dyndns.c | 128 ++++++++++++++++++++------------------- - src/providers/dp_dyndns.h | 13 +++- - src/providers/ldap/sdap_dyndns.c | 121 ++++++++++++++++++++++++++++++++++-- - src/tests/cmocka/test_dyndns.c | 29 +++++++++ - 4 files changed, 219 insertions(+), 72 deletions(-) - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 0577743cb2daca9c0e86b5beb6bf059ee7b5783f..50b087446f9437466de355e4d72b39a69512da03 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -52,6 +52,25 @@ struct sss_iface_addr { - struct sockaddr_storage *addr; - }; - -+struct sockaddr_storage* -+sss_iface_addr_get_address(struct sss_iface_addr *address) -+{ -+ if (address == NULL) { -+ return NULL; -+ } -+ -+ return address->addr; -+} -+ -+struct sss_iface_addr *sss_iface_addr_get_next(struct sss_iface_addr *address) -+{ -+ if (address) { -+ return address->next; -+ } -+ -+ return NULL; -+} -+ - void sss_iface_addr_concatenate(struct sss_iface_addr **list, - struct sss_iface_addr *list2) - { -@@ -293,80 +312,63 @@ nsupdate_msg_add_fwd(char *update_msg, struct sss_iface_addr *addresses, - return talloc_asprintf_append(update_msg, "send\n"); - } - --static char * --nsupdate_msg_add_ptr(char *update_msg, struct sss_iface_addr *addresses, -- const char *hostname, int ttl, uint8_t remove_af, -- struct sss_iface_addr *old_addresses) -+static uint8_t *nsupdate_convert_address(struct sockaddr_storage *add_address) -+{ -+ uint8_t *addr; -+ -+ switch(add_address->ss_family) { -+ case AF_INET: -+ addr = (uint8_t *) &((struct sockaddr_in *) add_address)->sin_addr; -+ break; -+ case AF_INET6: -+ addr = (uint8_t *) &((struct sockaddr_in6 *) add_address)->sin6_addr; -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n"); -+ addr = NULL; -+ break; -+ } -+ -+ return addr; -+} -+ -+static char *nsupdate_msg_add_ptr(char *update_msg, -+ struct sockaddr_storage *address, -+ const char *hostname, -+ int ttl, -+ bool delete) - { -- struct sss_iface_addr *new_record, *old_record; - char *strptr; - uint8_t *addr; - -- DLIST_FOR_EACH(old_record, old_addresses) { -- switch(old_record->addr->ss_family) { -- case AF_INET: -- if (!(remove_af & DYNDNS_REMOVE_A)) { -- continue; -- } -- addr = (uint8_t *) &((struct sockaddr_in *) old_record->addr)->sin_addr; -- break; -- case AF_INET6: -- if (!(remove_af & DYNDNS_REMOVE_AAAA)) { -- continue; -- } -- addr = (uint8_t *) &((struct sockaddr_in6 *) old_record->addr)->sin6_addr; -- break; -- default: -- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n"); -- return NULL; -- } -+ addr = nsupdate_convert_address(address); -+ if (addr == NULL) { -+ return NULL; -+ } - -- strptr = resolv_get_string_ptr_address(update_msg, old_record->addr->ss_family, -- addr); -- if (strptr == NULL) { -- return NULL; -- } -+ strptr = resolv_get_string_ptr_address(update_msg, address->ss_family, -+ addr); -+ if (strptr == NULL) { -+ return NULL; -+ } - -+ if (delete) { - /* example: update delete 38.78.16.10.in-addr.arpa. in PTR */ - update_msg = talloc_asprintf_append(update_msg, - "update delete %s in PTR\n" - "send\n", - strptr); -- talloc_free(strptr); -- if (update_msg == NULL) { -- return NULL; -- } -- } -- -- /* example: update add 11.78.16.10.in-addr.arpa. 85000 in PTR testvm.example.com */ -- DLIST_FOR_EACH(new_record, addresses) { -- switch(new_record->addr->ss_family) { -- case AF_INET: -- addr = (uint8_t *) &((struct sockaddr_in *) new_record->addr)->sin_addr; -- break; -- case AF_INET6: -- addr = (uint8_t *) &((struct sockaddr_in6 *) new_record->addr)->sin6_addr; -- break; -- default: -- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n"); -- return NULL; -- } -- -- strptr = resolv_get_string_ptr_address(update_msg, new_record->addr->ss_family, -- addr); -- if (strptr == NULL) { -- return NULL; -- } -- -+ } else { - /* example: update delete 38.78.16.10.in-addr.arpa. in PTR */ - update_msg = talloc_asprintf_append(update_msg, - "update add %s %d in PTR %s.\n" - "send\n", - strptr, ttl, hostname); -- talloc_free(strptr); -- if (update_msg == NULL) { -- return NULL; -- } -+ } -+ -+ talloc_free(strptr); -+ if (update_msg == NULL) { -+ return NULL; - } - - return update_msg; -@@ -471,9 +473,9 @@ done: - errno_t - be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm, - const char *servername, const char *hostname, -- const unsigned int ttl, uint8_t remove_af, -- struct sss_iface_addr *addresses, -- struct sss_iface_addr *old_addresses, -+ const unsigned int ttl, -+ struct sockaddr_storage *address, -+ bool delete, - char **_update_msg) - { - errno_t ret; -@@ -490,8 +492,8 @@ be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm, - goto done; - } - -- update_msg = nsupdate_msg_add_ptr(update_msg, addresses, hostname, -- ttl, remove_af, old_addresses); -+ update_msg = nsupdate_msg_add_ptr(update_msg, address, hostname, ttl, -+ delete); - if (update_msg == NULL) { - ret = ENOMEM; - goto done; -diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h -index 9f72331b6fd68e17e9eb91505a13fc839d3f54e1..9f39e5d48ed46e69d4052f2139ea5f13b9e5d12c 100644 ---- a/src/providers/dp_dyndns.h -+++ b/src/providers/dp_dyndns.h -@@ -97,9 +97,9 @@ be_nsupdate_create_fwd_msg(TALLOC_CTX *mem_ctx, const char *realm, - errno_t - be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm, - const char *servername, const char *hostname, -- const unsigned int ttl, uint8_t remove_af, -- struct sss_iface_addr *addresses, -- struct sss_iface_addr *old_addresses, -+ const unsigned int ttl, -+ struct sockaddr_storage *address, -+ bool delete, - char **_update_msg); - - /* Returns: -@@ -133,4 +133,11 @@ errno_t - sss_get_dualstack_addresses(TALLOC_CTX *mem_ctx, - struct sockaddr *ss, - struct sss_iface_addr **_iface_addrs); -+ -+struct sss_iface_addr * -+sss_iface_addr_get_next(struct sss_iface_addr *address); -+ -+struct sockaddr_storage* -+sss_iface_addr_get_address(struct sss_iface_addr *address); -+ - #endif /* DP_DYNDNS_H_ */ -diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c -index 2a179fd1b5e88bdf2442657ff6fa1dcc55417467..3a52a11d1e1c86ee7b26cf6affd81f7cf1bb7d03 100644 ---- a/src/providers/ldap/sdap_dyndns.c -+++ b/src/providers/ldap/sdap_dyndns.c -@@ -60,6 +60,8 @@ struct sdap_dyndns_update_state { - enum be_nsupdate_auth auth_type; - bool fallback_mode; - char *update_msg; -+ struct sss_iface_addr *ptr_addr_iter; -+ bool del_phase; - }; - - static void sdap_dyndns_update_addrs_done(struct tevent_req *subreq); -@@ -70,6 +72,12 @@ static errno_t sdap_dyndns_update_step(struct tevent_req *req); - static errno_t sdap_dyndns_update_ptr_step(struct tevent_req *req); - static void sdap_dyndns_update_done(struct tevent_req *subreq); - static void sdap_dyndns_update_ptr_done(struct tevent_req *subreq); -+static errno_t -+sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state, -+ struct tevent_req *req); -+static struct sss_iface_addr* -+sdap_get_address_to_delete(struct sss_iface_addr *address_it, -+ uint8_t remove_af); - - struct tevent_req * - sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, -@@ -106,6 +114,8 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, - state->ev = ev; - state->opts = opts; - state->auth_type = auth_type; -+ state->ptr_addr_iter = NULL; -+ state->del_phase = true; - - /* fallback servername is overriden by user option */ - conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER); -@@ -381,6 +391,16 @@ sdap_dyndns_update_done(struct tevent_req *subreq) - } - - talloc_free(state->update_msg); -+ -+ /* init iterator for addresses to be deleted */ -+ state->ptr_addr_iter = sdap_get_address_to_delete(state->dns_addrlist, -+ state->remove_af); -+ if (state->ptr_addr_iter == NULL) { -+ /* init iterator for addresses to be added */ -+ state->del_phase = false; -+ state->ptr_addr_iter = state->addresses; -+ } -+ - ret = sdap_dyndns_update_ptr_step(req); - if (ret != EOK) { - tevent_req_error(req, ret); -@@ -389,6 +409,50 @@ sdap_dyndns_update_done(struct tevent_req *subreq) - /* Execution will resume in sdap_dyndns_update_ptr_done */ - } - -+ -+static bool remove_addr(int address_family, uint8_t remove_af) -+{ -+ bool ret = false; -+ -+ switch(address_family) { -+ case AF_INET: -+ if (remove_af & DYNDNS_REMOVE_A) { -+ ret = true; -+ } -+ break; -+ case AF_INET6: -+ if (remove_af & DYNDNS_REMOVE_AAAA) { -+ ret = true; -+ } -+ break; -+ default: -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n"); -+ ret = false; -+ } -+ -+ return ret; -+} -+ -+static struct sss_iface_addr* -+sdap_get_address_to_delete(struct sss_iface_addr *address_it, -+ uint8_t remove_af) -+{ -+ struct sockaddr_storage* address; -+ -+ while (address_it != NULL) { -+ address = sss_iface_addr_get_address(address_it); -+ -+ /* skip addresses that are not to be deleted */ -+ if (remove_addr(address->ss_family, remove_af)) { -+ break; -+ } -+ -+ address_it = sss_iface_addr_get_next(address_it); -+ } -+ -+ return address_it; -+} -+ - static errno_t - sdap_dyndns_update_ptr_step(struct tevent_req *req) - { -@@ -396,6 +460,7 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req) - struct sdap_dyndns_update_state *state; - const char *servername; - struct tevent_req *subreq; -+ struct sockaddr_storage *address; - - state = tevent_req_data(req, struct sdap_dyndns_update_state); - -@@ -405,11 +470,14 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req) - servername = state->servername; - } - -- ret = be_nsupdate_create_ptr_msg(state, state->realm, -- servername, state->hostname, -- state->ttl, state->remove_af, -- state->addresses, state->dns_addrlist, -- &state->update_msg); -+ address = sss_iface_addr_get_address(state->ptr_addr_iter); -+ if (address == NULL) { -+ return EIO; -+ } -+ -+ ret = be_nsupdate_create_ptr_msg(state, state->realm, servername, -+ state->hostname, state->ttl, address, -+ state->del_phase, &state->update_msg); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n"); - return ret; -@@ -454,13 +522,55 @@ sdap_dyndns_update_ptr_done(struct tevent_req *subreq) - } - } - -+ ret = sdap_dyndns_next_ptr_record(state, req); -+ if (ret == EAGAIN) { -+ return; -+ } -+ - tevent_req_error(req, ret); - return; - } - -+ ret = sdap_dyndns_next_ptr_record(state, req); -+ if (ret == EAGAIN) { -+ return; -+ } -+ - tevent_req_done(req); - } - -+static errno_t -+sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state, -+ struct tevent_req *req) -+{ -+ errno_t ret; -+ -+ if (state->del_phase) { -+ /* iterate to next address to delete */ -+ state->ptr_addr_iter = sdap_get_address_to_delete( -+ sss_iface_addr_get_next(state->ptr_addr_iter), state->remove_af); -+ if (state->ptr_addr_iter == NULL) { -+ /* init iterator for addresses to be added */ -+ state->del_phase = false; -+ state->ptr_addr_iter = state->addresses; -+ } -+ } else { -+ /* iterate to next address to add */ -+ state->ptr_addr_iter = sss_iface_addr_get_next(state->ptr_addr_iter); -+ } -+ -+ if (state->ptr_addr_iter != NULL) { -+ -+ state->fallback_mode = false; -+ ret = sdap_dyndns_update_ptr_step(req); -+ if (ret == EOK) { -+ return EAGAIN; -+ } -+ } -+ -+ return EOK; -+} -+ - errno_t - sdap_dyndns_update_recv(struct tevent_req *req) - { -@@ -755,7 +865,6 @@ fail: - return req; - } - -- - static void - sdap_dyndns_timer_conn_done(struct tevent_req *subreq) - { -diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c -index 8118e9438e89465674155c11f4523d2313f6a59c..0a2fd1227c84c7783207444e21269026d268f993 100644 ---- a/src/tests/cmocka/test_dyndns.c -+++ b/src/tests/cmocka/test_dyndns.c -@@ -200,6 +200,32 @@ void will_return_getifaddrs(const char *ifname, const char *straddr, - } - } - -+void dyndns_test_sss_iface_addr_get_misc(void **state) -+{ -+ struct sss_iface_addr addrs[3]; -+ struct sockaddr_storage ss[3]; -+ -+ addrs[0].prev = NULL; -+ addrs[0].next = &addrs[1]; -+ addrs[0].addr = &ss[0]; -+ addrs[1].prev = &addrs[0]; -+ addrs[1].next = &addrs[2]; -+ addrs[1].addr = &ss[1]; -+ addrs[2].prev = &addrs[1]; -+ addrs[2].next = NULL; -+ addrs[2].addr = &ss[2]; -+ -+ assert_ptr_equal(sss_iface_addr_get_address(NULL), NULL); -+ assert_ptr_equal(sss_iface_addr_get_address(&addrs[0]), &ss[0]); -+ assert_ptr_equal(sss_iface_addr_get_address(&addrs[1]), &ss[1]); -+ assert_ptr_equal(sss_iface_addr_get_address(&addrs[2]), &ss[2]); -+ -+ assert_ptr_equal(sss_iface_addr_get_next(NULL), NULL); -+ assert_ptr_equal(sss_iface_addr_get_next(&addrs[0]), &addrs[1]); -+ assert_ptr_equal(sss_iface_addr_get_next(&addrs[1]), &addrs[2]); -+ assert_ptr_equal(sss_iface_addr_get_next(&addrs[2]), NULL); -+} -+ - void dyndns_test_get_ifaddr(void **state) - { - errno_t ret; -@@ -663,6 +689,9 @@ int main(int argc, const char *argv[]) - - const struct CMUnitTest tests[] = { - /* Utility functions unit test */ -+ cmocka_unit_test_setup_teardown(dyndns_test_sss_iface_addr_get_misc, -+ dyndns_test_simple_setup, -+ dyndns_test_teardown), - cmocka_unit_test_setup_teardown(dyndns_test_get_ifaddr, - dyndns_test_simple_setup, - dyndns_test_teardown), --- -2.4.3 - diff --git a/SOURCES/0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch b/SOURCES/0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch deleted file mode 100644 index a448123..0000000 --- a/SOURCES/0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 02e61ddc6986c6ada9c702bf2dd4ef42d20425c1 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Wed, 23 Sep 2015 13:50:22 +0200 -Subject: [PATCH 91/96] DYNDNS: Return right error code in case of failure - -The variable will be zero if getifaddrs succeeds -and therefore wrong error code will be returned -in case of insufficient memory (talloc_zero failed) - -Reviewed-by: Pavel Reichl -(cherry picked from commit 75889713afc99ea52f4ff13b40672a12b28bdd41) ---- - src/providers/dp_dyndns.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c -index 50b087446f9437466de355e4d72b39a69512da03..a5eb383bd4f6c08b846a69f0588b9c25647dc5c8 100644 ---- a/src/providers/dp_dyndns.c -+++ b/src/providers/dp_dyndns.c -@@ -228,6 +228,7 @@ sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname, - /* Add this address to the IP address list */ - address = talloc_zero(mem_ctx, struct sss_iface_addr); - if (!address) { -+ ret = ENOMEM; - goto done; - } - --- -2.4.3 - diff --git a/SOURCES/0091-rdp-add-ability-to-forward-reply-to-the-client-reque.patch b/SOURCES/0091-rdp-add-ability-to-forward-reply-to-the-client-reque.patch new file mode 100644 index 0000000..1719c18 --- /dev/null +++ b/SOURCES/0091-rdp-add-ability-to-forward-reply-to-the-client-reque.patch @@ -0,0 +1,518 @@ +From dc115d8a6aa1a656522c4f11c89e11d61360fd05 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 28 Jun 2016 11:40:16 +0200 +Subject: [PATCH 091/102] rdp: add ability to forward reply to the client + request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In cases where the InfoPipe servers just as a middle-man between +the DataProvider and a client we can simply forward the reply +reducing amount of coded needed in the InfoPipe. + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit a40d9cc11d17d9c3c22a0462cd8c419d1e79ffb8) +--- + src/responder/common/data_provider/rdp.h | 20 ++ + src/responder/common/data_provider/rdp_message.c | 260 +++++++++++++++++------ + src/responder/ifp/ifp_domains.c | 78 +------ + 3 files changed, 220 insertions(+), 138 deletions(-) + +diff --git a/src/responder/common/data_provider/rdp.h b/src/responder/common/data_provider/rdp.h +index 8a3ec803d8ea7914e2a54661e31dec084586582a..f0aed179a3d33de0462591e6c0bcd3c518105707 100644 +--- a/src/responder/common/data_provider/rdp.h ++++ b/src/responder/common/data_provider/rdp.h +@@ -54,6 +54,26 @@ errno_t _rdp_message_recv(struct tevent_req *req, + #define rdp_message_recv(req, ...) \ + _rdp_message_recv(req, ##__VA_ARGS__, DBUS_TYPE_INVALID) + ++/** ++ * Send D-Bus message to Data Provider but instead of returning the reply ++ * to the caller it forwards the reply to the client request. No further ++ * processing is required by the caller. In case of a failure the client ++ * request is freed since there is nothing we can do. ++ */ ++void _rdp_message_send_and_reply(struct sbus_request *sbus_req, ++ struct resp_ctx *rctx, ++ struct sss_domain_info *domain, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ ...); ++ ++#define rdp_message_send_and_reply(sbus_req, rctx, domain, path, iface, \ ++ method, ...) \ ++ _rdp_message_send_and_reply(sbus_req, rctx, domain, path, iface, method, \ ++ ##__VA_ARGS__, DBUS_TYPE_INVALID) ++ + errno_t rdp_register_client(struct be_conn *be_conn, + const char *client_name); + +diff --git a/src/responder/common/data_provider/rdp_message.c b/src/responder/common/data_provider/rdp_message.c +index 78af6f8967b378536b6456274fbcac4b609d1033..e226401567e4a1b2b9784a9aba21540ff5f0bc8d 100644 +--- a/src/responder/common/data_provider/rdp_message.c ++++ b/src/responder/common/data_provider/rdp_message.c +@@ -53,104 +53,72 @@ static errno_t rdp_error_to_errno(DBusError *error) + return EIO; + } + +-struct rdp_message_state { +- struct DBusMessage *reply; +-}; +- +-static int rdp_message_state_destructor(struct rdp_message_state *state) ++static errno_t ++rdp_message_send_internal(struct resp_ctx *rctx, ++ struct sss_domain_info *domain, ++ DBusPendingCallNotifyFunction notify_fn, ++ void *notify_fn_data, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ va_list va) + { +- if (state->reply != NULL) { +- dbus_message_unref(state->reply); +- } +- +- return 0; +-} +- +-static void rdp_message_done(DBusPendingCall *pending, void *ptr); +- +-struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx, +- struct resp_ctx *rctx, +- struct sss_domain_info *domain, +- const char *path, +- const char *iface, +- const char *method, +- int first_arg_type, +- ...) +-{ +- struct rdp_message_state *state; + struct be_conn *be_conn; +- struct tevent_req *req; +- DBusMessage *msg; ++ DBusMessage *msg = NULL; + dbus_bool_t bret; + errno_t ret; +- va_list va; +- +- req = tevent_req_create(mem_ctx, &state, struct rdp_message_state); +- if (req == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); +- return NULL; +- } +- +- talloc_set_destructor(state, rdp_message_state_destructor); + + ret = sss_dp_get_domain_conn(rctx, domain->conn_name, &be_conn); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "BUG: The Data Provider connection for " + "%s is not available!\n", domain->name); +- ret = ERR_INTERNAL; +- goto immediately; ++ goto done; + } + + msg = dbus_message_new_method_call(NULL, path, iface, method); + if (msg == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create message\n"); + ret = ENOMEM; +- goto immediately; ++ goto done; + } + +- va_start(va, first_arg_type); + bret = dbus_message_append_args_valist(msg, first_arg_type, va); +- va_end(va); + if (!bret) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n"); + ret = EIO; +- goto immediately; ++ goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "DP Request: %s %s.%s\n", path, iface, method); + +- ret = sbus_conn_send(be_conn->conn, msg, 30000, +- rdp_message_done, req, NULL); ++ ret = sbus_conn_send(be_conn->conn, msg, 3000, ++ notify_fn, notify_fn_data, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to contact Data Provider " + "[%d]: %s\n", ret, sss_strerror(ret)); +- goto immediately; ++ goto done; + } + +- return req; ++ ret = EOK; + +-immediately: +- if (ret == EOK) { +- tevent_req_done(req); +- } else { +- tevent_req_error(req, ret); ++done: ++ if (msg != NULL) { ++ dbus_message_unref(msg); + } +- tevent_req_post(req, rctx->ev); + +- return req; ++ return ret; + } + +-static void rdp_message_done(DBusPendingCall *pending, void *ptr) ++static errno_t rdp_process_pending_call(DBusPendingCall *pending, ++ DBusMessage **_reply) + { +- struct rdp_message_state *state; +- DBusMessage *reply = NULL; +- struct tevent_req *req; +- DBusError error; ++ DBusMessage *reply; + dbus_bool_t bret; ++ DBusError error; + errno_t ret; + +- req = talloc_get_type(ptr, struct tevent_req); +- state = tevent_req_data(req, struct rdp_message_state); ++ *_reply = NULL; + + dbus_error_init(&error); + +@@ -165,9 +133,8 @@ static void rdp_message_done(DBusPendingCall *pending, void *ptr) + switch (dbus_message_get_type(reply)) { + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + DEBUG(SSSDBG_TRACE_FUNC, "DP Success\n"); +- state->reply = reply; + ret = EOK; +- goto done; ++ break; + + case DBUS_MESSAGE_TYPE_ERROR: + bret = dbus_set_error_from_message(&error, reply); +@@ -180,28 +147,105 @@ static void rdp_message_done(DBusPendingCall *pending, void *ptr) + DEBUG(SSSDBG_CRIT_FAILURE, "DP Error [%s]: %s\n", + error.name, (error.message == NULL ? "(null)" : error.message)); + ret = rdp_error_to_errno(&error); +- goto done; ++ break; + default: ++ dbus_message_unref(reply); + DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected type?\n"); + ret = ERR_INTERNAL; + goto done; + } + +- ret = ERR_INTERNAL; ++ *_reply = reply; + + done: + dbus_pending_call_unref(pending); + dbus_error_free(&error); + ++ return ret; ++} ++ ++struct rdp_message_state { ++ struct DBusMessage *reply; ++}; ++ ++static int rdp_message_state_destructor(struct rdp_message_state *state) ++{ ++ if (state->reply != NULL) { ++ dbus_message_unref(state->reply); ++ } ++ ++ return 0; ++} ++ ++static void rdp_message_done(DBusPendingCall *pending, void *ptr); ++ ++struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx, ++ struct resp_ctx *rctx, ++ struct sss_domain_info *domain, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ ...) ++{ ++ struct rdp_message_state *state; ++ struct tevent_req *req; ++ errno_t ret; ++ va_list va; ++ ++ req = tevent_req_create(mem_ctx, &state, struct rdp_message_state); ++ if (req == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); ++ return NULL; ++ } ++ ++ talloc_set_destructor(state, rdp_message_state_destructor); ++ ++ va_start(va, first_arg_type); ++ ret = rdp_message_send_internal(rctx, domain, rdp_message_done, req, ++ path, iface, method, first_arg_type, va); ++ va_end(va); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to contact Data Provider " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ goto immediately; ++ } ++ ++ return req; ++ ++immediately: + if (ret == EOK) { + tevent_req_done(req); ++ } else { ++ tevent_req_error(req, ret); ++ } ++ tevent_req_post(req, rctx->ev); ++ ++ return req; ++} ++ ++static void rdp_message_done(DBusPendingCall *pending, void *ptr) ++{ ++ struct rdp_message_state *state; ++ struct tevent_req *req; ++ errno_t ret; ++ ++ req = talloc_get_type(ptr, struct tevent_req); ++ state = tevent_req_data(req, struct rdp_message_state); ++ ++ ret = rdp_process_pending_call(pending, &state->reply); ++ if (ret != EOK) { ++ if (state->reply != NULL) { ++ dbus_message_unref(state->reply); ++ } ++ ++ state->reply = NULL; ++ ++ tevent_req_error(req, ret); + return; + } + +- if (reply != NULL) { +- dbus_message_unref(reply); +- } +- tevent_req_error(req, ret); ++ tevent_req_done(req); + } + + errno_t _rdp_message_recv(struct tevent_req *req, +@@ -241,3 +285,85 @@ done: + return ret; + } + ++static void rdp_message_send_and_reply_done(DBusPendingCall *pending, ++ void *ptr); ++ ++void _rdp_message_send_and_reply(struct sbus_request *sbus_req, ++ struct resp_ctx *rctx, ++ struct sss_domain_info *domain, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ ...) ++{ ++ errno_t ret; ++ va_list va; ++ ++ va_start(va, first_arg_type); ++ ret = rdp_message_send_internal(rctx, domain, ++ rdp_message_send_and_reply_done, sbus_req, ++ path, iface, method, first_arg_type, va); ++ va_end(va); ++ ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to contact Data Provider " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ talloc_free(sbus_req); ++ } ++} ++ ++static void rdp_message_send_and_reply_done(DBusPendingCall *pending, ++ void *ptr) ++{ ++ struct sbus_request *sbus_req; ++ DBusMessage *reply = NULL; ++ dbus_uint32_t serial; ++ const char *sender; ++ dbus_bool_t dbret; ++ errno_t ret; ++ ++ sbus_req = talloc_get_type(ptr, struct sbus_request); ++ ++ ret = rdp_process_pending_call(pending, &reply); ++ if (reply == NULL) { ++ /* Something bad happened. Just kill the request. */ ++ ret = EIO; ++ goto done; ++ } ++ ++ /* Otherwise we have a valid reply and we do not care about returned ++ * value. We set destination and serial in reply to point to the original ++ * client request. */ ++ ++ sender = dbus_message_get_sender(sbus_req->message); ++ serial = dbus_message_get_serial(sbus_req->message); ++ ++ dbret = dbus_message_set_destination(reply, sender); ++ if (dbret == false) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set reply sender!\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ dbret = dbus_message_set_reply_serial(reply, serial); ++ if (dbret == false) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set reply serial!\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ sbus_request_finish(sbus_req, reply); ++ ++ ret = EOK; ++ ++done: ++ if (reply != NULL) { ++ dbus_message_unref(reply); ++ } ++ ++ if (ret != EOK) { ++ /* Something bad happend, just kill the request. */ ++ talloc_free(sbus_req); ++ } ++} +diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c +index 5333b25275e0847015f9cdd294eab5dbdda32f6c..8bfd39feb39822921ea703d8a89ac372e0ad5410 100644 +--- a/src/responder/ifp/ifp_domains.c ++++ b/src/responder/ifp/ifp_domains.c +@@ -538,14 +538,11 @@ void ifp_dom_get_parent_domain(struct sbus_request *dbus_req, + dom->parent->name); + } + +-static void ifp_domains_domain_is_online_done(struct tevent_req *req); +- + int ifp_domains_domain_is_online(struct sbus_request *sbus_req, + void *data) + { + struct ifp_ctx *ifp_ctx; + struct sss_domain_info *dom; +- struct tevent_req *req; + DBusError *error; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); +@@ -558,49 +555,18 @@ int ifp_domains_domain_is_online(struct sbus_request *sbus_req, + return EOK; + } + +- req = rdp_message_send(sbus_req, ifp_ctx->rctx, dom, DP_PATH, +- IFACE_DP_BACKEND, IFACE_DP_BACKEND_ISONLINE, +- DBUS_TYPE_STRING, &dom->name); +- if (req == NULL) { +- return ENOMEM; +- } +- +- tevent_req_set_callback(req, ifp_domains_domain_is_online_done, sbus_req); ++ rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH, ++ IFACE_DP_BACKEND, IFACE_DP_BACKEND_ISONLINE, ++ DBUS_TYPE_STRING, &dom->name); + + return EOK; + } + +-static void ifp_domains_domain_is_online_done(struct tevent_req *req) +-{ +- struct sbus_request *sbus_req; +- DBusError *error; +- bool is_online; +- errno_t ret; +- +- sbus_req = tevent_req_callback_data(req, struct sbus_request); +- +- ret = rdp_message_recv(req, DBUS_TYPE_BOOLEAN, &is_online); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Unable to get online status [%d]: %s\n", +- ret, sss_strerror(ret)); +- error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, +- "Unable to get online status [%d]: %s", +- ret, sss_strerror(ret)); +- sbus_request_fail_and_finish(sbus_req, error); +- return; +- } +- +- iface_ifp_domains_domain_IsOnline_finish(sbus_req, is_online); +-} +- +-static void ifp_domains_domain_list_services_done(struct tevent_req *req); +- + int ifp_domains_domain_list_services(struct sbus_request *sbus_req, + void *data) + { + struct ifp_ctx *ifp_ctx; + struct sss_domain_info *dom; +- struct tevent_req *req; + DBusError *error; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); +@@ -613,40 +579,10 @@ int ifp_domains_domain_list_services(struct sbus_request *sbus_req, + return EOK; + } + +- req = rdp_message_send(sbus_req, ifp_ctx->rctx, dom, DP_PATH, +- IFACE_DP_FAILOVER, IFACE_DP_FAILOVER_LISTSERVICES, +- DBUS_TYPE_STRING, &dom->name); +- if (req == NULL) { +- return ENOMEM; +- } +- +- tevent_req_set_callback(req, ifp_domains_domain_list_services_done, sbus_req); ++ rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH, ++ IFACE_DP_FAILOVER, ++ IFACE_DP_FAILOVER_LISTSERVICES, ++ DBUS_TYPE_STRING, &dom->name); + + return EOK; + } +- +-static void ifp_domains_domain_list_services_done(struct tevent_req *req) +-{ +- struct sbus_request *sbus_req; +- DBusError *error; +- int num_services; +- const char **services; +- errno_t ret; +- +- sbus_req = tevent_req_callback_data(req, struct sbus_request); +- +- ret = rdp_message_recv(req, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, +- &services, &num_services); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Unable to get failover services [%d]: %s\n", +- ret, sss_strerror(ret)); +- error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, +- "Unable to get failover services [%d]: %s", +- ret, sss_strerror(ret)); +- sbus_request_fail_and_finish(sbus_req, error); +- return; +- } +- +- iface_ifp_domains_domain_ListServices_finish(sbus_req, services, +- num_services); +-} +-- +2.4.11 + diff --git a/SOURCES/0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch b/SOURCES/0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch deleted file mode 100644 index 797fd6a..0000000 --- a/SOURCES/0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch +++ /dev/null @@ -1,270 +0,0 @@ -From ce69c907f04214e16c07c5a05fb8dac12b271aba Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 17 Sep 2015 17:09:24 +0200 -Subject: [PATCH 92/96] IPA: Change ipa_server_trust_add_send request to be - reusable from ID code - -Required for: - https://fedorahosted.org/sssd/ticket/2639 - -Expose a request ipa_server_trusted_dom_setup_send that sets up a -trusted domain. The setup might include actions like retrieving a keytab -for one-way trusts. - -Creating the AD ID context for the trused domain is now done in the -caller of this new request. - -Reviewed-by: Sumit Bose -(cherry picked from commit 1ccfd8e2e5cf4cdb6807d9809c150b7f6ba3e0eb) ---- - src/providers/ipa/ipa_subdomains.h | 11 +++ - src/providers/ipa/ipa_subdomains_server.c | 122 ++++++++++++++++-------------- - 2 files changed, 75 insertions(+), 58 deletions(-) - -diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h -index 2302c5f03e80de2ea1efad424769e777cd6dd8d5..0c13f8ed2eeda87237dfb097f532c7137095ddf1 100644 ---- a/src/providers/ipa/ipa_subdomains.h -+++ b/src/providers/ipa/ipa_subdomains.h -@@ -52,6 +52,17 @@ struct ipa_ad_server_ctx { - struct ipa_ad_server_ctx *next, *prev; - }; - -+/* Can be used to set up trusted subdomain, for example fetch -+ * keytab in server mode -+ */ -+struct tevent_req * -+ipa_server_trusted_dom_setup_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct be_ctx *be_ctx, -+ struct ipa_id_ctx *id_ctx, -+ struct sss_domain_info *subdom); -+errno_t ipa_server_trusted_dom_setup_recv(struct tevent_req *req); -+ - /* To be used by ipa_subdomains.c only */ - struct tevent_req * - ipa_server_create_trusts_send(TALLOC_CTX *mem_ctx, -diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c -index dfecab1bc362b5772379bae6d51f9cef8443f225..c561118946e2ba76b2b4076e5057b1b5c0075a41 100644 ---- a/src/providers/ipa/ipa_subdomains_server.c -+++ b/src/providers/ipa/ipa_subdomains_server.c -@@ -563,7 +563,7 @@ done: - return ret; - } - --struct ipa_server_trust_add_state { -+struct ipa_server_trusted_dom_setup_state { - struct tevent_context *ev; - struct be_ctx *be_ctx; - struct ipa_id_ctx *id_ctx; -@@ -578,22 +578,22 @@ struct ipa_server_trust_add_state { - const char *ccache; - }; - --static errno_t ipa_server_trust_add_1way(struct tevent_req *req); -+static errno_t ipa_server_trusted_dom_setup_1way(struct tevent_req *req); - static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq); --static errno_t ipa_server_trust_add_step(struct tevent_req *req); - --static struct tevent_req * --ipa_server_trust_add_send(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct be_ctx *be_ctx, -- struct ipa_id_ctx *id_ctx, -- struct sss_domain_info *subdom) -+struct tevent_req * -+ipa_server_trusted_dom_setup_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct be_ctx *be_ctx, -+ struct ipa_id_ctx *id_ctx, -+ struct sss_domain_info *subdom) - { - struct tevent_req *req = NULL; -- struct ipa_server_trust_add_state *state = NULL; -+ struct ipa_server_trusted_dom_setup_state *state = NULL; - errno_t ret; - -- req = tevent_req_create(mem_ctx, &state, struct ipa_server_trust_add_state); -+ req = tevent_req_create(mem_ctx, &state, -+ struct ipa_server_trusted_dom_setup_state); - if (req == NULL) { - return NULL; - } -@@ -626,16 +626,19 @@ ipa_server_trust_add_send(TALLOC_CTX *mem_ctx, - ipa_trust_dir2str(state->direction)); - - if (state->direction & LSA_TRUST_DIRECTION_OUTBOUND) { -- /* Use system keytab */ -- ret = ipa_server_trust_add_step(req); -+ /* Use system keytab, nothing to do here */ -+ ret = EOK; -+ goto immediate; - } else if (state->direction & LSA_TRUST_DIRECTION_INBOUND) { - /* Need special keytab */ -- ret = ipa_server_trust_add_1way(req); -+ ret = ipa_server_trusted_dom_setup_1way(req); - if (ret == EAGAIN) { - /* In progress.. */ - return req; - } else if (ret == EOK) { -- ret = ipa_server_trust_add_step(req); -+ /* Keytab available, shortcut */ -+ ret = EOK; -+ goto immediate; - } - } else { - /* Even unset is an error at this point */ -@@ -658,12 +661,12 @@ immediate: - return req; - } - --static errno_t ipa_server_trust_add_1way(struct tevent_req *req) -+static errno_t ipa_server_trusted_dom_setup_1way(struct tevent_req *req) - { - errno_t ret; - struct tevent_req *subreq = NULL; -- struct ipa_server_trust_add_state *state = -- tevent_req_data(req, struct ipa_server_trust_add_state); -+ struct ipa_server_trusted_dom_setup_state *state = -+ tevent_req_data(req, struct ipa_server_trusted_dom_setup_state); - const char *hostname; - - state->keytab = forest_keytab(state, state->forest); -@@ -715,8 +718,8 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq) - errno_t ret; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); -- struct ipa_server_trust_add_state *state = -- tevent_req_data(req, struct ipa_server_trust_add_state); -+ struct ipa_server_trusted_dom_setup_state *state = -+ tevent_req_data(req, struct ipa_server_trusted_dom_setup_state); - - ret = ipa_getkeytab_recv(subreq, NULL); - talloc_zfree(subreq); -@@ -764,46 +767,12 @@ static void ipa_server_trust_1way_kt_done(struct tevent_req *subreq) - DEBUG(SSSDBG_TRACE_FUNC, - "Keytab %s contains the expected principals\n", state->new_keytab); - -- ret = ipa_server_trust_add_step(req); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "ipa_server_trust_add_step failed: %d\n", ret); -- tevent_req_error(req, ret); -- return; -- } -- - DEBUG(SSSDBG_TRACE_FUNC, - "Established trust context for %s\n", state->subdom->name); - tevent_req_done(req); - } - --static errno_t ipa_server_trust_add_step(struct tevent_req *req) --{ -- struct ipa_ad_server_ctx *trust_ctx; -- struct ad_id_ctx *ad_id_ctx; -- errno_t ret; -- struct ipa_server_trust_add_state *state = -- tevent_req_data(req, struct ipa_server_trust_add_state); -- -- ret = ipa_ad_ctx_new(state->be_ctx, state->id_ctx, state->subdom, &ad_id_ctx); -- if (ret != EOK) { -- DEBUG(SSSDBG_OP_FAILURE, -- "Cannot create ad_id_ctx for subdomain %s\n", state->subdom->name); -- return ret; -- } -- -- trust_ctx = talloc(state->id_ctx->server_mode, struct ipa_ad_server_ctx); -- if (trust_ctx == NULL) { -- return ENOMEM; -- } -- trust_ctx->dom = state->subdom; -- trust_ctx->ad_id_ctx = ad_id_ctx; -- -- DLIST_ADD(state->id_ctx->server_mode->trusts, trust_ctx); -- return EOK; --} -- --static errno_t ipa_server_trust_add_recv(struct tevent_req *req) -+errno_t ipa_server_trusted_dom_setup_recv(struct tevent_req *req) - { - TEVENT_REQ_RETURN_ON_ERROR(req); - return EOK; -@@ -817,6 +786,7 @@ struct ipa_server_create_trusts_state { - }; - - static errno_t ipa_server_create_trusts_step(struct tevent_req *req); -+static errno_t ipa_server_create_trusts_ctx(struct tevent_req *req); - static void ipa_server_create_trusts_done(struct tevent_req *subreq); - - struct tevent_req * -@@ -879,8 +849,11 @@ static errno_t ipa_server_create_trusts_step(struct tevent_req *req) - - /* Newly detected trust */ - if (trust_iter == NULL) { -- subreq = ipa_server_trust_add_send(state, state->ev, state->be_ctx, -- state->id_ctx, state->domiter); -+ subreq = ipa_server_trusted_dom_setup_send(state, -+ state->ev, -+ state->be_ctx, -+ state->id_ctx, -+ state->domiter); - if (subreq == NULL) { - return ENOMEM; - } -@@ -898,13 +871,19 @@ static void ipa_server_create_trusts_done(struct tevent_req *subreq) - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - -- ret = ipa_server_trust_add_recv(subreq); -+ ret = ipa_server_trusted_dom_setup_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - -+ ret = ipa_server_create_trusts_ctx(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ - ret = ipa_server_create_trusts_step(req); - if (ret == EOK) { - tevent_req_done(req); -@@ -917,6 +896,33 @@ static void ipa_server_create_trusts_done(struct tevent_req *subreq) - /* Will cycle back */ - } - -+static errno_t ipa_server_create_trusts_ctx(struct tevent_req *req) -+{ -+ struct ipa_ad_server_ctx *trust_ctx; -+ struct ad_id_ctx *ad_id_ctx; -+ errno_t ret; -+ struct ipa_server_create_trusts_state *state = NULL; -+ -+ state = tevent_req_data(req, struct ipa_server_create_trusts_state); -+ -+ ret = ipa_ad_ctx_new(state->be_ctx, state->id_ctx, state->domiter, &ad_id_ctx); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot create ad_id_ctx for subdomain %s\n", state->domiter->name); -+ return ret; -+ } -+ -+ trust_ctx = talloc(state->id_ctx->server_mode, struct ipa_ad_server_ctx); -+ if (trust_ctx == NULL) { -+ return ENOMEM; -+ } -+ trust_ctx->dom = state->domiter; -+ trust_ctx->ad_id_ctx = ad_id_ctx; -+ -+ DLIST_ADD(state->id_ctx->server_mode->trusts, trust_ctx); -+ return EOK; -+} -+ - errno_t ipa_server_create_trusts_recv(struct tevent_req *req) - { - TEVENT_REQ_RETURN_ON_ERROR(req); --- -2.4.3 - diff --git a/SOURCES/0092-sbus-add-sbus_request_reply_error.patch b/SOURCES/0092-sbus-add-sbus_request_reply_error.patch new file mode 100644 index 0000000..623cc9c --- /dev/null +++ b/SOURCES/0092-sbus-add-sbus_request_reply_error.patch @@ -0,0 +1,218 @@ +From 9b0cda6876a5407b152bdeb51bb312aa52916172 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 28 Jun 2016 15:29:39 +0200 +Subject: [PATCH 092/102] sbus: add sbus_request_reply_error() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This simplifies error handling in sbus requests since we avoid +creating DBusError and checking for NULL manually. It removes +few lines of code. + +This patch does not replace all calls to sbus_request_fail_and_finish +since sometimes it is desirable to create the error manualy. But +it replaces it in most recent places. + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit a06e23c0bcf0c8669a29b801876aca8aac422931) +--- + src/providers/data_provider/dp_iface_backend.c | 11 ++-- + src/responder/ifp/ifp_domains.c | 12 ++--- + src/sbus/sssd_dbus.h | 9 +++- + src/sbus/sssd_dbus_request.c | 73 ++++++++++++++++++++------ + 4 files changed, 70 insertions(+), 35 deletions(-) + +diff --git a/src/providers/data_provider/dp_iface_backend.c b/src/providers/data_provider/dp_iface_backend.c +index f4af35ed6ec3858b7fff80cf2933926a653ba6f5..d9a84bfee4c5c11e46e0e8f7021f829825ad95c1 100644 +--- a/src/providers/data_provider/dp_iface_backend.c ++++ b/src/providers/data_provider/dp_iface_backend.c +@@ -34,7 +34,6 @@ errno_t dp_backend_is_online(struct sbus_request *sbus_req, + { + struct be_ctx *be_ctx; + struct sss_domain_info *domain; +- DBusError *error; + bool online; + + be_ctx = dp_client_be(dp_cli); +@@ -44,13 +43,9 @@ errno_t dp_backend_is_online(struct sbus_request *sbus_req, + } else { + domain = find_domain_by_name(be_ctx->domain, domname, false); + if (domain == NULL) { +- error = sbus_error_new(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, +- "Unknown domain %s", domname); +- if (error == NULL) { +- return ENOMEM; +- } +- +- return sbus_request_fail_and_finish(sbus_req, error); ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, ++ "Unknown domain %s", domname); ++ return EOK; + } + } + +diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c +index 8bfd39feb39822921ea703d8a89ac372e0ad5410..ff690ed6a7d5519979d242a4d5dadd08aff50347 100644 +--- a/src/responder/ifp/ifp_domains.c ++++ b/src/responder/ifp/ifp_domains.c +@@ -543,15 +543,13 @@ int ifp_domains_domain_is_online(struct sbus_request *sbus_req, + { + struct ifp_ctx *ifp_ctx; + struct sss_domain_info *dom; +- DBusError *error; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + + dom = get_domain_info_from_req(sbus_req, data); + if (dom == NULL) { +- error = sbus_error_new(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, +- "Unknown domain"); +- sbus_request_fail_and_finish(sbus_req, error); ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, ++ "Unknown domain"); + return EOK; + } + +@@ -567,15 +565,13 @@ int ifp_domains_domain_list_services(struct sbus_request *sbus_req, + { + struct ifp_ctx *ifp_ctx; + struct sss_domain_info *dom; +- DBusError *error; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + + dom = get_domain_info_from_req(sbus_req, data); + if (dom == NULL) { +- error = sbus_error_new(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, +- "Unknown domain"); +- sbus_request_fail_and_finish(sbus_req, error); ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, ++ "Unknown domain"); + return EOK; + } + +diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h +index fe1c4a7e1730e088647744d9b49a68c3c71db57f..c0aedf36b496bfda05dcde921ea7060efb4cc91f 100644 +--- a/src/sbus/sssd_dbus.h ++++ b/src/sbus/sssd_dbus.h +@@ -357,6 +357,11 @@ int sbus_request_return_and_finish(struct sbus_request *dbus_req, + int sbus_request_fail_and_finish(struct sbus_request *dbus_req, + const DBusError *error); + ++void sbus_request_reply_error(struct sbus_request *sbus_req, ++ const char *error_name, ++ const char *fmt, ++ ...) SSS_ATTRIBUTE_PRINTF(3, 4); ++ + /* + * Construct a new DBusError instance which can be consumed by functions such + * as @sbus_request_fail_and_finish(). +@@ -368,9 +373,9 @@ int sbus_request_fail_and_finish(struct sbus_request *dbus_req, + * is duplicated using the returned DBusError instance as a talloc parent. + */ + DBusError *sbus_error_new(TALLOC_CTX *mem_ctx, +- const char *dbus_err_name, ++ const char *dbus_error_name, + const char *fmt, +- ...) SSS_ATTRIBUTE_PRINTF(3,4); ++ ...) SSS_ATTRIBUTE_PRINTF(3, 4); + + /* + * Parse a DBus method call request. +diff --git a/src/sbus/sssd_dbus_request.c b/src/sbus/sssd_dbus_request.c +index f8647b5ecfb4a49d45a15733b22c6014f4bd084c..c5b08539ff85b5427e41f6e03991b40a0a43a7e3 100644 +--- a/src/sbus/sssd_dbus_request.c ++++ b/src/sbus/sssd_dbus_request.c +@@ -199,31 +199,70 @@ int sbus_request_fail_and_finish(struct sbus_request *dbus_req, + return ret; + } + ++static DBusError *sbus_error_new_va(TALLOC_CTX *mem_ctx, ++ const char *error_name, ++ const char *fmt, ++ va_list ap) ++{ ++ DBusError *error; ++ const char *error_msg; ++ ++ error = talloc_zero(mem_ctx, DBusError); ++ if (error == NULL) { ++ return NULL; ++ } ++ ++ if (fmt != NULL) { ++ error_msg = talloc_vasprintf(error, fmt, ap); ++ if (error_msg == NULL) { ++ talloc_free(error); ++ return NULL; ++ } ++ } else { ++ error_msg = NULL; ++ } ++ ++ dbus_error_init(error); ++ dbus_set_error_const(error, error_name, error_msg); ++ ++ return error; ++} ++ + DBusError *sbus_error_new(TALLOC_CTX *mem_ctx, +- const char *dbus_err_name, ++ const char *dbus_error_name, + const char *fmt, + ...) + { +- DBusError *dberr; +- const char *err_msg_dup = NULL; ++ DBusError *error; + va_list ap; + +- dberr = talloc(mem_ctx, DBusError); +- if (dberr == NULL) return NULL; +- +- if (fmt) { +- va_start(ap, fmt); +- err_msg_dup = talloc_vasprintf(dberr, fmt, ap); +- va_end(ap); +- if (err_msg_dup == NULL) { +- talloc_free(dberr); +- return NULL; +- } ++ va_start(ap, fmt); ++ error = sbus_error_new_va(mem_ctx, dbus_error_name, fmt, ap); ++ va_end(ap); ++ ++ return error; ++} ++ ++void sbus_request_reply_error(struct sbus_request *sbus_req, ++ const char *error_name, ++ const char *fmt, ++ ...) ++{ ++ DBusError *error; ++ va_list ap; ++ ++ va_start(ap, fmt); ++ error = sbus_error_new_va(sbus_req, error_name, fmt, ap); ++ va_end(ap); ++ ++ if (error == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unable to create D-Bus error, killing request!\n"); ++ talloc_free(sbus_req); ++ return; + } + +- dbus_error_init(dberr); +- dbus_set_error_const(dberr, dbus_err_name, err_msg_dup); +- return dberr; ++ sbus_request_fail_and_finish(sbus_req, error); + } + + struct array_arg { +-- +2.4.11 + diff --git a/SOURCES/0093-DEBUG-Add-new-debug-category-for-fail-over.patch b/SOURCES/0093-DEBUG-Add-new-debug-category-for-fail-over.patch deleted file mode 100644 index 6e4651f..0000000 --- a/SOURCES/0093-DEBUG-Add-new-debug-category-for-fail-over.patch +++ /dev/null @@ -1,129 +0,0 @@ -From ac77db34a46e36f42e917f1b6d66fee39234d5f8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20=C5=BDidek?= -Date: Mon, 10 Aug 2015 18:35:16 +0200 -Subject: [PATCH 93/96] DEBUG: Add new debug category for fail over. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Lukáš Slebodník -(cherry picked from commit c4fb8f55f2894de431478ccfec63f9a97e090d0e) ---- - src/providers/data_provider_fo.c | 30 ++++++++++++++++++++++++++---- - src/providers/dp_backend.h | 15 +++++++++++---- - src/tests/debug-tests.c | 2 +- - src/util/debug.c | 2 +- - src/util/util.h | 1 + - 5 files changed, 40 insertions(+), 10 deletions(-) - -diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c -index dab796d4647a552c2fd1c626c490278de91c2e81..41d70de065260f31dcea4c2b664a1f436823ccc1 100644 ---- a/src/providers/data_provider_fo.c -+++ b/src/providers/data_provider_fo.c -@@ -743,13 +743,35 @@ void reset_fo(struct be_ctx *be_ctx) - fo_reset_services(be_ctx->be_fo->fo_ctx); - } - --void be_fo_set_port_status(struct be_ctx *ctx, -- const char *service_name, -- struct fo_server *server, -- enum port_status status) -+void _be_fo_set_port_status(struct be_ctx *ctx, -+ const char *service_name, -+ struct fo_server *server, -+ enum port_status status, -+ int line, -+ const char *file, -+ const char *function) - { - struct be_svc_data *be_svc; - -+ /* Print debug info */ -+ switch (status) { -+ case PORT_NEUTRAL: -+ DEBUG(SSSDBG_BE_FO, -+ "Setting status: PORT_NEUTRAL. Called from: %s: %s: %d\n", -+ file, function, line); -+ break; -+ case PORT_WORKING: -+ DEBUG(SSSDBG_BE_FO, -+ "Setting status: PORT_WORKING. Called from: %s: %s: %d\n", -+ file, function, line); -+ break; -+ case PORT_NOT_WORKING: -+ DEBUG(SSSDBG_BE_FO, -+ "Setting status: PORT_NOT_WORKING. Called from: %s: %s: %d\n", -+ file, function, line); -+ break; -+ } -+ - be_svc = be_fo_find_svc_data(ctx, service_name); - if (be_svc == NULL) { - DEBUG(SSSDBG_OP_FAILURE, -diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h -index 4d54bf547682379bcb8cf855b8fae39214495728..4bffcee9e8739302343b7813d3540eb43e966581 100644 ---- a/src/providers/dp_backend.h -+++ b/src/providers/dp_backend.h -@@ -260,10 +260,17 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx, - bool first_try); - int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv); - --void be_fo_set_port_status(struct be_ctx *ctx, -- const char *service_name, -- struct fo_server *server, -- enum port_status status); -+#define be_fo_set_port_status(ctx, service_name, server, status) \ -+ _be_fo_set_port_status(ctx, service_name, server, status, \ -+ __LINE__, __FILE__, __FUNCTION__) -+ -+void _be_fo_set_port_status(struct be_ctx *ctx, -+ const char *service_name, -+ struct fo_server *server, -+ enum port_status status, -+ int line, -+ const char *file, -+ const char *function); - - /* - * Instruct fail-over to try next server on the next connect attempt. -diff --git a/src/tests/debug-tests.c b/src/tests/debug-tests.c -index 2b91c149d79483316794240498e7fe33545dede0..067209b1dda1c445b971bcec7108d0b886d55e53 100644 ---- a/src/tests/debug-tests.c -+++ b/src/tests/debug-tests.c -@@ -48,7 +48,7 @@ START_TEST(test_debug_convert_old_level_old_format) - SSSDBG_TRACE_FUNC, - SSSDBG_TRACE_LIBS, - SSSDBG_TRACE_INTERNAL, -- SSSDBG_TRACE_ALL -+ SSSDBG_TRACE_ALL | SSSDBG_BE_FO - }; - - for (old_level = 0; old_level <= 9; old_level++) { -diff --git a/src/util/debug.c b/src/util/debug.c -index bf83624c98769c4c53d9c25522712a9705b26ed2..69df54386101973548108c3194a1bfd111f046f0 100644 ---- a/src/util/debug.c -+++ b/src/util/debug.c -@@ -114,7 +114,7 @@ int debug_convert_old_level(int old_level) - new_level |= SSSDBG_TRACE_INTERNAL; - - if (old_level >= 9) -- new_level |= SSSDBG_TRACE_ALL; -+ new_level |= SSSDBG_TRACE_ALL | SSSDBG_BE_FO; - - return new_level; - } -diff --git a/src/util/util.h b/src/util/util.h -index 4655e90a89b0ff3c457b80c943aefc4d6cf8e21f..f9fe1ca7189c6b2cdcb29f143005b20a2d969fee 100644 ---- a/src/util/util.h -+++ b/src/util/util.h -@@ -92,6 +92,7 @@ int get_fd_from_debug_file(void); - #define SSSDBG_TRACE_LIBS 0x1000 /* level 7 */ - #define SSSDBG_TRACE_INTERNAL 0x2000 /* level 8 */ - #define SSSDBG_TRACE_ALL 0x4000 /* level 9 */ -+#define SSSDBG_BE_FO 0x8000 /* level 9 */ - #define SSSDBG_IMPORTANT_INFO SSSDBG_OP_FAILURE - - #define SSSDBG_INVALID -1 --- -2.4.3 - diff --git a/SOURCES/0093-sbus-add-utility-function-to-simplify-message-and-re.patch b/SOURCES/0093-sbus-add-utility-function-to-simplify-message-and-re.patch new file mode 100644 index 0000000..561fd47 --- /dev/null +++ b/SOURCES/0093-sbus-add-utility-function-to-simplify-message-and-re.patch @@ -0,0 +1,624 @@ +From 420e47f6a0e173e774faa426d172c6e2160b8302 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 29 Jun 2016 12:35:59 +0200 +Subject: [PATCH 093/102] sbus: add utility function to simplify message and + reply handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds the ability to hook DBusMessage to a talloc context +to remove the need of calling dbus_message_unref(). It also provides +an automatical way to detect error in a reply so the caller does +not need to parse it manually and the whole code around DBusError +can be avoided. + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit 439e08cdc5c83b3e5835cb0435983f1da2ffbaf1) +--- + Makefile.am | 2 + + src/responder/common/data_provider/rdp_message.c | 85 ++------- + src/sbus/sssd_dbus.h | 2 + + src/sbus/sssd_dbus_utils.c | 226 +++++++++++++++++++++++ + src/sbus/sssd_dbus_utils.h | 64 +++++++ + src/tools/sssctl/sssctl_domains.c | 32 +--- + 6 files changed, 313 insertions(+), 98 deletions(-) + create mode 100644 src/sbus/sssd_dbus_utils.c + create mode 100644 src/sbus/sssd_dbus_utils.h + +diff --git a/Makefile.am b/Makefile.am +index ee9b48c666a44781b582ba5d83102b705e898f29..1837e36da7302cb51c0b90e51b762ce0a87cd65f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -634,6 +634,7 @@ dist_noinst_HEADERS = \ + src/sbus/sssd_dbus_private.h \ + src/sbus/sssd_dbus_invokers.h \ + src/sbus/sssd_dbus_errors.h \ ++ src/sbus/sssd_dbus_utils.h \ + src/db/sysdb.h \ + src/db/sysdb_sudo.h \ + src/db/sysdb_autofs.h \ +@@ -915,6 +916,7 @@ libsss_util_la_SOURCES = \ + src/sbus/sssd_dbus_server.c \ + src/sbus/sssd_dbus_signals.c \ + src/sbus/sssd_dbus_common_signals.c \ ++ src/sbus/sssd_dbus_utils.c \ + src/util/util.c \ + src/util/memory.c \ + src/util/safe-format-string.c \ +diff --git a/src/responder/common/data_provider/rdp_message.c b/src/responder/common/data_provider/rdp_message.c +index e226401567e4a1b2b9784a9aba21540ff5f0bc8d..6ad2ba056e992cd89b87b478d422d1a4259a12d9 100644 +--- a/src/responder/common/data_provider/rdp_message.c ++++ b/src/responder/common/data_provider/rdp_message.c +@@ -26,33 +26,6 @@ + #include "sbus/sssd_dbus_errors.h" + #include "util/util.h" + +-static errno_t rdp_error_to_errno(DBusError *error) +-{ +- static struct { +- const char *name; +- errno_t ret; +- } list[] = {{SBUS_ERROR_INTERNAL, ERR_INTERNAL}, +- {SBUS_ERROR_NOT_FOUND, ENOENT}, +- {SBUS_ERROR_DP_FATAL, ERR_TERMINATED}, +- {SBUS_ERROR_DP_OFFLINE, ERR_OFFLINE}, +- {SBUS_ERROR_DP_NOTSUP, ENOTSUP}, +- {NULL, ERR_INTERNAL} +- }; +- int i; +- +- if (!dbus_error_is_set(error)) { +- return EOK; +- } +- +- for (i = 0; list[i].name != NULL; i ++) { +- if (dbus_error_has_name(error, list[i].name)) { +- return list[i].ret; +- } +- } +- +- return EIO; +-} +- + static errno_t + rdp_message_send_internal(struct resp_ctx *rctx, + struct sss_domain_info *domain, +@@ -110,7 +83,8 @@ done: + return ret; + } + +-static errno_t rdp_process_pending_call(DBusPendingCall *pending, ++static errno_t rdp_process_pending_call(TALLOC_CTX *mem_ctx, ++ DBusPendingCall *pending, + DBusMessage **_reply) + { + DBusMessage *reply; +@@ -130,6 +104,11 @@ static errno_t rdp_process_pending_call(DBusPendingCall *pending, + goto done; + } + ++ ret = sbus_talloc_bound_message(mem_ctx, reply); ++ if (ret != EOK) { ++ return ret; ++ } ++ + switch (dbus_message_get_type(reply)) { + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + DEBUG(SSSDBG_TRACE_FUNC, "DP Success\n"); +@@ -146,10 +125,9 @@ static errno_t rdp_process_pending_call(DBusPendingCall *pending, + + DEBUG(SSSDBG_CRIT_FAILURE, "DP Error [%s]: %s\n", + error.name, (error.message == NULL ? "(null)" : error.message)); +- ret = rdp_error_to_errno(&error); ++ ret = sbus_error_to_errno(&error); + break; + default: +- dbus_message_unref(reply); + DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected type?\n"); + ret = ERR_INTERNAL; + goto done; +@@ -168,15 +146,6 @@ struct rdp_message_state { + struct DBusMessage *reply; + }; + +-static int rdp_message_state_destructor(struct rdp_message_state *state) +-{ +- if (state->reply != NULL) { +- dbus_message_unref(state->reply); +- } +- +- return 0; +-} +- + static void rdp_message_done(DBusPendingCall *pending, void *ptr); + + struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx, +@@ -199,8 +168,6 @@ struct tevent_req *_rdp_message_send(TALLOC_CTX *mem_ctx, + return NULL; + } + +- talloc_set_destructor(state, rdp_message_state_destructor); +- + va_start(va, first_arg_type); + ret = rdp_message_send_internal(rctx, domain, rdp_message_done, req, + path, iface, method, first_arg_type, va); +@@ -233,14 +200,8 @@ static void rdp_message_done(DBusPendingCall *pending, void *ptr) + req = talloc_get_type(ptr, struct tevent_req); + state = tevent_req_data(req, struct rdp_message_state); + +- ret = rdp_process_pending_call(pending, &state->reply); ++ ret = rdp_process_pending_call(state, pending, &state->reply); + if (ret != EOK) { +- if (state->reply != NULL) { +- dbus_message_unref(state->reply); +- } +- +- state->reply = NULL; +- + tevent_req_error(req, ret); + return; + } +@@ -253,35 +214,17 @@ errno_t _rdp_message_recv(struct tevent_req *req, + ...) + { + struct rdp_message_state *state; +- DBusError error; +- dbus_bool_t bret; + errno_t ret; + va_list va; + + TEVENT_REQ_RETURN_ON_ERROR(req); + + state = tevent_req_data(req, struct rdp_message_state); +- dbus_error_init(&error); + + va_start(va, first_arg_type); +- bret = dbus_message_get_args_valist(state->reply, &error, first_arg_type, va); ++ ret = sbus_parse_message_valist(state->reply, false, first_arg_type, va); + va_end(va); + +- if (bret == false) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse reply\n"); +- ret = EIO; +- goto done; +- } +- +- ret = rdp_error_to_errno(&error); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse message [%s]: %s\n", +- error.name, error.message); +- goto done; +- } +- +-done: +- dbus_error_free(&error); + return ret; + } + +@@ -317,7 +260,7 @@ static void rdp_message_send_and_reply_done(DBusPendingCall *pending, + void *ptr) + { + struct sbus_request *sbus_req; +- DBusMessage *reply = NULL; ++ DBusMessage *reply; + dbus_uint32_t serial; + const char *sender; + dbus_bool_t dbret; +@@ -325,7 +268,7 @@ static void rdp_message_send_and_reply_done(DBusPendingCall *pending, + + sbus_req = talloc_get_type(ptr, struct sbus_request); + +- ret = rdp_process_pending_call(pending, &reply); ++ ret = rdp_process_pending_call(sbus_req, pending, &reply); + if (reply == NULL) { + /* Something bad happened. Just kill the request. */ + ret = EIO; +@@ -358,10 +301,6 @@ static void rdp_message_send_and_reply_done(DBusPendingCall *pending, + ret = EOK; + + done: +- if (reply != NULL) { +- dbus_message_unref(reply); +- } +- + if (ret != EOK) { + /* Something bad happend, just kill the request. */ + talloc_free(sbus_req); +diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h +index c0aedf36b496bfda05dcde921ea7060efb4cc91f..15e3b117e1a467f4e250cdf4ba8fd0326e4d380e 100644 +--- a/src/sbus/sssd_dbus.h ++++ b/src/sbus/sssd_dbus.h +@@ -29,6 +29,8 @@ struct sbus_request; + #include + #include + #include "util/util.h" ++#include "sbus/sssd_dbus_errors.h" ++#include "sbus/sssd_dbus_utils.h" + + /* Older platforms (such as RHEL-6) might not have these error constants + * defined */ +diff --git a/src/sbus/sssd_dbus_utils.c b/src/sbus/sssd_dbus_utils.c +new file mode 100644 +index 0000000000000000000000000000000000000000..4c33f9fd75cac2d4a56a5638982f8ecb73da8e2e +--- /dev/null ++++ b/src/sbus/sssd_dbus_utils.c +@@ -0,0 +1,226 @@ ++/* ++ Authors: ++ Pavel Březina ++ ++ Copyright (C) 2016 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 "sbus/sssd_dbus.h" ++#include "util/util.h" ++ ++struct sbus_talloc_msg { ++ DBusMessage *msg; ++}; ++ ++static int sbus_talloc_msg_destructor(struct sbus_talloc_msg *talloc_msg) ++{ ++ if (talloc_msg->msg == NULL) { ++ return 0; ++ } ++ ++ dbus_message_unref(talloc_msg->msg); ++ return 0; ++} ++ ++errno_t sbus_talloc_bound_message(TALLOC_CTX *mem_ctx, DBusMessage *msg) ++{ ++ struct sbus_talloc_msg *talloc_msg; ++ ++ talloc_msg = talloc(mem_ctx, struct sbus_talloc_msg); ++ if (talloc_msg == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unable to bound D-Bus message with talloc context!\n"); ++ return ENOMEM; ++ } ++ ++ talloc_msg->msg = msg; ++ ++ talloc_set_destructor(talloc_msg, sbus_talloc_msg_destructor); ++ ++ return EOK; ++} ++ ++errno_t sbus_error_to_errno(DBusError *error) ++{ ++ static struct { ++ const char *name; ++ errno_t ret; ++ } list[] = { { SBUS_ERROR_INTERNAL, ERR_INTERNAL }, ++ { SBUS_ERROR_NOT_FOUND, ENOENT }, ++ { SBUS_ERROR_UNKNOWN_DOMAIN, ERR_DOMAIN_NOT_FOUND }, ++ { SBUS_ERROR_DP_FATAL, ERR_TERMINATED }, ++ { SBUS_ERROR_DP_OFFLINE, ERR_OFFLINE }, ++ { SBUS_ERROR_DP_NOTSUP, ENOTSUP }, ++ { NULL, ERR_INTERNAL } }; ++ int i; ++ ++ if (!dbus_error_is_set(error)) { ++ return EOK; ++ } ++ ++ for (i = 0; list[i].name != NULL; i++) { ++ if (dbus_error_has_name(error, list[i].name)) { ++ return list[i].ret; ++ } ++ } ++ ++ return EIO; ++} ++ ++errno_t sbus_check_reply(DBusMessage *reply) ++{ ++ dbus_bool_t bret; ++ DBusError error; ++ errno_t ret; ++ ++ dbus_error_init(&error); ++ ++ switch (dbus_message_get_type(reply)) { ++ case DBUS_MESSAGE_TYPE_METHOD_RETURN: ++ ret = EOK; ++ goto done; ++ ++ case DBUS_MESSAGE_TYPE_ERROR: ++ bret = dbus_set_error_from_message(&error, reply); ++ if (bret == false) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read error from message\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ DEBUG(SSSDBG_CRIT_FAILURE, "D-Bus error [%s]: %s\n", ++ error.name, (error.message == NULL ? "(null)" : error.message)); ++ ret = sbus_error_to_errno(&error); ++ goto done; ++ default: ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected D-Bus message type?\n"); ++ ret = ERR_INTERNAL; ++ goto done; ++ } ++ ++done: ++ dbus_error_free(&error); ++ ++ return ret; ++} ++ ++DBusMessage *sbus_create_message_valist(TALLOC_CTX *mem_ctx, ++ const char *bus, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ va_list va) ++{ ++ DBusMessage *msg; ++ dbus_bool_t bret; ++ errno_t ret; ++ ++ msg = dbus_message_new_method_call(bus, path, iface, method); ++ if (msg == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create message\n"); ++ return NULL; ++ } ++ ++ bret = dbus_message_append_args_valist(msg, first_arg_type, va); ++ if (!bret) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = sbus_talloc_bound_message(mem_ctx, msg); ++ ++done: ++ if (ret != EOK) { ++ dbus_message_unref(msg); ++ } ++ ++ return msg; ++} ++ ++DBusMessage *_sbus_create_message(TALLOC_CTX *mem_ctx, ++ const char *bus, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ ...) ++{ ++ DBusMessage *msg; ++ va_list va; ++ ++ va_start(va, first_arg_type); ++ msg = sbus_create_message_valist(mem_ctx, bus, path, iface, method, ++ first_arg_type, va); ++ va_end(va); ++ ++ return msg; ++} ++ ++errno_t sbus_parse_message_valist(DBusMessage *msg, ++ bool check_reply, ++ int first_arg_type, ++ va_list va) ++{ ++ DBusError error; ++ dbus_bool_t bret; ++ errno_t ret; ++ ++ if (check_reply) { ++ ret = sbus_check_reply(msg); ++ if (ret != EOK) { ++ return ret; ++ } ++ } ++ ++ dbus_error_init(&error); ++ ++ bret = dbus_message_get_args_valist(msg, &error, first_arg_type, va); ++ if (bret == false) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse D-Bus message\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = sbus_error_to_errno(&error); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse D-Bus message [%s]: %s\n", ++ error.name, error.message); ++ goto done; ++ } ++ ++done: ++ dbus_error_free(&error); ++ return ret; ++} ++ ++errno_t _sbus_parse_message(DBusMessage *msg, ++ bool check_reply, ++ int first_arg_type, ++ ...) ++{ ++ errno_t ret; ++ va_list va; ++ ++ va_start(va, first_arg_type); ++ ret = sbus_parse_message_valist(msg, check_reply, first_arg_type, va); ++ va_end(va); ++ ++ return ret; ++} +diff --git a/src/sbus/sssd_dbus_utils.h b/src/sbus/sssd_dbus_utils.h +new file mode 100644 +index 0000000000000000000000000000000000000000..74c21fb7930c7f5f5417b6a2587cf691b1bc0b19 +--- /dev/null ++++ b/src/sbus/sssd_dbus_utils.h +@@ -0,0 +1,64 @@ ++/* ++ Authors: ++ Pavel Březina ++ ++ Copyright (C) 2016 Red Hat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#ifndef SSSD_DBUS_UTILS_H_ ++#define SSSD_DBUS_UTILS_H_ ++ ++errno_t sbus_talloc_bound_message(TALLOC_CTX *mem_ctx, DBusMessage *msg); ++errno_t sbus_error_to_errno(DBusError *error); ++errno_t sbus_check_reply(DBusMessage *reply); ++ ++DBusMessage *sbus_create_message_valist(TALLOC_CTX *mem_ctx, ++ const char *bus, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ va_list va); ++ ++DBusMessage *_sbus_create_message(TALLOC_CTX *mem_ctx, ++ const char *bus, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ ...); ++ ++#define sbus_create_message(mem_ctx, bus, path, iface, method, ...) \ ++ _sbus_create_message(mem_ctx, bus, path, iface, method, \ ++ ##__VA_ARGS__, DBUS_TYPE_INVALID) ++ ++errno_t sbus_parse_message_valist(DBusMessage *msg, ++ bool check_reply, ++ int first_arg_type, ++ va_list va); ++ ++errno_t _sbus_parse_message(DBusMessage *msg, ++ bool check_reply, ++ int first_arg_type, ++ ...); ++ ++#define sbus_parse_message(msg, ...) \ ++ _sbus_parse_message(msg, false, ##__VA_ARGS__, DBUS_TYPE_INVALID) ++ ++#define sbus_parse_reply(msg, ...) \ ++ _sbus_parse_message(msg, true, ##__VA_ARGS__, DBUS_TYPE_INVALID) ++ ++#endif /* SSSD_DBUS_UTILS_H_ */ +diff --git a/src/tools/sssctl/sssctl_domains.c b/src/tools/sssctl/sssctl_domains.c +index cfc4e56133213e27496350033d4d28c3f5b5c63d..17ad670f39dfc045ba090210ffcfa77df713c306 100644 +--- a/src/tools/sssctl/sssctl_domains.c ++++ b/src/tools/sssctl/sssctl_domains.c +@@ -79,15 +79,11 @@ static errno_t sssctl_domain_status_online(struct sss_tool_ctx *tool_ctx, + { + sss_sifp_ctx *sifp; + sss_sifp_error sifp_error; +- DBusError dbus_error; + DBusMessage *reply = NULL; +- DBusMessage *msg = NULL; ++ DBusMessage *msg; + bool is_online; +- dbus_bool_t dbret; + errno_t ret; + +- dbus_error_init(&dbus_error); +- + if (!sssctl_start_sssd(force_start)) { + ret = ERR_SSSD_NOT_RUNNING; + goto done; +@@ -100,16 +96,15 @@ static errno_t sssctl_domain_status_online(struct sss_tool_ctx *tool_ctx, + goto done; + } + +- +- msg = sss_sifp_create_message(domain_path, IFACE_IFP_DOMAINS_DOMAIN, +- IFACE_IFP_DOMAINS_DOMAIN_ISONLINE); ++ msg = sbus_create_message(tool_ctx, SSS_SIFP_ADDRESS, domain_path, ++ IFACE_IFP_DOMAINS_DOMAIN, ++ IFACE_IFP_DOMAINS_DOMAIN_ISONLINE); + if (msg == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create D-Bus message\n"); + ret = ENOMEM; + goto done; + } + +- + sifp_error = sss_sifp_send_message(sifp, msg, &reply); + if (sifp_error != SSS_SIFP_OK) { + sssctl_sifp_error(sifp, sifp_error, "Unable to get online status"); +@@ -117,16 +112,9 @@ static errno_t sssctl_domain_status_online(struct sss_tool_ctx *tool_ctx, + goto done; + } + +- dbret = dbus_message_get_args(reply, &dbus_error, +- DBUS_TYPE_BOOLEAN, &is_online, +- DBUS_TYPE_INVALID); +- if (!dbret) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse D-Bus reply\n"); +- if (dbus_error_is_set(&dbus_error)) { +- DEBUG(SSSDBG_CRIT_FAILURE, "%s: %s\n", +- dbus_error.name, dbus_error.message); +- } +- ret = EIO; ++ ret = sbus_parse_reply(reply, DBUS_TYPE_BOOLEAN, &is_online); ++ if (ret != EOK) { ++ fprintf(stderr, _("Unable to get information from SSSD\n")); + goto done; + } + +@@ -135,16 +123,10 @@ static errno_t sssctl_domain_status_online(struct sss_tool_ctx *tool_ctx, + ret = EOK; + + done: +- if (msg != NULL) { +- dbus_message_unref(msg); +- } +- + if (reply != NULL) { + dbus_message_unref(reply); + } + +- dbus_error_free(&dbus_error); +- + return ret; + } + +-- +2.4.11 + diff --git a/SOURCES/0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch b/SOURCES/0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch deleted file mode 100644 index dfe3da8..0000000 --- a/SOURCES/0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 3551dd5c2c2c75ce68ef95b91fc2420f17c92b92 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 21 Sep 2015 12:31:18 +0200 -Subject: [PATCH 94/96] FO: Add an API to reset all servers in a single service - -Required for: - https://fedorahosted.org/sssd/ticket/2639 - -Previously, we had a function that allowed the caller to reset the -status of all services in the global fail over context. This patch adds -a new function that allows the caller to reset a single service instead. - -The main user would be IPA subdomain provider that might need to reset -the status of an AD trusted domain on demand. - -Reviewed-by: Sumit Bose -(cherry picked from commit 3ac3b5746f08970c109664b95340c556057e3c6a) ---- - src/providers/data_provider_fo.c | 19 +++++++++++++++++++ - src/providers/dp_backend.h | 1 + - src/providers/fail_over.c | 30 ++++++++++++++++++++---------- - src/providers/fail_over.h | 2 ++ - 4 files changed, 42 insertions(+), 10 deletions(-) - -diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c -index 41d70de065260f31dcea4c2b664a1f436823ccc1..cd57340a0ba0ac7e474dc502bf1f1b4de0e1f778 100644 ---- a/src/providers/data_provider_fo.c -+++ b/src/providers/data_provider_fo.c -@@ -743,6 +743,25 @@ void reset_fo(struct be_ctx *be_ctx) - fo_reset_services(be_ctx->be_fo->fo_ctx); - } - -+void be_fo_reset_svc(struct be_ctx *be_ctx, -+ const char *svc_name) -+{ -+ struct fo_service *service; -+ int ret; -+ -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Resetting all servers in service %s\n", svc_name); -+ -+ ret = fo_get_service(be_ctx->be_fo->fo_ctx, svc_name, &service); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot retrieve service [%s]\n", svc_name); -+ return; -+ } -+ -+ fo_reset_servers(service); -+} -+ - void _be_fo_set_port_status(struct be_ctx *ctx, - const char *service_name, - struct fo_server *server, -diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h -index 4bffcee9e8739302343b7813d3540eb43e966581..0ced851be8468ce21a9d283e26461fc47194557e 100644 ---- a/src/providers/dp_backend.h -+++ b/src/providers/dp_backend.h -@@ -283,6 +283,7 @@ int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx, - const char *service_name); - - void reset_fo(struct be_ctx *be_ctx); -+void be_fo_reset_svc(struct be_ctx *be_ctx, const char *svc_name); - - errno_t be_res_init(struct be_ctx *ctx); - -diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c -index 6d835ae0efdfdf96532e8458e12238ba17910a4f..562f0b3fd7870387a80c889b245cda0d39dea509 100644 ---- a/src/providers/fail_over.c -+++ b/src/providers/fail_over.c -@@ -1547,21 +1547,31 @@ time_t fo_get_service_retry_timeout(struct fo_service *svc) - return svc->ctx->opts->retry_timeout; - } - -+void fo_reset_servers(struct fo_service *service) -+{ -+ struct fo_server *server; -+ -+ DLIST_FOR_EACH(server, service->server_list) { -+ if (server->srv_data != NULL) { -+ set_srv_data_status(server->srv_data, SRV_NEUTRAL); -+ } else { -+ fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED); -+ } -+ -+ fo_set_port_status(server, PORT_NEUTRAL); -+ } -+} -+ -+ - void fo_reset_services(struct fo_ctx *fo_ctx) - { - struct fo_service *service; -- struct fo_server *server; -+ -+ DEBUG(SSSDBG_TRACE_LIBS, -+ "Resetting all servers in all services\n"); - - DLIST_FOR_EACH(service, fo_ctx->service_list) { -- DLIST_FOR_EACH(server, service->server_list) { -- if (server->srv_data != NULL) { -- set_srv_data_status(server->srv_data, SRV_NEUTRAL); -- } else { -- fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED); -- } -- -- fo_set_port_status(server, PORT_NEUTRAL); -- } -+ fo_reset_servers(service); - } - } - -diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h -index d44ad2ff145dc6b3617e6f2ea665c7d82d923ddb..e49c6414a14eb6ca2cad333f8efbb58576811345 100644 ---- a/src/providers/fail_over.h -+++ b/src/providers/fail_over.h -@@ -198,6 +198,8 @@ time_t fo_get_service_retry_timeout(struct fo_service *svc); - - void fo_reset_services(struct fo_ctx *fo_ctx); - -+void fo_reset_servers(struct fo_service *svc); -+ - bool fo_svc_has_server(struct fo_service *service, struct fo_server *server); - - /* --- -2.4.3 - diff --git a/SOURCES/0094-sssctl-use-talloc-with-sifp.patch b/SOURCES/0094-sssctl-use-talloc-with-sifp.patch new file mode 100644 index 0000000..4417086 --- /dev/null +++ b/SOURCES/0094-sssctl-use-talloc-with-sifp.patch @@ -0,0 +1,215 @@ +From bb8653ba6ba4eddb7faeddd9ceb3349107f77fd9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 29 Jun 2016 14:03:38 +0200 +Subject: [PATCH 094/102] sssctl: use talloc with sifp +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This way we completely move D-Bus memory management to talloc and +we reduce number of code lines needed to send and receive reply. + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit 9b74009c1260e6f3b1031a6ae110bf1d957cba81) +--- + src/tools/sssctl/sssctl.h | 14 +++++++++ + src/tools/sssctl/sssctl_domains.c | 62 ++++++++++++++++++--------------------- + src/tools/sssctl/sssctl_sifp.c | 46 +++++++++++++++++++++++++++++ + 3 files changed, 88 insertions(+), 34 deletions(-) + +diff --git a/src/tools/sssctl/sssctl.h b/src/tools/sssctl/sssctl.h +index 72930ee5c3a1195e90c6e35768f715cbf6a1c4e1..d4e3359b0b160d12a0c2699f754989a24b2b336a 100644 +--- a/src/tools/sssctl/sssctl.h ++++ b/src/tools/sssctl/sssctl.h +@@ -24,6 +24,7 @@ + #include "lib/sifp/sss_sifp.h" + #include "lib/sifp/sss_sifp_dbus.h" + #include "tools/common/sss_tools.h" ++#include "sbus/sssd_dbus.h" + + enum sssctl_prompt_result { + SSSCTL_PROMPT_YES, +@@ -56,6 +57,19 @@ void _sssctl_sifp_error(sss_sifp_ctx *sifp, + #define sssctl_sifp_error(sifp, error, message) \ + _sssctl_sifp_error(sifp, error, _(message)) + ++sss_sifp_error _sssctl_sifp_send(TALLOC_CTX *mem_ctx, ++ sss_sifp_ctx *sifp, ++ DBusMessage **_reply, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ ...); ++ ++#define sssctl_sifp_send(mem_ctx, sifp, reply, path, iface, method, ...) \ ++ _sssctl_sifp_send(mem_ctx, sifp, reply, path, iface, method, \ ++ ##__VA_ARGS__, DBUS_TYPE_INVALID); ++ + errno_t sssctl_domain_list(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt); +diff --git a/src/tools/sssctl/sssctl_domains.c b/src/tools/sssctl/sssctl_domains.c +index 17ad670f39dfc045ba090210ffcfa77df713c306..40962792b84eabeb2c142f158184b17180a01669 100644 +--- a/src/tools/sssctl/sssctl_domains.c ++++ b/src/tools/sssctl/sssctl_domains.c +@@ -74,47 +74,32 @@ errno_t sssctl_domain_list(struct sss_cmdline *cmdline, + } + + static errno_t sssctl_domain_status_online(struct sss_tool_ctx *tool_ctx, +- const char *domain_path, +- bool force_start) ++ sss_sifp_ctx *sifp, ++ const char *domain_path) + { +- sss_sifp_ctx *sifp; +- sss_sifp_error sifp_error; +- DBusMessage *reply = NULL; +- DBusMessage *msg; ++ TALLOC_CTX *tmp_ctx; ++ sss_sifp_error error; ++ DBusMessage *reply; + bool is_online; + errno_t ret; + +- if (!sssctl_start_sssd(force_start)) { +- ret = ERR_SSSD_NOT_RUNNING; +- goto done; ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); ++ return ENOMEM; + } + +- sifp_error = sssctl_sifp_init(tool_ctx, &sifp); +- if (sifp_error != SSS_SIFP_OK) { +- sssctl_sifp_error(sifp, sifp_error, "Unable to connect to the InfoPipe"); +- ret = EFAULT; +- goto done; +- } +- +- msg = sbus_create_message(tool_ctx, SSS_SIFP_ADDRESS, domain_path, +- IFACE_IFP_DOMAINS_DOMAIN, +- IFACE_IFP_DOMAINS_DOMAIN_ISONLINE); +- if (msg == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create D-Bus message\n"); +- ret = ENOMEM; +- goto done; +- } +- +- sifp_error = sss_sifp_send_message(sifp, msg, &reply); +- if (sifp_error != SSS_SIFP_OK) { +- sssctl_sifp_error(sifp, sifp_error, "Unable to get online status"); ++ error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, ++ IFACE_IFP_DOMAINS_DOMAIN, ++ IFACE_IFP_DOMAINS_DOMAIN_ISONLINE); ++ if (error != SSS_SIFP_OK) { ++ sssctl_sifp_error(sifp, error, "Unable to get online status"); + ret = EIO; + goto done; + } + + ret = sbus_parse_reply(reply, DBUS_TYPE_BOOLEAN, &is_online); + if (ret != EOK) { +- fprintf(stderr, _("Unable to get information from SSSD\n")); + goto done; + } + +@@ -123,10 +108,7 @@ static errno_t sssctl_domain_status_online(struct sss_tool_ctx *tool_ctx, + ret = EOK; + + done: +- if (reply != NULL) { +- dbus_message_unref(reply); +- } +- ++ talloc_free(tmp_ctx); + return ret; + } + +@@ -144,6 +126,8 @@ errno_t sssctl_domain_status(struct sss_cmdline *cmdline, + void *pvt) + { + struct sssctl_domain_status_opts opts = {0}; ++ sss_sifp_ctx *sifp; ++ sss_sifp_error error; + const char *path; + bool opt_set; + errno_t ret; +@@ -181,7 +165,17 @@ errno_t sssctl_domain_status(struct sss_cmdline *cmdline, + return ENOMEM; + } + +- ret = sssctl_domain_status_online(tool_ctx, path, opts.force_start); ++ if (!sssctl_start_sssd(opts.force_start)) { ++ return ERR_SSSD_NOT_RUNNING; ++ } ++ ++ error = sssctl_sifp_init(tool_ctx, &sifp); ++ if (error != SSS_SIFP_OK) { ++ sssctl_sifp_error(sifp, error, "Unable to connect to the InfoPipe"); ++ return EFAULT; ++ } ++ ++ ret = sssctl_domain_status_online(tool_ctx, sifp, path); + if (ret != EOK) { + fprintf(stderr, _("Unable to get online status\n")); + return ret; +diff --git a/src/tools/sssctl/sssctl_sifp.c b/src/tools/sssctl/sssctl_sifp.c +index e541c4b27ba38e50b209b0957c8b38f03afc891a..782a72d7ce8bbf1080c6d6ac988ffac2f432955f 100644 +--- a/src/tools/sssctl/sssctl_sifp.c ++++ b/src/tools/sssctl/sssctl_sifp.c +@@ -116,3 +116,49 @@ void _sssctl_sifp_error(sss_sifp_ctx *sifp, + break; + } + } ++ ++sss_sifp_error _sssctl_sifp_send(TALLOC_CTX *mem_ctx, ++ sss_sifp_ctx *sifp, ++ DBusMessage **_reply, ++ const char *path, ++ const char *iface, ++ const char *method, ++ int first_arg_type, ++ ...) ++{ ++ sss_sifp_error error; ++ DBusMessage *msg; ++ dbus_bool_t bret; ++ errno_t ret; ++ va_list va; ++ ++ msg = sss_sifp_create_message(path, iface, method); ++ if (msg == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create D-Bus message\n"); ++ return SSS_SIFP_OUT_OF_MEMORY; ++ } ++ ++ va_start(va, first_arg_type); ++ bret = dbus_message_append_args_valist(msg, first_arg_type, va); ++ va_end(va); ++ if (!bret) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n"); ++ error = SSS_SIFP_OUT_OF_MEMORY; ++ goto done; ++ } ++ ++ error = sss_sifp_send_message(sifp, msg, _reply); ++ if (error != SSS_SIFP_OK) { ++ goto done; ++ } ++ ++ ret = sbus_talloc_bound_message(mem_ctx, *_reply); ++ if (ret != EOK) { ++ error = SSS_SIFP_OUT_OF_MEMORY; ++ goto done; ++ } ++ ++done: ++ dbus_message_unref(msg); ++ return error; ++} +-- +2.4.11 + diff --git a/SOURCES/0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch b/SOURCES/0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch deleted file mode 100644 index ea5b245..0000000 --- a/SOURCES/0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch +++ /dev/null @@ -1,426 +0,0 @@ -From 1f861441042380362345d8ce3f9e81151664c6c0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 21 Sep 2015 12:31:38 +0200 -Subject: [PATCH 95/96] FO: Also reset the server common data in addition to - SRV - -In a server that is expanded from a SRV query was reset, only it's -'meta-server' status was set to neutral, but the server->common -structure still retained its not_working status. - -This patch also resets the status of the common structure so that both -the SRV query and resolving the server are retried next time. - -Reviewed-by: Sumit Bose -(cherry picked from commit 6ac6e8f83da241458742b7f8a3406ed66bded292) ---- - src/providers/fail_over.c | 4 +- - src/tests/cmocka/test_fo_srv.c | 188 ++++++++++++++++++++++++++++++----------- - 2 files changed, 142 insertions(+), 50 deletions(-) - -diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c -index 562f0b3fd7870387a80c889b245cda0d39dea509..b076687ac6e571f7e27402fd11ac60183ea46951 100644 ---- a/src/providers/fail_over.c -+++ b/src/providers/fail_over.c -@@ -1554,7 +1554,9 @@ void fo_reset_servers(struct fo_service *service) - DLIST_FOR_EACH(server, service->server_list) { - if (server->srv_data != NULL) { - set_srv_data_status(server->srv_data, SRV_NEUTRAL); -- } else { -+ } -+ -+ if (server->common) { - fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED); - } - -diff --git a/src/tests/cmocka/test_fo_srv.c b/src/tests/cmocka/test_fo_srv.c -index e5c5e4fe3b818ca2df0ab7bcd1a83719fefba191..e892bab0a261779363ea78a10038b15acefc49b7 100644 ---- a/src/tests/cmocka/test_fo_srv.c -+++ b/src/tests/cmocka/test_fo_srv.c -@@ -194,7 +194,7 @@ errno_t resolv_get_domain_recv(TALLOC_CTX *mem_ctx, - } - - /* The unit test */ --struct test_fo_srv_ctx { -+struct test_fo_ctx { - struct resolv_ctx *resolv; - struct fo_ctx *fo_ctx; - struct fo_resolve_srv_dns_ctx *srv_ctx; -@@ -208,19 +208,18 @@ int test_fo_srv_data_cmp(void *ud1, void *ud2) - return strcasecmp((char*) ud1, (char*) ud2); - } - --static int test_fo_srv_setup(void **state) -+static int test_fo_setup(void **state) - { -- struct test_fo_srv_ctx *test_ctx; -+ struct test_fo_ctx *test_ctx; - errno_t ret; - struct fo_options fopts; -- bool ok; - - assert_true(leak_check_setup()); - global_mock_context = talloc_new(global_talloc_context); - assert_non_null(global_mock_context); - - test_ctx = talloc_zero(global_mock_context, -- struct test_fo_srv_ctx); -+ struct test_fo_ctx); - assert_non_null(test_ctx); - - test_ctx->ctx = create_ev_test_ctx(test_ctx); -@@ -237,6 +236,34 @@ static int test_fo_srv_setup(void **state) - test_ctx->fo_ctx = fo_context_init(test_ctx, &fopts); - assert_non_null(test_ctx->fo_ctx); - -+ ret = fo_new_service(test_ctx->fo_ctx, "ldap", -+ test_fo_srv_data_cmp, -+ &test_ctx->fo_svc); -+ assert_int_equal(ret, ERR_OK); -+ -+ *state = test_ctx; -+ return 0; -+} -+ -+static int test_fo_teardown(void **state) -+{ -+ struct test_fo_ctx *test_ctx = -+ talloc_get_type(*state, struct test_fo_ctx); -+ -+ talloc_free(test_ctx); -+ talloc_free(global_mock_context); -+ assert_true(leak_check_teardown()); -+ return 0; -+} -+ -+static int test_fo_srv_setup(void **state) -+{ -+ struct test_fo_ctx *test_ctx; -+ bool ok; -+ -+ test_fo_setup(state); -+ test_ctx = *state; -+ - test_ctx->srv_ctx = fo_resolve_srv_dns_ctx_init(test_ctx, test_ctx->resolv, - IPV4_FIRST, default_host_dbs, - "client.sssd.com", "sssd.local"); -@@ -248,23 +275,13 @@ static int test_fo_srv_setup(void **state) - test_ctx->srv_ctx); - assert_true(ok); - -- ret = fo_new_service(test_ctx->fo_ctx, "ldap", -- test_fo_srv_data_cmp, -- &test_ctx->fo_svc); -- assert_int_equal(ret, ERR_OK); -- - *state = test_ctx; - return 0; - } - - static int test_fo_srv_teardown(void **state) - { -- struct test_fo_srv_ctx *test_ctx = -- talloc_get_type(*state, struct test_fo_srv_ctx); -- -- talloc_free(test_ctx); -- talloc_free(global_mock_context); -- assert_true(leak_check_teardown()); -+ test_fo_teardown(state); - return 0; - } - -@@ -280,25 +297,30 @@ static void mock_srv_results(struct ares_srv_reply *reply_list, - will_return(resolv_discover_srv_recv, dns_domain); - } - --static void check_server(struct fo_server *srv, int port, const char *name) -+static void check_server(struct test_fo_ctx *ctx, -+ struct fo_server *srv, -+ int port, -+ const char *name) - { - assert_non_null(srv); -- assert_true(fo_is_srv_lookup(srv)); - assert_int_equal(fo_get_server_port(srv), port); - assert_string_equal(fo_get_server_name(srv), name); -+ -+ -+ if (ctx->srv_ctx) { -+ assert_true(fo_is_srv_lookup(srv)); -+ } - } - -+static void test_fo_srv_step1(struct test_fo_ctx *test_ctx); - static void test_fo_srv_done1(struct tevent_req *req); - static void test_fo_srv_done2(struct tevent_req *req); - static void test_fo_srv_done3(struct tevent_req *req); - static void test_fo_srv_done4(struct tevent_req *req); -+static void test_fo_srv_done5(struct tevent_req *req); - --void test_fo_srv(void **state) -+static void test_fo_srv_mock_dns(struct test_fo_ctx *test_ctx) - { -- errno_t ret; -- struct tevent_req *req; -- struct test_fo_srv_ctx *test_ctx = -- talloc_get_type(*state, struct test_fo_srv_ctx); - struct ares_srv_reply *s1; - struct ares_srv_reply *s2; - char *dns_domain; -@@ -325,25 +347,41 @@ void test_fo_srv(void **state) - assert_non_null(dns_domain); - - mock_srv_results(s1, TEST_SRV_TTL, dns_domain); -+} -+ -+static void test_fo_srv(void **state) -+{ -+ errno_t ret; -+ struct test_fo_ctx *test_ctx = -+ talloc_get_type(*state, struct test_fo_ctx); -+ -+ test_fo_srv_mock_dns(test_ctx); - - ret = fo_add_srv_server(test_ctx->fo_svc, "_ldap", "sssd.com", - "sssd.local", "tcp", test_ctx); - assert_int_equal(ret, ERR_OK); - -+ test_fo_srv_step1(test_ctx); -+ -+ ret = test_ev_loop(test_ctx->ctx); -+ assert_int_equal(ret, ERR_OK); -+} -+ -+static void test_fo_srv_step1(struct test_fo_ctx *test_ctx) -+{ -+ struct tevent_req *req; -+ - req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev, - test_ctx->resolv, test_ctx->fo_ctx, - test_ctx->fo_svc); - assert_non_null(req); - tevent_req_set_callback(req, test_fo_srv_done1, test_ctx); -- -- ret = test_ev_loop(test_ctx->ctx); -- assert_int_equal(ret, ERR_OK); - } - - static void test_fo_srv_done1(struct tevent_req *req) - { -- struct test_fo_srv_ctx *test_ctx = \ -- tevent_req_callback_data(req, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct test_fo_ctx); - struct fo_server *srv; - errno_t ret; - -@@ -352,7 +390,7 @@ static void test_fo_srv_done1(struct tevent_req *req) - assert_int_equal(ret, ERR_OK); - - /* ldap1.sssd.com has lower priority, it must always be first */ -- check_server(srv, 389, "ldap1.sssd.com"); -+ check_server(test_ctx, srv, 389, "ldap1.sssd.com"); - - /* Mark the server as working and request the service again. The same server - * must be returned */ -@@ -367,8 +405,8 @@ static void test_fo_srv_done1(struct tevent_req *req) - - static void test_fo_srv_done2(struct tevent_req *req) - { -- struct test_fo_srv_ctx *test_ctx = \ -- tevent_req_callback_data(req, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct test_fo_ctx); - struct fo_server *srv; - errno_t ret; - -@@ -377,7 +415,7 @@ static void test_fo_srv_done2(struct tevent_req *req) - assert_int_equal(ret, ERR_OK); - - /* Must be ldap1 again */ -- check_server(srv, 389, "ldap1.sssd.com"); -+ check_server(test_ctx, srv, 389, "ldap1.sssd.com"); - - /* Mark it at wrong, next lookup should yield ldap2 */ - fo_set_server_status(srv, SERVER_NOT_WORKING); -@@ -391,8 +429,8 @@ static void test_fo_srv_done2(struct tevent_req *req) - - static void test_fo_srv_done3(struct tevent_req *req) - { -- struct test_fo_srv_ctx *test_ctx = \ -- tevent_req_callback_data(req, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct test_fo_ctx); - struct fo_server *srv; - errno_t ret; - -@@ -401,7 +439,7 @@ static void test_fo_srv_done3(struct tevent_req *req) - assert_int_equal(ret, ERR_OK); - - /* Must be ldap2 now */ -- check_server(srv, 389, "ldap2.sssd.com"); -+ check_server(test_ctx, srv, 389, "ldap2.sssd.com"); - - /* Mark is at wrong, next lookup must reach the end of the server list */ - fo_set_server_status(srv, SERVER_NOT_WORKING); -@@ -415,8 +453,8 @@ static void test_fo_srv_done3(struct tevent_req *req) - - static void test_fo_srv_done4(struct tevent_req *req) - { -- struct test_fo_srv_ctx *test_ctx = \ -- tevent_req_callback_data(req, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct test_fo_ctx); - struct fo_server *srv; - errno_t ret; - -@@ -425,6 +463,35 @@ static void test_fo_srv_done4(struct tevent_req *req) - /* No servers are left..*/ - assert_int_equal(ret, ENOENT); - -+ /* reset the server status and try again.. */ -+ fo_reset_servers(test_ctx->fo_svc); -+ if (test_ctx->srv_ctx) { -+ test_fo_srv_mock_dns(test_ctx); -+ } -+ -+ req = fo_resolve_service_send(test_ctx, test_ctx->ctx->ev, -+ test_ctx->resolv, test_ctx->fo_ctx, -+ test_ctx->fo_svc); -+ assert_non_null(req); -+ tevent_req_set_callback(req, test_fo_srv_done5, test_ctx); -+} -+ -+static void test_fo_srv_done5(struct tevent_req *req) -+{ -+ struct test_fo_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct test_fo_ctx); -+ struct fo_server *srv; -+ errno_t ret; -+ -+ ret = fo_resolve_service_recv(req, &srv); -+ talloc_zfree(req); -+ -+ assert_int_equal(ret, ERR_OK); -+ -+ /* ldap1.sssd.com has lower priority, it must always be first */ -+ check_server(test_ctx, srv, 389, "ldap1.sssd.com"); -+ -+ /* OK, we made a full circle with the test, done */ - test_ctx->ctx->error = ERR_OK; - test_ctx->ctx->done = true; - } -@@ -432,20 +499,20 @@ static void test_fo_srv_done4(struct tevent_req *req) - /* Make sure that two queries more than TTL seconds apart resolve - * into two different lists - */ --static void test_fo_srv_ttl_change_step(struct test_fo_srv_ctx *test_ctx); -+static void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx); - static void test_fo_srv_before(struct tevent_req *req); - static void test_fo_srv_after(struct tevent_req *req); - - void test_fo_srv_ttl_change(void **state) - { -- struct test_fo_srv_ctx *test_ctx = -- talloc_get_type(*state, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = -+ talloc_get_type(*state, struct test_fo_ctx); - - test_ctx->ttl = TEST_SRV_SHORT_TTL; - test_fo_srv_ttl_change_step(test_ctx); - } - --static void test_fo_srv_ttl_change_step(struct test_fo_srv_ctx *test_ctx) -+static void test_fo_srv_ttl_change_step(struct test_fo_ctx *test_ctx) - { - errno_t ret; - struct tevent_req *req; -@@ -497,8 +564,8 @@ static void test_fo_srv_ttl_change_step(struct test_fo_srv_ctx *test_ctx) - - static void test_fo_srv_before(struct tevent_req *req) - { -- struct test_fo_srv_ctx *test_ctx = \ -- tevent_req_callback_data(req, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct test_fo_ctx); - struct fo_server *srv; - struct ares_srv_reply *s1; - struct ares_srv_reply *s2; -@@ -511,7 +578,7 @@ static void test_fo_srv_before(struct tevent_req *req) - - DEBUG(SSSDBG_TRACE_FUNC, "Before TTL change\n"); - -- check_server(srv, 389, "ldap1.sssd.com"); -+ check_server(test_ctx, srv, 389, "ldap1.sssd.com"); - fo_set_server_status(srv, SERVER_WORKING); - - /* Simulate changing the DNS environment. Change the host names */ -@@ -548,8 +615,8 @@ static void test_fo_srv_before(struct tevent_req *req) - - static void test_fo_srv_after(struct tevent_req *req) - { -- struct test_fo_srv_ctx *test_ctx = \ -- tevent_req_callback_data(req, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = \ -+ tevent_req_callback_data(req, struct test_fo_ctx); - struct fo_server *srv; - errno_t ret; - -@@ -558,7 +625,7 @@ static void test_fo_srv_after(struct tevent_req *req) - assert_int_equal(ret, ERR_OK); - - /* Must be a different server now */ -- check_server(srv, 389, "ldap3.sssd.com"); -+ check_server(test_ctx, srv, 389, "ldap3.sssd.com"); - - test_ctx->ctx->error = ERR_OK; - test_ctx->ctx->done = true; -@@ -566,13 +633,33 @@ static void test_fo_srv_after(struct tevent_req *req) - - void test_fo_srv_ttl_zero(void **state) - { -- struct test_fo_srv_ctx *test_ctx = -- talloc_get_type(*state, struct test_fo_srv_ctx); -+ struct test_fo_ctx *test_ctx = -+ talloc_get_type(*state, struct test_fo_ctx); - - test_ctx->ttl = 0; - test_fo_srv_ttl_change_step(test_ctx); - } - -+static void test_fo_hostlist(void **state) -+{ -+ errno_t ret; -+ struct test_fo_ctx *test_ctx = -+ talloc_get_type(*state, struct test_fo_ctx); -+ -+ ret = fo_add_server(test_ctx->fo_svc, -+ "ldap1.sssd.com", 389, test_ctx, true); -+ assert_int_equal(ret, ERR_OK); -+ -+ ret = fo_add_server(test_ctx->fo_svc, -+ "ldap2.sssd.com", 389, test_ctx, true); -+ assert_int_equal(ret, ERR_OK); -+ -+ test_fo_srv_step1(test_ctx); -+ -+ ret = test_ev_loop(test_ctx->ctx); -+ assert_int_equal(ret, ERR_OK); -+} -+ - int main(int argc, const char *argv[]) - { - int rv; -@@ -585,6 +672,9 @@ int main(int argc, const char *argv[]) - }; - - const struct CMUnitTest tests[] = { -+ cmocka_unit_test_setup_teardown(test_fo_hostlist, -+ test_fo_setup, -+ test_fo_teardown), - cmocka_unit_test_setup_teardown(test_fo_srv, - test_fo_srv_setup, - test_fo_srv_teardown), --- -2.4.3 - diff --git a/SOURCES/0095-failover-mark-subdomain-service-with-sd_-prefix.patch b/SOURCES/0095-failover-mark-subdomain-service-with-sd_-prefix.patch new file mode 100644 index 0000000..4d9a1bf --- /dev/null +++ b/SOURCES/0095-failover-mark-subdomain-service-with-sd_-prefix.patch @@ -0,0 +1,92 @@ +From a3b502fa85d493795c963e4298aeec3dc5806fcf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 29 Jun 2016 14:58:37 +0200 +Subject: [PATCH 095/102] failover: mark subdomain service with sd_ prefix +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit 778f241e78241b0d6b8734148175f8dee804f494) +--- + src/providers/ad/ad_subdomains.c | 11 +++++++++-- + src/providers/ipa/ipa_subdomains_server.c | 11 +++++++++-- + 2 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index e9da04e384e598927f9c8c203a751bcccd29e895..a0d5c2e544fc62fda64771dce59b3b7ab8ecd8b6 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -66,6 +66,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, + struct ad_options *ad_options; + struct ad_id_ctx *ad_id_ctx; + const char *gc_service_name; ++ const char *service_name; + struct ad_srv_plugin_ctx *srv_ctx; + char *ad_domain; + char *ad_site_override; +@@ -94,14 +95,20 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, + + ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE); + +- gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name); ++ gc_service_name = talloc_asprintf(ad_options, "sd_gc_%s", subdom->name); + if (gc_service_name == NULL) { + talloc_free(ad_options); + return ENOMEM; + } + ++ service_name = talloc_asprintf(ad_options, "sd_%s", subdom->name); ++ if (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, ++ service_name, gc_service_name, + subdom->name, &ad_options->service); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n"); +diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c +index 43636098f6928006db0e0a9c05f2e39f8427d705..13640b04d66a1cdbbf0c8eab7648f7ebe921884b 100644 +--- a/src/providers/ipa/ipa_subdomains_server.c ++++ b/src/providers/ipa/ipa_subdomains_server.c +@@ -203,6 +203,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, + struct ad_options *ad_options; + struct ad_id_ctx *ad_id_ctx; + const char *gc_service_name; ++ const char *service_name; + struct ad_srv_plugin_ctx *srv_ctx; + const char *ad_domain; + const char *ad_site_override; +@@ -250,17 +251,23 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, + DEBUG(SSSDBG_TRACE_ALL, "No extra attrs set.\n"); + } + +- gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->forest); ++ gc_service_name = talloc_asprintf(ad_options, "sd_gc_%s", subdom->forest); + if (gc_service_name == NULL) { + talloc_free(ad_options); + return ENOMEM; + } + ++ service_name = talloc_asprintf(ad_options, "sd_%s", subdom->name); ++ if (service_name == NULL) { ++ talloc_free(ad_options); ++ return ENOMEM; ++ } ++ + /* Set KRB5 realm to same as the one of IPA when IPA + * is able to attach PAC. For testing, use hardcoded. */ + ret = ad_failover_init(ad_options, be_ctx, NULL, NULL, + id_ctx->server_mode->realm, +- subdom->name, gc_service_name, ++ service_name, gc_service_name, + subdom->name, &ad_options->service); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot initialize AD failover\n"); +-- +2.4.11 + diff --git a/SOURCES/0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch b/SOURCES/0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch deleted file mode 100644 index f5b2c27..0000000 --- a/SOURCES/0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 569233a9db93bfd2926bb1ecf73d9b67a634e840 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 17 Sep 2015 17:11:34 +0200 -Subject: [PATCH 96/96] IPA: Retry fetching keytab if IPA user lookup fails - -Required for: - https://fedorahosted.org/sssd/ticket/2639 - -Instead of calling ipa_get_ad_acct_send directly, call a new request -ipa_srv_ad_acct_send. The new request wraps ipa_get_ad_acct_send and -either tries to request a new keytab every time the lookup fails but the -domain is online. - -be_mark_dom_offline() is called when the retry fails with the new code. - -The retry tries to re-setup the trusted domain. With two-way setups, the -request is a no-op. With one-way trust setups, the request re-fetches -new keytab unconditionally. - -Reviewed-by: Sumit Bose -(cherry picked from commit 0aff5b651a414a1fd58ab3eb2f029399c0278a18) ---- - src/providers/ipa/ipa_id.h | 9 -- - src/providers/ipa/ipa_subdomains_id.c | 190 +++++++++++++++++++++++++++++++++- - 2 files changed, 185 insertions(+), 14 deletions(-) - -diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h -index c03ca037a2850478a8f4933bac4fcf8bd70ada04..91a94115386955f63eca706bf6f4ac41884445eb 100644 ---- a/src/providers/ipa/ipa_id.h -+++ b/src/providers/ipa/ipa_id.h -@@ -70,15 +70,6 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, - struct be_acct_req *ar); - int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out); - --struct tevent_req *ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, -- struct tevent_context *ev, -- struct ipa_id_ctx *ipa_ctx, -- struct be_req *be_req, -- struct sysdb_attrs *override_attrs, -- struct be_acct_req *ar); -- --errno_t ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out); -- - errno_t get_be_acct_req_for_sid(TALLOC_CTX *mem_ctx, const char *sid, - const char *domain_name, - struct be_acct_req **_ar); -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index ff14b4a4c68cb5c6e9865a66931ee4ecd6e49211..86dd71f3cc09f11de88c4269d49552718c5ba027 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -34,6 +34,16 @@ - #include "providers/ad/ad_id.h" - #include "providers/ipa/ipa_subdomains.h" - -+static struct tevent_req * -+ipa_srv_ad_acct_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ipa_id_ctx *ipa_ctx, -+ struct be_req *be_req, -+ struct sysdb_attrs *override_attrs, -+ struct be_acct_req *ar); -+static errno_t -+ipa_srv_ad_acct_recv(struct tevent_req *req, int *dp_error_out); -+ - struct ipa_subdomain_account_state { - struct tevent_context *ev; - struct ipa_id_ctx *ipa_ctx; -@@ -45,6 +55,7 @@ struct ipa_subdomain_account_state { - struct be_acct_req *ar; - - bool ipa_server_mode; -+ bool server_retry; - int entry_type; - const char *filter; - int filter_type; -@@ -263,7 +274,7 @@ static errno_t ipa_subdomain_account_get_original_step(struct tevent_req *req, - struct tevent_req *subreq; - - if (state->ipa_server_mode) { -- subreq = ipa_get_ad_acct_send(state, state->ev, state->ipa_ctx, -+ subreq = ipa_srv_ad_acct_send(state, state->ev, state->ipa_ctx, - state->be_req, state->override_attrs, ar); - } else { - subreq = ipa_get_subdom_acct_send(state, state->ev, state->ipa_ctx, -@@ -291,7 +302,7 @@ static void ipa_subdomain_account_done(struct tevent_req *subreq) - int ret; - - if (state->ipa_server_mode) { -- ret = ipa_get_ad_acct_recv(subreq, &dp_error); -+ ret = ipa_srv_ad_acct_recv(subreq, &dp_error); - } else { - ret = ipa_get_subdom_acct_recv(subreq, &dp_error); - } -@@ -575,7 +586,7 @@ static void ipa_get_ad_acct_done(struct tevent_req *subreq); - static struct ad_id_ctx *ipa_get_ad_id_ctx(struct ipa_id_ctx *ipa_ctx, - struct sss_domain_info *dom); - --struct tevent_req * -+static struct tevent_req * - ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct ipa_id_ctx *ipa_ctx, -@@ -1039,7 +1050,6 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) - ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL); - talloc_zfree(subreq); - if (ret == ERR_SUBDOM_INACTIVE) { -- be_mark_dom_offline(state->obj_dom, be_req_get_be_ctx(state->be_req)); - tevent_req_error(req, ret); - return; - } else if (ret != EOK) { -@@ -1324,7 +1334,7 @@ ipa_get_ad_acct_done(struct tevent_req *subreq) - tevent_req_done(req); - } - --errno_t -+static errno_t - ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out) - { - struct ipa_get_ad_acct_state *state = tevent_req_data(req, -@@ -1338,3 +1348,173 @@ ipa_get_ad_acct_recv(struct tevent_req *req, int *dp_error_out) - - return EOK; - } -+ -+struct ipa_srv_ad_acct_state { -+ struct tevent_context *ev; -+ struct ipa_id_ctx *ipa_ctx; -+ struct be_req *be_req; -+ struct sysdb_attrs *override_attrs; -+ struct be_acct_req *ar; -+ -+ struct sss_domain_info *obj_dom; -+ struct be_ctx *be_ctx; -+ bool retry; -+ -+ int dp_error; -+}; -+ -+static int ipa_srv_ad_acct_lookup_step(struct tevent_req *req); -+static void ipa_srv_ad_acct_lookup_done(struct tevent_req *subreq); -+static void ipa_srv_ad_acct_retried(struct tevent_req *subreq); -+ -+static struct tevent_req * -+ipa_srv_ad_acct_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct ipa_id_ctx *ipa_ctx, -+ struct be_req *be_req, -+ struct sysdb_attrs *override_attrs, -+ struct be_acct_req *ar) -+{ -+ errno_t ret; -+ struct tevent_req *req; -+ struct ipa_srv_ad_acct_state *state; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ipa_srv_ad_acct_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ -+ state->ev = ev; -+ state->ipa_ctx = ipa_ctx; -+ state->be_req = be_req; -+ state->override_attrs = override_attrs; -+ state->ar = ar; -+ state->retry = true; -+ state->dp_error = DP_ERR_FATAL; -+ state->be_ctx = be_req_get_be_ctx(state->be_req); -+ -+ state->obj_dom = find_domain_by_name( -+ state->ipa_ctx->sdap_id_ctx->be->domain, -+ state->ar->domain, true); -+ if (state->obj_dom == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "Domain not found\n"); -+ ret = ERR_DOMAIN_NOT_FOUND; -+ goto fail; -+ } -+ -+ ret = ipa_srv_ad_acct_lookup_step(req); -+ if (ret != EOK) { -+ goto fail; -+ } -+ -+ return req; -+ -+fail: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static int ipa_srv_ad_acct_lookup_step(struct tevent_req *req) -+{ -+ struct tevent_req *subreq; -+ struct ipa_srv_ad_acct_state *state = tevent_req_data(req, -+ struct ipa_srv_ad_acct_state); -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Looking up AD account\n"); -+ subreq = ipa_get_ad_acct_send(state, state->ev, state->ipa_ctx, -+ state->be_req, state->override_attrs, -+ state->ar); -+ if (subreq == NULL) { -+ return ENOMEM; -+ } -+ tevent_req_set_callback(subreq, ipa_srv_ad_acct_lookup_done, req); -+ -+ return EOK; -+} -+ -+static void ipa_srv_ad_acct_lookup_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ int dp_error = DP_ERR_FATAL; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ipa_srv_ad_acct_state *state = tevent_req_data(req, -+ struct ipa_srv_ad_acct_state); -+ -+ ret = ipa_get_ad_acct_recv(subreq, &dp_error); -+ talloc_free(subreq); -+ if (ret == ERR_SUBDOM_INACTIVE && state->retry == true) { -+ -+ state->retry = false; -+ -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Sudomain lookup failed, will try to reset sudomain..\n"); -+ subreq = ipa_server_trusted_dom_setup_send(state, state->ev, -+ state->be_ctx, -+ state->ipa_ctx, -+ state->obj_dom); -+ if (subreq == NULL) { -+ goto fail; -+ } -+ tevent_req_set_callback(subreq, ipa_srv_ad_acct_retried, req); -+ return; -+ } else if (ret != EOK) { -+ be_mark_dom_offline(state->obj_dom, state->be_ctx); -+ -+ DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct request failed: [%d]: %s.\n", -+ ret, sss_strerror(ret)); -+ goto fail; -+ } -+ -+ state->dp_error = DP_ERR_OK; -+ tevent_req_done(req); -+ return; -+ -+fail: -+ state->dp_error = dp_error; -+ tevent_req_error(req, ret); -+} -+ -+static void ipa_srv_ad_acct_retried(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ipa_srv_ad_acct_state *state = tevent_req_data(req, -+ struct ipa_srv_ad_acct_state); -+ -+ ret = ipa_server_trusted_dom_setup_recv(subreq); -+ talloc_free(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to re-set subdomain [%d]: %s\n", ret, sss_strerror(ret)); -+ state->dp_error = DP_ERR_FATAL; -+ tevent_req_error(req, ret); -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, "Sudomain re-set, will retry lookup\n"); -+ be_fo_reset_svc(state->be_ctx, state->obj_dom->name); -+ -+ ret = ipa_srv_ad_acct_lookup_step(req); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Failed to look up AD acct [%d]: %s\n", ret, sss_strerror(ret)); -+ state->dp_error = DP_ERR_FATAL; -+ tevent_req_error(req, ret); -+ } -+} -+ -+static errno_t -+ipa_srv_ad_acct_recv(struct tevent_req *req, int *dp_error_out) -+{ -+ struct ipa_srv_ad_acct_state *state = tevent_req_data(req, -+ struct ipa_srv_ad_acct_state); -+ -+ if (dp_error_out) { -+ *dp_error_out = state->dp_error; -+ } -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ return EOK; -+} --- -2.4.3 - diff --git a/SOURCES/0096-sssctl-print-active-server-and-server-list.patch b/SOURCES/0096-sssctl-print-active-server-and-server-list.patch new file mode 100644 index 0000000..8bb1918 --- /dev/null +++ b/SOURCES/0096-sssctl-print-active-server-and-server-list.patch @@ -0,0 +1,1013 @@ +From 7f4199c2d4dc9147be436005d75e03fc468f5349 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 27 Jun 2016 13:56:13 +0200 +Subject: [PATCH 096/102] sssctl: print active server and server list +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/3069 + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit bd4c2ed5aec7f57ea04500f0e43f151eedfdde45) +--- + src/providers/data_provider/dp_iface.c | 6 +- + src/providers/data_provider/dp_iface.h | 8 + + src/providers/data_provider/dp_iface.xml | 8 + + src/providers/data_provider/dp_iface_failover.c | 297 ++++++++++++++++++++++- + src/providers/data_provider/dp_iface_generated.c | 52 ++++ + src/providers/data_provider/dp_iface_generated.h | 10 + + src/providers/fail_over.c | 42 ++++ + src/providers/fail_over.h | 4 + + src/responder/ifp/ifp_domains.c | 48 ++++ + src/responder/ifp/ifp_domains.h | 8 + + src/responder/ifp/ifp_iface.c | 4 +- + src/responder/ifp/ifp_iface.xml | 10 + + src/responder/ifp/ifp_iface_generated.c | 52 ++++ + src/responder/ifp/ifp_iface_generated.h | 10 + + src/tools/sssctl/sssctl_domains.c | 182 +++++++++++++- + 15 files changed, 722 insertions(+), 19 deletions(-) + +diff --git a/src/providers/data_provider/dp_iface.c b/src/providers/data_provider/dp_iface.c +index 8ed7274f0dd7b59598e2cf21e0dd59d16666df0b..4b2b0ddca68be8899f7285b4d881a91444b99362 100644 +--- a/src/providers/data_provider/dp_iface.c ++++ b/src/providers/data_provider/dp_iface.c +@@ -42,8 +42,10 @@ struct iface_dp_backend iface_dp_backend = { + }; + + struct iface_dp_failover iface_dp_failover = { +- {&iface_dp_failover_meta, 0}, +- .ListServices = dp_failover_list_services ++ { &iface_dp_failover_meta, 0 }, ++ .ListServices = dp_failover_list_services, ++ .ActiveServer = dp_failover_active_server, ++ .ListServers = dp_failover_list_servers + }; + + static struct sbus_iface_map dp_map[] = { +diff --git a/src/providers/data_provider/dp_iface.h b/src/providers/data_provider/dp_iface.h +index 76e623d21c413fd68f8f3c9a91ea32fd707dc54d..5c6f0eb2f5dd68b63bda389e6fdd2446ca9efb21 100644 +--- a/src/providers/data_provider/dp_iface.h ++++ b/src/providers/data_provider/dp_iface.h +@@ -69,4 +69,12 @@ errno_t dp_failover_list_services(struct sbus_request *sbus_req, + void *dp_cli, + const char *domname); + ++errno_t dp_failover_active_server(struct sbus_request *sbus_req, ++ void *dp_cli, ++ const char *service_name); ++ ++errno_t dp_failover_list_servers(struct sbus_request *sbus_req, ++ void *dp_cli, ++ const char *service_name); ++ + #endif /* DP_IFACE_H_ */ +diff --git a/src/providers/data_provider/dp_iface.xml b/src/providers/data_provider/dp_iface.xml +index eab7fc0f1500bf8890030352421da62c134115b9..992848a048ef9fe813d6ae05bbcabd0913ecb277 100644 +--- a/src/providers/data_provider/dp_iface.xml ++++ b/src/providers/data_provider/dp_iface.xml +@@ -22,6 +22,14 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/providers/data_provider/dp_iface_failover.c b/src/providers/data_provider/dp_iface_failover.c +index 038791088eeab7e9c5923996db77d2a107ff067d..7d95ffdd627604eb8c7e1b2882bf1665f792b660 100644 +--- a/src/providers/data_provider/dp_iface_failover.c ++++ b/src/providers/data_provider/dp_iface_failover.c +@@ -28,20 +28,208 @@ + #include "providers/backend.h" + #include "util/util.h" + ++static errno_t ++dp_failover_list_services_ldap(struct be_ctx *be_ctx, ++ const char **services, ++ int *_count) ++{ ++ struct be_svc_data *svc; ++ int count; ++ ++ count = 0; ++ DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { ++ services[count] = talloc_strdup(services, svc->name); ++ if (services[count] == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); ++ return ENOMEM; ++ } ++ count++; ++ } ++ ++ *_count = count; ++ ++ return EOK; ++} ++ ++static errno_t ++dp_failover_list_services_ad(struct be_ctx *be_ctx, ++ struct sss_domain_info *domain, ++ const char **services, ++ int *_count) ++{ ++ char *fo_svc_name = NULL; ++ struct be_svc_data *svc; ++ errno_t ret; ++ int count; ++ ++ fo_svc_name = talloc_asprintf(services, "sd_%s", domain->name); ++ if (fo_svc_name == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ count = 0; ++ DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { ++ /* Drop each sd_gc_* since this service is not used with AD at all, ++ * we only connect to AD_GC for global catalog. */ ++ if (strncasecmp(svc->name, "sd_gc_", strlen("sd_gc_")) == 0) { ++ continue; ++ } ++ ++ /* Drop all subdomain services for different domain. */ ++ if (strncasecmp(svc->name, "sd_", strlen("sd_")) == 0) { ++ if (!IS_SUBDOMAIN(domain)) { ++ continue; ++ } ++ ++ if (strcasecmp(svc->name, fo_svc_name) != 0) { ++ continue; ++ } ++ } ++ ++ if (IS_SUBDOMAIN(domain)) { ++ /* Drop AD since we connect to subdomain.com for LDAP. */ ++ if (strcasecmp(svc->name, "AD") == 0) { ++ continue; ++ } ++ } ++ ++ services[count] = talloc_strdup(services, svc->name); ++ if (services[count] == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ count++; ++ } ++ ++ *_count = count; ++ ++ ret = EOK; ++ ++done: ++ talloc_free(fo_svc_name); ++ return ret; ++} ++ ++static errno_t ++dp_failover_list_services_ipa(struct be_ctx *be_ctx, ++ struct sss_domain_info *domain, ++ const char **services, ++ int *_count) ++{ ++ struct be_svc_data *svc; ++ char *fo_svc_name = NULL; ++ char *fo_gc_name = NULL; ++ errno_t ret; ++ int count; ++ ++ fo_svc_name = talloc_asprintf(services, "sd_%s", domain->name); ++ if (fo_svc_name == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ fo_gc_name = talloc_asprintf(services, "sd_gc_%s", domain->name); ++ if (fo_gc_name == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ count = 0; ++ DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { ++ /* Drop all subdomain services for different domain. */ ++ if (strncasecmp(svc->name, "sd_", strlen("sd_")) == 0) { ++ if (!IS_SUBDOMAIN(domain)) { ++ continue; ++ } ++ ++ if (strcasecmp(svc->name, fo_svc_name) != 0 ++ && strcasecmp(svc->name, fo_gc_name) != 0) { ++ continue; ++ } ++ } ++ ++ services[count] = talloc_strdup(services, svc->name); ++ if (services[count] == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); ++ return ENOMEM; ++ } ++ count++; ++ } ++ ++ *_count = count; ++ ++ ret = EOK; ++ ++done: ++ talloc_free(fo_svc_name); ++ talloc_free(fo_gc_name); ++ ++ return ret; ++} ++ ++enum dp_fo_svc_type { ++ DP_FO_SVC_LDAP = 0, ++ DP_FO_SVC_AD = 1, ++ DP_FO_SVC_IPA = 1 << 1, ++ DP_FO_SVC_MIXED = DP_FO_SVC_AD | DP_FO_SVC_IPA ++}; ++ + errno_t dp_failover_list_services(struct sbus_request *sbus_req, + void *dp_cli, + const char *domname) + { ++ enum dp_fo_svc_type svc_type = DP_FO_SVC_LDAP; ++ struct sss_domain_info *domain; + struct be_ctx *be_ctx; + struct be_svc_data *svc; + const char **services; + int num_services; ++ errno_t ret; + + be_ctx = dp_client_be(dp_cli); + ++ if (SBUS_IS_STRING_EMPTY(domname)) { ++ domain = be_ctx->domain; ++ } else { ++ domain = find_domain_by_name(be_ctx->domain, domname, false); ++ if (domain == NULL) { ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, ++ "Unknown domain %s", domname); ++ return EOK; ++ } ++ } ++ ++ /** ++ * Returning list of failover services is currently rather difficult ++ * since there is only one failover context for the whole backend. ++ * ++ * The list of services for the given domain depends on whether it is ++ * a master domain or a subdomain and whether we are using IPA, AD or ++ * LDAP backend. ++ * ++ * For LDAP we just return everything we have. ++ * For AD master domain we return AD, AD_GC. ++ * For AD subdomain we return subdomain.com, AD_GC. ++ * For IPA in client mode we return IPA. ++ * For IPA in server mode we return IPA for master domain and ++ * subdomain.com, gc_subdomain.com for subdomain. ++ * ++ * We also return everything else for all cases if any other service ++ * such as kerberos is configured separately. ++ */ ++ ++ /* Allocate enough space. */ + num_services = 0; + DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { + num_services++; ++ ++ if (strcasecmp(svc->name, "AD") == 0) { ++ svc_type |= DP_FO_SVC_AD; ++ } else if (strcasecmp(svc->name, "IPA") == 0) { ++ svc_type |= DP_FO_SVC_IPA; ++ } + } + + services = talloc_zero_array(sbus_req, const char *, num_services); +@@ -50,17 +238,108 @@ errno_t dp_failover_list_services(struct sbus_request *sbus_req, + return ENOMEM; + } + +- num_services = 0; +- DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { +- services[num_services] = talloc_strdup(services, svc->name); +- if (services[num_services] == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); +- talloc_free(services); +- return ENOMEM; +- } +- num_services++; ++ /* Fill the list. */ ++ switch (svc_type) { ++ case DP_FO_SVC_LDAP: ++ case DP_FO_SVC_MIXED: ++ ret = dp_failover_list_services_ldap(be_ctx, services, &num_services); ++ break; ++ case DP_FO_SVC_AD: ++ ret = dp_failover_list_services_ad(be_ctx, domain, ++ services, &num_services); ++ break; ++ case DP_FO_SVC_IPA: ++ ret = dp_failover_list_services_ipa(be_ctx, domain, ++ services, &num_services); ++ break; ++ default: ++ ret = ERR_INTERNAL; ++ break; ++ } ++ ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create service list [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ talloc_free(services); ++ return ret; + } + + iface_dp_failover_ListServices_finish(sbus_req, services, num_services); + return EOK; + } ++ ++errno_t dp_failover_active_server(struct sbus_request *sbus_req, ++ void *dp_cli, ++ const char *service_name) ++{ ++ struct be_ctx *be_ctx; ++ struct be_svc_data *svc; ++ const char *server; ++ bool found = false; ++ ++ be_ctx = dp_client_be(dp_cli); ++ ++ DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { ++ if (strcmp(svc->name, service_name) == 0) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server name\n"); ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_NOT_FOUND, ++ "Unknown service name"); ++ return EOK; ++ } ++ ++ if (svc->last_good_srv == NULL) { ++ server = ""; ++ } else { ++ server = fo_get_server_name(svc->last_good_srv); ++ if (server == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server name\n"); ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_INTERNAL, ++ "Unable to get server name"); ++ return EOK; ++ } ++ } ++ ++ iface_dp_failover_ActiveServer_finish(sbus_req, server); ++ return EOK; ++} ++ ++errno_t dp_failover_list_servers(struct sbus_request *sbus_req, ++ void *dp_cli, ++ const char *service_name) ++{ ++ struct be_ctx *be_ctx; ++ struct be_svc_data *svc; ++ const char **servers; ++ bool found = false; ++ size_t count; ++ ++ be_ctx = dp_client_be(dp_cli); ++ ++ DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { ++ if (strcmp(svc->name, service_name) == 0) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server list\n"); ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_NOT_FOUND, ++ "Unknown service name"); ++ return EOK; ++ } ++ ++ servers = fo_svc_server_list(sbus_req, svc->fo_service, &count); ++ if (servers == NULL) { ++ return ENOMEM; ++ } ++ ++ iface_dp_failover_ListServers_finish(sbus_req, servers, (int)count); ++ return EOK; ++} +diff --git a/src/providers/data_provider/dp_iface_generated.c b/src/providers/data_provider/dp_iface_generated.c +index 7b36fd8aaeebb976a511c5592b1dd0ae28e9bb8a..fd2acb4f4bd8cf1dcbe8842cccc6dc2077fc83a2 100644 +--- a/src/providers/data_provider/dp_iface_generated.c ++++ b/src/providers/data_provider/dp_iface_generated.c +@@ -111,6 +111,44 @@ int iface_dp_failover_ListServices_finish(struct sbus_request *req, const char * + DBUS_TYPE_INVALID); + } + ++/* arguments for org.freedesktop.sssd.DataProvider.Failover.ActiveServer */ ++const struct sbus_arg_meta iface_dp_failover_ActiveServer__in[] = { ++ { "service_name", "s" }, ++ { NULL, } ++}; ++ ++/* arguments for org.freedesktop.sssd.DataProvider.Failover.ActiveServer */ ++const struct sbus_arg_meta iface_dp_failover_ActiveServer__out[] = { ++ { "server", "s" }, ++ { NULL, } ++}; ++ ++int iface_dp_failover_ActiveServer_finish(struct sbus_request *req, const char *arg_server) ++{ ++ return sbus_request_return_and_finish(req, ++ DBUS_TYPE_STRING, &arg_server, ++ DBUS_TYPE_INVALID); ++} ++ ++/* arguments for org.freedesktop.sssd.DataProvider.Failover.ListServers */ ++const struct sbus_arg_meta iface_dp_failover_ListServers__in[] = { ++ { "service_name", "s" }, ++ { NULL, } ++}; ++ ++/* arguments for org.freedesktop.sssd.DataProvider.Failover.ListServers */ ++const struct sbus_arg_meta iface_dp_failover_ListServers__out[] = { ++ { "servers", "as" }, ++ { NULL, } ++}; ++ ++int iface_dp_failover_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers) ++{ ++ return sbus_request_return_and_finish(req, ++ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &arg_servers, len_servers, ++ DBUS_TYPE_INVALID); ++} ++ + /* methods for org.freedesktop.sssd.DataProvider.Failover */ + const struct sbus_method_meta iface_dp_failover__methods[] = { + { +@@ -120,6 +158,20 @@ const struct sbus_method_meta iface_dp_failover__methods[] = { + offsetof(struct iface_dp_failover, ListServices), + invoke_s_method, + }, ++ { ++ "ActiveServer", /* name */ ++ iface_dp_failover_ActiveServer__in, ++ iface_dp_failover_ActiveServer__out, ++ offsetof(struct iface_dp_failover, ActiveServer), ++ invoke_s_method, ++ }, ++ { ++ "ListServers", /* name */ ++ iface_dp_failover_ListServers__in, ++ iface_dp_failover_ListServers__out, ++ offsetof(struct iface_dp_failover, ListServers), ++ invoke_s_method, ++ }, + { NULL, } + }; + +diff --git a/src/providers/data_provider/dp_iface_generated.h b/src/providers/data_provider/dp_iface_generated.h +index 977ab3bae803ca002162b02d0c3d9677779983f4..7c2216aa27022769c707d80b59e9b436e72d1739 100644 +--- a/src/providers/data_provider/dp_iface_generated.h ++++ b/src/providers/data_provider/dp_iface_generated.h +@@ -22,6 +22,8 @@ + /* constants for org.freedesktop.sssd.DataProvider.Failover */ + #define IFACE_DP_FAILOVER "org.freedesktop.sssd.DataProvider.Failover" + #define IFACE_DP_FAILOVER_LISTSERVICES "ListServices" ++#define IFACE_DP_FAILOVER_ACTIVESERVER "ActiveServer" ++#define IFACE_DP_FAILOVER_LISTSERVERS "ListServers" + + /* constants for org.freedesktop.sssd.dataprovider */ + #define IFACE_DP "org.freedesktop.sssd.dataprovider" +@@ -72,11 +74,19 @@ int iface_dp_backend_IsOnline_finish(struct sbus_request *req, bool arg_status); + struct iface_dp_failover { + struct sbus_vtable vtable; /* derive from sbus_vtable */ + int (*ListServices)(struct sbus_request *req, void *data, const char *arg_domain_name); ++ int (*ActiveServer)(struct sbus_request *req, void *data, const char *arg_service_name); ++ int (*ListServers)(struct sbus_request *req, void *data, const char *arg_service_name); + }; + + /* finish function for ListServices */ + int iface_dp_failover_ListServices_finish(struct sbus_request *req, const char *arg_services[], int len_services); + ++/* finish function for ActiveServer */ ++int iface_dp_failover_ActiveServer_finish(struct sbus_request *req, const char *arg_server); ++ ++/* finish function for ListServers */ ++int iface_dp_failover_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers); ++ + /* vtable for org.freedesktop.sssd.dataprovider */ + struct iface_dp { + struct sbus_vtable vtable; /* derive from sbus_vtable */ +diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c +index 1d88d2aa54bfdebd4b648e2b13fa8d03e2be3973..8ab39f27f77e19e601855632196006a8dbbdf136 100644 +--- a/src/providers/fail_over.c ++++ b/src/providers/fail_over.c +@@ -1660,6 +1660,48 @@ bool fo_svc_has_server(struct fo_service *service, struct fo_server *server) + return false; + } + ++const char **fo_svc_server_list(TALLOC_CTX *mem_ctx, ++ struct fo_service *service, ++ size_t *_count) ++{ ++ const char **list; ++ const char *server; ++ struct fo_server *srv; ++ size_t count; ++ ++ count = 0; ++ DLIST_FOR_EACH(srv, service->server_list) { ++ count++; ++ } ++ ++ list = talloc_zero_array(mem_ctx, const char *, count + 1); ++ if (list == NULL) { ++ return NULL; ++ } ++ ++ count = 0; ++ DLIST_FOR_EACH(srv, service->server_list) { ++ server = fo_get_server_name(srv); ++ if (server == NULL) { ++ /* _srv_ */ ++ continue; ++ } ++ ++ list[count] = talloc_strdup(list, server); ++ if (list[count] == NULL) { ++ talloc_free(list); ++ return NULL; ++ } ++ count++; ++ } ++ ++ if (_count != NULL) { ++ *_count = count; ++ } ++ ++ return list; ++} ++ + bool fo_set_srv_lookup_plugin(struct fo_ctx *ctx, + fo_srv_lookup_plugin_send_t send_fn, + fo_srv_lookup_plugin_recv_t recv_fn, +diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h +index f24b5715f13931965400c20562a1578aaf756908..d70212fb7ea569b9c47bba36704aa8ae18754cbb 100644 +--- a/src/providers/fail_over.h ++++ b/src/providers/fail_over.h +@@ -212,6 +212,10 @@ struct fo_server *fo_get_active_server(struct fo_service *service); + + bool fo_svc_has_server(struct fo_service *service, struct fo_server *server); + ++const char **fo_svc_server_list(TALLOC_CTX *mem_ctx, ++ struct fo_service *service, ++ size_t *_count); ++ + /* + * pvt will be talloc_stealed to ctx + */ +diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c +index ff690ed6a7d5519979d242a4d5dadd08aff50347..977bbfcbe818f08873ce072d34fdcf900cabf52f 100644 +--- a/src/responder/ifp/ifp_domains.c ++++ b/src/responder/ifp/ifp_domains.c +@@ -582,3 +582,51 @@ int ifp_domains_domain_list_services(struct sbus_request *sbus_req, + + return EOK; + } ++ ++int ifp_domains_domain_active_server(struct sbus_request *sbus_req, ++ void *data, ++ const char *service) ++{ ++ struct ifp_ctx *ifp_ctx; ++ struct sss_domain_info *dom; ++ ++ ifp_ctx = talloc_get_type(data, struct ifp_ctx); ++ ++ dom = get_domain_info_from_req(sbus_req, data); ++ if (dom == NULL) { ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, ++ "Unknown domain"); ++ return EOK; ++ } ++ ++ rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH, ++ IFACE_DP_FAILOVER, ++ IFACE_DP_FAILOVER_ACTIVESERVER, ++ DBUS_TYPE_STRING, &service); ++ ++ return EOK; ++} ++ ++int ifp_domains_domain_list_servers(struct sbus_request *sbus_req, ++ void *data, ++ const char *service) ++{ ++ struct ifp_ctx *ifp_ctx; ++ struct sss_domain_info *dom; ++ ++ ifp_ctx = talloc_get_type(data, struct ifp_ctx); ++ ++ dom = get_domain_info_from_req(sbus_req, data); ++ if (dom == NULL) { ++ sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, ++ "Unknown domain"); ++ return EOK; ++ } ++ ++ rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH, ++ IFACE_DP_FAILOVER, ++ IFACE_DP_FAILOVER_LISTSERVERS, ++ DBUS_TYPE_STRING, &service); ++ ++ return EOK; ++} +diff --git a/src/responder/ifp/ifp_domains.h b/src/responder/ifp/ifp_domains.h +index 91645e60701f8f75e89a42e93e2c066def67b018..621ba6158e285911cb8298cef212219dfd3afec8 100644 +--- a/src/responder/ifp/ifp_domains.h ++++ b/src/responder/ifp/ifp_domains.h +@@ -100,4 +100,12 @@ int ifp_domains_domain_is_online(struct sbus_request *sbus_req, + int ifp_domains_domain_list_services(struct sbus_request *sbus_req, + void *data); + ++int ifp_domains_domain_active_server(struct sbus_request *sbus_req, ++ void *data, ++ const char *service); ++ ++int ifp_domains_domain_list_servers(struct sbus_request *sbus_req, ++ void *data, ++ const char *service); ++ + #endif /* IFP_DOMAINS_H_ */ +diff --git a/src/responder/ifp/ifp_iface.c b/src/responder/ifp/ifp_iface.c +index 90bb52b2ccf5207034abbe12bddbfa1eeaf875f7..e6ddc687ba9db878ee39fee5868d1f924d58482d 100644 +--- a/src/responder/ifp/ifp_iface.c ++++ b/src/responder/ifp/ifp_iface.c +@@ -81,7 +81,9 @@ struct iface_ifp_domains iface_ifp_domains = { + struct iface_ifp_domains_domain iface_ifp_domains_domain = { + { &iface_ifp_domains_domain_meta, 0 }, + .IsOnline = ifp_domains_domain_is_online, +- .ListServices = ifp_domains_domain_list_services ++ .ListServices = ifp_domains_domain_list_services, ++ .ActiveServer = ifp_domains_domain_active_server, ++ .ListServers = ifp_domains_domain_list_servers + }; + + struct iface_ifp_users iface_ifp_users = { +diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml +index 7f6f47299deeba4b1baa23d1e63ee7bb17304a59..25b104ad70c0fd84b6c0fe9dbb0dc6e6439c1376 100644 +--- a/src/responder/ifp/ifp_iface.xml ++++ b/src/responder/ifp/ifp_iface.xml +@@ -112,6 +112,16 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c +index 4d3bb5727b03ae64adad14fcdbb3eb5366edb406..6156ca2947434f301d206232f83cfc0647007707 100644 +--- a/src/responder/ifp/ifp_iface_generated.c ++++ b/src/responder/ifp/ifp_iface_generated.c +@@ -558,6 +558,44 @@ int iface_ifp_domains_domain_ListServices_finish(struct sbus_request *req, const + DBUS_TYPE_INVALID); + } + ++/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ActiveServer */ ++const struct sbus_arg_meta iface_ifp_domains_domain_ActiveServer__in[] = { ++ { "service", "s" }, ++ { NULL, } ++}; ++ ++/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ActiveServer */ ++const struct sbus_arg_meta iface_ifp_domains_domain_ActiveServer__out[] = { ++ { "server", "s" }, ++ { NULL, } ++}; ++ ++int iface_ifp_domains_domain_ActiveServer_finish(struct sbus_request *req, const char *arg_server) ++{ ++ return sbus_request_return_and_finish(req, ++ DBUS_TYPE_STRING, &arg_server, ++ DBUS_TYPE_INVALID); ++} ++ ++/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ListServers */ ++const struct sbus_arg_meta iface_ifp_domains_domain_ListServers__in[] = { ++ { "service_name", "s" }, ++ { NULL, } ++}; ++ ++/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ListServers */ ++const struct sbus_arg_meta iface_ifp_domains_domain_ListServers__out[] = { ++ { "servers", "as" }, ++ { NULL, } ++}; ++ ++int iface_ifp_domains_domain_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers) ++{ ++ return sbus_request_return_and_finish(req, ++ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &arg_servers, len_servers, ++ DBUS_TYPE_INVALID); ++} ++ + /* methods for org.freedesktop.sssd.infopipe.Domains.Domain */ + const struct sbus_method_meta iface_ifp_domains_domain__methods[] = { + { +@@ -574,6 +612,20 @@ const struct sbus_method_meta iface_ifp_domains_domain__methods[] = { + offsetof(struct iface_ifp_domains_domain, ListServices), + NULL, /* no invoker */ + }, ++ { ++ "ActiveServer", /* name */ ++ iface_ifp_domains_domain_ActiveServer__in, ++ iface_ifp_domains_domain_ActiveServer__out, ++ offsetof(struct iface_ifp_domains_domain, ActiveServer), ++ invoke_s_method, ++ }, ++ { ++ "ListServers", /* name */ ++ iface_ifp_domains_domain_ListServers__in, ++ iface_ifp_domains_domain_ListServers__out, ++ offsetof(struct iface_ifp_domains_domain, ListServers), ++ invoke_s_method, ++ }, + { NULL, } + }; + +diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h +index 2eff57410e5292a05818050b96eb85aa3a4f2e16..141348249d2da5447fa04495564a8c6a55d67a1b 100644 +--- a/src/responder/ifp/ifp_iface_generated.h ++++ b/src/responder/ifp/ifp_iface_generated.h +@@ -58,6 +58,8 @@ + #define IFACE_IFP_DOMAINS_DOMAIN "org.freedesktop.sssd.infopipe.Domains.Domain" + #define IFACE_IFP_DOMAINS_DOMAIN_ISONLINE "IsOnline" + #define IFACE_IFP_DOMAINS_DOMAIN_LISTSERVICES "ListServices" ++#define IFACE_IFP_DOMAINS_DOMAIN_ACTIVESERVER "ActiveServer" ++#define IFACE_IFP_DOMAINS_DOMAIN_LISTSERVERS "ListServers" + + /* constants for org.freedesktop.sssd.infopipe.Cache */ + #define IFACE_IFP_CACHE "org.freedesktop.sssd.infopipe.Cache" +@@ -215,6 +217,8 @@ struct iface_ifp_domains_domain { + struct sbus_vtable vtable; /* derive from sbus_vtable */ + int (*IsOnline)(struct sbus_request *req, void *data); + int (*ListServices)(struct sbus_request *req, void *data); ++ int (*ActiveServer)(struct sbus_request *req, void *data, const char *arg_service); ++ int (*ListServers)(struct sbus_request *req, void *data, const char *arg_service_name); + }; + + /* finish function for IsOnline */ +@@ -223,6 +227,12 @@ int iface_ifp_domains_domain_IsOnline_finish(struct sbus_request *req, bool arg_ + /* finish function for ListServices */ + int iface_ifp_domains_domain_ListServices_finish(struct sbus_request *req, const char *arg_services[], int len_services); + ++/* finish function for ActiveServer */ ++int iface_ifp_domains_domain_ActiveServer_finish(struct sbus_request *req, const char *arg_server); ++ ++/* finish function for ListServers */ ++int iface_ifp_domains_domain_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers); ++ + /* vtable for org.freedesktop.sssd.infopipe.Cache */ + struct iface_ifp_cache { + struct sbus_vtable vtable; /* derive from sbus_vtable */ +diff --git a/src/tools/sssctl/sssctl_domains.c b/src/tools/sssctl/sssctl_domains.c +index 40962792b84eabeb2c142f158184b17180a01669..545ed95f4415da597b191146409ea6ba028f36f8 100644 +--- a/src/tools/sssctl/sssctl_domains.c ++++ b/src/tools/sssctl/sssctl_domains.c +@@ -112,6 +112,155 @@ done: + return ret; + } + ++static const char *proper_service_name(const char *service) ++{ ++ if (strcasecmp(service, "AD_GC") == 0) { ++ return "AD Global Catalog"; ++ } else if (strcasecmp(service, "AD") == 0) { ++ return "AD Domain Controller"; ++ } else if (strncasecmp(service, "sd_gc_", strlen("sd_gc_")) == 0) { ++ return "AD Global Catalog"; ++ } else if (strncasecmp(service, "sd_", strlen("sd_")) == 0) { ++ return "AD Domain Controller"; ++ } ++ ++ return service; ++} ++ ++static errno_t sssctl_domain_status_active_server(struct sss_tool_ctx *tool_ctx, ++ sss_sifp_ctx *sifp, ++ const char *domain_path) ++{ ++ TALLOC_CTX *tmp_ctx; ++ sss_sifp_error error; ++ DBusMessage *reply; ++ const char *server; ++ const char **services; ++ int num_services; ++ errno_t ret; ++ int i; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); ++ return ENOMEM; ++ } ++ ++ error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, ++ IFACE_IFP_DOMAINS_DOMAIN, ++ IFACE_IFP_DOMAINS_DOMAIN_LISTSERVICES); ++ if (error != SSS_SIFP_OK) { ++ sssctl_sifp_error(sifp, error, "Unable to list services"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = sbus_parse_reply(reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, ++ &services, &num_services); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ printf(_("Active servers:\n")); ++ for (i = 0; i < num_services; i++) { ++ error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, ++ IFACE_IFP_DOMAINS_DOMAIN, ++ IFACE_IFP_DOMAINS_DOMAIN_ACTIVESERVER, ++ DBUS_TYPE_STRING, &services[i]); ++ if (error != SSS_SIFP_OK) { ++ sssctl_sifp_error(sifp, error, "Unable to get active server"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = sbus_parse_reply(reply, DBUS_TYPE_STRING, &server); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ server = SBUS_IS_STRING_EMPTY(server) ? _("not connected") : server; ++ printf("%s: %s\n", proper_service_name(services[i]), server); ++ } ++ ++ ret = EOK; ++ ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ ++static errno_t sssctl_domain_status_server_list(struct sss_tool_ctx *tool_ctx, ++ sss_sifp_ctx *sifp, ++ const char *domain_path) ++{ ++ TALLOC_CTX *tmp_ctx; ++ sss_sifp_error error; ++ DBusMessage *reply; ++ const char **servers; ++ int num_servers; ++ const char **services; ++ int num_services; ++ errno_t ret; ++ int i, j; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); ++ return ENOMEM; ++ } ++ ++ error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, ++ IFACE_IFP_DOMAINS_DOMAIN, ++ IFACE_IFP_DOMAINS_DOMAIN_LISTSERVICES); ++ if (error != SSS_SIFP_OK) { ++ sssctl_sifp_error(sifp, error, "Unable to list services"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = sbus_parse_reply(reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, ++ &services, &num_services); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ for (i = 0; i < num_services; i++) { ++ printf(_("Discovered %s servers:\n"), proper_service_name(services[i])); ++ error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, ++ IFACE_IFP_DOMAINS_DOMAIN, ++ IFACE_IFP_DOMAINS_DOMAIN_LISTSERVERS, ++ DBUS_TYPE_STRING, &services[i]); ++ if (error != SSS_SIFP_OK) { ++ sssctl_sifp_error(sifp, error, "Unable to get active server"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = sbus_parse_reply(reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, ++ &servers, &num_servers); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ if (num_servers == 0) { ++ puts(_("None so far.\n")); ++ continue; ++ } ++ ++ for (j = 0; j < num_servers; j++) { ++ printf("- %s\n", servers[j]); ++ } ++ ++ printf("\n"); ++ } ++ ++ ret = EOK; ++ ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ + struct sssctl_domain_status_opts { + const char *domain; + int online; +@@ -135,11 +284,8 @@ errno_t sssctl_domain_status(struct sss_cmdline *cmdline, + /* Parse command line. */ + struct poptOption options[] = { + {"online", 'o', POPT_ARG_NONE , &opts.online, 0, _("Show online status"), NULL }, +- /* +- {"last-requests", 'l', POPT_ARG_NONE, &opts.last, 0, _("Show last requests that went to data provider"), NULL }, + {"active-server", 'a', POPT_ARG_NONE, &opts.active, 0, _("Show information about active server"), NULL }, + {"servers", 'r', POPT_ARG_NONE, &opts.servers, 0, _("Show list of discovered servers"), NULL }, +- */ + {"start", 's', POPT_ARG_NONE, &opts.force_start, 0, _("Start SSSD if it is not running"), NULL }, + POPT_TABLEEND + }; +@@ -175,10 +321,32 @@ errno_t sssctl_domain_status(struct sss_cmdline *cmdline, + return EFAULT; + } + +- ret = sssctl_domain_status_online(tool_ctx, sifp, path); +- if (ret != EOK) { +- fprintf(stderr, _("Unable to get online status\n")); +- return ret; ++ if (opts.online) { ++ ret = sssctl_domain_status_online(tool_ctx, sifp, path); ++ if (ret != EOK) { ++ fprintf(stderr, _("Unable to get online status\n")); ++ return ret; ++ } ++ ++ printf("\n"); ++ } ++ ++ if (opts.active) { ++ ret = sssctl_domain_status_active_server(tool_ctx, sifp, path); ++ if (ret != EOK) { ++ fprintf(stderr, _("Unable to get online status\n")); ++ return ret; ++ } ++ ++ printf("\n"); ++ } ++ ++ if (opts.servers) { ++ ret = sssctl_domain_status_server_list(tool_ctx, sifp, path); ++ if (ret != EOK) { ++ fprintf(stderr, _("Unable to get server list\n")); ++ return ret; ++ } + } + + return EOK; +-- +2.4.11 + diff --git a/SOURCES/0097-AD-inicialize-root_domain_attrs-field.patch b/SOURCES/0097-AD-inicialize-root_domain_attrs-field.patch deleted file mode 100644 index 2537ab2..0000000 --- a/SOURCES/0097-AD-inicialize-root_domain_attrs-field.patch +++ /dev/null @@ -1,41 +0,0 @@ -From d97d6d3acc32d0e4914a1d2c39bfb7fa8ecc7197 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Thu, 24 Sep 2015 11:03:12 -0400 -Subject: [PATCH 97/97] AD: inicialize root_domain_attrs field -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves: -https://fedorahosted.org/sssd/ticket/2805 - -Reviewed-by: Pavel Březina -(cherry picked from commit 101628a48d25ffae3b13c75d0b0b01577188c803) ---- - src/providers/ad/ad_subdomains.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c -index 8ed3dab0995f78a16f4a7df2e729ea88a39a782c..c2a6544fb7f146058acee9baca9b0cc6ee50aa3f 100644 ---- a/src/providers/ad/ad_subdomains.c -+++ b/src/providers/ad/ad_subdomains.c -@@ -505,7 +505,7 @@ static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx, - int dp_error = DP_ERR_FATAL; - int ret; - -- req_ctx = talloc(be_req, struct ad_subdomains_req_ctx); -+ req_ctx = talloc_zero(be_req, struct ad_subdomains_req_ctx); - if (req_ctx == NULL) { - ret = ENOMEM; - goto done; -@@ -519,6 +519,7 @@ static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx, - req_ctx->root_id_ctx = NULL; - req_ctx->root_op = NULL; - req_ctx->root_domain = NULL; -+ req_ctx->root_domain_attrs = NULL; - req_ctx->reply_count = 0; - req_ctx->reply = NULL; - --- -2.4.3 - diff --git a/SOURCES/0097-sifp-fix-coverity-warning.patch b/SOURCES/0097-sifp-fix-coverity-warning.patch new file mode 100644 index 0000000..6a761a7 --- /dev/null +++ b/SOURCES/0097-sifp-fix-coverity-warning.patch @@ -0,0 +1,47 @@ +From 87f7c2f1f44085963b41eb78e337840ddbc7be76 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 14 Jul 2016 10:49:37 +0200 +Subject: [PATCH 097/102] sifp: fix coverity warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sssd-1.14.1/src/lib/sifp/sss_sifp_dbus.c:51: check_return: + Calling "dbus_message_append_args_valist" without checking return value + (as is done elsewhere 4 out of 5 times). + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit de5160e354c02020f0593c7cabdb811107d5d8e2) +--- + src/lib/sifp/sss_sifp_dbus.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/lib/sifp/sss_sifp_dbus.c b/src/lib/sifp/sss_sifp_dbus.c +index 7c72c52f0d226ccdfaf7b8ffaed7776647a7771c..2906c5ac383c412231127f6ffa8081d47eb2bced 100644 +--- a/src/lib/sifp/sss_sifp_dbus.c ++++ b/src/lib/sifp/sss_sifp_dbus.c +@@ -36,6 +36,7 @@ static sss_sifp_error sss_sifp_ifp_call(sss_sifp_ctx *ctx, + { + DBusMessage *msg = NULL; + sss_sifp_error ret; ++ dbus_bool_t bret; + + if (object_path == NULL || interface == NULL || method == NULL) { + return SSS_SIFP_INVALID_ARGUMENT; +@@ -48,7 +49,11 @@ static sss_sifp_error sss_sifp_ifp_call(sss_sifp_ctx *ctx, + } + + if (first_arg_type != DBUS_TYPE_INVALID) { +- dbus_message_append_args_valist(msg, first_arg_type, ap); ++ bret = dbus_message_append_args_valist(msg, first_arg_type, ap); ++ if (!bret) { ++ ret = SSS_SIFP_IO_ERROR; ++ goto done; ++ } + } + + ret = sss_sifp_send_message(ctx, msg, _reply); +-- +2.4.11 + diff --git a/SOURCES/0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch b/SOURCES/0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch deleted file mode 100644 index 2168ab2..0000000 --- a/SOURCES/0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 63c52299e122a05e7b25b5ee94b528fe64a6c6ef Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 1 Oct 2015 10:10:22 +0200 -Subject: [PATCH 98/99] PAM: only allow missing user name for certificate - authentication -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves: -https://fedorahosted.org/sssd/ticket/2811 - -Reviewed-by: Lukáš Slebodník -(cherry picked from commit 2e76b32e74abedb23665808bacc73cafd1097c37) -(cherry picked from commit ba9d5c0456a2fbb9adf9b4b4dffbfb190628a273) ---- - src/responder/pam/pamsrv_cmd.c | 12 +++++++++--- - src/tests/cmocka/test_pam_srv.c | 41 +++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 50 insertions(+), 3 deletions(-) - -diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c -index aa5c20906a36351e425304122517c81676e730b7..ae14b9287268ffb36500b0cfdb38e69adb0ecce9 100644 ---- a/src/responder/pam/pamsrv_cmd.c -+++ b/src/responder/pam/pamsrv_cmd.c -@@ -962,11 +962,13 @@ static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *p - } else { - /* Only SSS_PAM_PREAUTH request may have a missing name, e.g. if the - * name is determined with the help of a certificate */ -- if (pd->cmd == SSS_PAM_PREAUTH) { -+ if (pd->cmd == SSS_PAM_PREAUTH -+ && may_do_cert_auth(talloc_get_type(cctx->rctx->pvt_ctx, -+ struct pam_ctx), pd)) { - ret = EOK; - } else { - DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n"); -- ret = EINVAL; -+ ret = ERR_NO_CREDS; - goto done; - } - } -@@ -1076,7 +1078,6 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) - } - goto done; - } else if (ret != EOK) { -- ret = EINVAL; - goto done; - } - -@@ -1597,6 +1598,11 @@ static int pam_check_user_done(struct pam_auth_req *preq, int ret) - pam_reply(preq); - break; - -+ case ERR_NO_CREDS: -+ preq->pd->pam_status = PAM_CRED_INSUFFICIENT; -+ pam_reply(preq); -+ break; -+ - default: - preq->pd->pam_status = PAM_SYSTEM_ERR; - pam_reply(preq); -diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c -index 3c70c599060e09125ab5b73ce3d2698eaa3006bd..0ae2554032d28329ebb1d6ad09cfd859cf9b4260 100644 ---- a/src/tests/cmocka/test_pam_srv.c -+++ b/src/tests/cmocka/test_pam_srv.c -@@ -596,6 +596,23 @@ static int test_pam_wrong_pw_offline_auth_check(uint32_t status, - return test_pam_simple_check(status, body, blen); - } - -+static int test_pam_creds_insufficient_check(uint32_t status, -+ uint8_t *body, size_t blen) -+{ -+ size_t rp = 0; -+ uint32_t val; -+ -+ assert_int_equal(status, 0); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, PAM_CRED_INSUFFICIENT); -+ -+ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); -+ assert_int_equal(val, 0); -+ -+ return EOK; -+} -+ - static int test_pam_user_unknown_check(uint32_t status, - uint8_t *body, size_t blen) - { -@@ -1100,6 +1117,25 @@ void test_pam_offline_chauthtok(void **state) - assert_int_equal(ret, EOK); - } - -+void test_pam_preauth_no_logon_name(void **state) -+{ -+ int ret; -+ -+ mock_input_pam_cert(pam_test_ctx, NULL, NULL); -+ -+ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); -+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); -+ -+ set_cmd_cb(test_pam_creds_insufficient_check); -+ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, -+ pam_test_ctx->pam_cmds); -+ assert_int_equal(ret, EOK); -+ -+ /* Wait until the test finishes with EOK */ -+ ret = test_ev_loop(pam_test_ctx->tctx); -+ assert_int_equal(ret, EOK); -+} -+ - static void set_cert_auth_param(struct pam_ctx *pctx, const char *dbpath) - { - pam_test_ctx->pctx->cert_auth = true; -@@ -1405,6 +1441,8 @@ int main(int argc, const char *argv[]) - pam_test_setup, pam_test_teardown), - cmocka_unit_test_setup_teardown(test_pam_offline_chauthtok, - pam_test_setup, pam_test_teardown), -+/* p11_child is not built without NSS */ -+#ifdef HAVE_NSS - cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nocert, - pam_test_setup, pam_test_teardown), - cmocka_unit_test_setup_teardown(test_pam_preauth_cert_nomatch, -@@ -1422,6 +1460,9 @@ int main(int argc, const char *argv[]) - pam_test_setup, pam_test_teardown), - cmocka_unit_test_setup_teardown(test_pam_cert_auth, - pam_test_setup, pam_test_teardown), -+ cmocka_unit_test_setup_teardown(test_pam_preauth_no_logon_name, -+ pam_test_setup, pam_test_teardown), -+#endif - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.4.3 - diff --git a/SOURCES/0098-sbus-allow-freeing-msg-through-dbus-api-when-using-t.patch b/SOURCES/0098-sbus-allow-freeing-msg-through-dbus-api-when-using-t.patch new file mode 100644 index 0000000..37be3b9 --- /dev/null +++ b/SOURCES/0098-sbus-allow-freeing-msg-through-dbus-api-when-using-t.patch @@ -0,0 +1,112 @@ +From efb18a2688546db9c6fe7ba75b595a2fc54dff41 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 15 Jul 2016 14:50:41 +0200 +Subject: [PATCH 098/102] sbus: allow freeing msg through dbus api when using + talloc +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When a talloc-bound message was freed by removing all references +to it with dbus_message_unref we failed to free the talloc context +and thus leaking memory or unreferencing invalid message when +the parent context is freed. + +This patch allows to bound dbus message to talloc in the way that +allows us to free the message by both talloc and dbus api. + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 5d556f70f00c43864d8495d7caacfadf962799df) +--- + src/sbus/sssd_dbus_utils.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +diff --git a/src/sbus/sssd_dbus_utils.c b/src/sbus/sssd_dbus_utils.c +index 4c33f9fd75cac2d4a56a5638982f8ecb73da8e2e..b0150e2fe7f829013677e0a4a894d1468e5b9128 100644 +--- a/src/sbus/sssd_dbus_utils.c ++++ b/src/sbus/sssd_dbus_utils.c +@@ -25,22 +25,52 @@ + + struct sbus_talloc_msg { + DBusMessage *msg; ++ dbus_int32_t data_slot; ++ bool in_talloc_destructor; + }; + + static int sbus_talloc_msg_destructor(struct sbus_talloc_msg *talloc_msg) + { ++ talloc_msg->in_talloc_destructor = true; ++ + if (talloc_msg->msg == NULL) { + return 0; + } + ++ /* There may exist more references to this message but this talloc ++ * context is no longer valid. We remove dbus message data to invoke ++ * dbus destructor now. */ ++ dbus_message_set_data(talloc_msg->msg, talloc_msg->data_slot, NULL, NULL); + dbus_message_unref(talloc_msg->msg); + return 0; + } + ++static void sbus_msg_data_destructor(void *ctx) ++{ ++ struct sbus_talloc_msg *talloc_msg; ++ ++ talloc_msg = talloc_get_type(ctx, struct sbus_talloc_msg); ++ ++ dbus_message_free_data_slot(&talloc_msg->data_slot); ++ ++ if (!talloc_msg->in_talloc_destructor) { ++ /* References to this message dropped to zero but through ++ * dbus_message_unref(), not by calling talloc_free(). We need to free ++ * the talloc context and avoid running talloc desctuctor. */ ++ talloc_set_destructor(talloc_msg, NULL); ++ talloc_free(talloc_msg); ++ } ++} ++ + errno_t sbus_talloc_bound_message(TALLOC_CTX *mem_ctx, DBusMessage *msg) + { + struct sbus_talloc_msg *talloc_msg; ++ dbus_int32_t data_slot = -1; ++ DBusFreeFunction free_fn; ++ dbus_bool_t bret; + ++ /* Create a talloc context that will unreference this message when ++ * the parent context is freed. */ + talloc_msg = talloc(mem_ctx, struct sbus_talloc_msg); + if (talloc_msg == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, +@@ -48,7 +78,28 @@ errno_t sbus_talloc_bound_message(TALLOC_CTX *mem_ctx, DBusMessage *msg) + return ENOMEM; + } + ++ /* Allocate a dbus message data slot that will contain point to the ++ * talloc context so we can pick up cases when the dbus message is ++ * freed through dbus api. */ ++ bret = dbus_message_allocate_data_slot(&data_slot); ++ if (!bret) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate data slot!\n"); ++ talloc_free(talloc_msg); ++ return ENOMEM; ++ } ++ ++ free_fn = sbus_msg_data_destructor; ++ bret = dbus_message_set_data(msg, data_slot, talloc_msg, free_fn); ++ if (!bret) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set message data!\n"); ++ talloc_free(talloc_msg); ++ dbus_message_free_data_slot(&data_slot); ++ return ENOMEM; ++ } ++ + talloc_msg->msg = msg; ++ talloc_msg->data_slot = data_slot; ++ talloc_msg->in_talloc_destructor = false; + + talloc_set_destructor(talloc_msg, sbus_talloc_msg_destructor); + +-- +2.4.11 + diff --git a/SOURCES/0099-Fix-memory-leak-in-sssdpac_verify.patch b/SOURCES/0099-Fix-memory-leak-in-sssdpac_verify.patch deleted file mode 100644 index 3324d44..0000000 --- a/SOURCES/0099-Fix-memory-leak-in-sssdpac_verify.patch +++ /dev/null @@ -1,30 +0,0 @@ -From d600e8bedf05d447ba84d9a89be7d46ba34f1b5d Mon Sep 17 00:00:00 2001 -From: Thomas Oulevey -Date: Wed, 23 Sep 2015 10:55:59 +0200 -Subject: [PATCH 99/99] Fix memory leak in sssdpac_verify() - -Resolves https://fedorahosted.org/sssd/ticket/2803 - -Reviewed-by: Sumit Bose -(cherry picked from commit b4c44ebb8997d3debb33607c123ccfd9926e0cba) ---- - src/sss_client/sssd_pac.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/sss_client/sssd_pac.c b/src/sss_client/sssd_pac.c -index 1939f61b18398f62a3e3d6b29cc4fef151b1c3b7..1d98e38826b36aed199b32880a7e27de905a4592 100644 ---- a/src/sss_client/sssd_pac.c -+++ b/src/sss_client/sssd_pac.c -@@ -150,6 +150,9 @@ static krb5_error_code sssdpac_verify(krb5_context kcontext, - kerr = krb5_pac_verify(kcontext, pac, - req->ticket->enc_part2->times.authtime, - req->ticket->enc_part2->client, key, NULL); -+ /* deallocate pac */ -+ krb5_pac_free(kcontext, pac); -+ pac = NULL; - if (kerr != 0) { - /* The krb5 documentation says: - * A checksum mismatch can occur if the PAC was copied from a --- -2.4.3 - diff --git a/SOURCES/0099-PROXY-Do-not-abuse-data-provider-interface.patch b/SOURCES/0099-PROXY-Do-not-abuse-data-provider-interface.patch new file mode 100644 index 0000000..df4370b --- /dev/null +++ b/SOURCES/0099-PROXY-Do-not-abuse-data-provider-interface.patch @@ -0,0 +1,730 @@ +From 4b23c3128726fe59e02d28352e37bb0ff7f97640 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 15 Jul 2016 14:20:32 +0200 +Subject: [PATCH 099/102] PROXY: Do not abuse data provider interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We want to use custom interface for proxy provider so we do not +abuse the data provider one. This way we gain more control over +it and we can remove the old interface entirely. + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit e07d700ed9daf0cf96607fa2d72978cb2431b794) +--- + Makefile.am | 6 +- + src/providers/dp_auth_util.c | 64 --------------- + src/providers/proxy/proxy.h | 2 + + src/providers/proxy/proxy_auth.c | 8 +- + src/providers/proxy/proxy_child.c | 119 +++++++++++++++------------- + src/providers/proxy/proxy_client.c | 108 +++++++++++-------------- + src/providers/proxy/proxy_iface.xml | 17 ++++ + src/providers/proxy/proxy_iface_generated.c | 80 +++++++++++++++++++ + src/providers/proxy/proxy_iface_generated.h | 71 +++++++++++++++++ + 9 files changed, 288 insertions(+), 187 deletions(-) + create mode 100644 src/providers/proxy/proxy_iface.xml + create mode 100644 src/providers/proxy/proxy_iface_generated.c + create mode 100644 src/providers/proxy/proxy_iface_generated.h + +diff --git a/Makefile.am b/Makefile.am +index 1837e36da7302cb51c0b90e51b762ce0a87cd65f..5d54838659e44fa446fc921d014e48ac91469b25 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -715,6 +715,7 @@ dist_noinst_HEADERS = \ + src/providers/ad/ad_domain_info.h \ + src/providers/ad/ad_subdomains.h \ + src/providers/proxy/proxy.h \ ++ src/providers/proxy/proxy_iface_generated.h \ + src/tools/tools_util.h \ + src/tools/sss_sync_ops.h \ + src/resolv/async_resolv.h \ +@@ -1197,6 +1198,7 @@ CODEGEN_XML = \ + $(srcdir)/src/monitor/monitor_iface.xml \ + $(srcdir)/src/providers/data_provider_iface.xml \ + $(srcdir)/src/providers/data_provider/dp_iface.xml \ ++ $(srcdir)/src/providers/proxy/proxy_iface.xml \ + $(srcdir)/src/responder/ifp/ifp_iface.xml + + SBUS_CODEGEN = src/sbus/sbus_codegen +@@ -3337,7 +3339,7 @@ libsss_proxy_la_SOURCES = \ + src/providers/proxy/proxy_netgroup.c \ + src/providers/proxy/proxy_services.c \ + src/providers/proxy/proxy_auth.c \ +- src/providers/data_provider_iface_generated.c \ ++ src/providers/proxy/proxy_iface_generated.c \ + $(NULL) + libsss_proxy_la_CFLAGS = \ + $(AM_CFLAGS) +@@ -3606,7 +3608,7 @@ gpo_child_LDADD = \ + + proxy_child_SOURCES = \ + src/providers/proxy/proxy_child.c \ +- src/providers/data_provider_iface_generated.c \ ++ src/providers/proxy/proxy_iface_generated.c \ + $(NULL) + proxy_child_CFLAGS = \ + $(AM_CFLAGS) \ +diff --git a/src/providers/dp_auth_util.c b/src/providers/dp_auth_util.c +index 8c09299b12c703ed703a025d1e8cfe5df2088eb2..35d22ab5f24ba2300889256f477a9ed856b69cb9 100644 +--- a/src/providers/dp_auth_util.c ++++ b/src/providers/dp_auth_util.c +@@ -321,67 +321,3 @@ bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *db + + return true; + } +- +-void dp_id_callback(DBusPendingCall *pending, void *ptr) +-{ +- DBusMessage *reply; +- DBusError dbus_error; +- dbus_bool_t ret; +- dbus_uint16_t dp_ver; +- int type; +- +- dbus_error_init(&dbus_error); +- +- reply = dbus_pending_call_steal_reply(pending); +- if (!reply) { +- /* reply should never be null. This function shouldn't be called +- * until reply is valid or timeout has occurred. If reply is NULL +- * here, something is seriously wrong and we should bail out. +- */ +- DEBUG(SSSDBG_FATAL_FAILURE, +- "Severe error. A reply callback was called but no" +- " reply was received and no timeout occurred\n"); +- +- /* FIXME: Destroy this connection ? */ +- goto done; +- } +- +- type = dbus_message_get_type(reply); +- switch (type) { +- case DBUS_MESSAGE_TYPE_METHOD_RETURN: +- ret = dbus_message_get_args(reply, &dbus_error, +- DBUS_TYPE_UINT16, &dp_ver, +- DBUS_TYPE_INVALID); +- if (!ret) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse message\n"); +- if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error); +- /* FIXME: Destroy this connection ? */ +- goto done; +- } +- +- DEBUG(SSSDBG_CONF_SETTINGS, +- "Got id ack and version (%d) from DP\n", dp_ver); +- +- break; +- +- case DBUS_MESSAGE_TYPE_ERROR: +- DEBUG(SSSDBG_FATAL_FAILURE,"The Monitor returned an error [%s]\n", +- dbus_message_get_error_name(reply)); +- /* Falling through to default intentionally*/ +- default: +- /* +- * Timeout or other error occurred or something +- * unexpected happened. +- * It doesn't matter which, because either way we +- * know that this connection isn't trustworthy. +- * We'll destroy it now. +- */ +- +- /* FIXME: Destroy this connection ? */ +- break; +- } +- +-done: +- dbus_pending_call_unref(pending); +- dbus_message_unref(reply); +-} +diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h +index 11c85c54ea64db7ad9feb163bd5a86f65ac0ea90..6f91782bb06ea8bbf3ac35052b840dd21300b96e 100644 +--- a/src/providers/proxy/proxy.h ++++ b/src/providers/proxy/proxy.h +@@ -42,6 +42,8 @@ + #include "sss_client/nss_compat.h" + #include + ++#define PROXY_CHILD_PATH "/org/freedesktop/sssd/proxychild" ++ + struct proxy_nss_ops { + enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop); +diff --git a/src/providers/proxy/proxy_auth.c b/src/providers/proxy/proxy_auth.c +index 6e7139aaa5d45631fa08f265c54b66ab97555a64..2b3510c38b1cb265e3042425c373f39e524a71eb 100644 +--- a/src/providers/proxy/proxy_auth.c ++++ b/src/providers/proxy/proxy_auth.c +@@ -23,6 +23,7 @@ + */ + + #include "providers/proxy/proxy.h" ++#include "providers/proxy/proxy_iface_generated.h" + + struct pc_init_ctx; + +@@ -531,9 +532,9 @@ static struct tevent_req *proxy_pam_conv_send(TALLOC_CTX *mem_ctx, + state->pid = pid; + + msg = dbus_message_new_method_call(NULL, +- DP_PATH, +- DATA_PROVIDER_IFACE, +- DATA_PROVIDER_IFACE_PAMHANDLER); ++ PROXY_CHILD_PATH, ++ IFACE_PROXY_AUTH, ++ IFACE_PROXY_AUTH_PAM); + if (msg == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "dbus_message_new_method_call failed.\n"); + talloc_zfree(req); +@@ -847,4 +848,3 @@ proxy_pam_handler_recv(TALLOC_CTX *mem_ctx, + + return EOK; + } +- +diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c +index efd304d5aafd5e53792ef96b75d8aa0c908bbe13..b492adcb3b5efefc08e6eb9e069035aeff8d34df 100644 +--- a/src/providers/proxy/proxy_child.c ++++ b/src/providers/proxy/proxy_child.c +@@ -44,22 +44,10 @@ + #include "confdb/confdb.h" + #include "sbus/sssd_dbus.h" + #include "providers/proxy/proxy.h" ++#include "providers/proxy/proxy_iface_generated.h" + + #include "providers/backend.h" + +-static int pc_pam_handler(struct sbus_request *dbus_req, void *user_data); +- +-struct data_provider_iface pc_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = NULL, +- .pamHandler = pc_pam_handler, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + struct pc_ctx { + struct tevent_context *ev; + struct confdb_ctx *cdb; +@@ -382,17 +370,71 @@ done: + exit(ret); + } + +-int proxy_child_send_id(struct sbus_connection *conn, +- uint16_t version, +- uint32_t id); ++static void proxy_child_id_callback(DBusPendingCall *pending, void *ptr) ++{ ++ DBusMessage *reply; ++ errno_t ret; ++ ++ reply = dbus_pending_call_steal_reply(pending); ++ if (reply == NULL) { ++ /* reply should never be null. This function shouldn't be called ++ * until reply is valid or timeout has occurred. If reply is NULL ++ * here, something is seriously wrong and we should bail out. ++ */ ++ DEBUG(SSSDBG_FATAL_FAILURE, "Severe error. A reply callback was " ++ "called but no reply was received and no timeout occurred\n"); ++ goto done; ++ } ++ ++ ret = sbus_parse_reply(reply); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get ID ack [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ } ++ ++ DEBUG(SSSDBG_TRACE_FUNC, "Got id ack from proxy child\n"); ++ ++done: ++ dbus_pending_call_unref(pending); ++ dbus_message_unref(reply); ++} ++ ++static errno_t proxy_child_send_id(struct sbus_connection *conn, uint32_t id) ++{ ++ DBusMessage *msg; ++ errno_t ret; ++ ++ msg = sbus_create_message(NULL, NULL, PROXY_CHILD_PATH, IFACE_PROXY_CLIENT, ++ IFACE_PROXY_CLIENT_REGISTER, ++ DBUS_TYPE_UINT32, &id); ++ if (msg == NULL) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?!\n"); ++ return ENOMEM; ++ } ++ ++ DEBUG(SSSDBG_TRACE_FUNC, "Sending ID to Proxy Backend: (%"PRIu32")\n", id); ++ ++ ret = sbus_conn_send(conn, msg, 30000, proxy_child_id_callback, NULL, NULL); ++ ++ dbus_message_unref(msg); ++ ++ return ret; ++} ++ + static int proxy_cli_init(struct pc_ctx *ctx) + { + char *sbus_address; + int ret; + ++ static struct iface_proxy_auth iface_proxy_auth = { ++ { &iface_proxy_auth_meta, 0 }, ++ ++ .PAM = pc_pam_handler, ++ }; ++ + sbus_address = talloc_asprintf(ctx, "unix:path=%s/%s_%s", +- PIPE_PATH, PROXY_CHILD_PIPE, +- ctx->domain->name); ++ PIPE_PATH, PROXY_CHILD_PIPE, ++ ctx->domain->name); + if (sbus_address == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf failed.\n"); + return ENOMEM; +@@ -404,13 +446,14 @@ static int proxy_cli_init(struct pc_ctx *ctx) + return ret; + } + +- ret = sbus_conn_register_iface(ctx->conn, &pc_methods.vtable, DP_PATH, ctx); ++ ret = sbus_conn_register_iface(ctx->conn, &iface_proxy_auth.vtable, ++ PROXY_CHILD_PATH, ctx); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to export proxy.\n"); + return ret; + } + +- ret = proxy_child_send_id(ctx->conn, DATA_PROVIDER_VERSION, ctx->id); ++ ret = proxy_child_send_id(ctx->conn, ctx->id); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "dp_common_send_id failed.\n"); + return ret; +@@ -419,42 +462,6 @@ static int proxy_cli_init(struct pc_ctx *ctx) + return EOK; + } + +-int proxy_child_send_id(struct sbus_connection *conn, +- uint16_t version, +- uint32_t id) +-{ +- DBusMessage *msg; +- dbus_bool_t ret; +- int retval; +- +- /* create the message */ +- msg = dbus_message_new_method_call(NULL, +- DP_PATH, +- DATA_PROVIDER_IFACE, +- DATA_PROVIDER_IFACE_REGISTERSERVICE); +- if (msg == NULL) { +- DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?!\n"); +- return ENOMEM; +- } +- +- DEBUG(SSSDBG_FUNC_DATA, "Sending ID to Proxy Backend: (%d,%"PRIu32")\n", +- version, id); +- +- ret = dbus_message_append_args(msg, +- DBUS_TYPE_UINT16, &version, +- DBUS_TYPE_UINT32, &id, +- DBUS_TYPE_INVALID); +- if (!ret) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build message\n"); +- return EIO; +- } +- +- retval = sbus_conn_send(conn, msg, 30000, dp_id_callback, NULL, NULL); +- +- dbus_message_unref(msg); +- return retval; +-} +- + int proxy_child_process_init(TALLOC_CTX *mem_ctx, const char *domain, + struct tevent_context *ev, struct confdb_ctx *cdb, + const char *pam_target, uint32_t id) +diff --git a/src/providers/proxy/proxy_client.c b/src/providers/proxy/proxy_client.c +index fc1735f2a101528a1edeaf3cf9c1118e4a21e937..74957caeec5bf50b5cb959d6f5b8ec1ca9ecba37 100644 +--- a/src/providers/proxy/proxy_client.c ++++ b/src/providers/proxy/proxy_client.c +@@ -22,24 +22,10 @@ + along with this program. If not, see . + */ + +-#include "config.h" +- +-#include "util/sss_format.h" ++#include "util/util.h" ++#include "providers/proxy/proxy_iface_generated.h" + #include "providers/proxy/proxy.h" + +-static int client_registration(struct sbus_request *dbus_req, void *data); +- +-static struct data_provider_iface proxy_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = client_registration, +- .pamHandler = NULL, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + struct proxy_client { + struct proxy_auth_ctx *proxy_auth_ctx; + struct sbus_connection *conn; +@@ -47,24 +33,22 @@ struct proxy_client { + bool initialized; + }; + +-static int client_registration(struct sbus_request *dbus_req, void *data) ++static int proxy_client_register(struct sbus_request *sbus_req, ++ void *data, ++ uint32_t cli_id) + { +- dbus_uint16_t version = DATA_PROVIDER_VERSION; + struct sbus_connection *conn; + struct proxy_client *proxy_cli; +- dbus_uint16_t cli_ver; +- uint32_t cli_id; + int hret; + hash_key_t key; + hash_value_t value; + struct tevent_req *req; + struct proxy_child_ctx *child_ctx; + struct pc_init_ctx *init_ctx; +- int ret; + +- conn = dbus_req->conn; ++ conn = sbus_req->conn; + proxy_cli = talloc_get_type(data, struct proxy_client); +- if (!proxy_cli) { ++ if (proxy_cli == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Connection holds no valid init data\n"); + return EINVAL; + } +@@ -74,14 +58,6 @@ static int client_registration(struct sbus_request *dbus_req, void *data) + "Cancel proxy client ID timeout [%p]\n", proxy_cli->timeout); + talloc_zfree(proxy_cli->timeout); + +- if (!sbus_request_parse_or_finish(dbus_req, +- DBUS_TYPE_UINT16, &cli_ver, +- DBUS_TYPE_UINT32, &cli_id, +- DBUS_TYPE_INVALID)) { +- sbus_disconnect(conn); +- return EOK; /* handled */ +- } +- + DEBUG(SSSDBG_FUNC_DATA, "Proxy client [%"PRIu32"] connected\n", cli_id); + + /* Check the hash table */ +@@ -94,20 +70,14 @@ static int client_registration(struct sbus_request *dbus_req, void *data) + return EIO; + } + +- /* reply that all is ok */ +- ret = sbus_request_return_and_finish(dbus_req, +- DBUS_TYPE_UINT16, &version, +- DBUS_TYPE_INVALID); +- if (ret != EOK) { +- sbus_disconnect(conn); +- return ret; +- } ++ iface_proxy_client_Register_finish(sbus_req); + + hret = hash_lookup(proxy_cli->proxy_auth_ctx->request_table, &key, &value); + if (hret != HASH_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Hash error [%d][%s]\n", hret, hash_error_string(hret)); ++ "Hash error [%d]: %s\n", hret, hash_error_string(hret)); + sbus_disconnect(conn); ++ return EIO; + } + + /* Signal that the child is up and ready to receive the request */ +@@ -121,7 +91,7 @@ static int client_registration(struct sbus_request *dbus_req, void *data) + * break. + */ + DEBUG(SSSDBG_CRIT_FAILURE, "Client connection from a request " +- "that's not marked as running\n"); ++ "that's not marked as running\n"); + return EIO; + } + +@@ -133,9 +103,10 @@ static int client_registration(struct sbus_request *dbus_req, void *data) + return EOK; + } + +-static void init_timeout(struct tevent_context *ev, +- struct tevent_timer *te, +- struct timeval t, void *ptr) ++static void proxy_client_timeout(struct tevent_context *ev, ++ struct tevent_timer *te, ++ struct timeval t, ++ void *ptr) + { + struct proxy_client *proxy_cli; + +@@ -155,38 +126,53 @@ static void init_timeout(struct tevent_context *ev, + + int proxy_client_init(struct sbus_connection *conn, void *data) + { +- struct proxy_auth_ctx *proxy_auth_ctx; ++ struct proxy_auth_ctx *auth_ctx; + struct proxy_client *proxy_cli; + struct timeval tv; ++ errno_t ret; + +- proxy_auth_ctx = talloc_get_type(data, struct proxy_auth_ctx); ++ static struct iface_proxy_client iface_proxy_client = { ++ { &iface_proxy_client_meta, 0 }, + +- /* hang off this memory to the connection so that when the connection +- * is freed we can potentially call a destructor */ ++ .Register = proxy_client_register, ++ }; + ++ auth_ctx = talloc_get_type(data, struct proxy_auth_ctx); ++ ++ /* When connection is lost we also free the client. */ + proxy_cli = talloc_zero(conn, struct proxy_client); +- if (!proxy_cli) { +- DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n"); +- talloc_zfree(conn); ++ if (proxy_cli == NULL) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory, killing connection.\n"); ++ talloc_free(conn); + return ENOMEM; + } +- proxy_cli->proxy_auth_ctx = proxy_auth_ctx; ++ ++ proxy_cli->proxy_auth_ctx = auth_ctx; + proxy_cli->conn = conn; + proxy_cli->initialized = false; + +- /* 5 seconds should be plenty */ ++ /* Setup timeout in case client fails to register himself in time. */ + tv = tevent_timeval_current_ofs(5, 0); +- +- proxy_cli->timeout = tevent_add_timer(proxy_auth_ctx->be->ev, proxy_cli, +- tv, init_timeout, proxy_cli); +- if (!proxy_cli->timeout) { +- DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n"); +- talloc_zfree(conn); ++ proxy_cli->timeout = tevent_add_timer(auth_ctx->be->ev, proxy_cli, tv, ++ proxy_client_timeout, proxy_cli); ++ if (proxy_cli->timeout == NULL) { ++ /* Connection is closed in the caller. */ ++ DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory, killing connection\n"); + return ENOMEM; + } ++ + DEBUG(SSSDBG_CONF_SETTINGS, + "Set-up proxy client ID timeout [%p]\n", proxy_cli->timeout); + +- return sbus_conn_register_iface(conn, &proxy_methods.vtable, +- DP_PATH, proxy_cli); ++ /* Setup D-Bus interfaces and methods. */ ++ ret = sbus_conn_register_iface(conn, &iface_proxy_client.vtable, ++ PROXY_CHILD_PATH, proxy_cli); ++ if (ret != EOK) { ++ /* Connection is closed in the caller. */ ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register D-Bus interface, " ++ "killing connection [%d]: %s\n", ret, sss_strerror(ret)); ++ return ret; ++ } ++ ++ return ret; + } +diff --git a/src/providers/proxy/proxy_iface.xml b/src/providers/proxy/proxy_iface.xml +new file mode 100644 +index 0000000000000000000000000000000000000000..39b0b03928661a1851fd739598b0194547441c2c +--- /dev/null ++++ b/src/providers/proxy/proxy_iface.xml +@@ -0,0 +1,17 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/providers/proxy/proxy_iface_generated.c b/src/providers/proxy/proxy_iface_generated.c +new file mode 100644 +index 0000000000000000000000000000000000000000..425727d1496b537eb25b002815d14e1f57b8f00d +--- /dev/null ++++ b/src/providers/proxy/proxy_iface_generated.c +@@ -0,0 +1,80 @@ ++/* The following definitions are auto-generated from proxy_iface.xml */ ++ ++#include "util/util.h" ++#include "sbus/sssd_dbus.h" ++#include "sbus/sssd_dbus_meta.h" ++#include "sbus/sssd_dbus_invokers.h" ++#include "proxy_iface_generated.h" ++ ++/* invokes a handler with a 'u' DBus signature */ ++static int invoke_u_method(struct sbus_request *dbus_req, void *function_ptr); ++ ++/* arguments for org.freedesktop.sssd.ProxyChild.Client.Register */ ++const struct sbus_arg_meta iface_proxy_client_Register__in[] = { ++ { "ID", "u" }, ++ { NULL, } ++}; ++ ++int iface_proxy_client_Register_finish(struct sbus_request *req) ++{ ++ return sbus_request_return_and_finish(req, ++ DBUS_TYPE_INVALID); ++} ++ ++/* methods for org.freedesktop.sssd.ProxyChild.Client */ ++const struct sbus_method_meta iface_proxy_client__methods[] = { ++ { ++ "Register", /* name */ ++ iface_proxy_client_Register__in, ++ NULL, /* no out_args */ ++ offsetof(struct iface_proxy_client, Register), ++ invoke_u_method, ++ }, ++ { NULL, } ++}; ++ ++/* interface info for org.freedesktop.sssd.ProxyChild.Client */ ++const struct sbus_interface_meta iface_proxy_client_meta = { ++ "org.freedesktop.sssd.ProxyChild.Client", /* name */ ++ iface_proxy_client__methods, ++ NULL, /* no signals */ ++ NULL, /* no properties */ ++ sbus_invoke_get_all, /* GetAll invoker */ ++}; ++ ++/* methods for org.freedesktop.sssd.ProxyChild.Auth */ ++const struct sbus_method_meta iface_proxy_auth__methods[] = { ++ { ++ "PAM", /* name */ ++ NULL, /* no in_args */ ++ NULL, /* no out_args */ ++ offsetof(struct iface_proxy_auth, PAM), ++ NULL, /* no invoker */ ++ }, ++ { NULL, } ++}; ++ ++/* interface info for org.freedesktop.sssd.ProxyChild.Auth */ ++const struct sbus_interface_meta iface_proxy_auth_meta = { ++ "org.freedesktop.sssd.ProxyChild.Auth", /* name */ ++ iface_proxy_auth__methods, ++ NULL, /* no signals */ ++ NULL, /* no properties */ ++ sbus_invoke_get_all, /* GetAll invoker */ ++}; ++ ++/* invokes a handler with a 'u' DBus signature */ ++static int invoke_u_method(struct sbus_request *dbus_req, void *function_ptr) ++{ ++ uint32_t arg_0; ++ int (*handler)(struct sbus_request *, void *, uint32_t) = function_ptr; ++ ++ if (!sbus_request_parse_or_finish(dbus_req, ++ DBUS_TYPE_UINT32, &arg_0, ++ DBUS_TYPE_INVALID)) { ++ return EOK; /* request handled */ ++ } ++ ++ return (handler)(dbus_req, dbus_req->intf->handler_data, ++ arg_0); ++} +diff --git a/src/providers/proxy/proxy_iface_generated.h b/src/providers/proxy/proxy_iface_generated.h +new file mode 100644 +index 0000000000000000000000000000000000000000..7af074fa3d839263318ceac7ea34f62dcde64563 +--- /dev/null ++++ b/src/providers/proxy/proxy_iface_generated.h +@@ -0,0 +1,71 @@ ++/* The following declarations are auto-generated from proxy_iface.xml */ ++ ++#ifndef __PROXY_IFACE_XML__ ++#define __PROXY_IFACE_XML__ ++ ++#include "sbus/sssd_dbus.h" ++ ++/* ------------------------------------------------------------------------ ++ * DBus Constants ++ * ++ * Various constants of interface and method names mostly for use by clients ++ */ ++ ++/* constants for org.freedesktop.sssd.ProxyChild.Client */ ++#define IFACE_PROXY_CLIENT "org.freedesktop.sssd.ProxyChild.Client" ++#define IFACE_PROXY_CLIENT_REGISTER "Register" ++ ++/* constants for org.freedesktop.sssd.ProxyChild.Auth */ ++#define IFACE_PROXY_AUTH "org.freedesktop.sssd.ProxyChild.Auth" ++#define IFACE_PROXY_AUTH_PAM "PAM" ++ ++/* ------------------------------------------------------------------------ ++ * DBus handlers ++ * ++ * These structures are filled in by implementors of the different ++ * dbus interfaces to handle method calls. ++ * ++ * Handler functions of type sbus_msg_handler_fn accept raw messages, ++ * other handlers are typed appropriately. If a handler that is ++ * set to NULL is invoked it will result in a ++ * org.freedesktop.DBus.Error.NotSupported error for the caller. ++ * ++ * Handlers have a matching xxx_finish() function (unless the method has ++ * accepts raw messages). These finish functions the ++ * sbus_request_return_and_finish() with the appropriate arguments to ++ * construct a valid reply. Once a finish function has been called, the ++ * @dbus_req it was called with is freed and no longer valid. ++ */ ++ ++/* vtable for org.freedesktop.sssd.ProxyChild.Client */ ++struct iface_proxy_client { ++ struct sbus_vtable vtable; /* derive from sbus_vtable */ ++ int (*Register)(struct sbus_request *req, void *data, uint32_t arg_ID); ++}; ++ ++/* finish function for Register */ ++int iface_proxy_client_Register_finish(struct sbus_request *req); ++ ++/* vtable for org.freedesktop.sssd.ProxyChild.Auth */ ++struct iface_proxy_auth { ++ struct sbus_vtable vtable; /* derive from sbus_vtable */ ++ sbus_msg_handler_fn PAM; ++}; ++ ++/* ------------------------------------------------------------------------ ++ * DBus Interface Metadata ++ * ++ * These structure definitions are filled in with the information about ++ * the interfaces, methods, properties and so on. ++ * ++ * The actual definitions are found in the accompanying C file next ++ * to this header. ++ */ ++ ++/* interface info for org.freedesktop.sssd.ProxyChild.Client */ ++extern const struct sbus_interface_meta iface_proxy_client_meta; ++ ++/* interface info for org.freedesktop.sssd.ProxyChild.Auth */ ++extern const struct sbus_interface_meta iface_proxy_auth_meta; ++ ++#endif /* __PROXY_IFACE_XML__ */ +-- +2.4.11 + diff --git a/SOURCES/0100-AD-Provide-common-connection-list-construction-funct.patch b/SOURCES/0100-AD-Provide-common-connection-list-construction-funct.patch deleted file mode 100644 index 33f2ef6..0000000 --- a/SOURCES/0100-AD-Provide-common-connection-list-construction-funct.patch +++ /dev/null @@ -1,241 +0,0 @@ -From 809f139ac4c23dd9db20ea6068e18682f32eb1db Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 1 Oct 2015 13:13:05 +0200 -Subject: [PATCH 100/101] AD: Provide common connection list construction - functions - -https://fedorahosted.org/sssd/ticket/2810 - -Provides a new AD common function ad_ldap_conn_list() that creates a -list of AD connection to use along with properties to avoid mistakes -when manually constructing these lists. - -Reviewed-by: Sumit Bose -(cherry picked from commit 309aa83d16b5919f727af04850bcd0799ba0962f) -(cherry picked from commit 15a4b34ccfcfbcec2c9ba529d0113adf251abc16) ---- - src/providers/ad/ad_common.c | 26 +++++++++++++++++++ - src/providers/ad/ad_common.h | 5 ++++ - src/providers/ad/ad_id.c | 17 +------------ - src/providers/ipa/ipa_subdomains_id.c | 21 ++++++---------- - src/tests/cmocka/test_ad_common.c | 47 ++++++++++++++++++++++++++++++----- - 5 files changed, 81 insertions(+), 35 deletions(-) - -diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c -index 130cdeb613aae3843f7453a478815daaae6aab77..df277e55e234d4d4efe34d5f5d8efdfe7267fb60 100644 ---- a/src/providers/ad/ad_common.c -+++ b/src/providers/ad/ad_common.c -@@ -1236,6 +1236,14 @@ ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom) - subdom_id_ctx = talloc_get_type(sdom->pvt, struct ad_id_ctx); - conn = subdom_id_ctx->ldap_ctx; - -+ if (IS_SUBDOMAIN(sdom->dom) == true && conn != NULL) { -+ /* Regardless of connection types, a subdomain error must not be -+ * allowed to set the whole back end offline, rather report an error -+ * and let the caller deal with it (normally disable the subdomain -+ */ -+ conn->ignore_mark_offline = true; -+ } -+ - return conn; - } - -@@ -1260,3 +1268,21 @@ ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, - - return clist; - } -+ -+struct sdap_id_conn_ctx ** -+ad_ldap_conn_list(TALLOC_CTX *mem_ctx, -+ struct ad_id_ctx *ad_ctx, -+ struct sss_domain_info *dom) -+{ -+ struct sdap_id_conn_ctx **clist; -+ -+ clist = talloc_zero_array(mem_ctx, struct sdap_id_conn_ctx *, 2); -+ if (clist == NULL) { -+ return NULL; -+ } -+ -+ clist[0] = ad_get_dom_ldap_conn(ad_ctx, dom); -+ -+ clist[1] = NULL; -+ return clist; -+} -diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h -index 817f5b42cad7cad6a88244fd43bd91a4358d56c0..701e461987cb286ca7add2766ffb4dc496bde01e 100644 ---- a/src/providers/ad/ad_common.h -+++ b/src/providers/ad/ad_common.h -@@ -148,6 +148,11 @@ struct sdap_id_conn_ctx ** - ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom); - -+struct sdap_id_conn_ctx ** -+ad_ldap_conn_list(TALLOC_CTX *mem_ctx, -+ struct ad_id_ctx *ad_ctx, -+ struct sss_domain_info *dom); -+ - struct sdap_id_conn_ctx * - ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom); - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index ecaf6c993bf7ddb7ba565d40ef0ad250114f5536..be0cb3b12f2e3a2b53d740ecf3befc07fd853f8b 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -269,29 +269,14 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - case BE_REQ_GROUP: /* group */ - case BE_REQ_INITGROUPS: /* init groups for user */ - clist = ad_gc_conn_list(breq, ad_ctx, dom); -- if (clist == NULL) return NULL; - break; - - default: - /* Requests for other object should only contact LDAP by default */ -- clist = talloc_zero_array(breq, struct sdap_id_conn_ctx *, 2); -- if (clist == NULL) return NULL; -- -- clist[0] = ad_ctx->ldap_ctx; -- clist[1] = NULL; -+ clist = ad_ldap_conn_list(breq, ad_ctx, dom); - break; - } - -- /* Regardless of connection types, a subdomain error must not be allowed -- * to set the whole back end offline, rather report an error and let the -- * caller deal with it (normally disable the subdomain -- */ -- if (IS_SUBDOMAIN(dom)) { -- for (cindex = 0; clist[cindex] != NULL; cindex++) { -- clist[cindex]->ignore_mark_offline = true; -- } -- } -- - return clist; - } - -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 86dd71f3cc09f11de88c4269d49552718c5ba027..7acbb38e66c2c36ff230ae35b236544195a8104b 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -640,21 +640,16 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx, - case BE_REQ_BY_SECID: - case BE_REQ_GROUP: - clist = ad_gc_conn_list(req, ad_id_ctx, state->obj_dom); -- if (clist == NULL) { -- ret = ENOMEM; -- goto fail; -- } -- clist[1]->ignore_mark_offline = true; - break; - default: -- clist = talloc_zero_array(req, struct sdap_id_conn_ctx *, 2); -- if (clist == NULL) { -- ret = ENOMEM; -- goto fail; -- } -- clist[0] = ad_id_ctx->ldap_ctx; -- clist[0]->ignore_mark_offline = true; -- clist[1] = NULL; -+ clist = ad_ldap_conn_list(req, ad_id_ctx, state->obj_dom); -+ break; -+ } -+ -+ if (clist == NULL) { -+ DEBUG(SSSDBG_OP_FAILURE, "Cannot generate AD connection list!\n"); -+ ret = ENOMEM; -+ goto fail; - } - - /* Now we already need ad_id_ctx in particular sdap_id_conn_ctx */ -diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c -index 985a05fae5a4d09ab102ed611c7d03ca8e4d955b..c7bcc0f7cfde7164672123a35940327ee3ca4aba 100644 ---- a/src/tests/cmocka/test_ad_common.c -+++ b/src/tests/cmocka/test_ad_common.c -@@ -337,7 +337,7 @@ __wrap_sdap_set_sasl_options(struct sdap_options *id_opts, - return EOK; - } - --void test_ldap_conn_list(void **state) -+void test_ad_get_dom_ldap_conn(void **state) - { - struct sdap_id_conn_ctx *conn; - -@@ -352,7 +352,7 @@ void test_ldap_conn_list(void **state) - assert_true(conn == test_ctx->subdom_ad_ctx->ldap_ctx); - } - --void test_conn_list(void **state) -+void test_gc_conn_list(void **state) - { - struct sdap_id_conn_ctx **conn_list; - -@@ -379,7 +379,8 @@ void test_conn_list(void **state) - assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx); - assert_true(conn_list[0]->ignore_mark_offline); - assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx); -- assert_false(conn_list[1]->ignore_mark_offline); -+ /* Subdomain error should not set the backend offline! */ -+ assert_true(conn_list[1]->ignore_mark_offline); - talloc_free(conn_list); - - dp_opt_set_bool(test_ctx->ad_ctx->ad_options->basic, AD_ENABLE_GC, false); -@@ -398,6 +399,37 @@ void test_conn_list(void **state) - assert_non_null(conn_list); - - assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx); -+ assert_true(conn_list[0]->ignore_mark_offline); -+ assert_null(conn_list[1]); -+ talloc_free(conn_list); -+} -+ -+void test_ldap_conn_list(void **state) -+{ -+ struct sdap_id_conn_ctx **conn_list; -+ -+ struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, -+ struct ad_common_test_ctx); -+ assert_non_null(test_ctx); -+ -+ conn_list = ad_ldap_conn_list(test_ctx, -+ test_ctx->ad_ctx, -+ test_ctx->dom); -+ assert_non_null(conn_list); -+ -+ assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx); -+ assert_false(conn_list[0]->ignore_mark_offline); -+ assert_null(conn_list[1]); -+ talloc_free(conn_list); -+ -+ conn_list = ad_ldap_conn_list(test_ctx, -+ test_ctx->ad_ctx, -+ test_ctx->subdom); -+ assert_non_null(conn_list); -+ -+ assert_true(conn_list[0] == test_ctx->subdom_ad_ctx->ldap_ctx); -+ assert_true(conn_list[0]->ignore_mark_offline); -+ assert_null(conn_list[1]); - talloc_free(conn_list); - } - -@@ -419,12 +451,15 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(test_ad_create_2way_trust_options, - test_ad_common_setup, - test_ad_common_teardown), -+ cmocka_unit_test_setup_teardown(test_ad_get_dom_ldap_conn, -+ test_ldap_conn_setup, -+ test_ldap_conn_teardown), -+ cmocka_unit_test_setup_teardown(test_gc_conn_list, -+ test_ldap_conn_setup, -+ test_ldap_conn_teardown), - cmocka_unit_test_setup_teardown(test_ldap_conn_list, - test_ldap_conn_setup, - test_ldap_conn_teardown), -- cmocka_unit_test_setup_teardown(test_conn_list, -- test_ldap_conn_setup, -- test_ldap_conn_teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.4.3 - diff --git a/SOURCES/0100-DP-Remove-old-data-provider-interface.patch b/SOURCES/0100-DP-Remove-old-data-provider-interface.patch new file mode 100644 index 0000000..db73927 --- /dev/null +++ b/SOURCES/0100-DP-Remove-old-data-provider-interface.patch @@ -0,0 +1,1034 @@ +From c2fe5c54faa92c670161d65fe5a1ff62acd4ac91 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 19 Jul 2016 14:24:16 +0200 +Subject: [PATCH 100/102] DP: Remove old data provider interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reverse data provider interface is moved to a better location in +NSS responder. All responders now can have an sbus interface +defined per data provider connection. The unused old data provider +interface is removed. + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 04e870d99e72aa3160bdb6ab05d986fb4005c3ed) +--- + Makefile.am | 11 +-- + src/providers/data_provider.h | 1 - + src/providers/data_provider/dp_target_id.c | 7 +- + src/providers/data_provider_iface.xml | 53 --------------- + src/providers/data_provider_iface_generated.c | 98 --------------------------- + src/providers/data_provider_iface_generated.h | 82 ---------------------- + src/responder/autofs/autofssrv.c | 13 +--- + src/responder/common/responder.h | 8 +-- + src/responder/common/responder_common.c | 16 +++-- + src/responder/common/responder_get_domains.c | 4 +- + src/responder/ifp/ifpsrv.c | 13 +--- + src/responder/nss/nss_iface.c | 38 +++++++++++ + src/responder/nss/nss_iface.h | 30 ++++++++ + src/responder/nss/nss_iface.xml | 12 ++++ + src/responder/nss/nss_iface_generated.c | 69 +++++++++++++++++++ + src/responder/nss/nss_iface_generated.h | 58 ++++++++++++++++ + src/responder/nss/nsssrv.c | 39 ++++------- + src/responder/nss/nsssrv.h | 7 ++ + src/responder/pac/pacsrv.c | 13 +--- + src/responder/pam/pamsrv.c | 13 +--- + src/responder/pam/pamsrv_dp.c | 4 +- + src/responder/ssh/sshsrv.c | 13 +--- + src/responder/sudo/sudosrv.c | 13 +--- + src/tests/cwrap/Makefile.am | 1 - + 24 files changed, 259 insertions(+), 357 deletions(-) + delete mode 100644 src/providers/data_provider_iface.xml + delete mode 100644 src/providers/data_provider_iface_generated.c + delete mode 100644 src/providers/data_provider_iface_generated.h + create mode 100644 src/responder/nss/nss_iface.c + create mode 100644 src/responder/nss/nss_iface.h + create mode 100644 src/responder/nss/nss_iface.xml + create mode 100644 src/responder/nss/nss_iface_generated.c + create mode 100644 src/responder/nss/nss_iface_generated.h + +diff --git a/Makefile.am b/Makefile.am +index 5d54838659e44fa446fc921d014e48ac91469b25..e2e4c4c08f66ef15684e1b3b1fe17bfae4e4131b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -492,7 +492,6 @@ SSSD_RESPONDER_OBJ = \ + src/responder/common/data_provider/rdp_message.c \ + src/responder/common/data_provider/rdp_client.c \ + src/monitor/monitor_iface_generated.c \ +- src/providers/data_provider_iface_generated.c \ + src/providers/data_provider_req.c + + SSSD_TOOLS_OBJ = \ +@@ -610,6 +609,8 @@ dist_noinst_HEADERS = \ + src/responder/nss/nsssrv_netgroup.h \ + src/responder/nss/nsssrv_services.h \ + src/responder/nss/nsssrv_mmap_cache.h \ ++ src/responder/nss/nss_iface_generated.h \ ++ src/responder/nss/nss_iface.h \ + src/responder/pac/pacsrv.h \ + src/responder/common/negcache_files.h \ + src/responder/common/negcache.h \ +@@ -647,7 +648,6 @@ dist_noinst_HEADERS = \ + src/confdb/confdb_setup.h \ + src/providers/data_provider.h \ + src/providers/data_provider_req.h \ +- src/providers/data_provider_iface_generated.h \ + src/providers/data_provider/dp.h \ + src/providers/data_provider/dp_flags.h \ + src/providers/data_provider/dp_responder_iface.h \ +@@ -1196,10 +1196,10 @@ endif + CODEGEN_XML = \ + $(srcdir)/src/tests/sbus_codegen_tests.xml \ + $(srcdir)/src/monitor/monitor_iface.xml \ +- $(srcdir)/src/providers/data_provider_iface.xml \ + $(srcdir)/src/providers/data_provider/dp_iface.xml \ + $(srcdir)/src/providers/proxy/proxy_iface.xml \ +- $(srcdir)/src/responder/ifp/ifp_iface.xml ++ $(srcdir)/src/responder/ifp/ifp_iface.xml \ ++ $(srcdir)/src/responder/nss/nss_iface.xml + + SBUS_CODEGEN = src/sbus/sbus_codegen + +@@ -1248,6 +1248,8 @@ sssd_nss_SOURCES = \ + src/responder/nss/nsssrv_netgroup.c \ + src/responder/nss/nsssrv_services.c \ + src/responder/nss/nsssrv_mmap_cache.c \ ++ src/responder/nss/nss_iface_generated.c \ ++ src/responder/nss/nss_iface.c \ + $(SSSD_RESPONDER_OBJ) + sssd_nss_LDADD = \ + $(TDB_LIBS) \ +@@ -1411,7 +1413,6 @@ sssd_be_SOURCES = \ + src/providers/be_ptask.c \ + src/providers/be_refresh.c \ + src/monitor/monitor_iface_generated.c \ +- src/providers/data_provider_iface_generated.c \ + src/providers/data_provider/dp.c \ + src/providers/data_provider/dp_modules.c \ + src/providers/data_provider/dp_targets.c \ +diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h +index b0b6876d984d7c6574baaa8d130e374ba2e6f0c4..14a0902c265850d91fa7d29cc2708e70b060ec18 100644 +--- a/src/providers/data_provider.h ++++ b/src/providers/data_provider.h +@@ -44,7 +44,6 @@ + #include "sss_client/sss_cli.h" + #include "util/authtok.h" + #include "providers/data_provider_req.h" +-#include "providers/data_provider_iface_generated.h" + + #define DATA_PROVIDER_VERSION 0x0001 + #define DATA_PROVIDER_PIPE "private/sbus-dp" +diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c +index 1b06cbe5b96f56c33dd048cf6211b7c97819db8c..938651545ea995091d0aaf29da12bbb8110c9add 100644 +--- a/src/providers/data_provider/dp_target_id.c ++++ b/src/providers/data_provider/dp_target_id.c +@@ -25,6 +25,7 @@ + #include "providers/data_provider/dp_private.h" + #include "providers/data_provider/dp_iface.h" + #include "providers/backend.h" ++#include "responder/nss/nss_iface.h" + #include "util/util.h" + + #define FILTER_TYPE(str, type) {str "=", sizeof(str "=") - 1, type} +@@ -168,9 +169,9 @@ static void dp_req_initgr_pp(const char *req_name, + } + + msg = dbus_message_new_method_call(NULL, +- DP_PATH, +- DATA_PROVIDER_REV_IFACE, +- DATA_PROVIDER_REV_IFACE_INITGRCHECK); ++ NSS_MEMORYCACHE_PATH, ++ IFACE_NSS_MEMORYCACHE, ++ IFACE_NSS_MEMORYCACHE_UPDATEINITGROUPS); + if (msg == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory?!\n"); + return; +diff --git a/src/providers/data_provider_iface.xml b/src/providers/data_provider_iface.xml +deleted file mode 100644 +index 143975633081ce2ae5690c4036e7169e41d776fc..0000000000000000000000000000000000000000 +--- a/src/providers/data_provider_iface.xml ++++ /dev/null +@@ -1,53 +0,0 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +diff --git a/src/providers/data_provider_iface_generated.c b/src/providers/data_provider_iface_generated.c +deleted file mode 100644 +index bdd6a4d76d18bbb44530d816fce14009736b6f6d..0000000000000000000000000000000000000000 +--- a/src/providers/data_provider_iface_generated.c ++++ /dev/null +@@ -1,98 +0,0 @@ +-/* The following definitions are auto-generated from data_provider_iface.xml */ +- +-#include "util/util.h" +-#include "sbus/sssd_dbus.h" +-#include "sbus/sssd_dbus_meta.h" +-#include "sbus/sssd_dbus_invokers.h" +-#include "data_provider_iface_generated.h" +- +-/* methods for org.freedesktop.sssd.dataprovider */ +-const struct sbus_method_meta data_provider_iface__methods[] = { +- { +- "RegisterService", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_iface, RegisterService), +- NULL, /* no invoker */ +- }, +- { +- "pamHandler", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_iface, pamHandler), +- NULL, /* no invoker */ +- }, +- { +- "sudoHandler", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_iface, sudoHandler), +- NULL, /* no invoker */ +- }, +- { +- "autofsHandler", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_iface, autofsHandler), +- NULL, /* no invoker */ +- }, +- { +- "hostHandler", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_iface, hostHandler), +- NULL, /* no invoker */ +- }, +- { +- "getDomains", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_iface, getDomains), +- NULL, /* no invoker */ +- }, +- { +- "getAccountInfo", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_iface, getAccountInfo), +- NULL, /* no invoker */ +- }, +- { NULL, } +-}; +- +-/* interface info for org.freedesktop.sssd.dataprovider */ +-const struct sbus_interface_meta data_provider_iface_meta = { +- "org.freedesktop.sssd.dataprovider", /* name */ +- data_provider_iface__methods, +- NULL, /* no signals */ +- NULL, /* no properties */ +- sbus_invoke_get_all, /* GetAll invoker */ +-}; +- +-/* methods for org.freedesktop.sssd.dataprovider_rev */ +-const struct sbus_method_meta data_provider_rev_iface__methods[] = { +- { +- "updateCache", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_rev_iface, updateCache), +- NULL, /* no invoker */ +- }, +- { +- "initgrCheck", /* name */ +- NULL, /* no in_args */ +- NULL, /* no out_args */ +- offsetof(struct data_provider_rev_iface, initgrCheck), +- NULL, /* no invoker */ +- }, +- { NULL, } +-}; +- +-/* interface info for org.freedesktop.sssd.dataprovider_rev */ +-const struct sbus_interface_meta data_provider_rev_iface_meta = { +- "org.freedesktop.sssd.dataprovider_rev", /* name */ +- data_provider_rev_iface__methods, +- NULL, /* no signals */ +- NULL, /* no properties */ +- sbus_invoke_get_all, /* GetAll invoker */ +-}; +diff --git a/src/providers/data_provider_iface_generated.h b/src/providers/data_provider_iface_generated.h +deleted file mode 100644 +index 976e42b89c6aaf9523b16999b8f5103a1e6f8e66..0000000000000000000000000000000000000000 +--- a/src/providers/data_provider_iface_generated.h ++++ /dev/null +@@ -1,82 +0,0 @@ +-/* The following declarations are auto-generated from data_provider_iface.xml */ +- +-#ifndef __DATA_PROVIDER_IFACE_XML__ +-#define __DATA_PROVIDER_IFACE_XML__ +- +-#include "sbus/sssd_dbus.h" +- +-/* ------------------------------------------------------------------------ +- * DBus Constants +- * +- * Various constants of interface and method names mostly for use by clients +- */ +- +-/* constants for org.freedesktop.sssd.dataprovider */ +-#define DATA_PROVIDER_IFACE "org.freedesktop.sssd.dataprovider" +-#define DATA_PROVIDER_IFACE_REGISTERSERVICE "RegisterService" +-#define DATA_PROVIDER_IFACE_PAMHANDLER "pamHandler" +-#define DATA_PROVIDER_IFACE_SUDOHANDLER "sudoHandler" +-#define DATA_PROVIDER_IFACE_AUTOFSHANDLER "autofsHandler" +-#define DATA_PROVIDER_IFACE_HOSTHANDLER "hostHandler" +-#define DATA_PROVIDER_IFACE_GETDOMAINS "getDomains" +-#define DATA_PROVIDER_IFACE_GETACCOUNTINFO "getAccountInfo" +- +-/* constants for org.freedesktop.sssd.dataprovider_rev */ +-#define DATA_PROVIDER_REV_IFACE "org.freedesktop.sssd.dataprovider_rev" +-#define DATA_PROVIDER_REV_IFACE_UPDATECACHE "updateCache" +-#define DATA_PROVIDER_REV_IFACE_INITGRCHECK "initgrCheck" +- +-/* ------------------------------------------------------------------------ +- * DBus handlers +- * +- * These structures are filled in by implementors of the different +- * dbus interfaces to handle method calls. +- * +- * Handler functions of type sbus_msg_handler_fn accept raw messages, +- * other handlers are typed appropriately. If a handler that is +- * set to NULL is invoked it will result in a +- * org.freedesktop.DBus.Error.NotSupported error for the caller. +- * +- * Handlers have a matching xxx_finish() function (unless the method has +- * accepts raw messages). These finish functions the +- * sbus_request_return_and_finish() with the appropriate arguments to +- * construct a valid reply. Once a finish function has been called, the +- * @dbus_req it was called with is freed and no longer valid. +- */ +- +-/* vtable for org.freedesktop.sssd.dataprovider */ +-struct data_provider_iface { +- struct sbus_vtable vtable; /* derive from sbus_vtable */ +- sbus_msg_handler_fn RegisterService; +- sbus_msg_handler_fn pamHandler; +- sbus_msg_handler_fn sudoHandler; +- sbus_msg_handler_fn autofsHandler; +- sbus_msg_handler_fn hostHandler; +- sbus_msg_handler_fn getDomains; +- sbus_msg_handler_fn getAccountInfo; +-}; +- +-/* vtable for org.freedesktop.sssd.dataprovider_rev */ +-struct data_provider_rev_iface { +- struct sbus_vtable vtable; /* derive from sbus_vtable */ +- sbus_msg_handler_fn updateCache; +- sbus_msg_handler_fn initgrCheck; +-}; +- +-/* ------------------------------------------------------------------------ +- * DBus Interface Metadata +- * +- * These structure definitions are filled in with the information about +- * the interfaces, methods, properties and so on. +- * +- * The actual definitions are found in the accompanying C file next +- * to this header. +- */ +- +-/* interface info for org.freedesktop.sssd.dataprovider */ +-extern const struct sbus_interface_meta data_provider_iface_meta; +- +-/* interface info for org.freedesktop.sssd.dataprovider_rev */ +-extern const struct sbus_interface_meta data_provider_rev_iface_meta; +- +-#endif /* __DATA_PROVIDER_IFACE_XML__ */ +diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c +index c72f3c1f7aee81a9986076975086cdd88e968edb..826a36e9bc0e2afedfda17104d15b86c5fc1b7e1 100644 +--- a/src/responder/autofs/autofssrv.c ++++ b/src/responder/autofs/autofssrv.c +@@ -44,17 +44,6 @@ struct mon_cli_iface monitor_autofs_methods = { + .sysbusReconnect = NULL, + }; + +-static struct data_provider_iface autofs_dp_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = NULL, +- .pamHandler = NULL, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + static errno_t + autofs_get_config(struct autofs_ctx *actx, + struct confdb_ctx *cdb) +@@ -130,7 +119,7 @@ autofs_process_init(TALLOC_CTX *mem_ctx, + SSS_AUTOFS_SBUS_SERVICE_VERSION, + &monitor_autofs_methods, + "autofs", +- &autofs_dp_methods.vtable, ++ NULL, + autofs_connection_setup, + &rctx); + if (ret != EOK) { +diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h +index 335b313ce1a6bc7c0e0ba332786e2e9f39a04ff1..9e3b2fdbda4e30b859df597374fc7d490b1720e5 100644 +--- a/src/responder/common/responder.h ++++ b/src/responder/common/responder.h +@@ -163,11 +163,7 @@ struct mon_cli_iface; + typedef int (*connection_setup_t)(struct cli_ctx *cctx); + + int sss_connection_setup(struct cli_ctx *cctx); +-/* +- * NOTE: We would like to use more strong typing for the @dp_vtable argument +- * but can't since it accepts either a struct data_provider_iface +- * or struct data_provider_rev_iface. So pass the base struct: sbus_vtable +- */ ++ + int sss_process_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx *cdb, +@@ -181,7 +177,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, + uint16_t svc_version, + struct mon_cli_iface *monitor_intf, + const char *cli_name, +- struct sbus_vtable *dp_intf, ++ struct sbus_iface_map *sbus_iface, + connection_setup_t conn_setup, + struct resp_ctx **responder_ctx); + +diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c +index 7f6264ae70e5073063b5cfcd73098eefad2ce653..c604c64a652221521ec7114b8588186f087eb11a 100644 +--- a/src/responder/common/responder_common.c ++++ b/src/responder/common/responder_common.c +@@ -549,7 +549,7 @@ void idle_handler(struct tevent_context *ev, + } + + static int sss_dp_init(struct resp_ctx *rctx, +- struct sbus_vtable *dp_intf, ++ struct sbus_iface_map *sbus_iface, + const char *cli_name, + struct sss_domain_info *domain) + { +@@ -577,10 +577,12 @@ static int sss_dp_init(struct resp_ctx *rctx, + return ret; + } + +- ret = sbus_conn_register_iface(be_conn->conn, dp_intf, DP_PATH, rctx); +- if (ret != EOK) { +- DEBUG(SSSDBG_FATAL_FAILURE, "Failed to export data provider.\n"); +- return ret; ++ if (sbus_iface != NULL) { ++ ret = sbus_conn_register_iface_map(be_conn->conn, sbus_iface, rctx); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to register D-Bus interface.\n"); ++ return ret; ++ } + } + + DLIST_ADD_END(rctx->be_conns, be_conn, struct be_conn *); +@@ -925,7 +927,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, + uint16_t svc_version, + struct mon_cli_iface *monitor_intf, + const char *cli_name, +- struct sbus_vtable *dp_intf, ++ struct sbus_iface_map *sbus_iface, + connection_setup_t conn_setup, + struct resp_ctx **responder_ctx) + { +@@ -1040,7 +1042,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, + continue; + } + +- ret = sss_dp_init(rctx, dp_intf, cli_name, dom); ++ ret = sss_dp_init(rctx, sbus_iface, cli_name, dom); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + "fatal error setting up backend connector\n"); +diff --git a/src/responder/common/responder_get_domains.c b/src/responder/common/responder_get_domains.c +index 6b354d8b2251f3a5cf576a58ae191fd99f307dd7..cc7b99f30046569547a08f83e46cbbe9d6c19897 100644 +--- a/src/responder/common/responder_get_domains.c ++++ b/src/responder/common/responder_get_domains.c +@@ -88,8 +88,8 @@ sss_dp_get_domains_msg(void *pvt) + + msg = dbus_message_new_method_call(NULL, + DP_PATH, +- DATA_PROVIDER_IFACE, +- DATA_PROVIDER_IFACE_GETDOMAINS); ++ IFACE_DP, ++ IFACE_DP_GETDOMAINS); + if (msg == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory?!\n"); + return NULL; +diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c +index a2137ecb218824909325df6c7052dbbbcb144679..0555c00167045707b7d455d28df368749b9b84f6 100644 +--- a/src/responder/ifp/ifpsrv.c ++++ b/src/responder/ifp/ifpsrv.c +@@ -58,17 +58,6 @@ struct mon_cli_iface monitor_ifp_methods = { + .sysbusReconnect = ifp_sysbus_reconnect, + }; + +-static struct data_provider_iface ifp_dp_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = NULL, +- .pamHandler = NULL, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + struct sss_cmd_table *get_ifp_cmds(void) + { + static struct sss_cmd_table ifp_cmds[] = { +@@ -238,7 +227,7 @@ int ifp_process_init(TALLOC_CTX *mem_ctx, + SSS_IFP_SBUS_SERVICE_VERSION, + &monitor_ifp_methods, + "InfoPipe", +- &ifp_dp_methods.vtable, ++ NULL, + sss_connection_setup, + &rctx); + if (ret != EOK) { +diff --git a/src/responder/nss/nss_iface.c b/src/responder/nss/nss_iface.c +new file mode 100644 +index 0000000000000000000000000000000000000000..b01732e086c5fc5c7018ec84c3438e19ed812fef +--- /dev/null ++++ b/src/responder/nss/nss_iface.c +@@ -0,0 +1,38 @@ ++/* ++ Authors: ++ Pavel Březina ++ ++ Copyright (C) 2016 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 "sbus/sssd_dbus.h" ++#include "responder/nss/nss_iface.h" ++#include "responder/nss/nsssrv.h" ++ ++struct iface_nss_memorycache iface_nss_memorycache = { ++ { &iface_nss_memorycache_meta, 0 }, ++ .UpdateInitgroups = nss_memorycache_update_initgroups ++}; ++ ++static struct sbus_iface_map iface_map[] = { ++ { NSS_MEMORYCACHE_PATH, &iface_nss_memorycache.vtable }, ++ { NULL, NULL } ++}; ++ ++struct sbus_iface_map *nss_get_sbus_interface() ++{ ++ return iface_map; ++} +diff --git a/src/responder/nss/nss_iface.h b/src/responder/nss/nss_iface.h +new file mode 100644 +index 0000000000000000000000000000000000000000..ab59928c3e2dac62cea6f793ff774d9e0f8da6db +--- /dev/null ++++ b/src/responder/nss/nss_iface.h +@@ -0,0 +1,30 @@ ++/* ++ Authors: ++ Pavel Březina ++ ++ Copyright (C) 2016 Red Hat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#ifndef _NSS_IFACE_H_ ++#define _NSS_IFACE_H_ ++ ++#include "responder/nss/nss_iface_generated.h" ++ ++#define NSS_MEMORYCACHE_PATH "/org/freedesktop/sssd/nss/memcache" ++ ++struct sbus_iface_map *nss_get_sbus_interface(void); ++ ++#endif /* _NSS_IFACE_H_ */ +diff --git a/src/responder/nss/nss_iface.xml b/src/responder/nss/nss_iface.xml +new file mode 100644 +index 0000000000000000000000000000000000000000..b7cc4deb77135a592bad2ca62570f206231129b7 +--- /dev/null ++++ b/src/responder/nss/nss_iface.xml +@@ -0,0 +1,12 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/responder/nss/nss_iface_generated.c b/src/responder/nss/nss_iface_generated.c +new file mode 100644 +index 0000000000000000000000000000000000000000..2d0031090e33df9c9e9d9fbf1a18825026509803 +--- /dev/null ++++ b/src/responder/nss/nss_iface_generated.c +@@ -0,0 +1,69 @@ ++/* The following definitions are auto-generated from nss_iface.xml */ ++ ++#include "util/util.h" ++#include "sbus/sssd_dbus.h" ++#include "sbus/sssd_dbus_meta.h" ++#include "sbus/sssd_dbus_invokers.h" ++#include "nss_iface_generated.h" ++ ++/* invokes a handler with a 'ssau' DBus signature */ ++static int invoke_ssau_method(struct sbus_request *dbus_req, void *function_ptr); ++ ++/* arguments for org.freedesktop.sssd.nss.MemoryCache.UpdateInitgroups */ ++const struct sbus_arg_meta iface_nss_memorycache_UpdateInitgroups__in[] = { ++ { "user", "s" }, ++ { "domain", "s" }, ++ { "groups", "au" }, ++ { NULL, } ++}; ++ ++int iface_nss_memorycache_UpdateInitgroups_finish(struct sbus_request *req) ++{ ++ return sbus_request_return_and_finish(req, ++ DBUS_TYPE_INVALID); ++} ++ ++/* methods for org.freedesktop.sssd.nss.MemoryCache */ ++const struct sbus_method_meta iface_nss_memorycache__methods[] = { ++ { ++ "UpdateInitgroups", /* name */ ++ iface_nss_memorycache_UpdateInitgroups__in, ++ NULL, /* no out_args */ ++ offsetof(struct iface_nss_memorycache, UpdateInitgroups), ++ invoke_ssau_method, ++ }, ++ { NULL, } ++}; ++ ++/* interface info for org.freedesktop.sssd.nss.MemoryCache */ ++const struct sbus_interface_meta iface_nss_memorycache_meta = { ++ "org.freedesktop.sssd.nss.MemoryCache", /* name */ ++ iface_nss_memorycache__methods, ++ NULL, /* no signals */ ++ NULL, /* no properties */ ++ sbus_invoke_get_all, /* GetAll invoker */ ++}; ++ ++/* invokes a handler with a 'ssau' DBus signature */ ++static int invoke_ssau_method(struct sbus_request *dbus_req, void *function_ptr) ++{ ++ const char * arg_0; ++ const char * arg_1; ++ uint32_t *arg_2; ++ int len_2; ++ int (*handler)(struct sbus_request *, void *, const char *, const char *, uint32_t[], int) = function_ptr; ++ ++ if (!sbus_request_parse_or_finish(dbus_req, ++ DBUS_TYPE_STRING, &arg_0, ++ DBUS_TYPE_STRING, &arg_1, ++ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &arg_2, &len_2, ++ DBUS_TYPE_INVALID)) { ++ return EOK; /* request handled */ ++ } ++ ++ return (handler)(dbus_req, dbus_req->intf->handler_data, ++ arg_0, ++ arg_1, ++ arg_2, ++ len_2); ++} +diff --git a/src/responder/nss/nss_iface_generated.h b/src/responder/nss/nss_iface_generated.h +new file mode 100644 +index 0000000000000000000000000000000000000000..ad902482a9be03a60cbf3663b6f771d0a2020b88 +--- /dev/null ++++ b/src/responder/nss/nss_iface_generated.h +@@ -0,0 +1,58 @@ ++/* The following declarations are auto-generated from nss_iface.xml */ ++ ++#ifndef __NSS_IFACE_XML__ ++#define __NSS_IFACE_XML__ ++ ++#include "sbus/sssd_dbus.h" ++ ++/* ------------------------------------------------------------------------ ++ * DBus Constants ++ * ++ * Various constants of interface and method names mostly for use by clients ++ */ ++ ++/* constants for org.freedesktop.sssd.nss.MemoryCache */ ++#define IFACE_NSS_MEMORYCACHE "org.freedesktop.sssd.nss.MemoryCache" ++#define IFACE_NSS_MEMORYCACHE_UPDATEINITGROUPS "UpdateInitgroups" ++ ++/* ------------------------------------------------------------------------ ++ * DBus handlers ++ * ++ * These structures are filled in by implementors of the different ++ * dbus interfaces to handle method calls. ++ * ++ * Handler functions of type sbus_msg_handler_fn accept raw messages, ++ * other handlers are typed appropriately. If a handler that is ++ * set to NULL is invoked it will result in a ++ * org.freedesktop.DBus.Error.NotSupported error for the caller. ++ * ++ * Handlers have a matching xxx_finish() function (unless the method has ++ * accepts raw messages). These finish functions the ++ * sbus_request_return_and_finish() with the appropriate arguments to ++ * construct a valid reply. Once a finish function has been called, the ++ * @dbus_req it was called with is freed and no longer valid. ++ */ ++ ++/* vtable for org.freedesktop.sssd.nss.MemoryCache */ ++struct iface_nss_memorycache { ++ struct sbus_vtable vtable; /* derive from sbus_vtable */ ++ int (*UpdateInitgroups)(struct sbus_request *req, void *data, const char *arg_user, const char *arg_domain, uint32_t arg_groups[], int len_groups); ++}; ++ ++/* finish function for UpdateInitgroups */ ++int iface_nss_memorycache_UpdateInitgroups_finish(struct sbus_request *req); ++ ++/* ------------------------------------------------------------------------ ++ * DBus Interface Metadata ++ * ++ * These structure definitions are filled in with the information about ++ * the interfaces, methods, properties and so on. ++ * ++ * The actual definitions are found in the accompanying C file next ++ * to this header. ++ */ ++ ++/* interface info for org.freedesktop.sssd.nss.MemoryCache */ ++extern const struct sbus_interface_meta iface_nss_memorycache_meta; ++ ++#endif /* __NSS_IFACE_XML__ */ +diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c +index 8be3455e57e07481e7cf7d4d0f525dad5b8601fc..05b51ecdf2e17e20af2ee3ee48377cbe1bf19a24 100644 +--- a/src/responder/nss/nsssrv.c ++++ b/src/responder/nss/nsssrv.c +@@ -37,6 +37,7 @@ + #include "responder/nss/nsssrv_private.h" + #include "responder/nss/nsssrv_mmap_cache.h" + #include "responder/nss/nsssrv_netgroup.h" ++#include "responder/nss/nss_iface.h" + #include "responder/common/negcache.h" + #include "db/sysdb.h" + #include "confdb/confdb.h" +@@ -327,7 +328,7 @@ done: + return ret; + } + +-static int nss_update_memcache(struct sbus_request *dbus_req, void *data) ++int nss_update_memcache(struct sbus_request *dbus_req, void *data) + { + struct resp_ctx *rctx = talloc_get_type(data, struct resp_ctx); + struct nss_ctx *nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx); +@@ -338,37 +339,24 @@ static int nss_update_memcache(struct sbus_request *dbus_req, void *data) + return EOK; + } + +-static int nss_memcache_initgr_check(struct sbus_request *dbus_req, void *data) ++int nss_memorycache_update_initgroups(struct sbus_request *sbus_req, ++ void *data, ++ const char *user, ++ const char *domain, ++ uint32_t *groups, ++ int num_groups) + { + struct resp_ctx *rctx = talloc_get_type(data, struct resp_ctx); + struct nss_ctx *nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx); +- char *user; +- char *domain; +- uint32_t *groups; +- int gnum; + +- if (!sbus_request_parse_or_finish(dbus_req, +- DBUS_TYPE_STRING, &user, +- DBUS_TYPE_STRING, &domain, +- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &groups, &gnum, +- DBUS_TYPE_INVALID)) { +- return EOK; /* handled */ +- } ++ DEBUG(SSSDBG_TRACE_LIBS, "Updating inigroups memory cache of [%s@%s]\n", ++ user, domain); + +- DEBUG(SSSDBG_TRACE_LIBS, +- "Got request for [%s@%s]\n", user, domain); ++ nss_update_initgr_memcache(nctx, user, domain, num_groups, groups); + +- nss_update_initgr_memcache(nctx, user, domain, gnum, groups); +- +- return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID); ++ return iface_nss_memorycache_UpdateInitgroups_finish(sbus_req); + } + +-static struct data_provider_rev_iface nss_dp_methods = { +- { &data_provider_rev_iface_meta, 0 }, +- .updateCache = nss_update_memcache, +- .initgrCheck = nss_memcache_initgr_check +-}; +- + static void nss_dp_reconnect_init(struct sbus_connection *conn, + int status, void *pvt) + { +@@ -419,7 +407,8 @@ int nss_process_init(TALLOC_CTX *mem_ctx, + NSS_SBUS_SERVICE_NAME, + NSS_SBUS_SERVICE_VERSION, + &monitor_nss_methods, +- "NSS", &nss_dp_methods.vtable, ++ "NSS", ++ nss_get_sbus_interface(), + nss_connection_setup, + &rctx); + if (ret != EOK) { +diff --git a/src/responder/nss/nsssrv.h b/src/responder/nss/nsssrv.h +index 2977479aa52082480f92eab94f7833e2e696a9ac..d4a80f76df236f40d872c701687bf453255d9890 100644 +--- a/src/responder/nss/nsssrv.h ++++ b/src/responder/nss/nsssrv.h +@@ -81,4 +81,11 @@ struct nss_packet; + + struct sss_cmd_table *get_nss_cmds(void); + ++int nss_memorycache_update_initgroups(struct sbus_request *sbus_req, ++ void *data, ++ const char *user, ++ const char *domain, ++ uint32_t *groups, ++ int num_groups); ++ + #endif /* __NSSSRV_H__ */ +diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c +index 15d1986f842ac8397cf509ca8ef44728d6ddc5f1..852deb10eff014189d35a2769d895a901d8296e1 100644 +--- a/src/responder/pac/pacsrv.c ++++ b/src/responder/pac/pacsrv.c +@@ -61,17 +61,6 @@ struct mon_cli_iface monitor_pac_methods = { + .sysbusReconnect = NULL, + }; + +-static struct data_provider_iface pac_dp_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = NULL, +- .pamHandler = NULL, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + /* TODO: check if this can be made generic for all responders */ + static void pac_dp_reconnect_init(struct sbus_connection *conn, + int status, void *pvt) +@@ -122,7 +111,7 @@ int pac_process_init(TALLOC_CTX *mem_ctx, + PAC_SBUS_SERVICE_NAME, + PAC_SBUS_SERVICE_VERSION, + &monitor_pac_methods, +- "PAC", &pac_dp_methods.vtable, ++ "PAC", NULL, + sss_connection_setup, + &rctx); + if (ret != EOK) { +diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c +index efd1e5c7527decda5de7304b54919846fa2ee0db..9374de4d63b2886262ca1541daff581603d7c838 100644 +--- a/src/responder/pam/pamsrv.c ++++ b/src/responder/pam/pamsrv.c +@@ -66,17 +66,6 @@ struct mon_cli_iface monitor_pam_methods = { + .sysbusReconnect = NULL, + }; + +-static struct data_provider_iface pam_dp_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = NULL, +- .pamHandler = NULL, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + static void pam_dp_reconnect_init(struct sbus_connection *conn, int status, void *pvt) + { + struct be_conn *be_conn = talloc_get_type(pvt, struct be_conn); +@@ -201,7 +190,7 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, + SSS_PAM_SBUS_SERVICE_NAME, + SSS_PAM_SBUS_SERVICE_VERSION, + &monitor_pam_methods, +- "PAM", &pam_dp_methods.vtable, ++ "PAM", NULL, + sss_connection_setup, + &rctx); + if (ret != EOK) { +diff --git a/src/responder/pam/pamsrv_dp.c b/src/responder/pam/pamsrv_dp.c +index 826146350670d67f897ee7eec2cf6ca607b96435..aa3fdc3c32d234ed54a9f5202886157601ee3846 100644 +--- a/src/responder/pam/pamsrv_dp.c ++++ b/src/responder/pam/pamsrv_dp.c +@@ -130,8 +130,8 @@ int pam_dp_send_req(struct pam_auth_req *preq, int timeout) + + msg = dbus_message_new_method_call(NULL, + DP_PATH, +- DATA_PROVIDER_IFACE, +- DATA_PROVIDER_IFACE_PAMHANDLER); ++ IFACE_DP, ++ IFACE_DP_PAMHANDLER); + if (msg == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n"); + return ENOMEM; +diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c +index f763e3b00d20527225046a85609e7ff56861f682..88938215b542b5748721cfecc59ca4141010fb88 100644 +--- a/src/responder/ssh/sshsrv.c ++++ b/src/responder/ssh/sshsrv.c +@@ -41,17 +41,6 @@ struct mon_cli_iface monitor_ssh_methods = { + .sysbusReconnect = NULL, + }; + +-static struct data_provider_iface ssh_dp_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = NULL, +- .pamHandler = NULL, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + static void ssh_dp_reconnect_init(struct sbus_connection *conn, + int status, void *pvt) + { +@@ -96,7 +85,7 @@ int ssh_process_init(TALLOC_CTX *mem_ctx, + SSS_SSH_SBUS_SERVICE_VERSION, + &monitor_ssh_methods, + "SSH", +- &ssh_dp_methods.vtable, ++ NULL, + sss_connection_setup, + &rctx); + if (ret != EOK) { +diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c +index e0346033e38f1e39e621e131c3265a583b91a5c3..d832686a8572f3729a0477cdca2f77ebcb19fbc0 100644 +--- a/src/responder/sudo/sudosrv.c ++++ b/src/responder/sudo/sudosrv.c +@@ -42,17 +42,6 @@ struct mon_cli_iface monitor_sudo_methods = { + .sysbusReconnect = NULL, + }; + +-static struct data_provider_iface sudo_dp_methods = { +- { &data_provider_iface_meta, 0 }, +- .RegisterService = NULL, +- .pamHandler = NULL, +- .sudoHandler = NULL, +- .autofsHandler = NULL, +- .hostHandler = NULL, +- .getDomains = NULL, +- .getAccountInfo = NULL, +-}; +- + static void sudo_dp_reconnect_init(struct sbus_connection *conn, + int status, + void *pvt) +@@ -98,7 +87,7 @@ int sudo_process_init(TALLOC_CTX *mem_ctx, + SSS_SUDO_SBUS_SERVICE_VERSION, + &monitor_sudo_methods, + "SUDO", +- &sudo_dp_methods.vtable, ++ NULL, + sss_connection_setup, + &rctx); + if (ret != EOK) { +diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am +index d8a49f1434cefc02bc7fce505d1b4e07fc74ec5f..3e40cba52e927730483b14cc7e56687b250de646 100644 +--- a/src/tests/cwrap/Makefile.am ++++ b/src/tests/cwrap/Makefile.am +@@ -49,7 +49,6 @@ SSSD_RESPONDER_OBJ = \ + ../../../src/responder/common/data_provider/rdp_message.c \ + ../../../src/responder/common/data_provider/rdp_client.c \ + ../../../src/monitor/monitor_iface_generated.c \ +- ../../../src/providers/data_provider_iface_generated.c \ + ../../../src/providers/data_provider_req.c + + dist_noinst_DATA = \ +-- +2.4.11 + diff --git a/SOURCES/0101-AD-Consolidate-connection-list-construction-on-ad_co.patch b/SOURCES/0101-AD-Consolidate-connection-list-construction-on-ad_co.patch deleted file mode 100644 index 9e4fbf4..0000000 --- a/SOURCES/0101-AD-Consolidate-connection-list-construction-on-ad_co.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 64b1b88acacf4004acdfca1a6cda9763e017dfbf Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 5 Oct 2015 16:11:14 +0200 -Subject: [PATCH 101/101] AD: Consolidate connection list construction on - ad_common.c - -Reviewed-by: Sumit Bose -(cherry picked from commit afb21fd06690a0bec288a7970abf74ed2ea7dfdc) -(cherry picked from commit f1742784d9b1cffd74f67beeb26375124183428a) ---- - src/providers/ad/ad_common.c | 31 +++++++++++++++++++++++++++++++ - src/providers/ad/ad_common.h | 5 +++++ - src/providers/ad/ad_id.c | 18 +----------------- - src/tests/cmocka/test_ad_common.c | 34 ++++++++++++++++++++++++++++++++++ - 4 files changed, 71 insertions(+), 17 deletions(-) - -diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c -index df277e55e234d4d4efe34d5f5d8efdfe7267fb60..650ec41578297f7b3a59df118b71a6bb8bc6d6ed 100644 ---- a/src/providers/ad/ad_common.c -+++ b/src/providers/ad/ad_common.c -@@ -1286,3 +1286,34 @@ ad_ldap_conn_list(TALLOC_CTX *mem_ctx, - clist[1] = NULL; - return clist; - } -+ -+struct sdap_id_conn_ctx ** -+ad_user_conn_list(TALLOC_CTX *mem_ctx, -+ struct ad_id_ctx *ad_ctx, -+ struct sss_domain_info *dom) -+{ -+ struct sdap_id_conn_ctx **clist; -+ int cindex = 0; -+ -+ clist = talloc_zero_array(ad_ctx, struct sdap_id_conn_ctx *, 3); -+ if (clist == NULL) { -+ return NULL; -+ } -+ -+ /* Try GC first for users from trusted domains, but go to LDAP -+ * for users from non-trusted domains to get all POSIX attrs -+ */ -+ if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC) -+ && IS_SUBDOMAIN(dom)) { -+ clist[cindex] = ad_ctx->gc_ctx; -+ clist[cindex]->ignore_mark_offline = true; -+ cindex++; -+ } -+ -+ /* Users from primary domain can be just downloaded from LDAP. -+ * The domain's LDAP connection also works as a fallback -+ */ -+ clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom); -+ -+ return clist; -+} -diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h -index 701e461987cb286ca7add2766ffb4dc496bde01e..0cefa1859aaa75731267917e66ab9a1905528e91 100644 ---- a/src/providers/ad/ad_common.h -+++ b/src/providers/ad/ad_common.h -@@ -153,6 +153,11 @@ ad_ldap_conn_list(TALLOC_CTX *mem_ctx, - struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom); - -+struct sdap_id_conn_ctx ** -+ad_user_conn_list(TALLOC_CTX *mem_ctx, -+ struct ad_id_ctx *ad_ctx, -+ struct sss_domain_info *dom); -+ - struct sdap_id_conn_ctx * - ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom); - -diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c -index be0cb3b12f2e3a2b53d740ecf3befc07fd853f8b..51d378863a5c7394ca3a2b8bd72f8c131a2b02b1 100644 ---- a/src/providers/ad/ad_id.c -+++ b/src/providers/ad/ad_id.c -@@ -244,25 +244,10 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - struct sss_domain_info *dom, struct be_acct_req *ar) - { - struct sdap_id_conn_ctx **clist; -- int cindex = 0; - - switch (ar->entry_type & BE_REQ_TYPE_MASK) { - case BE_REQ_USER: /* user */ -- clist = talloc_zero_array(ad_ctx, struct sdap_id_conn_ctx *, 3); -- if (clist == NULL) return NULL; -- -- /* Try GC first for users from trusted domains */ -- if (dp_opt_get_bool(ad_ctx->ad_options->basic, AD_ENABLE_GC) -- && IS_SUBDOMAIN(dom)) { -- clist[cindex] = ad_ctx->gc_ctx; -- clist[cindex]->ignore_mark_offline = true; -- cindex++; -- } -- -- /* Users from primary domain can be just downloaded from LDAP. -- * The domain's LDAP connection also works as a fallback -- */ -- clist[cindex] = ad_get_dom_ldap_conn(ad_ctx, dom); -+ clist = ad_user_conn_list(breq, ad_ctx, dom); - break; - case BE_REQ_BY_SECID: /* by SID */ - case BE_REQ_USER_AND_GROUP: /* get SID */ -@@ -270,7 +255,6 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx, - case BE_REQ_INITGROUPS: /* init groups for user */ - clist = ad_gc_conn_list(breq, ad_ctx, dom); - break; -- - default: - /* Requests for other object should only contact LDAP by default */ - clist = ad_ldap_conn_list(breq, ad_ctx, dom); -diff --git a/src/tests/cmocka/test_ad_common.c b/src/tests/cmocka/test_ad_common.c -index c7bcc0f7cfde7164672123a35940327ee3ca4aba..f6a4c0db413bbe9c79e6d41f3de5ac75d080c225 100644 ---- a/src/tests/cmocka/test_ad_common.c -+++ b/src/tests/cmocka/test_ad_common.c -@@ -433,6 +433,37 @@ void test_ldap_conn_list(void **state) - talloc_free(conn_list); - } - -+void test_user_conn_list(void **state) -+{ -+ struct sdap_id_conn_ctx **conn_list; -+ -+ struct ad_common_test_ctx *test_ctx = talloc_get_type(*state, -+ struct ad_common_test_ctx); -+ assert_non_null(test_ctx); -+ -+ conn_list = ad_user_conn_list(test_ctx, -+ test_ctx->ad_ctx, -+ test_ctx->dom); -+ assert_non_null(conn_list); -+ -+ assert_true(conn_list[0] == test_ctx->ad_ctx->ldap_ctx); -+ assert_false(conn_list[0]->ignore_mark_offline); -+ assert_null(conn_list[1]); -+ talloc_free(conn_list); -+ -+ conn_list = ad_user_conn_list(test_ctx, -+ test_ctx->ad_ctx, -+ test_ctx->subdom); -+ assert_non_null(conn_list); -+ -+ assert_true(conn_list[0] == test_ctx->ad_ctx->gc_ctx); -+ assert_true(conn_list[0]->ignore_mark_offline); -+ assert_true(conn_list[1] == test_ctx->subdom_ad_ctx->ldap_ctx); -+ /* Subdomain error should not set the backend offline! */ -+ assert_true(conn_list[1]->ignore_mark_offline); -+ talloc_free(conn_list); -+} -+ - int main(int argc, const char *argv[]) - { - poptContext pc; -@@ -460,6 +491,9 @@ int main(int argc, const char *argv[]) - cmocka_unit_test_setup_teardown(test_ldap_conn_list, - test_ldap_conn_setup, - test_ldap_conn_teardown), -+ cmocka_unit_test_setup_teardown(test_user_conn_list, -+ test_ldap_conn_setup, -+ test_ldap_conn_teardown), - }; - - /* Set debug level to invalid value so we can deside if -d 0 was used. */ --- -2.4.3 - diff --git a/SOURCES/0101-NSS-Remove-unused-functions.patch b/SOURCES/0101-NSS-Remove-unused-functions.patch new file mode 100644 index 0000000..f7b683f --- /dev/null +++ b/SOURCES/0101-NSS-Remove-unused-functions.patch @@ -0,0 +1,187 @@ +From 684ab7416ea1311a98516faddcc975a9731b2a0f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 19 Jul 2016 14:42:26 +0200 +Subject: [PATCH 101/102] NSS: Remove unused functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When removing the old data provider I noticed that those functions +are not used at all. + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit f31610a9ba26b46de9eeab2b0719ff6ad8961104) +--- + src/responder/nss/nsssrv.c | 11 ---- + src/responder/nss/nsssrv_cmd.c | 112 ------------------------------------- + src/responder/nss/nsssrv_private.h | 2 - + 3 files changed, 125 deletions(-) + +diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c +index 05b51ecdf2e17e20af2ee3ee48377cbe1bf19a24..06d58f21b00b73c6c7a4b7583e10b4b61a627d75 100644 +--- a/src/responder/nss/nsssrv.c ++++ b/src/responder/nss/nsssrv.c +@@ -328,17 +328,6 @@ done: + return ret; + } + +-int nss_update_memcache(struct sbus_request *dbus_req, void *data) +-{ +- struct resp_ctx *rctx = talloc_get_type(data, struct resp_ctx); +- struct nss_ctx *nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx); +- +- nss_update_pw_memcache(nctx); +- nss_update_gr_memcache(nctx); +- +- return EOK; +-} +- + int nss_memorycache_update_initgroups(struct sbus_request *sbus_req, + void *data, + const char *user, +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index 573959ea76fc1277fe84f40b88dcd34093da468d..b64cea2a53ec6032904237b0afc1377022c2c804 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -118,66 +118,6 @@ static int nss_reset_negcache(struct resp_ctx *rctx) + * PASSWD db related functions + ***************************************************************************/ + +-void nss_update_pw_memcache(struct nss_ctx *nctx) +-{ +- struct sss_domain_info *dom; +- struct ldb_result *res; +- uint64_t exp; +- struct sized_string key; +- const char *id; +- time_t now; +- int ret; +- int i; +- +- now = time(NULL); +- +- for (dom = nctx->rctx->domains; dom; dom = get_next_domain(dom, 0)) { +- ret = sysdb_enumpwent_with_views(nctx, dom, &res); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to enumerate users for domain [%s]\n", dom->name); +- continue; +- } +- +- for (i = 0; i < res->count; i++) { +- exp = ldb_msg_find_attr_as_uint64(res->msgs[i], +- SYSDB_CACHE_EXPIRE, 0); +- if (exp >= now) { +- continue; +- } +- +- /* names require more manipulation (build up fqname conditionally), +- * but uidNumber is unique and always resolvable too, so we use +- * that to update the cache, as it points to the same entry */ +- id = sss_view_ldb_msg_find_attr_as_string(dom, res->msgs[i], +- SYSDB_UIDNUM, NULL); +- if (!id) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to find uidNumber in %s.\n", +- ldb_dn_get_linearized(res->msgs[i]->dn)); +- continue; +- } +- to_sized_string(&key, id); +- +- ret = sss_mmap_cache_pw_invalidate(nctx->pwd_mc_ctx, &key); +- if (ret != EOK && ret != ENOENT) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Internal failure in memory cache code: %d [%s]\n", +- ret, strerror(ret)); +- } +- +- ret = sss_mmap_cache_pw_invalidate(nctx->initgr_mc_ctx, &key); +- if (ret != EOK && ret != ENOENT) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Internal failure in memory cache code: %d [%s]\n", +- ret, strerror(ret)); +- } +- } +- +- talloc_zfree(res); +- } +-} +- + static gid_t get_gid_override(struct ldb_message *msg, + struct sss_domain_info *dom) + { +@@ -2743,58 +2683,6 @@ done: + * GROUP db related functions + ***************************************************************************/ + +-void nss_update_gr_memcache(struct nss_ctx *nctx) +-{ +- struct sss_domain_info *dom; +- struct ldb_result *res; +- uint64_t exp; +- struct sized_string key; +- const char *id; +- time_t now; +- int ret; +- int i; +- +- now = time(NULL); +- +- for (dom = nctx->rctx->domains; dom; dom = get_next_domain(dom, 0)) { +- ret = sysdb_enumgrent_with_views(nctx, dom, &res); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to enumerate users for domain [%s]\n", dom->name); +- continue; +- } +- +- for (i = 0; i < res->count; i++) { +- exp = ldb_msg_find_attr_as_uint64(res->msgs[i], +- SYSDB_CACHE_EXPIRE, 0); +- if (exp >= now) { +- continue; +- } +- +- /* names require more manipulation (build up fqname conditionally), +- * but uidNumber is unique and always resolvable too, so we use +- * that to update the cache, as it points to the same entry */ +- id = sss_view_ldb_msg_find_attr_as_string(dom, res->msgs[i], +- SYSDB_GIDNUM, NULL); +- if (!id) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to find gidNumber in %s.\n", +- ldb_dn_get_linearized(res->msgs[i]->dn)); +- continue; +- } +- to_sized_string(&key, id); +- +- ret = sss_mmap_cache_gr_invalidate(nctx->grp_mc_ctx, &key); +- if (ret != EOK && ret != ENOENT) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Internal failure in memory cache code: %d [%s]\n", +- ret, strerror(ret)); +- } +- } +- talloc_zfree(res); +- } +-} +- + #define GID_ROFFSET 0 + #define MNUM_ROFFSET sizeof(uint32_t) + #define STRS_ROFFSET 2*sizeof(uint32_t) +diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h +index 391eaaf40f84a7436bee63fd699241e4957fdbeb..472022235adab2c2d2547ee2706ef23fa91b1f8d 100644 +--- a/src/responder/nss/nsssrv_private.h ++++ b/src/responder/nss/nsssrv_private.h +@@ -143,8 +143,6 @@ errno_t check_cache(struct nss_dom_ctx *dctx, + sss_dp_callback_t callback, + void *pvt); + +-void nss_update_pw_memcache(struct nss_ctx *nctx); +-void nss_update_gr_memcache(struct nss_ctx *nctx); + void nss_update_initgr_memcache(struct nss_ctx *nctx, + const char *fq_name, const char *domain, + int gnum, uint32_t *groups); +-- +2.4.11 + diff --git a/SOURCES/0102-LDAP-Fixing-of-removing-netgroup-from-cache.patch b/SOURCES/0102-LDAP-Fixing-of-removing-netgroup-from-cache.patch new file mode 100644 index 0000000..2932c7e --- /dev/null +++ b/SOURCES/0102-LDAP-Fixing-of-removing-netgroup-from-cache.patch @@ -0,0 +1,75 @@ +From c0dedeccc42fa7cc14e207182d54595926dfd700 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Fri, 22 Jul 2016 14:28:54 +0200 +Subject: [PATCH 102/102] LDAP: Fixing of removing netgroup from cache + +There were problem with local key which wasn't properly removed. +This patch fixes it. + +Resolves: +https://fedorahosted.org/sssd/ticket/2841 +--- + src/providers/ldap/sdap_async_netgroups.c | 40 +++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/src/providers/ldap/sdap_async_netgroups.c b/src/providers/ldap/sdap_async_netgroups.c +index df233d956df70cfcb5f68bd2afc9e2a23c50c3bb..cf7d7b12361f8cc578b891961c0c5566442f1b4e 100644 +--- a/src/providers/ldap/sdap_async_netgroups.c ++++ b/src/providers/ldap/sdap_async_netgroups.c +@@ -38,6 +38,35 @@ bool is_dn(const char *str) + return (ret == LDAP_SUCCESS ? true : false); + } + ++static errno_t add_to_missing_attrs(TALLOC_CTX * mem_ctx, ++ struct sysdb_attrs *attrs, ++ const char *ext_key, ++ char ***_missing) ++{ ++ bool is_present = false; ++ size_t size = 0; ++ size_t ret; ++ ++ for (int i = 0; i < attrs->num; i++) { ++ if (strcmp(ext_key, attrs->a[i].name) == 0) { ++ is_present = true; ++ } ++ size++; ++ } ++ ++ if (is_present == false) { ++ ret = add_string_to_list(attrs, ext_key, _missing); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ ++ ret = EOK; ++ ++done: ++ return ret; ++} ++ + static errno_t sdap_save_netgroup(TALLOC_CTX *memctx, + struct sss_domain_info *dom, + struct sdap_options *opts, +@@ -138,6 +167,17 @@ static errno_t sdap_save_netgroup(TALLOC_CTX *memctx, + goto fail; + } + ++ /* Prepare SYSDB_NETGROUP_MEMBER removing ++ * if not present in netgroup_attrs ++ */ ++ ret = add_to_missing_attrs(attrs, netgroup_attrs, SYSDB_NETGROUP_MEMBER, ++ &missing); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add [%s] to missing attributes\n", ++ SYSDB_NETGROUP_MEMBER); ++ goto fail; ++ } ++ + ret = sysdb_add_netgroup(dom, name, NULL, netgroup_attrs, missing, + dom->netgroup_timeout, now); + if (ret) goto fail; +-- +2.4.11 + diff --git a/SOURCES/0102-nss-send-original-name-and-id-with-local-views-if-po.patch b/SOURCES/0102-nss-send-original-name-and-id-with-local-views-if-po.patch deleted file mode 100644 index 475bf31..0000000 --- a/SOURCES/0102-nss-send-original-name-and-id-with-local-views-if-po.patch +++ /dev/null @@ -1,191 +0,0 @@ -From c12a2635adacbb321c4c2208160f2eb306333e71 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Sun, 11 Oct 2015 16:45:19 +0200 -Subject: [PATCH 102/104] nss: send original name and id with local views if - possible - -Resolves: -https://fedorahosted.org/sssd/ticket/2833 - -Reviewed-by: Sumit Bose -Reviewed-by: Jakub Hrozek -(cherry picked from commit 2f793681b4debbe015815f908dc12c0463711609) ---- - src/responder/nss/nsssrv_cmd.c | 131 ++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 128 insertions(+), 3 deletions(-) - -diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c -index d177135db00369c2af69eb62f6a4a4aaf54ba510..39fd5b41a31796a05a1790e78cb6c425b39c47cb 100644 ---- a/src/responder/nss/nsssrv_cmd.c -+++ b/src/responder/nss/nsssrv_cmd.c -@@ -599,6 +599,124 @@ is_refreshed_on_bg(enum sss_dp_acct_type req_type, - - static void nsssrv_dp_send_acct_req_done(struct tevent_req *req); - -+static void get_dp_name_and_id(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *dom, -+ enum sss_dp_acct_type req_type, -+ const char *opt_name, -+ uint32_t opt_id, -+ const char **_name, -+ uint32_t *_id) -+{ -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_result *res = NULL; -+ const char *attr; -+ const char *name; -+ uint32_t id; -+ errno_t ret; -+ -+ /* First set the same values to make things easier. */ -+ *_name = opt_name; -+ *_id = opt_id; -+ -+ if (!DOM_HAS_VIEWS(dom) || !is_local_view(dom->view_name)) { -+ DEBUG(SSSDBG_TRACE_FUNC, "Not a LOCAL view, continuing with " -+ "provided values.\n"); -+ return; -+ } -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); -+ return; -+ } -+ -+ if (opt_name != NULL) { -+ switch (req_type) { -+ case SSS_DP_USER: -+ case SSS_DP_INITGROUPS: -+ ret = sysdb_getpwnam_with_views(tmp_ctx, dom, opt_name, &res); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ "sysdb_getpwnam_with_views() failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ break; -+ case SSS_DP_GROUP: -+ ret = sysdb_getgrnam_with_views(tmp_ctx, dom, opt_name, &res); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ "sysdb_getgrnam_with_views() failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ break; -+ default: -+ goto done; -+ } -+ -+ if (res == NULL || res->count != 1) { -+ /* This should not happen with LOCAL view and overridden value. */ -+ DEBUG(SSSDBG_TRACE_FUNC, "Entry is missing?! Continuing with " -+ "provided values.\n"); -+ goto done; -+ } -+ -+ name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL); -+ if (name == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); -+ goto done; -+ } -+ -+ *_name = talloc_steal(mem_ctx, name); -+ } else if (opt_id != 0) { -+ switch (req_type) { -+ case SSS_DP_USER: -+ ret = sysdb_getpwuid_with_views(tmp_ctx, dom, opt_id, &res); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ "sysdb_getpwuid_with_views() failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ attr = SYSDB_UIDNUM; -+ break; -+ case SSS_DP_GROUP: -+ ret = sysdb_getgrgid_with_views(tmp_ctx, dom, opt_id, &res); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CONF_SETTINGS, -+ "sysdb_getgrgid_with_views() failed [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ attr = SYSDB_GIDNUM; -+ break; -+ default: -+ goto done; -+ } -+ -+ if (res == NULL || res->count != 1) { -+ /* This should not happen with LOCAL view and overridden value. */ -+ DEBUG(SSSDBG_TRACE_FUNC, "Entry is missing?! Continuing with " -+ "provided values.\n"); -+ goto done; -+ } -+ -+ id = ldb_msg_find_attr_as_uint64(res->msgs[0], attr, 0); -+ if (id == 0) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n"); -+ goto done; -+ } -+ -+ *_id = id; -+ } -+ -+done: -+ talloc_free(tmp_ctx); -+} -+ - /* FIXME: do not check res->count, but get in a msgs and check in parent */ - errno_t check_cache(struct nss_dom_ctx *dctx, - struct nss_ctx *nctx, -@@ -616,6 +734,8 @@ errno_t check_cache(struct nss_dom_ctx *dctx, - struct tevent_req *req = NULL; - struct dp_callback_ctx *cb_ctx = NULL; - uint64_t cacheExpire = 0; -+ const char *name = opt_name; -+ uint32_t id = opt_id; - - /* when searching for a user or netgroup, more than one reply is a - * db error -@@ -627,6 +747,11 @@ errno_t check_cache(struct nss_dom_ctx *dctx, - return ENOENT; - } - -+ /* In case of local view we have to always contant DP with the original -+ * name or id. */ -+ get_dp_name_and_id(dctx->cmdctx, dctx->domain, req_type, opt_name, opt_id, -+ &name, &id); -+ - /* if we have any reply let's check cache validity, but ignore netgroups - * if refresh_expired_interval is set (which implies that another method - * is used to refresh netgroups) -@@ -671,10 +796,10 @@ errno_t check_cache(struct nss_dom_ctx *dctx, - * immediately. - */ - DEBUG(SSSDBG_TRACE_FUNC, -- "Performing midpoint cache update on [%s]\n", opt_name); -+ "Performing midpoint cache update on [%s]\n", name); - - req = sss_dp_get_account_send(cctx, cctx->rctx, dctx->domain, true, -- req_type, opt_name, opt_id, extra); -+ req_type, name, id, extra); - if (!req) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Out of memory sending out-of-band data provider " -@@ -703,7 +828,7 @@ errno_t check_cache(struct nss_dom_ctx *dctx, - } - - req = sss_dp_get_account_send(cctx, cctx->rctx, dctx->domain, true, -- req_type, opt_name, opt_id, extra); -+ req_type, name, id, extra); - if (!req) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Out of memory sending data provider request\n"); --- -2.4.3 - diff --git a/SOURCES/0103-AD_PROVIDER-Add-ad_enabled_domains-option.patch b/SOURCES/0103-AD_PROVIDER-Add-ad_enabled_domains-option.patch new file mode 100644 index 0000000..d31b96f --- /dev/null +++ b/SOURCES/0103-AD_PROVIDER-Add-ad_enabled_domains-option.patch @@ -0,0 +1,122 @@ +From 5377817417b800335c5ae21f7e6b301ddbcbe1d1 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Fri, 13 May 2016 05:21:07 -0400 +Subject: [PATCH 103/108] AD_PROVIDER: Add ad_enabled_domains option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/2828 + +Reviewed-by: Jakub Hrozek +Reviewed-by: Lukáš Slebodník +--- + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/cfg_rules.ini | 1 + + src/config/etc/sssd.api.d/sssd-ad.conf | 1 + + src/man/sssd-ad.5.xml | 27 +++++++++++++++++++++++++++ + src/providers/ad/ad_common.h | 1 + + src/providers/ad/ad_opts.c | 1 + + 6 files changed, 32 insertions(+) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index ac538788b9878dc2613cb48b7483d392cca41d47..1718a9babf390b95710ec356f25f09ea679bdd73 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -192,6 +192,7 @@ option_strings = { + + # [provider/ad] + 'ad_domain' : _('Active Directory domain'), ++ 'ad_enabled_domains' : _('Enabled Active Directory domains'), + 'ad_server' : _('Active Directory server address'), + 'ad_backup_server' : _('Active Directory backup server address'), + 'ad_hostname' : _('Active Directory client hostname'), +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index bd0116f334e2605e7671a208225761421511a75a..ef6435b08aee416e377fe854e6768f3fa4fd9650 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -335,6 +335,7 @@ option = ad_access_filter + option = ad_backup_server + option = ad_domain + option = ad_enable_dns_sites ++option = ad_enabled_domains + option = ad_enable_gc + option = ad_gpo_access_control + option = ad_gpo_cache_timeout +diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf +index 87a74f4af0770874c71baaea02d2313721db78bf..8d97a416c8c97bff096042b0b70a3b2c18183710 100644 +--- a/src/config/etc/sssd.api.d/sssd-ad.conf ++++ b/src/config/etc/sssd.api.d/sssd-ad.conf +@@ -1,5 +1,6 @@ + [provider/ad] + ad_domain = str, None, false ++ad_enabled_domains = str, None, false + ad_server = str, None, false + ad_backup_server = str, None, false + ad_hostname = str, None, false +diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml +index ef27976dd62e164cfb91359efc69bd54e1aa9711..8a2f4ade9387f0d5723b7056bdce9e83363cf035 100644 +--- a/src/man/sssd-ad.5.xml ++++ b/src/man/sssd-ad.5.xml +@@ -114,6 +114,33 @@ ldap_id_mapping = False + + + ++ ad_enabled_domains (string) ++ ++ ++ A comma-separated list of enabled Active Directory domains. ++ If provided, SSSD will ignore any domains not listed in this ++ option. If left unset, all domains from the AD forest will ++ be available. ++ ++ ++ For proper operation, this option must be specified in all ++ lower-case and as the fully qualified domain name of the ++ Active Directory domain. For example: ++ ++ad_enabled_domains = sales.example.com, eng.example.com ++ ++ ++ ++ The short domain name (also known as the NetBIOS or the flat ++ name) will be autodetected by SSSD. ++ ++ ++ Default: Not set ++ ++ ++ ++ ++ + ad_server, ad_backup_server (string) + + +diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h +index 7e86faf1142d7be49eef01e1ddd7bfafea2fcedc..23351e328968918aa9ca9009c052e670a7d55258 100644 +--- a/src/providers/ad/ad_common.h ++++ b/src/providers/ad/ad_common.h +@@ -42,6 +42,7 @@ struct ad_options; + + enum ad_basic_opt { + AD_DOMAIN = 0, ++ AD_ENABLED_DOMAINS, + AD_SERVER, + AD_BACKUP_SERVER, + AD_HOSTNAME, +diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c +index 829f9d9556bc3fa74a95eb76db0e31b19befe8fe..fc1dc67337845754eba8c879c78e08c1777a4abc 100644 +--- a/src/providers/ad/ad_opts.c ++++ b/src/providers/ad/ad_opts.c +@@ -28,6 +28,7 @@ + + struct dp_option ad_basic_opts[] = { + { "ad_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, ++ { "ad_enabled_domains", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ad_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ad_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ad_hostname", DP_OPT_STRING, NULL_STRING, NULL_STRING }, +-- +2.4.11 + diff --git a/SOURCES/0103-sudo-search-with-view-even-if-user-is-found.patch b/SOURCES/0103-sudo-search-with-view-even-if-user-is-found.patch deleted file mode 100644 index fe9f9bf..0000000 --- a/SOURCES/0103-sudo-search-with-view-even-if-user-is-found.patch +++ /dev/null @@ -1,35 +0,0 @@ -From f69e9a566540896682c1021de92e5eec6a95dd9d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Sun, 11 Oct 2015 17:38:34 +0200 -Subject: [PATCH 103/104] sudo: search with view even if user is found - -If an overriden name is provided and the user is already cache we fail -to refresh it since we won't search with VIEW flag. This patch fix -it. - -Reviewed-by: Sumit Bose -Reviewed-by: Jakub Hrozek -(cherry picked from commit 51a0e3a2ef9186d19cbc28d87fe6fc5d5998a0a7) ---- - src/responder/sudo/sudosrv_get_sudorules.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c -index a0b09e69b71f963c353c9c6331c0708cc364924c..cc06977d97e3319584251bdab26e85855d275e8a 100644 ---- a/src/responder/sudo/sudosrv_get_sudorules.c -+++ b/src/responder/sudo/sudosrv_get_sudorules.c -@@ -160,7 +160,10 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx) - if ((user->count == 0 || cache_expire < time(NULL)) - && dctx->check_provider) { - -- if (DOM_HAS_VIEWS(dom) && user->count == 0) { -+ if (DOM_HAS_VIEWS(dom) && (user->count == 0 -+ || ldb_msg_find_attr_as_string(user->msgs[0], -+ OVERRIDE_PREFIX SYSDB_NAME, -+ NULL) != NULL)) { - extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; - } - --- -2.4.3 - diff --git a/SOURCES/0104-AD_PROVIDER-Initializing-of-ad_enabled_domains.patch b/SOURCES/0104-AD_PROVIDER-Initializing-of-ad_enabled_domains.patch new file mode 100644 index 0000000..9fa1c6c --- /dev/null +++ b/SOURCES/0104-AD_PROVIDER-Initializing-of-ad_enabled_domains.patch @@ -0,0 +1,143 @@ +From 7e8b6166086cf04c5b1290c3dffd268438ef9c2c Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 21 Jun 2016 08:34:15 +0200 +Subject: [PATCH 104/108] AD_PROVIDER: Initializing of ad_enabled_domains +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We add ad_enabled_domains into ad_subdomains_ctx. + +Resolves: +https://fedorahosted.org/sssd/ticket/2828 + +Reviewed-by: Jakub Hrozek +Reviewed-by: Lukáš Slebodník +--- + src/providers/ad/ad_subdomains.c | 82 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 82 insertions(+) + +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index a0d5c2e544fc62fda64771dce59b3b7ab8ecd8b6..6e44760330275f7e4262e6863f180747f659edb5 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -57,6 +57,79 @@ + /* do not refresh more often than every 5 seconds for now */ + #define AD_SUBDOMAIN_REFRESH_LIMIT 5 + ++static errno_t ad_get_enabled_domains(TALLOC_CTX *mem_ctx, ++ struct ad_id_ctx *ad_id_ctx, ++ const char *ad_domain, ++ const char ***_ad_enabled_domains) ++{ ++ int ret; ++ const char *str; ++ const char *option_name; ++ const char **domains = NULL; ++ int count; ++ bool is_ad_in_domains; ++ TALLOC_CTX *tmp_ctx = NULL; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ str = dp_opt_get_cstring(ad_id_ctx->ad_options->basic, AD_ENABLED_DOMAINS); ++ if (str == NULL) { ++ *_ad_enabled_domains = NULL; ++ ret = EOK; ++ goto done; ++ } ++ ++ count = 0; ++ ret = split_on_separator(tmp_ctx, str, ',', true, true, ++ discard_const_p(char **, &domains), &count); ++ if (ret != EOK) { ++ option_name = ad_id_ctx->ad_options->basic[AD_ENABLED_DOMAINS].opt_name; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse option [%s], [%i] [%s]!\n", ++ option_name, ret, sss_strerror(ret)); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ is_ad_in_domains = false; ++ for (int i = 0; i < count; i++) { ++ is_ad_in_domains += strcmp(ad_domain, domains[i]) == 0 ? true : false; ++ } ++ ++ if (is_ad_in_domains == false) { ++ domains = talloc_realloc(tmp_ctx, domains, const char*, count + 2); ++ if (domains == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ domains[count] = talloc_strdup(domains, ad_domain); ++ if (domains[count] == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ domains[count + 1] = NULL; ++ } else { ++ domains = talloc_realloc(tmp_ctx, domains, const char*, count + 1); ++ if (domains == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ domains[count] = NULL; ++ } ++ ++ *_ad_enabled_domains = talloc_steal(mem_ctx, domains); ++ ret = EOK; ++ ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ + static errno_t + ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, + struct ad_id_ctx *id_ctx, +@@ -171,6 +244,7 @@ struct ad_subdomains_ctx { + + struct sdap_domain *sdom; + char *domain_name; ++ const char **ad_enabled_domains; + + time_t last_refreshed; + }; +@@ -1357,6 +1431,7 @@ errno_t ad_subdomains_init(TALLOC_CTX *mem_ctx, + { + struct ad_subdomains_ctx *sd_ctx; + const char *ad_domain; ++ const char **ad_enabled_domains = NULL; + time_t period; + errno_t ret; + +@@ -1368,6 +1443,12 @@ errno_t ad_subdomains_init(TALLOC_CTX *mem_ctx, + return ENOMEM; + } + ++ ret = ad_get_enabled_domains(sd_ctx, ad_id_ctx, ad_domain, ++ &ad_enabled_domains); ++ if (ret != EOK) { ++ return EINVAL; ++ } ++ + sd_ctx->be_ctx = be_ctx; + sd_ctx->sdom = ad_id_ctx->sdap_id_ctx->opts->sdom; + sd_ctx->sdap_id_ctx = ad_id_ctx->sdap_id_ctx; +@@ -1376,6 +1457,7 @@ errno_t ad_subdomains_init(TALLOC_CTX *mem_ctx, + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + return ENOMEM; + } ++ sd_ctx->ad_enabled_domains = ad_enabled_domains; + sd_ctx->ad_id_ctx = ad_id_ctx; + + dp_set_method(dp_methods, DPM_DOMAINS_HANDLER, +-- +2.4.11 + diff --git a/SOURCES/0104-sudo-send-original-name-and-id-with-local-views-if-p.patch b/SOURCES/0104-sudo-send-original-name-and-id-with-local-views-if-p.patch deleted file mode 100644 index 241248c..0000000 --- a/SOURCES/0104-sudo-send-original-name-and-id-with-local-views-if-p.patch +++ /dev/null @@ -1,60 +0,0 @@ -From ea4b1387c604093036559a1bfc0368c70d73fc4f Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pavel=20B=C5=99ezina?= -Date: Sun, 11 Oct 2015 17:53:28 +0200 -Subject: [PATCH 104/104] sudo: send original name and id with local views if - possible - -Resolves: -https://fedorahosted.org/sssd/ticket/2833 - -Reviewed-by: Sumit Bose -Reviewed-by: Jakub Hrozek -(cherry picked from commit fb8985a3a3a267940760967beaf8af3979ce91ea) ---- - src/responder/sudo/sudosrv_get_sudorules.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c -index cc06977d97e3319584251bdab26e85855d275e8a..c3336960eeac18ee63167de81891984aa764540c 100644 ---- a/src/responder/sudo/sudosrv_get_sudorules.c -+++ b/src/responder/sudo/sudosrv_get_sudorules.c -@@ -79,6 +79,7 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx) - struct dp_callback_ctx *cb_ctx; - const char *original_name = NULL; - const char *extra_flag = NULL; -+ const char *search_name = NULL; - char *name = NULL; - uid_t uid = 0; - errno_t ret; -@@ -160,16 +161,23 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx) - if ((user->count == 0 || cache_expire < time(NULL)) - && dctx->check_provider) { - -- if (DOM_HAS_VIEWS(dom) && (user->count == 0 -- || ldb_msg_find_attr_as_string(user->msgs[0], -- OVERRIDE_PREFIX SYSDB_NAME, -- NULL) != NULL)) { -+ search_name = cmd_ctx->username; -+ if (is_local_view(dom->view_name)) { -+ /* Search with original name in case of local view. */ -+ if (user->count != 0) { -+ search_name = ldb_msg_find_attr_as_string(user->msgs[0], -+ SYSDB_NAME, NULL); -+ } -+ } else if (DOM_HAS_VIEWS(dom) && (user->count == 0 -+ || ldb_msg_find_attr_as_string(user->msgs[0], -+ OVERRIDE_PREFIX SYSDB_NAME, -+ NULL) != NULL)) { - extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; - } - - dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx, - dom, false, SSS_DP_INITGROUPS, -- cmd_ctx->username, 0, extra_flag); -+ search_name, 0, extra_flag); - if (!dpreq) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Out of memory sending data provider request\n"); --- -2.4.3 - diff --git a/SOURCES/0105-AD_PROVIDER-ad_enabled_domains-only-master.patch b/SOURCES/0105-AD_PROVIDER-ad_enabled_domains-only-master.patch new file mode 100644 index 0000000..81520da --- /dev/null +++ b/SOURCES/0105-AD_PROVIDER-ad_enabled_domains-only-master.patch @@ -0,0 +1,57 @@ +From a0009ecf7cfaaa14eb5b041b9e1d8247d18c61cb Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 21 Jun 2016 09:48:52 +0200 +Subject: [PATCH 105/108] AD_PROVIDER: ad_enabled_domains - only master +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We can skip looking up other domains if option ad_enabled_domains +contains only master domain. + +Resolves: +https://fedorahosted.org/sssd/ticket/2828 + +Reviewed-by: Jakub Hrozek +Reviewed-by: Lukáš Slebodník +--- + src/providers/ad/ad_subdomains.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index 6e44760330275f7e4262e6863f180747f659edb5..5fdfc63886457db02ea4edc430341b31c3e545ce 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -1170,6 +1170,7 @@ static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq) + return; + } + ++ /* connect to the DC we are a member of */ + subreq = ad_master_domain_send(state, state->ev, state->id_ctx->conn, + state->sdap_op, state->sd_ctx->domain_name); + if (subreq == NULL) { +@@ -1218,6 +1219,21 @@ static void ad_subdomains_refresh_master_done(struct tevent_req *subreq) + goto done; + } + ++ /* ++ * If ad_enabled_domains contains only master domain ++ * we shouldn't lookup other domains. ++ */ ++ if (state->sd_ctx->ad_enabled_domains != NULL) { ++ if (talloc_array_length(state->sd_ctx->ad_enabled_domains) == 2) { ++ if (strcasecmp(state->sd_ctx->ad_enabled_domains[0], ++ state->be_ctx->domain->name) == 0) { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "No other enabled domain than master.\n"); ++ goto done; ++ } ++ } ++ } ++ + subreq = ad_get_root_domain_send(state, state->ev, forest, + sdap_id_op_handle(state->sdap_op), + state->sd_ctx); +-- +2.4.11 + diff --git a/SOURCES/0105-IPA-fix-override-with-the-same-name.patch b/SOURCES/0105-IPA-fix-override-with-the-same-name.patch deleted file mode 100644 index 1709e1c..0000000 --- a/SOURCES/0105-IPA-fix-override-with-the-same-name.patch +++ /dev/null @@ -1,238 +0,0 @@ -From 6f25f357e3d000f6ad750bc336d24f8402e896af Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 19 Nov 2015 11:42:39 +0100 -Subject: [PATCH] IPA: fix override with the same name - -If the user name of a AD user is overridden with the name itself in an -IPA override object SSSD adds this name twice to the alias list causing -an ldb error when trying to write the user object to the cache. As a -result the user is not available. - -This patch makes sure that there are no duplicated alias names. - -Resolves https://fedorahosted.org/sssd/ticket/2874 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit aedc71fe8360a51785933523f14bb5c4e7e2c38b) ---- - src/db/sysdb.c | 18 ++++++++-- - src/db/sysdb.h | 4 ++- - src/providers/ipa/ipa_s2n_exop.c | 13 +++---- - src/tests/sysdb-tests.c | 78 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 103 insertions(+), 10 deletions(-) - -diff --git a/src/db/sysdb.c b/src/db/sysdb.c -index 07a83a8a8e30df1b8e461a8d04866f2dbc53baf8..a71364d7c4b600eafd10fafa6641eac7b2292764 100644 ---- a/src/db/sysdb.c -+++ b/src/db/sysdb.c -@@ -598,7 +598,7 @@ int sysdb_attrs_add_string(struct sysdb_attrs *attrs, - return sysdb_attrs_add_val(attrs, name, &v); - } - --int sysdb_attrs_add_lower_case_string(struct sysdb_attrs *attrs, -+int sysdb_attrs_add_lower_case_string(struct sysdb_attrs *attrs, bool safe, - const char *name, const char *str) - { - char *lc_str; -@@ -614,7 +614,11 @@ int sysdb_attrs_add_lower_case_string(struct sysdb_attrs *attrs, - return ENOMEM; - } - -- ret = sysdb_attrs_add_string(attrs, name, lc_str); -+ if (safe) { -+ ret = sysdb_attrs_add_string_safe(attrs, name, lc_str); -+ } else { -+ ret = sysdb_attrs_add_string(attrs, name, lc_str); -+ } - talloc_free(lc_str); - - return ret; -@@ -729,7 +733,15 @@ int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs, - int sysdb_attrs_add_lc_name_alias(struct sysdb_attrs *attrs, - const char *value) - { -- return sysdb_attrs_add_lower_case_string(attrs, SYSDB_NAME_ALIAS, value); -+ return sysdb_attrs_add_lower_case_string(attrs, false, SYSDB_NAME_ALIAS, -+ value); -+} -+ -+int sysdb_attrs_add_lc_name_alias_safe(struct sysdb_attrs *attrs, -+ const char *value) -+{ -+ return sysdb_attrs_add_lower_case_string(attrs, true, SYSDB_NAME_ALIAS, -+ value); - } - - int sysdb_attrs_copy_values(struct sysdb_attrs *src, -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index 9e28b5c6691f3710e3051d9746ac5fa47aff8424..3fa3f040708a4984158206d66a1d28a079091cf7 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -315,7 +315,7 @@ int sysdb_attrs_add_string_safe(struct sysdb_attrs *attrs, - const char *name, const char *str); - int sysdb_attrs_add_string(struct sysdb_attrs *attrs, - const char *name, const char *str); --int sysdb_attrs_add_lower_case_string(struct sysdb_attrs *attrs, -+int sysdb_attrs_add_lower_case_string(struct sysdb_attrs *attrs, bool safe, - const char *name, const char *str); - int sysdb_attrs_add_mem(struct sysdb_attrs *attrs, const char *name, - const void *mem, size_t size); -@@ -329,6 +329,8 @@ 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_add_lc_name_alias_safe(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/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index 1e6368dc7ef1a6f60b541409f7f6740d602f0d43..bcd11749fbde4cae2a47b9b2182138ae04f2d6bc 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -1804,10 +1804,11 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - ret = sysdb_attrs_get_string(attrs->sysdb_attrs, - SYSDB_DEFAULT_OVERRIDE_NAME, &tmp_str); - if (ret == EOK) { -- ret = sysdb_attrs_add_lc_name_alias(attrs->sysdb_attrs, tmp_str); -+ ret = sysdb_attrs_add_lc_name_alias_safe(attrs->sysdb_attrs, -+ tmp_str); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, -- "sysdb_attrs_add_lc_name_alias failed.\n"); -+ "sysdb_attrs_add_lc_name_alias_safe failed.\n"); - goto done; - } - } else if (ret != ENOENT) { -@@ -1876,10 +1877,10 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - } - } - -- ret = sysdb_attrs_add_lc_name_alias(attrs->sysdb_attrs, name); -+ ret = sysdb_attrs_add_lc_name_alias_safe(attrs->sysdb_attrs, name); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, -- "sysdb_attrs_add_lc_name_alias failed.\n"); -+ "sysdb_attrs_add_lc_name_alias_safe failed.\n"); - goto done; - } - -@@ -2133,10 +2134,10 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - } - DEBUG(SSSDBG_TRACE_FUNC, "Processing group %s\n", name); - -- ret = sysdb_attrs_add_lc_name_alias(attrs->sysdb_attrs, name); -+ ret = sysdb_attrs_add_lc_name_alias_safe(attrs->sysdb_attrs, name); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, -- "sysdb_attrs_add_lc_name_alias failed.\n"); -+ "sysdb_attrs_add_lc_name_alias_safe failed.\n"); - goto done; - } - -diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c -index 522a44aa4d5c0da6d10bba10d960fff9426200c1..0b091f741ce158713ed383ad3d98dfea25f388ed 100644 ---- a/src/tests/sysdb-tests.c -+++ b/src/tests/sysdb-tests.c -@@ -4690,6 +4690,7 @@ START_TEST(test_sysdb_attrs_add_lc_name_alias) - int ret; - struct sysdb_attrs *attrs; - const char *str; -+ char **list = NULL; - - ret = sysdb_attrs_add_lc_name_alias(NULL, NULL); - fail_unless(ret == EINVAL, "EINVAL not returned for NULL input"); -@@ -4706,6 +4707,82 @@ START_TEST(test_sysdb_attrs_add_lc_name_alias) - "Unexpected value, expected [%s], got [%s]", - LC_NAME_ALIAS_CHECK_VAL, str); - -+ /* Add the same value a second time, it is not recommended to do this on -+ * purpose but the test should illustrate the different to -+ * sysdb_attrs_add_lc_name_alias_safe(). */ -+ 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_array(attrs, SYSDB_NAME_ALIAS, attrs, &list); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string_array failed"); -+ fail_unless(list != NULL, "No list returned"); -+ fail_unless(list[0] != NULL, "Missing first list element"); -+ fail_unless(strcmp(list[0], LC_NAME_ALIAS_CHECK_VAL) == 0, -+ "Unexpected value, expected [%s], got [%s]", -+ LC_NAME_ALIAS_CHECK_VAL, list[0]); -+ fail_unless(list[1] != NULL, "Missing second list element"); -+ fail_unless(strcmp(list[1], LC_NAME_ALIAS_CHECK_VAL) == 0, -+ "Unexpected value, expected [%s], got [%s]", -+ LC_NAME_ALIAS_CHECK_VAL, list[1]); -+ fail_unless(list[2] == NULL, "Missing list terminator"); -+ -+ talloc_free(attrs); -+} -+END_TEST -+ -+START_TEST(test_sysdb_attrs_add_lc_name_alias_safe) -+{ -+ int ret; -+ struct sysdb_attrs *attrs; -+ const char *str; -+ char **list = NULL; -+ -+ ret = sysdb_attrs_add_lc_name_alias_safe(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_safe(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); -+ -+ /* Adding the same value a second time should be ignored */ -+ ret = sysdb_attrs_add_lc_name_alias_safe(attrs, LC_NAME_ALIAS_TEST_VAL); -+ fail_unless(ret == EOK, "sysdb_attrs_add_lc_name_alias failed"); -+ -+ ret = sysdb_attrs_get_string_array(attrs, SYSDB_NAME_ALIAS, attrs, &list); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string_array failed"); -+ fail_unless(list != NULL, "No list returned"); -+ fail_unless(list[0] != NULL, "Missing first list element"); -+ fail_unless(strcmp(list[0], LC_NAME_ALIAS_CHECK_VAL) == 0, -+ "Unexpected value, expected [%s], got [%s]", -+ LC_NAME_ALIAS_CHECK_VAL, list[0]); -+ fail_unless(list[1] == NULL, "Missing list terminator"); -+ -+ /* Adding different value */ -+ ret = sysdb_attrs_add_lc_name_alias_safe(attrs, -+ "2nd_" LC_NAME_ALIAS_TEST_VAL); -+ fail_unless(ret == EOK, "sysdb_attrs_add_lc_name_alias failed"); -+ -+ ret = sysdb_attrs_get_string_array(attrs, SYSDB_NAME_ALIAS, attrs, &list); -+ fail_unless(ret == EOK, "sysdb_attrs_get_string_array failed"); -+ fail_unless(list != NULL, "No list returned"); -+ fail_unless(list[0] != NULL, "Missing first list element"); -+ fail_unless(strcmp(list[0], LC_NAME_ALIAS_CHECK_VAL) == 0, -+ "Unexpected value, expected [%s], got [%s]", -+ LC_NAME_ALIAS_CHECK_VAL, list[0]); -+ fail_unless(list[1] != NULL, "Missing first list element"); -+ fail_unless(strcmp(list[1], "2nd_" LC_NAME_ALIAS_CHECK_VAL) == 0, -+ "Unexpected value, expected [%s], got [%s]", -+ "2nd_" LC_NAME_ALIAS_CHECK_VAL, list[1]); -+ fail_unless(list[2] == NULL, "Missing list terminator"); -+ - talloc_free(attrs); - } - END_TEST -@@ -6412,6 +6489,7 @@ Suite *create_sysdb_suite(void) - tcase_add_test(tc_sysdb, test_sysdb_svc_remove_alias); - - tcase_add_test(tc_sysdb, test_sysdb_attrs_add_lc_name_alias); -+ tcase_add_test(tc_sysdb, test_sysdb_attrs_add_lc_name_alias_safe); - - /* ===== UTIL TESTS ===== */ - tcase_add_test(tc_sysdb, test_sysdb_attrs_get_string_array); --- -2.4.3 - diff --git a/SOURCES/0106-AD_PROVIDER-ad_enabled_domains-other-then-master.patch b/SOURCES/0106-AD_PROVIDER-ad_enabled_domains-other-then-master.patch new file mode 100644 index 0000000..6946373 --- /dev/null +++ b/SOURCES/0106-AD_PROVIDER-ad_enabled_domains-other-then-master.patch @@ -0,0 +1,112 @@ +From 9438cd7b8c8cca1e919afec6c5aa3a3233a31f8c Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Mon, 27 Jun 2016 11:51:30 +0200 +Subject: [PATCH 106/108] AD_PROVIDER: ad_enabled_domains - other then master +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We can skip looking up other domains if +option ad_enabled_domains doesn't contain them. + +Resolves: +https://fedorahosted.org/sssd/ticket/2828 + +Reviewed-by: Jakub Hrozek +Reviewed-by: Lukáš Slebodník +--- + src/providers/ad/ad_subdomains.c | 40 +++++++++++++++++++++++++++++++++++++--- + 1 file changed, 37 insertions(+), 3 deletions(-) + +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index 5fdfc63886457db02ea4edc430341b31c3e545ce..52bf5361fa8de02c7165cbc3513a923ec018fc15 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -130,6 +130,16 @@ done: + return ret; + } + ++static bool is_domain_enabled(const char *domain, ++ const char **enabled_doms) ++{ ++ if (enabled_doms == NULL) { ++ return true; ++ } ++ ++ return string_in_list(domain, discard_const_p(char *, enabled_doms), false); ++} ++ + static errno_t + ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, + struct ad_id_ctx *id_ctx, +@@ -492,6 +502,7 @@ done: + + static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, ++ const char **enabled_domains_list, + size_t nsd, struct sysdb_attrs **sd, + struct sysdb_attrs *root, + size_t *_nsd_out, +@@ -500,9 +511,10 @@ static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx, + size_t i, sdi; + struct sysdb_attrs **sd_out; + const char *sd_name; ++ const char *root_name; + errno_t ret; + +- if (root == NULL) { ++ if (root == NULL && enabled_domains_list == NULL) { + /* We are connected directly to the root domain. The 'sd' + * list is complete and we can just use it + */ +@@ -529,6 +541,13 @@ static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx, + goto fail; + } + ++ if (is_domain_enabled(sd_name, enabled_domains_list) == false) { ++ DEBUG(SSSDBG_TRACE_FUNC, "Disabling subdomain %s\n", sd_name); ++ continue; ++ } else { ++ DEBUG(SSSDBG_TRACE_FUNC, "Enabling subdomain %s\n", sd_name); ++ } ++ + if (strcasecmp(sd_name, domain->name) == 0) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Not including primary domain %s in the subdomain list\n", +@@ -541,9 +560,23 @@ static errno_t ad_subdomains_process(TALLOC_CTX *mem_ctx, + } + + /* Now include the root */ +- sd_out[sdi] = talloc_steal(sd_out, root); ++ if (root != NULL) { ++ ret = sysdb_attrs_get_string(root, AD_AT_TRUST_PARTNER, &root_name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); ++ goto fail; ++ } + +- *_nsd_out = sdi+1; ++ if (is_domain_enabled(root_name, enabled_domains_list) == true) { ++ sd_out[sdi] = talloc_steal(sd_out, root); ++ sdi++; ++ } else { ++ DEBUG(SSSDBG_TRACE_FUNC, "Disabling forest root domain %s\n", ++ root_name); ++ } ++ } ++ ++ *_nsd_out = sdi; + *_sd_out = sd_out; + return EOK; + +@@ -789,6 +822,7 @@ static void ad_get_slave_domain_done(struct tevent_req *subreq) + * subdomains. + */ + ret = ad_subdomains_process(state, state->be_ctx->domain, ++ state->sd_ctx->ad_enabled_domains, + reply_count, reply, state->root_attrs, + &nsubdoms, &subdoms); + if (ret != EOK) { +-- +2.4.11 + diff --git a/SOURCES/0106-Add-a-new-option-ldap_group_external_member.patch b/SOURCES/0106-Add-a-new-option-ldap_group_external_member.patch deleted file mode 100644 index a17aa8a..0000000 --- a/SOURCES/0106-Add-a-new-option-ldap_group_external_member.patch +++ /dev/null @@ -1,178 +0,0 @@ -From b842e04a1e73dd9af3096b065fcf5b2a7fe55b51 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 25 Jan 2016 16:03:23 +0100 -Subject: [PATCH 106/108] Add a new option ldap_group_external_member - -Required for: - https://fedorahosted.org/sssd/ticket/2522 - -Reviewed-by: Sumit Bose -(cherry picked from commit 3cf7fdfcaedb986f42a6640e26aa057007b64045) -(cherry picked from commit 7db3bdfd6b1b845866c1ff062d25de5804141e89) ---- - 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 | 16 ++++++++++++++++ - 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, 27 insertions(+) - -diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in -index a7cd1dd243a53e7038dc69628475c76ccdd93260..7ec28d1d4a121cef0f7a8f3122c95bd396f773a7 100644 ---- a/src/config/SSSDConfig/__init__.py.in -+++ b/src/config/SSSDConfig/__init__.py.in -@@ -328,6 +328,7 @@ option_strings = { - 'ldap_group_objectsid' : _("objectSID attribute"), - 'ldap_group_modify_timestamp' : _('Modification time attribute for groups'), - 'ldap_group_type' : _('Type of the group and other flags'), -+ 'ldap_group_external_member' : _('The LDAP group external member attribute'), - #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 b636d93108ef0a3831970d7827895c14b0f3571c..e1083aa2a6d9a0ebf61a6029af05aea62ec7b217 100644 ---- a/src/config/etc/sssd.api.d/sssd-ad.conf -+++ b/src/config/etc/sssd.api.d/sssd-ad.conf -@@ -108,6 +108,7 @@ 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_external_member = str, 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 ab712fe55cdac6d247a085aeca5cc82d65966623..3cbfb2ee5e06f2ef731e8f9eb79be374351d7281 100644 ---- a/src/config/etc/sssd.api.d/sssd-ipa.conf -+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf -@@ -104,6 +104,7 @@ 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_external_member = str, 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 8fd45fd4093714f458161eb352157c845d926f06..21a38b9581ea35f78618a272bc3a943f6968d37e 100644 ---- a/src/config/etc/sssd.api.d/sssd-ldap.conf -+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf -@@ -98,6 +98,7 @@ 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_external_member = str, 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 3fa3f040708a4984158206d66a1d28a079091cf7..817ecd2764c3fac3ca3e38ba78f9e8ef2afab51b 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -81,6 +81,7 @@ - #define SYSDB_USER_CATEGORY "userCategory" - #define SYSDB_HOST_CATEGORY "hostCategory" - #define SYSDB_GROUP_TYPE "groupType" -+#define SYSDB_EXTERNAL_MEMBER "externalMember" - - #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 49e84560f825b1bff255c1ad131487ba3243300d..cc1b17108500c5d241008f683d14ab32cefab396 100644 ---- a/src/man/sssd-ldap.5.xml -+++ b/src/man/sssd-ldap.5.xml -@@ -942,6 +942,22 @@ - - - -+ ldap_group_external_member (string) -+ -+ -+ The LDAP attribute that references group -+ members that are defined in an external -+ domain. At the moment, only IPA's external -+ members are supported. -+ -+ -+ Default: ipaExternalMember in the IPA provider, -+ otherwise unset. -+ -+ -+ -+ -+ - ldap_group_nesting_level (integer) - - -diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h -index 00586a7ada63ad4c89630e9589d3ff75d1726703..b2133db1859914d54d2db2a871d7fbae7aeff268 100644 ---- a/src/providers/ad/ad_opts.h -+++ b/src/providers/ad/ad_opts.h -@@ -233,6 +233,7 @@ struct sdap_attr_map ad_2008r2_group_map[] = { - { "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 }, -+ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h -index 78949e3ddec95f7f4303eab905bbbf6ec14ed6ae..81ccc42fc0c9f21c8ef16e2d1735bc06199ba747 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -221,6 +221,7 @@ struct sdap_attr_map ipa_group_map[] = { - { "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 }, -+ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h -index 9f58db5bd9eef1391e97c1890cbff94c2a5406d6..bda2e79e849ab9e4e3e91407faafc0d8b06df899 100644 ---- a/src/providers/ldap/ldap_opts.h -+++ b/src/providers/ldap/ldap_opts.h -@@ -197,6 +197,7 @@ struct sdap_attr_map rfc2307_group_map[] = { - { "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 }, -+ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -@@ -253,6 +254,7 @@ struct sdap_attr_map rfc2307bis_group_map[] = { - { "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 }, -+ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -@@ -309,6 +311,7 @@ struct sdap_attr_map gen_ad2008r2_group_map[] = { - { "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 }, -+ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index 444502bf7159edcf4cebe530cce8b216c737ec30..d7053949f5804b637c27bb2d8e34991653770639 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -303,6 +303,7 @@ enum sdap_group_attrs { - SDAP_AT_GROUP_MODSTAMP, - SDAP_AT_GROUP_USN, - SDAP_AT_GROUP_TYPE, -+ SDAP_AT_GROUP_EXT_MEMBER, - - SDAP_OPTS_GROUP /* attrs counter */ - }; --- -2.4.3 - diff --git a/SOURCES/0107-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch b/SOURCES/0107-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch deleted file mode 100644 index 9c83b71..0000000 --- a/SOURCES/0107-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch +++ /dev/null @@ -1,446 +0,0 @@ -From 2515f7d9a19c2634baf1cd2f008a2148b5300db0 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 25 Jan 2016 16:11:59 +0100 -Subject: [PATCH 107/108] IPA: Add interface to call into IPA provider from - LDAP provider - -https://fedorahosted.org/sssd/ticket/2522 - -Adds a pluggable interface that is able to resolve the IPA group's -external members. At the moment, the request calls the full be_ -interface to make sure all corner cases like id-views are handled -internally. - -Reviewed-by: Sumit Bose -(cherry picked from commit e2d96566aeb881bd89e5c9236d663f6a9a88019a) -(cherry picked from commit 00ee45423f0712b83926c6f8b354a1a18ff741c8) ---- - src/providers/ipa/ipa_id.c | 5 +- - src/providers/ipa/ipa_init.c | 28 +++ - src/providers/ipa/ipa_subdomains.h | 11 ++ - src/providers/ipa/ipa_subdomains_ext_groups.c | 275 ++++++++++++++++++++++++++ - src/providers/ipa/ipa_subdomains_id.c | 1 + - src/providers/ldap/sdap.h | 23 +++ - 6 files changed, 342 insertions(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c -index e81ccb34dd6eb44618538593f5473fbe5e89d896..8782a81247f7ca7ba6d2aa55f8d01897a0b38523 100644 ---- a/src/providers/ipa/ipa_id.c -+++ b/src/providers/ipa/ipa_id.c -@@ -384,7 +384,10 @@ static int ipa_initgr_get_overrides_step(struct tevent_req *req) - /* 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"); -+ DEBUG(SSSDBG_OP_FAILURE, -+ "The group %s has no UUID attribute %s, error!\n", -+ ldb_dn_get_linearized(state->groups[state->group_idx]->dn), -+ state->groups_id_attr); - return EINVAL; - } - -diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c -index 0e16dd97c78a087256fb77be500c9741484867c5..453e2b25673ac709c9fa3809d35b7885630c8b24 100644 ---- a/src/providers/ipa/ipa_init.c -+++ b/src/providers/ipa/ipa_init.c -@@ -139,6 +139,24 @@ int common_ipa_init(struct be_ctx *bectx) - return EOK; - } - -+static struct sdap_ext_member_ctx * -+ipa_create_ext_members_ctx(TALLOC_CTX *mem_ctx, -+ struct ipa_id_ctx *id_ctx) -+{ -+ struct sdap_ext_member_ctx *ext_ctx = NULL; -+ -+ ext_ctx = talloc_zero(mem_ctx, struct sdap_ext_member_ctx); -+ if (ext_ctx == NULL) { -+ return NULL; -+ } -+ -+ ext_ctx->pvt = id_ctx; -+ ext_ctx->ext_member_resolve_send = ipa_ext_group_member_send; -+ ext_ctx->ext_member_resolve_recv = ipa_ext_group_member_recv; -+ -+ return ext_ctx; -+} -+ - int sssm_ipa_id_init(struct be_ctx *bectx, - struct bet_ops **ops, - void **pvt_data) -@@ -360,6 +378,16 @@ int sssm_ipa_id_init(struct be_ctx *bectx, - "will not work [%d]: %s\n", ret, strerror(ret)); - } - -+ ipa_ctx->sdap_id_ctx->opts->ext_ctx = ipa_create_ext_members_ctx( -+ ipa_ctx->sdap_id_ctx->opts, -+ ipa_ctx); -+ if (ipa_ctx->sdap_id_ctx->opts->ext_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Unable to set SRV the extrernal group ctx\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ - *ops = &ipa_id_ops; - *pvt_data = ipa_ctx; - ret = EOK; -diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h -index 0c13f8ed2eeda87237dfb097f532c7137095ddf1..23c3b7e3cd3ee1e0ac1dbcf98dc71a6c2337b835 100644 ---- a/src/providers/ipa/ipa_subdomains.h -+++ b/src/providers/ipa/ipa_subdomains.h -@@ -137,4 +137,15 @@ struct tevent_req *ipa_get_ad_memberships_send(TALLOC_CTX *mem_ctx, - const char *domain); - - errno_t ipa_get_ad_memberships_recv(struct tevent_req *req, int *dp_error_out); -+ -+struct tevent_req *ipa_ext_group_member_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ const char *ext_member, -+ void *pvt); -+errno_t ipa_ext_group_member_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ enum sysdb_member_type *_member_type, -+ struct sss_domain_info **_dom, -+ struct sysdb_attrs **_member); -+ - #endif /* _IPA_SUBDOMAINS_H_ */ -diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c -index d487a58b8adffabe09ff50e31cb750b800b1d252..5dc6d0d6417ec3fb5e7865e4cbaf3c07f4afbd07 100644 ---- a/src/providers/ipa/ipa_subdomains_ext_groups.c -+++ b/src/providers/ipa/ipa_subdomains_ext_groups.c -@@ -923,3 +923,278 @@ static errno_t ipa_add_ad_memberships_recv(struct tevent_req *req, - - return EOK; - } -+ -+static errno_t -+search_user_or_group_by_sid_str(TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *domain, -+ const char *sid_str, -+ enum sysdb_member_type *_member_type, -+ struct ldb_message **_msg) -+{ -+ errno_t ret; -+ struct ldb_message *msg = NULL; -+ const char *attrs[] = { SYSDB_NAME, -+ SYSDB_SID_STR, -+ SYSDB_ORIG_DN, -+ SYSDB_OBJECTCLASS, -+ SYSDB_CACHE_EXPIRE, -+ NULL }; -+ TALLOC_CTX *tmp_ctx = NULL; -+ char *sanitized_sid = NULL; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); -+ return ENOMEM; -+ } -+ -+ /* In theory SID shouldn't contain any special LDAP characters, but let's -+ * be paranoid -+ */ -+ ret = sss_filter_sanitize(tmp_ctx, sid_str, &sanitized_sid); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ ret = sysdb_search_user_by_sid_str(tmp_ctx, domain, -+ sid_str, attrs, &msg); -+ if (ret == EOK) { -+ *_member_type = SYSDB_MEMBER_USER; -+ } else if (ret == ENOENT) { -+ ret = sysdb_search_group_by_sid_str(tmp_ctx, domain, -+ sid_str, attrs, &msg); -+ if (ret == EOK) { -+ *_member_type = SYSDB_MEMBER_GROUP; -+ } -+ } -+ -+ switch (ret) { -+ case EOK: -+ DEBUG(SSSDBG_TRACE_FUNC, "Found %s in sysdb\n", sid_str); -+ *_msg = talloc_steal(mem_ctx, msg); -+ break; -+ case ENOENT: -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "Could not find %s in sysdb", sid_str); -+ break; -+ default: -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Error looking for %s in sysdb [%d]: %s\n", -+ sid_str, ret, sss_strerror(ret)); -+ break; -+ } -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t -+ipa_ext_group_member_check(TALLOC_CTX *mem_ctx, -+ struct ipa_id_ctx *ipa_ctx, -+ struct sss_domain_info *member_dom, -+ const char *ext_member, -+ enum sysdb_member_type *_member_type, -+ struct sysdb_attrs **_member) -+{ -+ TALLOC_CTX *tmp_ctx = NULL; -+ errno_t ret; -+ uint64_t expire; -+ time_t now = time(NULL); -+ struct ldb_message *msg; -+ struct sysdb_attrs **members; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); -+ return ENOMEM; -+ } -+ -+ ret = search_user_or_group_by_sid_str(tmp_ctx, member_dom, ext_member, -+ _member_type, &msg); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Error looking up sid %s: [%d]: %s\n", -+ ext_member, ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ ret = sysdb_msg2attrs(tmp_ctx, 1, &msg, &members); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not convert result to sysdb_attrs [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ goto done; -+ } -+ -+ /* Return the member both expired and valid */ -+ *_member = talloc_steal(mem_ctx, members[0]); -+ -+ expire = ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0); -+ if (expire != 0 && expire <= now) { -+ DEBUG(SSSDBG_TRACE_FUNC, "%s is expired", ext_member); -+ ret = EAGAIN; -+ goto done; -+ } -+ -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+/* For the IPA external member resolution, we expect a SID as the input. -+ * The _recv() function output is the member and a type (user/group) -+ * since nothing else can be a group member. -+ */ -+struct ipa_ext_member_state { -+ const char *ext_member; -+ struct sss_domain_info *dom; -+ -+ enum sysdb_member_type member_type; -+ struct sysdb_attrs *member; -+}; -+ -+static void ipa_ext_group_member_done(struct tevent_req *subreq); -+ -+struct tevent_req *ipa_ext_group_member_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ const char *ext_member, -+ void *pvt) -+{ -+ struct ipa_id_ctx *ipa_ctx; -+ struct ipa_ext_member_state *state; -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct be_acct_req *ar; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, struct ipa_ext_member_state); -+ if (req == NULL) { -+ return NULL; -+ } -+ state->ext_member = ext_member; -+ -+ ipa_ctx = talloc_get_type(pvt, struct ipa_id_ctx); -+ if (ipa_ctx == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong private context!\n"); -+ ret = EINVAL; -+ goto immediate; -+ } -+ -+ state->dom = find_domain_by_sid(ipa_ctx->sdap_id_ctx->be->domain, -+ ext_member); -+ if (state->dom == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot find domain of SID [%s]\n", ext_member); -+ ret = ENOENT; -+ goto immediate; -+ } -+ -+ ret = ipa_ext_group_member_check(state, ipa_ctx, state->dom, ext_member, -+ &state->member_type, &state->member); -+ if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "external member %s already cached\n", ext_member); -+ goto immediate; -+ } -+ -+ ret = get_be_acct_req_for_sid(state, ext_member, state->dom->name, &ar); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot create the account request for [%s]\n", ext_member); -+ goto immediate; -+ } -+ -+ subreq = be_get_account_info_send(state, ev, NULL, -+ ipa_ctx->sdap_id_ctx->be, ar); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, ipa_ext_group_member_done, req); -+ -+ return req; -+ -+immediate: -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ } else { -+ tevent_req_done(req); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void ipa_ext_group_member_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct ipa_ext_member_state *state = tevent_req_data(req, -+ struct ipa_ext_member_state); -+ errno_t ret; -+ int err_maj; -+ int err_min; -+ const char *err_msg; -+ struct ldb_message *msg; -+ struct sysdb_attrs **members; -+ -+ ret = be_get_account_info_recv(subreq, state, -+ &err_maj, &err_min, &err_msg); -+ talloc_free(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "be request failed %d:%d: %s\n", err_maj, err_min, err_msg); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = search_user_or_group_by_sid_str(state, -+ state->dom, -+ state->ext_member, -+ &state->member_type, -+ &msg); -+ if (ret != EOK) { -+ DEBUG(ret == ENOENT ? SSSDBG_TRACE_FUNC : SSSDBG_OP_FAILURE, -+ "Could not find %s in sysdb [%d]: %s\n", -+ state->ext_member, ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = sysdb_msg2attrs(state, 1, &msg, &members); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Could not convert result to sysdb_attrs [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->member = members[0]; -+ tevent_req_done(req); -+} -+ -+errno_t ipa_ext_group_member_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ enum sysdb_member_type *_member_type, -+ struct sss_domain_info **_dom, -+ struct sysdb_attrs **_member) -+{ -+ struct ipa_ext_member_state *state = tevent_req_data(req, -+ struct ipa_ext_member_state); -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ if (_member_type != NULL) { -+ *_member_type = state->member_type; -+ } -+ -+ if (_dom) { -+ *_dom = state->dom; -+ } -+ -+ if (_member != NULL) { -+ *_member = talloc_steal(mem_ctx, state->member); -+ } -+ -+ return EOK; -+} -diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c -index 7acbb38e66c2c36ff230ae35b236544195a8104b..ebbf3be71d7488c0e5138183925668fc6187df97 100644 ---- a/src/providers/ipa/ipa_subdomains_id.c -+++ b/src/providers/ipa/ipa_subdomains_id.c -@@ -1229,6 +1229,7 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req) - * attributes set, i.e. where overrides might not have been applied. */ - ret = sysdb_asq_search(state, state->obj_dom, state->obj_msg->dn, - "(&("SYSDB_GC")("SYSDB_GIDNUM"=*)" \ -+ "("SYSDB_POSIX"=TRUE)" \ - "(!("ORIGINALAD_PREFIX SYSDB_GIDNUM"=*))" \ - "(!("ORIGINALAD_PREFIX SYSDB_NAME"=*)))", - SYSDB_INITGR_ATTR, -diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h -index d7053949f5804b637c27bb2d8e34991653770639..312789411fa273dd263bd6319f7a5ff45437d8d0 100644 ---- a/src/providers/ldap/sdap.h -+++ b/src/providers/ldap/sdap.h -@@ -415,6 +415,26 @@ struct sdap_domain { - void *pvt; - }; - -+typedef struct tevent_req * -+(*ext_member_send_fn_t)(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ const char *ext_member, -+ void *pvt); -+typedef errno_t -+(*ext_member_recv_fn_t)(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req, -+ enum sysdb_member_type *member_type, -+ struct sss_domain_info **_dom, -+ struct sysdb_attrs **_member); -+ -+struct sdap_ext_member_ctx { -+ /* Typically ID context of the external ID provider */ -+ void *pvt; -+ -+ ext_member_send_fn_t ext_member_resolve_send; -+ ext_member_recv_fn_t ext_member_resolve_recv; -+}; -+ - struct sdap_options { - struct dp_option *basic; - struct sdap_attr_map *gen_map; -@@ -427,6 +447,9 @@ struct sdap_options { - /* ID-mapping support */ - struct sdap_idmap_ctx *idmap_ctx; - -+ /* Resolving external members */ -+ struct sdap_ext_member_ctx *ext_ctx; -+ - /* FIXME - should this go to a special struct to avoid mixing with name-service-switch maps? */ - struct sdap_attr_map *sudorule_map; - struct sdap_attr_map *autofs_mobject_map; --- -2.4.3 - diff --git a/SOURCES/0107-TESTS-Adding-tests-for-ad_enabled_domains-option.patch b/SOURCES/0107-TESTS-Adding-tests-for-ad_enabled_domains-option.patch new file mode 100644 index 0000000..96cddc6 --- /dev/null +++ b/SOURCES/0107-TESTS-Adding-tests-for-ad_enabled_domains-option.patch @@ -0,0 +1,398 @@ +From 70c1809c7ad309d87fba7570cff5c5e9f10d17f1 Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Mon, 27 Jun 2016 11:53:19 +0200 +Subject: [PATCH 107/108] TESTS: Adding tests for ad_enabled_domains option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There is special logic around ad_enabled_domains option: + * option is disabled by default + * master domain is always added to enabled domains + +Resolves: +https://fedorahosted.org/sssd/ticket/2828 + +Reviewed-by: Jakub Hrozek +Reviewed-by: Lukáš Slebodník +--- + Makefile.am | 20 +++ + src/tests/cmocka/test_ad_subdomains.c | 328 ++++++++++++++++++++++++++++++++++ + 2 files changed, 348 insertions(+) + create mode 100644 src/tests/cmocka/test_ad_subdomains.c + +diff --git a/Makefile.am b/Makefile.am +index e2e4c4c08f66ef15684e1b3b1fe17bfae4e4131b..4d90c7a46e2ee0fe652aa392cf647d056e06c7fc 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -257,6 +257,7 @@ if HAVE_CMOCKA + test_sbus_opath \ + test_fo_srv \ + pam-srv-tests \ ++ test_ad_subdom \ + test_ipa_subdom_util \ + test_tools_colondb \ + test_krb5_wait_queue \ +@@ -2817,6 +2818,25 @@ test_fo_srv_LDADD = \ + libsss_test_common.la \ + $(NULL) + ++test_ad_subdom_SOURCES = \ ++ src/tests/cmocka/test_ad_subdomains.c \ ++ $(NULL) ++test_ad_subdom_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ $(NDR_NBT_CFLAGS) \ ++ $(NULL) ++test_ad_subdom_LDADD = \ ++ $(CMOCKA_LIBS) \ ++ $(POPT_LIBS) \ ++ $(TALLOC_LIBS) \ ++ $(SSSD_INTERNAL_LTLIBS) \ ++ libsss_ldap_common.la \ ++ libsss_ad_tests.la \ ++ libsss_idmap.la \ ++ libsss_test_common.la \ ++ libdlopen_test_providers.la \ ++ $(NULL) ++ + test_ipa_subdom_util_SOURCES = \ + src/tests/cmocka/test_ipa_subdomains_utils.c \ + src/providers/ipa/ipa_subdomains_utils.c \ +diff --git a/src/tests/cmocka/test_ad_subdomains.c b/src/tests/cmocka/test_ad_subdomains.c +new file mode 100644 +index 0000000000000000000000000000000000000000..99908b5f8f0b89c2cc391b5496e24a247bfd7448 +--- /dev/null ++++ b/src/tests/cmocka/test_ad_subdomains.c +@@ -0,0 +1,328 @@ ++/* ++ Authors: ++ Petr Čech ++ ++ Copyright (C) 2016 Red Hat ++ ++ SSSD tests: AD subdomain 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 ++#include ++ ++#include "tests/cmocka/common_mock.h" ++#include "tests/cmocka/common_mock_resp.h" ++#include "providers/ad/ad_common.h" ++ ++#include "providers/ad/ad_subdomains.c" ++#include "providers/ad/ad_opts.c" ++ ++#define AD_DOMAIN "ad_domain.domain.test" ++#define DOMAIN_1 "one.domain.test" ++#define DOMAIN_2 "two.domain.test" ++ ++struct test_ad_subdom_ctx { ++ struct ad_id_ctx *ad_id_ctx; ++}; ++ ++static struct ad_id_ctx * ++test_ad_subdom_init_ad_id_ctx(TALLOC_CTX *mem_ctx) ++{ ++ struct ad_id_ctx *ad_id_ctx; ++ struct ad_options *ad_options; ++ errno_t ret; ++ ++ ad_id_ctx = talloc_zero(mem_ctx, struct ad_id_ctx); ++ assert_non_null(ad_id_ctx); ++ ++ ad_options = talloc_zero(ad_id_ctx, struct ad_options); ++ assert_non_null(ad_options); ++ ++ ret = dp_copy_defaults(ad_options, ++ ad_basic_opts, ++ AD_OPTS_BASIC, ++ &ad_options->basic); ++ assert_int_equal(ret, EOK); ++ ++ ad_id_ctx->ad_options = ad_options; ++ ++ return ad_id_ctx; ++} ++ ++static int test_ad_subdom_setup(void **state) ++{ ++ struct test_ad_subdom_ctx *test_ctx; ++ ++ assert_true(leak_check_setup()); ++ ++ test_ctx = talloc_zero(global_talloc_context, struct test_ad_subdom_ctx); ++ assert_non_null(test_ctx); ++ ++ test_ctx->ad_id_ctx = NULL; ++ ++ check_leaks_push(test_ctx); ++ *state = test_ctx; ++ return 0; ++} ++ ++static int test_ad_subdom_teardown(void **state) ++{ ++ struct test_ad_subdom_ctx *test_ctx; ++ ++ test_ctx = talloc_get_type(*state, struct test_ad_subdom_ctx); ++ assert_non_null(test_ctx); ++ ++ assert_true(check_leaks_pop(test_ctx) == true); ++ talloc_free(test_ctx); ++ assert_true(leak_check_teardown()); ++ return 0; ++} ++ ++static void test_ad_subdom_default(void **state) ++{ ++ struct test_ad_subdom_ctx *test_ctx; ++ const char **ad_enabled_domains = NULL; ++ errno_t ret; ++ ++ test_ctx = talloc_get_type(*state, struct test_ad_subdom_ctx); ++ test_ctx->ad_id_ctx = test_ad_subdom_init_ad_id_ctx(test_ctx); ++ assert_non_null(test_ctx->ad_id_ctx); ++ ++ ret = ad_get_enabled_domains(test_ctx, test_ctx->ad_id_ctx, ++ AD_DOMAIN, ++ &ad_enabled_domains); ++ assert_int_equal(ret, EOK); ++ assert_null(ad_enabled_domains); ++ ++ talloc_zfree(test_ctx->ad_id_ctx); ++} ++ ++static void test_ad_subdom_add_one(void **state) ++{ ++ struct test_ad_subdom_ctx *test_ctx; ++ const char **ad_enabled_domains = NULL; ++ int enabled_domains_count; ++ int domain_count = 2; ++ const char *domains[domain_count]; ++ errno_t ret; ++ ++ test_ctx = talloc_get_type(*state, struct test_ad_subdom_ctx); ++ test_ctx->ad_id_ctx = test_ad_subdom_init_ad_id_ctx(test_ctx); ++ assert_non_null(test_ctx->ad_id_ctx); ++ ++ ret = dp_opt_set_string(test_ctx->ad_id_ctx->ad_options->basic, ++ AD_ENABLED_DOMAINS, DOMAIN_1); ++ assert_int_equal(ret, EOK); ++ ++ ret = ad_get_enabled_domains(test_ctx, test_ctx->ad_id_ctx, ++ AD_DOMAIN, ++ &ad_enabled_domains); ++ assert_int_equal(ret, EOK); ++ assert_non_null(ad_enabled_domains); ++ ++ for (enabled_domains_count = 0; ++ ad_enabled_domains[enabled_domains_count] != NULL; ++ enabled_domains_count++) { ++ } ++ assert_int_equal(domain_count, enabled_domains_count); ++ ++ domains[0] = AD_DOMAIN; ++ domains[1] = DOMAIN_1; ++ assert_true(are_values_in_array(domains, domain_count, ++ ad_enabled_domains, enabled_domains_count)); ++ ++ talloc_zfree(test_ctx->ad_id_ctx); ++ talloc_zfree(ad_enabled_domains); ++} ++ ++static void test_ad_subdom_add_two(void **state) ++{ ++ struct test_ad_subdom_ctx *test_ctx; ++ const char **ad_enabled_domains = NULL; ++ int enabled_domains_count; ++ int domain_count = 3; ++ const char *domains[domain_count]; ++ errno_t ret; ++ ++ test_ctx = talloc_get_type(*state, struct test_ad_subdom_ctx); ++ test_ctx->ad_id_ctx = test_ad_subdom_init_ad_id_ctx(test_ctx); ++ assert_non_null(test_ctx->ad_id_ctx); ++ ++ ret = dp_opt_set_string(test_ctx->ad_id_ctx->ad_options->basic, ++ AD_ENABLED_DOMAINS, DOMAIN_1","DOMAIN_2); ++ assert_int_equal(ret, EOK); ++ ++ ret = ad_get_enabled_domains(test_ctx, test_ctx->ad_id_ctx, ++ AD_DOMAIN, ++ &ad_enabled_domains); ++ assert_int_equal(ret, EOK); ++ assert_non_null(ad_enabled_domains); ++ ++ for (enabled_domains_count = 0; ++ ad_enabled_domains[enabled_domains_count] != NULL; ++ enabled_domains_count++) { ++ } ++ assert_int_equal(domain_count, enabled_domains_count); ++ ++ domains[0] = AD_DOMAIN; ++ domains[1] = DOMAIN_1; ++ domains[2] = DOMAIN_2; ++ assert_true(are_values_in_array(domains, domain_count, ++ ad_enabled_domains, enabled_domains_count)); ++ ++ talloc_zfree(test_ctx->ad_id_ctx); ++ talloc_zfree(ad_enabled_domains); ++} ++ ++static void test_ad_subdom_add_master(void **state) ++{ ++ struct test_ad_subdom_ctx *test_ctx; ++ const char **ad_enabled_domains = NULL; ++ int enabled_domains_count; ++ int domain_count = 1; ++ const char *domains[domain_count]; ++ errno_t ret; ++ ++ test_ctx = talloc_get_type(*state, struct test_ad_subdom_ctx); ++ test_ctx->ad_id_ctx = test_ad_subdom_init_ad_id_ctx(test_ctx); ++ assert_non_null(test_ctx->ad_id_ctx); ++ ++ ret = dp_opt_set_string(test_ctx->ad_id_ctx->ad_options->basic, ++ AD_ENABLED_DOMAINS, AD_DOMAIN); ++ assert_int_equal(ret, EOK); ++ ++ ret = ad_get_enabled_domains(test_ctx, test_ctx->ad_id_ctx, ++ AD_DOMAIN, ++ &ad_enabled_domains); ++ assert_int_equal(ret, EOK); ++ assert_non_null(ad_enabled_domains); ++ ++ for (enabled_domains_count = 0; ++ ad_enabled_domains[enabled_domains_count] != NULL; ++ enabled_domains_count++) { ++ } ++ assert_int_equal(domain_count, enabled_domains_count); ++ ++ domains[0] = AD_DOMAIN; ++ assert_true(are_values_in_array(domains, domain_count, ++ ad_enabled_domains, enabled_domains_count)); ++ ++ talloc_zfree(test_ctx->ad_id_ctx); ++ talloc_zfree(ad_enabled_domains); ++} ++ ++static void test_ad_subdom_add_two_with_master(void **state) ++{ ++ struct test_ad_subdom_ctx *test_ctx; ++ const char **ad_enabled_domains = NULL; ++ int enabled_domains_count; ++ int domain_count = 3; ++ const char *domains[domain_count]; ++ errno_t ret; ++ ++ test_ctx = talloc_get_type(*state, struct test_ad_subdom_ctx); ++ test_ctx->ad_id_ctx = test_ad_subdom_init_ad_id_ctx(test_ctx); ++ assert_non_null(test_ctx->ad_id_ctx); ++ ++ ret = dp_opt_set_string(test_ctx->ad_id_ctx->ad_options->basic, ++ AD_ENABLED_DOMAINS, ++ DOMAIN_1","AD_DOMAIN","DOMAIN_2); ++ assert_int_equal(ret, EOK); ++ ++ ret = ad_get_enabled_domains(test_ctx, test_ctx->ad_id_ctx, ++ AD_DOMAIN, ++ &ad_enabled_domains); ++ assert_int_equal(ret, EOK); ++ assert_non_null(ad_enabled_domains); ++ ++ for (enabled_domains_count = 0; ++ ad_enabled_domains[enabled_domains_count] != NULL; ++ enabled_domains_count++) { ++ } ++ assert_int_equal(domain_count, enabled_domains_count); ++ ++ domains[0] = AD_DOMAIN; ++ domains[1] = DOMAIN_1; ++ domains[2] = DOMAIN_2; ++ assert_true(are_values_in_array(domains, domain_count, ++ ad_enabled_domains, enabled_domains_count)); ++ ++ talloc_zfree(test_ctx->ad_id_ctx); ++ talloc_zfree(ad_enabled_domains); ++} ++ ++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 struct CMUnitTest tests[] = { ++ cmocka_unit_test_setup_teardown(test_ad_subdom_default, ++ test_ad_subdom_setup, ++ test_ad_subdom_teardown), ++ cmocka_unit_test_setup_teardown(test_ad_subdom_add_one, ++ test_ad_subdom_setup, ++ test_ad_subdom_teardown), ++ cmocka_unit_test_setup_teardown(test_ad_subdom_add_two, ++ test_ad_subdom_setup, ++ test_ad_subdom_teardown), ++ cmocka_unit_test_setup_teardown(test_ad_subdom_add_master, ++ test_ad_subdom_setup, ++ test_ad_subdom_teardown), ++ cmocka_unit_test_setup_teardown(test_ad_subdom_add_two_with_master, ++ test_ad_subdom_setup, ++ test_ad_subdom_teardown), ++ }; ++ ++ /* Set debug level to invalid value so we can deside if -d 0 was used. */ ++ debug_level = SSSDBG_INVALID; ++ ++ pc = poptGetContext(argv[0], argc, argv, long_options, 0); ++ while((opt = poptGetNextOpt(pc)) != -1) { ++ switch(opt) { ++ default: ++ fprintf(stderr, "\nInvalid option %s: %s\n\n", ++ poptBadOption(pc, 0), poptStrerror(opt)); ++ poptPrintUsage(pc, stderr, 0); ++ return 1; ++ } ++ } ++ poptFreeContext(pc); ++ ++ DEBUG_CLI_INIT(debug_level); ++ ++ /* Even though normally the tests should clean up after themselves ++ * they might not after a failed run. Remove the old db to be sure */ ++ tests_set_cwd(); ++ ++ rv = cmocka_run_group_tests(tests, NULL, NULL); ++ return rv; ++} +-- +2.4.11 + diff --git a/SOURCES/0108-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch b/SOURCES/0108-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch deleted file mode 100644 index 845a2c8..0000000 --- a/SOURCES/0108-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch +++ /dev/null @@ -1,916 +0,0 @@ -From 3af57ba315eb5268c56919297e3a688c3f2f5b05 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 25 Jan 2016 16:13:03 +0100 -Subject: [PATCH 108/108] LDAP: Use the IPA provider interface to resolve - external group members - -Resolves: - https://fedorahosted.org/sssd/ticket/2522 - -Currently the approach is not optimized for performance, because each -external member is resolved in a full transaction to make sure even ID -views and similar information is processed. - -In future, we should implement https://fedorahosted.org/sssd/ticket/2943 -we will again be able to process all the data in a single transaction. - -Reviewed-by: Sumit Bose -(cherry picked from commit c32266e79f9d4bebd0c31eaa8d6fa26050e7fb3e) -(cherry picked from commit 19194cb18a1cc20f02423861dd831aa5bc3a1003) ---- - src/providers/ldap/sdap_async_groups.c | 49 +- - src/providers/ldap/sdap_async_nested_groups.c | 618 +++++++++++++++++++++++++- - src/providers/ldap/sdap_async_private.h | 16 +- - src/tests/cmocka/test_nested_groups.c | 4 +- - 4 files changed, 659 insertions(+), 28 deletions(-) - -diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c -index 57a53af3f4eb46e6f31af9ee7c4d4625239d2a54..485f79d2fb2e7e34f1420b43baadb40ab3f96d17 100644 ---- a/src/providers/ldap/sdap_async_groups.c -+++ b/src/providers/ldap/sdap_async_groups.c -@@ -1728,6 +1728,7 @@ struct sdap_get_groups_state { - struct sysdb_attrs **groups; - size_t count; - size_t check_count; -+ hash_table_t *missing_external; - - hash_table_t *user_hash; - hash_table_t *group_hash; -@@ -2289,6 +2290,8 @@ int sdap_get_groups_recv(struct tevent_req *req, - return EOK; - } - -+static void sdap_nested_ext_done(struct tevent_req *subreq); -+ - static void sdap_nested_done(struct tevent_req *subreq) - { - errno_t ret, tret; -@@ -2304,7 +2307,8 @@ static void sdap_nested_done(struct tevent_req *subreq) - struct sdap_get_groups_state); - - ret = sdap_nested_group_recv(state, subreq, &user_count, &users, -- &group_count, &groups); -+ &group_count, &groups, -+ &state->missing_external); - talloc_zfree(subreq); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Nested group processing failed: [%d][%s]\n", -@@ -2343,8 +2347,25 @@ static void sdap_nested_done(struct tevent_req *subreq) - } - in_transaction = false; - -- /* Processing complete */ -- tevent_req_done(req); -+ if (hash_count(state->missing_external) == 0) { -+ /* No external members. Processing complete */ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "No external members, done"); -+ tevent_req_done(req); -+ return; -+ } -+ -+ /* At the moment, we need to save the direct groups & members in one -+ * transaction and then query the others in a separate requests -+ */ -+ subreq = sdap_nested_group_lookup_external_send(state, state->ev, -+ state->dom, -+ state->opts->ext_ctx, -+ state->missing_external); -+ if (subreq == NULL) { -+ ret = ENOMEM; -+ goto fail; -+ } -+ tevent_req_set_callback(subreq, sdap_nested_ext_done, req); - return; - - fail: -@@ -2357,6 +2378,28 @@ fail: - tevent_req_error(req, ret); - } - -+static void sdap_nested_ext_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = tevent_req_callback_data(subreq, -+ struct tevent_req); -+ struct sdap_get_groups_state *state = tevent_req_data(req, -+ struct sdap_get_groups_state); -+ -+ ret = sdap_nested_group_lookup_external_recv(state, subreq); -+ talloc_free(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "Cannot resolve external members [%d]: %s\n", -+ ret, sss_strerror(ret)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+ return; -+} -+ - static errno_t sdap_nested_group_populate_users(TALLOC_CTX *mem_ctx, - struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, -diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c -index 08e199869ad16c3b19d998a2a28eae9a0dd0a371..f5be6b5a5946453151918f97aa0632df4b218a29 100644 ---- a/src/providers/ldap/sdap_async_nested_groups.c -+++ b/src/providers/ldap/sdap_async_nested_groups.c -@@ -55,6 +55,13 @@ struct sdap_nested_group_member { - const char *group_filter; - }; - -+const size_t external_members_chunk = 16; -+ -+struct sdap_external_missing_member { -+ const char **parent_group_dns; -+ size_t parent_dn_idx; -+}; -+ - struct sdap_nested_group_ctx { - struct sss_domain_info *domain; - struct sdap_options *opts; -@@ -63,6 +70,7 @@ struct sdap_nested_group_ctx { - struct sdap_handle *sh; - hash_table_t *users; - hash_table_t *groups; -+ hash_table_t *missing_external; - bool try_deref; - int deref_treshold; - int max_nesting_level; -@@ -183,37 +191,32 @@ done: - return ret; - } - --static errno_t sdap_nested_group_hash_entry(hash_table_t *table, -- struct sysdb_attrs *entry, -- const char *table_name) -+static errno_t sdap_nested_group_hash_insert(hash_table_t *table, -+ const char *entry_key, -+ void *entry_value, -+ bool overwrite, -+ const char *table_name) - { - hash_key_t key; - hash_value_t value; -- const char *name = NULL; -- errno_t ret; - int hret; - -- ret = sysdb_attrs_get_string(entry, SYSDB_ORIG_DN, &name); -- if (ret != EOK) { -- return ret; -- } -- - DEBUG(SSSDBG_TRACE_ALL, "Inserting [%s] into hash table [%s]\n", -- name, table_name); -+ entry_key, table_name); - - key.type = HASH_KEY_STRING; -- key.str = talloc_strdup(NULL, name); -+ key.str = talloc_strdup(NULL, entry_key); - if (key.str == NULL) { - return ENOMEM; - } - -- if (hash_has_key(table, &key)) { -+ if (overwrite == false && hash_has_key(table, &key)) { - talloc_free(key.str); - return EEXIST; - } - - value.type = HASH_VALUE_PTR; -- value.ptr = entry; -+ value.ptr = entry_value; - - hret = hash_enter(table, &key, &value); - if (hret != HASH_SUCCESS) { -@@ -227,6 +230,21 @@ static errno_t sdap_nested_group_hash_entry(hash_table_t *table, - return EOK; - } - -+static errno_t sdap_nested_group_hash_entry(hash_table_t *table, -+ struct sysdb_attrs *entry, -+ const char *table_name) -+{ -+ const char *name = NULL; -+ errno_t ret; -+ -+ ret = sysdb_attrs_get_string(entry, SYSDB_ORIG_DN, &name); -+ if (ret != EOK) { -+ return ret; -+ } -+ -+ return sdap_nested_group_hash_insert(table, name, entry, false, table_name); -+} -+ - static errno_t - sdap_nested_group_hash_user(struct sdap_nested_group_ctx *group_ctx, - struct sysdb_attrs *user) -@@ -296,6 +314,76 @@ sdap_nested_group_hash_group(struct sdap_nested_group_ctx *group_ctx, - return sdap_nested_group_hash_entry(group_ctx->groups, group, "groups"); - } - -+static errno_t sdap_nested_group_external_add(hash_table_t *table, -+ const char *ext_member, -+ const char *parent_group_dn) -+{ -+ hash_key_t key; -+ hash_value_t value; -+ int hret; -+ int ret; -+ struct sdap_external_missing_member *ext_mem; -+ -+ key.type = HASH_KEY_STRING; -+ key.str = discard_const(ext_member); -+ -+ DEBUG(SSSDBG_TRACE_ALL, -+ "Inserting external member [%s] into external members hash table\n", -+ ext_member); -+ -+ hret = hash_lookup(table, &key, &value); -+ switch (hret) { -+ case HASH_ERROR_KEY_NOT_FOUND: -+ ext_mem = talloc_zero(table, struct sdap_external_missing_member); -+ if (ext_mem == NULL) { -+ return ENOMEM; -+ } -+ ext_mem->parent_group_dns = talloc_zero_array(ext_mem, -+ const char *, -+ external_members_chunk); -+ if (ext_mem->parent_group_dns == NULL) { -+ talloc_free(ext_mem); -+ return ENOMEM; -+ } -+ -+ ret = sdap_nested_group_hash_insert(table, ext_member, ext_mem, -+ true, "missing external users"); -+ if (ret != EOK) { -+ return ret; -+ } -+ break; -+ -+ case HASH_SUCCESS: -+ ext_mem = talloc_get_type(value.ptr, -+ struct sdap_external_missing_member); -+ if (ext_mem->parent_dn_idx == \ -+ talloc_array_length(ext_mem->parent_group_dns)) { -+ ext_mem->parent_group_dns = talloc_realloc(ext_mem, -+ ext_mem->parent_group_dns, -+ const char *, -+ ext_mem->parent_dn_idx + \ -+ external_members_chunk); -+ if (ext_mem->parent_group_dns == NULL) { -+ talloc_free(ext_mem); -+ return ENOMEM; -+ } -+ } -+ break; -+ default: -+ return EIO; -+ } -+ -+ ext_mem->parent_group_dns[ext_mem->parent_dn_idx] = \ -+ talloc_strdup(ext_mem->parent_group_dns, -+ parent_group_dn); -+ if (ext_mem->parent_group_dns[ext_mem->parent_dn_idx] == NULL) { -+ return ENOMEM; -+ } -+ ext_mem->parent_dn_idx++; -+ -+ return EOK; -+} -+ - static errno_t sdap_nested_group_sysdb_search(struct sss_domain_info *domain, - const char *filter, - bool user) -@@ -477,6 +565,13 @@ sdap_nested_group_split_members(TALLOC_CTX *mem_ctx, - errno_t ret; - int i; - -+ if (members == NULL) { -+ *_missing = NULL; -+ *_num_missing = 0; -+ *_num_groups = 0; -+ return EOK; -+ } -+ - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); -@@ -618,6 +713,66 @@ done: - return ret; - } - -+static errno_t -+sdap_nested_group_add_ext_members(TALLOC_CTX *mem_ctx, -+ struct sdap_nested_group_ctx *group_ctx, -+ struct sysdb_attrs *group, -+ struct ldb_message_element *ext_members) -+{ -+ errno_t ret; -+ const char *ext_member_attr; -+ const char *orig_dn; -+ size_t i; -+ -+ if (ext_members == NULL) { -+ return EOK; -+ } -+ -+ ret = sysdb_attrs_get_string(group, SYSDB_ORIG_DN, &orig_dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "A group with no originalDN!?!\n"); -+ return ret; -+ } -+ -+ for (i = 0; i < ext_members->num_values; i++) { -+ ext_member_attr = (const char *) ext_members->values[i].data; -+ -+ ret = sdap_nested_group_external_add(group_ctx->missing_external, -+ ext_member_attr, -+ orig_dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot add %s into external members [%d]: %s\n", -+ ext_member_attr, ret, sss_strerror(ret)); -+ return ret; -+ } -+ } -+ -+ return EOK; -+} -+ -+static struct ldb_message_element * -+sdap_nested_group_ext_members(struct sdap_options *opts, -+ struct sysdb_attrs *group) -+{ -+ errno_t ret; -+ struct ldb_message_element *ext_members = NULL; -+ -+ if (opts->ext_ctx == NULL) { -+ return NULL; -+ } -+ -+ ret = sysdb_attrs_get_el_ext(group, -+ opts->group_map[SDAP_AT_GROUP_EXT_MEMBER].sys_name, -+ false, &ext_members); -+ if (ret != EOK && ret != ENOENT) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve external member list " -+ "[%d]: %s\n", ret, sss_strerror(ret)); -+ } -+ -+ return ext_members; -+} -+ - - struct sdap_nested_group_state { - struct sdap_nested_group_ctx *group_ctx; -@@ -666,6 +821,14 @@ sdap_nested_group_send(TALLOC_CTX *mem_ctx, - goto immediately; - } - -+ ret = sss_hash_create(state->group_ctx, 32, -+ &state->group_ctx->missing_external); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create hash table [%d]: %s\n", -+ ret, strerror(ret)); -+ goto immediately; -+ } -+ - state->group_ctx->try_deref = true; - state->group_ctx->deref_treshold = dp_opt_get_int(opts->basic, - SDAP_DEREF_THRESHOLD); -@@ -759,7 +922,8 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx, - unsigned long *_num_users, - struct sysdb_attrs ***_users, - unsigned long *_num_groups, -- struct sysdb_attrs ***_groups) -+ struct sysdb_attrs ***_groups, -+ hash_table_t **_missing_external) - { - struct sdap_nested_group_state *state = NULL; - struct sysdb_attrs **users = NULL; -@@ -806,6 +970,11 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx, - *_groups = talloc_steal(mem_ctx, groups); - } - -+ if (_missing_external) { -+ *_missing_external = talloc_steal(mem_ctx, -+ state->group_ctx->missing_external); -+ } -+ - return EOK; - } - -@@ -815,6 +984,7 @@ struct sdap_nested_group_process_state { - struct sdap_nested_group_member *missing; - int num_missing_total; - int num_missing_groups; -+ struct ldb_message_element *ext_members; - int nesting_level; - char *group_dn; - bool deref; -@@ -865,13 +1035,16 @@ sdap_nested_group_process_send(TALLOC_CTX *mem_ctx, - - DEBUG(SSSDBG_TRACE_INTERNAL, "About to process group [%s]\n", orig_dn); - -- /* get member list */ -+ /* get member list, both direct and external */ -+ state->ext_members = sdap_nested_group_ext_members(state->group_ctx->opts, -+ group); -+ - ret = sysdb_attrs_get_el_ext(group, group_map[SDAP_AT_GROUP_MEMBER].sys_name, - false, &members); -- if (ret == ENOENT) { -- ret = EOK; /* no members */ -+ if (ret == ENOENT && state->ext_members == NULL) { -+ ret = EOK; /* no members, direct or external */ - goto immediately; -- } else if (ret != EOK) { -+ } else if (ret != EOK && ret != ENOENT) { - DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve member list " - "[%d]: %s\n", ret, strerror(ret)); - goto immediately; -@@ -889,14 +1062,31 @@ sdap_nested_group_process_send(TALLOC_CTX *mem_ctx, - goto immediately; - } - -- DEBUG(SSSDBG_TRACE_INTERNAL, "Looking up %d/%d members of group [%s]\n", -- state->num_missing_total, members->num_values, orig_dn); -+ ret = sdap_nested_group_add_ext_members(state, -+ state->group_ctx, -+ group, -+ state->ext_members); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to split external member list " -+ "[%d]: %s\n", ret, sss_strerror(ret)); -+ goto immediately; -+ } - -- if (state->num_missing_total == 0) { -+ if (state->num_missing_total == 0 -+ && hash_count(state->group_ctx->missing_external) == 0) { - ret = EOK; /* we're done */ - goto immediately; - } - -+ /* If there are only indirect members of the group, it's still safe to -+ * proceed and let the direct lookup code just fall through. -+ */ -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, "Looking up %d/%d members of group [%s]\n", -+ state->num_missing_total, -+ members ? members->num_values : 0, -+ orig_dn); -+ - /* process members */ - if (group_ctx->try_deref - && state->num_missing_total > group_ctx->deref_treshold) { -@@ -2332,3 +2522,387 @@ static errno_t sdap_nested_group_deref_recv(struct tevent_req *req) - - return EOK; - } -+ -+struct sdap_ext_member { -+ struct sdap_external_missing_member *missing_mem; -+ const char *ext_member_attr; -+ -+ enum sysdb_member_type member_type; -+ struct sss_domain_info *dom; -+ struct sysdb_attrs *attrs; -+}; -+ -+struct sdap_nested_group_lookup_external_state { -+ struct tevent_context *ev; -+ struct sdap_ext_member_ctx *ext_ctx; -+ struct sss_domain_info *group_dom; -+ hash_table_t *missing_external; -+ -+ hash_entry_t *entries; -+ unsigned long n_entries; -+ unsigned long eniter; -+ -+ struct sdap_ext_member *ext_members; -+ -+ ext_member_send_fn_t ext_member_resolve_send; -+ ext_member_recv_fn_t ext_member_resolve_recv; -+}; -+ -+static errno_t -+sdap_nested_group_lookup_external_step(struct tevent_req *req); -+static void -+sdap_nested_group_lookup_external_done(struct tevent_req *subreq); -+static errno_t -+sdap_nested_group_lookup_external_link(struct tevent_req *req); -+static errno_t -+sdap_nested_group_lookup_external_link_member( -+ struct sdap_nested_group_lookup_external_state *state, -+ struct sdap_ext_member *member); -+static errno_t -+sdap_nested_group_memberof_dn_by_original_dn( -+ TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *group_dom, -+ const char *original_dn, -+ const char ***_parents); -+ -+struct tevent_req * -+sdap_nested_group_lookup_external_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sss_domain_info *group_dom, -+ struct sdap_ext_member_ctx *ext_ctx, -+ hash_table_t *missing_external) -+{ -+ struct sdap_nested_group_lookup_external_state *state = NULL; -+ struct tevent_req *req = NULL; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct sdap_nested_group_lookup_external_state); -+ if (req == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); -+ return NULL; -+ } -+ -+ state->ev = ev; -+ state->group_dom = group_dom; -+ state->ext_ctx = ext_ctx; -+ state->missing_external = missing_external; -+ -+ if (state->ext_ctx->ext_member_resolve_send == NULL -+ || state->ext_ctx->ext_member_resolve_recv == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong private context\n"); -+ ret = EINVAL; -+ goto immediately; -+ } -+ -+ ret = hash_entries(state->missing_external, -+ &state->n_entries, &state->entries); -+ if (ret != HASH_SUCCESS) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "hash_entries returned %d\n", ret); -+ ret = EIO; -+ goto immediately; -+ } -+ state->eniter = 0; -+ -+ state->ext_members = talloc_zero_array(state, -+ struct sdap_ext_member, -+ state->n_entries); -+ if (state->ext_members == NULL) { -+ ret = ENOMEM; -+ goto immediately; -+ } -+ -+ ret = sdap_nested_group_lookup_external_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_nested_group_lookup_external_step(struct tevent_req *req) -+{ -+ struct tevent_req *subreq = NULL; -+ struct sdap_nested_group_lookup_external_state *state = NULL; -+ state = tevent_req_data(req, -+ struct sdap_nested_group_lookup_external_state); -+ -+ subreq = state->ext_ctx->ext_member_resolve_send(state, -+ state->ev, -+ state->entries[state->eniter].key.str, -+ state->ext_ctx->pvt); -+ if (subreq == NULL) { -+ return ENOMEM; -+ } -+ DEBUG(SSSDBG_TRACE_FUNC, "Refreshing member %lu/%lu\n", -+ state->eniter, state->n_entries); -+ tevent_req_set_callback(subreq, -+ sdap_nested_group_lookup_external_done, -+ req); -+ -+ return EAGAIN; -+} -+ -+static void -+sdap_nested_group_lookup_external_done(struct tevent_req *subreq) -+{ -+ errno_t ret; -+ struct tevent_req *req = NULL; -+ struct sdap_nested_group_lookup_external_state *state = NULL; -+ enum sysdb_member_type member_type; -+ struct sysdb_attrs *member; -+ struct sss_domain_info *member_dom; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, -+ struct sdap_nested_group_lookup_external_state); -+ -+ ret = state->ext_ctx->ext_member_resolve_recv(state, subreq, -+ &member_type, -+ &member_dom, -+ &member); -+ talloc_free(subreq); -+ if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_FUNC, "Refreshing member %lu\n", state->eniter); -+ state->ext_members[state->eniter].missing_mem = \ -+ state->entries[state->eniter].value.ptr; -+ state->ext_members[state->eniter].dom = member_dom; -+ -+ state->ext_members[state->eniter].ext_member_attr = \ -+ talloc_steal(state->ext_members, -+ state->entries[state->eniter].key.str); -+ state->ext_members[state->eniter].member_type = member_type; -+ state->ext_members[state->eniter].attrs = \ -+ talloc_steal(state->ext_members, member); -+ } -+ -+ state->eniter++; -+ if (state->eniter >= state->n_entries) { -+ DEBUG(SSSDBG_TRACE_FUNC, "All external members processed\n"); -+ ret = sdap_nested_group_lookup_external_link(req); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ tevent_req_done(req); -+ return; -+ } -+ -+ ret = sdap_nested_group_lookup_external_step(req); -+ if (ret != EOK && ret != EAGAIN) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ return; -+} -+ -+static errno_t -+sdap_nested_group_lookup_external_link(struct tevent_req *req) -+{ -+ errno_t ret, tret; -+ bool in_transaction = false; -+ struct sdap_nested_group_lookup_external_state *state = NULL; -+ state = tevent_req_data(req, -+ struct sdap_nested_group_lookup_external_state); -+ size_t i; -+ -+ ret = sysdb_transaction_start(state->group_dom->sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); -+ goto fail; -+ } -+ in_transaction = true; -+ -+ -+ for (i = 0; i < state->eniter; i++) { -+ if (state->ext_members[i].attrs == NULL) { -+ DEBUG(SSSDBG_MINOR_FAILURE, "The member %s could not be resolved\n", -+ state->ext_members[i].ext_member_attr); -+ continue; -+ } -+ -+ ret = sdap_nested_group_lookup_external_link_member(state, -+ &state->ext_members[i]); -+ if (ret != EOK) { -+ goto fail; -+ } -+ } -+ -+ ret = sysdb_transaction_commit(state->group_dom->sysdb); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); -+ goto fail; -+ } -+ in_transaction = false; -+ -+ return EOK; -+ -+fail: -+ if (in_transaction) { -+ tret = sysdb_transaction_cancel(state->group_dom->sysdb); -+ if (tret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n"); -+ } -+ } -+ return EFAULT; -+} -+ -+static errno_t -+sdap_nested_group_lookup_external_link_member( -+ struct sdap_nested_group_lookup_external_state *state, -+ struct sdap_ext_member *member) -+{ -+ const char *name; -+ int ret; -+ const char **parents = NULL; -+ size_t i; -+ TALLOC_CTX *tmp_ctx; -+ const char *orig_dn; -+ -+ tmp_ctx = talloc_new(state); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = sysdb_attrs_get_string(member->attrs, SYSDB_NAME, &name); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "No name for a user\n"); -+ goto done; -+ } -+ -+ /* This only works because the groups were saved in a previous -+ * transaction */ -+ for (i=0; i < member->missing_mem->parent_dn_idx; i++) { -+ orig_dn = member->missing_mem->parent_group_dns[i]; -+ DEBUG(SSSDBG_TRACE_INTERNAL, -+ "Linking external members %s from domain %s to parents of %s\n", -+ name, member->dom->name, orig_dn); -+ ret = sdap_nested_group_memberof_dn_by_original_dn(tmp_ctx, -+ state->group_dom, -+ orig_dn, -+ &parents); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "Cannot find parents of %s\n", orig_dn); -+ continue; -+ } -+ -+ /* We don't have to remove the members here, since all members attributes -+ * are always written anew -+ */ -+ ret = sysdb_update_members_dn(member->dom, name, member->member_type, -+ parents, NULL); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot link %s@%s to its parents\n", -+ name, member->dom->name); -+ goto done; -+ } -+ -+ } -+ -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+static errno_t -+sdap_nested_group_memberof_dn_by_original_dn( -+ TALLOC_CTX *mem_ctx, -+ struct sss_domain_info *group_dom, -+ const char *original_dn, -+ const char ***_parents) -+{ -+ errno_t ret; -+ char *sanitized_dn; -+ char *filter; -+ const char *attrs[] = { SYSDB_NAME, -+ SYSDB_MEMBEROF, -+ NULL }; -+ struct ldb_message **msgs = NULL; -+ size_t count; -+ TALLOC_CTX *tmp_ctx; -+ struct ldb_message_element *memberof; -+ const char **parents; -+ size_t i; -+ -+ tmp_ctx = talloc_new(mem_ctx); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = sss_filter_sanitize(tmp_ctx, original_dn, &sanitized_dn); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "Cannot sanitize originalDN [%s]\n", original_dn); -+ goto done; -+ } -+ -+ filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_ORIG_DN, sanitized_dn); -+ if (filter == NULL) { -+ goto done; -+ } -+ -+ ret = sysdb_search_groups(tmp_ctx, group_dom, filter, attrs, -+ &count, &msgs); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ if (count != 1) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ "More than one entry found by originalDN?\n"); -+ goto done; -+ } -+ -+ memberof = ldb_msg_find_element(msgs[0], SYSDB_MEMBEROF); -+ if (memberof == NULL || memberof->num_values == 0) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ "The external group is not a member of any groups\n"); -+ ret = ENOENT; -+ goto done; -+ } -+ -+ parents = talloc_zero_array(tmp_ctx, -+ const char *, -+ memberof->num_values + 1); -+ if (parents == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (i = 0; i < memberof->num_values; i++) { -+ parents[i] = talloc_strdup(parents, -+ (const char *) memberof->values[i].data); -+ if (parents[i] == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ } -+ -+ *_parents = talloc_steal(mem_ctx, parents); -+ ret = EOK; -+done: -+ talloc_free(tmp_ctx); -+ return ret; -+} -+ -+errno_t -+sdap_nested_group_lookup_external_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req) -+{ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ return EOK; -+} -diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h -index db542eaf869efcd53d0937bef3fc6e99cc78b938..9cde6f5dfe0114f797135b4989b9a4bd336a3f27 100644 ---- a/src/providers/ldap/sdap_async_private.h -+++ b/src/providers/ldap/sdap_async_private.h -@@ -130,8 +130,20 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx, - unsigned long *_num_users, - struct sysdb_attrs ***_users, - unsigned long *_num_groups, -- struct sysdb_attrs ***_groups); -+ struct sysdb_attrs ***_groups, -+ hash_table_t **missing_external); - -+struct tevent_req * -+sdap_nested_group_lookup_external_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct sss_domain_info *group_dom, -+ struct sdap_ext_member_ctx *ext_ctx, -+ hash_table_t *missing_external); -+errno_t -+sdap_nested_group_lookup_external_recv(TALLOC_CTX *mem_ctx, -+ struct tevent_req *req); -+ -+/* from sdap_async_initgroups.c */ - errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, - struct sss_domain_info *domain, - struct sdap_options *opts, -@@ -139,7 +151,7 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, - struct sysdb_attrs **ldap_groups, - int ldap_groups_count); - --/* from sdap_async_nested_groups.c */ -+/* from sdap_ad_groups.c */ - errno_t sdap_check_ad_group_type(struct sss_domain_info *dom, - struct sdap_options *opts, - struct sysdb_attrs *group_attrs, -diff --git a/src/tests/cmocka/test_nested_groups.c b/src/tests/cmocka/test_nested_groups.c -index 8081ff26102e53b2e453838c3a18e4560ac5317e..22b8caefc92a44a2339cbdcaa98226ebb4dc1ef5 100644 ---- a/src/tests/cmocka/test_nested_groups.c -+++ b/src/tests/cmocka/test_nested_groups.c -@@ -57,6 +57,7 @@ struct nested_groups_test_ctx { - struct sdap_domain *sdap_domain; - struct sdap_idmap_ctx *idmap_ctx; - struct sdap_id_ctx *sdap_id_ctx; -+ hash_table_t *missing_external; - - struct sysdb_attrs **users; - struct sysdb_attrs **groups; -@@ -110,7 +111,8 @@ static void nested_groups_test_done(struct tevent_req *req) - - ctx->tctx->error = sdap_nested_group_recv(ctx, req, - &ctx->num_users, &ctx->users, -- &ctx->num_groups, &ctx->groups); -+ &ctx->num_groups, &ctx->groups, -+ &ctx->missing_external); - talloc_zfree(req); - - ctx->tctx->done = true; --- -2.4.3 - diff --git a/SOURCES/0109-UTIL-Use-sss_atomic_read_s-in-generate_csprng_buffer.patch b/SOURCES/0109-UTIL-Use-sss_atomic_read_s-in-generate_csprng_buffer.patch new file mode 100644 index 0000000..0734ff1 --- /dev/null +++ b/SOURCES/0109-UTIL-Use-sss_atomic_read_s-in-generate_csprng_buffer.patch @@ -0,0 +1,94 @@ +From 60596973b503637c742b597aeb862eecae9f9c91 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 8 Aug 2016 14:07:04 +0200 +Subject: [PATCH 109/111] UTIL: Use sss_atomic_read_s in generate_csprng_buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There was a bug in generate_csprng_buffer() where if we read the exact +amount of bytes from /dev/urandom, we would always return EIO. Instead, +let's reuse the existing code from sss_atomic_read_s() which fixes this +bug and reduces code duplication. + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Fabiano Fidêncio +--- + Makefile.am | 2 ++ + src/util/crypto/sss_crypto.c | 29 +++++------------------------ + 2 files changed, 7 insertions(+), 24 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 4d90c7a46e2ee0fe652aa392cf647d056e06c7fc..a32a1e37c85e2370fa006ee73b730145f03c3fc1 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -815,6 +815,7 @@ if HAVE_NSS + src/util/crypto/nss/nss_nite.c \ + src/util/crypto/nss/nss_util.c \ + src/util/crypto/sss_crypto.c \ ++ src/util/atomic_io.c \ + $(NULL) + SSS_CRYPT_CFLAGS = $(NSS_CFLAGS) + SSS_CRYPT_LIBS = $(NSS_LIBS) +@@ -836,6 +837,7 @@ else + src/util/crypto/libcrypto/crypto_obfuscate.c \ + src/util/crypto/libcrypto/crypto_nite.c \ + src/util/crypto/sss_crypto.c \ ++ src/util/atomic_io.c \ + $(NULL) + SSS_CRYPT_CFLAGS = $(CRYPTO_CFLAGS) + SSS_CRYPT_LIBS = $(CRYPTO_LIBS) +diff --git a/src/util/crypto/sss_crypto.c b/src/util/crypto/sss_crypto.c +index 4c775f3d926ae32f3cb72b1329c0a025a0550ed5..ac90bac07c7006a2950331b86bcc412207a3e401 100644 +--- a/src/util/crypto/sss_crypto.c ++++ b/src/util/crypto/sss_crypto.c +@@ -25,41 +25,22 @@ + int generate_csprng_buffer(uint8_t *buf, size_t size) + { + ssize_t rsize; +- ssize_t pos; + int ret; + int fd; + + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) return errno; + +- rsize = 0; +- pos = 0; +- while (rsize < size) { +- rsize = read(fd, buf + pos, size - pos); +- switch (rsize) { +- case -1: +- if (errno == EINTR) continue; +- ret = EIO; +- goto done; +- case 0: +- ret = EIO; +- goto done; +- default: +- if (rsize + pos < size - pos) { +- pos += rsize; +- continue; +- } +- ret = EIO; +- goto done; +- } +- } +- if (rsize != size) { ++ rsize = sss_atomic_read_s(fd, buf, size); ++ if (rsize == -1) { ++ ret = errno; ++ goto done; ++ } else if (rsize != size) { + ret = EFAULT; + goto done; + } + + ret = EOK; +- + done: + close(fd); + return ret; +-- +2.4.11 + diff --git a/SOURCES/0109-memberof-Don-t-allocate-on-a-NULL-context.patch b/SOURCES/0109-memberof-Don-t-allocate-on-a-NULL-context.patch deleted file mode 100644 index 9e25a2d..0000000 --- a/SOURCES/0109-memberof-Don-t-allocate-on-a-NULL-context.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 50d5d5c2b8b304234b222c76413c47dc31a6379f Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 19 Feb 2016 15:50:12 +0100 -Subject: [PATCH 109/109] memberof: Don't allocate on a NULL context -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -https://fedorahosted.org/sssd/ticket/2959 - -In case no previous delete operation occured, the del_ctx->muops pointer we -allocate the diff structure was would be NULL, effectivelly leaking the -diff array during the memberof processing. - -Allocating on del_ctx is safer as that pointer is always allocated and -prevents the leak. - -Reviewed-by: Pavel Březina -(cherry picked from commit cd7a272fb361626a45d54cd45daaab4bfe7ad93f) ---- - src/ldb_modules/memberof.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c -index 4d7b23ea1b95bed0ec5c7cc717b95e6da3cd0717..be7c07dbcda257b6d813bb232ec27973167c25c4 100644 ---- a/src/ldb_modules/memberof.c -+++ b/src/ldb_modules/memberof.c -@@ -2145,7 +2145,7 @@ static int mbof_del_mod_entry(struct mbof_del_operation *delop) - if (!el || !el->num_values) { - return LDB_ERR_OPERATIONS_ERROR; - } -- diff = talloc_array(del_ctx->muops, struct ldb_dn *, -+ diff = talloc_array(del_ctx, struct ldb_dn *, - el->num_values + 1); - if (!diff) { - return LDB_ERR_OPERATIONS_ERROR; -@@ -2241,6 +2241,7 @@ static int mbof_del_mod_entry(struct mbof_del_operation *delop) - if (ret != LDB_SUCCESS) { - return ret; - } -+ talloc_steal(del_ctx->muops, diff[i]); - } - } - --- -2.4.11 - diff --git a/SOURCES/0110-SECRETS-Use-sss_atomic_read-write-for-better-readabi.patch b/SOURCES/0110-SECRETS-Use-sss_atomic_read-write-for-better-readabi.patch new file mode 100644 index 0000000..1c66e09 --- /dev/null +++ b/SOURCES/0110-SECRETS-Use-sss_atomic_read-write-for-better-readabi.patch @@ -0,0 +1,46 @@ +From eb6a90621a53424e4d0a5534eca303b432509433 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 8 Aug 2016 13:50:54 +0200 +Subject: [PATCH 110/111] SECRETS: Use sss_atomic_read/write for better + readability +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sss_atomic_read_s and sss_atomic_write_s are macro-wrappers around +sss_atomic_io_s but it's easier to follow the code with the read/write +vairants used directly. + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Fabiano Fidêncio +--- + src/responder/secrets/local.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c +index 470aec0e195a54dd2af2b929ff1b7a304331a214..17469249b357cbdc5e50ddff6b563fdf2f377577 100644 +--- a/src/responder/secrets/local.c ++++ b/src/responder/secrets/local.c +@@ -621,7 +621,7 @@ int generate_master_key(const char *filename, size_t size) + fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, 0600); + if (fd == -1) return errno; + +- rsize = sss_atomic_io_s(fd, buf, size, false); ++ rsize = sss_atomic_write_s(fd, buf, size); + close(fd); + if (rsize != size) { + ret = unlink(filename); +@@ -681,8 +681,8 @@ int local_secrets_provider_handle(struct sec_ctx *sctx, + } + if (ret) return EFAULT; + +- size = sss_atomic_io_s(mfd, lctx->master_key.data, +- lctx->master_key.length, true); ++ size = sss_atomic_read_s(mfd, lctx->master_key.data, ++ lctx->master_key.length); + close(mfd); + if (size < 0 || size != lctx->master_key.length) return EIO; + +-- +2.4.11 + diff --git a/SOURCES/0110-memberof-Fix-a-memory-leak-when-removing-ghost-users.patch b/SOURCES/0110-memberof-Fix-a-memory-leak-when-removing-ghost-users.patch deleted file mode 100644 index 1a8ab09..0000000 --- a/SOURCES/0110-memberof-Fix-a-memory-leak-when-removing-ghost-users.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 54aa951a69cb0d0d4f2b154bff520145ecd659cf Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Wed, 6 Apr 2016 18:35:39 +0200 -Subject: [PATCH 110/111] memberof: Fix a memory leak when removing ghost users -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit c07fb3f111b4dc2780fa4e1408ea04cd36e95a4d) ---- - src/ldb_modules/memberof.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c -index be7c07dbcda257b6d813bb232ec27973167c25c4..118e95a4d3b6246f2c7775f300ac345ac63ff17a 100644 ---- a/src/ldb_modules/memberof.c -+++ b/src/ldb_modules/memberof.c -@@ -2531,7 +2531,7 @@ static int mbof_del_fill_ghop_ex(struct mbof_del_ctx *del_ctx, - num_gh_vals, mbof->num_values); - - for (i = 0; i < mbof->num_values; i++) { -- valdn = ldb_dn_from_ldb_val(del_ctx->ghops, -+ valdn = ldb_dn_from_ldb_val(del_ctx, - ldb_module_get_ctx(del_ctx->ctx->module), - &mbof->values[i]); - if (!valdn || !ldb_dn_validate(valdn)) { -@@ -2556,6 +2556,7 @@ static int mbof_del_fill_ghop_ex(struct mbof_del_ctx *del_ctx, - if (ret != LDB_SUCCESS) { - return ret; - } -+ talloc_steal(del_ctx->ghops, valdn); - } - } - --- -2.4.11 - diff --git a/SOURCES/0111-BUILD-Ship-systemd-service-file-for-sssd-secrets.patch b/SOURCES/0111-BUILD-Ship-systemd-service-file-for-sssd-secrets.patch new file mode 100644 index 0000000..3b6ae74 --- /dev/null +++ b/SOURCES/0111-BUILD-Ship-systemd-service-file-for-sssd-secrets.patch @@ -0,0 +1,154 @@ +From d0b2cd8d161e7fc6e6c96f51342c88e6572eb1da Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 15 Aug 2016 14:10:23 +0200 +Subject: [PATCH 111/111] BUILD: Ship systemd service file for sssd-secrets +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds two new files: sssd-secrets.socket and sssd-secrets.service. These +can be used to socket-acticate the secrets responder even without +explicitly starting it in the sssd config file. + +The specfile activates the socket after installation which means that +the admin would just be able to use the secrets socket and the +sssd_secrets responder would be started automatically by systemd. + +The sssd-secrets responder is started as root, mostly because I didn't +think of an easy way to pass the uid/gid to the responders without +asking about the sssd user identity in the first place. But nonetheless, +the sssd-secrets responder wasn't tested as non-root and at least the +initialization should be performed as root for the time being. + +Reviewed-by: Fabiano Fidêncio +Reviewed-by: Lukáš Slebodník +--- + Makefile.am | 21 +++++++++++++++++++-- + contrib/sssd.spec.in | 6 ++++++ + src/sysv/systemd/sssd-secrets.service.in | 8 ++++++++ + src/sysv/systemd/sssd-secrets.socket.in | 8 ++++++++ + 4 files changed, 41 insertions(+), 2 deletions(-) + create mode 100644 src/sysv/systemd/sssd-secrets.service.in + create mode 100644 src/sysv/systemd/sssd-secrets.socket.in + +diff --git a/Makefile.am b/Makefile.am +index a32a1e37c85e2370fa006ee73b730145f03c3fc1..6ab4399d5b68644668198bc9b0e3056562a4e51a 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3888,7 +3888,10 @@ systemdunit_DATA = + systemdconf_DATA = + if HAVE_SYSTEMD_UNIT + systemdunit_DATA += \ +- src/sysv/systemd/sssd.service ++ src/sysv/systemd/sssd.service \ ++ src/sysv/systemd/sssd-secrets.socket \ ++ src/sysv/systemd/sssd-secrets.service \ ++ $(NULL) + if WITH_JOURNALD + systemdconf_DATA += \ + src/sysv/systemd/journal.conf +@@ -3926,6 +3929,7 @@ edit_cmd = $(SED) \ + -e 's|@sbindir[@]|$(sbindir)|g' \ + -e 's|@environment_file[@]|$(environment_file)|g' \ + -e 's|@localstatedir[@]|$(localstatedir)|g' \ ++ -e 's|@libexecdir[@]|$(libexecdir)|g' \ + -e 's|@prefix[@]|$(prefix)|g' + + replace_script = \ +@@ -3937,7 +3941,10 @@ replace_script = \ + + EXTRA_DIST += \ + src/sysv/systemd/sssd.service.in \ +- src/sysv/systemd/journal.conf.in ++ src/sysv/systemd/journal.conf.in \ ++ src/sysv/systemd/sssd-secrets.socket.in \ ++ src/sysv/systemd/sssd-secrets.service.in \ ++ $(NULL) + + src/sysv/systemd/sssd.service: src/sysv/systemd/sssd.service.in Makefile + @$(MKDIR_P) src/sysv/systemd/ +@@ -3947,6 +3954,14 @@ src/sysv/systemd/journal.conf: src/sysv/systemd/journal.conf.in Makefile + @$(MKDIR_P) src/sysv/systemd/ + $(replace_script) + ++src/sysv/systemd/sssd-secrets.socket: src/sysv/systemd/sssd-secrets.socket.in Makefile ++ @$(MKDIR_P) src/sysv/systemd/ ++ $(replace_script) ++ ++src/sysv/systemd/sssd-secrets.service: src/sysv/systemd/sssd-secrets.service.in Makefile ++ @$(MKDIR_P) src/sysv/systemd/ ++ $(replace_script) ++ + SSSD_USER_DIRS = \ + $(DESTDIR)$(dbpath) \ + $(DESTDIR)$(keytabdir) \ +@@ -4162,6 +4177,8 @@ endif + done; + rm -Rf ldb_mod_test_dir + rm -f $(builddir)/src/sysv/systemd/sssd.service ++ rm -f $(builddir)/src/sysv/systemd/sssd-secrets.socket ++ rm -f $(builddir)/src/sysv/systemd/sssd-secrets.service + rm -f $(builddir)/src/sysv/systemd/journal.conf + + CLEANFILES += *.X */*.X */*/*.X +diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in +index 14f0cb27ac8f1acc3aa0786da576be33b727e024..f1ff16176cb8ca974b98948958cfa1e9290b0bca 100644 +--- a/contrib/sssd.spec.in ++++ b/contrib/sssd.spec.in +@@ -737,6 +737,8 @@ done + %{_sbindir}/sssd + %if (0%{?use_systemd} == 1) + %{_unitdir}/sssd.service ++%{_unitdir}/sssd-secrets.socket ++%{_unitdir}/sssd-secrets.service + %else + %{_initrddir}/%{name} + %endif +@@ -1069,12 +1071,16 @@ getent passwd sssd >/dev/null || useradd -r -g sssd -d / -s /sbin/nologin -c "Us + # systemd + %post common + %systemd_post sssd.service ++%systemd_post sssd-secrets.socket + + %preun common + %systemd_preun sssd.service ++%systemd_preun sssd-secrets.socket + + %postun common + %systemd_postun_with_restart sssd.service ++%systemd_postun_with_restart sssd-secrets.socket ++%systemd_postun_with_restart sssd-secrets.service + + %else + # sysv +diff --git a/src/sysv/systemd/sssd-secrets.service.in b/src/sysv/systemd/sssd-secrets.service.in +new file mode 100644 +index 0000000000000000000000000000000000000000..119c9bb4b37b672159db707aa11a6d11215f29bf +--- /dev/null ++++ b/src/sysv/systemd/sssd-secrets.service.in +@@ -0,0 +1,8 @@ ++[Unit] ++Description=SSSD Secrets Service responder ++ ++[Install] ++Also=sssd-secrets.socket ++ ++[Service] ++ExecStart=@libexecdir@/sssd/sssd_secrets --uid 0 --gid 0 --debug-to-files +diff --git a/src/sysv/systemd/sssd-secrets.socket.in b/src/sysv/systemd/sssd-secrets.socket.in +new file mode 100644 +index 0000000000000000000000000000000000000000..682e8f6e0fa58092a90259523f9f2f59e0131435 +--- /dev/null ++++ b/src/sysv/systemd/sssd-secrets.socket.in +@@ -0,0 +1,8 @@ ++[Unit] ++Description=SSSD Secrets Service responder socket ++ ++[Socket] ++ListenStream=@localstatedir@/run/secrets.socket ++ ++[Install] ++WantedBy=sockets.target +-- +2.4.11 + diff --git a/SOURCES/0111-memberof-Don-t-allocate-on-NULL-when-deleting-member.patch b/SOURCES/0111-memberof-Don-t-allocate-on-NULL-when-deleting-member.patch deleted file mode 100644 index fdb2593..0000000 --- a/SOURCES/0111-memberof-Don-t-allocate-on-NULL-when-deleting-member.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 58e3bfad6a6fc5d44c928b37e79bc36775aee2a8 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 8 Apr 2016 11:47:44 +0200 -Subject: [PATCH 111/111] memberof: Don't allocate on NULL when deleting - memberUids -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Pavel Březina -(cherry picked from commit 27a0be2bb6f21f66527e0edea4ed2cb4b5cafa53) ---- - src/ldb_modules/memberof.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c -index 118e95a4d3b6246f2c7775f300ac345ac63ff17a..6c0180a493ce0c013b5882100a85b453e4111e63 100644 ---- a/src/ldb_modules/memberof.c -+++ b/src/ldb_modules/memberof.c -@@ -2471,7 +2471,7 @@ static int mbof_del_fill_muop(struct mbof_del_ctx *del_ctx, - for (i = 0; i < el->num_values; i++) { - struct ldb_dn *valdn; - -- valdn = ldb_dn_from_ldb_val(del_ctx->muops, -+ valdn = ldb_dn_from_ldb_val(del_ctx, - ldb_module_get_ctx(del_ctx->ctx->module), - &el->values[i]); - if (!valdn || !ldb_dn_validate(valdn)) { -@@ -2489,6 +2489,7 @@ static int mbof_del_fill_muop(struct mbof_del_ctx *del_ctx, - if (ret != LDB_SUCCESS) { - return ret; - } -+ talloc_steal(del_ctx->muops, valdn); - } - - return LDB_SUCCESS; --- -2.4.11 - diff --git a/SOURCES/0112-DP-Add-log-message-for-get-account-info.patch b/SOURCES/0112-DP-Add-log-message-for-get-account-info.patch new file mode 100644 index 0000000..a2fa19c --- /dev/null +++ b/SOURCES/0112-DP-Add-log-message-for-get-account-info.patch @@ -0,0 +1,33 @@ +From b05afb6811e42d3297e884b0664884aa47af923f Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Tue, 16 Aug 2016 08:49:57 +0200 +Subject: [PATCH 112/115] DP: Add log message for get account info +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Petr Čech +(cherry picked from commit 806f65f3c90dc0f7921932494228ad93f3ed3027) +--- + src/providers/data_provider/dp_target_id.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c +index 938651545ea995091d0aaf29da12bbb8110c9add..8b126d70e59cb33b6de8b678f5b4c1a15b391329 100644 +--- a/src/providers/data_provider/dp_target_id.c ++++ b/src/providers/data_provider/dp_target_id.c +@@ -281,6 +281,11 @@ errno_t dp_get_account_info_handler(struct sbus_request *sbus_req, + goto done; + } + ++ DEBUG(SSSDBG_FUNC_DATA, ++ "Got request for [%#"PRIx32"][%s][%"PRId32"][%s]\n", ++ data->entry_type, be_req2str(data->entry_type), ++ attr_type, filter); ++ + key = talloc_asprintf(data, "%u:%u:%s:%s:%s", data->entry_type, + data->attr_type, extra, domain, filter); + if (key == NULL) { +-- +2.4.11 + diff --git a/SOURCES/0112-IPA-Handle-requests-for-netgroups-from-trusted-domai.patch b/SOURCES/0112-IPA-Handle-requests-for-netgroups-from-trusted-domai.patch deleted file mode 100644 index e60a668..0000000 --- a/SOURCES/0112-IPA-Handle-requests-for-netgroups-from-trusted-domai.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 18cbf559addfeb77ad83b81e23431295a3e5c6ae Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 6 May 2016 15:02:19 +0200 -Subject: [PATCH] IPA: Handle requests for netgroups from trusted domains - gracefully - -In ipa_account_info_handler we first check if the request is for a user -from a trusted domain and go that way for all request types. In -contrast, in the ipa_account_info_done we first check if the requested -object is a netgroup. If both are true, we first start a subdomain -lookup send but then call netgroup lookup recv, which results in talloc -type mismatch and crashes sssd_be. - -Resolves: -https://fedorahosted.org/sssd/ticket/3007 ---- - src/providers/ipa/ipa_id.c | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - -diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c -index 29e22982c415220c931f0422e10cd06dfa1a195b..dff4b23580d8c7502a1fbe9c57d21b8c555883be 100644 ---- a/src/providers/ipa/ipa_id.c -+++ b/src/providers/ipa/ipa_id.c -@@ -115,21 +115,27 @@ void ipa_account_info_handler(struct be_req *breq) - return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success"); - } - -- if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) { -- /* if domain names do not match, this is a subdomain case -- * subdomain lookups are handled differently on the server -- * and the client -- */ -- req = ipa_subdomain_account_send(breq, be_ctx->ev, ipa_ctx, breq, ar); -- -- } else if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) { -+ if ((ar->entry_type & BE_REQ_TYPE_MASK) == BE_REQ_NETGROUP) { - /* netgroups are handled by a separate request function */ - if (ar->filter_type != BE_FILTER_NAME) { - return sdap_handler_done(breq, DP_ERR_FATAL, - EINVAL, "Invalid filter type"); - } -+ -+ if ((strcasecmp(ar->domain, be_ctx->domain->name) != 0)) { -+ return sdap_handler_done(breq, DP_ERR_OK, EOK, -+ "netgroups in subdomains are " -+ "not handled\n"); -+ } -+ - req = ipa_id_get_netgroup_send(breq, be_ctx->ev, - ipa_ctx, ar->filter_value); -+ } else if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) { -+ /* if domain names do not match, this is a subdomain case -+ * subdomain lookups are handled differently on the server -+ * and the client -+ */ -+ req = ipa_subdomain_account_send(breq, be_ctx->ev, ipa_ctx, breq, ar); - } else { - /* any account request is handled by sdap, - * any invalid request is caught there. */ --- -2.4.11 - diff --git a/SOURCES/0113-LDAP-Log-autofs-rfc2307-config-changes-only-with-ena.patch b/SOURCES/0113-LDAP-Log-autofs-rfc2307-config-changes-only-with-ena.patch new file mode 100644 index 0000000..678ec4e --- /dev/null +++ b/SOURCES/0113-LDAP-Log-autofs-rfc2307-config-changes-only-with-ena.patch @@ -0,0 +1,65 @@ +From b415b9d2b6d016928a2bbcaa710cdc876e4ecc9c Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Tue, 16 Aug 2016 13:32:06 +0200 +Subject: [PATCH 113/115] LDAP: Log autofs rfc2307 config changes only with + enabled responder +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +grep -nE "0x0040" /var/log/sssd/sssd_example.com.log +361:(Tue Aug 16 13:04:04 2016) [sssd[be[example.com]]] + [ldap_get_autofs_options] (0x0040): Your configuration uses the autofs + provider with schema set to rfc2307 and default attribute mappings. + The default map has changed in this release, please make sure + the configuration matches the server attributes. + +Reviewed-by: Petr Čech +--- + src/providers/ldap/ldap_options.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ldap/ldap_options.c b/src/providers/ldap/ldap_options.c +index 018f6c31fb6360952308e44979581790b8477dc3..15a2609f07506b6dd442b180651a7e25461976c0 100644 +--- a/src/providers/ldap/ldap_options.c ++++ b/src/providers/ldap/ldap_options.c +@@ -444,6 +444,10 @@ static bool has_defaults(struct confdb_ctx *cdb, + static bool ldap_rfc2307_autofs_defaults(struct confdb_ctx *cdb, + const char *conf_path) + { ++ char **services = NULL; ++ errno_t ret; ++ bool has_autofs_defaults = false; ++ + const char *attrs[] = { + rfc2307_autofs_entry_map[SDAP_OC_AUTOFS_ENTRY].opt_name, + /* SDAP_AT_AUTOFS_ENTRY_KEY missing on purpose, its value was +@@ -455,7 +459,24 @@ static bool ldap_rfc2307_autofs_defaults(struct confdb_ctx *cdb, + NULL, + }; + +- return has_defaults(cdb, conf_path, attrs); ++ ret = confdb_get_string_as_list(cdb, cdb, ++ CONFDB_MONITOR_CONF_ENTRY, ++ CONFDB_MONITOR_ACTIVE_SERVICES, &services); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to read from confdb [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ if (string_in_list("autofs", services, true) == false) { ++ goto done; ++ } ++ ++ has_autofs_defaults = has_defaults(cdb, conf_path, attrs); ++done: ++ talloc_free(services); ++ ++ return has_autofs_defaults; + } + + int ldap_get_autofs_options(TALLOC_CTX *memctx, +-- +2.4.11 + diff --git a/SOURCES/0113-LDAP-Try-also-the-AD-access-control-for-IPA-users.patch b/SOURCES/0113-LDAP-Try-also-the-AD-access-control-for-IPA-users.patch deleted file mode 100644 index ac735c0..0000000 --- a/SOURCES/0113-LDAP-Try-also-the-AD-access-control-for-IPA-users.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 01598f563378f8cf85e7a7fb0c29e7bf32518c3f Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 22 Apr 2016 18:32:26 +0200 -Subject: [PATCH] LDAP: Try also the AD access control for IPA users - -Resolves: - https://fedorahosted.org/sssd/ticket/2927 - -If a user from an AD trusted domain is logging in, we should also check -their AD lockout status. This helps cases where the user might have been -disabled but is logging in with an SSH public key. ---- - src/providers/ldap/sdap_access.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c -index 3ef45b717787058ec61c4d6875cb41bb2e8195fc..14ec34508636c19b288a57cd305d874705bdb842 100644 ---- a/src/providers/ldap/sdap_access.c -+++ b/src/providers/ldap/sdap_access.c -@@ -741,6 +741,21 @@ static errno_t sdap_account_expired(struct sdap_access_ctx *access_ctx, - DEBUG(SSSDBG_CRIT_FAILURE, - "sdap_account_expired_rhds failed.\n"); - } -+ -+ if (ret == EOK && -+ strcasecmp(expire, LDAP_ACCOUNT_EXPIRE_IPA) == 0) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "IPA access control succeeded, checking AD " -+ "access control\n"); -+ ret = sdap_account_expired_ad(pd, user_entry); -+ if (ret == ERR_ACCOUNT_EXPIRED || ret == ERR_ACCESS_DENIED) { -+ DEBUG(SSSDBG_TRACE_FUNC, -+ "sdap_account_expired_ad: %s.\n", sss_strerror(ret)); -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, -+ "sdap_account_expired_ad failed.\n"); -+ } -+ } - } else if (strcasecmp(expire, LDAP_ACCOUNT_EXPIRE_NDS) == 0) { - ret = sdap_account_expired_nds(pd, user_entry); - if (ret == ERR_ACCESS_DENIED) { --- -2.4.11 - diff --git a/SOURCES/0114-NSS-Fix-memory-leak-netgroup.patch b/SOURCES/0114-NSS-Fix-memory-leak-netgroup.patch deleted file mode 100644 index 7b94d48..0000000 --- a/SOURCES/0114-NSS-Fix-memory-leak-netgroup.patch +++ /dev/null @@ -1,106 +0,0 @@ -From de876c0de1056008786f56aa56f1198479cb58d2 Mon Sep 17 00:00:00 2001 -From: Pavel Reichl -Date: Fri, 27 Nov 2015 07:53:00 -0500 -Subject: [PATCH] NSS: Fix memory leak netgroup - -Resolves: -https://fedorahosted.org/sssd/ticket/2865 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 4231a17e66e0809a9c3d42207b45f95429cbb46c) ---- - src/responder/nss/nsssrv_netgroup.c | 41 ++++++++++++++++++++++++++----------- - 1 file changed, 29 insertions(+), 12 deletions(-) - -diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c -index c71043858988bbf6c66aaab1357d24d3701c777f..94fe3776d94a24dec03a5766c4026c3887b448aa 100644 ---- a/src/responder/nss/nsssrv_netgroup.c -+++ b/src/responder/nss/nsssrv_netgroup.c -@@ -435,14 +435,18 @@ static errno_t create_negcache_netgr(struct setent_step_ctx *step_ctx) - errno_t ret; - struct getent_ctx *netgr; - -- netgr = talloc_zero(step_ctx->nctx, struct getent_ctx); -- if (netgr == NULL) { -- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); -- ret = ENOMEM; -- goto done; -- } else { -- netgr->ready = true; -- netgr->found = false; -+ /* Is there already netgroup with such name? */ -+ ret = get_netgroup_entry(step_ctx->nctx, step_ctx->name, -+ &netgr); -+ if (ret != EOK || netgr == NULL) { -+ -+ netgr = talloc_zero(step_ctx->nctx, struct getent_ctx); -+ if (netgr == NULL) { -+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); -+ ret = ENOMEM; -+ goto done; -+ } -+ - netgr->entries = NULL; - netgr->lookup_table = step_ctx->nctx->netgroups; - netgr->name = talloc_strdup(netgr, step_ctx->name); -@@ -457,13 +461,20 @@ static errno_t create_negcache_netgr(struct setent_step_ctx *step_ctx) - DEBUG(SSSDBG_CRIT_FAILURE, "set_netgroup_entry failed.\n"); - goto done; - } -- set_netgr_lifetime(step_ctx->nctx->neg_timeout, step_ctx, netgr); - } - -+ netgr->ready = true; -+ netgr->found = false; -+ -+ set_netgr_lifetime(step_ctx->nctx->neg_timeout, step_ctx, netgr); -+ -+ ret = EOK; -+ - done: - if (ret != EOK) { - talloc_free(netgr); - } -+ - return ret; - } - -@@ -474,6 +485,12 @@ static errno_t lookup_netgr_step(struct setent_step_ctx *step_ctx) - struct getent_ctx *netgr; - char *name = NULL; - uint32_t lifetime; -+ TALLOC_CTX *tmp_ctx; -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } - - /* Check each domain for this netgroup name */ - while (dom) { -@@ -494,8 +511,7 @@ static errno_t lookup_netgr_step(struct setent_step_ctx *step_ctx) - /* make sure to update the dctx if we changed domain */ - step_ctx->dctx->domain = dom; - -- talloc_free(name); -- name = sss_get_cased_name(step_ctx, step_ctx->name, -+ name = sss_get_cased_name(tmp_ctx, step_ctx->name, - dom->case_sensitive); - if (!name) { - DEBUG(SSSDBG_CRIT_FAILURE, "sss_get_cased_name failed\n"); -@@ -623,10 +639,11 @@ static errno_t lookup_netgr_step(struct setent_step_ctx *step_ctx) - "create_negcache_netgr failed with: %d:[%s], ignored.\n", - ret, sss_strerror(ret)); - } -+ - ret = ENOENT; - - done: -- talloc_free(name); -+ talloc_free(tmp_ctx); - return ret; - } - --- -2.4.11 - diff --git a/SOURCES/0114-SSSCTL-More-helpful-error-message-when-InfoPipe-is-d.patch b/SOURCES/0114-SSSCTL-More-helpful-error-message-when-InfoPipe-is-d.patch new file mode 100644 index 0000000..f59feff --- /dev/null +++ b/SOURCES/0114-SSSCTL-More-helpful-error-message-when-InfoPipe-is-d.patch @@ -0,0 +1,36 @@ +From 2b8b5e03319ab72d2c74d61ec24038c5ca412661 Mon Sep 17 00:00:00 2001 +From: Justin Stephenson +Date: Fri, 12 Aug 2016 12:12:57 -0400 +Subject: [PATCH 114/115] SSSCTL: More helpful error message when InfoPipe is + disabled +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/3130 + +Reviewed-by: Petr Čech +Reviewed-by: Pavel Březina +--- + src/tools/sssctl/sssctl_sifp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/tools/sssctl/sssctl_sifp.c b/src/tools/sssctl/sssctl_sifp.c +index 782a72d7ce8bbf1080c6d6ac988ffac2f432955f..c53119b4e199852d1d233c79a0ad3c0bc4de7470 100644 +--- a/src/tools/sssctl/sssctl_sifp.c ++++ b/src/tools/sssctl/sssctl_sifp.c +@@ -26,7 +26,9 @@ + #include "tools/sssctl/sssctl.h" + + #define ERR_SSSD _("Check that SSSD is running and " \ +- "the InfoPipe responder is enabled.\n") ++ "the InfoPipe responder is enabled. " \ ++ "Make sure 'ifp' is listed in the " \ ++ "'services' option in sssd.conf.\n") + + struct sssctl_sifp_data { + sss_sifp_ctx *sifp; +-- +2.4.11 + diff --git a/SOURCES/0115-ipa_s2n_save_objects-use-configured-user-and-group-t.patch b/SOURCES/0115-ipa_s2n_save_objects-use-configured-user-and-group-t.patch deleted file mode 100644 index 2829467..0000000 --- a/SOURCES/0115-ipa_s2n_save_objects-use-configured-user-and-group-t.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 8233ca6a64e673aad41f2aeb1f6152930fd16f72 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 5 Jan 2016 13:46:55 +0100 -Subject: [PATCH] ipa_s2n_save_objects(): use configured user and group timeout -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Resolves https://fedorahosted.org/sssd/ticket/2899 - -Reviewed-by: Lukáš Slebodník -(cherry picked from commit acce97e8d97e81a9e660d46c4e3c00bcb423c035) -(cherry picked from commit e8b5470df44c9f4eb0a4ccc0c79efe778c9658ba) ---- - src/providers/ipa/ipa_s2n_exop.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c -index bcd11749fbde4cae2a47b9b2182138ae04f2d6bc..d101a437dfaf2829013f9e3e3705a7161c654d78 100644 ---- a/src/providers/ipa/ipa_s2n_exop.c -+++ b/src/providers/ipa/ipa_s2n_exop.c -@@ -1743,7 +1743,6 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - { - int ret; - time_t now; -- uint64_t timeout = 10*60*60; /* FIXME: find a better timeout ! */ - struct sss_nss_homedir_ctx homedir_ctx; - char *name = NULL; - char *realm; -@@ -1947,7 +1946,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - * SYSDB_INITGR_EXPIRE will be set.*/ - ret = sysdb_attrs_add_time_t(attrs->sysdb_attrs, - SYSDB_INITGR_EXPIRE, -- time(NULL) + timeout); -+ time(NULL) + dom->user_timeout); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_attrs_add_time_t failed.\n"); -@@ -2006,7 +2005,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - gid, attrs->a.user.pw_gecos, - attrs->a.user.pw_dir, attrs->a.user.pw_shell, - NULL, attrs->sysdb_attrs, NULL, -- timeout, now); -+ dom->user_timeout, now); - 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 -@@ -2034,7 +2033,7 @@ 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); -+ dom->user_timeout, now); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sysdb_store_user failed for MPG user [%d]: %s\n", -@@ -2174,7 +2173,8 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, - } - - ret = sysdb_store_group(dom, name, attrs->a.group.gr_gid, -- attrs->sysdb_attrs, timeout, now); -+ attrs->sysdb_attrs, dom->group_timeout, -+ now); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_group failed.\n"); - goto done; --- -2.4.11 - diff --git a/SOURCES/0115-sdap-Skip-exact-duplicates-when-extending-maps.patch b/SOURCES/0115-sdap-Skip-exact-duplicates-when-extending-maps.patch new file mode 100644 index 0000000..cfd3300 --- /dev/null +++ b/SOURCES/0115-sdap-Skip-exact-duplicates-when-extending-maps.patch @@ -0,0 +1,111 @@ +From c4379aa97754b4c4cfc02663315b7c6319e3fa61 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 10 Aug 2016 15:41:34 +0200 +Subject: [PATCH 115/115] sdap: Skip exact duplicates when extending maps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When extending map with entry that already +exists in the map in the exacty same form, +then there is no need to fail. + +We should only fail if we try to +change purpose of already used sysdb +attribute. + +Resolves: +https://fedorahosted.org/sssd/ticket/3120 + +Signed-off-by: Lukas Slebodnik + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +--- + src/providers/ldap/sdap.c | 42 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 32 insertions(+), 10 deletions(-) + +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index 97b8f126d4ed6bc59c510d5763789a458bd4863a..dc7d5e0caf223c3ee3c43054aa44e796f1b37766 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -122,19 +122,30 @@ static errno_t split_extra_attr(TALLOC_CTX *mem_ctx, + return EOK; + } + +-static bool is_sysdb_duplicate(struct sdap_attr_map *map, +- int num_entries, +- const char *sysdb_attr) ++enum duplicate_t { ++ NOT_FOUND = 0, ++ ALREADY_IN_MAP, /* nothing to add */ ++ CONFLICT_WITH_MAP /* attempt to redefine attribute */ ++}; ++ ++static enum duplicate_t check_duplicate(struct sdap_attr_map *map, ++ int num_entries, ++ const char *sysdb_attr, ++ const char *ldap_attr) + { + int i; + + for (i = 0; i < num_entries; i++) { + if (strcmp(map[i].sys_name, sysdb_attr) == 0) { +- return true; ++ if (strcmp(map[i].name, ldap_attr) == 0) { ++ return ALREADY_IN_MAP; ++ } else { ++ return CONFLICT_WITH_MAP; ++ } + } + } + +- return false; ++ return NOT_FOUND; + } + + int sdap_extend_map(TALLOC_CTX *memctx, +@@ -167,14 +178,20 @@ int sdap_extend_map(TALLOC_CTX *memctx, + return ENOMEM; + } + +- for (i = 0; extra_attrs[i]; i++) { +- ret = split_extra_attr(map, extra_attrs[i], &sysdb_attr, &ldap_attr); ++ for (i = 0; *extra_attrs != NULL; extra_attrs++) { ++ ret = split_extra_attr(map, *extra_attrs, &sysdb_attr, &ldap_attr); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Cannot split %s\n", extra_attrs[i]); ++ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot split %s\n", *extra_attrs); + continue; + } + +- if (is_sysdb_duplicate(map, num_entries, sysdb_attr)) { ++ ret = check_duplicate(map, num_entries, sysdb_attr, ldap_attr); ++ if (ret == ALREADY_IN_MAP) { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Attribute %s (%s in LDAP) is already in map.\n", ++ sysdb_attr, ldap_attr); ++ continue; ++ } else if (ret == CONFLICT_WITH_MAP) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Attribute %s (%s in LDAP) is already used by SSSD, please " + "choose a different cache name\n", sysdb_attr, ldap_attr); +@@ -193,9 +210,14 @@ int sdap_extend_map(TALLOC_CTX *memctx, + map[num_entries+i].def_name == NULL) { + return ENOMEM; + } +- DEBUG(SSSDBG_TRACE_FUNC, "Extending map with %s\n", extra_attrs[i]); ++ DEBUG(SSSDBG_TRACE_FUNC, "Extending map with %s\n", *extra_attrs); ++ ++ /* index must be incremented only for appended entry. */ ++ i++; + } + ++ nextra = i; ++ + /* Sentinel */ + memset(&map[num_entries+nextra], 0, sizeof(struct sdap_attr_map)); + +-- +2.4.11 + diff --git a/SOURCES/0116-IPA-use-forest-name-when-looking-up-the-Global-Catal.patch b/SOURCES/0116-IPA-use-forest-name-when-looking-up-the-Global-Catal.patch deleted file mode 100644 index 164e78d..0000000 --- a/SOURCES/0116-IPA-use-forest-name-when-looking-up-the-Global-Catal.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0a7c43151c362bf8e7276fc1d08c49cb91fdb005 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Tue, 17 May 2016 11:54:10 +0200 -Subject: [PATCH] IPA: use forest name when looking up the Global Catalog - -Resolves https://fedorahosted.org/sssd/ticket/3015 - -Reviewed-by: Jakub Hrozek -(cherry picked from commit 149174acae677d1e72a0da431bf0850d55f2ccb4) ---- - src/providers/ipa/ipa_subdomains_server.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c -index c561118946e2ba76b2b4076e5057b1b5c0075a41..b75266701904d8bd1723bc277ae96d407f90f30d 100644 ---- a/src/providers/ipa/ipa_subdomains_server.c -+++ b/src/providers/ipa/ipa_subdomains_server.c -@@ -249,7 +249,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, - DEBUG(SSSDBG_TRACE_ALL, "No extra attrs set.\n"); - } - -- gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->name); -+ gc_service_name = talloc_asprintf(ad_options, "%s%s", "gc_", subdom->forest); - if (gc_service_name == NULL) { - talloc_free(ad_options); - return ENOMEM; --- -2.4.11 - diff --git a/SOURCES/0116-watchdog-cope-with-time-shift.patch b/SOURCES/0116-watchdog-cope-with-time-shift.patch new file mode 100644 index 0000000..dbea5c2 --- /dev/null +++ b/SOURCES/0116-watchdog-cope-with-time-shift.patch @@ -0,0 +1,96 @@ +From c99c5bb88c8b02f24a2b0b15ea8bc9fe2a8dc6c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Mon, 22 Aug 2016 13:15:04 +0200 +Subject: [PATCH 116/117] watchdog: cope with time shift +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When a time is changed into the past during sssd runtime +(e.g. on boot during time correction), it is possible that +we never hit watchdog tevent timer since it is based on +system time. + +This patch adds a past-time shift detection mechanism. If a time +shift is detected we restart watchdog. + +Resolves: +https://fedorahosted.org/sssd/ticket/3154 + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Fabiano Fidêncio +--- + src/util/util_watchdog.c | 41 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + +diff --git a/src/util/util_watchdog.c b/src/util/util_watchdog.c +index 5032fddba1b94b3fc7e560162c392dfa57d699cf..1c27d73f13b3042ecb549a2184e1368e8339d199 100644 +--- a/src/util/util_watchdog.c ++++ b/src/util/util_watchdog.c +@@ -29,8 +29,39 @@ struct watchdog_ctx { + struct timeval interval; + struct tevent_timer *te; + volatile int ticks; ++ ++ /* To detect time shift. */ ++ struct tevent_context *ev; ++ int input_interval; ++ time_t timestamp; + } watchdog_ctx; + ++static bool watchdog_detect_timeshift(void) ++{ ++ time_t prev_time; ++ time_t cur_time; ++ errno_t ret; ++ ++ prev_time = watchdog_ctx.timestamp; ++ cur_time = watchdog_ctx.timestamp = time(NULL); ++ if (cur_time < prev_time) { ++ /* Time shift detected. We need to restart watchdog. */ ++ DEBUG(SSSDBG_IMPORTANT_INFO, "Time shift detected, " ++ "restarting watchdog!\n"); ++ teardown_watchdog(); ++ ret = setup_watchdog(watchdog_ctx.ev, watchdog_ctx.input_interval); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to restart watchdog " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ orderly_shutdown(1); ++ } ++ ++ return true; ++ } ++ ++ return false; ++} ++ + /* the watchdog is purposefully *not* handled by the tevent + * signal handler as it is meant to check if the daemon is + * still processing the event queue itself. A stuck process +@@ -38,6 +69,12 @@ struct watchdog_ctx { + * signals either */ + static void watchdog_handler(int sig) + { ++ /* Do not count ticks if time shift was detected ++ * since watchdog was restarted. */ ++ if (watchdog_detect_timeshift()) { ++ return; ++ } ++ + /* if 3 ticks passed by kills itself */ + + if (__sync_add_and_fetch(&watchdog_ctx.ticks, 1) > 3) { +@@ -101,6 +138,10 @@ int setup_watchdog(struct tevent_context *ev, int interval) + watchdog_ctx.interval.tv_sec = interval; + watchdog_ctx.interval.tv_usec = 0; + ++ watchdog_ctx.ev = ev; ++ watchdog_ctx.input_interval = interval; ++ watchdog_ctx.timestamp = time(NULL); ++ + /* Start the timer */ + /* we give 1 second head start to the watchdog event */ + its.it_value.tv_sec = interval + 1; +-- +2.4.11 + diff --git a/SOURCES/0117-LDAP-Fix-leak-of-file-descriptors.patch b/SOURCES/0117-LDAP-Fix-leak-of-file-descriptors.patch deleted file mode 100644 index 0db92d2..0000000 --- a/SOURCES/0117-LDAP-Fix-leak-of-file-descriptors.patch +++ /dev/null @@ -1,113 +0,0 @@ -From bb3365aee62f616c9d0c8cc8d737ef69d46544d3 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 22 Oct 2015 10:30:12 +0200 -Subject: [PATCH 117/117] 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) -(cherry picked from commit 2136f71c94660bcdde83f80feb83734389d57674) ---- - 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 dd63b4b4f22f0aa1b540bc04ede211ac9cb88ebe..f42f9404bb9b79cdeb6a01c0a6e5025bb0370a6c 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.4.11 - diff --git a/SOURCES/0117-PROXY-Use-the-fqname-when-converting-to-lowercase.patch b/SOURCES/0117-PROXY-Use-the-fqname-when-converting-to-lowercase.patch new file mode 100644 index 0000000..a41eedb --- /dev/null +++ b/SOURCES/0117-PROXY-Use-the-fqname-when-converting-to-lowercase.patch @@ -0,0 +1,39 @@ +From fe4117b3203c0464b1366066bf09d83978c632d8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Tue, 23 Aug 2016 23:46:59 +0200 +Subject: [PATCH 117/117] PROXY: Use the fqname when converting to lowercase +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When saving the user there is a comparison between the "cased alias" +and the "lowercase password name". However, the first doesn't use fully +qualified name while the second does, resulting in a not expected +override of the "nameAlias" attribute of a stored user when trying to +authenticate more than once using an alias. + +Resolves: +https://fedorahosted.org/sssd/ticket/3134 + +Signed-off-by: Fabiano Fidêncio +Reviewed-by: Lukáš Slebodník +--- + src/providers/proxy/proxy_id.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c +index f633a5e1c71dfc7f8d124e62169cfda48773bbb1..df8a329d4a5a4bd7ed7723d0219089e7b4ef639d 100644 +--- a/src/providers/proxy/proxy_id.c ++++ b/src/providers/proxy/proxy_id.c +@@ -256,7 +256,7 @@ static int save_user(struct sss_domain_info *domain, + } + + if (lowercase) { +- lc_pw_name = sss_tc_utf8_str_tolower(attrs, pwd->pw_name); ++ lc_pw_name = sss_tc_utf8_str_tolower(attrs, real_name); + if (lc_pw_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n"); + ret = ENOMEM; +-- +2.4.11 + diff --git a/SOURCES/0118-BUILD-Allow-to-read-private-pipes-for-root.patch b/SOURCES/0118-BUILD-Allow-to-read-private-pipes-for-root.patch new file mode 100644 index 0000000..8d87aad --- /dev/null +++ b/SOURCES/0118-BUILD-Allow-to-read-private-pipes-for-root.patch @@ -0,0 +1,81 @@ +From 711a29023252013a8451ee1b90f045782fee1a38 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 19 Aug 2016 10:46:12 +0200 +Subject: [PATCH 118/121] BUILD: Allow to read private pipes for root + +Root can read anything from any directory even with permissions 000. + +However SELinux checks discretionary access control (DAC) +and deny access if access is not allowed for root by DAC. +The pam_sss use different unix socket /var/lib/sss/pipes/private/pam +for user with uid 0. Therefore root need to be able read content +of directory with private pipes. + +type=AVC msg=audit(08/19/2016 10:58:34.081:3369) : avc: denied + { dac_read_search } for pid=20257 comm=vsftpd capability=dac_read_search + scontext=system_u:system_r:ftpd_t:s0-s0:c0.c1023 + tcontext=system_u:system_r:ftpd_t:s0-s0:c0.c1023 tclass=capability + +type=AVC msg=audit(08/19/2016 10:58:34.081:3369) : avc: denied + { dac_override } for pid=20257 comm=vsftpd capability=dac_override + scontext=system_u:system_r:ftpd_t:s0-s0:c0.c1023 + tcontext=system_u:system_r:ftpd_t:s0-s0:c0.c1023 tclass=capability + +Resolves: +https://fedorahosted.org/sssd/ticket/3143 + +Reviewed-by: Jakub Hrozek +--- + Makefile.am | 8 ++++---- + contrib/sssd.spec.in | 2 +- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 6ab4399d5b68644668198bc9b0e3056562a4e51a..b8cd8b64ca8a130a5dd3107e1fb1445310192059 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3967,7 +3967,6 @@ SSSD_USER_DIRS = \ + $(DESTDIR)$(keytabdir) \ + $(DESTDIR)$(mcpath) \ + $(DESTDIR)$(pipepath) \ +- $(DESTDIR)$(pipepath)/private \ + $(DESTDIR)$(pubconfpath) \ + $(DESTDIR)$(pubconfpath)/krb5.include.d \ + $(DESTDIR)$(gpocachepath) \ +@@ -3994,16 +3993,17 @@ installsssddirs:: + $(DESTDIR)$(sssddatadir) \ + $(DESTDIR)$(sudolibdir) \ + $(DESTDIR)$(autofslibdir) \ ++ $(DESTDIR)$(pipepath)/private \ + $(SSSD_USER_DIRS) \ + $(NULL); + if SSSD_USER +- -chown $(SSSD_USER):$(SSSD_USER) \ +- $(SSSD_USER_DIRS) ++ -chown $(SSSD_USER):$(SSSD_USER) $(SSSD_USER_DIRS) ++ -chown $(SSSD_USER) $(DESTDIR)$(pipepath)/private + endif + $(INSTALL) -d -m 0700 $(DESTDIR)$(dbpath) $(DESTDIR)$(logpath) \ +- $(DESTDIR)$(pipepath)/private \ + $(DESTDIR)$(keytabdir) \ + $(NULL) ++ $(INSTALL) -d -m 0750 $(DESTDIR)$(pipepath)/private + $(INSTALL) -d -m 0755 $(DESTDIR)$(mcpath) $(DESTDIR)$(pipepath) \ + $(DESTDIR)$(pubconfpath) \ + $(DESTDIR)$(pubconfpath)/krb5.include.d $(DESTDIR)$(gpocachepath) +diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in +index f1ff16176cb8ca974b98948958cfa1e9290b0bca..cb68a73e85122b016de7df37bcf4fc232a10a2ac 100644 +--- a/contrib/sssd.spec.in ++++ b/contrib/sssd.spec.in +@@ -784,7 +784,7 @@ done + %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/group + %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/initgroups + %attr(755,sssd,sssd) %dir %{pipepath} +-%attr(700,sssd,sssd) %dir %{pipepath}/private ++%attr(750,sssd,root) %dir %{pipepath}/private + %attr(755,sssd,sssd) %dir %{pubconfpath} + %attr(755,sssd,sssd) %dir %{gpocachepath} + %attr(750,sssd,sssd) %dir %{_var}/log/%{name} +-- +2.4.11 + diff --git a/SOURCES/0118-libwbclient-wbcSidsToUnixIds-don-t-fail-on-errors.patch b/SOURCES/0118-libwbclient-wbcSidsToUnixIds-don-t-fail-on-errors.patch deleted file mode 100644 index 9bda53e..0000000 --- a/SOURCES/0118-libwbclient-wbcSidsToUnixIds-don-t-fail-on-errors.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 02a5b8945863755e8708b6a11954c1f398680e01 Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Thu, 2 Jun 2016 21:01:11 +0200 -Subject: [PATCH 118/118] libwbclient: wbcSidsToUnixIds() don't fail on errors - -Resolves: https://fedorahosted.org/sssd/ticket/3028 - -Reviewed-by: Alexander Bokovoy -(cherry picked from commit 52f1093ef3d7c44132ec10c57436865b2cbb19d7) -(cherry picked from commit 15ad5f603a5797c61a01f67365c2581c7bddcdfa) ---- - src/sss_client/libwbclient/wbc_idmap_sssd.c | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - -diff --git a/src/sss_client/libwbclient/wbc_idmap_sssd.c b/src/sss_client/libwbclient/wbc_idmap_sssd.c -index 1b0e2e10a5ce1a0c7577d391b740ff988f920903..6b5f525f0433c948e4d570d177dc6cffd82eff40 100644 ---- a/src/sss_client/libwbclient/wbc_idmap_sssd.c -+++ b/src/sss_client/libwbclient/wbc_idmap_sssd.c -@@ -172,15 +172,14 @@ wbcErr wbcSidsToUnixIds(const struct wbcDomainSid *sids, uint32_t num_sids, - wbcErr wbc_status; - - for (c = 0; c < num_sids; c++) { -+ type = SSS_ID_TYPE_NOT_SPECIFIED; - wbc_status = wbcSidToString(&sids[c], &sid_str); -- if (!WBC_ERROR_IS_OK(wbc_status)) { -- return wbc_status; -- } -- -- ret = sss_nss_getidbysid(sid_str, &id, &type); -- wbcFreeMemory(sid_str); -- if (ret != 0) { -- return WBC_ERR_UNKNOWN_FAILURE; -+ if (WBC_ERROR_IS_OK(wbc_status)) { -+ ret = sss_nss_getidbysid(sid_str, &id, &type); -+ wbcFreeMemory(sid_str); -+ if (ret != 0) { -+ type = SSS_ID_TYPE_NOT_SPECIFIED; -+ } - } - - switch (type) { --- -2.4.11 - diff --git a/SOURCES/0119-IPA-ldap_group_external_member-defaults-to-ipaExtern.patch b/SOURCES/0119-IPA-ldap_group_external_member-defaults-to-ipaExtern.patch deleted file mode 100644 index beab91b..0000000 --- a/SOURCES/0119-IPA-ldap_group_external_member-defaults-to-ipaExtern.patch +++ /dev/null @@ -1,26 +0,0 @@ -From fe540303e8fa2000160d087da4f19df317fb7de6 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Thu, 14 Jul 2016 12:21:25 +0200 -Subject: [PATCH 119/119] IPA: ldap_group_external_member defaults to - ipaExternalMember - ---- - 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 81ccc42fc0c9f21c8ef16e2d1735bc06199ba747..c1bfc9fde38a9c0fbd0a464b340e644cc4835455 100644 ---- a/src/providers/ipa/ipa_opts.h -+++ b/src/providers/ipa/ipa_opts.h -@@ -221,7 +221,7 @@ struct sdap_attr_map ipa_group_map[] = { - { "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 }, -- { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, -+ { "ldap_group_external_member", "ipaExternalMember", SYSDB_EXTERNAL_MEMBER, NULL }, - SDAP_ATTR_MAP_TERMINATOR - }; - --- -2.4.11 - diff --git a/SOURCES/0119-SYSDB-Rework-sysdb_cache_connect.patch b/SOURCES/0119-SYSDB-Rework-sysdb_cache_connect.patch new file mode 100644 index 0000000..bc2bacb --- /dev/null +++ b/SOURCES/0119-SYSDB-Rework-sysdb_cache_connect.patch @@ -0,0 +1,123 @@ +From 960eca66245f23cf8ae0f32c3e44581a0e1117f9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Tue, 16 Aug 2016 11:20:49 +0200 +Subject: [PATCH 119/121] SYSDB: Rework sysdb_cache_connect() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As sysdb_cache_connect() has two very specific use cases (connect to the +cache and connect to the timestamp cache) and each of those calls have a +predetermined/fixed sets of values for a few parameters, let's try to +make the code a bit simpler to follow by having explicit functions for +connecting to the cache and connecting to the timestamp cache. + +Macros could be used as well, but I have a slightly preference for +having two new functions instead of macros accessing internal parameters +of the macro's parameter. + +Related: +https://fedorahosted.org/sssd/ticket/3128 + +Signed-off-by: Fabiano Fidêncio + +Reviewed-by: Jakub Hrozek +--- + src/db/sysdb_init.c | 53 ++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 34 insertions(+), 19 deletions(-) + +diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c +index 9e3646bfeb9a494ebff2d348ab1c53336f8a5c03..59934701c4d2b9d770385a202af058404a6d3eb9 100644 +--- a/src/db/sysdb_init.c ++++ b/src/db/sysdb_init.c +@@ -511,14 +511,14 @@ done: + return ret; + } + +-static errno_t sysdb_cache_connect(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domain, +- const char *ldb_file, +- int flags, +- const char *exp_version, +- const char *base_ldif, +- struct ldb_context **_ldb, +- const char **_version) ++static errno_t sysdb_cache_connect_helper(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain, ++ const char *ldb_file, ++ int flags, ++ const char *exp_version, ++ const char *base_ldif, ++ struct ldb_context **_ldb, ++ const char **_version) + { + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_message_element *el; +@@ -619,6 +619,29 @@ done: + return ret; + } + ++static errno_t sysdb_cache_connect(TALLOC_CTX *mem_ctx, ++ struct sysdb_ctx *sysdb, ++ struct sss_domain_info *domain, ++ struct ldb_context **ldb, ++ const char **version) ++{ ++ return sysdb_cache_connect_helper(mem_ctx, domain, sysdb->ldb_file, ++ 0, SYSDB_VERSION, SYSDB_BASE_LDIF, ++ ldb, version); ++} ++ ++static errno_t sysdb_ts_cache_connect(TALLOC_CTX *mem_ctx, ++ struct sysdb_ctx *sysdb, ++ struct sss_domain_info *domain, ++ struct ldb_context **ldb, ++ const char **version) ++{ ++ return sysdb_cache_connect_helper(mem_ctx, domain, sysdb->ldb_ts_file, ++ LDB_FLG_NOSYNC, SYSDB_TS_VERSION, ++ SYSDB_TS_BASE_LDIF, ++ ldb, version); ++} ++ + static errno_t remove_ts_cache(struct sysdb_ctx *sysdb) + { + errno_t ret; +@@ -649,9 +672,7 @@ static int sysdb_domain_cache_connect(struct sysdb_ctx *sysdb, + return ENOMEM; + } + +- ret = sysdb_cache_connect(tmp_ctx, domain, sysdb->ldb_file, 0, +- SYSDB_VERSION, SYSDB_BASE_LDIF, +- &ldb, &version); ++ ret = sysdb_cache_connect(tmp_ctx, sysdb, domain, &ldb, &version); + switch (ret) { + case ERR_SYSDB_VERSION_TOO_OLD: + if (upgrade_ctx == NULL) { +@@ -731,10 +752,7 @@ static int sysdb_timestamp_cache_connect(struct sysdb_ctx *sysdb, + return ENOMEM; + } + +- ret = sysdb_cache_connect(tmp_ctx, domain, +- sysdb->ldb_ts_file, LDB_FLG_NOSYNC, +- SYSDB_TS_VERSION, SYSDB_TS_BASE_LDIF, +- &ldb, &version); ++ ret = sysdb_ts_cache_connect(tmp_ctx, sysdb, domain, &ldb, &version); + switch (ret) { + case ERR_SYSDB_VERSION_TOO_OLD: + if (upgrade_ctx == NULL) { +@@ -801,10 +819,7 @@ static int sysdb_timestamp_cache_connect(struct sysdb_ctx *sysdb, + /* Now the connect must succeed because the previous cache doesn't + * exist anymore. + */ +- ret = sysdb_cache_connect(tmp_ctx, domain, +- sysdb->ldb_ts_file, LDB_FLG_NOSYNC, +- SYSDB_TS_VERSION, SYSDB_TS_BASE_LDIF, +- &ldb, &version); ++ ret = sysdb_ts_cache_connect(tmp_ctx, sysdb, domain, &ldb, &version); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not delete the timestamp ldb file (%d) (%s)\n", +-- +2.4.11 + diff --git a/SOURCES/0120-SYSDB-Remove-the-timestamp-cache-for-a-newly-created.patch b/SOURCES/0120-SYSDB-Remove-the-timestamp-cache-for-a-newly-created.patch new file mode 100644 index 0000000..9145773 --- /dev/null +++ b/SOURCES/0120-SYSDB-Remove-the-timestamp-cache-for-a-newly-created.patch @@ -0,0 +1,151 @@ +From 9e5fc47e6636f6a149dba9a0a708892be85a6f22 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Tue, 16 Aug 2016 11:46:41 +0200 +Subject: [PATCH 120/121] SYSDB: Remove the timestamp cache for a newly created + cache +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +As many users are used to remove the persistent cache without removing +the timestamp cache, let's throw away the timestamp cache in this case. + +Resolves: +https://fedorahosted.org/sssd/ticket/3128 + +Signed-off-by: Fabiano Fidêncio + +Reviewed-by: Jakub Hrozek +--- + src/db/sysdb_init.c | 69 ++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 47 insertions(+), 22 deletions(-) + +diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c +index 59934701c4d2b9d770385a202af058404a6d3eb9..c387c1b12c116f38d5a13f1adeac5ef64d593af8 100644 +--- a/src/db/sysdb_init.c ++++ b/src/db/sysdb_init.c +@@ -511,12 +511,30 @@ done: + return ret; + } + ++static errno_t remove_ts_cache(struct sysdb_ctx *sysdb) ++{ ++ errno_t ret; ++ ++ if (sysdb->ldb_ts_file == NULL) { ++ return EOK; ++ } ++ ++ ret = unlink(sysdb->ldb_ts_file); ++ if (ret != EOK && errno != ENOENT) { ++ return errno; ++ } ++ ++ return EOK; ++} ++ + static errno_t sysdb_cache_connect_helper(TALLOC_CTX *mem_ctx, ++ struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, + const char *ldb_file, + int flags, + const char *exp_version, + const char *base_ldif, ++ bool *_newly_created, + struct ldb_context **_ldb, + const char **_version) + { +@@ -527,6 +545,7 @@ static errno_t sysdb_cache_connect_helper(TALLOC_CTX *mem_ctx, + const char *version = NULL; + int ret; + struct ldb_context *ldb; ++ bool newly_created; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { +@@ -592,8 +611,9 @@ static errno_t sysdb_cache_connect_helper(TALLOC_CTX *mem_ctx, + goto done; + } + +- /* The cache has been newly created. +- * We need to reopen the LDB to ensure that ++ newly_created = true; ++ ++ /* We need to reopen the LDB to ensure that + * all of the special values take effect + * (such as enabling the memberOf plugin and + * the various indexes). +@@ -613,6 +633,9 @@ static errno_t sysdb_cache_connect_helper(TALLOC_CTX *mem_ctx, + } + done: + if (ret == EOK) { ++ if (_newly_created != NULL) { ++ *_newly_created = newly_created; ++ } + *_ldb = talloc_steal(mem_ctx, ldb); + } + talloc_free(tmp_ctx); +@@ -625,9 +648,27 @@ static errno_t sysdb_cache_connect(TALLOC_CTX *mem_ctx, + struct ldb_context **ldb, + const char **version) + { +- return sysdb_cache_connect_helper(mem_ctx, domain, sysdb->ldb_file, ++ bool newly_created; ++ bool ldb_file_exists; ++ errno_t ret; ++ ++ ldb_file_exists = !(access(sysdb->ldb_file, F_OK) == -1 && errno == ENOENT); ++ ++ ret = sysdb_cache_connect_helper(mem_ctx, sysdb, domain, sysdb->ldb_file, + 0, SYSDB_VERSION, SYSDB_BASE_LDIF, +- ldb, version); ++ &newly_created, ldb, version); ++ ++ /* The cache has been newly created. */ ++ if (ret == EOK && newly_created && !ldb_file_exists) { ++ ret = remove_ts_cache(sysdb); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Could not delete the timestamp ldb file (%d) (%s)\n", ++ ret, sss_strerror(ret)); ++ } ++ } ++ ++ return ret; + } + + static errno_t sysdb_ts_cache_connect(TALLOC_CTX *mem_ctx, +@@ -636,28 +677,12 @@ static errno_t sysdb_ts_cache_connect(TALLOC_CTX *mem_ctx, + struct ldb_context **ldb, + const char **version) + { +- return sysdb_cache_connect_helper(mem_ctx, domain, sysdb->ldb_ts_file, ++ return sysdb_cache_connect_helper(mem_ctx, sysdb, domain, sysdb->ldb_ts_file, + LDB_FLG_NOSYNC, SYSDB_TS_VERSION, +- SYSDB_TS_BASE_LDIF, ++ SYSDB_TS_BASE_LDIF, NULL, + ldb, version); + } + +-static errno_t remove_ts_cache(struct sysdb_ctx *sysdb) +-{ +- errno_t ret; +- +- if (sysdb->ldb_ts_file == NULL) { +- return EOK; +- } +- +- ret = unlink(sysdb->ldb_ts_file); +- if (ret != EOK && errno != ENOENT) { +- return errno; +- } +- +- return EOK; +-} +- + static int sysdb_domain_cache_connect(struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, + struct sysdb_dom_upgrade_ctx *upgrade_ctx) +-- +2.4.11 + diff --git a/SOURCES/0121-SECRETS-Return-ENOENT-when_deleting-a-non-existent-s.patch b/SOURCES/0121-SECRETS-Return-ENOENT-when_deleting-a-non-existent-s.patch new file mode 100644 index 0000000..80ff5bb --- /dev/null +++ b/SOURCES/0121-SECRETS-Return-ENOENT-when_deleting-a-non-existent-s.patch @@ -0,0 +1,47 @@ +From 0f3b872aa881d5480fc98b0cfc7421ffc7f802a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Wed, 17 Aug 2016 13:12:21 +0200 +Subject: [PATCH 121/121] SECRETS: Return ENOENT when_deleting a non-existent + secret +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For this, just make use of the sysdb_error_to_errno() function. + +Resolves: +https://fedorahosted.org/sssd/ticket/3125 + +Signed-off-by: Fabiano Fidêncio + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +--- + src/responder/secrets/local.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c +index 17469249b357cbdc5e50ddff6b563fdf2f377577..ac3049b62fa77f69d44ec5792139fe3378afb3f4 100644 +--- a/src/responder/secrets/local.c ++++ b/src/responder/secrets/local.c +@@ -375,15 +375,10 @@ int local_db_delete(TALLOC_CTX *mem_ctx, + int ret; + + ret = local_db_dn(mem_ctx, lctx->ldb, req_path, &dn); +- if (ret != EOK) goto done; ++ if (ret != EOK) return ret; + + ret = ldb_delete(lctx->ldb, dn); +- if (ret != EOK) { +- ret = EIO; +- } +- +-done: +- return ret; ++ return sysdb_error_to_errno(ret); + } + + int local_db_create(TALLOC_CTX *mem_ctx, +-- +2.4.11 + diff --git a/SOURCES/0122-IPA-Parse-qualified-names-when-guessing-AD-user-prin.patch b/SOURCES/0122-IPA-Parse-qualified-names-when-guessing-AD-user-prin.patch new file mode 100644 index 0000000..8bc504d --- /dev/null +++ b/SOURCES/0122-IPA-Parse-qualified-names-when-guessing-AD-user-prin.patch @@ -0,0 +1,61 @@ +From b93f618189d9906802c79d3090fcc477f762e6e6 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 9 Aug 2016 22:08:27 +0200 +Subject: [PATCH 122/126] IPA: Parse qualified names when guessing AD user + principal + +Most AD users store their UPN in an attribute. If they don't, or the sssd +was configured (typically in earlier versions to work around a bug) to not +look at the principal attribute, then sssd is supposed to guess +the attribute. + +That currently doesn't work in 1.14, because the username is already +qualified and then we also append the realm name to it. We need to parse +the simple username from the qualified name first. + +The issue can be reproduced simply by authenticating as the Administrator +account in IPA-AD trust setups. + +Resolves: +https://fedorahosted.org/sssd/ticket/3127 + +Reviewed-by: Sumit Bose +--- + src/providers/ipa/ipa_s2n_exop.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c +index 255dad45037a6cb8f399bf2df500215f6fb25b59..bfa6757046282d656627aa57cb9054b09facd2b8 100644 +--- a/src/providers/ipa/ipa_s2n_exop.c ++++ b/src/providers/ipa/ipa_s2n_exop.c +@@ -1941,6 +1941,7 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, + struct sss_nss_homedir_ctx homedir_ctx; + char *name = NULL; + char *realm; ++ char *short_name = NULL; + char *upn = NULL; + gid_t gid; + gid_t orig_gid = 0; +@@ -2092,8 +2093,17 @@ static errno_t ipa_s2n_save_objects(struct sss_domain_info *dom, + ret = ENOMEM; + goto done; + } +- upn = talloc_asprintf(tmp_ctx, "%s@%s", +- attrs->a.user.pw_name, realm); ++ ++ ret = sss_parse_internal_fqname(tmp_ctx, attrs->a.user.pw_name, ++ &short_name, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot parse internal name %s\n", ++ attrs->a.user.pw_name); ++ goto done; ++ } ++ ++ upn = talloc_asprintf(tmp_ctx, "%s@%s", short_name, realm); + if (!upn) { + DEBUG(SSSDBG_OP_FAILURE, "failed to format UPN.\n"); + ret = ENOMEM; +-- +2.4.11 + diff --git a/SOURCES/0123-SYSDB-Fix-uninitialized-scalar-variable.patch b/SOURCES/0123-SYSDB-Fix-uninitialized-scalar-variable.patch new file mode 100644 index 0000000..d9897ba --- /dev/null +++ b/SOURCES/0123-SYSDB-Fix-uninitialized-scalar-variable.patch @@ -0,0 +1,35 @@ +From d6ecd69f63496446d23252426de41523ebe2bbf6 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 29 Aug 2016 09:13:49 +0200 +Subject: [PATCH 123/126] SYSDB: Fix uninitialized scalar variable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The boolean variable newly_created could be used uninitialized +in done section in case of failure. The variable was firstly initialized +to true after succesfull execution of function sysdb_cache_create_empty. + +Uninitialized variable usually means true for boolean variable. + +Reviewed-by: Fabiano Fidêncio +--- + src/db/sysdb_init.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c +index c387c1b12c116f38d5a13f1adeac5ef64d593af8..d110aa7a2878e47650db177cfd342d0ac32248ab 100644 +--- a/src/db/sysdb_init.c ++++ b/src/db/sysdb_init.c +@@ -545,7 +545,7 @@ static errno_t sysdb_cache_connect_helper(TALLOC_CTX *mem_ctx, + const char *version = NULL; + int ret; + struct ldb_context *ldb; +- bool newly_created; ++ bool newly_created = false; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { +-- +2.4.11 + diff --git a/SOURCES/0124-PROXY-Use-right-name-in-ldap-filter.patch b/SOURCES/0124-PROXY-Use-right-name-in-ldap-filter.patch new file mode 100644 index 0000000..77703a5 --- /dev/null +++ b/SOURCES/0124-PROXY-Use-right-name-in-ldap-filter.patch @@ -0,0 +1,51 @@ +From d2636b0f34d6e4ff7cf99a44db8317fd485a3783 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 26 Aug 2016 14:57:22 +0200 +Subject: [PATCH 124/126] PROXY: Use right name in ldap filter + +We used internal fq name in ldap filter +with id_provider proxy to files and auth provider +ldap + +[sssd[be[LDAP]]] [sdap_get_generic_ext_step] + (0x0400): calling ldap_search_ext with + [(&(uid=testuser1@ldap)(objectclass=posixAccount))][dc=example,dc=com]. + +Reviewed-by: Jakub Hrozek +--- + src/providers/ldap/ldap_auth.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c +index 35f16b0d4a6f8e566b0cf63b65ba46f31e7c1bcd..00d38284e428eea42254820fd08ee4fb125235a6 100644 +--- a/src/providers/ldap/ldap_auth.c ++++ b/src/providers/ldap/ldap_auth.c +@@ -361,7 +361,7 @@ shadow_fail: + + /* ==Get-User-DN========================================================== */ + struct get_user_dn_state { +- const char *username; ++ char *username; + + char *orig_dn; + }; +@@ -386,9 +386,14 @@ static struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx, + req = tevent_req_create(memctx, &state, struct get_user_dn_state); + if (!req) return NULL; + +- state->username = username; ++ ret = sss_parse_internal_fqname(state, username, ++ &state->username, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Cannot parse %s\n", username); ++ goto done; ++ } + +- ret = sss_filter_sanitize(state, username, &clean_name); ++ ret = sss_filter_sanitize(state, state->username, &clean_name); + if (ret != EOK) { + goto done; + } +-- +2.4.11 + diff --git a/SOURCES/0125-SYSDB-Fix-error-handling-in-sysdb_get_user_members_r.patch b/SOURCES/0125-SYSDB-Fix-error-handling-in-sysdb_get_user_members_r.patch new file mode 100644 index 0000000..f2581b1 --- /dev/null +++ b/SOURCES/0125-SYSDB-Fix-error-handling-in-sysdb_get_user_members_r.patch @@ -0,0 +1,50 @@ +From fde5249cee996276492886697be570b9e698e454 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Tue, 30 Aug 2016 15:37:43 +0200 +Subject: [PATCH 125/126] SYSDB: Fix error handling in + sysdb_get_user_members_recursively +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We ignored failures from sysdb_search_entry + +Reviewed-by: Petr Čech +--- + src/db/sysdb_ops.c | 3 +++ + src/db/sysdb_views.c | 5 ++++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 44fb5b70e6d33fffbca5824f831a3229254ecb57..e4c8e1e285e3bc49710f71c896ba9a30c742d4fa 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -4738,6 +4738,9 @@ errno_t sysdb_get_user_members_recursively(TALLOC_CTX *mem_ctx, + + ret = sysdb_search_entry(tmp_ctx, dom->sysdb, base_dn, LDB_SCOPE_SUBTREE, + filter, attrs, &count, &msgs); ++ if (ret != EOK) { ++ goto done; ++ } + + res = talloc_zero(tmp_ctx, struct ldb_result); + if (res == NULL) { +diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c +index 79f513d13ba41212a6cd84e1d9e609df6acba29c..9dc48f5b6c414bbc7c64bcd1fe73553f388588bd 100644 +--- a/src/db/sysdb_views.c ++++ b/src/db/sysdb_views.c +@@ -1374,7 +1374,10 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + + ret = sysdb_get_user_members_recursively(tmp_ctx, domain, obj->dn, + &res_members); +- if (ret != EOK) { ++ if (ret == ENOENT) { ++ ret = EOK; ++ goto done; ++ } else if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_get_user_members_recursively failed.\n"); + goto done; +-- +2.4.11 + diff --git a/SOURCES/0126-sdap_initgr_nested_get_membership_diff-use-fully-qua.patch b/SOURCES/0126-sdap_initgr_nested_get_membership_diff-use-fully-qua.patch new file mode 100644 index 0000000..0cb5cc4 --- /dev/null +++ b/SOURCES/0126-sdap_initgr_nested_get_membership_diff-use-fully-qua.patch @@ -0,0 +1,35 @@ +From 16196f3248a32a7bd9e395b0fdc85249ca4201d7 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 30 Aug 2016 17:30:10 +0200 +Subject: [PATCH 126/126] sdap_initgr_nested_get_membership_diff: use + fully-qualified names + +I think this is a leftover from the change to use fully-qualified names +in sysdb. To verify this you can create a nested group in IPA. Without +this patch the id command will only show the groups the user is a direct +member of. With the patch the indirect groups memberships should be +shown as well. + +https://fedorahosted.org/sssd/ticket/3163 + +Reviewed-by: Jakub Hrozek +--- + src/providers/ldap/sdap_async_initgroups.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 82c708c226bf1a645ff5a395947dfdbad71e0f1f..f9593f0dfaa2dc6e33fd6c9d1f0c9b78cad3a1d9 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -1414,7 +1414,7 @@ sdap_initgr_nested_get_membership_diff(TALLOC_CTX *mem_ctx, + group_name, parents_count); + + if (parents_count > 0) { +- ret = sysdb_attrs_primary_name_list(dom, tmp_ctx, ++ ret = sysdb_attrs_primary_fqdn_list(dom, tmp_ctx, + ldap_parentlist, + parents_count, + opts->group_map[SDAP_AT_GROUP_NAME].name, +-- +2.4.11 + diff --git a/SOURCES/0127-Revert-CONFIG-Use-default-config-when-none-provided.patch b/SOURCES/0127-Revert-CONFIG-Use-default-config-when-none-provided.patch new file mode 100644 index 0000000..623336d --- /dev/null +++ b/SOURCES/0127-Revert-CONFIG-Use-default-config-when-none-provided.patch @@ -0,0 +1,196 @@ +From 17ba1565f6dc3874c554f37ca949ad284647141d Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 7 Sep 2016 17:21:19 +0200 +Subject: [PATCH 127/127] Revert "CONFIG: Use default config when none + provided" + +This reverts commit 59744cff6edb106ae799b2321cb8731edadf409a. +--- + Makefile.am | 10 ---------- + contrib/sssd.spec.in | 3 --- + src/confdb/confdb.h | 1 - + src/confdb/confdb_setup.c | 40 ++++------------------------------------ + src/examples/sssd-shadowutils | 6 ------ + src/examples/sssd.conf | 17 ----------------- + 6 files changed, 4 insertions(+), 73 deletions(-) + delete mode 100644 src/examples/sssd-shadowutils + delete mode 100644 src/examples/sssd.conf + +diff --git a/Makefile.am b/Makefile.am +index b8cd8b64ca8a130a5dd3107e1fb1445310192059..056c73bb265523705a0de16d4d5e078f516f566f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -35,7 +35,6 @@ endif + + sssdlibexecdir = $(libexecdir)/sssd + sssdlibdir = $(libdir)/sssd +-sssddefaultconfdir = $(sssdlibdir)/conf + ldblibdir = @ldblibdir@ + if BUILD_KRB5_LOCATOR_PLUGIN + krb5plugindir = @krb5pluginpath@ +@@ -85,7 +84,6 @@ pkgconfigdir = $(libdir)/pkgconfig + krb5rcachedir = @krb5rcachedir@ + sudolibdir = @sudolibpath@ + polkitdir = @polkitdir@ +-pamconfdir = $(sysconfdir)/pam.d + systemtap_tapdir = @tapset_dir@ + + secdbpath = @secdbpath@ +@@ -464,7 +462,6 @@ AM_CPPFLAGS = \ + -DSSSDDATADIR=\"$(sssddatadir)\" \ + -DSSSD_LIBEXEC_PATH=\"$(sssdlibexecdir)\" \ + -DSSSD_CONF_DIR=\"$(sssdconfdir)\" \ +- -DSSSD_DEFAULT_CONF_DIR=\"$(sssddefaultconfdir)\" \ + -DSSS_NSS_MCACHE_DIR=\"$(mcpath)\" \ + -DSSS_NSS_SOCKET_NAME=\"$(pipepath)/nss\" \ + -DSSS_PAM_SOCKET_NAME=\"$(pipepath)/pam\" \ +@@ -1465,12 +1462,6 @@ dist_noinst_DATA += \ + src/sss_client/COPYING.LESSER \ + src/m4 + +-dist_sssddefaultconf_DATA = \ +- src/examples/sssd.conf +- +-dist_pamconf_DATA = \ +- src/examples/sssd-shadowutils +- + ###################### + # Command-line Tools # + ###################### +@@ -3972,7 +3963,6 @@ SSSD_USER_DIRS = \ + $(DESTDIR)$(gpocachepath) \ + $(DESTDIR)$(sssdconfdir) \ + $(DESTDIR)$(sssdconfdir)/conf.d \ +- $(DESTDIR)$(sssddefaultconfdir) \ + $(DESTDIR)$(logpath) \ + $(NULL) + +diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in +index cb68a73e85122b016de7df37bcf4fc232a10a2ac..4e24aa39c65ad698607615d93de8624e2e1832ff 100644 +--- a/contrib/sssd.spec.in ++++ b/contrib/sssd.spec.in +@@ -800,9 +800,6 @@ done + %dir %{_sysconfdir}/rwtab.d + %config(noreplace) %{_sysconfdir}/rwtab.d/sssd + %dir %{_datadir}/sssd +-%{_sysconfdir}/pam.d/sssd-shadowutils +-%{_libdir}/%{name}/conf/sssd.conf +- + %{_datadir}/sssd/cfg_rules.ini + %{_datadir}/sssd/sssd.api.conf + %{_datadir}/sssd/sssd.api.d +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index 72adbd80ea534eb0becd3e517c00b0c26d00444c..e8df280562d7014e0dc5d4fe5c3336eaba204537 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -40,7 +40,6 @@ + + #define CONFDB_DEFAULT_CFG_FILE_VER 2 + #define CONFDB_FILE "config.ldb" +-#define SSSD_DEFAULT_CONFIG_FILE SSSD_DEFAULT_CONF_DIR"/sssd.conf" + #define SSSD_CONFIG_FILE SSSD_CONF_DIR"/sssd.conf" + #define CONFDB_DEFAULT_CONFIG_DIR SSSD_CONF_DIR"/conf.d" + #define SSSD_MIN_ID 1 +diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c +index d6feab9000d54d2c3761de6d8e990053ade7e85f..a71d9dd1202824b3c9a7e69f1d8fa905ac1b8c02 100644 +--- a/src/confdb/confdb_setup.c ++++ b/src/confdb/confdb_setup.c +@@ -21,14 +21,12 @@ + + #include "config.h" + #include +-#include + #include "util/util.h" + #include "db/sysdb.h" + #include "confdb.h" + #include "confdb_private.h" + #include "confdb_setup.h" + #include "util/sss_ini.h" +-#include "tools/tools_util.h" + + + static int confdb_test(struct confdb_ctx *cdb) +@@ -161,41 +159,11 @@ static int confdb_init_db(const char *config_file, const char *config_dir, + DEBUG(SSSDBG_TRACE_FUNC, + "sss_ini_config_file_open failed: %s [%d]\n", strerror(ret), + ret); +- if (ret != ENOENT) { +- /* Anything other than ENOENT is unrecoverable */ +- goto done; +- } else { +- /* Copy the default configuration file to the standard location +- * and then retry +- */ +- ret = copy_file_secure(SSSD_DEFAULT_CONFIG_FILE, +- SSSD_CONFIG_FILE, +- 0600, +- getuid(), +- getgid(), +- false); +- if (ret != EOK) { +- DEBUG(SSSDBG_FATAL_FAILURE, +- "Could not copy default configuration: %s", +- sss_strerror(ret)); +- /* sss specific error denoting missing configuration file */ +- ret = ERR_MISSING_CONF; +- goto done; +- } +- +- /* Try again */ +- ret = sss_ini_config_file_open(init_data, config_file); +- if (ret != EOK) { +- DEBUG(SSSDBG_TRACE_FUNC, +- "sss_ini_config_file_open(default) failed: %s [%d]\n", +- strerror(ret), ret); +- if (ret == ENOENT) { +- /* sss specific error denoting missing configuration file */ +- ret = ERR_MISSING_CONF; +- } +- goto done; +- } ++ if (ret == ENOENT) { ++ /* sss specific error denoting missing configuration file */ ++ ret = ERR_MISSING_CONF; + } ++ goto done; + } + + ret = sss_ini_config_access_check(init_data); +diff --git a/src/examples/sssd-shadowutils b/src/examples/sssd-shadowutils +deleted file mode 100644 +index 626c7d075dfbf97dd91e259f94c6061689c83e9e..0000000000000000000000000000000000000000 +--- a/src/examples/sssd-shadowutils ++++ /dev/null +@@ -1,6 +0,0 @@ +-#%PAM-1.0 +-auth [success=done ignore=ignore default=die] pam_unix.so nullok try_first_pass +-auth required pam_deny.so +- +-account required pam_unix.so +-account required pam_permit.so +diff --git a/src/examples/sssd.conf b/src/examples/sssd.conf +deleted file mode 100644 +index a851dbb7ecd5c3220fbd6a946a6c7be2822dbd27..0000000000000000000000000000000000000000 +--- a/src/examples/sssd.conf ++++ /dev/null +@@ -1,17 +0,0 @@ +-[sssd] +-config_file_version = 2 +-services = nss, pam +-domains = shadowutils +- +-[nss] +- +-[pam] +- +-[domain/shadowutils] +-id_provider = proxy +-proxy_lib_name = files +- +-auth_provider = proxy +-proxy_pam_target = sssd-shadowutils +- +-proxy_fast_alias = True +-- +2.7.4 + diff --git a/SOURCES/0128-TOOLS-Fix-a-typo-in-groupadd.patch b/SOURCES/0128-TOOLS-Fix-a-typo-in-groupadd.patch new file mode 100644 index 0000000..4476896 --- /dev/null +++ b/SOURCES/0128-TOOLS-Fix-a-typo-in-groupadd.patch @@ -0,0 +1,33 @@ +From bac0f5a1d74d2dbedc5873592edbbdd791db2ede Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 6 Sep 2016 12:13:08 +0200 +Subject: [PATCH 128/135] TOOLS: Fix a typo in groupadd() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/3173 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 6be723a089a1e07a1cd19b4fa53fd142c13f0c69) +--- + src/tools/sss_sync_ops.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tools/sss_sync_ops.c b/src/tools/sss_sync_ops.c +index a23a0b8c30366d2fb68554bfed184b8fce675e2b..39ef5bec96bd3942da8a8adfd21c99b03a77e551 100644 +--- a/src/tools/sss_sync_ops.c ++++ b/src/tools/sss_sync_ops.c +@@ -657,7 +657,7 @@ int groupadd(struct ops_ctx *data) + int ret; + + data->sysdb_fqname = sss_create_internal_fqname(data, +- data->sysdb_fqname, ++ data->name, + data->domain->name); + if (data->sysdb_fqname == NULL) { + return ENOMEM; +-- +2.7.4 + diff --git a/SOURCES/0129-TOOLS-sss_groupshow-did-not-work.patch b/SOURCES/0129-TOOLS-sss_groupshow-did-not-work.patch new file mode 100644 index 0000000..7179654 --- /dev/null +++ b/SOURCES/0129-TOOLS-sss_groupshow-did-not-work.patch @@ -0,0 +1,60 @@ +From 7d8269e8a885cc0344dc78951d2880edac32a02c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Tue, 6 Sep 2016 13:46:53 +0200 +Subject: [PATCH 129/135] TOOLS: sss_groupshow did not work +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sss_groupshow used shortname to search +in sysdb database. We have to u e sysdb_fqname +(aka internal_fqname) format for all sysdb +oprations. + +Resolves: +https://fedorahosted.org/sssd/ticket/3175 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 5210c5d3a5a83b5d08396ee23d88f6ba0994097d) +--- + src/tools/sss_groupshow.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/tools/sss_groupshow.c b/src/tools/sss_groupshow.c +index 41d7475cef1093a4cb214ec4b017db59e6c26fe2..5870cc802c70366c47a0d30cb0d9795cf6035bc5 100644 +--- a/src/tools/sss_groupshow.c ++++ b/src/tools/sss_groupshow.c +@@ -318,7 +318,7 @@ int group_show(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, + bool recursive, +- const char *name, ++ const char *shortname, + struct group_info **res) + { + struct group_info *root; +@@ -326,11 +326,20 @@ int group_show(TALLOC_CTX *mem_ctx, + struct ldb_message *msg = NULL; + const char **group_members = NULL; + int nmembers = 0; ++ char *sysdb_fqname = NULL; + int ret; + int i; + ++ sysdb_fqname = sss_create_internal_fqname(mem_ctx, ++ shortname, ++ domain->name); ++ if (sysdb_fqname == NULL) { ++ return ENOMEM; ++ } ++ + /* First, search for the root group */ +- ret = sysdb_search_group_by_name(mem_ctx, domain, name, attrs, &msg); ++ ret = sysdb_search_group_by_name(mem_ctx, domain, sysdb_fqname, attrs, ++ &msg); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, + "Search failed: %s (%d)\n", strerror(ret), ret); +-- +2.7.4 + diff --git a/SOURCES/0130-TESTS-sss_groupadd-groupshow-regressions.patch b/SOURCES/0130-TESTS-sss_groupadd-groupshow-regressions.patch new file mode 100644 index 0000000..11e71cf --- /dev/null +++ b/SOURCES/0130-TESTS-sss_groupadd-groupshow-regressions.patch @@ -0,0 +1,78 @@ +From cb355831d3f128688b33b9099ec047f8ef6a3234 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Tue, 6 Sep 2016 17:37:14 +0200 +Subject: [PATCH 130/135] TESTS: sss_groupadd/groupshow regressions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds regression CI test for ticket #3173 and #3175. + +Resolves: +https://fedorahosted.org/sssd/ticket/3173 +https://fedorahosted.org/sssd/ticket/3175 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 20c2d76d9430a1fc069531ff537df046a74c8f61) +--- + src/tests/intg/test_local_domain.py | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +diff --git a/src/tests/intg/test_local_domain.py b/src/tests/intg/test_local_domain.py +index 31834b5b9ab93329ac5eb76e3676d6f89f5b996e..56e3812b113b36301d1ec6049e5a1210d3070442 100644 +--- a/src/tests/intg/test_local_domain.py ++++ b/src/tests/intg/test_local_domain.py +@@ -19,11 +19,13 @@ + import os + import stat + import pwd ++import grp + import time + import config + import signal + import subprocess + import pytest ++import ent + from util import unindent + + +@@ -90,6 +92,11 @@ def assert_nonexistent_user(name): + pwd.getpwnam(name) + + ++def assert_nonexistent_group(name): ++ with pytest.raises(KeyError): ++ grp.getgrnam(name) ++ ++ + def test_wrong_LC_ALL(local_domain_only): + """ + Regression test for ticket +@@ -106,4 +113,23 @@ def test_wrong_LC_ALL(local_domain_only): + # sss_userdel must remove the user despite wrong LC_ALL + subprocess.check_call(["sss_userdel", "foo", "-R"]) + assert_nonexistent_user("foo") +- os.environ["LC_LOCAL"] = oldvalue ++ os.environ["LC_ALL"] = oldvalue ++ ++ ++def test_sss_group_add_show_del(local_domain_only): ++ """ ++ Regression test for tickets ++ https://fedorahosted.org/sssd/ticket/3173 ++ https://fedorahosted.org/sssd/ticket/3175 ++ """ ++ ++ subprocess.check_call(["sss_groupadd", "foo", "-g", "10001"]) ++ ++ "This should not raise KeyError" ++ ent.assert_group_by_name("foo", dict(name="foo", gid=10001)) ++ ++ "sss_grupshow should return 0 with existing group name" ++ subprocess.check_call(["sss_groupshow", "foo"]) ++ ++ subprocess.check_call(["sss_groupdel", "foo"]) ++ assert_nonexistent_group("foo") +-- +2.7.4 + diff --git a/SOURCES/0131-TOOLS-use-internal-fqdn-for-DN.patch b/SOURCES/0131-TOOLS-use-internal-fqdn-for-DN.patch new file mode 100644 index 0000000..9b77d88 --- /dev/null +++ b/SOURCES/0131-TOOLS-use-internal-fqdn-for-DN.patch @@ -0,0 +1,57 @@ +From bfbad5b20c8a34b545cea8df6c937125edf0e42c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 7 Sep 2016 10:58:25 +0200 +Subject: [PATCH 131/135] TOOLS: use internal fqdn for DN +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use internal fqdn when creating sysdb group dn. + +Resolves: +https://fedorahosted.org/sssd/ticket/3178 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 5e2142b66589e5e50cb404fc972ed5418bbaa772) +--- + src/tools/sss_sync_ops.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/tools/sss_sync_ops.c b/src/tools/sss_sync_ops.c +index 39ef5bec96bd3942da8a8adfd21c99b03a77e551..a0291baeada49b9f21e040a54e303214d5a46332 100644 +--- a/src/tools/sss_sync_ops.c ++++ b/src/tools/sss_sync_ops.c +@@ -137,6 +137,7 @@ static int mod_groups_member(struct sss_domain_info *dom, + struct ldb_dn *parent_dn; + int ret; + int i; ++ char *grp_sysdb_fqname = NULL; + + tmpctx = talloc_new(NULL); + if (!tmpctx) { +@@ -145,13 +146,21 @@ static int mod_groups_member(struct sss_domain_info *dom, + + /* FIXME: add transaction around loop */ + for (i = 0; grouplist[i]; i++) { ++ grp_sysdb_fqname = sss_create_internal_fqname(tmpctx, grouplist[i], ++ dom->name); ++ if (grp_sysdb_fqname == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } + +- parent_dn = sysdb_group_dn(tmpctx, dom, grouplist[i]); ++ parent_dn = sysdb_group_dn(tmpctx, dom, grp_sysdb_fqname); + if (!parent_dn) { + ret = ENOMEM; + goto done; + } + ++ talloc_free(grp_sysdb_fqname); ++ + ret = sysdb_mod_group_member(dom, member_dn, parent_dn, optype); + if (ret) { + goto done; +-- +2.7.4 + diff --git a/SOURCES/0132-TESTS-Test-for-sss_user-groupmod-a.patch b/SOURCES/0132-TESTS-Test-for-sss_user-groupmod-a.patch new file mode 100644 index 0000000..af34532 --- /dev/null +++ b/SOURCES/0132-TESTS-Test-for-sss_user-groupmod-a.patch @@ -0,0 +1,66 @@ +From 2eb23ddb5f03a71a329bf4874194455ff87e1806 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 7 Sep 2016 13:08:59 +0200 +Subject: [PATCH 132/135] TESTS: Test for sss_user/groupmod -a +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Regression tests for ticket #3178. + +Resolves: +https://fedorahosted.org/sssd/ticket/3178 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 7fa4964d84f41bd80a6d971ffaeef87a7c2f19be) +--- + src/tests/intg/test_local_domain.py | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/src/tests/intg/test_local_domain.py b/src/tests/intg/test_local_domain.py +index 56e3812b113b36301d1ec6049e5a1210d3070442..5e3e3d4d1cdc6db5d68a6e5b9d96d94c2c694b14 100644 +--- a/src/tests/intg/test_local_domain.py ++++ b/src/tests/intg/test_local_domain.py +@@ -133,3 +133,39 @@ def test_sss_group_add_show_del(local_domain_only): + + subprocess.check_call(["sss_groupdel", "foo"]) + assert_nonexistent_group("foo") ++ ++ ++def test_add_local_user_to_local_group(local_domain_only): ++ """ ++ Regression test for ticket ++ https://fedorahosted.org/sssd/ticket/3178 ++ """ ++ subprocess.check_call(["sss_groupadd", "-g", "10009", "group10009"]) ++ subprocess.check_call(["sss_useradd", "-u", "10009", "-M", "user10009"]) ++ subprocess.check_call(["sss_usermod", "-a", "group10009", "user10009"]) ++ ++ ent.assert_group_by_name( ++ "group10009", ++ dict(name="group10009", passwd="*", gid=10009, ++ mem=ent.contains_only("user10009"))) ++ ++ ++def test_add_local_group_to_local_group(local_domain_only): ++ """ ++ Regression test for tickets ++ https://fedorahosted.org/sssd/ticket/3178 ++ """ ++ subprocess.check_call(["sss_groupadd", "-g", "10009", "group_child"]) ++ subprocess.check_call(["sss_useradd", "-u", "10009", "-M", "user_child"]) ++ subprocess.check_call(["sss_usermod", "-a", "group_child", "user_child"]) ++ ++ subprocess.check_call(["sss_groupadd", "-g", "10008", "group_parent"]) ++ subprocess.check_call( ++ ["sss_groupmod", "-a", "group_parent", "group_child"]) ++ ++ # User from child_group is member of parent_group, so child_group's ++ # member must be also parent_group's member ++ ent.assert_group_by_name( ++ "group_parent", ++ dict(name="group_parent", passwd="*", gid=10008, ++ mem=ent.contains_only("user_child"))) +-- +2.7.4 + diff --git a/SOURCES/0133-TOOLS-sss_mc_refresh_nested_group-short-fqname-usage.patch b/SOURCES/0133-TOOLS-sss_mc_refresh_nested_group-short-fqname-usage.patch new file mode 100644 index 0000000..6f8b54e --- /dev/null +++ b/SOURCES/0133-TOOLS-sss_mc_refresh_nested_group-short-fqname-usage.patch @@ -0,0 +1,137 @@ +From 1a1aaf46d1ee3ae4c9346c5c492520257c7c1b42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 7 Sep 2016 14:43:13 +0200 +Subject: [PATCH 133/135] TOOLS: sss_mc_refresh_nested_group short/fqname usage +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We use shortname to refresh memory cache, but in case of nested groups, +we used internal_fqname to refresh parent groups. + +We also wrongly used the shortname for sysdb_search operation. +Which caused error message to be printed when sss_usermod -a or +sss_groupmod -a where called. + +Reviewed-by: Lukáš Slebodník +--- + src/tools/tools_mc_util.c | 66 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 47 insertions(+), 19 deletions(-) + +diff --git a/src/tools/tools_mc_util.c b/src/tools/tools_mc_util.c +index 2516a1981ddd965d4cae8c469ed79aaef8fa7193..716e3760f67d958f2139adbb49998d9e352d23f4 100644 +--- a/src/tools/tools_mc_util.c ++++ b/src/tools/tools_mc_util.c +@@ -293,62 +293,90 @@ errno_t sss_mc_refresh_group(const char *groupname) + return sss_mc_refresh_ent(groupname, SSS_TOOLS_GROUP); + } + +-errno_t sss_mc_refresh_nested_group(struct tools_ctx *tctx, +- const char *name) ++static errno_t sss_mc_refresh_nested_group(struct tools_ctx *tctx, ++ const char *shortname) + { + errno_t ret; +- struct ldb_message *msg; ++ struct ldb_message *msg = NULL; + struct ldb_message_element *el; + const char *attrs[] = { SYSDB_MEMBEROF, + SYSDB_NAME, + NULL }; + size_t i; +- char *parent_name; ++ char *parent_internal_name; ++ char *parent_outname; ++ char *internal_name; ++ TALLOC_CTX *tmpctx; + +- ret = sss_mc_refresh_group(name); ++ tmpctx = talloc_new(tctx); ++ if (tmpctx == NULL) { ++ return ENOMEM; ++ } ++ ++ internal_name = sss_create_internal_fqname(tmpctx, shortname, ++ tctx->local->name); ++ if (internal_name == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = sss_mc_refresh_group(shortname); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, +- "Cannot refresh group %s from memory cache\n", name); ++ "Cannot refresh group %s from memory cache\n", shortname); + /* try to carry on */ + } + +- ret = sysdb_search_group_by_name(tctx, tctx->local, name, attrs, &msg); ++ ret = sysdb_search_group_by_name(tmpctx, tctx->local, internal_name, attrs, ++ &msg); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, + "Search failed: %s (%d)\n", strerror(ret), ret); +- return ret; ++ goto done; + } + + el = ldb_msg_find_element(msg, SYSDB_MEMBEROF); + if (!el || el->num_values == 0) { +- DEBUG(SSSDBG_TRACE_INTERNAL, "Group %s has no parents\n", name); +- talloc_free(msg); +- return EOK; ++ DEBUG(SSSDBG_TRACE_INTERNAL, "Group %s has no parents\n", ++ internal_name); ++ ret = EOK; ++ goto done; + } + + /* This group is nested. We need to invalidate all its parents, too */ + for (i=0; i < el->num_values; i++) { +- ret = sysdb_group_dn_name(tctx->sysdb, tctx, ++ ret = sysdb_group_dn_name(tctx->sysdb, tmpctx, + (const char *) el->values[i].data, +- &parent_name); ++ &parent_internal_name); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Malformed DN [%s]? Skipping\n", + (const char *) el->values[i].data); +- talloc_free(parent_name); ++ talloc_free(parent_internal_name); + continue; + } + +- ret = sss_mc_refresh_group(parent_name); +- talloc_free(parent_name); ++ parent_outname = sss_output_name(tmpctx, parent_internal_name, ++ tctx->local->case_preserve, 0); ++ if (parent_outname == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = sss_mc_refresh_group(parent_outname); ++ talloc_free(parent_internal_name); ++ talloc_free(parent_outname); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, +- "Cannot refresh group %s from memory cache\n", name); ++ "Cannot refresh group %s from memory cache\n", parent_outname); + /* try to carry on */ + } + } + +- talloc_free(msg); +- return EOK; ++ ret = EOK; ++ ++done: ++ talloc_free(tmpctx); ++ return ret; + } + + errno_t sss_mc_refresh_grouplist(struct tools_ctx *tctx, +-- +2.7.4 + diff --git a/SOURCES/0134-TESTS-Add-FQDN-variants-for-some-tests.patch b/SOURCES/0134-TESTS-Add-FQDN-variants-for-some-tests.patch new file mode 100644 index 0000000..109d2ef --- /dev/null +++ b/SOURCES/0134-TESTS-Add-FQDN-variants-for-some-tests.patch @@ -0,0 +1,116 @@ +From 28db1765c40137e9452b4aa27281a1deb25d1d36 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 7 Sep 2016 15:00:12 +0200 +Subject: [PATCH 134/135] TESTS: Add FQDN variants for some tests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Adds FQDN variants of some already existing tests. + +Reviewed-by: Lukáš Slebodník +--- + src/tests/intg/test_local_domain.py | 83 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 83 insertions(+) + +diff --git a/src/tests/intg/test_local_domain.py b/src/tests/intg/test_local_domain.py +index 5e3e3d4d1cdc6db5d68a6e5b9d96d94c2c694b14..b34e4a3d31cdbc1dc257d8fffcf0f5a07803b20c 100644 +--- a/src/tests/intg/test_local_domain.py ++++ b/src/tests/intg/test_local_domain.py +@@ -87,6 +87,27 @@ def local_domain_only(request): + return None + + ++@pytest.fixture ++def local_domain_only_fqdn(request): ++ conf = unindent("""\ ++ [sssd] ++ domains = LOCAL ++ services = nss ++ ++ [nss] ++ memcache_timeout = 0 ++ ++ [domain/LOCAL] ++ id_provider = local ++ min_id = 10000 ++ max_id = 20000 ++ use_fully_qualified_names = True ++ """).format(**locals()) ++ create_conf_fixture(request, conf) ++ create_sssd_fixture(request) ++ return None ++ ++ + def assert_nonexistent_user(name): + with pytest.raises(KeyError): + pwd.getpwnam(name) +@@ -169,3 +190,65 @@ def test_add_local_group_to_local_group(local_domain_only): + "group_parent", + dict(name="group_parent", passwd="*", gid=10008, + mem=ent.contains_only("user_child"))) ++ ++ ++def test_sss_group_add_show_del_fqdn(local_domain_only_fqdn): ++ """ ++ Regression test for tickets ++ https://fedorahosted.org/sssd/ticket/3173 ++ https://fedorahosted.org/sssd/ticket/3175 ++ """ ++ ++ subprocess.check_call(["sss_groupadd", "foo@LOCAL", "-g", "10001"]) ++ ++ "This should not raise KeyError" ++ ent.assert_group_by_name("foo@LOCAL", dict(name="foo@LOCAL", gid=10001)) ++ ++ "sss_grupshow should return 0 with existing group name" ++ subprocess.check_call(["sss_groupshow", "foo@LOCAL"]) ++ ++ subprocess.check_call(["sss_groupdel", "foo@LOCAL"]) ++ assert_nonexistent_group("foo@LOCAL") ++ ++ ++def test_add_local_user_to_local_group_fqdn(local_domain_only_fqdn): ++ """ ++ Regression test for ticket ++ https://fedorahosted.org/sssd/ticket/3178 ++ """ ++ subprocess.check_call( ++ ["sss_groupadd", "-g", "10009", "group10009@LOCAL"]) ++ subprocess.check_call( ++ ["sss_useradd", "-u", "10009", "-M", "user10009@LOCAL"]) ++ subprocess.check_call( ++ ["sss_usermod", "-a", "group10009@LOCAL", "user10009@LOCAL"]) ++ ++ ent.assert_group_by_name( ++ "group10009@LOCAL", ++ dict(name="group10009@LOCAL", passwd="*", gid=10009, ++ mem=ent.contains_only("user10009@LOCAL"))) ++ ++ ++def test_add_local_group_to_local_group_fqdn(local_domain_only_fqdn): ++ """ ++ Regression test for tickets ++ https://fedorahosted.org/sssd/ticket/3178 ++ """ ++ subprocess.check_call( ++ ["sss_groupadd", "-g", "10009", "group_child@LOCAL"]) ++ subprocess.check_call( ++ ["sss_useradd", "-u", "10009", "-M", "user_child@LOCAL"]) ++ subprocess.check_call( ++ ["sss_usermod", "-a", "group_child@LOCAL", "user_child@LOCAL"]) ++ ++ subprocess.check_call( ++ ["sss_groupadd", "-g", "10008", "group_parent@LOCAL"]) ++ subprocess.check_call( ++ ["sss_groupmod", "-a", "group_parent@LOCAL", "group_child@LOCAL"]) ++ ++ # User from child_group is member of parent_group, so child_group's ++ # member must be also parent_group's member ++ ent.assert_group_by_name( ++ "group_parent@LOCAL", ++ dict(name="group_parent@LOCAL", passwd="*", gid=10008, ++ mem=ent.contains_only("user_child@LOCAL"))) +-- +2.7.4 + diff --git a/SOURCES/0135-KRB5-Send-the-output-username-not-internal-fqname-to.patch b/SOURCES/0135-KRB5-Send-the-output-username-not-internal-fqname-to.patch new file mode 100644 index 0000000..a3368d4 --- /dev/null +++ b/SOURCES/0135-KRB5-Send-the-output-username-not-internal-fqname-to.patch @@ -0,0 +1,155 @@ +From 0f0480dd1c227a841542d621a778e23cf637a644 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 7 Sep 2016 12:07:36 +0200 +Subject: [PATCH 135/135] KRB5: Send the output username, not internal fqname + to krb5_child +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +krb5_child calls krb5_kuserok() during the access phase which checks if +a particular user is allowed to authenticate as a particular principal. +We used to pass the internal fqname to krb5_kuserok() which broke the +functionality and all users were denied access. + +This patch changes that to send the 'output' username to krb5_child, +because that's the username the system receives through getpwnam() or +getpwuid() anyway. The patch also adds a new structure member fo the +krb5child_req structure to avoid reusing the pd->user variable but have +an explicit one that serves as the input for the child process. + +Resolves: +https://fedorahosted.org/sssd/ticket/3172 + +Reviewed-by: Lukáš Slebodník +--- + src/providers/krb5/krb5_access.c | 10 ++++++++-- + src/providers/krb5/krb5_auth.c | 18 ++++++++++++++---- + src/providers/krb5/krb5_auth.h | 9 ++++++--- + src/providers/krb5/krb5_child_handler.c | 4 ++-- + 4 files changed, 30 insertions(+), 11 deletions(-) + +diff --git a/src/providers/krb5/krb5_access.c b/src/providers/krb5/krb5_access.c +index 3afb90150d77ef4ab2c1b5b79abb95d68eb131f6..be9068c0f9180f8de0de259aae368534effaf7fb 100644 +--- a/src/providers/krb5/krb5_access.c ++++ b/src/providers/krb5/krb5_access.c +@@ -51,6 +51,7 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, + int ret; + const char **attrs; + struct ldb_result *res; ++ struct sss_domain_info *dom; + + req = tevent_req_create(mem_ctx, &state, struct krb5_access_state); + if (req == NULL) { +@@ -64,8 +65,13 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, + state->krb5_ctx = krb5_ctx; + state->access_allowed = false; + +- ret = krb5_setup(state, pd, krb5_ctx, be_ctx->domain->case_sensitive, +- &state->kr); ++ ret = get_domain_or_subdomain(be_ctx, pd->domain, &dom); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "get_domain_or_subdomain failed.\n"); ++ goto done; ++ } ++ ++ ret = krb5_setup(state, pd, dom, krb5_ctx, &state->kr); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n"); + goto done; +diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c +index dabf55cf24a8afda16fee6697120c7c6f088b796..f0f2280022a3ee951ccfa0040b616c48c3b25706 100644 +--- a/src/providers/krb5/krb5_auth.c ++++ b/src/providers/krb5/krb5_auth.c +@@ -174,8 +174,10 @@ done: + return ret; + } + +-errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, +- struct krb5_ctx *krb5_ctx, bool cs, ++errno_t krb5_setup(TALLOC_CTX *mem_ctx, ++ struct pam_data *pd, ++ struct sss_domain_info *dom, ++ struct krb5_ctx *krb5_ctx, + struct krb5child_req **_krb5_req) + { + struct krb5child_req *kr; +@@ -201,13 +203,21 @@ errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, + kr->krb5_ctx = krb5_ctx; + + ret = get_krb_primary(krb5_ctx->name_to_primary, +- pd->user, cs, &mapped_name); ++ pd->user, dom->case_sensitive, &mapped_name); + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "Setting mapped name to: %s\n", mapped_name); + kr->user = mapped_name; ++ kr->kuserok_user = mapped_name; + } else if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_ALL, "No mapping for: %s\n", pd->user); + kr->user = pd->user; ++ ++ kr->kuserok_user = sss_output_name(kr, kr->user, ++ dom->case_sensitive, 0); ++ if (kr->kuserok_user == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } + } else { + DEBUG(SSSDBG_CRIT_FAILURE, "get_krb_primary failed - %s:[%d]\n", + sss_strerror(ret), ret); +@@ -534,7 +544,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, + attrs[6] = SYSDB_AUTH_TYPE; + attrs[7] = NULL; + +- ret = krb5_setup(state, pd, krb5_ctx, state->domain->case_sensitive, ++ ret = krb5_setup(state, pd, state->domain, krb5_ctx, + &state->kr); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "krb5_setup failed.\n"); +diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h +index dbad061f0203b6383daeeab506bf9950d892ea4b..11bb595833269177b7e2c5fc6372d6a6fb6d93d2 100644 +--- a/src/providers/krb5/krb5_auth.h ++++ b/src/providers/krb5/krb5_auth.h +@@ -57,11 +57,14 @@ struct krb5child_req { + bool send_pac; + + const char *user; ++ const char *kuserok_user; + }; + +-errno_t krb5_setup(TALLOC_CTX *mem_ctx, struct pam_data *pd, +- struct krb5_ctx *krb5_ctx, bool case_sensitive, +- struct krb5child_req **krb5_req); ++errno_t krb5_setup(TALLOC_CTX *mem_ctx, ++ struct pam_data *pd, ++ struct sss_domain_info *dom, ++ struct krb5_ctx *krb5_ctx, ++ struct krb5child_req **_krb5_req); + + struct tevent_req * + krb5_pam_handler_send(TALLOC_CTX *mem_ctx, +diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c +index 09a1e5f59494a5c07d5c9eefb94919ca9389cb27..1eec7261f00976b3725fee9323755edecd5409a5 100644 +--- a/src/providers/krb5/krb5_child_handler.c ++++ b/src/providers/krb5/krb5_child_handler.c +@@ -161,7 +161,7 @@ static errno_t create_send_buffer(struct krb5child_req *kr, + } + + if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) { +- username_len = strlen(kr->pd->user); ++ username_len = strlen(kr->kuserok_user); + buf->size += sizeof(uint32_t) + username_len; + } + +@@ -217,7 +217,7 @@ static errno_t create_send_buffer(struct krb5child_req *kr, + + if (kr->pd->cmd == SSS_PAM_ACCT_MGMT) { + SAFEALIGN_SET_UINT32(&buf->data[rp], username_len, &rp); +- safealign_memcpy(&buf->data[rp], kr->pd->user, username_len, &rp); ++ safealign_memcpy(&buf->data[rp], kr->kuserok_user, username_len, &rp); + } + + *io_buf = buf; +-- +2.7.4 + diff --git a/SOURCES/0136-LDAP-Return-partial-results-from-adminlimit-exceeded.patch b/SOURCES/0136-LDAP-Return-partial-results-from-adminlimit-exceeded.patch new file mode 100644 index 0000000..806432b --- /dev/null +++ b/SOURCES/0136-LDAP-Return-partial-results-from-adminlimit-exceeded.patch @@ -0,0 +1,42 @@ +From abbbcb79ff0c5b82d7a3acb324c3d44f87479837 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 12 Sep 2016 17:36:09 +0200 +Subject: [PATCH 136/140] LDAP: Return partial results from adminlimit exceeded +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: + https://fedorahosted.org/sssd/ticket/3185 + +Since commit c420ce830ac0b0b288a2a887ec2cfce5c748018c we try to move to +the next server on any error on the connection, which in case there is +only one server sends SSSD offline. + +It's more graceful to try to process the results, same as we already do +with sizelimit exceeded. + +Reviewed-by: Michal Židek +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 3319d964721396c07daba383ded6aaaf33ed6e3b) +--- + src/providers/ldap/sdap_async.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c +index 4195ba95d911f3956f8cca665310b4b92091e6cd..b8e04b9d8464d7c2c681080cba456c34b93b923a 100644 +--- a/src/providers/ldap/sdap_async.c ++++ b/src/providers/ldap/sdap_async.c +@@ -1526,7 +1526,8 @@ static void sdap_get_generic_op_finished(struct sdap_op *op, + sss_ldap_err2string(result), result, + errmsg ? errmsg : "no errmsg set"); + +- if (result == LDAP_SIZELIMIT_EXCEEDED) { ++ if (result == LDAP_SIZELIMIT_EXCEEDED ++ || result == LDAP_ADMINLIMIT_EXCEEDED) { + /* Try to return what we've got */ + + if ( ! (state->flags & SDAP_SRCH_FLG_SIZELIMIT_SILENT)) { +-- +2.7.4 + diff --git a/SOURCES/0137-TOOLS-sss_groupshow-fails-to-show-MPG.patch b/SOURCES/0137-TOOLS-sss_groupshow-fails-to-show-MPG.patch new file mode 100644 index 0000000..285ef6e --- /dev/null +++ b/SOURCES/0137-TOOLS-sss_groupshow-fails-to-show-MPG.patch @@ -0,0 +1,60 @@ +From 8125ddd951a9e66fb3b11e16489e003d32ce4890 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 12 Sep 2016 19:22:56 +0200 +Subject: [PATCH 137/140] TOOLS: sss_groupshow fails to show MPG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The MPG search uses it's own search function +that used sysdb operation with shortname, +but it expects internal fqname. + +Resolves: +https://fedorahosted.org/sssd/ticket/3184 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 812bed08943df8bf3fd1ff9eabcaf5bedc635c92) +--- + src/tools/sss_groupshow.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/src/tools/sss_groupshow.c b/src/tools/sss_groupshow.c +index 5870cc802c70366c47a0d30cb0d9795cf6035bc5..00f6f12939b6bef2dd10085f8cf99304e87f1211 100644 +--- a/src/tools/sss_groupshow.c ++++ b/src/tools/sss_groupshow.c +@@ -553,13 +553,14 @@ int group_show_recurse(TALLOC_CTX *mem_ctx, + + static int group_show_mpg(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, +- const char *name, ++ const char *shortname, + struct group_info **res) + { + const char *attrs[] = GROUP_SHOW_MPG_ATTRS; + struct ldb_message *msg; + struct group_info *info; + int ret; ++ char *sysdb_fqname; + + info = talloc_zero(mem_ctx, struct group_info); + if (!info) { +@@ -567,7 +568,14 @@ static int group_show_mpg(TALLOC_CTX *mem_ctx, + goto fail; + } + +- ret = sysdb_search_user_by_name(info, domain, name, attrs, &msg); ++ sysdb_fqname = sss_create_internal_fqname(mem_ctx, ++ shortname, ++ domain->name); ++ if (sysdb_fqname == NULL) { ++ return ENOMEM; ++ } ++ ++ ret = sysdb_search_user_by_name(info, domain, sysdb_fqname, attrs, &msg); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, + "Search failed: %s (%d)\n", strerror(ret), ret); +-- +2.7.4 + diff --git a/SOURCES/0138-TESTS-sss_groupshow-with-MPG.patch b/SOURCES/0138-TESTS-sss_groupshow-with-MPG.patch new file mode 100644 index 0000000..e273877 --- /dev/null +++ b/SOURCES/0138-TESTS-sss_groupshow-with-MPG.patch @@ -0,0 +1,55 @@ +From 6eb330b5370db40a55d18de2d932601d6b3128b2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 12 Sep 2016 19:25:13 +0200 +Subject: [PATCH 138/140] TESTS: sss_groupshow with MPG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Regression test for ticket #3184 + +Resolves: +https://fedorahosted.org/sssd/ticket/3184 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit bb14556c1df503314644fc424fbbf95759791db9) +--- + src/tests/intg/test_local_domain.py | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/src/tests/intg/test_local_domain.py b/src/tests/intg/test_local_domain.py +index b34e4a3d31cdbc1dc257d8fffcf0f5a07803b20c..8e1d6fb2b69f5e6e033ae06d4bd52cc88e54872b 100644 +--- a/src/tests/intg/test_local_domain.py ++++ b/src/tests/intg/test_local_domain.py +@@ -118,6 +118,28 @@ def assert_nonexistent_group(name): + grp.getgrnam(name) + + ++def test_groupshow_mpg(local_domain_only): ++ """ ++ Regression test for ticket ++ https://fedorahosted.org/sssd/ticket/3184 ++ """ ++ subprocess.check_call(["sss_useradd", "foo", "-M"]) ++ ++ # The user's mpg has to be found (should return 0) ++ subprocess.check_call(["sss_groupshow", "foo"]) ++ ++ ++def test_groupshow_mpg_fqdn(local_domain_only_fqdn): ++ """ ++ Regression test for ticket (fq variant) ++ https://fedorahosted.org/sssd/ticket/3184 ++ """ ++ subprocess.check_call(["sss_useradd", "foo@LOCAL", "-M"]) ++ ++ # The user's mpg has to be found (should return 0) ++ subprocess.check_call(["sss_groupshow", "foo@LOCAL"]) ++ ++ + def test_wrong_LC_ALL(local_domain_only): + """ + Regression test for ticket +-- +2.7.4 + diff --git a/SOURCES/0139-TOOLS-sss_override-without-name-override.patch b/SOURCES/0139-TOOLS-sss_override-without-name-override.patch new file mode 100644 index 0000000..b9114ef --- /dev/null +++ b/SOURCES/0139-TOOLS-sss_override-without-name-override.patch @@ -0,0 +1,67 @@ +From e56e1396bab69d9498f4ec6a36e9e228ded90116 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 7 Sep 2016 17:09:53 +0200 +Subject: [PATCH 139/140] TOOLS: sss_override without name override +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +sss_override failed to export user/group overrides +if user had no overrides for name. + +Resolves: +https://fedorahosted.org/sssd/ticket/3179 + +Reviewed-by: Pavel Březina +(cherry picked from commit 07e7683f5a86991feaa764e2055116554ada1b93) +--- + src/tools/sss_override.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c +index d41da52e69acdb67b5a6d624254e3b89a8aa27b8..212bf9ab84b20d4777fc2601359fad58596bb7c4 100644 +--- a/src/tools/sss_override.c ++++ b/src/tools/sss_override.c +@@ -1159,12 +1159,14 @@ list_user_overrides(TALLOC_CTX *mem_ctx, + } + + fqname = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL); +- ret = sss_parse_internal_fqname(tmp_ctx, fqname, &name, NULL); +- if (ret != EOK) { +- ret = ERR_WRONG_NAME_FORMAT; +- goto done; ++ if (fqname != NULL) { ++ ret = sss_parse_internal_fqname(tmp_ctx, fqname, &name, NULL); ++ if (ret != EOK) { ++ ret = ERR_WRONG_NAME_FORMAT; ++ goto done; ++ } ++ objs[i].name = talloc_steal(objs, name); + } +- objs[i].name = talloc_steal(objs, name); + + objs[i].uid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_UIDNUM, 0); + objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0); +@@ -1248,12 +1250,14 @@ list_group_overrides(TALLOC_CTX *mem_ctx, + talloc_steal(objs, objs[i].orig_name); + + fqname = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL); +- ret = sss_parse_internal_fqname(tmp_ctx, fqname, &name, NULL); +- if (ret != EOK) { +- ret = ERR_WRONG_NAME_FORMAT; +- goto done; ++ if (fqname != NULL) { ++ ret = sss_parse_internal_fqname(tmp_ctx, fqname, &name, NULL); ++ if (ret != EOK) { ++ ret = ERR_WRONG_NAME_FORMAT; ++ goto done; ++ } ++ objs[i].name = talloc_steal(objs, name); + } +- objs[i].name = talloc_steal(objs, name); + + objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0); + } +-- +2.7.4 + diff --git a/SOURCES/0140-TEST-Add-regression-test-for-ticket-3179.patch b/SOURCES/0140-TEST-Add-regression-test-for-ticket-3179.patch new file mode 100644 index 0000000..18f80b9 --- /dev/null +++ b/SOURCES/0140-TEST-Add-regression-test-for-ticket-3179.patch @@ -0,0 +1,203 @@ +From d3e93eafcf3e484ee8ec092c59914018b42ea4ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Wed, 7 Sep 2016 18:23:16 +0200 +Subject: [PATCH 140/140] TEST: Add regression test for ticket #3179 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/3179 + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Pavel Březina +(cherry picked from commit 1c72723cde8bea0d390b928c7cd29e48e7a7deab) +--- + src/tests/intg/ldap_local_override_test.py | 126 ++++++++++++++++++++++++++--- + 1 file changed, 114 insertions(+), 12 deletions(-) + +diff --git a/src/tests/intg/ldap_local_override_test.py b/src/tests/intg/ldap_local_override_test.py +index 046535c7727d0f2271f4b974f68ba0722222982b..832849713e1185e836f3dd6decf2deac79ab98dd 100644 +--- a/src/tests/intg/ldap_local_override_test.py ++++ b/src/tests/intg/ldap_local_override_test.py +@@ -205,27 +205,38 @@ def assert_user_default(): + ent.assert_passwd_by_name('user2@LDAP', user2) + + +-def assert_user_overriden(): ++def assert_user_overriden(override_name=True): + +- user1 = dict(name='ov_user1', passwd='*', uid=10010, gid=20010, ++ if override_name: ++ name1 = "ov_user1" ++ name2 = "ov_user2" ++ else: ++ name1 = "user1" ++ name2 = "user2" ++ ++ user1 = dict(name=name1, passwd='*', uid=10010, gid=20010, + gecos='Overriden User 1', + dir='/home/ov/user1', + shell='/bin/ov_user1_shell') + +- user2 = dict(name='ov_user2', passwd='*', uid=10020, gid=20020, ++ user2 = dict(name=name2, passwd='*', uid=10020, gid=20020, + gecos='Overriden User 2', + dir='/home/ov/user2', + shell='/bin/ov_user2_shell') + + ent.assert_passwd_by_name('user1', user1) + ent.assert_passwd_by_name('user1@LDAP', user1) +- ent.assert_passwd_by_name('ov_user1', user1) +- ent.assert_passwd_by_name('ov_user1@LDAP', user1) ++ ++ if override_name: ++ ent.assert_passwd_by_name('ov_user1', user1) ++ ent.assert_passwd_by_name('ov_user1@LDAP', user1) + + ent.assert_passwd_by_name('user2', user2) + ent.assert_passwd_by_name('user2@LDAP', user2) +- ent.assert_passwd_by_name('ov_user2', user2) +- ent.assert_passwd_by_name('ov_user2@LDAP', user2) ++ ++ if override_name: ++ ent.assert_passwd_by_name('ov_user2', user2) ++ ent.assert_passwd_by_name('ov_user2@LDAP', user2) + + + # +@@ -514,6 +525,54 @@ def test_imp_exp_user_override(ldap_conn, env_imp_exp_user_override): + assert_user_overriden() + + ++# Regression test for bug 3179 ++ ++ ++def test_imp_exp_user_overrride_noname(ldap_conn, ++ env_two_users_and_group): ++ ++ # Override ++ subprocess.check_call(["sss_override", "user-add", "user1", ++ "-u", "10010", ++ "-g", "20010", ++ "-c", "Overriden User 1", ++ "-h", "/home/ov/user1", ++ "-s", "/bin/ov_user1_shell"]) ++ ++ subprocess.check_call(["sss_override", "user-add", "user2@LDAP", ++ "-u", "10020", ++ "-g", "20020", ++ "-c", "Overriden User 2", ++ "-h", "/home/ov/user2", ++ "-s", "/bin/ov_user2_shell"]) ++ ++ # Restart SSSD so the override might take effect ++ restart_sssd() ++ ++ # Assert entries are overriden ++ assert_user_overriden(override_name=False) ++ ++ # Export overrides ++ subprocess.check_call(["sss_override", "user-export", OVERRIDE_FILENAME]) ++ ++ # Drop all overrides ++ subprocess.check_call(["sss_override", "user-del", "user1"]) ++ subprocess.check_call(["sss_override", "user-del", "user2@LDAP"]) ++ ++ # Avoid hitting memory cache ++ time.sleep(2) ++ ++ # Assert entries are not overridden ++ assert_user_default() ++ ++ # Import overrides ++ subprocess.check_call(["sss_override", "user-import", ++ OVERRIDE_FILENAME]) ++ restart_sssd() ++ ++ assert_user_overriden(override_name=False) ++ ++ + # + # Override user-show + # +@@ -581,7 +640,7 @@ def test_find_user_override(ldap_conn, env_find_user_override): + # Common group asserts + # + +-def assert_group_overriden(): ++def assert_group_overriden(override_name=True): + + # Assert entries are overridden + empty_group = dict(gid=3002, mem=ent.contains_only()) +@@ -589,13 +648,17 @@ def assert_group_overriden(): + + ent.assert_group_by_name("group", group) + ent.assert_group_by_name("group@LDAP", group) +- ent.assert_group_by_name("ov_group", group) +- ent.assert_group_by_name("ov_group@LDAP", group) ++ ++ if override_name: ++ ent.assert_group_by_name("ov_group", group) ++ ent.assert_group_by_name("ov_group@LDAP", group) + + ent.assert_group_by_name("empty_group", empty_group) + ent.assert_group_by_name("empty_group@LDAP", empty_group) +- ent.assert_group_by_name("ov_empty_group", empty_group) +- ent.assert_group_by_name("ov_empty_group@LDAP", empty_group) ++ ++ if override_name: ++ ent.assert_group_by_name("ov_empty_group", empty_group) ++ ent.assert_group_by_name("ov_empty_group@LDAP", empty_group) + + + def assert_group_default(): +@@ -841,6 +904,45 @@ def test_imp_exp_group_override(ldap_conn, env_imp_exp_group_override): + assert_group_overriden() + + ++# Regression test for bug 3179 ++ ++ ++def test_imp_exp_group_override_noname(ldap_conn, env_group_basic): ++ ++ # Override - do not use -n here) ++ subprocess.check_call(["sss_override", "group-add", "group", ++ "-g", "3001"]) ++ ++ subprocess.check_call(["sss_override", "group-add", "empty_group@LDAP", ++ "--gid", "3002"]) ++ ++ # Restart SSSD so the override might take effect ++ restart_sssd() ++ ++ # Assert entries are overridden ++ assert_group_overriden(override_name=False) ++ ++ # Export overrides ++ subprocess.check_call(["sss_override", "group-export", ++ OVERRIDE_FILENAME]) ++ ++ # Drop all overrides ++ subprocess.check_call(["sss_override", "group-del", "group"]) ++ subprocess.check_call(["sss_override", "group-del", "empty_group@LDAP"]) ++ ++ # Avoid hitting memory cache ++ time.sleep(2) ++ ++ assert_group_default() ++ ++ # Import overrides ++ subprocess.check_call(["sss_override", "group-import", ++ OVERRIDE_FILENAME]) ++ restart_sssd() ++ ++ assert_group_overriden(override_name=False) ++ ++ + # Regression test for bug #2802 + # sss_override segfaults when accidentally adding --help flag to some commands + +-- +2.7.4 + diff --git a/SOURCES/0141-p11-only-set-PKCS11_LOGIN_TOKEN_NAME-if-gdm-smartcar.patch b/SOURCES/0141-p11-only-set-PKCS11_LOGIN_TOKEN_NAME-if-gdm-smartcar.patch new file mode 100644 index 0000000..2df0058 --- /dev/null +++ b/SOURCES/0141-p11-only-set-PKCS11_LOGIN_TOKEN_NAME-if-gdm-smartcar.patch @@ -0,0 +1,267 @@ +From 5000ad4c45d3cfb4ffa0d76d291c8b1b6c49b02b Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 31 Aug 2016 14:32:31 +0200 +Subject: [PATCH 141/143] p11: only set PKCS11_LOGIN_TOKEN_NAME if + gdm-smartcard is used + +Resolves https://fedorahosted.org/sssd/ticket/3165 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 71cd9f98150577224559bdc12c53c01ce6f2c3d9) +--- + src/responder/pam/pamsrv_p11.c | 33 +++++++++------ + src/tests/cmocka/test_pam_srv.c | 89 +++++++++++++++++++++++++++++++++++------ + 2 files changed, 97 insertions(+), 25 deletions(-) + +diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c +index a2514f6a1d699de3a245063f49db1b7e51a2b10b..22da33067d5c479153376927855dcd6b43322d8b 100644 +--- a/src/responder/pam/pamsrv_p11.c ++++ b/src/responder/pam/pamsrv_p11.c +@@ -505,7 +505,11 @@ errno_t pam_check_cert_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + } + + /* The PKCS11_LOGIN_TOKEN_NAME environment variable is e.g. used by the Gnome +- * Settings Daemon to determine the name of the token used for login */ ++ * Settings Daemon to determine the name of the token used for login but it ++ * should be only set if SSSD is called by gdm-smartcard. Otherwise desktop ++ * components might assume that gdm-smartcard PAM stack is configured ++ * correctly which might not be the case e.g. if Smartcard authentication was ++ * used when running gdm-password. */ + #define PKCS11_LOGIN_TOKEN_ENV_NAME "PKCS11_LOGIN_TOKEN_NAME" + + errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username, +@@ -553,19 +557,22 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username, + return ret; + } + +- env = talloc_asprintf(pd, "%s=%s", PKCS11_LOGIN_TOKEN_ENV_NAME, token_name); +- if (env == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); +- return ENOMEM; +- } ++ if (strcmp(pd->service, "gdm-smartcard") == 0) { ++ env = talloc_asprintf(pd, "%s=%s", PKCS11_LOGIN_TOKEN_ENV_NAME, ++ token_name); ++ if (env == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); ++ return ENOMEM; ++ } + +- ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(env) + 1, +- (uint8_t *)env); +- talloc_free(env); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "pam_add_response failed to add environment variable.\n"); +- return ret; ++ ret = pam_add_response(pd, SSS_PAM_ENV_ITEM, strlen(env) + 1, ++ (uint8_t *)env); ++ talloc_free(env); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "pam_add_response failed to add environment variable.\n"); ++ return ret; ++ } + } + + return ret; +diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c +index 5de092d0f19318d1d6c773355dbb38e345600133..02199e6f121cab0784389256cdaac38baf9d73e3 100644 +--- a/src/tests/cmocka/test_pam_srv.c ++++ b/src/tests/cmocka/test_pam_srv.c +@@ -554,7 +554,7 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, const char *name, + } + + static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name, +- const char *pin) ++ const char *pin, const char *service) + { + size_t buf_size; + uint8_t *m_buf; +@@ -576,7 +576,7 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name, + pi.pam_authtok_type = SSS_AUTHTOK_TYPE_SC_PIN; + } + +- pi.pam_service = "login"; ++ pi.pam_service = service == NULL ? "login" : service; + pi.pam_service_size = strlen(pi.pam_service) + 1; + pi.pam_tty = "/dev/tty"; + pi.pam_tty_size = strlen(pi.pam_tty) + 1; +@@ -626,7 +626,8 @@ static int test_pam_simple_check(uint32_t status, uint8_t *body, size_t blen) + + #define PKCS11_LOGIN_TOKEN_ENV_NAME "PKCS11_LOGIN_TOKEN_NAME" + +-static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen) ++static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body, ++ size_t blen) + { + size_t rp = 0; + uint32_t val; +@@ -675,6 +676,44 @@ static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen) + return EOK; + } + ++static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen) ++{ ++ size_t rp = 0; ++ uint32_t val; ++ ++ assert_int_equal(status, 0); ++ ++ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); ++ assert_int_equal(val, pam_test_ctx->exp_pam_status); ++ ++ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); ++ assert_int_equal(val, 2); ++ ++ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); ++ assert_int_equal(val, SSS_PAM_DOMAIN_NAME); ++ ++ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); ++ assert_int_equal(val, 9); ++ ++ assert_int_equal(*(body + rp + val - 1), 0); ++ assert_string_equal(body + rp, TEST_DOM_NAME); ++ rp += val; ++ ++ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); ++ assert_int_equal(val, SSS_PAM_CERT_INFO); ++ ++ SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); ++ assert_int_equal(val, (sizeof("pamuser") + sizeof(TEST_TOKEN_NAME))); ++ ++ assert_int_equal(*(body + rp + sizeof("pamuser") - 1), 0); ++ assert_string_equal(body + rp, "pamuser"); ++ rp += sizeof("pamuser"); ++ ++ assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0); ++ assert_string_equal(body + rp, TEST_TOKEN_NAME); ++ ++ return EOK; ++} + + static int test_pam_offline_chauthtok_check(uint32_t status, + uint8_t *body, size_t blen) +@@ -1438,7 +1477,7 @@ void test_pam_preauth_no_logon_name(void **state) + { + int ret; + +- mock_input_pam_cert(pam_test_ctx, NULL, NULL); ++ mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1465,7 +1504,7 @@ void test_pam_preauth_cert_nocert(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, "/no/path"); + +- mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); ++ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1544,7 +1583,7 @@ void test_pam_preauth_cert_nomatch(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); + +- mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); ++ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1566,7 +1605,7 @@ void test_pam_preauth_cert_match(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); + +- mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); ++ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1583,13 +1622,37 @@ void test_pam_preauth_cert_match(void **state) + assert_int_equal(ret, EOK); + } + ++/* Test if PKCS11_LOGIN_TOKEN_NAME is added for the gdm-smartcard service */ ++void test_pam_preauth_cert_match_gdm_smartcard(void **state) ++{ ++ int ret; ++ ++ set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); ++ ++ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, "gdm-smartcard"); ++ ++ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); ++ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); ++ mock_account_recv(0, 0, NULL, test_lookup_by_cert_cb, ++ discard_const(TEST_TOKEN_CERT)); ++ ++ set_cmd_cb(test_pam_cert_check_gdm_smartcard); ++ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_PREAUTH, ++ pam_test_ctx->pam_cmds); ++ assert_int_equal(ret, EOK); ++ ++ /* Wait until the test finishes with EOK */ ++ ret = test_ev_loop(pam_test_ctx->tctx); ++ assert_int_equal(ret, EOK); ++} ++ + void test_pam_preauth_cert_match_wrong_user(void **state) + { + int ret; + + set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); + +- mock_input_pam_cert(pam_test_ctx, "pamuser", NULL); ++ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1613,7 +1676,7 @@ void test_pam_preauth_cert_no_logon_name(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); + +- mock_input_pam_cert(pam_test_ctx, NULL, NULL); ++ mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1636,7 +1699,7 @@ void test_pam_preauth_no_cert_no_logon_name(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, "/no/path"); + +- mock_input_pam_cert(pam_test_ctx, NULL, NULL); ++ mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1657,7 +1720,7 @@ void test_pam_preauth_cert_no_logon_name_no_match(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); + +- mock_input_pam_cert(pam_test_ctx, NULL, NULL); ++ mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1679,7 +1742,7 @@ void test_pam_cert_auth(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, NSS_DB); + +- mock_input_pam_cert(pam_test_ctx, "pamuser", "123456"); ++ mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1790,6 +1853,8 @@ int main(int argc, const char *argv[]) + pam_test_setup, pam_test_teardown), + cmocka_unit_test_setup_teardown(test_pam_preauth_cert_match, + pam_test_setup, pam_test_teardown), ++ cmocka_unit_test_setup_teardown(test_pam_preauth_cert_match_gdm_smartcard, ++ pam_test_setup, pam_test_teardown), + cmocka_unit_test_setup_teardown(test_pam_preauth_cert_match_wrong_user, + pam_test_setup, pam_test_teardown), + cmocka_unit_test_setup_teardown(test_pam_preauth_cert_no_logon_name, +-- +2.7.4 + diff --git a/SOURCES/0142-p11-return-a-fully-qualified-name.patch b/SOURCES/0142-p11-return-a-fully-qualified-name.patch new file mode 100644 index 0000000..195b9cc --- /dev/null +++ b/SOURCES/0142-p11-return-a-fully-qualified-name.patch @@ -0,0 +1,100 @@ +From e87e0059520de24047e8448a5b417393adc6c5b4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 16 Sep 2016 11:47:40 +0200 +Subject: [PATCH 142/143] p11: return a fully-qualified name + +Related to https://fedorahosted.org/sssd/ticket/3165 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 3649b959709f1ab187092f054d4aace0798c98fa) +--- + src/responder/pam/pamsrv_p11.c | 20 +++++++++----------- + src/tests/cmocka/test_pam_srv.c | 16 ++++++++-------- + 2 files changed, 17 insertions(+), 19 deletions(-) + +diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c +index 22da33067d5c479153376927855dcd6b43322d8b..570bfe09d4385a038e7e03fcb64c72dd794774a6 100644 +--- a/src/responder/pam/pamsrv_p11.c ++++ b/src/responder/pam/pamsrv_p11.c +@@ -521,33 +521,31 @@ errno_t add_pam_cert_response(struct pam_data *pd, const char *sysdb_username, + size_t msg_len; + size_t slot_len; + int ret; +- char *username; + + if (sysdb_username == NULL || token_name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing mandatory user or slot name.\n"); + return EINVAL; + } + +- ret = sss_parse_internal_fqname(pd, sysdb_username, &username, NULL); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot parse [%s]\n", sysdb_username); +- return ret; +- } +- +- user_len = strlen(username) + 1; ++ user_len = strlen(sysdb_username) + 1; + slot_len = strlen(token_name) + 1; + msg_len = user_len + slot_len; + + msg = talloc_zero_size(pd, msg_len); + if (msg == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_size failed.\n"); +- talloc_free(username); + return ENOMEM; + } + +- memcpy(msg, username, user_len); ++ /* sysdb_username is a fully-qualified name which is used by pam_sss when ++ * prompting the user for the PIN and as login name if it wasn't set by ++ * the PAM caller but has to be determined based on the inserted ++ * Smartcard. If this type of name is irritating at the PIN prompt or the ++ * re_expression config option was set in a way that user@domain cannot be ++ * handled anymore some more logic has to be added here. But for the time ++ * being I think using sysdb_username is fine. */ ++ memcpy(msg, sysdb_username, user_len); + memcpy(msg + user_len, token_name, slot_len); +- talloc_free(username); + + ret = pam_add_response(pd, SSS_PAM_CERT_INFO, msg_len, msg); + talloc_free(msg); +diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c +index 02199e6f121cab0784389256cdaac38baf9d73e3..4b2dea4be6a819b23afd243ba99cd9bd57c16c20 100644 +--- a/src/tests/cmocka/test_pam_srv.c ++++ b/src/tests/cmocka/test_pam_srv.c +@@ -664,11 +664,11 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body, + assert_int_equal(val, SSS_PAM_CERT_INFO); + + SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); +- assert_int_equal(val, (sizeof("pamuser") + sizeof(TEST_TOKEN_NAME))); ++ assert_int_equal(val, (sizeof("pamuser@"TEST_DOM_NAME) + sizeof(TEST_TOKEN_NAME))); + +- assert_int_equal(*(body + rp + sizeof("pamuser") - 1), 0); +- assert_string_equal(body + rp, "pamuser"); +- rp += sizeof("pamuser"); ++ assert_int_equal(*(body + rp + sizeof("pamuser@"TEST_DOM_NAME) - 1), 0); ++ assert_string_equal(body + rp, "pamuser@"TEST_DOM_NAME); ++ rp += sizeof("pamuser@"TEST_DOM_NAME); + + assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0); + assert_string_equal(body + rp, TEST_TOKEN_NAME); +@@ -703,11 +703,11 @@ static int test_pam_cert_check(uint32_t status, uint8_t *body, size_t blen) + assert_int_equal(val, SSS_PAM_CERT_INFO); + + SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); +- assert_int_equal(val, (sizeof("pamuser") + sizeof(TEST_TOKEN_NAME))); ++ assert_int_equal(val, (sizeof("pamuser@"TEST_DOM_NAME) + sizeof(TEST_TOKEN_NAME))); + +- assert_int_equal(*(body + rp + sizeof("pamuser") - 1), 0); +- assert_string_equal(body + rp, "pamuser"); +- rp += sizeof("pamuser"); ++ assert_int_equal(*(body + rp + sizeof("pamuser@"TEST_DOM_NAME) - 1), 0); ++ assert_string_equal(body + rp, "pamuser@"TEST_DOM_NAME); ++ rp += sizeof("pamuser@"TEST_DOM_NAME); + + assert_int_equal(*(body + rp + sizeof(TEST_TOKEN_NAME) - 1), 0); + assert_string_equal(body + rp, TEST_TOKEN_NAME); +-- +2.7.4 + diff --git a/SOURCES/0143-pam_sss-check-PKCS11_LOGIN_TOKEN_NAME.patch b/SOURCES/0143-pam_sss-check-PKCS11_LOGIN_TOKEN_NAME.patch new file mode 100644 index 0000000..1cd1c77 --- /dev/null +++ b/SOURCES/0143-pam_sss-check-PKCS11_LOGIN_TOKEN_NAME.patch @@ -0,0 +1,109 @@ +From b5a092b4b0e4f072f0f402146a83addb97cf2977 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 16 Sep 2016 11:48:18 +0200 +Subject: [PATCH 143/143] pam_sss: check PKCS11_LOGIN_TOKEN_NAME + +Check if PKCS11_LOGIN_TOKEN_NAME is set and prompt the user if the +matching Smartcard is not inserted. + +Related to https://fedorahosted.org/sssd/ticket/3165 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 35ba922bc51416f02877b53a6f25c04104ae5f03) +--- + src/sss_client/pam_sss.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c +index fdb9c907644f1317b6f8e58619f01ad2753deafc..2049d5fb0c6092aaaa914385c79d02d8f44b447e 100644 +--- a/src/sss_client/pam_sss.c ++++ b/src/sss_client/pam_sss.c +@@ -1410,6 +1410,7 @@ done: + } + + #define SC_PROMPT_FMT "PIN for %s for user %s" ++ + static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi) + { + int ret; +@@ -1691,6 +1692,62 @@ static int get_authtok_for_password_change(pam_handle_t *pamh, + return PAM_SUCCESS; + } + ++#define SC_ENTER_FMT "Please enter smart card labeled\n %s\nand press enter" ++ ++static int check_login_token_name(pam_handle_t *pamh, struct pam_items *pi, ++ bool quiet_mode) ++{ ++ int ret; ++ int pam_status; ++ char *login_token_name; ++ char *prompt = NULL; ++ size_t size; ++ char *answer = NULL; ++ ++ login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME"); ++ if (login_token_name == NULL) { ++ return PAM_SUCCESS; ++ } ++ ++ while (pi->token_name == NULL ++ || strcmp(login_token_name, pi->token_name) != 0) { ++ size = sizeof(SC_ENTER_FMT) + strlen(login_token_name); ++ prompt = malloc(size); ++ if (prompt == NULL) { ++ D(("malloc failed.")); ++ return ENOMEM; ++ } ++ ++ ret = snprintf(prompt, size, SC_ENTER_FMT, ++ login_token_name); ++ if (ret < 0 || ret >= size) { ++ D(("snprintf failed.")); ++ free(prompt); ++ return EFAULT; ++ } ++ ++ ret = do_pam_conversation(pamh, PAM_PROMPT_ECHO_OFF, prompt, ++ NULL, &answer); ++ free(prompt); ++ free(answer); ++ if (ret != PAM_SUCCESS) { ++ D(("do_pam_conversation failed.")); ++ return ret; ++ } ++ ++ pam_status = send_and_receive(pamh, pi, SSS_PAM_PREAUTH, quiet_mode); ++ if (pam_status != PAM_SUCCESS) { ++ D(("send_and_receive returned [%d] during pre-auth", pam_status)); ++ /* ++ * Since we are waiting for the right Smartcard to be inserted errors ++ * can be ignored here. ++ */ ++ } ++ } ++ ++ return PAM_SUCCESS; ++} ++ + static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh, + int pam_flags, int argc, const char **argv) + { +@@ -1758,6 +1815,14 @@ static int pam_sss(enum sss_cli_command task, pam_handle_t *pamh, + } + } + ++ if (strcmp(pi.pam_service, "gdm-smartcard") == 0) { ++ ret = check_login_token_name(pamh, &pi, quiet_mode); ++ if (ret != PAM_SUCCESS) { ++ D(("check_login_token_name failed.\n")); ++ return ret; ++ } ++ } ++ + ret = get_authtok_for_authentication(pamh, &pi, flags); + if (ret != PAM_SUCCESS) { + D(("failed to get authentication token: %s", +-- +2.7.4 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 84381b9..370e6d7 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -4,17 +4,20 @@ %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 + %global install_pcscd_polkit_rule 1 # Determine the location of the LDB modules directory %global ldb_modulesdir %(pkg-config --variable=modulesdir ldb) %global ldb_version 1.1.17 -%global with_krb5_localauth_plugin 1 + +%if (0%{?fedora} || 0%{?rhel} >= 7) + %global with_cifs_utils_plugin 1 +%else + %global with_cifs_utils_plugin_option --disable-cifs-idmap-plugin +%endif + + %global with_krb5_localauth_plugin 1 %global libwbc_alternatives_version 0.12 %global libwbc_lib_version %{libwbc_alternatives_version}.0 @@ -23,148 +26,174 @@ %global libwbc_alternatives_suffix -64 %endif +%global enable_systemtap 1 +%if (0%{?enable_systemtap} == 1) + %global enable_systemtap_opt --enable-systemtap +%endif + Name: sssd -Version: 1.13.0 -Release: 40%{?dist}.12 +Version: 1.14.0 +Release: 43%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ URL: http://fedorahosted.org/sssd/ Source0: https://fedorahosted.org/released/sssd/%{name}-%{version}.tar.gz -Source1: cert9.db -Source2: key4.db BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) ### Patches ### -Patch0001: 0001-test-common-sss_dp_get_account_recv-fix-assignment.patch -Patch0002: 0002-tests-Move-N_ELEMENTS-definition-to-tests-common.h.patch -Patch0003: 0003-SYSDB-Add-functions-to-look-up-multiple-entries-incl.patch -Patch0004: 0004-DP-Add-DP_WILDCARD-and-SSS_DP_WILDCARD_USER-SSS_DP_W.patch -Patch0005: 0005-cache_req-Extend-cache_req-with-wildcard-lookups.patch -Patch0006: 0006-UTIL-Add-sss_filter_sanitize_ex.patch -Patch0007: 0007-LDAP-Fetch-users-and-groups-using-wildcards.patch -Patch0008: 0008-LDAP-Add-sdap_get_and_parse_generic_send.patch -Patch0009: 0009-LDAP-Use-sdap_get_and_parse_generic_-_recv.patch -Patch0010: 0010-LDAP-Add-sdap_lookup_type-enum.patch -Patch0011: 0011-LDAP-Add-the-wildcard_limit-option.patch -Patch0012: 0012-IFP-Add-wildcard-requests.patch -Patch0013: 0013-KRB5-Return-right-data-provider-error-code.patch -Patch0014: 0014-nss_check_name_of_well_known_sid-improve-name-splitt.patch -Patch0015: 0015-DYNDNS-sss_iface_addr_list_get-return-ENOENT.patch -Patch0016: 0016-DYNDNS-support-mult.-interfaces-for-dyndns_iface-opt.patch -Patch0017: 0017-DYNDNS-special-value-for-dyndns_iface-option.patch -Patch0018: 0018-TESTS-dyndns-tests-support-AAAA-addresses.patch -Patch0019: 0019-DYNDNS-support-for-dualstack.patch -Patch0020: 0020-VIEWS-TEST-add-null-check.patch -Patch0021: 0021-SYSDB-prepare-for-LOCAL-view.patch -Patch0022: 0022-TOOLS-add-common-command-framework.patch -Patch0023: 0023-TOOLS-add-sss_override-for-local-overrides.patch -Patch0024: 0024-IPA-Better-debugging.patch -Patch0025: 0025-UTIL-Lower-debug-level-in-perform_checks.patch -Patch0026: 0026-IPA-Handle-sssd-owned-keytabs-when-running-as-root.patch -Patch0027: 0027-TESTS-fix-compiler-warnings.patch -Patch0028: 0028-intg-Invalidate-memory-cache-before-removing-files.patch -Patch0029: 0029-krb5-do-not-send-SSS_OTP-if-two-factors-were-used.patch -Patch0030: 0030-utils-add-NSS-version-of-cert-utils.patch -Patch0031: 0031-Add-NSS-version-of-p11_child.patch -Patch0032: 0032-pack_message_v3-allow-empty-name.patch -Patch0033: 0033-authok-add-support-for-Smart-Card-related-authtokens.patch -Patch0034: 0034-PAM-add-certificate-support-to-PAM-pre-auth-NOTEST.patch -Patch0035: 0035-pam_sss-add-sc-support.patch -Patch0036: 0036-ssh-generate-public-keys-from-certificate.patch -Patch0037: 0037-IPA-Remove-MPG-groups-if-getgrgid-was-called-before-.patch -Patch0038: 0038-mmap_cache-Rename-variables.patch -Patch0039: 0039-mmap_cache-Override-functions-for-initgr-mmap-cache.patch -Patch0040: 0040-mmap-Invalidate-initgroups-memory-cache-after-any-ch.patch -Patch0041: 0041-sss_client-Update-integrity-check-of-records-in-mmap.patch -Patch0042: 0042-intg_test-Add-module-for-simulation-of-utility-id.patch -Patch0043: 0043-intg_test-Add-integration-test-for-memory-cache.patch -Patch0044: 0044-NSS-Initgr-memory-cache-should-work-with-fq-names.patch -Patch0045: 0045-test_memory_cache-Add-test-for-initgroups-mc-with-fq.patch -Patch0046: 0046-test_memory_cache-Test-mmap-cache-after-initgroups.patch -Patch0047: 0047-test_memory_cache-Test-invalidation-with-sss_cache.patch -Patch0048: 0048-krb5-utils-add-sss_krb5_realm_has_proxy.patch -Patch0049: 0049-krb5-do-not-create-kdcinfo-file-if-proxy-configurati.patch -Patch0050: 0050-krb5-assume-online-state-if-KDC-proxy-is-configured.patch -Patch0051: 0051-sss_cache-Wait-a-while-for-invalidation-of-mc-by-nss.patch -Patch0052: 0052-IFP-use-default-limit-if-provided-is-0.patch -Patch0053: 0053-sudo-use-higher-value-wins-when-ordering-rules.patch -Patch0054: 0054-LDAP-use-ldb_binary_encode-when-printing-attribute-v.patch -Patch0055: 0055-IPA-Change-the-default-of-ldap_user_certificate-to-u.patch -Patch0056: 0056-UTIL-Provide-a-common-interface-to-safely-create-tem.patch -Patch0057: 0057-IPA-Always-re-fetch-the-keytab-from-the-IPA-server.patch -Patch0058: 0058-p11child-set-restrictive-umask-and-clear-environment.patch -Patch0059: 0059-pam-Incerease-p11-child-timeout.patch -Patch0060: 0060-SYSDB-Index-the-objectSIDString-attribute.patch -Patch0061: 0061-sss_override-print-input-name-if-unable-to-parse-it.patch -Patch0062: 0062-sss_override-support-domains-that-require-fqname.patch -Patch0063: 0063-TOOLS-add-sss_colondb-API.patch -Patch0064: 0064-sss_override-decompose-code-better.patch -Patch0065: 0065-sss_override-support-import-and-export.patch -Patch0066: 0066-NSS-Fix-use-after-free.patch -Patch0067: 0067-sss_override-document-debug-options.patch -Patch0068: 0068-NSS-Don-t-ignore-backslash-in-usernames-with-ldap-pr.patch -Patch0069: 0069-GPO-fix-memory-leak.patch -Patch0070: 0070-sss_override-support-fqn-in-override-name.patch -Patch0071: 0071-views-do-not-require-overrideDN-in-grous-when-LOCAL-.patch -Patch0072: 0072-views-fix-two-typos-in-debug-messages.patch -Patch0073: 0073-views-allow-ghost-members-for-LOCAL-view.patch -Patch0074: 0074-UTIL-Convert-domain-disabled-into-tri-state-with-dom.patch -Patch0075: 0075-DP-Provide-a-way-to-mark-subdomain-as-disabled-and-a.patch -Patch0076: 0076-SDAP-Do-not-set-is_offline-if-ignore_mark_offline-is.patch -Patch0077: 0077-AD-Only-ignore-errors-from-SDAP-lookups-if-there-s-a.patch -Patch0078: 0078-KRB5-Offline-operation-with-disabled-domain.patch -Patch0079: 0079-AD-Do-not-mark-the-whole-back-end-as-offline-if-subd.patch -Patch0080: 0080-AD-Set-ignore_mark_offline-false-when-resolving-AD-r.patch -Patch0081: 0081-IPA-Do-not-allow-the-AD-lookup-code-to-set-backend-a.patch -Patch0082: 0082-sss_override-remove-d-from-manpage.patch -Patch0083: 0083-LDAP-imposing-sizelimit-1-for-single-entry-searches-.patch -Patch0084: 0084-DYNDNS-Add-a-new-option-dyndns_server.patch -Patch0085: 0085-DYNDNS-Don-t-use-server-cmd-in-nsupdate-by-default.patch -Patch0086: 0086-DYNDNS-remove-redundant-talloc_steal.patch -Patch0087: 0087-DYNDNS-remove-zone-command.patch -Patch0088: 0088-DYNDNS-rename-field-of-sdap_dyndns_update_state.patch -Patch0089: 0089-DYNDNS-remove-code-duplication.patch -Patch0090: 0090-DDNS-execute-nsupdate-for-single-update-of-PTR-rec.patch -Patch0091: 0091-DYNDNS-Return-right-error-code-in-case-of-failure.patch -Patch0092: 0092-IPA-Change-ipa_server_trust_add_send-request-to-be-r.patch -Patch0093: 0093-DEBUG-Add-new-debug-category-for-fail-over.patch -Patch0094: 0094-FO-Add-an-API-to-reset-all-servers-in-a-single-servi.patch -Patch0095: 0095-FO-Also-reset-the-server-common-data-in-addition-to-.patch -Patch0096: 0096-IPA-Retry-fetching-keytab-if-IPA-user-lookup-fails.patch -Patch0097: 0097-AD-inicialize-root_domain_attrs-field.patch -Patch0098: 0098-PAM-only-allow-missing-user-name-for-certificate-aut.patch -Patch0099: 0099-Fix-memory-leak-in-sssdpac_verify.patch -Patch0100: 0100-AD-Provide-common-connection-list-construction-funct.patch -Patch0101: 0101-AD-Consolidate-connection-list-construction-on-ad_co.patch -Patch0102: 0102-nss-send-original-name-and-id-with-local-views-if-po.patch -Patch0103: 0103-sudo-search-with-view-even-if-user-is-found.patch -Patch0104: 0104-sudo-send-original-name-and-id-with-local-views-if-p.patch -Patch0105: 0105-IPA-fix-override-with-the-same-name.patch -Patch0106: 0106-Add-a-new-option-ldap_group_external_member.patch -Patch0107: 0107-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch -Patch0108: 0108-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch -Patch0109: 0109-memberof-Don-t-allocate-on-a-NULL-context.patch -Patch0110: 0110-memberof-Fix-a-memory-leak-when-removing-ghost-users.patch -Patch0111: 0111-memberof-Don-t-allocate-on-NULL-when-deleting-member.patch -Patch0112: 0112-IPA-Handle-requests-for-netgroups-from-trusted-domai.patch -Patch0113: 0113-LDAP-Try-also-the-AD-access-control-for-IPA-users.patch -Patch0114: 0114-NSS-Fix-memory-leak-netgroup.patch -Patch0115: 0115-ipa_s2n_save_objects-use-configured-user-and-group-t.patch -Patch0116: 0116-IPA-use-forest-name-when-looking-up-the-Global-Catal.patch -Patch0117: 0117-LDAP-Fix-leak-of-file-descriptors.patch -Patch0118: 0118-libwbclient-wbcSidsToUnixIds-don-t-fail-on-errors.patch -Patch0119: 0119-IPA-ldap_group_external_member-defaults-to-ipaExtern.patch +Patch0001: 0001-SYSDB-Fixing-DB-update.patch +Patch0002: 0002-sssctl-Fix-error-handling-after-memory-allocation-fa.patch +Patch0003: 0003-sssctl-config-check-access-check-report.patch +Patch0004: 0004-FO-Set-port-to-NOT_WORKING-when-trying-a-next-server.patch +Patch0005: 0005-sssctl-Fix-format-string-for-size_t.patch +Patch0006: 0006-doxygen-Fix-path-to-header-file-ipa_hbac.h.patch +Patch0007: 0007-ipa_hbac-Fix-documentation-for-hbac_enable_debug.patch +Patch0008: 0008-sssctl-Fix-warning-maybe-uninitialized.patch +Patch0009: 0009-NOUPSTREAM-Bundle-http-parser.patch +Patch0010: 0010-MAN-Update-description-of-sssctl.patch +Patch0011: 0011-nss-srv-tests-Fix-prototype-of-wrapped-ncache-functi.patch +Patch0012: 0012-TOOLS-Prevent-dereference-of-null-pointer.patch +Patch0013: 0013-config-override_space-is-monitor-s-option.patch +Patch0014: 0014-config-Fix-user_attributes.patch +Patch0015: 0015-sysdb-tests-Fix-cast-from-pointer-to-integer.patch +Patch0016: 0016-PROVIDERS-Setting-right-u-g-id-if-unprivileged.patch +Patch0017: 0017-config-Allow-timeout-for-all-sevices.patch +Patch0018: 0018-config-Add-config_file_version-to-schema.patch +Patch0019: 0019-dyndns-Add-checks-for-NULL.patch +Patch0020: 0020-sdap-Fix-ldap_rfc_2307_fallback_to_local_users.patch +Patch0021: 0021-test_utils-Clean-files-after-sss_write_krb5_conf_sni.patch +Patch0022: 0022-IPA-read-ipaNTAdditionalSuffixes-for-master-and-trus.patch +Patch0023: 0023-sysdb-add-UPN-suffix-support-for-the-master-domain.patch +Patch0024: 0024-sysdb-make-subdomain-calls-aware-of-upn_suffixes.patch +Patch0025: 0025-DP-add-dp_get_module_data.patch +Patch0026: 0026-IPA-add-ipa_init_get_krb5_auth_ctx.patch +Patch0027: 0027-IPA-enable-enterprise-principals-if-server-supports-.patch +Patch0028: 0028-views-allow-override-added-for-non-default-views-at-.patch +Patch0029: 0029-sssctl-move-filter-creation-to-separate-function.patch +Patch0030: 0030-sssctl-improve-readability-of-a-condition.patch +Patch0031: 0031-sssctl-Use-localtime-for-time-stamps.patch +Patch0032: 0032-SECRETS-Log-message-for-failures-with-removing-file.patch +Patch0033: 0033-IPA-fix-capaths-output.patch +Patch0034: 0034-UTIL-make-domain-mapping-content-testable.patch +Patch0035: 0035-tests-add-tests-for-sss_get_domain_mappings_content.patch +Patch0036: 0036-Amend-debug-messages-after-failure-of-unlink.patch +Patch0037: 0037-SYSDB-Do-not-try-to-modify-ts-cache-for-unsupported-.patch +Patch0038: 0038-AD-avoid-memory-leak-in-netlogon_get_domain_info-and.patch +Patch0039: 0039-AD-netlogon_get_domain_info-allow-missing-arguments-.patch +Patch0040: 0040-tests-add-tests-for-netlogon_get_domain_info.patch +Patch0041: 0041-AD-replace-ad_get_client_site_parse_ndr-with-netlogo.patch +Patch0042: 0042-sysdb_master_domain_add_info-properly-set-do_update.patch +Patch0043: 0043-SYSDB-Removing-of-duplication-of-sysdb_ts_cache_attr.patch +Patch0044: 0044-test_utils-Fixing-assignment-discards-const-qualifie.patch +Patch0045: 0045-IPA-make-ipa_resolve_user_list_-send-recv-public-and.patch +Patch0046: 0046-IPA-expand-ghost-members-of-AD-groups-in-server-mode.patch +Patch0047: 0047-sysdb-add-sysdb_get_user_members_recursively.patch +Patch0048: 0048-views-properly-override-group-member-names.patch +Patch0049: 0049-IPA-fix-lookup-by-UPN-for-subdomains.patch +Patch0050: 0050-LDAP-allow-multiple-user-principals.patch +Patch0051: 0051-LDAP-new-attribute-option-ldap_user_email.patch +Patch0052: 0052-sysdb-include-email-in-UPN-searches.patch +Patch0053: 0053-LDAP-include-email-in-UPN-searches.patch +Patch0054: 0054-NSS-add-user-email-to-fill_orig.patch +Patch0055: 0055-utils-add-is_email_from_domain.patch +Patch0056: 0056-LDAP-IPA-add-local-email-address-to-aliases.patch +Patch0057: 0057-NSS-continue-with-UPN-email-search-if-name-was-not-f.patch +Patch0058: 0058-PAM-continue-with-UPN-email-search-if-name-was-not-f.patch +Patch0059: 0059-NSS-use-different-neg-cache-name-for-UPN-searches.patch +Patch0060: 0060-PAM-Fix-domain-for-UPN-based-lookups.patch +Patch0061: 0061-SDAP-add-special-handling-for-IPA-Kerberos-enterpris.patch +Patch0062: 0062-SDAP-add-enterprise-principal-strings-for-user-searc.patch +Patch0063: 0063-LDAP-Fix-storing-initgroups-for-users-with-no-supple.patch +Patch0064: 0064-LDAP-Changing-of-confusing-debug-message.patch +Patch0065: 0065-LDAP-Use-FQDN-when-linking-parent-LDAP-groups.patch +Patch0066: 0066-sssctl-Consistent-commands-naming.patch +Patch0067: 0067-SDAP-sanitize-member-name-before-using-in-filter.patch +Patch0068: 0068-SDAP-sysdb_search_users-does-not-set-users_count-for.patch +Patch0069: 0069-SYSDB-Sanitize-dn-in-sysdb_get_user_members_recursiv.patch +Patch0070: 0070-SYSDB-Fix-setting-dataExpireTimestamp-if-sysdb-is-su.patch +Patch0071: 0071-Revert-LDAP-Lookup-services-by-all-protocols-unless-.patch +Patch0072: 0072-PROVIDER-Conversion-empty-string-from-D-Bus-to-NULL.patch +Patch0073: 0073-LDAP-Fix-Dereference-after-NULL-check.patch +Patch0074: 0074-LDAP-Fixing-wrong-pam-error-code-for-passwd.patch +Patch0075: 0075-PAM-Do-not-act-on-ldb_message-in-case-of-a-failure.patch +Patch0076: 0076-IPA-Check-the-return-value-of-sss_parse_internal_fqn.patch +Patch0077: 0077-DP-Initialize-D-Bus-as-soon-as-possible.patch +Patch0078: 0078-sssctl-Generic-help-for-cache-upgrade-and-config-che.patch +Patch0079: 0079-NSS-Do-not-check-local-users-with-disabled-local_neg.patch +Patch0080: 0080-config_schema-Add-ldap_user_email-to-schema.patch +Patch0081: 0081-NSS-Use-correct-name-for-invalidating-memory-cache.patch +Patch0082: 0082-SYSDB-Avoid-optimisation-with-modifyTimestamp-for-us.patch +Patch0083: 0083-SIMPLE-Do-not-parse-names-on-startup.patch +Patch0084: 0084-SIMPLE-Fail-on-any-error-parsing-the-access-control-.patch +Patch0085: 0085-SIMPLE-Make-the-DP-handlers-testable.patch +Patch0086: 0086-TESTS-Use-the-DP-handlers-in-simple-provider-tests-a.patch +Patch0087: 0087-gpo-gPCMachineExtensionNames-with-just-whitespaces.patch +Patch0088: 0088-sss_ini-Change-debug-level-of-config-error-msgs.patch +Patch0089: 0089-CONFIG-full_name_format-is-an-allowed-option-for-all.patch +Patch0090: 0090-CONFIG-re_expression-is-an-allowed-option-for-all-do.patch +Patch0091: 0091-rdp-add-ability-to-forward-reply-to-the-client-reque.patch +Patch0092: 0092-sbus-add-sbus_request_reply_error.patch +Patch0093: 0093-sbus-add-utility-function-to-simplify-message-and-re.patch +Patch0094: 0094-sssctl-use-talloc-with-sifp.patch +Patch0095: 0095-failover-mark-subdomain-service-with-sd_-prefix.patch +Patch0096: 0096-sssctl-print-active-server-and-server-list.patch +Patch0097: 0097-sifp-fix-coverity-warning.patch +Patch0098: 0098-sbus-allow-freeing-msg-through-dbus-api-when-using-t.patch +Patch0099: 0099-PROXY-Do-not-abuse-data-provider-interface.patch +Patch0100: 0100-DP-Remove-old-data-provider-interface.patch +Patch0101: 0101-NSS-Remove-unused-functions.patch +Patch0102: 0102-LDAP-Fixing-of-removing-netgroup-from-cache.patch +Patch0103: 0103-AD_PROVIDER-Add-ad_enabled_domains-option.patch +Patch0104: 0104-AD_PROVIDER-Initializing-of-ad_enabled_domains.patch +Patch0105: 0105-AD_PROVIDER-ad_enabled_domains-only-master.patch +Patch0106: 0106-AD_PROVIDER-ad_enabled_domains-other-then-master.patch +Patch0107: 0107-TESTS-Adding-tests-for-ad_enabled_domains-option.patch +Patch0109: 0109-UTIL-Use-sss_atomic_read_s-in-generate_csprng_buffer.patch +Patch0110: 0110-SECRETS-Use-sss_atomic_read-write-for-better-readabi.patch +Patch0111: 0111-BUILD-Ship-systemd-service-file-for-sssd-secrets.patch +Patch0112: 0112-DP-Add-log-message-for-get-account-info.patch +Patch0113: 0113-LDAP-Log-autofs-rfc2307-config-changes-only-with-ena.patch +Patch0114: 0114-SSSCTL-More-helpful-error-message-when-InfoPipe-is-d.patch +Patch0115: 0115-sdap-Skip-exact-duplicates-when-extending-maps.patch +Patch0116: 0116-watchdog-cope-with-time-shift.patch +Patch0117: 0117-PROXY-Use-the-fqname-when-converting-to-lowercase.patch +Patch0118: 0118-BUILD-Allow-to-read-private-pipes-for-root.patch +Patch0119: 0119-SYSDB-Rework-sysdb_cache_connect.patch +Patch0120: 0120-SYSDB-Remove-the-timestamp-cache-for-a-newly-created.patch +Patch0121: 0121-SECRETS-Return-ENOENT-when_deleting-a-non-existent-s.patch +Patch0122: 0122-IPA-Parse-qualified-names-when-guessing-AD-user-prin.patch +Patch0123: 0123-SYSDB-Fix-uninitialized-scalar-variable.patch +Patch0124: 0124-PROXY-Use-right-name-in-ldap-filter.patch +Patch0125: 0125-SYSDB-Fix-error-handling-in-sysdb_get_user_members_r.patch +Patch0126: 0126-sdap_initgr_nested_get_membership_diff-use-fully-qua.patch +Patch0127: 0127-Revert-CONFIG-Use-default-config-when-none-provided.patch +Patch0128: 0128-TOOLS-Fix-a-typo-in-groupadd.patch +Patch0129: 0129-TOOLS-sss_groupshow-did-not-work.patch +Patch0130: 0130-TESTS-sss_groupadd-groupshow-regressions.patch +Patch0131: 0131-TOOLS-use-internal-fqdn-for-DN.patch +Patch0132: 0132-TESTS-Test-for-sss_user-groupmod-a.patch +Patch0133: 0133-TOOLS-sss_mc_refresh_nested_group-short-fqname-usage.patch +Patch0134: 0134-TESTS-Add-FQDN-variants-for-some-tests.patch +Patch0135: 0135-KRB5-Send-the-output-username-not-internal-fqname-to.patch +Patch0136: 0136-LDAP-Return-partial-results-from-adminlimit-exceeded.patch +Patch0137: 0137-TOOLS-sss_groupshow-fails-to-show-MPG.patch +Patch0138: 0138-TESTS-sss_groupshow-with-MPG.patch +Patch0139: 0139-TOOLS-sss_override-without-name-override.patch +Patch0140: 0140-TEST-Add-regression-test-for-ticket-3179.patch +Patch0141: 0141-p11-only-set-PKCS11_LOGIN_TOKEN_NAME-if-gdm-smartcar.patch +Patch0142: 0142-p11-return-a-fully-qualified-name.patch +Patch0143: 0143-pam_sss-check-PKCS11_LOGIN_TOKEN_NAME.patch #This patch should not be removed in RHEL-7 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec ### Dependencies ### + Requires: sssd-common = %{version}-%{release} Requires: sssd-ldap = %{version}-%{release} Requires: sssd-krb5 = %{version}-%{release} Requires: sssd-ipa = %{version}-%{release} -Requires: sssd-common-pac = %{version}-%{release} Requires: sssd-ad = %{version}-%{release} Requires: sssd-proxy = %{version}-%{release} Requires: python-sssdconfig = %{version}-%{release} @@ -177,6 +206,7 @@ Requires: python-sssdconfig = %{version}-%{release} %global mcpath %{sssdstatedir}/mc %global pubconfpath %{sssdstatedir}/pubconf %global gpocachepath %{sssdstatedir}/gpo_cache +%global secdbpath %{sssdstatedir}/secrets ### Build Dependencies ### @@ -193,23 +223,18 @@ BuildRequires: libtdb-devel BuildRequires: libldb-devel >= %{ldb_version} BuildRequires: libdhash-devel >= 0.4.2 BuildRequires: libcollection-devel -BuildRequires: libini_config-devel >= 1.1.0-24 +BuildRequires: libini_config-devel >= 1.3.0 BuildRequires: dbus-devel BuildRequires: dbus-libs BuildRequires: openldap-devel BuildRequires: pam-devel BuildRequires: nss-devel -BuildRequires: openssl-devel BuildRequires: nspr-devel 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 @@ -218,20 +243,22 @@ BuildRequires: libselinux-devel BuildRequires: libsemanage-devel BuildRequires: bind-utils BuildRequires: keyutils-libs-devel -BuildRequires: libnl3-devel BuildRequires: gettext-devel BuildRequires: pkgconfig -BuildRequires: glib2-devel BuildRequires: diffstat BuildRequires: findutils -BuildRequires: samba4-devel >= 4.0.0-59beta2 +BuildRequires: glib2-devel BuildRequires: selinux-policy-targeted +BuildRequires: libnl3-devel BuildRequires: systemd-devel -BuildRequires: libsmbclient-devel %if (0%{?with_cifs_utils_plugin} == 1) BuildRequires: cifs-utils-devel %endif BuildRequires: libnfsidmap-devel +BuildRequires: samba4-devel >= 4.0.0-59beta2 +BuildRequires: libsmbclient-devel +BuildRequires: systemtap-sdt-devel +BuildRequires: jansson-devel %description Provides a set of daemons to manage access to remote directories and @@ -252,15 +279,10 @@ 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.1.0-24 +Requires: libsss_sudo%{?_isa} = %{version}-%{release} +Requires: libsss_autofs%{?_isa} = %{version}-%{release} Requires(post): systemd-units chkconfig Requires(preun): systemd-units chkconfig Requires(postun): systemd-units chkconfig @@ -268,12 +290,8 @@ Requires(pre): shadow-utils ### Provides ### -Provides: libsss_sudo = %{version}-%{release} -Obsoletes: libsss_sudo <= 1.10.0-7%{?dist}.beta1 Provides: libsss_sudo-devel = %{version}-%{release} Obsoletes: libsss_sudo-devel <= 1.10.0-7%{?dist}.beta1 -Provides: libsss_autofs = %{version}-%{release} -Obsoletes: libsss_autofs <= 1.10.0-7%{?dist}.beta1 %description common Common files for the SSSD. The common package includes all the files needed @@ -293,6 +311,24 @@ Requires(preun): /usr/sbin/alternatives Provides the libraries needed by the PAM and NSS stacks to connect to the SSSD service. +%package -n libsss_sudo +Summary: A library to allow communication between SUDO and SSSD +Group: Development/Libraries +License: LGPLv3+ +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description -n libsss_sudo +A utility library to allow communication between SUDO and SSSD + +%package -n libsss_autofs +Summary: A library to allow communication between Autofs and SSSD +Group: Development/Libraries +License: LGPLv3+ + +%description -n libsss_autofs +A utility library to allow communication between Autofs and SSSD + %package tools Summary: Userspace tools for use with the SSSD Group: Applications/System @@ -309,6 +345,7 @@ Also provides several other administrative tools: * sss_debuglevel to change the debug level on the fly * sss_seed which pre-creates a user entry for use in kickstarts * sss_obfuscate for generating an obfuscated LDAP password + * sssctl -- an sssd status and control utility %package -n python-sssdconfig Summary: SSSD and IPA configuration file manipulation classes and functions @@ -317,7 +354,7 @@ License: GPLv3+ BuildArch: noarch %description -n python-sssdconfig -Provides python files for manipulation SSSD and IPA configuration files. +Provides python2 files for manipulation SSSD and IPA configuration files. %package -n python-sss Summary: Python2 bindings for sssd @@ -378,8 +415,6 @@ Requires: sssd-krb5-common = %{version}-%{release} Provides the Kerberos back end that the SSSD can utilize authenticate against a Kerberos server. -# RHEL 5 is too old to support the PAC responder -%if !0%{?is_rhel5} %package common-pac Summary: Common files needed for supporting PAC processing Group: Applications/System @@ -389,7 +424,6 @@ Requires: sssd-common = %{version}-%{release} %description common-pac Provides common files needed by SSSD providers such as IPA and Active Directory for handling Kerberos PACs. -%endif #is_rhel5 %package ipa Summary: The IPA back end of the SSSD @@ -474,7 +508,7 @@ Requires: libipa_hbac = %{version}-%{release} Utility library to validate FreeIPA HBAC rules for authorization requests %package -n python-libipa_hbac -Summary: Python bindings for the FreeIPA HBAC Evaluator library +Summary: Python2 bindings for the FreeIPA HBAC Evaluator library Group: Development/Libraries License: LGPLv3+ Requires: libipa_hbac = %{version}-%{release} @@ -486,26 +520,26 @@ The python-libipa_hbac contains the bindings so that libipa_hbac can be used by Python applications. %package -n libsss_nss_idmap -Summary: Library for SID based lookups +Summary: Library for SID and certificate based lookups Group: Development/Libraries License: LGPLv3+ Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig %description -n libsss_nss_idmap -Utility library for SID based lookups +Utility library for SID and certificate based lookups %package -n libsss_nss_idmap-devel -Summary: Library for SID based lookups +Summary: Library for SID and certificate based lookups Group: Development/Libraries License: LGPLv3+ Requires: libsss_nss_idmap = %{version}-%{release} %description -n libsss_nss_idmap-devel -Utility library for SID based lookups +Utility library for SID and certificate based lookups %package -n python-libsss_nss_idmap -Summary: Python bindings for libsss_nss_idmap +Summary: Python2 bindings for libsss_nss_idmap Group: Development/Libraries License: LGPLv3+ Requires: libsss_nss_idmap = %{version}-%{release} @@ -527,11 +561,23 @@ Requires: sssd-common = %{version}-%{release} 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. +%if (0%{?install_pcscd_polkit_rule} == 1) +%package polkit-rules +Summary: Rules for polkit integration for SSSD +Group: Applications/System +License: GPLv3+ +Requires: polkit >= 0.106 +Requires: sssd-common = %{version}-%{release} + +%description polkit-rules +Provides rules for polkit integration with SSSD. This is required +for smartcard support. +%endif + %package -n libsss_simpleifp Summary: The SSSD D-Bus responder helper library Group: Development/Libraries License: GPLv3+ -Requires: dbus-libs Requires: sssd-dbus = %{version}-%{release} Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig @@ -567,6 +613,15 @@ Conflicts: libwbclient-devel < 4.1.12 %description libwbclient-devel Development libraries for the SSSD libwbclient implementation. +%package winbind-idmap +Summary: SSSSD's idmap_sss Backend for Winbind +Group: Applications/System +License: GPLv3+ and LGPLv3+ + +%description winbind-idmap +The idmap_sss module provides a way for Winbind to call SSSD to map UIDs/GIDs +and SIDs. + %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" @@ -590,19 +645,15 @@ for p in %patches ; do UpdateTimestamps -p1 $p done -# patch(1) doesn't handle binary files we need for tests. Package them -# as additional sources and add to the source tree -mkdir src/tests/cmocka/p11_nssdb/ -cp %{SOURCE1} src/tests/cmocka/p11_nssdb/ -cp %{SOURCE2} src/tests/cmocka/p11_nssdb/ - %build autoreconf -ivf + %configure \ + --with-test-dir=/dev/shm \ --with-db-path=%{dbpath} \ + --with-mcache-path=%{mcpath} \ --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 \ @@ -612,14 +663,14 @@ autoreconf -ivf --disable-static \ --disable-rpath \ --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} \ --without-python3-bindings \ - --with-ad-gpo-default=permissive + --with-ad-gpo-default=permissive \ + %{?enable_polkit_rules_option} \ + %{?enable_systemtap_opt} make %{?_smp_mflags} all docs @@ -629,7 +680,6 @@ make %{?_smp_mflags} check VERBOSE=yes unset CK_TIMEOUT_MULTIPLIER %install -rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT @@ -642,10 +692,6 @@ fi # Prepare language files /usr/lib/rpm/find-lang.sh $RPM_BUILD_ROOT sssd -# Prepare empty config file -mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sssd -touch $RPM_BUILD_ROOT/%{_sysconfdir}/sssd/sssd.conf - # Copy default logrotate file mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d install -m644 src/examples/logrotate $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/sssd @@ -654,6 +700,12 @@ install -m644 src/examples/logrotate $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/s mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/rwtab.d install -m644 src/examples/rwtab $RPM_BUILD_ROOT%{_sysconfdir}/rwtab.d/sssd +%if (0%{?with_cifs_utils_plugin} == 1) +# Create directory for cifs-idmap alternative +# Otherwise this directory could not be owned by sssd-client +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/cifs-utils +%endif + # Replace sysv init script with systemd unit file rm -f $RPM_BUILD_ROOT/%{_initrddir}/%{name} mkdir -p $RPM_BUILD_ROOT/%{_unitdir}/ @@ -732,10 +784,6 @@ do cat sssd_$provider.lang done - -%clean -rm -rf $RPM_BUILD_ROOT - %files %defattr(-,root,root,-) %doc COPYING @@ -744,14 +792,17 @@ rm -rf $RPM_BUILD_ROOT %defattr(-,root,root,-) %doc COPYING %doc src/examples/sssd-example.conf -%{_unitdir}/sssd.service %{_sbindir}/sssd +%{_unitdir}/sssd.service +%{_unitdir}/sssd-secrets.socket +%{_unitdir}/sssd-secrets.service %dir %{_libexecdir}/%{servicename} %{_libexecdir}/%{servicename}/sssd_be %{_libexecdir}/%{servicename}/sssd_nss %{_libexecdir}/%{servicename}/sssd_pam %{_libexecdir}/%{servicename}/sssd_autofs +%{_libexecdir}/%{servicename}/sssd_secrets %{_libexecdir}/%{servicename}/sssd_ssh %{_libexecdir}/%{servicename}/sssd_sudo %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/p11_child @@ -770,8 +821,6 @@ rm -rf $RPM_BUILD_ROOT %{_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 @@ -784,21 +833,27 @@ rm -rf $RPM_BUILD_ROOT %dir %{_localstatedir}/cache/krb5rcache %attr(700,sssd,sssd) %dir %{dbpath} %attr(755,sssd,sssd) %dir %{mcpath} +%attr(700,root,root) %dir %{secdbpath} %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/passwd %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/group %ghost %attr(0644,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/initgroups %attr(755,sssd,sssd) %dir %{pipepath} +%attr(750,sssd,root) %dir %{pipepath}/private %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 +%attr(711,sssd,sssd) %dir %{_sysconfdir}/sssd/conf.d %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 +%dir %{_sysconfdir}/logrotate.d %config(noreplace) %{_sysconfdir}/logrotate.d/sssd +%dir %{_sysconfdir}/rwtab.d %config(noreplace) %{_sysconfdir}/rwtab.d/sssd %dir %{_datadir}/sssd + +%{_datadir}/sssd/cfg_rules.ini %{_datadir}/sssd/sssd.api.conf %{_datadir}/sssd/sssd.api.d %{_mandir}/man1/sss_ssh_authorizedkeys.1* @@ -809,6 +864,20 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man5/sss_rpcidmapd.5* %{_mandir}/man8/sssd.8* %{_mandir}/man8/sss_cache.8* +%if (0%{?enable_systemtap} == 1) +%dir %{_datadir}/sssd/systemtap +%{_datadir}/sssd/systemtap/id_perf.stp +%{_datadir}/sssd/systemtap/nested_group_perf.stp +%dir %{_datadir}/systemtap +%dir %{_datadir}/systemtap/tapset +%{_datadir}/systemtap/tapset/sssd.stp +%{_datadir}/systemtap/tapset/sssd_functions.stp +%endif + +%if (0%{?install_pcscd_polkit_rule} == 1) +%files polkit-rules +%{_datadir}/polkit-1/rules.d/* +%endif %files ldap -f sssd_ldap.lang %defattr(-,root,root,-) @@ -819,6 +888,7 @@ rm -rf $RPM_BUILD_ROOT %files krb5-common %defattr(-,root,root,-) %doc COPYING +%attr(755,sssd,sssd) %dir %{pubconfpath}/krb5.include.d %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/ldap_child %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/krb5_child @@ -836,7 +906,6 @@ rm -rf $RPM_BUILD_ROOT %files ipa -f sssd_ipa.lang %defattr(-,root,root,-) %doc COPYING -%attr(755,root,root) %dir %{pubconfpath}/krb5.include.d %attr(700,sssd,sssd) %dir %{keytabdir} %{_libdir}/%{name}/libsss_ipa.so %attr(4750,root,sssd) %{_libexecdir}/%{servicename}/selinux_child @@ -846,7 +915,6 @@ rm -rf $RPM_BUILD_ROOT %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* @@ -872,12 +940,7 @@ rm -rf $RPM_BUILD_ROOT %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 @@ -891,15 +954,30 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so %{_libdir}/krb5/plugins/authdata/sssd_pac_plugin.so %if (0%{?with_cifs_utils_plugin} == 1) +%dir %{_libdir}/cifs-utils %{_libdir}/cifs-utils/cifs_idmap_sss.so +%dir %{_sysconfdir}/cifs-utils %ghost %{_sysconfdir}/cifs-utils/idmap-plugin %endif %if (0%{?with_krb5_localauth_plugin} == 1) +%dir %{_libdir}/%{name} +%dir %{_libdir}/%{name}/modules %{_libdir}/%{name}/modules/sssd_krb5_localauth_plugin.so %endif %{_mandir}/man8/pam_sss.8* %{_mandir}/man8/sssd_krb5_locator_plugin.8* +%files -n libsss_sudo +%defattr(-,root,root,-) +%doc src/sss_client/COPYING +%{_libdir}/libsss_sudo.so* + +%files -n libsss_autofs +%defattr(-,root,root,-) +%doc src/sss_client/COPYING src/sss_client/COPYING.LESSER +%dir %{_libdir}/%{name}/modules +%{_libdir}/%{name}/modules/libsss_autofs.so + %files tools -f sssd_tools.lang %defattr(-,root,root,-) %doc COPYING @@ -914,6 +992,7 @@ rm -rf $RPM_BUILD_ROOT %{_sbindir}/sss_override %{_sbindir}/sss_debuglevel %{_sbindir}/sss_seed +%{_sbindir}/sssctl %{_mandir}/man8/sss_groupadd.8* %{_mandir}/man8/sss_groupdel.8* %{_mandir}/man8/sss_groupmod.8* @@ -925,6 +1004,7 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man8/sss_override.8* %{_mandir}/man8/sss_debuglevel.8* %{_mandir}/man8/sss_seed.8* +%{_mandir}/man8/sssctl.8* %files -n python-sssdconfig -f python_sssdconfig.lang %defattr(-,root,root,-) @@ -934,12 +1014,10 @@ rm -rf $RPM_BUILD_ROOT %files -n python-sss %defattr(-,root,root,-) %{python_sitearch}/pysss.so -%{python_sitearch}/_py2sss.so %files -n python-sss-murmur %defattr(-,root,root,-) %{python_sitearch}/pysss_murmur.so -%{python_sitearch}/_py2sss_murmur.so %files -n libsss_idmap %defattr(-,root,root,-) @@ -965,11 +1043,6 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/libipa_hbac.so %{_libdir}/pkgconfig/ipa_hbac.pc -%files -n python-libipa_hbac -%defattr(-,root,root,-) -%{python_sitearch}/pyhbac.so -%{python_sitearch}/_py2hbac.so - %files -n libsss_nss_idmap %defattr(-,root,root,-) %doc src/sss_client/COPYING src/sss_client/COPYING.LESSER @@ -985,10 +1058,15 @@ rm -rf $RPM_BUILD_ROOT %files -n python-libsss_nss_idmap %defattr(-,root,root,-) %{python_sitearch}/pysss_nss_idmap.so -%{python_sitearch}/_py2sss_nss_idmap.so + +%files -n python-libipa_hbac +%defattr(-,root,root,-) +%{python_sitearch}/pyhbac.so %files libwbclient %defattr(-,root,root,-) +%dir %{_libdir}/%{name} +%dir %{_libdir}/%{name}/modules %{_libdir}/%{name}/modules/libwbclient.so.* %files libwbclient-devel @@ -997,6 +1075,11 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/%{name}/modules/libwbclient.so %{_libdir}/pkgconfig/wbclient_sssd.pc +%files winbind-idmap +%dir %{_libdir}/samba/idmap +%{_libdir}/samba/idmap/sss.so +%{_mandir}/man8/idmap_sss.8* + %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 @@ -1011,17 +1094,17 @@ getent passwd sssd >/dev/null || useradd -r -g sssd -d / -s /sbin/nologin -c "Us /bin/systemctl status sssd.service >/dev/null 2>&1 && touch /var/tmp/sssd.upgrade || : %post common -if [ $1 -ge 1 ] ; then - # Initial installation - /bin/systemctl daemon-reload >/dev/null 2>&1 || : -fi +%systemd_post sssd.service +%systemd_post sssd-secrets.socket %preun common -if [ $1 -eq 0 ] ; then - # Package removal, not upgrade - /bin/systemctl --no-reload disable sssd.service > /dev/null 2>&1 || : - /bin/systemctl stop sssd.service > /dev/null 2>&1 || : -fi +%systemd_preun sssd.service +%systemd_preun sssd-secrets.socket + +%postun common +%systemd_postun_with_restart sssd.service +%systemd_postun_with_restart sssd-secrets.socket +%systemd_postun_with_restart sssd-secrets.service %if (0%{?with_cifs_utils_plugin} == 1) %post client @@ -1038,6 +1121,10 @@ fi %postun client -p /sbin/ldconfig +%post -n libsss_sudo -p /sbin/ldconfig + +%postun -n libsss_sudo -p /sbin/ldconfig + %post -n libipa_hbac -p /sbin/ldconfig %postun -n libipa_hbac -p /sbin/ldconfig @@ -1050,6 +1137,10 @@ fi %postun -n libsss_nss_idmap -p /sbin/ldconfig +%post -n libsss_simpleifp -p /sbin/ldconfig + +%postun -n libsss_simpleifp -p /sbin/ldconfig + %post libwbclient %{_sbindir}/update-alternatives \ --install %{_libdir}/libwbclient.so.%{libwbc_alternatives_version} \ @@ -1087,51 +1178,302 @@ fi /usr/bin/rm -f /var/tmp/sssd.upgrade || : %changelog -* Thu Jul 14 2016 Jakub Hrozek - 1.13.0-40.12 -- Resolves: rhbz#1356433 - ldap_group_external_member is no set for the - IPA provider +* Tue Sep 20 2016 Jakub Hrozek - 1.14.0-43 +- Resolves: rhbz#1376831 - sssd-common is missing dependency on sssd-sudo + +* Fri Sep 16 2016 Jakub Hrozek - 1.14.0-42 +- Resolves: rhbz#1371631 - login using gdm calls for gdm-smartcard when + smartcard authentication is not enabled + +* Wed Sep 14 2016 Jakub Hrozek - 1.14.0-41 +- Resolves: rhbz#1373420 - sss_override fails to export + +* Wed Sep 14 2016 Jakub Hrozek - 1.14.0-40 +- Resolves: rhbz#1375299 - sss_groupshow fails with error "No such + group in local domain. Printing groups only + allowed in local domain" -* Fri Jul 8 2016 Jakub Hrozek - 1.13.0-40.11 -- Resolves: rhbz#1353605 - sssd-libwbclient: wbcSidsToUnixIds should not +* Wed Sep 14 2016 Jakub Hrozek - 1.14.0-39 +- Resolves: rhbz#1375182 - SSSD goes offline when the LDAP server returns + sizelimit exceeded + +* Mon Sep 12 2016 Jakub Hrozek - 1.14.0-38 +- Resolves: rhbz#1372753 - Access denied for user when access_provider = + krb5 is set in sssd.conf + +* Mon Sep 12 2016 Jakub Hrozek - 1.14.0-37 +- Resolves: rhbz#1373444 - unable to create group in sssd cache +- Resolves: rhbz#1373577 - unable to add local user in sssd to a group in sssd + +* Wed Sep 7 2016 Jakub Hrozek - 1.14.0-36 +- Resolves: rhbz#1369118 - Don't enable the default shadowtils domain in RHEL + +* Mon Sep 5 2016 Jakub Hrozek - 1.14.0-35 +- Fix permissions for the private pipe directory +- Resolves: rhbz#1362716 - selinux avc denial for vsftp login as ipa user + +* Fri Sep 2 2016 Jakub Hrozek - 1.14.0-34 +- Resolves: rhbz#1371977 - resolving IPA nested user groups is broken in 1.14 + +* Fri Sep 2 2016 Jakub Hrozek - 1.14.0-33 +- Resolves: rhbz#1368496 - sssd is not able to authenticate with alias + +* Fri Sep 2 2016 Jakub Hrozek - 1.14.0-32 +- Resolves: rhbz#1371152 - SSSD qualifies principal twice in IPA-AD trust + if the principal attribute doesn't exist on the + AD side + +* Fri Aug 26 2016 Jakub Hrozek - 1.14.0-31 +- Apply forgotten patch +- Resolves: rhbz#1368496 - sssd is not able to authenticate with alias +- Resolves: rhbz#1366470 - sssd: throw away the timestamp cache if + re-initializing the persistent cache +- Fix deleting non-existent secret +- Related: rhbz#1311056 - Add a Secrets as a Service component + +* Fri Aug 26 2016 Jakub Hrozek - 1.14.0-30 +- Resolves: rhbz#1362716 - selinux avc denial for vsftp login as ipa user + +* Fri Aug 26 2016 Jakub Hrozek - 1.14.0-29 +- Resolves: rhbz#1368496 - sssd is not able to authenticate with alias + +* Fri Aug 26 2016 Jakub Hrozek - 1.14.0-28 +- Resolves: rhbz#1364033 - sssd exits if clock is adjusted backwards + after boot + +* Fri Aug 19 2016 Jakub Hrozek - 1.14.0-27 +- Resolves: rhbz#1362023 - SSSD fails to start when ldap_user_extra_attrs + contains mail + +* Fri Aug 19 2016 Jakub Hrozek - 1.14.0-26 +- Resolves: rhbz#1368324 - libsss_autofs.so is packaged in two packages + sssd-common and libsss_autofs + +* Fri Aug 19 2016 Jakub Hrozek - 1.14.0-25 +- Fix RPM scriptlet plumbing for the sssd-secrets responder +- Related: rhbz#1311056 - Add a Secrets as a Service component + +* Wed Aug 17 2016 Jakub Hrozek - 1.14.0-24 +- Add socket-activation plumbing for the sssd-secrets responder +- Related: rhbz#1311056 - Add a Secrets as a Service component + +* Wed Aug 17 2016 Jakub Hrozek - 1.14.0-23 +- Own the secrets directory +- Related: rhbz#1311056 - Add a Secrets as a Service component + +* Wed Aug 17 2016 Jakub Hrozek - 1.14.0-22 +- Resolves: rhbz#1268874 - Add an option to disable checking for trusted + domains in the subdomains provider + +* Tue Aug 16 2016 Jakub Hrozek - 1.14.0-21 +- Resolves: rhbz#1271280 - sssd stores and returns incorrect information + about empty netgroup (ldap-server: 389-ds) + +* Tue Aug 16 2016 Jakub Hrozek - 1.14.0-20 +- Resolves: rhbz#1290500 - [feat] command to manually list + fo_add_server_to_list information + +* Tue Aug 16 2016 Jakub Hrozek - 1.14.0-19 +- Add several small fixes related to the config API +- Related: rhbz#1072458 - [RFE] SSSD configuration file test tool (sssd_check) + +* Thu Aug 11 2016 Jakub Hrozek - 1.14.0-18 +- Resolves: rhbz#1349900 - gpo search errors out and gpo_cache file is + never created + +* Wed Aug 10 2016 Jakub Hrozek - 1.14.0-17 +- Fix regressions in the simple access provider +- Resolves: rhbz#1360806 - sssd does not start if sub-domain user is used + with simple access provider +- Apply a number of specfile patches to better match the upstream spefile +- Related: rhbz#1290381 - Rebase SSSD to 1.14.x in RHEL-7.3 + +* Wed Aug 10 2016 Jakub Hrozek - 1.14.0-16 +- Cherry-pick patches from upstream that fix several regressions +- Avoid checking local users in all cases +- Resolves: rhbz#1353951 - sssd_pam leaks file descriptors + +* Mon Aug 8 2016 Jakub Hrozek - 1.14.0-15 +- Resolves: rhbz#1364118 - [abrt] [faf] sssd: unknown function(): + /usr/libexec/sssd/sssd_nss killed by 11 +- Resolves: rhbz#1361563 - Wrong pam error code returned for password + change in offline mode + +* Fri Jul 29 2016 Jakub Hrozek - 1.14.0-14 +- Resolves: rhbz#1309745 - Support multiple principals for IPA users + +* Fri Jul 29 2016 Jakub Hrozek - 1.14.0-13 +- Resolves: rhbz#1304992 - Handle overriden name of members in the + memberUid attribute + +* Wed Jul 27 2016 Jakub Hrozek - 1.14.0-12 +- handle unresolvable sites more gracefully +- Resolves: rhbz#1346011 - sssd is looking at a server in the GC of a + subdomain, not the root domain. +- fix compilation warnings in unit tests + +* Wed Jul 27 2016 Jakub Hrozek - 1.14.0-11 +- fix capaths output +- Resolves: rhbz#1344940 - GSSAPI error causes failures for child domain + user logins across IPA - AD trust +- also fix Coverity issues in the secrets responder and suppress noisy + debug messages when setting the timestamp cache + +* Tue Jul 19 2016 Jakub Hrozek - 1.14.0-10 +- Resolves: rhbz#1356577 - sssctl: Time stamps without time zone information + +* Tue Jul 19 2016 Jakub Hrozek - 1.14.0-9 +- Resolves: rhbz#1354414 - New or modified ID-View User overrides are not + visible unless rm -f /var/lib/sss/db/*cache* + +* Mon Jul 18 2016 Jakub Hrozek - 1.14.0-8 +- Resolves: rhbz#1211631 - [RFE] Support of UPN for IdM trusted domains + +* Thu Jul 14 2016 Jakub Hrozek - 1.14.0-7 +- Resolves: rhbz#1350520 - [abrt] sssd-common: ipa_dyndns_update_send(): + sssd_be killed by SIGSEGV + +* Wed Jul 13 2016 Jakub Hrozek - 1.14.0-6 +- Resolves: rhbz#1349882 - sssd does not work under non-root user +- Also cherry-pick a few patches from upstream to fix config schema +- Related: rhbz#1072458 - [RFE] SSSD configuration file test tool (sssd_check) + +* Wed Jul 13 2016 Jakub Hrozek - 1.14.0-5 +- Sync a few minor patches from upstream +- Fix sssctl manpage +- Fix nss-tests unit test on big-endian machines +- Fix several issues in the config schema +- Related: rhbz#1072458 - [RFE] SSSD configuration file test tool (sssd_check) + +* Wed Jul 13 2016 Jakub Hrozek - 1.14.0-4 +- Bundle http-parser +- Resolves: rhbz#1311056 - Add a Secrets as a Service component + +* Tue Jul 12 2016 Jakub Hrozek - 1.14.0-3 +- Sync a few minor patches from upstream +- Fix a failover issue +- Resolves: rhbz#1334749 - sssd fails to mark a connection as bad on + searches that time out + +* Mon Jul 11 2016 Jakub Hrozek - 1.14.0-2 +- Explicitly BuildRequire newer ding-libs +- Resolves: rhbz#1072458 - [RFE] SSSD configuration file test tool (sssd_check) + +* Fri Jul 8 2016 Jakub Hrozek - 1.14.0-1 +- New upstream release 1.14.0 +- Resolves: rhbz#1290381 - Rebase SSSD to 1.14.x in RHEL-7.3 +- Resolves: rhbz#835492 - [RFE] SSSD admin tool request - force reload +- Resolves: rhbz#1072458 - [RFE] SSSD configuration file test tool (sssd_check) +- Resolves: rhbz#1278691 - Please fix rfc2307 autofs schema defaults +- Resolves: rhbz#1287209 - default_domain_suffix Appended to User Name +- Resolves: rhbz#1300663 - Improve sudo protocol to support configurations + with default_domain_suffix +- Resolves: rhbz#1312275 - Support authentication indicators from IPA + +* Thu Jun 30 2016 Jakub Hrozek - 1.14.0beta1-2 +- Resolves: rhbz#1290381 - Rebase SSSD to 1.14.x in RHEL-7.3 +- Resolves: rhbz#790113 - [RFE] "include" directive in sssd.conf +- Resolves: rhbz#874985 - [RFE] AD provider support for automount lookups +- Resolves: rhbz#879333 - [RFE] SSSD admin tool request - status overview +- Resolves: rhbz#1140022 - [RFE]Allow sssd to add a new option that would + specify which server to update DNS with +- Resolves: rhbz#1290380 - RFE: Improve SSSD performance in large + environments +- Resolves: rhbz#883886 - sssd: incorrect checks on length values during + packet decoding +- Resolves: rhbz#988207 - sssd does not detail which line in configuration + is invalid +- Resolves: rhbz#1007969 - sssd_cache does not remove have an option to + remove the sssd database +- Resolves: rhbz#1103249 - PAC responder needs much time to process large + group lists +- Resolves: rhbz#1118257 - Users in ipa groups, added to netgroups are + not resovable +- Resolves: rhbz#1269018 - Too much logging from sssd_be +- Resolves: rhbz#1293695 - sssd mixup nested group from AD trusted domains +- Resolves: rhbz#1308935 - After removing certificate from user in IPA + and even after sss_cache, FindByCertificate + still finds the user +- Resolves: rhbz#1315766 - SSSD PAM module does not support multiple + password prompts (e.g. Password + Token) with sudo +- Resolves: rhbz#1316164 - SSSD fails to process GPO from Active Directory +- Resolves: rhbz#1322458 - sssd_be[11010]: segfault at 0 ip 00007ff889ff61bb + sp 00007ffc7d66a3b0 error 4 in + libsss_ipa.so[7ff889fcf000+5d000] + +* Mon Jun 20 2016 Jakub Hrozek - 1.14.0alpha-1 +- Resolves: rhbz#1290381 - Rebase SSSD to 1.14.x in RHEL-7.3 +- The rebase includes fixes for the following bugzillas: +- Resolves: rhbz#789477 - [RFE] SUDO: Support the IPA schema +- Resolves: rhbz#1059972 - RFE: SSSD: Automatically assign new slices for + any AD domain +- Resolves: rhbz#1233200 - man sssd.conf should clarify details about + subdomain_inherit option. +- Resolves: rhbz#1238144 - Need better libhbac debuging added to sssd +- Resolves: rhbz#1265366 - sss_override segfaults when accidentally adding + --help flag to some commands +- Resolves: rhbz#1269512 - sss_override: memory violation +- Resolves: rhbz#1278566 - crash in sssd when non-Englsh locale is used + and pam_strerror prints non-ASCII characters +- Resolves: rhbz#1283686 - groups get deleted from the cache +- Resolves: rhbz#1290378 - Smart Cards: Certificate in the ID View +- Resolves: rhbz#1292238 - extreme memory usage in libnfsidmap sss.so + plug-in when resolving groups with many members +- Resolves: rhbz#1292456 - sssd_be AD segfaults on missing A record +- Resolves: rhbz#1294670 - Local users with local sudo rules causes + LDAP queries +- Resolves: rhbz#1296618 - Properly remove OriginalMemberOf attribute in + SSSD cache if user has no secondary groups anymore +- Resolves: rhbz#1299553 - Cannot retrieve users after upgrade from 1.12 + to 1.13 +- Resolves: rhbz#1302821 - Cannot start sssd after switching to non-root +- Resolves: rhbz#1310877 - [RFE] Support Automatic Renewing of Kerberos + Host Keytabs +- Resolves: rhbz#1313014 - sssd is not closing sockets properly +- Resolves: rhbz#1318996 - SSSD does not fail over to next GC +- Resolves: rhbz#1327270 - local overrides: issues with sub-domain users + and mixed case names +- Resolves: rhbz#1342547 - sssd-libwbclient: wbcSidsToUnixIds should not fail on lookup errors -* Tue Jun 21 2016 Jakub Hrozek - 1.13.0-40.10 -- Resolves: rhbz#1347723 - sssd is not closing sockets properly +* Tue May 24 2016 Jakub Hrozek - 1.13.0-50 +- Build the PAC plugin with krb5-1.14 +- Related: rhbz#1336688 - sssd tries to resolve global catalog servers + from AD forest sub-domains in AD-IPA trust setup -* Tue May 24 2016 Jakub Hrozek - 1.13.0-40.9 -- Resolves: rhbz#1339509 - sssd tries to resolve global catalog servers +* Tue May 24 2016 Jakub Hrozek - 1.13.0-49 +- Resolves: rhbz#1336688 - sssd tries to resolve global catalog servers from AD forest sub-domains in AD-IPA trust setup -* Tue May 24 2016 Jakub Hrozek - 1.13.0-40.8 -- Resolves: rhbz#1339258 - [sssd] Trusted (AD) user's info stays in sssd +* Tue May 24 2016 Jakub Hrozek - 1.13.0-48 +- Resolves: rhbz#1290853 - [sssd] Trusted (AD) user's info stays in sssd cache for much more than expected. -* Tue May 24 2016 Jakub Hrozek - 1.13.0-40.7 -- Resolves: rhbz#1339207 - sssd_nss memory usage keeps growing when trying +* Mon May 23 2016 Jakub Hrozek - 1.13.0-47 +- Resolves: rhbz#1336706 - sssd_nss memory usage keeps growing when trying to retrieve non-existing netgroups -* Thu May 19 2016 Jakub Hrozek - 1.13.0-40.6 -- Resolves: rhbz#1337292 - In IPA-AD trust environment access is granted +* Tue May 17 2016 Jakub Hrozek - 1.13.0-46 +- Resolves: rhbz#1296902 - In IPA-AD trust environment access is granted to AD user even if the user is disabled on AD. -* Tue May 17 2016 Jakub Hrozek - 1.13.0-40.5 -- Resolves: rhbz#1336836 - IPA provider crashes if a netgroup from a +* Tue May 17 2016 Jakub Hrozek - 1.13.0-45 +- Resolves: rhbz#1334159 - IPA provider crashes if a netgroup from a trusted domain is requested -* Mon Apr 18 2016 Jakub Hrozek - 1.13.0-40.4 -- Resolves: rhbz#1324442 - sssd be memory leak in sssd's memberof plugin +* Mon Apr 18 2016 Jakub Hrozek - 1.13.0-44 +- Resolves: rhbz#1308913 - sssd be memory leak in sssd's memberof plugin - More patches from upstream related to the memory leak -* Wed Apr 6 2016 Jakub Hrozek - 1.13.0-40.3 -- Resolves: rhbz#1324442 - sssd be memory leak in sssd's memberof plugin +* Fri Apr 1 2016 Jakub Hrozek - 1.13.0-43 +- Resolves: rhbz#1308913 - sssd be memory leak in sssd's memberof plugin -* Wed Feb 24 2016 Jakub Hrozek - 1.13.0-40.2 -- Resolves: rhbz#1311569 - [RFE] IPA: resolve external group memberships +* Wed Feb 24 2016 Jakub Hrozek - 1.13.0-42 +- Resolves: rhbz#1300740 - [RFE] IPA: resolve external group memberships of IPA groups during getgrnam and getgrgid -* Tue Nov 24 2015 Jakub Hrozek - 1.13.0-40.1 +* Tue Nov 24 2015 Jakub Hrozek - 1.13.0-41 - Resolves: rhbz#1284814 - sssd: [sysdb_add_user] (0x0400): Error: 17 - (File exists) * Wed Oct 14 2015 Jakub Hrozek - 1.13.0-40 - Resolves: rhbz#1270827 - local overrides: don't contact server with