From 573e987c72c9665810b28ac0e849f514c8d2f05f Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Mon, 16 Apr 2018 10:31:30 -0400 Subject: [PATCH 1/6] Drop PyOpenSSL requirement (rhbz 1567862) Signed-off-by: Jeremy Cline --- python-urllib3.spec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python-urllib3.spec b/python-urllib3.spec index 4effa36..6a650c8 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -2,7 +2,7 @@ Name: python-%{srcname} Version: 1.22 -Release: 6%{?dist} +Release: 7%{?dist} Summary: Python HTTP library with thread-safe connection pooling and file post License: MIT @@ -28,7 +28,6 @@ Requires: python2-six Requires: python2-backports-ssl_match_hostname # Secure extra requirements -Requires: python2-pyOpenSSL Requires: python2-cryptography Requires: python2-idna Requires: python2-ipaddress @@ -66,7 +65,6 @@ BuildRequires: python3-tornado Requires: ca-certificates Requires: python3-six Requires: python3-pysocks -Requires: python3-pyOpenSSL Requires: python3-cryptography Requires: python3-idna Requires: python3-pysocks @@ -142,6 +140,9 @@ py.test-3 %changelog +* Mon Apr 16 2018 Jeremy Cline - 1.22-7 +- Drop the dependency on PyOpenSSL, it's not needed (rhbz 1567862) + * Fri Feb 09 2018 Fedora Release Engineering - 1.22-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild From d6a8e52d2418ae9dab5c3eff28eceaeb6edd5860 Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Wed, 18 Apr 2018 12:16:13 -0400 Subject: [PATCH 2/6] Drop the dependency on cryptography and idna Both these dependencies were only used by the PyOpenSSL injection module, which we don't need on Fedora as we ship sufficiently new versions of Python. --- python-urllib3.spec | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/python-urllib3.spec b/python-urllib3.spec index 6a650c8..1e9f8c9 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -2,7 +2,7 @@ Name: python-%{srcname} Version: 1.22 -Release: 7%{?dist} +Release: 8%{?dist} Summary: Python HTTP library with thread-safe connection pooling and file post License: MIT @@ -28,8 +28,6 @@ Requires: python2-six Requires: python2-backports-ssl_match_hostname # Secure extra requirements -Requires: python2-cryptography -Requires: python2-idna Requires: python2-ipaddress Requires: python2-pysocks @@ -65,9 +63,6 @@ BuildRequires: python3-tornado Requires: ca-certificates Requires: python3-six Requires: python3-pysocks -Requires: python3-cryptography -Requires: python3-idna -Requires: python3-pysocks %description -n python3-%{srcname} Python3 HTTP module with connection pooling and file POST abilities. @@ -140,6 +135,9 @@ py.test-3 %changelog +* Wed Apr 18 2018 Jeremy Cline - 1.22-8 +- Drop the dependency on idna and cryptography (rhbz 1567862) + * Mon Apr 16 2018 Jeremy Cline - 1.22-7 - Drop the dependency on PyOpenSSL, it's not needed (rhbz 1567862) From b7dcb3a9f38d76136dee4a7555ff1436239bef02 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Thu, 3 May 2018 18:04:23 +0200 Subject: [PATCH 3/6] Do not lowercase hostnames with custom-protocol (rhbz 1574684) upstream: https://github.com/urllib3/urllib3/issues/1267 --- ...rcase-hostnames-with-custom-protocol.patch | 114 ++++++++++++++++++ python-urllib3.spec | 9 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 0001-Do-not-lowercase-hostnames-with-custom-protocol.patch diff --git a/0001-Do-not-lowercase-hostnames-with-custom-protocol.patch b/0001-Do-not-lowercase-hostnames-with-custom-protocol.patch new file mode 100644 index 0000000..7e98a4b --- /dev/null +++ b/0001-Do-not-lowercase-hostnames-with-custom-protocol.patch @@ -0,0 +1,114 @@ +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/python-urllib3.spec b/python-urllib3.spec index 1e9f8c9..10dc210 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -2,7 +2,7 @@ Name: python-%{srcname} Version: 1.22 -Release: 8%{?dist} +Release: 9%{?dist} Summary: Python HTTP library with thread-safe connection pooling and file post License: MIT @@ -12,6 +12,8 @@ Source0: %{url}/archive/%{version}/%{srcname}-%{version}.tar.gz 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 BuildArch: noarch %description @@ -71,6 +73,7 @@ Python3 HTTP module with connection pooling and file POST abilities. %prep %setup -q -n %{srcname}-%{version} %patch0 -p1 -b .recent-date +%patch1 -p1 # Drop the dummyserver tests in koji. They fail there in real builds, but not # in scratch builds (weird). rm -rf test/with_dummyserver/ @@ -135,6 +138,10 @@ py.test-3 %changelog +* 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 + * Wed Apr 18 2018 Jeremy Cline - 1.22-8 - Drop the dependency on idna and cryptography (rhbz 1567862) From 2d9f3272e550961004257fed15991f485af410ae Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Tue, 5 Jun 2018 14:30:24 -0400 Subject: [PATCH 4/6] Update to v1.24.1 This addresses rhbz #1649155 --- .gitignore | 3 + ...rcase-hostnames-with-custom-protocol.patch | 114 ---------- Unbundle-ssl_match_hostname-backport.patch | 207 ++++++++++++++++++ python-urllib3-recent-date.patch | 32 --- python-urllib3.spec | 54 +++-- sources | 2 +- 6 files changed, 237 insertions(+), 175 deletions(-) delete mode 100644 0001-Do-not-lowercase-hostnames-with-custom-protocol.patch create mode 100644 Unbundle-ssl_match_hostname-backport.patch delete mode 100644 python-urllib3-recent-date.patch 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 From d79390d4909d562d889ccc2a494bb559928303fc Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Tue, 13 Nov 2018 13:54:11 -0500 Subject: [PATCH 5/6] Bring back the ssl_match_hostname source and hackery Python 3 has ssl_match_hostname as a file, but Python 2 symlinks the directory and upgrading is troublesome. Rather than dealing with an upgrade scriptlet, just bring back the old rm -rf stuff and wait for Python 2 to die. --- Unbundle-ssl_match_hostname-backport.patch | 207 --------------------- python-urllib3.spec | 12 +- 2 files changed, 10 insertions(+), 209 deletions(-) delete mode 100644 Unbundle-ssl_match_hostname-backport.patch diff --git a/Unbundle-ssl_match_hostname-backport.patch b/Unbundle-ssl_match_hostname-backport.patch deleted file mode 100644 index 5ad88ed..0000000 --- a/Unbundle-ssl_match_hostname-backport.patch +++ /dev/null @@ -1,207 +0,0 @@ -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.spec b/python-urllib3.spec index 61d59e3..80237cc 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -2,14 +2,14 @@ Name: python-%{srcname} Version: 1.24.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Python HTTP library with thread-safe connection pooling and file post License: MIT URL: https://github.com/urllib3/urllib3 Source0: %{url}/archive/%{version}/%{srcname}-%{version}.tar.gz # Unbundle ssl_match_hostname since we depend on it -Patch0: Unbundle-ssl_match_hostname-backport.patch +Source1: ssl_match_hostname_py3.py BuildArch: noarch %description @@ -93,17 +93,22 @@ rm -f test/test_no_ssl.py # 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 %{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 +ln -s %{python2_sitelib}/backports/ssl_match_hostname \ + %{buildroot}/%{python2_sitelib}/urllib3/packages/ssl_match_hostname # 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/ +cp -a %{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__/ @@ -133,6 +138,9 @@ popd %changelog +* Tue Nov 13 2018 Jeremy Cline - 1.24.1-2 +- Adjust unbundling of ssl_match_hostname + * Mon Oct 29 2018 Jeremy Cline - 1.24.1-1 - Update to v1.24.1 From f5172ae63e5e71e7c4e297c3776034ce184e2f5a Mon Sep 17 00:00:00 2001 From: Jeremy Cline Date: Wed, 17 Apr 2019 16:51:22 -0400 Subject: [PATCH 6/6] Update to v1.24.2 --- .gitignore | 1 + python-urllib3.spec | 7 +++++-- sources | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 630c966..10a86e0 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ /urllib3-1.23.tar.gz /urllib3-1.24.tar.gz /urllib3-1.24.1.tar.gz +/urllib3-1.24.2.tar.gz diff --git a/python-urllib3.spec b/python-urllib3.spec index 80237cc..e61d263 100644 --- a/python-urllib3.spec +++ b/python-urllib3.spec @@ -1,8 +1,8 @@ %global srcname urllib3 Name: python-%{srcname} -Version: 1.24.1 -Release: 2%{?dist} +Version: 1.24.2 +Release: 1%{?dist} Summary: Python HTTP library with thread-safe connection pooling and file post License: MIT @@ -138,6 +138,9 @@ popd %changelog +* Wed Apr 17 2019 Jeremy Cline - 1.24.2-1 +- Update to v1.24.2 + * Tue Nov 13 2018 Jeremy Cline - 1.24.1-2 - Adjust unbundling of ssl_match_hostname diff --git a/sources b/sources index d1287f7..360033c 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (urllib3-1.24.1.tar.gz) = 2f5453cf0ec1b65de9a9fca0fdb45664f7481507c875b7115c063cb177628b4b611377e588508ab8433e0797fc78b60fd3ea5cc5ac0a3f105d36bfff9a56f1f4 +SHA512 (urllib3-1.24.2.tar.gz) = 08e8d896f57eb9af5511d07002859f87f2a7bddbd5e66468908188dfe13d2e3985a8cdd2da12d06d0b337945ca8314c1f026d4e82badf23a09bf686fa121e863