-
Notifications
You must be signed in to change notification settings - Fork 32
Fenrir fixes #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Fenrir fixes #66
Changes from all commits
ffd86de
dc49a53
a406dce
84bd637
e436664
89667f9
760cb46
c81c839
e1ede23
2c4ba3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,3 +74,17 @@ def test_load_verify_locations_with_cafile(ssl_context): | |
|
|
||
| def test_load_verify_locations_with_cadata(ssl_context): | ||
| ssl_context.load_verify_locations(cadata=_CADATA) | ||
|
|
||
|
|
||
| def test_check_hostname_requires_cert_required(ssl_provider, ssl_context): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Description: This diff introduces several significant behavior changes to
The two new tests ( Recommendation: Add tests that verify:
|
||
| with pytest.raises(ValueError): | ||
| ssl_context.check_hostname = True | ||
|
|
||
| ssl_context.verify_mode = ssl_provider.CERT_REQUIRED | ||
| ssl_context.check_hostname = True | ||
| assert ssl_context.check_hostname is True | ||
|
|
||
|
|
||
| def test_wrap_socket_server_side_mismatch(ssl_context, tcp_socket): | ||
| with pytest.raises(ValueError): | ||
| ssl_context.wrap_socket(tcp_socket, server_side=True) | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -81,7 +81,9 @@ class WolfSSL(object): | |||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def enable_debug(self): | ||||||||||||||||
| _lib.wolfSSL_Debugging_ON() | ||||||||||||||||
| if _lib.wolfSSL_Debugging_ON() != _SSL_SUCCESS: | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Description: The diff changes # examples/client.py:143
wolfssl.WolfSSL.enable_debug()
# examples/server.py:139
wolfssl.WolfSSL.enable_debug()Previously, The comments in the examples even acknowledge this: "enable debug, if native wolfSSL has been compiled with '--enable-debug'" — the "if" implies it should be tolerant. Code: # wolfssl/__init__.py (new)
@classmethod
def enable_debug(self):
if _lib.wolfSSL_Debugging_ON() != _SSL_SUCCESS:
raise RuntimeError(
"wolfSSL debugging not available")Recommendation: Wrap
Suggested change
Alternatively, the library could provide a |
||||||||||||||||
| raise RuntimeError( | ||||||||||||||||
| "wolfSSL debugging not available") | ||||||||||||||||
|
|
||||||||||||||||
| @classmethod | ||||||||||||||||
| def disable_debug(self): | ||||||||||||||||
|
|
@@ -143,9 +145,7 @@ def get_der(self): | |||||||||||||||
| if derPtr == _ffi.NULL: | ||||||||||||||||
| return None | ||||||||||||||||
|
|
||||||||||||||||
| derBytes = _ffi.buffer(derPtr, outSz[0]) | ||||||||||||||||
|
|
||||||||||||||||
| return derBytes | ||||||||||||||||
| return _ffi.buffer(derPtr, outSz[0])[:] | ||||||||||||||||
|
|
||||||||||||||||
| class SSLContext(object): | ||||||||||||||||
| """ | ||||||||||||||||
|
|
@@ -154,7 +154,9 @@ class SSLContext(object): | |||||||||||||||
| """ | ||||||||||||||||
|
|
||||||||||||||||
| def __init__(self, protocol, server_side=None): | ||||||||||||||||
| _lib.wolfSSL_Init() | ||||||||||||||||
| if _lib.wolfSSL_Init() != _SSL_SUCCESS: | ||||||||||||||||
| raise RuntimeError( | ||||||||||||||||
| "wolfSSL library initialization failed") | ||||||||||||||||
| method = _WolfSSLMethod(protocol, server_side) | ||||||||||||||||
|
|
||||||||||||||||
| self.protocol = protocol | ||||||||||||||||
|
|
@@ -356,9 +358,10 @@ def load_verify_locations(self, cafile=None, capath=None, cadata=None): | |||||||||||||||
| raise SSLError("Unable to load verify locations. E(%d)" % ret) | ||||||||||||||||
|
|
||||||||||||||||
| if cadata is not None: | ||||||||||||||||
| cadata_bytes = t2b(cadata) | ||||||||||||||||
| ret = _lib.wolfSSL_CTX_load_verify_buffer( | ||||||||||||||||
| self.native_object, t2b(cadata), | ||||||||||||||||
| len(cadata), _SSL_FILETYPE_PEM) | ||||||||||||||||
| self.native_object, cadata_bytes, | ||||||||||||||||
| len(cadata_bytes), _SSL_FILETYPE_PEM) | ||||||||||||||||
|
|
||||||||||||||||
| if ret != _SSL_SUCCESS: | ||||||||||||||||
| raise SSLError("Unable to load verify locations. E(%d)" % ret) | ||||||||||||||||
|
|
@@ -476,8 +479,11 @@ def __init__(self, sock=None, keyfile=None, certfile=None, | |||||||||||||||
| ret = _lib.wolfSSL_check_domain_name(self.native_object, | ||||||||||||||||
| sni) | ||||||||||||||||
| if ret != _SSL_SUCCESS: | ||||||||||||||||
| raise SSLError("Unable to set domain name check for " | ||||||||||||||||
| "hostname verification") | ||||||||||||||||
| self._release_native_object() | ||||||||||||||||
| raise SSLError( | ||||||||||||||||
| "Unable to set domain name " | ||||||||||||||||
| "check for hostname " | ||||||||||||||||
| "verification") | ||||||||||||||||
|
|
||||||||||||||||
| if connected: | ||||||||||||||||
| try: | ||||||||||||||||
|
|
@@ -497,6 +503,7 @@ def _release_native_object(self): | |||||||||||||||
| self.native_object = _ffi.NULL | ||||||||||||||||
|
|
||||||||||||||||
| def pending(self): | ||||||||||||||||
| self._check_closed("pending") | ||||||||||||||||
| return _lib.wolfSSL_pending(self.native_object) | ||||||||||||||||
|
|
||||||||||||||||
| @property | ||||||||||||||||
|
|
@@ -605,13 +612,6 @@ def sendall(self, data, flags=0): | |||||||||||||||
|
|
||||||||||||||||
| while sent < length: | ||||||||||||||||
| ret = self.write(data[sent:]) | ||||||||||||||||
| if (ret <= 0): | ||||||||||||||||
| #expect to receive 0 when peer is reset or closed | ||||||||||||||||
| err = _lib.wolfSSL_get_error(self.native_object, 0) | ||||||||||||||||
| if err == _SSL_ERROR_WANT_WRITE: | ||||||||||||||||
| raise SSLWantWriteError() | ||||||||||||||||
| else: | ||||||||||||||||
| raise SSLError("wolfSSL_write error (%d)" % err) | ||||||||||||||||
|
|
||||||||||||||||
| sent += ret | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -676,11 +676,13 @@ def recv_into(self, buffer, nbytes=None, flags=0): | |||||||||||||||
| self._check_closed("read") | ||||||||||||||||
| if self._context.protocol < PROTOCOL_DTLSv1: | ||||||||||||||||
| self._check_connected() | ||||||||||||||||
| else: | ||||||||||||||||
| self.do_handshake() | ||||||||||||||||
|
|
||||||||||||||||
| if buffer is None: | ||||||||||||||||
| raise ValueError("buffer cannot be None") | ||||||||||||||||
|
|
||||||||||||||||
| if nbytes is None: | ||||||||||||||||
| if nbytes is None or nbytes == 0: | ||||||||||||||||
| nbytes = len(buffer) | ||||||||||||||||
| else: | ||||||||||||||||
| nbytes = min(len(buffer), nbytes) | ||||||||||||||||
|
|
@@ -721,7 +723,9 @@ def recvmsg_into(self, *args, **kwargs): | |||||||||||||||
|
|
||||||||||||||||
| def shutdown(self, how): | ||||||||||||||||
| if self.native_object != _ffi.NULL: | ||||||||||||||||
| _lib.wolfSSL_shutdown(self.native_object) | ||||||||||||||||
| ret = _lib.wolfSSL_shutdown(self.native_object) | ||||||||||||||||
| if ret == 0: | ||||||||||||||||
| _lib.wolfSSL_shutdown(self.native_object) | ||||||||||||||||
| self._release_native_object() | ||||||||||||||||
| if self._context.protocol < PROTOCOL_DTLSv1: | ||||||||||||||||
| self._sock.shutdown(how) | ||||||||||||||||
|
|
@@ -732,7 +736,8 @@ def unwrap(self): | |||||||||||||||
| Returns the wrapped OS socket. | ||||||||||||||||
| """ | ||||||||||||||||
| if self.native_object != _ffi.NULL: | ||||||||||||||||
| _lib.wolfSSL_set_fd(self.native_object, -1) | ||||||||||||||||
| _lib.wolfSSL_shutdown(self.native_object) | ||||||||||||||||
| self._release_native_object() | ||||||||||||||||
|
|
||||||||||||||||
| sock = socket(family=self._sock.family, | ||||||||||||||||
| sock_type=self._sock.type, | ||||||||||||||||
|
|
@@ -748,11 +753,16 @@ def add_peer(self, addr): | |||||||||||||||
| peerAddr = _lib.wolfSSL_dtls_create_peer(addr[1],t2b(addr[0])) | ||||||||||||||||
| if peerAddr == _ffi.NULL: | ||||||||||||||||
| raise SSLError("Failed to create peer") | ||||||||||||||||
| ret = _lib.wolfSSL_dtls_set_peer(self.native_object, peerAddr, | ||||||||||||||||
| _SOCKADDR_SZ) | ||||||||||||||||
| if ret != _SSL_SUCCESS: | ||||||||||||||||
| raise SSLError("Unable to set dtls peer. E(%d)" % ret) | ||||||||||||||||
| _lib.wolfSSL_dtls_free_peer(peerAddr) | ||||||||||||||||
| try: | ||||||||||||||||
| ret = _lib.wolfSSL_dtls_set_peer( | ||||||||||||||||
| self.native_object, peerAddr, | ||||||||||||||||
| _SOCKADDR_SZ) | ||||||||||||||||
| if ret != _SSL_SUCCESS: | ||||||||||||||||
| raise SSLError( | ||||||||||||||||
| "Unable to set dtls peer." | ||||||||||||||||
| " E(%d)" % ret) | ||||||||||||||||
| finally: | ||||||||||||||||
| _lib.wolfSSL_dtls_free_peer(peerAddr) | ||||||||||||||||
|
|
||||||||||||||||
| def do_handshake(self, block=False): # pylint: disable=unused-argument | ||||||||||||||||
| """ | ||||||||||||||||
|
|
@@ -814,18 +824,16 @@ def _real_connect(self, addr, connect_ex): | |||||||||||||||
| raise ValueError("attempt to connect already-connected SSLSocket!") | ||||||||||||||||
|
|
||||||||||||||||
| err = 0 | ||||||||||||||||
| ret = _SSL_SUCCESS | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| if self._context.protocol >= PROTOCOL_DTLSv1: | ||||||||||||||||
| self.add_peer(addr) | ||||||||||||||||
| self.add_peer(addr) | ||||||||||||||||
| else: | ||||||||||||||||
| if connect_ex: | ||||||||||||||||
| err = self._sock.connect_ex(addr) | ||||||||||||||||
| else: | ||||||||||||||||
| err = 0 | ||||||||||||||||
| self._sock.connect(addr) | ||||||||||||||||
|
|
||||||||||||||||
| if err == 0 and ret == _SSL_SUCCESS: | ||||||||||||||||
| if err == 0: | ||||||||||||||||
| self._connected = True | ||||||||||||||||
| if self.do_handshake_on_connect: | ||||||||||||||||
| self.do_handshake() | ||||||||||||||||
|
|
@@ -894,12 +902,18 @@ def version(self): | |||||||||||||||
| """ | ||||||||||||||||
| Returns the version of the protocol used in the connection. | ||||||||||||||||
| """ | ||||||||||||||||
| return _ffi.string(_lib.wolfSSL_get_version(self.native_object)).decode("ascii") | ||||||||||||||||
| self._check_closed("version") | ||||||||||||||||
| return _ffi.string( | ||||||||||||||||
| _lib.wolfSSL_get_version( | ||||||||||||||||
| self.native_object)).decode("ascii") | ||||||||||||||||
|
|
||||||||||||||||
| # The following functions expose functionality of the underlying | ||||||||||||||||
| # Socket object. These are also exposed through Python's ssl module | ||||||||||||||||
| # API and are provided here for compatibility. | ||||||||||||||||
| def close(self): | ||||||||||||||||
| if self.native_object != _ffi.NULL: | ||||||||||||||||
| _lib.wolfSSL_shutdown(self.native_object) | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Description: The new Code: def close(self):
if self.native_object != _ffi.NULL:
_lib.wolfSSL_shutdown(self.native_object)
self._release_native_object()
self._sock.close()Recommendation: Consider guarding the shutdown call to only run when a connection was established:
Suggested change
|
||||||||||||||||
| self._release_native_object() | ||||||||||||||||
| self._sock.close() | ||||||||||||||||
|
|
||||||||||||||||
| def fileno(self): | ||||||||||||||||
|
|
@@ -1029,12 +1043,17 @@ def callback(self): | |||||||||||||||
| def _get_passwd(self, passwd, sz, rw, userdata): | ||||||||||||||||
| try: | ||||||||||||||||
| result = self._passwd_wrapper(sz, rw, userdata) | ||||||||||||||||
| if not isinstance(result, bytes): | ||||||||||||||||
| raise ValueError("Problem, expected String, not bytes") | ||||||||||||||||
| if len(result) > sz: | ||||||||||||||||
| raise ValueError("Problem with password returned being long") | ||||||||||||||||
| for i in range(len(result)): | ||||||||||||||||
| passwd[i] = result[i:i + 1] | ||||||||||||||||
| return len(result) | ||||||||||||||||
| except Exception as e: | ||||||||||||||||
| raise ValueError("Problem getting password from callback") | ||||||||||||||||
| except Exception: | ||||||||||||||||
| raise ValueError( | ||||||||||||||||
| "Problem getting password from callback") | ||||||||||||||||
| if not isinstance(result, bytes): | ||||||||||||||||
| raise ValueError( | ||||||||||||||||
| "Password callback must return bytes," | ||||||||||||||||
| " not str") | ||||||||||||||||
| if len(result) > sz: | ||||||||||||||||
| raise ValueError( | ||||||||||||||||
| "Problem with password returned" | ||||||||||||||||
| " being long") | ||||||||||||||||
| for i in range(len(result)): | ||||||||||||||||
| passwd[i] = result[i:i + 1] | ||||||||||||||||
| return len(result) | ||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description: The new code conditionally skips
secure_socket.close()for DTLS (args.u). This is correct because for DTLS,secure_socketwrapsbind_socket(the listening UDP socket), and closing it would prevent subsequent loop iterations from accepting new connections. However, the reasoning isn't documented and could confuse future readers.Code:
Recommendation: Add a comment explaining why close is skipped for DTLS: