Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 33 additions & 15 deletions lib/ssl-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,48 @@ module SSLTest
extend OCSP
extend CRL

VERSION = -"1.4.1"
VERSION = -"1.4.1f"

class << self
def test url, open_timeout: 5, read_timeout: 5, redirection_limit: 5
uri = URI.parse(url)
return if uri.scheme != 'https' and uri.scheme != 'tcps'
cert = failed_cert_reason = chain = nil

@logger&.info { "SSLTest #{url} started" }
http = Net::HTTP.new(uri.host, uri.port)
http.open_timeout = open_timeout
http.read_timeout = read_timeout
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.verify_callback = -> (verify_ok, store_context) {
def test url, open_timeout: 5, read_timeout: 5, proxy_host:nil, proxy_port: nil, redirection_limit: 5, client_cert: nil, ca_certs: []
cert = failed_cert_reason = chain = store = nil

if url.nil? && (client_cert.nil? || ca_certs.empty?)
raise ArgumentError, "A url must be provided as the first argument, OR ... client_cert: AND ca_certs: must both be specified"
end

certificate_verify_callback = -> (verify_ok, store_context) {
cert = store_context.current_cert
chain = store_context.chain
failed_cert_reason = [store_context.error, store_context.error_string] if store_context.error != 0
verify_ok
}

if !client_cert.nil? && !ca_certs.empty?
store = OpenSSL::X509::Store.new
ca_certs.each { store.add_cert(_1) }
store.verify_callback = certificate_verify_callback
else
uri = URI.parse(url)
return if uri.scheme != 'https' and uri.scheme != 'tcps'

@logger&.info { "SSLTest #{url} started" }
http = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port)
http.open_timeout = open_timeout
http.read_timeout = read_timeout
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.verify_callback = certificate_verify_callback
end

begin
http.start { }
revoked, message, revocation_date = test_chain_revocation(chain, open_timeout: open_timeout, read_timeout: read_timeout, redirection_limit: redirection_limit)
if store.nil?
http.start { }
else
store.verify(client_cert)
end

revoked, message, revocation_date = test_chain_revocation(chain, open_timeout: open_timeout, read_timeout: read_timeout, proxy_host: proxy_host, proxy_port: proxy_port, redirection_limit: redirection_limit)
@logger&.info { "SSLTest #{url} finished: revoked=#{revoked} #{message}" }
return [false, "SSL certificate revoked: #{message} (revocation date: #{revocation_date})", cert] if revoked
return [true, "Revocation test couldn't be performed: #{message}", cert] if message
Expand Down
6 changes: 3 additions & 3 deletions lib/ssl-test/crl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def test_crl_revocation cert, issuer:, chain:, **options
end

# Returns an array with [response, error_message]
def follow_crl_redirects(uri, open_timeout: 5, read_timeout: 5, redirection_limit: 5)
def follow_crl_redirects(uri, open_timeout: 5, read_timeout: 5, redirection_limit: 5, proxy_host: nil, proxy_port: nil)
return [nil, "Too many redirections (> #{redirection_limit})"] if redirection_limit == 0

# Return file from cache if not expired
Expand All @@ -61,7 +61,7 @@ def follow_crl_redirects(uri, open_timeout: 5, read_timeout: 5, redirection_limi

@logger&.debug { "SSLTest + CRL: fetch URI #{uri}" }
path = uri.path == "" ? "/" : uri.path
http = Net::HTTP.new(uri.hostname, uri.port)
http = Net::HTTP.new(uri.hostname, uri.port, proxy_host, proxy_port)
http.open_timeout = open_timeout
http.read_timeout = read_timeout

Expand Down Expand Up @@ -92,7 +92,7 @@ def follow_crl_redirects(uri, open_timeout: 5, read_timeout: 5, redirection_limi
}
[http_response.body, nil]
when Net::HTTPRedirection
follow_crl_redirects(URI(http_response["location"]), open_timeout: open_timeout, read_timeout: read_timeout, redirection_limit: redirection_limit - 1)
follow_crl_redirects(URI(http_response["location"]), open_timeout: open_timeout, read_timeout: read_timeout, proxy_host: proxy_host, proxy_port: proxy_port, redirection_limit: redirection_limit - 1)
else
@logger&.debug { "SSLTest + CRL: Error: #{http_response.class}" }
[nil, "Wrong response type (#{http_response.class})"]
Expand Down
6 changes: 3 additions & 3 deletions lib/ssl-test/ocsp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ def test_ocsp_revocation cert, issuer:, chain:, **options
end

# Returns an array with [response, error_message]
def follow_ocsp_redirects(uri, data, open_timeout: 5, read_timeout: 5, redirection_limit: 5)
def follow_ocsp_redirects(uri, data, open_timeout: 5, read_timeout: 5, redirection_limit: 5, proxy_host: nil, proxy_port: nil)
return [nil, "Too many redirections (> #{redirection_limit})"] if redirection_limit == 0

@logger&.debug { "SSLTest + OCSP: fetch URI #{uri}" }
path = uri.path == "" ? "/" : uri.path
http = Net::HTTP.new(uri.hostname, uri.port)
http = Net::HTTP.new(uri.hostname, uri.port, proxy_host, proxy_port)
http.open_timeout = open_timeout
http.read_timeout = read_timeout

Expand All @@ -82,7 +82,7 @@ def follow_ocsp_redirects(uri, data, open_timeout: 5, read_timeout: 5, redirecti
@logger&.debug { "SSLTest + OCSP: 200 OK (#{http_response.body.bytesize} bytes)" }
[http_response.body, nil]
when Net::HTTPRedirection
follow_ocsp_redirects(URI(http_response["location"]), data, open_timeout: open_timeout, read_timeout: read_timeout, redirection_limit: redirection_limit - 1)
follow_ocsp_redirects(URI(http_response["location"]), data, open_timeout: open_timeout, read_timeout: read_timeout, rproxy_host: proxy_host, proxy_port: proxy_port, edirection_limit: redirection_limit - 1)
else
@logger&.debug { "SSLTest + OCSP: Error: #{http_response.class}" }
[nil, "Wrong response type (#{http_response.class})"]
Expand Down