16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
# File 'lib/ssl-test.rb', line 16
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) {
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
}
begin
http.start { }
revoked, message, revocation_date = test_chain_revocation(chain, open_timeout: open_timeout, read_timeout: read_timeout, 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
return [true, nil, cert]
rescue OpenSSL::SSL::SSLError => e
error = e.message
error = "error code %d: %s" % failed_cert_reason if failed_cert_reason
if error =~ /certificate verify failed/
domains = cert_domains(cert)
if matching_domains(domains, uri.host).none?
error = "hostname \"#{uri.host}\" does not match the server certificate (#{domains.join(', ')})"
end
end
@logger&.info { "SSLTest #{url} finished: #{error}" }
return [false, error, cert]
rescue => e
@logger&.error { "SSLTest #{url} failed: #{e.message}" }
return [nil, "SSL certificate test failed: #{e.message}", cert]
end
end
|