From 854cc6d17bb923b3399fd95b9e8044eace747a2e Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 18 2016 14:25:41 +0000 Subject: import python-2.7.5-38.el7_2 --- diff --git a/SOURCES/00229-Expect-a-failure-when-trying-to-connect-with-SSLv2-c.patch b/SOURCES/00229-Expect-a-failure-when-trying-to-connect-with-SSLv2-c.patch new file mode 100644 index 0000000..2fee0c0 --- /dev/null +++ b/SOURCES/00229-Expect-a-failure-when-trying-to-connect-with-SSLv2-c.patch @@ -0,0 +1,48 @@ +From a1d7acf899fccd0eda10e011e2d11d1d81c2d9e6 Mon Sep 17 00:00:00 2001 +From: Robert Kuska +Date: Wed, 9 Mar 2016 20:16:17 +0100 +Subject: [PATCH] Expect a failure when trying to connect with SSLv2 client to + SSLv23 server. Default value of options in tests enchanced to reflect SSLv2 + being disabled + +--- + Lib/test/test_ssl.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 11122db..b2ba186 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -691,7 +691,7 @@ class ContextTests(unittest.TestCase): + @skip_if_broken_ubuntu_ssl + def test_options(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) +- self.assertEqual(ssl.OP_ALL, ctx.options) ++ self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, ctx.options) + ctx.options |= ssl.OP_NO_SSLv2 + self.assertEqual(ssl.OP_ALL | ssl.OP_NO_SSLv2, + ctx.options) +@@ -2152,17 +2152,17 @@ else: + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True) + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_OPTIONAL) + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True, ssl.CERT_REQUIRED) +- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True) ++ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False) + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv3, False) + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLSv1, False) + # SSLv23 client with specific SSL options + if no_sslv2_implies_sslv3_hello(): + # No SSLv2 => client will use an SSLv3 hello on recent OpenSSLs + try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, + client_options=ssl.OP_NO_SSLv2) +- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, ++ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, + client_options=ssl.OP_NO_SSLv3) +- try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, True, ++ try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv23, False, + client_options=ssl.OP_NO_TLSv1) + + @skip_if_broken_ubuntu_ssl +-- +2.5.0 + diff --git a/SOURCES/00230-force-all-child-threads-to-terminate-in-TestForkInThread.patch b/SOURCES/00230-force-all-child-threads-to-terminate-in-TestForkInThread.patch new file mode 100644 index 0000000..b6b52b3 --- /dev/null +++ b/SOURCES/00230-force-all-child-threads-to-terminate-in-TestForkInThread.patch @@ -0,0 +1,18 @@ +diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py +index 413889a..fb312aa 100644 +--- a/Lib/test/test_thread.py ++++ b/Lib/test/test_thread.py +@@ -237,7 +237,12 @@ class TestForkInThread(unittest.TestCase): + if pid == 0: # child + os.close(self.read_fd) + os.write(self.write_fd, "OK") +- sys.exit(0) ++ # Exiting the thread normally in the child process can leave ++ # any additional threads (such as the one started by ++ # importing _tkinter) still running, and this can prevent ++ # the half-zombie child process from being cleaned up. See ++ # Issue #26456. ++ os._exit(0) + else: # parent + os.close(self.write_fd) + diff --git a/SOURCES/00237-CVE-2016-0772-smtplib.patch b/SOURCES/00237-CVE-2016-0772-smtplib.patch new file mode 100644 index 0000000..b11fac1 --- /dev/null +++ b/SOURCES/00237-CVE-2016-0772-smtplib.patch @@ -0,0 +1,34 @@ +From 5b67aca6fb4246e84981d6361ba218bd52e73ac2 Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Tue, 21 Jun 2016 15:52:03 +0200 +Subject: [PATCH] Raise an error when STARTTLS fails + +CVE-2016-0772 python: smtplib StartTLS stripping attack +rhbz#1303647: https://bugzilla.redhat.com/show_bug.cgi?id=1303647 + +Based on an upstream change by Benjamin Peterson +- in changeset 101886:b3ce713fb9be 2.7 +- https://hg.python.org/cpython/rev/b3ce713fb9be +--- + Lib/smtplib.py | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/Lib/smtplib.py b/Lib/smtplib.py +index dc16ef6..8bc806b 100755 +--- a/Lib/smtplib.py ++++ b/Lib/smtplib.py +@@ -655,6 +655,11 @@ class SMTP: + self.ehlo_resp = None + self.esmtp_features = {} + self.does_esmtp = 0 ++ else: ++ # RFC 3207: ++ # 501 Syntax error (no parameters allowed) ++ # 454 TLS not available due to temporary reason ++ raise SMTPResponseException(resp, reply) + return (resp, reply) + + def sendmail(self, from_addr, to_addrs, msg, mail_options=[], +-- +2.5.5 + diff --git a/SOURCES/00238-CVE-2016-5699-httplib.patch b/SOURCES/00238-CVE-2016-5699-httplib.patch new file mode 100644 index 0000000..e8cf7a4 --- /dev/null +++ b/SOURCES/00238-CVE-2016-5699-httplib.patch @@ -0,0 +1,158 @@ +From e91c46c7a1a904eba04e29cdf896c99cb546d989 Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Wed, 22 Jun 2016 17:06:01 +0200 +Subject: [PATCH] Disabled HTTP header injections in httplib + +CVE-2016-5699 python: http protocol steam injection attack +rhbz#1303699 : https://bugzilla.redhat.com/show_bug.cgi?id=1303699 + +Based on an upstream change by Demian Brecht and Serhiy Storchaka +- in changeset 94951:1c45047c5102 2.7 +- https://hg.python.org/cpython/rev/1c45047c5102 +--- + Lib/httplib.py | 40 +++++++++++++++++++++++++++++++++- + Lib/test/test_httplib.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 95 insertions(+), 1 deletion(-) + +diff --git a/Lib/httplib.py b/Lib/httplib.py +index 8e02ac3..592ee57 100644 +--- a/Lib/httplib.py ++++ b/Lib/httplib.py +@@ -68,6 +68,7 @@ Req-sent-unread-response _CS_REQ_SENT + + from array import array + import os ++import re + import socket + from sys import py3kwarning + from urlparse import urlsplit +@@ -218,6 +219,34 @@ _MAXLINE = 65536 + # maximum amount of headers accepted + _MAXHEADERS = 100 + ++# Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2) ++# ++# VCHAR = %x21-7E ++# obs-text = %x80-FF ++# header-field = field-name ":" OWS field-value OWS ++# field-name = token ++# field-value = *( field-content / obs-fold ) ++# field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] ++# field-vchar = VCHAR / obs-text ++# ++# obs-fold = CRLF 1*( SP / HTAB ) ++# ; obsolete line folding ++# ; see Section 3.2.4 ++ ++# token = 1*tchar ++# ++# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" ++# / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" ++# / DIGIT / ALPHA ++# ; any VCHAR, except delimiters ++# ++# VCHAR defined in http://tools.ietf.org/html/rfc5234#appendix-B.1 ++ ++# the patterns for both name and value are more leniant than RFC ++# definitions to allow for backwards compatibility ++_is_legal_header_name = re.compile(r'\A[^:\s][^:\r\n]*\Z').match ++_is_illegal_header_value = re.compile(r'\n(?![ \t])|\r(?![ \t\n])').search ++ + + class HTTPMessage(mimetools.Message): + +@@ -956,7 +985,16 @@ class HTTPConnection: + if self.__state != _CS_REQ_STARTED: + raise CannotSendHeader() + +- hdr = '%s: %s' % (header, '\r\n\t'.join([str(v) for v in values])) ++ header = '%s' % header ++ if not _is_legal_header_name(header): ++ raise ValueError('Invalid header name %r' % (header,)) ++ ++ values = [str(v) for v in values] ++ for one_value in values: ++ if _is_illegal_header_value(one_value): ++ raise ValueError('Invalid header value %r' % (one_value,)) ++ ++ hdr = '%s: %s' % (header, '\r\n\t'.join(values)) + self._output(hdr) + + def endheaders(self, message_body=None): +diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py +index c29aceb..29af589 100644 +--- a/Lib/test/test_httplib.py ++++ b/Lib/test/test_httplib.py +@@ -133,6 +133,33 @@ class HeaderTests(TestCase): + conn.putheader('Content-length',42) + self.assertTrue('Content-length: 42' in conn._buffer) + ++ conn.putheader('Foo', ' bar ') ++ self.assertIn(b'Foo: bar ', conn._buffer) ++ conn.putheader('Bar', '\tbaz\t') ++ self.assertIn(b'Bar: \tbaz\t', conn._buffer) ++ conn.putheader('Authorization', 'Bearer mytoken') ++ self.assertIn(b'Authorization: Bearer mytoken', conn._buffer) ++ conn.putheader('IterHeader', 'IterA', 'IterB') ++ self.assertIn(b'IterHeader: IterA\r\n\tIterB', conn._buffer) ++ conn.putheader('LatinHeader', b'\xFF') ++ self.assertIn(b'LatinHeader: \xFF', conn._buffer) ++ conn.putheader('Utf8Header', b'\xc3\x80') ++ self.assertIn(b'Utf8Header: \xc3\x80', conn._buffer) ++ conn.putheader('C1-Control', b'next\x85line') ++ self.assertIn(b'C1-Control: next\x85line', conn._buffer) ++ conn.putheader('Embedded-Fold-Space', 'is\r\n allowed') ++ self.assertIn(b'Embedded-Fold-Space: is\r\n allowed', conn._buffer) ++ conn.putheader('Embedded-Fold-Tab', 'is\r\n\tallowed') ++ self.assertIn(b'Embedded-Fold-Tab: is\r\n\tallowed', conn._buffer) ++ conn.putheader('Key Space', 'value') ++ self.assertIn(b'Key Space: value', conn._buffer) ++ conn.putheader('KeySpace ', 'value') ++ self.assertIn(b'KeySpace : value', conn._buffer) ++ conn.putheader(b'Nonbreak\xa0Space', 'value') ++ self.assertIn(b'Nonbreak\xa0Space: value', conn._buffer) ++ conn.putheader(b'\xa0NonbreakSpace', 'value') ++ self.assertIn(b'\xa0NonbreakSpace: value', conn._buffer) ++ + def test_ipv6host_header(self): + # Default host header on IPv6 transaction should wrapped by [] if + # its actual IPv6 address +@@ -152,6 +179,35 @@ class HeaderTests(TestCase): + conn.request('GET', '/foo') + self.assertTrue(sock.data.startswith(expected)) + ++ def test_invalid_headers(self): ++ conn = httplib.HTTPConnection('example.com') ++ conn.sock = FakeSocket('') ++ conn.putrequest('GET', '/') ++ ++ # http://tools.ietf.org/html/rfc7230#section-3.2.4, whitespace is no ++ # longer allowed in header names ++ cases = ( ++ (b'Invalid\r\nName', b'ValidValue'), ++ (b'Invalid\rName', b'ValidValue'), ++ (b'Invalid\nName', b'ValidValue'), ++ (b'\r\nInvalidName', b'ValidValue'), ++ (b'\rInvalidName', b'ValidValue'), ++ (b'\nInvalidName', b'ValidValue'), ++ (b' InvalidName', b'ValidValue'), ++ (b'\tInvalidName', b'ValidValue'), ++ (b'Invalid:Name', b'ValidValue'), ++ (b':InvalidName', b'ValidValue'), ++ (b'ValidName', b'Invalid\r\nValue'), ++ (b'ValidName', b'Invalid\rValue'), ++ (b'ValidName', b'Invalid\nValue'), ++ (b'ValidName', b'InvalidValue\r\n'), ++ (b'ValidName', b'InvalidValue\r'), ++ (b'ValidName', b'InvalidValue\n'), ++ ) ++ for name, value in cases: ++ with self.assertRaisesRegexp(ValueError, 'Invalid header'): ++ conn.putheader(name, value) ++ + + class BasicTest(TestCase): + def test_status_lines(self): +-- +2.9.0 + diff --git a/SOURCES/00242-CVE-2016-1000110-httpoxy.patch b/SOURCES/00242-CVE-2016-1000110-httpoxy.patch new file mode 100644 index 0000000..ada467c --- /dev/null +++ b/SOURCES/00242-CVE-2016-1000110-httpoxy.patch @@ -0,0 +1,121 @@ +From 3a184cc875709d4324d234a4b939d614a2c9bb0f Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Mon, 1 Aug 2016 11:20:11 +0200 +Subject: [PATCH] =?UTF-8?q?Fix=20for=20CVE-2016-1000110=20http://bugs.pyth?= + =?UTF-8?q?on.org/issue27568=20Based=20on=20the=20patch=20by=20R=C3=A9mi?= + =?UTF-8?q?=20Rampin?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + Doc/howto/urllib2.rst | 5 +++++ + Doc/library/urllib.rst | 10 ++++++++++ + Doc/library/urllib2.rst | 4 ++++ + Lib/test/test_urllib.py | 12 ++++++++++++ + Lib/urllib.py | 9 +++++++++ + 5 files changed, 40 insertions(+) + +diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst +index f84bf08..6542846 100644 +--- a/Doc/howto/urllib2.rst ++++ b/Doc/howto/urllib2.rst +@@ -523,6 +523,11 @@ setting up a `Basic Authentication`_ handler : :: + through a proxy. However, this can be enabled by extending urllib2 as + shown in the recipe [#]_. + ++.. note:: ++ ++ ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; see ++ the documentation on :func:`~urllib.getproxies`. ++ + + Sockets and Layers + ================== +diff --git a/Doc/library/urllib.rst b/Doc/library/urllib.rst +index c7d200d..3b9876e 100644 +--- a/Doc/library/urllib.rst ++++ b/Doc/library/urllib.rst +@@ -280,6 +280,16 @@ Utility functions + find it, looks for proxy information from Mac OSX System Configuration for + Mac OS X and Windows Systems Registry for Windows. + ++ .. note:: ++ ++ If the environment variable ``REQUEST_METHOD`` is set, which usually ++ indicates your script is running in a CGI environment, the environment ++ variable ``HTTP_PROXY`` (uppercase ``_PROXY``) will be ignored. This is ++ because that variable can be injected by a client using the "Proxy:" ++ HTTP header. If you need to use an HTTP proxy in a CGI environment, ++ either use ``ProxyHandler`` explicitly, or make sure the variable name ++ is in lowercase (or at least the ``_proxy`` suffix). ++ + .. note:: + urllib also exposes certain utility functions like splittype, splithost and + others parsing url into various components. But it is recommended to use +diff --git a/Doc/library/urllib2.rst b/Doc/library/urllib2.rst +index 24deeb4..46fce59 100644 +--- a/Doc/library/urllib2.rst ++++ b/Doc/library/urllib2.rst +@@ -224,6 +224,10 @@ The following classes are provided: + + To disable autodetected proxy pass an empty dictionary. + ++ .. note:: ++ ++ ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; ++ see the documentation on :func:`~urllib.getproxies`. + + .. class:: HTTPPasswordMgr() + +diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py +index 3a273f8..3845012 100644 +--- a/Lib/test/test_urllib.py ++++ b/Lib/test/test_urllib.py +@@ -161,6 +161,18 @@ class ProxyTests(unittest.TestCase): + self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com') + self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com')) + ++ def test_proxy_cgi_ignore(self): ++ try: ++ self.env.set('HTTP_PROXY', 'http://somewhere:3128') ++ proxies = urllib.getproxies_environment() ++ self.assertEqual('http://somewhere:3128', proxies['http']) ++ self.env.set('REQUEST_METHOD', 'GET') ++ proxies = urllib.getproxies_environment() ++ self.assertNotIn('http', proxies) ++ finally: ++ self.env.unset('REQUEST_METHOD') ++ self.env.unset('HTTP_PROXY') ++ + + class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin): + """Test urlopen() opening a fake http connection.""" +diff --git a/Lib/urllib.py b/Lib/urllib.py +index f9655f9..9b31df1 100644 +--- a/Lib/urllib.py ++++ b/Lib/urllib.py +@@ -1361,11 +1361,20 @@ def getproxies_environment(): + [Fancy]URLopener constructor. + + """ ++ # Get all variables + proxies = {} + for name, value in os.environ.items(): + name = name.lower() + if value and name[-6:] == '_proxy': + proxies[name[:-6]] = value ++ ++ # CVE-2016-1000110 - If we are running as CGI script, forget HTTP_PROXY ++ # (non-all-lowercase) as it may be set from the web server by a "Proxy:" ++ # header from the client ++ # If "proxy" is lowercase, it will still be used thanks to the next block ++ if 'REQUEST_METHOD' in os.environ: ++ proxies.pop('http', None) ++ + return proxies + + def proxy_bypass_environment(host): +-- +2.7.4 + diff --git a/SPECS/python.spec b/SPECS/python.spec index 143375c..c9f0f05 100644 --- a/SPECS/python.spec +++ b/SPECS/python.spec @@ -106,7 +106,7 @@ Summary: An interpreted, interactive, object-oriented programming language Name: %{python} # Remember to also rebase python-docs when changing this: Version: 2.7.5 -Release: 34%{?dist} +Release: 38%{?dist} License: Python Group: Development/Languages Requires: %{python}-libs%{?_isa} = %{version}-%{release} @@ -1019,6 +1019,42 @@ Patch227: 00227-accept-none-keyfile-loadcertchain.patch # Resolves: rhbz#1259421 Patch228: 00228-backport-ssl-version.patch +# 00229 # +# Adjusted tests to acknowledge lack of SSLv2 support +# Resolves: rhbz#1315310 +Patch229: 00229-Expect-a-failure-when-trying-to-connect-with-SSLv2-c.patch + +# 00230 # +# Force all child threads to terminate in TestForkInThread, so no zombie +# processes get left behind with stalled threads which hang Python builds. +# https://bugs.python.org/issue26456 +# Resolves: rhbz#1365200 +Patch230: 00230-force-all-child-threads-to-terminate-in-TestForkInThread.patch + +# 00237 # +# CVE-2016-0772 python: smtplib StartTLS stripping attack +# https://bugzilla.redhat.com/show_bug.cgi?id=1303647 +# FIXED UPSTREAM: https://hg.python.org/cpython/rev/b3ce713fb9be +# Raise an error when STARTTLS fails +# Resolves: rhbz#1346356 +Patch237: 00237-CVE-2016-0772-smtplib.patch + +# 00238 # +# CVE-2016-5699 python: http protocol steam injection attack +# https://bugzilla.redhat.com/show_bug.cgi?id=1303699 +# FIXED UPSTREAM: https://hg.python.org/cpython/rev/1c45047c5102 +# Disabled HTTP header injections in httplib +# Resolves: rhbz#1346356 +Patch238: 00238-CVE-2016-5699-httplib.patch + +# 00242 # +# HTTPoxy attack (CVE-2016-1000110) +# https://httpoxy.org/ +# FIXED UPSTREAM: http://bugs.python.org/issue27568 +# Based on a patch by RĂ©mi Rampin +# Resolves: rhbz#1359163 +Patch242: 00242-CVE-2016-1000110-httpoxy.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora 17 onwards, @@ -1410,7 +1446,11 @@ mv Modules/cryptmodule.c Modules/_cryptmodule.c %patch225 -p1 %patch227 -p1 %patch228 -p1 - +%patch229 -p1 +%patch230 -p1 +%patch237 -p1 +%patch238 -p1 +%patch242 -p1 # This shouldn't be necesarry, but is right now (2.2a3) @@ -2280,6 +2320,25 @@ rm -fr %{buildroot} # ====================================================== %changelog +* Tue Aug 09 2016 Charalampos Stratakis - 2.7.5-38 +- Fix for CVE-2016-1000110 HTTPoxy attack +Resolves: rhbz#1359163 + +* Tue Aug 09 2016 Charalampos Stratakis - 2.7.5-37 +- Force all child threads to terminate in TestForkInThread +Resolves: rhbz#1365200 + +* Tue Jun 21 2016 Tomas Orsava - 2.7.5-36 +- Fix for CVE-2016-0772 python: smtplib StartTLS stripping attack (rhbz#1303647) + Raise an error when STARTTLS fails (upstream patch) +- Fix for CVE-2016-5699 python: http protocol steam injection attack (rhbz#1303699) + Disabled HTTP header injections in httplib (upstream patch) +Resolves: rhbz#1346356 + +* Thu Mar 10 2016 Charalampos Stratakis - 2.7.5-35 +- Adjusted tests to acknowledge lack of SSLv2 support +Resolves: rhbz#1351584 + * Fri Oct 09 2015 Matej Stuchlik - 2.7.5-34 - Revert fix for rhbz#1117751 as it leads to regressions Resolves: rhbz#1117751