1require "test/unit"
2begin
3  require 'net/https'
4  require 'stringio'
5  require 'timeout'
6  require File.expand_path("../../openssl/utils", File.dirname(__FILE__))
7  require File.expand_path("utils", File.dirname(__FILE__))
8rescue LoadError
9  # should skip this test
10end
11
12class TestNetHTTPS < Test::Unit::TestCase
13  include TestNetHTTPUtils
14
15  subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
16  exts = [
17    ["keyUsage", "keyEncipherment,digitalSignature", true],
18  ]
19  key = OpenSSL::TestUtils::TEST_KEY_RSA1024
20  cert = OpenSSL::TestUtils.issue_cert(
21    subject, key, 1, Time.now, Time.now + 3600, exts,
22    nil, nil, OpenSSL::Digest::SHA1.new
23  )
24
25  CONFIG = {
26    'host' => '127.0.0.1',
27    'port' => 0,
28    'proxy_host' => nil,
29    'proxy_port' => nil,
30    'ssl_enable' => true,
31    'ssl_certificate' => cert,
32    'ssl_private_key' => key,
33  }
34
35  def test_get
36    http = Net::HTTP.new("localhost", config("port"))
37    http.use_ssl = true
38    http.verify_callback = Proc.new do |preverify_ok, store_ctx|
39      store_ctx.current_cert.to_der == config('ssl_certificate').to_der
40    end
41    http.request_get("/") {|res|
42      assert_equal($test_net_http_data, res.body)
43    }
44  rescue SystemCallError
45    skip $!
46  end
47
48  def test_post
49    http = Net::HTTP.new("localhost", config("port"))
50    http.use_ssl = true
51    http.verify_callback = Proc.new do |preverify_ok, store_ctx|
52      store_ctx.current_cert.to_der == config('ssl_certificate').to_der
53    end
54    data = config('ssl_private_key').to_der
55    http.request_post("/", data) {|res|
56      assert_equal(data, res.body)
57    }
58  rescue SystemCallError
59    skip $!
60  end
61
62  def test_session_reuse
63    http = Net::HTTP.new("localhost", config("port"))
64    http.use_ssl = true
65    http.verify_callback = Proc.new do |preverify_ok, store_ctx|
66      store_ctx.current_cert.to_der == config('ssl_certificate').to_der
67    end
68
69    http.start
70    http.get("/")
71    http.finish
72
73    http.start
74    http.get("/")
75    http.finish # three times due to possible bug in OpenSSL 0.9.8
76
77    http.start
78    http.get("/")
79
80    socket = http.instance_variable_get(:@socket).io
81
82    assert socket.session_reused?
83  rescue SystemCallError
84    skip $!
85  end
86
87  if ENV["RUBY_OPENSSL_TEST_ALL"]
88    def test_verify
89      http = Net::HTTP.new("ssl.netlab.jp", 443)
90      http.use_ssl = true
91      assert(
92        (http.request_head("/"){|res| } rescue false),
93        "The system may not have default CA certificate store."
94      )
95    end
96  end
97
98  def test_verify_none
99    http = Net::HTTP.new("localhost", config("port"))
100    http.use_ssl = true
101    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
102    http.request_get("/") {|res|
103      assert_equal($test_net_http_data, res.body)
104    }
105  rescue SystemCallError
106    skip $!
107  end
108
109  def test_certificate_verify_failure
110    http = Net::HTTP.new("localhost", config("port"))
111    http.use_ssl = true
112    ex = assert_raise(OpenSSL::SSL::SSLError){
113      begin
114        http.request_get("/") {|res| }
115      rescue SystemCallError
116        skip $!
117      end
118    }
119    assert_match(/certificate verify failed/, ex.message)
120  end
121
122  def test_identity_verify_failure
123    http = Net::HTTP.new("127.0.0.1", config("port"))
124    http.use_ssl = true
125    http.verify_callback = Proc.new do |preverify_ok, store_ctx|
126      store_ctx.current_cert.to_der == config('ssl_certificate').to_der
127    end
128    ex = assert_raise(OpenSSL::SSL::SSLError){
129      http.request_get("/") {|res| }
130    }
131    assert_match(/hostname \"127.0.0.1\" does not match/, ex.message)
132  end
133
134  def test_timeout_during_SSL_handshake
135    bug4246 = "expected the SSL connection to have timed out but have not. [ruby-core:34203]"
136
137    # listen for connections... but deliberately do not complete SSL handshake
138    TCPServer.open('localhost', 0) {|server|
139      port = server.addr[1]
140
141      conn = Net::HTTP.new('localhost', port)
142      conn.use_ssl = true
143      conn.read_timeout = 0.01
144      conn.open_timeout = 0.01
145
146      th = Thread.new do
147        assert_raise(Net::OpenTimeout) {
148          conn.get('/')
149        }
150      end
151      assert th.join(10), bug4246
152    }
153  end
154end if defined?(OpenSSL)
155