Skip to content

Commit

Permalink
SSL min_version/max_version support
Browse files Browse the repository at this point in the history
  • Loading branch information
mrpasquini authored and Matt Pasquini committed Nov 22, 2020
1 parent 4658227 commit 001b93a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 3 deletions.
3 changes: 3 additions & 0 deletions lib/httpclient/jruby_ssl_socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ def self.create_socket(session)
DEFAULT_SSL_PROTOCOL = (java.lang.System.getProperty('java.specification.version') == '1.7') ? 'TLSv1.2' : 'TLS'
def initialize(socket, dest, config, opts = {})
@config = config
raise NotImplementedError.new('SSL min_version is not yet supported by jruby') if config.min_version
raise NotImplementedError.new('SSL max_version is not yet supported by jruby') if config.max_version

begin
@ssl_socket = create_ssl_socket(socket, dest, config, opts)
ssl_version = java_ssl_version(config)
Expand Down
17 changes: 15 additions & 2 deletions lib/httpclient/ssl_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,17 @@ def attr_config(symbol)
# 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.
# in your specific Ruby environment. This is
# deprecated and only provided for backwards compatibility. Use
# #min_version= and #max_version= instead.
attr_config :ssl_version
# Sets the upper bound on the supported SSL/TLS protocol version.
# See min_version for possible values.
attr_config :max_version
# Sets the lower bound on the supported SSL/TLS protocol version.
# The version may be specified by an integer constant named
# OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version".
attr_config :min_version
# OpenSSL::X509::Certificate:: certificate for SSL client authentication.
# nil by default. (no client authentication)
attr_config :client_cert
Expand Down Expand Up @@ -125,7 +134,7 @@ def attr_config(symbol)
# A number of OpenSSL's SSL options. Default value is
# OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2
# CAUTION: this is OpenSSL specific option and ignored on JRuby.
# Use ssl_version to specify the TLS version you want to use.
# Use min_version and max_version to specify the TLS versions you want to use.
attr_config :options
# A String of OpenSSL's cipher configuration. Default value is
# ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH
Expand Down Expand Up @@ -158,6 +167,8 @@ def initialize(client)
@dest = nil
@timeout = nil
@ssl_version = :auto
@max_version = nil
@min_version = nil
# 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)
Expand Down Expand Up @@ -309,6 +320,8 @@ def set_context(ctx) # :nodoc:
ctx.options = @options
ctx.ciphers = @ciphers
ctx.ssl_version = @ssl_version unless @ssl_version == :auto
ctx.min_version = @min_version if @min_version
ctx.max_version = @max_version if @max_version
end

# post connection check proc for ruby < 1.8.5.
Expand Down
45 changes: 44 additions & 1 deletion test/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def test_no_sslv3
omit('TODO: SSLv3 is not supported in many environments. re-enable when disable TLSv1')
teardown_server
setup_server_with_ssl_version(:SSLv3)
assert_raise(OpenSSL::SSL::SSLError) do
assert_raise(NotImplementedError) do
@client.ssl_config.verify_mode = nil
@client.get("https://localhost:#{serverport}/hello")
end
Expand All @@ -266,6 +266,22 @@ def test_allow_tlsv1
end
end

def test_allow_with_min_max
teardown_server
setup_server_with_min_and_max_version(:TLS1_2)
if RUBY_ENGINE == 'jruby'
assert_raise(OpenSSL::SSL::SSLError) do
@client.ssl_config.verify_mode = nil
@client.get("https://localhost:#{serverport}/hello")
end
else
assert_nothing_raised do
@client.ssl_config.verify_mode = nil
@client.get("https://localhost:#{serverport}/hello")
end
end
end

def test_use_higher_TLS
omit('TODO: it does not pass with Java 7 or old openssl')
teardown_server
Expand Down Expand Up @@ -500,6 +516,33 @@ def setup_server_with_ssl_version(ssl_version)
@server_thread = start_server_thread(@server)
end

def setup_server_with_min_and_max_version(version)
logger = Logger.new(STDERR)
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
@server = WEBrick::HTTPServer.new(
:BindAddress => "localhost",
:Logger => logger,
:Port => 0,
:AccessLog => [],
:DocumentRoot => DIR,
:SSLEnable => true,
:SSLCACertificateFile => File.join(DIR, 'ca.cert'),
:SSLCertificate => cert('server.cert'),
:SSLPrivateKey => key('server.key')
)
@server.ssl_context.min_version = version
@server.ssl_context.max_version = version

@serverport = @server.config[:Port]
[:hello].each do |sym|
@server.mount(
"/#{sym}",
WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
)
end
@server_thread = start_server_thread(@server)
end

def setup_server_with_server_cert(ca_cert, server_cert, server_key)
logger = Logger.new(STDERR)
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
Expand Down

0 comments on commit 001b93a

Please sign in to comment.