SSH support

v1
Aeris 8 years ago
parent 11c86006b7
commit 02e6367d17
  1. 16
      app/assets/javascripts/ssh.coffee.erb
  2. 3
      app/assets/stylesheets/ssh.scss
  3. 1
      app/controllers/check_controller.rb
  4. 4
      app/controllers/https_controller.rb
  5. 4
      app/controllers/smtp_controller.rb
  6. 43
      app/controllers/ssh_controller.rb
  7. 4
      app/controllers/xmpp_controller.rb
  8. 2
      app/helpers/site_helper.rb
  9. 28
      app/helpers/ssh_helper.rb
  10. 10
      app/views/application/_headers.erb
  11. 5
      app/views/check/no_tls.html.erb
  12. 2
      app/views/check/processing.html.erb
  13. 2
      app/views/check/show.html.erb
  14. 18
      app/views/ssh/index.html.erb
  15. 12
      app/views/ssh/no_ssh.html.erb
  16. 20
      app/views/ssh/processing.html.erb
  17. 67
      app/views/ssh/show.html.erb
  18. 24
      app/workers/ssh_worker.rb
  19. 10
      config/routes.rb
  20. 14
      test/controllers/ssh_controller_test.rb

@ -0,0 +1,16 @@
$ ->
ssh_submit = ->
host = $('#ssh_check_host').val()
port = $('#ssh_check_port').val()
port = 22 if port == ''
window.location.href = "<%= Rails.configuration.relative_url_root %>/ssh/#{host}:#{port}"
$('#ssh_check_host').keypress (e) ->
ssh_submit() if e.which == 13
return
$('#ssh_check_port').keypress (e) ->
ssh_submit() if e.which == 13
return
$('#ssh_check_submit').click ->
ssh_submit()
return

@ -0,0 +1,3 @@
// Place all the styles related to the ssh controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

@ -1,5 +1,6 @@
class CheckController < ApplicationController
before_action :check_host
helper_method :tls_type, :type
def check_host
@host = params[:id]

@ -7,4 +7,8 @@ class HttpsController < CheckController
def worker
HTTPSWorker
end
def tls_type
'HTTPS'
end
end

@ -7,4 +7,8 @@ class SmtpController < CheckController
def worker
SMTPWorker
end
def tls_type
'STARTTLS'
end
end

@ -0,0 +1,43 @@
class SshController < ApplicationController
before_action :check_host, except: %i(index)
def check_host
@host, @port = params[:id].split ':'
@idn = SimpleIDN.to_ascii @host
if /[^a-zA-Z0-9.-]/.match @idn
flash[:danger] = "Hôte #{@host} invalide"
redirect_to :index
return false
end
@host = "#{@idn}:#{@port}"
@result = Datastore.host :ssh, @host
end
def index
end
def show
enqueue_host unless @result
return render :processing if @result.pending
return render :no_ssh if @result.no_ssh
end
def refresh
unless @result.pending
refresh_allowed = @result.date + Rails.configuration.refresh_delay
if Time.now < refresh_allowed
flash[:warning] = "Merci d’attendre au moins #{l refresh_allowed} pour rafraîchir"
return redirect_to result_path @host
end
enqueue_host
end
redirect_to action: :show
end
protected
def enqueue_host
Datastore.pending :ssh, @host
SSHWorker.perform_async @idn, @port
@result = OpenStruct.new pending: true, date: Time.now
end
end

@ -7,4 +7,8 @@ class XmppController < CheckController
def worker
XMPPWorker
end
def tls_type
'STARTTLS'
end
end

@ -96,7 +96,7 @@ module SiteHelper
when Hashie::Mash
{ success: %i(pfs),
warning: %i(des3 sha1),
danger: %i(md5 psk srp anonymous null export des rc2 rc4)
danger: %i(dss md5 psk srp anonymous null export des rc2 rc4)
}.collect do |c, ts|
ts.select { |t| CryptCheck::Tls::Cipher.send "#{t}?", cipher.name }.collect { |t| [c, t] }
end

@ -0,0 +1,28 @@
module SshHelper
COLORS = { green: :success, yellow: :warning, red: :danger, nil => :default }
def kex_label(key)
label key, COLORS[CryptCheck::Ssh::Server::KEX[key]]
end
def cipher_label(cipher)
label cipher, COLORS[CryptCheck::Ssh::Server::ENCRYPTION[cipher]]
end
def hmac_label(hmac)
label hmac, COLORS[CryptCheck::Ssh::Server::HMAC[hmac]]
end
def compression_label(compression)
label compression, COLORS[CryptCheck::Ssh::Server::COMPRESSION[compression]]
end
def key_label(key)
label key, COLORS[CryptCheck::Ssh::Server::KEY[key]]
end
private
def label(name, color)
"<span class=\"label label-#{color}\">&nbsp;</span>&nbsp;#{name}".html_safe
end
end

@ -2,13 +2,15 @@
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<%= link_to 'CryptCheck', root_path, class: %i(navbar-brand) %>
<span class="navbar-brand">CryptCheck</span>
</div>
<ul class="nav navbar-nav">
<li><%= link_to 'Ciphers', ciphers_path %></li>
<li><%= link_to 'HTTPS / SMTP / XMPP', root_path %></li>
<li><%= link_to 'SSH', ssh_path %></li>
</ul>
<!--
<ul class="nav navbar-nav navbar-right">
<li><%= link_to 'Ciphers', ciphers_path %></li>
<!--
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Hall of f/sh·ame
@ -24,8 +26,8 @@
<li><a href="#">US gov</a></li>
</ul>
</li>
-->
</ul>
-->
</div>
</nav>
</header>

