class HTTPClient::SSLConfig

then add_trust_ca for that purpose.
You may want to change trust anchor by yourself. Call clear_cert_store
site by the author and included in released package.
like Web browsers. ‘httpclient/cacert.pem’ is downloaded from curl web
This means that HTTPClient instance trusts some CA certificates by default,
(trusted certificate(s)) with add_trust_ca in initialization time.
SSLConfig loads ‘httpclient/cacert.pem’ as a trust anchor
== Trust Anchor Control
The implementation depends on OpenSSL.
Represents SSL configuration for HTTPClient instance.

def add_crl(crl)

Calling this method resets all existing sessions.

Revoked cert example: https://test-sspev.verisign.com:2443/test-SSPEV-revoked-verisign.html

ex. jruby -J-Dcom.sun.security.enableCRLDP=true -J-Dcom.sun.net.ssl.checkRevocation=true app.rb
-J-Dcom.sun.security.enableCRLDP=true -J-Dcom.sun.net.ssl.checkRevocation=true
options to let HTTPClient to perform revocation check with CRL and OCSP:
On JRuby, instead of setting CRL by yourself you can set following

OpenSSL::X509::CRL.
crl:: a OpenSSL::X509::CRL or a filename of a PEM/DER formatted
Adds CRL for verification.
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_crl_items << crl
  @cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
  change_notify
end

def add_trust_ca(trust_ca_file_or_hashed_dir)

Calling this method resets all existing sessions.

trusted certificate files.
a 'c-rehash'eddirectory name which stores
OpenSSL::X509::Certificate or
trust_ca_file_or_hashed_dir:: a filename of a PEM/DER formatted
Sets trust anchor certificate(s) for verification.
def add_trust_ca(trust_ca_file_or_hashed_dir)
  @cacerts_loaded = true # avoid lazy override
  add_trust_ca_to_store(@cert_store, trust_ca_file_or_hashed_dir)
  @cert_store_items << trust_ca_file_or_hashed_dir
  change_notify
end

def add_trust_ca_to_store(cert_store, trust_ca_file_or_hashed_dir)

def add_trust_ca_to_store(cert_store, trust_ca_file_or_hashed_dir)
  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
end

def cert_store=(cert_store)

Calling this method resets all existing sessions.

don't use if you don't know what it is.
Sets new certificate store (OpenSSL::X509::Store).
def cert_store=(cert_store)
  @cacerts_loaded = true # avoid lazy override
  @cert_store = cert_store
  @cert_store_items.clear
  change_notify
end

def change_notify

def change_notify
  @client.reset_all
  nil
end

def ciphers=(ciphers)

Calling this method resets all existing sessions.

Sets cipher configuration. New value must be a String.
def ciphers=(ciphers)
  @ciphers = ciphers
  change_notify
end

def clear_cert_store

Calling this method resets all existing sessions.

new one for the next session.
Drops current certificate store (OpenSSL::X509::Store) for SSL and create
def clear_cert_store
  @cacerts_loaded = true # avoid lazy override
  @cert_store = X509::Store.new
  @cert_store_items.clear
  change_notify
end

def client_ca=(client_ca) # :nodoc:

:nodoc:
def client_ca=(client_ca) # :nodoc:
  @client_ca = client_ca
  change_notify
end

def client_cert=(client_cert)

Calling this method resets all existing sessions.

client_key and client_cert must be a pair.
authentication.
Sets certificate (OpenSSL::X509::Certificate) for SSL client
def client_cert=(client_cert)
  @client_cert = client_cert
  change_notify
end

def client_key=(client_key)

Calling this method resets all existing sessions.

client_key and client_cert must be a pair.
Sets private key (OpenSSL::PKey::PKey) for SSL client authentication.
def client_key=(client_key)
  @client_key = client_key
  change_notify
end

def default_verify_callback(is_ok, ctx)

