Skip to content

Commit

Permalink
Merge pull request mobius-software-ltd#3 from mcfreis/master
Browse files Browse the repository at this point in the history
Update "Patched ssl-Module with SSL_BUILD_*- and ERR_*- constants and added aliases for wrap_server() and wrap_client()"
  • Loading branch information
mcfreis authored Mar 23, 2017
2 parents 2663428 + dade3b8 commit 418655b
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 133 deletions.
14 changes: 14 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
2017-03-23 Björn Freise <[email protected]>

Patched ssl-Module with SSL_BUILD_*- and ERR_*- constants and added aliases for wrap_server() and wrap_client()

* dtls/__init__.py: Added DtlsSocket() from wrapper and aliases for wrap_server() and wrap_client()
* dtls/err.py: Added patch_ssl_errors() to patch ssl-Module with ERR_* constants
* dtls/patch.py: Patched ssl-Module with SSL_BUILD_* constants and added call to patch_ssl_errors()
* dtls/wrapper.py:
- Added a server and client function to alias/wrap DtlsSocket() creation
- Cleanup of DtlsSocket.__init__()
- Cleanup of exception handling in all member methods
- Cleanup sendto() from client: no endless loop and first do a connect if not already connected
* dtls/test/unit_wrapper.py: Adopt the changes made described above

2017-03-17 Björn Freise <[email protected]>

Added a wrapper for a DTLS-Socket either as client or server - including unit tests
Expand Down
18 changes: 9 additions & 9 deletions dtls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ def _prep_bins():
for prebuilt_file in files:
try:
copy(path.join(prebuilt_path, prebuilt_file), package_root)
except IOError:
pass

_prep_bins() # prepare before module imports

from patch import do_patch
from sslconnection import SSLContext, SSL, SSLConnection
from demux import force_routing_demux, reset_default_demux
import err as error_codes
except IOError:
pass

_prep_bins() # prepare before module imports

from patch import do_patch
from sslconnection import SSLContext, SSL, SSLConnection
from demux import force_routing_demux, reset_default_demux
from wrapper import DtlsSocket, client as wrap_client, server as wrap_server
43 changes: 25 additions & 18 deletions dtls/err.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,31 @@
ERR_BOTH_KEY_CERT_FILES = 500
ERR_BOTH_KEY_CERT_FILES_SVR = 298
ERR_NO_CERTS = 331
ERR_NO_CIPHER = 501
ERR_READ_TIMEOUT = 502
ERR_WRITE_TIMEOUT = 503
ERR_HANDSHAKE_TIMEOUT = 504
ERR_PORT_UNREACHABLE = 505

ERR_WRONG_SSL_VERSION = 0x1409210A
ERR_WRONG_VERSION_NUMBER = 0x1408A10B
ERR_COOKIE_MISMATCH = 0x1408A134
ERR_CERTIFICATE_VERIFY_FAILED = 0x14090086
ERR_NO_SHARED_CIPHER = 0x1408A0C1
ERR_SSL_HANDSHAKE_FAILURE = 0x1410C0E5


class SSLError(socket_error):
"""This exception is raised by modules in the dtls package."""
def __init__(self, *args):
super(SSLError, self).__init__(*args)
ERR_NO_CIPHER = 501
ERR_READ_TIMEOUT = 502
ERR_WRITE_TIMEOUT = 503
ERR_HANDSHAKE_TIMEOUT = 504
ERR_PORT_UNREACHABLE = 505

ERR_WRONG_SSL_VERSION = 0x1409210A
ERR_WRONG_VERSION_NUMBER = 0x1408A10B
ERR_COOKIE_MISMATCH = 0x1408A134
ERR_CERTIFICATE_VERIFY_FAILED = 0x14090086
ERR_NO_SHARED_CIPHER = 0x1408A0C1
ERR_SSL_HANDSHAKE_FAILURE = 0x1410C0E5
ERR_TLSV1_ALERT_UNKNOWN_CA = 0x14102418

