From 4017ecdf5ccfe5bac4db9917474f0719a1a7bfd3 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Aug 09 2016 12:59:54 +0000 Subject: Fix for CVE-2016-1000110 HTTPoxy attack --- diff --git a/00209-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.patch b/00209-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.patch deleted file mode 100644 index 587d6f9..0000000 --- a/00209-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.patch +++ /dev/null @@ -1,39 +0,0 @@ -From ae99040f6c1f329d6b6c984f39c920f09d383925 Mon Sep 17 00:00:00 2001 -From: Charalampos Stratakis -Date: Mon, 11 Jul 2016 11:21:29 +0200 -Subject: [PATCH] CVE-2016-5636 fix - ---- - Modules/zipimport.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/Modules/zipimport.c b/Modules/zipimport.c -index 8fe9195..f72e89f 100644 ---- a/Modules/zipimport.c -+++ b/Modules/zipimport.c -@@ -1071,6 +1071,10 @@ get_data(PyObject *archive, PyObject *toc_entry) - &date, &crc)) { - return NULL; - } -+ if (data_size < 0) { -+ PyErr_Format(ZipImportError, "negative data size"); -+ return NULL; -+ } - - fp = _Py_fopen_obj(archive, "rb"); - if (!fp) { -@@ -1111,6 +1115,11 @@ get_data(PyObject *archive, PyObject *toc_entry) - } - file_offset += l; /* Start of file data */ - -+ if (data_size > LONG_MAX - 1) { -+ fclose(fp); -+ PyErr_NoMemory(); -+ return NULL; -+ } - bytes_size = compress == 0 ? data_size : data_size + 1; - if (bytes_size == 0) - bytes_size++; --- -2.7.4 - diff --git a/00209-fix-test-pyexpat-failure.patch b/00209-fix-test-pyexpat-failure.patch new file mode 100644 index 0000000..7b40280 --- /dev/null +++ b/00209-fix-test-pyexpat-failure.patch @@ -0,0 +1,17 @@ +diff -r 682a8e36dd18 Lib/test/test_pyexpat.py +--- a/Lib/test/test_pyexpat.py Tue Jul 05 17:08:52 2016 +0300 ++++ b/Lib/test/test_pyexpat.py Thu Jul 07 17:04:35 2016 +0800 +@@ -656,11 +656,9 @@ + # \xc2\x85 is UTF-8 encoded U+0085 (NEXT LINE) + xml = b"\r\n" + parser = expat.ParserCreate() +- try: ++ err_pattern = r'XML declaration not well-formed: line 1, column \d+' ++ with self.assertRaisesRegex(expat.ExpatError, err_pattern): + parser.Parse(xml, True) +- self.fail() +- except expat.ExpatError as e: +- self.assertEqual(str(e), 'XML declaration not well-formed: line 1, column 14') + + class ErrorMessageTest(unittest.TestCase): + def test_codes(self): diff --git a/00210-Raise-an-error-when-STARTTLS-fails.patch b/00210-Raise-an-error-when-STARTTLS-fails.patch deleted file mode 100644 index 9083e61..0000000 --- a/00210-Raise-an-error-when-STARTTLS-fails.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 761db274ca898f8a92348ed5979d3d3c1b0d634a Mon Sep 17 00:00:00 2001 -From: Tomas Orsava -Date: Fri, 17 Jun 2016 16:08:11 +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 -rhbz#1346345: https://bugzilla.redhat.com/show_bug.cgi?id=1346345 - -Based on an upstream change by Benjamin Peterson -- in changeset 101887:d590114c2394 3.4 -- https://hg.python.org/cpython/rev/d590114c2394 ---- - Lib/smtplib.py | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/Lib/smtplib.py b/Lib/smtplib.py -index 4756973..dfbf5f9 100755 ---- a/Lib/smtplib.py -+++ b/Lib/smtplib.py -@@ -773,6 +773,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/00211-Disabled-HTTP-header-injections-in-http-client.patch b/00211-Disabled-HTTP-header-injections-in-http-client.patch deleted file mode 100644 index 1dba41d..0000000 --- a/00211-Disabled-HTTP-header-injections-in-http-client.patch +++ /dev/null @@ -1,162 +0,0 @@ -From 86589512cc1192e58343bbbc51bb4c09450dab90 Mon Sep 17 00:00:00 2001 -From: Tomas Orsava -Date: Fri, 24 Jun 2016 12:35:26 +0200 -Subject: [PATCH] Disabled HTTP header injections in http.client. - -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 94952:bf3e1c9b80e9 3.4 -- https://hg.python.org/cpython/rev/bf3e1c9b80e9 ---- - Lib/http/client.py | 37 +++++++++++++++++++++++++++++++ - Lib/test/test_httplib.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 94 insertions(+) - -diff --git a/Lib/http/client.py b/Lib/http/client.py -index 6de4b0e..7ec5899 100644 ---- a/Lib/http/client.py -+++ b/Lib/http/client.py -@@ -70,6 +70,7 @@ import email.parser - import email.message - import io - import os -+import re - import socket - import collections - from urllib.parse import urlsplit -@@ -215,6 +216,34 @@ MAXAMOUNT = 1048576 - _MAXLINE = 65536 - _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(rb'[^:\s][^:\r\n]*').fullmatch -+_is_illegal_header_value = re.compile(rb'\n(?![ \t])|\r(?![ \t\n])').search -+ - - class HTTPMessage(email.message.Message): - # XXX The only usage of this method is in -@@ -1058,12 +1087,20 @@ class HTTPConnection: - - if hasattr(header, 'encode'): - header = header.encode('ascii') -+ -+ if not _is_legal_header_name(header): -+ raise ValueError('Invalid header name %r' % (header,)) -+ - values = list(values) - for i, one_value in enumerate(values): - if hasattr(one_value, 'encode'): - values[i] = one_value.encode('latin-1') - elif isinstance(one_value, int): - values[i] = str(one_value).encode('ascii') -+ -+ if _is_illegal_header_value(values[i]): -+ raise ValueError('Invalid header value %r' % (values[i],)) -+ - value = b'\r\n\t'.join(values) - header = header + b': ' + value - self._output(header) -diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py -index 3fc3466..d5037f0 100644 ---- a/Lib/test/test_httplib.py -+++ b/Lib/test/test_httplib.py -@@ -148,6 +148,33 @@ class HeaderTests(TestCase): - conn.putheader('Content-length', 42) - self.assertIn(b'Content-length: 42', 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 -@@ -177,6 +204,36 @@ class HeaderTests(TestCase): - self.assertEqual(resp.getheader('First'), 'val') - self.assertEqual(resp.getheader('Second'), 'val') - -+ def test_invalid_headers(self): -+ conn = client.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.subTest((name, value)): -+ with self.assertRaisesRegex(ValueError, 'Invalid header'): -+ conn.putheader(name, value) -+ - - class BasicTest(TestCase): - def test_status_lines(self): --- -2.9.0 - diff --git a/00212-fix-test-pyexpat-failure.patch b/00212-fix-test-pyexpat-failure.patch deleted file mode 100644 index 7b40280..0000000 --- a/00212-fix-test-pyexpat-failure.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff -r 682a8e36dd18 Lib/test/test_pyexpat.py ---- a/Lib/test/test_pyexpat.py Tue Jul 05 17:08:52 2016 +0300 -+++ b/Lib/test/test_pyexpat.py Thu Jul 07 17:04:35 2016 +0800 -@@ -656,11 +656,9 @@ - # \xc2\x85 is UTF-8 encoded U+0085 (NEXT LINE) - xml = b"\r\n" - parser = expat.ParserCreate() -- try: -+ err_pattern = r'XML declaration not well-formed: line 1, column \d+' -+ with self.assertRaisesRegex(expat.ExpatError, err_pattern): - parser.Parse(xml, True) -- self.fail() -- except expat.ExpatError as e: -- self.assertEqual(str(e), 'XML declaration not well-formed: line 1, column 14') - - class ErrorMessageTest(unittest.TestCase): - def test_codes(self): diff --git a/00237-Raise-an-error-when-STARTTLS-fails.patch b/00237-Raise-an-error-when-STARTTLS-fails.patch new file mode 100644 index 0000000..9083e61 --- /dev/null +++ b/00237-Raise-an-error-when-STARTTLS-fails.patch @@ -0,0 +1,35 @@ +From 761db274ca898f8a92348ed5979d3d3c1b0d634a Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Fri, 17 Jun 2016 16:08:11 +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 +rhbz#1346345: https://bugzilla.redhat.com/show_bug.cgi?id=1346345 + +Based on an upstream change by Benjamin Peterson +- in changeset 101887:d590114c2394 3.4 +- https://hg.python.org/cpython/rev/d590114c2394 +--- + Lib/smtplib.py | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/Lib/smtplib.py b/Lib/smtplib.py +index 4756973..dfbf5f9 100755 +--- a/Lib/smtplib.py ++++ b/Lib/smtplib.py +@@ -773,6 +773,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/00238-Disabled-HTTP-header-injections-in-http-client.patch b/00238-Disabled-HTTP-header-injections-in-http-client.patch new file mode 100644 index 0000000..1dba41d --- /dev/null +++ b/00238-Disabled-HTTP-header-injections-in-http-client.patch @@ -0,0 +1,162 @@ +From 86589512cc1192e58343bbbc51bb4c09450dab90 Mon Sep 17 00:00:00 2001 +From: Tomas Orsava +Date: Fri, 24 Jun 2016 12:35:26 +0200 +Subject: [PATCH] Disabled HTTP header injections in http.client. + +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 94952:bf3e1c9b80e9 3.4 +- https://hg.python.org/cpython/rev/bf3e1c9b80e9 +--- + Lib/http/client.py | 37 +++++++++++++++++++++++++++++++ + Lib/test/test_httplib.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 94 insertions(+) + +diff --git a/Lib/http/client.py b/Lib/http/client.py +index 6de4b0e..7ec5899 100644 +--- a/Lib/http/client.py ++++ b/Lib/http/client.py +@@ -70,6 +70,7 @@ import email.parser + import email.message + import io + import os ++import re + import socket + import collections + from urllib.parse import urlsplit +@@ -215,6 +216,34 @@ MAXAMOUNT = 1048576 + _MAXLINE = 65536 + _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(rb'[^:\s][^:\r\n]*').fullmatch ++_is_illegal_header_value = re.compile(rb'\n(?![ \t])|\r(?![ \t\n])').search ++ + + class HTTPMessage(email.message.Message): + # XXX The only usage of this method is in +@@ -1058,12 +1087,20 @@ class HTTPConnection: + + if hasattr(header, 'encode'): + header = header.encode('ascii') ++ ++ if not _is_legal_header_name(header): ++ raise ValueError('Invalid header name %r' % (header,)) ++ + values = list(values) + for i, one_value in enumerate(values): + if hasattr(one_value, 'encode'): + values[i] = one_value.encode('latin-1') + elif isinstance(one_value, int): + values[i] = str(one_value).encode('ascii') ++ ++ if _is_illegal_header_value(values[i]): ++ raise ValueError('Invalid header value %r' % (values[i],)) ++ + value = b'\r\n\t'.join(values) + header = header + b': ' + value + self._output(header) +diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py +index 3fc3466..d5037f0 100644 +--- a/Lib/test/test_httplib.py ++++ b/Lib/test/test_httplib.py +@@ -148,6 +148,33 @@ class HeaderTests(TestCase): + conn.putheader('Content-length', 42) + self.assertIn(b'Content-length: 42', 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 +@@ -177,6 +204,36 @@ class HeaderTests(TestCase): + self.assertEqual(resp.getheader('First'), 'val') + self.assertEqual(resp.getheader('Second'), 'val') + ++ def test_invalid_headers(self): ++ conn = client.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.subTest((name, value)): ++ with self.assertRaisesRegex(ValueError, 'Invalid header'): ++ conn.putheader(name, value) ++ + + class BasicTest(TestCase): + def test_status_lines(self): +-- +2.9.0 + diff --git a/00241-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.patch b/00241-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.patch new file mode 100644 index 0000000..587d6f9 --- /dev/null +++ b/00241-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.patch @@ -0,0 +1,39 @@ +From ae99040f6c1f329d6b6c984f39c920f09d383925 Mon Sep 17 00:00:00 2001 +From: Charalampos Stratakis +Date: Mon, 11 Jul 2016 11:21:29 +0200 +Subject: [PATCH] CVE-2016-5636 fix + +--- + Modules/zipimport.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/Modules/zipimport.c b/Modules/zipimport.c +index 8fe9195..f72e89f 100644 +--- a/Modules/zipimport.c ++++ b/Modules/zipimport.c +@@ -1071,6 +1071,10 @@ get_data(PyObject *archive, PyObject *toc_entry) + &date, &crc)) { + return NULL; + } ++ if (data_size < 0) { ++ PyErr_Format(ZipImportError, "negative data size"); ++ return NULL; ++ } + + fp = _Py_fopen_obj(archive, "rb"); + if (!fp) { +@@ -1111,6 +1115,11 @@ get_data(PyObject *archive, PyObject *toc_entry) + } + file_offset += l; /* Start of file data */ + ++ if (data_size > LONG_MAX - 1) { ++ fclose(fp); ++ PyErr_NoMemory(); ++ return NULL; ++ } + bytes_size = compress == 0 ? data_size : data_size + 1; + if (bytes_size == 0) + bytes_size++; +-- +2.7.4 + diff --git a/00242-CVE-2016-1000110-httpoxy.patch b/00242-CVE-2016-1000110-httpoxy.patch new file mode 100644 index 0000000..7c17b31 --- /dev/null +++ b/00242-CVE-2016-1000110-httpoxy.patch @@ -0,0 +1,100 @@ + +# HG changeset patch +# User Senthil Kumaran +# Date 1469947146 25200 +# Node ID a0ac52ed8f7918222603b584ec8fc93d9b7bc0a5 +# Parent 4cb94e561e2db9865fb4d752f2bceefca4c6819a# Parent 3c19023c9fec5a615c25598468b44fade89049ce +[merge from 3.4] - Prevent HTTPoxy attack (CVE-2016-1000110) + +Ignore the HTTP_PROXY variable when REQUEST_METHOD environment is set, which +indicates that the script is in CGI mode. + +Issue #27568 Reported and patch contributed by Rémi Rampin. + +diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst +--- a/Doc/howto/urllib2.rst ++++ b/Doc/howto/urllib2.rst +@@ -538,6 +538,11 @@ setting up a `Basic Authentication`_ han + through a proxy. However, this can be enabled by extending urllib.request as + shown in the recipe [#]_. + ++.. note:: ++ ++ ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; see ++ the documentation on :func:`~urllib.request.getproxies`. ++ + + Sockets and Layers + ================== +diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst +--- a/Doc/library/urllib.request.rst ++++ b/Doc/library/urllib.request.rst +@@ -166,6 +166,16 @@ The :mod:`urllib.request` module defines the following functions: + cannot 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). ++ + + The following classes are provided: + +@@ -275,6 +285,12 @@ 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.request.getproxies`. ++ ++ + + .. class:: HTTPPasswordMgr() + +diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py +--- a/Lib/test/test_urllib.py ++++ b/Lib/test/test_urllib.py +@@ -225,6 +225,18 @@ class ProxyTests(unittest.TestCase): + self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com') + self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com')) + ++ def test_proxy_cgi_ignore(self): ++ try: ++ self.env.set('HTTP_PROXY', 'http://somewhere:3128') ++ proxies = urllib.request.getproxies_environment() ++ self.assertEqual('http://somewhere:3128', proxies['http']) ++ self.env.set('REQUEST_METHOD', 'GET') ++ proxies = urllib.request.getproxies_environment() ++ self.assertNotIn('http', proxies) ++ finally: ++ self.env.unset('REQUEST_METHOD') ++ self.env.unset('HTTP_PROXY') ++ + class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin, FakeFTPMixin): + """Test urlopen() opening a fake http connection.""" + +diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py +--- a/Lib/urllib/request.py ++++ b/Lib/urllib/request.py +@@ -2394,6 +2394,12 @@ def getproxies_environment(): + 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): + diff --git a/python3.spec b/python3.spec index 7b9c2b0..924f033 100644 --- a/python3.spec +++ b/python3.spec @@ -140,7 +140,7 @@ Summary: Version 3 of the Python programming language aka Python 3000 Name: python3 Version: %{pybasever}.3 -Release: 11%{?dist} +Release: 12%{?dist} License: Python Group: Development/Languages @@ -731,55 +731,53 @@ Patch203: 00203-disable-threading-test-koji.patch Patch204: 00204-increase-dh-keys-size.patch # 00209 # -# CVE-2016-5636: http://seclists.org/oss-sec/2016/q2/560 -# rhbz#1345859: https://bugzilla.redhat.com/show_bug.cgi?id=1345859 -# https://hg.python.org/cpython/rev/10dad6da1b28/ -# https://hg.python.org/cpython/rev/5533a9e02b21 -# Fix possible integer overflow and heap corruption in zipimporter.get_data() -# FIXED UPSTREAM: https://bugs.python.org/issue26171 -Patch209: 00209-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.patch +# Fix test breakage with version 2.2.0 of Expat +# rhbz#1353918: https://bugzilla.redhat.com/show_bug.cgi?id=1353918 +# FIXED UPSTREAM: http://bugs.python.org/issue27369 +Patch209: 00209-fix-test-pyexpat-failure.patch -# 00210 # +# 00237 # # CVE-2016-0772 python: smtplib StartTLS stripping attack # rhbz#1303647: https://bugzilla.redhat.com/show_bug.cgi?id=1303647 # rhbz#1346345: https://bugzilla.redhat.com/show_bug.cgi?id=1346345 # FIXED UPSTREAM: https://hg.python.org/cpython/rev/d590114c2394 # Raise an error when STARTTLS fails -Patch210: 00210-Raise-an-error-when-STARTTLS-fails.patch +Patch237: 00237-Raise-an-error-when-STARTTLS-fails.patch -# 00211 # +# 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/bf3e1c9b80e9 # Disabled HTTP header injections in http.client # Resolves: rhbz#1331392 -Patch211: 00211-Disabled-HTTP-header-injections-in-http-client.patch +Patch238: 00238-Disabled-HTTP-header-injections-in-http-client.patch -# 00212 # -# Fix test breakage with version 2.2.0 of Expat -# rhbz#1353918: https://bugzilla.redhat.com/show_bug.cgi?id=1353918 -# NOT YET FIXED UPSTREAM: http://bugs.python.org/issue27369 -Patch212: 00212-fix-test-pyexpat-failure.patch +# 00241 # +# CVE-2016-5636: http://seclists.org/oss-sec/2016/q2/560 +# rhbz#1345859: https://bugzilla.redhat.com/show_bug.cgi?id=1345859 +# https://hg.python.org/cpython/rev/10dad6da1b28/ +# https://hg.python.org/cpython/rev/5533a9e02b21 +# Fix possible integer overflow and heap corruption in zipimporter.get_data() +# FIXED UPSTREAM: https://bugs.python.org/issue26171 +Patch241: 00241-CVE-2016-5636-buffer-overflow-in-zipimport-module-fix.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#1359177 +Patch242: 00242-CVE-2016-1000110-httpoxy.patch # (New patches go here ^^^) # -# When adding new patches to "python" and "python3" in Fedora 17 onwards, -# please try to keep the patch numbers in-sync between the two specfiles: -# -# - use the same patch number across both specfiles for conceptually-equivalent -# fixes, ideally with the same name -# -# - when a patch is relevant to both specfiles, use the same introductory -# comment in both specfiles where possible (to improve "diff" output when -# comparing them) +# When adding new patches to "python" and "python3" in Fedora, EL, etc., +# please try to keep the patch numbers in-sync between all specfiles. # -# - when a patch is only relevant for one of the two specfiles, leave a gap -# in the patch numbering in the other specfile, adding a comment when -# omitting a patch, both in the manifest section here, and in the "prep" -# phase below +# More information, and a patch number catalog, is at: # -# Hopefully this will make it easier to ensure that all relevant fixes are -# applied to both versions. +# https://fedoraproject.org/wiki/SIGs/Python/PythonPatches + # This is the generated patch to "configure"; see the description of # %{regenerate_autotooling_patch} @@ -1053,9 +1051,10 @@ sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/en %patch204 -p1 %patch209 -p1 -%patch210 -p1 -%patch211 -p1 -%patch212 -p1 +%patch237 -p1 +%patch238 -p1 +%patch241 -p1 +%patch242 -p1 # Currently (2010-01-15), http://docs.python.org/library is for 2.6, and there # are many differences between 2.6 and the Python 3 library. @@ -1950,6 +1949,10 @@ rm -fr %{buildroot} # ====================================================== %changelog +* Tue Aug 09 2016 Charalampos Stratakis - 3.4.3-12 +- Fix for CVE-2016-1000110 HTTPoxy attack +- SPEC file cleanup + * Mon Jul 11 2016 Charalampos Stratakis - 3.4.3-11 - Refactor patch for properly fixing CVE-2016-5636