Default callback for verification: only dumps error.
def default_verify_callback(is_ok, ctx)
  if $DEBUG
    if is_ok
      warn("ok: #{ctx.current_cert.subject.to_s.dump}")
    else
      warn("ng: #{ctx.current_cert.subject.to_s.dump} at depth #{ctx.error_depth} - #{ctx.error}: #{ctx.error_string} in #{ctx.chain.inspect}")
    end
    warn(ctx.current_cert.to_text)
    warn(ctx.current_cert.to_pem)
  end
  if !is_ok
    depth = ctx.error_depth
    code = ctx.error
    msg = ctx.error_string
    warn("at depth #{depth} - #{code}: #{msg}") if $DEBUG
  end
  is_ok
end

def initialize(client)

Creates a SSLConfig.
def initialize(client)
  return unless SSLEnabled
  @client = client
  @cert_store = X509::Store.new
  @cert_store_items = [:default]
  @cert_store_crl_items = []
  @client_cert = @client_key = @client_ca = nil
  @verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT
  @verify_depth = nil
  @verify_callback = nil
  @dest = nil
  @timeout = nil
  @ssl_version = :auto
  # Follow ruby-ossl's definition
  @options = OpenSSL::SSL::OP_ALL
  @options &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
  @options |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
  @options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
  @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

def load_cacerts(cert_store)

OpenSSL before 1.0.1 does not have CVE-2015-1793 problem
CVE-2015-1793 requires: OpenSSL >= 1.0.2d or OpenSSL >= 1.0.1p
Use 2014 bit certs trust anchor if possible.
def load_cacerts(cert_store)
  ver = OpenSSL::OPENSSL_VERSION
  if (ver.start_with?('OpenSSL 1.0.1') && ver >= 'OpenSSL 1.0.1p') ||
      (ver.start_with?('OpenSSL ') && ver >= 'OpenSSL 1.0.2d')
    filename = 'cacert.pem'
  else
    filename = 'cacert1024.pem'
  end
  file = File.join(File.dirname(__FILE__), filename)
  add_trust_ca_to_store(cert_store, file)
  @cert_store_items << file
end

def load_trust_ca

Calling this method resets all existing sessions.
Loads default trust anchors.
def load_trust_ca
  load_cacerts(@cert_store)
  change_notify
end

def options=(options)

Calling this method resets all existing sessions.

OpenSSL::SSL::OP_*
Sets SSL options. New value must be a combination of # constants
def options=(options)
  @options = options
  change_notify
end

def post_connection_check(peer_cert, hostname) # :nodoc:

:nodoc:
this definition must match with the one in ext/openssl/lib/openssl/ssl.rb
post connection check proc for ruby < 1.8.5.
def post_connection_check(peer_cert, hostname) # :nodoc:
  check_common_name = true
  cert = peer_cert
  cert.extensions.each{|ext|
    next if ext.oid != "subjectAltName"
    ext.value.split(/,\s+/).each{|general_name|
      if /\ADNS:(.*)/ =~ general_name
        check_common_name = false
        reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
        return true if /\A#{reg}\z/i =~ hostname
      elsif /\AIP Address:(.*)/ =~ general_name
        check_common_name = false
        return true if $1 == hostname
      end
    }
  }
  if check_common_name
    cert.subject.to_a.each{|oid, value|
      if oid == "CN"
        reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
        return true if /\A#{reg}\z/i =~ hostname
      end
    }
  end
  raise SSL::SSLError, "hostname was not match with the server certificate"
end

def sample_verify_callback(is_ok, ctx)

Sample callback method: CAUTION: does not check CRL/ARL.
def sample_verify_callback(is_ok, ctx)
  unless is_ok
    depth = ctx.error_depth
    code = ctx.error
    msg = ctx.error_string
    warn("at depth #{depth} - #{code}: #{msg}") if $DEBUG
    return false
  end
  cert = ctx.current_cert
  self_signed = false
  ca = false
  pathlen = nil
  server_auth = true
  self_signed = (cert.subject.cmp(cert.issuer) == 0)
  # Check extensions whatever its criticality is. (sample)
  cert.extensions.each do |ex|
    case ex.oid
    when 'basicConstraints'
      /CA:(TRUE|FALSE), pathlen:(\d+)/ =~ ex.value
      ca = ($1 == 'TRUE')
      pathlen = $2.to_i
    when 'keyUsage'
      usage = ex.value.split(/\s*,\s*/)
      ca = usage.include?('Certificate Sign')
      server_auth = usage.include?('Key Encipherment')
    when 'extendedKeyUsage'
      usage = ex.value.split(/\s*,\s*/)
      server_auth = usage.include?('Netscape Server Gated Crypto')
    when 'nsCertType'
      usage = ex.value.split(/\s*,\s*/)
      ca = usage.include?('SSL CA')
      server_auth = usage.include?('SSL Server')
    end
  end
  if self_signed
    warn('self signing CA') if $DEBUG
    return true
  elsif ca
    warn('middle level CA') if $DEBUG
    return true
  elsif server_auth
    warn('for server authentication') if $DEBUG
    return true
  end
  return false
