backports.ssl_match_hostname-3.5.0.1/0000775000175000017500000000000012635355454020230 5ustar badgerbadger00000000000000backports.ssl_match_hostname-3.5.0.1/setup.py0000664000175000017500000000236012635355204021734 0ustar badgerbadger00000000000000# -*- coding: utf-8 -*- import os from distutils.core import setup long_description = open(os.path.join( os.path.dirname(__file__), 'backports', 'ssl_match_hostname', 'README.txt', )).read() setup( name='backports.ssl_match_hostname', version='3.5.0.1', description='The ssl.match_hostname() function from Python 3.5', long_description=long_description, author='Brandon Rhodes', author_email='brandon@rhodesmill.org', maintainer='Toshio Kuratomi', maintainer_email='toshio@fedoraproject.org', url='http://bitbucket.org/brandon/backports.ssl_match_hostname', license='Python Software Foundation License', classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: Python Software Foundation License', 'Programming Language :: Python :: 2.4', 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.0', 'Programming Language :: Python :: 3.1', 'Topic :: Security :: Cryptography', ], packages=['backports', 'backports.ssl_match_hostname'], ) backports.ssl_match_hostname-3.5.0.1/PKG-INFO0000664000175000017500000000772312635355454021336 0ustar badgerbadger00000000000000Metadata-Version: 1.1 Name: backports.ssl_match_hostname Version: 3.5.0.1 Summary: The ssl.match_hostname() function from Python 3.5 Home-page: http://bitbucket.org/brandon/backports.ssl_match_hostname Author: Toshio Kuratomi Author-email: toshio@fedoraproject.org License: Python Software Foundation License Description: The ssl.match_hostname() function from Python 3.5 ================================================= 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 that you are trying to reach. But the matching logic, defined in `RFC2818`_, can be a bit tricky to implement on your own. So the ``ssl`` package in the Standard Library of Python 3.2 and greater now includes a ``match_hostname()`` function for performing this check instead of requiring every application to implement the check separately. This backport brings ``match_hostname()`` to users of earlier versions of Python. 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_SSLv23, cert_reqs=ssl.CERT_REQUIRED, ca_certs=...) try: match_hostname(sslsock.getpeercert(), hostname) except CertificateError, ce: ... Brandon Craig Rhodes is merely the packager of this distribution; 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 Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: Python Software Foundation License Classifier: Programming Language :: Python :: 2.4 Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.0 Classifier: Programming Language :: Python :: 3.1 Classifier: Topic :: Security :: Cryptography backports.ssl_match_hostname-3.5.0.1/backports/0000775000175000017500000000000012635355454022220 5ustar badgerbadger00000000000000backports.ssl_match_hostname-3.5.0.1/backports/__init__.py0000664000175000017500000000023312635355204024320 0ustar badgerbadger00000000000000# This is a Python "namespace package" http://www.python.org/dev/peps/pep-0382/ from pkgutil import extend_path __path__ = extend_path(__path__, __name__) backports.ssl_match_hostname-3.5.0.1/backports/ssl_match_hostname/0000775000175000017500000000000012635355454026073 5ustar badgerbadger00000000000000backports.ssl_match_hostname-3.5.0.1/backports/ssl_match_hostname/__init__.py0000664000175000017500000001270612635355204030203 0ustar badgerbadger00000000000000"""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' 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") backports.ssl_match_hostname-3.5.0.1/backports/ssl_match_hostname/README.txt0000664000175000017500000000511212635355204027561 0ustar badgerbadger00000000000000 The ssl.match_hostname() function from Python 3.5 ================================================= 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 that you are trying to reach. But the matching logic, defined in `RFC2818`_, can be a bit tricky to implement on your own. So the ``ssl`` package in the Standard Library of Python 3.2 and greater now includes a ``match_hostname()`` function for performing this check instead of requiring every application to implement the check separately. This backport brings ``match_hostname()`` to users of earlier versions of Python. 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_SSLv23, cert_reqs=ssl.CERT_REQUIRED, ca_certs=...) try: match_hostname(sslsock.getpeercert(), hostname) except CertificateError, ce: ... Brandon Craig Rhodes is merely the packager of this distribution; 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 backports.ssl_match_hostname-3.5.0.1/backports/ssl_match_hostname/LICENSE.txt0000664000175000017500000000460312635355204027712 0ustar badgerbadger00000000000000Python License (Python-2.0) Python License, Version 2 (Python-2.0) PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 -------------------------------------------- 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001-2013 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python. 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this License Agreement.