From d32f056989f82b35f3dc40f6ea33d217844dad3d Mon Sep 17 00:00:00 2001 From: Artem Ignatyev Date: Tue, 17 Dec 2019 17:47:52 +0300 Subject: [PATCH] Introduce client_extra_certs option to SSLConfig Some websites relying on client certificate authentication reject requests with proper client certificate unless authority chain is presented with the certificate as well. New `client_extra_certs` tunable allows adding CA certificates to the `extra_chain_cert` option of SSL connection context, thus providing a way of supplying the authority chain together with request. --- lib/httpclient/ssl_config.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/httpclient/ssl_config.rb b/lib/httpclient/ssl_config.rb index f6e7ce92..3b9ee5b2 100644 --- a/lib/httpclient/ssl_config.rb +++ b/lib/httpclient/ssl_config.rb @@ -104,6 +104,10 @@ def attr_config(symbol) # OpenSSL::PKey::PKey:: private key pass phrase for client_key. # nil by default. (no pass phrase) attr_config :client_key_pass + # Array:: Extra certificates of OpenSSL::X509::Certificate to be presented + # along with the client certificate to the server. + # nil by default (no extra certificates) + attr_config :client_extra_certs # A number which represents OpenSSL's verify mode. Default value is # OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT. @@ -147,7 +151,7 @@ def initialize(client) @client = client @cert_store = X509::Store.new @cert_store_crl_items = [] - @client_cert = @client_key = @client_key_pass = @client_ca = nil + @client_cert = @client_key = @client_key_pass = @client_ca = @client_extra_certs = nil @verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT @verify_depth = nil @verify_callback = nil @@ -298,6 +302,13 @@ def set_context(ctx) # :nodoc: ctx.key = @client_key.is_a?(PKey::PKey) ? @client_key : PKey::RSA.new(File.open(@client_key) { |f| f.read }, @client_key_pass) end + if @client_extra_certs + ctx.extra_chain_cert = Array(client_extra_certs). + map do |cert| + cert.is_a?(X509::Certificate) ? cert : + X509::Certificate.new(File.open(cert)) { |f| f.read } + end + end ctx.client_ca = @client_ca ctx.timeout = @timeout ctx.options = @options