python rebuild python3 ver.bum

This commit is contained in:
Rmys
2021-08-29 11:05:39 +03:00
parent 7824ed40cf
commit ab60302ced
10 changed files with 871 additions and 8 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ def setup():
#shelltools.cd("..")
os.system("echo -e '\033[0;36mBuilding OpenSSL\033[0m' ")
shelltools.cd("openssl-1.1.1k")
shelltools.cd("openssl-1.1.1l")
shelltools.system("./Configure --prefix=%s/temp --openssldir=%s/openssl/etc/ssl --libdir=lib no-shared enable-ec_nistp_64_gcc_128 linux-x86_64 -Wa,--noexecstack" %(get.workDIR(), get.workDIR()))
autotools.make()
autotools.make("install")
@@ -0,0 +1,133 @@
From 117bd40b3844733e96a8f5ccc9460900698cffbe Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Tue, 16 Mar 2021 14:08:30 -0700
Subject: [PATCH 26/30] [3.6] bpo-43285 Make ftplib not trust the PASV
response. (GH-24838) (GH-24881) (GH-24882)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The IPv4 address value returned from the server in response to the PASV command
should not be trusted. This prevents a malicious FTP server from using the
response to probe IPv4 address and port combinations on the client network.
Instead of using the returned address, we use the IP address we're
already connected to. This is the strategy other ftp clients adopted,
and matches the only strategy available for the modern IPv6 EPSV command
where the server response must return a port number and nothing else.
For the rare user who _wants_ this ugly behavior, set a `trust_server_pasv_ipv4_address`
attribute on your `ftplib.FTP` instance to True..
(cherry picked from commit 0ab152c6b5d95caa2dc1a30fa96e10258b5f188e)
Co-authored-by: Gregory P. Smith <greg@krypto.org>
(cherry picked from commit 664d1d16274b47eea6ec92572e1ebf3939a6fa0c)
Rebased for Python 2.7 by Michał Górny <mgorny@gentoo.org>
---
Lib/ftplib.py | 9 +++++-
Lib/test/test_ftplib.py | 29 +++++++++++++++++--
.../2021-03-13-03-48-14.bpo-43285.g-Hah3.rst | 8 +++++
3 files changed, 43 insertions(+), 3 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2021-03-13-03-48-14.bpo-43285.g-Hah3.rst
diff --git a/Lib/ftplib.py b/Lib/ftplib.py
index 6644554792..0550f0ab9f 100644
--- a/Lib/ftplib.py
+++ b/Lib/ftplib.py
@@ -108,6 +108,8 @@ class FTP:
file = None
welcome = None
passiveserver = 1
+ # Disables https://bugs.python.org/issue43285 security if set to True.
+ trust_server_pasv_ipv4_address = False
# Initialization method (called by class instantiation).
# Initialize host to localhost, port to standard ftp port
@@ -310,8 +312,13 @@ class FTP:
return sock
def makepasv(self):
+ """Internal: Does the PASV or EPSV handshake -> (address, port)"""
if self.af == socket.AF_INET:
- host, port = parse227(self.sendcmd('PASV'))
+ untrusted_host, port = parse227(self.sendcmd('PASV'))
+ if self.trust_server_pasv_ipv4_address:
+ host = untrusted_host
+ else:
+ host = self.sock.getpeername()[0]
else:
host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
return host, port
diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py
index 8a3eb067a4..f3217d686d 100644
--- a/Lib/test/test_ftplib.py
+++ b/Lib/test/test_ftplib.py
@@ -67,6 +67,10 @@ class DummyFTPHandler(asynchat.async_chat):
self.rest = None
self.next_retr_data = RETR_DATA
self.push('220 welcome')
+ # We use this as the string IPv4 address to direct the client
+ # to in response to a PASV command. To test security behavior.
+ # https://bugs.python.org/issue43285/.
+ self.fake_pasv_server_ip = '252.253.254.255'
def collect_incoming_data(self, data):
self.in_buffer.append(data)
@@ -109,8 +113,9 @@ class DummyFTPHandler(asynchat.async_chat):
sock.bind((self.socket.getsockname()[0], 0))
sock.listen(5)
sock.settimeout(10)
- ip, port = sock.getsockname()[:2]
- ip = ip.replace('.', ',')
+ port = sock.getsockname()[1]
+ ip = self.fake_pasv_server_ip
+ ip = ip.replace('.', ','); p1 = port // 256; p2 = port % 256
p1, p2 = divmod(port, 256)
self.push('227 entering passive mode (%s,%d,%d)' %(ip, p1, p2))
conn, addr = sock.accept()
@@ -577,6 +582,26 @@ class TestFTPClass(TestCase):
# IPv4 is in use, just make sure send_epsv has not been used
self.assertEqual(self.server.handler_instance.last_received_cmd, 'pasv')
+ def test_makepasv_issue43285_security_disabled(self):
+ """Test the opt-in to the old vulnerable behavior."""
+ self.client.trust_server_pasv_ipv4_address = True
+ bad_host, port = self.client.makepasv()
+ self.assertEqual(
+ bad_host, self.server.handler_instance.fake_pasv_server_ip)
+ # Opening and closing a connection keeps the dummy server happy
+ # instead of timing out on accept.
+ socket.create_connection((self.client.sock.getpeername()[0], port),
+ timeout=TIMEOUT).close()
+
+ def test_makepasv_issue43285_security_enabled_default(self):
+ self.assertFalse(self.client.trust_server_pasv_ipv4_address)
+ trusted_host, port = self.client.makepasv()
+ self.assertNotEqual(
+ trusted_host, self.server.handler_instance.fake_pasv_server_ip)
+ # Opening and closing a connection keeps the dummy server happy
+ # instead of timing out on accept.
+ socket.create_connection((trusted_host, port), timeout=TIMEOUT).close()
+
def test_line_too_long(self):
self.assertRaises(ftplib.Error, self.client.sendcmd,
'x' * self.client.maxline * 2)
diff --git a/Misc/NEWS.d/next/Security/2021-03-13-03-48-14.bpo-43285.g-Hah3.rst b/Misc/NEWS.d/next/Security/2021-03-13-03-48-14.bpo-43285.g-Hah3.rst
new file mode 100644
index 0000000000..8312b7e885
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2021-03-13-03-48-14.bpo-43285.g-Hah3.rst
@@ -0,0 +1,8 @@
+:mod:`ftplib` no longer trusts the IP address value returned from the server
+in response to the PASV command by default. This prevents a malicious FTP
+server from using the response to probe IPv4 address and port combinations
+on the client network.
+
+Code that requires the former vulnerable behavior may set a
+``trust_server_pasv_ipv4_address`` attribute on their
+:class:`ftplib.FTP` instances to ``True`` to re-enable it.
--
2.32.0
@@ -0,0 +1,39 @@
From 93742fbb8de75c036b552294fc2bd73eafa47592 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Wed, 7 Apr 2021 04:45:05 -0700
Subject: [PATCH 27/30] bpo-43075: Fix ReDoS in urllib AbstractBasicAuthHandler
(GH-24391)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fix Regular Expression Denial of Service (ReDoS) vulnerability in
urllib.request.AbstractBasicAuthHandler. The ReDoS-vulnerable regex
has quadratic worst-case complexity and it allows cause a denial of
service when identifying crafted invalid RFCs. This ReDoS issue is on
the client side and needs remote attackers to control the HTTP server.
(cherry picked from commit 7215d1ae25525c92b026166f9d5cac85fb1defe1)
Co-authored-by: Yeting Li <liyt@ios.ac.cn>
(backported to Python 2.7 by Michał Górny)
---
Lib/urllib2.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index b2d1fad6f2..c92fb6afb8 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -858,7 +858,7 @@ class AbstractBasicAuthHandler:
# (single quotes are a violation of the RFC, but appear in the wild)
rx = re.compile('(?:^|,)' # start of the string or ','
'[ \t]*' # optional whitespaces
- '([^ \t]+)' # scheme like "Basic"
+ '([^ \t,]+)' # scheme like "Basic"
'[ \t]+' # mandatory whitespaces
# realm=xxx
# realm='xxx'
--
2.32.0
@@ -0,0 +1,150 @@
From 429f40abd4dfc8d8b795de68ff9e268a43b12c25 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Thu, 29 Apr 2021 10:57:31 -0700
Subject: [PATCH 28/30] [3.9] bpo-43882 - urllib.parse should sanitize urls
containing ASCII newline and tabs. (GH-25595) (GH-25725)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* bpo-43882 - urllib.parse should sanitize urls containing ASCII newline and tabs. (GH-25595)
Co-authored-by: Gregory P. Smith <greg@krypto.org>
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
(cherry picked from commit 76cd81d60310d65d01f9d7b48a8985d8ab89c8b4)
Co-authored-by: Senthil Kumaran <skumaran@gatech.edu>
(backported to Python 2.7 by Michał Górny)
---
Doc/library/urlparse.rst | 13 +++++++++
Lib/test/test_urlparse.py | 29 +++++++++++++++++++
Lib/urlparse.py | 7 +++++
.../2021-04-25-07-46-37.bpo-43882.Jpwx85.rst | 6 ++++
4 files changed, 55 insertions(+)
create mode 100644 Misc/NEWS.d/next/Security/2021-04-25-07-46-37.bpo-43882.Jpwx85.rst
diff --git a/Doc/library/urlparse.rst b/Doc/library/urlparse.rst
index 2f8e4c5a44..0546dcae8c 100644
--- a/Doc/library/urlparse.rst
+++ b/Doc/library/urlparse.rst
@@ -267,6 +267,9 @@ The :mod:`urlparse` module defines the following functions:
decomposed before parsing, or is not a Unicode string, no error will be
raised.
+ Following the `WHATWG spec`_ that updates RFC 3986, ASCII newline
+ ``\n``, ``\r`` and tab ``\t`` characters are stripped from the URL.
+
.. versionadded:: 2.2
.. versionchanged:: 2.5
@@ -276,6 +279,10 @@ The :mod:`urlparse` module defines the following functions:
Characters that affect netloc parsing under NFKC normalization will
now raise :exc:`ValueError`.
+ .. versionchanged:: 2.7.18_p9 (Gentoo)
+ ASCII newline and tab characters are stripped from the URL.
+
+.. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser
.. function:: urlunsplit(parts)
@@ -327,6 +334,10 @@ The :mod:`urlparse` module defines the following functions:
.. seealso::
+ `WHATWG`_ - URL Living standard
+ Working Group for the URL Standard that defines URLs, domains, IP addresses, the
+ application/x-www-form-urlencoded format, and their API.
+
:rfc:`3986` - Uniform Resource Identifiers
This is the current standard (STD66). Any changes to urlparse module
should conform to this. Certain deviations could be observed, which are
@@ -351,6 +362,8 @@ The :mod:`urlparse` module defines the following functions:
:rfc:`1738` - Uniform Resource Locators (URL)
This specifies the formal syntax and semantics of absolute URLs.
+.. _WHATWG: https://url.spec.whatwg.org/
+
.. _urlparse-result-object:
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
index 0b2107339a..9912fe2888 100644
--- a/Lib/test/test_urlparse.py
+++ b/Lib/test/test_urlparse.py
@@ -543,6 +543,35 @@ class UrlParseTestCase(unittest.TestCase):
self.assertEqual(p1.params, 'phone-context=+1-914-555')
+ def test_urlsplit_remove_unsafe_bytes(self):
+ # Remove ASCII tabs and newlines from input
+ url = "http://www.python.org/java\nscript:\talert('msg\r\n')/#frag"
+ p = urlparse.urlsplit(url)
+ self.assertEqual(p.scheme, "http")
+ self.assertEqual(p.netloc, "www.python.org")
+ self.assertEqual(p.path, "/javascript:alert('msg')/")
+ self.assertEqual(p.query, "")
+ self.assertEqual(p.fragment, "frag")
+ self.assertEqual(p.username, None)
+ self.assertEqual(p.password, None)
+ self.assertEqual(p.hostname, "www.python.org")
+ self.assertEqual(p.port, None)
+ self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/#frag")
+
+ # Remove ASCII tabs and newlines from input as bytes.
+ url = b"http://www.python.org/java\nscript:\talert('msg\r\n')/#frag"
+ p = urlparse.urlsplit(url)
+ self.assertEqual(p.scheme, b"http")
+ self.assertEqual(p.netloc, b"www.python.org")
+ self.assertEqual(p.path, b"/javascript:alert('msg')/")
+ self.assertEqual(p.query, b"")
+ self.assertEqual(p.fragment, b"frag")
+ self.assertEqual(p.username, None)
+ self.assertEqual(p.password, None)
+ self.assertEqual(p.hostname, b"www.python.org")
+ self.assertEqual(p.port, None)
+ self.assertEqual(p.geturl(), b"http://www.python.org/javascript:alert('msg')/#frag")
+
def test_attributes_bad_port(self):
"""Check handling of non-integer ports."""
p = urlparse.urlsplit("http://www.example.net:foo")
diff --git a/Lib/urlparse.py b/Lib/urlparse.py
index 6c32727fce..4f24cc12c6 100644
--- a/Lib/urlparse.py
+++ b/Lib/urlparse.py
@@ -62,6 +62,9 @@ scheme_chars = ('abcdefghijklmnopqrstuvwxyz'
'0123456789'
'+-.')
+# Unsafe bytes to be removed per WHATWG spec
+_UNSAFE_URL_BYTES_TO_REMOVE = ['\t', '\r', '\n']
+
MAX_CACHE_SIZE = 20
_parse_cache = {}
@@ -198,6 +201,10 @@ def urlsplit(url, scheme='', allow_fragments=True):
if len(_parse_cache) >= MAX_CACHE_SIZE: # avoid runaway growth
clear_cache()
netloc = query = fragment = ''
+
+ for b in _UNSAFE_URL_BYTES_TO_REMOVE:
+ url = url.replace(b, "")
+
i = url.find(':')
if i > 0:
if url[:i] == 'http': # optimize the common case
diff --git a/Misc/NEWS.d/next/Security/2021-04-25-07-46-37.bpo-43882.Jpwx85.rst b/Misc/NEWS.d/next/Security/2021-04-25-07-46-37.bpo-43882.Jpwx85.rst
new file mode 100644
index 0000000000..a326d079df
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2021-04-25-07-46-37.bpo-43882.Jpwx85.rst
@@ -0,0 +1,6 @@
+The presence of newline or tab characters in parts of a URL could allow
+some forms of attacks.
+
+Following the controlling specification for URLs defined by WHATWG
+:func:`urllib.parse` now removes ASCII newlines and tabs from URLs,
+preventing such attacks.
--
2.32.0
@@ -0,0 +1,83 @@
From e1a42c83c6cae70dd42c6ecf1261049edce5ce63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <mgorny@gentoo.org>
Date: Sat, 19 Jun 2021 20:46:09 +0200
Subject: [PATCH 30/30] Backport bpo-44022: Fix http client infinite line
reading (DoS) after a HTTP 100 Continue (GH-25916)
Backport the fix from the following commit:
commit 47895e31b6f626bc6ce47d175fe9d43c1098909d
Author: Gen Xu <xgbarry@gmail.com>
Date: 2021-05-06 00:42:41 +0200
bpo-44022: Fix http client infinite line reading (DoS) after a HTTP 100 Continue (GH-25916)
Fixes http.client potential denial of service where it could get stuck reading lines from a malicious server after a 100 Continue response.
Co-authored-by: Gregory P. Smith <greg@krypto.org>
Instead of reusing the header reading code, I have just added explicit
counter to avoid having to refactor the old code.
Plus the improved test from:
commit e60ab843cbb016fb6ff8b4f418641ac05a9b2fcc
Author: Gregory P. Smith <greg@krypto.org>
Date: 2021-06-03 05:43:38 +0200
bpo-44022: Improve the regression test. (GH-26503)
It wasn't actually detecting the regression due to the
assertion being too lenient.
---
Lib/httplib.py | 5 ++++-
Lib/test/test_httplib.py | 13 +++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/Lib/httplib.py b/Lib/httplib.py
index 81a08d5d71..ebfa59ff93 100644
--- a/Lib/httplib.py
+++ b/Lib/httplib.py
@@ -453,11 +453,14 @@ class HTTPResponse:
if status != CONTINUE:
break
# skip the header from the 100 response
+ header_count = 0
while True:
skip = self.fp.readline(_MAXLINE + 1)
if len(skip) > _MAXLINE:
raise LineTooLong("header line")
- skip = skip.strip()
+ header_count += 1
+ if header_count > _MAXHEADERS:
+ raise HTTPException("got more than %d headers" % _MAXHEADERS)
if not skip:
break
if self.debuglevel > 0:
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index e20a0986dc..5f6b1d0b20 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -675,6 +675,19 @@ class BasicTest(TestCase):
resp = httplib.HTTPResponse(FakeSocket(body))
self.assertRaises(httplib.LineTooLong, resp.begin)
+ def test_overflowing_header_limit_after_100(self):
+ body = (
+ 'HTTP/1.1 100 OK\r\n'
+ 'r\n' * 32768
+ )
+ resp = httplib.HTTPResponse(FakeSocket(body))
+ with self.assertRaises(httplib.HTTPException) as cm:
+ resp.begin()
+ # We must assert more because other reasonable errors that we
+ # do not want can also be HTTPException derived.
+ self.assertIn('got more than ', str(cm.exception))
+ self.assertIn('headers', str(cm.exception))
+
def test_overflowing_chunked_line(self):
body = (
'HTTP/1.1 200 OK\r\n'
--
2.32.0
+13 -2
View File
@@ -14,7 +14,7 @@
<Description>Python is a dynamic object-oriented programming language that can be used for many kinds of software development. It offers strong support for integration with other languages and tools, comes with extensive standard libraries, and can be learned in a few days.</Description>
<Archive sha1sum="678d4cf483a1c92efd347ee8e1e79326dc82810b" type="tarxz">https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tar.xz</Archive>
<!-- <Archive sha1sum="bf7badf7e248e0ecf465d33c2f5aeec774209227" type="targz" target="Python-2.7.18">https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz</Archive> -->
<Archive sha1sum="bad9dc4ae6dcc1855085463099b5dacb0ec6130b" type="targz" target="Python-2.7.18">https://www.openssl.org/source/openssl-1.1.1k.tar.gz</Archive>
<Archive sha1sum="f8819dd31642eebea6cc1fa5c256fc9a4f40809b" type="targz" target="Python-2.7.18">https://www.openssl.org/source/openssl-1.1.1l.tar.gz</Archive>
<BuildDependencies>
<Dependency>bzip2</Dependency>
<!--<Dependency>tcl-devel</Dependency>-->
@@ -25,7 +25,7 @@
<Dependency>libffi-devel</Dependency>
<Dependency>sqlite-devel</Dependency>
<Dependency>ncurses-devel</Dependency>
<Dependency versionFrom="1.1.1k">openssl-devel</Dependency>
<Dependency versionFrom="1.1.1l">openssl-devel</Dependency>
<Dependency>readline-devel</Dependency>
<Dependency versionFrom="2.32">glibc-devel</Dependency>
<!-- Bootstrap -->
@@ -55,6 +55,10 @@
<Patch>gentoo/0015-Turkish-locale.patch</Patch>
<Patch>gentoo/0022-Force-using-system-libffi.patch</Patch>
<Patch>gentoo/0024-3.6-bpo-42967-only-use-as-a-query-string-separator-G.patch</Patch>
<Patch>gentoo/0026-3.6-bpo-43285-Make-ftplib-not-trust-the-PASV-respons.patch</Patch>
<Patch>gentoo/0027-bpo-43075-Fix-ReDoS-in-urllib-AbstractBasicAuthHandl.patch</Patch>
<Patch>gentoo/0028-3.9-bpo-43882-urllib.parse-should-sanitize-urls-cont.patch</Patch>
<Patch>gentoo/0030-Backport-bpo-44022-Fix-http-client-infinite-line-rea.patch</Patch>
</Patches>
</Source>
@@ -150,6 +154,13 @@
</Package>-->
<History>
<Update release="13">
<Date>2021-08-27</Date>-
<Version>2.7.18</Version>
<Comment>Rebuild.</Comment>
<Name>Mustafa Cinasal</Name>
<Email>muscnsl@gmail.com</Email>
</Update>
<Update release="12">
<Date>2021-06-19</Date>-
<Version>2.7.18</Version>
@@ -0,0 +1,166 @@
From d2b1b144b75974db6c16087398bccdd5117908e3 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Sun, 2 May 2021 06:49:03 -0700
Subject: [PATCH 14/17] bpo-36384: Leading zeros in IPv4 addresses are no
longer tolerated (GH-25099) (GH-25815)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reverts commit e653d4d8e820a7a004ad399530af0135b45db27a and makes
parsing even more strict. Like socket.inet_pton() any leading zero
is now treated as invalid input.
Signed-off-by: Christian Heimes <christian@python.org>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
(cherry picked from commit 60ce8f0be6354ad565393ab449d8de5d713f35bc)
---
Doc/library/ipaddress.rst | 19 +++++++++++++++--
Doc/tools/susp-ignored.csv | 8 +++++--
Doc/whatsnew/3.8.rst | 8 +++++++
Lib/ipaddress.py | 5 +++++
Lib/test/test_ipaddress.py | 21 +++++++++++++++----
.../2021-03-30-16-29-51.bpo-36384.sCAmLs.rst | 6 ++++++
6 files changed, 59 insertions(+), 8 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2021-03-30-16-29-51.bpo-36384.sCAmLs.rst
diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst
index 2cdfddb02e..a6833dae57 100644
--- a/Doc/library/ipaddress.rst
+++ b/Doc/library/ipaddress.rst
@@ -104,8 +104,7 @@ write code that handles both IP versions correctly. Address objects are
1. A string in decimal-dot notation, consisting of four decimal integers in
the inclusive range 0--255, separated by dots (e.g. ``192.168.0.1``). Each
integer represents an octet (byte) in the address. Leading zeroes are
- tolerated only for values less than 8 (as there is no ambiguity
- between the decimal and octal interpretations of such strings).
+ not tolerated to prevent confusion with octal notation.
2. An integer that fits into 32 bits.
3. An integer packed into a :class:`bytes` object of length 4 (most
significant octet first).
@@ -117,6 +116,22 @@ write code that handles both IP versions correctly. Address objects are
>>> ipaddress.IPv4Address(b'\xC0\xA8\x00\x01')
IPv4Address('192.168.0.1')
+ .. versionchanged:: 3.8
+
+ Leading zeros are tolerated, even in ambiguous cases that look like
+ octal notation.
+
+ .. versionchanged:: 3.10
+
+ Leading zeros are no longer tolerated and are treated as an error.
+ IPv4 address strings are now parsed as strict as glibc
+ :func:`~socket.inet_pton`.
+
+ .. versionchanged:: 3.9.5
+
+ The above change was also included in Python 3.9 starting with
+ version 3.9.5.
+
.. attribute:: version
The appropriate version number: ``4`` for IPv4, ``6`` for IPv6.
diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv
index dd6aa38d72..1d7ebefe25 100644
--- a/Doc/tools/susp-ignored.csv
+++ b/Doc/tools/susp-ignored.csv
@@ -142,8 +142,12 @@ library/ipaddress,,:db8,IPv6Address('2001:db8::')
library/ipaddress,,::,IPv6Address('2001:db8::')
library/ipaddress,,:db8,>>> ipaddress.IPv6Address('2001:db8::1000')
library/ipaddress,,::,>>> ipaddress.IPv6Address('2001:db8::1000')
-library/ipaddress,,:db8,IPv6Address('2001:db8::1000')
-library/ipaddress,,::,IPv6Address('2001:db8::1000')
+library/ipaddress,,:db8,'2001:db8::1000'
+library/ipaddress,,::,'2001:db8::1000'
+library/ipaddress,,:db8,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
+library/ipaddress,,::,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
+library/ipaddress,,::,IPv6Address('ff02::5678%1')
+library/ipaddress,,::,fe80::1234
library/ipaddress,,:db8,">>> ipaddress.ip_address(""2001:db8::1"").reverse_pointer"
library/ipaddress,,::,">>> ipaddress.ip_address(""2001:db8::1"").reverse_pointer"
library/ipaddress,,::,"""::abc:7:def"""
diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst
index 109a06e92e..95ab18d15b 100644
--- a/Doc/whatsnew/3.8.rst
+++ b/Doc/whatsnew/3.8.rst
@@ -950,6 +950,14 @@ notebook.
reviewed by Vinay Sajip in :issue:`33897`.)
+ipaddress
+---------
+
+Starting with Python 3.8.9_p1 (Gentoo) the :mod:`ipaddress` module no longer
+accepts any leading zeros in IPv4 address strings.
+(Contributed by Christian Heimes in :issue:`36384`).
+
+
math
----
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py
index 28b7b6159a..d351f07a5b 100644
--- a/Lib/ipaddress.py
+++ b/Lib/ipaddress.py
@@ -1173,6 +1173,11 @@ class _BaseV4:
if len(octet_str) > 3:
msg = "At most 3 characters permitted in %r"
raise ValueError(msg % octet_str)
+ # Handle leading zeros as strict as glibc's inet_pton()
+ # See security bug bpo-36384
+ if octet_str != '0' and octet_str[0] == '0':
+ msg = "Leading zeros are not permitted in %r"
+ raise ValueError(msg % octet_str)
# Convert to integer (we know digits are legal)
octet_int = int(octet_str, 10)
if octet_int > 255:
diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py
index 2f1c5b6b6f..1297b8371d 100644
--- a/Lib/test/test_ipaddress.py
+++ b/Lib/test/test_ipaddress.py
@@ -97,10 +97,23 @@ class CommonTestMixin:
class CommonTestMixin_v4(CommonTestMixin):
def test_leading_zeros(self):
- self.assertInstancesEqual("000.000.000.000", "0.0.0.0")
- self.assertInstancesEqual("192.168.000.001", "192.168.0.1")
- self.assertInstancesEqual("016.016.016.016", "16.16.16.16")
- self.assertInstancesEqual("001.000.008.016", "1.0.8.16")
+ # bpo-36384: no leading zeros to avoid ambiguity with octal notation
+ msg = "Leading zeros are not permitted in '\d+'"
+ addresses = [
+ "000.000.000.000",
+ "192.168.000.001",
+ "016.016.016.016",
+ "192.168.000.001",
+ "001.000.008.016",
+ "01.2.3.40",
+ "1.02.3.40",
+ "1.2.03.40",
+ "1.2.3.040",
+ ]
+ for address in addresses:
+ with self.subTest(address=address):
+ with self.assertAddressError(msg):
+ self.factory(address)
def test_int(self):
self.assertInstancesEqual(0, "0.0.0.0")
diff --git a/Misc/NEWS.d/next/Security/2021-03-30-16-29-51.bpo-36384.sCAmLs.rst b/Misc/NEWS.d/next/Security/2021-03-30-16-29-51.bpo-36384.sCAmLs.rst
new file mode 100644
index 0000000000..f956cde948
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2021-03-30-16-29-51.bpo-36384.sCAmLs.rst
@@ -0,0 +1,6 @@
+:mod:`ipaddress` module no longer accepts any leading zeros in IPv4 address
+strings. Leading zeros are ambiguous and interpreted as octal notation by
+some libraries. For example the legacy function :func:`socket.inet_aton`
+treats leading zeros as octal notatation. glibc implementation of modern
+:func:`~socket.inet_pton` does not accept any leading zeros. For a while
+the :mod:`ipaddress` module used to accept ambiguous leading zeros.
--
2.32.0
@@ -0,0 +1,61 @@
From 5a5335aba36f6c4204ba65faa8b2e67025c1bd4a Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Mon, 17 May 2021 10:34:39 -0700
Subject: [PATCH 16/17] bpo-43650: Fix MemoryError on zip.read in
shutil._unpack_zipfile for large files (GH-25058)
`shutil.unpack_archive()` tries to read the whole file into memory, making no use of any kind of smaller buffer. Process crashes for really large files: I.e. archive: ~1.7G, unpacked: ~10G. Before the crash it can easily take away all available RAM on smaller systems. Had to pull the code form `zipfile.Zipfile.extractall()` to fix this
Automerge-Triggered-By: GH:gpshead
(cherry picked from commit f32c7950e0077b6d9a8e217c2796fc582f18ca08)
Co-authored-by: Igor Bolshakov <ibolsch@gmail.com>
---
Lib/shutil.py | 16 ++++++----------
.../2021-03-29-00-23-30.bpo-43650.v01tic.rst | 2 ++
2 files changed, 8 insertions(+), 10 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst
diff --git a/Lib/shutil.py b/Lib/shutil.py
index fdadb83800..aaf76c651b 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -1144,20 +1144,16 @@ def _unpack_zipfile(filename, extract_dir):
if name.startswith('/') or '..' in name:
continue
- target = os.path.join(extract_dir, *name.split('/'))
- if not target:
+ targetpath = os.path.join(extract_dir, *name.split('/'))
+ if not targetpath:
continue
- _ensure_directory(target)
+ _ensure_directory(targetpath)
if not name.endswith('/'):
# file
- data = zip.read(info.filename)
- f = open(target, 'wb')
- try:
- f.write(data)
- finally:
- f.close()
- del data
+ with zip.open(name, 'r') as source, \
+ open(targetpath, 'wb') as target:
+ copyfileobj(source, target)
finally:
zip.close()
diff --git a/Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst b/Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst
new file mode 100644
index 0000000000..a2ea4a4800
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-03-29-00-23-30.bpo-43650.v01tic.rst
@@ -0,0 +1,2 @@
+Fix :exc:`MemoryError` in :func:`shutil.unpack_archive` which fails inside
+:func:`shutil._unpack_zipfile` on large files. Patch by Igor Bolshakov.
--
2.32.0
@@ -0,0 +1,214 @@
From 5b42865796c6bf768d4d11e3c93dc0994d46f783 Mon Sep 17 00:00:00 2001
From: Christian Heimes <christian@python.org>
Date: Sat, 1 May 2021 20:53:10 +0200
Subject: [PATCH 17/17] bpo-43998: Default to TLS 1.2 and increase cipher suite
security (GH-25778)
The ssl module now has more secure default settings. Ciphers without forward
secrecy or SHA-1 MAC are disabled by default. Security level 2 prohibits
weak RSA, DH, and ECC keys with less than 112 bits of security.
:class:`~ssl.SSLContext` defaults to minimum protocol version TLS 1.2.
Settings are based on Hynek Schlawack's research.
```
$ openssl version
OpenSSL 1.1.1k FIPS 25 Mar 2021
$ openssl ciphers -v '@SECLEVEL=2:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES:DHE+AES:!aNULL:!eNULL:!aDSS:!SHA1:!AESCCM'
TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
TLS_AES_128_CCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESCCM(128) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD
ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH Au=ECDSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
ECDHE-RSA-CHACHA20-POLY1305 TLSv1.2 Kx=ECDH Au=RSA Enc=CHACHA20/POLY1305(256) Mac=AEAD
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384
ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256
ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256
DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD
DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256
DHE-RSA-AES128-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(128) Mac=SHA256
```
Signed-off-by: Christian Heimes <christian@python.org>
---
Doc/library/ssl.rst | 8 ++++
Lib/test/test_nntplib.py | 24 +++++++++--
.../2021-05-01-13-13-40.bpo-43998.xhmWD7.rst | 5 +++
Modules/_ssl.c | 43 ++++++++++++++++---
4 files changed, 72 insertions(+), 8 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2021-05-01-13-13-40.bpo-43998.xhmWD7.rst
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index a58717c3ab..f1c43ee3d8 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -1471,6 +1471,14 @@ to speed up repeated connections from the same clients.
ciphers, no ``NULL`` ciphers and no ``MD5`` ciphers (except for
:data:`PROTOCOL_SSLv2`).
+ .. versionchanged:: 3.9.5_p2 (Gentoo)
+
+ The default cipher suites now include only secure AES and ChaCha20
+ ciphers with forward secrecy and security level 2. RSA and DH keys with
+ less than 2048 bits and ECC keys with less than 224 bits are prohibited.
+ :data:`PROTOCOL_TLS`, :data:`PROTOCOL_TLS_CLIENT`, and
+ :data:`PROTOCOL_TLS_SERVER` use TLS 1.2 as minimum TLS version.
+
:class:`SSLContext` objects have the following methods and attributes:
diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py
index 89a2004dfb..d27e4abae8 100644
--- a/Lib/test/test_nntplib.py
+++ b/Lib/test/test_nntplib.py
@@ -37,6 +37,8 @@ else:
class NetworkedNNTPTestsMixin:
+ ssl_context = None
+
def test_welcome(self):
welcome = self.server.getwelcome()
self.assertEqual(str, type(welcome))
@@ -269,6 +271,13 @@ class NetworkedNNTPTestsMixin:
return False
return True
+ kwargs = dict(
+ timeout=support.INTERNET_TIMEOUT,
+ usenetrc=False
+ )
+ if self.ssl_context is not None:
+ kwargs["ssl_context"] = self.ssl_context
+
try:
with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
self.assertTrue(is_connected())
@@ -306,15 +315,21 @@ class NetworkedNNTPTests(NetworkedNNTPTestsMixin, unittest.TestCase):
@classmethod
def setUpClass(cls):
support.requires("network")
- with support.transient_internet(cls.NNTP_HOST):
+ kwargs = dict(
+ timeout=support.INTERNET_TIMEOUT,
+ usenetrc=False
+ )
+ if cls.ssl_context is not None:
+ kwargs["ssl_context"] = cls.ssl_context
+ with socket_helper.transient_internet(cls.NNTP_HOST):
try:
- cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, timeout=TIMEOUT,
- usenetrc=False)
+ cls.server = cls.NNTP_CLASS(cls.NNTP_HOST, **kwargs)
except SSLError as ssl_err:
# matches "[SSL: DH_KEY_TOO_SMALL] dh key too small"
if re.search(r'(?i)KEY.TOO.SMALL', ssl_err.reason):
raise unittest.SkipTest(f"{cls} got {ssl_err} connecting "
f"to {cls.NNTP_HOST!r}")
+ print(cls.NNTP_HOST)
raise
except EOF_ERRORS:
raise unittest.SkipTest(f"{cls} got EOF error on connecting "
@@ -347,6 +362,9 @@ class NetworkedNNTP_SSLTests(NetworkedNNTPTests):
# Disabled as the connection will already be encrypted.
test_starttls = None
+ ssl_context = ssl._create_unverified_context()
+ ssl_context.set_ciphers("DEFAULT")
+ ssl_context.maximum_version = ssl.TLSVersion.TLSv1_2
#
# Non-networked tests using a local server (or something mocking it).
diff --git a/Misc/NEWS.d/next/Security/2021-05-01-13-13-40.bpo-43998.xhmWD7.rst b/Misc/NEWS.d/next/Security/2021-05-01-13-13-40.bpo-43998.xhmWD7.rst
new file mode 100644
index 0000000000..6a40346128
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2021-05-01-13-13-40.bpo-43998.xhmWD7.rst
@@ -0,0 +1,5 @@
+The :mod:`ssl` module sets more secure cipher suites defaults. Ciphers
+without forward secrecy and with SHA-1 MAC are disabled by default. Security
+level 2 prohibits weak RSA, DH, and ECC keys with less than 112 bits of
+security. :class:`~ssl.SSLContext` defaults to minimum protocol version TLS
+1.2. Settings are based on Hynek Schlawack's research.
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index bc665db0d5..01a2067596 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -300,15 +300,27 @@ SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s)
#ifndef PY_SSL_DEFAULT_CIPHER_STRING
#error "Py_SSL_DEFAULT_CIPHERS 0 needs Py_SSL_DEFAULT_CIPHER_STRING"
#endif
+ #ifndef PY_SSL_MIN_PROTOCOL
+ #define PY_SSL_MIN_PROTOCOL TLS1_2_VERSION
+ #endif
#elif PY_SSL_DEFAULT_CIPHERS == 1
/* Python custom selection of sensible cipher suites
- * DEFAULT: OpenSSL's default cipher list. Since 1.0.2 the list is in sensible order.
+ * @SECLEVEL=2: security level 2 with 112 bits minimum security (e.g. 2048 bits RSA key)
+ * ECDH+*: enable ephemeral elliptic curve Diffie-Hellman
+ * DHE+*: fallback to ephemeral finite field Diffie-Hellman
+ * encryption order: AES AEAD (GCM), ChaCha AEAD, AES CBC
* !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
+ * !SHA1: no weak SHA1 MAC
+ * !AESCCM: no CCM mode, it's uncommon and slow
+ *
+ * Based on Hynek's excellent blog post (update 2021-02-11)
+ * https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
*/
- #define PY_SSL_DEFAULT_CIPHER_STRING "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"
+ #define PY_SSL_DEFAULT_CIPHER_STRING "@SECLEVEL=2:ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES:DHE+AES:!aNULL:!eNULL:!aDSS:!SHA1:!AESCCM"
+ #ifndef PY_SSL_MIN_PROTOCOL
+ #define PY_SSL_MIN_PROTOCOL TLS1_2_VERSION
+ #endif
#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
@@ -3249,8 +3261,25 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
ERR_clear_error();
PyErr_SetString(PySSLErrorObject,
"No cipher can be selected.");
- return NULL;
+ goto error;
+ }
+#ifdef PY_SSL_MIN_PROTOCOL
+ switch(proto_version) {
+ case PY_SSL_VERSION_TLS:
+ case PY_SSL_VERSION_TLS_CLIENT:
+ case PY_SSL_VERSION_TLS_SERVER:
+ result = SSL_CTX_set_min_proto_version(ctx, PY_SSL_MIN_PROTOCOL);
+ if (result == 0) {
+ PyErr_Format(PyExc_ValueError,
+ "Failed to set minimum protocol 0x%x",
+ PY_SSL_MIN_PROTOCOL);
+ goto error;
+ }
+ break;
+ default:
+ break;
}
+#endif
#if defined(SSL_MODE_RELEASE_BUFFERS)
/* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory
@@ -3303,6 +3332,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
#endif
return (PyObject *)self;
+ error:
+ Py_XDECREF(self);
+ ERR_clear_error();
+ return NULL;
}
static int
--
2.32.0
+11 -5
View File
@@ -12,7 +12,7 @@
<License>custom</License>
<Summary>Next generation of the python high-level scripting language</Summary>
<Description>Python is an accessible, high-level, dynamically typed, interpreted programming language, designed with an emphasis on code readability. It includes an extensive standard library, and has a vast ecosystem of third-party libraries.</Description>
<Archive sha1sum="f6579351d42a81c77b55aa4ca8b1280b4f5b37f9" type="tarxz">https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tar.xz</Archive>
<Archive sha1sum="1561060627fd171de19c53eb374cd92d2f297bff" type="tarxz">https://www.python.org/ftp/python/3.8.11/Python-3.8.11.tar.xz</Archive>
<!-- <Archive sha1sum="bf7badf7e248e0ecf465d33c2f5aeec774209227" type="targz" target="Python-3.8.5">https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz</Archive> -->
<BuildDependencies>
<Dependency>bzip2</Dependency>
@@ -31,10 +31,9 @@
<!--<Dependency>tcltk-devel</Dependency>-->
</BuildDependencies>
<Patches>
<!--
<Patch level="1">dont-make-libpython-readonly.patch</Patch>
<Patch level="1">0001-compileall-Fix-ddir-when-recursing.patch</Patch>
-->
<Patch level="1">gentoo/0014-bpo-36384-Leading-zeros-in-IPv4-addresses-are-no-lon.patch</Patch>
<Patch level="1">gentoo/0016-bpo-43650-Fix-MemoryError-on-zip.read-in-shutil._unp.patch</Patch>
<Patch level="1">gentoo/0017-bpo-43998-Default-to-TLS-1.2-and-increase-cipher-sui.patch</Patch>
</Patches>
</Source>
@@ -128,6 +127,13 @@
</Package>
<History>
<Update release="16">
<Date>2021-08-27</Date>
<Version>3.8.11</Version>
<Comment>Version bump.</Comment>
<Name>Mustafa Cinasal</Name>
<Email>muscnsl@gmail.com</Email>
</Update>
<Update release="15">
<Date>2021-06-19</Date>
<Version>3.8.10</Version>