Browse Source

Encapsulate certificate/chain

new-scoring
aeris 2 years ago
parent
commit
5c08e8c44b
2 changed files with 53 additions and 27 deletions
  1. 40
    5
      lib/cryptcheck/tls/cert.rb
  2. 13
    22
      lib/cryptcheck/tls/server.rb

+ 40
- 5
lib/cryptcheck/tls/cert.rb View File

@@ -45,17 +45,24 @@ module CryptCheck
45 45
 
46 46
 			%i(md2 mdc2 md4 md5 ripemd160 sha sha1 sha2 rsa dss ecc ghost).each do |name|
47 47
 				class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
48
-					def #{name}_sig?
49
-						@chains.any? do |chain|
50
-							SIGNATURE_ALGORITHMS[chain[:cert].signature_algorithm].include? :#{name}
51
-						end
48
+					def #{name}?
49
+						SIGNATURE_ALGORITHMS[@cert.signature_algorithm].include? :#{name}
52 50
 					end
53 51
 				RUBY_EVAL
54 52
 			end
55 53
 
54
+			def initialize(cert, chain=[])
55
+				@cert, @chain = case cert
56
+									when ::OpenSSL::X509::Certificate
57
+										[cert, chain]
58
+									when ::OpenSSL::SSL::SSLSocket
59
+										[cert.peer_cert, cert.peer_cert_chain]
60
+								end
61
+			end
62
+
56 63
 			def self.trusted?(cert, chain, roots: DEFAULT_CA_DIRECTORIES)
57 64
 				store         = ::OpenSSL::X509::Store.new
58
-				store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
65
+				store.purpose = ::OpenSSL::X509::PURPOSE_SSL_CLIENT
59 66
 				store.add_chains roots
60 67
 				chain.each do |cert|
61 68
 					# Never add other self signed certificates than system CA !
@@ -67,6 +74,34 @@ module CryptCheck
67 74
 				return :trusted if trusted
68 75
 				store.error_string
69 76
 			end
77
+
78
+			def trusted?(roots: DEFAULT_CA_DIRECTORIES)
79
+				Cert.trusted? @cert, @chain, roots: roots
80
+			end
81
+
82
+			def valid?(host)
83
+				::OpenSSL::SSL.verify_certificate_identity @cert, host
84
+			end
85
+
86
+			def fingerprint
87
+				::OpenSSL::Digest::SHA256.hexdigest @cert.to_der
88
+			end
89
+
90
+			def key
91
+				@cert.public_key
92
+			end
93
+
94
+			def subject
95
+				@cert.subject
96
+			end
97
+
98
+			def serial
99
+				@cert.serial
100
+			end
101
+
102
+			def issuer
103
+				@cert.issuer
104
+			end
70 105
 		end
71 106
 	end
72 107
 end

+ 13
- 22
lib/cryptcheck/tls/server.rb View File

@@ -447,29 +447,21 @@ module CryptCheck
447 447
 				# Let's begin the fun
448 448
 				# First, collect "standard" connections
449 449
 				# { method => { cipher => connection, ... }, ... }
450
-				certs = @supported_ciphers.values.collect(&:values).flatten 1
450
+				certs  = @supported_ciphers.values.collect(&:values).flatten 1
451 451
 				# Then, collect "ecdsa" connections
452 452
 				# { curve => connection, ... }
453
-				certs += @ecdsa_certs.values
454
-				# Then, fetch cert and chain
455
-				certs = certs.collect { |c| [c.peer_cert, c.peer_cert_chain] }
456
-				# Then, filter cert to keep uniq subject + issuer + serial
457
-				#certs = certs.uniq { |c, _| [c.subject, c.serial, c.issuer] }
453
+				certs  += @ecdsa_certs.values
454
+				# Then, fetch cert
455
+				certs  = certs.collect { |c| Cert.new c }
458 456
 				# Then, filter cert to keep uniq fingerprint
459
-				certs = certs.uniq { |c, _| OpenSSL::Digest::SHA256.hexdigest c.to_der }
460
-
461
-				view = {}
462
-				certs.each do |cert, chain|
463
-					id = cert.subject, cert.serial, cert.issuer
464
-					next if view.include? id
465
-					subject, serial, issuer = id
466
-					key                     = cert.public_key
467
-
468
-					identity = ::OpenSSL::SSL.verify_certificate_identity cert, (@hostname || @ip)
469
-					trust    = Cert.trusted? cert, chain
470
-					view[id] = { cert: cert, chain: chain, key: key, identity: identity, trust: trust }
471
-					Logger.info { "  Certificate #{subject} [#{serial}] issued by #{issuer}" }
472
-					Logger.info { '    Key : ' +  Tls.key_to_s(key) }
457
+				@certs = certs.uniq { |c| c.fingerprint }
458
+
459
+				@certs.each do |cert|
460
+					key      = cert.key
461
+					identity = cert.valid?(@hostname || @ip)
462
+					trust    = cert.trusted?
463
+					Logger.info { "  Certificate #{cert.subject} [#{cert.serial}] issued by #{cert.issuer}" }
464
+					Logger.info { '    Key : ' + Tls.key_to_s(key) }
473 465
 					if identity
474 466
 						Logger.info { '    Identity : ' + 'valid'.colorize(:good) }
475 467
 					else
@@ -481,8 +473,7 @@ module CryptCheck
481 473
 						Logger.info { '    Trust : ' + 'untrusted'.colorize(:error) + ' - ' + trust }
482 474
 					end
483 475
 				end
484
-				@chains = view.values
485
-				@keys   = @chains.collect { |c| c[:key] }
476
+				@keys   = @certs.collect &:key
486 477
 			end
487 478
 
488 479
 			def uniq_dh

Loading…
Cancel
Save