From 5950312ef5d3d521088b0e0e530dbcfa60ea4028 Mon Sep 17 00:00:00 2001 From: aeris Date: Wed, 1 Feb 2017 19:15:30 +0100 Subject: [PATCH] Clean unit tests --- bin/supported.rb | 2 +- lib/cryptcheck/tls/method.rb | 39 ++-- spec/cryptcheck/tls/cert_spec.rb | 39 ++++ spec/cryptcheck/tls/method_spec.rb | 61 ++++++ spec/cryptcheck/tls/server_spec.rb | 292 +++++++++++++---------------- 5 files changed, 254 insertions(+), 179 deletions(-) create mode 100644 spec/cryptcheck/tls/method_spec.rb diff --git a/bin/supported.rb b/bin/supported.rb index 84551fb..ba173bb 100755 --- a/bin/supported.rb +++ b/bin/supported.rb @@ -5,7 +5,7 @@ require 'bundler/setup' require 'cryptcheck' puts 'Supported methods' -puts CryptCheck::Tls::Method::SUPPORTED.sort.collect(&:to_s).join ' ' +puts CryptCheck::Tls::Method::SUPPORTED.values.sort.collect(&:to_s).join ' ' CryptCheck::Tls::Cipher.each do |method, ciphers| puts diff --git a/lib/cryptcheck/tls/method.rb b/lib/cryptcheck/tls/method.rb index d0345e2..4ff26c2 100644 --- a/lib/cryptcheck/tls/method.rb +++ b/lib/cryptcheck/tls/method.rb @@ -1,34 +1,45 @@ +require 'delegate' + module CryptCheck module Tls - class Method + class Method < SimpleDelegator + EXISTING = %i(TLSv1_2 TLSv1_1 TLSv1 SSLv3 SSLv2).freeze + SUPPORTED = (EXISTING & ::OpenSSL::SSL::SSLContext::METHODS) + .collect { |m| [m, self.new(m)] }.to_h.freeze + + def self.[](method) + SUPPORTED[method] + end + extend Enumerable def self.each(&block) - SUPPORTED.each &block + SUPPORTED.values.each &block end - attr_reader :name - - def initialize(name) - @name = name - end - - EXISTING = %i(TLSv1_2 TLSv1_1 TLSv1 SSLv3 SSLv2).freeze - SUPPORTED = (EXISTING & ::OpenSSL::SSL::SSLContext::METHODS).collect { |m| self.new m }.freeze - def to_s - colors = case @name + colors = case self.to_sym when *%i(SSLv3 SSLv2) :critical when :TLSv1_2 :good end - @name.to_s.colorize colors + super.colorize colors end + alias :to_sym :__getobj__ + def <=>(other) - EXISTING.find_index(@name) <=> EXISTING.find_index(other.name) + EXISTING.find_index(self) <=> EXISTING.find_index(other) end + + # def eql?(other) + # self.to_sym.eql? other.to_sym + # end + # + # def equal?(other) + # self.to_sym.equal? other.to_sym + # end end end end diff --git a/spec/cryptcheck/tls/cert_spec.rb b/spec/cryptcheck/tls/cert_spec.rb index 2916250..5fa01d7 100644 --- a/spec/cryptcheck/tls/cert_spec.rb +++ b/spec/cryptcheck/tls/cert_spec.rb @@ -54,4 +54,43 @@ describe CryptCheck::Tls::Cert do end end end + + describe '#md5?' do + it 'must detect md5 certificate' do + cert = ::CryptCheck::Tls::Cert.new cert(:md5) + expect(cert.md5?).to be true + + cert = ::CryptCheck::Tls::Cert.new cert(:sha1) + expect(cert.md5?).to be false + + cert = ::CryptCheck::Tls::Cert.new cert(:ecdsa, :prime256v1) + expect(cert.md5?).to be false + end + end + + describe '#sha1?' do + it 'must detect sha1 certificate' do + cert = ::CryptCheck::Tls::Cert.new cert(:md5) + expect(cert.sha1?).to be false + + cert = ::CryptCheck::Tls::Cert.new cert(:sha1) + expect(cert.sha1?).to be true + + cert = ::CryptCheck::Tls::Cert.new cert(:ecdsa, :prime256v1) + expect(cert.sha1?).to be false + end + end + + describe '#sha2?' do + it 'must detect sha2 certificate' do + cert = ::CryptCheck::Tls::Cert.new cert(:md5) + expect(cert.sha2?).to be false + + cert = ::CryptCheck::Tls::Cert.new cert(:sha1) + expect(cert.sha2?).to be false + + cert = ::CryptCheck::Tls::Cert.new cert(:ecdsa, :prime256v1) + expect(cert.sha2?).to be true + end + end end diff --git a/spec/cryptcheck/tls/method_spec.rb b/spec/cryptcheck/tls/method_spec.rb new file mode 100644 index 0000000..489fac2 --- /dev/null +++ b/spec/cryptcheck/tls/method_spec.rb @@ -0,0 +1,61 @@ +describe CryptCheck::Tls::Method do + describe '#==' do + it 'must be equals to corresponding symbol' do + method = ::CryptCheck::Tls::Method[:TLSv1_2] + expect(method == :SSLv2).to be false + expect(method == :SSLv3).to be false + expect(method == :TLSv1).to be false + expect(method == :TLSv1_1).to be false + expect(method == :TLSv1_2).to be true + end + + it 'must be equals to corresponding method' do + method = ::CryptCheck::Tls::Method[:TLSv1_2] + expect(method == ::CryptCheck::Tls::Method[:SSLv2]).to be false + expect(method == ::CryptCheck::Tls::Method[:SSLv3]).to be false + expect(method == ::CryptCheck::Tls::Method[:TLSv1]).to be false + expect(method == ::CryptCheck::Tls::Method[:TLSv1_1]).to be false + expect(method == ::CryptCheck::Tls::Method[:TLSv1_2]).to be true + end + end + + # describe '#eql?' do + # it 'must be equals to corresponding symbol' do + # method = ::CryptCheck::Tls::Method[:TLSv1_2] + # expect(method.eql? :SSLv2).to be false + # expect(method.eql? :SSLv3).to be false + # expect(method.eql? :TLSv1).to be false + # expect(method.eql? :TLSv1_1).to be false + # expect(method.eql? :TLSv1_2).to be true + # end + # + # it 'must be equals to corresponding method' do + # method = ::CryptCheck::Tls::Method[:TLSv1_2] + # expect(method.eql? ::CryptCheck::Tls::Method[:SSLv2]).to be false + # expect(method.eql? ::CryptCheck::Tls::Method[:SSLv3]).to be false + # expect(method.eql? ::CryptCheck::Tls::Method[:TLSv1]).to be false + # expect(method.eql? ::CryptCheck::Tls::Method[:TLSv1_1]).to be false + # expect(method.eql? ::CryptCheck::Tls::Method[:TLSv1_2]).to be true + # end + # end + # + # describe '#equal?' do + # it 'must be equals to corresponding symbol' do + # method = ::CryptCheck::Tls::Method[:TLSv1_2] + # expect(method.equal? :SSLv2).to be false + # expect(method.equal? :SSLv3).to be false + # expect(method.equal? :TLSv1).to be false + # expect(method.equal? :TLSv1_1).to be false + # expect(method.equal? :TLSv1_2).to be true + # end + # + # it 'must be equals to corresponding method' do + # method = ::CryptCheck::Tls::Method[:TLSv1_2] + # expect(method.equal? ::CryptCheck::Tls::Method[:SSLv2]).to be false + # expect(method.equal? ::CryptCheck::Tls::Method[:SSLv3]).to be false + # expect(method.equal? ::CryptCheck::Tls::Method[:TLSv1]).to be false + # expect(method.equal? ::CryptCheck::Tls::Method[:TLSv1_1]).to be false + # expect(method.equal? ::CryptCheck::Tls::Method[:TLSv1_2]).to be true + # end + # end +end diff --git a/spec/cryptcheck/tls/server_spec.rb b/spec/cryptcheck/tls/server_spec.rb index 56bd2a0..89a591e 100644 --- a/spec/cryptcheck/tls/server_spec.rb +++ b/spec/cryptcheck/tls/server_spec.rb @@ -9,268 +9,232 @@ describe CryptCheck::Tls::Server do FakeTime.unfreeze end - def server - CryptCheck::Tls::TcpServer.new 'localhost', ::Socket::PF_INET, '127.0.0.1', 5000 + default_parameters = { + methods: %i(TLSv1_2), + chain: %w(intermediate ca), + curves: %i(prime256v1), + server_preference: true + }.freeze + default_ecdsa_parameters = default_parameters.merge({ + material: [[:ecdsa, :prime256v1]], + ciphers: %i(ECDHE-ECDSA-AES128-SHA), + curves: %i(prime256v1) + }).freeze + default_rsa_parameters = default_parameters.merge({ + material: [[:rsa, 1024]], + ciphers: %i(ECDHE-RSA-AES128-SHA), + curves: %i(prime256v1), + dh: 1024 + }).freeze + default_mixed_parameters = default_parameters.merge({ + material: [[:ecdsa, :prime256v1], [:rsa, 1024]], + ciphers: %i(ECDHE-ECDSA-AES128-SHA ECDHE-RSA-AES128-SHA), + curves: %i(prime256v1), + dh: 1024 + }).freeze + default_sslv2_parameters = default_parameters.merge({ + methods: :SSLv2, + material: [[:rsa, 1024]], + ciphers: %i(RC4-MD5), + chain: [] + }).freeze + DEFAULT_PARAMETERS = { ecdsa: default_ecdsa_parameters.freeze, + rsa: default_rsa_parameters.freeze, + mixed: default_mixed_parameters.freeze, + sslv2: default_sslv2_parameters.freeze }.freeze + + def server(type=:ecdsa, **kargs) + params = DEFAULT_PARAMETERS[type].dup + params.merge!(kargs) if kargs + host, port = '127.0.0.1', 5000 + params.merge!({ host: host, port: port }) + tls_serv **params do + CryptCheck::Tls::TcpServer.new 'localhost', ::Socket::PF_INET, host, port + end end describe '#certs' do it 'must detect RSA certificate' do - tls_serv material: [[:rsa, 1024]] do - certs = server.certs.collect &:fingerprint - expect(certs).to match_array %w(a11802a4407aaeb93ccd0bd8c8a61be17eaba6b378433af5ad45ecbb1d633f71) - end + certs = server(:rsa).certs.collect &:fingerprint + expect(certs).to match_array %w(a11802a4407aaeb93ccd0bd8c8a61be17eaba6b378433af5ad45ecbb1d633f71) end it 'must detect ECDSA certificate' do - tls_serv material: [[:ecdsa, :prime256v1]] do - certs = server.certs.collect &:fingerprint - expect(certs).to match_array %w(531ab9545f052818ff0559f648a147b104223834cc8f780516b3aacf1fdc8c06) - end + certs = server.certs.collect &:fingerprint + expect(certs).to match_array %w(531ab9545f052818ff0559f648a147b104223834cc8f780516b3aacf1fdc8c06) end it 'must detect RSA and ECDSA certificates' do - tls_serv material: [[:ecdsa, :prime256v1], [:rsa, 1024]] do - certs = server.certs.collect &:fingerprint - expect(certs).to match_array %w(531ab9545f052818ff0559f648a147b104223834cc8f780516b3aacf1fdc8c06 + certs = server(:mixed).certs.collect &:fingerprint + expect(certs).to match_array %w(531ab9545f052818ff0559f648a147b104223834cc8f780516b3aacf1fdc8c06 a11802a4407aaeb93ccd0bd8c8a61be17eaba6b378433af5ad45ecbb1d633f71) - end end end describe '#md5_sign?' do it 'must detect server using MD5 certificate' do - tls_serv do - expect(server.md5_sign?).to be false - end - - tls_serv material: [:md5, [:rsa, 1024]] do - expect(server.md5_sign?).to be true - end + expect(server.md5_sign?).to be false + expect(server(material: [:md5, [:rsa, 1024]]).md5_sign?).to be true end end describe '#sha1_sign?' do it 'must detect server using SHA1 certificate' do - tls_serv do - expect(server.sha1_sign?).to be false - end - - tls_serv material: [:sha1, [:rsa, 1024]] do - expect(server.sha1_sign?).to be true - end + expect(server.sha1_sign?).to be false + expect(server(material: [:sha1, [:rsa, 1024]]).sha1_sign?).to be true end end describe '#sha2_sign?' do it 'must detect server using SHA2 certificate' do - tls_serv do - expect(server.sha2_sign?).to be true - end - - tls_serv material: [:md5, :sha1] do - expect(server.sha2_sign?).to be false - end + expect(server.sha2_sign?).to be true + expect(server(material: [:md5]).sha2_sign?).to be false + expect(server(material: [:sha1]).sha2_sign?).to be false end end describe '#supported_methods' do it 'must detect SSLv2' do - tls_serv methods: :SSLv2, material: [[:rsa, 1024]], chain: [], - ciphers: %w(RC4-MD5) do - methods = server.supported_methods.collect &:name - expect(methods).to match_array %i(SSLv2) - end + s = server :sslv2 + methods = s.supported_methods.collect &:to_sym + expect(methods).to match_array %i(SSLv2) end it 'must detect SSLv3' do - tls_serv methods: %i(SSLv3), material: [[:rsa, 1024]], - ciphers: %w(ECDHE-RSA-AES128-SHA) do - methods = server.supported_methods.collect &:name - expect(methods).to match_array %i(SSLv3) - end + server = server methods: %i(SSLv3) + methods = server.supported_methods.collect &:to_sym + expect(methods).to match_array %i(SSLv3) end it 'must detect TLSv1.0' do - tls_serv methods: %i(TLSv1), material: [[:rsa, 1024]], - ciphers: %w(ECDHE-RSA-AES128-SHA) do - methods = server.supported_methods.collect &:name - expect(methods).to match_array %i(TLSv1) - end + server = server methods: %i(TLSv1) + methods = server.supported_methods.collect &:to_sym + expect(methods).to match_array %i(TLSv1) end it 'must detect TLSv1.1' do - tls_serv methods: %i(TLSv1_1), material: [[:rsa, 1024]], - ciphers: %w(ECDHE-RSA-AES128-SHA) do - methods = server.supported_methods.collect &:name - expect(methods).to match_array %i(TLSv1_1) - end + server = server methods: %i(TLSv1_1) + methods = server.supported_methods.collect &:to_sym + expect(methods).to match_array %i(TLSv1_1) end it 'must detect TLSv1.2' do - tls_serv methods: %i(TLSv1_2), material: [[:rsa, 1024]], - ciphers: %w(ECDHE-RSA-AES128-SHA) do - methods = server.supported_methods.collect &:name - expect(methods).to match_array %i(TLSv1_2) - end + server = server methods: %i(TLSv1_2) + methods = server.supported_methods.collect &:to_sym + expect(methods).to match_array %i(TLSv1_2) end it 'must detect mixed methods' do - tls_serv methods: %i(SSLv3 TLSv1 TLSv1_1 TLSv1_2), material: [[:rsa, 1024]], - ciphers: %w(ECDHE-RSA-AES128-SHA) do - methods = server.supported_methods.collect &:name - expect(methods).to match_array %i(SSLv3 TLSv1 TLSv1_1 TLSv1_2) - end + server = server methods: %i(SSLv3 TLSv1 TLSv1_1 TLSv1_2) + methods = server.supported_methods.collect &:to_sym + expect(methods).to match_array %i(SSLv3 TLSv1 TLSv1_1 TLSv1_2) end end describe '#supported_curves' do it 'must detect no supported curves' do - tls_serv material: [[:rsa, 1024]], ciphers: %w(AES128-GCM-SHA256) do - curves = server.supported_curves.collect &:name - expect(curves).to be_empty - end + s = server :rsa, ciphers: %w(AES128-SHA) + curves = s.supported_curves.collect &:name + expect(curves).to be_empty end it 'must detect supported curves for RSA' do - tls_serv material: [[:rsa, 1024]], ciphers: %w(ECDHE-RSA-AES128-GCM-SHA256), - curves: %i(prime256v1 sect571r1) do - curves = server.supported_curves.collect &:name - expect(curves).to contain_exactly :prime256v1, :sect571r1 - end + s = server :rsa, curves: %i(prime256v1 sect571r1) + curves = s.supported_curves.collect &:name + expect(curves).to contain_exactly :prime256v1, :sect571r1 end it 'must detect supported curves from ECDSA' do - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(prime256v1), server_preference: false do - curves = server.supported_curves.collect &:name - expect(curves).to contain_exactly :prime256v1 - end + server = server server_preference: false + curves = server.supported_curves.collect &:name + expect(curves).to contain_exactly :prime256v1 end it 'must detect supported curves from ECDSA and ECDHE' do - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(prime256v1 sect571r1), server_preference: false do - curves = server.supported_curves.collect &:name - expect(curves).to contain_exactly :prime256v1, :sect571r1 - end + server = server curves: %i(prime256v1 sect571r1), server_preference: false + curves = server.supported_curves.collect &:name + expect(curves).to contain_exactly :prime256v1, :sect571r1 end # No luck here :'( it 'can\'t detect supported curves from ECDHE if server preference enforced' do - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(prime256v1 sect571r1), server_preference: true do - curves = server.supported_curves.collect &:name - expect(curves).to contain_exactly :prime256v1 - end + server = server curves: %i(prime256v1 sect571r1) + curves = server.supported_curves.collect &:name + expect(curves).to contain_exactly :prime256v1 - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(sect571r1 prime256v1), server_preference: true do - curves = server.supported_curves.collect &:name - expect(curves).to contain_exactly :prime256v1, :sect571r1 - end + server = server curves: %i(sect571r1 prime256v1) + curves = server.supported_curves.collect &:name + expect(curves).to contain_exactly :prime256v1, :sect571r1 end end describe '#curves_preference' do it 'must report N/A if no curve on RSA' do - tls_serv material: [[:rsa, 1024]], ciphers: %w(AES128-GCM-SHA256), - server_preference: true do - curves = server.curves_preference - expect(curves).to be_nil - end + s = server :rsa, ciphers: %w(AES128-GCM-SHA256) + curves = s.curves_preference + expect(curves).to be_nil - tls_serv material: [[:rsa, 1024]], ciphers: %w(AES128-GCM-SHA256), - server_preference: false do - curves = server.curves_preference - expect(curves).to be_nil - end + s = server :rsa, ciphers: %w(AES128-GCM-SHA256), server_preference: false + curves = s.curves_preference + expect(curves).to be_nil end it 'must report N/A if a single curve on RSA' do - tls_serv material: [[:rsa, 1024]], ciphers: %w(ECDHE-RSA-AES128-GCM-SHA256), - curves: %i(prime256v1), server_preference: true do - curves = server.curves_preference - expect(curves).to be_nil - end + curves = server(:rsa).curves_preference + expect(curves).to be_nil - tls_serv material: [[:rsa, 1024]], ciphers: %w(ECDHE-RSA-AES128-GCM-SHA256), - curves: %i(prime256v1), server_preference: false do - curves = server.curves_preference - expect(curves).to be_nil - end + curves = server(:rsa, server_preference: false).curves_preference + expect(curves).to be_nil end it 'must report server preference if server preference enforced on RSA' do - tls_serv material: [[:rsa, 1024]], ciphers: %w(ECDHE-RSA-AES128-GCM-SHA256), - curves: %i(prime256v1 sect571r1), server_preference: true do - curves = server.curves_preference.collect &:name - expect(curves).to eq %i(prime256v1 sect571r1) - end + s = server :rsa, curves: %i(prime256v1 sect571r1) + curves = s.curves_preference.collect &:name + expect(curves).to eq %i(prime256v1 sect571r1) - tls_serv material: [[:rsa, 1024]], ciphers: %w(ECDHE-RSA-AES128-GCM-SHA256), - curves: %i(sect571r1 prime256v1), server_preference: true do - curves = server.curves_preference.collect &:name - expect(curves).to eq %i(sect571r1 prime256v1) - end + s = server :rsa, curves: %i(sect571r1 prime256v1) + curves = s.curves_preference.collect &:name + expect(curves).to eq %i(sect571r1 prime256v1) end it 'must report client preference if server preference not enforced on RSA' do - tls_serv material: [[:rsa, 1024]], ciphers: %w(ECDHE-RSA-AES128-GCM-SHA256), - curves: %i(prime256v1 sect571r1), server_preference: false do - curves = server.curves_preference - expect(curves).to be :client - end + s = server :rsa, curves: %i(prime256v1 sect571r1), server_preference: false + curves = s.curves_preference + expect(curves).to be :client - tls_serv material: [[:rsa, 1024]], ciphers: %w(ECDHE-RSA-AES128-GCM-SHA256), - curves: %i(sect571r1 prime256v1), server_preference: false do - curves = server.curves_preference - expect(curves).to be :client - end + s = server :rsa, curves: %i(sect571r1 prime256v1), server_preference: false + curves = s.curves_preference + expect(curves).to be :client end it 'must report N/A if a single curve on ECDSA' do - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(prime256v1), server_preference: true do - curves = server.curves_preference - expect(curves).to be_nil - end + curves = server.curves_preference + expect(curves).to be_nil - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(prime256v1), server_preference: false do - curves = server.curves_preference - expect(curves).to be_nil - end + curves = server(server_preference: false).curves_preference + expect(curves).to be_nil end # No luck here :'( it 'can\'t detect server preference if server preference enforced on ECDSA with preference on ECDSA curve' do - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(prime256v1 sect571r1), server_preference: true do - curves = server.curves_preference - expect(curves).to be_nil - end + curves = server(curves: %i(prime256v1 sect571r1)).curves_preference + expect(curves).to be_nil end it 'must report server preference if server preference enforced on ECDSA with preference not on ECDSA curve' do - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(sect571r1 prime256v1), server_preference: true do - curves = server.curves_preference.collect &:name - expect(curves).to eq %i(sect571r1 prime256v1) - end + s = server curves: %i(sect571r1 prime256v1) + curves = s.curves_preference.collect &:name + expect(curves).to eq %i(sect571r1 prime256v1) end it 'must report client preference if server preference not enforced on ECDSA' do - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(prime256v1 sect571r1), server_preference: false do - curves = server.curves_preference - expect(curves).to be :client - end + s = server curves: %i(prime256v1 sect571r1), server_preference: false + curves = s.curves_preference + expect(curves).to be :client - tls_serv material: [[:ecdsa, :prime256v1]], ciphers: %w(ECDHE-ECDSA-AES128-GCM-SHA256), - curves: %i(sect571r1 prime256v1), server_preference: false do - curves = server.curves_preference - expect(curves).to be :client - end + s = server curves: %i(sect571r1 prime256v1), server_preference: false + curves = s.curves_preference + expect(curves).to be :client end end end