-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Added TLS_method bindings for OpenSSL and LibreSSL #5483
Changes from 2 commits
07b8132
dc9cde7
a5f30c8
f9b9e05
1814d4f
f1a5433
50c398c
d0dd934
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 |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
static const long Cryptography_HAS_TLSv1_1; | ||
static const long Cryptography_HAS_TLSv1_2; | ||
static const long Cryptography_HAS_TLSv1_3; | ||
static const long Cryptography_HAS_TLS_METHOD; | ||
static const long Cryptography_HAS_SECURE_RENEGOTIATION; | ||
static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB; | ||
static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP; | ||
|
@@ -362,6 +363,11 @@ | |
const SSL_METHOD *DTLSv1_server_method(void); | ||
const SSL_METHOD *DTLSv1_client_method(void); | ||
|
||
/* Added in 1.1.0 */ | ||
const SSL_METHOD *TLS_method(void); | ||
const SSL_METHOD *TLS_client_method(void); | ||
const SSL_METHOD *TLS_server_method(void); | ||
|
||
/* Added in 1.0.2 */ | ||
const SSL_METHOD *DTLS_method(void); | ||
const SSL_METHOD *DTLS_server_method(void); | ||
|
@@ -501,6 +507,7 @@ | |
""" | ||
|
||
CUSTOMIZATIONS = """ | ||
|
||
#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 | ||
static const long Cryptography_HAS_VERIFIED_CHAIN = 0; | ||
Cryptography_STACK_OF_X509 *(*SSL_get0_verified_chain)(const SSL *) = NULL; | ||
|
@@ -755,4 +762,13 @@ | |
#else | ||
static const long Cryptography_HAS_TLSv1_3 = 1; | ||
#endif | ||
|
||
#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL | ||
static const long Cryptography_HAS_TLS_METHOD = 0; | ||
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.
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. @reaperhulk Thank you for the very thorough and useful review (lots of great stuff that would've slipped through the cracks due to my inexperience with CFFI and lack of attention). I'm reviewing one last issue here related to how this functionally modifies program behavior. I suspect I'll have my final item ready for submission today or tomorrow. Hold tight. (This update caused paramiko to fail its downstream build in Travis CI) 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. Initially, I was in agreement on this, but now I am thinking that it might be unwise to implement the Additionally, I am beginning to think that I might need to actually implement more tests in this PR before it's ready due to the kinds of problems described in this Code Review for Google's BoringSSL: https://boringssl-review.googlesource.com/c/boringssl/+/8513/ As a specific test, I think it might be important to add a test related to whether Note: I have the jupyter notebook describing the issue on Github, but it's private and the code demonstrating the discontinuous range issue "got lost" because I apparently forgot to push it before deleting the folder. Not sure what happened actually, because (upon reinspection) it looks like I might have lost a little more than just the demo code. 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. Err, what is my location? 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. It's true I live in Washington, DC but I don't see the relevance? 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.
cryptography's bindings layer cannot enforce sanity in OpenSSL's APIs. That way lies madness. We can only expose their API and attempt use it safely/sanely within our own code. We don't even consider our bindings public surface area any more (pyOpenSSL is a special case that we ensure does not break). I'm opposed to trying to test for behavioral quirks (even dangerous ones) since it almost definitionally can't be useful to this project. That effort is much better expended upstream in conversations with OpenSSL about how to improve/replace dangerous APIs. 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. Yeah there's no difference in behavior between SSLv23_method and TLS_method. The version disabling flags do indeed behave a little oddly but I don't think it's related to this. The less surprising API is SSL_set_min/max_proto_version if you all want to switch to those, but they only exist starting 1.1.0. 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. |
||
const SSL_METHOD* (*TLS_method)(void) = NULL; | ||
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. Why isn't this just 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. Lack of attention on my part, I failed to pull this in from the prior PR. Excellent catch and suggestion, I've committed and pushed. Thank you, very much. |
||
const SSL_METHOD* (*TLS_client_method)(void) = NULL; | ||
const SSL_METHOD* (*TLS_server_method)(void) = NULL; | ||
#else | ||
static const long Cryptography_HAS_TLS_METHOD = 1; | ||
#endif | ||
""" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,6 +85,61 @@ def test_ssl_mode(self): | |
assert resp == expected_options | ||
assert b.lib.SSL_get_mode(ssl) == expected_options | ||
|
||
@pytest.mark.skipif( | ||
Binding.lib.Cryptography_HAS_TLS_METHOD == 0, | ||
reason="TLS_method requires OpenSSL >= 1.1.0", | ||
) | ||
def test_tls_ctx_options(self): | ||
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. Duplicating these tests just to pass TLS_method isn't necessary. 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. Noted in the commit update (currently building). Thanks for catching that. |
||
# Test that we're properly handling 32-bit unsigned on all platforms. | ||
b = Binding() | ||
assert b.lib.SSL_OP_ALL > 0 | ||
ctx = b.lib.SSL_CTX_new(b.lib.TLS_method()) | ||
assert ctx != b.ffi.NULL | ||
ctx = b.ffi.gc(ctx, b.lib.SSL_CTX_free) | ||
current_options = b.lib.SSL_CTX_get_options(ctx) | ||
resp = b.lib.SSL_CTX_set_options(ctx, b.lib.SSL_OP_ALL) | ||
expected_options = current_options | b.lib.SSL_OP_ALL | ||
assert resp == expected_options | ||
assert b.lib.SSL_CTX_get_options(ctx) == expected_options | ||
|
||
@pytest.mark.skipif( | ||
Binding.lib.Cryptography_HAS_TLS_METHOD == 0, | ||
reason="TLS_method requires OpenSSL >= 1.1.0", | ||
) | ||
def test_tls_options(self): | ||
# Test that we're properly handling 32-bit unsigned on all platforms. | ||
b = Binding() | ||
assert b.lib.SSL_OP_ALL > 0 | ||
ctx = b.lib.SSL_CTX_new(b.lib.TLS_method()) | ||
assert ctx != b.ffi.NULL | ||
ctx = b.ffi.gc(ctx, b.lib.SSL_CTX_free) | ||
ssl = b.lib.SSL_new(ctx) | ||
ssl = b.ffi.gc(ssl, b.lib.SSL_free) | ||
current_options = b.lib.SSL_get_options(ssl) | ||
resp = b.lib.SSL_set_options(ssl, b.lib.SSL_OP_ALL) | ||
expected_options = current_options | b.lib.SSL_OP_ALL | ||
assert resp == expected_options | ||
assert b.lib.SSL_get_options(ssl) == expected_options | ||
|
||
@pytest.mark.skipif( | ||
Binding.lib.Cryptography_HAS_TLS_METHOD == 0, | ||
reason="TLS_method requires OpenSSL >= 1.1.0", | ||
) | ||
def test_tls_mode(self): | ||
# Test that we're properly handling 32-bit unsigned on all platforms. | ||
b = Binding() | ||
assert b.lib.SSL_OP_ALL > 0 | ||
ctx = b.lib.SSL_CTX_new(b.lib.TLS_method()) | ||
assert ctx != b.ffi.NULL | ||
ctx = b.ffi.gc(ctx, b.lib.SSL_CTX_free) | ||
ssl = b.lib.SSL_new(ctx) | ||
ssl = b.ffi.gc(ssl, b.lib.SSL_free) | ||
current_options = b.lib.SSL_get_mode(ssl) | ||
resp = b.lib.SSL_set_mode(ssl, b.lib.SSL_OP_ALL) | ||
expected_options = current_options | b.lib.SSL_OP_ALL | ||
assert resp == expected_options | ||
assert b.lib.SSL_get_mode(ssl) == expected_options | ||
|
||
def test_conditional_removal(self): | ||
b = Binding() | ||
|
||
|
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.
Extraneous newline. Otherwise this LGTM now.