@@ -49,6 +49,10 @@ td.primary { | |||
background-color: $state-info-bg; | |||
} | |||
.translation_missing { | |||
border: 1px solid red; | |||
} | |||
.progress-bar-default { | |||
background-color: $label-default-bg; | |||
} | |||
@@ -62,3 +66,37 @@ td.primary { | |||
#tls_check { | |||
margin-top: 100px; | |||
} | |||
.label-state-critical { | |||
//background-color: #800000; | |||
background-color: #ff0000; | |||
} | |||
.label-state-error { | |||
//background-color: #803300; | |||
background-color: #ff6600; | |||
} | |||
.label-state-warning { | |||
//background-color: #806600; | |||
background-color: #ffcc00; | |||
color: $text-color; | |||
} | |||
.label-state-good { | |||
//background-color: #668000; | |||
background-color: #cbff00; | |||
color: $text-color; | |||
} | |||
.label-state-great { | |||
//background-color: #338000; | |||
background-color: #65ff00; | |||
} | |||
.label-state-best { | |||
//background-color: #008000; | |||
background-color: #00ff00; | |||
} | |||
@@ -59,6 +59,10 @@ class CheckController < ApplicationController | |||
return false | |||
end | |||
@port = @port.to_i if @port | |||
@result = Datastore.host self.type, @host, @port | |||
# @result = Datastore.host self.type, @host, @port | |||
file = File.join Rails.root, 'config/host.dump' | |||
# open(file, 'wb') { |f| f.write Marshal.dump @result } | |||
@result = Marshal.load File.read file | |||
end | |||
end |
@@ -1,12 +1,36 @@ | |||
module CheckHelper | |||
private def __label(value, color) | |||
"<span class=\"label label-#{color} %>\">#{value}</span>" | |||
end | |||
def label(value, color) | |||
"<span class=\"label label-#{color} %>\">#{value}</span>".html_safe | |||
__label(value, color).html_safe | |||
end | |||
def cell(value, color) | |||
"<td class=\"#{color}\">#{value}</td>".html_safe | |||
end | |||
def labels(level, states) | |||
states.each_pair.collect do |name, value| | |||
color = if value.nil? | |||
:default | |||
elsif ::CryptCheck::State.bad? level | |||
value ? :danger : :success | |||
else | |||
value ? :success : :danger | |||
end | |||
__label name, color | |||
end.join(' ').html_safe | |||
end | |||
def states(states) | |||
::CryptCheck::State.collect do |level| | |||
states[level].each_pair.select { |_, v| v == true }.collect do |name, _| | |||
__label name, "state-#{level}" | |||
end | |||
end.flatten(1).join(' ').html_safe | |||
end | |||
def rank_color(rank) | |||
case rank | |||
when 'A+' then | |||
@@ -30,12 +54,18 @@ module CheckHelper | |||
def progress_color(percentage) | |||
case percentage | |||
when 0...20 then :error | |||
when 20...40 then :danger | |||
when 40...60 then :warning | |||
when 60...80 then :default | |||
when 80...90 then :success | |||
else :primary | |||
when 0...20 then | |||
:error | |||
when 20...40 then | |||
:danger | |||
when 40...60 then | |||
:warning | |||
when 60...80 then | |||
:default | |||
when 80...90 then | |||
:success | |||
else | |||
:primary | |||
end | |||
end | |||
@@ -50,9 +80,12 @@ module CheckHelper | |||
def protocol_label(protocol) | |||
color = case protocol.to_s | |||
when 'TLSv1_2' then :success | |||
when 'SSLv3', 'SSLv2' then :error | |||
else :default | |||
when 'TLSv1_2' then | |||
:success | |||
when 'SSLv3', 'SSLv2' then | |||
:error | |||
else | |||
:default | |||
end | |||
label protocol, color | |||
end | |||
@@ -63,12 +96,12 @@ module CheckHelper | |||
def key_label(key) | |||
return label('Aucune', :error) unless key | |||
label "#{key.type.upcase} #{key[:size]} bits", key_color(key) | |||
label "#{key[:type].upcase} #{key[:size]} bits", key_color(key) | |||
end | |||
def key_labels(keys) | |||
return label('Aucune', :error) if keys.empty? | |||
keys.sort { |a, b| -1 * (a.rsa_size <=> b.rsa_size) }.collect { |k| key_label k }.join("\n").html_safe | |||
keys.sort { |a, b| -1 * (a[:size] <=> b[:size]) }.collect { |k| key_label k }.join("\n").html_safe | |||
end | |||
def cipher_size_label(cipher) | |||
@@ -77,33 +110,48 @@ module CheckHelper | |||
end | |||
def key_color(key) | |||
case key&.rsa_size | |||
when nil then :default | |||
when 0...1024 then :error | |||
when 1024...2048 then :danger | |||
when 2048...4096 then :warning | |||
else :success | |||
case key[:size] | |||
when nil then | |||
:default | |||
when 0...1024 then | |||
:error | |||
when 1024...2048 then | |||
:danger | |||
when 2048...4096 then | |||
:warning | |||
else | |||
:success | |||
end | |||
end | |||
def cipher_color(key) | |||
case key | |||
when nil then :default | |||
when 0...112 then :error | |||
when 112...128 then :danger | |||
when 128...256 then :success | |||
else :primary | |||
when nil then | |||
:default | |||
when 0...128 then | |||
:error | |||
when 112...128 then | |||
:danger | |||
when 128...256 then | |||
:success | |||
else | |||
:primary | |||
end | |||
end | |||
def cipher_name_label(cipher) | |||
state = cipher.state | |||
state = cipher[:state] | |||
color = case | |||
when !state[:error].empty? then :error | |||
when !state[:danger].empty? then :danger | |||
when !state[:warning].empty? then :warning | |||
when !state[:success].empty? then :success | |||
else :default | |||
when !state[:error].empty? then | |||
:error | |||
when !state[:danger].empty? then | |||
:danger | |||
when !state[:warning].empty? then | |||
:warning | |||
when !state[:success].empty? then | |||
:success | |||
else | |||
:default | |||
end | |||
color = :primary if color == :success and cipher.size >= 256 | |||
label(" ", color) + " #{cipher.name}".html_safe | |||
@@ -111,17 +159,21 @@ module CheckHelper | |||
def cipher_labels(cipher) | |||
cipher.state.collect { |c, ls| ls.collect { |l| label l.upcase, c } } | |||
.flatten(1).join("\n").html_safe | |||
.flatten(1).join("\n").html_safe | |||
end | |||
def cipher_kex_type_cell(kex) | |||
color = case kex | |||
when :ecdh then :primary | |||
when :dh then :success | |||
when :rsa then :warning | |||
else :error | |||
when :ecdh then | |||
:primary | |||
when :dh then | |||
:success | |||
when :rsa then | |||
:warning | |||
else | |||
:error | |||
end | |||
kex ||= 'None' | |||
kex ||= 'None' | |||
cell kex.to_s.upcase, color | |||
end | |||
@@ -132,11 +184,14 @@ module CheckHelper | |||
def cipher_auth_type_cell(auth) | |||
color = case auth | |||
when :ecdsa then :primary | |||
when :rsa then :default | |||
else :error | |||
when :ecdsa then | |||
:primary | |||
when :rsa then | |||
:default | |||
else | |||
:error | |||
end | |||
auth ||= 'None' | |||
auth ||= 'None' | |||
cell auth.to_s.upcase, color | |||
end | |||
@@ -147,18 +202,21 @@ module CheckHelper | |||
def cipher_enc_type_cell(enc) | |||
color = case enc | |||
when :chacha20 then :primary | |||
when :aes then :success | |||
when :camellia, :seed, :idea then :default | |||
when :'3des' then :danger | |||
else :error | |||
when :chacha20 then | |||
:primary | |||
when :aes then | |||
:success | |||
when :camellia, :seed then | |||
:default | |||
else | |||
:error | |||
end | |||
enc ||= 'NONE' | |||
enc ||= 'NONE' | |||
cell enc.to_s.upcase, color | |||
end | |||
def cipher_enc_key_size_cell(enc) | |||
enc ||= 0 | |||
enc ||= 0 | |||
color = cipher_color enc | |||
cell enc, color | |||
end | |||
@@ -171,19 +229,25 @@ module CheckHelper | |||
def cipher_enc_mode_cell(enc) | |||
color = case enc | |||
when :gcm, :ccm then :primary | |||
when :cbc then :warning | |||
when :gcm, :ccm then | |||
:primary | |||
when :cbc then | |||
:danger | |||
end | |||
enc ||= '' | |||
enc ||= '' | |||
cell enc.to_s.upcase, color | |||
end | |||
def cipher_mac_type_cell(mac) | |||
color = case mac | |||
when :poly1305 then :primary | |||
when :sha384, :sha256 then :success | |||
when :sha1 then :default | |||
when :md5 then :error | |||
when :poly1305 then | |||
:primary | |||
when :sha384, :sha256 then | |||
:success | |||
when :sha1 then | |||
:warning | |||
when :md5 then | |||
:error | |||
end | |||
cell mac.to_s.upcase, color | |||
end | |||
@@ -9,7 +9,7 @@ | |||
[<%= self.type.to_s.upcase %>] <%= t 'Currently analysing %{host}', host: @host %> | |||
</h1> | |||
<p class="small"> | |||
<%= t 'Start of analysis: %{date}', date: l(@result.date) %> | |||
<%= t 'Start of analysis: %{date}', date: l(@result[:date]) %> | |||
</p> | |||
<p class="pull-right"> | |||
<%= t('Please wait…') %> | |||
@@ -6,151 +6,86 @@ | |||
</h1> | |||
</div> | |||
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %> | |||
<div class="col-sm-1"> | |||
<%= link_to t('Refresh'), {action: :refresh}, class: %i(btn btn-default) %> | |||
</div> | |||
<div class="col-sm-1"> | |||
<%= link_to t('Refresh'), { action: :refresh }, class: %i(btn btn-default) %> | |||
</div> | |||
<% end %> | |||
</div> | |||
<% | |||
@result.hosts.each do |host| | |||
if host.error | |||
error, host = host.error, host.host | |||
%> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2> | |||
<%= t 'Error during analysis:' %> | |||
<span class="label label-error"><%= error %></span> | |||
</div> | |||
</div> | |||
<% | |||
else | |||
host, grade, handshake = host.host, host.grade, host.handshake | |||
%> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2> | |||
<% @result.hosts.each do |host| %> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h2> | |||
<%= rank_label host.grade %> | |||
<%= host.ip %> : <%= host.port %> | |||
<span class="small">(<%= host.hostname %>)</span></h2> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-6"> | |||
<table class="table table-bordered table-condensed table-striped"> | |||
<thead> | |||
<tr> | |||
<th colspan="2"> | |||
Scores | |||
<%= rank_label grade.rank %> | |||
</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<% | |||
{ 'Protocol' => 'protocol', | |||
'Key exchange' => 'key_exchange', | |||
'Cipher' => 'cipher_strengths', | |||
'Overall' => 'score'}.each do |name, v| %> | |||
<tr> | |||
<th class="col-sm-4"><%= t name %></th> | |||
<td class="col-sm-8"><%= score_progress grade.details[v] %></td> | |||
</tr> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h3><%= t 'Checks' %></h3> | |||
<table class="table table-bordered table-condensed table-striped"> | |||
<thead> | |||
<th><%= t 'Severity' %></th> | |||
<td></td> | |||
</thead> | |||
<tbody> | |||
<% ::CryptCheck::State.each do |level| %> | |||
<tr> | |||
<th><%= label level, "state-#{level}" %></th> | |||
<td><%= labels level, host.states[level] %></td> | |||
</tr> | |||
<% end %> | |||
</tbody> | |||
</table> | |||
</tbody> | |||
</table> | |||
</div> | |||
</div> | |||
<div class="col-sm-6"> | |||
<table class="table table-bordered table-condensed table-striped"> | |||
<tbody> | |||
<tr> | |||
<th class="col-sm-4"><%= t 'Protocols' %></th> | |||
<td class="col-sm-8"><%= protocol_labels handshake.protocols %></td> | |||
</tr> | |||
<tr> | |||
<th><%= t 'Keys' %></th> | |||
<td> | |||
<p><%= t 'Certificates:' %> <%= key_label handshake[:key] %></p> | |||
<p>Diffie Hellman : <%= key_labels handshake.dh %></p> | |||
</td> | |||
</tr> | |||
<% { 'Good practices' => :success, | |||
'Warning' => :warning, | |||
'Critical' => :danger, | |||
'Fatal' => :error }.each do |name, color| | |||
names = grade[color] | |||
next if names.nil? or names.empty? | |||
%> | |||
<tr> | |||
<th><%= t name %></th> | |||
<td> | |||
<% names.each do |name| %> | |||
<span class="label label-<%= color %>"><%= name.upcase %></span> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h3><%= t 'Certificates' %></h3> | |||
<table class="table table-bordered table-condensed table-striped"> | |||
<thead> | |||
<tr> | |||
<th> | |||
<%= t 'Subject' %> | |||
<span class="small">[<%= t 'Serial' %>]</span> | |||
<div class="small"><%= t 'Fingerprint' %></div> | |||
</th> | |||
<td><%= t 'Issuer' %></td> | |||
<td><%= t 'Not before' %></td> | |||
<td><%= t 'Not after' %></td> | |||
<th></th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<% host.handshakes.certs.each do |cert| %> | |||
<tr> | |||
<th> | |||
<%= cert.subject %> [<%= cert.serial %>] | |||
<div class="small"><%= cert.fingerprint %></div> | |||
</th> | |||
<td><%= cert.issuer %></td> | |||
<td><%= l cert.lifetime.not_before %></td> | |||
<td><%= l cert.lifetime.not_after %></td> | |||
<td><%= states cert.states %></td> | |||
</tr> | |||
<% cert.chain.each do |cert| %> | |||
<tr> | |||
<th> | |||
<%= cert.subject %> [<%= cert.serial %>] | |||
<div class="small"><%= cert.fingerprint %></div> | |||
</th> | |||
<td><%= cert.issuer %></td> | |||
<td><%= l cert.lifetime.not_before %></td> | |||
<td><%= l cert.lifetime.not_after %></td> | |||
</tr> | |||
<% end %> | |||
</td> | |||
</tr> | |||
<% end %> | |||
</tbody> | |||
</table> | |||
<% end %> | |||
</tbody> | |||
</table> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<table class="table table-bordered table-condensed table-striped center"> | |||
<thead> | |||
<tr> | |||
<th rowspan="2"><%= t 'Name' %></th> | |||
<th colspan="2"><%= t 'Key exchange' %></th> | |||
<th colspan="2"><%= t 'Authentication' %></th> | |||
<th colspan="4"><%= t 'Encryption' %></th> | |||
<th colspan="2"><%= t 'MAC' %></th> | |||
<th rowspan="2"><%= t 'PFS' %></th> | |||
</tr> | |||
<tr> | |||
<th><%= t 'Type' %></th> | |||
<th><%= t 'Key size' %></th> | |||
<th><%= t 'Type' %></th> | |||
<th><%= t 'Key size' %></th> | |||
<th><%= t 'Type' %></th> | |||
<th><%= t 'Key size' %></th> | |||
<th><%= t 'Block size' %></th> | |||
<th><%= t 'Mode' %></th> | |||
<th><%= t 'Type' %></th> | |||
<th><%= t 'Size' %></th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<% CryptCheck::Tls::Server::EXISTING_METHODS.each do |protocol| | |||
ciphers = CryptCheck::Tls::Cipher.sort(handshake.ciphers.select { |c| c.protocol == protocol.to_s } | |||
.collect { |c| CryptCheck::Tls::Cipher.new protocol, [c.name, nil, c[:size]], c.dh, handshake[:key] }) | |||
unless ciphers.empty? %> | |||
<tr> | |||
<th colspan="12"><%= protocol_label protocol %></th> | |||
</tr> | |||
<% ciphers.each do |cipher| | |||
params = cipher.params | |||
kex = params[:kex] | |||
auth = params[:auth] | |||
enc = params[:enc] | |||
mac = params[:mac] | |||
pfs = params[:pfs] | |||
%> | |||
<tr> | |||
<th><%= cipher_name_label cipher %></th> | |||
<%= cipher_kex_type_cell kex&.first %> | |||
<%= cipher_kex_size_cell kex&.last %> | |||
<%= cipher_auth_type_cell auth&.first %> | |||
<%= cipher_auth_size_cell auth&.last %> | |||
<%= cipher_enc_type_cell enc&.first %> | |||
<%= cipher_enc_key_size_cell enc&.[] 1 %> | |||
<%= cipher_enc_block_size_cell enc&.[] 2 %> | |||
<%= cipher_enc_mode_cell enc&.last %> | |||
<%= cipher_mac_type_cell mac&.first %> | |||
<%= cipher_mac_size_cell mac&.last %> | |||
<%= cipher_pfs_cell pfs %> | |||
</tr> | |||
<% end end end %> | |||
</tbody> | |||
</table> | |||
</div> | |||
</div> | |||
<% end | |||
end %> | |||
<% end %> | |||
</div> |
@@ -54,7 +54,7 @@ | |||
<%= cipher_mac_size_cell mac&.last %> | |||
<%= cipher_pfs_cell pfs %> | |||
<% else %> | |||
<td colspan="10"><%= label('Non supporté', :error) %></td> | |||
<td colspan="10"><%= label t('Not supported'), :error %></td> | |||
<% end %> | |||
</tr> | |||
<% end %> | |||
@@ -44,3 +44,5 @@ en: | |||
Size: Size | |||
Not supported: Not supported | |||
"Serial: %{serial}": "Serial: %{serial}" |
@@ -45,6 +45,18 @@ fr: | |||
Not supported: Non supporté | |||
Checks: Vérifications | |||
Severity: Sévèrité | |||
Certificates: Certificats | |||
Subject: Sujet | |||
Serial: Numéro de série | |||
Issuer: Émetteur | |||
Not before: Pas avant | |||
Not after: Pas après | |||
Fingerprint: Empreinte | |||
"Fingerprint: %{fingerprint}": "Empreinte : %{fingerprint}" | |||
date: | |||
abbr_day_names: | |||
- dim | |||