Bläddra i källkod

Refactor logging

master
Nicolas Vinot 4 år sedan
förälder
incheckning
4fa9497a0d

+ 4
- 3
Gemfile Visa fil

@@ -1,5 +1,6 @@
source 'https://rubygems.org'

gem 'rake'
gem 'httparty'
gem 'nokogiri'
gem 'net-ssh', '>= 2.9.2.beta'
@@ -8,9 +9,9 @@ gem 'tcp_timeout'
gem 'parallel'
gem 'ruby-progressbar'
gem 'logging'
gem 'activerecord'
gem 'sqlite3'
gem 'rake'
#gem 'activerecord'
#gem 'sqlite3'
gem 'colorize'

group :test do
gem 'rspec'

+ 4
- 2
Makefile Visa fil

@@ -34,13 +34,15 @@ $(OPENSSL_DIR)/:
$(OPENSSL_DIR)/Makefile: | $(OPENSSL_DIR)/
cd $(OPENSSL_DIR); ./config shared

$(OPENSSL_DIR)/libssl.so.1.0.0 $(OPENSSL_DIR)/libcrypto.so.1.0.0: $(OPENSSL_DIR)/Makefile
$(OPENSSL_DIR)/libssl.so $(OPENSSL_DIR)/libcrypto.so: $(OPENSSL_DIR)/Makefile
$(MAKE) -C $(OPENSSL_DIR) depend build_libs

lib/%.so: $(OPENSSL_DIR)/%.so
cp $< $@
lib/%.so.1.0.0: $(OPENSSL_DIR)/%.so.1.0.0
cp $< $@

libs: lib/libssl.so.1.0.0 lib/libcrypto.so.1.0.0
libs: lib/libssl.so lib/libcrypto.so lib/libssl.so.1.0.0 lib/libcrypto.so.1.0.0

$(RUBY_DIR)/:
wget http://cache.ruby-lang.org/pub/ruby/$(RUBY_MAJOR_VERSION)/$(RUBY_DIR).tar.gz

+ 5
- 5
bin/check_https.rb Visa fil

@@ -2,18 +2,18 @@
$:.unshift File.expand_path File.join File.dirname(__FILE__), '../lib'
require 'rubygems'
require 'bundler/setup'
require 'logging'
require 'cryptcheck'

name = ARGV[0] || 'index'
file = ::File.join 'output', "#{name}.yml"

if ::File.exist? file
::CryptCheck::Logger.level = :none
::CryptCheck::Tls::Https.analyze_from_file "output/#{name}.yml", "output/#{name}.html"
else
::Logging.logger.root.appenders = ::Logging.appenders.stdout
::Logging.logger.root.level = :warn

::CryptCheck::Logger.level = :info
server = ::CryptCheck::Tls::Https::Server.new(ARGV[0], ARGV[1] || 443)
p grade = ::CryptCheck::Tls::Https::Grade.new(server)
grade = ::CryptCheck::Tls::Https::Grade.new server
::CryptCheck::Logger.info { '' }
grade.display
end

+ 1
- 2
bin/check_https_alexa.rb Visa fil

@@ -7,8 +7,7 @@ require 'cryptcheck'

GROUP_NAME = 'Top 100 Alexa'

::Logging.logger.root.appenders = ::Logging.appenders.stdout
::Logging.logger.root.level = :error
::CryptCheck::Logger.level = :none

hosts = []
::File.open('top-1m.csv', 'r') do |file|

+ 8
- 7
bin/check_smtp.rb Visa fil

@@ -6,14 +6,15 @@ require 'logging'
require 'cryptcheck'

name = ARGV[0]
unless name
::CryptCheck::Tls::Smtp.analyze_from_file 'output/smtp.yml', 'output/smtp.html'
else
::Logging.logger.root.appenders = ::Logging.appenders.stdout
::Logging.logger.root.level = :warn

if name
::CryptCheck::Logger.level = :info
server = ::CryptCheck::Tls::Smtp::Server.new(ARGV[0], ARGV[1] || 25)
p grade = ::CryptCheck::Tls::Smtp::Grade.new(server)
grade = ::CryptCheck::Tls::Smtp::Grade.new server
::CryptCheck::Logger.info { '' }
grade.display
else
::CryptCheck::Logger.level = :none
::CryptCheck::Tls::Smtp.analyze_from_file 'output/smtp.yml', 'output/smtp.html'
end



