Code Monkey home page Code Monkey logo

backports.ssl's People

Contributors

alekstorm avatar lukasa avatar rianhunter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

backports.ssl's Issues

get_subject_alt_name fails to find subjectAltName data under Python 3

Under Python 3, extension names come back as bytes but get_subject_alt_name compares the name to a unicode string so the comparison fails.

I noticed the problem when connecting to imap.mail.yahoo.com. The commonName has *.imap.mail.yahoo.com which doesn't match the hostname and one of the subjectAltName entries is imap.mail.yahoo.com so that is the entry that's required. Under Python 3, the hostname check fails but it works under Python 2.

This should be easy enough to fix but I don't have time right now so I'm just filing the bug for now.

Python 2.6.6 (Windows) - backports.ssl example code does not run

This:

import backports.ssl as ssl
import socket

context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_REQUIRED

conn = context.wrap_socket(socket.socket(socket.AF_INET))
conn.connect(('google.com', 443))
print conn.getpeercert()
conn.close()

Results in:

Traceback (most recent call last):
  File "test.py", line 8, in <module>
    conn.connect(('google.com', 443))
  File "C:\Python26\lib\site-packages\backports\ssl\core.py", line 258, in connect
    self.do_handshake()
  File "C:\Python26\lib\site-packages\backports\ssl\core.py", line 261, in do_handshake
    _safe_ssl_call(False, self._conn, 'do_handshake')
  File "C:\Python26\lib\site-packages\backports\ssl\core.py", line 222, in _safe_ssl_call
raise SSLError(*e.args)
backports.ssl.core.SSLError: [('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')]

If using match_hostname, subject_alt_name support should be mandatory

A good reason to use backports.ssl is that it makes correct SNI and match_hostname support available to python programs running on RHEL 7 or CentOS 7. These OSes ship with python 2.7.5, and this support was only added into mainstream python in 2.7.9.

However, it turns out that match_hostname silently fails to decode subject_alt_name extension records if the subject_alt_name import fails:

try:
    from .subject_alt_name import get_subject_alt_name
except ImportError:
    get_subject_alt_name = None

This can happen, for example, if the pyasn1 library (python-pyasn1 RPM) isn't installed.

The net effect is that match_hostname erroneously fails, e.g. against domains such as pypi.python.org, which is listed as a SAN.

My RFE is that if match_hostname is being used, it should fail as early as possible if subject_alt_name isn't available.

Here's a test case:

import sys
import socket

if sys.version_info >= (2, 7, 9):
    import ssl
else:
    import backports.ssl as ssl


(OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION, OP_CIPHER_SERVER_PREFERENCE,
 OP_SINGLE_DH_USE, OP_SINGLE_ECDH_USE) = (16777216, 33554432, 131072, 4194304,
                                          1048576, 524288)

def mk_clientctx():
    ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    ctx.options |= OP_NO_SSLv2 | OP_NO_SSLv3 | OP_NO_COMPRESSION
    ctx.verify_mode = ssl.CERT_REQUIRED
    ctx.check_hostname = True
    ctx.load_verify_locations("/etc/pki/tls/certs/ca-bundle.crt")
    return ctx

d = "pypi.python.org"
s = socket.socket()
s.connect((d, 443))
clientctx = mk_clientctx()
s = clientctx.wrap_socket(s, server_hostname=d)

On CentOS 7 / RHEL 7, if python-pyasn1 is available, this test case works fine. If not, you get the error:

Traceback (most recent call last):
  File "test.py", line 25, in <module>
    s = clientctx.wrap_socket(s, server_hostname=d)
  File "/usr/lib/python2.7/site-packages/backports/ssl/core.py", line 669, in wrap_socket
    self.check_hostname)
  File "/usr/lib/python2.7/site-packages/backports/ssl/core.py", line 241, in __init__
    self.do_handshake()
  File "/usr/lib/python2.7/site-packages/backports/ssl/core.py", line 263, in do_handshake
    match_hostname(self.getpeercert(), self._conn.get_servername().decode('utf-8'))
  File "/usr/lib/python2.7/site-packages/backports/ssl/core.py", line 184, in match_hostname
    % (hostname, dnsnames[0]))
backports.ssl.core.CertificateError: hostname u'pypi.python.org' doesn't match u'www.python.org'

Incorrect Information RE: PEP466

PEP466 does include NPN and SNI and anything else that the 3.4 ssl module has. In it's words it proposes:

  • in the ssl module:
    • this module is almost entirely synchronised with its Python 3 counterpart, bringing TLSv1.2, SSLContext manipulation, Server Name Identification, access to platform certificate stores, standard library support for peer hostname validation and more to the Python 2 series.
    • the only ssl module features not backported under this policy are the ssl.RAND_* functions that provide access to OpenSSL's random number generation capabilities - use os.urandom() instead.

pyopenssl raises SysCallError(-1, "Unexpected EOF")

