lib/openssl/ssl.rb in rubysl-openssl-2.10 vs lib/openssl/ssl.rb in rubysl-openssl-2.11

- old
+ new

@@ -14,72 +14,64 @@ require "io/nonblock" module OpenSSL module SSL class SSLContext - DEFAULT_PARAMS = { + DEFAULT_PARAMS = { # :nodoc: :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(":"), + :verify_hostname => true, :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_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 |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 opts }.call } - 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 + if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") && + OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000) + DEFAULT_PARAMS.merge!( + 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 + }.join(":"), + ) end - INIT_VARS = ["cert", "key", "client_ca", "ca_file", "ca_path", - "timeout", "verify_mode", "verify_depth", "renegotiation_cb", - "verify_callback", "cert_store", "extra_chain_cert", - "client_cert_cb", "session_id_context", "tmp_dh_callback", - "session_get_cb", "session_new_cb", "session_remove_cb", - "tmp_ecdh_callback", "servername_cb", "npn_protocols", - "alpn_protocols", "alpn_select_cb", - "npn_select_cb"].map { |x| "@#{x}" } + 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. # # The callback is invoked with the Session for the key exchange, an # flag indicating the use of an export cipher and the keylength @@ -88,40 +80,40 @@ # The callback must return an OpenSSL::PKey::DH instance of the correct # key length. attr_accessor :tmp_dh_callback - if ExtConfig::HAVE_TLSEXT_HOST_NAME - # A callback invoked at connect time to distinguish between multiple - # server names. - # - # The callback is invoked with an SSLSocket and a server name. The - # callback must return an SSLContext for the server name or nil. - attr_accessor :servername_cb - end + # A callback invoked at connect time to distinguish between multiple + # server names. + # + # The callback is invoked with an SSLSocket and a server name. The + # callback must return an SSLContext for the server name or nil. + attr_accessor :servername_cb if ExtConfig::HAVE_TLSEXT_HOST_NAME # call-seq: # SSLContext.new => ctx # SSLContext.new(:TLSv1) => ctx # SSLContext.new("SSLv23_client") => ctx # # You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS def initialize(version = nil) - 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.options |= OpenSSL::SSL::OP_ALL + self.ssl_version = version if version end ## - # Sets the parameters for this SSL context to the values in +params+. + # call-seq: + # ctx.set_params(params = {}) -> params + # + # Sets saner defaults optimized for the use with HTTP-like protocols. + # + # If a Hash +params+ is given, the parameters are overridden with it. # 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 @@ -250,48 +242,24 @@ class SSLSocket include Buffering include SocketForwarder - if ExtConfig::OPENSSL_NO_SOCK - def initialize(io, ctx = nil); raise NotImplementedError; end - else - if ExtConfig::HAVE_TLSEXT_HOST_NAME - attr_accessor :hostname - end + if ExtConfig::HAVE_TLSEXT_HOST_NAME + attr_reader :hostname + end - attr_reader :io, :context - attr_accessor :sync_close - alias :to_io :io + # The underlying IO object. + attr_reader :io + alias :to_io :io - # call-seq: - # SSLSocket.new(io) => aSSLSocket - # SSLSocket.new(io, ctx) => aSSLSocket - # - # Creates a new SSL socket from +io+ which must be a real ruby object (not an - # IO-like object that responds to read/write). - # - # If +ctx+ is provided the SSL Sockets initial params will be taken from - # the context. - # - # The OpenSSL::Buffering module provides additional IO methods. - # - # This method will freeze the SSLContext if one is provided; - # however, session management is still allowed in the frozen SSLContext. + # The SSLContext object used in this connection. + attr_reader :context - def initialize(io, context = OpenSSL::SSL::SSLContext.new) - @io = io - @context = context - @sync_close = false - @hostname = nil - @io.nonblock = true if @io.respond_to?(:nonblock=) - Rubinius.synchronize(SSL) do - context.setup - end - super() - end - end + # Whether to close the underlying socket as well, when the SSL/TLS + # connection is shut down. This defaults to +false+. + attr_accessor :sync_close # call-seq: # ssl.sysclose => nil # # Sends "close notify" to the peer and tries to shut down the SSL @@ -302,29 +270,37 @@ return if closed? stop io.close if sync_close end - ## - # Perform hostname verification after an SSL connection is established + # call-seq: + # ssl.post_connection_check(hostname) -> true # + # Perform hostname verification following RFC 6125. + # # 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." + 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 + # call-seq: + # ssl.session -> aSession + # + # Returns the SSLSession object currently used, or nil if the session is + # not established. def session SSL::Session.new(self) rescue SSL::Session::SessionError nil end