+ 5
- 4
bin/check_xmpp.rb Visa fil

@@ -7,12 +7,13 @@ require 'cryptcheck'

name = ARGV[0]
if name
::Logging.logger.root.appenders = ::Logging.appenders.stdout
::Logging.logger.root.level = :warn

::CryptCheck::Logger.level = :info
server = ::CryptCheck::Tls::Xmpp::Server.new(name, ARGV[1] || :s2s)
p grade = ::CryptCheck::Tls::Xmpp::Grade.new(server)
grade = ::CryptCheck::Tls::Xmpp::Grade.new(server)
::CryptCheck::Logger.info { '' }
grade.display
else
::CryptCheck::Logger.level = :none
::CryptCheck::Tls::Xmpp.analyze_from_file 'output/xmpp.yml', 'output/xmpp.html'
end


+ 3
- 0
lib/cryptcheck.rb Visa fil

@@ -1,4 +1,7 @@
require 'colorize'

module CryptCheck
autoload :Logger, 'cryptcheck/logger'
autoload :Tls, 'cryptcheck/tls'
module Tls
autoload :Server, 'cryptcheck/tls/server'

+ 28
- 0
lib/cryptcheck/logger.rb Visa fil

@@ -0,0 +1,28 @@
module CryptCheck
class Logger
LEVELS = %i(trace debug info warning error fatal none)
@@level = :info

def self.level=(level)
@@level = level
end

def self.log(level, string=nil, output: $stdout, &block)
return unless enabled? level
output.puts(string ? string : block.call)
end

LEVELS.each do |level|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def self.#{level}(string=nil, output: $stdout, &block)
self.log :#{level}, string, output: output, &block
end
RUBY_EVAL
end

private
def self.enabled?(level)
LEVELS.index(level) >= LEVELS.index(@@level)
end
end
end

+ 51
- 5
lib/cryptcheck/tls.rb Visa fil

@@ -5,20 +5,46 @@ require 'parallel'
module CryptCheck
module Tls
MAX_ANALYSIS_DURATION = 600
PARALLEL_ANALYSIS = 10
@@log = ::Logging.logger[Tls]
PARALLEL_ANALYSIS = 10

TYPES = {
md5: %w(MD5),
sha1: %w(SHA),

psk: %w(PSK),
srp: %w(SRP),
anonymous: %w(ADH AECDH),

dss: %w(DSS),

null: %w(NULL),
export: %w(EXP),
des: %w(DES-CBC),
rc4: %w(RC4),
des3: %w(3DES DES-CBC3),

pfs: %w(DHE EDH ECDHE ECDH)
}

TYPES.each do |name, ciphers|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def self.#{name}?(cipher)
#{ciphers}.any? { |c| /(^|-)#\{c\}(-|$)/ =~ cipher }
end
RUBY_EVAL
end

def self.grade(hostname, port, server_class:, grade_class:)
timeout MAX_ANALYSIS_DURATION do
grade_class.new server_class.new hostname, port
end
rescue ::Exception => e
@@log.error { "Error during #{hostname}:#{port} analysis : #{e}" }
@Logger.error { "Error during #{hostname}:#{port} analysis : #{e}" }
TlsNotSupportedGrade.new TlsNotSupportedServer.new hostname, port
end

def self.analyze(hosts, template, output, groups = nil, port:, server_class:, grade_class:)
results = {}
results = {}
semaphore = ::Mutex.new
::Parallel.each hosts, progress: 'Analysing', in_threads: PARALLEL_ANALYSIS, finish: lambda { |item, _, _| puts item[1] } do |description, host|
result = grade host.strip, port, server_class: server_class, grade_class: grade_class
@@ -51,7 +77,7 @@ module CryptCheck

def self.analyze_from_file(file, template, output, port:, server_class:, grade_class:)
config = ::YAML.load_file file
hosts = []
hosts = []
groups = []
config.each do |c|
d, hs = c['description'], c['hostnames']
@@ -61,6 +87,26 @@ module CryptCheck
self.analyze hosts, template, output, groups, port: port, server_class: server_class, grade_class: grade_class
end

