diff --git a/lib/cryptcheck/tls/cert.rb b/lib/cryptcheck/tls/cert.rb index d34b214..52ab0be 100644 --- a/lib/cryptcheck/tls/cert.rb +++ b/lib/cryptcheck/tls/cert.rb @@ -42,6 +42,9 @@ module CryptCheck 'id_GostR3411_94_with_GostR3410_94_cc' => %i(ghost), 'id_GostR3411_94_with_GostR3410_2001_cc' => %i(ghost) } + WEAK_SIGN = { + critical: %i(mdc2 md2 md4 md5 sha sha1) + } %i(md2 mdc2 md4 md5 ripemd160 sha sha1 sha2 rsa dss ecc ghost).each do |name| class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 diff --git a/lib/cryptcheck/tls/grade.rb b/lib/cryptcheck/tls/grade.rb index 51f5dec..30c637c 100644 --- a/lib/cryptcheck/tls/grade.rb +++ b/lib/cryptcheck/tls/grade.rb @@ -7,7 +7,7 @@ module CryptCheck @server = server @checks = checks @states = calculate_states - @grade = calculate_grade + @grade = calculate_grade end def display @@ -68,22 +68,17 @@ module CryptCheck 'A+' end - CHECKS = [ + CHECKS = ([ + # Certificates + [:weak_sign, Proc.new { |s| + Cert::WEAK_SIGN[:critical] + }, :critical], + # Keys - [:dss_sign, Proc.new { |s| s.dss_sig? }, :critical], - [:weak_key, Proc.new { |s| Status.problem s.key_status } ], + [:weak_key, Proc.new { |s| Status.problem s.keys.collect &:status }], # DH - [:weak_dh, Proc.new { |s| Status.problem s.dh_status } ], - - # Certificates - [:md2_sign, Proc.new { |s| s.md2_sig? }, :critical], - [:mdc2_sign, Proc.new { |s| s.mdc2_sig? }, :critical], - [:md4_sign, Proc.new { |s| s.md4_sig? }, :critical], - [:md5_sign, Proc.new { |s| s.md5_sig? }, :critical], - [:sha_sign, Proc.new { |s| s.sha_sig? }, :critical], - - [:sha1_sign, Proc.new { |s| s.sha1_sig? }, :warning], + [:weak_dh, Proc.new { |s| Status.problem s.dh.collect &:status }], # Protocols [:ssl, Proc.new { |s| s.ssl? }, :critical], @@ -111,14 +106,18 @@ module CryptCheck [:aead, Proc.new { |s| s.aead? }, :good], #[:aead_only, Proc.new { |s| s.aead_only? }, :best], - ] + ] + Cert::WEAK_SIGN.collect do |level, hashes| + hashes.collect do |hash| + ["#{hash}_sig?".to_sym, Proc.new { |s| s.certs.any? &"#{hash}?".to_sym }, level ] + end + end.flatten(1)).freeze def checks checks = CHECKS unless @server.fallback_scsv? == nil checks += [ - [:no_fallback_scsv, Proc.new { |s| not s.fallback_scsv? }, :error], - [:fallback_scsv, Proc.new { |s| s.fallback_scsv? }, :good] + [:no_fallback_scsv, Proc.new { |s| not s.fallback_scsv? }, :error], + [:fallback_scsv, Proc.new { |s| s.fallback_scsv? }, :good] ] end checks diff --git a/lib/cryptcheck/tls/server.rb b/lib/cryptcheck/tls/server.rb index ec71ecb..0dee213 100644 --- a/lib/cryptcheck/tls/server.rb +++ b/lib/cryptcheck/tls/server.rb @@ -28,6 +28,8 @@ module CryptCheck class ConnectionError < ::StandardError end + attr_reader :certs, :keys, :dh + def initialize(hostname, family, ip, port) @hostname, @family, @ip, @port = hostname, family, ip, port @dh = [] @@ -48,6 +50,7 @@ module CryptCheck check_fallback_scsv verify_certs + exit end def supported_method?(method) @@ -105,7 +108,7 @@ module CryptCheck ab = ssl_client(method, [a, b]).cipher.first ba = ssl_client(method, [b, a]).cipher.first if ab != ba - Logger.info { " #{method} : " + 'client preference'.colorize(:warning) } + Logger.info { " #{method} : " + 'client preference'.colorize(:warning) } :client else sort = -> (a, b) do @@ -151,6 +154,7 @@ module CryptCheck def fetch_supported_curves Logger.info { '' } Logger.info { 'Supported elliptic curves' } + @supported_curves = [] ecdsa_curve = @ecdsa_certs.keys.first if ecdsa_curve @@ -286,7 +290,7 @@ module CryptCheck Cipher::TYPES.each do |type, _| class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{type}? - supported_ciphers.any? { |c| c.#{type}? } + @supported_ciphers.any? { |c| c.#{type}? } end RUBY_EVAL end @@ -451,6 +455,8 @@ module CryptCheck # Then, collect "ecdsa" connections # { curve => connection, ... } certs += @ecdsa_certs.values + # For anonymous cipher, there is no certificate at all + certs = certs.reject { |c| c.peer_cert.nil? } # Then, fetch cert certs = certs.collect { |c| Cert.new c } # Then, filter cert to keep uniq fingerprint