@@ -37,20 +37,17 @@ module CryptCheck | |||
autoload :Https, 'cryptcheck/tls/https' | |||
module Https | |||
autoload :Server, 'cryptcheck/tls/https/server' | |||
autoload :Grade, 'cryptcheck/tls/https/grade' | |||
autoload :Host, 'cryptcheck/tls/https/host' | |||
end | |||
autoload :Xmpp, 'cryptcheck/tls/xmpp' | |||
module Xmpp | |||
autoload :Server, 'cryptcheck/tls/xmpp/server' | |||
autoload :Grade, 'cryptcheck/tls/xmpp/grade' | |||
end | |||
autoload :Smtp, 'cryptcheck/tls/smtp' | |||
module Smtp | |||
autoload :Server, 'cryptcheck/tls/smtp/server' | |||
autoload :Grade, 'cryptcheck/tls/smtp/grade' | |||
end | |||
end | |||
@@ -59,7 +56,6 @@ module CryptCheck | |||
autoload :Packet, 'cryptcheck/ssh/packet' | |||
autoload :Server, 'cryptcheck/ssh/server' | |||
autoload :SshNotSupportedServer, 'cryptcheck/ssh/server' | |||
autoload :Grade, 'cryptcheck/ssh/grade' | |||
end | |||
private | |||
@@ -106,7 +102,7 @@ module CryptCheck | |||
end.to_h | |||
end | |||
def self.analyze(host, port, server, grade, *args, **kargs) | |||
def self.analyze(host, port, server, *args, **kargs) | |||
addresses = begin | |||
addresses host | |||
rescue ::SocketError => e | |||
@@ -115,7 +111,7 @@ module CryptCheck | |||
error = AnalysisFailure.new "Unable to resolve #{host}" | |||
return { key => error } | |||
end | |||
analyze_addresses host, addresses, port, server, grade, *args, **kargs | |||
analyze_addresses host, addresses, port, server, *args, **kargs | |||
end | |||
def self.analyze_hosts(hosts, template, output, groups: nil, &block) |
@@ -1,7 +1,7 @@ | |||
module CryptCheck | |||
module Ssh | |||
def self.analyze(host, port=22) | |||
::CryptCheck.analyze host, port, Server, Grade | |||
::CryptCheck.analyze host, port, Server | |||
end | |||
end | |||
end |
@@ -61,11 +61,6 @@ module CryptCheck | |||
a <=> b | |||
end | |||
def performed_checks | |||
self.states # Force internal resolution | |||
@performed_checks | |||
end | |||
protected | |||
def checks | |||
@checks ||= self.available_checks.collect { |c| perform_check c }.flatten(1) + children.collect(&:checks).flatten(1) |
@@ -4,7 +4,7 @@ require 'parallel' | |||
module CryptCheck | |||
module Tls | |||
def self.analyze(host, port) | |||
::CryptCheck.analyze host, port, TcpServer, Grade | |||
::CryptCheck.analyze host, port, TcpServer | |||
end | |||
def self.key_to_s(key) |
@@ -1,71 +1,31 @@ | |||
module CryptCheck | |||
module Tls | |||
class Grade | |||
attr_reader :server, :grade | |||
def initialize(server) | |||
@server = server | |||
@states = @server.states | |||
@checks = @server.performed_checks | |||
Logger.info { '' } | |||
Logger.ap :checks, @checks | |||
Logger.ap :states, @states | |||
@grade = calculate_grade | |||
color = case @grade | |||
when 'A', 'A+' | |||
:best | |||
when 'B', 'B+' | |||
:great | |||
when 'C', 'C+' | |||
:good | |||
when 'E' | |||
:warning | |||
when 'F' | |||
:error | |||
when 'G' | |||
:critical | |||
when 'T', 'V' | |||
:unknown | |||
end | |||
Logger.info { "Grade : #{self.grade.colorize color }" } | |||
end | |||
def to_h | |||
{ checks: @checks, states: @states } | |||
module Grade | |||
def grade | |||
@grade ||= calculate_grade | |||
end | |||
private | |||
def calculate_grade | |||
return 'V' unless @server.valid? | |||
return 'T' unless @server.trusted? | |||
return :V unless self.valid? | |||
return :T unless self.trusted? | |||
states = self.states | |||
case | |||
when !@states[:critical].empty? | |||
return 'G' | |||
when !@states[:error].empty? | |||
return 'F' | |||
when !@states[:warning].empty? | |||
return 'E' | |||
{ critical: :G, error: :F, warning: :E }.each do |type, grade| | |||
return grade if states[type].any? { |s| s == true } | |||
end | |||
[[:good, 'D', 'C'], | |||
[:great, 'C', 'B'], | |||
[:best, 'B', 'A']].each do |type, score1, score2| | |||
expected = @checks[type] | |||
unless expected.empty? | |||
available = @states[type] | |||
return score1 if available.empty? | |||
missed = expected - available | |||
unless missed.empty? | |||
Logger.info { "Missing #{type} : #{missed}" } | |||
return score2 | |||
end | |||
{good: %i(D C), great: %i(C B), best: %i(B A)}.each do |type, scores| | |||
state = states[type] | |||
return scores.first if state.all? { |s| s != false } | |||
if state.any? { |s| s == false } | |||
Logger.info { "Missing #{type} : #{states[type].select { |s| s == false }.collect &:key}" } | |||
return scores.last | |||
end | |||
end | |||
'A+' | |||
:'A+' | |||
end | |||
end | |||
end |
@@ -36,7 +36,9 @@ module CryptCheck | |||
server = ::Timeout.timeout MAX_ANALYSIS_DURATION do | |||
server(*args) | |||
end | |||
grade server | |||
Logger.info '' | |||
Logger.info { "Grade : #{server.grade.to_s.colorize server.status}" } | |||
server | |||
rescue Engine::TLSException, Engine::ConnectionError, Engine::Timeout => e | |||
AnalysisFailure.new e | |||
rescue ::Timeout::Error | |||
@@ -57,19 +59,20 @@ module CryptCheck | |||
if @error | |||
target[:error] = @error | |||
else | |||
target[:hosts] = @servers.collect do |host, grade| | |||
target[:hosts] = @servers.collect do |host, server| | |||
hostname, ip, port = host | |||
host = { | |||
hostname: hostname, | |||
ip: ip, | |||
port: port | |||
} | |||
case grade | |||
when Grade | |||
host[:analysis] = grade.server.to_h | |||
host[:status] = grade.to_h | |||
case server | |||
when Server | |||
host[:handshakes] = server.to_h | |||
host[:states] = server.states | |||
host[:grade] = server.grade | |||
else | |||
host[:error] = grade.message | |||
host[:error] = server.message | |||
end | |||
host | |||
end | |||
@@ -91,10 +94,6 @@ module CryptCheck | |||
def server(*args) | |||
TcpServer.new *args | |||
end | |||
def grade(server) | |||
Grade.new server | |||
end | |||
end | |||
end | |||
end |
@@ -1,16 +0,0 @@ | |||
module CryptCheck | |||
module Tls | |||
module Https | |||
class Grade < Tls::Grade | |||
CHECKS = { | |||
good: %i(hsts), | |||
perfect: %i(hsts_long) | |||
} | |||
def checks | |||
State.merge super, CHECKS | |||
end | |||
end | |||
end | |||
end | |||
end |
@@ -6,10 +6,6 @@ module CryptCheck | |||
def server(*args) | |||
Https::Server.new *args | |||
end | |||
def grade(server) | |||
Https::Grade.new server | |||
end | |||
end | |||
end | |||
end |
@@ -85,6 +85,7 @@ module CryptCheck | |||
end | |||
include Engine | |||
include Grade | |||
end | |||
class TcpServer < Server |
@@ -1,14 +0,0 @@ | |||
module CryptCheck | |||
module Tls | |||
module Smtp | |||
class Grade < Tls::Grade | |||
CHECKS = { | |||
} | |||
def checks | |||
State.merge super, CHECKS | |||
end | |||
end | |||
end | |||
end | |||
end |
@@ -1,15 +0,0 @@ | |||
module CryptCheck | |||
module Tls | |||
module Xmpp | |||
class Grade < Tls::Grade | |||
CHECKS = { | |||
good: %i(required) | |||
} | |||
def checks | |||
State.merge super, CHECKS | |||
end | |||
end | |||
end | |||
end | |||
end |