def self.colorize(cipher)
colors = case
when /^SSL/ =~ cipher,
dss?(cipher),
anonymous?(cipher),
null?(cipher),
export?(cipher),
md5?(cipher),
des?(cipher),
rc4?(cipher)
{ color: :white, background: :red }
when des3?(cipher)
{ color: :yellow }
when :TLSv1_2 == cipher,
pfs?(cipher)
{ color: :green }
end
cipher.to_s.colorize colors
end

private
SCORES = %w(A+ A A- B C D E F T M X)


+ 111
- 47
lib/cryptcheck/tls/grade.rb Visa fil

@@ -2,109 +2,173 @@ module CryptCheck
module Tls
class TlsNotSupportedGrade
attr_reader :server, :score, :grade

def initialize(server)
@server, @score, @grade = server, -1, 'X'
end
end

class Grade
attr_reader :server, :score, :grade, :warning, :success
attr_reader :server, :protocol_score, :key_exchange_score, :cipher_strengths_score, :score, :grade, :error, :warning, :success

def initialize(server)
@server = server
protocol_score
key_exchange_score
cipher_strengths_score
@score = @protocol_score*0.3 + @key_exchange_score*0.3 + @cipher_strengths_score*0.4
calculate_protocol_score
calculate_key_exchange_score
calculate_cipher_strengths_score
@score = @protocol_score*0.3 + @key_exchange_score*0.3 + @cipher_strengths_score*0.4
calculate_error
calculate_warning
calculate_success
calculate_grade
warning
success
perfect
calculate_perfect
end

def display
color = case self.grade
when 'A+'
:blue
when 'A'
:green
when 'B', 'C'
:yellow
when 'E', 'F'
:red
when 'M', 'T'
{ color: :white, background: :red }
end

Logger.info { "Grade : #{self.grade.colorize color }" }
Logger.info { '' }
Logger.info { "Protocole : #{self.protocol_score} / 100" }
Logger.info { "Key exchange : #{self.key_exchange_score} / 100" }
Logger.info { "Ciphers strength : #{self.cipher_strengths_score} / 100" }
Logger.info { "Overall score : #{self.score} / 100" }
Logger.info { '' }
Logger.info { "Errors : #{self.error.join(' ').colorize :red }" } unless self.error.empty?
Logger.info { "Warnings : #{self.warning.join(' ').colorize :yellow }" } unless self.warning.empty?
Logger.info { "Best practices : #{self.success.join(' ').colorize :green }" } unless self.success.empty?
end

private
def calculate_grade
@grade = case @score
when 0...20 then 'F'
when 20...35 then 'E'
when 35...50 then 'D'
when 50...65 then 'C'
when 65...80 then 'B'
else 'A'
end
when 0...20 then
'F'
when 20...35 then
'E'
when 35...50 then
'D'
when 50...65 then
'C'
when 65...80 then
'B'
else
'A'
end

@grade = [@grade, 'B'].max if !@server.tlsv1_2? or @server.key_size < 2048
@grade = [@grade, 'C'].max if @server.des3?
@grade = [@grade, 'E'].max if @server.rc4? or @server.des?
@grade = [@grade, 'F'].max if @server.ssl? or @server.key_size < 1024
@grade = [@grade, 'F'].max unless @error.empty?

@grade = 'M' unless @server.cert_valid
@grade = 'T' unless @server.cert_trusted
end

def warning
def calculate_error
@error = []

@error << :md5_sig if @server.md5_sig?

@error << :md5 if @server.md5?

@error << :anonymous if @server.anonymous?

@error << :dss if @server.dss?

@error << :null if @server.null?
@error << :export if @server.export?
@error << :des if @server.des?
@error << :rc4 if @server.rc4?
end

def calculate_warning
@warning = []

@warning << :md5_sig if @server.md5_sig?
@warning << :sha1_sig if @server.sha1_sig?

@warning << :md5 if @server.md5?
#@warning << :sha1 if @server.sha1?

@warning << :rc4 if @server.rc4?
@warning << :des if @server.des?
@warning << :des3 if @server.des3?
end

