Skip to content

Commit

Permalink
lib/puma\minissl.rb - TLSv1.3 updates
Browse files Browse the repository at this point in the history
Changes to Puma::MiniSSL

1. Add HAS_TLS1_3 constant.
2. Add #bad_tlsv1_3? method, used to determine if an http  connection to an https server has been made.  TLSv1.3 behaves differently than previous TLS versions.
3. Change #engine_read_all to close http connections.
4. Add #ssl_version_state method, unused at present.
  • Loading branch information
MSP-Greg committed May 13, 2020
1 parent 68d535c commit 7751c84
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions lib/puma/minissl.rb
Expand Up @@ -5,8 +5,18 @@
rescue LoadError
end

# need for Puma::MiniSSL::OPENSSL constants used in `HAS_TLS1_3`
require 'puma/puma_http11'

module Puma
module MiniSSL

# define constant at runtime, as it's easy to determine at built time,
# but Puma could (it shouldn't) be loaded with an older OpenSSL version
HAS_TLS1_3 = !IS_JRUBY ||
(OPENSSL_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) != -1 ||
(OPENSSL_LIBRARY_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) !=-1

class Socket
def initialize(socket, engine)
@socket = socket
Expand All @@ -22,6 +32,24 @@ def closed?
@socket.closed?
end

# returns a two element array
# first is protocol version (SSL_get_version)
# second is 'handshake' state (SSL_state_string)
#
# used for dropping tcp connections to ssl
# see OpenSSL ssl/ssl_stat.c SSL_state_string for info
#
def ssl_version_state
IS_JRUBY ? [nil, nil] : @engine.ssl_vers_st
end

# used to check the handshake status, in particular when a TCP connection
# is made with TLSv1.3 as an available protocol
def bad_tlsv1_3?
HAS_TLS1_3 && @engine.ssl_vers_st == ['TLSv1.3', 'SSLERR']
end
private :bad_tlsv1_3?

def readpartial(size)
while true
output = @engine.read
Expand All @@ -41,6 +69,7 @@ def readpartial(size)

def engine_read_all
output = @engine.read
raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
while output and additional_output = @engine.read
output << additional_output
end
Expand Down Expand Up @@ -167,7 +196,7 @@ def peercert
end
end

if defined?(JRUBY_VERSION)
if IS_JRUBY
class SSLError < StandardError
# Define this for jruby even though it isn't used.
end
Expand All @@ -184,7 +213,7 @@ def initialize
@no_tlsv1_1 = false
end

if defined?(JRUBY_VERSION)
if IS_JRUBY
# jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
attr_reader :keystore
attr_accessor :keystore_pass
Expand Down

0 comments on commit 7751c84

Please sign in to comment.