From e8486e1cdf07922322f75410ab3ffca0d0a0f176 Mon Sep 17 00:00:00 2001 From: Yoshinari Takaoka Date: Mon, 17 Sep 2018 18:25:24 +0900 Subject: [PATCH] applied #386 for fixing CI error. --- lib/httpclient/ssl_config.rb | 19 ++++++-- test/helper.rb | 3 +- test/test_ssl.rb | 89 +++++++++++++++++++++++++++++++++--- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/lib/httpclient/ssl_config.rb b/lib/httpclient/ssl_config.rb index f6e7ce92..b8a98502 100644 --- a/lib/httpclient/ssl_config.rb +++ b/lib/httpclient/ssl_config.rb @@ -146,6 +146,9 @@ def initialize(client) return unless SSLEnabled @client = client @cert_store = X509::Store.new + @cert_store.set_default_paths + @cacerts_loaded = working_openssl_platform? + @cert_store_crl_items = [] @client_cert = @client_key = @client_key_pass = @client_ca = nil @verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT @@ -162,7 +165,6 @@ def initialize(client) @options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3) # OpenSSL 0.9.8 default: "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH" @ciphers = CIPHERS_DEFAULT - @cacerts_loaded = false end # Sets certificate and private key for SSL client authentication. @@ -413,10 +415,21 @@ def change_notify nil end + def working_openssl_platform? + File.exist?(OpenSSL::X509::DEFAULT_CERT_FILE) && Dir.exist?(OpenSSL::X509::DEFAULT_CERT_DIR) + end + # Use 2048 bit certs trust anchor def load_cacerts(cert_store) - file = File.join(File.dirname(__FILE__), 'cacert.pem') - add_trust_ca_to_store(cert_store, file) + certs = if ENV.key?('SSL_CERT_DIR'.freeze) || ENV.key?('SSL_CERT_FILE') + [ ENV['SSL_CERT_DIR'], ENV['SSL_CERT_FILE'] ].compact + else + [ File.join(File.dirname(__FILE__), 'cacert.pem') ] + end + + certs.each do |cert| + add_trust_ca_to_store(cert_store, cert) + end end end diff --git a/test/helper.rb b/test/helper.rb index 501e55a0..881303dc 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -5,7 +5,8 @@ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter SimpleCov.start rescue LoadError -end +end if ENV['CI'] + require 'test/unit' require 'httpclient' diff --git a/test/test_ssl.rb b/test/test_ssl.rb index 2e634d71..0e1a9b73 100644 --- a/test/test_ssl.rb +++ b/test/test_ssl.rb @@ -81,10 +81,42 @@ def test_debug_dev end def test_verification_without_httpclient - 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-----" - 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-----" - ca_cert = ::OpenSSL::X509::Certificate.new(raw_ca_cert) - cert = ::OpenSSL::X509::Certificate.new(raw_cert) + ca_cert = ::OpenSSL::X509::Certificate.new(%w[-----BEGIN\ CERTIFICATE----- +MIIC3jCCAcYCCQCUWi3t8e122TANBgkqhkiG9w0BAQsFADAxMQ0wCwYDVQQKDARS +dWJ5MRMwEQYDVQQLDApodHRwY2xpZW50MQswCQYDVQQDDAJDQTAeFw0xODAyMjcx +MTM0NDRaFw0yODAyMjUxMTM0NDRaMDExDTALBgNVBAoMBFJ1YnkxEzARBgNVBAsM +Cmh0dHBjbGllbnQxCzAJBgNVBAMMAkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAs6FPPj8PVl1uxsMZas4VC/ibRvtyXQkfrEa7TO032Kh+ETsOQNS8 +QJedhw/BMHuoVbU0/b6PZ//LJTUDN/C77/QWHKzcMoxkNye5PC2cJlSQMosaKjYG +1ERYmJ+FBiMMSpcLOCS5cYoP2fJHGtHqZPkxIPYy+IKQ7WuP3tUXkVC+ftpD6H4V +6MUnfLwagpaAAbRoFUJQoZISmH2+F5GOKX9KKiMBI94yqRRN4K/B9iqXgld45Hmg +67vX0ckRbqBhrz1CwPtaETLFB4hZT2ouBkMQYtrvpNXv80p7vcz+BwORo8b2Ns9B +4FqtpjMaS9Mf95z4Mn+NG7lanYtsHO2svwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB +AQBu614zHB5SS+ORYrRwl7tICKUipWHdCJfYsJOQy/FKwe7vedwd/Uclfe06GU+m +bNv0y22/oF7vrM3EfnxFe2DNIKXTndszrQSLpT6OPBe4mAOSJxnIMy6B6/PyhK6I +D7TWFSVlYX9a4OfolsoE0gQtxhyLud4rvJgXyAq9kRZ1FcNfI75cImk67rCa8jRY +TJOTidKq1Kcn6RY7d8cf581HP7y/eK887K6lBvGiQE1aFDSLe2ZLY+rxS9GSMYfK +81XhUX2QKytGYch2y95ThMwOljVTg6fKDrtKGwj9mSsnlfTFX3gikvLLtB/o7JPR +2pWBic8PX7gnANQqH/4ahv1M +-----END\ CERTIFICATE-----].join("\n")) + cert = ::OpenSSL::X509::Certificate.new(%w[-----BEGIN\ CERTIFICATE----- +MIIC5zCCAc8CCQCz/lMJNLxQDjANBgkqhkiG9w0BAQsFADAxMQ0wCwYDVQQKDARS +dWJ5MRMwEQYDVQQLDApodHRwY2xpZW50MQswCQYDVQQDDAJDQTAeFw0xODAyMjcx +MTM1MTNaFw0yNzExMjcxMTM1MTNaMDoxDTALBgNVBAoMBFJ1YnkxEzARBgNVBAsM +Cmh0dHBjbGllbnQxFDASBgNVBAMMC0NlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAo/zP4oPyqerNyJYNTKzAGGQR8uKmP9wLnLm/yTf/ +jwzVLj3rvunw54aw89V3R4LLwBBMgFlE9OrUa+2zCvZJ8ykSoltU+w9E2EdXnXAR +C/GW678MA06NPBuMNQyf+7Lv7dipdv+0hUNXFarwGiJkCms0zcmTonkOC8Bh7stZ +EykkvQs5zmYVd+G26D5un8Wzjl6OckbBDcKTS9u9H1YveRcnN7odsh+qI4PjDmKG +PXR8Gz/loNYN/I55Hqe7vkQJZ7r1PjSBp/fIcb4pNEkKS9DAcNWkoHF2j5nBNdOq +mH3WR36vKlw5S4HLzDXQDeueFbtk3QGrWY2MWrpJNapeAQIDAQABMA0GCSqGSIb3 +DQEBCwUAA4IBAQB2CiGKAvHjr4kjOavWqGfPv115N4fhmBcPH4YAeJB9mHTzpoPV +BCm0ouRG5Oqj/DJhm+mckFKSorZFSgVb/G92w0uXRvBMPJb4wyIbp5ld6K3138cn +DtmeON3gbHwh3or741LdD6GIaulA9CL/qI3bbiyrJrHAZuHbpA6UqHfTKTBVi0uq +kv8qmA8FrzI2itDqdp0dq3QMNGnG40OM8NSDX+8A9wMahPh+Oe3TePSvDTahXIU1 +o+dzaUEIVhUWEikQBnfeEnxzN8B/qtt3wEpliAip9Z3LuN0pVFb81Mx1wEZls2Bd +Kj83iBw7flO651USNPnkOkU3DegNtcpTaT5M +-----END\ CERTIFICATE-----].join("\n")) store = ::OpenSSL::X509::Store.new store.add_cert(ca_cert) assert(store.verify(cert)) @@ -245,10 +277,39 @@ def test_set_default_paths end end + def test_load_cacerts + omit_if(RUBY_ENGINE == 'jruby', 'SSL_CERT_FILE environment does not work on JRuby') + + # disables loading default openssl paths + stub_x509_const(:DEFAULT_CERT_FILE, '/invalid') do + assert_raise(OpenSSL::SSL::SSLError) do + @client.get(@url) + end + + setup_client + + escape_env do + ENV['SSL_CERT_FILE'] = File.join(DIR, 'ca-chain.pem') + @client.get(@url) + end + end + end + + def test_default_paths + assert_raise(OpenSSL::SSL::SSLError) do + @client.get(@url) + end + escape_env do + ENV['SSL_CERT_FILE'] = File.join(DIR, 'ca-chain.pem') + setup_client + @client.get(@url) + end + end + def test_no_sslv3 teardown_server setup_server_with_ssl_version(:SSLv3) - assert_raise(OpenSSL::SSL::SSLError) do + assert_raise() do @client.ssl_config.verify_mode = nil @client.get("https://localhost:#{serverport}/hello") end @@ -264,7 +325,7 @@ def test_allow_tlsv1 end def test_use_higher_TLS - omit('TODO: it does not pass with Java 7 or old openssl ') + # TODO: it does not pass with Java 7 or old openssl teardown_server setup_server_with_ssl_version('TLSv1_2') assert_nothing_raised do @@ -429,6 +490,20 @@ def test_timeout private + def stub_x509_const(name, value) + OpenSSL::X509.module_eval do + begin + original = remove_const(name) + const_set(name, value) + + yield + ensure + remove_const(name) + const_set(name, original) + end + end + end + def cert(filename) OpenSSL::X509::Certificate.new(File.read(File.join(DIR, filename))) end @@ -474,7 +549,7 @@ def setup_server_with_ssl_version(ssl_version) ssl_version = ssl_version.tr('_', '.') end logger = Logger.new(STDERR) - logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level) + logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level) @server = WEBrick::HTTPServer.new( :BindAddress => "localhost", :Logger => logger,