def success
def calculate_success
@success = []
@success << :pfs if @server.pfs_only?
end

ALL_WARNING = %i(md5_sig md5 rc4 des)
ALL_ERROR = %i(md5_sig md5 anonymous dss null export des rc4)
ALL_WARNING = %i(sha1_sig des3)
ALL_SUCCESS = %i(pfs)

def all_error
ALL_ERROR
end

def all_warning
ALL_WARNING
end
ALL_SUCCESS = %i(pfs)
def all_success
ALL_SUCCESS
end

def perfect
@grade = 'A+' if @grade == 'A' and (all_warning & @warning).empty? and (all_success & @success) == all_success
def calculate_perfect
@grade = 'A+' if @grade == 'A' and @error.empty? and @warning.empty? and (ALL_SUCCESS & @success) == ALL_SUCCESS
end

METHODS_SCORES = { SSLv2: 0, SSLv3: 80, TLSv1: 90, TLSv1_1: 95, TLSv1_2: 100 }
def protocol_score
methods = @server.supported_methods
worst, best = methods[:worst], methods[:best]

def calculate_protocol_score
methods = @server.supported_methods
worst, best = methods[:worst], methods[:best]
@protocol_score = (METHODS_SCORES[worst] + METHODS_SCORES[best]) / 2
end

def key_exchange_score
def calculate_key_exchange_score
@key_exchange_score = case @server.key_size
when 0 then 0
when 0...512 then 20
when 512...1024 then 40
when 1024...2048 then 80
when 2048...4096 then 90
else 100
end
when 0 then
0
when 0...512 then
20
when 512...1024 then
40
when 1024...2048 then
80
when 2048...4096 then
90
else
100
end
end

def cipher_strength_score(cipher_strength)
def calculate_cipher_strength_score(cipher_strength)
case cipher_strength
when 0 then 0
when 0...128 then 20
when 128...256 then 80
else 100
when 0 then
0
when 0...128 then
20
when 128...256 then
80
else
100
end
end

def cipher_strengths_score
strength = @server.cipher_size
worst, best = strength[:min], strength[:max]
@cipher_strengths_score = (cipher_strength_score(worst) + cipher_strength_score(best)) / 2
def calculate_cipher_strengths_score
strength = @server.cipher_size
worst, best = strength[:min], strength[:max]
@cipher_strengths_score = (calculate_cipher_strength_score(worst) + calculate_cipher_strength_score(best)) / 2
end
end
end

+ 1
- 1
lib/cryptcheck/tls/https/grade.rb Visa fil

@@ -3,7 +3,7 @@ module CryptCheck
module Https
class Grade < Tls::Grade
private
def success
def calculate_success
super
@success << :hsts if @server.hsts?
@success << :hsts_long if @server.hsts_long?

+ 4
- 15
lib/cryptcheck/tls/https/server.rb Visa fil

@@ -14,28 +14,17 @@ module CryptCheck
def fetch_hsts
port = @port == 443 ? '' : ":#{@port}"

response = nil
EXISTING_METHODS.each do |method|
begin
next unless SUPPORTED_METHODS.include? method
@log.debug { "Check HSTS with #{method}" }
response = ::HTTParty.head "https://#{@hostname}#{port}/", { follow_redirects: false, verify: false, ssl_version: method, timeout: SSL_TIMEOUT }
break
rescue Exception => e
@log.debug { "#{method} not supported : #{e}" }
end
end

if response and header = response.headers['strict-transport-security']
response = ::HTTParty.head "https://#{@hostname}#{port}/", { follow_redirects: false, verify: false, timeout: SSL_TIMEOUT }
if header = response.headers['strict-transport-security']
name, value = header.split '='
if name == 'max-age'
@hsts = value.to_i
@log.info { "HSTS : #{@hsts}" }
Logger.info { "HSTS : #{@hsts.to_s.colorize hsts_long? ? :green : nil}" }
return
end
end

@log.info { 'No HSTS' }
Logger.info { 'No HSTS'.colorize :yellow }
@hsts = nil
end


+ 65
- 70
lib/cryptcheck/tls/server.rb Visa fil

@@ -13,9 +13,9 @@ module CryptCheck
end

