1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
Description: Change default SSL configuration
The POODLE attack (https://en.wikipedia.org/wiki/POODLE) deprecated the use
of SSLv3 protocol. We change the default configuration to autodetection
and try to explicitly disable SSLv2 and SSLv3, preferring TLS protocol suites
instead.
This patch is a minimal adaptation of a commit in the project's upstream:
https://github.com/nahi/httpclient/commit/90d5c791c941c72521784dc4ea8eed60987800da
--- a/lib/httpclient/ssl_config.rb
+++ b/lib/httpclient/ssl_config.rb
@@ -34,7 +34,13 @@
class SSLConfig
include OpenSSL if SSLEnabled
- # String name of OpenSSL's SSL version method name: SSLv2, SSLv23 or SSLv3
+ # Which TLS protocol version (also called method) will be used. Defaults
+ # to :auto which means that OpenSSL decides (In my tests this resulted
+ # with always the highest available protocol being used).
+ # String name of OpenSSL's SSL version method name: TLSv1_2, TLSv1_1, TLSv1,
+ # SSLv2, SSLv23, SSLv3 or :auto (and nil) to allow version negotiation (default).
+ # See {OpenSSL::SSL::SSLContext::METHODS} for a list of available versions
+ # in your specific Ruby environment.
attr_reader :ssl_version
# OpenSSL::X509::Certificate:: certificate for SSL client authenticateion.
# nil by default. (no client authenticateion)
@@ -83,8 +89,13 @@
@verify_callback = nil
@dest = nil
@timeout = nil
- @ssl_version = "SSLv3"
- @options = defined?(SSL::OP_ALL) ? SSL::OP_ALL | SSL::OP_NO_SSLv2 : nil
+ @ssl_version = :auto
+ # Follow ruby-ossl's definition
+ @options = OpenSSL::SSL::OP_ALL
+ @options &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
+ @options |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
+ @options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
+ @options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
# OpenSSL 0.9.8 default: "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH"
@ciphers = "ALL:!aNULL:!eNULL:!SSLv2" # OpenSSL >1.0.0 default
@cacerts_loaded = false
@@ -283,7 +294,7 @@
ctx.timeout = @timeout
ctx.options = @options
ctx.ciphers = @ciphers
- ctx.ssl_version = @ssl_version
+ ctx.ssl_version = @ssl_version unless @ssl_version == :auto
end
# post connection check proc for ruby < 1.8.5.
--- a/test/test_ssl.rb
+++ b/test/test_ssl.rb
@@ -33,7 +33,10 @@
assert_equal(OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT, cfg.verify_mode)
assert_nil(cfg.verify_callback)
assert_nil(cfg.timeout)
- assert_equal(OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2, cfg.options)
+ expected_options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
+ expected_options &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
+ expected_options |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
+ assert_equal(expected_options, cfg.options)
assert_equal("ALL:!aNULL:!eNULL:!SSLv2", cfg.ciphers)
assert_instance_of(OpenSSL::X509::Store, cfg.cert_store)
end
|