Skip to content

Commit

Permalink
Merge pull request #1836 from MSP-Greg/openssl-updates
Browse files Browse the repository at this point in the history
Openssl updates
  • Loading branch information
evanphx committed Aug 6, 2019
2 parents 6dd084b + 35dbec0 commit 3ea2471
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 35 deletions.
16 changes: 10 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
dist: xenial
env: OS="Xenial 16.04 OpenSSL 1.0.2"
language: ruby
cache: bundler

Expand All @@ -19,6 +20,7 @@ before_install:
- ruby -v && gem --version && bundle version

before_script:
- if [ "$jit" == "yes" ]; then export RUBYOPT=--jit ; fi ; echo RUBYOPT is $RUBYOPT
- bundle exec rake compile

script:
Expand All @@ -37,26 +39,28 @@ matrix:
include:
- rvm: 2.2
dist: trusty
env: NOTES="Trusty OpenSSL 1.0.1"
env: OS="Trusty 14.04 OpenSSL 1.0.1"
- rvm: 2.6
dist: bionic
env: OS="Bionic 18.04 OpenSSL 1.1.1"
- rvm: ruby-head
env: RUBYOPT="--jit"
env: jit=yes
- rvm: 2.4.6
os: osx
osx_image: xcode10.2
env: OS="osx xcode10.2"
- rvm: 2.5.5
os: osx
osx_image: xcode10.2
- rvm: 2.6.3
os: osx
osx_image: xcode10.2
env: OS="osx xcode10.2"
- rvm: jruby-9.2.7.0
env: JRUBY_OPTS="--debug" JAVA_OPTS="--add-opens java.base/sun.nio.ch=org.jruby.dist --add-opens java.base/java.io=org.jruby.dist --add-opens java.base/java.util.zip=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.security.cert=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED"
- rvm: jruby-head

allow_failures:
- rvm: ruby-head
- rvm: ruby-head
env: RUBYOPT="--jit"
env: jit=yes
- rvm: jruby-9.2.7.0
- rvm: jruby-head

Expand Down
62 changes: 55 additions & 7 deletions ext/puma_http11/mini_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
VALUE obj;
SSL_CTX* ctx;
SSL* ssl;
int ssl_options;
int min, ssl_options;

ms_conn* conn = engine_alloc(self, &obj);

Expand All @@ -168,6 +168,9 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
ID sym_no_tlsv1 = rb_intern("no_tlsv1");
VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);

ID sym_no_tlsv1_1 = rb_intern("no_tlsv1_1");
VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);

#ifdef HAVE_TLS_SERVER_METHOD
ctx = SSL_CTX_new(TLS_server_method());
#else
Expand All @@ -183,12 +186,36 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
}

ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;

if(RTEST(no_tlsv1)) {
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
if (RTEST(no_tlsv1_1)) {
min = TLS1_2_VERSION;
}
else if (RTEST(no_tlsv1)) {
min = TLS1_1_VERSION;
}
else {
min = TLS1_VERSION;
}

SSL_CTX_set_min_proto_version(ctx, min);

SSL_CTX_set_options(ctx, ssl_options);

#else
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;

if (RTEST(no_tlsv1)) {
ssl_options |= SSL_OP_NO_TLSv1;
}
if(RTEST(no_tlsv1_1)) {
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
}
SSL_CTX_set_options(ctx, ssl_options);
#endif

SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);

if (!NIL_P(ssl_cipher_filter)) {
Expand Down Expand Up @@ -458,14 +485,35 @@ void Init_mini_ssl(VALUE puma) {
// OpenSSL Build / Runtime/Load versions

/* Version of OpenSSL that Puma was compiled with */
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));

#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
/* Version of OpenSSL that Puma loaded with */
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
/* Version of OpenSSL that Puma loaded with */
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
#else
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
#endif

#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
/* True if SSL3 is not available */
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
#else
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
#endif

#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
/* True if TLS1 is not available */
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
#else
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
#endif

#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
/* True if TLS1_1 is not available */
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
#else
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
#endif