class Server
TCP_TIMEOUT = 10
SSL_TIMEOUT = 2*TCP_TIMEOUT
EXISTING_METHODS = %i(TLSv1_2 TLSv1_1 TLSv1 SSLv3 SSLv2)
TCP_TIMEOUT = 10
SSL_TIMEOUT = 2*TCP_TIMEOUT
EXISTING_METHODS = %i(TLSv1_2 TLSv1_1 TLSv1 SSLv3 SSLv2)
SUPPORTED_METHODS = ::OpenSSL::SSL::SSLContext::METHODS
class TLSException < ::Exception
end
@@ -33,20 +33,18 @@ module CryptCheck
attr_reader :hostname, :port, :prefered_ciphers, :cert, :cert_valid, :cert_trusted

def initialize(hostname, port)
@log = Logging.logger[hostname]
@hostname = hostname
@port = port
@log.error { "Begin analysis" }
@port = port
Logger.info { "#{hostname}:#{port}".colorize :blue }
extract_cert
#@prefered_ciphers = @supported_ciphers = Hash[SUPPORTED_METHODS.collect { |m| [m, []]}]
fetch_prefered_ciphers
check_supported_cipher
@log.error { "End analysis" }
end

def supported_methods
worst = EXISTING_METHODS.find { |method| !@prefered_ciphers[method].nil? }
best = EXISTING_METHODS.reverse.find { |method| !@prefered_ciphers[method].nil? }
best = EXISTING_METHODS.reverse.find { |method| !@prefered_ciphers[method].nil? }
{ worst: worst, best: best }
end

@@ -66,24 +64,24 @@ module CryptCheck
type, size = self.key
if type == :ecc
size = case size
when 160 then
1024
when 224 then
2048
when 256 then
3072
when 384 then
7680
when 521 then
15360
end
when 160 then
1024
when 224 then
2048
when 256 then
3072
when 384 then
7680
when 521 then
15360
end
end
size
end

def cipher_size
cipher_strengths = supported_ciphers.collect { |c| c[2] }.uniq.sort
worst, best = cipher_strengths.first, cipher_strengths.last
worst, best = cipher_strengths.first, cipher_strengths.last
{ worst: worst, best: best }
end

@@ -96,29 +94,22 @@ module CryptCheck
end

{
md2: %w(md2WithRSAEncryption),
md5: %w(md5WithRSAEncryption md5WithRSA),
md2: %w(md2WithRSAEncryption),
md5: %w(md5WithRSAEncryption md5WithRSA),
sha1: %w(sha1WithRSAEncryption sha1WithRSA dsaWithSHA1 dsaWithSHA1_2 ecdsa_with_SHA1)
}.each do |name, signature|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{name}_sig?
#{signature}.include? @cert.signature_algorithm
end
def #{name}_sig?
#{signature}.include? @cert.signature_algorithm
end
RUBY_EVAL
end

