Module: SSLTest
- Defined in:
- lib/ssl-test.rb
Constant Summary collapse
- VERSION =
"1.2.0"
Class Method Summary collapse
- .cert_domains(cert) ⇒ Object
- .cert_field_to_hash(field) ⇒ Object
- .matching_domains(domains, hostname) ⇒ Object
- .test(url, open_timeout: 5, read_timeout: 5) ⇒ Object
Class Method Details
.cert_domains(cert) ⇒ Object
47 48 49 50 51 52 53 |
# File 'lib/ssl-test.rb', line 47 def self.cert_domains cert (Array(cert_field_to_hash(cert.subject)['CN']) + cert_field_to_hash(cert.extensions)['subjectAltName'].split(/\s*,\s*/)) .compact .map {|s| s.gsub(/^DNS:/, '') } .uniq end |
.cert_field_to_hash(field) ⇒ Object
40 41 42 43 44 45 |
# File 'lib/ssl-test.rb', line 40 def self.cert_field_to_hash field field.to_a.each.with_object({}) do |v, h| v = v.to_a h[v[0]] = v[1].encode('UTF-8', undef: :replace, invalid: :replace) end end |
.matching_domains(domains, hostname) ⇒ Object
55 56 57 58 |
# File 'lib/ssl-test.rb', line 55 def self.matching_domains domains, hostname domains.map {|s| Regexp.new("\A#{Regexp.escape(s).gsub('\*', '[^.]+')}\z") } .select {|domain| domain.match?(hostname) } end |
.test(url, open_timeout: 5, read_timeout: 5) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/ssl-test.rb', line 6 def self.test url, open_timeout: 5, read_timeout: 5 uri = URI.parse(url) return if uri.scheme != 'https' cert = failed_cert_reason = nil 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 failed_cert_reason = [store_context.error, store_context.error_string] if store_context.error != 0 verify_ok } begin http.start { } return [true, nil, cert] rescue OpenSSL::SSL::SSLError => e error = e. 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 return [false, error, cert] rescue => e return [nil, "SSL certificate test failed: #{e.}"] end end |