def patch_ssl_errors():
import ssl
errors = [i for i in globals().iteritems() if type(i[1]) == int and str(i[0]).startswith('ERR_')]
for k, v in errors:
if not hasattr(ssl, k):
setattr(ssl, k, v)

class SSLError(socket_error):
"""This exception is raised by modules in the dtls package."""
def __init__(self, *args):
super(SSLError, self).__init__(*args)


class InvalidSocketError(Exception):
Expand Down
47 changes: 28 additions & 19 deletions dtls/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@

from sslconnection import SSLConnection, PROTOCOL_DTLS, PROTOCOL_DTLSv1, PROTOCOL_DTLSv1_2
from sslconnection import DTLS_OPENSSL_VERSION_NUMBER, DTLS_OPENSSL_VERSION, DTLS_OPENSSL_VERSION_INFO
from err import raise_as_ssl_module_error
from sslconnection import SSL_BUILD_CHAIN_FLAG_NONE, SSL_BUILD_CHAIN_FLAG_UNTRUSTED, \
SSL_BUILD_CHAIN_FLAG_NO_ROOT, SSL_BUILD_CHAIN_FLAG_CHECK, SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR, SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR
from err import raise_as_ssl_module_error, patch_ssl_errors


def do_patch():
Expand All @@ -64,10 +66,17 @@ def do_patch():
ssl.DTLS_OPENSSL_VERSION_NUMBER = DTLS_OPENSSL_VERSION_NUMBER
ssl.DTLS_OPENSSL_VERSION = DTLS_OPENSSL_VERSION
ssl.DTLS_OPENSSL_VERSION_INFO = DTLS_OPENSSL_VERSION_INFO
ssl.SSL_BUILD_CHAIN_FLAG_NONE = SSL_BUILD_CHAIN_FLAG_NONE
ssl.SSL_BUILD_CHAIN_FLAG_UNTRUSTED = SSL_BUILD_CHAIN_FLAG_UNTRUSTED
ssl.SSL_BUILD_CHAIN_FLAG_NO_ROOT = SSL_BUILD_CHAIN_FLAG_NO_ROOT
ssl.SSL_BUILD_CHAIN_FLAG_CHECK = SSL_BUILD_CHAIN_FLAG_CHECK
ssl.SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR = SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR
ssl.SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR = SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR
_orig_SSLSocket_init = ssl.SSLSocket.__init__
_orig_get_server_certificate = ssl.get_server_certificate
ssl.SSLSocket.__init__ = _SSLSocket_init
ssl.get_server_certificate = _get_server_certificate
patch_ssl_errors()
raise_as_ssl_module_error()