{
md5: %w(MD5),
sha1: %w(SHA),

rc4: %w(RC4),
des3: %w(3DES DES-CBC3),
des: %w(DES-CBC)
}.each do |name, ciphers|
Tls::TYPES.each do |type, _|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{name}?
supported_ciphers.any? { |supported| #{ciphers}.any? { |available| /(^|-)#\{available\}(-|$)/ =~ supported[0] } }
end
def #{type}?
supported_ciphers.any? { |s| Tls.#{type}? s.first }
end
RUBY_EVAL
end

@@ -134,14 +125,12 @@ module CryptCheck
tls? and !ssl?
end

PFS_CIPHERS = [/^DHE-RSA-/, /^DHE-DSS-/, /^ECDHE-RSA-/, /^ECDHE-ECDSA-/]

def pfs?
supported_ciphers.any? { |cipher| PFS_CIPHERS.any? { |pc| pc =~ cipher[0] } }
supported_ciphers.any? { |c| Tls.pfs? c.first }
end

def pfs_only?
supported_ciphers.all? { |cipher| PFS_CIPHERS.any? { |pc| pc =~ cipher[0] } }
supported_ciphers.all? { |c| Tls.pfs? c.first }
end

def supported_ciphers
@@ -154,21 +143,21 @@ module CryptCheck

private
def connect(family, host, port, &block)
socket = ::Socket.new family, sock_type
socket = ::Socket.new family, sock_type
sockaddr = ::Socket.sockaddr_in port, host
@log.debug { "Connecting to #{host}:#{port}" }
Logger.trace { "Connecting to #{host}:#{port}" }
begin
status = socket.connect_nonblock sockaddr
@log.debug { "Connecting to #{host}:#{port} status : #{status}" }
Logger.trace { "Connecting to #{host}:#{port} status : #{status}" }
raise ConnectionError, status unless status == 0
@log.debug { "Connected to #{host}:#{port}" }
Logger.trace { "Connected to #{host}:#{port}" }
block_given? ? block.call(socket) : nil
rescue ::IO::WaitReadable
@log.debug { "Waiting for read to #{host}:#{port}" }
Logger.trace { "Waiting for read to #{host}:#{port}" }
raise Timeout unless IO.select [socket], nil, nil, TCP_TIMEOUT
retry
rescue ::IO::WaitWritable
@log.debug { "Waiting for write to #{host}:#{port}" }
Logger.trace { "Waiting for write to #{host}:#{port}" }
raise Timeout unless IO.select nil, [socket], nil, TCP_TIMEOUT
retry
ensure
@@ -177,39 +166,39 @@ module CryptCheck
end

def ssl_connect(socket, context, method, &block)
ssl_socket = ::OpenSSL::SSL::SSLSocket.new socket, context
ssl_socket = ::OpenSSL::SSL::SSLSocket.new socket, context
ssl_socket.hostname = @hostname unless method == :SSLv2
@log.debug { "SSL connecting to #{@hostname}:#{@port}" }
Logger.trace { "SSL connecting to #{@hostname}:#{@port}" }
begin
ssl_socket.connect_nonblock
@log.debug { "SSL connected to #{@hostname}:#{@port}" }
Logger.trace { "SSL connected to #{@hostname}:#{@port}" }
return block_given? ? block.call(ssl_socket) : nil
rescue ::IO::WaitReadable
@log.debug { "Waiting for SSL read to #{@hostname}:#{@port}" }
Logger.trace { "Waiting for SSL read to #{@hostname}:#{@port}" }
raise TLSTimeout unless IO.select [socket], nil, nil, SSL_TIMEOUT
retry
rescue ::IO::WaitWritable
@log.debug { "Waiting for SSL write to #{@hostname}:#{@port}" }
Logger.trace { "Waiting for SSL write to #{@hostname}:#{@port}" }
raise TLSTimeout unless IO.select nil, [socket], nil, SSL_TIMEOUT
retry
rescue => e
raise TLSException, e
rescue => e
raise TLSNotAvailableException, e
ensure
ssl_socket.close
end
end

def ssl_client(method, ciphers = nil, &block)
ssl_context = ::OpenSSL::SSL::SSLContext.new method
ssl_context = ::OpenSSL::SSL::SSLContext.new method
ssl_context.ciphers = ciphers if ciphers
@log.debug { "Try #{method} connection with #{ciphers}" }
Logger.trace { "Try #{method} connection with #{ciphers}" }

[::Socket::AF_INET, ::Socket::AF_INET6].each do |family|
@log.debug { "Try connection for family #{family}" }
Logger.trace { "Try connection for family #{family}" }
addrs = begin
::Socket.getaddrinfo @hostname, nil, family, :STREAM
rescue ::SocketError => e
@log.debug { "Unable to resolv #{@hostname} : #{e}" }
Logger.error { "Unable to resolv #{@hostname} : #{e}" }
next
end

@@ -222,7 +211,7 @@ module CryptCheck
end
end

@log.debug { "No SSL available on #{@hostname}" }
Logger.debug { "No SSL available on #{@hostname}" }
raise CipherNotAvailable
end

@@ -231,27 +220,28 @@ module CryptCheck
next unless SUPPORTED_METHODS.include? method
begin
@cert, @chain = ssl_client(method) { |s| [s.peer_cert, s.peer_cert_chain] }
@log.warn { "Certificate #{@cert.subject}" }
Logger.debug { "Certificate #{@cert.subject}" }
break
rescue TLSException => e
@log.info { "Method #{method} not supported : #{e}" }
Logger.trace { "Method #{Tls.colorize method} not supported : #{e}" }
end
end
raise TLSNotAvailableException unless @cert
@cert_valid = ::OpenSSL::SSL.verify_certificate_identity @cert, @hostname
@cert_valid = ::OpenSSL::SSL.verify_certificate_identity @cert, @hostname
@cert_trusted = verify_trust @chain, @cert
end

def prefered_cipher(method)
cipher = ssl_client(method, %w(ALL:COMPLEMENTOFALL)) { |s| s.cipher }
@log.warn { "Prefered cipher for #{method} : #{cipher[0]}" }
cipher = ssl_client(method, 'ALL:COMPLEMENTOFALL') { |s| s.cipher }
Logger.info { "Prefered cipher for #{Tls.colorize method} : #{Tls.colorize cipher.first}" }
cipher
rescue Exception => e
@log.info { "Method #{method} not supported : #{e}" }
rescue Exception
Logger.debug { "Method #{Tls.colorize method} not supported" }
nil
end

def fetch_prefered_ciphers
Logger.info { '' }
@prefered_ciphers = {}
EXISTING_METHODS.each do |method|
next unless SUPPORTED_METHODS.include? method
@@ -261,28 +251,33 @@ module CryptCheck
end

def available_ciphers(method)
::OpenSSL::SSL::SSLContext.new(method).ciphers
context = ::OpenSSL::SSL::SSLContext.new method
context.ciphers = 'ALL:COMPLEMENTOFALL'
context.ciphers
end

def supported_cipher?(method, cipher)
ssl_client method, [cipher]
@log.warn { "Verify #{method} / #{cipher[0]} : OK" }
Logger.info { "#{Tls.colorize method} / #{Tls.colorize cipher[0]} : Supported" }
true
rescue TLSException => e
@log.info { "Verify #{method} / #{cipher[0]} : NOK (#{e})" }
Logger.debug { "#{Tls.colorize method} / #{Tls.colorize cipher[0]} : Not supported" }
false
end

def check_supported_cipher
Logger.info { '' }
@supported_ciphers = {}
EXISTING_METHODS.each do |method|
next unless SUPPORTED_METHODS.include? method and @prefered_ciphers[method]
@supported_ciphers[method] = available_ciphers(method).select { |cipher| supported_cipher? method, cipher }
ciphers = available_ciphers(method).select { |cipher| supported_cipher? method, cipher }
@supported_ciphers[method] = ciphers
Logger.info { '' } unless ciphers.empty?
end
end

def verify_trust(chain, cert)
store = ::OpenSSL::X509::Store.new
store = ::OpenSSL::X509::Store.new
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
store.set_default_paths


+ 2
- 2
lib/cryptcheck/tls/xmpp.rb Visa fil

@@ -7,14 +7,14 @@ module CryptCheck
module Xmpp
MAX_ANALYSIS_DURATION = 600
PARALLEL_ANALYSIS = 10
@@log = ::Logging.logger[Xmpp]
@Logger = ::Logging.logger[Xmpp]

def self.grade(hostname, type=:s2s)
timeout MAX_ANALYSIS_DURATION do
Grade.new Server.new hostname, type
end
rescue ::Exception => e
@@log.error { "Error during #{hostname}:#{type} analysis : #{e}" }
@Logger.error { "Error during #{hostname}:#{type} analysis : #{e}" }
TlsNotSupportedGrade.new TlsNotSupportedServer.new hostname, type
end


+ 1
- 1
lib/cryptcheck/tls/xmpp/grade.rb Visa fil

@@ -2,7 +2,7 @@ module CryptCheck
module Tls
module Xmpp
class Grade < Tls::Grade
def success
def calculate_success
super
@success << :required if @server.required?
end

+ 2
- 0
lib/cryptcheck/tls/xmpp/server.rb Visa fil

@@ -25,6 +25,8 @@ module CryptCheck
end
end
super hostname, port
Logger.info { '' }
Logger.info { self.required? ? 'Required'.colorize(:green) : 'Not required'.colorize(:yellow) }
end

def ssl_connect(socket, context, method, &block)

Laddar…
Avbryt
Spara