Quellcode durchsuchen

Verify cert chain and hostname

master
Nicolas Vinot vor 4 Jahren
Ursprung
Commit
d356969013
2 geänderte Dateien mit 47 neuen und 18 gelöschten Zeilen
  1. 7
    3
      lib/sslcheck/grade.rb
  2. 40
    15
      lib/sslcheck/server.rb

+ 7
- 3
lib/sslcheck/grade.rb Datei anzeigen

@@ -36,9 +36,12 @@ module SSLCheck
end

@grade = [@grade, 'B'].max if !@server.tlsv1_2? or @server.key_size < 2048
@grade = [@grade, 'D'].max if @server.rc4?
@grade = [@grade, 'E'].max if @server.des3?
@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 = 'M' unless @server.cert_valid
@grade = 'T' unless @server.cert_trusted
end

def warning
@@ -62,9 +65,10 @@ module SSLCheck
@success << :hsts_long if @server.hsts_long?
end

ALL_WARNING = %i(md5_sig md5 rc4 des)
ALL_SUCCESS = %i(pfs hsts hsts_long)
def perfect
@grade = 'A+' if @grade == 'A' and @warning.empty? and (ALL_SUCCESS & @success) == ALL_SUCCESS
@grade = 'A+' if @grade == 'A' and (ALL_WARNING & @warning).empty? and (ALL_SUCCESS & @success) == ALL_SUCCESS
end

METHODS_SCORES = { SSLv2: 0, SSLv3: 80, TLSv1: 90, TLSv1_1: 95, TLSv1_2: 100 }

+ 40
- 15
lib/sslcheck/server.rb Datei anzeigen

@@ -14,16 +14,18 @@ module SSLCheck
end

class Server
TCP_TIMEOUT = 60
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 TLSNotAvailableException < Exception; end
class CipherNotAvailable < Exception; end
class Timeout < Exception; end
class ConnectionError < Exception; end
class TLSException < Exception; end
class TLSNotAvailableException < TLSException; end
class CipherNotAvailable < TLSException; end
class Timeout < TLSException; end
class TLSTimeout < TLSException; end
class ConnectionError < TLSException; end

attr_reader :hostname, :port, :prefered_ciphers, :cert, :hsts
attr_reader :hostname, :port, :prefered_ciphers, :cert, :hsts, :cert_valid, :cert_trusted

def initialize(hostname, port=443, methods: EXISTING_METHODS)
@log = Logging.logger[hostname]
@@ -111,10 +113,6 @@ module SSLCheck
RUBY_EVAL
end

def any_des?
des? or des3?
end

def ssl?
sslv2? or sslv3?
end
@@ -187,12 +185,14 @@ module SSLCheck
return block_given? ? block.call(ssl_socket) : nil
rescue IO::WaitReadable
@log.debug { "Waiting for SSL read to #{@hostname}:#{@port}" }
raise Timeout.new unless IO.select [socket], nil, nil, SSL_TIMEOUT
raise TLSTimeout.new unless IO.select [socket], nil, nil, SSL_TIMEOUT
retry
rescue IO::WaitWritable
@log.debug { "Waiting for SSL write to #{@hostname}:#{@port}" }
raise Timeout.new unless IO.select nil, [socket], nil, SSL_TIMEOUT
raise TLSTimeout.new unless IO.select nil, [socket], nil, SSL_TIMEOUT
retry
rescue OpenSSL::SSL::SSLError => e
raise TLSException, e
ensure
ssl_socket.close
end
@@ -229,14 +229,16 @@ module SSLCheck
@methods.each do |method|
next unless SUPPORTED_METHODS.include? method
begin
@cert = ssl_client(method) { |s| s.peer_cert }
@cert, @chain = ssl_client(method) { |s| [s.peer_cert, s.peer_cert_chain] }
@log.warn { "Certificate #{@cert.subject}" }
break
rescue Exception => e
rescue TLSException => e
@log.info { "Method #{method} not supported : #{e}" }
end
end
raise TLSNotAvailableException.new unless @cert
@cert_valid = OpenSSL::SSL.verify_certificate_identity @cert, @hostname
@cert_trusted = verify_trust @chain, @cert
end

def prefered_cipher(method)
@@ -265,7 +267,7 @@ module SSLCheck
ssl_client method, [cipher]
@log.warn { "Verify #{method} / #{cipher[0]} : OK" }
true
rescue Exception => e
rescue TLSException => e
@log.info { "Verify #{method} / #{cipher[0]} : NOK (#{e})" }
false
end
@@ -305,5 +307,28 @@ module SSLCheck
@log.info { 'No HSTS' }
@hsts = nil
end

def verify_trust(chain, cert)
store = OpenSSL::X509::Store.new
#store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
%w(mozilla cacert).each do |directory|
Dir.glob(File.join '/usr/share/ca-certificates', directory, '*').each do |file|
File.open file, 'r' do |file|
cert = OpenSSL::X509::Certificate.new file.read
begin
store.add_cert cert
rescue OpenSSL::X509::StoreError
end
end
end
end
chain.each do |cert|
begin
store.add_cert cert
rescue OpenSSL::X509::StoreError
end
end
store.verify cert
end
end
end

Laden…
Abbrechen
Speichern