-
Notifications
You must be signed in to change notification settings - Fork 171
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
TLS Fallback Signaling Cipher Suite Value #165
Conversation
ext/openssl/ossl_ssl.c
Outdated
long modes; | ||
|
||
GetSSLCTX(self, ctx); | ||
if(!ctx){ |
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.
ctx is never NULL.
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.
Fixed
ext/openssl/ossl_ssl.c
Outdated
|
||
modes = SSL_CTX_get_mode(ctx); | ||
modes |= SSL_MODE_SEND_FALLBACK_SCSV; | ||
SSL_CTX_set_mode(ctx, modes); |
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.
SSL_CTX_set_mode() preserves the previously set flags, so just SSL_CTX_set_mode(ctx, SSL_MODE_SEND_FALLBACK_SCSV)
is fine.
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.
Fixed
test/utils.rb
Outdated
rescue OpenSSL::SSL::SSLError => e | ||
retry if ignore_listener_error | ||
raise unless e.message =~ /inappropriate fallback/ | ||
rescue IOError, Errno::EBADF, Errno::EINVAL, |
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.
Are changes in start_server really needed? I'd like to have all SCSV specific code in TestSSL#test_fallback_scsv.
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.
An exception occurs on server part too in case of SCSV error.
Without this catch, unit test detect only the server part and not the tested client part as expected.
I didn't find a proper way to do this :'(
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.
You can get a raw TCP socket pair by socketpair
defined in TestSSL when the exception raised by SSLSocket#accept has to be tested.
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.
Ah, I misinterpreted your comment. Errors raised in server can be suppressed by passing 'ignore_listener_error: true' to start_server.
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.
I fix the test with socketpair
, to also test server side error.
ext/openssl/ossl_ssl.c
Outdated
static VALUE | ||
ossl_sslctx_enable_fallback_scsv(VALUE self) | ||
{ | ||
#ifdef SSL_MODE_SEND_FALLBACK_SCSV |
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.
The method should not be defined at all if SSL_MODE_SEND_FALLBACK_SCSV is not usable.
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.
Fixed
lib/openssl/ssl.rb
Outdated
self.options |= OpenSSL::SSL::OP_ALL | ||
self.ssl_version = version if version | ||
self.enable_fallback_scsv if fallback_scsv |
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.
I think #initialize should take all or nothing -- it's just confusing to have only fallback_scsv option.
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.
OpenSSL::SSL::SSLContext
is generally used with the short form SSLContext.new version
, without configuration after that. Having SCSV set on initialize
allows to keep short form with SCSV protection SSLContext.new version, fallback_scsv: true
without configuration too.
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.
As in the RDoc comment above, use of the form "SSL::SSLContext.new(ssl_method_name)" (and SSL::SSLContext#ssl_version= which is called from it) is not recommended anymore. This is because the version-specific SSL methods has been deprecated in the OpenSSL C API.
In addition to the protocol version which is now preferably set by SSL::SSLContext#{min,max}_version=, clients would usually need to set other options such as verify_mode, too. IMHO SSL::SSLContext has too much options to enumerate in kwargs...
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.
Ping on this?
test/test_ssl.rb
Outdated
@@ -1222,6 +1222,49 @@ def test_get_ephemeral_key | |||
end | |||
end | |||
|
|||
def test_fallback_scsv | |||
ctx_proc = proc { |ctx| | |||
ctx.ciphers = "kRSA" |
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.
Avoid kRSA since it will not work with TLS 1.3-capable OpenSSL. It's not finalized yet, but I try to keep the tests pass with the master branch of OpenSSL.
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.
Fixed
Just out of curiosity (I'm fine with either one), is there any particular reason to choose #enable_fallback_scsv over #{send_,}fallback_scsv=true|false? |
|
Fair enough, I agree nobody would bother with setting that explicitly. |
@@ -1222,6 +1222,56 @@ def test_get_ephemeral_key | |||
end | |||
end | |||
|
|||
def test_fallback_scsv |
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.
This test case is failing with LibreSSL or older patch versions of OpenSSL 1.0.1 because they lack support for TLS_FALLBACK_SCSV. pend
if the method does not exist.
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.
Fixed
test/test_ssl.rb
Outdated
} | ||
|
||
assert t.join | ||
end |
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.
Sockets created by socketpair have to be closed manually to prevent FD leak (which could be an issue when running tests repeatedly for debugging).
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.
Fixed
test/test_ssl.rb
Outdated
@@ -1222,6 +1222,56 @@ def test_get_ephemeral_key | |||
end | |||
end | |||
|
|||
def test_fallback_scsv | |||
ctx_proc = proc { |ctx| | |||
ctx.ssl_version = :TLSv1_2 |
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.
Please use #max_version= and #min_version= in new tests. In this case, specifying just max_version would be enough. (This applies to the other instances too.)
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.
Fixed
test/test_ssl.rb
Outdated
sock1, sock2 = socketpair | ||
ctx1 = OpenSSL::SSL::SSLContext.new | ||
ctx1.min_version = OpenSSL::SSL::TLS1_1_VERSION | ||
ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION |
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.
The server doesn't need to set neither min_version nor max_version since we know all protocol versions are enabled by default.
test/test_ssl.rb
Outdated
ctx1 = OpenSSL::SSL::SSLContext.new | ||
ctx1.min_version = OpenSSL::SSL::TLS1_1_VERSION | ||
ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION | ||
s1 = OpenSSL::SSL::SSLSocket.new sock1, ctx1 |
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.
Please parenthesize arguments for consistency with other tests in this file.
ext/openssl/ossl_ssl.c
Outdated
* Activate TLS_FALLBACK_SCSV for this context. | ||
* See RFC 7507. | ||
*/ | ||
#ifdef SSL_MODE_SEND_FALLBACK_SCSV |
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.
I think ossl_sslctx_enable_fallback_scsv() should be placed after ossl_sslctx_set_security_level() so the ordering match with the rb_define_method() lines. (We haven't been always consistent, but ...)
By the way, RDoc seems to fail to find the doc. Moving #ifdef SSL_MODE_SEND_FALLBACK_SCSV
above the block comment fixes it for me. This might be considered a bug of RDoc's C parser, though.
test/test_ssl.rb
Outdated
|
||
start_server do |port| | ||
ctx = OpenSSL::SSL::SSLContext.new | ||
ctx.ssl_version = :TLSv1_2 |
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.
Please use #max_version= for client SSL contexts, too.
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.
Ok, fixed.
But for client, it's strange to have to use min/max, because AFAIK, SSLContext doesn't handle fallback by itself and support only a single version (the max_version).
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.
Yes, in a real use case, the client will surely enable only one protocol version. The point is, in this case, that #ssl_version= should not be used because it's an old and deprecated method. New applications should write as:
ctx.min_version = ctx.max_version = ...
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.
In this case, why not reimplement old ssl_version with min/max_version under the hood ?
min/max is cool for server part, but for client part, better to have a single version, no ?
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.
Actually It's been rewritten to call #min_version= and #max_version=. But it's a different story whether we should recommend using that or not.
Line 186 in d834e86
# call-seq: |
It's a decision of the OpenSSL C API that the SSL/TLS protocol version specific SSL methods, such as TLSv1_2_method() which corresponds to :TLSv1_2, are now deprecated. Please see TLSv1_2_method(3).
https://www.openssl.org/docs/manmaster/man3/TLSv1_2_method.html
(The web site seems down now)
This looks really nice to me. Thanks for your patience! Lastly, can you squash the commits into one commit? |
Support for fallback SCSV [RFC 7507](https://tools.ietf.org/html/rfc7507). Expected behaviour is to refuse connection if the client signals a protocol with the fallback flag but the server supports a better one (downgrade attack detection).
Done :) |
Support for fallback SCSV RFC 7507.
Expected behaviour is to refuse connection if the client signals a protocol with
the fallback flag but the server supports a better one (downgrade attack detection).