diff --git a/SOURCES/0055-krb5_locator-always-use-port-88-for-master-KDC.patch b/SOURCES/0055-krb5_locator-always-use-port-88-for-master-KDC.patch new file mode 100644 index 0000000..1bd571e --- /dev/null +++ b/SOURCES/0055-krb5_locator-always-use-port-88-for-master-KDC.patch @@ -0,0 +1,402 @@ +From 941a381d7a7be2af73e41bd584aca4d22675d765 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 15 Feb 2019 16:54:19 +0100 +Subject: [PATCH] krb5_locator: always use port 88 for master KDC + +If the kpasswdinfo file exists and the found IP address includes a port +number as well the master KDC lookup will use this port number which is +most probably wrong. Better use the default port 88 always for master +KDC lookups. + +This patch also updates the man page for the locator plugin which was +quite outdated. + +Related to https://pagure.io/SSSD/sssd/issue/3958 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 05350abdf2ab98770ca296b9485578218644a2a7) +--- + src/krb5_plugin/sssd_krb5_locator_plugin.c | 43 +++-- + src/man/sssd_krb5_locator_plugin.8.xml | 76 +++++---- + .../cmocka/test_sssd_krb5_locator_plugin.c | 156 ++++++++++++++++++ + 3 files changed, 233 insertions(+), 42 deletions(-) + +diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c +index 952d487c2..fc5a4235d 100644 +--- a/src/krb5_plugin/sssd_krb5_locator_plugin.c ++++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c +@@ -80,6 +80,7 @@ struct sssd_ctx { + struct addr_port *kpasswd_addr; + bool debug; + bool disabled; ++ bool kpasswdinfo_used; + }; + + void plugin_debug_fn(const char *format, ...) +@@ -411,6 +412,7 @@ krb5_error_code sssd_krb5_locator_init(krb5_context context, + ctx->disabled = true; + PLUGIN_DEBUG(("SSSD KRB5 locator plugin is disabled.\n")); + } ++ ctx->kpasswdinfo_used = false; + + *private_data = ctx; + +@@ -451,6 +453,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data, + struct addr_port *addr = NULL; + char port_str[PORT_STR_SIZE]; + size_t c; ++ bool force_port = false; + + if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE; + ctx = (struct sssd_ctx *) private_data; +@@ -478,20 +481,24 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data, + return KRB5_PLUGIN_NO_HANDLE; + } + +- if (svc == locate_service_kadmin || svc == locate_service_kpasswd || +- svc == locate_service_master_kdc) { +- ret = get_krb5info(realm, ctx, locate_service_kpasswd); ++ } ++ ++ if (ctx->kpasswd_addr == NULL ++ && (svc == locate_service_kadmin || svc == locate_service_kpasswd || ++ svc == locate_service_master_kdc)) { ++ ret = get_krb5info(realm, ctx, locate_service_kpasswd); ++ if (ret != EOK) { ++ PLUGIN_DEBUG(("reading kpasswd address failed, " ++ "using kdc address.\n")); ++ free_addr_port_list(&(ctx->kpasswd_addr)); ++ ret = copy_addr_port_list(ctx->kdc_addr, true, ++ &(ctx->kpasswd_addr)); + if (ret != EOK) { +- PLUGIN_DEBUG(("reading kpasswd address failed, " +- "using kdc address.\n")); +- free_addr_port_list(&(ctx->kpasswd_addr)); +- ret = copy_addr_port_list(ctx->kdc_addr, true, +- &(ctx->kpasswd_addr)); +- if (ret != EOK) { +- PLUGIN_DEBUG(("copying address list failed.\n")); +- return KRB5_PLUGIN_NO_HANDLE; +- } ++ PLUGIN_DEBUG(("copying address list failed.\n")); ++ return KRB5_PLUGIN_NO_HANDLE; + } ++ } else { ++ ctx->kpasswdinfo_used = true; + } + } + +@@ -507,6 +514,12 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data, + case locate_service_master_kdc: + addr = ctx->kpasswd_addr; + default_port = DEFAULT_KERBEROS_PORT; ++ if (ctx->kpasswdinfo_used) { ++ /* Use default port if the addresses from the kpasswdinfo ++ * files are used because the port numbers from the file will ++ * most probably not be suitable. */ ++ force_port = true; ++ } + break; + case locate_service_kadmin: + addr = ctx->kpasswd_addr; +@@ -539,11 +552,13 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data, + return KRB5_PLUGIN_NO_HANDLE; + } + +- if (strcmp(realm, ctx->sssd_realm) != 0) ++ if (strcmp(realm, ctx->sssd_realm) != 0 || addr == NULL) { + return KRB5_PLUGIN_NO_HANDLE; ++ } + + for (c = 0; addr[c].addr != NULL; c++) { +- port = (addr[c].port == 0 ? default_port : addr[c].port); ++ port = ((addr[c].port == 0 || force_port) ? default_port ++ : addr[c].port); + memset(port_str, 0, PORT_STR_SIZE); + ret = snprintf(port_str, PORT_STR_SIZE-1, "%u", port); + if (ret < 0 || ret >= (PORT_STR_SIZE-1)) { +diff --git a/src/man/sssd_krb5_locator_plugin.8.xml b/src/man/sssd_krb5_locator_plugin.8.xml +index d28546012..d77f59d6a 100644 +--- a/src/man/sssd_krb5_locator_plugin.8.xml ++++ b/src/man/sssd_krb5_locator_plugin.8.xml +@@ -20,40 +20,60 @@ + DESCRIPTION + + The Kerberos locator plugin +- sssd_krb5_locator_plugin is used by the Kerberos +- provider of +- +- sssd +- 8 +- +- to tell the Kerberos libraries what Realm and which KDC to use. +- Typically this is done in ++ sssd_krb5_locator_plugin is used by libkrb5 to ++ find KDCs for a given Kerberos realm. SSSD provides such a plugin to ++ guide all Kerberos clients on a system to a single KDC. In general ++ it should not matter to which KDC a client process is talking to. ++ But there are cases, e.g. after a password change, where not all ++ KDCs are in the same state because the new data has to be replicated ++ first. To avoid unexpected authentication failures and maybe even ++ account lockings it would be good to talk to a single KDC as long as ++ possible. ++ ++ ++ libkrb5 will search the locator plugin in the libkrb5 sub-directory ++ of the Kerberos plugin directory, see plugin_base_dir in + + krb5.conf + 5 + +- which is always read by the Kerberos libraries. To simplify the +- configuration the Realm and the KDC can be defined in +- +- sssd.conf +- 5 +- +- as described in +- +- sssd-krb5 +- 5 +- ++ for details. The plugin can only be disabled by removing the plugin ++ file. There is no option in the Kerberos configuration to disable ++ it. But the SSSD_KRB5_LOCATOR_DISABLE environment variable can be ++ used to disable the plugin for individual commands. Alternatively ++ the SSSD option krb5_use_kdcinfo=False can be used to not generate ++ the data needed by the plugin. With this the plugin is still ++ called but will provide no data to the caller so that libkrb5 can ++ fall back to other methods defined in krb5.conf. + + +- +- sssd +- 8 +- +- puts the Realm and the name or IP address of the KDC into the +- environment variables SSSD_KRB5_REALM and SSSD_KRB5_KDC respectively. +- When sssd_krb5_locator_plugin is called by the +- kerberos libraries it reads and evaluates these variables and returns +- them to the libraries. ++ The plugin reads the information about the KDCs of a given realm ++ from a file called kdcinfo.REALM. The file ++ should contain one or more IP addresses either in dotted-decimal ++ IPv4 notation or the hexadecimal IPv6 notation. An optional port ++ number can be added to the end separated with a colon, the IPv6 ++ address has to be enclosed in squared brackets in this case as ++ usual. Valid entries are: ++ ++ 1.2.3.4 ++ 5.6.7.8:99 ++ 2001:db8:85a3::8a2e:370:7334 ++ [2001:db8:85a3::8a2e:370:7334]:321 ++ ++ SSSD's krb5 auth-provider which is used by the IPA and AD providers ++ as well adds the address of the current KDC or domain controller ++ SSSD is using to this file. ++ ++ ++ In environments with read-only and read-write KDCs where clients are ++ expected to use the read-only instances for the general operations ++ and only the read-write KDC for config changes like password changes ++ a kpasswdinfo.REALM is used as well to identify ++ read-write KDCs. If this file exists for the given realm the content ++ will be used by the plugin to reply to requests for a kpasswd or ++ kadmin server or for the MIT Kerberos specific master KDC. If the ++ address contains a port number the default KDC port 88 will be used ++ for the latter. + + + +diff --git a/src/tests/cmocka/test_sssd_krb5_locator_plugin.c b/src/tests/cmocka/test_sssd_krb5_locator_plugin.c +index 3e7d00632..1b6838345 100644 +--- a/src/tests/cmocka/test_sssd_krb5_locator_plugin.c ++++ b/src/tests/cmocka/test_sssd_krb5_locator_plugin.c +@@ -44,6 +44,9 @@ + #define TEST_IP_1_WITH_SERVICE TEST_IP_1":"TEST_SERVICE_1 + #define TEST_IPV6_1_WITH_SERVICE TEST_IPV6_1":"TEST_SERVICE_2 + ++#define TEST_IP_1_WITH_SERVICE_2 TEST_IP_1":"TEST_SERVICE_2 ++#define TEST_IPV6_1_WITH_SERVICE_1 TEST_IPV6_1":"TEST_SERVICE_1 ++ + struct test_state { + void *dummy; + }; +@@ -61,6 +64,7 @@ static int setup(void **state) + *state = (void *)ts; + + unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM); ++ unlink(TEST_PUBCONF_PATH"/kpasswdinfo."TEST_REALM); + rmdir(TEST_PUBCONF_PATH); + + return 0; +@@ -574,7 +578,157 @@ void test_service(void **state) + + k5_free_serverlist(&list); + ++ /* locate_service_master_kdc should get the default port 88 if kpasswdinfo ++ * does not exists. */ ++ kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM, ++ SOCK_DGRAM, AF_INET, module_callback, ++ &cbdata); ++ assert_int_equal(kerr, 0); ++ assert_int_equal(list.nservers, 1); ++ assert_non_null(list.servers); ++ ret = getnameinfo((struct sockaddr *) &list.servers[0].addr, ++ list.servers[0].addrlen, ++ host, sizeof(host), service, sizeof(service), ++ NI_NUMERICHOST|NI_NUMERICSERV); ++ assert_int_equal(ret, 0); ++ assert_string_equal(TEST_IP_1, host); ++ assert_string_equal("88", service); ++ ++ k5_free_serverlist(&list); ++ ++ kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM, ++ SOCK_DGRAM, AF_INET6, module_callback, ++ &cbdata); ++ assert_int_equal(kerr, 0); ++ assert_int_equal(list.nservers, 1); ++ assert_non_null(list.servers); ++ ret = getnameinfo((struct sockaddr *) &list.servers[0].addr, ++ list.servers[0].addrlen, ++ host, sizeof(host), service, sizeof(service), ++ NI_NUMERICHOST|NI_NUMERICSERV); ++ assert_int_equal(ret, 0); ++ assert_string_equal(TEST_IPV6_1_PURE, host); ++ assert_string_equal("88", service); ++ ++ k5_free_serverlist(&list); ++ ++ unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM); ++ rmdir(TEST_PUBCONF_PATH); ++ sssd_krb5_locator_close(priv); ++ ++ krb5_free_context(ctx); ++} ++ ++void test_kpasswd_and_master_kdc(void **state) ++{ ++ krb5_context ctx; ++ krb5_error_code kerr; ++ void *priv; ++ int fd; ++ struct serverlist list = SERVERLIST_INIT; ++ struct module_callback_data cbdata = { 0 }; ++ ssize_t s; ++ int ret; ++ char host[NI_MAXHOST]; ++ char service[NI_MAXSERV]; ++ ++ cbdata.list = &list; ++ ++ kerr = krb5_init_context (&ctx); ++ assert_int_equal(kerr, 0); ++ ++ kerr = sssd_krb5_locator_init(ctx, &priv); ++ assert_int_equal(kerr, 0); ++ ++ mkdir(TEST_PUBCONF_PATH, 0777); ++ fd = open(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM, O_CREAT|O_RDWR, 0777); ++ assert_int_not_equal(fd, -1); ++ s = write(fd, TEST_IP_1_WITH_SERVICE, sizeof(TEST_IP_1_WITH_SERVICE)); ++ assert_int_equal(s, sizeof(TEST_IP_1_WITH_SERVICE)); ++ s = write(fd, "\n", 1); ++ assert_int_equal(s, 1); ++ s = write(fd, TEST_IPV6_1_WITH_SERVICE, sizeof(TEST_IPV6_1_WITH_SERVICE)); ++ assert_int_equal(s, sizeof(TEST_IPV6_1_WITH_SERVICE)); ++ close(fd); ++ fd = open(TEST_PUBCONF_PATH"/kpasswdinfo."TEST_REALM, O_CREAT|O_RDWR, 0777); ++ assert_int_not_equal(fd, -1); ++ s = write(fd, TEST_IP_1_WITH_SERVICE_2, sizeof(TEST_IP_1_WITH_SERVICE_2)); ++ assert_int_equal(s, sizeof(TEST_IP_1_WITH_SERVICE_2)); ++ s = write(fd, "\n", 1); ++ assert_int_equal(s, 1); ++ s = write(fd, TEST_IPV6_1_WITH_SERVICE_1, ++ sizeof(TEST_IPV6_1_WITH_SERVICE_1)); ++ assert_int_equal(s, sizeof(TEST_IPV6_1_WITH_SERVICE_1)); ++ close(fd); ++ ++ kerr = sssd_krb5_locator_lookup(priv, locate_service_kpasswd, TEST_REALM, ++ SOCK_DGRAM, AF_INET, module_callback, ++ &cbdata); ++ assert_int_equal(kerr, 0); ++ assert_int_equal(list.nservers, 1); ++ assert_non_null(list.servers); ++ ret = getnameinfo((struct sockaddr *) &list.servers[0].addr, ++ list.servers[0].addrlen, ++ host, sizeof(host), service, sizeof(service), ++ NI_NUMERICHOST|NI_NUMERICSERV); ++ assert_int_equal(ret, 0); ++ assert_string_equal(TEST_IP_1, host); ++ assert_string_equal(TEST_SERVICE_2, service); ++ ++ k5_free_serverlist(&list); ++ ++ kerr = sssd_krb5_locator_lookup(priv, locate_service_kpasswd , TEST_REALM, ++ SOCK_DGRAM, AF_INET6, module_callback, ++ &cbdata); ++ assert_int_equal(kerr, 0); ++ ++ assert_int_equal(list.nservers, 1); ++ assert_non_null(list.servers); ++ ret = getnameinfo((struct sockaddr *) &list.servers[0].addr, ++ list.servers[0].addrlen, ++ host, sizeof(host), service, sizeof(service), ++ NI_NUMERICHOST|NI_NUMERICSERV); ++ assert_int_equal(ret, 0); ++ assert_string_equal(TEST_IPV6_1_PURE, host); ++ assert_string_equal(TEST_SERVICE_1, service); ++ ++ k5_free_serverlist(&list); ++ ++ /* locate_service_master_kdc should use the default KDC port 88 and not ++ * the one set in the kpasswdinfo file. */ ++ kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM, ++ SOCK_DGRAM, AF_INET, module_callback, ++ &cbdata); ++ assert_int_equal(kerr, 0); ++ assert_int_equal(list.nservers, 1); ++ assert_non_null(list.servers); ++ ret = getnameinfo((struct sockaddr *) &list.servers[0].addr, ++ list.servers[0].addrlen, ++ host, sizeof(host), service, sizeof(service), ++ NI_NUMERICHOST|NI_NUMERICSERV); ++ assert_int_equal(ret, 0); ++ assert_string_equal(TEST_IP_1, host); ++ assert_string_equal("88", service); ++ ++ k5_free_serverlist(&list); + ++ kerr = sssd_krb5_locator_lookup(priv, locate_service_master_kdc, TEST_REALM, ++ SOCK_DGRAM, AF_INET6, module_callback, ++ &cbdata); ++ assert_int_equal(kerr, 0); ++ assert_int_equal(list.nservers, 1); ++ assert_non_null(list.servers); ++ ret = getnameinfo((struct sockaddr *) &list.servers[0].addr, ++ list.servers[0].addrlen, ++ host, sizeof(host), service, sizeof(service), ++ NI_NUMERICHOST|NI_NUMERICSERV); ++ assert_int_equal(ret, 0); ++ assert_string_equal(TEST_IPV6_1_PURE, host); ++ assert_string_equal("88", service); ++ ++ k5_free_serverlist(&list); ++ ++ unlink(TEST_PUBCONF_PATH"/kpasswdinfo."TEST_REALM); + unlink(TEST_PUBCONF_PATH"/kdcinfo."TEST_REALM); + rmdir(TEST_PUBCONF_PATH); + sssd_krb5_locator_close(priv); +@@ -606,6 +760,8 @@ int main(int argc, const char *argv[]) + setup, teardown), + cmocka_unit_test_setup_teardown(test_service, + setup, teardown), ++ cmocka_unit_test_setup_teardown(test_kpasswd_and_master_kdc, ++ setup, teardown), + }; + + /* Set debug level to invalid value so we can decide if -d 0 was used. */ +-- +2.19.1 + diff --git a/SOURCES/0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch b/SOURCES/0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch new file mode 100644 index 0000000..ca07f08 --- /dev/null +++ b/SOURCES/0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch @@ -0,0 +1,358 @@ +From 118c44f90c9c901ffbf1b676be57b7a83a190399 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 30 Nov 2018 13:06:13 +0100 +Subject: [PATCH] NSS: Avoid changing the memory cache ownership away from the + sssd user +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://pagure.io/SSSD/sssd/issue/3890 + +In case SSSD is compiled --with-sssd-user but run as root (which is the +default on RHEL and derivatives), then the memory cache will be owned by +the user that sssd_nss runs as, so root. + +This conflicts with the packaging which specifies sssd.sssd as the owner. And +in turn, this means that users can't reliably assess the package integrity +using rpm -V. + +This patch makes sure that the memory cache files are chowned to sssd.sssd +even if the nss responder runs as root. + +Also, this patch changes the sssd_nss responder so that is becomes a member +of the supplementary sssd group. Even though in traditional UNIX sense, +a process running as root could write to a file owned by sssd:sssd, with +SELinux enforcing mode this becomes problematic as SELinux emits an error +such as: + +type=AVC msg=audit(1543524888.125:1495): avc: denied { fsetid } for +pid=7706 comm="sssd_nss" capability=4 scontext=system_u:system_r:sssd_t:s0 +tcontext=system_u:system_r:sssd_t:s0 tclass=capability + +To make it possible for the sssd_nss process to write to the files, the +files are also made group-writable. The 'others' permission is still set +to read only. + +Reviewed-by: Michal Židek +(cherry picked from commit 61e4ba58934b20a950255e05797aca25aadc1242) +--- + src/responder/nss/nss_private.h | 2 + + src/responder/nss/nsssrv.c | 106 ++++++++++++++++++++++++-- + src/responder/nss/nsssrv_mmap_cache.c | 51 ++++++++++++- + src/responder/nss/nsssrv_mmap_cache.h | 5 +- + 5 files changed, 154 insertions(+), 10 deletions(-) + +diff --git a/src/responder/nss/nss_private.h b/src/responder/nss/nss_private.h +index cd0d35517..bae5fe074 100644 +--- a/src/responder/nss/nss_private.h ++++ b/src/responder/nss/nss_private.h +@@ -87,6 +87,8 @@ struct nss_ctx { + struct sss_mc_ctx *pwd_mc_ctx; + struct sss_mc_ctx *grp_mc_ctx; + struct sss_mc_ctx *initgr_mc_ctx; ++ uid_t mc_uid; ++ gid_t mc_gid; + }; + + struct sss_cmd_table *get_nss_cmds(void); +diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c +index d6c5a08a9..87a3f1d50 100644 +--- a/src/responder/nss/nsssrv.c ++++ b/src/responder/nss/nsssrv.c +@@ -101,7 +101,8 @@ static int nss_clear_memcache(struct sbus_request *dbus_req, void *data) + + /* TODO: read cache sizes from configuration */ + DEBUG(SSSDBG_TRACE_FUNC, "Clearing memory caches.\n"); +- ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS, ++ ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid, ++ SSS_MC_CACHE_ELEMENTS, + (time_t) memcache_timeout, + &nctx->pwd_mc_ctx); + if (ret != EOK) { +@@ -110,7 +111,8 @@ static int nss_clear_memcache(struct sbus_request *dbus_req, void *data) + return ret; + } + +- ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS, ++ ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid, ++ SSS_MC_CACHE_ELEMENTS, + (time_t) memcache_timeout, + &nctx->grp_mc_ctx); + if (ret != EOK) { +@@ -119,7 +121,8 @@ static int nss_clear_memcache(struct sbus_request *dbus_req, void *data) + return ret; + } + +- ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS, ++ ret = sss_mmap_cache_reinit(nctx, nctx->mc_uid, nctx->mc_gid, ++ SSS_MC_CACHE_ELEMENTS, + (time_t)memcache_timeout, + &nctx->initgr_mc_ctx); + if (ret != EOK) { +@@ -284,21 +287,27 @@ static int setup_memcaches(struct nss_ctx *nctx) + } + + /* TODO: read cache sizes from configuration */ +- ret = sss_mmap_cache_init(nctx, "passwd", SSS_MC_PASSWD, ++ ret = sss_mmap_cache_init(nctx, "passwd", ++ nctx->mc_uid, nctx->mc_gid, ++ SSS_MC_PASSWD, + SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout, + &nctx->pwd_mc_ctx); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, "passwd mmap cache is DISABLED\n"); + } + +- ret = sss_mmap_cache_init(nctx, "group", SSS_MC_GROUP, ++ ret = sss_mmap_cache_init(nctx, "group", ++ nctx->mc_uid, nctx->mc_gid, ++ SSS_MC_GROUP, + SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout, + &nctx->grp_mc_ctx); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, "group mmap cache is DISABLED\n"); + } + +- ret = sss_mmap_cache_init(nctx, "initgroups", SSS_MC_INITGROUPS, ++ ret = sss_mmap_cache_init(nctx, "initgroups", ++ nctx->mc_uid, nctx->mc_gid, ++ SSS_MC_INITGROUPS, + SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout, + &nctx->initgr_mc_ctx); + if (ret) { +@@ -308,6 +317,79 @@ static int setup_memcaches(struct nss_ctx *nctx) + return EOK; + } + ++static int sssd_supplementary_group(struct nss_ctx *nss_ctx) ++{ ++ errno_t ret; ++ int size; ++ gid_t *supp_gids = NULL; ++ ++ /* ++ * We explicitly read the IDs of the SSSD user even though the server ++ * receives --uid and --gid by parameters to account for the case where ++ * the SSSD is compiled --with-sssd-user=sssd but the default of the ++ * user option is root (this is what RHEL does) ++ */ ++ ret = sss_user_by_name_or_uid(SSSD_USER, ++ &nss_ctx->mc_uid, ++ &nss_ctx->mc_gid); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot get info on "SSSD_USER); ++ return ret; ++ } ++ ++ if (getgid() == nss_ctx->mc_gid) { ++ DEBUG(SSSDBG_TRACE_FUNC, "Already running as the sssd group\n"); ++ return EOK; ++ } ++ ++ size = getgroups(0, NULL); ++ if (size == -1) { ++ ret = errno; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Getgroups failed! (%d, %s)\n", ++ ret, sss_strerror(ret)); ++ return ret; ++ } ++ ++ if (size > 0) { ++ supp_gids = talloc_zero_array(NULL, gid_t, size); ++ if (supp_gids == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Allocation failed!\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ size = getgroups(size, supp_gids); ++ if (size == -1) { ++ ret = errno; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Getgroups failed! (%d, %s)\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ for (int i = 0; i < size; i++) { ++ if (supp_gids[i] == nss_ctx->mc_gid) { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Already assigned to the SSSD supplementary group\n"); ++ ret = EOK; ++ goto done; ++ } ++ } ++ ++ ret = setgroups(1, &nss_ctx->mc_gid); ++ if (ret != EOK) { ++ ret = errno; ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Cannot setgroups [%d]: %s\n", ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ ret = EOK; ++done: ++ talloc_free(supp_gids); ++ return ret; ++} ++ + int nss_process_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx *cdb) +@@ -405,6 +487,18 @@ int nss_process_init(TALLOC_CTX *mem_ctx, + ret = EFAULT; + goto fail; + } ++ /* ++ * Adding the NSS process to the SSSD supplementary group avoids ++ * dac_override AVC messages from SELinux in case sssd_nss runs ++ * as root and tries to write to memcache owned by sssd:sssd ++ */ ++ ret = sssd_supplementary_group(nctx); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Cannot add process to the sssd supplementary group [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto fail; ++ } + + ret = setup_memcaches(nctx); + if (ret != EOK) { +diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c +index de9e67513..d5181d771 100644 +--- a/src/responder/nss/nsssrv_mmap_cache.c ++++ b/src/responder/nss/nsssrv_mmap_cache.c +@@ -57,6 +57,9 @@ struct sss_mc_ctx { + char *file; /* mmap cache file name */ + int fd; /* file descriptor */ + ++ uid_t uid; /* User ID of owner */ ++ gid_t gid; /* Group ID of owner */ ++ + uint32_t seed; /* pseudo-random seed to avoid collision attacks */ + time_t valid_time_slot; /* maximum time the entry is valid in seconds */ + +@@ -623,7 +626,9 @@ static errno_t sss_mc_get_record(struct sss_mc_ctx **_mcc, + if (ret == EFAULT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Fatal internal mmap cache error, invalidating cache!\n"); +- (void)sss_mmap_cache_reinit(talloc_parent(mcc), -1, -1, _mcc); ++ (void)sss_mmap_cache_reinit(talloc_parent(mcc), ++ -1, -1, -1, -1, ++ _mcc); + } + return ret; + } +@@ -1144,6 +1149,26 @@ static errno_t sss_mc_create_file(struct sss_mc_ctx *mc_ctx) + return ret; + } + ++ /* Make sure that the memory cache files are chowned to sssd.sssd even ++ * if the nss responder runs as root. This is because the specfile ++ * has the ownership recorded as sssd.sssd ++ */ ++ ret = fchown(mc_ctx->fd, mc_ctx->uid, mc_ctx->gid); ++ if (ret != 0) { ++ ret = errno; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to chown mmap file %s: %d(%s)\n", ++ mc_ctx->file, ret, strerror(ret)); ++ return ret; ++ } ++ ++ ret = fchmod(mc_ctx->fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); ++ if (ret == -1) { ++ ret = errno; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to chmod mmap file %s: %d(%s)\n", ++ mc_ctx->file, ret, strerror(ret)); ++ return ret; ++ } ++ + ret = sss_br_lock_file(mc_ctx->fd, 0, 1, retries, t); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, +@@ -1224,6 +1249,7 @@ static int mc_ctx_destructor(struct sss_mc_ctx *mc_ctx) + } + + errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name, ++ uid_t uid, gid_t gid, + enum sss_mc_type type, size_t n_elem, + time_t timeout, struct sss_mc_ctx **mcc) + { +@@ -1259,6 +1285,9 @@ errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name, + goto done; + } + ++ mc_ctx->uid = uid; ++ mc_ctx->gid = gid; ++ + mc_ctx->type = type; + + mc_ctx->valid_time_slot = timeout; +@@ -1352,7 +1381,9 @@ done: + return ret; + } + +-errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem, ++errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, ++ uid_t uid, gid_t gid, ++ size_t n_elem, + time_t timeout, struct sss_mc_ctx **mc_ctx) + { + errno_t ret; +@@ -1389,12 +1420,26 @@ errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem, + timeout = (*mc_ctx)->valid_time_slot; + } + ++ if (uid == (uid_t)-1) { ++ uid = (*mc_ctx)->uid; ++ } ++ ++ if (gid == (gid_t)-1) { ++ gid = (*mc_ctx)->gid; ++ } ++ + talloc_free(*mc_ctx); + + /* make sure we do not leave a potentially freed pointer around */ + *mc_ctx = NULL; + +- ret = sss_mmap_cache_init(mem_ctx, name, type, n_elem, timeout, mc_ctx); ++ ret = sss_mmap_cache_init(mem_ctx, ++ name, ++ uid, gid, ++ type, ++ n_elem, ++ timeout, ++ mc_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to re-initialize mmap cache.\n"); + goto done; +diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h +index b84fbc8ed..e06257949 100644 +--- a/src/responder/nss/nsssrv_mmap_cache.h ++++ b/src/responder/nss/nsssrv_mmap_cache.h +@@ -34,6 +34,7 @@ enum sss_mc_type { + }; + + errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name, ++ uid_t uid, gid_t gid, + enum sss_mc_type type, size_t n_elem, + time_t valid_time, struct sss_mc_ctx **mcc); + +@@ -70,7 +71,9 @@ errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid); + errno_t sss_mmap_cache_initgr_invalidate(struct sss_mc_ctx *mcc, + struct sized_string *name); + +-errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem, ++errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, ++ uid_t uid, gid_t gid, ++ size_t n_elem, + time_t timeout, struct sss_mc_ctx **mc_ctx); + + void sss_mmap_cache_reset(struct sss_mc_ctx *mc_ctx); +-- +2.19.1 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 75d23a1..ca52f84 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -48,7 +48,7 @@ Name: sssd Version: 1.16.2 -Release: 13%{?dist}.5 +Release: 13%{?dist}.8 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -111,6 +111,8 @@ Patch0051: 0051-ipa-use-only-the-global-catalog-service-of-the-fores.patch Patch0052: 0052-LDAP-minor-refactoring-in-auth_send-to-conform-to-ou.patch Patch0053: 0053-LDAP-Only-authenticate-the-auth-connection-if-we-nee.patch Patch0054: 0054-LDAP-Log-the-encryption-used-during-LDAP-authenticat.patch +Patch0055: 0055-krb5_locator-always-use-port-88-for-master-KDC.patch +Patch0056: 0056-NSS-Avoid-changing-the-memory-cache-ownership-away-f.patch #This patch should not be removed in RHEL-7 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec @@ -834,12 +836,12 @@ done %dir %{sssdstatedir} %dir %{_localstatedir}/cache/krb5rcache %attr(700,sssd,sssd) %dir %{dbpath} -%attr(755,sssd,sssd) %dir %{mcpath} +%attr(775,sssd,sssd) %dir %{mcpath} %attr(700,root,root) %dir %{secdbpath} %attr(755,root,root) %dir %{deskprofilepath} -%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 +%ghost %attr(0664,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/passwd +%ghost %attr(0664,sssd,sssd) %verify(not md5 size mtime) %{mcpath}/group +%ghost %attr(0664,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} @@ -847,7 +849,7 @@ done %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 +%ghost %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/sssd/sssd.conf %dir %{_sysconfdir}/logrotate.d %config(noreplace) %{_sysconfdir}/logrotate.d/sssd %dir %{_sysconfdir}/rwtab.d @@ -1263,22 +1265,33 @@ systemctl try-restart sssd >/dev/null 2>&1 || : } %changelog -* Tue Dec 18 2018 Michal Židek - 1.16.3-5 +* Tue Mar 26 2019 Michal Židek - 1.16.2-13.8 +- Resolves: rhbz#1690759 - RHEL STIG pointing sssd Packaging issue [rhel-7.6.z] + - Part 2. + +* Tue Mar 26 2019 Michal Židek - 1.16.2-13.7 +- Resolves: rhbz#1690759 - RHEL STIG pointing sssd Packaging issue [rhel-7.6.z] + +* Tue Dec 18 2018 Michal Židek - 1.16.2-13.6 +- Resolves: rhbz#1683578 - sssd_krb5_locator_plugin introduces delay in + cifs.upcall krb5 calls [rhel-7.6.z] + +* Tue Dec 18 2018 Michal Židek - 1.16.2-13.5 - Resolves: rhbz#1659507 - SSSD's LDAP authentication provider does not work if ID provider is authenticated with GSSAPI [rhel-7.6.z] -* Tue Dec 18 2018 Michal Židek - 1.16.3-4 +* Tue Dec 18 2018 Michal Židek - 1.16.2-13.4 - Resolves: rhbz#1659083 - SSSD must be cleared/restarted periodically in order to retrieve AD users through IPA Trust [rhel-7.6.z] -* Tue Dec 18 2018 Michal Židek - 1.16.3-3 +* Tue Dec 18 2018 Michal Židek - 1.16.2-13.3 - Resolves: rhbz#1656833 - sssd_nss memory leak [rhel-7.6.z] -* Wed Nov 28 2018 Michal Židek - 1.16.3-2 +* Wed Nov 28 2018 Michal Židek - 1.16.2-13.2 - Resolves: Bug 1649784 - SSSD not fetching all sudo rules from AD [rhel-7.6.z] -* Wed Nov 14 2018 Michal Židek - 1.16.3-1 +* Wed Nov 14 2018 Michal Židek - 1.16.2-13.1 - Resolves: rhbz#1645047 - sssd only sets the SELinux login context if it differs from the default [rhel-7.6.z]