diff --git a/.gitignore b/.gitignore index 61a4314..630c966 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ /urllib3-1.20.tar.gz /urllib3-1.21.1.tar.gz /urllib3-1.22.tar.gz +/urllib3-1.23.tar.gz +/urllib3-1.24.tar.gz +/urllib3-1.24.1.tar.gz diff --git a/0001-Do-not-lowercase-hostnames-with-custom-protocol.patch b/0001-Do-not-lowercase-hostnames-with-custom-protocol.patch deleted file mode 100644 index 7e98a4b..0000000 --- a/0001-Do-not-lowercase-hostnames-with-custom-protocol.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 92da9e010f506cdd2408f6915ff87926f907c927 Mon Sep 17 00:00:00 2001 -From: Lukas Slebodnik -Date: Thu, 12 Apr 2018 00:34:07 +0200 -Subject: [PATCH 1] Do not lowercase hostnames with custom-protocol(#1267) - -Unix sockets are are case sensitive the same as other files -on standard unix file systems. ---- - urllib3/connectionpool.py | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - -diff --git a/test/test_connectionpool.py b/test/test_connectionpool.py -index d8b8a83..4b74ab4 100644 ---- a/test/test_connectionpool.py -+++ b/test/test_connectionpool.py -@@ -32,6 +32,19 @@ from ssl import SSLError as BaseSSLError - from dummyserver.server import DEFAULT_CA - - -+class HTTPUnixConnection(HTTPConnection): -+ def __init__(self, host, timeout=60, **kwargs): -+ super(HTTPUnixConnection, self).__init__('localhost') -+ self.unix_socket = host -+ self.timeout = timeout -+ self.sock = None -+ -+ -+class HTTPUnixConnectionPool(HTTPConnectionPool): -+ scheme = 'http+unix' -+ ConnectionCls = HTTPUnixConnection -+ -+ - class TestConnectionPool(object): - """ - Tests in this suite should exercise the ConnectionPool functionality -@@ -138,6 +151,31 @@ class TestConnectionPool(object): - with HTTPSConnectionPool(b) as c: - assert not c.is_same_host(a) - -+ @pytest.mark.parametrize('a, b', [ -+ ('%2Fvar%2Frun%2Fdocker.sock', -+ 'http+unix://%2Fvar%2Frun%2Fdocker.sock'), -+ ('%2Fvar%2Frun%2Fdocker.sock', -+ 'http+unix://%2Fvar%2Frun%2Fdocker.sock/'), -+ ('%2Fvar%2Frun%2Fdocker.sock', -+ 'http+unix://%2Fvar%2Frun%2Fdocker.sock/abracadabra'), -+ ('%2Ftmp%2FTEST.sock', 'http+unix://%2Ftmp%2FTEST.sock'), -+ ('%2Ftmp%2FTEST.sock', 'http+unix://%2Ftmp%2FTEST.sock/'), -+ ('%2Ftmp%2FTEST.sock', 'http+unix://%2Ftmp%2FTEST.sock/abracadabra'), -+ ]) -+ def test_same_host_custom_protocol(self, a, b): -+ with HTTPUnixConnectionPool(a) as c: -+ assert c.is_same_host(b) -+ -+ @pytest.mark.parametrize('a, b', [ -+ ('%2Ftmp%2Ftest.sock', 'http+unix://%2Ftmp%2FTEST.sock'), -+ ('%2Ftmp%2Ftest.sock', 'http+unix://%2Ftmp%2FTEST.sock/'), -+ ('%2Ftmp%2Ftest.sock', 'http+unix://%2Ftmp%2FTEST.sock/abracadabra'), -+ ('%2Fvar%2Frun%2Fdocker.sock', 'http+unix://%2Ftmp%2FTEST.sock'), -+ ]) -+ def test_not_same_host_custom_protocol(self, a, b): -+ with HTTPUnixConnectionPool(a) as c: -+ assert not c.is_same_host(b) -+ - def test_max_connections(self): - with HTTPConnectionPool(host='localhost', maxsize=1, block=True) as pool: - pool._get_conn(timeout=0.01) -diff --git a/urllib3/connectionpool.py b/urllib3/connectionpool.py -index ec9600f..2d7a26b 100644 ---- a/urllib3/connectionpool.py -+++ b/urllib3/connectionpool.py -@@ -40,7 +40,7 @@ from .util.request import set_file_position - from .util.response import assert_header_parsing - from .util.retry import Retry - from .util.timeout import Timeout --from .util.url import get_host, Url -+from .util.url import get_host, Url, NORMALIZABLE_SCHEMES - - - if six.PY2: -@@ -68,7 +68,7 @@ class ConnectionPool(object): - if not host: - raise LocationValueError("No host specified.") - -- self.host = _ipv6_host(host).lower() -+ self.host = _ipv6_host(host, self.scheme) - self._proxy_host = host.lower() - self.port = port - -@@ -434,7 +434,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods): - # TODO: Add optional support for socket.gethostbyname checking. - scheme, host, port = get_host(url) - -- host = _ipv6_host(host).lower() -+ host = _ipv6_host(host, self.scheme) - - # Use explicit default port for comparison when none is given - if self.port and not port: -@@ -886,7 +886,7 @@ def connection_from_url(url, **kw): - return HTTPConnectionPool(host, port=port, **kw) - - --def _ipv6_host(host): -+def _ipv6_host(host, scheme): - """ - Process IPv6 address literals - """ -@@ -902,4 +902,6 @@ def _ipv6_host(host): - # percent sign might be URIencoded, convert it back into ASCII - if host.startswith('[') and host.endswith(']'): - host = host.replace('%25', '%').strip('[]') -+ if scheme in NORMALIZABLE_SCHEMES: -+ host = host.lower() - return host diff --git a/Unbundle-ssl_match_hostname-backport.patch b/Unbundle-ssl_match_hostname-backport.patch new file mode 100644 index 0000000..5ad88ed --- /dev/null +++ b/Unbundle-ssl_match_hostname-backport.patch @@ -0,0 +1,207 @@ +From ee3425b5bfba3262c3485265c3aaaf99169e11d0 Mon Sep 17 00:00:00 2001 +From: Jeremy Cline +Date: Mon, 29 Oct 2018 16:07:52 -0400 +Subject: [PATCH] Unbundle ssl_match_hostname backport + +Fedora has shipped 3.5+ for a long time and we depend on backports of +Python 2. + +Signed-off-by: Jeremy Cline +--- + .../packages/ssl_match_hostname/__init__.py | 14 +- + .../ssl_match_hostname/_implementation.py | 156 ------------------ + 2 files changed, 3 insertions(+), 167 deletions(-) + delete mode 100644 src/urllib3/packages/ssl_match_hostname/_implementation.py + +diff --git a/src/urllib3/packages/ssl_match_hostname/__init__.py b/src/urllib3/packages/ssl_match_hostname/__init__.py +index d6594eb..6bd8fb9 100644 +--- a/src/urllib3/packages/ssl_match_hostname/__init__.py ++++ b/src/urllib3/packages/ssl_match_hostname/__init__.py +@@ -1,19 +1,11 @@ + import sys + + try: +- # Our match_hostname function is the same as 3.5's, so we only want to +- # import the match_hostname function if it's at least that good. +- if sys.version_info < (3, 5): +- raise ImportError("Fallback to vendored code") +- ++ # Python 3.5+ + from ssl import CertificateError, match_hostname + except ImportError: +- try: +- # Backport of the function from a pypi module +- from backports.ssl_match_hostname import CertificateError, match_hostname +- except ImportError: +- # Our vendored copy +- from ._implementation import CertificateError, match_hostname ++ # Python 2 ++ from backports.ssl_match_hostname import CertificateError, match_hostname + + # Not needed, but documenting what we provide. + __all__ = ('CertificateError', 'match_hostname') +diff --git a/src/urllib3/packages/ssl_match_hostname/_implementation.py b/src/urllib3/packages/ssl_match_hostname/_implementation.py +deleted file mode 100644 +index d6e66c0..0000000 +--- a/src/urllib3/packages/ssl_match_hostname/_implementation.py ++++ /dev/null +@@ -1,156 +0,0 @@ +-"""The match_hostname() function from Python 3.3.3, essential when using SSL.""" +- +-# Note: This file is under the PSF license as the code comes from the python +-# stdlib. http://docs.python.org/3/license.html +- +-import re +-import sys +- +-# ipaddress has been backported to 2.6+ in pypi. If it is installed on the +-# system, use it to handle IPAddress ServerAltnames (this was added in +-# python-3.5) otherwise only do DNS matching. This allows +-# backports.ssl_match_hostname to continue to be used in Python 2.7. +-try: +- import ipaddress +-except ImportError: +- ipaddress = None +- +-__version__ = '3.5.0.1' +- +- +-class CertificateError(ValueError): +- pass +- +- +-def _dnsname_match(dn, hostname, max_wildcards=1): +- """Matching according to RFC 6125, section 6.4.3 +- +- http://tools.ietf.org/html/rfc6125#section-6.4.3 +- """ +- pats = [] +- if not dn: +- return False +- +- # Ported from python3-syntax: +- # leftmost, *remainder = dn.split(r'.') +- parts = dn.split(r'.') +- leftmost = parts[0] +- remainder = parts[1:] +- +- wildcards = leftmost.count('*') +- if wildcards > max_wildcards: +- # Issue #17980: avoid denials of service by refusing more +- # than one wildcard per fragment. A survey of established +- # policy among SSL implementations showed it to be a +- # reasonable choice. +- raise CertificateError( +- "too many wildcards in certificate DNS name: " + repr(dn)) +- +- # speed up common case w/o wildcards +- if not wildcards: +- return dn.lower() == hostname.lower() +- +- # RFC 6125, section 6.4.3, subitem 1. +- # The client SHOULD NOT attempt to match a presented identifier in which +- # the wildcard character comprises a label other than the left-most label. +- if leftmost == '*': +- # When '*' is a fragment by itself, it matches a non-empty dotless +- # fragment. +- pats.append('[^.]+') +- elif leftmost.startswith('xn--') or hostname.startswith('xn--'): +- # RFC 6125, section 6.4.3, subitem 3. +- # The client SHOULD NOT attempt to match a presented identifier +- # where the wildcard character is embedded within an A-label or +- # U-label of an internationalized domain name. +- pats.append(re.escape(leftmost)) +- else: +- # Otherwise, '*' matches any dotless string, e.g. www* +- pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) +- +- # add the remaining fragments, ignore any wildcards +- for frag in remainder: +- pats.append(re.escape(frag)) +- +- pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) +- return pat.match(hostname) +- +- +-def _to_unicode(obj): +- if isinstance(obj, str) and sys.version_info < (3,): +- obj = unicode(obj, encoding='ascii', errors='strict') +- return obj +- +-def _ipaddress_match(ipname, host_ip): +- """Exact matching of IP addresses. +- +- RFC 6125 explicitly doesn't define an algorithm for this +- (section 1.7.2 - "Out of Scope"). +- """ +- # OpenSSL may add a trailing newline to a subjectAltName's IP address +- # Divergence from upstream: ipaddress can't handle byte str +- ip = ipaddress.ip_address(_to_unicode(ipname).rstrip()) +- return ip == host_ip +- +- +-def match_hostname(cert, hostname): +- """Verify that *cert* (in decoded format as returned by +- SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 +- rules are followed, but IP addresses are not accepted for *hostname*. +- +- CertificateError is raised on failure. On success, the function +- returns nothing. +- """ +- if not cert: +- raise ValueError("empty or no certificate, match_hostname needs a " +- "SSL socket or SSL context with either " +- "CERT_OPTIONAL or CERT_REQUIRED") +- try: +- # Divergence from upstream: ipaddress can't handle byte str +- host_ip = ipaddress.ip_address(_to_unicode(hostname)) +- except ValueError: +- # Not an IP address (common case) +- host_ip = None +- except UnicodeError: +- # Divergence from upstream: Have to deal with ipaddress not taking +- # byte strings. addresses should be all ascii, so we consider it not +- # an ipaddress in this case +- host_ip = None +- except AttributeError: +- # Divergence from upstream: Make ipaddress library optional +- if ipaddress is None: +- host_ip = None +- else: +- raise +- dnsnames = [] +- san = cert.get('subjectAltName', ()) +- for key, value in san: +- if key == 'DNS': +- if host_ip is None and _dnsname_match(value, hostname): +- return +- dnsnames.append(value) +- elif key == 'IP Address': +- if host_ip is not None and _ipaddress_match(value, host_ip): +- return +- dnsnames.append(value) +- if not dnsnames: +- # The subject is only checked when there is no dNSName entry +- # in subjectAltName +- for sub in cert.get('subject', ()): +- for key, value in sub: +- # XXX according to RFC 2818, the most specific Common Name +- # must be used. +- if key == 'commonName': +- if _dnsname_match(value, hostname): +- return +- dnsnames.append(value) +- if len(dnsnames) > 1: +- raise CertificateError("hostname %r " +- "doesn't match either of %s" +- % (hostname, ', '.join(map(repr, dnsnames)))) +- elif len(dnsnames) == 1: +- raise CertificateError("hostname %r " +- "doesn't match %r" +- % (hostname, dnsnames[0])) +- else: +- raise CertificateError("no appropriate commonName or " +- "subjectAltName fields were found") +-- +2.19.1 + diff --git a/python-urllib3-recent-date.patch b/python-urllib3-recent-date.patch deleted file mode 100644 index 720d76f..0000000 --- a/python-urllib3-recent-date.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 4bff1e93d2dd4663d422d7e290473d9189cec5db Mon Sep 17 00:00:00 2001 -From: Dominique Leuenberger -Date: Sun, 31 Dec 2017 15:11:16 +0100 -Subject: [PATCH] Move RECENT_DATE to 2017-06-30 - -The test suite expects the current date to be no more than two years in the future -of RECENT_DATE, which just serves as a reference point. - -Also clarify the comment about how to update RECENT_DATE - -Fixes #1303 - -diff --git a/urllib3/connection.py b/urllib3/connection.py -index 06bcbde1a..a03b573f0 100644 ---- a/urllib3/connection.py -+++ b/urllib3/connection.py -@@ -56,10 +56,11 @@ class ConnectionError(Exception): - 'https': 443, - } - --# When updating RECENT_DATE, move it to --# within two years of the current date, and no --# earlier than 6 months ago. --RECENT_DATE = datetime.date(2016, 1, 1) -+# When updating RECENT_DATE, move it to within two years of the current date, -+# and not less than 6 months ago. -+# Example: if Today is 2018-01-01, then RECENT_DATE should be any date on or -+# after 2016-01-01 (today - 2 years) AND before 2017-07-01 (today - 6 months) -+RECENT_DATE = datetime.date(2017, 6, 30) - - - class DummyConnection(object): diff --git a/python-urllib3.spec b/python-urllib3.spec index 10dc210..61d59e3 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -1,19 +1,15 @@ %global srcname urllib3 Name: python-%{srcname} -Version: 1.22 -Release: 9%{?dist} +Version: 1.24.1 +Release: 1%{?dist} Summary: Python HTTP library with thread-safe connection pooling and file post License: MIT -URL: https://github.com/shazow/urllib3 +URL: https://github.com/urllib3/urllib3 Source0: %{url}/archive/%{version}/%{srcname}-%{version}.tar.gz -# Used with Python 3.5+ -Source1: ssl_match_hostname_py3.py -# https://github.com/shazow/urllib3/commit/4bff1e93d2dd4663d422d7e290473d9189cec5db -Patch0: python-urllib3-recent-date.patch -# https://github.com/urllib3/urllib3/commit/9f09cb4b9d69bd8944c881f61b8fe933ad425b5b -Patch0001: 0001-Do-not-lowercase-hostnames-with-custom-protocol.patch +# Unbundle ssl_match_hostname since we depend on it +Patch0: Unbundle-ssl_match_hostname-backport.patch BuildArch: noarch %description @@ -35,6 +31,7 @@ Requires: python2-pysocks BuildRequires: python2-devel # For unittests +BuildRequires: python2-backports-ssl_match_hostname BuildRequires: python2-nose BuildRequires: python2-nose-exclude BuildRequires: python2-coverage @@ -71,9 +68,7 @@ Python3 HTTP module with connection pooling and file POST abilities. %prep -%setup -q -n %{srcname}-%{version} -%patch0 -p1 -b .recent-date -%patch1 -p1 +%autosetup -p1 -n %{srcname}-%{version} # Drop the dummyserver tests in koji. They fail there in real builds, but not # in scratch builds (weird). rm -rf test/with_dummyserver/ @@ -83,6 +78,10 @@ rm -rf test/appengine/ # to do with Fedora in particular. They don't fail in upstream build infrastructure rm -rf test/contrib/ +# Tests for Python built without SSL, but Fedora builds with SSL. These tests +# fail when combined with the unbundling of backports-ssl_match_hostname +rm -f test/test_no_ssl.py + %build %py2_build %py3_build @@ -94,33 +93,29 @@ rm -rf test/contrib/ # Unbundle the Python 2 build rm -rf %{buildroot}/%{python2_sitelib}/urllib3/packages/six.py* -rm -rf %{buildroot}/%{python2_sitelib}/urllib3/packages/ssl_match_hostname/ mkdir -p %{buildroot}/%{python2_sitelib}/urllib3/packages/ -ln -s ../../six.py %{buildroot}/%{python2_sitelib}/urllib3/packages/six.py -ln -s ../../six.pyc %{buildroot}/%{python2_sitelib}/urllib3/packages/six.pyc -ln -s ../../six.pyo %{buildroot}/%{python2_sitelib}/urllib3/packages/six.pyo - -ln -s ../../backports/ssl_match_hostname %{buildroot}/%{python2_sitelib}/urllib3/packages/ssl_match_hostname +ln -s %{python2_sitelib}/six.py %{buildroot}/%{python2_sitelib}/urllib3/packages/six.py +ln -s %{python2_sitelib}/six.pyc %{buildroot}/%{python2_sitelib}/urllib3/packages/six.pyc +ln -s %{python2_sitelib}/six.pyo %{buildroot}/%{python2_sitelib}/urllib3/packages/six.pyo # Unbundle the Python 3 build rm -rf %{buildroot}/%{python3_sitelib}/urllib3/packages/six.py* rm -rf %{buildroot}/%{python3_sitelib}/urllib3/packages/__pycache__/six* -rm -rf %{buildroot}/%{python3_sitelib}/urllib3/packages/ssl_match_hostname/ mkdir -p %{buildroot}/%{python3_sitelib}/urllib3/packages/ -ln -s ../../six.py %{buildroot}/%{python3_sitelib}/urllib3/packages/six.py -ln -s ../../../__pycache__/six.cpython-%{python3_version_nodots}.opt-1.pyc %{buildroot}/%{python3_sitelib}/urllib3/packages/__pycache__/ -ln -s ../../../__pycache__/six.cpython-%{python3_version_nodots}.pyc %{buildroot}/%{python3_sitelib}/urllib3/packages/__pycache__/ -# urllib3 requires Python 3.5 to use the standard library's match_hostname, -# which we ship in Fedora 26, so we can safely replace the bundled version with -# this stub which imports the necessary objects. -cp %{SOURCE1} %{buildroot}/%{python3_sitelib}/urllib3/packages/ssl_match_hostname.py +ln -s %{python3_sitelib}/six.py %{buildroot}/%{python3_sitelib}/urllib3/packages/six.py +ln -s %{python3_sitelib}/__pycache__/six.cpython-%{python3_version_nodots}.opt-1.pyc \ + %{buildroot}/%{python3_sitelib}/urllib3/packages/__pycache__/ +ln -s %{python3_sitelib}/__pycache__/six.cpython-%{python3_version_nodots}.pyc \ + %{buildroot}/%{python3_sitelib}/urllib3/packages/__pycache__/ %check -py.test -py.test-3 +pushd test +PYTHONPATH=%{buildroot}%{python2_sitelib}:%{python2_sitelib} %{__python2} -m pytest -v +PYTHONPATH=%{buildroot}%{python3_sitelib}:%{python3_sitelib} %{__python3} -m pytest -v +popd %files -n python2-%{srcname} @@ -138,6 +133,9 @@ py.test-3 %changelog +* Mon Oct 29 2018 Jeremy Cline - 1.24.1-1 +- Update to v1.24.1 + * Thu May 03 2018 Lukas Slebodnik - 1.22-9 - Do not lowercase hostnames with custom-protocol (rhbz 1567862) - upstream: https://github.com/urllib3/urllib3/issues/1267 diff --git a/sources b/sources index 8488c8b..d1287f7 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (urllib3-1.22.tar.gz) = 1b45a4a64e71847a4fc62b9263235d5b05b62076698fa324454efeb7ad065abd702cc9eadb2d396d9270b07e91e9bad94c52a4b9b115aadccb27f81955e6feab +SHA512 (urllib3-1.24.1.tar.gz) = 2f5453cf0ec1b65de9a9fca0fdb45664f7481507c875b7115c063cb177628b4b611377e588508ab8433e0797fc78b60fd3ea5cc5ac0a3f105d36bfff9a56f1f4