TLS server for testing

new-scoring
aeris 6 years ago
parent 0c3bda1467
commit 52a19f8c35
  1. 15
      .gitignore
  2. 1
      bin/tls_server
  3. 123
      bin/tls_server.rb
  4. 73
      lib/cryptcheck/tls/fixture.rb
  5. 4
      lib/cryptcheck/tls/server.rb
  6. 4
      spec/helpers.rb

15
.gitignore vendored

@ -1,13 +1,14 @@
*.iml
*.gem
Gemfile.lock
*.pem
.rakeTasks
.idea/
/html/
/rakefile
/output/*.html
/build/
/db/*.sqlite3
/db/schema.rb
/lib/**/*.so
/lib/**/*.so.1.0.0
/build/
/output/*.html
/lib/*.so
/lib/*.so.*
/.ruby-version
/rakefile
Gemfile.lock

@ -0,0 +1 @@
runner

@ -0,0 +1,123 @@
#!/usr/bin/env ruby
$:.unshift File.expand_path File.join File.dirname(__FILE__), '../lib'
require 'rubygems'
require 'bundler/setup'
require 'openssl'
require 'socket'
require 'cryptcheck'
::CryptCheck::Logger.level = ENV['LOG'] || :info
OpenSSL::PKey::EC.send :alias_method, :private?, :private_key?
# [512, 768, 1024, 2048, 3072, 4096].each do |s|
# file = "config/rsa-#{s}.pem"
# unless File.exists? file
# puts :rsa, s
# dh = OpenSSL::PKey::RSA.new s
# File.write file, dh.to_pem
# end
#
# file = "config/dh-#{s}.pem"
# unless File.exists? file
# puts :dh, s
# dh = OpenSSL::PKey::DH.new s
# File.write file, dh.to_pem
# end
# end
# exit
def certificate(key)
CryptCheck::Logger.info 'Generating certificate'
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = rand 2**(20*8-1) .. 2**(20*8)
cert.not_before = Time.now
cert.not_after = Time.now + 365*24*60*60
cert.public_key = case key
when OpenSSL::PKey::EC
curve = key.group.curve_name
public = OpenSSL::PKey::EC.new curve
public.public_key = key.public_key
public
else
key.public_key
end
name = OpenSSL::X509::Name.parse 'CN=localhost'
cert.subject = name
cert.issuer = name
extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
extension_factory.subject_certificate = cert
extension_factory.issuer_certificate = cert
cert.add_extension extension_factory.create_extension 'basicConstraints', 'CA:TRUE', true
cert.add_extension extension_factory.create_extension 'keyUsage', 'keyEncipherment, dataEncipherment, digitalSignature,nonRepudiation,keyCertSign'
cert.add_extension extension_factory.create_extension 'extendedKeyUsage', 'serverAuth, clientAuth'
cert.add_extension extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
cert.add_extension extension_factory.create_extension 'authorityKeyIdentifier', 'keyid:always'
cert.add_extension extension_factory.create_extension 'subjectAltName', 'DNS:localhost'
cert.add_extension OpenSSL::X509::Extension.new '1.3.6.1.5.5.7.1.24', '0', true
cert.sign key, OpenSSL::Digest::SHA512.new
CryptCheck::Logger.info 'Certificate generated'
cert
end
key = OpenSSL::PKey::RSA.new File.read 'config/rsa-2048.pem'
#key = OpenSSL::PKey::EC.new('secp521r1').generate_key
cert = certificate key
CryptCheck::Logger.info 'Starting server'
context = OpenSSL::SSL::SSLContext.new
#context = OpenSSL::SSL::SSLContext.new :SSLv3
#context = OpenSSL::SSL::SSLContext.new :TLSv1_1
context.cert = cert
context.key = key
context.ciphers = ARGV[0] || 'ECDHE+AESGCM'
dh = OpenSSL::PKey::DH.new File.read 'config/dh-4096.pem'
context.tmp_dh_callback = proc { dh }
#context.ecdh_curves = CryptCheck::Tls::Server::SUPPORTED_CURVES.join ':'
#context.ecdh_curves = 'secp384r1:secp521r1:sect571r1'
context.ecdh_curves = 'secp384r1'
#ecdh = OpenSSL::PKey::EC.new('secp384r1').generate_key
#context.tmp_ecdh_callback = proc { ecdh }
host, port = '::', 5000
tcp_server = TCPServer.new host, port
tls_server = OpenSSL::SSL::SSLServer.new tcp_server, context
::CryptCheck::Logger.info "Server started on #{host}:#{port}"
loop do
begin
connection = tls_server.accept
method = connection.ssl_version
dh = connection.tmp_key
cipher = connection.cipher
cipher = CryptCheck::Tls::Cipher.new method, cipher, dh
states = cipher.states
text = %i(critical error warning good perfect best).collect do |s|
states[s].collect { |t| t.to_s.colorize s }.join ' '
end.reject &:empty?
text = text.join ' '
dh = dh ? " (#{'PFS'.colorize :good} : #{CryptCheck::Tls.key_to_s dh})" : ''
CryptCheck::Logger.info { "#{CryptCheck::Tls.colorize method} / #{cipher.colorize}#{dh} [#{text}]" }
data = connection.gets
if data
CryptCheck::Logger.info data
end
connection.puts 'HTTP/1.1 200 OK'
connection.puts 'Strict-Transport-Security: max-age=31536000'
connection.close
rescue OpenSSL::SSL::SSLError, SystemCallError
end
end

@ -5,29 +5,51 @@ class String
COLORS = {
critical: { color: :white, background: :red },
error: :red,
warning: :light_red,
good: :green,
perfect: :blue,
best: :magenta,
unknown: { background: :black }
error: :red,
warning: :light_red,
good: :green,
perfect: :blue,
best: :magenta,
unknown: { background: :black }
}
def colorize(state)
self.colorize_old COLORS[state]
color = COLORS[state] || state
self.colorize_old color
end
end
class Exception
BACKTRACE_REGEXP = /^(.*):(\d+):in `(.*)'$/
def colorize
$stderr.puts self.message.colorize(:red)
self.backtrace.each do |line|
line = BACKTRACE_REGEXP.match line
line = '%s:%s:in `%s\'' % [
line[1].colorize(:yellow),
line[2].colorize(:blue),
line[3].colorize(:magenta)
]
$stderr.puts line
end
end
end
class Integer
def humanize
secs = self
[[60, :second], [60, :minute], [24, :hour], [30, :day], [12, :month]].map { |count, name|
[[60, :second],
[60, :minute],
[24, :hour],
[30, :day],
[12, :month]].map do |count, name|
if secs > 0
secs, n = secs.divmod count
n = n.to_i
n = n.to_i
n > 0 ? "#{n} #{name}#{n > 1 ? 's' : ''}" : nil
end
}.compact.reverse.join(' ')
end.compact.reverse.join ' '
end
end
@ -46,10 +68,14 @@ class ::OpenSSL::PKey::EC
def status
case self.size
when 0...160 then :critical
when 160...192 then :error
when 192...256 then :warning
when 384...::Float::INFINITY then :good
when 0...160
:critical
when 160...192
:error
when 192...256
:warning
when 384...::Float::INFINITY
:good
end
end
end
@ -69,9 +95,12 @@ class ::OpenSSL::PKey::RSA
def status
case self.size
when 0...1024 then :critical
when 1024...2048 then :error
when 4096...::Float::INFINITY then :good
when 0...1024
:critical
when 1024...2048
:error
when 4096...::Float::INFINITY
:good
end
end
end
@ -109,9 +138,13 @@ class ::OpenSSL::PKey::DH
def status
case self.size
when 0...1024 then :critical
when 1024...2048 then :error
when 4096...::Float::INFINITY then :good
when 0...1024
:critical
when 1024...2048
:error
when 2048...4096
else
:good
end
end
end

@ -260,7 +260,8 @@ module CryptCheck
sect571r1 X25519)
def ssl_client(method, ciphers = %w(ALL COMPLEMENTOFALL), curves = nil, fallback: false, &block)
ssl_context = ::OpenSSL::SSL::SSLContext.new method, fallback_scsv: fallback
ssl_context = ::OpenSSL::SSL::SSLContext.new method #, fallback_scsv: fallback
ssl_context.enable_fallback_scsv if fallback
ssl_context.ciphers = ciphers.join ':'
ssl_context.ecdh_curves = curves.join ':' if curves
@ -285,7 +286,6 @@ module CryptCheck
break
rescue Timeout, TLSTimeout, ConnectionError, ::SystemCallError
raise
rescue
end
end
raise TLSNotAvailableException unless @cert

@ -184,9 +184,9 @@ module Helpers
expect(server.ip).to eq ip
expect(server.port).to eq port
expect(server.family).to eq case family
when :ipv4 then
when :ipv4
Socket::AF_INET
when :ipv6 then
when :ipv6
Socket::AF_INET6
end
[grade, server]

Loading…
Cancel
Save