summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Rees <maxcrees@me.com>2020-03-16 19:40:54 -0500
committerMax Rees <maxcrees@me.com>2020-03-19 22:21:24 -0500
commit789547051d191f170ba4a2712d2060a42fe2fed8 (patch)
treef47f47ada9d312193cb588ae1865355b2e4bb416
parent44858d9784799f0a00b6d0384143e191d3c53744 (diff)
downloadpackages-789547051d191f170ba4a2712d2060a42fe2fed8.tar.gz
packages-789547051d191f170ba4a2712d2060a42fe2fed8.tar.bz2
packages-789547051d191f170ba4a2712d2060a42fe2fed8.tar.xz
packages-789547051d191f170ba4a2712d2060a42fe2fed8.zip
system/python3: bump to 3.6.10 and patch CVE-2019-18348 (#232)
-rw-r--r--system/python3/APKBUILD15
-rw-r--r--system/python3/CVE-2019-16056.patch131
-rw-r--r--system/python3/CVE-2019-16935.patch80
-rw-r--r--system/python3/CVE-2019-18348.patch147
4 files changed, 156 insertions, 217 deletions
diff --git a/system/python3/APKBUILD b/system/python3/APKBUILD
index b8c72f3a7..e875d3941 100644
--- a/system/python3/APKBUILD
+++ b/system/python3/APKBUILD
@@ -1,7 +1,7 @@
# Contributor: Kiyoshi Aman <adelie@aerdan.vulpine.house>
# Maintainer: A. Wilcox <awilfox@adelielinux.org>
pkgname=python3
-pkgver=3.6.9
+pkgver=3.6.10
_basever="${pkgver%.*}"
pkgrel=2
pkgdesc="A high-level scripting language"
@@ -40,8 +40,7 @@ makedepends="expat-dev openssl-dev zlib-dev ncurses-dev bzip2-dev xz-dev
source="https://www.python.org/ftp/python/$pkgver/Python-$pkgver.tar.xz
musl-find_library.patch
fix-xattrs-glibc.patch
- CVE-2019-16056.patch
- CVE-2019-16935.patch
+ CVE-2019-18348.patch
"
builddir="$srcdir/Python-$pkgver"
@@ -63,6 +62,8 @@ builddir="$srcdir/Python-$pkgver"
# - CVE-2019-16056
# 3.6.9-r2:
# - CVE-2019-16935
+# 3.6.10-r0:
+# - CVE-2019-18348
prepare() {
default_prepare
@@ -153,11 +154,14 @@ EOF
}
package() {
+ export XDG_CACHE_HOME="$(mktemp -d)"
make -j1 DESTDIR="$pkgdir" EXTRA_CFLAGS="$CFLAGS" install maninstall
install -Dm644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
# those are provided by python3-tkinter
rm -r "$pkgdir"/usr/bin/idle* "$pkgdir"/usr/lib/python*/idlelib \
"$pkgdir"/usr/lib/python*/tkinter
+
+ rm -rf "$XDG_CACHE_HOME"
}
dev() {
@@ -189,8 +193,7 @@ wininst() {
"$subpkgdir"/usr/lib/python$_basever/distutils/command
}
-sha512sums="05de9c6f44d96a52bfce10ede4312de892573edaf8bece65926d19973a3a800d65eed7a857af945f69efcfb25efa3788e7a54016b03d80b611eb51c3ea074819 Python-3.6.9.tar.xz
+sha512sums="26147099e1f1a0ffc85febad26e18e991f019599a150887ea0b925e34663fad8e03b3c2a941e2770c1a63960695e173ef32709572c9361e7f2cb862ccf75b28a Python-3.6.10.tar.xz
ab8eaa2858d5109049b1f9f553198d40e0ef8d78211ad6455f7b491af525bffb16738fed60fc84e960c4889568d25753b9e4a1494834fea48291b33f07000ec2 musl-find_library.patch
37b6ee5d0d5de43799316aa111423ba5a666c17dc7f81b04c330f59c1d1565540eac4c585abe2199bbed52ebe7426001edb1c53bd0a17486a2a8e052d0f494ad fix-xattrs-glibc.patch
-1f1eb61355eb7832bef8e9c3915895cc3b2966a30c809371430b4416260452cd39c48ba593b2259574867bd1e8fea98efbc45c4b0bd95aeb0690c8514b380ea0 CVE-2019-16056.patch
-7f94d887c81f79d90afd4a9621547c13cbdd0232250f62a686b26a63160a4d286a6db9b342d06b9b63af64f994835b489c37bab499a2093c3c2585dc7a04d8a1 CVE-2019-16935.patch"
+7a15409165feb60358455b711f978b7b1c4dea9ad53aa7b5be07c1f70262988e592e7a630f83125f37051bbed14d14b66d2acd775234a163ff5b048621b9a59c CVE-2019-18348.patch"
diff --git a/system/python3/CVE-2019-16056.patch b/system/python3/CVE-2019-16056.patch
deleted file mode 100644
index b2f5ce826..000000000
--- a/system/python3/CVE-2019-16056.patch
+++ /dev/null
@@ -1,131 +0,0 @@
-From 13a19139b5e76175bc95294d54afc9425e4f36c9 Mon Sep 17 00:00:00 2001
-From: "Miss Islington (bot)"
- <31488909+miss-islington@users.noreply.github.com>
-Date: Fri, 9 Aug 2019 08:22:19 -0700
-Subject: [PATCH] bpo-34155: Dont parse domains containing @ (GH-13079)
- (GH-14826)
-
-Before:
-
- >>> email.message_from_string('From: a@malicious.org@important.com', policy=email.policy.default)['from'].addresses
- (Address(display_name='', username='a', domain='malicious.org'),)
-
- >>> parseaddr('a@malicious.org@important.com')
- ('', 'a@malicious.org')
-
- After:
-
- >>> email.message_from_string('From: a@malicious.org@important.com', policy=email.policy.default)['from'].addresses
- (Address(display_name='', username='', domain=''),)
-
- >>> parseaddr('a@malicious.org@important.com')
- ('', 'a@')
-
-https://bugs.python.org/issue34155
-(cherry picked from commit 8cb65d1381b027f0b09ee36bfed7f35bb4dec9a9)
-
-Co-authored-by: jpic <jpic@users.noreply.github.com>
----
- Lib/email/_header_value_parser.py | 2 ++
- Lib/email/_parseaddr.py | 11 ++++++++++-
- Lib/test/test_email/test__header_value_parser.py | 10 ++++++++++
- Lib/test/test_email/test_email.py | 14 ++++++++++++++
- .../2019-05-04-13-33-37.bpo-34155.MJll68.rst | 1 +
- 5 files changed, 37 insertions(+), 1 deletion(-)
- create mode 100644 Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
-
-diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py
-index 737951e4b1b1..bc9c9b6241d4 100644
---- a/Lib/email/_header_value_parser.py
-+++ b/Lib/email/_header_value_parser.py
-@@ -1561,6 +1561,8 @@ def get_domain(value):
- token, value = get_dot_atom(value)
- except errors.HeaderParseError:
- token, value = get_atom(value)
-+ if value and value[0] == '@':
-+ raise errors.HeaderParseError('Invalid Domain')
- if leader is not None:
- token[:0] = [leader]
- domain.append(token)
-diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py
-index cdfa3729adc7..41ff6f8c000d 100644
---- a/Lib/email/_parseaddr.py
-+++ b/Lib/email/_parseaddr.py
-@@ -379,7 +379,12 @@ def getaddrspec(self):
- aslist.append('@')
- self.pos += 1
- self.gotonext()
-- return EMPTYSTRING.join(aslist) + self.getdomain()
-+ domain = self.getdomain()
-+ if not domain:
-+ # Invalid domain, return an empty address instead of returning a
-+ # local part to denote failed parsing.
-+ return EMPTYSTRING
-+ return EMPTYSTRING.join(aslist) + domain
-
- def getdomain(self):
- """Get the complete domain name from an address."""
-@@ -394,6 +399,10 @@ def getdomain(self):
- elif self.field[self.pos] == '.':
- self.pos += 1
- sdlist.append('.')
-+ elif self.field[self.pos] == '@':
-+ # bpo-34155: Don't parse domains with two `@` like
-+ # `a@malicious.org@important.com`.
-+ return EMPTYSTRING
- elif self.field[self.pos] in self.atomends:
- break
- else:
-diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py
-index a2c900fa7fd2..02ef3e1006c6 100644
---- a/Lib/test/test_email/test__header_value_parser.py
-+++ b/Lib/test/test_email/test__header_value_parser.py
-@@ -1418,6 +1418,16 @@ def test_get_addr_spec_dot_atom(self):
- self.assertEqual(addr_spec.domain, 'example.com')
- self.assertEqual(addr_spec.addr_spec, 'star.a.star@example.com')
-
-+ def test_get_addr_spec_multiple_domains(self):
-+ with self.assertRaises(errors.HeaderParseError):
-+ parser.get_addr_spec('star@a.star@example.com')
-+
-+ with self.assertRaises(errors.HeaderParseError):
-+ parser.get_addr_spec('star@a@example.com')
-+
-+ with self.assertRaises(errors.HeaderParseError):
-+ parser.get_addr_spec('star@172.17.0.1@example.com')
-+
- # get_obs_route
-
- def test_get_obs_route_simple(self):
-diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
-index f97ccc6711cc..68d052279987 100644
---- a/Lib/test/test_email/test_email.py
-+++ b/Lib/test/test_email/test_email.py
-@@ -3035,6 +3035,20 @@ def test_parseaddr_empty(self):
- self.assertEqual(utils.parseaddr('<>'), ('', ''))
- self.assertEqual(utils.formataddr(utils.parseaddr('<>')), '')
-
-+ def test_parseaddr_multiple_domains(self):
-+ self.assertEqual(
-+ utils.parseaddr('a@b@c'),
-+ ('', '')
-+ )
-+ self.assertEqual(
-+ utils.parseaddr('a@b.c@c'),
-+ ('', '')
-+ )
-+ self.assertEqual(
-+ utils.parseaddr('a@172.17.0.1@c'),
-+ ('', '')
-+ )
-+
- def test_noquote_dump(self):
- self.assertEqual(
- utils.formataddr(('A Silly Person', 'person@dom.ain')),
-diff --git a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
-new file mode 100644
-index 000000000000..50292e29ed1d
---- /dev/null
-+++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
-@@ -0,0 +1 @@
-+Fix parsing of invalid email addresses with more than one ``@`` (e.g. a@b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic.
diff --git a/system/python3/CVE-2019-16935.patch b/system/python3/CVE-2019-16935.patch
deleted file mode 100644
index 567eb90fc..000000000
--- a/system/python3/CVE-2019-16935.patch
+++ /dev/null
@@ -1,80 +0,0 @@
-From 1698cacfb924d1df452e78d11a4bf81ae7777389 Mon Sep 17 00:00:00 2001
-From: Victor Stinner <vstinner@redhat.com>
-Date: Sat, 28 Sep 2019 09:33:00 +0200
-Subject: [PATCH] bpo-38243, xmlrpc.server: Escape the server_title (GH-16373)
- (GH-16441)
-
-Escape the server title of xmlrpc.server.DocXMLRPCServer
-when rendering the document page as HTML.
-
-(cherry picked from commit e8650a4f8c7fb76f570d4ca9c1fbe44e91c8dfaa)
----
- Lib/test/test_docxmlrpc.py | 16 ++++++++++++++++
- Lib/xmlrpc/server.py | 3 ++-
- .../2019-09-25-13-21-09.bpo-38243.1pfz24.rst | 3 +++
- 3 files changed, 21 insertions(+), 1 deletion(-)
- create mode 100644 Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst
-
-diff --git a/Lib/test/test_docxmlrpc.py b/Lib/test/test_docxmlrpc.py
-index 00903337c07c2..d2adb21af0fb3 100644
---- a/Lib/test/test_docxmlrpc.py
-+++ b/Lib/test/test_docxmlrpc.py
-@@ -1,5 +1,6 @@
- from xmlrpc.server import DocXMLRPCServer
- import http.client
-+import re
- import sys
- from test import support
- threading = support.import_module('threading')
-@@ -193,6 +194,21 @@ def test_annotations(self):
- b'method_annotation</strong></a>(x: bytes)</dt></dl>'),
- response.read())
-
-+ def test_server_title_escape(self):
-+ # bpo-38243: Ensure that the server title and documentation
-+ # are escaped for HTML.
-+ self.serv.set_server_title('test_title<script>')
-+ self.serv.set_server_documentation('test_documentation<script>')
-+ self.assertEqual('test_title<script>', self.serv.server_title)
-+ self.assertEqual('test_documentation<script>',
-+ self.serv.server_documentation)
-+
-+ generated = self.serv.generate_html_documentation()
-+ title = re.search(r'<title>(.+?)</title>', generated).group()
-+ documentation = re.search(r'<p><tt>(.+?)</tt></p>', generated).group()
-+ self.assertEqual('<title>Python: test_title&lt;script&gt;</title>', title)
-+ self.assertEqual('<p><tt>test_documentation&lt;script&gt;</tt></p>', documentation)
-+
-
- if __name__ == '__main__':
- unittest.main()
-diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py
-index 3e0dca027f068..efe593748968c 100644
---- a/Lib/xmlrpc/server.py
-+++ b/Lib/xmlrpc/server.py
-@@ -106,6 +106,7 @@ def export_add(self, x, y):
-
- from xmlrpc.client import Fault, dumps, loads, gzip_encode, gzip_decode
- from http.server import BaseHTTPRequestHandler
-+import html
- import http.server
- import socketserver
- import sys
-@@ -904,7 +905,7 @@ def generate_html_documentation(self):
- methods
- )
-
-- return documenter.page(self.server_title, documentation)
-+ return documenter.page(html.escape(self.server_title), documentation)
-
- class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
- """XML-RPC and documentation request handler class.
-diff --git a/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst b/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst
-new file mode 100644
-index 0000000000000..98d7be129573a
---- /dev/null
-+++ b/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst
-@@ -0,0 +1,3 @@
-+Escape the server title of :class:`xmlrpc.server.DocXMLRPCServer`
-+when rendering the document page as HTML.
-+(Contributed by Dong-hee Na in :issue:`38243`.)
diff --git a/system/python3/CVE-2019-18348.patch b/system/python3/CVE-2019-18348.patch
new file mode 100644
index 000000000..9ebb963a8
--- /dev/null
+++ b/system/python3/CVE-2019-18348.patch
@@ -0,0 +1,147 @@
+From 83fc70159b24f5b11a5ef87c9b05c2cf4c7faeba Mon Sep 17 00:00:00 2001
+From: "Miss Islington (bot)"
+ <31488909+miss-islington@users.noreply.github.com>
+Date: Sat, 14 Mar 2020 15:35:52 -0700
+Subject: [PATCH] bpo-38576: Disallow control characters in hostnames in
+ http.client (GH-18995) (GH-19002)
+
+Add host validation for control characters for more CVE-2019-18348 protection.
+(cherry picked from commit 9165addc22d05e776a54319a8531ebd0b2fe01ef)
+
+Co-authored-by: Ashwin Ramaswami <aramaswamis@gmail.com>
+---
+ Lib/http/client.py | 10 ++++++
+ Lib/test/test_httplib.py | 13 ++++++-
+ Lib/test/test_urllib.py | 36 +++++++++++++++++--
+ .../2020-03-14-14-57-44.bpo-38576.OowwQn.rst | 1 +
+ 4 files changed, 57 insertions(+), 3 deletions(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2020-03-14-14-57-44.bpo-38576.OowwQn.rst
+
+diff --git a/Lib/http/client.py b/Lib/http/client.py
+index d4821f1a96e07..c0ac7db6f40a0 100644
+--- a/Lib/http/client.py
++++ b/Lib/http/client.py
+@@ -858,6 +858,8 @@ def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
+
+ (self.host, self.port) = self._get_hostport(host, port)
+
++ self._validate_host(self.host)
++
+ # This is stored as an instance variable to allow unit
+ # tests to replace it with a suitable mockup
+ self._create_connection = socket.create_connection
+@@ -1215,6 +1217,14 @@ def _validate_path(self, url):
+ raise InvalidURL(f"URL can't contain control characters. {url!r} "
+ f"(found at least {match.group()!r})")
+
++ def _validate_host(self, host):
++ """Validate a host so it doesn't contain control characters."""
++ # Prevent CVE-2019-18348.
++ match = _contains_disallowed_url_pchar_re.search(host)
++ if match:
++ raise InvalidURL(f"URL can't contain control characters. {host!r} "
++ f"(found at least {match.group()!r})")
++
+ def putheader(self, header, *values):
+ """Send a request header line to the server.
+
+diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
+index 14d42d483773c..fcd9231666ede 100644
+--- a/Lib/test/test_httplib.py
++++ b/Lib/test/test_httplib.py
+@@ -1132,7 +1132,7 @@ def run_server():
+ thread.join()
+ self.assertEqual(result, b"proxied data\n")
+
+- def test_putrequest_override_validation(self):
++ def test_putrequest_override_domain_validation(self):
+ """
+ It should be possible to override the default validation
+ behavior in putrequest (bpo-38216).
+@@ -1145,6 +1145,17 @@ def _validate_path(self, url):
+ conn.sock = FakeSocket('')
+ conn.putrequest('GET', '/\x00')
+
++ def test_putrequest_override_host_validation(self):
++ class UnsafeHTTPConnection(client.HTTPConnection):
++ def _validate_host(self, url):
++ pass
++
++ conn = UnsafeHTTPConnection('example.com\r\n')
++ conn.sock = FakeSocket('')
++ # set skip_host so a ValueError is not raised upon adding the
++ # invalid URL as the value of the "Host:" header
++ conn.putrequest('GET', '/', skip_host=1)
++
+ def test_putrequest_override_encoding(self):
+ """
+ It should be possible to override the default encoding
+diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py
+index 0061a5297cb35..ddf425fd8d4b5 100644
+--- a/Lib/test/test_urllib.py
++++ b/Lib/test/test_urllib.py
+@@ -331,7 +331,7 @@ def test_willclose(self):
+ self.unfakehttp()
+
+ @unittest.skipUnless(ssl, "ssl module required")
+- def test_url_with_control_char_rejected(self):
++ def test_url_path_with_control_char_rejected(self):
+ for char_no in list(range(0, 0x21)) + [0x7f]:
+ char = chr(char_no)
+ schemeless_url = f"//localhost:7777/test{char}/"
+@@ -358,7 +358,7 @@ def test_url_with_control_char_rejected(self):
+ self.unfakehttp()
+
+ @unittest.skipUnless(ssl, "ssl module required")
+- def test_url_with_newline_header_injection_rejected(self):
++ def test_url_path_with_newline_header_injection_rejected(self):
+ self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.")
+ host = "localhost:7777?a=1 HTTP/1.1\r\nX-injected: header\r\nTEST: 123"
+ schemeless_url = "//" + host + ":8080/test/?test=a"
+@@ -383,6 +383,38 @@ def test_url_with_newline_header_injection_rejected(self):
+ finally:
+ self.unfakehttp()
+
++ @unittest.skipUnless(ssl, "ssl module required")
++ def test_url_host_with_control_char_rejected(self):
++ for char_no in list(range(0, 0x21)) + [0x7f]:
++ char = chr(char_no)
++ schemeless_url = f"//localhost{char}/test/"
++ self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.")
++ try:
++ escaped_char_repr = repr(char).replace('\\', r'\\')
++ InvalidURL = http.client.InvalidURL
++ with self.assertRaisesRegex(
++ InvalidURL, f"contain control.*{escaped_char_repr}"):
++ urlopen(f"http:{schemeless_url}")
++ with self.assertRaisesRegex(InvalidURL, f"contain control.*{escaped_char_repr}"):
++ urlopen(f"https:{schemeless_url}")
++ finally:
++ self.unfakehttp()
++
++ @unittest.skipUnless(ssl, "ssl module required")
++ def test_url_host_with_newline_header_injection_rejected(self):
++ self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.")
++ host = "localhost\r\nX-injected: header\r\n"
++ schemeless_url = "//" + host + ":8080/test/?test=a"
++ try:
++ InvalidURL = http.client.InvalidURL
++ with self.assertRaisesRegex(
++ InvalidURL, r"contain control.*\\r"):
++ urlopen(f"http:{schemeless_url}")
++ with self.assertRaisesRegex(InvalidURL, r"contain control.*\\n"):
++ urlopen(f"https:{schemeless_url}")
++ finally:
++ self.unfakehttp()
++
+ def test_read_0_9(self):
+ # "0.9" response accepted (but not "simple responses" without
+ # a status line)
+diff --git a/Misc/NEWS.d/next/Security/2020-03-14-14-57-44.bpo-38576.OowwQn.rst b/Misc/NEWS.d/next/Security/2020-03-14-14-57-44.bpo-38576.OowwQn.rst
+new file mode 100644
+index 0000000000000..34b8af28988fa
+--- /dev/null
++++ b/Misc/NEWS.d/next/Security/2020-03-14-14-57-44.bpo-38576.OowwQn.rst
+@@ -0,0 +1 @@
++Disallow control characters in hostnames in http.client, addressing CVE-2019-18348. Such potentially malicious header injection URLs now cause a InvalidURL to be raised.
+\ No newline at end of file