httpclient 2.3.0.1 → 2.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +85 -0
- data/bin/httpclient +18 -6
- data/bin/jsonclient +85 -0
- data/lib/http-access2.rb +1 -1
- data/lib/httpclient.rb +262 -88
- data/lib/httpclient/auth.rb +269 -244
- data/lib/httpclient/cacert.pem +3952 -0
- data/lib/httpclient/cacert1024.pem +3866 -0
- data/lib/httpclient/connection.rb +1 -1
- data/lib/httpclient/cookie.rb +161 -514
- data/lib/httpclient/http.rb +57 -21
- data/lib/httpclient/include_client.rb +2 -0
- data/lib/httpclient/jruby_ssl_socket.rb +588 -0
- data/lib/httpclient/session.rb +259 -317
- data/lib/httpclient/ssl_config.rb +141 -188
- data/lib/httpclient/ssl_socket.rb +150 -0
- data/lib/httpclient/timeout.rb +1 -1
- data/lib/httpclient/util.rb +62 -1
- data/lib/httpclient/version.rb +1 -1
- data/lib/httpclient/webagent-cookie.rb +459 -0
- data/lib/jsonclient.rb +63 -0
- data/lib/oauthclient.rb +2 -1
- data/sample/jsonclient.rb +67 -0
- data/sample/oauth_twitter.rb +4 -4
- data/test/{ca-chain.cert → ca-chain.pem} +0 -0
- data/test/client-pass.key +18 -0
- data/test/helper.rb +10 -8
- data/test/jruby_ssl_socket/test_pemutils.rb +32 -0
- data/test/test_auth.rb +175 -4
- data/test/test_cookie.rb +147 -243
- data/test/test_http-access2.rb +17 -16
- data/test/test_httpclient.rb +458 -77
- data/test/test_jsonclient.rb +80 -0
- data/test/test_ssl.rb +341 -17
- data/test/test_webagent-cookie.rb +465 -0
- metadata +57 -55
- data/README.txt +0 -721
- data/lib/httpclient/cacert.p7s +0 -1858
- data/lib/httpclient/cacert_sha1.p7s +0 -1858
- data/sample/oauth_salesforce_10.rb +0 -63
@@ -0,0 +1,80 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
3
|
+
require 'jsonclient'
|
4
|
+
|
5
|
+
|
6
|
+
class TestJSONClient < Test::Unit::TestCase
|
7
|
+
include Helper
|
8
|
+
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
setup_server
|
12
|
+
@client = JSONClient.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_post
|
20
|
+
res = @client.post(serverurl + 'json', {'a' => 1, 'b' => {'c' => 2}})
|
21
|
+
assert_equal(2, res.content['b']['c'])
|
22
|
+
assert_equal('application/json; charset=utf-8', res.content_type)
|
23
|
+
# #previous contains the original response
|
24
|
+
assert_equal(1, JSON.parse(res.previous.content)['a'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_post_with_header
|
28
|
+
res = @client.post(serverurl + 'json', :header => {'X-foo' => 'bar'}, :body => {'a' => 1, 'b' => {'c' => 2}})
|
29
|
+
assert_equal(2, res.content['b']['c'])
|
30
|
+
assert_equal('application/json; charset=utf-8', res.content_type)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_post_with_array_header
|
34
|
+
res = @client.post(serverurl + 'json', :header => [['X-foo', 'bar']], :body => {'a' => 1, 'b' => {'c' => 2}})
|
35
|
+
assert_equal(2, res.content['b']['c'])
|
36
|
+
assert_equal('application/json; charset=utf-8', res.content_type)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_post_non_json_body
|
40
|
+
res = @client.post(serverurl + 'json', 'a=b&c=d')
|
41
|
+
assert_equal('a=b&c=d', res.content)
|
42
|
+
assert_equal('application/x-www-form-urlencoded', res.content_type)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_put
|
46
|
+
res = @client.put(serverurl + 'json', {'a' => 1, 'b' => {'c' => 2}})
|
47
|
+
assert_equal(2, res.content['b']['c'])
|
48
|
+
assert_equal('application/json; charset=utf-8', res.content_type)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_get_not_affected
|
52
|
+
res = @client.get(serverurl + 'json', {'a' => 1, 'b' => {'c' => 2}})
|
53
|
+
assert_equal('', res.content)
|
54
|
+
assert_equal('', res.content_type)
|
55
|
+
end
|
56
|
+
|
57
|
+
class JSONServlet < WEBrick::HTTPServlet::AbstractServlet
|
58
|
+
def get_instance(*arg)
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
def service(req, res)
|
63
|
+
res['content-type'] = req['content-type']
|
64
|
+
res.body = req.body
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def setup_server
|
69
|
+
@server = WEBrick::HTTPServer.new(
|
70
|
+
:BindAddress => "localhost",
|
71
|
+
:Logger => @logger,
|
72
|
+
:Port => 0,
|
73
|
+
:AccessLog => [],
|
74
|
+
:DocumentRoot => File.dirname(File.expand_path(__FILE__))
|
75
|
+
)
|
76
|
+
@serverport = @server.config[:Port]
|
77
|
+
@server.mount('/json', JSONServlet.new(@server))
|
78
|
+
@server_thread = start_server_thread(@server)
|
79
|
+
end
|
80
|
+
end
|
data/test/test_ssl.rb
CHANGED
@@ -4,13 +4,13 @@ require 'webrick/https'
|
|
4
4
|
|
5
5
|
class TestSSL < Test::Unit::TestCase
|
6
6
|
include Helper
|
7
|
+
|
7
8
|
DIR = File.dirname(File.expand_path(__FILE__))
|
8
9
|
|
9
10
|
def setup
|
10
11
|
super
|
11
12
|
@serverpid = @client = nil
|
12
13
|
@verify_callback_called = false
|
13
|
-
@verbose, $VERBOSE = $VERBOSE, nil
|
14
14
|
setup_server
|
15
15
|
setup_client
|
16
16
|
@url = "https://localhost:#{serverport}/hello"
|
@@ -18,13 +18,26 @@ class TestSSL < Test::Unit::TestCase
|
|
18
18
|
|
19
19
|
def teardown
|
20
20
|
super
|
21
|
-
$VERBOSE = @verbose
|
22
21
|
end
|
23
22
|
|
24
23
|
def path(filename)
|
25
24
|
File.expand_path(filename, DIR)
|
26
25
|
end
|
27
26
|
|
27
|
+
def test_proxy_ssl
|
28
|
+
setup_proxyserver
|
29
|
+
escape_noproxy do
|
30
|
+
@client.proxy = proxyurl
|
31
|
+
@client.ssl_config.set_client_cert_file(path('client.cert'), path('client.key'))
|
32
|
+
@client.ssl_config.add_trust_ca(path('ca.cert'))
|
33
|
+
@client.ssl_config.add_trust_ca(path('subca.cert'))
|
34
|
+
@client.debug_dev = str = ""
|
35
|
+
assert_equal(200, @client.get(@url).status)
|
36
|
+
assert(/accept/ =~ @proxyio.string, 'proxy is not used')
|
37
|
+
assert(/Host: localhost:#{serverport}/ =~ str)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
28
41
|
def test_options
|
29
42
|
cfg = @client.ssl_config
|
30
43
|
assert_nil(cfg.client_cert)
|
@@ -33,11 +46,16 @@ class TestSSL < Test::Unit::TestCase
|
|
33
46
|
assert_equal(OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT, cfg.verify_mode)
|
34
47
|
assert_nil(cfg.verify_callback)
|
35
48
|
assert_nil(cfg.timeout)
|
36
|
-
|
49
|
+
expected_options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
|
50
|
+
expected_options &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
51
|
+
expected_options |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
|
52
|
+
assert_equal(expected_options, cfg.options)
|
37
53
|
assert_equal("ALL:!aNULL:!eNULL:!SSLv2", cfg.ciphers)
|
38
54
|
assert_instance_of(OpenSSL::X509::Store, cfg.cert_store)
|
39
55
|
end
|
40
56
|
|
57
|
+
unless defined?(HTTPClient::JRubySSLSocket)
|
58
|
+
# JRubySSLSocket does not support sync mode.
|
41
59
|
def test_sync
|
42
60
|
cfg = @client.ssl_config
|
43
61
|
cfg.set_client_cert_file(path('client.cert'), path('client.key'))
|
@@ -49,18 +67,29 @@ class TestSSL < Test::Unit::TestCase
|
|
49
67
|
@client.reset_all
|
50
68
|
assert_equal("hello", @client.get_content(@url))
|
51
69
|
end
|
70
|
+
end
|
52
71
|
|
53
72
|
def test_debug_dev
|
54
73
|
str = @client.debug_dev = ''
|
55
74
|
cfg = @client.ssl_config
|
56
|
-
cfg.client_cert =
|
57
|
-
cfg.client_key =
|
75
|
+
cfg.client_cert = path("client.cert")
|
76
|
+
cfg.client_key = path("client.key")
|
58
77
|
cfg.add_trust_ca(path('ca.cert'))
|
59
78
|
cfg.add_trust_ca(path('subca.cert'))
|
60
79
|
assert_equal("hello", @client.get_content(@url))
|
61
80
|
assert(str.scan(/^hello$/)[0])
|
62
81
|
end
|
63
82
|
|
83
|
+
def test_verification_without_httpclient
|
84
|
+
raw_cert = "-----BEGIN CERTIFICATE-----\nMIIDOTCCAiGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBCMRMwEQYKCZImiZPyLGQB\nGRYDb3JnMRkwFwYKCZImiZPyLGQBGRYJcnVieS1sYW5nMRAwDgYDVQQDDAdSdWJ5\nIENBMB4XDTE2MDgxMDE3MjEzNFoXDTE3MDgxMDE3MjEzNFowSzETMBEGCgmSJomT\n8ixkARkWA29yZzEZMBcGCgmSJomT8ixkARkWCXJ1YnktbGFuZzEZMBcGA1UEAwwQ\nUnVieSBjZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\nAJCfsSXpSMpmZCVa+ZCM+QDgomnhDlvnrGDq6pasTaIspGTXgws+7r8Dt/cNe6EH\nHJpRH2cGRiO4yPcfcT9eS4X7k8OC4f33wHfACOmLu6LeoNE8ujmSk6L6WzLUI+sE\nnLZbFrXxoAo4XHsm8vEG9C+jEoXZ1p+47wrAGaDwDQTnzlMy4dT9pRQEJP2G/Rry\nUkuZn8SUWmh3/YS78iaSzsNF1cgE1ealHOrPPFDjiCGDaH/LHyUPYlbFSLZ/B7Qx\nLxi5sePLcywWq/EJrmWpgeVTDjtNijsdKv/A3qkY+fm/oD0pzt7XsfJaP9YKNyJO\nQFdxWZeiPcDF+Hwf+IwSr+kCAwEAAaMxMC8wDgYDVR0PAQH/BAQDAgeAMB0GA1Ud\nDgQWBBQNvzYzJyXemGhxbA8NMXLolDnPyjANBgkqhkiG9w0BAQsFAAOCAQEARIJV\noKejGlOTn71QutnNnu07UtTu0IHs6YqjYzzND+m4JXLN+wvYm72AFUG0b1L7dRg0\niK8XjQrlNQNVqP1Mc6tffchy20neOPOHeiO6qTdRU8P2S8D3Uwe+1qhgxjfE+cWc\nwZmWxYK4HA8c58PxWMqrkr2QqXDplG9KWLvOgrtPGiLLZcQSKhvvB63QzItHBDU6\nRayiJY3oPkK/HrIvFlySqFqzWmuyknkciOFywEHQMz/tcSFJ2QFpPj/tBz9VXohH\nZ8KscmfhZrTPBjo+ky1lz/WraWoz4LMiLnkC2ABczWLRSawu+v3Irx1NFJngt05e\npqwtqIUeg7j+JLiTaA==\n-----END CERTIFICATE-----"
|
85
|
+
raw_ca_cert = "-----BEGIN CERTIFICATE-----\nMIIDYjCCAkqgAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMRMwEQYKCZImiZPyLGQB\nGRYDb3JnMRkwFwYKCZImiZPyLGQBGRYJcnVieS1sYW5nMRAwDgYDVQQDDAdSdWJ5\nIENBMB4XDTE2MDgxMDE3MjA1NFoXDTE4MDgxMDE3MjA1NFowQjETMBEGCgmSJomT\n8ixkARkWA29yZzEZMBcGCgmSJomT8ixkARkWCXJ1YnktbGFuZzEQMA4GA1UEAwwH\nUnVieSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALKGwyM3Ejtl\npo7CqaDlS71gDZn3gm6IwWpmRMLJofSI9LCwAbjijSC2HvO0xUWoYW40FbzjnnEi\ngszsWyPwuQIx9t0bhuAyllNIfImmkaQkrikXKBKzia4jPnbc4iXPnfjuThjESFWl\ntfbN6y1B5TjKhD1KelfakUO+iMu8WlIA9NKQZYfJ/F3QSpP5Iqb3KN/jVifFbDV8\nbAl3Ln4rT2kTCKrZZcl1jmWsJv8jBw6+P7hk0/Mu0JeHAITsjbNbpHd8UXpCfbVs\nsNGZrBU4uJdZ2YTG+Y27/t25jFNQwb+TWbvig7rfdX2sjssuxa00BBxarC08tIVj\nZprM37KcNn8CAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\nAQYwHQYDVR0OBBYEFA2/NjMnJd6YaHFsDw0xcuiUOc/KMB8GA1UdIwQYMBYEFA2/\nNjMnJd6YaHFsDw0xcuiUOc/KMA0GCSqGSIb3DQEBCwUAA4IBAQAJSOw49XqvUll0\n3vU9EAO6yUdeZSsQENIfYbRMQgapbnN1vTyrUjPZkGC5hIE1pVdoHtEoUEICxIwy\nr6BKxiSLBDLp+rvIuDdzMkXIWdUVvTZguVRyKtM2gfnpsPLpVnv+stBmAW2SMyxm\nkymhOpkjdv3He+45uorB3tdfBS9VVomDEUJdg38UE1b5eXRQ3D6gG0iCPFzKszXg\nLoAYhGxtjCJaKlbzduMK0YO6aelgW1+XnVIKcA7DJ9egk5d/dFZBPFfwumwr9hTH\nh7/fp3Fr87weI+CkfmFyJZrsEBlXJBVuvPesMVHTh3Whm5kmCdWcBJU0QmSq42ZL\n72U0PXLR\n-----END CERTIFICATE-----"
|
86
|
+
ca_cert = ::OpenSSL::X509::Certificate.new(raw_ca_cert)
|
87
|
+
cert = ::OpenSSL::X509::Certificate.new(raw_cert)
|
88
|
+
store = ::OpenSSL::X509::Store.new
|
89
|
+
store.add_cert(ca_cert)
|
90
|
+
assert(store.verify(cert))
|
91
|
+
end
|
92
|
+
|
64
93
|
def test_verification
|
65
94
|
cfg = @client.ssl_config
|
66
95
|
cfg.verify_callback = method(:verify_callback).to_proc
|
@@ -69,18 +98,18 @@ class TestSSL < Test::Unit::TestCase
|
|
69
98
|
@client.get(@url)
|
70
99
|
assert(false)
|
71
100
|
rescue OpenSSL::SSL::SSLError => ssle
|
72
|
-
assert_match(/certificate verify failed/, ssle.message)
|
101
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
73
102
|
assert(@verify_callback_called)
|
74
103
|
end
|
75
104
|
#
|
76
|
-
cfg.client_cert =
|
77
|
-
cfg.client_key =
|
105
|
+
cfg.client_cert = path("client.cert")
|
106
|
+
cfg.client_key = path("client.key")
|
78
107
|
@verify_callback_called = false
|
79
108
|
begin
|
80
109
|
@client.get(@url)
|
81
110
|
assert(false)
|
82
111
|
rescue OpenSSL::SSL::SSLError => ssle
|
83
|
-
assert_match(/certificate verify failed/, ssle.message)
|
112
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
84
113
|
assert(@verify_callback_called)
|
85
114
|
end
|
86
115
|
#
|
@@ -90,7 +119,7 @@ class TestSSL < Test::Unit::TestCase
|
|
90
119
|
@client.get(@url)
|
91
120
|
assert(false)
|
92
121
|
rescue OpenSSL::SSL::SSLError => ssle
|
93
|
-
assert_match(/certificate verify failed/, ssle.message)
|
122
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
94
123
|
assert(@verify_callback_called)
|
95
124
|
end
|
96
125
|
#
|
@@ -99,16 +128,16 @@ class TestSSL < Test::Unit::TestCase
|
|
99
128
|
assert_equal("hello", @client.get_content(@url))
|
100
129
|
assert(@verify_callback_called)
|
101
130
|
#
|
102
|
-
|
103
|
-
#
|
104
|
-
#
|
131
|
+
if false
|
132
|
+
# JRubySSLSocket does not support depth.
|
133
|
+
# Also on travis environment, verify_depth seems to not work properly.
|
105
134
|
cfg.verify_depth = 1 # 2 required: root-sub
|
106
135
|
@verify_callback_called = false
|
107
136
|
begin
|
108
137
|
@client.get(@url)
|
109
138
|
assert(false, "verify_depth is not supported? #{OpenSSL::OPENSSL_VERSION}")
|
110
139
|
rescue OpenSSL::SSL::SSLError => ssle
|
111
|
-
assert_match(/certificate verify failed/, ssle.message)
|
140
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
112
141
|
assert(@verify_callback_called)
|
113
142
|
end
|
114
143
|
#
|
@@ -125,16 +154,65 @@ end
|
|
125
154
|
@client.get_content(@url)
|
126
155
|
assert(false)
|
127
156
|
rescue OpenSSL::SSL::SSLError => ssle
|
128
|
-
assert_match(/certificate verify failed/, ssle.message)
|
157
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
129
158
|
end
|
130
159
|
#
|
131
160
|
cfg.verify_mode = nil
|
132
161
|
assert_equal("hello", @client.get_content(@url))
|
162
|
+
cfg.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
163
|
+
assert_equal("hello", @client.get_content(@url))
|
133
164
|
end
|
134
165
|
|
166
|
+
def test_cert_store
|
167
|
+
cfg = @client.ssl_config
|
168
|
+
cfg.cert_store.add_cert(cert('ca.cert'))
|
169
|
+
begin
|
170
|
+
@client.get(@url)
|
171
|
+
assert(false)
|
172
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
173
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
174
|
+
end
|
175
|
+
#
|
176
|
+
cfg.cert_store.add_cert(cert('subca.cert'))
|
177
|
+
assert_equal("hello", @client.get_content(@url))
|
178
|
+
cfg.clear_cert_store
|
179
|
+
begin
|
180
|
+
@client.get(@url)
|
181
|
+
assert(false)
|
182
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
183
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
if defined?(HTTPClient::JRubySSLSocket)
|
135
188
|
def test_ciphers
|
136
189
|
cfg = @client.ssl_config
|
137
|
-
cfg.set_client_cert_file(path('client.cert'), path('client.key'))
|
190
|
+
cfg.set_client_cert_file(path('client.cert'), path('client-pass.key'), 'pass4key')
|
191
|
+
cfg.add_trust_ca(path('ca.cert'))
|
192
|
+
cfg.add_trust_ca(path('subca.cert'))
|
193
|
+
cfg.timeout = 123
|
194
|
+
assert_equal("hello", @client.get_content(@url))
|
195
|
+
#
|
196
|
+
cfg.ciphers = []
|
197
|
+
begin
|
198
|
+
@client.get(@url)
|
199
|
+
assert(false)
|
200
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
201
|
+
assert_match(/No appropriate protocol/, ssle.message)
|
202
|
+
end
|
203
|
+
#
|
204
|
+
cfg.ciphers = %w(TLS_RSA_WITH_AES_128_CBC_SHA)
|
205
|
+
assert_equal("hello", @client.get_content(@url))
|
206
|
+
#
|
207
|
+
cfg.ciphers = HTTPClient::SSLConfig::CIPHERS_DEFAULT
|
208
|
+
assert_equal("hello", @client.get_content(@url))
|
209
|
+
end
|
210
|
+
|
211
|
+
else
|
212
|
+
|
213
|
+
def test_ciphers
|
214
|
+
cfg = @client.ssl_config
|
215
|
+
cfg.set_client_cert_file(path('client.cert'), path('client-pass.key'), 'pass4key')
|
138
216
|
cfg.add_trust_ca(path('ca.cert'))
|
139
217
|
cfg.add_trust_ca(path('subca.cert'))
|
140
218
|
cfg.timeout = 123
|
@@ -154,18 +232,201 @@ end
|
|
154
232
|
cfg.ciphers = "DEFAULT"
|
155
233
|
assert_equal("hello", @client.get_content(@url))
|
156
234
|
end
|
235
|
+
end
|
157
236
|
|
158
237
|
def test_set_default_paths
|
159
238
|
assert_raise(OpenSSL::SSL::SSLError) do
|
160
239
|
@client.get(@url)
|
161
240
|
end
|
162
241
|
escape_env do
|
163
|
-
ENV['SSL_CERT_FILE'] = File.join(DIR, 'ca-chain.
|
242
|
+
ENV['SSL_CERT_FILE'] = File.join(DIR, 'ca-chain.pem')
|
164
243
|
@client.ssl_config.set_default_paths
|
165
244
|
@client.get(@url)
|
166
245
|
end
|
167
246
|
end
|
168
247
|
|
248
|
+
def test_no_sslv3
|
249
|
+
teardown_server
|
250
|
+
setup_server_with_ssl_version(:SSLv3)
|
251
|
+
assert_raise(OpenSSL::SSL::SSLError) do
|
252
|
+
@client.ssl_config.verify_mode = nil
|
253
|
+
@client.get("https://localhost:#{serverport}/hello")
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_allow_tlsv1
|
258
|
+
teardown_server
|
259
|
+
setup_server_with_ssl_version(:TLSv1)
|
260
|
+
assert_nothing_raised do
|
261
|
+
@client.ssl_config.verify_mode = nil
|
262
|
+
@client.get("https://localhost:#{serverport}/hello")
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_use_higher_TLS
|
267
|
+
omit('TODO: it does not pass with Java 7 or old openssl ')
|
268
|
+
teardown_server
|
269
|
+
setup_server_with_ssl_version('TLSv1_2')
|
270
|
+
assert_nothing_raised do
|
271
|
+
@client.ssl_config.verify_mode = nil
|
272
|
+
@client.get("https://localhost:#{serverport}/hello")
|
273
|
+
# TODO: should check JRubySSLSocket.ssl_socket.getSession.getProtocol
|
274
|
+
# but it's not thread safe. How can I return protocol version to the caller?
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
VERIFY_TEST_CERT_LOCALHOST = OpenSSL::X509::Certificate.new(<<-EOS)
|
279
|
+
-----BEGIN CERTIFICATE-----
|
280
|
+
MIIB9jCCAV+gAwIBAgIJAIH8Gsm4PcNKMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
281
|
+
BAMMCWxvY2FsaG9zdDAeFw0xNjA4MTgxMDI2MDVaFw00NDAxMDMxMDI2MDVaMBQx
|
282
|
+
EjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
|
283
|
+
p7D8q0lcx5EZEV5+zPnQsxrbft5xyhH/MCStbH46DRATGPNSOaLRCG5r8gTKQzpD
|
284
|
+
4swGrQFYe2ienQ+7o4aEHErsXp4O/EmDKeiXWWrMqPr23r3HOBDebuynC/sCwy7N
|
285
|
+
epnX9u1VLB03eo+suj4d86OoOF+o11t9ZP+GA29Rsf8CAwEAAaNQME4wHQYDVR0O
|
286
|
+
BBYEFIxsJuPVvd5KKFcAvHGSeKSsWiUJMB8GA1UdIwQYMBaAFIxsJuPVvd5KKFcA
|
287
|
+
vHGSeKSsWiUJMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAMJaVCrrM
|
288
|
+
SM2I06Vr4BL+jtDFhZh3HmJFEDpwEFQ5Y9hduwdUGRBGCpkuea3fE2FKwWW9gLM1
|
289
|
+
w7rFMzYFtCEqm78dJWIU79MRy0wjO4LgtYfoikgBh6JKWuV5ed/+L3sLyLG0ZTtv
|
290
|
+
lrD7lzDtXgwvj007PxDoYRp3JwYzKRmTbH8=
|
291
|
+
-----END CERTIFICATE-----
|
292
|
+
EOS
|
293
|
+
|
294
|
+
VERIFY_TEST_CERT_FOO_DOMAIN = OpenSSL::X509::Certificate.new(<<-EOS)
|
295
|
+
-----BEGIN CERTIFICATE-----
|
296
|
+
MIIB8jCCAVugAwIBAgIJAL/od7Whx7VTMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
|
297
|
+
BAMMB2Zvby5jb20wHhcNMTYwODE4MTAyMzUyWhcNNDQwMTAzMTAyMzUyWjASMRAw
|
298
|
+
DgYDVQQDDAdmb28uY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnsPyr
|
299
|
+
SVzHkRkRXn7M+dCzGtt+3nHKEf8wJK1sfjoNEBMY81I5otEIbmvyBMpDOkPizAat
|
300
|
+
AVh7aJ6dD7ujhoQcSuxeng78SYMp6JdZasyo+vbevcc4EN5u7KcL+wLDLs16mdf2
|
301
|
+
7VUsHTd6j6y6Ph3zo6g4X6jXW31k/4YDb1Gx/wIDAQABo1AwTjAdBgNVHQ4EFgQU
|
302
|
+
jGwm49W93kooVwC8cZJ4pKxaJQkwHwYDVR0jBBgwFoAUjGwm49W93kooVwC8cZJ4
|
303
|
+
pKxaJQkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQCVKTvfxx+yezuR
|
304
|
+
5WpVKw1E9qabKOYFB5TqdHMHreRubMJTaoZC+YzhcCwtyLlAA9+axKINAiMM8T+z
|
305
|
+
jjfOHQSa2GS2TaaVDJWmXIgsAlEbjd2BEiQF0LZYGJRG9pyq0WbTV+CyFdrghjcO
|
306
|
+
xX/t7OG7NfOG9dhv3J+5SX10S5V5Dg==
|
307
|
+
-----END CERTIFICATE-----
|
308
|
+
EOS
|
309
|
+
|
310
|
+
VERIFY_TEST_CERT_ALT_NAME = OpenSSL::X509::Certificate.new(<<-EOS)
|
311
|
+
-----BEGIN CERTIFICATE-----
|
312
|
+
MIICDDCCAXWgAwIBAgIJAOxXY4nOwxhGMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
313
|
+
BAMMCWxvY2FsaG9zdDAeFw0xNjA4MTgxMDM0NTJaFw00NDAxMDMxMDM0NTJaMBQx
|
314
|
+
EjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
|
315
|
+
p7D8q0lcx5EZEV5+zPnQsxrbft5xyhH/MCStbH46DRATGPNSOaLRCG5r8gTKQzpD
|
316
|
+
4swGrQFYe2ienQ+7o4aEHErsXp4O/EmDKeiXWWrMqPr23r3HOBDebuynC/sCwy7N
|
317
|
+
epnX9u1VLB03eo+suj4d86OoOF+o11t9ZP+GA29Rsf8CAwEAAaNmMGQwFAYDVR0R
|
318
|
+
BA0wC4IJKi5mb28uY29tMB0GA1UdDgQWBBSMbCbj1b3eSihXALxxknikrFolCTAf
|
319
|
+
BgNVHSMEGDAWgBSMbCbj1b3eSihXALxxknikrFolCTAMBgNVHRMEBTADAQH/MA0G
|
320
|
+
CSqGSIb3DQEBCwUAA4GBADJlKNFuOnsDIhHGW72HuQw4naN6lM3eZE9JJ+UF/XIF
|
321
|
+
ghGtgqw+00Yy5wMFc1K2Wm4p5NymmDfC/P1FOe34bpxt9/IWm6mEoIWoodC3N4Cm
|
322
|
+
PtnSS1/CRWzVIPGMglTGGDcUc70tfeAWgyTxgcNQd4vTFtnN0f0RDdaXa8kfKMTw
|
323
|
+
-----END CERTIFICATE-----
|
324
|
+
EOS
|
325
|
+
|
326
|
+
VERIFY_TEST_PKEY = OpenSSL::PKey::RSA.new(<<-EOS)
|
327
|
+
-----BEGIN RSA PRIVATE KEY-----
|
328
|
+
MIICXQIBAAKBgQCnsPyrSVzHkRkRXn7M+dCzGtt+3nHKEf8wJK1sfjoNEBMY81I5
|
329
|
+
otEIbmvyBMpDOkPizAatAVh7aJ6dD7ujhoQcSuxeng78SYMp6JdZasyo+vbevcc4
|
330
|
+
EN5u7KcL+wLDLs16mdf27VUsHTd6j6y6Ph3zo6g4X6jXW31k/4YDb1Gx/wIDAQAB
|
331
|
+
AoGAe0RHx+WKtQx8/96VmTl951qzxMPho2etTYd4kAsNwzJwx2N9qu57eBYrdWF+
|
332
|
+
CQMYievucFhP4Y+bINtC1Eb6btz9TCUwjCfeIxfGRoFf3cxVmxlsRJJmN1kSZlu1
|
333
|
+
yYlcMVuP4noeFIMQBRrt5pyLCx2Z9A01NCQT4Y6VoREBIeECQQDWeNhsL6xkrmdB
|
334
|
+
M9+zl+SqHdNKhgKwMdp74+UNnAV9I8GB7bGlOWhc83aqMLgS+JBDFXcmNF/KawTR
|
335
|
+
zcnkod5xAkEAyClFgr3lZQSnwUwoA/AOcyW0+H63taaaXS/g8n3H8ENK6kL4ldUx
|
336
|
+
IgCk2ekbQ5Y3S2WScIGXNxMOza9MlsOvbwJAPUtoPvMZB+U4KVBT/JXKijvf6QqH
|
337
|
+
tidpU8L78XnHr84KPcHa5WeUxgvmvBkUYoebYzC9TrPlNIqFZBi2PJtuYQJBAMda
|
338
|
+
E5j7eJT75fhm2RPS6xFT5MH5sw6AOA3HucrJ63AoFVzsBpl0E9NBwO4ndLgDzF6T
|
339
|
+
cx4Kc4iuunewuB8QFpECQQCfvsHCjIJ/X4kiqeBzxDq2GR/oDgQkOzY+4H9U7Lwl
|
340
|
+
e61RBaxk5OHOA0bLtvJblV6NL72ZEZhX60wAWbrOPhpT
|
341
|
+
-----END RSA PRIVATE KEY-----
|
342
|
+
EOS
|
343
|
+
|
344
|
+
def test_post_connection_check
|
345
|
+
teardown_server
|
346
|
+
setup_server_with_server_cert(nil, VERIFY_TEST_CERT_LOCALHOST, VERIFY_TEST_PKEY)
|
347
|
+
file = Tempfile.new('cert')
|
348
|
+
File.write(file.path, VERIFY_TEST_CERT_LOCALHOST.to_pem)
|
349
|
+
@client.ssl_config.add_trust_ca(file.path)
|
350
|
+
assert_nothing_raised do
|
351
|
+
@client.get("https://localhost:#{serverport}/hello")
|
352
|
+
end
|
353
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
354
|
+
assert_nothing_raised do
|
355
|
+
@client.get("https://localhost:#{serverport}/hello")
|
356
|
+
end
|
357
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
358
|
+
|
359
|
+
teardown_server
|
360
|
+
setup_server_with_server_cert(nil, VERIFY_TEST_CERT_FOO_DOMAIN, VERIFY_TEST_PKEY)
|
361
|
+
File.write(file.path, VERIFY_TEST_CERT_FOO_DOMAIN.to_pem)
|
362
|
+
@client.ssl_config.add_trust_ca(file.path)
|
363
|
+
assert_raises(OpenSSL::SSL::SSLError) do
|
364
|
+
@client.get("https://localhost:#{serverport}/hello")
|
365
|
+
end
|
366
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
367
|
+
assert_nothing_raised do
|
368
|
+
@client.get("https://localhost:#{serverport}/hello")
|
369
|
+
end
|
370
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
371
|
+
|
372
|
+
teardown_server
|
373
|
+
setup_server_with_server_cert(nil, VERIFY_TEST_CERT_ALT_NAME, VERIFY_TEST_PKEY)
|
374
|
+
File.write(file.path, VERIFY_TEST_CERT_ALT_NAME.to_pem)
|
375
|
+
@client.ssl_config.add_trust_ca(file.path)
|
376
|
+
assert_raises(OpenSSL::SSL::SSLError) do
|
377
|
+
@client.get("https://localhost:#{serverport}/hello")
|
378
|
+
end
|
379
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
380
|
+
assert_nothing_raised do
|
381
|
+
@client.get("https://localhost:#{serverport}/hello")
|
382
|
+
end
|
383
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
384
|
+
end
|
385
|
+
|
386
|
+
def test_x509_store_add_cert_prepend
|
387
|
+
store = OpenSSL::X509::Store.new
|
388
|
+
assert_equal(store, store.add_cert(OpenSSL::X509::Certificate.new(VERIFY_TEST_CERT_LOCALHOST)))
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_tcp_keepalive
|
392
|
+
@client.tcp_keepalive = true
|
393
|
+
@client.ssl_config.add_trust_ca(path('ca-chain.pem'))
|
394
|
+
@client.get_content(@url)
|
395
|
+
|
396
|
+
# expecting HTTP keepalive caches the socket
|
397
|
+
session = @client.instance_variable_get(:@session_manager).send(:get_cached_session, HTTPClient::Site.new(URI.parse(@url)))
|
398
|
+
socket = session.instance_variable_get(:@socket).instance_variable_get(:@socket)
|
399
|
+
|
400
|
+
assert_true(session.tcp_keepalive)
|
401
|
+
if RUBY_ENGINE == 'jruby'
|
402
|
+
assert_true(socket.getKeepAlive())
|
403
|
+
else
|
404
|
+
assert_equal(Socket::SO_KEEPALIVE, socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE).optname)
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def test_timeout
|
409
|
+
url = "https://localhost:#{serverport}/"
|
410
|
+
@client.ssl_config.add_trust_ca(path('ca-chain.pem'))
|
411
|
+
assert_equal('sleep', @client.get_content(url + 'sleep?sec=2'))
|
412
|
+
@client.receive_timeout = 1
|
413
|
+
@client.reset_all
|
414
|
+
assert_equal('sleep', @client.get_content(url + 'sleep?sec=0'))
|
415
|
+
|
416
|
+
start = Time.now
|
417
|
+
assert_raise(HTTPClient::ReceiveTimeoutError) do
|
418
|
+
@client.get_content(url + 'sleep?sec=5')
|
419
|
+
end
|
420
|
+
if Time.now - start > 3
|
421
|
+
# before #342 it detected timeout when IO was freed
|
422
|
+
fail 'timeout does not work'
|
423
|
+
end
|
424
|
+
|
425
|
+
@client.receive_timeout = 3
|
426
|
+
@client.reset_all
|
427
|
+
assert_equal('sleep', @client.get_content(url + 'sleep?sec=2'))
|
428
|
+
end
|
429
|
+
|
169
430
|
private
|
170
431
|
|
171
432
|
def cert(filename)
|
@@ -198,6 +459,62 @@ private
|
|
198
459
|
:SSLCertName => nil
|
199
460
|
)
|
200
461
|
@serverport = @server.config[:Port]
|
462
|
+
[:hello, :sleep].each do |sym|
|
463
|
+
@server.mount(
|
464
|
+
"/#{sym}",
|
465
|
+
WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
|
466
|
+
)
|
467
|
+
end
|
468
|
+
@server_thread = start_server_thread(@server)
|
469
|
+
end
|
470
|
+
|
471
|
+
def setup_server_with_ssl_version(ssl_version)
|
472
|
+
# JRubyOpenSSL does not support "TLSv1_2" as an known version, and some JCE provides TLS v1.2 as "TLSv1.2" not "TLSv1_2"
|
473
|
+
if RUBY_ENGINE == 'jruby' && ['TLSv1_1', 'TLSv1_2'].include?(ssl_version)
|
474
|
+
ssl_version = ssl_version.tr('_', '.')
|
475
|
+
end
|
476
|
+
logger = Logger.new(STDERR)
|
477
|
+
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
|
478
|
+
@server = WEBrick::HTTPServer.new(
|
479
|
+
:BindAddress => "localhost",
|
480
|
+
:Logger => logger,
|
481
|
+
:Port => 0,
|
482
|
+
:AccessLog => [],
|
483
|
+
:DocumentRoot => DIR,
|
484
|
+
:SSLEnable => true,
|
485
|
+
:SSLCACertificateFile => File.join(DIR, 'ca.cert'),
|
486
|
+
:SSLCertificate => cert('server.cert'),
|
487
|
+
:SSLPrivateKey => key('server.key')
|
488
|
+
)
|
489
|
+
@server.ssl_context.ssl_version = ssl_version
|
490
|
+
@serverport = @server.config[:Port]
|
491
|
+
[:hello].each do |sym|
|
492
|
+
@server.mount(
|
493
|
+
"/#{sym}",
|
494
|
+
WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
|
495
|
+
)
|
496
|
+
end
|
497
|
+
@server_thread = start_server_thread(@server)
|
498
|
+
end
|
499
|
+
|
500
|
+
def setup_server_with_server_cert(ca_cert, server_cert, server_key)
|
501
|
+
logger = Logger.new(STDERR)
|
502
|
+
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
|
503
|
+
@server = WEBrick::HTTPServer.new(
|
504
|
+
:BindAddress => "localhost",
|
505
|
+
:Logger => logger,
|
506
|
+
:Port => 0,
|
507
|
+
:AccessLog => [],
|
508
|
+
:DocumentRoot => DIR,
|
509
|
+
:SSLEnable => true,
|
510
|
+
:SSLCACertificateFile => ca_cert,
|
511
|
+
:SSLCertificate => server_cert,
|
512
|
+
:SSLPrivateKey => server_key,
|
513
|
+
:SSLVerifyClient => nil,
|
514
|
+
:SSLClientCA => nil,
|
515
|
+
:SSLCertName => nil
|
516
|
+
)
|
517
|
+
@serverport = @server.config[:Port]
|
201
518
|
[:hello].each do |sym|
|
202
519
|
@server.mount(
|
203
520
|
"/#{sym}",
|
@@ -212,6 +529,13 @@ private
|
|
212
529
|
res.body = "hello"
|
213
530
|
end
|
214
531
|
|
532
|
+
def do_sleep(req, res)
|
533
|
+
sec = req.query['sec'].to_i
|
534
|
+
sleep sec
|
535
|
+
res['content-type'] = 'text/html'
|
536
|
+
res.body = "sleep"
|
537
|
+
end
|
538
|
+
|
215
539
|
def start_server_thread(server)
|
216
540
|
t = Thread.new {
|
217
541
|
Thread.current.abort_on_exception = true
|