httpclient 2.1.5 → 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 +77 -0
- data/bin/jsonclient +85 -0
- data/lib/hexdump.rb +50 -0
- data/lib/http-access2.rb +6 -4
- data/lib/httpclient/auth.rb +575 -173
- data/lib/httpclient/cacert.pem +3952 -0
- data/lib/httpclient/cacert1024.pem +3866 -0
- data/lib/httpclient/connection.rb +6 -2
- data/lib/httpclient/cookie.rb +162 -504
- data/lib/httpclient/http.rb +334 -119
- data/lib/httpclient/include_client.rb +85 -0
- data/lib/httpclient/jruby_ssl_socket.rb +588 -0
- data/lib/httpclient/session.rb +385 -288
- data/lib/httpclient/ssl_config.rb +195 -155
- data/lib/httpclient/ssl_socket.rb +150 -0
- data/lib/httpclient/timeout.rb +14 -10
- data/lib/httpclient/util.rb +142 -6
- data/lib/httpclient/version.rb +3 -0
- data/lib/httpclient/webagent-cookie.rb +459 -0
- data/lib/httpclient.rb +509 -202
- data/lib/jsonclient.rb +63 -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 +80 -0
- data/test/test_ssl.rb +559 -0
- data/test/test_webagent-cookie.rb +465 -0
- metadata +85 -44
- data/lib/httpclient/auth.rb.orig +0 -513
- data/lib/httpclient/cacert.p7s +0 -1579
- data/lib/httpclient.rb.orig +0 -1020
- data/lib/tags +0 -908
@@ -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,88 +20,149 @@ class HTTPClient
|
|
20
20
|
#
|
21
21
|
# == Trust Anchor Control
|
22
22
|
#
|
23
|
-
# SSLConfig loads 'httpclient/cacert.
|
24
|
-
# (trusted certificate(s)) with
|
23
|
+
# SSLConfig loads 'httpclient/cacert.pem' as a trust anchor
|
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
|
-
#
|
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://...")
|
30
34
|
#
|
31
35
|
# You may want to change trust anchor by yourself. Call clear_cert_store
|
32
|
-
# then
|
36
|
+
# then add_trust_ca for that purpose.
|
33
37
|
class SSLConfig
|
34
|
-
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
|
35
89
|
|
36
|
-
#
|
37
|
-
#
|
38
|
-
|
90
|
+
# Which TLS protocol version (also called method) will be used. Defaults
|
91
|
+
# to :auto which means that OpenSSL decides (In my tests this resulted
|
92
|
+
# with always the highest available protocol being used).
|
93
|
+
# String name of OpenSSL's SSL version method name: TLSv1_2, TLSv1_1, TLSv1,
|
94
|
+
# SSLv2, SSLv23, SSLv3 or :auto (and nil) to allow version negotiation (default).
|
95
|
+
# See {OpenSSL::SSL::SSLContext::METHODS} for a list of available versions
|
96
|
+
# in your specific Ruby environment.
|
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
|
39
101
|
# OpenSSL::PKey::PKey:: private key for SSL client authentication.
|
40
|
-
# nil by default. (no client
|
41
|
-
|
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
|
42
107
|
|
43
108
|
# A number which represents OpenSSL's verify mode. Default value is
|
44
109
|
# OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT.
|
45
|
-
|
110
|
+
attr_config :verify_mode
|
46
111
|
# A number of verify depth. Certification path which length is longer than
|
47
112
|
# this depth is not allowed.
|
48
|
-
|
113
|
+
# CAUTION: this is OpenSSL specific option and ignored on JRuby.
|
114
|
+
attr_config :verify_depth
|
49
115
|
# A callback handler for custom certificate verification. nil by default.
|
50
116
|
# If the handler is set, handler.call is invoked just after general
|
51
117
|
# OpenSSL's verification. handler.call is invoked with 2 arguments,
|
52
118
|
# ok and ctx; ok is a result of general OpenSSL's verification. ctx is a
|
53
119
|
# OpenSSL::X509::StoreContext.
|
54
|
-
|
120
|
+
attr_config :verify_callback
|
55
121
|
# SSL timeout in sec. nil by default.
|
56
|
-
|
122
|
+
attr_config :timeout
|
57
123
|
# A number of OpenSSL's SSL options. Default value is
|
58
124
|
# OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2
|
59
|
-
|
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
|
60
128
|
# A String of OpenSSL's cipher configuration. Default value is
|
61
129
|
# ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH
|
62
130
|
# See ciphers(1) man in OpenSSL for more detail.
|
63
|
-
|
131
|
+
attr_config :ciphers
|
64
132
|
|
65
133
|
# OpenSSL::X509::X509::Store used for verification. You can reset the
|
66
134
|
# store with clear_cert_store and set the new store with cert_store=.
|
67
135
|
attr_reader :cert_store # don't use if you don't know what it is.
|
68
136
|
|
69
137
|
# For server side configuration. Ignore this.
|
70
|
-
|
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
|
71
143
|
|
72
144
|
# Creates a SSLConfig.
|
73
145
|
def initialize(client)
|
74
146
|
return unless SSLEnabled
|
75
147
|
@client = client
|
76
148
|
@cert_store = X509::Store.new
|
77
|
-
@
|
149
|
+
@cert_store_crl_items = []
|
150
|
+
@client_cert = @client_key = @client_key_pass = @client_ca = nil
|
78
151
|
@verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
79
152
|
@verify_depth = nil
|
80
153
|
@verify_callback = nil
|
81
154
|
@dest = nil
|
82
155
|
@timeout = nil
|
83
|
-
@
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
def client_cert=(client_cert)
|
94
|
-
@client_cert = client_cert
|
95
|
-
change_notify
|
96
|
-
end
|
97
|
-
|
98
|
-
# Sets private key (OpenSSL::PKey::PKey) for SSL client authentication.
|
99
|
-
# client_key and client_cert must be a pair.
|
100
|
-
#
|
101
|
-
# Calling this method resets all existing sessions.
|
102
|
-
def client_key=(client_key)
|
103
|
-
@client_key = client_key
|
104
|
-
change_notify
|
156
|
+
@ssl_version = :auto
|
157
|
+
# Follow ruby-ossl's definition
|
158
|
+
@options = OpenSSL::SSL::OP_ALL
|
159
|
+
@options &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
160
|
+
@options |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
|
161
|
+
@options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
|
162
|
+
@options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
|
163
|
+
# OpenSSL 0.9.8 default: "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH"
|
164
|
+
@ciphers = CIPHERS_DEFAULT
|
165
|
+
@cacerts_loaded = false
|
105
166
|
end
|
106
167
|
|
107
168
|
# Sets certificate and private key for SSL client authentication.
|
@@ -110,10 +171,29 @@ class HTTPClient
|
|
110
171
|
# RSA key. If you want to use other PKey algorithm,
|
111
172
|
# use client_key=.
|
112
173
|
#
|
174
|
+
# Calling this method resets all existing sessions if value is changed.
|
175
|
+
def set_client_cert_file(cert_file, key_file, pass = nil)
|
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
|
180
|
+
end
|
181
|
+
|
182
|
+
# Sets OpenSSL's default trusted CA certificates. Generally, OpenSSL is
|
183
|
+
# configured to use OS's trusted CA certificates located at
|
184
|
+
# /etc/pki/certs or /etc/ssl/certs. Unfortunately OpenSSL's Windows build
|
185
|
+
# does not work with Windows Certificate Storage.
|
186
|
+
#
|
187
|
+
# On Windows or when you build OpenSSL manually, you can set the
|
188
|
+
# CA certificates directory by SSL_CERT_DIR env variable at runtime.
|
189
|
+
#
|
190
|
+
# SSL_CERT_DIR=/etc/ssl/certs ruby -rhttpclient -e "..."
|
191
|
+
#
|
113
192
|
# Calling this method resets all existing sessions.
|
114
|
-
def
|
115
|
-
@
|
116
|
-
@
|
193
|
+
def set_default_paths
|
194
|
+
@cacerts_loaded = true # avoid lazy override
|
195
|
+
@cert_store = X509::Store.new
|
196
|
+
@cert_store.set_default_paths
|
117
197
|
change_notify
|
118
198
|
end
|
119
199
|
|
@@ -122,7 +202,9 @@ class HTTPClient
|
|
122
202
|
#
|
123
203
|
# Calling this method resets all existing sessions.
|
124
204
|
def clear_cert_store
|
205
|
+
@cacerts_loaded = true # avoid lazy override
|
125
206
|
@cert_store = X509::Store.new
|
207
|
+
@cert_store._httpclient_cert_store_items.clear
|
126
208
|
change_notify
|
127
209
|
end
|
128
210
|
|
@@ -131,8 +213,12 @@ class HTTPClient
|
|
131
213
|
#
|
132
214
|
# Calling this method resets all existing sessions.
|
133
215
|
def cert_store=(cert_store)
|
134
|
-
|
135
|
-
|
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
|
136
222
|
end
|
137
223
|
|
138
224
|
# Sets trust anchor certificate(s) for verification.
|
@@ -142,99 +228,81 @@ class HTTPClient
|
|
142
228
|
# trusted certificate files.
|
143
229
|
#
|
144
230
|
# Calling this method resets all existing sessions.
|
145
|
-
def
|
146
|
-
|
147
|
-
|
148
|
-
else
|
149
|
-
@cert_store.add_file(trust_ca_file_or_hashed_dir)
|
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)
|
150
234
|
end
|
235
|
+
@cacerts_loaded = true # avoid lazy override
|
236
|
+
add_trust_ca_to_store(@cert_store, trust_ca_file_or_hashed_dir)
|
151
237
|
change_notify
|
152
238
|
end
|
239
|
+
alias set_trust_ca add_trust_ca
|
153
240
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
def set_crl(crl)
|
160
|
-
unless crl.is_a?(X509::CRL)
|
161
|
-
crl = X509::CRL.new(File.open(crl).read)
|
241
|
+
def add_trust_ca_to_store(cert_store, trust_ca_file_or_hashed_dir)
|
242
|
+
if FileTest.directory?(trust_ca_file_or_hashed_dir)
|
243
|
+
cert_store.add_path(trust_ca_file_or_hashed_dir)
|
244
|
+
else
|
245
|
+
cert_store.add_file(trust_ca_file_or_hashed_dir)
|
162
246
|
end
|
163
|
-
@cert_store.add_crl(crl)
|
164
|
-
@cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
|
165
|
-
change_notify
|
166
|
-
end
|
167
|
-
|
168
|
-
# Sets verify mode of OpenSSL. New value must be a combination of
|
169
|
-
# constants OpenSSL::SSL::VERIFY_*
|
170
|
-
#
|
171
|
-
# Calling this method resets all existing sessions.
|
172
|
-
def verify_mode=(verify_mode)
|
173
|
-
@verify_mode = verify_mode
|
174
|
-
change_notify
|
175
|
-
end
|
176
|
-
|
177
|
-
# Sets verify depth. New value must be a number.
|
178
|
-
#
|
179
|
-
# Calling this method resets all existing sessions.
|
180
|
-
def verify_depth=(verify_depth)
|
181
|
-
@verify_depth = verify_depth
|
182
|
-
change_notify
|
183
247
|
end
|
184
248
|
|
185
|
-
#
|
186
|
-
# See verify_callback.
|
187
|
-
#
|
249
|
+
# Loads default trust anchors.
|
188
250
|
# Calling this method resets all existing sessions.
|
189
|
-
def
|
190
|
-
@
|
251
|
+
def load_trust_ca
|
252
|
+
load_cacerts(@cert_store)
|
191
253
|
change_notify
|
192
254
|
end
|
193
255
|
|
194
|
-
#
|
256
|
+
# Adds CRL for verification.
|
257
|
+
# crl:: a OpenSSL::X509::CRL or a filename of a PEM/DER formatted
|
258
|
+
# OpenSSL::X509::CRL.
|
195
259
|
#
|
196
|
-
#
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
end
|
201
|
-
|
202
|
-
# Sets SSL options. New value must be a combination of # constants
|
203
|
-
# OpenSSL::SSL::OP_*
|
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
|
204
264
|
#
|
205
|
-
#
|
206
|
-
def options=(options)
|
207
|
-
@options = options
|
208
|
-
change_notify
|
209
|
-
end
|
210
|
-
|
211
|
-
# Sets cipher configuration. New value must be a String.
|
265
|
+
# Revoked cert example: https://test-sspev.verisign.com:2443/test-SSPEV-revoked-verisign.html
|
212
266
|
#
|
213
267
|
# Calling this method resets all existing sessions.
|
214
|
-
def
|
215
|
-
|
268
|
+
def add_crl(crl)
|
269
|
+
unless crl.is_a?(X509::CRL)
|
270
|
+
crl = X509::CRL.new(File.open(crl) { |f| f.read })
|
271
|
+
end
|
272
|
+
@cert_store.add_crl(crl)
|
273
|
+
@cert_store_crl_items << crl
|
274
|
+
@cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
|
216
275
|
change_notify
|
217
276
|
end
|
277
|
+
alias set_crl add_crl
|
218
278
|
|
219
|
-
def
|
220
|
-
@
|
221
|
-
change_notify
|
279
|
+
def verify?
|
280
|
+
@verify_mode && (@verify_mode & OpenSSL::SSL::VERIFY_PEER != 0)
|
222
281
|
end
|
223
282
|
|
224
|
-
# interfaces for
|
283
|
+
# interfaces for SSLSocket.
|
225
284
|
def set_context(ctx) # :nodoc:
|
285
|
+
load_trust_ca unless @cacerts_loaded
|
286
|
+
@cacerts_loaded = true
|
226
287
|
# Verification: Use Store#verify_callback instead of SSLContext#verify*?
|
227
288
|
ctx.cert_store = @cert_store
|
228
289
|
ctx.verify_mode = @verify_mode
|
229
290
|
ctx.verify_depth = @verify_depth if @verify_depth
|
230
291
|
ctx.verify_callback = @verify_callback || method(:default_verify_callback)
|
231
292
|
# SSL config
|
232
|
-
|
233
|
-
|
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
|
234
301
|
ctx.client_ca = @client_ca
|
235
302
|
ctx.timeout = @timeout
|
236
303
|
ctx.options = @options
|
237
304
|
ctx.ciphers = @ciphers
|
305
|
+
ctx.ssl_version = @ssl_version unless @ssl_version == :auto
|
238
306
|
end
|
239
307
|
|
240
308
|
# post connection check proc for ruby < 1.8.5.
|
@@ -269,13 +337,19 @@ class HTTPClient
|
|
269
337
|
# Default callback for verification: only dumps error.
|
270
338
|
def default_verify_callback(is_ok, ctx)
|
271
339
|
if $DEBUG
|
272
|
-
|
340
|
+
if is_ok
|
341
|
+
warn("ok: #{ctx.current_cert.subject.to_s.dump}")
|
342
|
+
else
|
343
|
+
warn("ng: #{ctx.current_cert.subject.to_s.dump} at depth #{ctx.error_depth} - #{ctx.error}: #{ctx.error_string} in #{ctx.chain.inspect}")
|
344
|
+
end
|
345
|
+
warn(ctx.current_cert.to_text)
|
346
|
+
warn(ctx.current_cert.to_pem)
|
273
347
|
end
|
274
348
|
if !is_ok
|
275
349
|
depth = ctx.error_depth
|
276
350
|
code = ctx.error
|
277
351
|
msg = ctx.error_string
|
278
|
-
|
352
|
+
warn("at depth #{depth} - #{code}: #{msg}") if $DEBUG
|
279
353
|
end
|
280
354
|
is_ok
|
281
355
|
end
|
@@ -286,7 +360,7 @@ class HTTPClient
|
|
286
360
|
depth = ctx.error_depth
|
287
361
|
code = ctx.error
|
288
362
|
msg = ctx.error_string
|
289
|
-
|
363
|
+
warn("at depth #{depth} - #{code}: #{msg}") if $DEBUG
|
290
364
|
return false
|
291
365
|
end
|
292
366
|
|
@@ -319,13 +393,13 @@ class HTTPClient
|
|
319
393
|
end
|
320
394
|
|
321
395
|
if self_signed
|
322
|
-
|
396
|
+
warn('self signing CA') if $DEBUG
|
323
397
|
return true
|
324
398
|
elsif ca
|
325
|
-
|
399
|
+
warn('middle level CA') if $DEBUG
|
326
400
|
return true
|
327
401
|
elsif server_auth
|
328
|
-
|
402
|
+
warn('for server authentication') if $DEBUG
|
329
403
|
return true
|
330
404
|
end
|
331
405
|
|
@@ -336,47 +410,13 @@ class HTTPClient
|
|
336
410
|
|
337
411
|
def change_notify
|
338
412
|
@client.reset_all
|
413
|
+
nil
|
339
414
|
end
|
340
415
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
-----BEGIN CERTIFICATE-----
|
346
|
-
MIID/TCCAuWgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBLMQswCQYDVQQGEwJKUDER
|
347
|
-
MA8GA1UECgwIY3Rvci5vcmcxFDASBgNVBAsMC0RldmVsb3BtZW50MRMwEQYDVQQD
|
348
|
-
DApodHRwY2xpZW50MB4XDTA5MDUyMTEyMzkwNVoXDTM3MTIzMTIzNTk1OVowSzEL
|
349
|
-
MAkGA1UEBhMCSlAxETAPBgNVBAoMCGN0b3Iub3JnMRQwEgYDVQQLDAtEZXZlbG9w
|
350
|
-
bWVudDETMBEGA1UEAwwKaHR0cGNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
351
|
-
ADCCAQoCggEBAM2PlkdTH97zvIHoPIMj87wnNvpqIQUD7L/hlysO0XBsmR/XZUeU
|
352
|
-
ZKB10JQqMXviWpTnU9KU6xGTx3EI4wfd2dpLwH/d4d7K4LngW1kY7kJlZeJhakno
|
353
|
-
GzQ40RSI9WkQ0R9KOE888f7OkTBafcL8UyWFVIMhQBw2d9iNl4Jc69QojayCDoSX
|
354
|
-
XbbEP0n8yi7HwIU3RFuX6DtMpOx4/1K7Z002ccOGJ3J9kHgeDQSQtF42cQYC7qj2
|
355
|
-
67I/OQgnB7ycxTCP0E7bdXQg+zqsngrhaoNn/+I+CoO7nD4t4uQ+B4agALh4PPxs
|
356
|
-
bQD9MCL+VurNGLYv0HVd+ZlLblpddC9PLTsCAwEAAaOB6zCB6DAPBgNVHRMBAf8E
|
357
|
-
BTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09wZW5TU0wgR2VuZXJhdGVkIENl
|
358
|
-
cnRpZmljYXRlMB0GA1UdDgQWBBRAnB6XlMoOcm7HVAw+JWxY205PHTAOBgNVHQ8B
|
359
|
-
Af8EBAMCAQYwcwYDVR0jBGwwaoAUQJwel5TKDnJux1QMPiVsWNtOTx2hT6RNMEsx
|
360
|
-
CzAJBgNVBAYTAkpQMREwDwYDVQQKDAhjdG9yLm9yZzEUMBIGA1UECwwLRGV2ZWxv
|
361
|
-
cG1lbnQxEzARBgNVBAMMCmh0dHBjbGllbnSCAQEwDQYJKoZIhvcNAQENBQADggEB
|
362
|
-
ABVFepybD5XqsBnOn/oDHvK0xAPMF4Ap4Ht1yMQLObg8paVhANSdqIevPlCr/mPL
|
363
|
-
DRjcy+J1fCnE6lCfsfLdTgAjirqt8pm92NccxmJ8hTmMd3LWC1n+eYWaolqTCVRM
|
364
|
-
Bpe8UY9enyXrFoudHlr9epr18E6As6VrCSfpXFZkD9WHVSWpzkB3qATu5qcDCzCH
|
365
|
-
bI0755Mdm/1hKJCD4l69h3J3OhRIEUPJfHnPvM5wtiyC2dcE9itwE/wdVzBJeIBX
|
366
|
-
JQm+Qj+K8qXcRTzZZGIBjw2n46xJgW6YncNCHU/WWfNCYwdkngHS/aN8IbEjhCwf
|
367
|
-
viXFisVrDN/+pZZGMf67ZaY=
|
368
|
-
-----END CERTIFICATE-----
|
369
|
-
__DIST_CERT__
|
370
|
-
p7 = PKCS7.read_smime(File.open(file) { |f| f.read })
|
371
|
-
selfcert = X509::Certificate.new(dist_cert)
|
372
|
-
store = X509::Store.new
|
373
|
-
store.add_cert(selfcert)
|
374
|
-
if (p7.verify(nil, store, p7.data, 0))
|
375
|
-
set_trust_ca(file)
|
376
|
-
else
|
377
|
-
STDERR.puts("cacerts: #{file} loading failed")
|
378
|
-
end
|
379
|
-
end
|
416
|
+
# Use 2048 bit certs trust anchor
|
417
|
+
def load_cacerts(cert_store)
|
418
|
+
file = File.join(File.dirname(__FILE__), 'cacert.pem')
|
419
|
+
add_trust_ca_to_store(cert_store, file)
|
380
420
|
end
|
381
421
|
end
|
382
422
|
|
@@ -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
|