httpclient-fixcerts 2.8.5
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 +98 -0
- data/bin/httpclient +77 -0
- data/bin/jsonclient +85 -0
- data/lib/hexdump.rb +50 -0
- data/lib/http-access2/cookie.rb +1 -0
- data/lib/http-access2/http.rb +1 -0
- data/lib/http-access2.rb +55 -0
- data/lib/httpclient/auth.rb +924 -0
- data/lib/httpclient/cacert.pem +3952 -0
- data/lib/httpclient/cacert1024.pem +3866 -0
- data/lib/httpclient/connection.rb +88 -0
- data/lib/httpclient/cookie.rb +220 -0
- data/lib/httpclient/http.rb +1082 -0
- data/lib/httpclient/include_client.rb +85 -0
- data/lib/httpclient/jruby_ssl_socket.rb +594 -0
- data/lib/httpclient/session.rb +960 -0
- data/lib/httpclient/ssl_config.rb +433 -0
- data/lib/httpclient/ssl_socket.rb +150 -0
- data/lib/httpclient/timeout.rb +140 -0
- data/lib/httpclient/util.rb +222 -0
- data/lib/httpclient/version.rb +3 -0
- data/lib/httpclient/webagent-cookie.rb +459 -0
- data/lib/httpclient.rb +1332 -0
- data/lib/jsonclient.rb +66 -0
- data/lib/oauthclient.rb +111 -0
- data/sample/async.rb +8 -0
- data/sample/auth.rb +11 -0
- data/sample/cookie.rb +18 -0
- data/sample/dav.rb +103 -0
- data/sample/howto.rb +49 -0
- data/sample/jsonclient.rb +67 -0
- data/sample/oauth_buzz.rb +57 -0
- data/sample/oauth_friendfeed.rb +59 -0
- data/sample/oauth_twitter.rb +61 -0
- data/sample/ssl/0cert.pem +22 -0
- data/sample/ssl/0key.pem +30 -0
- data/sample/ssl/1000cert.pem +19 -0
- data/sample/ssl/1000key.pem +18 -0
- data/sample/ssl/htdocs/index.html +10 -0
- data/sample/ssl/ssl_client.rb +22 -0
- data/sample/ssl/webrick_httpsd.rb +29 -0
- data/sample/stream.rb +21 -0
- data/sample/thread.rb +27 -0
- data/sample/wcat.rb +21 -0
- data/test/ca-chain.pem +44 -0
- data/test/ca.cert +23 -0
- data/test/client-pass.key +18 -0
- data/test/client.cert +19 -0
- data/test/client.key +15 -0
- data/test/helper.rb +131 -0
- data/test/htdigest +1 -0
- data/test/htpasswd +2 -0
- data/test/jruby_ssl_socket/test_pemutils.rb +32 -0
- data/test/runner.rb +2 -0
- data/test/server.cert +19 -0
- data/test/server.key +15 -0
- data/test/sslsvr.rb +65 -0
- data/test/subca.cert +21 -0
- data/test/test_auth.rb +492 -0
- data/test/test_cookie.rb +309 -0
- data/test/test_hexdump.rb +14 -0
- data/test/test_http-access2.rb +508 -0
- data/test/test_httpclient.rb +2145 -0
- data/test/test_include_client.rb +52 -0
- data/test/test_jsonclient.rb +98 -0
- data/test/test_ssl.rb +562 -0
- data/test/test_webagent-cookie.rb +465 -0
- metadata +124 -0
data/test/test_ssl.rb
ADDED
@@ -0,0 +1,562 @@
|
|
1
|
+
require File.expand_path('helper', File.dirname(__FILE__))
|
2
|
+
require 'webrick/https'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
|
6
|
+
class TestSSL < Test::Unit::TestCase
|
7
|
+
include Helper
|
8
|
+
|
9
|
+
DIR = File.dirname(File.expand_path(__FILE__))
|
10
|
+
|
11
|
+
def setup
|
12
|
+
super
|
13
|
+
@serverpid = @client = nil
|
14
|
+
@verify_callback_called = false
|
15
|
+
setup_server
|
16
|
+
setup_client
|
17
|
+
@url = "https://localhost:#{serverport}/hello"
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def path(filename)
|
25
|
+
File.expand_path(filename, DIR)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_proxy_ssl
|
29
|
+
setup_proxyserver
|
30
|
+
escape_noproxy do
|
31
|
+
@client.proxy = proxyurl
|
32
|
+
@client.ssl_config.set_client_cert_file(path('client.cert'), path('client.key'))
|
33
|
+
@client.ssl_config.add_trust_ca(path('ca.cert'))
|
34
|
+
@client.ssl_config.add_trust_ca(path('subca.cert'))
|
35
|
+
@client.debug_dev = str = ""
|
36
|
+
assert_equal(200, @client.get(@url).status)
|
37
|
+
assert(/accept/ =~ @proxyio.string, 'proxy is not used')
|
38
|
+
assert(/Host: localhost:#{serverport}/ =~ str)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_options
|
43
|
+
cfg = @client.ssl_config
|
44
|
+
assert_nil(cfg.client_cert)
|
45
|
+
assert_nil(cfg.client_key)
|
46
|
+
assert_nil(cfg.client_ca)
|
47
|
+
assert_equal(OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT, cfg.verify_mode)
|
48
|
+
assert_nil(cfg.verify_callback)
|
49
|
+
assert_nil(cfg.timeout)
|
50
|
+
expected_options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
|
51
|
+
expected_options &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
52
|
+
expected_options |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
|
53
|
+
assert_equal(expected_options, cfg.options)
|
54
|
+
assert_equal("ALL:!aNULL:!eNULL:!SSLv2", cfg.ciphers)
|
55
|
+
assert_instance_of(OpenSSL::X509::Store, cfg.cert_store)
|
56
|
+
end
|
57
|
+
|
58
|
+
unless defined?(HTTPClient::JRubySSLSocket)
|
59
|
+
# JRubySSLSocket does not support sync mode.
|
60
|
+
def test_sync
|
61
|
+
cfg = @client.ssl_config
|
62
|
+
cfg.set_client_cert_file(path('client.cert'), path('client.key'))
|
63
|
+
cfg.add_trust_ca(path('ca.cert'))
|
64
|
+
cfg.add_trust_ca(path('subca.cert'))
|
65
|
+
assert_equal("hello", @client.get_content(@url))
|
66
|
+
|
67
|
+
@client.socket_sync = false
|
68
|
+
@client.reset_all
|
69
|
+
assert_equal("hello", @client.get_content(@url))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_debug_dev
|
74
|
+
str = @client.debug_dev = ''
|
75
|
+
cfg = @client.ssl_config
|
76
|
+
cfg.client_cert = path("client.cert")
|
77
|
+
cfg.client_key = path("client.key")
|
78
|
+
cfg.add_trust_ca(path('ca.cert'))
|
79
|
+
cfg.add_trust_ca(path('subca.cert'))
|
80
|
+
assert_equal("hello", @client.get_content(@url))
|
81
|
+
assert(str.scan(/^hello$/)[0])
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_verification_without_httpclient
|
85
|
+
raw_cert = "-----BEGIN CERTIFICATE-----\nMIIDKDCCAhCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGDAJKUDES\nMBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxCzAJBgNVBAMMAkNBMB4X\nDTA0MDEzMTAzMTQ1OFoXDTM1MDEyMzAzMTQ1OFowZTELMAkGA1UEBgwCSlAxEjAQ\nBgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMRAwDgYDVQQDDAdleGFtcGxl\nMSIwIAYJKoZIhvcNAQkBDBNleGFtcGxlQGV4YW1wbGUub3JnMIGfMA0GCSqGSIb3\nDQEBAQUAA4GNADCBiQKBgQDRWssrK8Gyr+500hpLjCGR3+AHL8/hEJM5zKi/MgLW\njTkvsgOwbYwXOiNtAbR9y4/ucDq7EY+cMUMHES4uFaPTcOaAV0aZRmk8AgslN1tQ\ngNS6ew7/Luq3DcVeWkX8PYgR9VG0mD1MPfJ6+IFA5d3vKpdBkBgN4l46jjO0/2Xf\newIDAQABo4GPMIGMMAwGA1UdEwEB/wQCMAAwMQYJYIZIAYb4QgENBCQWIlJ1Ynkv\nT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFOFvay0H7lr2\nxUx6waYEV2bVDYQhMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYI\nKwYBBQUHAwQwDQYJKoZIhvcNAQEFBQADggEBABd2dYWqbDIWf5sWFvslezxJv8gI\nw64KCJBuyJAiDuf+oazr3016kMzAlt97KecLZDusGNagPrq02UX7YMoQFsWJBans\ncDtHrkM0al5r6/WGexNMgtYbNTYzt/IwodISGBgZ6dsOuhznwms+IBsTNDAvWeLP\nlt2tOqD8kEmjwMgn0GDRuKjs4EoboA3kMULb1p9akDV9ZESU3eOtpS5/G5J5msLI\n9WXbYBjcjvkLuJH9VsJhb+R58Vl0ViemvAHhPilSl1SPWVunGhv6FcIkdBEi1k9F\ne8BNMmsEjFiANiIRvpdLRbiGBt0KrKTndVfsmoKCvY48oCOvnzxtahFxfs8=\n-----END CERTIFICATE-----"
|
86
|
+
raw_ca_cert = "-----BEGIN CERTIFICATE-----\nMIID0DCCArigAwIBAgIBADANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGDAJKUDES\nMBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxCzAJBgNVBAMMAkNBMB4X\nDTA0MDEzMDAwNDIzMloXDTM2MDEyMjAwNDIzMlowPDELMAkGA1UEBgwCSlAxEjAQ\nBgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMQswCQYDVQQDDAJDQTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANbv0x42BTKFEQOE+KJ2XmiSdZpR\nwjzQLAkPLRnLB98tlzs4xo+y4RyY/rd5TT9UzBJTIhP8CJi5GbS1oXEerQXB3P0d\nL5oSSMwGGyuIzgZe5+vZ1kgzQxMEKMMKlzA73rbMd4Jx3u5+jdbP0EDrPYfXSvLY\nbS04n2aX7zrN3x5KdDrNBfwBio2/qeaaj4+9OxnwRvYP3WOvqdW0h329eMfHw0pi\nJI0drIVdsEqClUV4pebT/F+CPUPkEh/weySgo9wANockkYu5ujw2GbLFcO5LXxxm\ndEfcVr3r6t6zOA4bJwL0W/e6LBcrwiG/qPDFErhwtgTLYf6Er67SzLyA66UCAwEA\nAaOB3DCB2TAPBgNVHRMBAf8EBTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09w\nZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRJ7Xd380KzBV7f\nUSKIQ+O/vKbhDzAOBgNVHQ8BAf8EBAMCAQYwZAYDVR0jBF0wW4AUSe13d/NCswVe\n31EiiEPjv7ym4Q+hQKQ+MDwxCzAJBgNVBAYMAkpQMRIwEAYDVQQKDAlKSU4uR1Iu\nSlAxDDAKBgNVBAsMA1JSUjELMAkGA1UEAwwCQ0GCAQAwDQYJKoZIhvcNAQEFBQAD\nggEBAIu/mfiez5XN5tn2jScgShPgHEFJBR0BTJBZF6xCk0jyqNx/g9HMj2ELCuK+\nr/Y7KFW5c5M3AQ+xWW0ZSc4kvzyTcV7yTVIwj2jZ9ddYMN3nupZFgBK1GB4Y05GY\nMJJFRkSu6d/Ph5ypzBVw2YMT/nsOo5VwMUGLgS7YVjU+u/HNWz80J3oO17mNZllj\nPvORJcnjwlroDnS58KoJ7GDgejv3ESWADvX1OHLE4cRkiQGeLoEU4pxdCxXRqX0U\nPbwIkZN9mXVcrmPHq8MWi4eC/V7hnbZETMHuWhUoiNdOEfsAXr3iP4KjyyRdwc7a\nd/xgcK06UVQRL/HbEYGiQL056mc=\n-----END CERTIFICATE-----"
|
87
|
+
ca_cert = ::OpenSSL::X509::Certificate.new(raw_ca_cert)
|
88
|
+
cert = ::OpenSSL::X509::Certificate.new(raw_cert)
|
89
|
+
store = ::OpenSSL::X509::Store.new
|
90
|
+
store.add_cert(ca_cert)
|
91
|
+
store.time = Time.new(2017, 01, 01)
|
92
|
+
assert(store.verify(cert), "Verify failed: #{store.error_string}, #{store.error}")
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_verification
|
96
|
+
cfg = @client.ssl_config
|
97
|
+
cfg.verify_callback = method(:verify_callback).to_proc
|
98
|
+
begin
|
99
|
+
@verify_callback_called = false
|
100
|
+
@client.get(@url)
|
101
|
+
assert(false)
|
102
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
103
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
104
|
+
assert(@verify_callback_called)
|
105
|
+
end
|
106
|
+
#
|
107
|
+
cfg.client_cert = path("client.cert")
|
108
|
+
cfg.client_key = path("client.key")
|
109
|
+
@verify_callback_called = false
|
110
|
+
begin
|
111
|
+
@client.get(@url)
|
112
|
+
assert(false)
|
113
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
114
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
115
|
+
assert(@verify_callback_called)
|
116
|
+
end
|
117
|
+
#
|
118
|
+
cfg.add_trust_ca(path('ca.cert'))
|
119
|
+
@verify_callback_called = false
|
120
|
+
begin
|
121
|
+
@client.get(@url)
|
122
|
+
assert(false)
|
123
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
124
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
125
|
+
assert(@verify_callback_called)
|
126
|
+
end
|
127
|
+
#
|
128
|
+
cfg.add_trust_ca(path('subca.cert'))
|
129
|
+
@verify_callback_called = false
|
130
|
+
assert_equal("hello", @client.get_content(@url))
|
131
|
+
assert(@verify_callback_called)
|
132
|
+
#
|
133
|
+
if false
|
134
|
+
# JRubySSLSocket does not support depth.
|
135
|
+
# Also on travis environment, verify_depth seems to not work properly.
|
136
|
+
cfg.verify_depth = 1 # 2 required: root-sub
|
137
|
+
@verify_callback_called = false
|
138
|
+
begin
|
139
|
+
@client.get(@url)
|
140
|
+
assert(false, "verify_depth is not supported? #{OpenSSL::OPENSSL_VERSION}")
|
141
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
142
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
143
|
+
assert(@verify_callback_called)
|
144
|
+
end
|
145
|
+
#
|
146
|
+
cfg.verify_depth = 2 # 2 required: root-sub
|
147
|
+
@verify_callback_called = false
|
148
|
+
@client.get(@url)
|
149
|
+
assert(@verify_callback_called)
|
150
|
+
#
|
151
|
+
end
|
152
|
+
cfg.verify_depth = nil
|
153
|
+
cfg.cert_store = OpenSSL::X509::Store.new
|
154
|
+
cfg.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
155
|
+
begin
|
156
|
+
@client.get_content(@url)
|
157
|
+
assert(false)
|
158
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
159
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
160
|
+
end
|
161
|
+
#
|
162
|
+
cfg.verify_mode = nil
|
163
|
+
assert_equal("hello", @client.get_content(@url))
|
164
|
+
cfg.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
165
|
+
assert_equal("hello", @client.get_content(@url))
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_cert_store
|
169
|
+
cfg = @client.ssl_config
|
170
|
+
cfg.cert_store.add_cert(cert('ca.cert'))
|
171
|
+
begin
|
172
|
+
@client.get(@url)
|
173
|
+
assert(false)
|
174
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
175
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
176
|
+
end
|
177
|
+
#
|
178
|
+
cfg.cert_store.add_cert(cert('subca.cert'))
|
179
|
+
assert_equal("hello", @client.get_content(@url))
|
180
|
+
cfg.clear_cert_store
|
181
|
+
begin
|
182
|
+
@client.get(@url)
|
183
|
+
assert(false)
|
184
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
185
|
+
assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
if defined?(HTTPClient::JRubySSLSocket)
|
190
|
+
def test_ciphers
|
191
|
+
cfg = @client.ssl_config
|
192
|
+
cfg.set_client_cert_file(path('client.cert'), path('client-pass.key'), 'pass4key')
|
193
|
+
cfg.add_trust_ca(path('ca.cert'))
|
194
|
+
cfg.add_trust_ca(path('subca.cert'))
|
195
|
+
cfg.timeout = 123
|
196
|
+
assert_equal("hello", @client.get_content(@url))
|
197
|
+
#
|
198
|
+
cfg.ciphers = []
|
199
|
+
begin
|
200
|
+
@client.get(@url)
|
201
|
+
assert(false)
|
202
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
203
|
+
assert_match(/No appropriate protocol/, ssle.message)
|
204
|
+
end
|
205
|
+
#
|
206
|
+
cfg.ciphers = %w(TLS_RSA_WITH_AES_128_CBC_SHA)
|
207
|
+
assert_equal("hello", @client.get_content(@url))
|
208
|
+
#
|
209
|
+
cfg.ciphers = HTTPClient::SSLConfig::CIPHERS_DEFAULT
|
210
|
+
assert_equal("hello", @client.get_content(@url))
|
211
|
+
end
|
212
|
+
|
213
|
+
else
|
214
|
+
|
215
|
+
def test_ciphers
|
216
|
+
cfg = @client.ssl_config
|
217
|
+
cfg.set_client_cert_file(path('client.cert'), path('client-pass.key'), 'pass4key')
|
218
|
+
cfg.add_trust_ca(path('ca.cert'))
|
219
|
+
cfg.add_trust_ca(path('subca.cert'))
|
220
|
+
cfg.timeout = 123
|
221
|
+
assert_equal("hello", @client.get_content(@url))
|
222
|
+
#
|
223
|
+
cfg.ciphers = "!ALL"
|
224
|
+
begin
|
225
|
+
@client.get(@url)
|
226
|
+
assert(false)
|
227
|
+
rescue OpenSSL::SSL::SSLError => ssle
|
228
|
+
assert_match(/no cipher match/, ssle.message)
|
229
|
+
end
|
230
|
+
#
|
231
|
+
cfg.ciphers = "ALL"
|
232
|
+
assert_equal("hello", @client.get_content(@url))
|
233
|
+
#
|
234
|
+
cfg.ciphers = "DEFAULT"
|
235
|
+
assert_equal("hello", @client.get_content(@url))
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_set_default_paths
|
240
|
+
assert_raise(OpenSSL::SSL::SSLError) do
|
241
|
+
@client.get(@url)
|
242
|
+
end
|
243
|
+
escape_env do
|
244
|
+
ENV['SSL_CERT_FILE'] = File.join(DIR, 'ca-chain.pem')
|
245
|
+
@client.ssl_config.set_default_paths
|
246
|
+
@client.get(@url)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_no_sslv3
|
251
|
+
omit('TODO: SSLv3 is not supported in many environments. re-enable when disable TLSv1')
|
252
|
+
teardown_server
|
253
|
+
setup_server_with_ssl_version(:SSLv3)
|
254
|
+
assert_raise(OpenSSL::SSL::SSLError) do
|
255
|
+
@client.ssl_config.verify_mode = nil
|
256
|
+
@client.get("https://localhost:#{serverport}/hello")
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_allow_tlsv1
|
261
|
+
teardown_server
|
262
|
+
setup_server_with_ssl_version(:TLSv1)
|
263
|
+
assert_nothing_raised do
|
264
|
+
@client.ssl_config.verify_mode = nil
|
265
|
+
@client.get("https://localhost:#{serverport}/hello")
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_use_higher_TLS
|
270
|
+
omit('TODO: it does not pass with Java 7 or old openssl')
|
271
|
+
teardown_server
|
272
|
+
setup_server_with_ssl_version('TLSv1_2')
|
273
|
+
assert_nothing_raised do
|
274
|
+
@client.ssl_config.verify_mode = nil
|
275
|
+
@client.get("https://localhost:#{serverport}/hello")
|
276
|
+
# TODO: should check JRubySSLSocket.ssl_socket.getSession.getProtocol
|
277
|
+
# but it's not thread safe. How can I return protocol version to the caller?
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
VERIFY_TEST_CERT_LOCALHOST = OpenSSL::X509::Certificate.new(<<-EOS)
|
282
|
+
-----BEGIN CERTIFICATE-----
|
283
|
+
MIIB9jCCAV+gAwIBAgIJAIH8Gsm4PcNKMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
284
|
+
BAMMCWxvY2FsaG9zdDAeFw0xNjA4MTgxMDI2MDVaFw00NDAxMDMxMDI2MDVaMBQx
|
285
|
+
EjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
|
286
|
+
p7D8q0lcx5EZEV5+zPnQsxrbft5xyhH/MCStbH46DRATGPNSOaLRCG5r8gTKQzpD
|
287
|
+
4swGrQFYe2ienQ+7o4aEHErsXp4O/EmDKeiXWWrMqPr23r3HOBDebuynC/sCwy7N
|
288
|
+
epnX9u1VLB03eo+suj4d86OoOF+o11t9ZP+GA29Rsf8CAwEAAaNQME4wHQYDVR0O
|
289
|
+
BBYEFIxsJuPVvd5KKFcAvHGSeKSsWiUJMB8GA1UdIwQYMBaAFIxsJuPVvd5KKFcA
|
290
|
+
vHGSeKSsWiUJMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAMJaVCrrM
|
291
|
+
SM2I06Vr4BL+jtDFhZh3HmJFEDpwEFQ5Y9hduwdUGRBGCpkuea3fE2FKwWW9gLM1
|
292
|
+
w7rFMzYFtCEqm78dJWIU79MRy0wjO4LgtYfoikgBh6JKWuV5ed/+L3sLyLG0ZTtv
|
293
|
+
lrD7lzDtXgwvj007PxDoYRp3JwYzKRmTbH8=
|
294
|
+
-----END CERTIFICATE-----
|
295
|
+
EOS
|
296
|
+
|
297
|
+
VERIFY_TEST_CERT_FOO_DOMAIN = OpenSSL::X509::Certificate.new(<<-EOS)
|
298
|
+
-----BEGIN CERTIFICATE-----
|
299
|
+
MIIB8jCCAVugAwIBAgIJAL/od7Whx7VTMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
|
300
|
+
BAMMB2Zvby5jb20wHhcNMTYwODE4MTAyMzUyWhcNNDQwMTAzMTAyMzUyWjASMRAw
|
301
|
+
DgYDVQQDDAdmb28uY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnsPyr
|
302
|
+
SVzHkRkRXn7M+dCzGtt+3nHKEf8wJK1sfjoNEBMY81I5otEIbmvyBMpDOkPizAat
|
303
|
+
AVh7aJ6dD7ujhoQcSuxeng78SYMp6JdZasyo+vbevcc4EN5u7KcL+wLDLs16mdf2
|
304
|
+
7VUsHTd6j6y6Ph3zo6g4X6jXW31k/4YDb1Gx/wIDAQABo1AwTjAdBgNVHQ4EFgQU
|
305
|
+
jGwm49W93kooVwC8cZJ4pKxaJQkwHwYDVR0jBBgwFoAUjGwm49W93kooVwC8cZJ4
|
306
|
+
pKxaJQkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQCVKTvfxx+yezuR
|
307
|
+
5WpVKw1E9qabKOYFB5TqdHMHreRubMJTaoZC+YzhcCwtyLlAA9+axKINAiMM8T+z
|
308
|
+
jjfOHQSa2GS2TaaVDJWmXIgsAlEbjd2BEiQF0LZYGJRG9pyq0WbTV+CyFdrghjcO
|
309
|
+
xX/t7OG7NfOG9dhv3J+5SX10S5V5Dg==
|
310
|
+
-----END CERTIFICATE-----
|
311
|
+
EOS
|
312
|
+
|
313
|
+
VERIFY_TEST_CERT_ALT_NAME = OpenSSL::X509::Certificate.new(<<-EOS)
|
314
|
+
-----BEGIN CERTIFICATE-----
|
315
|
+
MIICDDCCAXWgAwIBAgIJAOxXY4nOwxhGMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
|
316
|
+
BAMMCWxvY2FsaG9zdDAeFw0xNjA4MTgxMDM0NTJaFw00NDAxMDMxMDM0NTJaMBQx
|
317
|
+
EjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
|
318
|
+
p7D8q0lcx5EZEV5+zPnQsxrbft5xyhH/MCStbH46DRATGPNSOaLRCG5r8gTKQzpD
|
319
|
+
4swGrQFYe2ienQ+7o4aEHErsXp4O/EmDKeiXWWrMqPr23r3HOBDebuynC/sCwy7N
|
320
|
+
epnX9u1VLB03eo+suj4d86OoOF+o11t9ZP+GA29Rsf8CAwEAAaNmMGQwFAYDVR0R
|
321
|
+
BA0wC4IJKi5mb28uY29tMB0GA1UdDgQWBBSMbCbj1b3eSihXALxxknikrFolCTAf
|
322
|
+
BgNVHSMEGDAWgBSMbCbj1b3eSihXALxxknikrFolCTAMBgNVHRMEBTADAQH/MA0G
|
323
|
+
CSqGSIb3DQEBCwUAA4GBADJlKNFuOnsDIhHGW72HuQw4naN6lM3eZE9JJ+UF/XIF
|
324
|
+
ghGtgqw+00Yy5wMFc1K2Wm4p5NymmDfC/P1FOe34bpxt9/IWm6mEoIWoodC3N4Cm
|
325
|
+
PtnSS1/CRWzVIPGMglTGGDcUc70tfeAWgyTxgcNQd4vTFtnN0f0RDdaXa8kfKMTw
|
326
|
+
-----END CERTIFICATE-----
|
327
|
+
EOS
|
328
|
+
|
329
|
+
VERIFY_TEST_PKEY = OpenSSL::PKey::RSA.new(<<-EOS)
|
330
|
+
-----BEGIN RSA PRIVATE KEY-----
|
331
|
+
MIICXQIBAAKBgQCnsPyrSVzHkRkRXn7M+dCzGtt+3nHKEf8wJK1sfjoNEBMY81I5
|
332
|
+
otEIbmvyBMpDOkPizAatAVh7aJ6dD7ujhoQcSuxeng78SYMp6JdZasyo+vbevcc4
|
333
|
+
EN5u7KcL+wLDLs16mdf27VUsHTd6j6y6Ph3zo6g4X6jXW31k/4YDb1Gx/wIDAQAB
|
334
|
+
AoGAe0RHx+WKtQx8/96VmTl951qzxMPho2etTYd4kAsNwzJwx2N9qu57eBYrdWF+
|
335
|
+
CQMYievucFhP4Y+bINtC1Eb6btz9TCUwjCfeIxfGRoFf3cxVmxlsRJJmN1kSZlu1
|
336
|
+
yYlcMVuP4noeFIMQBRrt5pyLCx2Z9A01NCQT4Y6VoREBIeECQQDWeNhsL6xkrmdB
|
337
|
+
M9+zl+SqHdNKhgKwMdp74+UNnAV9I8GB7bGlOWhc83aqMLgS+JBDFXcmNF/KawTR
|
338
|
+
zcnkod5xAkEAyClFgr3lZQSnwUwoA/AOcyW0+H63taaaXS/g8n3H8ENK6kL4ldUx
|
339
|
+
IgCk2ekbQ5Y3S2WScIGXNxMOza9MlsOvbwJAPUtoPvMZB+U4KVBT/JXKijvf6QqH
|
340
|
+
tidpU8L78XnHr84KPcHa5WeUxgvmvBkUYoebYzC9TrPlNIqFZBi2PJtuYQJBAMda
|
341
|
+
E5j7eJT75fhm2RPS6xFT5MH5sw6AOA3HucrJ63AoFVzsBpl0E9NBwO4ndLgDzF6T
|
342
|
+
cx4Kc4iuunewuB8QFpECQQCfvsHCjIJ/X4kiqeBzxDq2GR/oDgQkOzY+4H9U7Lwl
|
343
|
+
e61RBaxk5OHOA0bLtvJblV6NL72ZEZhX60wAWbrOPhpT
|
344
|
+
-----END RSA PRIVATE KEY-----
|
345
|
+
EOS
|
346
|
+
|
347
|
+
def test_post_connection_check
|
348
|
+
teardown_server
|
349
|
+
setup_server_with_server_cert(nil, VERIFY_TEST_CERT_LOCALHOST, VERIFY_TEST_PKEY)
|
350
|
+
file = Tempfile.new('cert')
|
351
|
+
File.write(file.path, VERIFY_TEST_CERT_LOCALHOST.to_pem)
|
352
|
+
@client.ssl_config.add_trust_ca(file.path)
|
353
|
+
assert_nothing_raised do
|
354
|
+
@client.get("https://localhost:#{serverport}/hello")
|
355
|
+
end
|
356
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
357
|
+
assert_nothing_raised do
|
358
|
+
@client.get("https://localhost:#{serverport}/hello")
|
359
|
+
end
|
360
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
361
|
+
|
362
|
+
teardown_server
|
363
|
+
setup_server_with_server_cert(nil, VERIFY_TEST_CERT_FOO_DOMAIN, VERIFY_TEST_PKEY)
|
364
|
+
File.write(file.path, VERIFY_TEST_CERT_FOO_DOMAIN.to_pem)
|
365
|
+
@client.ssl_config.add_trust_ca(file.path)
|
366
|
+
assert_raises(OpenSSL::SSL::SSLError) do
|
367
|
+
@client.get("https://localhost:#{serverport}/hello")
|
368
|
+
end
|
369
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
370
|
+
assert_nothing_raised do
|
371
|
+
@client.get("https://localhost:#{serverport}/hello")
|
372
|
+
end
|
373
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
374
|
+
|
375
|
+
teardown_server
|
376
|
+
setup_server_with_server_cert(nil, VERIFY_TEST_CERT_ALT_NAME, VERIFY_TEST_PKEY)
|
377
|
+
File.write(file.path, VERIFY_TEST_CERT_ALT_NAME.to_pem)
|
378
|
+
@client.ssl_config.add_trust_ca(file.path)
|
379
|
+
assert_raises(OpenSSL::SSL::SSLError) do
|
380
|
+
@client.get("https://localhost:#{serverport}/hello")
|
381
|
+
end
|
382
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
383
|
+
assert_nothing_raised do
|
384
|
+
@client.get("https://localhost:#{serverport}/hello")
|
385
|
+
end
|
386
|
+
@client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
387
|
+
end
|
388
|
+
|
389
|
+
def test_x509_store_add_cert_prepend
|
390
|
+
store = OpenSSL::X509::Store.new
|
391
|
+
assert_equal(store, store.add_cert(OpenSSL::X509::Certificate.new(VERIFY_TEST_CERT_LOCALHOST)))
|
392
|
+
end
|
393
|
+
|
394
|
+
def test_tcp_keepalive
|
395
|
+
@client.tcp_keepalive = true
|
396
|
+
@client.ssl_config.add_trust_ca(path('ca-chain.pem'))
|
397
|
+
@client.get_content(@url)
|
398
|
+
|
399
|
+
# expecting HTTP keepalive caches the socket
|
400
|
+
session = @client.instance_variable_get(:@session_manager).send(:get_cached_session, HTTPClient::Site.new(URI.parse(@url)))
|
401
|
+
socket = session.instance_variable_get(:@socket).instance_variable_get(:@socket)
|
402
|
+
|
403
|
+
assert_true(session.tcp_keepalive)
|
404
|
+
if RUBY_ENGINE == 'jruby'
|
405
|
+
assert_true(socket.getKeepAlive())
|
406
|
+
else
|
407
|
+
assert_equal(Socket::SO_KEEPALIVE, socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE).optname)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
def test_timeout
|
412
|
+
url = "https://localhost:#{serverport}/"
|
413
|
+
@client.ssl_config.add_trust_ca(path('ca-chain.pem'))
|
414
|
+
assert_equal('sleep', @client.get_content(url + 'sleep?sec=2'))
|
415
|
+
@client.receive_timeout = 1
|
416
|
+
@client.reset_all
|
417
|
+
assert_equal('sleep', @client.get_content(url + 'sleep?sec=0'))
|
418
|
+
|
419
|
+
start = Time.now
|
420
|
+
assert_raise(HTTPClient::ReceiveTimeoutError) do
|
421
|
+
@client.get_content(url + 'sleep?sec=5')
|
422
|
+
end
|
423
|
+
if Time.now - start > 3
|
424
|
+
# before #342 it detected timeout when IO was freed
|
425
|
+
fail 'timeout does not work'
|
426
|
+
end
|
427
|
+
|
428
|
+
@client.receive_timeout = 3
|
429
|
+
@client.reset_all
|
430
|
+
assert_equal('sleep', @client.get_content(url + 'sleep?sec=2'))
|
431
|
+
end
|
432
|
+
|
433
|
+
private
|
434
|
+
|
435
|
+
def cert(filename)
|
436
|
+
OpenSSL::X509::Certificate.new(File.read(File.join(DIR, filename)))
|
437
|
+
end
|
438
|
+
|
439
|
+
def key(filename)
|
440
|
+
OpenSSL::PKey::RSA.new(File.read(File.join(DIR, filename)))
|
441
|
+
end
|
442
|
+
|
443
|
+
def q(str)
|
444
|
+
%Q["#{str}"]
|
445
|
+
end
|
446
|
+
|
447
|
+
def setup_server
|
448
|
+
logger = Logger.new(STDERR)
|
449
|
+
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
|
450
|
+
@server = WEBrick::HTTPServer.new(
|
451
|
+
:BindAddress => "localhost",
|
452
|
+
:Logger => logger,
|
453
|
+
:Port => 0,
|
454
|
+
:AccessLog => [],
|
455
|
+
:DocumentRoot => DIR,
|
456
|
+
:SSLEnable => true,
|
457
|
+
:SSLCACertificateFile => File.join(DIR, 'ca.cert'),
|
458
|
+
:SSLCertificate => cert('server.cert'),
|
459
|
+
:SSLPrivateKey => key('server.key'),
|
460
|
+
:SSLVerifyClient => nil, #OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT|OpenSSL::SSL::VERIFY_PEER,
|
461
|
+
:SSLClientCA => cert('ca.cert'),
|
462
|
+
:SSLCertName => nil
|
463
|
+
)
|
464
|
+
@serverport = @server.config[:Port]
|
465
|
+
[:hello, :sleep].each do |sym|
|
466
|
+
@server.mount(
|
467
|
+
"/#{sym}",
|
468
|
+
WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
|
469
|
+
)
|
470
|
+
end
|
471
|
+
@server_thread = start_server_thread(@server)
|
472
|
+
end
|
473
|
+
|
474
|
+
def setup_server_with_ssl_version(ssl_version)
|
475
|
+
# JRubyOpenSSL does not support "TLSv1_2" as an known version, and some JCE provides TLS v1.2 as "TLSv1.2" not "TLSv1_2"
|
476
|
+
if RUBY_ENGINE == 'jruby' && ['TLSv1_1', 'TLSv1_2'].include?(ssl_version)
|
477
|
+
ssl_version = ssl_version.tr('_', '.')
|
478
|
+
end
|
479
|
+
logger = Logger.new(STDERR)
|
480
|
+
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
|
481
|
+
@server = WEBrick::HTTPServer.new(
|
482
|
+
:BindAddress => "localhost",
|
483
|
+
:Logger => logger,
|
484
|
+
:Port => 0,
|
485
|
+
:AccessLog => [],
|
486
|
+
:DocumentRoot => DIR,
|
487
|
+
:SSLEnable => true,
|
488
|
+
:SSLCACertificateFile => File.join(DIR, 'ca.cert'),
|
489
|
+
:SSLCertificate => cert('server.cert'),
|
490
|
+
:SSLPrivateKey => key('server.key')
|
491
|
+
)
|
492
|
+
@server.ssl_context.ssl_version = ssl_version
|
493
|
+
@serverport = @server.config[:Port]
|
494
|
+
[:hello].each do |sym|
|
495
|
+
@server.mount(
|
496
|
+
"/#{sym}",
|
497
|
+
WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
|
498
|
+
)
|
499
|
+
end
|
500
|
+
@server_thread = start_server_thread(@server)
|
501
|
+
end
|
502
|
+
|
503
|
+
def setup_server_with_server_cert(ca_cert, server_cert, server_key)
|
504
|
+
logger = Logger.new(STDERR)
|
505
|
+
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
|
506
|
+
@server = WEBrick::HTTPServer.new(
|
507
|
+
:BindAddress => "localhost",
|
508
|
+
:Logger => logger,
|
509
|
+
:Port => 0,
|
510
|
+
:AccessLog => [],
|
511
|
+
:DocumentRoot => DIR,
|
512
|
+
:SSLEnable => true,
|
513
|
+
:SSLCACertificateFile => ca_cert,
|
514
|
+
:SSLCertificate => server_cert,
|
515
|
+
:SSLPrivateKey => server_key,
|
516
|
+
:SSLVerifyClient => nil,
|
517
|
+
:SSLClientCA => nil,
|
518
|
+
:SSLCertName => nil
|
519
|
+
)
|
520
|
+
@serverport = @server.config[:Port]
|
521
|
+
[:hello].each do |sym|
|
522
|
+
@server.mount(
|
523
|
+
"/#{sym}",
|
524
|
+
WEBrick::HTTPServlet::ProcHandler.new(method("do_#{sym}").to_proc)
|
525
|
+
)
|
526
|
+
end
|
527
|
+
@server_thread = start_server_thread(@server)
|
528
|
+
end
|
529
|
+
|
530
|
+
def do_hello(req, res)
|
531
|
+
res['content-type'] = 'text/html'
|
532
|
+
res.body = "hello"
|
533
|
+
end
|
534
|
+
|
535
|
+
def do_sleep(req, res)
|
536
|
+
sec = req.query['sec'].to_i
|
537
|
+
sleep sec
|
538
|
+
res['content-type'] = 'text/html'
|
539
|
+
res.body = "sleep"
|
540
|
+
end
|
541
|
+
|
542
|
+
def start_server_thread(server)
|
543
|
+
t = Thread.new {
|
544
|
+
Thread.current.abort_on_exception = true
|
545
|
+
server.start
|
546
|
+
}
|
547
|
+
while server.status != :Running
|
548
|
+
sleep 0.1
|
549
|
+
unless t.alive?
|
550
|
+
t.join
|
551
|
+
raise
|
552
|
+
end
|
553
|
+
end
|
554
|
+
t
|
555
|
+
end
|
556
|
+
|
557
|
+
def verify_callback(ok, cert)
|
558
|
+
@verify_callback_called = true
|
559
|
+
p ["client", ok, cert] if $DEBUG
|
560
|
+
ok
|
561
|
+
end
|
562
|
+
end
|