pyopenssl raises "from time to time" SysCallError(-1, "Unexpected EOF"):

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/site-packages/backports/ssl/core.py", line 201, in _safe_ssl_call
    return getattr(sock, call)(*args, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/OpenSSL/SSL.py", line 1320, in recv
    self._raise_ssl_error(self._ssl, result)
  File "/usr/local/lib/python3.5/site-packages/OpenSSL/SSL.py", line 1180, in _raise_ssl_error
    raise SysCallError(-1, "Unexpected EOF")
OpenSSL.SSL.SysCallError: (-1, 'Unexpected EOF')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/tabellarius/tabellarius.py", line 180, in <module>
    exit(main())
  File "/tabellarius/tabellarius.py", line 142, in main
    mail_uids = imap_pool[acc].search_mails(pre_inbox, pre_inbox_search)
  File "/tabellarius/imap.py", line 61, in search_mails
    result = self.select_mailbox(mailbox)
  File "/tabellarius/imap.py", line 53, in select_mailbox
    return self.conn.select_folder(mailbox)
  File "/usr/local/lib/python3.5/site-packages/imapclient/imapclient.py", line 474, in select_folder
    self._command_and_check('select', self._normalise_folder(folder), readonly)
  File "/usr/local/lib/python3.5/site-packages/imapclient/imapclient.py", line 1173, in _command_and_check
    typ, data = meth(*args)
  File "/usr/local/lib/python3.5/imaplib.py", line 729, in select
    typ, dat = self._simple_command(name, mailbox)
  File "/usr/local/lib/python3.5/imaplib.py", line 1180, in _simple_command
    return self._command_complete(name, self._command(name, *args))
  File "/usr/local/lib/python3.5/imaplib.py", line 1003, in _command_complete
    typ, data = self._get_tagged_response(tag)
  File "/usr/local/lib/python3.5/imaplib.py", line 1123, in _get_tagged_response
    self._get_response()
  File "/usr/local/lib/python3.5/imaplib.py", line 1031, in _get_response
    resp = self._get_line()
  File "/usr/local/lib/python3.5/imaplib.py", line 1133, in _get_line
    line = self.readline()
  File "/usr/local/lib/python3.5/site-packages/imapclient/tls.py", line 166, in readline
    return self.file.readline()
  File "/usr/local/lib/python3.5/site-packages/backports/ssl/core.py", line 540, in readline
    data = _safe_ssl_call(False, self._sock, 'recv', self._rbufsize)
  File "/usr/local/lib/python3.5/site-packages/backports/ssl/core.py", line 216, in _safe_ssl_call
    raise SSLSysCallError(*e.args)
backports.ssl.core.SSLSysCallError: [Errno -1] Unexpected EOF

This appears on Python 3.2, 3.5 and others maybe too with the latest available version of backports.ssl and pyopenssl on pypi.

import fails: 'module' object has no attribute 'SSLContext'

$ pip freeze
backports.ssl==0.0.7
PyYAML==3.11
six==1.9.0
wheel==0.24.0
$ python
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 23 2015, 02:52:03)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import backports.ssl as ssl
>>> import socket
>>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'SSLContext'
>>>

Any ideas?

Python 3.4.4 (Windows) - backports.ssl example code (modified for Python3) does not run

This:

import backports.ssl as ssl
import socket

context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_REQUIRED

conn = context.wrap_socket(socket.socket(socket.AF_INET))
conn.connect(('google.com', 443))
print(conn.getpeercert()) # modified for Python3
conn.close()

Results in:

Traceback (most recent call last):
  File "C:\Python34\lib\site-packages\backports\ssl\core.py", line 201, in _safe_ssl_call
    return getattr(sock, call)(*args, **kwargs)
  File "C:\Python34\lib\site-packages\OpenSSL\SSL.py", line 1442, in do_handshake
    self._raise_ssl_error(self._ssl, result)    
  File "C:\Python34\lib\site-packages\OpenSSL\SSL.py", line 1187, in _raise_ssl_error
    _raise_current_error()    
  File "C:\Python34\lib\site-packages\OpenSSL\_util.py", line 48, in exception_from_error_queue
    raise exception_type(errors)
OpenSSL.SSL.Error: [('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test_outlook_imap.py", line 8, in <module>
    conn.connect(('google.com', 443))
  File "C:\Python34\lib\site-packages\backports\ssl\core.py", line 258, in connect
    self.do_handshake()
  File "C:\Python34\lib\site-packages\backports\ssl\core.py", li�ne 261, in do_handshake
    _safe_ssl_call(False, self._conn, 'do_handshake')
  File "C:\Python34\lib\site-packages\backports\ssl\core.py", line 222, in _safe_ssl_call
    raise SSLError(*e.args)
backports.ssl.core.SSLError: [('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')]

_fileobject.read() is pretty badly broken

There are several significant issues here:

  1. Depending on timing, when read() is called and the remote end terminates its SSL connection cleanly, SSLZeroReturnError will be raised to the user and the final bytes of the stream are lost forever.

                data = _safe_ssl_call(False, self._sock, 'recv', maxbufsize)
                if not data:
                    break
    

    In the above snippet, the second line will not execute when SSLZeroReturnError is raised. data is a local variable and its contents are lost.

  2. There are identical code patterns which need fixing in _fileobject.readline() as well (maybe other places too, I'm not sure).

  3. In the case size < 0, read() does not keep the contract of reading until EOF.

        if size < 0:
            # Read until EOF
            self._rbuf = BytesIO()  # reset _rbuf.  we consume it via buf.
            data = _safe_ssl_call(False, self._sock, 'recv', rbufsize)
            buf.write(data)
            return buf.getvalue()
    

    In the above snippet, the comment is mistaken. There would have to be a loop for it to be true. No more than rbufsize additional bytes are read from the channel.

Python 2.7.11 (Mac) backports.ssl example code does not run

This:

import backports.ssl as ssl
import socket

context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_REQUIRED

conn = context.wrap_socket(socket.socket(socket.AF_INET))
conn.connect(('google.com', 443))
print conn.getpeercert()
conn.close()

Results in:

Traceback (most recent call last):
  File "ffo.py", line 4, in <module>
    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
AttributeError: 'module' object has no attribute 'SSLContext'

HAS_SNI is missing

backports.ssl.HAS_SNI is missing:

Python 2.7.8 (default, Oct 17 2014, 10:22:45) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.54)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from backports.ssl import HAS_SNI
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name HAS_SNI

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.