mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-05 17:43:37 +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
|
||||
* Remove redundant MultipartPostHandler
|
||||
* 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)
|
||||
|
|
|
@ -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
|
||||
by the server to which you are connecting,
|
||||
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::
|
||||
|
||||
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=...)
|
||||
try:
|
||||
match_hostname(sslsock.getpeercert(), hostname)
|
||||
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;
|
||||
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
|
||||
-------
|
||||
|
||||
* This function was introduced in python-3.2
|
||||
* It was updated for python-3.4a1 for a CVE
|
||||
(backports-ssl_match_hostname-3.4.0.1)
|
||||
* 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
|
||||
(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
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
"""The match_hostname() function from Python 3.3.3, essential when using SSL."""
|
||||
|
||||
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):
|
||||
pass
|
||||
|
@ -61,6 +73,23 @@ def _dnsname_match(dn, hostname, max_wildcards=1):
|
|||
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
|
||||
|
@ -70,12 +99,35 @@ def match_hostname(cert, hostname):
|
|||
returns nothing.
|
||||
"""
|
||||
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 = []
|
||||
san = cert.get('subjectAltName', ())
|
||||
for key, value in san:
|
||||
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
|
||||
dnsnames.append(value)
|
||||
if not dnsnames:
|
||||
|
|
Loading…
Reference in a new issue