Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby-openssl
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 67820b9e8aba
Choose a base ref
...
head repository: jruby/jruby-openssl
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ec7b8e7deb84
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Nov 2, 2017

  1. Copy the full SHA
    c1901f2 View commit details
  2. Copy the full SHA
    ec7b8e7 View commit details
10 changes: 9 additions & 1 deletion src/main/java/org/jruby/ext/openssl/SSLContext.java
Original file line number Diff line number Diff line change
@@ -181,7 +181,6 @@ public static void createSSLContext(final Ruby runtime, final RubyModule SSL) {
SSLContext.defineAlias("ssl_timeout=", "timeout=");

SSLContext.defineAnnotatedMethods(SSLContext.class);
SSLContext.undefineMethod("dup");

final Set<String> methodKeys = SSL_VERSION_OSSL2JSSE.keySet();
final RubyArray methods = runtime.newArray( methodKeys.size() );
@@ -292,6 +291,15 @@ public IRubyObject initialize(IRubyObject[] args) {
return initializeImpl();
}

@Override
public IRubyObject initialize_copy(IRubyObject original) {
return super.initialize_copy(original);
// NOTE: only instance variables (no internal state) on #dup
// final SSLContext that = (SSLContext) original;
// this.ciphers = that.ciphers;
// return this;
}

final SSLContext initializeImpl() { return this; }

@JRubyMethod
121 changes: 117 additions & 4 deletions src/test/ruby/ssl/test_helper.rb
Original file line number Diff line number Diff line change
@@ -29,9 +29,40 @@ def setup; require 'openssl'
@server = nil
end

def start_server(port0, verify_mode, start_immediately, args = {}, &block)
require 'socket'
private

# threads should respond to shift method.
# Array can be used.
def assert_join_threads(threads, message = nil)
errs = []; values = []
while th = threads.shift
begin
values << th.value
rescue Exception
errs << [th, $!]
end
end
unless errs.empty?
msg = "exceptions on #{errs.length} threads:\n" +
errs.map {|t, err|
"#{t.inspect}:\n" +
err.backtrace.map.with_index {|line, i|
if i == 0
"#{line}: #{err.message} (#{err.class})"
else
"\tfrom #{line}"
end
}.join("\n")
}.join("\n---\n")
msg = "#{message}\n#{msg}" if message
fail msg # raise MiniTest::Assertion, msg
end
values
end

protected

def start_server0(port0, verify_mode, start_immediately, args = {}, &block); require 'socket'
ctx_proc = args[:ctx_proc]
server_proc = args[:server_proc]
server_proc ||= method(:readwrite_loop)
@@ -64,7 +95,7 @@ def start_server(port0, verify_mode, start_immediately, args = {}, &block)
begin
server = Thread.new do
Thread.current.abort_on_exception = true
server_loop(context, ssls, server_proc)
server_loop0(context, ssls, server_proc)
end

$stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, $$, port) #if $DEBUG
@@ -75,6 +106,63 @@ def start_server(port0, verify_mode, start_immediately, args = {}, &block)
end
end

def start_server(verify_mode, start_immediately, args = {}, &block); require 'socket'
IO.pipe do |stop_pipe_r, stop_pipe_w|
ctx_proc = args[:ctx_proc]
server_proc = args[:server_proc]
ignore_listener_error = args.fetch(:ignore_listener_error, false)
use_anon_cipher = args.fetch(:use_anon_cipher, false)
server_proc ||= method(:readwrite_loop)

store = OpenSSL::X509::Store.new
store.add_cert(@ca_cert)
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
ctx = OpenSSL::SSL::SSLContext.new
ctx.ciphers = "ADH-AES256-GCM-SHA384" if use_anon_cipher
ctx.cert_store = store
#ctx.extra_chain_cert = [ ca_cert ]
ctx.cert = @svr_cert
ctx.key = @svr_key
ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
ctx.verify_mode = verify_mode
ctx_proc.call(ctx) if ctx_proc

Socket.do_not_reverse_lookup = true

tcps = TCPServer.new("127.0.0.1", 0)
port = tcps.connect_address.ip_port

ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
ssls.start_immediately = start_immediately

threads = []
begin
server = Thread.new do
# Thread.current.abort_on_exception = true
begin
server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
ensure
tcps.close
end
end
threads.unshift server

$stderr.printf("SSL server started: pid=%d port=%d\n", $$, port) if $DEBUG

client = Thread.new do
begin
block.call(server, port.to_i)
ensure
stop_pipe_w.close
end
end
threads.unshift client
ensure
assert_join_threads(threads)
end
end
end

def tcp_server_close(thread, tcp_server)
begin
tcp_server.shutdown
@@ -110,7 +198,7 @@ def tcp_server_close(thread, tcp_server)
( defined? JRUBY_VERSION && JRUBY_VERSION < '1.7.0' )
private :tcp_server_close

def server_loop(context, server, server_proc)
def server_loop0(context, server, server_proc)
loop do
ssl = nil
begin
@@ -127,6 +215,31 @@ def server_loop(context, server, server_proc)
rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
end

def server_loop(ctx, ssls, stop_pipe_r, ignore_listener_error, server_proc, threads)
loop do
ssl = nil
begin
readable, = IO.select([ssls, stop_pipe_r])
return if readable.include? stop_pipe_r
ssl = ssls.accept
rescue OpenSSL::SSL::SSLError
if ignore_listener_error
retry
else
raise
end
end