end

def set_client_cert_file(cert_file, key_file, pass = nil)

Calling this method resets all existing sessions.

use client_key=.
RSA key. If you want to use other PKey algorithm,
key_file:: must be a filename of PEM/DER formatted file. Key must be an
cert_file:: must be a filename of PEM/DER formatted file.
Sets certificate and private key for SSL client authentication.
def set_client_cert_file(cert_file, key_file, pass = nil)
  @client_cert, @client_key, @client_key_pass = cert_file, key_file, pass
  change_notify
end

def set_context(ctx) # :nodoc:

:nodoc:
interfaces for SSLSocket.
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
  ctx.verify_depth = @verify_depth if @verify_depth
  ctx.verify_callback = @verify_callback || method(:default_verify_callback)
  # SSL config
  if @client_cert
    ctx.cert = @client_cert.is_a?(X509::Certificate) ?  @client_cert :
      X509::Certificate.new(File.open(@client_cert) { |f| f.read })
  end
  if @client_key
    ctx.key = @client_key.is_a?(PKey::PKey) ? @client_key :
      PKey::RSA.new(File.open(@client_key) { |f| f.read }, @client_key_pass)
  end
  ctx.client_ca = @client_ca
  ctx.timeout = @timeout
  ctx.options = @options
  ctx.ciphers = @ciphers
  ctx.ssl_version = @ssl_version unless @ssl_version == :auto
end

def set_default_paths

Calling this method resets all existing sessions.

SSL_CERT_DIR=/etc/ssl/certs ruby -rhttpclient -e "..."

CA certificates directory by SSL_CERT_DIR env variable at runtime.
On Windows or when you build OpenSSL manually, you can set the

does not work with Windows Certificate Storage.
/etc/pki/certs or /etc/ssl/certs. Unfortunately OpenSSL's Windows build
configured to use OS's trusted CA certificates located at
Sets OpenSSL's default trusted CA certificates. Generally, OpenSSL is
def set_default_paths
  @cacerts_loaded = true # avoid lazy override
  @cert_store = X509::Store.new
  @cert_store.set_default_paths
  @cert_store_items = [ENV['SSL_CERT_FILE'] || :default]
  change_notify
end

def ssl_version=(ssl_version)

"SSLv3" for SSL3 and TLS1.x, "SSLv23" for SSL3 with fallback to SSL2.
Sets SSL version method String. Possible values: "SSLv2" for SSL2,
def ssl_version=(ssl_version)
  @ssl_version = ssl_version
  change_notify
end

def timeout=(timeout)

Calling this method resets all existing sessions.

Sets SSL timeout in sec.
def timeout=(timeout)
  @timeout = timeout
  change_notify
end

def verify_callback=(verify_callback)

Calling this method resets all existing sessions.

See verify_callback.
Sets callback handler for custom certificate verification.
def verify_callback=(verify_callback)
  @verify_callback = verify_callback
  change_notify
end

def verify_depth=(verify_depth)

Calling this method resets all existing sessions.

Sets verify depth. New value must be a number.
def verify_depth=(verify_depth)
  @verify_depth = verify_depth
  change_notify
end

def verify_mode=(verify_mode)

Calling this method resets all existing sessions.

constants OpenSSL::SSL::VERIFY_*
Sets verify mode of OpenSSL. New value must be a combination of
def verify_mode=(verify_mode)
  @verify_mode = verify_mode
  change_notify
end