httpclient 2.6.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 +4 -4
- data/README.md +1 -1
- data/bin/httpclient +7 -1
- data/lib/http-access2.rb +1 -1
- data/lib/httpclient/auth.rb +3 -3
- data/lib/httpclient/cacert.pem +3952 -0
- data/lib/httpclient/connection.rb +1 -1
- data/lib/httpclient/cookie.rb +10 -10
- data/lib/httpclient/http.rb +9 -4
- data/lib/httpclient/jruby_ssl_socket.rb +588 -0
- data/lib/httpclient/session.rb +199 -262
- data/lib/httpclient/ssl_config.rb +123 -114
- data/lib/httpclient/ssl_socket.rb +150 -0
- data/lib/httpclient/timeout.rb +1 -1
- data/lib/httpclient/util.rb +33 -1
- data/lib/httpclient/version.rb +1 -1
- data/lib/httpclient/webagent-cookie.rb +2 -2
- data/lib/httpclient.rb +72 -20
- data/lib/oauthclient.rb +2 -1
- data/test/helper.rb +7 -5
- data/test/jruby_ssl_socket/test_pemutils.rb +32 -0
- data/test/test_auth.rb +28 -9
- data/test/test_cookie.rb +2 -2
- data/test/test_http-access2.rb +2 -0
- data/test/test_httpclient.rb +143 -23
- data/test/test_ssl.rb +295 -17
- data/test/test_webagent-cookie.rb +2 -2
- metadata +14 -10
- /data/lib/httpclient/{cacert.p7s → cacert1024.pem} +0 -0
- /data/test/{ca-chain.cert → ca-chain.pem} +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
# HTTPClient - HTTP client library.
|
2
|
-
# Copyright (C) 2000-
|
2
|
+
# Copyright (C) 2000-2015 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
3
3
|
#
|
4
4
|
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
5
5
|
# redistribute it and/or modify it under the same terms of Ruby's license;
|
@@ -20,70 +20,134 @@ class HTTPClient
|
|
20
20
|
#
|
21
21
|
# == Trust Anchor Control
|
22
22
|
#
|
23
|
-
# SSLConfig loads 'httpclient/cacert.
|
23
|
+
# SSLConfig loads 'httpclient/cacert.pem' as a trust anchor
|
24
24
|
# (trusted certificate(s)) with add_trust_ca in initialization time.
|
25
25
|
# This means that HTTPClient instance trusts some CA certificates by default,
|
26
|
-
# like Web browsers. 'httpclient/cacert.
|
27
|
-
# included in released package.
|
26
|
+
# like Web browsers. 'httpclient/cacert.pem' is downloaded from curl web
|
27
|
+
# site by the author and included in released package.
|
28
28
|
#
|
29
|
-
#
|
30
|
-
#
|
29
|
+
# On JRuby, HTTPClient uses Java runtime's trusted CA certificates, not
|
30
|
+
# cacert.pem by default. You can load cacert.pem by calling
|
31
|
+
# SSLConfig#load_trust_ca manually like:
|
32
|
+
#
|
33
|
+
# HTTPClient.new { self.ssl_config.load_trust_ca }.get("https://...")
|
31
34
|
#
|
32
35
|
# You may want to change trust anchor by yourself. Call clear_cert_store
|
33
36
|
# then add_trust_ca for that purpose.
|
34
37
|
class SSLConfig
|
35
|
-
include
|
38
|
+
include HTTPClient::Util
|
39
|
+
if SSLEnabled
|
40
|
+
include OpenSSL
|
41
|
+
|
42
|
+
module ::OpenSSL
|
43
|
+
module X509
|
44
|
+
class Store
|
45
|
+
attr_reader :_httpclient_cert_store_items
|
46
|
+
|
47
|
+
# TODO: use prepend instead when we drop JRuby + 1.9.x support
|
48
|
+
wrapped = {}
|
49
|
+
|
50
|
+
wrapped[:initialize] = instance_method(:initialize)
|
51
|
+
define_method(:initialize) do |*args|
|
52
|
+
wrapped[:initialize].bind(self).call(*args)
|
53
|
+
@_httpclient_cert_store_items = [ENV['SSL_CERT_FILE'] || :default]
|
54
|
+
end
|
55
|
+
|
56
|
+
[:add_cert, :add_file, :add_path].each do |m|
|
57
|
+
wrapped[m] = instance_method(m)
|
58
|
+
define_method(m) do |cert|
|
59
|
+
res = wrapped[m].bind(self).call(cert)
|
60
|
+
@_httpclient_cert_store_items << cert
|
61
|
+
res
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class << self
|
70
|
+
private
|
71
|
+
def attr_config(symbol)
|
72
|
+
name = symbol.to_s
|
73
|
+
ivar_name = "@#{name}"
|
74
|
+
define_method(name) {
|
75
|
+
instance_variable_get(ivar_name)
|
76
|
+
}
|
77
|
+
define_method("#{name}=") { |rhs|
|
78
|
+
if instance_variable_get(ivar_name) != rhs
|
79
|
+
instance_variable_set(ivar_name, rhs)
|
80
|
+
change_notify
|
81
|
+
end
|
82
|
+
}
|
83
|
+
symbol
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
CIPHERS_DEFAULT = "ALL:!aNULL:!eNULL:!SSLv2" # OpenSSL >1.0.0 default
|
36
89
|
|
37
90
|
# Which TLS protocol version (also called method) will be used. Defaults
|
38
|
-
# to :auto which means that OpenSSL decides (In my tests this resulted
|
91
|
+
# to :auto which means that OpenSSL decides (In my tests this resulted
|
39
92
|
# with always the highest available protocol being used).
|
40
93
|
# String name of OpenSSL's SSL version method name: TLSv1_2, TLSv1_1, TLSv1,
|
41
94
|
# SSLv2, SSLv23, SSLv3 or :auto (and nil) to allow version negotiation (default).
|
42
95
|
# See {OpenSSL::SSL::SSLContext::METHODS} for a list of available versions
|
43
96
|
# in your specific Ruby environment.
|
44
|
-
|
45
|
-
# OpenSSL::X509::Certificate:: certificate for SSL client
|
46
|
-
# nil by default. (no client
|
47
|
-
|
97
|
+
attr_config :ssl_version
|
98
|
+
# OpenSSL::X509::Certificate:: certificate for SSL client authentication.
|
99
|
+
# nil by default. (no client authentication)
|
100
|
+
attr_config :client_cert
|
48
101
|
# OpenSSL::PKey::PKey:: private key for SSL client authentication.
|
49
|
-
# nil by default. (no client
|
50
|
-
|
102
|
+
# nil by default. (no client authentication)
|
103
|
+
attr_config :client_key
|
104
|
+
# OpenSSL::PKey::PKey:: private key pass phrase for client_key.
|
105
|
+
# nil by default. (no pass phrase)
|
106
|
+
attr_config :client_key_pass
|
51
107
|
|
52
108
|
# A number which represents OpenSSL's verify mode. Default value is
|
53
109
|
# OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT.
|
54
|
-
|
110
|
+
attr_config :verify_mode
|
55
111
|
# A number of verify depth. Certification path which length is longer than
|
56
112
|
# this depth is not allowed.
|
57
|
-
|
113
|
+
# CAUTION: this is OpenSSL specific option and ignored on JRuby.
|
114
|
+
attr_config :verify_depth
|
58
115
|
# A callback handler for custom certificate verification. nil by default.
|
59
116
|
# If the handler is set, handler.call is invoked just after general
|
60
117
|
# OpenSSL's verification. handler.call is invoked with 2 arguments,
|
61
118
|
# ok and ctx; ok is a result of general OpenSSL's verification. ctx is a
|
62
119
|
# OpenSSL::X509::StoreContext.
|
63
|
-
|
120
|
+
attr_config :verify_callback
|
64
121
|
# SSL timeout in sec. nil by default.
|
65
|
-
|
122
|
+
attr_config :timeout
|
66
123
|
# A number of OpenSSL's SSL options. Default value is
|
67
124
|
# OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2
|
68
|
-
|
125
|
+
# CAUTION: this is OpenSSL specific option and ignored on JRuby.
|
126
|
+
# Use ssl_version to specify the TLS version you want to use.
|
127
|
+
attr_config :options
|
69
128
|
# A String of OpenSSL's cipher configuration. Default value is
|
70
129
|
# ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH
|
71
130
|
# See ciphers(1) man in OpenSSL for more detail.
|
72
|
-
|
131
|
+
attr_config :ciphers
|
73
132
|
|
74
133
|
# OpenSSL::X509::X509::Store used for verification. You can reset the
|
75
134
|
# store with clear_cert_store and set the new store with cert_store=.
|
76
135
|
attr_reader :cert_store # don't use if you don't know what it is.
|
77
136
|
|
78
137
|
# For server side configuration. Ignore this.
|
79
|
-
|
138
|
+
attr_config :client_ca # :nodoc:
|
139
|
+
|
140
|
+
# These array keeps original files/dirs that was added to @cert_store
|
141
|
+
def cert_store_items; @cert_store._httpclient_cert_store_items; end
|
142
|
+
attr_reader :cert_store_crl_items
|
80
143
|
|
81
144
|
# Creates a SSLConfig.
|
82
145
|
def initialize(client)
|
83
146
|
return unless SSLEnabled
|
84
147
|
@client = client
|
85
148
|
@cert_store = X509::Store.new
|
86
|
-
@
|
149
|
+
@cert_store_crl_items = []
|
150
|
+
@client_cert = @client_key = @client_key_pass = @client_ca = nil
|
87
151
|
@verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
88
152
|
@verify_depth = nil
|
89
153
|
@verify_callback = nil
|
@@ -97,47 +161,22 @@ class HTTPClient
|
|
97
161
|
@options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
|
98
162
|
@options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
|
99
163
|
# OpenSSL 0.9.8 default: "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH"
|
100
|
-
@ciphers =
|
164
|
+
@ciphers = CIPHERS_DEFAULT
|
101
165
|
@cacerts_loaded = false
|
102
166
|
end
|
103
167
|
|
104
|
-
# Sets SSL version method String. Possible values: "SSLv2" for SSL2,
|
105
|
-
# "SSLv3" for SSL3 and TLS1.x, "SSLv23" for SSL3 with fallback to SSL2.
|
106
|
-
def ssl_version=(ssl_version)
|
107
|
-
@ssl_version = ssl_version
|
108
|
-
change_notify
|
109
|
-
end
|
110
|
-
|
111
|
-
# Sets certificate (OpenSSL::X509::Certificate) for SSL client
|
112
|
-
# authentication.
|
113
|
-
# client_key and client_cert must be a pair.
|
114
|
-
#
|
115
|
-
# Calling this method resets all existing sessions.
|
116
|
-
def client_cert=(client_cert)
|
117
|
-
@client_cert = client_cert
|
118
|
-
change_notify
|
119
|
-
end
|
120
|
-
|
121
|
-
# Sets private key (OpenSSL::PKey::PKey) for SSL client authentication.
|
122
|
-
# client_key and client_cert must be a pair.
|
123
|
-
#
|
124
|
-
# Calling this method resets all existing sessions.
|
125
|
-
def client_key=(client_key)
|
126
|
-
@client_key = client_key
|
127
|
-
change_notify
|
128
|
-
end
|
129
|
-
|
130
168
|
# Sets certificate and private key for SSL client authentication.
|
131
169
|
# cert_file:: must be a filename of PEM/DER formatted file.
|
132
170
|
# key_file:: must be a filename of PEM/DER formatted file. Key must be an
|
133
171
|
# RSA key. If you want to use other PKey algorithm,
|
134
172
|
# use client_key=.
|
135
173
|
#
|
136
|
-
# Calling this method resets all existing sessions.
|
174
|
+
# Calling this method resets all existing sessions if value is changed.
|
137
175
|
def set_client_cert_file(cert_file, key_file, pass = nil)
|
138
|
-
@client_cert
|
139
|
-
|
140
|
-
|
176
|
+
if (@client_cert != cert_file) || (@client_key != key_file) || (@client_key_pass != pass)
|
177
|
+
@client_cert, @client_key, @client_key_pass = cert_file, key_file, pass
|
178
|
+
change_notify
|
179
|
+
end
|
141
180
|
end
|
142
181
|
|
143
182
|
# Sets OpenSSL's default trusted CA certificates. Generally, OpenSSL is
|
@@ -165,6 +204,7 @@ class HTTPClient
|
|
165
204
|
def clear_cert_store
|
166
205
|
@cacerts_loaded = true # avoid lazy override
|
167
206
|
@cert_store = X509::Store.new
|
207
|
+
@cert_store._httpclient_cert_store_items.clear
|
168
208
|
change_notify
|
169
209
|
end
|
170
210
|
|
@@ -173,9 +213,12 @@ class HTTPClient
|
|
173
213
|
#
|
174
214
|
# Calling this method resets all existing sessions.
|
175
215
|
def cert_store=(cert_store)
|
176
|
-
|
177
|
-
@cert_store
|
178
|
-
|
216
|
+
# This is object equality check, since OpenSSL::X509::Store doesn't overload ==
|
217
|
+
if !@cacerts_loaded || (@cert_store != cert_store)
|
218
|
+
@cacerts_loaded = true # avoid lazy override
|
219
|
+
@cert_store = cert_store
|
220
|
+
change_notify
|
221
|
+
end
|
179
222
|
end
|
180
223
|
|
181
224
|
# Sets trust anchor certificate(s) for verification.
|
@@ -186,6 +229,9 @@ class HTTPClient
|
|
186
229
|
#
|
187
230
|
# Calling this method resets all existing sessions.
|
188
231
|
def add_trust_ca(trust_ca_file_or_hashed_dir)
|
232
|
+
unless File.exist?(trust_ca_file_or_hashed_dir)
|
233
|
+
trust_ca_file_or_hashed_dir = File.join(File.dirname(__FILE__), trust_ca_file_or_hashed_dir)
|
234
|
+
end
|
189
235
|
@cacerts_loaded = true # avoid lazy override
|
190
236
|
add_trust_ca_to_store(@cert_store, trust_ca_file_or_hashed_dir)
|
191
237
|
change_notify
|
@@ -211,74 +257,30 @@ class HTTPClient
|
|
211
257
|
# crl:: a OpenSSL::X509::CRL or a filename of a PEM/DER formatted
|
212
258
|
# OpenSSL::X509::CRL.
|
213
259
|
#
|
260
|
+
# On JRuby, instead of setting CRL by yourself you can set following
|
261
|
+
# options to let HTTPClient to perform revocation check with CRL and OCSP:
|
262
|
+
# -J-Dcom.sun.security.enableCRLDP=true -J-Dcom.sun.net.ssl.checkRevocation=true
|
263
|
+
# ex. jruby -J-Dcom.sun.security.enableCRLDP=true -J-Dcom.sun.net.ssl.checkRevocation=true app.rb
|
264
|
+
#
|
265
|
+
# Revoked cert example: https://test-sspev.verisign.com:2443/test-SSPEV-revoked-verisign.html
|
266
|
+
#
|
214
267
|
# Calling this method resets all existing sessions.
|
215
268
|
def add_crl(crl)
|
216
269
|
unless crl.is_a?(X509::CRL)
|
217
270
|
crl = X509::CRL.new(File.open(crl) { |f| f.read })
|
218
271
|
end
|
219
272
|
@cert_store.add_crl(crl)
|
273
|
+
@cert_store_crl_items << crl
|
220
274
|
@cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
|
221
275
|
change_notify
|
222
276
|
end
|
223
277
|
alias set_crl add_crl
|
224
278
|
|
225
|
-
|
226
|
-
|
227
|
-
#
|
228
|
-
# Calling this method resets all existing sessions.
|
229
|
-
def verify_mode=(verify_mode)
|
230
|
-
@verify_mode = verify_mode
|
231
|
-
change_notify
|
232
|
-
end
|
233
|
-
|
234
|
-
# Sets verify depth. New value must be a number.
|
235
|
-
#
|
236
|
-
# Calling this method resets all existing sessions.
|
237
|
-
def verify_depth=(verify_depth)
|
238
|
-
@verify_depth = verify_depth
|
239
|
-
change_notify
|
240
|
-
end
|
241
|
-
|
242
|
-
# Sets callback handler for custom certificate verification.
|
243
|
-
# See verify_callback.
|
244
|
-
#
|
245
|
-
# Calling this method resets all existing sessions.
|
246
|
-
def verify_callback=(verify_callback)
|
247
|
-
@verify_callback = verify_callback
|
248
|
-
change_notify
|
249
|
-
end
|
250
|
-
|
251
|
-
# Sets SSL timeout in sec.
|
252
|
-
#
|
253
|
-
# Calling this method resets all existing sessions.
|
254
|
-
def timeout=(timeout)
|
255
|
-
@timeout = timeout
|
256
|
-
change_notify
|
257
|
-
end
|
258
|
-
|
259
|
-
# Sets SSL options. New value must be a combination of # constants
|
260
|
-
# OpenSSL::SSL::OP_*
|
261
|
-
#
|
262
|
-
# Calling this method resets all existing sessions.
|
263
|
-
def options=(options)
|
264
|
-
@options = options
|
265
|
-
change_notify
|
279
|
+
def verify?
|
280
|
+
@verify_mode && (@verify_mode & OpenSSL::SSL::VERIFY_PEER != 0)
|
266
281
|
end
|
267
282
|
|
268
|
-
#
|
269
|
-
#
|
270
|
-
# Calling this method resets all existing sessions.
|
271
|
-
def ciphers=(ciphers)
|
272
|
-
@ciphers = ciphers
|
273
|
-
change_notify
|
274
|
-
end
|
275
|
-
|
276
|
-
def client_ca=(client_ca) # :nodoc:
|
277
|
-
@client_ca = client_ca
|
278
|
-
change_notify
|
279
|
-
end
|
280
|
-
|
281
|
-
# interfaces for SSLSocketWrap.
|
283
|
+
# interfaces for SSLSocket.
|
282
284
|
def set_context(ctx) # :nodoc:
|
283
285
|
load_trust_ca unless @cacerts_loaded
|
284
286
|
@cacerts_loaded = true
|
@@ -288,8 +290,14 @@ class HTTPClient
|
|
288
290
|
ctx.verify_depth = @verify_depth if @verify_depth
|
289
291
|
ctx.verify_callback = @verify_callback || method(:default_verify_callback)
|
290
292
|
# SSL config
|
291
|
-
|
292
|
-
|
293
|
+
if @client_cert
|
294
|
+
ctx.cert = @client_cert.is_a?(X509::Certificate) ? @client_cert :
|
295
|
+
X509::Certificate.new(File.open(@client_cert) { |f| f.read })
|
296
|
+
end
|
297
|
+
if @client_key
|
298
|
+
ctx.key = @client_key.is_a?(PKey::PKey) ? @client_key :
|
299
|
+
PKey::RSA.new(File.open(@client_key) { |f| f.read }, @client_key_pass)
|
300
|
+
end
|
293
301
|
ctx.client_ca = @client_ca
|
294
302
|
ctx.timeout = @timeout
|
295
303
|
ctx.options = @options
|
@@ -405,8 +413,9 @@ class HTTPClient
|
|
405
413
|
nil
|
406
414
|
end
|
407
415
|
|
416
|
+
# Use 2048 bit certs trust anchor
|
408
417
|
def load_cacerts(cert_store)
|
409
|
-
file = File.join(File.dirname(__FILE__), 'cacert.
|
418
|
+
file = File.join(File.dirname(__FILE__), 'cacert.pem')
|
410
419
|
add_trust_ca_to_store(cert_store, file)
|
411
420
|
end
|
412
421
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# HTTPClient - HTTP client library.
|
2
|
+
# Copyright (C) 2000-2015 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
3
|
+
#
|
4
|
+
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
5
|
+
# redistribute it and/or modify it under the same terms of Ruby's license;
|
6
|
+
# either the dual license version in 2003, or any later version.
|
7
|
+
|
8
|
+
|
9
|
+
require 'httpclient/ssl_config'
|
10
|
+
|
11
|
+
|
12
|
+
class HTTPClient
|
13
|
+
|
14
|
+
# Wraps up OpenSSL::SSL::SSLSocket and offers debugging features.
|
15
|
+
class SSLSocket
|
16
|
+
def self.create_socket(session)
|
17
|
+
opts = {
|
18
|
+
:debug_dev => session.debug_dev
|
19
|
+
}
|
20
|
+
site = session.proxy || session.dest
|
21
|
+
socket = session.create_socket(site.host, site.port)
|
22
|
+
begin
|
23
|
+
if session.proxy
|
24
|
+
session.connect_ssl_proxy(socket, Util.urify(session.dest.to_s))
|
25
|
+
end
|
26
|
+
new(socket, session.dest, session.ssl_config, opts)
|
27
|
+
rescue
|
28
|
+
socket.close
|
29
|
+
raise
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(socket, dest, config, opts = {})
|
34
|
+
unless SSLEnabled
|
35
|
+
raise ConfigurationError.new('Ruby/OpenSSL module is required')
|
36
|
+
end
|
37
|
+
@socket = socket
|
38
|
+
@config = config
|
39
|
+
@ssl_socket = create_openssl_socket(@socket)
|
40
|
+
@debug_dev = opts[:debug_dev]
|
41
|
+
ssl_connect(dest.host)
|
42
|
+
end
|
43
|
+
|
44
|
+
def peer_cert
|
45
|
+
@ssl_socket.peer_cert
|
46
|
+
end
|
47
|
+
|
48
|
+
def close
|
49
|
+
@ssl_socket.close
|
50
|
+
@socket.close
|
51
|
+
end
|
52
|
+
|
53
|
+
def closed?
|
54
|
+
@socket.closed?
|
55
|
+
end
|
56
|
+
|
57
|
+
def eof?
|
58
|
+
@ssl_socket.eof?
|
59
|
+
end
|
60
|
+
|
61
|
+
def gets(rs)
|
62
|
+
str = @ssl_socket.gets(rs)
|
63
|
+
debug(str)
|
64
|
+
str
|
65
|
+
end
|
66
|
+
|
67
|
+
def read(size, buf = nil)
|
68
|
+
str = @ssl_socket.read(size, buf)
|
69
|
+
debug(str)
|
70
|
+
str
|
71
|
+
end
|
72
|
+
|
73
|
+
def readpartial(size, buf = nil)
|
74
|
+
str = @ssl_socket.readpartial(size, buf)
|
75
|
+
debug(str)
|
76
|
+
str
|
77
|
+
end
|
78
|
+
|
79
|
+
def <<(str)
|
80
|
+
rv = @ssl_socket.write(str)
|
81
|
+
debug(str)
|
82
|
+
rv
|
83
|
+
end
|
84
|
+
|
85
|
+
def flush
|
86
|
+
@ssl_socket.flush
|
87
|
+
end
|
88
|
+
|
89
|
+
def sync
|
90
|
+
@ssl_socket.sync
|
91
|
+
end
|
92
|
+
|
93
|
+
def sync=(sync)
|
94
|
+
@ssl_socket.sync = sync
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def ssl_connect(hostname = nil)
|
100
|
+
if hostname && @ssl_socket.respond_to?(:hostname=)
|
101
|
+
@ssl_socket.hostname = hostname
|
102
|
+
end
|
103
|
+
@ssl_socket.connect
|
104
|
+
if $DEBUG
|
105
|
+
if @ssl_socket.respond_to?(:ssl_version)
|
106
|
+
warn("Protocol version: #{@ssl_socket.ssl_version}")
|
107
|
+
end
|
108
|
+
warn("Cipher: #{@ssl_socket.cipher.inspect}")
|
109
|
+
end
|
110
|
+
post_connection_check(hostname)
|
111
|
+
end
|
112
|
+
|
113
|
+
def post_connection_check(hostname)
|
114
|
+
verify_mode = @config.verify_mode || OpenSSL::SSL::VERIFY_NONE
|
115
|
+
if verify_mode == OpenSSL::SSL::VERIFY_NONE
|
116
|
+
return
|
117
|
+
elsif @ssl_socket.peer_cert.nil? and
|
118
|
+
check_mask(verify_mode, OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT)
|
119
|
+
raise OpenSSL::SSL::SSLError.new('no peer cert')
|
120
|
+
end
|
121
|
+
if @ssl_socket.respond_to?(:post_connection_check) and RUBY_VERSION > "1.8.4"
|
122
|
+
@ssl_socket.post_connection_check(hostname)
|
123
|
+
else
|
124
|
+
@config.post_connection_check(@ssl_socket.peer_cert, hostname)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def check_mask(value, mask)
|
129
|
+
value & mask == mask
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_openssl_socket(socket)
|
133
|
+
ssl_socket = nil
|
134
|
+
if OpenSSL::SSL.const_defined?("SSLContext")
|
135
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
136
|
+
@config.set_context(ctx)
|
137
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
138
|
+
else
|
139
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket)
|
140
|
+
@config.set_context(ssl_socket)
|
141
|
+
end
|
142
|
+
ssl_socket
|
143
|
+
end
|
144
|
+
|
145
|
+
def debug(str)
|
146
|
+
@debug_dev << str if @debug_dev && str
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
data/lib/httpclient/timeout.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# HTTPClient - HTTP client library.
|
2
|
-
# Copyright (C) 2000-
|
2
|
+
# Copyright (C) 2000-2015 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
3
3
|
#
|
4
4
|
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
5
5
|
# redistribute it and/or modify it under the same terms of Ruby's license;
|
data/lib/httpclient/util.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# HTTPClient - HTTP client library.
|
2
|
-
# Copyright (C) 2000-
|
2
|
+
# Copyright (C) 2000-2015 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
|
3
3
|
#
|
4
4
|
# This program is copyrighted free software by NAKAMURA, Hiroshi. You can
|
5
5
|
# redistribute it and/or modify it under the same terms of Ruby's license;
|
@@ -24,6 +24,28 @@ if RUBY_VERSION < "1.9.3"
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
# With recent JRuby 1.7 + jruby-openssl, X509CRL#extentions_to_text causes
|
28
|
+
# StringIndexOOBException when we try to dump SSL Server Certificate.
|
29
|
+
# when one of extensions has "" as value.
|
30
|
+
if defined?(JRUBY_VERSION)
|
31
|
+
require 'openssl'
|
32
|
+
require 'java'
|
33
|
+
module OpenSSL
|
34
|
+
module X509
|
35
|
+
class Certificate
|
36
|
+
java_import 'java.security.cert.Certificate'
|
37
|
+
java_import 'java.security.cert.CertificateFactory'
|
38
|
+
java_import 'java.io.ByteArrayInputStream'
|
39
|
+
def to_text
|
40
|
+
cf = CertificateFactory.getInstance('X.509')
|
41
|
+
cf.generateCertificate(ByteArrayInputStream.new(self.to_der.to_java_bytes)).toString
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
27
49
|
class HTTPClient
|
28
50
|
|
29
51
|
|
@@ -176,6 +198,16 @@ class HTTPClient
|
|
176
198
|
end
|
177
199
|
module_function :try_require
|
178
200
|
|
201
|
+
# show one warning message only once by caching message
|
202
|
+
#
|
203
|
+
# it cached all messages in memory so be careful not to show many kinds of warning message.
|
204
|
+
@@__warned = {}
|
205
|
+
def warning(message)
|
206
|
+
return if @@__warned.key?(message)
|
207
|
+
warn(message)
|
208
|
+
@@__warned[message] = true
|
209
|
+
end
|
210
|
+
|
179
211
|
# Checks if the given URI is https.
|
180
212
|
def https?(uri)
|
181
213
|
uri.scheme && uri.scheme.downcase == 'https'
|
data/lib/httpclient/version.rb
CHANGED
@@ -342,7 +342,7 @@ class WebAgent
|
|
342
342
|
cookie.domain_orig = given.domain
|
343
343
|
cookie.path_orig = given.path
|
344
344
|
|
345
|
-
if cookie.discard? || cookie.expires
|
345
|
+
if cookie.discard? || cookie.expires.nil?
|
346
346
|
cookie.discard = true
|
347
347
|
else
|
348
348
|
cookie.discard = false
|
@@ -456,4 +456,4 @@ end
|
|
456
456
|
|
457
457
|
class HTTPClient
|
458
458
|
CookieManager = WebAgent::CookieManager
|
459
|
-
end
|
459
|
+
end unless defined?(HTTPClient::CookieManager)
|