jruby / jruby-openssl

JRuby's OpenSSL gem
http://www.jruby.org
Other
45 stars 79 forks source link

SSLSocket#alpn_protocol returning empty string #287

Closed HoneyryderChuck closed 4 months ago

HoneyryderChuck commented 9 months ago

When the SSLSocket client sets the alpn protocol parameters, but the server does not negotiate it, returned alpn_protocol is an empty string (instead of nil). This script reproduces it:


require "uri"
require "openssl"
require "logger"
require "webrick/ssl"

class TestServer < WEBrick::HTTPServer

  def initialize
    super(
      :BindAddress => "127.0.0.1",
      :Port => 0,
      :SSLEnable => true,
      :SSLStartImmediately => true,
      :SSLCertName => "/C=JP/O=www.ruby-lang.org/CN=Ruby",
      :SSLCertComment => "bang",
      :AccessLog => $stderr,
      :Logger => Logger.new($stderr)
    )
    mount_proc("/") do |_req, res|
      res.status = 200
      res.body = "hello"
    end
  end

  def origin
    sock = listeners.first
    _, port, ip, _ = sock.addr
    scheme = @config[:SSLEnable] ? URI::HTTPS : URI::HTTP
    scheme.build(host: ip, port: port)
  end
end

def start_test_servlet(servlet_class, *args)
  server = servlet_class.new(*args)
  th = Thread.new { server.start }
  begin
    yield server
  ensure
    if server.respond_to?(:shutdown)
      server.shutdown

      begin
        Timeout.timeout(3) { th.join }
      rescue Timeout::Error
        th.kill
      end
    else
      th.kill
    end
  end
end

start_test_servlet(TestServer) do |server|
  uri = URI(server.origin)
  ctx = OpenSSL::SSL::SSLContext.new
  ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE, alpn_protocols: %w[h2 http/1.1])
  ssl = OpenSSL::SSL::SSLSocket.open(uri.host,  uri.port, context: ctx)
  ssl.connect
  puts "alpn: #{ssl.alpn_protocol.inspect}"
  ssl.close
end
# nil in ruby 3.2. "" in jruby 9.4, jruby-openssl 0.14.1, BC 1.71