rb_define_singleton_method(mod, "check", noop, 0);

Expand Down
4 changes: 4 additions & 0 deletions ext/puma_http11/org/jruby/puma/MiniSSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ public IRubyObject initialize(ThreadContext threadContext, IRubyObject miniSSLCo
protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" };
}

if(miniSSLContext.callMethod(threadContext, "no_tlsv1_1").isTrue()) {
protocols = new String[] { "TLSv1.2" };
}

engine.setEnabledProtocols(protocols);
engine.setUseClientMode(false);

Expand Down
1 change: 1 addition & 0 deletions lib/puma/binder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def parse(binds, logger)
end

ctx.no_tlsv1 = true if params['no_tlsv1'] == 'true'
ctx.no_tlsv1_1 = true if params['no_tlsv1_1'] == 'true'

if params['verify_mode']
ctx.verify_mode = case params['verify_mode']
Expand Down
5 changes: 3 additions & 2 deletions lib/puma/dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,15 @@ def threads(min, max)
def ssl_bind(host, port, opts)
verify = opts.fetch(:verify_mode, 'none')
no_tlsv1 = opts.fetch(:no_tlsv1, 'false')
no_tlsv1_1 = opts.fetch(:no_tlsv1_1, 'false')
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)

if defined?(JRUBY_VERSION)
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}#{ca_additions}"
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
else
ssl_cipher_filter = "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" if opts[:ssl_cipher_filter]
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}#{ca_additions}"
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
end
end

Expand Down
13 changes: 10 additions & 3 deletions lib/puma/minissl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,11 @@ def self.check; end

class Context
attr_accessor :verify_mode
attr_reader :no_tlsv1
attr_reader :no_tlsv1, :no_tlsv1_1

def initialize
@no_tlsv1 = false
@no_tlsv1 = false
@no_tlsv1_1 = false
end

if defined?(JRUBY_VERSION)
Expand Down Expand Up @@ -219,18 +220,24 @@ def ca=(ca)
@ca = ca
end


def check
raise "Key not configured" unless @key
raise "Cert not configured" unless @cert
end
end

# disables TLSv1
def no_tlsv1=(tlsv1)
raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1)
@no_tlsv1 = tlsv1
end

# disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
def no_tlsv1_1=(tlsv1_1)
raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1_1)
@no_tlsv1_1 = tlsv1_1
end

end

VERIFY_NONE = 0
Expand Down
15 changes: 14 additions & 1 deletion test/test_binder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,22 @@ def test_binder_parses_tlsv1_enabled
refute ssl_context_for_binder(@binder).no_tlsv1
end

def test_binder_parses_tlsv1_unspecified_defaults_to_enabled
def test_binder_parses_tlsv1_tlsv1_1_unspecified_defaults_to_enabled
@binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}"], @events)

refute ssl_context_for_binder(@binder).no_tlsv1
refute ssl_context_for_binder(@binder).no_tlsv1_1
end

def test_binder_parses_tlsv1_1_disabled
@binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}&no_tlsv1_1=true"], @events)

assert ssl_context_for_binder(@binder).no_tlsv1_1
end

def test_binder_parses_tlsv1_1_enabled
@binder.parse(["ssl://0.0.0.0?key=#{@key}&cert=#{@cert}&no_tlsv1_1=false"], @events)

refute ssl_context_for_binder(@binder).no_tlsv1_1
end
end
2 changes: 1 addition & 1 deletion test/test_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def test_ssl_bind

conf.load

ssl_binding = "ssl://0.0.0.0:9292?cert=/path/to/cert&key=/path/to/key&verify_mode=the_verify_mode&no_tlsv1=false"
ssl_binding = "ssl://0.0.0.0:9292?cert=/path/to/cert&key=/path/to/key&verify_mode=the_verify_mode&no_tlsv1=false&no_tlsv1_1=false"
assert_equal [ssl_binding], conf.options[:binds]
end

Expand Down

0 comments on commit 3ea2471

Please sign in to comment.