def _wrap_socket(sock, keyfile=None, certfile=None,
Expand Down Expand Up @@ -198,24 +207,24 @@ class FakeContext(object):
self._user_config_ssl = cb_user_config_ssl

# Perform method substitution and addition (without reference cycle)
self._real_connect = MethodType(_SSLSocket_real_connect, proxy(self))
self.listen = MethodType(_SSLSocket_listen, proxy(self))
self.accept = MethodType(_SSLSocket_accept, proxy(self))
self.get_timeout = MethodType(_SSLSocket_get_timeout, proxy(self))
self.handle_timeout = MethodType(_SSLSocket_handle_timeout, proxy(self))

# Extra
self.getpeercertchain = MethodType(_getpeercertchain, proxy(self))

def _getpeercertchain(self, binary_form=False):
return self._sslobj.getpeercertchain(binary_form)

def _SSLSocket_listen(self, ignored):
if self._connected:
raise ValueError("attempt to listen on connected SSLSocket!")
if self._sslobj:
return
self._sslobj = SSLConnection(socket(_sock=self._sock),
self._real_connect = MethodType(_SSLSocket_real_connect, proxy(self))
self.listen = MethodType(_SSLSocket_listen, proxy(self))
self.accept = MethodType(_SSLSocket_accept, proxy(self))
self.get_timeout = MethodType(_SSLSocket_get_timeout, proxy(self))
self.handle_timeout = MethodType(_SSLSocket_handle_timeout, proxy(self))

# Extra
self.getpeercertchain = MethodType(_getpeercertchain, proxy(self))

def _getpeercertchain(self, binary_form=False):
return self._sslobj.getpeercertchain(binary_form)

def _SSLSocket_listen(self, ignored):
if self._connected:
raise ValueError("attempt to listen on connected SSLSocket!")
if self._sslobj:
return
self._sslobj = SSLConnection(socket(_sock=self._sock),
self.keyfile, self.certfile, True,
self.cert_reqs, self.ssl_version,
self.ca_certs,
Expand Down
22 changes: 8 additions & 14 deletions dtls/test/unit_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
_logger = getLogger(__name__)

import ssl
from dtls import do_patch, error_codes
from dtls.wrapper import DtlsSocket, SSL_BUILD_CHAIN_FLAG_NONE, SSL_BUILD_CHAIN_FLAG_NO_ROOT
from dtls import DtlsSocket


HOST = "localhost"
Expand Down Expand Up @@ -186,7 +185,7 @@ def stop(self):
'client_sigalgs': None},
'result':
{'ret_success': False,
'error_code': error_codes.ERR_WRONG_SSL_VERSION,
'error_code': ssl.ERR_WRONG_SSL_VERSION,
'exception': None}},
{'testcase':
{'name': 'certificate verify fails',
Expand All @@ -209,7 +208,7 @@ def stop(self):
'client_sigalgs': None},
'result':
{'ret_success': False,
'error_code': error_codes.ERR_CERTIFICATE_VERIFY_FAILED,
'error_code': ssl.ERR_CERTIFICATE_VERIFY_FAILED,
'exception': None}},
{'testcase':
{'name': 'no matching curve',
Expand All @@ -232,7 +231,7 @@ def stop(self):
'client_sigalgs': None},
'result':
{'ret_success': False,
'error_code': error_codes.ERR_SSL_HANDSHAKE_FAILURE,
'error_code': ssl.ERR_SSL_HANDSHAKE_FAILURE,
'exception': None}},
{'testcase':
{'name': 'matching curve',
Expand Down Expand Up @@ -278,7 +277,7 @@ def stop(self):
'client_sigalgs': None},
'result':
{'ret_success': False,
'error_code': error_codes.ERR_PORT_UNREACHABLE,
'error_code': ssl.ERR_PORT_UNREACHABLE,
'exception': None}},
{'testcase':
{'name': 'no matching sigalgs',
Expand All @@ -301,7 +300,7 @@ def stop(self):
'client_sigalgs': "RSA+SHA256"},
'result':
{'ret_success': False,
'error_code': error_codes.ERR_SSL_HANDSHAKE_FAILURE,
'error_code': ssl.ERR_SSL_HANDSHAKE_FAILURE,
'exception': None}},
{'testcase':
{'name': 'matching sigalgs',
Expand Down Expand Up @@ -347,7 +346,7 @@ def stop(self):
'client_sigalgs': None},
'result':
{'ret_success': False,
'error_code': error_codes.ERR_SSL_HANDSHAKE_FAILURE,
'error_code': ssl.ERR_SSL_HANDSHAKE_FAILURE,
'exception': None}},
{'testcase':
{'name': 'matching cipher',
Expand Down Expand Up @@ -493,13 +492,8 @@ def test(self):
class WrapperTests(unittest.TestCase):
__metaclass__ = TestSequenceMeta

def setUp(self):
super(WrapperTests, self).setUp()

do_patch()

def test_build_cert_chain(self):
steps = [SSL_BUILD_CHAIN_FLAG_NONE, SSL_BUILD_CHAIN_FLAG_NO_ROOT]
steps = [ssl.SSL_BUILD_CHAIN_FLAG_NONE, ssl.SSL_BUILD_CHAIN_FLAG_NO_ROOT]
chatty, connectionchatty = CHATTY, CHATTY_CLIENT
indata = 'FOO'
certs = dict()
Expand Down
Loading

0 comments on commit 418655b

Please sign in to comment.