threads << Thread.start do
# Thread.current.abort_on_exception = true
server_proc.call(ctx, ssl)
end
end
rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET => ex
raise(ex) unless ignore_listener_error
puts ex.inspect if $VERBOSE
end

def server_connect(port, ctx = nil)
sock = TCPSocket.new('127.0.0.1', port)
ssl = ctx ? OpenSSL::SSL::SSLSocket.new(sock, ctx) : OpenSSL::SSL::SSLSocket.new(sock)
2 changes: 1 addition & 1 deletion src/test/ruby/ssl/test_session.rb
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ class TestSSLSession < TestCase
include SSLTestHelper

def test_session
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ctx = OpenSSL::SSL::SSLContext.new("TLSv1")
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
2 changes: 1 addition & 1 deletion src/test/ruby/ssl/test_socket.rb
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ def test_sync_close_without_connect
include SSLTestHelper

def test_ssl_sysread_blocking_error
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
server_connect(port) do |ssl|
ssl.write("abc\n")
# assert_raise(TypeError) { eval 'ssl.sysread(4, exception: false)' }
65 changes: 53 additions & 12 deletions src/test/ruby/ssl/test_ssl.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ class TestSSL < TestCase
def test_context_default_constants
assert OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
assert_equal 'SSLv23', OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ssl_version]
assert_equal "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW", OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
# assert_equal "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW", OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
assert_equal OpenSSL::SSL::VERIFY_PEER, OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:verify_mode]

assert OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE
@@ -18,7 +18,7 @@ def test_context_default_constants
def test_post_connection_check
sslerr = OpenSSL::SSL::SSLError

start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -42,7 +42,7 @@ def test_post_connection_check
]
@svr_cert = issue_cert(@svr, @svr_key, 4, now, now + 1800, exts,
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -66,7 +66,7 @@ def test_post_connection_check
]
@svr_cert = issue_cert(@svr, @svr_key, 5, now, now + 1800, exts,
@ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -83,6 +83,10 @@ def test_post_connection_check
end

def test_post_connect_check_with_anon_ciphers
unless OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384
return skip('OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384 not enabled')
end

start_server(OpenSSL::SSL::VERIFY_NONE, true, { use_anon_cipher: true }) { |server, port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ciphers = "aNULL"
@@ -92,13 +96,13 @@ def test_post_connect_check_with_anon_ciphers
assert_raise_with_message(OpenSSL::SSL::SSLError, msg){ssl.post_connection_check("localhost.localdomain")}
}
}
end if OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384
end

def test_ssl_version_tlsv1
ctx_proc = Proc.new do |ctx|
ctx.ssl_version = "TLSv1"
end
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -111,7 +115,7 @@ def test_ssl_version_tlsv1_1
ctx_proc = Proc.new do |ctx|
ctx.ssl_version = "TLSv1_1"
end
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -124,7 +128,7 @@ def test_ssl_version_tlsv1_2
ctx_proc = Proc.new do |ctx|
ctx.ssl_version = "TLSv1_2"
end
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -134,7 +138,7 @@ def test_ssl_version_tlsv1_2
end unless java6? # TLS1_2 is not supported by JDK 6

def test_read_nonblock_would_block
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -158,15 +162,15 @@ def test_read_nonblock_would_block
result = eval "ssl.read_nonblock(5, 'buff', exception: false)"
assert_equal :wait_readable, result
end
result = ssl.sysread_nonblock(5, :exception => false)
result = ssl.send :sysread_nonblock, 5, :exception => false
assert_equal :wait_readable, result

ssl.close
end
end if RUBY_VERSION > '1.9'

def test_connect_nonblock_would_block
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)

@@ -201,7 +205,7 @@ def test_renegotiation_cb
num_handshakes = 0
renegotiation_cb = Proc.new { |ssl| num_handshakes += 1 }
ctx_proc = Proc.new { |ctx| ctx.renegotiation_cb = renegotiation_cb }
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true, {:ctx_proc => ctx_proc}) do |server, port|
start_server0(PORT, OpenSSL::SSL::VERIFY_NONE, true, {:ctx_proc => ctx_proc}) do |server, port|
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -210,4 +214,41 @@ def test_renegotiation_cb
end
end

def test_tlsext_hostname
return unless OpenSSL::SSL::SSLSocket.instance_methods.include?(:hostname)

ctx_proc = Proc.new do |ctx, ssl|
foo_ctx = ctx.dup

ctx.servername_cb = Proc.new do |ssl2, hostname|
case hostname
when 'foo.example.com'
foo_ctx
when 'bar.example.com'
nil
else
raise "unknown hostname #{hostname.inspect}"
end
end
end

server_proc = Proc.new { |ctx, ssl| readwrite_loop(ctx, ssl) }

start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => ctx_proc, :server_proc => server_proc) do |server, port|
2.times do |i|
ctx = OpenSSL::SSL::SSLContext.new
if defined?(OpenSSL::SSL::OP_NO_TICKET)
# disable RFC4507 support
ctx.options = OpenSSL::SSL::OP_NO_TICKET
end
server_connect(port, ctx) { |ssl|
ssl.hostname = (i & 1 == 0) ? 'foo.example.com' : 'bar.example.com'
str = "x" * 100 + "\n"
ssl.puts(str)
assert_equal(str, ssl.gets)
}
end
end
end

end