Skip to content
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

SSL min_version/max_version support #423

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
42 changes: 41 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,19 @@ def test_allow_tlsv1
end
end

def test_allow_with_min_max
if RUBY_ENGINE == 'jruby'
omit('jruby does not currently support setting OpenSSL min_version or max_version')
else
teardown_server
setup_server_with_min_and_max_version(:TLS1_2)
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 +513,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