ssl-test 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +3 -5
- data/README.md +46 -17
- data/lib/ssl-test/crl.rb +6 -6
- data/lib/ssl-test/ocsp.rb +3 -3
- data/lib/ssl-test.rb +75 -29
- data/spec/fixtures/digicert_com_ca_bundle.pem +92 -0
- data/spec/fixtures/digicert_com_client.pem +40 -0
- data/spec/fixtures/expired_cert_ca_bundle.pem +100 -0
- data/spec/fixtures/expired_cert_client.pem +31 -0
- data/spec/fixtures/google_com_ca_bundle.pem +108 -0
- data/spec/fixtures/google_com_client.pem +48 -0
- data/spec/fixtures/incomplete_chain_ca_bundle.pem +29 -0
- data/spec/fixtures/incomplete_chain_client.pem +29 -0
- data/spec/fixtures/revoked_badssl_ca_bundle.pem +79 -0
- data/spec/fixtures/revoked_badssl_client.pem +22 -0
- data/spec/fixtures/revoked_rsa_dv_ca_bundle.pem +114 -0
- data/spec/fixtures/revoked_rsa_dv_client.pem +41 -0
- data/spec/fixtures/self_signed_ca_bundle.pem +21 -0
- data/spec/fixtures/self_signed_client.pem +21 -0
- data/spec/fixtures/www_demarches-simplifiees_fr_ca_bundle.pem +132 -0
- data/spec/fixtures/www_demarches-simplifiees_fr_client.pem +56 -0
- data/spec/fixtures/www_github_com_ca_bundle.pem +59 -0
- data/spec/fixtures/www_github_com_client.pem +24 -0
- data/spec/fixtures/www_mycs_com_ca_bundle.pem +79 -0
- data/spec/fixtures/www_mycs_com_client.pem +33 -0
- data/spec/ssl-test_spec.rb +309 -53
- data/ssl-test.gemspec +2 -0
- metadata +71 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa4bf88f0998469b7b82910dcef9f53cc6a64827c5aba691591138b78d33877e
|
|
4
|
+
data.tar.gz: 1666b7fd1b40b3a611d04521041ad64a5a0c6536c3d2fafb3b412ce184c371d5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a40f9e0a498e0ede200cfd6382c24af3b1ab39163b4ac040b4817dff08dc7c320136b3e8516eb5a4fd4f443083da54cf5a822a5736a4795d93de8c7e2581e38b
|
|
7
|
+
data.tar.gz: c51a2d657031506b792960ccd3975521e8cfe5f9c5ffdfd06a7d48a6eacadef63811c4467acc34145d17022de8c3f92ac3a5ccf56316f4766b5ccbefe5fbc9a9
|
data/.github/workflows/ruby.yml
CHANGED
|
@@ -2,17 +2,15 @@ name: Specs
|
|
|
2
2
|
on: [push]
|
|
3
3
|
jobs:
|
|
4
4
|
specs:
|
|
5
|
-
runs-on: ubuntu-
|
|
6
|
-
strategy:
|
|
7
|
-
matrix:
|
|
8
|
-
ruby-version: ['2.6', '2.7', '3.0', '3.1', 'jruby-head', 'truffleruby-head']
|
|
5
|
+
runs-on: ubuntu-22.04
|
|
9
6
|
steps:
|
|
10
7
|
- uses: actions/checkout@v2
|
|
11
8
|
- name: Set up Ruby
|
|
12
9
|
uses: ruby/setup-ruby@v1
|
|
13
10
|
with:
|
|
14
|
-
ruby-version:
|
|
11
|
+
ruby-version: '3.1'
|
|
15
12
|
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
16
13
|
- name: Run specs
|
|
17
14
|
run: |
|
|
15
|
+
openssl version
|
|
18
16
|
bundle exec rspec
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SSLTest
|
|
1
|
+
# SSLTest
|
|
2
2
|
|
|
3
3
|
A small ruby gem (with no dependencies) to help you test a website's SSL certificate.
|
|
4
4
|
|
|
@@ -8,68 +8,95 @@ gem 'ssl-test'
|
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
|
-
Simply call the `SSLTest.
|
|
11
|
+
Simply call the `SSLTest.test_url` method and it'll return 3 values:
|
|
12
12
|
|
|
13
13
|
1. the validity of the certificate
|
|
14
14
|
2. the error message (if any)
|
|
15
15
|
3. the certificate itself
|
|
16
16
|
|
|
17
17
|
Example with good cert:
|
|
18
|
+
|
|
18
19
|
```ruby
|
|
19
|
-
valid, error, cert = SSLTest.
|
|
20
|
+
valid, error, cert = SSLTest.test_url "https://google.com"
|
|
20
21
|
valid # => true
|
|
21
22
|
error # => nil
|
|
22
23
|
cert # => #<OpenSSL::X509::Certificate...>
|
|
23
24
|
```
|
|
24
25
|
|
|
25
26
|
Example with bad certificate:
|
|
27
|
+
|
|
26
28
|
```ruby
|
|
27
|
-
valid, error, cert = SSLTest.
|
|
29
|
+
valid, error, cert = SSLTest.test_url "https://testssl-expire.disig.sk"
|
|
28
30
|
valid # => false
|
|
29
31
|
error # => "error code 10: certificate has expired"
|
|
30
32
|
cert # => #<OpenSSL::X509::Certificate...>
|
|
31
33
|
```
|
|
32
34
|
|
|
33
35
|
If the request fails and we're unable to detemine the validity, here are the returned values:
|
|
36
|
+
|
|
34
37
|
```ruby
|
|
35
|
-
valid, error, cert = SSLTest.
|
|
38
|
+
valid, error, cert = SSLTest.test_url "https://thisisdefinitelynotawebsite.com"
|
|
36
39
|
valid # => nil
|
|
37
40
|
error # => "SSL certificate test failed: getaddrinfo: Name or service not known"
|
|
38
41
|
cert # => nil
|
|
39
42
|
```
|
|
40
43
|
|
|
41
|
-
You can also pass custom timeout values:
|
|
44
|
+
You can also pass custom timeout values (defaults to 5 seconds for open and read):
|
|
45
|
+
|
|
42
46
|
```ruby
|
|
43
|
-
valid, error, cert = SSLTest.
|
|
47
|
+
valid, error, cert = SSLTest.test_url "https://slowebsite.com", open_timeout: 2, read_timeout: 2
|
|
44
48
|
valid # => nil
|
|
45
49
|
error # => "SSL certificate test failed: execution expired"
|
|
46
50
|
cert # => nil
|
|
47
51
|
```
|
|
48
|
-
Default timeout values are 5 seconds each (open and read)
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
Or a proxy host and port to use for the http requests:
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
valid, error, cert = SSLTest.test_url "https://slowebsite.com", proxy_host: 'localhost', proxy_port: 8080
|
|
57
|
+
valid # => true
|
|
58
|
+
error # => nil
|
|
59
|
+
cert # => #<OpenSSL::X509::Certificate...>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Revoked certificates are detected using [CRL](https://en.wikipedia.org/wiki/Certificate_revocation_list) by default:
|
|
63
|
+
|
|
51
64
|
```ruby
|
|
52
|
-
valid, error, cert = SSLTest.
|
|
65
|
+
valid, error, cert = SSLTest.test_url "https://revoked.badssl.com"
|
|
53
66
|
valid # => false
|
|
54
|
-
error # => "SSL certificate revoked:
|
|
67
|
+
error # => "SSL certificate revoked: Key Compromise (revocation date: 2019-10-07 20:30:39 UTC)"
|
|
55
68
|
cert # => #<OpenSSL::X509::Certificate...>
|
|
56
69
|
```
|
|
57
70
|
|
|
58
|
-
If the
|
|
71
|
+
If the CRL is missing, invalid or unreachable the certificate revocation will be tested using [OCSP](https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol).
|
|
72
|
+
|
|
73
|
+
If both CRL and OCSP tests are impossible, the certificate will still be considered valid but with an error message:
|
|
59
74
|
|
|
60
|
-
If both OCSP and CRL tests are impossible, the certificate will still be considered valid but with an error message:
|
|
61
75
|
```ruby
|
|
62
|
-
valid, error, cert = SSLTest.
|
|
76
|
+
valid, error, cert = SSLTest.test_url "https://sitewithnoOCSPorCRL.com"
|
|
63
77
|
valid # => true
|
|
64
|
-
error # => "Revocation test couldn't be performed: OCSP: Missing OCSP URI in authorityInfoAccess extension
|
|
78
|
+
error # => "Revocation test couldn't be performed: CRL: Missing crlDistributionPoints extension, OCSP: Missing OCSP URI in authorityInfoAccess extension"
|
|
65
79
|
cert # => #<OpenSSL::X509::Certificate...>
|
|
66
80
|
```
|
|
67
81
|
|
|
82
|
+
### Testing when you have the client certificate and Certificate Authority Bundle
|
|
83
|
+
|
|
84
|
+
If you already have access to the client certificate and the CA certificate bundle to check against, you can call `test_cert` which takes a certificate and ca bundle certificate instead of a URL. it has all the same options as `test_url`
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
cert = OpenSSL::X509::Certificate.new(File.read('path/to/certificate')))
|
|
88
|
+
ca_bundle = OpenSSL::X509::Certificate.load(File.read('path/to/ca-bundle-certificate'))
|
|
89
|
+
|
|
90
|
+
valid, error, cert = SSLTest.test_cert(cert, ca_bundle)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
This check will pass for self-signed certificates if the certificate is signed by the ca certificate provided.
|
|
94
|
+
|
|
68
95
|
## How it works
|
|
69
96
|
|
|
70
97
|
SSLTester connects as an HTTPS client (without issuing any requests) and then closes the connection. It does so using ruby `net/https` library and verifies the SSL status. It also hooks into the validation process to intercept the raw certificate for you.
|
|
71
98
|
|
|
72
|
-
After that it
|
|
99
|
+
After that it fetches the [CRL](https://en.wikipedia.org/wiki/Certificate_revocation_list) to verify if the certificate has been revoked. If the CRL is not available it'll query the [OCSP](https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol) endpoint instead. It does this for every certificates in the chain (except the root which is trusted by your Operating System). It is possible the first one will be validated with CRL and the intermediate with OCSP depending on what they offer.
|
|
73
100
|
|
|
74
101
|
### Caching
|
|
75
102
|
|
|
@@ -113,11 +140,11 @@ SSLTest will log various messages depending on the log level you specify, exampl
|
|
|
113
140
|
```
|
|
114
141
|
INFO -- : SSLTest https://www.anonymisation.gov.pf started
|
|
115
142
|
DEBUG -- : SSLTest + test_chain_revocation: www.anonymisation.gov.pf
|
|
143
|
+
DEBUG -- : SSLTest + CRL: [false, "Missing crlDistributionPoints extension", nil]
|
|
116
144
|
DEBUG -- : SSLTest + OCSP: fetch URI http://servicesca.ocsp.certigna.fr
|
|
117
145
|
DEBUG -- : SSLTest + OCSP: 200 OK (4661 bytes)
|
|
118
146
|
DEBUG -- : SSLTest + OCSP: ocsp_ok
|
|
119
147
|
DEBUG -- : SSLTest + test_chain_revocation: Certigna Services CA
|
|
120
|
-
DEBUG -- : SSLTest + OCSP: [false, "Missing OCSP URI in authorityInfoAccess extension", nil]
|
|
121
148
|
DEBUG -- : SSLTest + CRL: fetch URI http://crl.certigna.fr/certigna.crl
|
|
122
149
|
DEBUG -- : SSLTest + CRL: 200 OK (1152 bytes)
|
|
123
150
|
DEBUG -- : SSLTest + CRL: crl_ok
|
|
@@ -140,6 +167,8 @@ But also **revoked certs** like most browsers (not handled by `curl`)
|
|
|
140
167
|
|
|
141
168
|
See also github releases: https://github.com/jarthod/ssl-test/releases
|
|
142
169
|
|
|
170
|
+
* 1.6.0 - 2026-06-16: Check revocation with CRL first and fall back to OCSP (was OCSP first) to reduce revocation detection delay
|
|
171
|
+
* 1.5.0 - 2025-11-28: Add support for local certificates testing and HTTP proxies (#8), changed `#test` method into `#test_url` and `#test_cert` (`#test` remains as an alias for `#test_url` for backward-compatibility)
|
|
143
172
|
* 1.4.1 - 2022-10-24: Add support for "tcps://" scheme
|
|
144
173
|
* 1.4.0 - 2021-01-16: Implemented CRL as fallback to OCSP + expose cache metrics + add logger support
|
|
145
174
|
* 1.3.1 - 2020-04-25: Improved caching of failed OCSP responses (#5)
|
data/lib/ssl-test/crl.rb
CHANGED
|
@@ -13,9 +13,9 @@ module SSLTest
|
|
|
13
13
|
# and building a hash with serial, time and reason takes even more.
|
|
14
14
|
# So doing this would be MUCH faster in terms of CPU for subsequent tests on the same CRL
|
|
15
15
|
# but would take a LOT of memory.
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
16
|
+
# Note: we now check CRL first for every cert in the chain (leaf included), so leaf
|
|
17
|
+
# CRLs are fetched and cached too. These can be large for busy CAs, which makes the
|
|
18
|
+
# memory tradeoff above (caching the raw body rather than the parsed list) even more relevant.
|
|
19
19
|
|
|
20
20
|
private
|
|
21
21
|
|
|
@@ -51,7 +51,7 @@ module SSLTest
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Returns an array with [response, error_message]
|
|
54
|
-
def follow_crl_redirects(uri, open_timeout: 5, read_timeout: 5, redirection_limit: 5)
|
|
54
|
+
def follow_crl_redirects(uri, open_timeout: 5, read_timeout: 5, redirection_limit: 5, proxy_host: nil, proxy_port: nil)
|
|
55
55
|
return [nil, "Too many redirections (> #{redirection_limit})"] if redirection_limit == 0
|
|
56
56
|
|
|
57
57
|
# Return file from cache if not expired
|
|
@@ -61,7 +61,7 @@ module SSLTest
|
|
|
61
61
|
|
|
62
62
|
@logger&.debug { "SSLTest + CRL: fetch URI #{uri}" }
|
|
63
63
|
path = uri.path == "" ? "/" : uri.path
|
|
64
|
-
http = Net::HTTP.new(uri.hostname, uri.port)
|
|
64
|
+
http = Net::HTTP.new(uri.hostname, uri.port, proxy_host, proxy_port)
|
|
65
65
|
http.open_timeout = open_timeout
|
|
66
66
|
http.read_timeout = read_timeout
|
|
67
67
|
|
|
@@ -92,7 +92,7 @@ module SSLTest
|
|
|
92
92
|
}
|
|
93
93
|
[http_response.body, nil]
|
|
94
94
|
when Net::HTTPRedirection
|
|
95
|
-
follow_crl_redirects(URI(http_response["location"]), open_timeout: open_timeout, read_timeout: read_timeout, redirection_limit: redirection_limit - 1)
|
|
95
|
+
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)
|
|
96
96
|
else
|
|
97
97
|
@logger&.debug { "SSLTest + CRL: Error: #{http_response.class}" }
|
|
98
98
|
[nil, "Wrong response type (#{http_response.class})"]
|
data/lib/ssl-test/ocsp.rb
CHANGED
|
@@ -67,12 +67,12 @@ module SSLTest
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
# Returns an array with [response, error_message]
|
|
70
|
-
def follow_ocsp_redirects(uri, data, open_timeout: 5, read_timeout: 5, redirection_limit: 5)
|
|
70
|
+
def follow_ocsp_redirects(uri, data, open_timeout: 5, read_timeout: 5, redirection_limit: 5, proxy_host: nil, proxy_port: nil)
|
|
71
71
|
return [nil, "Too many redirections (> #{redirection_limit})"] if redirection_limit == 0
|
|
72
72
|
|
|
73
73
|
@logger&.debug { "SSLTest + OCSP: fetch URI #{uri}" }
|
|
74
74
|
path = uri.path == "" ? "/" : uri.path
|
|
75
|
-
http = Net::HTTP.new(uri.hostname, uri.port)
|
|
75
|
+
http = Net::HTTP.new(uri.hostname, uri.port, proxy_host, proxy_port)
|
|
76
76
|
http.open_timeout = open_timeout
|
|
77
77
|
http.read_timeout = read_timeout
|
|
78
78
|
|
|
@@ -82,7 +82,7 @@ module SSLTest
|
|
|
82
82
|
@logger&.debug { "SSLTest + OCSP: 200 OK (#{http_response.body.bytesize} bytes)" }
|
|
83
83
|
[http_response.body, nil]
|
|
84
84
|
when Net::HTTPRedirection
|
|
85
|
-
follow_ocsp_redirects(URI(http_response["location"]), data, open_timeout: open_timeout, read_timeout: read_timeout, redirection_limit: redirection_limit - 1)
|
|
85
|
+
follow_ocsp_redirects(URI(http_response["location"]), data, open_timeout: open_timeout, read_timeout: read_timeout, proxy_host: proxy_host, proxy_port: proxy_port, redirection_limit: redirection_limit - 1)
|
|
86
86
|
else
|
|
87
87
|
@logger&.debug { "SSLTest + OCSP: Error: #{http_response.class}" }
|
|
88
88
|
[nil, "Wrong response type (#{http_response.class})"]
|
data/lib/ssl-test.rb
CHANGED
|
@@ -10,16 +10,17 @@ module SSLTest
|
|
|
10
10
|
extend OCSP
|
|
11
11
|
extend CRL
|
|
12
12
|
|
|
13
|
-
VERSION = -"1.
|
|
13
|
+
VERSION = -"1.6.0"
|
|
14
14
|
|
|
15
15
|
class << self
|
|
16
|
-
def
|
|
16
|
+
def test_url url, open_timeout: 5, read_timeout: 5, proxy_host: nil, proxy_port: nil, redirection_limit: 5
|
|
17
|
+
cert = failed_cert_reason = chain = nil
|
|
18
|
+
|
|
17
19
|
uri = URI.parse(url)
|
|
18
20
|
return if uri.scheme != 'https' and uri.scheme != 'tcps'
|
|
19
|
-
cert = failed_cert_reason = chain = nil
|
|
20
21
|
|
|
21
22
|
@logger&.info { "SSLTest #{url} started" }
|
|
22
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
|
23
|
+
http = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port)
|
|
23
24
|
http.open_timeout = open_timeout
|
|
24
25
|
http.read_timeout = read_timeout
|
|
25
26
|
http.use_ssl = true
|
|
@@ -33,25 +34,48 @@ module SSLTest
|
|
|
33
34
|
|
|
34
35
|
begin
|
|
35
36
|
http.start { }
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
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)
|
|
37
39
|
@logger&.info { "SSLTest #{url} finished: revoked=#{revoked} #{message}" }
|
|
38
|
-
return [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
return [!revoked, revocation_message(revoked, revocation_date, message), cert]
|
|
41
|
+
rescue OpenSSL::SSL::SSLError => error
|
|
42
|
+
error_message = parse_ssl_error(error, cert, failed_cert_reason, uri:)
|
|
43
|
+
@logger&.info { "SSLTest #{url} finished: #{error_message}" }
|
|
44
|
+
return [false, error_message, cert]
|
|
45
|
+
rescue => error
|
|
46
|
+
@logger&.error { "SSLTest #{url} failed: #{error.message}" }
|
|
47
|
+
return [nil, "SSL certificate test failed: #{error.message}", cert]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
alias :test :test_url
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_cert client_cert, ca_certs, open_timeout: 5, read_timeout: 5, proxy_host:nil, proxy_port: nil, redirection_limit: 5
|
|
54
|
+
cert = failed_cert_reason = chain = store = nil
|
|
55
|
+
|
|
56
|
+
store = OpenSSL::X509::Store.new
|
|
57
|
+
ca_certs.each { store.add_cert(_1) }
|
|
58
|
+
store.verify_callback = -> (verify_ok, store_context) {
|
|
59
|
+
cert = store_context.current_cert
|
|
60
|
+
chain = store_context.chain
|
|
61
|
+
failed_cert_reason = [store_context.error, store_context.error_string] if store_context.error != 0
|
|
62
|
+
verify_ok
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
begin
|
|
66
|
+
store.verify(client_cert)
|
|
67
|
+
|
|
68
|
+
if failed_cert_reason
|
|
69
|
+
error_message = "error code #{failed_cert_reason[0]}: #{failed_cert_reason[1]}"
|
|
70
|
+
@logger&.info { "SSLTest #{cert.subject.to_s} finished: #{error_message}" }
|
|
71
|
+
return [false, error_message, cert]
|
|
72
|
+
else
|
|
73
|
+
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)
|
|
74
|
+
return [!revoked, revocation_message(revoked, revocation_date, message), cert]
|
|
49
75
|
end
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@logger&.error { "SSLTest #{url} failed: #{e.message}" }
|
|
54
|
-
return [nil, "SSL certificate test failed: #{e.message}", cert]
|
|
76
|
+
rescue => error
|
|
77
|
+
@logger&.error { "SSLTest #{cert.subject.to_s} failed: #{error.message}" }
|
|
78
|
+
return [nil, "SSL certificate test failed: #{error.message}", cert]
|
|
55
79
|
end
|
|
56
80
|
end
|
|
57
81
|
|
|
@@ -81,6 +105,28 @@ module SSLTest
|
|
|
81
105
|
|
|
82
106
|
private
|
|
83
107
|
|
|
108
|
+
def revocation_message(revoked, revocation_date, message)
|
|
109
|
+
if revoked
|
|
110
|
+
"SSL certificate revoked: #{message} (revocation date: #{revocation_date})"
|
|
111
|
+
elsif message
|
|
112
|
+
"Revocation test couldn't be performed: #{message}"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def parse_ssl_error(error, cert, failed_cert_reason, uri:)
|
|
117
|
+
message = error.message
|
|
118
|
+
message = "error code %d: %s" % failed_cert_reason if failed_cert_reason
|
|
119
|
+
if message =~ /certificate verify failed/
|
|
120
|
+
domains = cert_domains(cert)
|
|
121
|
+
if !uri.nil? && matching_domains(domains, uri.host).none?
|
|
122
|
+
message = "hostname \"#{uri.host}\" does not match the server certificate (#{domains.join(', ')})"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
message
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
|
|
84
130
|
# https://docs.ruby-lang.org/en/2.2.0/OpenSSL/OCSP.html
|
|
85
131
|
# https://stackoverflow.com/questions/16244084/how-to-programmatically-check-if-a-certificate-has-been-revoked#answer-16257470
|
|
86
132
|
# Returns an array with [certificate_revoked?, error_reason, revocation_date]
|
|
@@ -90,20 +136,20 @@ module SSLTest
|
|
|
90
136
|
chain[0..-2].each_with_index do |cert, i|
|
|
91
137
|
@logger&.debug { "SSLTest + test_chain_revocation: #{cert_field_to_hash(cert.subject)['CN']}" }
|
|
92
138
|
|
|
93
|
-
# Try with
|
|
94
|
-
ocsp_result = test_ocsp_revocation(cert, issuer: chain[i + 1], chain: chain, **options)
|
|
95
|
-
@logger&.debug { "SSLTest + OCSP: #{ocsp_result}" }
|
|
96
|
-
next if ocsp_result == :ocsp_ok # passed, go to next cert
|
|
97
|
-
return ocsp_result if ocsp_result[0] == true # revoked
|
|
98
|
-
|
|
99
|
-
# Otherwise it means there was an error so let's try with CRL instead
|
|
139
|
+
# Try with CRL first
|
|
100
140
|
crl_result = test_crl_revocation(cert, issuer: chain[i + 1], chain: chain, **options)
|
|
101
141
|
@logger&.debug { "SSLTest + CRL: #{crl_result}" }
|
|
102
142
|
next if crl_result == :crl_ok # passed, go to next cert
|
|
103
143
|
return crl_result if crl_result[0] == true # revoked
|
|
104
144
|
|
|
145
|
+
# Otherwise it means there was an error so let's try with OCSP instead
|
|
146
|
+
ocsp_result = test_ocsp_revocation(cert, issuer: chain[i + 1], chain: chain, **options)
|
|
147
|
+
@logger&.debug { "SSLTest + OCSP: #{ocsp_result}" }
|
|
148
|
+
next if ocsp_result == :ocsp_ok # passed, go to next cert
|
|
149
|
+
return ocsp_result if ocsp_result[0] == true # revoked
|
|
150
|
+
|
|
105
151
|
# If both method failed, return a soft fail with a combination of both error messages
|
|
106
|
-
return [false, "
|
|
152
|
+
return [false, "CRL: #{crl_result[1]}, OCSP: #{ocsp_result[1]}", nil]
|
|
107
153
|
end
|
|
108
154
|
|
|
109
155
|
# If all test passed, the certificate is not revoked
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIG7TCCBdWgAwIBAgIQD4I+q2GZA3ujBecwxBeStjANBgkqhkiG9w0BAQsFADBE
|
|
3
|
+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMR4wHAYDVQQDExVE
|
|
4
|
+
aWdpQ2VydCBFViBSU0EgQ0EgRzIwHhcNMjYwNjA5MDAwMDAwWhcNMjYwNzI1MjM1
|
|
5
|
+
OTU5WjCBwTETMBEGCysGAQQBgjc8AgEDEwJVUzEVMBMGCysGAQQBgjc8AgECEwRV
|
|
6
|
+
dGFoMR0wGwYDVQQPDBRQcml2YXRlIE9yZ2FuaXphdGlvbjEVMBMGA1UEBRMMNTI5
|
|
7
|
+
OTUzNy0wMTQyMQswCQYDVQQGEwJVUzENMAsGA1UECBMEVXRhaDENMAsGA1UEBxME
|
|
8
|
+
TGVoaTEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xGTAXBgNVBAMTEHd3dy5kaWdp
|
|
9
|
+
Y2VydC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDso4J0VSPj
|
|
10
|
+
9L8seWfRT+SDm0gw4xANEk34z3gDbVzCUNvAmi5SQIDxoSpUJaVaprR4wpkXT/di
|
|
11
|
+
WJK7uV2iOozOFZ05cHGBmrv/SQAjZjLhKYHgRXQr/Kuu89IH++nxp9WdT12BEzsS
|
|
12
|
+
WDxVRCissVv8LZBNkH3rJDGSqaW8mLTvfF9DKL3ReXsit5/ibELWnYoOwbG1uPvi
|
|
13
|
+
36Ennp7rR+hckf1bXN638K1/cBQQPAKiv750qxKDwv13XKwV9f3B/3RpRqIUcOAw
|
|
14
|
+
+cuj4nVtWE3+P/pkOEsy7ckH5aV0AIz5bF9prDVSmlYZm69o2Q03cUgt/BqcYkg7
|
|
15
|
+
YqOg203JLBNNAgMBAAGjggNbMIIDVzAfBgNVHSMEGDAWgBRqTlC/mGidW3sgddRZ
|
|
16
|
+
AXlIZpIyBjAdBgNVHQ4EFgQUMxYTQjzRD/R9svhyUBNlsQxeeTowKQYDVR0RBCIw
|
|
17
|
+
IIIQd3d3LmRpZ2ljZXJ0LmNvbYIMZGlnaWNlcnQuY29tMEoGA1UdIARDMEEwCwYJ
|
|
18
|
+
YIZIAYb9bAIBMDIGBWeBDAEBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGln
|
|
19
|
+
aWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH
|
|
20
|
+
AwEwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp
|
|
21
|
+
Z2lDZXJ0RVZSU0FDQUcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQu
|
|
22
|
+
Y29tL0RpZ2lDZXJ0RVZSU0FDQUcyLmNybDBzBggrBgEFBQcBAQRnMGUwJAYIKwYB
|
|
23
|
+
BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTA9BggrBgEFBQcwAoYxaHR0
|
|
24
|
+
cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0RVZSU0FDQUcyLmNydDAM
|
|
25
|
+
BgNVHRMBAf8EAjAAMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgDCMX5XRRmj
|
|
26
|
+
Re5/ON6ykEHrx8IhWiK/f9W1rXaa2Q5SzQAAAZ6rBBTHAAAEAwBHMEUCIQClS0CE
|
|
27
|
+
o9NLQgyRRj+NXa6M5vHiMAeQQXdvxrztgEUfpAIgVPxQCT16MQ2CJVoDwW1hP0//
|
|
28
|
+
QEb7cE3fYpJazoOv/+oAdgDXbX0Q0af1d8LH6V/XAL/5gskzWmXh0LMBcxfAyMVp
|
|
29
|
+
dwAAAZ6rBBSRAAAEAwBHMEUCIQC7NRXmFL0D3t/iLvfezwsB/DyzDuXle3u4BA8L
|
|
30
|
+
CT5LigIgZ5Tmcmgzv42s15QbHNEkgpi1DyocInQgxjo3yyVye94AdQCUTkOH+uzB
|
|
31
|
+
74HzGSQmqBhlAcfTXzgCAT9yZ31VNy4Z2AAAAZ6rBBS1AAAEAwBGMEQCICLSuVkk
|
|
32
|
+
OVVXxrPAzuUj7zs5dpgDAVoVgzQelsixO8H6AiB0bB4SNowTnVZDEJ5knILVRQof
|
|
33
|
+
4OrJVterjy9djCUUMDANBgkqhkiG9w0BAQsFAAOCAQEAMQ+sL8XkSJozMEFlXm3D
|
|
34
|
+
L5gN/ApjW+Yzz1naeWLuoz5qTO6q2mzB6b5F9PyWJH170xRFcY9DrAqY5KfXq2Pu
|
|
35
|
+
2ASgUecTeRWTF4HMgelFelPhlqycpHHCBrxLJkI7X9XNG/ZFVT4VdP8LRofpPM8b
|
|
36
|
+
0eHmt4RkiTKoSpbZbn06nobyb3UD7Snrya8iwMXmdHr5l9rknrmB6eYWbToRB+MN
|
|
37
|
+
PZXeabHjHp+etL8FUMc9HeFwWuI3rB0WstcrSiFtXI2gkdmR3wkMh1lmzTH8XHAx
|
|
38
|
+
61mAo5VRwqC8zWZ0S1RJOFu7H829vDFetORJUbhIKPaYFEtABdOwkWwexeyc1TH0
|
|
39
|
+
nA==
|
|
40
|
+
-----END CERTIFICATE-----
|
|
41
|
+
-----BEGIN CERTIFICATE-----
|
|
42
|
+
MIIFPDCCBCSgAwIBAgIQAWePH++IIlXYsKcOa3uyIDANBgkqhkiG9w0BAQsFADBh
|
|
43
|
+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
|
44
|
+
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
|
|
45
|
+
MjAeFw0yMDA3MDIxMjQyNTBaFw0zMDA3MDIxMjQyNTBaMEQxCzAJBgNVBAYTAlVT
|
|
46
|
+
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxHjAcBgNVBAMTFURpZ2lDZXJ0IEVWIFJT
|
|
47
|
+
QSBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK0eZsx/neTr
|
|
48
|
+
f4MXJz0R2fJTIDfN8AwUAu7hy4gI0vp7O8LAAHx2h3bbf8wl+pGMSxaJK9ffDDCD
|
|
49
|
+
63FqqFBqE9eTmo3RkgQhlu55a04LsXRLcK6crkBOO0djdonybmhrfGrtBqYvbRat
|
|
50
|
+
xenkv0Sg4frhRl4wYh4dnW0LOVRGhbt1G5Q19zm9CqMlq7LlUdAE+6d3a5++ppfG
|
|
51
|
+
cnWLmbEVEcLHPAnbl+/iKauQpQlU1Mi+wEBnjE5tK8Q778naXnF+DsedQJ7NEi+b
|
|
52
|
+
QoonTHEz9ryeEcUHuQTv7nApa/zCqes5lXn1pMs4LZJ3SVgbkTLj+RbBov/uiwTX
|
|
53
|
+
tkBEWawvZH8CAwEAAaOCAgswggIHMB0GA1UdDgQWBBRqTlC/mGidW3sgddRZAXlI
|
|
54
|
+
ZpIyBjAfBgNVHSMEGDAWgBROIlQgGJXm427mD/r6uRLtBhePOTAOBgNVHQ8BAf8E
|
|
55
|
+
BAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQI
|
|
56
|
+
MAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
|
|
57
|
+
cC5kaWdpY2VydC5jb20wewYDVR0fBHQwcjA3oDWgM4YxaHR0cDovL2NybDMuZGln
|
|
58
|
+
aWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDA3oDWgM4YxaHR0cDov
|
|
59
|
+
L2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDCBzgYD
|
|
60
|
+
VR0gBIHGMIHDMIHABgRVHSAAMIG3MCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k
|
|
61
|
+
aWdpY2VydC5jb20vQ1BTMIGKBggrBgEFBQcCAjB+DHxBbnkgdXNlIG9mIHRoaXMg
|
|
62
|
+
Q2VydGlmaWNhdGUgY29uc3RpdHV0ZXMgYWNjZXB0YW5jZSBvZiB0aGUgUmVseWlu
|
|
63
|
+
ZyBQYXJ0eSBBZ3JlZW1lbnQgbG9jYXRlZCBhdCBodHRwczovL3d3dy5kaWdpY2Vy
|
|
64
|
+
dC5jb20vcnBhLXVhMA0GCSqGSIb3DQEBCwUAA4IBAQBSMgrCdY2+O9spnYNvwHiG
|
|
65
|
+
+9lCJbyELR0UsoLwpzGpSdkHD7pVDDFJm3//B8Es+17T1o5Hat+HRDsvRr7d3MEy
|
|
66
|
+
o9iXkkxLhKEgApA2Ft2eZfPrTolc95PwSWnn3FZ8BhdGO4brTA4+zkPSKoMXi/X+
|
|
67
|
+
WLBNN29Z/nbCS7H/qLGt7gViEvTIdU8x+H4l/XigZMUDaVmJ+B5d7cwSK7yOoQdf
|
|
68
|
+
oIBGmA5Mp4LhMzo52rf//kXPfE3wYIZVHqVuxxlnTkFYmffCX9/Lon7SWaGdg6Rc
|
|
69
|
+
k4RHhHLWtmz2lTZ5CEo2ljDsGzCFGJP7oT4q6Q8oFC38irvdKIJ95cUxYzj4tnOI
|
|
70
|
+
-----END CERTIFICATE-----
|
|
71
|
+
-----BEGIN CERTIFICATE-----
|
|
72
|
+
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
|
|
73
|
+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
|
74
|
+
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
|
|
75
|
+
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
|
|
76
|
+
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
|
77
|
+
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
|
|
78
|
+
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
|
|
79
|
+
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
|
|
80
|
+
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
|
|
81
|
+
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
|
|
82
|
+
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
|
|
83
|
+
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
|
|
84
|
+
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
|
|
85
|
+
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
|
|
86
|
+
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
|
|
87
|
+
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
|
|
88
|
+
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
|
|
89
|
+
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
|
|
90
|
+
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
|
|
91
|
+
MrY=
|
|
92
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIG7TCCBdWgAwIBAgIQD4I+q2GZA3ujBecwxBeStjANBgkqhkiG9w0BAQsFADBE
|
|
3
|
+
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMR4wHAYDVQQDExVE
|
|
4
|
+
aWdpQ2VydCBFViBSU0EgQ0EgRzIwHhcNMjYwNjA5MDAwMDAwWhcNMjYwNzI1MjM1
|
|
5
|
+
OTU5WjCBwTETMBEGCysGAQQBgjc8AgEDEwJVUzEVMBMGCysGAQQBgjc8AgECEwRV
|
|
6
|
+
dGFoMR0wGwYDVQQPDBRQcml2YXRlIE9yZ2FuaXphdGlvbjEVMBMGA1UEBRMMNTI5
|
|
7
|
+
OTUzNy0wMTQyMQswCQYDVQQGEwJVUzENMAsGA1UECBMEVXRhaDENMAsGA1UEBxME
|
|
8
|
+
TGVoaTEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xGTAXBgNVBAMTEHd3dy5kaWdp
|
|
9
|
+
Y2VydC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDso4J0VSPj
|
|
10
|
+
9L8seWfRT+SDm0gw4xANEk34z3gDbVzCUNvAmi5SQIDxoSpUJaVaprR4wpkXT/di
|
|
11
|
+
WJK7uV2iOozOFZ05cHGBmrv/SQAjZjLhKYHgRXQr/Kuu89IH++nxp9WdT12BEzsS
|
|
12
|
+
WDxVRCissVv8LZBNkH3rJDGSqaW8mLTvfF9DKL3ReXsit5/ibELWnYoOwbG1uPvi
|
|
13
|
+
36Ennp7rR+hckf1bXN638K1/cBQQPAKiv750qxKDwv13XKwV9f3B/3RpRqIUcOAw
|
|
14
|
+
+cuj4nVtWE3+P/pkOEsy7ckH5aV0AIz5bF9prDVSmlYZm69o2Q03cUgt/BqcYkg7
|
|
15
|
+
YqOg203JLBNNAgMBAAGjggNbMIIDVzAfBgNVHSMEGDAWgBRqTlC/mGidW3sgddRZ
|
|
16
|
+
AXlIZpIyBjAdBgNVHQ4EFgQUMxYTQjzRD/R9svhyUBNlsQxeeTowKQYDVR0RBCIw
|
|
17
|
+
IIIQd3d3LmRpZ2ljZXJ0LmNvbYIMZGlnaWNlcnQuY29tMEoGA1UdIARDMEEwCwYJ
|
|
18
|
+
YIZIAYb9bAIBMDIGBWeBDAEBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGln
|
|
19
|
+
aWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH
|
|
20
|
+
AwEwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp
|
|
21
|
+
Z2lDZXJ0RVZSU0FDQUcyLmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQu
|
|
22
|
+
Y29tL0RpZ2lDZXJ0RVZSU0FDQUcyLmNybDBzBggrBgEFBQcBAQRnMGUwJAYIKwYB
|
|
23
|
+
BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTA9BggrBgEFBQcwAoYxaHR0
|
|
24
|
+
cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0RVZSU0FDQUcyLmNydDAM
|
|
25
|
+
BgNVHRMBAf8EAjAAMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgDCMX5XRRmj
|
|
26
|
+
Re5/ON6ykEHrx8IhWiK/f9W1rXaa2Q5SzQAAAZ6rBBTHAAAEAwBHMEUCIQClS0CE
|
|
27
|
+
o9NLQgyRRj+NXa6M5vHiMAeQQXdvxrztgEUfpAIgVPxQCT16MQ2CJVoDwW1hP0//
|
|
28
|
+
QEb7cE3fYpJazoOv/+oAdgDXbX0Q0af1d8LH6V/XAL/5gskzWmXh0LMBcxfAyMVp
|
|
29
|
+
dwAAAZ6rBBSRAAAEAwBHMEUCIQC7NRXmFL0D3t/iLvfezwsB/DyzDuXle3u4BA8L
|
|
30
|
+
CT5LigIgZ5Tmcmgzv42s15QbHNEkgpi1DyocInQgxjo3yyVye94AdQCUTkOH+uzB
|
|
31
|
+
74HzGSQmqBhlAcfTXzgCAT9yZ31VNy4Z2AAAAZ6rBBS1AAAEAwBGMEQCICLSuVkk
|
|
32
|
+
OVVXxrPAzuUj7zs5dpgDAVoVgzQelsixO8H6AiB0bB4SNowTnVZDEJ5knILVRQof
|
|
33
|
+
4OrJVterjy9djCUUMDANBgkqhkiG9w0BAQsFAAOCAQEAMQ+sL8XkSJozMEFlXm3D
|
|
34
|
+
L5gN/ApjW+Yzz1naeWLuoz5qTO6q2mzB6b5F9PyWJH170xRFcY9DrAqY5KfXq2Pu
|
|
35
|
+
2ASgUecTeRWTF4HMgelFelPhlqycpHHCBrxLJkI7X9XNG/ZFVT4VdP8LRofpPM8b
|
|
36
|
+
0eHmt4RkiTKoSpbZbn06nobyb3UD7Snrya8iwMXmdHr5l9rknrmB6eYWbToRB+MN
|
|
37
|
+
PZXeabHjHp+etL8FUMc9HeFwWuI3rB0WstcrSiFtXI2gkdmR3wkMh1lmzTH8XHAx
|
|
38
|
+
61mAo5VRwqC8zWZ0S1RJOFu7H829vDFetORJUbhIKPaYFEtABdOwkWwexeyc1TH0
|
|
39
|
+
nA==
|
|
40
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIFSzCCBDOgAwIBAgIQSueVSfqavj8QDxekeOFpCTANBgkqhkiG9w0BAQsFADCB
|
|
3
|
+
kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
|
4
|
+
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV
|
|
5
|
+
BAMTLUNPTU9ETyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD
|
|
6
|
+
QTAeFw0xNTA0MDkwMDAwMDBaFw0xNTA0MTIyMzU5NTlaMFkxITAfBgNVBAsTGERv
|
|
7
|
+
bWFpbiBDb250cm9sIFZhbGlkYXRlZDEdMBsGA1UECxMUUG9zaXRpdmVTU0wgV2ls
|
|
8
|
+
ZGNhcmQxFTATBgNVBAMUDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
|
|
9
|
+
ggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2PmzA
|
|
10
|
+
S2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMWhyef
|
|
11
|
+
dOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3AxPxT
|
|
12
|
+
uW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqveww9H
|
|
13
|
+
dFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SYQCeF
|
|
14
|
+
xxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaOCAdUwggHRMB8GA1Ud
|
|
15
|
+
IwQYMBaAFJCvajqUWgvYkOoSVnPfQ7Q6KNrnMB0GA1UdDgQWBBSd7sF7gQs6R2lx
|
|
16
|
+
GH0RN5O8pRs/+zAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUE
|
|
17
|
+
FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQIC
|
|
18
|
+
BzArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAI
|
|
19
|
+
BgZngQwBAgEwVAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5jb21vZG9jYS5j
|
|
20
|
+
b20vQ09NT0RPUlNBRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCB
|
|
21
|
+
hQYIKwYBBQUHAQEEeTB3ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LmNvbW9kb2Nh
|
|
22
|
+
LmNvbS9DT01PRE9SU0FEb21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0
|
|
23
|
+
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wIwYDVR0RBBww
|
|
24
|
+
GoIMKi5iYWRzc2wuY29tggpiYWRzc2wuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBq
|
|
25
|
+
evHa/wMHcnjFZqFPRkMOXxQhjHUa6zbgH6QQFezaMyV8O7UKxwE4PSf9WNnM6i1p
|
|
26
|
+
OXy+l+8L1gtY54x/v7NMHfO3kICmNnwUW+wHLQI+G1tjWxWrAPofOxkt3+IjEBEH
|
|
27
|
+
fnJ/4r+3ABuYLyw/zoWaJ4wQIghBK4o+gk783SHGVnRwpDTysUCeK1iiWQ8dSO/r
|
|
28
|
+
ET7BSp68ZVVtxqPv1dSWzfGuJ/ekVxQ8lEEFeouhN0fX9X3c+s5vMaKwjOrMEpsi
|
|
29
|
+
8TRwz311SotoKQwe6Zaoz7ASH1wq7mcvf71z81oBIgxw+s1F73hczg36TuHvzmWf
|
|
30
|
+
RwxPuzZEaFZcVlmtqoq8
|
|
31
|
+
-----END CERTIFICATE-----
|
|
32
|
+
-----BEGIN CERTIFICATE-----
|
|
33
|
+
MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB
|
|
34
|
+
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
|
35
|
+
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
|
|
36
|
+
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy
|
|
37
|
+
MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
|
|
38
|
+
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
|
|
39
|
+
Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh
|
|
40
|
+
bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
|
41
|
+
ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh
|
|
42
|
+
bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0
|
|
43
|
+
Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6
|
|
44
|
+
ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51
|
|
45
|
+
UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n
|
|
46
|
+
c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY
|
|
47
|
+
MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz
|
|
48
|
+
30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
|
|
49
|
+
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG
|
|
50
|
+
BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv
|
|
51
|
+
bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB
|
|
52
|
+
AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E
|
|
53
|
+
T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
|
|
54
|
+
ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p
|
|
55
|
+
mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/
|
|
56
|
+
e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps
|
|
57
|
+
P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY
|
|
58
|
+
dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc
|
|
59
|
+
2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG
|
|
60
|
+
V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4
|
|
61
|
+
HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX
|
|
62
|
+
j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII
|
|
63
|
+
0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap
|
|
64
|
+
lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf
|
|
65
|
+
+AZxAeKCINT+b72x
|
|
66
|
+
-----END CERTIFICATE-----
|
|
67
|
+
-----BEGIN CERTIFICATE-----
|
|
68
|
+
MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
|
|
69
|
+
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
|
70
|
+
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
|
|
71
|
+
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
|
|
72
|
+
MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
|
|
73
|
+
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
|
|
74
|
+
Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
|
|
75
|
+
dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
|
|
76
|
+
6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
|
|
77
|
+
pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
|
|
78
|
+
9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
|
|
79
|
+
/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
|
|
80
|
+
Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
|
|
81
|
+
+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
|
|
82
|
+
qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
|
|
83
|
+
SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
|
|
84
|
+
u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
|
|
85
|
+
Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
|
|
86
|
+
crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
|
|
87
|
+
FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
|
|
88
|
+
/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
|
|
89
|
+
wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
|
|
90
|
+
4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
|
|
91
|
+
2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
|
|
92
|
+
FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
|
|
93
|
+
CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
|
|
94
|
+
boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
|
|
95
|
+
jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
|
|
96
|
+
S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
|
|
97
|
+
QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
|
|
98
|
+
0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
|
|
99
|
+
NVOFBkpdn627G190
|
|
100
|
+
-----END CERTIFICATE-----
|