mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-22 01:23:43 +00:00
Update backports/ssl_match_hostname 3.4.0.2 to 3.5.0.1 (r18).
This commit is contained in:
parent
9ecc98fff0
commit
4d47258e94
3 changed files with 84 additions and 14 deletions
|
@ -7,6 +7,7 @@
|
||||||
* Change API response header for JSON content type and the return of JSONP data
|
* Change API response header for JSON content type and the return of JSONP data
|
||||||
* Remove redundant MultipartPostHandler
|
* Remove redundant MultipartPostHandler
|
||||||
* Update Beautiful Soup 4.4.0 (r390) to 4.4.0 (r397)
|
* Update Beautiful Soup 4.4.0 (r390) to 4.4.0 (r397)
|
||||||
|
* Update backports/ssl_match_hostname 3.4.0.2 to 3.5.0.1 (r18)
|
||||||
|
|
||||||
|
|
||||||
### 0.11.0 (2016-01-10 22:30:00 UTC)
|
### 0.11.0 (2016-01-10 22:30:00 UTC)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
The ssl.match_hostname() function from Python 3.4
|
The ssl.match_hostname() function from Python 3.5
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
The Secure Sockets layer is only actually *secure*
|
The Secure Sockets Layer is only actually *secure*
|
||||||
if you check the hostname in the certificate returned
|
if you check the hostname in the certificate returned
|
||||||
by the server to which you are connecting,
|
by the server to which you are connecting,
|
||||||
and verify that it matches to hostname
|
and verify that it matches to hostname
|
||||||
|
@ -21,31 +21,48 @@ Simply make this distribution a dependency of your package,
|
||||||
and then use it like this::
|
and then use it like this::
|
||||||
|
|
||||||
from backports.ssl_match_hostname import match_hostname, CertificateError
|
from backports.ssl_match_hostname import match_hostname, CertificateError
|
||||||
...
|
[...]
|
||||||
sslsock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv3,
|
sslsock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23,
|
||||||
cert_reqs=ssl.CERT_REQUIRED, ca_certs=...)
|
cert_reqs=ssl.CERT_REQUIRED, ca_certs=...)
|
||||||
try:
|
try:
|
||||||
match_hostname(sslsock.getpeercert(), hostname)
|
match_hostname(sslsock.getpeercert(), hostname)
|
||||||
except CertificateError, ce:
|
except CertificateError, ce:
|
||||||
...
|
...
|
||||||
|
|
||||||
Note that the ``ssl`` module is only included in the Standard Library
|
|
||||||
for Python 2.6 and later;
|
|
||||||
users of Python 2.5 or earlier versions
|
|
||||||
will also need to install the ``ssl`` distribution
|
|
||||||
from the Python Package Index to use code like that shown above.
|
|
||||||
|
|
||||||
Brandon Craig Rhodes is merely the packager of this distribution;
|
Brandon Craig Rhodes is merely the packager of this distribution;
|
||||||
the actual code inside comes verbatim from Python 3.4.
|
the actual code inside comes from Python 3.5 with small changes for
|
||||||
|
portability.
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* If you want to verify hosts match with certificates via ServerAltname
|
||||||
|
IPAddress fields, you need to install the `ipaddress module`_.
|
||||||
|
backports.ssl_match_hostname will continue to work without ipaddress but
|
||||||
|
will only be able to handle ServerAltName DNSName fields, not IPAddress.
|
||||||
|
System packagers (Linux distributions, et al) are encouraged to add
|
||||||
|
this as a hard dependency in their packages.
|
||||||
|
|
||||||
|
* If you need to use this on Python versions earlier than 2.6 you will need to
|
||||||
|
install the `ssl module`_. From Python 2.6 upwards ``ssl`` is included in
|
||||||
|
the Python Standard Library so you do not need to install it separately.
|
||||||
|
|
||||||
|
.. _`ipaddress module`:: https://pypi.python.org/pypi/ipaddress
|
||||||
|
.. _`ssl module`:: https://pypi.python.org/pypi/ssl
|
||||||
|
|
||||||
History
|
History
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* This function was introduced in python-3.2
|
* This function was introduced in python-3.2
|
||||||
* It was updated for python-3.4a1 for a CVE
|
* It was updated for python-3.4a1 for a CVE
|
||||||
(backports-ssl_match_hostname-3.4.0.1)
|
(backports-ssl_match_hostname-3.4.0.1)
|
||||||
* It was updated from RFC2818 to RFC 6125 compliance in order to fix another
|
* It was updated from RFC2818 to RFC 6125 compliance in order to fix another
|
||||||
security flaw for python-3.3.3 and python-3.4a5
|
security flaw for python-3.3.3 and python-3.4a5
|
||||||
(backports-ssl_match_hostname-3.4.0.2)
|
(backports-ssl_match_hostname-3.4.0.2)
|
||||||
|
* It was updated in python-3.5 to handle IPAddresses in ServerAltName fields
|
||||||
|
(something that backports.ssl_match_hostname will do if you also install the
|
||||||
|
ipaddress library from pypi).
|
||||||
|
|
||||||
|
|
||||||
.. _RFC2818: http://tools.ietf.org/html/rfc2818.html
|
.. _RFC2818: http://tools.ietf.org/html/rfc2818.html
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
"""The match_hostname() function from Python 3.3.3, essential when using SSL."""
|
"""The match_hostname() function from Python 3.3.3, essential when using SSL."""
|
||||||
|
|
||||||
import re
|
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 all the way back to
|
||||||
|
# python-2.4.
|
||||||
|
try:
|
||||||
|
import ipaddress
|
||||||
|
except ImportError:
|
||||||
|
ipaddress = None
|
||||||
|
|
||||||
|
__version__ = '3.5.0.1'
|
||||||
|
|
||||||
__version__ = '3.4.0.2'
|
|
||||||
|
|
||||||
class CertificateError(ValueError):
|
class CertificateError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
@ -61,6 +73,23 @@ def _dnsname_match(dn, hostname, max_wildcards=1):
|
||||||
return pat.match(hostname)
|
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):
|
def match_hostname(cert, hostname):
|
||||||
"""Verify that *cert* (in decoded format as returned by
|
"""Verify that *cert* (in decoded format as returned by
|
||||||
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
|
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
|
||||||
|
@ -70,12 +99,35 @@ def match_hostname(cert, hostname):
|
||||||
returns nothing.
|
returns nothing.
|
||||||
"""
|
"""
|
||||||
if not cert:
|
if not cert:
|
||||||
raise ValueError("empty or no certificate")
|
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 = []
|
dnsnames = []
|
||||||
san = cert.get('subjectAltName', ())
|
san = cert.get('subjectAltName', ())
|
||||||
for key, value in san:
|
for key, value in san:
|
||||||
if key == 'DNS':
|
if key == 'DNS':
|
||||||
if _dnsname_match(value, hostname):
|
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
|
return
|
||||||
dnsnames.append(value)
|
dnsnames.append(value)
|
||||||
if not dnsnames:
|
if not dnsnames:
|
||||||
|
|
Loading…
Reference in a new issue