Przeglądaj źródła

Certificate trust chain check

new-scoring
aeris 2 lat temu
rodzic
commit
e28b857213

+ 1
- 0
lib/cryptcheck.rb Wyświetl plik

@@ -38,6 +38,7 @@ module CryptCheck
38 38
 		autoload :Method, 'cryptcheck/tls/method'
39 39
 		autoload :Cipher, 'cryptcheck/tls/cipher'
40 40
 		autoload :Curve, 'cryptcheck/tls/curve'
41
+		autoload :Cert, 'cryptcheck/tls/cert'
41 42
 		autoload :Server, 'cryptcheck/tls/server'
42 43
 		autoload :TcpServer, 'cryptcheck/tls/server'
43 44
 		autoload :UdpServer, 'cryptcheck/tls/server'

+ 19
- 0
lib/cryptcheck/tls/cert.rb Wyświetl plik

@@ -1,6 +1,10 @@
1 1
 module CryptCheck
2 2
 	module Tls
3 3
 		class Cert
4
+			DEFAULT_CA_DIRECTORIES = [
5
+					'/usr/share/ca-certificates/mozilla'
6
+			]
7
+
4 8
 			SIGNATURE_ALGORITHMS = {
5 9
 					'dsaWithSHA'                             => %i(sha1 dss),
6 10
 					'dsaWithSHA1'                            => %i(sha1 dss),
@@ -48,6 +52,21 @@ module CryptCheck
48 52
 					end
49 53
 				RUBY_EVAL
50 54
 			end
55
+
56
+			def self.trusted?(cert, chain, roots: DEFAULT_CA_DIRECTORIES)
57
+				store         = ::OpenSSL::X509::Store.new
58
+				store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
59
+				store.add_chains roots
60
+				chain.each do |cert|
61
+					# Never add other self signed certificates than system CA !
62
+					next if cert.subject == cert.issuer
63
+					store.add_cert cert rescue nil
64
+				end
65
+
66
+				trusted = store.verify cert
67
+				return :trusted if trusted
68
+				store.error_string
69
+			end
51 70
 		end
52 71
 	end
53 72
 end

+ 21
- 0
lib/cryptcheck/tls/fixture.rb Wyświetl plik

@@ -154,3 +154,24 @@ class ::OpenSSL::PKey::DH
154 154
 		end
155 155
 	end
156 156
 end
157
+
158
+class ::OpenSSL::X509::Store
159
+	def add_chains(chains)
160
+		chains = [chains] unless chains.is_a? Enumerable
161
+		chains.each do |chain|
162
+			case chain
163
+				when ::OpenSSL::X509::Certificate
164
+					self.add_cert chain
165
+				else
166
+					if File.directory?(chain)
167
+						Dir.entries(chain)
168
+								.collect { |e| File.join chain, e }
169
+								.select { |e| File.file? e }
170
+								.each { |f| self.add_file f }
171
+					else
172
+						self.add_file chain
173
+					end
174
+			end
175
+		end
176
+	end
177
+end

+ 32
- 0
spec/cryptcheck/cert_spec.rb Wyświetl plik

@@ -0,0 +1,32 @@
1
+describe CryptCheck::Tls::Cert do
2
+	def load_chain(chain)
3
+		chain.collect { |f| ::OpenSSL::X509::Certificate.new File.read File.join 'spec/resources', "#{f}.crt" }
4
+	end
5
+
6
+	describe '::trusted?' do
7
+		it 'must accept valid certificat' do
8
+			cert, *chain, ca = load_chain %w(custom intermediate ca)
9
+			trust                  = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
10
+			expect(trust).to eq :trusted
11
+		end
12
+
13
+		it 'must reject self signed certificate' do
14
+			cert, ca = load_chain %w(self-signed ca)
15
+			trust                  = ::CryptCheck::Tls::Cert.trusted? cert, [], roots: ca
16
+			expect(trust).to eq 'self signed certificate'
17
+		end
18
+
19
+		it 'must reject unknown CA' do
20
+			cert, *chain = load_chain %w(custom intermediate ca)
21
+			trust        = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: []
22
+			expect(trust).to eq 'unable to get issuer certificate'
23
+		end
24
+
25
+		it 'must reject missing intermediate chain' do
26
+			cert, ca = load_chain %w(custom ca)
27
+			chain   = []
28
+			trust   = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
29
+			expect(trust).to eq 'unable to get local issuer certificate'
30
+		end
31
+	end
32
+end

+ 13
- 0
spec/resources/ca.crt Wyświetl plik

@@ -0,0 +1,13 @@
1
+-----BEGIN CERTIFICATE-----
2
+MIIB7zCCAXWgAwIBAgIJAKFu2k3vOIffMAoGCCqGSM49BAMEMBIxEDAOBgNVBAMM
3
+B3Rlc3QtY2EwHhcNMTcwMTIyMTg1NTUxWhcNMTgwMTIyMTg1NTUxWjASMRAwDgYD
4
+VQQDDAd0ZXN0LWNhMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhVE2pSx4GG922yqA
5
+z0W0usG8dFdY4qtTD5mwwBzRhu9NegzQmaE5oHNzQrQE8v0/ShrSHNdID6Phty9K
6
+lPYoenUmpH0sdJDqQ5cVUDkmw0+f+XpROtCiBcN8kTmiVXQ5o4GWMIGTMA8GA1Ud
7
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgL0MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr
8
+BgEFBQcDAjAdBgNVHQ4EFgQU2saIfk29nr+adaNemnS2AaNjXJEwHwYDVR0jBBgw
9
+FoAU2saIfk29nr+adaNemnS2AaNjXJEwFAYDVR0RBA0wC4IJbG9jYWxob3N0MAoG
10
+CCqGSM49BAMEA2gAMGUCMQCzxeexb5HauoM8OQPBK7MWxzganLfVoi1GCsbvjUQy
11
+AB8AAVijIPwT/MGcigge4z8CMFimJXl934AtL8iM+Jd9ykvNXXxzSn9YRm9aLD3K
12
+w6vam+k+gA4sdijDbRC/Tc/3NQ==
13
+-----END CERTIFICATE-----

+ 13
- 0
spec/resources/custom.crt Wyświetl plik

@@ -0,0 +1,13 @@
1
+-----BEGIN CERTIFICATE-----
2
+MIIB6jCCAXCgAwIBAgIJAKyx4KGEOyVdMAoGCCqGSM49BAMEMBwxGjAYBgNVBAMM
3
+EXRlc3QtaW50ZXJtZWRpYXRlMB4XDTE3MDEyMjE4NTU1MVoXDTE4MDEyMjE4NTU1
4
+MVowFDESMBAGA1UEAwwJdGVzdC1sZWFmMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE
5
+kZFi7jp4Z+3m1lR/aIHuNalLQtjaCErIgrWhFL7oUjzWMN1dR3nAmmosKlCSRc7A
6
+Xazs+CC0QB1LgsZCFFPhPqUd5456iwCHaSVQ3maESrZtzJo78v/fE9HRuuh5fFiL
7
+o4GFMIGCMAsGA1UdDwQEAwIE8DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH
8
+AwIwHQYDVR0OBBYEFB54cEd+wLKHpMKYkYCxmSgWERrQMB8GA1UdIwQYMBaAFMgN
9
+6Mqlnk3ZRmp4RrAXXKeC3yVHMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjO
10
+PQQDBANoADBlAjEAwbhbwXjekyl3esK9ywh+jKCVhf7BzaF4H7LAxUE1PmXTORrZ
11
+tqz2MXK3/zYfe1bXAjAuan+xZ4d5zCgBvnFO2/LMEX07SFQJT3l1hKAZjpbdNm/K
12
+MY23IR6iLWkPlG1u+Wo=
13
+-----END CERTIFICATE-----

+ 13
- 0
spec/resources/intermediate.crt Wyświetl plik

@@ -0,0 +1,13 @@
1
+-----BEGIN CERTIFICATE-----
2
+MIIB+TCCAX+gAwIBAgIJAOko1FM8hOfNMAoGCCqGSM49BAMEMBIxEDAOBgNVBAMM
3
+B3Rlc3QtY2EwHhcNMTcwMTIyMTg1NTUxWhcNMTgwMTIyMTg1NTUxWjAcMRowGAYD
4
+VQQDDBF0ZXN0LWludGVybWVkaWF0ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABNjg
5
+qyABIHj96OvYN1YCe+z3mILDlm1qNXm1bpoMcx7AVANk+AFUjbK/mhSyx5ONbBw/
6
+4kMBNtVW7OpkiZwLr57SbqDv0n4ExirUvvBm7OcqqSY+73lXM/cezMTRA/3ZqqOB
7
+ljCBkzAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIC9DAdBgNVHSUEFjAUBggr
8
+BgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFMgN6Mqlnk3ZRmp4RrAXXKeC3yVH
9
+MB8GA1UdIwQYMBaAFNrGiH5NvZ6/mnWjXpp0tgGjY1yRMBQGA1UdEQQNMAuCCWxv
10
+Y2FsaG9zdDAKBggqhkjOPQQDBANoADBlAjAUAte4U3OtzmeQLA/Cq1JTtsrE7sy9
11
+kZzxGHxACZ53sTGA2c4K86lR2RGoXYvW62wCMQCNSLH+qukadu52ip7HTkihrtae
12
+hBVOBO+el6rCcby91xUuWU24AJy9Ce9TxcQC384=
13
+-----END CERTIFICATE-----

+ 13
- 0
spec/resources/self-signed.crt Wyświetl plik

@@ -0,0 +1,13 @@
1
+-----BEGIN CERTIFICATE-----
2
+MIICBjCCAYugAwIBAgIJAPnnJnLp7H/XMAoGCCqGSM49BAMEMBQxEjAQBgNVBAMM
3
+CWxvY2FsaG9zdDAeFw0xNzAxMjIxNjM1NDdaFw0xODAxMjIxNjM1NDdaMBQxEjAQ
4
+BgNVBAMMCWxvY2FsaG9zdDB2MBAGByqGSM49AgEGBSuBBAAiA2IABJvRcgAMkjzZ
5
+p0YD/mXa2Td8sy7fBr7F5Sj8toSmLAxkxxPCnm9DDdLQXy7IZXA1HJkiRUIJ8BTk
6
+gSxmKQBwl3my2quHGx7GSZshpER4tRtqWI21dTUkuu9bGR66bbLa8aOBqDCBpTAP
7
+BgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIC9DAdBgNVHSUEFjAUBggrBgEFBQcD
8
+AQYIKwYBBQUHAwIwHQYDVR0OBBYEFCEkGXQc44mMopATg1jr+stKnF4LMB8GA1Ud
9
+IwQYMBaAFCEkGXQc44mMopATg1jr+stKnF4LMBQGA1UdEQQNMAuCCWxvY2FsaG9z
10
+dDAQBggrBgEFBQcBGAEB/wQBMDAKBggqhkjOPQQDBANpADBmAjEAkPKxToKRloWT
11
+eH4lGaUrqBGpRof92rWmJiBLs5WnaYM73S/GdKNK1j0jKRCKXKpzAjEAgpjvaUhd
12
+qXkR3g8iWedrFjkVHHVrUGV9JW7elHP7bD6XryqsGRNK2X8yq0J616gP
13
+-----END CERTIFICATE-----

Ładowanie…
Anuluj
Zapisz