diff options
Diffstat (limited to 'ext/openssl/lib')
| -rw-r--r-- | ext/openssl/lib/openssl.rb | 16 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/bn.rb | 2 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/buffering.rb | 90 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/cipher.rb | 2 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/digest.rb | 34 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/marshal.rb | 2 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/pkey.rb | 140 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/ssl.rb | 170 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/version.rb | 3 | ||||
| -rw-r--r-- | ext/openssl/lib/openssl/x509.rb | 21 |
10 files changed, 273 insertions, 207 deletions
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb index 8a342f15b6..98fa8d39f2 100644 --- a/ext/openssl/lib/openssl.rb +++ b/ext/openssl/lib/openssl.rb @@ -7,28 +7,32 @@ = Licence This program is licensed under the same licence as Ruby. - (See the file 'LICENCE'.) + (See the file 'COPYING'.) =end require 'openssl.so' require_relative 'openssl/bn' -require_relative 'openssl/pkey' require_relative 'openssl/cipher' require_relative 'openssl/digest' require_relative 'openssl/hmac' -require_relative 'openssl/x509' -require_relative 'openssl/ssl' require_relative 'openssl/pkcs5' +require_relative 'openssl/pkey' +require_relative 'openssl/ssl' require_relative 'openssl/version' +require_relative 'openssl/x509' module OpenSSL - # call-seq: - # OpenSSL.secure_compare(string, string) -> boolean + # :call-seq: + # OpenSSL.secure_compare(string, string) -> true or false # # Constant time memory comparison. Inputs are hashed using SHA-256 to mask # the length of the secret. Returns +true+ if the strings are identical, # +false+ otherwise. + # + # This method is expensive due to the SHA-256 hashing. In most cases, where + # the input lengths are known to be equal or are not sensitive, + # OpenSSL.fixed_length_secure_compare should be used instead. def self.secure_compare(a, b) hashed_a = OpenSSL::Digest.digest('SHA256', a) hashed_b = OpenSSL::Digest.digest('SHA256', b) diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb index 0a5e11b4c2..e4889a140c 100644 --- a/ext/openssl/lib/openssl/bn.rb +++ b/ext/openssl/lib/openssl/bn.rb @@ -10,7 +10,7 @@ # # = Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ module OpenSSL diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index d47e1082ef..1464a4292d 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -8,7 +8,7 @@ # #= Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ ## @@ -24,25 +24,21 @@ module OpenSSL::Buffering # A buffer which will retain binary encoding. class Buffer < String - BINARY = Encoding::BINARY - - def initialize - super - - force_encoding(BINARY) - end + unless String.method_defined?(:append_as_bytes) + alias_method :_append, :<< + def append_as_bytes(string) + if string.encoding == Encoding::BINARY + _append(string) + else + _append(string.b) + end - def << string - if string.encoding == BINARY - super(string) - else - super(string.b) + self end - - return self end - alias concat << + undef_method :concat + undef_method :<< end ## @@ -77,7 +73,7 @@ module OpenSSL::Buffering def fill_rbuff begin - @rbuffer << self.sysread(BLOCK_SIZE) + @rbuffer.append_as_bytes(self.sysread(BLOCK_SIZE)) rescue Errno::EAGAIN retry rescue EOFError @@ -93,9 +89,7 @@ module OpenSSL::Buffering nil else size = @rbuffer.size unless size - ret = @rbuffer[0, size] - @rbuffer[0, size] = "" - ret + @rbuffer.slice!(0, size) end end @@ -106,8 +100,13 @@ module OpenSSL::Buffering # # Get the next 8bit byte from `ssl`. Returns `nil` on EOF def getbyte - byte = read(1) - byte && byte.unpack1("C") + read(1)&.ord + end + + # Get the next 8bit byte. Raises EOFError on EOF + def readbyte + raise EOFError if eof? + getbyte end ## @@ -232,7 +231,7 @@ module OpenSSL::Buffering # # Unlike IO#gets the separator must be provided if a limit is provided. - def gets(eol=$/, limit=nil) + def gets(eol=$/, limit=nil, chomp: false) idx = @rbuffer.index(eol) until @eof break if idx @@ -247,7 +246,11 @@ module OpenSSL::Buffering if size && limit && limit >= 0 size = [size, limit].min end - consume_rbuff(size) + line = consume_rbuff(size) + if chomp && line + line.chomp!(eol) + end + line end ## @@ -345,17 +348,32 @@ module OpenSSL::Buffering def do_write(s) @wbuffer = Buffer.new unless defined? @wbuffer - @wbuffer << s - @wbuffer.force_encoding(Encoding::BINARY) + @wbuffer.append_as_bytes(s) + @sync ||= false - if @sync or @wbuffer.size > BLOCK_SIZE - until @wbuffer.empty? - begin - nwrote = syswrite(@wbuffer) - rescue Errno::EAGAIN - retry + buffer_size = @wbuffer.bytesize + if @sync or buffer_size > BLOCK_SIZE + nwrote = 0 + begin + while nwrote < buffer_size do + begin + chunk = if nwrote > 0 + @wbuffer.byteslice(nwrote, @wbuffer.bytesize) + else + @wbuffer + end + + nwrote += syswrite(chunk) + rescue Errno::EAGAIN + retry + end + end + ensure + if nwrote < @wbuffer.bytesize + @wbuffer[0, nwrote] = "" + else + @wbuffer.clear end - @wbuffer[0, nwrote] = "" end end end @@ -432,10 +450,10 @@ module OpenSSL::Buffering def puts(*args) s = Buffer.new if args.empty? - s << "\n" + s.append_as_bytes("\n") end args.each{|arg| - s << arg.to_s + s.append_as_bytes(arg.to_s) s.sub!(/(?<!\n)\z/, "\n") } do_write(s) @@ -449,7 +467,7 @@ module OpenSSL::Buffering def print(*args) s = Buffer.new - args.each{ |arg| s << arg.to_s } + args.each{ |arg| s.append_as_bytes(arg.to_s) } do_write(s) nil end diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb index 8ad8c35dd3..ab75ac8e1a 100644 --- a/ext/openssl/lib/openssl/cipher.rb +++ b/ext/openssl/lib/openssl/cipher.rb @@ -9,7 +9,7 @@ # # = Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ module OpenSSL diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb index 2ff8398e44..4e6dea8d03 100644 --- a/ext/openssl/lib/openssl/digest.rb +++ b/ext/openssl/lib/openssl/digest.rb @@ -9,7 +9,7 @@ # # = Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ module OpenSSL @@ -18,30 +18,30 @@ module OpenSSL # Return the hash value computed with _name_ Digest. _name_ is either the # long name or short name of a supported digest algorithm. # - # === Examples + # === Example # # OpenSSL::Digest.digest("SHA256", "abc") - # - # which is equivalent to: - # - # OpenSSL::Digest.digest('SHA256', "abc") def self.digest(name, data) super(data, name) end %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512).each do |name| - klass = Class.new(self) { - define_method(:initialize, ->(data = nil) {super(name, data)}) - } - - singleton = (class << klass; self; end) - - singleton.class_eval{ - define_method(:digest) {|data| new.digest(data)} - define_method(:hexdigest) {|data| new.hexdigest(data)} - } + klass = Class.new(self) + klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def initialize(data = nil) + super("#{name}", data) + end + RUBY + klass.singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def digest(data) + new.digest(data) + end + def hexdigest(data) + new.hexdigest(data) + end + RUBY const_set(name.tr('-', '_'), klass) end @@ -61,7 +61,7 @@ module OpenSSL # OpenSSL::Digest("MD5") # # => OpenSSL::Digest::MD5 # - # Digest("Foo") + # OpenSSL::Digest("Foo") # # => NameError: wrong constant name Foo def Digest(name) diff --git a/ext/openssl/lib/openssl/marshal.rb b/ext/openssl/lib/openssl/marshal.rb index af5647192a..eb8eda4748 100644 --- a/ext/openssl/lib/openssl/marshal.rb +++ b/ext/openssl/lib/openssl/marshal.rb @@ -9,7 +9,7 @@ # # = Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ module OpenSSL module Marshal diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb index c3e0629091..39871e15dd 100644 --- a/ext/openssl/lib/openssl/pkey.rb +++ b/ext/openssl/lib/openssl/pkey.rb @@ -7,6 +7,9 @@ require_relative 'marshal' module OpenSSL::PKey + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + DHError = PKeyError + class DH include OpenSSL::Marshal @@ -35,6 +38,18 @@ module OpenSSL::PKey end # :call-seq: + # dh.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'. + def params + %w{p q g pub_key priv_key}.map { |name| + [name, send(name)] + }.to_h + end + + # :call-seq: # dh.compute_key(pub_bn) -> string # # Returns a String containing a shared secret computed from the other @@ -90,7 +105,7 @@ module OpenSSL::PKey # puts dh0.pub_key == dh.pub_key #=> false def generate_key! if OpenSSL::OPENSSL_VERSION_NUMBER >= 0x30000000 - raise DHError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \ + raise PKeyError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \ "use OpenSSL::PKey.generate_key instead" end @@ -135,6 +150,9 @@ module OpenSSL::PKey end end + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + DSAError = PKeyError + class DSA include OpenSSL::Marshal @@ -154,6 +172,18 @@ module OpenSSL::PKey OpenSSL::PKey.read(public_to_der) end + # :call-seq: + # dsa.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'. + def params + %w{p q g pub_key priv_key}.map { |name| + [name, send(name)] + }.to_h + end + class << self # :call-seq: # DSA.generate(size) -> dsa @@ -167,8 +197,16 @@ module OpenSSL::PKey # +size+:: # The desired key size in bits. def generate(size, &blk) + # FIPS 186-4 specifies four (L,N) pairs: (1024,160), (2048,224), + # (2048,256), and (3072,256). + # + # q size is derived here with compatibility with + # DSA_generator_parameters_ex() which previous versions of ruby/openssl + # used to call. + qsize = size >= 2048 ? 256 : 160 dsaparams = OpenSSL::PKey.generate_parameters("DSA", { "dsa_paramgen_bits" => size, + "dsa_paramgen_q_bits" => qsize, }, &blk) OpenSSL::PKey.generate_key(dsaparams) end @@ -210,13 +248,9 @@ module OpenSSL::PKey # sig = dsa.sign_raw(nil, digest) # p dsa.verify_raw(nil, sig, digest) #=> true def syssign(string) - q or raise OpenSSL::PKey::DSAError, "incomplete DSA" - private? or raise OpenSSL::PKey::DSAError, "Private DSA key needed!" - begin - sign_raw(nil, string) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::DSAError, $!.message - end + q or raise PKeyError, "incomplete DSA" + private? or raise PKeyError, "Private DSA key needed!" + sign_raw(nil, string) end # :call-seq: @@ -234,12 +268,13 @@ module OpenSSL::PKey # A \DSA signature value. def sysverify(digest, sig) verify_raw(nil, sig, digest) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::DSAError, $!.message end end if defined?(EC) + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + ECError = PKeyError + class EC include OpenSSL::Marshal @@ -250,8 +285,6 @@ module OpenSSL::PKey # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. def dsa_sign_asn1(data) sign_raw(nil, data) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::ECError, $!.message end # :call-seq: @@ -261,8 +294,6 @@ module OpenSSL::PKey # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw instead. def dsa_verify_asn1(data, sig) verify_raw(nil, sig, data) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::ECError, $!.message end # :call-seq: @@ -302,6 +333,9 @@ module OpenSSL::PKey end end + # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError. + RSAError = PKeyError + class RSA include OpenSSL::Marshal @@ -320,6 +354,18 @@ module OpenSSL::PKey OpenSSL::PKey.read(public_to_der) end + # :call-seq: + # rsa.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'n', 'e', 'd', 'p', 'q', 'dmp1', 'dmq1', and 'iqmp'. + def params + %w{n e d p q dmp1 dmq1 iqmp}.map { |name| + [name, send(name)] + }.to_h + end + class << self # :call-seq: # RSA.generate(size, exponent = 65537) -> RSA @@ -355,22 +401,19 @@ module OpenSSL::PKey # rsa.private_encrypt(string, padding) -> String # # Encrypt +string+ with the private key. +padding+ defaults to - # PKCS1_PADDING. The encrypted string output can be decrypted using + # PKCS1_PADDING, which is known to be insecure but is kept for backwards + # compatibility. The encrypted string output can be decrypted using # #public_decrypt. # # <b>Deprecated in version 3.0</b>. # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and # PKey::PKey#verify_recover instead. def private_encrypt(string, padding = PKCS1_PADDING) - n or raise OpenSSL::PKey::RSAError, "incomplete RSA" - private? or raise OpenSSL::PKey::RSAError, "private key needed." - begin - sign_raw(nil, string, { - "rsa_padding_mode" => translate_padding_mode(padding), - }) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::RSAError, $!.message - end + n or raise PKeyError, "incomplete RSA" + private? or raise PKeyError, "private key needed." + sign_raw(nil, string, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) end # :call-seq: @@ -378,20 +421,17 @@ module OpenSSL::PKey # rsa.public_decrypt(string, padding) -> String # # Decrypt +string+, which has been encrypted with the private key, with the - # public key. +padding+ defaults to PKCS1_PADDING. + # public key. +padding+ defaults to PKCS1_PADDING which is known to be + # insecure but is kept for backwards compatibility. # # <b>Deprecated in version 3.0</b>. # Consider using PKey::PKey#sign_raw and PKey::PKey#verify_raw, and # PKey::PKey#verify_recover instead. def public_decrypt(string, padding = PKCS1_PADDING) - n or raise OpenSSL::PKey::RSAError, "incomplete RSA" - begin - verify_recover(nil, string, { - "rsa_padding_mode" => translate_padding_mode(padding), - }) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::RSAError, $!.message - end + n or raise PKeyError, "incomplete RSA" + verify_recover(nil, string, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) end # :call-seq: @@ -399,20 +439,17 @@ module OpenSSL::PKey # rsa.public_encrypt(string, padding) -> String # # Encrypt +string+ with the public key. +padding+ defaults to - # PKCS1_PADDING. The encrypted string output can be decrypted using + # PKCS1_PADDING, which is known to be insecure but is kept for backwards + # compatibility. The encrypted string output can be decrypted using # #private_decrypt. # # <b>Deprecated in version 3.0</b>. # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead. def public_encrypt(data, padding = PKCS1_PADDING) - n or raise OpenSSL::PKey::RSAError, "incomplete RSA" - begin - encrypt(data, { - "rsa_padding_mode" => translate_padding_mode(padding), - }) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::RSAError, $!.message - end + n or raise PKeyError, "incomplete RSA" + encrypt(data, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) end # :call-seq: @@ -420,20 +457,17 @@ module OpenSSL::PKey # rsa.private_decrypt(string, padding) -> String # # Decrypt +string+, which has been encrypted with the public key, with the - # private key. +padding+ defaults to PKCS1_PADDING. + # private key. +padding+ defaults to PKCS1_PADDING, which is known to be + # insecure but is kept for backwards compatibility. # # <b>Deprecated in version 3.0</b>. # Consider using PKey::PKey#encrypt and PKey::PKey#decrypt instead. def private_decrypt(data, padding = PKCS1_PADDING) - n or raise OpenSSL::PKey::RSAError, "incomplete RSA" - private? or raise OpenSSL::PKey::RSAError, "private key needed." - begin - decrypt(data, { - "rsa_padding_mode" => translate_padding_mode(padding), - }) - rescue OpenSSL::PKey::PKeyError - raise OpenSSL::PKey::RSAError, $!.message - end + n or raise PKeyError, "incomplete RSA" + private? or raise PKeyError, "private key needed." + decrypt(data, { + "rsa_padding_mode" => translate_padding_mode(padding), + }) end PKCS1_PADDING = 1 @@ -452,7 +486,7 @@ module OpenSSL::PKey when PKCS1_OAEP_PADDING "oaep" else - raise OpenSSL::PKey::PKeyError, "unsupported padding mode" + raise PKeyError, "unsupported padding mode" end end end diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index a9103ecd27..3268c126b9 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -7,10 +7,13 @@ = Licence This program is licensed under the same licence as Ruby. - (See the file 'LICENCE'.) + (See the file 'COPYING'.) =end require "openssl/buffering" + +if defined?(OpenSSL::SSL) + require "io/nonblock" require "ipaddr" require "socket" @@ -19,7 +22,6 @@ module OpenSSL module SSL class SSLContext DEFAULT_PARAMS = { # :nodoc: - :min_version => OpenSSL::SSL::TLS1_VERSION, :verify_mode => OpenSSL::SSL::VERIFY_PEER, :verify_hostname => true, :options => -> { @@ -30,28 +32,9 @@ module OpenSSL }.call } - if defined?(OpenSSL::PKey::DH) - DEFAULT_2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY -JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab -VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6 -YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 -1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD -7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg== ------END DH PARAMETERS----- - _end_of_pem_ - private_constant :DEFAULT_2048 - - DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen| # :nodoc: - warn "using default DH parameters." if $VERBOSE - DEFAULT_2048 - } - end - - if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") && - OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000) + if !OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") DEFAULT_PARAMS.merge!( + min_version: OpenSSL::SSL::TLS1_VERSION, ciphers: %w{ ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 @@ -83,26 +66,13 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 AES256-SHA256 AES128-SHA AES256-SHA - }.join(":"), + }.join(":").freeze, ) end + DEFAULT_PARAMS.freeze DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc: DEFAULT_CERT_STORE.set_default_paths - DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL - - # A callback invoked when DH parameters are required for ephemeral DH key - # exchange. - # - # The callback is invoked with the SSLSocket, a - # flag indicating the use of an export cipher and the keylength - # required. - # - # The callback must return an OpenSSL::PKey::DH instance of the correct - # key length. - # - # <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead. - attr_accessor :tmp_dh_callback # A callback invoked at connect time to distinguish between multiple # server names. @@ -122,7 +92,6 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 # that this form is deprecated. New applications should use #min_version= # and #max_version= as necessary. def initialize(version = nil) - self.options |= OpenSSL::SSL::OP_ALL self.ssl_version = version if version self.verify_mode = OpenSSL::SSL::VERIFY_NONE self.verify_hostname = false @@ -142,54 +111,24 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 # used. def set_params(params={}) params = DEFAULT_PARAMS.merge(params) - self.options = params.delete(:options) # set before min_version/max_version + self.options |= params.delete(:options) # set before min_version/max_version 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 + if not defined?(Ractor) or Ractor.current == Ractor.main + self.cert_store = DEFAULT_CERT_STORE + else + self.cert_store = Ractor.current[:__openssl_default_store__] ||= + OpenSSL::X509::Store.new.tap { |store| + store.set_default_paths + } + end end end return params end # call-seq: - # ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION - # ctx.min_version = :TLS1_2 - # ctx.min_version = nil - # - # Sets the lower bound on the supported SSL/TLS protocol version. The - # version may be specified by an integer constant named - # OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version". - # - # Be careful that you don't overwrite OpenSSL::SSL::OP_NO_{SSL,TLS}v* - # options by #options= once you have called #min_version= or - # #max_version=. - # - # === Example - # ctx = OpenSSL::SSL::SSLContext.new - # ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION - # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION - # - # sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) - # sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2 - def min_version=(version) - set_minmax_proto_version(version, @max_proto_version ||= nil) - @min_proto_version = version - end - - # call-seq: - # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION - # ctx.max_version = :TLS1_2 - # ctx.max_version = nil - # - # Sets the upper bound of the supported SSL/TLS protocol version. See - # #min_version= for the possible values. - def max_version=(version) - set_minmax_proto_version(@min_proto_version ||= nil, version) - @max_proto_version = version - end - - # call-seq: # ctx.ssl_version = :TLSv1 # ctx.ssl_version = "SSLv23" # @@ -213,8 +152,7 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 end version = METHODS_MAP[meth.intern] or raise ArgumentError, "unknown SSL method `%s'" % meth - set_minmax_proto_version(version, version) - @min_proto_version = @max_proto_version = version + self.min_version = self.max_version = version end METHODS_MAP = { @@ -249,6 +187,14 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 to_io.peeraddr end + def local_address + to_io.local_address + end + + def remote_address + to_io.remote_address + end + def setsockopt(level, optname, optval) to_io.setsockopt(level, optname, optval) end @@ -268,6 +214,36 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 def do_not_reverse_lookup=(flag) to_io.do_not_reverse_lookup = flag end + + def close_on_exec=(value) + to_io.close_on_exec = value + end + + def close_on_exec? + to_io.close_on_exec? + end + + def wait(*args) + to_io.wait(*args) + end + + def wait_readable(*args) + to_io.wait_readable(*args) + end + + def wait_writable(*args) + to_io.wait_writable(*args) + end + + if IO.method_defined?(:timeout) + def timeout + to_io.timeout + end + + def timeout=(value) + to_io.timeout=(value) + end + end end def verify_certificate_identity(cert, hostname) @@ -418,6 +394,32 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 nil end + # Close the stream for reading. + # This method is ignored by OpenSSL as there is no reasonable way to + # implement it, but exists for compatibility with IO. + def close_read + # Unsupported and ignored. + # Just don't read any more. + end + + # Closes the stream for writing. The behavior of this method depends on + # the version of OpenSSL and the TLS protocol in use. + # + # - Sends a 'close_notify' alert to the peer. + # - Does not wait for the peer's 'close_notify' alert in response. + # + # In TLS 1.2 and earlier: + # - On receipt of a 'close_notify' alert, responds with a 'close_notify' + # alert of its own and close down the connection immediately, + # discarding any pending writes. + # + # Therefore, on TLS 1.2, this method will cause the connection to be + # completely shut down. On TLS 1.3, the connection will remain open for + # reading only. + def close_write + stop + end + private def using_anon_cipher? @@ -430,10 +432,6 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 @context.client_cert_cb end - def tmp_dh_callback - @context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK - end - def session_new_cb @context.session_new_cb end @@ -491,7 +489,7 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 unless ctx.session_id_context # see #6137 - session id may not exceed 32 bytes prng = ::Random.new($0.hash) - session_id = prng.bytes(16).unpack('H*')[0] + session_id = prng.bytes(16).unpack1('H*') @ctx.session_id_context = session_id end @start_immediately = true @@ -540,3 +538,5 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 end end end + +end diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb index 5e60604353..395a720a31 100644 --- a/ext/openssl/lib/openssl/version.rb +++ b/ext/openssl/lib/openssl/version.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true module OpenSSL - VERSION = "3.0.0" + # The version string of Ruby/OpenSSL. + VERSION = "4.0.2" end diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb index f973f4f4dc..66765ffeab 100644 --- a/ext/openssl/lib/openssl/x509.rb +++ b/ext/openssl/lib/openssl/x509.rb @@ -9,7 +9,7 @@ # # = Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ require_relative 'marshal' @@ -122,8 +122,8 @@ module OpenSSL include Helpers # Get the distributionPoint fullName URI from the certificate's CRL - # distribution points extension, as described in RFC5280 Section - # 4.2.1.13 + # distribution points extension, as described in RFC 5280 Section + # 4.2.1.13. # # Returns an array of strings or nil or raises ASN1::ASN1Error. def crl_uris @@ -135,19 +135,19 @@ module OpenSSL raise ASN1::ASN1Error, "invalid extension" end - crl_uris = cdp_asn1.map do |crl_distribution_point| + crl_uris = cdp_asn1.flat_map do |crl_distribution_point| distribution_point = crl_distribution_point.value.find do |v| v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 end full_name = distribution_point&.value&.find do |v| v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 end - full_name&.value&.find do |v| + full_name&.value&.select do |v| v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier end end - crl_uris&.map(&:value) + crl_uris.empty? ? nil : crl_uris.map(&:value) end end @@ -346,6 +346,15 @@ module OpenSSL include Extension::CRLDistributionPoints include Extension::AuthorityInfoAccess + def inspect + "#<#{self.class}: " \ + "subject=#{subject.inspect}, " \ + "issuer=#{issuer.inspect}, " \ + "serial=#{serial.inspect}, " \ + "not_before=#{not_before.inspect rescue "(error)"}, " \ + "not_after=#{not_after.inspect rescue "(error)"}>" + end + def pretty_print(q) q.object_group(self) { q.breakable |
