From 969d51434e2479639d62c2b03fd51df7403eb722 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Feb 01 2018 10:20:15 +0000 Subject: Define TLS cipher suite on build time --- diff --git a/00294-define-TLS-cipher-suite-on-build-time.patch b/00294-define-TLS-cipher-suite-on-build-time.patch new file mode 100644 index 0000000..1aa348c --- /dev/null +++ b/00294-define-TLS-cipher-suite-on-build-time.patch @@ -0,0 +1,228 @@ +diff --git a/Lib/ssl.py b/Lib/ssl.py +index 1f3a31a..b54a684 100644 +--- a/Lib/ssl.py ++++ b/Lib/ssl.py +@@ -116,6 +116,7 @@ except ImportError: + + + from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3 ++from _ssl import _DEFAULT_CIPHERS + from _ssl import _OPENSSL_API_VERSION + + +@@ -174,48 +175,7 @@ else: + CHANNEL_BINDING_TYPES = [] + + +-# Disable weak or insecure ciphers by default +-# (OpenSSL's default setting is 'DEFAULT:!aNULL:!eNULL') +-# Enable a better set of ciphers by default +-# This list has been explicitly chosen to: +-# * TLS 1.3 ChaCha20 and AES-GCM cipher suites +-# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) +-# * Prefer ECDHE over DHE for better performance +-# * Prefer AEAD over CBC for better performance and security +-# * Prefer AES-GCM over ChaCha20 because most platforms have AES-NI +-# (ChaCha20 needs OpenSSL 1.1.0 or patched 1.0.2) +-# * Prefer any AES-GCM and ChaCha20 over any AES-CBC for better +-# performance and security +-# * Then Use HIGH cipher suites as a fallback +-# * Disable NULL authentication, NULL encryption, 3DES and MD5 MACs +-# for security reasons +-_DEFAULT_CIPHERS = ( +- 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:' +- 'TLS13-AES-128-GCM-SHA256:' +- 'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:' +- 'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:' +- '!aNULL:!eNULL:!MD5:!3DES' +- ) +- +-# Restricted and more secure ciphers for the server side +-# This list has been explicitly chosen to: +-# * TLS 1.3 ChaCha20 and AES-GCM cipher suites +-# * Prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE) +-# * Prefer ECDHE over DHE for better performance +-# * Prefer AEAD over CBC for better performance and security +-# * Prefer AES-GCM over ChaCha20 because most platforms have AES-NI +-# * Prefer any AES-GCM and ChaCha20 over any AES-CBC for better +-# performance and security +-# * Then Use HIGH cipher suites as a fallback +-# * Disable NULL authentication, NULL encryption, MD5 MACs, DSS, RC4, and +-# 3DES for security reasons +-_RESTRICTED_SERVER_CIPHERS = ( +- 'TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:' +- 'TLS13-AES-128-GCM-SHA256:' +- 'ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:DH+AES256:' +- 'ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:RSA+AES:RSA+HIGH:' +- '!aNULL:!eNULL:!MD5:!DSS:!RC4:!3DES' +-) ++_RESTRICTED_SERVER_CIPHERS = _DEFAULT_CIPHERS + + + class CertificateError(ValueError): +@@ -389,8 +349,6 @@ class SSLContext(_SSLContext): + + def __new__(cls, protocol=PROTOCOL_TLS, *args, **kwargs): + self = _SSLContext.__new__(cls, protocol) +- if protocol != _SSLv2_IF_EXISTS: +- self.set_ciphers(_DEFAULT_CIPHERS) + return self + + def __init__(self, protocol=PROTOCOL_TLS): +@@ -505,8 +463,6 @@ def create_default_context(purpose=Purpose.SERVER_AUTH, *, cafile=None, + # verify certs and host name in client mode + context.verify_mode = CERT_REQUIRED + context.check_hostname = True +- elif purpose == Purpose.CLIENT_AUTH: +- context.set_ciphers(_RESTRICTED_SERVER_CIPHERS) + + if cafile or capath or cadata: + context.load_verify_locations(cafile, capath, cadata) +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 54644e1..799100c 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -18,6 +18,7 @@ import asyncore + import weakref + import platform + import functools ++import sysconfig + try: + import ctypes + except ImportError: +@@ -36,7 +37,7 @@ PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) + HOST = support.HOST + IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL') + IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0) +- ++PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') + + def data_file(*name): + return os.path.join(os.path.dirname(__file__), *name) +@@ -889,6 +890,19 @@ class ContextTests(unittest.TestCase): + with self.assertRaisesRegex(ssl.SSLError, "No cipher can be selected"): + ctx.set_ciphers("^$:,;?*'dorothyx") + ++ @unittest.skipUnless(PY_SSL_DEFAULT_CIPHERS == 1, ++ "Test applies only to Python default ciphers") ++ def test_python_ciphers(self): ++ ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ++ ciphers = ctx.get_ciphers() ++ for suite in ciphers: ++ name = suite['name'] ++ self.assertNotIn("PSK", name) ++ self.assertNotIn("SRP", name) ++ self.assertNotIn("MD5", name) ++ self.assertNotIn("RC4", name) ++ self.assertNotIn("3DES", name) ++ + @unittest.skipIf(ssl.OPENSSL_VERSION_INFO < (1, 0, 2, 0, 0), 'OpenSSL too old') + def test_get_ciphers(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +diff --git a/Modules/_ssl.c b/Modules/_ssl.c +index df8c6a7..e23a569 100644 +--- a/Modules/_ssl.c ++++ b/Modules/_ssl.c +@@ -206,6 +206,31 @@ SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) + + #endif /* OpenSSL < 1.1.0 or LibreSSL */ + ++/* Default cipher suites */ ++#ifndef PY_SSL_DEFAULT_CIPHERS ++#define PY_SSL_DEFAULT_CIPHERS 1 ++#endif ++ ++#if PY_SSL_DEFAULT_CIPHERS == 0 ++ #ifndef PY_SSL_DEFAULT_CIPHER_STRING ++ #error "Py_SSL_DEFAULT_CIPHERS 0 needs Py_SSL_DEFAULT_CIPHER_STRING" ++ #endif ++#elif PY_SSL_DEFAULT_CIPHERS == 1 ++/* Python custom selection of sensible ciper suites ++ * DEFAULT: OpenSSL's default cipher list. Since 1.0.2 the list is in sensible order. ++ * !aNULL:!eNULL: really no NULL ciphers ++ * !MD5:!3DES:!DES:!RC4:!IDEA:!SEED: no weak or broken algorithms on old OpenSSL versions. ++ * !aDSS: no authentication with discrete logarithm DSA algorithm ++ * !SRP:!PSK: no secure remote password or pre-shared key authentication ++ */ ++ #define PY_SSL_DEFAULT_CIPHER_STRING "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" ++#elif PY_SSL_DEFAULT_CIPHERS == 2 ++/* Ignored in SSLContext constructor, only used to as _ssl.DEFAULT_CIPHER_STRING */ ++ #define PY_SSL_DEFAULT_CIPHER_STRING SSL_DEFAULT_CIPHER_LIST ++#else ++ #error "Unsupported PY_SSL_DEFAULT_CIPHERS" ++#endif ++ + + enum py_ssl_error { + /* these mirror ssl.h */ +@@ -2739,7 +2764,12 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) + /* A bare minimum cipher list without completely broken cipher suites. + * It's far from perfect but gives users a better head start. */ + if (proto_version != PY_SSL_VERSION_SSL2) { +- result = SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!eNULL:!MD5"); ++#if PY_SSL_DEFAULT_CIPHERS == 2 ++ /* stick to OpenSSL's default settings */ ++ result = 1; ++#else ++ result = SSL_CTX_set_cipher_list(ctx, PY_SSL_DEFAULT_CIPHER_STRING); ++#endif + } else { + /* SSLv2 needs MD5 */ + result = SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!eNULL"); +@@ -5279,6 +5309,9 @@ PyInit__ssl(void) + (PyObject *)&PySSLSession_Type) != 0) + return NULL; + ++ PyModule_AddStringConstant(m, "_DEFAULT_CIPHERS", ++ PY_SSL_DEFAULT_CIPHER_STRING); ++ + PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", + PY_SSL_ERROR_ZERO_RETURN); + PyModule_AddIntConstant(m, "SSL_ERROR_WANT_READ", +diff --git a/configure.ac b/configure.ac +index 7ea62f8..4b42393 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5555,6 +5555,42 @@ if test "$have_getrandom" = yes; then + [Define to 1 if the getrandom() function is available]) + fi + ++# ssl module default cipher suite string ++AH_TEMPLATE(PY_SSL_DEFAULT_CIPHERS, ++ [Default cipher suites list for ssl module. ++ 1: Python's preferred selection, 2: leave OpenSSL defaults untouched, 0: custom string]) ++AH_TEMPLATE(PY_SSL_DEFAULT_CIPHER_STRING, ++ [Cipher suite string for PY_SSL_DEFAULT_CIPHERS=0] ++) ++AC_MSG_CHECKING(for --with-ssl-default-suites) ++AC_ARG_WITH(ssl-default-suites, ++ AS_HELP_STRING([--with-ssl-default-suites=@<:@python|openssl|STRING@:>@], ++ [Override default cipher suites string, ++ python: use Python's preferred selection (default), ++ openssl: leave OpenSSL's defaults untouched, ++ STRING: use a custom string, ++ PROTOCOL_SSLv2 ignores the setting]), ++[ ++AC_MSG_RESULT($withval) ++case "$withval" in ++ python) ++ AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 1) ++ ;; ++ openssl) ++ AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 2) ++ ;; ++ *) ++ AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 0) ++ AC_DEFINE_UNQUOTED(PY_SSL_DEFAULT_CIPHER_STRING, "$withval") ++ ;; ++esac ++], ++[ ++AC_MSG_RESULT(python) ++AC_DEFINE(PY_SSL_DEFAULT_CIPHERS, 1) ++]) ++ ++ + # generate output files + AC_CONFIG_FILES(Makefile.pre Modules/Setup.config Misc/python.pc Misc/python-config.sh) + AC_CONFIG_FILES([Modules/ld_so_aix], [chmod +x Modules/ld_so_aix]) diff --git a/python3.spec b/python3.spec index f8a1509..e9465a6 100644 --- a/python3.spec +++ b/python3.spec @@ -14,7 +14,7 @@ URL: https://www.python.org/ # WARNING When rebasing to a new Python version, # remember to update the python3-docs package as well Version: %{pybasever}.4 -Release: 10%{?dist} +Release: 11%{?dist} License: Python @@ -378,6 +378,14 @@ Patch291: 00291-setup-Link-ctypes-against-dl-explicitly.patch # Reported upstream: https://bugs.python.org/issue30697 Patch292: 00292-restore-PyExc_RecursionErrorInst-symbol.patch +# 00294 # +# Define TLS cipher suite on build time depending +# on the OpenSSL default cipher suite selection. +# Fixed upstream on CPython's 3.7 branch: +# https://bugs.python.org/issue31429 +# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1489816 +Patch294: 00294-define-TLS-cipher-suite-on-build-time.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -647,6 +655,7 @@ sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/en %patch290 -p1 %patch291 -p1 %patch292 -p1 +%patch294 -p1 # Remove files that should be generated by the build @@ -718,6 +727,7 @@ BuildPython() { --enable-loadable-sqlite-extensions \ --with-dtrace \ --with-lto \ + --with-ssl-default-suites=openssl \ %if %{with valgrind} --with-valgrind \ %endif @@ -1512,6 +1522,9 @@ fi # ====================================================== %changelog +* Thu Feb 01 2018 Charalampos Stratakis - 3.6.4-11 +- Define TLS cipher suite on build time. + * Wed Jan 31 2018 Tomas Orsava - 3.6.4-10 - Disable test_gdb for all arches and test_buffer for ppc64le in anticipation of the F28 mass rebuild