@ -2,8 +2,11 @@
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<h1>
<%= @host %> ne supporte pas HTTPS
[<%= self.type.to_s.upcase %>] <%= @host %> ne supporte pas <%= self.tls_type %>
</h1>
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %>
<%= link_to 'Rafraîchir', {action: :refresh}, class: %i(btn btn-default pull-right) %>
<% end %>
</div>
</div>
</div>

@ -6,7 +6,7 @@
<div class="col-sm-8 col-sm-offset-2">
<h1>
<i class="fa fa-spinner fa-pulse"></i>
Analyse en cours de <%= @host %>
[<%= self.type.to_s.upcase %>] Analyse en cours de <%= @host %>
</h1>
<p class="small">
Début de l’analyse : <%= l @result.date %>

@ -2,7 +2,7 @@
<div class="row">
<div class="col-sm-11">
<h1>
Résultats pour <%= @host %> <span class="small">(<%= l @result.date %>)</span>
[<%= self.type.to_s.upcase %>] <%= @host %> <span class="small">(<%= l @result.date %>)</span>
<%= rank_label @result.score.rank %>
</h1>
</div>

@ -0,0 +1,18 @@
<div id="ssh_check" class="container">
<div class="row">
<div class="col-sm-12">
<h1>Vérifier votre serveur SSH</h1>
<div class="form-group">
<div class="col-sm-8">
<%= text_field_tag :ssh_check_host, nil, class: %i(form-control input-lg), placeholder: 'your-site.com' %>
</div>
<div class="col-sm-2">
<%= text_field_tag :ssh_check_port, nil, class: %i(form-control input-lg), placeholder: 'port' %>
</div>
<div class="col-sm-2">
<%= submit_tag 'Test-moi !', id: 'ssh_check_submit', class: %i(form-control btn btn-primary input-lg pull-right) %>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,12 @@
<div id="check" class="container">
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<h1>
<%= @host %> ne supporte pas SSH
</h1>
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %>
<%= link_to 'Rafraîchir', {action: :refresh}, class: %i(btn btn-default pull-right) %>
<% end %>
</div>
</div>
</div>

@ -0,0 +1,20 @@
<% content_for :head do %>
<meta http-equiv="refresh" content="10">
<% end %>
<div id="check" class="container">
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<h1>
<i class="fa fa-spinner fa-pulse"></i>
[SSH] Analyse en cours de <%= @host %>
</h1>
<p class="small">
Début de l’analyse : <%= l @result.date %>
</p>
<p class="pull-right">
Merci de patienter…
<span class="small">(Cette page se rafraîchit automatiquement toutes les 10 secondes)</span>
</p>
</div>
</div>
</div>

@ -0,0 +1,67 @@
<div class="container">
<div class="row">
<div class="col-sm-11">
<h1>
[SSH] <%= @host %> <span class="small">(<%= l @result.date %>)</span>
</h1>
</div>
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %>
<div class="col-sm-1">
<%= link_to 'Rafraîchir', {action: :refresh}, class: %i(btn btn-default) %>
</div>
<% end %>
</div>
<br/>
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered table-condensed table-striped">
<tbody>
<tr>
<th>Échange de clef</th>
</tr>
<% @result.kex.each do |kex| %>
<tr>
<td><%= kex_label kex %></td>
</tr>
<% end %>
<tr>
<th>Chiffrement</th>
</tr>
<% @result.encryption.each do |cipher| %>
<tr>
<td><%= cipher_label cipher %></td>
</tr>
<% end %>
<tr>
<th>HMAC</th>
</tr>
<% @result.hmac.each do |hmac| %>
<tr>
<td><%= hmac_label hmac %></td>
</tr>
<% end %>
<tr>
<th>Compression</th>
</tr>
<% @result.compression.each do |compression| %>
<tr>
<td><%= compression_label compression %></td>
</tr>
<% end %>
<tr>
<th>Clefs</th>
</tr>
<% @result['key'].each do |key| %>
<tr>
<td><%= key_label key %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>

@ -0,0 +1,24 @@
require 'simpleidn'
require 'cryptcheck'
class SSHWorker
include Sidekiq::Worker
sidekiq_options retry: false
def perform(host, port)
idn = SimpleIDN.to_ascii host
result = begin
server = CryptCheck::Ssh::Server.new idn, port
{
kex: server.kex,
encryption: server.encryption,
hmac: server.hmac,
compression: server.compression,
key: server.key
}
rescue CryptCheck::Ssh::Server::SshNotAvailableException
{ no_ssh: true }
end
Datastore.post :ssh, "#{host}:#{port}", result
end
end

@ -1,4 +1,8 @@
Rails.application.routes.draw do
get 'ssh/show'
get 'ssh/index'
namespace :https, id: /[^\/]*/ do
get ':id/', action: :show
get ':id/refresh', action: :refresh, as: :refresh
@ -14,6 +18,12 @@ Rails.application.routes.draw do
get ':id/refresh', action: :refresh, as: :refresh
end
namespace :ssh, id: /[^\/]*/ do
get '/', action: :index
get ':id/', action: :show
get ':id/refresh', action: :refresh, as: :refresh
end
root 'site#index'
get '/ciphers' => 'site#ciphers'
end

@ -0,0 +1,14 @@
require 'test_helper'
class SshControllerTest < ActionController::TestCase
test "should get show" do
get :show
assert_response :success
end
test "should get index" do
get :index
assert_response :success
end
end
Loading…
Cancel
Save