From 622f58358e9148a2c09f41f0e81735baa7105588 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Feb 2017 22:37:50 -0800 Subject: [PATCH] Compatibility Updates for Python 2.7.12 * dtls/openssl.py: support reading directly into given buffer instead of forcing buffer copy (for ssl module compatibility) * dtls/sslconnection.py: in-situ receive support, as above * dtls/patch.py: various changes for compatibility with the ssl module of Python 2.7.12; note that the ssl module's new SSLContext is not supported * dtls/test/unit.py: changes to support the updated ssl module, including fix of deprecation warnings * setup.py: increase version to 1.0.2 --- ChangeLog | 8 ++++++++ dtls/err.py | 4 ++-- dtls/openssl.py | 12 +++++++++--- dtls/patch.py | 33 ++++++++++++++++++++++++--------- dtls/sslconnection.py | 4 ++-- dtls/test/unit.py | 4 +++- setup.py | 2 +- 7 files changed, 49 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ebb728..373f614 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2017-02-27 Ray Brown + + * dtls/openssl.py: support reading directly into given buffer instead of forcing buffer copy (for ssl module compatibility) + * dtls/sslconnection.py: in-situ receive support, as above + * dtls/patch.py: various changes for compatibility with the ssl module of Python 2.7.12; note that the ssl module's new SSLContext is not supported + * dtls/test/unit.py: changes to support the updated ssl module, including fix of deprecation warnings + * setup.py: increase version to 1.0.2 + 2014-01-18 Ray Brown * setup.py: Increase version to 1.0.1 for release to PyPI diff --git a/dtls/err.py b/dtls/err.py index c96c7aa..212554b 100644 --- a/dtls/err.py +++ b/dtls/err.py @@ -96,8 +96,8 @@ def raise_ssl_error(code, nested=None): """Raise an SSL error with the given error code""" err_string = str(code) + ": " + _ssl_errors[code] if nested: - raise SSLError(err_string, nested) - raise SSLError(err_string) + raise SSLError(code, err_string + str(nested)) + raise SSLError(code, err_string) _ssl_errors = { ERR_NO_CERTS: "No root certificates specified for verification " + \ diff --git a/dtls/openssl.py b/dtls/openssl.py index 1331a01..4099504 100644 --- a/dtls/openssl.py +++ b/dtls/openssl.py @@ -735,9 +735,15 @@ def DTLSv1_listen(ssl): errcheck_ord(ret, _SSL_ctrl, (ssl, DTLS_CTRL_LISTEN, 0, byref(su))) return addr_tuple_from_sockaddr_u(su) -def SSL_read(ssl, length): - buf = create_string_buffer(length) - res_len = _SSL_read(ssl, buf, sizeof(buf)) +def SSL_read(ssl, length, buffer): + if buffer: + length = min(length, len(buffer)) + buf = (c_char * length).from_buffer(buffer) + else: + buf = create_string_buffer(length) + res_len = _SSL_read(ssl, buf, length) + if buffer: + return res_len return buf.raw[:res_len] def SSL_write(ssl, data): diff --git a/dtls/patch.py b/dtls/patch.py index d7d73d4..acd54dd 100644 --- a/dtls/patch.py +++ b/dtls/patch.py @@ -35,7 +35,7 @@ has the following effects: """ from socket import SOCK_DGRAM, socket, _delegate_methods, error as socket_error -from socket import AF_INET, SOCK_DGRAM, getaddrinfo +from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM, getaddrinfo from sslconnection import SSLConnection, PROTOCOL_DTLSv1, CERT_NONE from sslconnection import DTLS_OPENSSL_VERSION_NUMBER, DTLS_OPENSSL_VERSION from sslconnection import DTLS_OPENSSL_VERSION_INFO @@ -62,10 +62,9 @@ def do_patch(): ssl.get_server_certificate = _get_server_certificate raise_as_ssl_module_error() -PROTOCOL_SSLv3 = 1 PROTOCOL_SSLv23 = 2 -def _get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): +def _get_server_certificate(addr, ssl_version=PROTOCOL_SSLv23, ca_certs=None): """Retrieve a server certificate Retrieve the certificate from the server at the specified address, @@ -90,11 +89,14 @@ def _get_server_certificate(addr, ssl_version=PROTOCOL_SSLv3, ca_certs=None): s.close() return ssl.DER_cert_to_PEM_cert(dercert) -def _SSLSocket_init(self, sock, keyfile=None, certfile=None, +def _SSLSocket_init(self, sock=None, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version=PROTOCOL_SSLv23, ca_certs=None, do_handshake_on_connect=True, - suppress_ragged_eofs=True, ciphers=None): + family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, + suppress_ragged_eofs=True, npn_protocols=None, ciphers=None, + server_hostname=None, + _context=None): is_connection = is_datagram = False if isinstance(sock, SSLConnection): is_connection = True @@ -102,11 +104,19 @@ def _SSLSocket_init(self, sock, keyfile=None, certfile=None, is_datagram = True if not is_connection and not is_datagram: # Non-DTLS code path - return _orig_SSLSocket_init(self, sock, keyfile, certfile, - server_side, cert_reqs, - ssl_version, ca_certs, + return _orig_SSLSocket_init(self, sock=sock, keyfile=keyfile, + certfile=certfile, server_side=server_side, + cert_reqs=cert_reqs, + ssl_version=ssl_version, ca_certs=ca_certs, + do_handshake_on_connect= do_handshake_on_connect, - suppress_ragged_eofs, ciphers) + family=family, type=type, proto=proto, + fileno=fileno, + suppress_ragged_eofs=suppress_ragged_eofs, + npn_protocols=npn_protocols, + ciphers=ciphers, + server_hostname=server_hostname, + _context=_context) # DTLS code paths: datagram socket and newly accepted DTLS connection if is_datagram: socket.__init__(self, _sock=sock._sock) @@ -140,8 +150,13 @@ def _SSLSocket_init(self, sock, keyfile=None, certfile=None, do_handshake_on_connect, suppress_ragged_eofs, ciphers) else: + self._connected = True self._sslobj = sock + class FakeContext(object): + check_hostname = False + + self._context = FakeContext() self.keyfile = keyfile self.certfile = certfile self.cert_reqs = cert_reqs diff --git a/dtls/sslconnection.py b/dtls/sslconnection.py index 9a5dcef..09fc3dc 100644 --- a/dtls/sslconnection.py +++ b/dtls/sslconnection.py @@ -514,7 +514,7 @@ class SSLConnection(object): self._handshake_done = True _logger.debug("...completed handshake") - def read(self, len=1024): + def read(self, len=1024, buffer=None): """Read data from connection Read up to len bytes and return them. @@ -526,7 +526,7 @@ class SSLConnection(object): """ return self._wrap_socket_library_call( - lambda: SSL_read(self._ssl.value, len), ERR_READ_TIMEOUT) + lambda: SSL_read(self._ssl.value, len, buffer), ERR_READ_TIMEOUT) def write(self, data): """Write data to connection diff --git a/dtls/test/unit.py b/dtls/test/unit.py index 678d315..b7e28a5 100644 --- a/dtls/test/unit.py +++ b/dtls/test/unit.py @@ -78,7 +78,6 @@ class BasicSocketTests(unittest.TestCase): def test_constants(self): ssl.PROTOCOL_SSLv23 - ssl.PROTOCOL_SSLv3 ssl.PROTOCOL_TLSv1 ssl.PROTOCOL_DTLSv1 # added ssl.CERT_NONE @@ -574,6 +573,9 @@ class AsyncoreEchoServer(threading.Thread): # Complete the handshake self.handle_read_event() + def __hash__(self): + return hash(self.socket) + def readable(self): while self.socket.pending() > 0: self.handle_read_event() diff --git a/setup.py b/setup.py index 7043b97..62302aa 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ for scheme in INSTALL_SCHEMES.values(): scheme['data'] = scheme['purelib'] NAME = "Dtls" -VERSION = "1.0.1" +VERSION = "1.0.2" DIST_DIR = "dist" FORMAT_TO_SUFFIX = { "zip": ".zip",