Browse Source

Check for TLS_FALLBACK_SCSV

new-scoring
aeris 3 years ago
parent
commit
8a1c4f8856
4 changed files with 106 additions and 2 deletions
  1. 1
    0
      Makefile
  2. 62
    0
      fallback_scsv.patch
  3. 8
    1
      lib/cryptcheck/tls/grade.rb
  4. 35
    1
      lib/cryptcheck/tls/server.rb

+ 1
- 0
Makefile View File

@@ -69,6 +69,7 @@ $(RUBY_DIR)/: build/$(RUBY_NAME).tar.gz
$(RUBY_OPENSSL_EXT_DIR)/Makefile: libs | $(RUBY_DIR)/
patch -d $(RUBY_DIR)/ -p1 < tmp_key.patch
patch -d $(RUBY_DIR)/ -p1 < set_ecdh_curves.patch
patch -d $(RUBY_DIR)/ -p1 < fallback_scsv.patch
cd $(RUBY_OPENSSL_EXT_DIR) && ruby extconf.rb

$(RUBY_OPENSSL_EXT_DIR)/openssl.so: libs $(RUBY_OPENSSL_EXT_DIR)/Makefile

+ 62
- 0
fallback_scsv.patch View File

@@ -0,0 +1,62 @@
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 57519f2..c5b0c8b 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -105,11 +105,12 @@ class SSLContext
# SSLContext.new("SSLv23_client") => ctx
#
# You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS
- def initialize(version = nil)
+ def initialize(version = nil, fallback_scsv = false)
INIT_VARS.each { |v| instance_variable_set v, nil }
self.options = self.options | OpenSSL::SSL::OP_ALL
return unless version
self.ssl_version = version
+ self.enable_fallback_scsv if fallback_scsv
end

##
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index bcc624f..0c1780b 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -978,6 +978,31 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
return v;
}

+/*
+ * call-seq:
+ * ctx.enable_fallback_scsv() => nil
+ *
+ * Activate TLS_FALLBACK_SCSV for this context.
+ * See RFC 7507.
+ */
+static VALUE
+ossl_sslctx_enable_fallback_scsv(VALUE self)
+{
+ SSL_CTX *ctx;
+
+ GetSSLCTX(self, ctx);
+ if(!ctx){
+ rb_warning("SSL_CTX is not initialized.");
+ return Qnil;
+ }
+
+ long modes = SSL_CTX_get_mode(ctx);
+ modes |= SSL_MODE_SEND_FALLBACK_SCSV;
+ SSL_CTX_set_mode(ctx, modes);
+
+ return Qnil;
+}
+
#if !defined(OPENSSL_NO_EC)
/*
* call-seq:
@@ -2330,6 +2355,7 @@ Init_ossl_ssl(void)
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
+ rb_define_method(cSSLContext, "enable_fallback_scsv", ossl_sslctx_enable_fallback_scsv, 0);

rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);


+ 8
- 1
lib/cryptcheck/tls/grade.rb View File

@@ -119,7 +119,14 @@ module CryptCheck
]

def checks
CHECKS
checks = CHECKS
unless @server.fallback_scsv? == nil
checks += [
[:no_fallback_scsv, Proc.new { |s| not s.fallback_scsv? }, :error],
[:fallback_scsv, Proc.new { |s| s.fallback_scsv? }, :good]
]
end
checks
end

def calculate_states

+ 35
- 1
lib/cryptcheck/tls/server.rb View File

@@ -1,7 +1,6 @@
require 'socket'
require 'openssl'
require 'httparty'
require 'awesome_print'

module CryptCheck
module Tls
@@ -41,6 +40,7 @@ module CryptCheck
Logger.info { "Key : #{Tls.key_to_s self.key}" }
fetch_prefered_ciphers
check_supported_cipher
check_fallback_scsv
uniq_dh
end

@@ -174,6 +174,10 @@ module CryptCheck
supported_ciphers.any? { |c| c.sweet32? }
end

def fallback_scsv?
@fallback_scsv
end

private
def name
name = "#@ip:#@port"
@@ -229,6 +233,8 @@ module CryptCheck
when /state=error: no ciphers available$/,
/state=SSLv.* read server hello A: sslv.* alert handshake failure$/
raise CipherNotAvailable, e
when /state=SSLv.* read server hello A: tlsv.* alert inappropriate fallback$/
raise InappropriateFallback, e
end
raise
rescue ::SystemCallError => e
@@ -350,6 +356,34 @@ module CryptCheck
end
end

def check_fallback_scsv
@fallback_scsv = false

methods = @supported_ciphers.keys
if methods.size > 1
# We will try to connect to the not better supported method
method = methods[1]

begin
ssl_client method, fallback: true
rescue InappropriateFallback
@fallback_scsv = true
end
else
@fallback_scsv = nil
end

text, color = case @fallback_scsv
when true
['Supported', :good]
when false
['Not supported', :error]
when nil
['Not applicable', :unknown]
end
Logger.info { "Fallback SCSV : #{text.colorize color}" }
end

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

Loading…
Cancel
Save