Project

General

Profile

Feature #13729 ยป webrick_sni_support_fix.patch

Tietew (Toru Iwase), 07/14/2017 05:43 AM

View differences:

lib/webrick/https.rb
131 131
      server = lookup_server(req)
132 132
      server ? server.ssl_context : nil
133 133
    end
134

  
135
    # :stopdoc:
136

  
137
    ##
138
    # Check whether +server+ is also SSL server.
139
    # Also +server+'s SSL context will be created.
140

  
141
    alias orig_virtual_host virtual_host
142

  
143
    def virtual_host(server)
144
      if @config[:SSLEnable] && !server.ssl_context
145
        raise ArgumentError, "virtual host must set SSLEnable to true"
146
      end
147
      orig_virtual_host(server)
148
    end
149

  
150
    # :startdoc:
134 151
  end
135 152
end
lib/webrick/ssl.rb
147 147
    # SSL context for the server when run in SSL mode
148 148

  
149 149
    def ssl_context # :nodoc:
150
      @ssl_context ||= nil
150
      @ssl_context ||= begin
151
        if @config[:SSLEnable]
152
          ssl_context = setup_ssl_context(@config)
153
          @logger.info("\n" + @config[:SSLCertificate].to_text)
154
          ssl_context
155
        end
156
      end
151 157
    end
152 158

  
153 159
    undef listen
......
158 164
    def listen(address, port) # :nodoc:
159 165
      listeners = Utils::create_listeners(address, port)
160 166
      if @config[:SSLEnable]
161
        unless ssl_context
162
          @ssl_context = setup_ssl_context(@config)
163
          @logger.info("\n" + @config[:SSLCertificate].to_text)
164
        end
165 167
        listeners.collect!{|svr|
166 168
          ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
167 169
          ssvr.start_immediately = @config[:SSLStartImmediately]
test/webrick/test_https.rb
28 28
    super
29 29
  end
30 30

  
31
  def https_get(addr, port, hostname, path)
31
  def https_get(addr, port, hostname, path, verifyname = nil)
32
    subject = nil
32 33
    http = HTTPSNITest.new(addr, port)
33 34
    http.use_ssl = true
34 35
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
36
    http.verify_callback = proc { |x, store| subject = store.chain[0].subject.to_s; x }
35 37
    http.sni_hostname = hostname
36 38
    req = Net::HTTP::Get.new(path)
37 39
    req["Host"] = "#{hostname}:#{port}"
38
    http.request(req).body
40
    response = http.start { http.request(req).body }
41
    assert_equal("/CN=#{verifyname || hostname}", subject)
42
    response
39 43
  end
40 44

  
41 45
  def test_sni
42 46
    config = {
43 47
      :ServerName => "localhost",
44 48
      :SSLEnable => true,
45
      :SSLCertName => "/CN=locahost",
49
      :SSLCertName => "/CN=localhost",
46 50
    }
47 51
    TestWEBrick.start_httpserver(config){|server, addr, port, log|
48 52
      server.mount_proc("/") {|req, res| res.body = "master" }
49 53

  
50
      vhost_config1 = {
51
        :ServerName => "vhost1",
52
        :Port => port,
53
        :DoNotListen => true,
54
        :Logger => NoLog,
55
        :AccessLog => [],
56
        :SSLEnable => true,
57
        :SSLCertName => "/CN=vhost1",
58
      }
59
      vhost1 = WEBrick::HTTPServer.new(vhost_config1)
60
      vhost1.mount_proc("/") {|req, res| res.body = "vhost1" }
61
      server.virtual_host(vhost1)
54
      # catch stderr in create_self_signed_cert
55
      stderr_buffer = StringIO.new
56
      old_stderr, $stderr = $stderr, stderr_buffer
62 57

  
63
      vhost_config2 = {
64
        :ServerName => "vhost2",
65
        :ServerAlias => ["vhost2alias"],
66
        :Port => port,
67
        :DoNotListen => true,
68
        :Logger => NoLog,
69
        :AccessLog => [],
70
        :SSLEnable => true,
71
        :SSLCertName => "/CN=vhost2",
72
      }
73
      vhost2 = WEBrick::HTTPServer.new(vhost_config2)
74
      vhost2.mount_proc("/") {|req, res| res.body = "vhost2" }
75
      server.virtual_host(vhost2)
58
      begin
59
        vhost_config1 = {
60
          :ServerName => "vhost1",
61
          :Port => port,
62
          :DoNotListen => true,
63
          :Logger => NoLog,
64
          :AccessLog => [],
65
          :SSLEnable => true,
66
          :SSLCertName => "/CN=vhost1",
67
        }
68
        vhost1 = WEBrick::HTTPServer.new(vhost_config1)
69
        vhost1.mount_proc("/") {|req, res| res.body = "vhost1" }
70
        server.virtual_host(vhost1)
76 71

  
72
        vhost_config2 = {
73
          :ServerName => "vhost2",
74
          :ServerAlias => ["vhost2alias"],
75
          :Port => port,
76
          :DoNotListen => true,
77
          :Logger => NoLog,
78
          :AccessLog => [],
79
          :SSLEnable => true,
80
          :SSLCertName => "/CN=vhost2",
81
        }
82
        vhost2 = WEBrick::HTTPServer.new(vhost_config2)
83
        vhost2.mount_proc("/") {|req, res| res.body = "vhost2" }
84
        server.virtual_host(vhost2)
85
      ensure
86
        # restore stderr
87
        $stderr = old_stderr
88
      end
89

  
90
      assert_match(/\A([.+*]+\n)+\z/, stderr_buffer.string)
77 91
      assert_equal("master", https_get(addr, port, "localhost", "/localhost"))
78
      assert_equal("master", https_get(addr, port, "unknown", "/unknown"))
92
      assert_equal("master", https_get(addr, port, "unknown", "/unknown", "localhost"))
79 93
      assert_equal("vhost1", https_get(addr, port, "vhost1", "/vhost1"))
80 94
      assert_equal("vhost2", https_get(addr, port, "vhost2", "/vhost2"))
81
      assert_equal("vhost2", https_get(addr, port, "vhost2alias", "/vhost2alias"))
95
      assert_equal("vhost2", https_get(addr, port, "vhost2alias", "/vhost2alias", "vhost2"))
96
    }
97
  end
98

  
99
  def test_check_ssl_virtual
100
    config = {
101
      :ServerName => "localhost",
102
      :SSLEnable => true,
103
      :SSLCertName => "/CN=localhost",
104
    }
105
    TestWEBrick.start_httpserver(config){|server, addr, port, log|
106
      assert_raise ArgumentError do
107
        vhost = WEBrick::HTTPServer.new({:DoNotListen => true, :Logger => NoLog})
108
        server.virtual_host(vhost)
109
      end
82 110
    }
83 111
  end
84 112
end