Permalink
Browse files

Load CA certs lazily.

 * call load_cacerts lazily. new method SSLConfig#load_cacerts loads
   bundled CA certs as trust anchors.
 * rename: set_trust_ca -> add_trust_ca to fit the actual behavior.
  • Loading branch information...
1 parent 4ac6fee commit 9e7290bf92005d0769b4c3f7918fed7b1e14d4b6 @nahi committed Apr 6, 2011
Showing with 31 additions and 17 deletions.
  1. +20 −6 lib/httpclient/ssl_config.rb
  2. +3 −3 sample/ssl/ssl_client.rb
  3. +8 −8 test/test_ssl.rb
@@ -21,15 +21,15 @@ class HTTPClient
# == Trust Anchor Control
#
# SSLConfig loads 'httpclient/cacert.p7s' as a trust anchor
- # (trusted certificate(s)) with set_trust_ca in initialization time.
+ # (trusted certificate(s)) with add_trust_ca in initialization time.
# This means that HTTPClient instance trusts some CA certificates by default,
# like Web browsers. 'httpclient/cacert.p7s' is created by the author and
# included in released package.
#
# 'cacert.p7s' is automatically generated from JDK 1.6.
#
# You may want to change trust anchor by yourself. Call clear_cert_store
- # then set_trust_ca for that purpose.
+ # then add_trust_ca for that purpose.
class SSLConfig
include OpenSSL if SSLEnabled
@@ -82,7 +82,7 @@ def initialize(client)
@timeout = nil
@options = defined?(SSL::OP_ALL) ? SSL::OP_ALL | SSL::OP_NO_SSLv2 : nil
@ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH"
- load_cacerts
+ @cacerts_loaded = false
end
# Sets certificate (OpenSSL::X509::Certificate) for SSL client
@@ -122,6 +122,7 @@ def set_client_cert_file(cert_file, key_file)
#
# Calling this method resets all existing sessions.
def clear_cert_store
+ @cacerts_loaded = true # avoid lazy override
@cert_store = X509::Store.new
change_notify
end
@@ -131,6 +132,7 @@ def clear_cert_store
#
# Calling this method resets all existing sessions.
def cert_store=(cert_store)
+ @cacerts_loaded = true # avoid lazy override
@cert_store = cert_store
change_notify
end
@@ -142,28 +144,38 @@ def cert_store=(cert_store)
# trusted certificate files.
#
# Calling this method resets all existing sessions.
- def set_trust_ca(trust_ca_file_or_hashed_dir)
+ def add_trust_ca(trust_ca_file_or_hashed_dir)
+ @cacerts_loaded = true # avoid lazy override
if FileTest.directory?(trust_ca_file_or_hashed_dir)
@cert_store.add_path(trust_ca_file_or_hashed_dir)
else
@cert_store.add_file(trust_ca_file_or_hashed_dir)
end
change_notify
end
+ alias set_trust_ca add_trust_ca
+
+ # Loads default trust anchors.
+ # Calling this method resets all existing sessions.
+ def load_trust_ca
+ load_cacerts
+ change_notify
+ end
# Adds CRL for verification.
# crl:: a OpenSSL::X509::CRL or a filename of a PEM/DER formatted
# OpenSSL::X509::CRL.
#
# Calling this method resets all existing sessions.
- def set_crl(crl)
+ def add_crl(crl)
unless crl.is_a?(X509::CRL)
crl = X509::CRL.new(File.open(crl) { |f| f.read })
end
@cert_store.add_crl(crl)
@cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
change_notify
end
+ alias set_crl add_crl
# Sets verify mode of OpenSSL. New value must be a combination of
# constants OpenSSL::SSL::VERIFY_*
@@ -223,6 +235,8 @@ def client_ca=(client_ca) # :nodoc:
# interfaces for SSLSocketWrap.
def set_context(ctx) # :nodoc:
+ load_trust_ca unless @cacerts_loaded
+ @cacerts_loaded = true
# Verification: Use Store#verify_callback instead of SSLContext#verify*?
ctx.cert_store = @cert_store
ctx.verify_mode = @verify_mode
@@ -350,7 +364,7 @@ def load_cacerts
store = X509::Store.new
store.add_cert(selfcert)
if (p7.verify(nil, store, p7.data, 0))
- set_trust_ca(file)
+ add_trust_ca(file)
return
end
end
View
@@ -15,8 +15,8 @@
proxy = ENV['HTTP_PROXY'] || ENV['http_proxy'] || nil
h = HTTPClient.new(proxy)
-#h.ssl_config.set_trust_ca(ca_file)
-#h.ssl_config.set_crl(crl_file)
-h.ssl_config.set_trust_ca(ca_path)
+#h.ssl_config.add_trust_ca(ca_file)
+#h.ssl_config.add_crl(crl_file)
+h.ssl_config.add_trust_ca(ca_path)
print h.get_content(url)
View
@@ -43,8 +43,8 @@ def test_options
def test_sync
cfg = @client.ssl_config
cfg.set_client_cert_file(path('client.cert'), path('client.key'))
- cfg.set_trust_ca(path('ca.cert'))
- cfg.set_trust_ca(path('subca.cert'))
+ cfg.add_trust_ca(path('ca.cert'))
+ cfg.add_trust_ca(path('subca.cert'))
assert_equal("hello", @client.get_content(@url))
@client.socket_sync = false
@@ -57,8 +57,8 @@ def test_debug_dev
cfg = @client.ssl_config
cfg.client_cert = cert("client.cert")
cfg.client_key = key("client.key")
- cfg.set_trust_ca(path('ca.cert'))
- cfg.set_trust_ca(path('subca.cert'))
+ cfg.add_trust_ca(path('ca.cert'))
+ cfg.add_trust_ca(path('subca.cert'))
assert_equal("hello", @client.get_content(@url))
assert(str.scan(/^hello$/)[0])
end
@@ -86,7 +86,7 @@ def test_verification
assert(@verify_callback_called)
end
#
- cfg.set_trust_ca(path('ca.cert'))
+ cfg.add_trust_ca(path('ca.cert'))
@verify_callback_called = false
begin
@client.get(@url)
@@ -96,7 +96,7 @@ def test_verification
assert(@verify_callback_called)
end
#
- cfg.set_trust_ca(path('subca.cert'))
+ cfg.add_trust_ca(path('subca.cert'))
@verify_callback_called = false
assert_equal("hello", @client.get_content(@url))
assert(@verify_callback_called)
@@ -128,8 +128,8 @@ def test_verification
def test_ciphers
cfg = @client.ssl_config
cfg.set_client_cert_file(path('client.cert'), path('client.key'))
- cfg.set_trust_ca(path('ca.cert'))
- cfg.set_trust_ca(path('subca.cert'))
+ cfg.add_trust_ca(path('ca.cert'))
+ cfg.add_trust_ca(path('subca.cert'))
cfg.timeout = 123
assert_equal("hello", @client.get_content(@url))
#

0 comments on commit 9e7290b

Please sign in to comment.