You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

139 lines
3.6 KiB

module CryptCheck
module Tls
class Grade
attr_reader :server, :grade, :states
def initialize(server)
@server = server
@checks = checks
@states = calculate_states
@grade = calculate_grade
end
def display
color = case @grade
when 'A', 'A+'
:best
when 'B', 'B+'
:perfect
when 'C', 'C+'
:good
when 'E'
:warning
when 'F'
:error
when 'G'
:critical
when 'M', 'T'
:unknown
end
Logger.info { "Grade : #{self.grade.colorize color }" }
Logger.info { '' }
Status.each do |color|
states = @states[color]
Logger.info { "#{color.to_s.capitalize} : #{states.collect { |s| s.to_s.colorize color }.join ' '}" } unless states.empty?
end
end
private
def calculate_grade
case
when !@states[:critical].empty?
return 'G'
when !@states[:error].empty?
return 'F'
when !@states[:warning].empty?
return 'E'
end
goods = @checks.select { |c| c.last == :good }.collect &:first
unless goods.empty?
return 'D' if @states[:good].empty?
return 'C' if @states[:good] != goods
end
perfects = @checks.select { |c| c.last == :perfect }.collect &:first
unless perfects.empty?
return 'C+' if @states[:perfect].empty?
return 'B' if @states[:perfect] != perfects
end
bests = @checks.select { |c| c.last == :best }.collect &:first
unless bests.empty?
return 'B+' if @states[:best].empty?
return 'A' if @states[:best] != bests
end
'A+'
end
CHECKS = ([
# Certificates
[:weak_sign, Proc.new { |s|
Cert::WEAK_SIGN[:critical]
}, :critical],
# Keys
[:weak_key, Proc.new { |s| Status.problem s.keys.collect &:status }],
# DH
[:weak_dh, Proc.new { |s| Status.problem s.dh.collect &:status }],
# Protocols
[:ssl, Proc.new { |s| s.ssl? }, :critical],
[:tls12, Proc.new { |s| s.tlsv1_2? }, :good],
[:tls12_only, Proc.new { |s| s.tlsv1_2_only? }, :perfect],
# Ciphers
[:dss, Proc.new { |s| s.dss? }, :critical],
[:anonymous, Proc.new { |s| s.anonymous? }, :critical],
[:null, Proc.new { |s| s.null? }, :critical],
[:export, Proc.new { |s| s.export? }, :critical],
[:des, Proc.new { |s| s.des? }, :critical],
[:md5, Proc.new { |s| s.md5? }, :critical],
[:rc4, Proc.new { |s| s.rc4? }, :error],
[:sweet32, Proc.new { |s| s.sweet32? }, :error],
[:no_pfs, Proc.new { |s| not s.pfs_only? }, :warning],
[:pfs, Proc.new { |s| s.pfs? }, :good],
[:pfs_only, Proc.new { |s| s.pfs_only? }, :perfect],
[:no_ecdhe, Proc.new { |s| not s.ecdhe? }, :warning],
[:ecdhe, Proc.new { |s| s.ecdhe? }, :good],
[:ecdhe_only, Proc.new { |s| s.ecdhe_only? }, :perfect],
[: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]
]
end
checks
end
def calculate_states
states = Status.collect { |s| [s, []] }.to_h
@checks.each do |name, check, status|
result = check.call @server
if result
state = states[status ? status : result]
state << name if state
end
end
states
end
end
end
end