From 60d7aa4f36196ac810fd688d806dd57cda6196d5 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Dec 04 2017 23:02:01 +0000 Subject: import sssd-1.15.2-50.el7_4.8 --- diff --git a/SOURCES/0196-sssd_client-add-mutex-protected-call-to-the-PAC-resp.patch b/SOURCES/0196-sssd_client-add-mutex-protected-call-to-the-PAC-resp.patch new file mode 100644 index 0000000..2fe32d6 --- /dev/null +++ b/SOURCES/0196-sssd_client-add-mutex-protected-call-to-the-PAC-resp.patch @@ -0,0 +1,461 @@ +From daa59b79602cfeff81223a7461e18f513178c9d4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 18 Sep 2017 15:00:53 +0200 +Subject: [PATCH 196/196] sssd_client: add mutex protected call to the PAC + responder +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +SSSD's plugin for MIT Kerberos to send the PAC to the PAC responder +currently uses sss_pac_make_request() which does not protect the +communication with the PAC responder with a mutex as e.g. the NSS and +PAM clients. + +If an application using threads loads this plugin via libkrb5 in +different threads and is heavily processing Kerberos tickets with PACs +chances are that two threads try to communicate with SSSD at once. In +this case one of the threads will miss a reply and will wait for it +until the default client timeout of 300s is passed. + +This patch adds a call which uses a mutex to protect the communication +which will avoid the 300s delay mentioned above. + +Resolves: +https://pagure.io/SSSD/sssd/issue/3518 + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Fabiano Fidêncio +(cherry picked from commit 1f331476e7d33bb03cc35a2a9064ee1cc5bed6cf) +--- + Makefile.am | 16 ++++ + src/sss_client/common.c | 30 +++++++ + src/sss_client/sss_cli.h | 7 ++ + src/sss_client/sss_pac_responder_client.c | 137 ++++++++++++++++++++++++++++++ + src/sss_client/sssd_pac.c | 4 +- + src/tests/intg/Makefile.am | 1 + + src/tests/intg/test_pac_responder.py | 120 ++++++++++++++++++++++++++ + 7 files changed, 313 insertions(+), 2 deletions(-) + create mode 100644 src/sss_client/sss_pac_responder_client.c + create mode 100644 src/tests/intg/test_pac_responder.py + +diff --git a/Makefile.am b/Makefile.am +index 907c3256a154ebe2aae5a1667744e1dfbe8abaae..cdd517d50679b876814303fb7d6c63d49bcd8d38 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3501,6 +3501,9 @@ endif + if BUILD_WITH_LIBCURL + noinst_PROGRAMS += tcurl-test-tool + endif ++if BUILD_PAC_RESPONDER ++ noinst_PROGRAMS += sssd_pac_test_client ++endif + + if BUILD_AUTOFS + autofs_test_client_SOURCES = \ +@@ -4210,6 +4213,19 @@ sssd_pac_plugin_la_LDFLAGS = \ + -avoid-version \ + -module + ++sssd_pac_test_client_SOURCES = \ ++ src/sss_client/sss_pac_responder_client.c \ ++ src/sss_client/common.c \ ++ src/util/strtonum.c \ ++ $(NULL) ++sssd_pac_test_client_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ $(NULL) ++sssd_pac_test_client_LDADD = \ ++ $(CLIENT_LIBS) \ ++ -lpthread \ ++ $(NULL) ++ + # python[23] bindings + pysss_la_SOURCES = \ + $(SSSD_TOOLS_OBJ) \ +diff --git a/src/sss_client/common.c b/src/sss_client/common.c +index b7a5ed760ca379acdfd8f1d2bf95cee1aa271fd8..b527c046e2e3369934b4f9ea7efc1b52eb8c57ea 100644 +--- a/src/sss_client/common.c ++++ b/src/sss_client/common.c +@@ -821,6 +821,22 @@ int sss_pac_make_request(enum sss_cli_command cmd, + } + } + ++int sss_pac_make_request_with_lock(enum sss_cli_command cmd, ++ struct sss_cli_req_data *rd, ++ uint8_t **repbuf, size_t *replen, ++ int *errnop) ++{ ++ int ret; ++ ++ sss_pac_lock(); ++ ++ ret = sss_pac_make_request(cmd, rd, repbuf, replen, errnop); ++ ++ sss_pac_unlock(); ++ ++ return ret; ++} ++ + errno_t check_server_cred(int sockfd) + { + #ifdef HAVE_UCRED +@@ -1079,6 +1095,8 @@ static struct sss_mutex sss_pam_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER }; + + static struct sss_mutex sss_nss_mc_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER }; + ++static struct sss_mutex sss_pac_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER }; ++ + static void sss_mt_lock(struct sss_mutex *m) + { + pthread_mutex_lock(&m->mtx); +@@ -1121,6 +1139,16 @@ void sss_nss_mc_unlock(void) + sss_mt_unlock(&sss_nss_mc_mtx); + } + ++/* PAC mutex wrappers */ ++void sss_pac_lock(void) ++{ ++ sss_mt_lock(&sss_pac_mtx); ++} ++void sss_pac_unlock(void) ++{ ++ sss_mt_unlock(&sss_pac_mtx); ++} ++ + #else + + /* sorry no mutexes available */ +@@ -1130,6 +1158,8 @@ void sss_pam_lock(void) { return; } + void sss_pam_unlock(void) { return; } + void sss_nss_mc_lock(void) { return; } + void sss_nss_mc_unlock(void) { return; } ++void sss_pac_lock(void) { return; } ++void sss_pac_unlock(void) { return; } + #endif + + +diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h +index d4198407f2f86c6594aee6a2a43775e429692df0..337fe9803d2df3167cd2da77107dbd077f35a51b 100644 +--- a/src/sss_client/sss_cli.h ++++ b/src/sss_client/sss_cli.h +@@ -585,6 +585,11 @@ int sss_pac_make_request(enum sss_cli_command cmd, + uint8_t **repbuf, size_t *replen, + int *errnop); + ++int sss_pac_make_request_with_lock(enum sss_cli_command cmd, ++ struct sss_cli_req_data *rd, ++ uint8_t **repbuf, size_t *replen, ++ int *errnop); ++ + int sss_sudo_make_request(enum sss_cli_command cmd, + struct sss_cli_req_data *rd, + uint8_t **repbuf, size_t *replen, +@@ -634,6 +639,8 @@ void sss_pam_lock(void); + void sss_pam_unlock(void); + void sss_nss_mc_lock(void); + void sss_nss_mc_unlock(void); ++void sss_pac_lock(void); ++void sss_pac_unlock(void); + + errno_t sss_readrep_copy_string(const char *in, + size_t *offset, +diff --git a/src/sss_client/sss_pac_responder_client.c b/src/sss_client/sss_pac_responder_client.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9eb0cbea6175ee273b23d9a975529d85c02fc603 +--- /dev/null ++++ b/src/sss_client/sss_pac_responder_client.c +@@ -0,0 +1,137 @@ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "sss_client/sss_cli.h" ++ ++const uint8_t pac[] = { ++0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, ++0x02, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, ++0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x68, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x0c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xb8, ++0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, ++0x00, 0x00, 0xc8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, ++0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x02, 0x00, 0x30, 0xe3, 0xd6, 0x9e, 0x99, 0x2b, 0xd3, 0x01, 0xff, ++0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++0xff, 0x7f, 0xe2, 0xf7, 0x8a, 0xaf, 0x00, 0x0f, 0xd0, 0x01, 0xe2, 0xb7, 0xf4, ++0xd9, 0xc9, 0x0f, 0xd0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, ++0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x06, 0x00, 0x06, 0x00, 0x08, ++0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x45, 0x02, 0x00, 0x00, ++0x50, 0x04, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1c, ++0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x14, ++0x00, 0x20, 0x00, 0x02, 0x00, 0x04, 0x00, 0x06, 0x00, 0x24, 0x00, 0x02, 0x00, ++0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, ++0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, ++0x75, 0x00, 0x31, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x20, 0x00, 0x75, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, ++0xfd, 0xa2, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x07, ++0x00, 0x00, 0x00, 0x5c, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x56, 0x04, ++0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x89, 0xa6, 0x00, 0x00, 0x07, 0x00, 0x00, ++0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, ++0x41, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, ++0x00, 0x45, 0x00, 0x52, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, ++0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x41, 0x00, 0x44, 0x00, 0x04, 0x00, 0x00, ++0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, ++0xf8, 0x12, 0x13, 0xdc, 0x47, 0xf3, 0x1c, 0x76, 0x47, 0x2f, 0x2e, 0xd7, 0x02, ++0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x34, 0x00, ++0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x05, 0x00, ++0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x29, 0xc9, 0x4f, 0xd9, ++0xc2, 0x3c, 0xc3, 0x78, 0x36, 0x55, 0x87, 0xf8, 0x54, 0x04, 0x00, 0x00, 0x05, ++0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, ++0x00, 0x00, 0x25, 0xe1, 0xff, 0x1c, 0xf7, 0x87, 0x6b, 0x2c, 0x25, 0xd2, 0x0c, ++0xe3, 0xf2, 0x03, 0x00, 0x00, 0x00, 0x2c, 0x29, 0x89, 0x65, 0x2d, 0xd3, 0x01, ++0x06, 0x00, 0x74, 0x00, 0x75, 0x00, 0x31, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, ++0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, ++0x75, 0x00, 0x31, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x40, ++0x00, 0x61, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x65, 0x00, 0x76, 0x00, ++0x65, 0x00, 0x6c, 0x00, 0x41, 0x00, 0x44, 0x00, 0x2e, 0x00, 0x44, 0x00, 0x45, ++0x00, 0x56, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x76, 0x8e, ++0x25, 0x32, 0x7c, 0x85, 0x00, 0x32, 0xac, 0x8f, 0x02, 0x2c, 0x10, 0x00, 0x00, ++0x00, 0x6b, 0xe8, 0x51, 0x03, 0x30, 0xed, 0xca, 0x7d, 0xe2, 0x12, 0xa5, 0xde}; ++ ++enum nss_status _nss_sss_getpwuid_r(uid_t uid, struct passwd *result, ++ char *buffer, size_t buflen, int *errnop); ++static void *pac_client(void *arg) ++{ ++ struct sss_cli_req_data sss_data = { sizeof(pac), pac }; ++ int errnop = -1; ++ int ret; ++ size_t c; ++ ++ fprintf(stderr, "[%ld][%d][%ld][%s] started\n", time(NULL), getpid(), ++ syscall(SYS_gettid), ++ (char *) arg); ++ for (c = 0; c < 1000; c++) { ++ /* sss_pac_make_request() does not protect the client's file ++ * descriptor to the PAC responder. With this one thread will miss a ++ * reply for a SSS_GET_VERSION request and will wait until ++ * SSS_CLI_SOCKET_TIMEOUT is passed. ++ ++ ret = sss_pac_make_request(SSS_PAC_ADD_PAC_USER, &sss_data, ++ NULL, NULL, &errnop); ++ */ ++ ret = sss_pac_make_request_with_lock(SSS_PAC_ADD_PAC_USER, &sss_data, ++ NULL, NULL, &errnop); ++ if (ret != NSS_STATUS_SUCCESS ++ && !(ret == NSS_STATUS_UNAVAIL && errnop != ECONNREFUSED)) { ++ /* NSS_STATUS_UNAVAIL is returned if the PAC responder rejects ++ * the request which is ok becasue the client is waiting for a ++ * response here as well. Only errnop == ECONNREFUSED should ++ * be treated as error becasue this means that the PAC ++ * responder is not running. */ ++ fprintf(stderr, "pac: [%s][%d][%d]\n", (char *)arg, ret, errnop); ++ return ((void *)((uintptr_t)("X"))); ++ } ++ } ++ ++ fprintf(stderr, "[%ld][%s] done\n", time(NULL),(char *) arg); ++ return NULL; ++} ++ ++int main(void) ++{ ++ pthread_t thread1; ++ pthread_t thread2; ++ int ret; ++ void *t_ret; ++ ++ pthread_create(&thread1, NULL, pac_client, ++ ((void *)((uintptr_t)("Thread 1")))); ++ pthread_create(&thread2, NULL, pac_client, ++ ((void *)((uintptr_t)("Thread 2")))); ++ ++ ret = pthread_join(thread1, &t_ret); ++ if (ret != 0 || t_ret != NULL) { ++ fprintf(stderr, "Thread 1 failed.\n"); ++ return EIO; ++ } ++ ++ ret = pthread_join(thread2, &t_ret); ++ if (ret != 0 || t_ret != NULL) { ++ fprintf(stderr, "Thread 1 failed.\n"); ++ return EIO; ++ } ++ ++ return 0; ++} +diff --git a/src/sss_client/sssd_pac.c b/src/sss_client/sssd_pac.c +index 1d98e38826b36aed199b32880a7e27de905a4592..8444834a7f148787e847f5e8e21186c8701b2de7 100644 +--- a/src/sss_client/sssd_pac.c ++++ b/src/sss_client/sssd_pac.c +@@ -169,8 +169,8 @@ static krb5_error_code sssdpac_verify(krb5_context kcontext, + sss_data.len = sssdctx->data.length; + sss_data.data = sssdctx->data.data; + +- ret = sss_pac_make_request(SSS_PAC_ADD_PAC_USER, &sss_data, +- NULL, NULL, &errnop); ++ ret = sss_pac_make_request_with_lock(SSS_PAC_ADD_PAC_USER, &sss_data, ++ NULL, NULL, &errnop); + if (ret != 0) { + /* Ignore the error */ + } +diff --git a/src/tests/intg/Makefile.am b/src/tests/intg/Makefile.am +index 8566106e9017a8d3c9e7a3898a3a886e2966e346..0af7c62ca243822d919619f3d0ebc852a317efc4 100644 +--- a/src/tests/intg/Makefile.am ++++ b/src/tests/intg/Makefile.am +@@ -29,6 +29,7 @@ dist_noinst_DATA = \ + kdc.py \ + krb5utils.py \ + test_kcm.py \ ++ test_pac_responder.py \ + $(NULL) + + config.py: config.py.m4 +diff --git a/src/tests/intg/test_pac_responder.py b/src/tests/intg/test_pac_responder.py +new file mode 100644 +index 0000000000000000000000000000000000000000..4354a5d78da6a6627a27d0ca85c8a1d47419cedf +--- /dev/null ++++ b/src/tests/intg/test_pac_responder.py +@@ -0,0 +1,120 @@ ++# ++# SSSD PAC responder tests ++# ++# Copyright (c) 2017 Red Hat, Inc. ++# Author: Sumit Bose ++# ++# 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 time ++import config ++import signal ++import subprocess ++import pytest ++from util import unindent ++ ++ ++def stop_sssd(): ++ with open(config.PIDFILE_PATH, "r") as pid_file: ++ 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_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 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 ++ 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 local_domain_only(request): ++ conf = unindent("""\ ++ [sssd] ++ domains = LOCAL ++ services = nss, pac ++ ++ [nss] ++ memcache_timeout = 0 ++ ++ [domain/LOCAL] ++ id_provider = local ++ min_id = 10000 ++ max_id = 20000 ++ """).format(**locals()) ++ create_conf_fixture(request, conf) ++ create_sssd_fixture(request) ++ return None ++ ++ ++@pytest.fixture ++def sssd_pac_test_client(request): ++ path = os.path.join(config.ABS_BUILDDIR, ++ "..", "..", "..", "sssd_pac_test_client") ++ if os.access(path, os.X_OK): ++ return path ++ ++ return None ++ ++ ++def timeout_handler(signum, frame): ++ raise Exception("Timeout") ++ ++ ++def test_multithreaded_pac_client(local_domain_only, sssd_pac_test_client): ++ """ ++ Test for ticket ++ https://pagure.io/SSSD/sssd/issue/3518 ++ """ ++ ++ if not sssd_pac_test_client: ++ pytest.skip("The sssd_pac_test_client is not available, skipping test") ++ ++ signal.signal(signal.SIGALRM, timeout_handler) ++ signal.alarm(10) ++ ++ try: ++ subprocess.check_call(sssd_pac_test_client) ++ except: ++ # cancel alarm ++ signal.alarm(0) ++ raise Exception("sssd_pac_test_client failed") ++ ++ signal.alarm(0) +-- +2.13.5 + diff --git a/SOURCES/0197-sysdb-sanitize-search-filter-input.patch b/SOURCES/0197-sysdb-sanitize-search-filter-input.patch new file mode 100644 index 0000000..0b2134d --- /dev/null +++ b/SOURCES/0197-sysdb-sanitize-search-filter-input.patch @@ -0,0 +1,140 @@ +From 944295de4cf4eeba75d4f6bd476a4f59743e1813 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 5 Oct 2017 11:07:38 +0200 +Subject: [PATCH 197/197] sysdb: sanitize search filter input +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch sanitizes the input for sysdb searches by UPN/email, SID and +UUID. + +This security issue was assigned CVE-2017-12173 + +Reviewed-by: Lukáš Slebodník +Reviewed-by: Jakub Hrozek +(cherry picked from commit 1f2662c8f97c9c0fa250055d4b6750abfc6d0835) +--- + src/db/sysdb_ops.c | 43 +++++++++++++++++++++++++++++++++++-------- + src/tests/sysdb-tests.c | 7 +++++++ + 2 files changed, 42 insertions(+), 8 deletions(-) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 7ca6575ce75dab7805236c9f48dbf28a2f3946d2..408af9f389edbe0aff0fb8b96f49f0c4463a620a 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -601,6 +601,7 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx, + int ret; + const char *def_attrs[] = { SYSDB_NAME, SYSDB_UPN, SYSDB_CANONICAL_UPN, + SYSDB_USER_EMAIL, NULL }; ++ char *sanitized; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { +@@ -608,6 +609,12 @@ int sysdb_search_user_by_upn_res(TALLOC_CTX *mem_ctx, + goto done; + } + ++ ret = sss_filter_sanitize(tmp_ctx, upn, &sanitized); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize failed.\n"); ++ goto done; ++ } ++ + if (domain_scope == true) { + base_dn = sysdb_user_base_dn(tmp_ctx, domain); + } else { +@@ -620,7 +627,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, upn); ++ SYSDB_PWUPN_FILTER, sanitized, sanitized, sanitized); + if (ret != EOK) { + ret = sysdb_error_to_errno(ret); + goto done; +@@ -4757,17 +4764,31 @@ static errno_t sysdb_search_object_by_str_attr(TALLOC_CTX *mem_ctx, + bool expect_only_one_result, + struct ldb_result **_res) + { +- char *filter; ++ char *filter = NULL; + errno_t ret; ++ char *sanitized = NULL; + +- filter = talloc_asprintf(NULL, filter_tmpl, str); ++ if (str == NULL) { ++ return EINVAL; ++ } ++ ++ ret = sss_filter_sanitize(NULL, str, &sanitized); ++ if (ret != EOK || sanitized == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sss_filter_sanitize failed.\n"); ++ goto done; ++ } ++ ++ filter = talloc_asprintf(NULL, filter_tmpl, sanitized); + if (filter == NULL) { +- return ENOMEM; ++ ret = ENOMEM; ++ goto done; + } + + ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, + expect_only_one_result, _res); + ++done: ++ talloc_free(sanitized); + talloc_free(filter); + return ret; + } +@@ -4856,7 +4877,8 @@ errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx, + struct ldb_result **res) + { + int ret; +- char *user_filter; ++ char *user_filter = NULL; ++ char *filter = NULL; + + ret = sss_cert_derb64_to_ldap_filter(mem_ctx, cert, SYSDB_USER_MAPPED_CERT, + NULL, NULL, &user_filter); +@@ -4865,10 +4887,15 @@ errno_t sysdb_search_object_by_cert(TALLOC_CTX *mem_ctx, + return ret; + } + +- ret = sysdb_search_object_by_str_attr(mem_ctx, domain, +- SYSDB_USER_CERT_FILTER, +- user_filter, attrs, false, res); ++ filter = talloc_asprintf(NULL, SYSDB_USER_CERT_FILTER, user_filter); + talloc_free(user_filter); ++ if (filter == NULL) { ++ return ENOMEM; ++ } ++ ++ ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, false, res); ++ ++ talloc_free(filter); + + return ret; + } +diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c +index 6ec82ce4ca5c4f918bc9f3144c21f33b270ea47e..588eb9ef02033ec061b4187964fe562da84e86c8 100644 +--- a/src/tests/sysdb-tests.c ++++ b/src/tests/sysdb-tests.c +@@ -6444,6 +6444,13 @@ START_TEST(test_upn_basic) + fail_unless(strcmp(str, UPN_PRINC) == 0, + "Expected [%s], got [%s].", UPN_PRINC, str); + ++ /* check if input is sanitized */ ++ ret = sysdb_search_user_by_upn(test_ctx, test_ctx->domain, false, ++ "abc@def.ghi)(name="UPN_USER_NAME")(abc=xyz", ++ NULL, &msg); ++ fail_unless(ret == ENOENT, ++ "sysdb_search_user_by_upn failed with un-sanitized input."); ++ + talloc_free(test_ctx); + } + END_TEST +-- +2.13.5 + diff --git a/SOURCES/0198-ipa-make-sure-view-name-is-initialized-at-startup.patch b/SOURCES/0198-ipa-make-sure-view-name-is-initialized-at-startup.patch new file mode 100644 index 0000000..25422d6 --- /dev/null +++ b/SOURCES/0198-ipa-make-sure-view-name-is-initialized-at-startup.patch @@ -0,0 +1,60 @@ +From 2d39f46386fb36b5a68f41644ce22c15bf6ccb67 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 31 Aug 2017 22:30:25 +0200 +Subject: [PATCH 198/199] ipa: make sure view name is initialized at startup + +sysdb_master_domain_update() can only set the view name properly if it was not +set before but it might be called multiple times before the view name is +available if the cache is empty. Since ipa_apply_view() keeps track if +the view name was already set at startup or not the name can safely be +cleaned here before sysdb_master_domain_update() is called. + +Resolves: +https://pagure.io/SSSD/sssd/issue/3501 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit f00591a4615720640cf01b1c408315b57dd397dc) +--- + src/providers/ipa/ipa_subdomains.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index 6f0ff50bde234f72d62f43635d9a787316c78430..0cb4d405e45689e9548ad3652e7260f2265bd1fe 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -739,6 +739,18 @@ done: + return ret; + } + ++static void clean_view_name(struct sss_domain_info *domain) ++{ ++ struct sss_domain_info *dom = domain; ++ ++ while (dom) { ++ dom->has_views = false; ++ talloc_free(discard_const(dom->view_name)); ++ dom->view_name = NULL; ++ dom = get_next_domain(dom, SSS_GND_DESCEND); ++ } ++} ++ + static errno_t ipa_apply_view(struct sss_domain_info *domain, + struct ipa_id_ctx *ipa_id_ctx, + const char *view_name, +@@ -831,7 +843,12 @@ static errno_t ipa_apply_view(struct sss_domain_info *domain, + } + + if (!read_at_init) { +- /* refresh view data of all domains at startup */ ++ /* refresh view data of all domains at startup, since ++ * sysdb_master_domain_update and sysdb_update_subdomains might have ++ * been called earlier without the proper view name the name is ++ * cleaned here before the calls. This is acceptable because this is ++ * the initial setup (!read_at_init). */ ++ clean_view_name(domain); + ret = sysdb_master_domain_update(domain); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_master_domain_update failed " +-- +2.13.5 + diff --git a/SOURCES/0199-CACHE_REQ-Copy-the-cr_domain-list-for-each-request.patch b/SOURCES/0199-CACHE_REQ-Copy-the-cr_domain-list-for-each-request.patch new file mode 100644 index 0000000..ba0c504 --- /dev/null +++ b/SOURCES/0199-CACHE_REQ-Copy-the-cr_domain-list-for-each-request.patch @@ -0,0 +1,142 @@ +From a1634a3c4b977364fd7612efa3ee21872a8d578e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= +Date: Fri, 20 Oct 2017 09:26:43 +0200 +Subject: [PATCH 199/199] CACHE_REQ: Copy the cr_domain list for each request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Let's copy the cr_domain list for each request as this list may be +free'd due to a refresh domains request. + +Resolves: https://pagure.io/SSSD/sssd/issue/3551 + +Signed-off-by: Fabiano Fidêncio + +Reviewed-by: Pavel Březina +(cherry picked from commit 0f44eefe2ce75a0814c8688495477f6c57f3d39a) +--- + src/responder/common/cache_req/cache_req.c | 14 +++++++-- + src/responder/common/cache_req/cache_req_domain.c | 38 +++++++++++++++++++++++ + src/responder/common/cache_req/cache_req_domain.h | 5 +++ + 3 files changed, 55 insertions(+), 2 deletions(-) + +diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c +index 7d77eb7dd72a7ccf3d687eee8f746ab84176b487..83eab8ed2de0b5c7d25306d853aadc9b53cb4842 100644 +--- a/src/responder/common/cache_req/cache_req.c ++++ b/src/responder/common/cache_req/cache_req.c +@@ -688,6 +688,7 @@ struct cache_req_state { + const char *domain_name; + + /* work data */ ++ struct cache_req_domain *cr_domains; + struct cache_req_result **results; + size_t num_results; + bool first_iteration; +@@ -940,6 +941,7 @@ static errno_t cache_req_select_domains(struct tevent_req *req, + bool bypass_cache; + bool bypass_dp; + bool search; ++ errno_t ret; + + state = tevent_req_data(req, struct cache_req_state); + +@@ -951,12 +953,20 @@ static errno_t cache_req_select_domains(struct tevent_req *req, + return EOK; + } + ++ ret = cache_req_domain_copy_cr_domains(state, ++ state->cr->rctx->cr_domains, ++ &state->cr_domains); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "cache_req_copy_cr_domains() failed\n"); ++ return EINVAL; ++ } ++ + if (domain_name != NULL) { + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, + "Performing a single domain search\n"); + + cr_domain = cache_req_domain_get_domain_by_name( +- state->cr->rctx->cr_domains, domain_name); ++ state->cr_domains, domain_name); + if (cr_domain == NULL) { + return ERR_DOMAIN_NOT_FOUND; + } +@@ -965,7 +975,7 @@ static errno_t cache_req_select_domains(struct tevent_req *req, + CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, state->cr, + "Performing a multi-domain search\n"); + +- cr_domain = state->cr->rctx->cr_domains; ++ cr_domain = state->cr_domains; + check_next = true; + } + +diff --git a/src/responder/common/cache_req/cache_req_domain.c b/src/responder/common/cache_req/cache_req_domain.c +index c2b5abb74f3bd3d5055f29a4523f29b05feb2014..8c9f155303b174f16b884eb66ba1c88a0256719d 100644 +--- a/src/responder/common/cache_req/cache_req_domain.c ++++ b/src/responder/common/cache_req/cache_req_domain.c +@@ -47,6 +47,44 @@ cache_req_domain_get_domain_by_name(struct cache_req_domain *domains, + return ret; + } + ++errno_t ++cache_req_domain_copy_cr_domains(TALLOC_CTX *mem_ctx, ++ struct cache_req_domain *src, ++ struct cache_req_domain **_dest) ++{ ++ struct cache_req_domain *cr_domains = NULL; ++ struct cache_req_domain *cr_domain; ++ struct cache_req_domain *iter; ++ errno_t ret; ++ ++ if (src == NULL) { ++ return EINVAL; ++ } ++ ++ DLIST_FOR_EACH(iter, src) { ++ cr_domain = talloc_zero(mem_ctx, struct cache_req_domain); ++ if (cr_domain == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ cr_domain->domain = iter->domain; ++ cr_domain->fqnames = iter->fqnames; ++ ++ DLIST_ADD_END(cr_domains, cr_domain, struct cache_req_domain *); ++ } ++ ++ *_dest = cr_domains; ++ ret = EOK; ++ ++done: ++ if (ret != EOK) { ++ cache_req_domain_list_zfree(&cr_domains); ++ } ++ ++ return ret; ++} ++ + void cache_req_domain_list_zfree(struct cache_req_domain **cr_domains) + { + struct cache_req_domain *p, *q, *r; +diff --git a/src/responder/common/cache_req/cache_req_domain.h b/src/responder/common/cache_req/cache_req_domain.h +index 3780a5d8d88d76e100738d28d1dd0e697edf5eae..ebdc71dd635d5d8a5d06e30e96c5d4101b6d98bf 100644 +--- a/src/responder/common/cache_req/cache_req_domain.h ++++ b/src/responder/common/cache_req/cache_req_domain.h +@@ -50,6 +50,11 @@ cache_req_domain_new_list_from_domain_resolution_order( + const char *domain_resolution_order, + struct cache_req_domain **_cr_domains); + ++errno_t ++cache_req_domain_copy_cr_domains(TALLOC_CTX *mem_ctx, ++ struct cache_req_domain *src, ++ struct cache_req_domain **_dest); ++ + void cache_req_domain_list_zfree(struct cache_req_domain **cr_domains); + + +-- +2.13.5 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index af001cd..b6134a5 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -40,7 +40,7 @@ Name: sssd Version: 1.15.2 -Release: 50%{?dist}.6 +Release: 50%{?dist}.8 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -244,6 +244,10 @@ Patch0192: 0192-libwbclient-Change-return-code-for-wbcAuthenticateUs.patch Patch0193: 0193-IPA-fix-handling-of-certmap_ctx.patch Patch0194: 0194-certmap-make-sure-eku_oid_list-is-always-allocated.patch Patch0195: 0195-cache_req-Look-for-name-attribute-also-in-nss_cmd_ge.patch +Patch0196: 0196-sssd_client-add-mutex-protected-call-to-the-PAC-resp.patch +Patch0197: 0197-sysdb-sanitize-search-filter-input.patch +Patch0198: 0198-ipa-make-sure-view-name-is-initialized-at-startup.patch +Patch0199: 0199-CACHE_REQ-Copy-the-cr_domain-list-for-each-request.patch #This patch should not be removed in RHEL-7 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec @@ -340,6 +344,9 @@ License: GPLv3+ # Conflicts Conflicts: selinux-policy < 3.10.0-46 Conflicts: sssd < 1.10.0-8%{?dist}.beta2 +# Due to ABI changes in rhel-7,5 (1.1.30/1.2.0) +# rhel-7.4 <= will never have libldb 1.2.0 due to samba-4.6.x +Conflicts: libldb >= 1.1.30 # Requires Requires: sssd-client%{?_isa} = %{version}-%{release} Requires: libsss_idmap%{?_isa} = %{version}-%{release} @@ -1380,6 +1387,21 @@ fi } %changelog +* Fri Nov 03 2017 Fabiano Fidêncio - 1.15.2-50.8 +- Resolves: rhbz#1508972 - Accessing IdM kerberos ticket fails while id + mapping is applied [rhel-7.4.z] +- Resolves: rhbz#1509177 - Race condition between refreshing the cr_domain + list and a request that is using the list can + cause a segfault is sssd_nss [rhel-7.4.z] + +* Fri Oct 27 2017 Fabiano Fidêncio - 1.15.2-50.7 +- Resolves: rhbz#1506142 - SSSD can crash due to ABI changes in + libldb >= 1.2.0 (1.1.30) [rhel-7.4.z] +- Resolves: rhbz#1506682 - sssd_client: add mutex protected call to the + PAC responder [rhel-7.4.z] +- Resolves: rhbz#1499658 - CVE-2017-12173 sssd: unsanitized input when + searching in local cache database [rhel-7.4.z] + * Wed Sep 27 2017 Fabiano Fidêncio - 1.15.2-50.6 - Add a patch that was missed in 1.15.2-50.4 - Related: rhbz#1489290 - samba shares with sssd authentication broken