jruby-openssl
jruby-openssl copied to clipboard
1/n-1 record splitting BEAST mitigation not implemented in JRuby, is in MRI
To reproduce, I installed the mechanize gem, then hacked Net::HTTP to use :TLSv1, and then visited the site https://www.howsmyssl.com/, and then copy and pasted the body into a file and viewed it with my browser. On MRI 2.3.0, the site reports that the 1/n-1 record splitting BEAST mitigation is implemented, on JRuby it says its not. (It also reports unsafe cipher suites for both MRI and JRuby, but perhaps those needed for backwards compatibility?)
Oh and I'm using JRuby 9.1.2.0 with Java 7 on a Mac.
Here's the code to paste into irb to reproduce:
require 'mechanize'
module Net
class HTTP
def connect
if proxy? then
conn_address = proxy_address
conn_port = proxy_port
else
conn_address = address
conn_port = port
end
D "opening connection to #{conn_address}:#{conn_port}..."
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
begin
TCPSocket.open(conn_address, conn_port, @local_host, @local_port)
rescue => e
raise e, "Failed to open TCP connection to " +
"#{conn_address}:#{conn_port} (#{e.message})"
end
}
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
D "opened"
if use_ssl?
ssl_parameters = Hash.new
iv_list = instance_variables
SSL_IVNAMES.each_with_index do |ivname, i|
if iv_list.include?(ivname) and
value = instance_variable_get(ivname)
ssl_parameters[SSL_ATTRIBUTES[i]] = value if value
end
end
@ssl_context = OpenSSL::SSL::SSLContext.new
@ssl_context.set_params(ssl_parameters)
############################# hack to force :TLSv1 ################
@ssl_context.ssl_version = :TLSv1
####################################################################
D "starting SSL for #{conn_address}:#{conn_port}..."
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
s.sync_close = true
D "SSL established"
end
@socket = BufferedIO.new(s)
@socket.read_timeout = @read_timeout
@socket.continue_timeout = @continue_timeout
@socket.debug_output = @debug_output
if use_ssl?
begin
if proxy?
buf = "CONNECT #{@address}:#{@port} HTTP/#{HTTPVersion}\r\n"
buf << "Host: #{@address}:#{@port}\r\n"
if proxy_user
credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
credential.delete!("\r\n")
buf << "Proxy-Authorization: Basic #{credential}\r\n"
end
buf << "\r\n"
@socket.write(buf)
HTTPResponse.read_new(@socket).value
end
# Server Name Indication (SNI) RFC 3546
s.hostname = @address if s.respond_to? :hostname=
if @ssl_session and
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
s.session = @ssl_session if @ssl_session
end
if timeout = @open_timeout
while true
raise Net::OpenTimeout if timeout <= 0
start = Process.clock_gettime Process::CLOCK_MONOTONIC
# to_io is required because SSLSocket doesn't have wait_readable yet
case s.connect_nonblock(exception: false)
when :wait_readable; s.to_io.wait_readable(timeout)
when :wait_writable; s.to_io.wait_writable(timeout)
else; break
end
timeout -= Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
end
else
s.connect
end
if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
s.post_connection_check(@address)
end
# OpenSSL::SSL::Session somehow works but SSLSocket#session= does nothing with JRuby-OpenSSL
#@ssl_session = s.session
rescue => exception
D "Conn close because of connect error #{exception}"
@socket.close if @socket and not @socket.closed?
raise exception
end
end
on_connect
end
end
end
puts Mechanize.new.get("https://www.howsmyssl.com/").body