Skip to content

Commit

Permalink
update openssl/ssl.rb based on MRI 2.2's version
Browse files Browse the repository at this point in the history
kares committed Dec 20, 2015
1 parent 5a1575a commit cd47562
Showing 1 changed file with 155 additions and 18 deletions.
173 changes: 155 additions & 18 deletions lib/jopenssl22/openssl/ssl.rb
Original file line number Diff line number Diff line change
@@ -15,42 +15,154 @@
=end

require "openssl/buffering"
require 'fcntl' # used by OpenSSL::SSL::Nonblock (if loaded)
require "fcntl"

module OpenSSL
module SSL
class SSLContext
DEFAULT_PARAMS = {
:ssl_version => "SSLv23",
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:ciphers => %w{
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-DSS-AES256-GCM-SHA384
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA256
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA384
ECDHE-ECDSA-AES256-SHA
ECDHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA256
DHE-RSA-AES256-SHA256
DHE-RSA-AES128-SHA
DHE-RSA-AES256-SHA
DHE-DSS-AES128-SHA256
DHE-DSS-AES256-SHA256
DHE-DSS-AES128-SHA
DHE-DSS-AES256-SHA
AES128-GCM-SHA256
AES256-GCM-SHA384
AES128-SHA256
AES256-SHA256
AES128-SHA
AES256-SHA
ECDHE-ECDSA-RC4-SHA
ECDHE-RSA-RC4-SHA
RC4-SHA
}.join(":"),
:options => -> {
opts = OpenSSL::SSL::OP_ALL
opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
opts
}.call
} unless const_defined? :DEFAULT_PARAMS # JRuby does it in Java

unless const_defined? :DEFAULT_CERT_STORE # JRuby specific
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new
DEFAULT_CERT_STORE.set_default_paths
if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL)
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
end
end

##
# Sets the parameters for this SSL context to the values in +params+.
# The keys in +params+ must be assignment methods on SSLContext.
#
# If the verify_mode is not VERIFY_NONE and ca_file, ca_path and
# cert_store are not set then the system default certificate store is
# used.

def set_params(params={})
params = DEFAULT_PARAMS.merge(params)
params.each{|name, value| self.__send__("#{name}=", value) }
if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
unless self.ca_file or self.ca_path or self.cert_store
self.cert_store = DEFAULT_CERT_STORE
end
end
return params
end unless method_defined? :set_params # JRuby: hooked up in "native" Java
end

module SocketForwarder
def addr
to_io.addr
end

def peeraddr
to_io.peeraddr
end

def setsockopt(level, optname, optval)
to_io.setsockopt(level, optname, optval)
end

def getsockopt(level, optname)
to_io.getsockopt(level, optname)
end

def fcntl(*args)
to_io.fcntl(*args)
end

def closed?
to_io.closed?
end

def do_not_reverse_lookup=(flag)
to_io.do_not_reverse_lookup = flag
end
end unless const_defined? :SocketForwarder # JRuby: hooked up in "native" Java

module Nonblock
def initialize(*args)
flag = File::NONBLOCK
flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL)
@io.fcntl(Fcntl::F_SETFL, flag)
super
end
end unless const_defined? :Nonblock # JRuby: hooked up in "native" Java

# FIXME: Using the old non-ASN1 logic here because our ASN1 appears to
# return the wrong types for some decoded objects.
# @see https://github.com/jruby/jruby/issues/1102
# @private
def verify_certificate_identity(cert, hostname)
should_verify_common_name = true
cert.extensions.each { |ext|
next if ext.oid != "subjectAltName"
ext.value.split(/,\s+/).each { |general_name|
# MRI 1.9.3 (since we parse ASN.1 differently)
# when 2 # dNSName in GeneralName (RFC5280)
#case san.tag
# MRI 2.2.3 (JRuby parses ASN.1 differently)
#when 2 # dNSName in GeneralName (RFC5280)
if /\ADNS:(.*)/ =~ general_name
should_verify_common_name = false
return true if verify_hostname(hostname, $1)
# MRI 1.9.3 (since we parse ASN.1 differently)
# when 7 # iPAddress in GeneralName (RFC5280)
# MRI 2.2.3 (JRuby parses ASN.1 differently)
#when 7 # iPAddress in GeneralName (RFC5280)
elsif /\AIP(?: Address)?:(.*)/ =~ general_name
should_verify_common_name = false
return true if $1 == hostname
# NOTE: bellow logic makes little sense as we read exts differently
#value = $1 # follows GENERAL_NAME_print() in x509v3/v3_alt.c
#if value.size == 4
# return true if value.unpack('C*').join('.') == hostname
#elsif value.size == 16
# return true if value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
# NOTE: bellow logic makes little sense JRuby reads exts differently
# follows GENERAL_NAME_print() in x509v3/v3_alt.c
#if san.value.size == 4
# return true if san.value.unpack('C*').join('.') == hostname
#elsif san.value.size == 16
# return true if san.value.unpack('n*').map { |e| sprintf("%X", e) }.join(':') == hostname
#end
end
}
}
if should_verify_common_name
cert.subject.to_a.each { |oid, value|
cert.subject.to_a.each{|oid, value|
if oid == "CN"
return true if verify_hostname(hostname, value)
end
@@ -122,12 +234,33 @@ class SSLSocket
# This method MUST be called after calling #connect to ensure that the
# hostname of a remote peer has been verified.
def post_connection_check(hostname)
if peer_cert.nil?
msg = "Peer verification enabled, but no certificate received."
if using_anon_cipher?
msg += " Anonymous cipher suite #{cipher[0]} was negotiated. Anonymous suites must be disabled to use peer verification."
end
raise SSLError, msg
end

unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
end
return true
end

#def session
# SSL::Session.new(self)
#rescue SSL::Session::SessionError
# nil
#end

private

def using_anon_cipher?
ctx = OpenSSL::SSL::SSLContext.new
ctx.ciphers = "aNULL"
ctx.ciphers.include?(cipher)
end
end

##
@@ -178,8 +311,12 @@ def accept
ssl.sync_close = true
ssl.accept if @start_immediately
ssl
rescue SSLError => ex
sock.close
rescue Exception => ex
if ssl
ssl.close
else
sock.close
end
raise ex
end
end

0 comments on commit cd47562

Please sign in to comment.