Handle case of multiple certificates

new-scoring
aeris 7 years ago
parent 845626ee45
commit 61032231b2
  1. 84
      lib/cryptcheck/tls/server.rb

@ -35,20 +35,15 @@ module CryptCheck
def initialize(hostname, family, ip, port)
@hostname, @family, @ip, @port = hostname, family, ip, port
@dh = []
Logger.info { name.colorize :perfect }
extract_cert
Logger.info { '' }
Logger.info { "Key : #{Tls.key_to_s self.key}" }
@chains = []
Logger.info { name.colorize :blue }
fetch_prefered_ciphers
check_supported_cipher
verify_certs
check_fallback_scsv
uniq_dh
end
def key
@cert.public_key
end
def cipher_size
supported_ciphers.collect { |c| c.size }.min
end
@ -73,6 +68,14 @@ module CryptCheck
RUBY_EVAL
end
def key_status
Status[@keys]
end
def dh_status
Status[@dh]
end
SIGNATURE_ALGORITHMS = {
'dsaWithSHA' => %i(sha1 dss),
'dsaWithSHA1' => %i(sha1 dss),
@ -114,7 +117,9 @@ module CryptCheck
%i(md2 mdc2 md4 md5 ripemd160 sha sha1 sha2 rsa dss ecc ghost).each do |name|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{name}_sig?
SIGNATURE_ALGORITHMS[@cert.signature_algorithm].include? :#{name}
@chains.any? do |chain|
SIGNATURE_ALGORITHMS[chain[:cert].signature_algorithm].include? :#{name}
end
end
RUBY_EVAL
end
@ -127,10 +132,6 @@ module CryptCheck
RUBY_EVAL
end
def key_size
@cert.public_key.size
end
def ssl?
sslv2? or sslv3?
end
@ -253,15 +254,20 @@ module CryptCheck
end
end
# secp192r1 secp256r1
SUPPORTED_CURVES = %w(secp160k1 secp160r1 secp160r2 sect163k1
sect163r1 sect163r2 secp192k1 sect193r1 sect193r2 secp224k1
secp224r1 sect233k1 sect233r1 sect239k1 secp256k1 sect283k1
sect283r1 secp384r1 sect409k1 sect409r1 secp521r1 sect571k1
sect571r1 X25519)
# SUPPORTED_CURVES = %w(sect163k1 sect163r1 sect163r2 sect193r1
# sect193r2 sect233k1 sect233r1 sect239k1 sect283k1 sect283r1
# sect409k1 sect409r1 sect571k1 sect571r1 secp160k1 secp160r1
# secp160r2 secp192k1 secp192r1 secp224k1 secp224r1 secp256k1
# secp256r1 secp384r1 secp521r1
# prime256v1
# brainpoolP256r1 brainpoolP384r1 brainpoolP512r1)
SUPPORTED_CURVES = %w(secp256k1 sect283k1 sect283r1 secp384r1
sect409k1 sect409r1 secp521r1 sect571k1 sect571r1
prime192v1 prime256v1
brainpoolP256r1 brainpoolP384r1 brainpoolP512r1)
def ssl_client(method, ciphers = %w(ALL COMPLEMENTOFALL), curves = nil, fallback: false, &block)
ssl_context = ::OpenSSL::SSL::SSLContext.new method #, fallback_scsv: fallback
ssl_context = ::OpenSSL::SSL::SSLContext.new method
ssl_context.enable_fallback_scsv if fallback
ssl_context.ciphers = ciphers.join ':'
@ -278,20 +284,24 @@ module CryptCheck
end
end
def extract_cert
EXISTING_METHODS.each do |method|
next unless SUPPORTED_METHODS.include? method
begin
@cert, @chain = ssl_client(method) { |s| [s.peer_cert, s.peer_cert_chain] }
Logger.debug { "Certificate #{@cert.subject}" }
break
rescue Timeout, TLSTimeout, ConnectionError, ::SystemCallError
raise
end
def verify_certs
Logger.info { '' }
view = {}
@chains.each do |cert, chain|
id = cert.subject, cert.serial, cert.issuer
next if view.include? id
subject, serial, issuer = id
key = cert.public_key
Logger.info { "Certificate #{subject} [#{serial}] issued by #{issuer}" }
Logger.info { "Key : #{Tls.key_to_s key }" }
valid = ::OpenSSL::SSL.verify_certificate_identity cert, (@hostname || @ip)
trusted = verify_trust chain, cert
view[id] = { cert: cert, chain: chain, key: key, valid: valid, trusted: trusted }
end
raise TLSNotAvailableException unless @cert
@cert_valid = ::OpenSSL::SSL.verify_certificate_identity @cert, (@hostname || @ip)
@cert_trusted = verify_trust @chain, @cert
@chains = view.values
@keys = @chains.collect { |c| c[:key] }
end
def prefered_cipher(method)
@ -319,8 +329,12 @@ module CryptCheck
end
def supported_cipher?(method, cipher, curves = nil)
dh = ssl_client(method, [cipher], curves) { |s| s.tmp_key }
cert, chain, dh = ssl_client(method, [cipher], curves) do |s|
[s.peer_cert, s.peer_cert_chain, s.tmp_key]
end
@chains << [cert, chain]
@dh << dh if dh
p dh.group.curve_name
cipher = Cipher.new method, cipher, dh
dh = dh ? " (#{'PFS'.colorize :good} : #{Tls.key_to_s dh})" : ''
@ -348,7 +362,7 @@ module CryptCheck
available_ciphers = available_ciphers method
available_ciphers.each do |c|
cipher = Cipher.new method, c
cipher = Cipher.new method, c
supported = supported_cipher? method, c.first
if supported
if cipher.ecdhe?

Loading…
Cancel
Save